UNPKG

@frontmeans/drek

Version:
695 lines (677 loc) 26.5 kB
/// <reference lib="dom" /> /// <reference lib="es2019" /> declare module "@frontmeans/drek" { /** * A rendered content status. */ export interface DrekContentStatus { /** * Whether the content connected to the document. * * This is always `true` for document content, but may be `false` e.g. until a fragment is {@link DrekFragment.render * rendered}. */ readonly connected: boolean; readonly withinFragment?: unknown | undefined; } } declare module "@frontmeans/drek" { import { AfterEvent, AfterEvent__symbol, EventKeeper, OnEvent } from "@proc7ts/fun-events"; /** * A rendered content placement. * * @typeParam TStatus - A type of the tuple containing a rendered content status as its first element. */ export abstract class DrekPlacement<TStatus extends [ DrekContentStatus ] = [ DrekContentStatus ]> implements EventKeeper<TStatus> { /** * An `AfterEvent` keeper of content placement status. */ abstract readonly readStatus: AfterEvent<TStatus>; constructor(); /** * A {@link DrekFragment fragment} the content is placed to, if any. */ abstract readonly fragment: DrekFragment | undefined; /** * An alias of {@link readStatus}. * * @returns An `AfterEvent` keeper of content placement status. */ [AfterEvent__symbol](): AfterEvent<TStatus>; /** * An `OnEvent` sender of placed content connection event. * * The registered receiver is called when placed content is {@link DrekContentStatus.connected connected}. * If connected already the receiver is called immediately. */ get onceConnected(): OnEvent<TStatus>; /** * An `OnEvent` sender of single placed content connection event. * * The registered receiver is called when placed content is {@link DrekContentStatus.connected connected}. * If connected already the receiver is called immediately. * * In contrast to {@link onceConnected}, cuts off the event supply after sending the first event. */ get whenConnected(): OnEvent<TStatus>; } } declare module "@frontmeans/drek" { /** * Obtains an updatable rendering context of the given document. * * @param document - Target document. * * @returns Updatable document rendering context. */ export function drekContextOf(document: Document): DrekContext.Updatable; /** * Obtains a rendering context of the given node. * * If the node is connected to document, then the rendering context of that document is returned. Otherwise, if the node * belongs to the {@link DrekFragment.content content} of the rendered fragment, then the context * {@link DrekFragment.innerContext provided} by that fragment is returned. Otherwise, an unrooted context is created * and attached to the [root node] of the target `node`. * * [root node]: https://developer.mozilla.org/en-US/docs/Web/API/Node/getRootNode * * @param node - Target node. * * @returns Target node rendering context. */ export function drekContextOf(node: Node): DrekContext; } declare module "@frontmeans/drek" { /** * Rendering target. * * Represents a part of the DOM tree to place the rendered content to. * * @typeParam TStatus - A tuple type reflecting a content {@link DrekContentStatus placement status}. */ export interface DrekTarget<TStatus extends [ DrekContentStatus ] = [ DrekContentStatus ]> { /** * Rendering context of this rendering target. */ readonly context: DrekContext; /** * A DOM node that serves as a host of {@link placeContent placed content}. */ readonly host: Node; /** * Places rendered content to this target. * * It is up to the implementation to decide how the content is placed. E.g. some implementations append the content, * while the others replace it. * * It is expected that this operation is performed within a render scheduler the user chooses, probably the one of * rendering {@link context}. * * @param content - Rendered DOM node to place. * * @returns Rendered content placement status. */ placeContent(content: Node): DrekPlacement<TStatus>; } } declare module "@frontmeans/drek" { /** * Creates a rendering target that appends content to parent node. * * @param host - A node to append content to. * @param context - Custom rendering context. Defaults to `host` node context. * * @returns Rendering target. */ export function drekAppender(host: Node, context?: DrekContext): DrekTarget; } declare module "@frontmeans/drek" { /** * Creates a rendering target that charges rendered content prior to placing it to another target. * * @typeParam TStatus - A tuple type reflecting a content {@link DrekContentStatus placement status}. * @param target - Rendering target of charged content. * @param spec - Content charging options. * * @returns Rendering target. */ export function drekCharger<TStatus extends [ DrekContentStatus ] = [ DrekContentStatus ]>(target: DrekTarget<TStatus>, spec?: DrekCharger.Spec<TStatus>): DrekTarget; export namespace DrekCharger { /** * Rendered content charger specifier. * * Can be one of: * * - An arbitrary string containing a text for enclosing comments. * - A {@link Custom custom charger}. * - A {@link Factory charger factory} function. * - `null`/`undefined` to enclose the rendered contents in comments with random text. * * @typeParam TStatus - A tuple type reflecting a content {@link DrekContentStatus placement status}. */ type Spec<TStatus extends [ DrekContentStatus ] = [ DrekContentStatus ]> = string | Custom | Factory<TStatus> | null | undefined; /** * Custom rendered content charger. */ interface Custom { /** * Charges rendered content by representing it as another DOM node. * * @typeParam TStatus - A tuple type reflecting a content {@link DrekContentStatus placement status}. * @param content - Rendered content to charge. * @param target - Rendering target to place the charged content to. * * @returns Charged content placement status. */ charge<TStatus extends [ DrekContentStatus ]>(content: Node, target: DrekTarget<TStatus>): DrekPlacement<TStatus>; } /** * Rendered content charger factory signature. * * @typeParam TStatus - A tuple type reflecting a content {@link DrekContentStatus placement status}. */ type Factory<TStatus extends [ DrekContentStatus ] = [ DrekContentStatus ]> = /** * @param target - A target to render the charged content to. * * @returns Rendered content charger specifier. */ (this: void, target: DrekTarget<TStatus>) => Spec; } } declare module "@frontmeans/drek" { /** * Creates a rendering target that inserts content to parent node at particular position. * * @param host - A node to insert content to. * @param before - A child node of `host` one to insert the content before, or `null` to append it as the last child * of `host` node. * @param context - Custom rendering context. Defaults to `host` node context. * * @returns Rendering target. */ export function drekInserter(host: Node, before: Node | null, context?: DrekContext): DrekTarget; } declare module "@frontmeans/drek" { /** * Creates a rendering target that replaces content of the `host` node. * * @param host - A node to replace the content of. * @param context - Custom rendering context. Defaults to `host` node context. * * @returns Rendering target. */ export function drekReplacer(host: Node, context?: DrekContext): DrekTarget; } declare module "@frontmeans/drek" { import { RenderExecution, RenderSchedule, RenderScheduleOptions } from "@frontmeans/render-scheduler"; /** * Fragment render scheduler signature. * * @typeParam TStatus - A type of the tuple containing a rendered content status as its first element. */ export type DrekFragmentRenderScheduler<TStatus extends [ DrekContentStatus ] = [ DrekContentStatus ]> = /** * @param options - Options of constructed render schedule. * * @returns New render schedule. */ (this: void, options?: RenderScheduleOptions) => RenderSchedule<DrekFragmentRenderExecution<TStatus>>; /** * Fragment render shot execution context. * * @typeParam TStatus - A type of the tuple containing a rendered content status as its first element. */ export interface DrekFragmentRenderExecution<TStatus extends [ DrekContentStatus ] = [ DrekContentStatus ]> extends RenderExecution { /** * Rendered fragment instance. */ readonly fragment: DrekFragment<TStatus>; /** * The content of the rendered fragment. */ readonly content: DocumentFragment; } } declare module "@frontmeans/drek" { import { NamespaceAliaser } from "@frontmeans/namespace-aliaser"; import { RenderScheduler } from "@frontmeans/render-scheduler"; import { OnEvent } from "@proc7ts/fun-events"; /** * A fragment of DOM tree, which content is to be {@link DrekTarget#placeContent placed} to the document once rendered. * * Provides separate {@link DrekContext rendering context} for its nodes. * * @typeParam TStatus - A type of the tuple containing a rendered content status as its first element. */ export class DrekFragment<TStatus extends [ DrekContentStatus ] = [ DrekContentStatus ]> { /** * Rendering target. * * When the fragment is {@link render rendered}, the rendered content is placed to this target. */ get target(): DrekTarget; /** * Inner rendering context of the fragment. * * This context as available to the {@link content} nodes. * * This context updated each time the fragment is {@link render rendered}. */ get innerContext(): DrekFragment.InnerContext<TStatus>; /** * The content of the fragment. */ get content(): DocumentFragment; /** * An `OnEvent` sender of fragment rendering event. * * Sends a fragment content {@link DrekTarget#placeContent placement} to {@link target} when the fragment is actually * {@link render rendered}. * * Cuts off the event supply after sending the first event. */ get whenRendered(): OnEvent<[ DrekPlacement<DrekFragment.Status<TStatus>> ]>; /** * Construct rendered fragment. * * @param target - Rendering target to place the * @param options - Fragment rendering options. */ constructor(target: DrekTarget<TStatus>, options?: DrekFragment.Options); /** * Settles previously rendered content. * * A {@link DrekContext#whenSettled} event sender notifies its receivers once settled. * * @returns `this` instance. */ settle(): this; /** * Renders this fragment by {@link DrekTarget#placeContent placing} its {@link DrekFragmentRenderExecution#content * content} to {@link target rendering target}. * * Once rendered the fragment {@link content} becomes empty and can be reused. Its rendering context is updated. * * @returns Content {@link DrekTarget#placeContent placement} to {@link target}. */ render(): DrekPlacement<DrekFragment.Status<TStatus>>; } export namespace DrekFragment { /** * Rendering context provided by fragment to its content nodes. * * @typeParam TStatus - A type of the tuple containing a rendered content status as its first element. */ interface InnerContext<TStatus extends [ DrekContentStatus ]> extends DrekContext<Status<TStatus>> { readonly scheduler: DrekFragmentRenderScheduler<TStatus>; /** * Tries to lift this rendering context to {@link DrekFragment#target target} one. * * @returns The {@link DrekFragment#target target's} context when the fragment is rendered, or `this` instance * otherwise. */ lift(): DrekContext; } /** * A status of rendered fragment content. */ type Status<TStatus extends [ DrekContentStatus ]> = [ OwnStatus ] | TStatus; /** * A status of rendered fragment content. * * This status is replaced by the target one */ interface OwnStatus extends DrekContentStatus { readonly connected: false; /** * A status of the content within a fragment. * * Can be one of: * * - `'added'` - when the content is added to the fragment, but not yet rendered. * - `'rendered'` - while the content is being rendered, but not yet placed to {@link DrekFragment#target target}. */ readonly withinFragment: 'added' | 'rendered'; } /** * Rendered fragment construction options. */ interface Options { /** * Namespace aliaser to use by content nodes. * * The one from the {@link DrekTarget#context target context} is used when omitted. */ readonly nsAlias?: NamespaceAliaser | undefined; /** * Render scheduler to use by content nodes. * * A `queuedRenderScheduler` is used when omitted. */ readonly scheduler?: RenderScheduler | undefined; /** * The content of constructed fragment. * * A new document fragment will be created when omitted. */ readonly content?: DocumentFragment | undefined; } } } declare module "@frontmeans/drek" { import type { NamespaceAliaser } from "@frontmeans/namespace-aliaser"; import type { RenderScheduler } from "@frontmeans/render-scheduler"; import { OnEvent } from "@proc7ts/fun-events"; /** * Document rendering context. * * Can be obtained by {@link drekContextOf} function, or {@link DrekFragment#innerContext provided} by rendered * fragment. * * There are three kinds of rendering contexts: * * 1. Document rendering context. * * Such context is always available in document and returned by {@link drekContextOf} function for any DOM node * connected to the document. * * 2. Fragment content rendering context. * * It is created for each rendered fragment and is available via {@link DrekFragment#innerContext} property. * The {@link drekContextOf} function returns this context for fragment's {@link DrekFragment#content content}, * as well as for each DOM node added to it. * * 3. Unrooted rendering context. * * When a DOM node is neither connected to a document, nor part of a rendered fragment's * {@link DrekFragment#content content}, the {@link drekContextOf} function creates an unrooted context for the * [root node] of that node. * * Unrooted context tracks a {@link DrekPlacement#whenConnected document connection} and * {@link DrekContext#whenSettled settlement} semi-automatically. A {@link DrekContext#lift} method can be used * to forcibly update them. * * Semi-automatic tracking means that each time an unrooted context {@link drekContextOf created}, it is registered * for automatic lifting. The lifting happens either asynchronously, or synchronously right before the * {@link drekBuild} function exit. * * Alternatively, a {@link drekLift} function can be used to lift a context of the [root node] after adding it to * another one. * * [root node]: https://developer.mozilla.org/en-US/docs/Web/API/Node/getRootNode * * @typeParam TStatus - A type of the tuple containing a context content status as its first element. */ export abstract class DrekContext<TStatus extends [ DrekContentStatus ] = [ DrekContentStatus ]> extends DrekPlacement<TStatus> { /** * A rendered {@link DrekFragment fragment} this context is provided by, if any. */ abstract readonly fragment: DrekFragment | undefined; /** * The window this context belongs to. */ abstract readonly window: Window; /** * The document this context belongs to. */ abstract readonly document: Document; /** * Namespace aliaser to use. */ abstract readonly nsAlias: NamespaceAliaser; /** * Render scheduler to use. */ abstract readonly scheduler: RenderScheduler; /** * An `OnEvent` sender of a settlement event. * * Such event can be sent by {@link DrekFragment.settle rendered fragment}. * * The same as {@link whenConnected} by default. * * Cuts off the event supply after sending the first event. */ get whenSettled(): OnEvent<TStatus>; /** * Tries to lift this rendering context to enclosing one. * * Tries to find a new root node. If the new root differs from current one, then {@link drekContextOf finds} a context * of that new root and connects the status of this context to the found one. After successful lifting the context * becomes a proxy accessor of the context it is lifted to, so the latter can be used instead. * * This has effect for unrooted contexts only. * * @returns Either a rendering context of the new root node, or this one. */ abstract lift(): DrekContext; } export namespace DrekContext { /** * Updatable document rendering context. */ interface Updatable extends DrekContext { /** * Updates this context. * * @param update - An update to apply to this context. * * @returns `this` instance. */ update(update?: Update): this; } /** * An update to rendering context. */ interface Update { /** * Namespace aliaser to use. * * The aliaser is not updated when omitted. */ readonly nsAlias?: NamespaceAliaser | undefined; /** * Render scheduler to use. * * The scheduler is not updated when omitted. */ readonly scheduler?: RenderScheduler | undefined; } } } declare module "@frontmeans/drek" { /** * Executes a DOM builder function and then {@link DrekContext.lift lifts} all unrooted rendering contexts created by * it. * * This helps to track a {@link DrekContext.whenConnected document connection} or {@link DrekContext.whenSettled * settlement} of any unrooted rendering contexts that created before its node added to document or * {@link DrekFragment rendered fragment}. This may happen e.g. when the rendering context {@link drekContextOf * accessed} from inside a custom element constructor when calling `document.createElement('custom-element')`. * * @typeParam TResult - DOM builder result type. * @param builder - A DOM builder function to call. * * @returns The value returned from DOM `builder` function. */ export function drekBuild<TResult>(builder: (this: void) => TResult): TResult; } declare module "@frontmeans/drek" { import { QualifiedName } from "@frontmeans/namespace-aliaser"; import { Supply, SupplyPeer } from "@proc7ts/supply"; /** * An accessor to CSS classes of some element. * * Can be obtained by {@link drekCssClassesOf} function. */ export interface DrekCssClasses { /** * Adds CSS class to target element. * * The same CSS class can be supplied multiple times. In this case the class would be removed when no more suppliers * left. * * Utilizes a {@link DrekContext.nsAlias namespace aliaser} of element rendering context for resolving class names. * * {@link DrekContext.scheduler Schedules} element CSS updates via element rendering context. * * @param className - CSS class name to add. Either a string or qualified one. * @param user - A supply peer of the CSS class. When specified, its supply us returned from the method call. * * @returns Added CSS class supply that removes the class once cut off, unless there are other supplies of the same * class. */ add(className: QualifiedName, user?: SupplyPeer): Supply; /** * Checks whether the target element has the given CSS class. * * @param className - CSS class name to check. Either a string or qualified one. * * @returns `true` if the target element has this class, or `false` otherwise. */ has(className: QualifiedName): boolean; /** * Obtains CSS classes accessor using different rendering context., * * @param context - A rendering context to use instead of the {@link drekContextOf default one}. * * @returns Either new CSS classes accessor instance, or `this` one if context is the same. */ renderIn(context: DrekContext): DrekCssClasses; } /** * Obtains CSS classes of the given element. * * @param element - Target element. * * @returns CSS classes accessor, either already existing or newly created one. */ export function drekCssClassesOf(element: Element): DrekCssClasses; } declare module "@frontmeans/drek" { /** * Creates a rendering context based on another one. * * @typeParam TStatus - A type of the tuple containing a context content status as its first element. * @param base - Base rendering context. * @param update - Context update. * * @returns Updated rendering context, or the `base` one if nothing to update. */ export function deriveDrekContext<TStatus extends [ DrekContentStatus ] = [ DrekContentStatus ]>(base: DrekContext<TStatus>, update?: DrekContext.Update): DrekContext<TStatus>; } declare module "@frontmeans/drek" { /** * Finds a host element of the given DOM node with respect to rendering targets. * * Crosses shadow DOM and {@link DrekFragment rendered fragment} bounds. In the latter case returns a * {@link DrekTarget.host rendering target host} instead of the document fragment. * * @param node - Target DOM element. * * @returns Either parent element of the given node, or `undefined` when not found. */ export function drekHost(node: Node): Element | undefined; } declare module "@frontmeans/drek" { /** * Tries to {@link DrekContext.lift lift} the rendering context of the given DOM `node` to enclosing one. * * It may be useful to call this method e.g. on a custom element after appending it to {@link DrekFragment fragment}. * The former may access its rendering context in constructor. Calling this method would lift that context to fragment's * one, so the custom element would be notified on its {@link DrekContext.whenSettled settlement}. * * Does nothing if the given node has no rendering context attached to it. * * @param node - A DOM node with rendering context to lift. * * @returns The `node` itself. */ export function drekLift<TNode extends Node>(node: TNode): TNode; } declare module "@frontmeans/drek" { import { CxEntry } from "@proc7ts/context-values"; /** * Document render kit instance. */ export interface DocumentRenderKit { /** * Obtains a rendering context of the given DOM node. * * Does the same as {@link drekContextOf} function, and also makes sure that the rendering context for the document * is initialized with global `RenderScheduler` and `NamespaceAliaser`. * * @param node - Target DOM node. * * @returns Target node rendering context. */ contextOf(node: Node): DrekContext; } /** * Context entry containing {@link DocumentRenderKit} instance. * * Initiated lazily. So the replacement should be provided before the kit used for the first time. * * Constructs global render kit instance by default. */ export const DocumentRenderKit: CxEntry<DocumentRenderKit>; } declare module "@frontmeans/drek" { import { NamespaceDef } from "@frontmeans/namespace-aliaser"; /** * Default Drek namespace definition. */ export const Drek__NS: NamespaceDef; } //# sourceMappingURL=drek.d.ts.map