/// <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
