UNPKG

@oslokommune/punkt-elements

Version:

Komponentbiblioteket til Punkt, et designsystem laget av Oslo Origo

129 lines (128 loc) 4.96 kB
import { LitElement } from 'lit'; import { AsyncDirective, PartInfo } from 'lit/async-directive.js'; import { ChildPart } from 'lit/directive.js'; /** * Returns the SlotManager for a host, creating one if it doesn't exist. * Call this in connectedCallback() to eagerly collect children before Lit renders. */ export declare function getSlotManager(host: LitElement): SlotManager; /** * Per-host singleton that manages node collection and observation. * Scans host children, categorizes them by slot attribute, and notifies * registered directives when children change. * * IMPORTANT: collectNodes() must be called BEFORE Lit's first render * (typically in connectedCallback via PktElement.hasSlotContent or getSlotManager). * Lit's first render clears host children, so collecting during render is too late. */ export declare class SlotManager { private host; private observer; private nodesBySlot; private directives; private observing; private trackedNodes; generation: number; private initialCollectionDone; private processingMutations; private placeholderToNode; private nodeToPlaceholder; private static PLACEHOLDER_PREFIX; constructor(host: LitElement); /** * Collect original children BEFORE Lit's first render. * Must be called in connectedCallback or earlier. * Safe to call multiple times — only the first call scans. */ collectNodes(): void; /** * Register a directive instance and start observing for dynamic changes. */ addDirective(d: SlotContentDirective): void; /** * Unregister a directive instance. Stops observing if no directives remain. */ removeDirective(d: SlotContentDirective): void; /** * Returns nodes matching the given slot name. */ getNodes(slotName?: string): Node[]; /** * Returns whether the given slot has any content. */ hasContent(slotName?: string): boolean; /** * Ensure a placeholder comment exists for a node that is about to be distributed. * Called by the directive before Lit moves the node to the target position. * The placeholder stays between Lit's ChildPart markers so that when the parent * template conditionally removes the content, the MutationObserver can detect * the placeholder removal and clean up the real node. */ ensurePlaceholder(node: Node): void; /** * Start MutationObserver for dynamic child changes. * Deferred via setTimeout to avoid catching Lit's first render mutations. */ private startObserving; private stopObserving; /** * Handle MutationObserver mutations incrementally. * Only processes nodes that are NOT already part of Lit's rendered template. * * Uses a guard flag to prevent recursive handling: when notifyDirectives() * causes setValue() to move nodes (e.g., from host into a ChildPart container), * that move triggers another mutation which must be ignored. */ private handleMutations; /** * Determines if a node is user-provided content (not Lit's rendered template). * Lit's rendered content includes comment markers and elements created by the template. */ private isUserContent; private removeFromSlots; private notifyDirectives; } /** * AsyncDirective that renders slot content at its position in a Lit template. * * Usage: * html`<div>${slotContent(this)}</div>` // default slot * html`<div>${slotContent(this, 'helptext')}</div>` // named slot */ declare class SlotContentDirective extends AsyncDirective { private manager; private slotName; private lastGeneration; constructor(partInfo: PartInfo); render(_host: LitElement, _slotName?: string): unknown; update(_part: ChildPart, [host, slotName]: [LitElement, string?]): unknown; /** * Called by SlotManager when child mutations are detected. * Uses setValue() to push an async update to Lit. */ handleNodesChanged(): void; /** * Insert placeholders for nodes that are still direct children of the host. * Must be called before Lit moves them to the target position. */ private ensurePlaceholders; disconnected(): void; reconnected(): void; private getNodesOrNoChange; } /** * Directive that distributes Light DOM children into Lit template positions, * functioning like Shadow DOM slots but without a shadow root. * * @param host - The component instance (typically `this`) * @param slotName - Optional slot name. Omit for the default slot. * * @example * // Default slot * html`<div class="content">${slotContent(this)}</div>` * * // Named slot * html`<div class="help">${slotContent(this, 'helptext')}</div>` */ export declare const slotContent: (_host: LitElement, _slotName?: string | undefined) => import('lit-html/directive.js').DirectiveResult<typeof SlotContentDirective>; export {};