/** * Build and register a Custom Element class from a component definition. * * @template {Record} [TData=Record] * @template {Record} [TProps=Record] * @param {string} tagName Custom element tag (must contain a hyphen, or `domma-` is prefixed) * @param {ComponentDefinition} definition Component definition object * @returns {typeof DommaElement|undefined} The element class, or undefined when the tag is already registered */ export function createComponent = Record, TProps extends Record = Record>(tagName: string, definition: ComponentDefinition): typeof DommaElement | undefined; export namespace components { /** * Define and register a new component. * * @template {Record} [TData=Record] * @template {Record} [TProps=Record] * @param {string} tagName Custom element tag name * @param {ComponentDefinition} definition Component definition * @returns {typeof DommaElement|undefined} The element class, or undefined when the tag is already registered */ function define = Record, TProps extends Record = Record>(tagName: string, definition: ComponentDefinition): typeof DommaElement | undefined; /** * Returns true if a component with this tag name has been registered. * @param {string} tagName * @returns {boolean} */ function has(tagName: string): boolean; /** * Returns a copy of the component registry (for tooling / inspection). * @returns {Map} */ function registry(): Map; const templateCache: Map; } /** * Valid primitive type tokens for component props. */ export type PropType = "string" | "number" | "boolean" | "array" | "object" | "any"; /** * A declared prop: an HTML attribute coerced to a type. `number` -> Number (NaN -> null), * `boolean` -> '' / 'true' are true, 'false' false; `array` / `object` -> JSON.parse (the raw * string when it is not JSON); anything else stays a string. */ export type PropDefinition = { /** * - Expected type - a token or an `M.types.*` constant */ type?: PropType | ((value: any) => boolean) | undefined; /** * - Marks the prop as required (documentation only - not enforced) */ required?: boolean | undefined; /** * - Value used when the attribute is absent; a function is called for it */ default?: any; }; /** * `this` inside a component's hooks, computed properties and methods. Computed properties are * also on it as getters (`this.fullName`) and methods as bound functions (`this.save()`). */ export type ComponentContext = Record, TProps extends Record = Record> = { /** * - Live, read-tracked view of the reactive data; reads inside a computed register a dependency */ data: TData; /** * - Resolved prop values after type coercion (a copy) */ props: TProps; /** * - The Shadow DOM root of this component */ root: ShadowRoot; /** * - The host Custom Element */ el: HTMLElement; /** * - Batch-update reactive data fields; bound template text updates surgically, then `onUpdated` runs */ set: (updates: Partial) => void; }; /** * A component definition for `Domma.component(tagName, definition)`. */ export type ComponentDefinition = Record, TProps extends Record = Record> = { /** * - Inline Mustache template string. Use `templateUrl` for non-trivial templates */ template?: string | undefined; /** * - URL to an external HTML template file, fetched once and cached across all instances */ templateUrl?: string | undefined; /** * - Declared HTML attributes (camelCase name, kebab-case attribute) with type coercion and defaults */ props?: Record | undefined; /** * - Factory returning the component's initial reactive state; called once per instance. Declare every field here */ data?: (() => TData) | undefined; /** * - Derived values, memoised and recalculated when a field they read changes; available in templates and as `this.name` */ computed?: Record) => any> | undefined; /** * - Functions bound to the component context; callable as `this.name()` and from `data-on-*` bindings */ methods?: Record, ...args: any[]) => any> | undefined; /** * - Scoped CSS injected into the component's Shadow DOM `