import type { RenderOptions } from "./render"; const states = new WeakMap>(); type BoundaryRender = (options?: RenderOptions) => boolean; type BoundaryState = { current: T | null; render: BoundaryRender | null; attachment: object | null; }; export interface Boundary { readonly current: T | null; render(options?: RenderOptions): boolean; } export function createBoundary(): Boundary { const state: BoundaryState = { current: null, render: null, attachment: null, }; const boundary: Boundary = { get current() { return state.current; }, render(options) { return state.render?.(options) ?? false; }, }; states.set(boundary, state as BoundaryState); return boundary; } export function isBoundary(value: unknown): value is Boundary { return !!value && typeof value === "object" && states.has(value); } export function attachBoundary( boundary: Boundary, element: Element, attachment: object, render: BoundaryRender, ): void { const state = states.get(boundary); if (!state) return; if ( state.attachment && state.attachment !== attachment && state.current !== element ) { throw new Error( "[tradjs] A boundary can be mounted on only one host element at a time.", ); } state.current = element; state.attachment = attachment; state.render = render; } export function detachBoundary( boundary: Boundary, element: Element, attachment: object, ): void { const state = states.get(boundary); if (!state || state.attachment !== attachment || state.current !== element) { return; } state.current = null; state.attachment = null; state.render = null; }