diff --git a/mod.ts b/mod.ts index dbe70ad..836815f 100644 --- a/mod.ts +++ b/mod.ts @@ -1,4 +1,5 @@ /*! Cell v0.5.0 | Copyright 2024 Yoshiya Hinosawa and Capsule contributors | MIT license */ +import type { GroupSignal, Signal } from "@kt3k/signal" import { documentReady, logEvent } from "./util.ts" export { GroupSignal, Signal } from "@kt3k/signal" @@ -148,6 +149,10 @@ export interface Context { queryAll( selector: string, ): NodeListOf + /** Subscribe to the signal. Unsubscribe it when the component unmounted */ + subscribe(signal: Signal, handler: (value: T) => void): void + /** Subscribe to the group signal. Unsubscribe it when the component unmounted */ + subscribe(signal: GroupSignal, handler: (value: T) => void): void } /** The component type */ @@ -218,13 +223,15 @@ export function register( /** Initializes the html element by the given configuration. */ const initializer = (el: EL) => { if (!el.classList.contains(initClass)) { + const onUnmount = (handler: () => void) => { + el.addEventListener(`__unmount__:${name}`, handler, { once: true }) + } + // FIXME(kt3k): the below can be written as .add(name, initClass) // when deno_dom fixes add class. el.classList.add(name) el.classList.add(initClass) - el.addEventListener(`__unmount__:${name}`, () => { - el.classList.remove(initClass) - }, { once: true }) + onUnmount(() => el.classList.remove(initClass)) const on = ( type: string, @@ -279,13 +286,14 @@ export function register( } } document.addEventListener(type, listener) - el.addEventListener(`__unmount__:${name}`, () => { - document.removeEventListener(type, listener) - }, { once: true }) + onUnmount(() => document.removeEventListener(type, listener)) } - const onUnmount = (handler: () => void) => { - el.addEventListener(`__unmount__:${name}`, handler, { once: true }) + const subscribe = ( + signal: Signal | GroupSignal, + handler: (value: unknown) => void, + ) => { + onUnmount(signal.subscribe(handler)) } const context = { @@ -297,6 +305,7 @@ export function register( el.querySelector(s) as T | null, queryAll: (s: string) => el.querySelectorAll(s) as NodeListOf, + subscribe, } const html = component(context) if (typeof html === "string") {