/**
 *
 * Functions (and classes) for creating elements with javascript.
 *
 * Can be used on the server or client. Provides a better DX
 * than manually creating and setting up elements by using
 * call chaining.
 *
 * Benefits:
 * 1. Easily reuse `templates` which are just JS variables here.
 * 2. More natural within js code. Variables can be interpolated naturally.
 * 3. Better intellisense during development.
 * 4. Leads to more confidence about code correctness.
 * 5. Elements can be built more dynamically.
 * 6. Elements can be composed from different places
 * 7. Use the same code to create elements on the client and server.
 * 8. Safe by default. You need to pass functions instead of text to
 * specify HTML text. All text supplied as children are escaped. All
 * attributes are also escaped. (Note this only applies to `render` methods
 * which output HTML text).
 *
 * Notes:
 *
 * 1. This module supersedes 'dom/element/element' but that one has
 * been retained (for now) to avoid new breaking changes with this
 * release. Use this one for new code, and if possible, port old code
 * using the other module to this one.
 *
 * 2. Although this module may seem more verbose, it is actually easier to write
 * because you get autocomplete from the editor/IDE. The explicitness also
 * makes the code easier to remember, understand and maintain.
 *
 */
import { IComponent } from "../dom";
export type IConstructor<T> = {
    new (): T;
    prototype: T;
};
export type IBuilder = Builder<string, typeof Element>;
export type IElementChild = IBuilder | (() => string) | string | number | Element;
/**
 * This will escape all input strings so it is safe by
 * default. Pass a function that returns a string to explicitly
 * indicate that you want the string treated as innerHTML.
 */
export declare class Builder<T extends string, U extends typeof Element> {
    tag: T;
    attrs: object;
    nsAttrs: object;
    props: object;
    children: IElementChild[];
    components: IComponent[];
    parents?: Set<IBuilder>;
    constructor(tag: T, ...children: IElementChild[]);
    set(attrs: {
        [key: string]: any;
    }): this;
    setNs(namespace: string, attrs: {
        [key: string]: any;
    }): this;
    assign(props: object): this;
    prepend(...children: IElementChild[]): this;
    append(...children: IElementChild[]): this;
    replaceChildren(...children: IElementChild[]): this;
    apply(...components: IComponent[]): this;
    replaceComponents(...components: IComponent[]): this;
    render(indent?: number): string;
    build(): InstanceType<U>;
    create(): InstanceType<U>;
    setup(element: InstanceType<U>): InstanceType<U>;
    appendTo(...targets: (Element | IBuilder)[]): this;
    prependTo(...targets: (Element | IBuilder)[]): this;
    insertBefore(...targets: (Element | IBuilder)[]): this;
    insertAfter(...targets: (Element | IBuilder)[]): this;
    replace(...targets: (Element | IBuilder)[]): this;
}
export type IBuilderMethods = IMethods<IBuilder>;
export type IBuilders = {
    builders: Iterable<IBuilder>;
    self?: IBuilders;
} & {
    [key in keyof IBuilderMethods]: (...args: Parameters<IBuilderMethods[key]>) => ReturnType<IBuilderMethods[key]> extends IBuilder ? IBuilders : ReturnType<IBuilderMethods[key]>[];
};
export type ICallable = (...args: any[]) => any;
export type IMethods<T> = {
    [key in keyof T]: T[key] extends ICallable ? T[key] : never;
};
export declare function builders(...builders: Builder<string, typeof Element>[]): IBuilders;
export declare const b: typeof builders;
export declare class HTMLElementBuilder<T extends string & keyof HTMLElementTagNameMap> extends Builder<T, IConstructor<HTMLElementTagNameMap[T]>> {
    create(): HTMLElementTagNameMap[T];
}
/**
 *
 * Returns an HTML builder which can be used to create HTMLElement instances
 * (with `build` method) or their text representations (with `render` method).
 *
 * @example
 * import { html, h } from 'deleight/dom/builder'
 * // const verboseBuilder = html('main').set({ class: 'right bg' }).append(9);
 * const builder = h.main.set({ class: 'right bg' }).append(9);
 *
 * const markup = builder.render();
 * console.log(markup === `
 * <main class="right bg">
 *    9
 * </main>
 * `);      // true
 *
 * const element = builder.build();
 * console.log(element.tagName);     // MAIN
 *
 * @param tag
 * @returns
 */
export declare function html<T extends string & keyof HTMLElementTagNameMap>(tag: T, ...children: IElementChild[]): HTMLElementBuilder<T>;
export type IHtml = typeof html & {
    [key in keyof HTMLElementTagNameMap]: HTMLElementBuilder<key>;
};
export declare const h: IHtml;
export type IHtml2 = typeof html & {
    [key in keyof HTMLElementTagNameMap]: (...children: IElementChild[]) => HTMLElementBuilder<key>;
};
export declare const hh: IHtml2;
export declare class SVGElementBuilder<T extends string & keyof SVGElementTagNameMap> extends Builder<T, IConstructor<SVGElementTagNameMap[T]>> {
    create(): SVGElementTagNameMap[T];
}
/**
 * Similar to {@link html} but for SVG elements.
 *
 * @param tag
 * @returns
 */
export declare function svg<T extends string & keyof SVGElementTagNameMap>(tag: T, ...children: IElementChild[]): SVGElementBuilder<T>;
export type ISvg = typeof svg & {
    [key in keyof SVGElementTagNameMap]: SVGElementBuilder<key>;
};
export declare const s: ISvg;
export type ISvg2 = typeof svg & {
    [key in keyof SVGElementTagNameMap]: (...children: IElementChild[]) => SVGElementBuilder<key>;
};
export declare const ss: ISvg2;
export declare class MathMLElementBuilder<T extends string & keyof MathMLElementTagNameMap> extends Builder<T, IConstructor<MathMLElementTagNameMap[T]>> {
    create(): MathMLElementTagNameMap[T];
}
/**
 * Similar to {@link html} but for MathML elements.
 *
 * @param tag
 * @returns
 */
export declare function math<T extends string & keyof MathMLElementTagNameMap>(tag: T, ...children: IElementChild[]): MathMLElementBuilder<T>;
export type IMath = typeof math & {
    [key in keyof MathMLElementTagNameMap]: MathMLElementBuilder<key>;
};
export declare const m: IMath;
export type IMath2 = typeof math & {
    [key in keyof MathMLElementTagNameMap]: (...children: IElementChild[]) => MathMLElementBuilder<key>;
};
export declare const mm: IMath2;
