UNPKG

@design.estate/dees-element

Version:

A library for creating custom elements extending the lit element class with additional functionalities.

61 lines (55 loc) 1.9 kB
import { type TemplateResult, noChange } from 'lit'; import type { DirectiveResult } from 'lit/directive.js'; import { AsyncDirective, directive } from 'lit/async-directive.js'; import { rxjs } from '@push.rocks/smartrx'; /** * Subscribes to an observable and applies a template function to each emission. * @param observable - the source Observable * @param templateFn - function mapping each emitted value to a TemplateResult or other renderable content */ class SubscribeWithTemplateDirective extends AsyncDirective { private observable?: rxjs.Observable<unknown>; private templateFn?: (value: unknown) => TemplateResult | unknown; private sub: rxjs.Subscription | null = null; render( observable: rxjs.Observable<unknown>, templateFn: (value: unknown) => TemplateResult | unknown ) { const changed = this.observable !== observable || this.templateFn !== templateFn; if (changed) { this.sub?.unsubscribe(); this.observable = observable; this.templateFn = templateFn; if (this.isConnected) { this.startSubscription(); } } return noChange; } private startSubscription() { this.sub = this.observable!.subscribe((v: unknown) => { const out = this.templateFn!(v); this.setValue(out); }); } disconnected() { this.sub?.unsubscribe(); } reconnected() { this.startSubscription(); } } /** * Directive that renders templates for each emission of an Observable. * Usage: html`${subscribeWithTemplate(myObservable, v => html`<span>${v}</span>`)}` */ /** * Typed directive function signature: returns a Lit DirectiveResult. */ type SubscribeWithTemplateFn = <T>( observable: rxjs.Observable<T>, templateFn: (value: T) => TemplateResult | unknown ) => DirectiveResult; export const subscribeWithTemplate = directive( SubscribeWithTemplateDirective ) as SubscribeWithTemplateFn;