/** * `attr(name, value)` — create a pre-computed attribute descriptor (static form). * `attr(name)` — create a per-render factory for dynamic attribute values (dynamic form). * * **Static form** — best for fixed action names, filter keys, role values, etc. * Escapes once at module-load time; produces a full {@link AttrSpec} with * `.name`, `.value`, `.selector`, and `.attrs`. * * const ACTIONS = { * toggle: attr('data-action', 'toggle'), * remove: attr('data-action', 'remove'), * } as const satisfies Record>; * * // In JSX — spread .attrs (rename-safe; no hardcoded attribute name): * * * // In delegate — use the pre-computed selector: * delegate(root, 'click', ACTIONS.toggle.selector, handler); * * **Dynamic form** — best for per-row data like `data-id`, where the value * changes per item but the attribute name is constant. * The name is validated and pre-escaped at definition time; calling the * returned factory is cheap (it just freezes a one-key object — the value is * escaped later by the JSX attribute renderer when the result is spread). * * const ITEM = { id: attr('data-id') } as const; * * // In JSX — call the factory inline: *
  • …
  • * * For ad-hoc compound selectors, concatenate `.selector` strings: * * delegate(root, 'click', * ACTIONS.toggle.selector + attr('data-id', id).selector, * handler); * * Escaping: * - Attribute name: escaped as a CSS identifier via `cssEscapeIdent`, which is * an SSR-safe (no `CSS.escape`) adaptation of the Mathias Bynens polyfill * (https://github.com/mathiasbynens/CSS.escape, MIT licensed — see the * Acknowledgements section of LICENSE). Handles * control chars, leading digits, non-ASCII, and CSS metacharacters. * - Attribute value: embedded in double quotes as a CSS string. Backslashes and * double-quote characters are backslash-escaped; control characters are * hex-escaped per CSS Syntax Level 3 §3.4. * * Throws on an empty attribute name (not a valid CSS identifier). */ /** Descriptor created by the static {@link attr} overload. */ interface AttrSpec { /** The raw attribute name passed to `attr()`. */ readonly name: N; /** The raw attribute value passed to `attr()`. */ readonly value: V; /** Pre-computed `[name="value"]` CSS selector string, safe to pass to `delegate()`. */ readonly selector: string; /** Spreadable JSX object — `{ [name]: value }` — keeps the attribute name out of JSX literals. */ readonly attrs: { readonly [K in N]: V; }; } /** * Static overload — pre-computes the full descriptor at definition time. * Returns an {@link AttrSpec} with `.name`, `.value`, `.selector`, and `.attrs`. */ declare function attr(name: N, value: V): AttrSpec; /** * Dynamic overload — pre-validates and pre-escapes the attribute name, returns a * factory that accepts a per-render value and produces a frozen spreadable object. * Use for per-row attributes like `data-id` where the value changes per item. * The optional `V` generic constrains which values the factory accepts: * `attr<'data-id', 'a'|'b'>('data-id')` → `(value: 'a'|'b') => { 'data-id': 'a'|'b' }`. * Leaving both generics off infers `N` from the argument and defaults `V` to `string`. */ declare function attr(name: N): (value: V) => { readonly [K in N]: V; }; export { type AttrSpec as A, attr as a };