a post-component library for building user-interfaces on the web.
1import type { Renderable } from '../index.ts'
2import { assert, is_renderable } from '../shared.ts'
3import { type Cleanup } from './util.ts'
4
5export interface Controller {
6 _mount_callbacks: (() => Cleanup)[]
7 _unmount_callbacks: Cleanup[]
8 _invalidate: Map<object, () => void>
9}
10
11export const controllers: WeakMap<Renderable, Controller> = new WeakMap()
12
13export function get_controller(renderable: Renderable): Controller {
14 let controller = controllers.get(renderable)
15 if (!controller)
16 controllers.set(
17 renderable,
18 (controller = {
19 _mount_callbacks: [],
20 _unmount_callbacks: [],
21 _invalidate: new Map(),
22 }),
23 )
24 return controller
25}
26
27export function invalidate(renderable: Renderable): void {
28 const controller = controllers.get(renderable)
29 assert(controller, 'the renderable has not been rendered')
30 controller._invalidate.forEach(invalidate => invalidate())
31}
32
33export function onMount(renderable: Renderable, callback: () => Cleanup): void {
34 assert(is_renderable(renderable), 'expected a renderable')
35 const controller = get_controller(renderable)
36 if (controller._invalidate.size) {
37 controller._unmount_callbacks.push(callback())
38 } else {
39 controller._mount_callbacks.push(callback)
40 }
41}
42
43export function onUnmount(renderable: Renderable, callback: () => void): void {
44 onMount(renderable, () => callback)
45}