# @rhtml/component

> Reactive HyperText Markup Language

Latest version **0.0.148** (published 2026-05-02) · MIT license · 0 weekly downloads

## Install

```sh
npm install @rhtml/component
pnpm add @rhtml/component
yarn add @rhtml/component
bun add @rhtml/component
```

## Health

**Score 60/100 (C)** — status: active.

Positive: has types; esm support; no vulnerabilities; high quality score.

Warnings: low downloads; pre 1.0.

## Facts

| | |
|---|---|
| Version | 0.0.148 |
| Published | 2026-05-02 |
| First published | 2020-12-13 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 2 |
| Unpacked size | 15.6 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Author | Kristiyan Tachev |
| Maintainers | rxdi |

## Links

- npm: https://www.npmjs.com/package/@rhtml/component
- Repository: https://github.com/rhtml/rhtml
- Homepage: https://github.com/rhtml/rhtml#readme
- Issues: https://github.com/rhtml/rhtml/issues
- npm.io page: https://npm.io/package/@rhtml/component

## Dependencies (2)

- [@rxdi/lit-html](https://npm.io/package/@rxdi/lit-html.md) ^0.7.225
- [@rhtml/renderer](https://npm.io/package/@rhtml/renderer.md) 0.0.148

## Recent versions

- 0.0.148 (latest) — 2026-05-02
- 0.0.147 — 2026-05-02
- 0.0.146 — 2026-03-25
- 0.0.145 — 2026-01-31
- 0.0.144 — 2026-01-29
- 0.0.143 — 2026-01-29
- 0.0.142 — 2026-01-28
- 0.0.141 — 2026-01-13
- 0.0.140 — 2026-01-12
- 0.0.139 — 2026-01-07
- 0.0.138 — 2026-01-06
- 0.0.137 — 2026-01-05
- 0.0.136 — 2025-08-28
- 0.0.135 — 2025-08-26
- 0.0.134 — 2025-02-27
- … 65 more at https://npm.io/package/@rhtml/component/versions

## README

# Strange component representing more functional approach of defining decorators

```typescript
import { DefineDependencies, Component } from '@rhtml/component';
import { Container, Injectable } from '@rxdi/core';
import { html, LitElement, property } from '@rxdi/lit-html';
import { interval } from 'rxjs';
import { map } from 'rxjs/operators';

@Injectable()
class CounterService {
  counter = 55;
}

const Providers = DefineDependencies(CounterService)(Container);

@Component({
  Settings: {
    selector: 'counter-component'
  },
  Providers,
  State: function(this: CounterComponent, [counterService]) {
    return interval(1000).pipe(
      map(value => ({ counter: this.counter + counterService.counter + value }))
    );
  },
  Render: ([counterService]) =>
    function(this, { counter }) {
      return html`
        ${counter} ${counterService.counter}
      `;
    }
})
export class CounterComponent extends LitElement {
  @property({ type: Number })
  counter: number;
}

/* 
  <counter-component .counter=${1000}></counter-component>
*/
```

#### Functional composition

```ts
import { Partial } from '@rhtml/component';

const compose = <T, D = []>(selector: string, styles?: CSSResult[], deps?: D) =>
  Partial<T, D>({
    selector,
    styles
  })(deps);

const state = () => interval(1000).pipe(map(() => new Date().getSeconds()));

@(compose<number>('date-component')(state)(() => date => date))
export class DateComponent extends LitElement {}

@(compose<number, typeof Dependencies>(
  'date-component2',
  null,
  Dependencies
)(([appService]) => state().pipe(map(res => res)))(() => date => date))
export class DateComponent2 extends LitElement {}

@(compose<number>('date-component3')(state)(() => date =>
  html`
    ${date}
  `
))
export class DateComponent3 extends LitElement {}
```

#### Usage inside DOM

```html
<date-component></date-component>
<date-component2></date-component2>
<date-component3></date-component3>
```

```ts
import { Component } from '@rhtml/component';
/**
 * @customElement counter-component
 */
@Component<{ counter: number }, [], CounterComponent>({
  Settings: {
    selector: 'counter-component',
    style: css`
      .counter {
        background: red;
        color: white;
      }
    `
  },
  Providers: [],
  State: function(this) {
    return combineLatest([this.counter, this.mega]).pipe(
      map(([value, v2]) => ({ counter: value + v2 }))
    );
  },
  Render: () =>
    function(this, { counter }, setState) {
      return html`
        <p>${counter}</p>
        <button @click=${() => setState({ counter: counter + counter })}>
          CLICK ME
        </button>
      `;
    }
})
export class CounterComponent extends LitElement {
  @property({ type: Object })
  counter: Observable<number>;

  @property({ type: Object })
  mega: Observable<number>;
}
```

```ts
import { Component, DefineDependencies } from '@rhtml/component';

@Component({
  Settings: {
    selector: 'date-component'
  },
  Providers: DefineDependencies(AppsService, SocialService)(Container),
  State: ([appService, socialService]) =>
    interval(1000).pipe(map(() => new Date().getSeconds())),
  Render: ([appService, socialService]) => seconds => seconds
})
export class ComposableComponent extends LitElement {}
```

---
_Source: https://npm.io/package/@rhtml/component · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
