import type { Unsubscribe, ValueReactor } from "#Source/reactor/index.ts" import { subscribe } from "#Source/reactor/index.ts" import * as Lit from "../lit-html/index.ts" export class ReactorDirective extends Lit.AsyncDirective { protected target: ValueReactor | undefined protected unsubscribe: Unsubscribe | undefined constructor(partInfo: Lit.PartInfo) { super(partInfo) this.target = undefined this.unsubscribe = undefined } protected subscribeToTarget(): void { if (this.target === undefined) { return } if (this.unsubscribe !== undefined) { return } if (this.isConnected === false) { return } this.unsubscribe = subscribe({ target: this.target, subscriber: (value) => { this.setValue(value) }, }) } protected unsubscribeFromTarget(): void { this.unsubscribe?.() this.unsubscribe = undefined } render(valueReactor: ValueReactor): V { if (this.target !== valueReactor) { this.unsubscribeFromTarget() this.target = valueReactor this.subscribeToTarget() } const value = valueReactor.getWithoutTrack() return value } override disconnected(): void { super.disconnected() this.unsubscribeFromTarget() } override reconnected(): void { super.reconnected() this.subscribeToTarget() if (this.target !== undefined) { const value = this.target.getWithoutTrack() this.setValue(value) } } } type ReactorDirectiveClass = typeof ReactorDirective type ReactorDirectiveResult = Lit.DirectiveResult> const directive = Lit.directive(ReactorDirective) export const reactor = (valueReactor: ValueReactor): ReactorDirectiveResult => { const directiveResult = directive(valueReactor as ValueReactor) return directiveResult }