UNPKG

@furystack/shades

Version:

A lightweight UI framework for FuryStack with JSX support

65 lines 3 kB
import type { Constructable } from '@furystack/core'; import type { ChildrenList, CSSObject, PartialElement, RenderOptions } from './models/index.js'; export type ShadeOptions<TProps, TElementBase extends HTMLElement> = { /** * The custom element tag name used to register the component. * Must follow the Custom Elements naming convention (lowercase, must contain a hyphen). * * @example 'my-button', 'shade-dialog', 'app-header' */ customElementName: string; render: (options: RenderOptions<TProps, TElementBase>) => JSX.Element | string | null; /** * Tag name of the base built-in element when extending one (e.g. `'a'`, * `'button'`, `'input'`). Required when {@link ShadeOptions.elementBase} * is set; passed to `customElements.define` as `{ extends }`. */ elementBaseName?: string; /** * Constructor of the built-in element to extend (e.g. `HTMLButtonElement`). * Defaults to `HTMLElement`. Pair with {@link ShadeOptions.elementBaseName}. */ elementBase?: Constructable<TElementBase>; /** * Inline styles applied to each component instance. * Use for per-instance dynamic overrides. Prefer `css` for component-level defaults. */ style?: Partial<CSSStyleDeclaration>; /** * CSS styles injected as a stylesheet during component registration. * Supports pseudo-selectors (`&:hover`, `&:active`) and nested selectors (`& .class`). * * **Best practice:** Prefer `css` over `style` for component defaults -- styles are injected * once per component type (better performance), and support pseudo-selectors and nesting. * * @example * ```typescript * css: { * display: 'flex', * padding: '16px', * '&:hover': { backgroundColor: '#f0f0f0' }, * '& .title': { fontWeight: 'bold' } * } * ``` */ css?: CSSObject; }; /** * Defines and registers a Shade component as a custom element. Returns a * JSX-callable factory `(props, children?) => JSX.Element`. Throws when a * component with the same {@link ShadeOptions.customElementName} has * already been registered — registration is global and process-wide. * * The returned factory is the entry point for downstream code. The custom * element class itself is installed via `customElements.define` and never * directly exposed. */ export declare const Shade: <TProps, TElementBase extends HTMLElement = HTMLElement>(o: ShadeOptions<TProps, TElementBase>) => (props: TProps & PartialElement<TElementBase>, children?: ChildrenList) => JSX.Element; /** * Awaits the next microtask tick — long enough for `updateComponent`'s * batching microtask to drain. A single `await flushUpdates()` settles the * entire component tree because child reconciliation is synchronous within * the parent's render. Use in tests before asserting on DOM state. */ export declare const flushUpdates: () => Promise<void>; //# sourceMappingURL=shade.d.ts.map