@furystack/shades
Version:
A lightweight UI framework for FuryStack with JSX support
65 lines • 3 kB
TypeScript
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