@domphy/ui 0.22.3 → 0.22.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/dist/core-theme-ui.global.js +1 -1
- package/dist/core-theme-ui.global.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/patches/abbreviation.ts","../src/patches/accordion.ts","../src/utils/focusRing.ts","../src/patches/alert.ts","../src/patches/avatar.ts","../src/patches/badge.ts","../src/patches/blockquote.ts","../src/patches/breadcrumb.ts","../src/patches/breadcrumbEllipsis.ts","../src/patches/button.ts","../src/utils/buttonSize.ts","../src/patches/buttonGhost.ts","../src/patches/buttonSwitch.ts","../src/patches/card.ts","../src/utils/elevation.ts","../src/patches/code.ts","../src/patches/combobox.ts","../src/utils/fieldText.ts","../src/utils/floating.ts","../src/utils/openState.ts","../src/utils/optionList.ts","../src/patches/tag.ts","../src/patches/command.ts","../src/patches/datePicker.ts","../src/patches/descriptionList.ts","../src/patches/details.ts","../src/patches/dialog.ts","../src/utils/scrollLock.ts","../src/patches/divider.ts","../src/patches/drawer.ts","../src/patches/emphasis.ts","../src/patches/empty.ts","../src/patches/errorBoundary.ts","../src/patches/fab.ts","../src/patches/figure.ts","../src/patches/formGroup.ts","../src/patches/grid.ts","../src/patches/heading.ts","../src/patches/horizontalRule.ts","../src/patches/icon.ts","../src/patches/image.ts","../src/patches/inputCheckbox.ts","../src/patches/inputColor.ts","../src/patches/inputDateTime.ts","../src/patches/inputFile.ts","../src/patches/inputNumber.ts","../src/patches/inputOTP.ts","../src/patches/inputPassword.ts","../src/patches/inputRadio.ts","../src/patches/inputRange.ts","../src/patches/inputSearch.ts","../src/patches/inputSwitch.ts","../src/patches/inputText.ts","../src/patches/keyboard.ts","../src/patches/label.ts","../src/patches/link.ts","../src/patches/linkButton.ts","../src/patches/list.ts","../src/patches/mark.ts","../src/patches/menu.ts","../src/patches/motion.ts","../src/utils/reducedMotion.ts","../src/patches/orderedList.ts","../src/patches/pagination.ts","../src/patches/panelSection.ts","../src/patches/paragraph.ts","../src/patches/popover.ts","../src/patches/popoverArrow.ts","../src/patches/preformated.ts","../src/patches/progress.ts","../src/patches/rating.ts","../src/utils/direction.ts","../src/patches/ringProgress.ts","../src/patches/row.ts","../src/patches/scrollArea.ts","../src/patches/segmented.ts","../src/patches/select.ts","../src/patches/selectBox.ts","../src/patches/selectItem.ts","../src/patches/selectList.ts","../src/patches/skeleton.ts","../src/patches/small.ts","../src/patches/spinner.ts","../src/patches/splitter.ts","../src/patches/stack.ts","../src/patches/steps.ts","../src/patches/strong.ts","../src/patches/subscript.ts","../src/patches/superscript.ts","../src/patches/table.ts","../src/patches/tabs.ts","../src/patches/textarea.ts","../src/patches/timeline.ts","../src/patches/toast.ts","../src/patches/toggleGroup.ts","../src/patches/toolbar.ts","../src/patches/tooltip.ts","../src/patches/transitionGroup.ts","../src/patches/unorderedList.ts","../src/patches/visuallyHidden.ts"],"sourcesContent":["export * from \"./classes.js\";\nexport * from \"./patches.js\";\nexport * from \"./types.js\";\nexport * from \"./utils.js\";\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * Styles an abbreviation/acronym with a dotted underline and a \"help\" cursor,\n * shifting to the accent color on hover. Apply to an `<abbr>` element.\n *\n * @hostTag abbr\n * @param props.color - Base text/decoration color tone. Optional `ValueOrState<ThemeColor>`, default \"neutral\".\n * @param props.accentColor - Hover color tone. Optional `ValueOrState<ThemeColor>`, default \"primary\".\n * @example { abbr: \"HTML\", title: \"HyperText Markup Language\", $: [abbreviation({ accentColor: \"primary\" })] }\n */\nfunction abbreviation(\n props: {\n color?: ValueOrState<ThemeColor>;\n accentColor?: ValueOrState<ThemeColor>;\n } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n const accentColor = toState(props.accentColor ?? \"primary\", \"accentColor\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"abbr\") {\n console.warn(`\"abbreviation\" primitive patch must use abbr tag`);\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener),\n backgroundColor: (listener) => themeColor(listener),\n color: (listener) =>\n themeColor(listener, \"shift-10\", color.get(listener)),\n textDecorationLine: \"underline\",\n textDecorationStyle: \"dotted\",\n textDecorationColor: (listener) =>\n themeColor(listener, \"shift-7\", color.get(listener)),\n textUnderlineOffset: themeSpacing(0.72),\n cursor: \"help\",\n \"&:hover\": {\n color: (listener) =>\n themeColor(listener, \"shift-11\", accentColor.get(listener)),\n textDecorationColor: (listener) =>\n themeColor(listener, \"shift-9\", accentColor.get(listener)),\n },\n },\n };\n}\n\nexport { abbreviation };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * Container patch that groups `<details>` elements into a bordered accordion.\n * In `type: \"single\"` mode (default), opening one item closes all siblings.\n *\n * @param props.type - `\"single\"` (default) or `\"multiple\"`. Single mode auto-closes siblings.\n * @param props.color - Theme color tone for borders and backgrounds. Defaults to `\"neutral\"`.\n * @param props.accentColor - Accent color for focus rings on summary. Defaults to `\"primary\"`.\n * @example\n * { div: [\n * { details: [{ summary: \"Section A\" }, { p: \"Content A\" }], $: [details()] },\n * { details: [{ summary: \"Section B\" }, { p: \"Content B\" }], $: [details()] },\n * ], $: [accordion()] }\n */\nfunction accordion(\n props: {\n type?: \"single\" | \"multiple\";\n color?: ValueOrState<ThemeColor>;\n accentColor?: ValueOrState<ThemeColor>;\n } = {},\n): PartialElement {\n const { type = \"single\" } = props;\n const color = toState(props.color ?? \"neutral\", \"color\");\n const accentColor = toState(props.accentColor ?? \"primary\", \"accentColor\");\n\n return {\n _onMount: (node) => {\n const el = node.domElement;\n if (!el) return;\n\n if (type === \"single\") {\n const handler = (event: Event) => {\n const summary = (event.target as Element).closest(\"summary\");\n if (!summary) return;\n const item = summary.closest(\"details\") as HTMLDetailsElement | null;\n if (!item || item.parentElement !== el) return;\n if (!item.open) {\n Array.from(el.querySelectorAll(\":scope > details\")).forEach(\n (detail) => {\n if (detail !== item)\n (detail as HTMLDetailsElement).open = false;\n },\n );\n }\n };\n el.addEventListener(\"click\", handler);\n node.addHook(\"Remove\", () => el.removeEventListener(\"click\", handler));\n }\n\n // WAI-ARIA APG accordion pattern (optional, both modes): ArrowUp/Down\n // moves focus between headers, Home/End jump to the first/last. Tab\n // already reaches every summary; this is an accelerator on top of it.\n const onKeyDown = (event: Event) => {\n const key = (event as KeyboardEvent).key;\n if (![\"ArrowUp\", \"ArrowDown\", \"Home\", \"End\"].includes(key)) return;\n const summary = (event.target as Element).closest(\"summary\");\n if (!summary) return;\n const item = summary.closest(\"details\") as HTMLDetailsElement | null;\n if (!item || item.parentElement !== el) return;\n const summaries = Array.from(\n el.querySelectorAll<HTMLElement>(\":scope > details > summary\"),\n );\n const index = summaries.indexOf(summary as HTMLElement);\n if (index === -1) return;\n let next = index;\n if (key === \"ArrowDown\") next = (index + 1) % summaries.length;\n else if (key === \"ArrowUp\")\n next = (index - 1 + summaries.length) % summaries.length;\n else if (key === \"Home\") next = 0;\n else if (key === \"End\") next = summaries.length - 1;\n event.preventDefault();\n summaries[next]?.focus();\n };\n el.addEventListener(\"keydown\", onKeyDown);\n node.addHook(\"Remove\", () =>\n el.removeEventListener(\"keydown\", onKeyDown),\n );\n },\n style: {\n display: \"flex\",\n flexDirection: \"column\",\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", color.get(listener))}`,\n outlineOffset: \"-1px\",\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n overflow: \"hidden\",\n \"& > details\": {\n borderBottom: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", color.get(listener))}`,\n },\n \"& > details:last-child\": {\n borderBottom: \"none\",\n },\n \"& > details > summary:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, accentColor.get(listener)),\n },\n },\n };\n}\n\nexport { accordion };\n","import type { Listener } from \"@domphy/core\";\nimport { type ThemeColor, themeColor } from \"@domphy/theme\";\n\n/**\n * Shared `:focus-visible` ring — ring-offset pattern used by Radix / shadcn /\n * Vercel / Linear:\n *\n * 1. 2px \"gap\" in the surface tone (reads as space between control + ring)\n * 2. 2px accent halo outside that gap\n *\n * Implemented as a layered `box-shadow` so it composes with a control's own\n * resting outline / elevation instead of replacing them. Prefer this over a\n * flush `0 0 0 2px` ring (looks like a thick pastel border glued to the edge)\n * and over the browser default outline.\n *\n * Accent at `shift-9` stays legible on both light and dark surfaces; the\n * washed `shift-6` flush ring is what made focus look broken in product UIs.\n */\nfunction focusRing(listener: Listener, color: ThemeColor = \"primary\"): string {\n const gap = themeColor(listener, \"surface\");\n const ring = themeColor(listener, \"shift-9\", color);\n return `0 0 0 2px ${gap}, 0 0 0 4px ${ring}`;\n}\n\nexport { focusRing };\n","import type { PartialElement } from \"@domphy/core\";\nimport { toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * A semantic alert surface block with a colored inset bar, padding, and\n * `role=\"alert\"`. Typically applied to a `<div>` (any block container).\n *\n * @param props.color - Surface/accent color tone. Optional `ValueOrState<ThemeColor>`, default \"primary\".\n * @example { div: \"Saved successfully\", $: [alert({ color: \"success\" })] }\n */\nfunction alert(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"primary\", \"color\");\n\n return {\n role: \"alert\",\n // Alert is a semantic surface block, so it should shift the local surface context.\n dataTone: \"shift-2\",\n style: {\n display: \"flex\",\n alignItems: \"flex-start\",\n gap: themeSpacing(3),\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 2),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 4),\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n boxShadow: (listener) =>\n `inset ${themeSpacing(1)} 0 0 0 ${themeColor(listener, \"shift-8\", color.get(listener))}`,\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n color: (listener) =>\n themeColor(listener, \"shift-10\", color.get(listener)),\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n },\n };\n}\n\nexport { alert };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n themeWeight,\n} from \"@domphy/theme\";\n\n/**\n * A circular avatar container that centers initials/text and cover-fits any\n * child `<img>`. Typically applied to an inline-flex container such as a `<span>`.\n *\n * @param props.color - Background/foreground color tone. Optional `ValueOrState<ThemeColor>`, default \"primary\".\n * @example { span: \"JD\", $: [avatar({ color: \"primary\" })] }\n */\nfunction avatar(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"primary\", \"color\");\n\n return {\n dataTone: \"shift-2\",\n style: {\n position: \"relative\",\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n overflow: \"hidden\",\n borderRadius: \"50%\",\n flexShrink: 0,\n width: themeSpacing(9),\n height: themeSpacing(9),\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n fontWeight: themeWeight(\"semibold\"),\n userSelect: \"none\",\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n color: (listener) =>\n themeColor(listener, \"shift-11\", color.get(listener)),\n // Hairline so the circle separates from same-tone surfaces.\n boxShadow: (listener) =>\n `0 0 0 1px ${themeColor(listener, \"border\", color.get(listener))}`,\n \"& img\": {\n position: \"absolute\",\n inset: 0,\n width: \"100%\",\n height: \"100%\",\n objectFit: \"cover\",\n },\n },\n };\n}\n\nexport { avatar };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n themeWeight,\n} from \"@domphy/theme\";\n\n/**\n * Renders a small count/label bubble pinned to the top-right corner of its host\n * (via a `::after` pseudo-element). Typically applied to an inline container such\n * as a `<span>` wrapping an icon or element.\n *\n * @param props.color - Badge color tone. Optional `ValueOrState<ThemeColor>`, default \"danger\".\n * @param props.label - Text/number shown in the badge. Optional `ValueOrState<string | number>`, default 999.\n * @example { span: \"🔔\", $: [badge({ label: 3, color: \"danger\" })] }\n */\nfunction badge(\n props: {\n color?: ValueOrState<ThemeColor>;\n label?: ValueOrState<string | number>;\n } = {},\n): PartialElement {\n const { label = 999 } = props;\n const state = toState(label);\n const color = toState(props.color ?? \"danger\", \"color\");\n return {\n style: {\n position: \"relative\",\n \"&::after\": {\n content: (l) => `\"${state.get(l)}\"`,\n position: \"absolute\",\n top: 0,\n insetInlineEnd: 0,\n transform: \"translate(50%,-50%)\",\n // Bare themeSpacing(U) at snapshot time; n = U / 1.5 (light.densities[2]).\n paddingInline: (l) => themeSpacing(themeDensity(l) * (1.5 / 1.5)),\n minWidth: themeSpacing(5),\n height: (l) => themeSpacing(themeDensity(l) * (5 / 1.5)),\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n fontSize: (l) => themeSize(l, \"decrease-2\"),\n fontWeight: themeWeight(\"semibold\"),\n lineHeight: 1,\n borderRadius: (l) => themeSpacing(themeDensity(l) * 999),\n backgroundColor: (l) => themeColor(l, \"shift-9\", color.get(l)),\n color: (l) => themeColor(l, \"shift-0\", color.get(l)),\n // Hairline ring so the pill pops on same-hue surfaces.\n boxShadow: (l) => `0 0 0 1px ${themeColor(l, \"shift-0\", color.get(l))}`,\n },\n },\n };\n}\n\nexport { badge };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * Styles a quotation block with a colored inset side bar, padded surface, and\n * shifted tone. Apply to a `<blockquote>` element.\n *\n * @hostTag blockquote\n * @param props.color - Surface/bar color tone. Optional `ValueOrState<ThemeColor>`, default \"neutral\".\n * @example { blockquote: \"Design is how it works.\", $: [blockquote({ color: \"primary\" })] }\n */\nfunction blockquote(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"blockquote\") {\n console.warn(`\"blockquote\" primitive patch must use blockquote tag`);\n }\n },\n dataTone: \"shift-2\",\n style: {\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n boxShadow: (listener) =>\n `inset ${themeSpacing(1)} 0 0 0 ${themeColor(listener, \"shift-4\", color.get(listener))}`,\n border: \"none\",\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 2),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 4),\n margin: 0,\n },\n };\n}\n\nexport { blockquote };\n","import type { PartialElement } from \"@domphy/core\";\nimport { toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * A horizontal breadcrumb navigation that lays out its children with a\n * separator between items and marks the `[aria-current=page]` item\n * non-interactive. Apply to a `<nav>` element.\n *\n * Does not paint `color` on any crumb — each composed child (`link()` for\n * non-current items, `strong()` for the current one, or any other patch) owns\n * its own color; wrap the current crumb in `strong()` for the usual \"reads\n * stronger\" emphasis rather than relying on breadcrumb to repaint it.\n *\n * @hostTag nav\n * @param props.color - Color tone for the nav's own background/inherited text\n * color and the separator glyphs. Optional `ValueOrState<ThemeColor>`, default \"neutral\".\n * @param props.separator - String inserted between items via `::after`. Optional `string`, default \"/\".\n * @example\n * { nav: [\n * { a: \"Home\", href: \"#\", $: [link()] },\n * { strong: \"Settings\", ariaCurrent: \"page\", $: [strong()] },\n * ], $: [breadcrumb({ separator: \"›\" })] }\n */\nfunction breadcrumb(\n props: { color?: ValueOrState<ThemeColor>; separator?: string } = {},\n): PartialElement {\n const { separator = \"/\" } = props;\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"nav\")\n console.warn('\"breadcrumb\" patch must use nav tag');\n },\n // The `::after` separator glyph below sits at \"muted\" (shift-8, an 8-step\n // gap) — WCAG 1.4.3 exempts pure decoration, and the hierarchy it hints at\n // is already carried by the links themselves. Measured 4.06:1 light /\n // 4.24:1 dark. Declared here so the decision lives with the patch instead\n // of surfacing as an un-actionable info at all 26 breadcrumb call sites.\n _doctorDisable: \"low-contrast\",\n ariaLabel: \"breadcrumb\",\n style: {\n display: \"flex\",\n alignItems: \"center\",\n flexWrap: \"wrap\",\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n gap: themeSpacing(1),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n // No `color` here: `color` inherits from the nav's own style above, so a\n // plain crumb (no patch of its own) already reads at \"text\" tone without\n // this rule repeating it — and repeating it at (0,1,0)+combinator\n // specificity used to tie (or beat, depending on injection order) a\n // composed crumb's own generated class, silently forcing link()'s\n // themed color or strong()'s emphasis color back to plain \"text\" (measured:\n // packages/blocks' shadcn sidebar breadcrumb, doctor's\n // descendant-color-override rule, 10 call sites).\n \"& > *\": {\n display: \"inline-flex\",\n alignItems: \"center\",\n },\n \"& > *:not(:last-child)::after\": {\n content: `\"${separator}\"`,\n // shift-4 measured 1.94:1 on the page surface (light) — the glyph was\n // all but invisible. \"muted\" is the de-emphasis tone shadcn's\n // breadcrumb separator uses (4.06:1 light / 4.24:1 dark).\n color: (listener) => themeColor(listener, \"muted\", color.get(listener)),\n paddingInlineStart: themeSpacing(1),\n },\n // No `color` here either, same reasoning as \"& > *\" above: the composed\n // crumb owns its own color (strong()'s shift-11, link()'s shift-13, or\n // nav's inherited \"text\" for a bare crumb) and breadcrumb does not\n // silently repaint it — measured via getComputedStyle in real Chromium\n // that a `color` here, even boosted to (0,3,0) specificity so it always\n // wins, forced strong()'s current-crumb text from its own shift-11 down\n // to breadcrumb's shift-10. A bare-text current crumb that wants visual\n // emphasis is the CALLER's recipe to add (wrap it in strong()), not\n // something breadcrumb prescribes for every consumer. `pointerEvents`\n // stays: the current item should not be clickable regardless of what\n // colors it.\n \"& > [aria-current=page]\": {\n pointerEvents: \"none\",\n },\n },\n };\n}\n\nexport { breadcrumb };\n","import type { PartialElement } from \"@domphy/core\";\nimport { toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n textToneOn,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * An ellipsis trigger button for collapsed breadcrumb items, with hover and\n * focus-visible states. Apply to a `<button>` element.\n *\n * @hostTag button\n * @param props.color - Color tone for the trigger. Optional `ValueOrState<ThemeColor>`, default \"neutral\".\n * @example { button: \"…\", $: [breadcrumbEllipsis({ color: \"neutral\" })] }\n */\nfunction breadcrumbEllipsis(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n // Native `type` on the host still wins (mergePartial: native over patch).\n type: \"button\",\n _onInsert: (node) => {\n if (node.tagName !== \"button\") {\n console.warn('\"breadcrumbEllipsis\" patch must use button tag');\n }\n },\n ariaLabel: \"More breadcrumb items\",\n style: {\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n paddingInline: themeSpacing(1),\n border: \"none\",\n background: \"none\",\n cursor: \"pointer\",\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n borderRadius: themeSpacing(1),\n transition:\n \"color 140ms ease, background-color 140ms ease, box-shadow 140ms ease\",\n \"&:hover\": {\n // Tracks the +2 hover fill; shift-10 left a gap of 8 (4.34:1).\n color: (listener) =>\n themeColor(listener, textToneOn(2), color.get(listener)),\n backgroundColor: (listener) =>\n themeColor(listener, \"hover\", color.get(listener)),\n },\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, color.get(listener)),\n },\n },\n };\n}\n\nexport { breadcrumbEllipsis };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { BUTTON_SIZE_FONT, type ButtonSize } from \"../utils/buttonSize.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\nimport { buttonGhost } from \"./buttonGhost.js\";\n\ntype ButtonVariant = \"solid\" | \"outline\" | \"ghost\";\n\nconst PADDING_STEPS: Record<ButtonSize, { block: number; inline: number }> = {\n small: { block: 0.5, inline: 2 },\n medium: { block: 1, inline: 3 },\n large: { block: 1.5, inline: 4 },\n};\n\n/**\n * A themed button control with density-aware padding/radius and hover, pressed\n * (`:active` ±2), focus-visible, `[disabled]`, and `[aria-busy=true]` states.\n * Apply to a `<button>` element.\n *\n * @hostTag button\n * @param props.color - Button color tone. Optional `ValueOrState<ThemeColor>`, default \"primary\".\n * @param props.variant - Visual style: `\"outline\"` (tinted background + outline, default,\n * backward compatible), `\"solid\"` (filled background, readable contrast text), or `\"ghost\"`\n * (no background/border — delegates to `buttonGhost()` so the two stay visually identical).\n * @param props.size - Button size preset. Optional `\"small\" | \"medium\" | \"large\"`, defaults to `\"medium\"`.\n * @example { button: \"Save\", $: [button({ color: \"primary\" })] }\n * @example { button: \"Delete\", $: [button({ color: \"error\", variant: \"solid\" })] }\n */\nfunction button(\n props: {\n color?: ValueOrState<ThemeColor>;\n variant?: ButtonVariant;\n size?: ButtonSize;\n } = {},\n): PartialElement {\n const variant = props.variant ?? \"outline\";\n if (variant === \"ghost\") {\n return buttonGhost({ color: props.color, size: props.size });\n }\n\n const color = toState(props.color ?? \"primary\", \"color\");\n const isSolid = variant === \"solid\";\n const padding = PADDING_STEPS[props.size ?? \"medium\"];\n const fontSize = BUTTON_SIZE_FONT[props.size ?? \"medium\"];\n\n return {\n // Native `type` on the host still wins (mergePartial: native over patch).\n type: \"button\",\n _onInsert: (node) => {\n if (node.tagName !== \"button\") {\n console.warn(`\"button\" primitive patch must use button tag`);\n }\n },\n // Solid: deep brand fill (shift-13) + light-end neutral text (shift-0).\n // Mid-ramp shift-8 failed WCAG (~2.2:1 white-on-medium). NOT dataTone-17\n // (that collapsed every color into a near-black pill). Outline text:\n // shift-13 for ≥4.5:1 on light surfaces (shift-9 failed at ~2.57).\n ...(isSolid\n ? {\n _doctorDisable: [\n \"low-contrast\",\n \"color-shift-minimum\",\n \"tone-background-inherit\",\n ] as const,\n }\n : {}),\n style: {\n appearance: \"none\",\n fontSize: (listener) => themeSize(listener, fontSize),\n // Single-line bounded control: block/radius = 1D, inline = 3D.\n paddingBlock: (listener) =>\n themeSpacing(themeDensity(listener) * padding.block),\n paddingInline: (listener) =>\n themeSpacing(themeDensity(listener) * padding.inline),\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n width: \"fit-content\",\n display: \"flex\",\n justifyContent: \"center\",\n alignItems: \"center\",\n gap: (listener) => themeSpacing(themeDensity(listener) * 1),\n userSelect: \"none\",\n cursor: \"pointer\",\n lineHeight: \"inherit\",\n border: \"none\",\n outlineOffset: \"-1px\",\n outlineWidth: \"1px\",\n outline: isSolid\n ? \"none\"\n : (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", color.get(listener))}`,\n color: (listener) =>\n isSolid\n ? themeColor(listener, \"shift-0\", \"neutral\")\n : themeColor(listener, \"shift-13\", color.get(listener)),\n backgroundColor: (listener) =>\n isSolid\n ? themeColor(listener, \"shift-13\", color.get(listener))\n : themeColor(listener, \"inherit\", color.get(listener)),\n transition:\n \"background-color 140ms ease, color 140ms ease, border-color 140ms ease, box-shadow 140ms ease\",\n \"&:hover:not([disabled]):not([aria-busy=true])\": {\n color: (listener) =>\n isSolid\n ? themeColor(listener, \"shift-0\", \"neutral\")\n : themeColor(listener, \"shift-14\", color.get(listener)),\n backgroundColor: (listener) =>\n isSolid\n ? themeColor(listener, \"shift-14\", color.get(listener))\n : themeColor(listener, \"hover\", color.get(listener)),\n },\n // Pressed: solid steps deeper on the brand ramp; outline uses +2 surface.\n \"&:active:not([disabled]):not([aria-busy=true])\": {\n backgroundColor: (listener) =>\n isSolid\n ? themeColor(listener, \"shift-15\", color.get(listener))\n : themeColor(listener, \"increase-2\", color.get(listener)),\n },\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, color.get(listener)),\n },\n \"&[disabled]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-2\", \"neutral\"),\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", \"neutral\")}`,\n color: (listener) => themeColor(listener, \"muted\", \"neutral\"),\n },\n \"&[aria-busy=true]\": {\n opacity: 0.7,\n cursor: \"wait\",\n pointerEvents: \"none\",\n },\n },\n };\n}\n\nexport { button };\nexport type { ButtonVariant };\n","/**\n * The `fontSize` step for `button()`/`buttonGhost()`'s `size` prop. Padding stays\n * per-component (button and buttonGhost start from different base paddings) so\n * only the part that's genuinely identical — the font-size step — lives here.\n */\nconst BUTTON_SIZE_FONT = {\n small: \"decrease-1\",\n medium: \"inherit\",\n large: \"increase-1\",\n} as const;\n\ntype ButtonSize = keyof typeof BUTTON_SIZE_FONT;\n\nexport { BUTTON_SIZE_FONT };\nexport type { ButtonSize };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n textToneOn,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { BUTTON_SIZE_FONT, type ButtonSize } from \"../utils/buttonSize.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\nconst PADDING_STEPS: Record<ButtonSize, number> = {\n small: 0.5,\n medium: 1,\n large: 1.5,\n};\n\n/**\n * A transparent button with no border or background — suitable for icon\n * actions, inline controls, and delete/close triggers. Apply to a `<button>`\n * element.\n *\n * @hostTag button\n * @param props.color - Text color tone. Optional `ValueOrState<ThemeColor>`, defaults to `\"neutral\"`.\n * @param props.size - Button size preset. Optional `\"small\" | \"medium\" | \"large\"`, defaults to `\"medium\"`.\n * @example { button: \"×\", $: [buttonGhost()] }\n * @example { button: [{ span: \"🗑\", $: [icon()] }], $: [buttonGhost({ color: \"error\" })] }\n */\nfunction buttonGhost(\n props: { color?: ValueOrState<ThemeColor>; size?: ButtonSize } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n const padding = PADDING_STEPS[props.size ?? \"medium\"];\n const fontSize = BUTTON_SIZE_FONT[props.size ?? \"medium\"];\n\n return {\n // Native `type` on the host still wins (mergePartial: native over patch).\n type: \"button\",\n _onInsert: (node) => {\n if (node.tagName !== \"button\") {\n console.warn(`\"buttonGhost\" primitive patch must use button tag`);\n }\n },\n style: {\n appearance: \"none\",\n fontSize: (listener) => themeSize(listener, fontSize),\n paddingBlock: (listener) =>\n themeSpacing(themeDensity(listener) * padding),\n paddingInline: (listener) =>\n themeSpacing(themeDensity(listener) * padding),\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n display: \"inline-flex\",\n // Same as button(): without it a flex/grid parent stretches the control\n // to the full column. Measured in Chromium inside a `stack()`: an\n // outline button was 88px wide and the ghost button next to it 1232px,\n // although `button({ variant: \"ghost\" })` documents the two as visually\n // identical.\n width: \"fit-content\",\n justifyContent: \"center\",\n alignItems: \"center\",\n gap: (listener) => themeSpacing(themeDensity(listener) * 1),\n userSelect: \"none\",\n cursor: \"pointer\",\n lineHeight: \"inherit\",\n border: \"none\",\n background: \"none\",\n outline: \"none\",\n transition:\n \"background-color 140ms ease, color 140ms ease, box-shadow 140ms ease\",\n // Resting text uses the \"text\" alias (shift-9) — NOT the semantic-zone\n // shift-6 the patch previously used. A ghost button's label is essential\n // interactive content, and shift-6 on an edge surface measures ~2.4:1,\n // failing WCAG AA (axe color-contrast). shadcn's ghost variant likewise\n // rests at full foreground; hover/active keep the same text color and\n // differentiate via background only.\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n // Hover/active paint a fill 2 steps off the surface, so the label moves\n // with it (textToneOn) — a fixed \"text\" label measured 3.58:1 on the\n // hover fill (light) / 4.37:1 (dark), below WCAG AA.\n \"&:hover:not([disabled]):not([aria-busy=true])\": {\n color: (listener) =>\n themeColor(listener, textToneOn(2), color.get(listener)),\n backgroundColor: (listener) =>\n themeColor(listener, \"hover\", color.get(listener)),\n },\n \"&:active:not([disabled]):not([aria-busy=true])\": {\n color: (listener) =>\n themeColor(listener, textToneOn(2), color.get(listener)),\n backgroundColor: (listener) =>\n themeColor(listener, \"increase-2\", color.get(listener)),\n },\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, color.get(listener)),\n },\n \"&[disabled]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n color: (listener) => themeColor(listener, \"border-strong\", \"neutral\"),\n },\n \"&[aria-busy=true]\": {\n opacity: 0.7,\n cursor: \"wait\",\n pointerEvents: \"none\",\n },\n },\n };\n}\n\nexport { buttonGhost };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n textToneOn,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * A pill-shaped toggle switch with `role=\"switch\"`; clicking flips the bound\n * `checked` state and slides the thumb. Apply to a `<button>` element.\n *\n * @hostTag button\n * @param props.checked - Toggle state. Optional `ValueOrState<boolean>`, default false.\n * @param props.accentColor - Color tone when checked (on). Optional `ValueOrState<ThemeColor>`, default \"primary\".\n * @param props.color - Color tone when unchecked (off track). Optional `ValueOrState<ThemeColor>`, default \"neutral\".\n * @example { button: [{ span: null }], $: [buttonSwitch({ checked: true })] }\n */\nfunction buttonSwitch(\n props: {\n checked?: ValueOrState<boolean>;\n accentColor?: ValueOrState<ThemeColor>;\n color?: ValueOrState<ThemeColor>;\n } = {},\n): PartialElement {\n const { checked = false } = props;\n\n const check = toState(checked);\n const color = toState(props.color ?? \"neutral\", \"color\");\n const accentColor = toState(props.accentColor ?? \"primary\", \"accentColor\");\n\n return {\n // Native `type` on the host still wins (mergePartial: native over patch).\n type: \"button\",\n _onSchedule: (node) => {\n if (node.tagName !== \"button\") {\n console.warn(`\"buttonSwitch\" primitive patch must use button tag`);\n }\n },\n role: \"switch\",\n // A <button> is not a labelable element, so <label for> cannot name it and\n // the thumb span carries no text — the control had NO accessible name at\n // all (axe `button-name`). A host-declared aria-label/aria-labelledby\n // still wins over this default.\n ariaLabel: \"Toggle\",\n ariaChecked: (listener) => check.get(listener),\n dataTone: \"shift-2\",\n onClick: () => check.set(!check.get()),\n style: {\n position: \"relative\",\n display: \"inline-flex\",\n alignItems: \"center\",\n fontSize: (listener) => themeSize(listener),\n border: \"none\",\n outlineWidth: \"1px\",\n // WCAG 2.1 SC 1.4.11 Non-text Contrast: the OFF track is tone-inherited\n // and sits at ~1.4:1 against the page, so the boundary has to carry the\n // 3:1. \"border\" (shift-3) measured 1.64:1 in Chromium; shift-7 measures\n // 3.32:1 (light) / 3.50:1 (dark).\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"shift-7\", color.get(listener))}`,\n minWidth: themeSpacing(12),\n minHeight: themeSpacing(6),\n // A switch is a fixed-size track, never a full-width bar. Measured in\n // Chromium: inside a `stack()` the 48px pill stretched to 1232px and the\n // thumb (absolutely positioned from the left edge) floated alone at the\n // far end of it. `inline-flex` does not survive flex/grid blockification.\n width: \"fit-content\",\n flexShrink: 0,\n borderRadius: themeSpacing(999),\n paddingInlineStart: themeSpacing(7),\n paddingInlineEnd: themeSpacing(2),\n cursor: \"pointer\",\n transition:\n \"padding-inline-start 0.3s, padding-inline-end 0.3s, background-color 140ms ease, box-shadow 140ms ease\",\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, accentColor.get(listener)),\n },\n \"& > :first-child\": {\n content: '\"\"',\n position: \"absolute\",\n display: \"inline-flex\",\n alignItems: \"center\",\n insetInlineStart: themeSpacing(0.5),\n top: \"50%\",\n transform: \"translateY(-50%)\",\n transition: \"inset-inline-start 0.3s\",\n width: themeSpacing(5),\n height: themeSpacing(5),\n borderRadius: themeSpacing(999),\n color: (listener) => themeColor(listener, \"text\"),\n backgroundColor: (listener) =>\n themeColor(listener, \"decrease-2\", color.get(listener)),\n // The thumb is tone-inherited too — same 1.4:1 problem as the track.\n // Its own boundary makes the ON/OFF position identifiable on either\n // track colour (SC 1.4.11), the way Radix rings its switch thumb.\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"shift-7\", color.get(listener))}`,\n outlineOffset: \"-1px\",\n },\n \"&[aria-checked=true]\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"increase-3\", accentColor.get(listener)),\n outline: \"none\",\n // Host label tracks the ON fill (+3 off this element's own shift-2\n // anchor). `decrease-2` pinned it to the light end of the ramp and\n // measured 2.48:1 (light) / 1.87:1 (dark) on that fill.\n color: (listener) =>\n themeColor(listener, textToneOn(3), accentColor.get(listener)),\n paddingInlineStart: themeSpacing(2),\n paddingInlineEnd: themeSpacing(7),\n },\n \"&[aria-checked=true] > :first-child\": {\n insetInlineStart: `calc(100% - ${themeSpacing(5.5)})`,\n },\n \"&[disabled]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n },\n },\n };\n}\n\nexport { buttonSwitch };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSpacing,\n themeWeight,\n} from \"@domphy/theme\";\nimport { elevation } from \"../utils/elevation.js\";\n\n/**\n * A grid-based card surface that auto-places known child elements into named\n * regions: `<img>` (image), headings (title), `<p>` (description), `<aside>`\n * (aside), `<div>` (content), and `<footer>` (footer). Typically applied to a\n * `<div>` (any block container).\n *\n * @param props.color - Surface/border color tone. Optional `ValueOrState<ThemeColor>`, default \"neutral\".\n * @example { div: [{ h3: \"Title\", $: [heading()] }, { p: \"Body\", $: [paragraph()] }], $: [card({ color: \"neutral\" })] }\n */\nfunction card(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n return {\n style: {\n display: \"grid\",\n gridTemplateColumns: \"1fr auto\",\n gridTemplateAreas:\n '\"image image\" \"title aside\" \"desc aside\" \"content content\" \"footer footer\"',\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 2),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n color: (listener) =>\n themeColor(listener, \"shift-10\", color.get(listener)),\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", color.get(listener))}`,\n outlineOffset: \"-1px\",\n // Soft lift so cards separate from the page without looking like dialogs.\n boxShadow: elevation(\"low\"),\n overflow: \"hidden\",\n \"& > img\": {\n gridArea: \"image\",\n width: \"100%\",\n height: \"auto\",\n display: \"block\",\n },\n \"& > :is(h1,h2,h3,h4,h5,h6)\": {\n gridArea: \"title\",\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 2),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 4),\n fontWeight: themeWeight(\"semibold\"),\n color: (listener) =>\n themeColor(listener, \"shift-11\", color.get(listener)),\n margin: 0,\n },\n \"& > p\": {\n gridArea: \"desc\",\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 4),\n paddingBottom: (listener) => themeSpacing(themeDensity(listener) * 2),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n margin: 0,\n },\n \"& > aside\": {\n gridArea: \"aside\",\n alignSelf: \"center\",\n padding: (listener) => themeSpacing(themeDensity(listener) * 2),\n height: \"auto\",\n },\n // No `color` here: it repeated the exact same shift-10 the card's own\n // top-level `color` above already sets (and this content area inherits),\n // at (0,1,0)+combinator specificity that used to silently outrank a\n // composed child's own generated-class color — e.g. a `chart()`-mounted\n // div's own styling (packages/blocks' chart-bar/-line-interactive\n // recipes, doctor's descendant-color-override rule).\n \"& > div\": {\n gridArea: \"content\",\n padding: (listener) => themeSpacing(themeDensity(listener) * 4),\n },\n \"& > footer\": {\n gridArea: \"footer\",\n display: \"flex\",\n gap: themeSpacing(2),\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 2),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 4),\n borderTop: (listener) =>\n `1px solid ${themeColor(listener, \"border\", color.get(listener))}`,\n },\n },\n };\n}\n\nexport { card };\n","/** Named elevation levels for floating/raised surfaces. */\ntype ElevationLevel = \"low\" | \"medium\" | \"high\";\n\n// Layered soft shadows (a tight contact shadow + a broad ambient one), black at\n// low alpha so the same value reads correctly on both light and dark surfaces\n// without a theme/context lookup.\nconst SHADOWS: Record<ElevationLevel, string> = {\n low: \"0 1px 2px rgba(0,0,0,0.08), 0 4px 10px rgba(0,0,0,0.10)\",\n medium: \"0 2px 4px rgba(0,0,0,0.10), 0 10px 24px rgba(0,0,0,0.14)\",\n high: \"0 6px 12px rgba(0,0,0,0.14), 0 24px 48px rgba(0,0,0,0.20)\",\n};\n\n/**\n * Shared box-shadow value for a named elevation level. Used by floating/raised\n * surface patches (popover, menu, dialog, drawer, toast, tooltip, combobox/\n * selectBox dropdown, datePicker popup, fab) so elevation reads consistently\n * across the library instead of each patch picking its own shadow.\n */\nfunction elevation(level: ElevationLevel): string {\n return SHADOWS[level];\n}\n\nexport { elevation };\nexport type { ElevationLevel };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeFont,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * Styles an inline code snippet in the theme's monospace stack, with a subtle\n * surface background, rounded corners, and shifted tone. Apply to a `<code>` element.\n *\n * @hostTag code\n * @param props.color - Surface/text color tone. Optional `ValueOrState<ThemeColor>`, default \"neutral\".\n * @example { code: \"npm install\", $: [code({ color: \"neutral\" })] }\n */\nfunction code(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n dataTone: \"shift-2\",\n _onInsert: (node) => {\n if (node.tagName !== \"code\") {\n console.warn(`\"code\" primitive patch must use code tag`);\n }\n },\n style: {\n display: \"inline-flex\",\n alignItems: \"center\",\n whiteSpace: \"nowrap\",\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n // The theme owns the code stack; <code>/<kbd>/<pre> otherwise keep the\n // UA generic \"monospace\" (Courier New on Windows), so a theme that swaps\n // fontFamilies.monospace never reaches them.\n fontFamily: themeFont(\"monospace\"),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n // Bare themeSpacing(U) at snapshot time; n = U / 1.5 (light.densities[2]).\n height: (listener) => themeSpacing(themeDensity(listener) * (6 / 1.5)),\n paddingInline: (listener) =>\n themeSpacing(themeDensity(listener) * (1.5 / 1.5)),\n borderRadius: (listener) =>\n themeSpacing(themeDensity(listener) * (1 / 1.5)),\n },\n };\n}\n\nexport { code };\n","import {\n type BehaviorInstance,\n behavior,\n type DomphyElement,\n type ElementNode,\n merge,\n type PartialElement,\n type State,\n type StyleObject,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport type { Placement } from \"@domphy/floating\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { elevation } from \"../utils/elevation.js\";\nimport { fieldTextStyle } from \"../utils/fieldText.js\";\nimport { createFloating, floatingPanelId } from \"../utils/floating.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\nimport { subscribeOpen } from \"../utils/openState.js\";\nimport { enabledOptionsIn } from \"../utils/optionList.js\";\nimport { tag } from \"./tag.js\";\n\n/**\n * A combobox/multi-select control: renders selected options as removable tags\n * plus an input, and shows a floating popover (`content`) anchored to the host.\n * Apply to a `<div>` element.\n *\n * @hostTag div\n * @param props.multiple - Allow selecting multiple values (popover stays open on click). Optional `boolean`, default false.\n * @param props.value - Selected value(s). Optional `ValueOrState<Array<number | string | null | undefined> | number | string | null | undefined>`, no default.\n * @param props.options - Available `{ label, value }` options used to render selected tags. Optional `Array<{ label: string; value: string }>`, default `[]`.\n * @param props.placement - Floating popover placement. Optional `ValueOrState<Placement>`, default \"bottom\".\n * @param props.content - The floating popover content element. Required `DomphyElement`.\n * @param props.color - Color tone for the control. Optional `ThemeColor`, default \"neutral\".\n * @param props.open - Whether the popover is open. Optional `ValueOrState<boolean>` (including `Computed`/`ReadableState`), default false. When the source is read-only, pass `onDismiss` so dismiss can close.\n * @param props.onDismiss - Called when the popover requests close. Optional. Required to close when `open` is a read-only `Computed`/`ReadableState`.\n * @param props.input - Custom input element; when omitted a default `<input>` is created. Optional `DomphyElement`.\n * @example { div: null, $: [combobox({ options: [{ label: \"A\", value: \"a\" }], content: { div: null } })] }\n */\nfunction combobox(props: {\n multiple?: boolean;\n value?: ValueOrState<\n | Array<number | string | null | undefined>\n | number\n | string\n | null\n | undefined\n >;\n options?: Array<{ label: string; value: string }>;\n placement?: ValueOrState<Placement>;\n content: DomphyElement;\n color?: ThemeColor;\n open?: ValueOrState<boolean>;\n onDismiss?: () => void;\n input?: DomphyElement;\n}): PartialElement {\n const {\n options = [],\n placement = \"bottom\",\n color = \"neutral\",\n open = false,\n multiple = false,\n } = props;\n\n const state = toState(props.value);\n const openState = toState(open);\n const { show, hide, anchorPartial } = createFloating({\n kind: \"combobox\",\n open: openState,\n onDismiss: props.onDismiss,\n placement: toState(placement),\n content: props.content,\n });\n\n const popoverPartial: PartialElement = {\n onClick: (_e, node) => !multiple && hide(node),\n dataTone: \"shift-0\",\n style: {\n backgroundColor: (listener) => themeColor(listener, \"inherit\"),\n // Surface contract (dataTone-surface-contract): a tone-anchored panel\n // must declare BOTH background and text color. Page-matching shift-0\n // (same as menu/selectList/dialog), not the inverted tooltip surface.\n color: (listener) => themeColor(listener, \"text\"),\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 2),\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\")}`,\n outlineOffset: \"-1px\",\n boxShadow: elevation(\"medium\"),\n },\n };\n\n merge(props.content, popoverPartial);\n\n const inputStyle: StyleObject = {\n border: \"none\",\n outline: \"none\",\n padding: 0,\n margin: 0,\n flex: 1,\n height: themeSpacing(6),\n marginInlineStart: themeSpacing(2),\n fontSize: (listener: any) => themeSize(listener, \"inherit\"),\n // Without an explicit rule the placeholder falls back to the UA default\n // (`darkgray` on the Chrome 88-class engines Domphy ships into — 2.3:1 on\n // a light field).\n ...fieldTextStyle(color),\n backgroundColor: (listener: any) => themeColor(listener, \"inherit\", color),\n };\n\n type InnerProps = {\n options: Array<{ label: string; value: string }>;\n multiple: boolean;\n color: ThemeColor;\n state: State<\n | Array<number | string | null | undefined>\n | number\n | string\n | null\n | undefined\n >;\n input?: DomphyElement;\n };\n\n type ComboboxInner = BehaviorInstance<InnerProps> & {\n query: State<string>;\n };\n\n const readQuery = (listener?: { elementNode?: ElementNode }) =>\n listener?.elementNode?.getBehavior<ComboboxInner>(\"comboboxInner\")?.query;\n\n const findComboboxAnchor = (from: ElementNode): ElementNode => {\n let current: ElementNode | null = from;\n while (current) {\n if (current._behaviorInstances.has(\"floating:combobox\")) return current;\n current = current.parent;\n }\n return from;\n };\n\n // WAI-ARIA APG \"Combobox with List Autocomplete\": Down/Up move into the\n // popup, Enter with nothing highlighted just closes it. Escape is already\n // handled document-wide by createFloating. Without this the popup was\n // mouse-only — Tab from the input skipped straight past every option.\n const moveIntoPanel = (node: ElementNode, toLast: boolean): void => {\n const anchor = findComboboxAnchor(node);\n const root = anchor.getRoot().domElement as Element | null;\n const panel =\n root?.querySelector(`#${floatingPanelId(\"combobox\", anchor)}`) ?? null;\n const options = enabledOptionsIn(panel);\n if (!options.length) return;\n const target = options[toLast ? options.length - 1 : 0]!;\n target.focus();\n target.scrollIntoView?.({ block: \"nearest\" });\n };\n\n // show() is debounced by 100ms and flips `openState` only AFTER mounting the\n // panel, so waiting on that flip is exact where a fixed delay is not: a bare\n // requestAnimationFrame (~16ms) ran while the panel did not exist yet, and\n // in Chromium the first ArrowDown left focus on the input — only a SECOND\n // press reached an option. The extra frame after the flip is also required:\n // floating.ts drives the panel's `visibility` from the same state and that\n // style write has not landed when the listener runs, so `focus()` would hit\n // a `visibility: hidden` element and do nothing.\n const openThenMove = (node: ElementNode, toLast: boolean): void => {\n let release: (() => void) | undefined;\n release = subscribeOpen(\n openState,\n (isOpen) => {\n if (!isOpen) return;\n release?.();\n requestAnimationFrame(() => moveIntoPanel(node, toLast));\n },\n false,\n );\n show(node);\n };\n\n const onInputKey = (event: Event, node: ElementNode): void => {\n const key = (event as KeyboardEvent).key;\n if (key !== \"ArrowDown\" && key !== \"ArrowUp\") return;\n event.preventDefault();\n if (openState.get()) {\n moveIntoPanel(node, key === \"ArrowUp\");\n return;\n }\n openThenMove(node, key === \"ArrowUp\");\n };\n\n const inputAria: PartialElement = {\n role: \"combobox\",\n ariaHaspopup: \"listbox\",\n // The popup filters an existing list; it does not complete inline.\n ariaAutocomplete: \"list\",\n ariaExpanded: (listener) => openState.get(listener),\n ariaControls: (listener) =>\n listener?.elementNode\n ? floatingPanelId(\"combobox\", findComboboxAnchor(listener.elementNode))\n : undefined,\n onKeyDown: onInputKey,\n };\n\n const buildInput = (custom?: DomphyElement): DomphyElement => {\n if (custom) {\n merge(custom, {\n onClick: (_e: Event, node: ElementNode) => show(node),\n style: inputStyle,\n _key: \"combobox-input\",\n ...inputAria,\n });\n return custom;\n }\n return {\n input: null,\n // Accessible name for the filter field (critical for axe label rule).\n ariaLabel: \"Filter options\",\n // Click / typing / ArrowDown open the popup — NOT plain focus. Escape\n // returns focus to this input (floating.ts), so an onFocus that re-opens\n // made Escape un-dismissable: measured in Chromium, the panel was back\n // within 100ms of every Escape and never closed again. MUI Autocomplete\n // defaults `openOnFocus` to false for the same reason.\n onClick: (_e: Event, node: ElementNode) => show(node),\n value: (listener: { elementNode?: ElementNode }) =>\n readQuery(listener)?.get(listener as never) ?? \"\",\n onInput: (event: Event, node: ElementNode) => {\n node\n .getBehavior<ComboboxInner>(\"comboboxInner\")\n ?.query.set((event.target as HTMLInputElement).value);\n show(node);\n },\n style: inputStyle,\n _key: \"combobox-input\",\n ...inputAria,\n };\n };\n\n const buildWrap = (inner: InnerProps): DomphyElement<\"div\"> => ({\n div: (listener) => {\n openState.get(listener);\n const val = inner.state.get(listener);\n const vals = Array.isArray(val) ? val : [val];\n const opts = inner.options.filter((opt) => vals.includes(opt.value));\n const items: DomphyElement[] = opts.map((opt) => {\n return {\n span: opt.label,\n $: [tag({ color: inner.color, removable: true })],\n _key: opt.value,\n _onRemove: (_node: ElementNode) => {\n const cur = inner.state.get();\n const curVals = Array.isArray(cur) ? cur : [cur];\n const filter = curVals.filter((v) => v !== opt.value);\n inner.multiple\n ? inner.state.set(filter as any)\n : inner.state.set(filter[0] as any);\n },\n };\n });\n items.push(buildInput(inner.input));\n return items;\n },\n _key: \"comboboxWrap\",\n style: {\n display: \"flex\",\n flexWrap: \"wrap\",\n gap: themeSpacing(1),\n },\n });\n\n const attachInner = (\n node: ElementNode,\n _inner: InnerProps,\n ): ComboboxInner => {\n let query = node.getMetadata(\"comboboxQuery\") as State<string> | undefined;\n if (!query) {\n query = toState(\"\");\n node.setMetadata(\"comboboxQuery\", query);\n }\n return {\n query,\n update(next) {\n node.children.update([buildWrap(next)]);\n },\n };\n };\n\n const partial: PartialElement = {\n _onInsert: (node) => {\n if (node.tagName !== \"div\") {\n console.warn(`\"combobox\" primitive patch must use div tag`);\n }\n },\n _onSchedule: (node, element) => {\n (element as Record<string, unknown>)[node.tagName] = [\n buildWrap({\n options,\n multiple,\n color,\n state,\n input: props.input,\n }),\n ];\n },\n ...behavior<InnerProps>(\"comboboxInner\", attachInner, {\n options,\n multiple,\n color,\n state,\n input: props.input,\n }),\n style: {\n minWidth: themeSpacing(32),\n outlineOffset: \"-1px\",\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", \"neutral\")}`,\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 1),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 1),\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n color: (listener) => themeColor(listener, \"text\", color),\n backgroundColor: (listener) => themeColor(listener, \"inherit\", color),\n transition:\n \"background-color 140ms ease, outline-color 140ms ease, box-shadow 140ms ease\",\n \"&:focus-within\": {\n boxShadow: (listener) => focusRing(listener, color),\n },\n },\n };\n\n merge(anchorPartial, partial);\n return anchorPartial;\n}\n\nexport { combobox };\n","import {\n type Listener,\n type StyleObject,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport { type ThemeColor, themeColor } from \"@domphy/theme\";\n\n/**\n * Tone of an editable field's PLACEHOLDER.\n *\n * MEASURED — `packages/ui/tests/field-text-contrast.test.ts` sweeps all 10\n * built-in roles x the 8 edge anchors (shift-0..3, shift-14..17) x both built-in\n * themes, resolving tones through `resolveToneStep()` so the numbers are the\n * ones the browser paints:\n *\n * shift-7 worst 2.83:1 fails 142/160\n * \"muted\" worst 3.55:1 fails 40/160\n * \"text\" worst 4.53:1 fails 0/160 <- lowest tone clearing AA\n *\n * WCAG 2.1 SC 1.4.3 covers placeholder text: its only relevant exception is\n * \"inactive user interface components\", and an editable field is not inactive.\n * So `\"text\"` is the floor, not a preference.\n */\nconst PLACEHOLDER_TONE = \"text\";\n\n/**\n * Tone of the value the user has typed.\n *\n * The placeholder is pinned at the AA floor, so the hint/value distinction has\n * to be made by painting the VALUE stronger — the inverse of MUI/Carbon, whose\n * placeholders sit below AA. Two ramp steps, not one:\n *\n * \"text\" vs shift-10 worst CIELAB dE 5.27\n * \"text\" vs shift-11 worst CIELAB dE 10.67 (~4.6x the ~2.3 JND)\n *\n * shift-11 also clears AAA on every edge anchor (worst 7.34:1), so the value is\n * never the weaker of the two.\n */\nconst VALUE_TONE = \"shift-11\";\n\n/**\n * The `color` + `::placeholder` pair every editable text field paints. Keeping\n * it in one place is what stops the two tones drifting apart per patch (they\n * had, across `inputText` / `inputSearch` / `textarea` / `command`) and keeps\n * the placeholder in the field's own `color` role rather than always neutral.\n */\nfunction fieldTextStyle(\n color: ValueOrState<ThemeColor> = \"neutral\",\n): StyleObject {\n const colorState = toState(color, \"color\");\n return {\n color: (listener: Listener) =>\n themeColor(listener, VALUE_TONE, colorState.get(listener)),\n \"&::placeholder\": {\n color: (listener: Listener) =>\n themeColor(listener, PLACEHOLDER_TONE, colorState.get(listener)),\n },\n };\n}\n\nexport { fieldTextStyle, PLACEHOLDER_TONE, VALUE_TONE };\n","import {\n type BehaviorInstance,\n behavior,\n type DomphyElement,\n type ElementNode,\n merge,\n type PartialElement,\n type ReadableState,\n type State,\n type ValueOrState,\n} from \"@domphy/core\";\nimport {\n autoUpdate,\n computePosition,\n flip,\n offset,\n type Placement,\n shift,\n} from \"@domphy/floating\";\nimport {\n asOpenState,\n dismissOpen,\n subscribeOpen,\n writeOpen,\n} from \"./openState.js\";\n\ntype FloatingProps = {\n kind: string;\n openState: ReadableState<boolean>;\n // Lives on the behavior instance so a reused node gets the latest callback\n // via update() — do not close over factory-generation onDismiss.\n onDismiss?: () => void;\n placement: State<Placement>;\n content: DomphyElement;\n // popover's openOn === \"hover\" case: hovering the floating PANEL itself\n // (not just the anchor) must keep it open, so the pointer can travel from\n // trigger to panel without the debounced hide() firing first.\n keepOpenOnContentHover: boolean;\n // Hover-intent debounce, in ms. Configurable per consumer (Radix Tooltip\n // parity: `delayDuration`) instead of the single fixed value every floating\n // consumer used to share.\n openDelay: number;\n closeDelay: number;\n};\n\n// The previous fixed debounce, kept as the default when a consumer does not\n// pass its own delay — INHERITED from the pre-existing behavior this file\n// hard-coded before openDelay/closeDelay became configurable.\nconst FLOATING_DEFAULT_DELAY_MS = 100;\n\n// The panel id every floating component gets, derived deterministically from\n// the ANCHOR's nodeId (stable across generations — a reused node keeps its\n// nodeId — and across SSR/hydration, unlike Math.random()). The anchor's\n// trigger partial references the same id via _onSchedule (aria-controls /\n// aria-describedby), so trigger and panel agree without any factory-scope\n// mutable variable that a fresh generation would lose.\nfunction floatingPanelId(kind: string, node: ElementNode): string {\n return `domphy-${kind}-${node.nodeId}`;\n}\n\n// The overlay container every floating panel portals into. Marked with a data\n// ATTRIBUTE, not an id: there is one container per app root and one more per\n// open <dialog>, so a document can legitimately hold several at once and a\n// fixed `id=\"domphy-floating\"` made every one after the first a duplicate id —\n// invalid HTML, and `document.getElementById`/`querySelector(\"#…\")` silently\n// resolved to whichever happened to come first in document order. Every lookup\n// below is `:scope >` scoped to one parent anyway, so uniqueness was never\n// what the selector needed.\nconst OVERLAY_ATTRIBUTE = \"data-domphy-floating\";\nconst OVERLAY_SELECTOR = `:scope > [${OVERLAY_ATTRIBUTE}]`;\n// Stamped on every floating panel element with its `kind` (\"tooltip\",\n// \"popover\", \"menu\", ...) so hasOpenFloatingPanel can tell a hover tooltip\n// apart from a layer the user is actually inside.\nconst OVERLAY_KIND_ATTRIBUTE = \"data-domphy-floating-kind\";\n\n/**\n * True while a popover/select/datePicker panel is mounted inside this\n * `<dialog>` (they portal into the dialog's own overlay container, see\n * `_portal`). A hover-only tooltip does NOT count: Radix's DismissableLayer\n * and React Aria's overlay stack both treat a hover tooltip as decoration,\n * not a layer the user is \"inside\" — it never consumes a Dismiss keypress.\n * Before this exclusion, a tooltip left open by a lingering hover cost the\n * dialog's Escape an extra press before it closed.\n *\n * Escape must dismiss only the TOP layer — Radix's DismissableLayer and React\n * Aria's overlay stack both stop at the innermost open layer. The browser\n * fires the dialog's `cancel` event for the same keypress that the panel's own\n * dismiss handler sees, so a modal dialog with an open dropdown closed\n * entirely on one Escape. The panel's `hide()` is debounced, so it is still\n * mounted when `cancel` arrives; the next Escape closes the dialog.\n */\nfunction hasOpenFloatingPanel(dialogElement: Element): boolean {\n const overlay = dialogElement.querySelector(OVERLAY_SELECTOR);\n if (!overlay) return false;\n return Array.from(overlay.children).some(\n (child) => child.getAttribute(OVERLAY_KIND_ATTRIBUTE) !== \"tooltip\",\n );\n}\n\ntype FloatingInstance = BehaviorInstance<FloatingProps> & {\n show: () => void;\n hide: () => void;\n panelId: string;\n};\n\n// The per-anchor persistent state a floating component needs (position\n// cleanup, the inserted panel node, debounce timer) used to live in\n// createFloating()'s own closure — but that closure is recreated fresh every\n// time a reactive ancestor re-renders the anchor (popover()/tooltip() called\n// again on the SAME reused DOM element). Only the FIRST-ever generation's\n// _onMount ever fires (ElementNode hooks run once per node), so imperative,\n// document-level listeners (outside-click, Escape-inside-panel) that closed\n// over that generation's `openState`/`reference`/`floating` kept acting on an\n// orphaned copy forever, while live-rebound trigger events (onClick etc.)\n// moved on to whatever generation was actually current — the trigger opened\n// the panel, but nothing could ever close it again from outside.\n//\n// Fixed by moving all of this into ONE `behavior()` instance per (anchor,\n// kind): `attach` runs once, and every later generation's `show`/`hide`\n// calls and `_behaviors` re-declaration route into that SAME instance via\n// `getBehavior`/`update()` — so there is exactly one canonical `openState`/\n// `reference`/`floating` for the anchor's whole lifetime, not one per\n// generation.\nfunction attachFloating(\n node: ElementNode,\n initialProps: FloatingProps,\n): FloatingInstance {\n let {\n openState,\n onDismiss,\n placement,\n content,\n keepOpenOnContentHover,\n openDelay,\n closeDelay,\n } = initialProps;\n const { kind } = initialProps;\n const behaviorKey = `floating:${kind}`;\n\n let timer: ReturnType<typeof setTimeout> | null = null;\n let cleanup: (() => void) | null = null;\n let floating: HTMLElement | null = null;\n let floatingNode: ElementNode | null = null;\n let mounted = false;\n\n const reference = node.domElement as HTMLElement;\n const rootNode = node.getRoot();\n const panelId = floatingPanelId(kind, node);\n\n const floatingPartial: PartialElement = {\n style: {\n position: \"fixed\",\n pointerEvents: \"auto\",\n visibility: (listener) =>\n openState.get(listener) ? \"visible\" : \"hidden\",\n },\n // Escape must dismiss the panel from INSIDE it too: the content is\n // portaled as a DOM sibling of the anchor, so a keydown on a focused\n // element within the panel (menu item, calendar cell, footer button)\n // never bubbles to the anchor's own Escape handler.\n //\n // Top-layer gated, like the document-level handler below. A nested\n // popover's TRIGGER is an ordinary element inside the outer panel, so an\n // Escape pressed there bubbles into this handler on the OUTER panel:\n // measured in Chromium, `outer trigger -> click -> inner trigger ->\n // Escape` removed BOTH panels at once and returned focus two levels, to\n // the outer trigger. Only the innermost open layer dismisses, and it\n // stops the event so no ancestor panel sees the same keypress.\n onKeyDown: (event) => {\n if ((event as KeyboardEvent).key !== \"Escape\") return;\n if (!isTopLayer()) return;\n event.stopPropagation();\n hide();\n },\n onMouseEnter: () => keepOpenOnContentHover && show(),\n onMouseLeave: () => keepOpenOnContentHover && hide(),\n _onMount: (mountedNode) => {\n floating = mountedNode.domElement as HTMLElement;\n // Stamped as a plain DOM property (not node.attributes.set) so a later\n // floatingNode.patch(content) — which strips undeclared ATTRIBUTES from\n // its own bookkeeping — never removes it. A consumer-declared id on the\n // content element wins.\n if (!floating.id) floating.id = panelId;\n floating.setAttribute(OVERLAY_KIND_ATTRIBUTE, kind);\n // Propagate data-theme from the trigger's ancestor so floating content\n // inherits CSS variable scope. Stamped on the PANEL, not the shared\n // overlay: the one overlay serves every floating component under the\n // root, so an overlay-level stamp would let whichever anchor opened\n // FIRST permanently impose its theme on later panels anchored under a\n // different [data-theme] scope. Skipped when the content declares its\n // own data-theme.\n if (reference && floating && !floating.hasAttribute(\"data-theme\")) {\n const dataTheme = reference\n .closest(\"[data-theme]\")\n ?.getAttribute(\"data-theme\");\n if (dataTheme) floating.setAttribute(\"data-theme\", dataTheme);\n }\n },\n _portal: (rNode) => {\n // showModal() puts the dialog in the top layer, above every z-index.\n // A panel portaled to the root overlay (z-index 20) would paint UNDER\n // an open dialog — drop it into the ancestor dialog instead so it\n // shares the top layer.\n const dialogHost = reference.closest(\"dialog\");\n if (dialogHost) {\n let overlay = dialogHost.querySelector(OVERLAY_SELECTOR);\n if (!overlay) {\n overlay = dialogHost.ownerDocument.createElement(\"div\");\n overlay.setAttribute(OVERLAY_ATTRIBUTE, \"\");\n Object.assign((overlay as HTMLElement).style, {\n position: \"fixed\",\n inset: \"0\",\n zIndex: \"20\",\n pointerEvents: \"none\",\n });\n dialogHost.appendChild(overlay);\n }\n return overlay;\n }\n // `:scope >` is load-bearing. The in-dialog branch above creates a\n // SECOND overlay container inside the <dialog>. A plain descendant\n // `querySelector(\"[data-domphy-floating]\")` returns the first match in\n // document order — the dialog's copy — so\n // once any popover/tooltip/select had been opened inside a modal\n // dialog, every later floating panel in the whole app was portaled\n // into that dialog. Measured: with the dialog closed (display:none,\n // set by dialog.ts's finalizeClose) the panel reported\n // aria-expanded=\"true\" and visibility:visible while its items had a\n // 0x0 rect and could not take focus. The root's own overlay is always\n // inserted as a DIRECT child of the root, so scoping is exact.\n let overlay = rNode.domElement!.querySelector(OVERLAY_SELECTOR);\n if (!overlay) {\n const overlayEle: DomphyElement<\"div\"> = {\n div: [],\n [OVERLAY_ATTRIBUTE]: \"\",\n style: {\n position: \"fixed\",\n inset: 0,\n zIndex: 20,\n pointerEvents: \"none\",\n },\n };\n const overlayNode = rNode.children!.insert(overlayEle) as ElementNode;\n overlay = overlayNode.domElement!;\n }\n return overlay;\n },\n };\n\n // Later generations declare their OWN fresh `content` object (a new object\n // literal at the popover()/tooltip() call site) — wire it every time, not\n // just at attach, so the panel wiring (theming, portal, dismiss handlers)\n // is present regardless of which generation's content ends up mounted.\n const wireContent = (target: DomphyElement) => merge(target, floatingPartial);\n wireContent(content);\n\n const ensureMounted = () => {\n if (mounted) return;\n mounted = true;\n floatingNode = rootNode.children!.insert(content) as ElementNode;\n // Expose THIS instance on the panel node too: the panel is portaled as a\n // child of the ROOT (not of the anchor), so getBehavior's ancestor walk\n // from a panel descendant (a selectBox/combobox option, a datePicker day\n // cell) never reaches the anchor's registration. Registering the same\n // instance on the panel lets panel-originated events resolve it via\n // `node.getBehavior(behaviorKey)` — the documented walk-up pattern. The\n // registration must be withdrawn again before the panel node is removed\n // (see detachPanel): its lifetime is owned by the ANCHOR, not the panel.\n floatingNode._behaviorInstances.set(behaviorKey, instance);\n };\n\n // ElementNode teardown DESTROYS every instance in the removed node's\n // `_behaviorInstances` (BeforeRemove hook + _dispose). The panel carries a\n // registration of the ANCHOR's instance, so removing the panel used to\n // destroy the anchor's behavior with it: measured in Chromium, after the\n // FIRST close of any popover/menu/select/tooltip the document-level\n // outside-click and Escape listeners were gone, and the component could\n // then only be closed by clicking its own trigger again. Withdraw the\n // borrowed registration first so only the panel's own state dies with it.\n const detachPanel = () => {\n if (!floatingNode) return;\n floatingNode._behaviorInstances.delete(behaviorKey);\n floatingNode.remove();\n floatingNode = null;\n };\n\n const instantShow = () => {\n // A re-render can detach the panel DOM without going through\n // instantHide (overlay reconcile, in-place patch). If we still think\n // we are mounted, skip insert and the panel never comes back.\n if (mounted && (!floating || !floating.isConnected)) {\n cleanup?.();\n cleanup = null;\n floatingNode = null;\n floating = null;\n mounted = false;\n }\n ensureMounted();\n if (reference && floating) {\n cleanup?.();\n cleanup = autoUpdate(reference, floating, () => {\n computePosition(reference as HTMLElement, floating as HTMLElement, {\n placement: placement.get() as Placement,\n // rootBoundary deliberately stays at the upstream default\n // ('viewport', i.e. the VISUAL viewport): with strategy \"fixed\" the\n // 1.8.0 'layoutViewport' option would stop clamping flip/shift to\n // the visible area, letting a panel land (partly) outside the\n // visible viewport during mobile pinch-zoom — a worse failure than\n // the jumpiness it fixes. Pinch-zoom/keyboard drift is already\n // handled by autoUpdate's post-1.8.0 observeMove re-anchoring.\n middleware: [offset(12), flip(), shift()],\n strategy: \"fixed\",\n }).then(({ x, y, placement: resolved }) => {\n // Teardown can run while computePosition's async work is in\n // flight (it nulls `floating` and removes the panel) — skip the\n // late positioning instead of dereferencing null.\n if (!floating) return;\n Object.assign(floating.style, {\n left: `${x}px`,\n top: `${y}px`,\n });\n placement.set(resolved);\n });\n });\n writeOpen(openState, true);\n }\n };\n // True only while the panel itself owns the focus. Shadow-root aware:\n // `document.activeElement` reports the shadow HOST for focus inside a shadow\n // tree, so `floating.contains(...)` would say false for a panel rendered in\n // one — ask the panel's own root instead.\n const focusIsInsidePanel = (): boolean => {\n if (!floating) return false;\n const root = floating.getRootNode() as Document | ShadowRoot;\n const active = (root as DocumentOrShadowRoot).activeElement;\n return !!active && floating.contains(active);\n };\n\n // The anchor is not always the focusable element: combobox anchors its panel\n // to the WRAPPER div and the tab stop is the `<input>` inside it, so a bare\n // reference.focus() was a no-op there and focus still ended on <body>\n // (measured). Fall back to the anchor's first tab stop.\n const focusReference = (): void => {\n if (!reference) return;\n reference.focus?.();\n const root = reference.getRootNode() as Document | ShadowRoot;\n const active = (root as DocumentOrShadowRoot).activeElement;\n if (active && reference.contains(active)) return;\n reference\n .querySelector<HTMLElement>(\n 'input, button, select, textarea, a[href], [tabindex]:not([tabindex=\"-1\"])',\n )\n ?.focus?.();\n };\n\n // Fully unmounts (not just CSS-hides) the panel — mirrors show()'s own\n // insert-on-demand: a closed floating component holds no DOM/listeners.\n // ensureMounted() re-inserts a fresh panel node next time show() runs.\n // Visual unmount runs even when the source is read-only (Computed).\n const instantHide = () => {\n cleanup?.();\n cleanup = null;\n // WCAG 2.4.3 Focus Order: removing the panel while it holds the focus\n // drops the caret to <body> and strands a keyboard user at the top of the\n // document (measured: selectBox trigger -> ArrowDown -> Escape left\n // document.activeElement === BODY). Radix DismissableLayer and React Aria\n // both return focus to the trigger. The containment test IS the\n // \"don't steal focus\" guard Radix gets from its pointer/focus-outside\n // tracking: if the dismissal happened because the user clicked or tabbed\n // to something else, the focus already left the panel and we leave it\n // alone. With nested panels only the innermost one contains the focus, so\n // Escape returns focus exactly one level.\n const restoreFocus = focusIsInsidePanel();\n detachPanel();\n floating = null;\n mounted = false;\n if (restoreFocus) focusReference();\n dismissOpen(openState, onDismiss);\n };\n const show = () => {\n timer && clearTimeout(timer);\n timer = setTimeout(instantShow, openDelay);\n };\n const hide = () => {\n timer && clearTimeout(timer);\n timer = setTimeout(instantHide, closeDelay);\n };\n\n const handleOutside = (event: MouseEvent) => {\n if (!openState.get() || !reference || !floating) return;\n const target = event.target as Node;\n if (!reference.contains(target) && !floating.contains(target)) hide();\n };\n rootNode.domElement?.addEventListener(\"click\", handleOutside);\n\n // Escape must dismiss an open panel from ANYWHERE, not just from the\n // trigger or inside the panel (peer parity: Radix DismissableLayer closes\n // on a document-level Escape) — a hover-opened tooltip with focus sitting\n // on <body> otherwise ignores Escape entirely. Keyboard events target the\n // FOCUSED element and bubble UP, so unlike the outside-click listener this\n // one must live on the document (keydown is composed, so panels inside a\n // shadow root still reach it). Idempotent alongside the trigger/panel-level\n // Escape handlers: hide() is debounced and re-arming it on an\n // already-closed panel is a no-op.\n // ...but only for the TOP layer. Panels portal as siblings of one another in\n // the shared overlay container in mount order, so the last element\n // child is the innermost open layer — the same stack Radix's DismissableLayer\n // keeps. Without this, a document-level Escape closed every open panel at\n // once: measured with a popover opened from inside another popover, one\n // Escape removed both, and because the outer's hide() ran first it tore out\n // the inner's trigger, so the restored focus landed on a detached element and\n // fell through to <body>. The panel's own `onKeyDown` above still closes\n // whichever layer actually holds the focus.\n const isTopLayer = () =>\n !!floating && floating.parentElement?.lastElementChild === floating;\n const handleEscape = (event: Event) => {\n if (\n (event as KeyboardEvent).key === \"Escape\" &&\n openState.get() &&\n isTopLayer()\n )\n hide();\n };\n const escapeTarget: EventTarget | null =\n rootNode.domElement?.ownerDocument ?? rootNode.domElement ?? null;\n escapeTarget?.addEventListener(\"keydown\", handleEscape);\n\n // Caller-driven open (open.set(true) / open:true) must insert the panel —\n // show()/hide() are only the trigger-event path. Guard with `mounted` so\n // instantShow/instantHide's own writeOpen/dismissOpen does not recurse\n // (writable State.set notifies listeners).\n const onOpen = (val: boolean) => {\n if (val) {\n if (!mounted) instantShow();\n } else if (mounted) {\n instantHide();\n }\n };\n let release = () => {};\n let destroyed = false;\n let updating = false;\n let instance: FloatingInstance;\n\n // Stamped after `instance` exists. The panel is patched in place on every\n // generation; patch() prunes _behaviorInstances keys absent from the new\n // descriptor and destroy()s them. The instance is SHARED with the anchor —\n // pruning it unmounts the live panel. Declaring the key on the content\n // keeps prune from treating it as leftover.\n const stampPanelBehavior = (target: DomphyElement) => {\n target._behaviors = {\n ...(target._behaviors ?? {}),\n [behaviorKey]: { attach: () => instance, props: {} },\n };\n };\n\n instance = {\n show,\n hide,\n panelId,\n update(props) {\n if (updating) return;\n onDismiss = props.onDismiss;\n if (props.openState !== openState) {\n release();\n openState = props.openState;\n // emitCurrent false: a fresh uncontrolled toState(false) on a reused\n // node is not a caller close.\n release = subscribeOpen(openState, onOpen, false);\n // Show if the new object is already true (open:true / caller-owned).\n if (openState.get()) instantShow();\n }\n placement = props.placement;\n content = props.content;\n keepOpenOnContentHover = props.keepOpenOnContentHover;\n openDelay = props.openDelay;\n closeDelay = props.closeDelay;\n wireContent(content);\n stampPanelBehavior(content);\n // Reflect the new generation's declared content into the already-\n // mounted panel in place (same DOM node, no flicker/teardown) — the\n // ordinary reused-node \"patch, don't recreate\" contract, applied to\n // the imperatively-inserted panel too.\n if (floatingNode) {\n updating = true;\n try {\n floatingNode.patch(content);\n } finally {\n updating = false;\n }\n }\n },\n destroy() {\n if (destroyed) return;\n destroyed = true;\n if (timer) clearTimeout(timer);\n timer = null;\n cleanup?.();\n cleanup = null;\n detachPanel();\n floating = null;\n mounted = false;\n release();\n release = () => {};\n rootNode.domElement?.removeEventListener(\"click\", handleOutside);\n escapeTarget?.removeEventListener(\"keydown\", handleEscape);\n },\n };\n stampPanelBehavior(content);\n // After `instance` exists: ensureMounted registers it on the panel node.\n // subscribeOpen notifies immediately (replaces onOpen(openState.get())).\n release = subscribeOpen(openState, onOpen);\n return instance;\n}\n\nfunction createFloating(props: {\n kind: string;\n open?: ValueOrState<boolean>;\n onDismiss?: () => void;\n placement: State<Placement>;\n content: DomphyElement;\n keepOpenOnContentHover?: boolean;\n // Hover-intent debounce, in ms. Defaults to FLOATING_DEFAULT_DELAY_MS.\n openDelay?: number;\n closeDelay?: number;\n}) {\n const { kind, placement, onDismiss } = props;\n const openState = asOpenState(props.open);\n const behaviorKey = `floating:${kind}`;\n\n // Trigger event handlers ARE live-rebound on every patch and already\n // receive the current ElementNode as their 2nd argument (unlike lifecycle\n // hooks) — so show(node)/hide(node) just forward to whatever instance is\n // attached there, regardless of which generation's closure is calling.\n const show = (node?: ElementNode) =>\n node?.getBehavior<FloatingInstance>(behaviorKey)?.show();\n const hide = (node?: ElementNode) =>\n node?.getBehavior<FloatingInstance>(behaviorKey)?.hide();\n\n // Plain spread, NOT merge(): merge() defensively deep-clones its `target`\n // argument, which would snapshot `props.content` right now — but the\n // caller (popover()/tooltip()) hasn't finished mutating it yet (it pushes\n // its OWN partial onto `content.$` right after this call returns). A\n // premature clone silently drops that later mutation, so the panel loses\n // its role/style/dismiss wiring. Spread keeps the `_behaviors` record's\n // `props.content` a live reference to the SAME object the caller mutates.\n const anchorPartial: PartialElement = {\n onKeyDown: (e: Event, node: ElementNode) =>\n (e as KeyboardEvent).key === \"Escape\" && hide(node),\n ...behavior<FloatingProps>(behaviorKey, attachFloating, {\n kind,\n openState,\n onDismiss,\n placement,\n content: props.content,\n keepOpenOnContentHover: !!props.keepOpenOnContentHover,\n openDelay: props.openDelay ?? FLOATING_DEFAULT_DELAY_MS,\n closeDelay: props.closeDelay ?? FLOATING_DEFAULT_DELAY_MS,\n }),\n };\n\n return { show, hide, anchorPartial, openState };\n}\n\nexport { createFloating, floatingPanelId, hasOpenFloatingPanel };\n","import {\n effect,\n type ReadableState,\n type State,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\n\nexport function isWritableState<T>(\n source: ReadableState<T>,\n): source is State<T> {\n return typeof (source as State<T>).set === \"function\";\n}\n\n/**\n * Subscribe to overlay `open`. Writable State uses `addListener` (no\n * fabricated `.set()`, existing listenerCount-on-remove tests). Computed has\n * no `addListener` — `effect()` reads `get()`.\n *\n * `emitCurrent` (default true) delivers the value once on subscribe, matching\n * first-attach `update(state.get())`. Pass false when re-subscribing on a\n * reused node so a fresh uncontrolled `toState(false)` is not a caller close.\n */\nexport function subscribeOpen(\n source: ReadableState<boolean>,\n onChange: (open: boolean) => void,\n emitCurrent = true,\n): () => void {\n if (typeof (source as State<boolean>).addListener === \"function\") {\n if (emitCurrent) onChange(source.get());\n return (source as State<boolean>).addListener(onChange);\n }\n if (emitCurrent) {\n return effect(() => {\n onChange(source.get());\n });\n }\n let skipInitial = true;\n const release = effect(() => {\n const value = source.get();\n if (skipInitial) return;\n onChange(value);\n });\n skipInitial = false;\n return release;\n}\n\nexport function writeOpen(\n source: ReadableState<boolean>,\n value: boolean,\n): void {\n if (isWritableState(source)) source.set(value);\n}\n\nexport function dismissOpen(\n source: ReadableState<boolean>,\n onDismiss?: () => void,\n): void {\n onDismiss?.();\n writeOpen(source, false);\n}\n\nexport function asOpenState(\n open: ValueOrState<boolean> | undefined,\n): ReadableState<boolean> {\n return toState(open ?? false);\n}\n","/**\n * Every `[role=option]` under `root` that is not disabled, in DOM order.\n *\n * Lives in `utils/` rather than in one of the patch modules because\n * `patches.ts` re-exports each patch module with `export *` — an export there\n * would put this internal DOM walk in the public API. Shared by `selectList`\n * (its own listbox key model), `selectBox` (typeahead + arrow entry into the\n * panel) and `combobox` (arrow entry into the popup).\n */\nfunction enabledOptionsIn(root: Element | null): HTMLElement[] {\n if (!root) return [];\n return Array.from(root.querySelectorAll<HTMLElement>(\"[role=option]\")).filter(\n (el) =>\n el.getAttribute(\"aria-disabled\") !== \"true\" &&\n !el.hasAttribute(\"disabled\"),\n );\n}\n\nexport { enabledOptionsIn };\n","import {\n behavior,\n type DomphyElement,\n ElementNode,\n type PartialElement,\n rawHtml,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\nconst xSvg = `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"/><path d=\"M6.707 5.293l5.293 5.292l5.293 -5.292a1 1 0 0 1 1.414 1.414l-5.292 5.293l5.292 5.293a1 1 0 0 1 -1.414 1.414l-5.293 -5.292l-5.293 5.292a1 1 0 1 1 -1.414 -1.414l5.292 -5.293l-5.292 -5.293a1 1 0 0 1 1.414 -1.414\" /></svg>`;\n\n// Compact-chip chrome was bare `themeSpacing(U)` (catalog snapshots). Default\n// density is 1.5 (`light.densities[2]`, density.ts origin index 2). n = U / 1.5\n// keeps those pixels at default while dataDensity still scales. Height 6U must\n// stay below selectBox/combobox minHeight `(6 + 2d)U` or the chip fills the trigger.\nconst DEFAULT_DENSITY = 1.5;\nconst TAG_HEIGHT = 6 / DEFAULT_DENSITY;\nconst TAG_PAD_INLINE = 2.5 / DEFAULT_DENSITY;\nconst TAG_PAD_END_REMOVABLE = 1 / DEFAULT_DENSITY;\nconst TAG_REMOVE = 4 / DEFAULT_DENSITY;\nconst TAG_REMOVE_RADIUS = 1 / DEFAULT_DENSITY;\n\ntype TagRemoveProps = { removable: boolean };\n\n/**\n * Styles an inline chip/tag (rounded, bordered, optional remove button).\n * No host tag check; typically applied to a `<span>`. When `removable` is true,\n * a close button is inserted that removes the host node on click or Enter/Space.\n *\n * @hostTag span\n * @param props.color - Theme color for the chip background/border/text. Optional, accepts a value or state. Defaults to `\"neutral\"`.\n * @param props.removable - When true, renders a remove (x) button that removes the tag on click or Enter/Space. Optional. Defaults to `false`.\n * @example { span: \"Label\", $: [tag({ removable: true })] }\n */\nfunction tag(\n props: { color?: ValueOrState<ThemeColor>; removable?: boolean } = {},\n): PartialElement {\n const { removable = false } = props;\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n dataTone: \"shift-2\",\n // _onInit would miss/orphan the button when a reused node is re-patched\n // with a flipped `removable`. behavior() attaches once and routes later\n // generations through update().\n ...behavior<TagRemoveProps>(\n \"tag-remove\",\n (node, initial) => {\n const removeHost = () => node.remove();\n const makeButton = (): DomphyElement<\"span\"> => ({\n span: rawHtml(xSvg),\n _key: \"tag-remove\",\n onClick: (e) => {\n (e as Event).stopPropagation();\n removeHost();\n },\n onKeyDown: (e) => {\n const event = e as KeyboardEvent;\n if (event.key !== \"Enter\" && event.key !== \" \") return;\n event.preventDefault();\n event.stopPropagation();\n removeHost();\n },\n tabindex: 0,\n role: \"button\",\n ariaLabel: \"Remove\",\n style: {\n display: \"inline-flex\",\n alignItems: \"center\",\n cursor: \"pointer\",\n borderRadius: (listener) =>\n themeSpacing(themeDensity(listener) * TAG_REMOVE_RADIUS),\n width: (listener) =>\n themeSpacing(themeDensity(listener) * TAG_REMOVE),\n height: (listener) =>\n themeSpacing(themeDensity(listener) * TAG_REMOVE),\n flexShrink: 0,\n transition: \"background-color 140ms ease, box-shadow 140ms ease\",\n \"&:hover\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-4\", color.get(listener)),\n },\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, color.get(listener)),\n },\n },\n });\n const findButton = () =>\n node.children.items.find(\n (item) => item instanceof ElementNode && item.key === \"tag-remove\",\n ) ?? null;\n // attach() runs from the host Mount hook, which fires bottom-up: the\n // children walk has already finished by then (both on a fresh render\n // and on hydration), so the button always has to be materialized here.\n // The list-only insert this used to do on first paint relied on the\n // old top-down Mount and left the button DOM-less after hydration.\n const sync = (next: TagRemoveProps) => {\n const existing = findButton();\n if (next.removable && !existing) {\n node.children.insert(makeButton());\n } else if (!next.removable && existing) {\n node.children.remove(existing);\n }\n };\n sync(initial);\n return {\n update: sync,\n };\n },\n { removable },\n ),\n style: {\n display: \"inline-flex\",\n // A chip hugs its label. Measured in Chromium: inside a `stack()` the\n // pill stretched to the full 1232px column (shadcn's badge carries the\n // same `w-fit` for this reason) — `inline-flex` is blockified by a\n // flex/grid parent.\n width: \"fit-content\",\n alignItems: \"center\",\n whiteSpace: \"nowrap\",\n userSelect: \"none\",\n height: (listener) => themeSpacing(themeDensity(listener) * TAG_HEIGHT),\n paddingBlock: 0,\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 999),\n paddingInlineStart: (listener) =>\n themeSpacing(themeDensity(listener) * TAG_PAD_INLINE),\n paddingInlineEnd: (listener) =>\n themeSpacing(\n themeDensity(listener) *\n (removable ? TAG_PAD_END_REMOVABLE : TAG_PAD_INLINE),\n ),\n gap: themeSpacing(1.5),\n fontSize: (listener) => themeSize(listener, \"decrease-1\"),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n border: \"none\",\n outlineOffset: \"-1px\",\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", color.get(listener))}`,\n },\n };\n}\n\nexport { tag };\n","import {\n type ElementNode,\n merge,\n type PartialElement,\n toState,\n} from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { fieldTextStyle } from \"../utils/fieldText.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n// Items opt in with `data-command-item`; `commandItem` hides non-matching\n// rows with the `hidden` attribute, so the filter and the keyboard walk\n// agree on what is currently on screen.\nfunction visibleItems(host: HTMLElement): HTMLElement[] {\n return Array.from(\n host.querySelectorAll<HTMLElement>(\"[data-command-item]\"),\n ).filter((el) => !el.hidden && !el.hasAttribute(\"disabled\"));\n}\n\n// Arrow-key navigation over the filtered result list is what makes a command\n// palette usable from the search field (cmdk / shadcn Command parity): without\n// it the only way to reach a result was Tab, which also walked every hidden\n// row's siblings. Enter runs the highlighted item.\nfunction onCommandKey(event: Event, node: ElementNode): void {\n const key = (event as KeyboardEvent).key;\n const host = node.domElement as HTMLElement | null;\n if (!host) return;\n const items = visibleItems(host);\n if (!items.length) return;\n const active = host.ownerDocument.activeElement as HTMLElement | null;\n const current = active ? items.indexOf(active) : -1;\n\n if (key === \"Enter\") {\n if (current === -1) return;\n event.preventDefault();\n items[current]!.click();\n return;\n }\n\n let next: number;\n // Wraps at both ends — the search field stays focused until Down is pressed,\n // so there is no \"above the first item\" position to fall back to.\n if (key === \"ArrowDown\") next = (current + 1) % items.length;\n else if (key === \"ArrowUp\")\n next = current <= 0 ? items.length - 1 : current - 1;\n else if (key === \"Home\") next = 0;\n else if (key === \"End\") next = items.length - 1;\n else return;\n\n event.preventDefault();\n const target = items[next]!;\n target.focus();\n target.scrollIntoView?.({ block: \"nearest\" });\n}\n\n/**\n * Command-palette container patch. Sets up a vertical flex column and provides a\n * shared `command` context (a query State) consumed by `commandSearch` and\n * `commandItem` descendants to filter the list. Typically applied to a `<div>`.\n *\n * @example { div: [...], $: [command()] }\n */\nfunction command(): PartialElement {\n return {\n // Group (not listbox): search input + option buttons share one container;\n // listbox forbids non-option children (aria-required-children).\n role: \"group\",\n ariaLabel: \"Commands\",\n onKeyDown: onCommandKey,\n _onSchedule: (_node, element) => {\n merge(element, {\n _context: {\n command: {\n query: toState(\"\"),\n },\n },\n });\n },\n style: {\n display: \"flex\",\n flexDirection: \"column\",\n overflow: \"hidden\",\n },\n };\n}\n\n/**\n * Search input for a command palette. Wires the input's value into the parent\n * `command` context's query State so descendant `commandItem`s filter live.\n * Apply to an `<input>` element used inside a `command()`.\n *\n * @hostTag input\n * @param props.color - Base theme color tone. Defaults to \"neutral\".\n * @param props.accentColor - Accent color used for the focus border. Defaults to \"primary\".\n * @example { input: null, $: [commandSearch({ accentColor: \"primary\" })] }\n */\nfunction commandSearch(\n props: { color?: ThemeColor; accentColor?: ThemeColor } = {},\n): PartialElement {\n const { color = \"neutral\", accentColor = \"primary\" } = props;\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"input\") {\n console.warn(`\"commandSearch\" patch must use input tag`);\n }\n },\n _onMount: (node) => {\n const ctx = node.getContext(\"command\");\n if (!ctx) {\n console.warn(`\"commandSearch\" patch must be used inside a \"command\"`);\n return;\n }\n const input = node.domElement as HTMLInputElement;\n const onInput = () => ctx.query.set(input.value);\n input.addEventListener(\"input\", onInput);\n node.addHook(\"Remove\", () => input.removeEventListener(\"input\", onInput));\n },\n style: {\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 3),\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 2),\n border: \"none\",\n borderBottom: (listener) =>\n `1px solid ${themeColor(listener, \"border\", color)}`,\n outline: \"none\",\n ...fieldTextStyle(color),\n backgroundColor: (listener) => themeColor(listener, \"inherit\", color),\n transition: \"border-bottom-color 140ms ease, box-shadow 140ms ease\",\n \"&:focus-visible\": {\n borderBottomColor: (listener) =>\n themeColor(listener, \"shift-6\", accentColor),\n boxShadow: (listener) => focusRing(listener, accentColor),\n },\n },\n };\n}\n\n/**\n * Selectable item in a command palette. On mount, immediately hides itself if\n * the current query doesn't match its text content, and subscribes to future\n * query changes — so items added dynamically after a search is typed are\n * correctly filtered. Apply to a `<button>` inside a `command()`. Uses native\n * button semantics (not `role=option`) so the search input may sit as a\n * sibling without a listbox parent requirement. A non-focusable host (a bare\n * `<div>`) still filters, but the container's arrow-key walk calls `focus()`\n * on it and that is a no-op — give such a host a `tabindex` of its own.\n *\n * @param props.color - Base theme color tone. Defaults to \"neutral\".\n * @param props.accentColor - Accent color used for the focus ring. Defaults to \"primary\".\n * @example { button: \"Open file\", $: [commandItem({ color: \"neutral\" })] }\n */\nfunction commandItem(\n props: { color?: ThemeColor; accentColor?: ThemeColor } = {},\n): PartialElement {\n const { color = \"neutral\", accentColor = \"primary\" } = props;\n return {\n // Native `type` on the host still wins (mergePartial: native over patch).\n type: \"button\",\n // Marker the container's keyboard walk looks for.\n dataCommandItem: \"\",\n _onMount: (node) => {\n const ctx = node.getContext(\"command\");\n if (!ctx) {\n console.warn(`\"commandItem\" patch must be used inside a \"command\"`);\n return;\n }\n const el = node.domElement as HTMLElement;\n // Read the label AT FILTER TIME. Captured once in _onMount it was the\n // empty string — _onMount fires before the child text node is attached —\n // so the first keystroke hid every item in the palette. Reading late\n // also keeps a reactive label in sync.\n const applyFilter = (q: string) => {\n if (q.length === 0) {\n el.hidden = false;\n return;\n }\n const text = el.textContent?.toLowerCase() ?? \"\";\n el.hidden = !text.includes(q.toLowerCase());\n };\n applyFilter(ctx.query.get());\n const release = ctx.query.addListener(applyFilter);\n node.addHook(\"Remove\", release);\n },\n style: {\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n width: \"100%\",\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n height: (listener) => themeSpacing(6 + themeDensity(listener) * 2),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 3),\n border: \"none\",\n outline: \"none\",\n // shift-13: menu-row labels need ≥4.5:1 on light surface (visual catalog).\n color: (listener) => themeColor(listener, \"shift-13\", color),\n backgroundColor: (listener) => themeColor(listener, \"inherit\", color),\n transition: \"background-color 140ms ease, box-shadow 140ms ease\",\n \"&:hover:not([disabled])\": {\n color: (listener) => themeColor(listener, \"shift-13\", color),\n backgroundColor: (listener) => themeColor(listener, \"hover\", color),\n },\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, accentColor),\n },\n },\n };\n}\n\nexport { command, commandSearch, commandItem };\n","import {\n type BehaviorInstance,\n behavior,\n type DomphyElement,\n type ElementNode,\n type Listener,\n merge,\n type PartialElement,\n type State,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport type { Placement } from \"@domphy/floating\";\nimport {\n type ThemeColor,\n textToneOn,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n themeWeight,\n} from \"@domphy/theme\";\nimport { elevation } from \"../utils/elevation.js\";\nimport { createFloating, floatingPanelId } from \"../utils/floating.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/** A single date selection, or a `[start, end]` tuple in range mode. */\nexport type DatePickerValue = Date | null | [Date | null, Date | null];\n\nexport interface DatePickerProps {\n /** Controlled value: a `Date` in single mode, a `[start, end]` tuple in range mode. */\n value?: ValueOrState<DatePickerValue>;\n /** Selection mode. */\n mode?: \"single\" | \"range\";\n /** Also pick hour + minute. The chosen time applies to the selected date(s). */\n time?: boolean;\n /** Earliest selectable day (inclusive). */\n min?: Date;\n /** Latest selectable day (inclusive). */\n max?: Date;\n /** Disable arbitrary days. */\n disabledDate?: (date: Date) => boolean;\n /** BCP-47 locale for month/weekday names, first-day-of-week, and formatting. */\n locale?: string;\n /** Override the first day of the week (0 = Sunday … 6 = Saturday). */\n weekStartsOn?: number;\n /** Override the input display string. */\n format?: (value: DatePickerValue) => string;\n /** Called whenever the selection changes. */\n onChange?: (value: DatePickerValue) => void;\n /** Accent color for the selected/active days. */\n accentColor?: ValueOrState<ThemeColor>;\n /** Popover placement relative to the input. */\n placement?: ValueOrState<Placement>;\n}\n\n// --- date helpers (no third-party library) -----------------------------------\n\nconst atMidnight = (date: Date): Date =>\n new Date(date.getFullYear(), date.getMonth(), date.getDate());\nconst addDays = (date: Date, count: number): Date =>\n new Date(date.getFullYear(), date.getMonth(), date.getDate() + count);\nconst addMonths = (date: Date, count: number): Date =>\n new Date(date.getFullYear(), date.getMonth() + count, date.getDate());\nconst sameDay = (a: Date | null, b: Date | null): boolean =>\n !!a &&\n !!b &&\n a.getFullYear() === b.getFullYear() &&\n a.getMonth() === b.getMonth() &&\n a.getDate() === b.getDate();\nconst isoOf = (date: Date): string =>\n `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, \"0\")}-${String(\n date.getDate(),\n ).padStart(2, \"0\")}`;\nconst startOfWeek = (date: Date, weekStart: number): Date =>\n addDays(date, -((date.getDay() - weekStart + 7) % 7));\n\n/** Resolves the locale's first day of week, falling back to Sunday. */\nfunction localeWeekStart(locale: string): number {\n try {\n const localeObject = new Intl.Locale(locale) as Intl.Locale & {\n weekInfo?: { firstDay: number };\n getWeekInfo?: () => { firstDay: number };\n };\n const info = localeObject.getWeekInfo?.() ?? localeObject.weekInfo;\n if (info?.firstDay) return info.firstDay % 7; // Intl uses 1=Mon … 7=Sun\n } catch {\n // unsupported locale or engine — fall through to Sunday\n }\n return 0;\n}\n\n// --- per-node state preservation (reused-node lifecycle) -------------------\n\ntype DatePickerStates = {\n selection: State<DatePickerValue>;\n // When the caller passed `value`, each generation's toState(Date) is a\n // new object whose current value IS the caller's Date — copying the\n // previous internal selection onto it would overwrite that Date.\n selectionIsCallerOwned: boolean;\n viewYear: State<number>;\n viewMonth: State<number>;\n focused: State<Date>;\n hovered: State<Date | null>;\n hour: State<number>;\n minute: State<number>;\n open: State<boolean>;\n onChange?: (value: DatePickerValue) => void;\n};\n\n// Every ancestor re-render re-invokes datePicker() on the SAME reused input\n// node, allocating a fresh set of internal states with INITIAL values —\n// without carry-forward the user's uncontrolled selection, calendar view and\n// time silently reset on the next re-render, and the onChange subscription\n// (wired to the first generation's selection object) goes stale. ONE\n// behavior instance per node copies the live values into each new\n// generation's states (update() runs during patch(), before the fresh\n// input/calendar bindings evaluate) and keeps exactly one onChange\n// subscription on the CURRENT generation's selection.\nfunction attachDatePicker(\n _node: ElementNode,\n initialProps: DatePickerStates,\n): BehaviorInstance<DatePickerStates> {\n let current = initialProps;\n let releaseOnChange: (() => void) | null = null;\n const subscribe = (props: DatePickerStates) => {\n releaseOnChange?.();\n releaseOnChange = props.onChange\n ? props.selection.addListener((value) => props.onChange!(value))\n : null;\n };\n const carryForward = (next: State<any>, prev: State<any>) => {\n if (next !== prev) next.set(prev.get());\n };\n subscribe(current);\n return {\n update(next) {\n if (!next.selectionIsCallerOwned) {\n carryForward(next.selection, current.selection);\n }\n carryForward(next.viewYear, current.viewYear);\n carryForward(next.viewMonth, current.viewMonth);\n carryForward(next.focused, current.focused);\n carryForward(next.hovered, current.hovered);\n carryForward(next.hour, current.hour);\n carryForward(next.minute, current.minute);\n carryForward(next.open, current.open);\n if (\n next.selection !== current.selection ||\n next.onChange !== current.onChange\n ) {\n // Re-subscribe AFTER the carry-forward so it never fires onChange.\n subscribe(next);\n }\n current = next;\n },\n destroy() {\n releaseOnChange?.();\n releaseOnChange = null;\n },\n };\n}\n\n/**\n * A native, themeable date picker patch for an `<input>`. Opens a calendar\n * popover (rendered with Domphy elements, positioned via `@domphy/floating`)\n * supporting single/range selection, optional time, min/max + disabled days,\n * localized names, and keyboard navigation. The input is read-only and shows the\n * formatted selection; compose with `inputText()` for the input's look.\n *\n * @hostTag input\n * @param props.value - Controlled value (`ValueOrState<DatePickerValue>`): a `Date`/`null` in single mode, a `[start, end]` tuple in range mode.\n * @param props.mode - Selection mode, \"single\" | \"range\". Defaults to \"single\".\n * @param props.time - When true, also pick hour + minute (applied to the selected date(s)). Defaults to false.\n * @param props.min - Earliest selectable day (inclusive), a `Date`.\n * @param props.max - Latest selectable day (inclusive), a `Date`.\n * @param props.disabledDate - Predicate `(date: Date) => boolean` to disable arbitrary days.\n * @param props.locale - BCP-47 locale for names/first-day-of-week/formatting. Defaults to `navigator.language` (or \"en-US\" in non-browser).\n * @param props.weekStartsOn - Override first day of week (0 = Sunday … 6 = Saturday). Defaults to the locale's first day.\n * @param props.format - Override the input display string, `(value: DatePickerValue) => string`.\n * @param props.onChange - Called with the new value whenever the selection changes, `(value: DatePickerValue) => void`.\n * @param props.accentColor - Accent color (`ValueOrState<ThemeColor>`) for selected/active days. Defaults to \"primary\".\n * @param props.placement - Popover placement (`ValueOrState<Placement>`) relative to the input. Defaults to \"bottom-start\".\n * @example { input: null, $: [inputText(), datePicker({ mode: \"range\" })] }\n */\nfunction datePicker(props: DatePickerProps = {}): PartialElement {\n const {\n mode = \"single\",\n time = false,\n min,\n max,\n disabledDate,\n locale = typeof navigator !== \"undefined\" ? navigator.language : \"en-US\",\n format,\n onChange,\n } = props;\n\n const weekStart = props.weekStartsOn ?? localeWeekStart(locale);\n const accentColor = toState(props.accentColor ?? \"primary\", \"accentColor\");\n const placeState = toState(props.placement ?? \"bottom-start\");\n\n const selection = toState<DatePickerValue>(\n props.value ?? (mode === \"range\" ? [null, null] : null),\n );\n\n const primaryDate = ((): Date => {\n const current = selection.get();\n const base =\n mode === \"range\" ? (current as [Date | null, Date | null])?.[0] : current;\n return base instanceof Date ? base : new Date();\n })();\n\n const viewYear = toState(primaryDate.getFullYear(), \"viewYear\");\n const viewMonth = toState(primaryDate.getMonth(), \"viewMonth\");\n const focused = toState<Date>(atMidnight(primaryDate), \"focused\");\n const hovered = toState<Date | null>(null, \"hovered\");\n const hour = toState(primaryDate.getHours(), \"hour\");\n const minute = toState(primaryDate.getMinutes(), \"minute\");\n\n // --- formatting -----------------------------------------------------------\n const dateFormatter = new Intl.DateTimeFormat(locale, {\n dateStyle: \"medium\",\n ...(time ? { timeStyle: \"short\" as const } : {}),\n });\n const monthFormatter = new Intl.DateTimeFormat(locale, {\n month: \"long\",\n year: \"numeric\",\n });\n const weekdayFormatter = new Intl.DateTimeFormat(locale, {\n weekday: \"short\",\n });\n const fullDateFormatter = new Intl.DateTimeFormat(locale, {\n dateStyle: \"full\",\n });\n\n const formatOne = (date: Date | null): string =>\n date ? dateFormatter.format(date) : \"\";\n const formatDisplay = (value: DatePickerValue): string => {\n if (format) return format(value);\n if (mode === \"range\") {\n const [start, end] = (value as [Date | null, Date | null]) ?? [\n null,\n null,\n ];\n return start ? `${formatOne(start)} – ${formatOne(end)}` : \"\";\n }\n return formatOne(value as Date | null);\n };\n\n // 2023-01-01 is a Sunday, so index 0 maps to Sunday before the week-start shift.\n const weekdayNames = Array.from({ length: 7 }, (_unused, index) =>\n weekdayFormatter.format(new Date(2023, 0, 1 + ((index + weekStart) % 7))),\n );\n\n // --- selection logic ------------------------------------------------------\n const isDisabled = (date: Date): boolean =>\n (!!min && atMidnight(date) < atMidnight(min)) ||\n (!!max && atMidnight(date) > atMidnight(max)) ||\n (!!disabledDate && disabledDate(date));\n\n const withTime = (date: Date): Date => {\n if (!time) return atMidnight(date);\n const result = atMidnight(date);\n result.setHours(hour.get(), minute.get(), 0, 0);\n return result;\n };\n\n const selectDate = (date: Date, node?: ElementNode): void => {\n if (isDisabled(date)) return;\n if (mode === \"single\") {\n selection.set(withTime(date));\n // Close via the cell's node: the floating behavior instance is\n // registered on the panel node (floating.ts), so getBehavior's\n // ancestor walk from any panel descendant resolves it.\n if (!time) hide(node);\n return;\n }\n const [start, end] = (selection.get() as [Date | null, Date | null]) ?? [\n null,\n null,\n ];\n if (!start || (start && end)) {\n selection.set([withTime(date), null]);\n } else if (atMidnight(date) < atMidnight(start)) {\n selection.set([withTime(date), withTime(start)]);\n if (!time) hide(node);\n } else {\n selection.set([start, withTime(date)]);\n if (!time) hide(node);\n }\n };\n\n const reapplyTime = (): void => {\n if (!time) return;\n if (mode === \"single\") {\n const current = selection.get() as Date | null;\n if (current) selection.set(withTime(current));\n } else {\n const [start, end] = (selection.get() as [Date | null, Date | null]) ?? [\n null,\n null,\n ];\n selection.set([\n start ? withTime(start) : start,\n end ? withTime(end) : end,\n ]);\n }\n };\n\n const inSelectedRange = (date: Date, listener?: Listener): boolean => {\n if (mode !== \"range\") return false;\n const [start, end] = (selection.get(listener) as [\n Date | null,\n Date | null,\n ]) ?? [null, null];\n const tail = end ?? hovered.get(listener);\n if (!start || !tail) return false;\n const low = atMidnight(start) <= atMidnight(tail) ? start : tail;\n const high = atMidnight(start) <= atMidnight(tail) ? tail : start;\n const day = atMidnight(date);\n return day >= atMidnight(low) && day <= atMidnight(high);\n };\n\n const isSelectedEnd = (date: Date, listener?: Listener): boolean => {\n const current = selection.get(listener);\n if (mode === \"range\") {\n const [start, end] = (current as [Date | null, Date | null]) ?? [\n null,\n null,\n ];\n return sameDay(date, start) || sameDay(date, end);\n }\n return sameDay(date, current as Date | null);\n };\n\n // --- view navigation ------------------------------------------------------\n const goToDate = (date: Date): void => {\n viewYear.set(date.getFullYear());\n viewMonth.set(date.getMonth());\n };\n const shiftMonth = (delta: number): void => {\n const next = addMonths(new Date(viewYear.get(), viewMonth.get(), 1), delta);\n goToDate(next);\n };\n const shiftYear = (delta: number): void =>\n viewYear.set(viewYear.get() + delta);\n\n const focusActiveCell = (node?: ElementNode): void => {\n // Resolve the panel from the caller's live node (trigger or grid cell):\n // the old factory-scope `contentElement` was only ever assigned by the\n // first panel generation's _onMount, so later generations (reused node,\n // fresh closure) could never move focus into the grid.\n const root = node?.getRoot()?.domElement;\n setTimeout(() => {\n root\n ?.querySelector<HTMLElement>(`[data-date=\"${isoOf(focused.get())}\"]`)\n ?.focus();\n }, 0);\n };\n\n // --- floating popover ------------------------------------------------------\n const calendar = buildCalendar();\n const openState = toState(false);\n const { show, hide, anchorPartial } = createFloating({\n kind: \"datePicker\",\n open: openState,\n placement: placeState,\n content: calendar,\n });\n\n // Move focus into the grid when the popover opens.\n const triggerPartial: PartialElement = {\n type: \"text\",\n readonly: true,\n value: (listener) => formatDisplay(selection.get(listener)),\n role: \"combobox\",\n ariaHaspopup: \"dialog\",\n ariaExpanded: (listener) => openState.get(listener),\n ariaControls: (listener) =>\n listener?.elementNode\n ? floatingPanelId(\"datePicker\", listener.elementNode)\n : undefined,\n ariaLabel: \"Choose date\",\n style: { cursor: \"pointer\" },\n onClick: (_e, node) => {\n openAndFocus(node);\n },\n // NOT on focus. The APG combobox contract is \"Escape dismisses the popup\n // and returns focus to the combobox\" — and floating.ts now does return the\n // focus — so an onFocus that re-opens makes Escape permanently\n // un-dismissable (measured in Chromium: panel back within 100ms of every\n // Escape). It also popped the calendar over the next fields whenever a\n // keyboard user merely Tabbed through the form. Click, ArrowDown and Enter\n // cover every path, as in the APG Date Picker Combobox example, React Aria\n // and MUI.\n onKeyDown: (event, node) => {\n const key = (event as KeyboardEvent).key;\n if (key === \"ArrowDown\" || key === \"Enter\") {\n event.preventDefault();\n openAndFocus(node);\n }\n },\n ...behavior<DatePickerStates>(\"datePicker\", attachDatePicker, {\n selection,\n selectionIsCallerOwned: props.value !== undefined,\n viewYear,\n viewMonth,\n focused,\n hovered,\n hour,\n minute,\n open: openState,\n onChange,\n }),\n };\n function openAndFocus(node?: ElementNode): void {\n const current = isSelectedPrimary() ?? new Date();\n focused.set(atMidnight(current));\n goToDate(current);\n show(node);\n focusActiveCell(node);\n }\n function isSelectedPrimary(): Date | null {\n const current = selection.get();\n if (mode === \"range\")\n return (current as [Date | null, Date | null])?.[0] ?? null;\n return (current as Date | null) ?? null;\n }\n merge(anchorPartial, triggerPartial);\n return anchorPartial;\n\n // --- calendar builder -----------------------------------------------------\n function buildCalendar(): DomphyElement<\"div\"> {\n const navButton = (label: string, ariaLabel: string, onClick: () => void) =>\n ({\n button: label,\n type: \"button\",\n ariaLabel,\n onClick,\n style: navButtonStyle(),\n }) as DomphyElement;\n\n const header: DomphyElement<\"div\"> = {\n div: [\n navButton(\"«\", \"Previous year\", () => shiftYear(-1)),\n navButton(\"‹\", \"Previous month\", () => shiftMonth(-1)),\n {\n div: (listener) =>\n monthFormatter.format(\n new Date(viewYear.get(listener), viewMonth.get(listener), 1),\n ),\n ariaLive: \"polite\",\n style: {\n flex: \"1\",\n textAlign: \"center\",\n fontWeight: themeWeight(\"bold\"),\n fontSize: (listener) => themeSize(listener),\n },\n },\n navButton(\"›\", \"Next month\", () => shiftMonth(1)),\n navButton(\"»\", \"Next year\", () => shiftYear(1)),\n ],\n style: {\n display: \"flex\",\n alignItems: \"center\",\n gap: themeSpacing(1),\n marginBottom: themeSpacing(2),\n },\n };\n\n const weekdayHeader: DomphyElement<\"div\"> = {\n div: weekdayNames.map((name, index) => ({\n div: name,\n style: {\n textAlign: \"center\",\n fontSize: (listener) => themeSize(listener, \"decrease-1\"),\n fontWeight: themeWeight(\"bold\"),\n color: (listener) => themeColor(listener, \"shift-7\"),\n paddingBlock: themeSpacing(1),\n },\n _key: index,\n })),\n role: \"row\",\n style: gridRowStyle(),\n };\n\n const grid: DomphyElement<\"div\"> = {\n div: (listener) => buildWeeks(listener),\n role: \"grid\",\n ariaLabel: \"Calendar\",\n onKeyDown: onGridKey,\n onMouseLeave: () => mode === \"range\" && hovered.set(null),\n style: {\n display: \"flex\",\n flexDirection: \"column\",\n gap: themeSpacing(0.5),\n },\n };\n\n const children: DomphyElement[] = [header, weekdayHeader, grid];\n if (time) children.push(buildTimeRow());\n children.push(buildFooter());\n\n return {\n div: children,\n role: \"dialog\",\n ariaModal: \"false\",\n // Surface contract (same as popover/combobox): page-matching shift-0\n // (menu/selectList/dialog), inherit background + \"text\" color. The\n // previous `themeColor(l, \"base\")` resolved to the ramp's MID anchor\n // (var(--neutral-8), gray) with text only 2 tone steps away — an\n // unreadable washed-out panel, invisible to doctor because the calendar\n // is mounted imperatively at runtime. shift-14 inverted the panel in\n // light theme (a dark calendar on a light page).\n dataTone: \"shift-0\",\n style: {\n minWidth: themeSpacing(70),\n padding: themeSpacing(3),\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 2),\n backgroundColor: (listener) => themeColor(listener, \"inherit\"),\n color: (listener) => themeColor(listener, \"text\"),\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\")}`,\n outlineOffset: \"-1px\",\n boxShadow: elevation(\"medium\"),\n },\n };\n }\n\n function buildWeeks(listener: Listener): DomphyElement[] {\n const first = new Date(viewYear.get(listener), viewMonth.get(listener), 1);\n const month = viewMonth.get(listener);\n const start = startOfWeek(first, weekStart);\n const weeks: DomphyElement[] = [];\n for (let week = 0; week < 6; week++) {\n const cells: DomphyElement[] = [];\n for (let day = 0; day < 7; day++) {\n const date = addDays(start, week * 7 + day);\n cells.push(buildDayCell(date, month, listener));\n }\n weeks.push({\n div: cells,\n role: \"row\",\n style: gridRowStyle(),\n _key: week,\n });\n }\n return weeks;\n }\n\n function buildDayCell(\n date: Date,\n month: number,\n listener: Listener,\n ): DomphyElement {\n const disabled = isDisabled(date);\n const selected = isSelectedEnd(date, listener);\n const within = inSelectedRange(date, listener);\n const outside = date.getMonth() !== month;\n const isFocused = sameDay(date, focused.get(listener));\n const isToday = sameDay(date, new Date());\n\n return {\n button: String(date.getDate()),\n type: \"button\",\n role: \"gridcell\",\n tabIndex: isFocused ? 0 : -1,\n ariaSelected: selected,\n ariaDisabled: disabled,\n disabled,\n ariaLabel: fullDateFormatter.format(date),\n dataDate: isoOf(date),\n onClick: (_e: Event, node: ElementNode) => selectDate(date, node),\n onMouseEnter: () => mode === \"range\" && hovered.set(date),\n style: {\n appearance: \"none\",\n border: \"none\",\n cursor: disabled ? \"not-allowed\" : \"pointer\",\n aspectRatio: \"1\",\n borderRadius: themeSpacing(1),\n fontSize: (l: Listener) => themeSize(l),\n opacity: disabled ? 0.35 : outside ? 0.5 : 1,\n // Selected day: the deep-fill + light-text pairing the rest of the\n // library uses for a chosen row (selectItem, pagination, solid\n // button). The old shift-7 fill under shift-0 text measured 3.73:1\n // (light) / 2.92:1 (dark) — a gap of 7, below the ramp's K=9 span.\n backgroundColor: (l: Listener) =>\n selected\n ? themeColor(l, \"shift-13\", accentColor.get(l))\n : within\n ? themeColor(l, \"hover\", accentColor.get(l))\n : \"transparent\",\n // An in-range day sits on a +2 accent fill, so its number tracks it\n // (3.51:1 at the plain \"text\" tone, light).\n color: (l: Listener) =>\n selected\n ? themeColor(l, \"shift-0\", \"neutral\")\n : within\n ? themeColor(l, textToneOn(2))\n : themeColor(l, \"text\"),\n outline: isToday\n ? (l: Listener) =>\n `1px solid ${themeColor(l, \"shift-6\", accentColor.get(l))}`\n : \"none\",\n outlineOffset: \"-2px\",\n \"&:hover:not([disabled])\": {\n backgroundColor: (l: Listener) =>\n selected\n ? themeColor(l, \"shift-13\", accentColor.get(l))\n : themeColor(l, \"shift-3\", accentColor.get(l)),\n // Unselected hover paints a +3 fill; the day number follows it\n // (2.93:1 at the plain \"text\" tone, light).\n ...(selected\n ? {}\n : { color: (l: Listener) => themeColor(l, textToneOn(3)) }),\n },\n transition: \"background-color 140ms ease, box-shadow 140ms ease\",\n \"&:focus-visible\": {\n boxShadow: (l: Listener) => focusRing(l, accentColor.get(l)),\n },\n },\n _key: isoOf(date),\n } as DomphyElement;\n }\n\n function buildTimeRow(): DomphyElement<\"div\"> {\n const numberSelect = (\n count: number,\n state: ReturnType<typeof toState<number>>,\n ariaLabel: string,\n ): DomphyElement => ({\n select: Array.from({ length: count }, (_unused, value) => ({\n option: String(value).padStart(2, \"0\"),\n value: String(value),\n selected: (listener) => state.get(listener) === value,\n _key: value,\n })) as DomphyElement[],\n ariaLabel,\n onChange: (event) => {\n state.set(Number((event.target as HTMLSelectElement).value));\n reapplyTime();\n },\n style: timeSelectStyle(),\n });\n\n return {\n div: [\n numberSelect(24, hour, \"Hour\"),\n { span: \":\", style: { fontWeight: themeWeight(\"bold\") } },\n numberSelect(60, minute, \"Minute\"),\n ],\n style: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: themeSpacing(1),\n marginTop: themeSpacing(3),\n },\n };\n }\n\n function buildFooter(): DomphyElement<\"div\"> {\n const action = (\n label: string,\n onClick: (node: ElementNode) => void,\n ): DomphyElement => ({\n button: label,\n type: \"button\",\n onClick: (_e: Event, node: ElementNode) => onClick(node),\n style: {\n appearance: \"none\",\n border: \"none\",\n background: \"transparent\",\n cursor: \"pointer\",\n fontSize: (l: Listener) => themeSize(l, \"decrease-1\"),\n color: (l: Listener) => themeColor(l, \"muted\", accentColor.get(l)),\n padding: themeSpacing(1),\n },\n });\n return {\n div: [\n action(\"Today\", (node) => {\n const today = new Date();\n focused.set(atMidnight(today));\n goToDate(today);\n focusActiveCell(node);\n }),\n action(\"Clear\", () => {\n selection.set(mode === \"range\" ? [null, null] : null);\n hovered.set(null);\n }),\n ],\n style: {\n display: \"flex\",\n justifyContent: \"space-between\",\n marginTop: themeSpacing(2),\n paddingTop: themeSpacing(2),\n borderTop: (l: Listener) => `1px solid ${themeColor(l, \"border\")}`,\n },\n };\n }\n\n function onGridKey(event: Event, node: ElementNode): void {\n const keyboard = event as KeyboardEvent;\n const current = focused.get();\n let next: Date | null = null;\n switch (keyboard.key) {\n case \"ArrowLeft\":\n next = addDays(current, -1);\n break;\n case \"ArrowRight\":\n next = addDays(current, 1);\n break;\n case \"ArrowUp\":\n next = addDays(current, -7);\n break;\n case \"ArrowDown\":\n next = addDays(current, 7);\n break;\n case \"Home\":\n next = startOfWeek(current, weekStart);\n break;\n case \"End\":\n next = addDays(startOfWeek(current, weekStart), 6);\n break;\n case \"PageUp\":\n next = addMonths(current, keyboard.shiftKey ? -12 : -1);\n break;\n case \"PageDown\":\n next = addMonths(current, keyboard.shiftKey ? 12 : 1);\n break;\n case \"Enter\":\n case \" \":\n keyboard.preventDefault();\n selectDate(current, node);\n return;\n default:\n return;\n }\n keyboard.preventDefault();\n focused.set(next);\n goToDate(next);\n focusActiveCell(node);\n }\n}\n\n// --- shared style fragments --------------------------------------------------\n\nfunction gridRowStyle() {\n return {\n display: \"grid\",\n gridTemplateColumns: \"repeat(7, 1fr)\",\n gap: themeSpacing(0.5),\n };\n}\n\nfunction navButtonStyle() {\n return {\n appearance: \"none\" as const,\n border: \"none\",\n background: \"transparent\",\n cursor: \"pointer\",\n fontSize: (l: Listener) => themeSize(l),\n color: (l: Listener) => themeColor(l, \"muted\"),\n width: themeSpacing(7),\n height: themeSpacing(7),\n borderRadius: themeSpacing(1),\n \"&:hover\": {\n backgroundColor: (l: Listener) => themeColor(l, \"shift-3\"),\n // The chevron glyph tracks the +3 hover fill: \"muted\" on it measured\n // 2.48:1 (light) / 2.98:1 (dark).\n color: (l: Listener) => themeColor(l, textToneOn(3)),\n },\n };\n}\n\nfunction timeSelectStyle() {\n return {\n fontSize: (l: Listener) => themeSize(l),\n padding: themeSpacing(1),\n borderRadius: themeSpacing(1),\n // outline, not border — bounded control, keep the geometry formula exact.\n border: \"none\",\n outlineOffset: \"-1px\",\n outline: (l: Listener) => `1px solid ${themeColor(l, \"border-strong\")}`,\n backgroundColor: (l: Listener) => themeColor(l, \"inherit\"),\n color: (l: Listener) => themeColor(l, \"text\"),\n };\n}\n\nexport { datePicker };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n themeWeight,\n} from \"@domphy/theme\";\n\n/**\n * Styles a description list as a two-column grid (terms in the first column,\n * descriptions in the second), theming the nested `<dt>`/`<dd>` elements.\n * Apply to a `<dl>` element.\n *\n * @hostTag dl\n * @param props.color - Theme color tone (`ValueOrState<ThemeColor>`) for the term/description text. Defaults to \"neutral\".\n * @example { dl: [{ dt: \"Name\" }, { dd: \"Domphy\" }], $: [descriptionList()] }\n */\nfunction descriptionList(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"dl\") {\n console.warn(`\"descriptionList\" primitive patch must use dl tag`);\n }\n },\n style: {\n display: \"grid\",\n gridTemplateColumns: `minmax(${themeSpacing(24)}, max-content) 1fr`,\n columnGap: themeSpacing(4),\n margin: 0,\n \"& dt\": {\n margin: 0,\n fontWeight: themeWeight(\"semibold\"),\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n color: (listener) =>\n themeColor(listener, \"shift-10\", color.get(listener)),\n },\n \"& dd\": {\n margin: 0,\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n },\n },\n };\n}\n\nexport { descriptionList };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n textToneOn,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n themeWeight,\n} from \"@domphy/theme\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * Styles a native disclosure widget: a themed `<summary>` header with an\n * animated rotating chevron and an expand/collapse transition on the body\n * content. Apply to a `<details>` element.\n *\n * @hostTag details\n * @param props.color - Theme color tone (`ValueOrState<ThemeColor>`) for the body/summary. Defaults to \"neutral\".\n * @param props.accentColor - Accent color (`ValueOrState<ThemeColor>`) for the summary's focus ring. Defaults to \"primary\".\n * @param props.duration - Open/close transition duration in milliseconds. Defaults to 240.\n * @example { details: [{ summary: \"More\" }, { div: \"Body\" }], $: [details()] }\n */\nfunction details(\n props: {\n color?: ValueOrState<ThemeColor>;\n accentColor?: ValueOrState<ThemeColor>;\n duration?: number;\n } = {},\n): PartialElement {\n const { duration = 240 } = props;\n const color = toState(props.color ?? \"neutral\", \"color\");\n const accentColor = toState(props.accentColor ?? \"primary\", \"accentColor\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"details\") {\n console.warn(`\"details\" primitive patch must use details tag`);\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n\n overflow: \"hidden\",\n \"& > summary\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-2\", color.get(listener)),\n // shift-11 on a shift-2 header band = the design system's 9-step\n // contrast span. shift-10 was a gap of 8 and measured 4.33:1\n // (#636363 on #dbdbdb) — an axe `color-contrast` WCAG AA failure.\n color: (listener) =>\n themeColor(listener, \"shift-11\", color.get(listener)),\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n listStyle: \"none\",\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n gap: themeSpacing(2),\n cursor: \"pointer\",\n userSelect: \"none\",\n fontWeight: themeWeight(\"medium\"),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 4),\n height: themeSpacing(10),\n },\n \"& > summary::-webkit-details-marker\": {\n display: \"none\",\n },\n \"& > summary::marker\": {\n content: `\"\"`,\n },\n \"& > summary::after\": {\n content: `\"\"`,\n width: themeSpacing(2),\n height: themeSpacing(2),\n flexShrink: 0,\n marginTop: themeSpacing(-0.5),\n borderInlineEnd: (listener) =>\n `${themeSpacing(0.5)} solid ${themeColor(listener, \"shift-9\", color.get(listener))}`,\n borderBottom: (listener) =>\n `${themeSpacing(0.5)} solid ${themeColor(listener, \"shift-9\", color.get(listener))}`,\n transform: \"rotate(45deg)\",\n transition: `transform ${duration}ms ease`,\n },\n \"&[open] > summary::after\": {\n transform: \"rotate(-135deg)\",\n },\n \"& > summary:hover\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-3\", color.get(listener)),\n // Summary text tracks the +3 hover fill: inherited shift-9 body text\n // measured 3.02:1 on it (light) / 3.63:1 (dark), below WCAG AA.\n color: (listener) =>\n themeColor(listener, textToneOn(3), color.get(listener)),\n },\n \"& > summary:focus-visible\": {\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 2),\n boxShadow: (listener) => focusRing(listener, accentColor.get(listener)),\n },\n \"& > :not(summary)\": {\n maxHeight: 0,\n opacity: 0,\n overflow: \"hidden\",\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 3),\n paddingTop: 0,\n paddingBottom: 0,\n transition: `max-height ${duration}ms ease, opacity ${duration}ms ease, padding ${duration}ms ease`,\n },\n \"&[open] > :not(summary)\": {\n // Non-clipping open state: a bounded max-height here (previously\n // themeSpacing(250) ≈ 1000px) silently CUT OFF body content taller\n // than the cap while fully open. CSS cannot transition max-height\n // to/from `none`, so the open transition is carried by opacity +\n // padding (both still animate over `duration`); max-height jumps\n // straight to none and tall content is never clipped.\n maxHeight: \"none\",\n opacity: 1,\n paddingTop: (listener) => themeSpacing(themeDensity(listener) * 1),\n paddingBottom: (listener) => themeSpacing(themeDensity(listener) * 3),\n },\n },\n };\n}\n\nexport { details };\n","import {\n type BehaviorInstance,\n behavior,\n type ElementNode,\n type PartialElement,\n type ReadableState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { elevation } from \"../utils/elevation.js\";\nimport { hasOpenFloatingPanel } from \"../utils/floating.js\";\nimport { asOpenState, dismissOpen, subscribeOpen } from \"../utils/openState.js\";\nimport { lockScroll, unlockScroll } from \"../utils/scrollLock.js\";\n\nconst FOCUSABLE =\n 'button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), details, [tabindex]:not([tabindex=\"-1\"])';\n\ntype DialogProps = {\n state: ReadableState<boolean>;\n // Lives on the behavior instance so a reused node gets the latest callback\n // via update() — do not close over factory-generation onDismiss.\n onDismiss?: () => void;\n};\n\ntype DialogInstance = BehaviorInstance<DialogProps> & {\n // Close via the instance's CURRENT state — routing through the behavior\n // guarantees the state being set is the one the open/close subscription\n // listens to, even when a re-rendered generation's closure would otherwise\n // set its own fresh (unsubscribed) default state.\n requestClose: () => void;\n onTransitionEnd: (e: Event) => void;\n};\n\n// All close-finalization state (closing flag, previousFocus, scrollLocked,\n// the fallback timer) lives in ONE behavior instance per dialog node. It used\n// to be factory-scope variables captured by _onMount — but _onMount runs once\n// for the FIRST generation only, while onTransitionEnd (live-rebound every\n// patch) belongs to the LATEST generation: gen-1's update() set gen-1's\n// `closing = true` and the live gen-N handler read gen-N's `closing` (false)\n// and early-returned, so every close fell back to the 350ms timer and focus\n// restore scrolled through stale closures. behavior() attaches once and\n// routes every later generation's props into the same instance (floating.ts\n// pattern).\nfunction attachDialog(\n node: ElementNode,\n initialProps: DialogProps,\n): DialogInstance {\n let { state, onDismiss } = initialProps;\n let previousFocus: HTMLElement | null = null;\n let closing = false;\n let scrollLocked = false;\n let closeTimer: ReturnType<typeof setTimeout> | null = null;\n\n const dlg = node.domElement as HTMLDialogElement;\n dlg.setAttribute(\"aria-modal\", \"true\");\n\n const finalizeClose = () => {\n closing = false;\n // Guard for environments with HTMLDialogElement but no close()\n // implementation (e.g. jsdom in tests).\n if (typeof dlg.close === \"function\") dlg.close();\n // visibility/pointer-events/display (not just opacity) must reflect the\n // closed state: opacity alone leaves a closed dialog's content fully\n // reachable by Tab and exposed to the accessibility tree (opacity, unlike\n // visibility, never removes an element from either) — and a consumer\n // that sets its own `style: { display: ... }` on the dialog (a common\n // pattern for centering content) overrides the UA stylesheet's\n // `dialog:not([open]) { display: none }`, so `dlg.close()` alone doesn't\n // reliably hide it either. visibility+pointer-events still leave the\n // node in the layout and in the document for password-managers / autofocus.\n // Set INLINE so it always wins regardless of what the consumer's own\n // style object declares. Do not put `display: none` on the patch CSS\n // class — native `style.display` would lose to that class on reopen.\n dlg.style.visibility = \"hidden\";\n dlg.style.pointerEvents = \"none\";\n dlg.style.display = \"none\";\n if (scrollLocked) {\n unlockScroll();\n scrollLocked = false;\n }\n previousFocus?.focus();\n previousFocus = null;\n };\n\n const trapFocus = (e: KeyboardEvent) => {\n if (e.key !== \"Tab\") return;\n const focusables = Array.from(\n dlg.querySelectorAll<HTMLElement>(FOCUSABLE),\n ).filter(\n // getClientRects() is empty only when the element (or an ancestor) has\n // `display: none` or the element itself has no layout box — unlike\n // `offsetParent`, which is ALSO null for a `position: fixed`\n // descendant even though it is fully visible, so the trap silently\n // skipped fixed-position focusables inside the dialog.\n (el) =>\n !el.closest(\"[aria-hidden='true']\") && el.getClientRects().length > 0,\n );\n if (!focusables.length) {\n e.preventDefault();\n return;\n }\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey) {\n if (document.activeElement === first || document.activeElement === dlg) {\n e.preventDefault();\n last.focus();\n }\n } else {\n if (document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n };\n\n const onCancel = (e: Event) => {\n e.preventDefault();\n // Top-layer-only dismissal: an open popover/select/datePicker inside this\n // dialog owns the Escape (see hasOpenFloatingPanel).\n if (hasOpenFloatingPanel(dlg)) return;\n dismissOpen(state, onDismiss);\n };\n dlg.addEventListener(\"cancel\", onCancel);\n\n const update = (val: boolean) => {\n if (val) {\n // Cancel any in-flight close: a pending fallback timer or a true\n // `closing` flag left over from the previous close (e.g. reopening\n // within the 350ms window, or the mount-time close of an\n // initially-closed dialog) would otherwise finalize-close the\n // just-opened dialog on the open fade's own transitionend.\n closing = false;\n if (closeTimer) {\n clearTimeout(closeTimer);\n closeTimer = null;\n }\n previousFocus = document.activeElement as HTMLElement;\n dlg.style.visibility = \"visible\";\n dlg.style.pointerEvents = \"auto\";\n // Drop the closed-state inline display so the consumer's own\n // `style.display` (or the UA open-dialog rule) can apply.\n dlg.style.display = \"\";\n // Guard for environments with HTMLDialogElement but no showModal()\n // implementation (e.g. jsdom in tests). Also guard against re-entering\n // on an already-open dialog — showModal() throws InvalidStateError in\n // real browsers when the dialog is already open.\n if (typeof dlg.showModal === \"function\" && !dlg.open) dlg.showModal();\n if (!scrollLocked) {\n lockScroll();\n scrollLocked = true;\n }\n dlg.addEventListener(\"keydown\", trapFocus);\n requestAnimationFrame(() => {\n dlg.style.opacity = \"1\";\n // `[autofocus]` wins over \"first focusable\" — that is what the HTML\n // dialog focusing steps do, and what Radix Dialog / MUI Dialog /\n // Mantine Modal all honour. Without it the initial focus landed on\n // whatever happened to come first in the DOM (typically a close or\n // cancel button) and there was no way for a consumer to redirect it.\n const focusable =\n dlg.querySelector<HTMLElement>(\"[autofocus]:not([disabled])\") ??\n dlg.querySelector<HTMLElement>(FOCUSABLE);\n focusable?.focus();\n });\n } else {\n closing = true;\n dlg.style.opacity = \"0\";\n dlg.removeEventListener(\"keydown\", trapFocus);\n // Mounted already-closed (never opened): no fade to play — hide now\n // so a consumer `display: flex` cannot keep the closed node in layout\n // for the 350ms timer (or forever, if transitionend also never fires).\n if (!dlg.open) {\n finalizeClose();\n return;\n }\n // Fallback: if transitionend never fires (reduced-motion, display:none),\n // unblock close after the transition duration + buffer.\n closeTimer = setTimeout(() => {\n closeTimer = null;\n if (!closing) return;\n finalizeClose();\n }, 350);\n }\n };\n let release = subscribeOpen(state, update);\n\n return {\n requestClose: () => dismissOpen(state, onDismiss),\n onTransitionEnd: (e: Event) => {\n if (!closing) return;\n // Guard against bubbled transitionend from nested content (e.g. an\n // accordion/details transition inside the dialog) prematurely\n // triggering close-finalization.\n if (e.target !== dlg) return;\n if ((e as TransitionEvent).propertyName !== \"opacity\") return;\n finalizeClose();\n },\n update(props) {\n onDismiss = props.onDismiss;\n // Re-subscribe when a later generation brings a genuinely different\n // state object (e.g. the default `toState(false)` allocated per\n // factory call); a caller-owned state arrives as the SAME object and\n // keeps its existing subscription untouched.\n if (props.state !== state) {\n release();\n state = props.state;\n release = subscribeOpen(state, update, false);\n }\n },\n destroy() {\n if (closeTimer) {\n clearTimeout(closeTimer);\n closeTimer = null;\n }\n release();\n dlg.removeEventListener(\"cancel\", onCancel);\n if (scrollLocked) {\n unlockScroll();\n scrollLocked = false;\n }\n dlg.removeEventListener(\"keydown\", trapFocus);\n previousFocus?.focus();\n previousFocus = null;\n },\n };\n}\n\n/**\n * Modal dialog patch driven by an `open` State. Calls `showModal()`/`close()`,\n * fades via opacity, locks page scroll while open, traps Tab focus within the\n * dialog, restores focus to the previously focused element on close, sets\n * `aria-modal`, and closes on outside (backdrop) click. Apply to a `<dialog>`.\n * Closed state is inline `visibility`/`pointer-events`/`display:none` so a\n * consumer `style.display` cannot keep the node in layout.\n *\n * Accessible name/description: pass `labelledBy`/`describedBy` the `id` of a\n * heading/paragraph inside the dialog (Radix Title/Description parity). The\n * native `ariaLabelledby`/`ariaDescribedby` attributes on the host element\n * remain an equivalent escape hatch (the native element always wins).\n *\n * @hostTag dialog\n * @param props.color - Theme color tone for the dialog surface. Defaults to \"neutral\".\n * @param props.open - Open state (`ValueOrState<boolean>`), including `Computed`/`ReadableState`. When the source is read-only, pass `onDismiss` so Escape/backdrop can close. Defaults to false.\n * @param props.onDismiss - Called when Escape/backdrop/`requestClose` request close. Optional. Required to close when `open` is a read-only `Computed`/`ReadableState`.\n * @param props.labelledBy - `id` of the element labeling the dialog (wired to `aria-labelledby`). Optional.\n * @param props.describedBy - `id` of the element describing the dialog (wired to `aria-describedby`). Optional.\n * @example { dialog: [{ h2: \"Confirm\", id: \"dlg-title\" }], $: [dialog({ open, labelledBy: \"dlg-title\" })] }\n */\nfunction dialog(\n props: {\n color?: ThemeColor;\n open?: ValueOrState<boolean>;\n onDismiss?: () => void;\n labelledBy?: string;\n describedBy?: string;\n } = {},\n): PartialElement {\n const {\n color = \"neutral\",\n open = false,\n labelledBy,\n describedBy,\n onDismiss,\n } = props;\n const state = asOpenState(open);\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"dialog\") {\n console.warn(`\"dialog\" primitive patch must use dialog tag`);\n }\n },\n ...behavior<DialogProps>(\"dialog\", attachDialog, { state, onDismiss }),\n ariaLabelledby: labelledBy,\n ariaDescribedby: describedBy,\n onClick: (e: MouseEvent, node) => {\n if (e.target !== node.domElement) return;\n const r = node.domElement!.getBoundingClientRect();\n const inside =\n e.clientX >= r.left &&\n e.clientX <= r.right &&\n e.clientY >= r.top &&\n e.clientY <= r.bottom;\n if (!inside) node.getBehavior<DialogInstance>(\"dialog\")?.requestClose();\n },\n onTransitionEnd: (e, node) =>\n node.getBehavior<DialogInstance>(\"dialog\")?.onTransitionEnd(e),\n style: {\n opacity: \"0\",\n // Matches finalizeClose's inline defaults — a dialog that mounts\n // already-closed (the common case: `open` defaults to false) must\n // start out of the tab order/accessibility tree from first paint, not\n // just after its first open->close cycle runs finalizeClose.\n visibility: \"hidden\",\n pointerEvents: \"none\",\n transition: \"opacity 200ms ease\",\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n color: (listener) => themeColor(listener, \"shift-10\", color),\n backgroundColor: (listener) => themeColor(listener, \"inherit\", color),\n border: \"none\",\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 2),\n padding: (listener) => themeSpacing(themeDensity(listener) * 3),\n boxShadow: elevation(\"high\"),\n \"&::backdrop\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-2\", \"neutral\"),\n opacity: 0.75,\n },\n },\n };\n}\n\nexport { dialog };\n","// Shared page-scroll lock for modal-like patches (dialog, drawer). A\n// module-level counter (not a plain boolean) is required because two\n// overlays can be open at once (e.g. a dialog opened from within a drawer);\n// without a counter, closing the inner one would clear `overflow` while the\n// outer one is still open.\nlet lockCount = 0;\n\nfunction lockScroll(): void {\n lockCount++;\n if (lockCount === 1) document.body.style.overflow = \"hidden\";\n}\n\nfunction unlockScroll(): void {\n lockCount = Math.max(0, lockCount - 1);\n if (lockCount === 0) document.body.style.overflow = \"\";\n}\n\n// Test-only: reset the module-level counter so a test that unmounts its tree\n// via `document.body.innerHTML = \"\"` (skipping the Remove hook / unlockScroll\n// call) doesn't leak a locked count into the next test.\nfunction _resetScrollLock(): void {\n lockCount = 0;\n}\n\nexport { lockScroll, unlockScroll, _resetScrollLock };\n","import type { PartialElement } from \"@domphy/core\";\nimport { toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * A horizontal separator (`role=\"separator\"`) with a line on each side of its\n * content, suitable for labelled dividers (\"or\"). Apply to a `<div>` element.\n *\n * @hostTag div\n * @param props.color - Theme color tone (`ValueOrState<ThemeColor>`) for the label text and rules. Defaults to \"neutral\".\n * @example { div: \"or\", $: [divider()] }\n */\nfunction divider(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n role: \"separator\",\n _onInsert: (node) => {\n if (node.tagName !== \"div\") {\n console.warn(`\"divider\" patch should be used with <div>`);\n }\n },\n style: {\n display: \"flex\",\n justifyContent: \"center\",\n alignItems: \"baseline\",\n gap: themeSpacing(2),\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n backgroundColor: (listener) => themeColor(listener),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n minHeight: \"1lh\",\n \"&::before\": {\n content: `\"\"`,\n flex: 1,\n borderColor: (listener) =>\n themeColor(listener, \"border-strong\", color.get(listener)),\n borderWidth: \"1px\",\n borderBottomStyle: \"solid\",\n },\n \"&::after\": {\n content: `\"\"`,\n flex: 1,\n borderColor: (listener) =>\n themeColor(listener, \"border-strong\", color.get(listener)),\n borderWidth: \"1px\",\n borderBottomStyle: \"solid\",\n },\n },\n };\n}\n\nexport { divider };\n","import {\n type BehaviorInstance,\n behavior,\n type ElementNode,\n type PartialElement,\n type ReadableState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { elevation } from \"../utils/elevation.js\";\nimport { hasOpenFloatingPanel } from \"../utils/floating.js\";\nimport { asOpenState, dismissOpen, subscribeOpen } from \"../utils/openState.js\";\nimport { lockScroll, unlockScroll } from \"../utils/scrollLock.js\";\n\ntype PhysicalPlacement = \"left\" | \"right\" | \"top\" | \"bottom\";\ntype Placement = PhysicalPlacement | \"start\" | \"end\";\n\nconst translateOut: Record<PhysicalPlacement, string> = {\n left: \"translateX(-100%)\",\n right: \"translateX(100%)\",\n top: \"translateY(-100%)\",\n bottom: \"translateY(100%)\",\n};\n\nconst marginMap: Record<PhysicalPlacement, string> = {\n left: \"0 auto 0 0\",\n right: \"0 0 0 auto\",\n top: \"0 0 auto 0\",\n bottom: \"auto 0 0 0\",\n};\n\nconst isVertical = (p: PhysicalPlacement) => p === \"left\" || p === \"right\";\n\nfunction resolvePhysical(\n placement: Placement,\n isRTL: boolean,\n): PhysicalPlacement {\n if (placement === \"start\") return isRTL ? \"right\" : \"left\";\n if (placement === \"end\") return isRTL ? \"left\" : \"right\";\n return placement;\n}\n\ntype DrawerProps = {\n state: ReadableState<boolean>;\n // Lives on the behavior instance so a reused node gets the latest callback\n // via update() — do not close over factory-generation onDismiss.\n onDismiss?: () => void;\n placement: Placement;\n size?: string;\n};\n\ntype DrawerInstance = BehaviorInstance<DrawerProps> & {\n requestClose: () => void;\n};\n\nfunction attachDrawer(\n node: ElementNode,\n initialProps: DrawerProps,\n): DrawerInstance {\n let { state, onDismiss, placement, size } = initialProps;\n\n const dlg = node.domElement as HTMLDialogElement;\n dlg.setAttribute(\"aria-modal\", \"true\");\n\n const onCancel = (e: Event) => {\n e.preventDefault();\n // Top-layer-only dismissal: an open popover/select/datePicker inside this\n // drawer owns the Escape (see hasOpenFloatingPanel).\n if (hasOpenFloatingPanel(dlg)) return;\n dismissOpen(state, onDismiss);\n };\n dlg.addEventListener(\"cancel\", onCancel);\n\n const resolve = (nextPlacement: Placement, nextSize?: string) => {\n const isLogical = nextPlacement === \"start\" || nextPlacement === \"end\";\n const isRTL =\n isLogical &&\n (dlg.ownerDocument.documentElement.dir === \"rtl\" ||\n dlg.ownerDocument.dir === \"rtl\");\n const physical = resolvePhysical(nextPlacement, isRTL);\n const drawerSize =\n nextSize ?? (isVertical(physical) ? themeSpacing(80) : themeSpacing(64));\n dlg.style.margin = marginMap[physical];\n dlg.style.width = isVertical(physical) ? drawerSize : \"100dvw\";\n dlg.style.height = isVertical(physical) ? \"100dvh\" : drawerSize;\n return physical;\n };\n\n let physical = resolve(placement, size);\n\n let closing = false;\n let scrollLocked = false;\n let closeTimer: ReturnType<typeof setTimeout> | null = null;\n\n const finishClose = () => {\n closeTimer = null;\n if (!closing) return;\n closing = false;\n // Guard for environments with HTMLDialogElement but no close()\n // implementation (e.g. jsdom in tests).\n if (typeof dlg.close === \"function\") dlg.close();\n // Same fix as dialog.ts: the closed state was only ever represented\n // by an off-screen `transform`, never visibility/pointer-events/display\n // — a closed drawer stayed fully reachable by Tab and exposed to the\n // accessibility tree (a CSS transform, like opacity, does neither),\n // and a consumer's own `style: { display: ... }` overrides the UA\n // stylesheet's `dialog:not([open])` rule anyway. Set INLINE so it\n // always wins. Do not put `display: none` on the patch CSS class —\n // native `style.display` would lose to that class on reopen.\n dlg.style.visibility = \"hidden\";\n dlg.style.pointerEvents = \"none\";\n dlg.style.display = \"none\";\n if (scrollLocked) {\n unlockScroll();\n scrollLocked = false;\n }\n };\n\n const onTransitionEnd = (e: Event) => {\n if (e.target !== dlg) return;\n if ((e as TransitionEvent).propertyName !== \"transform\") return;\n finishClose();\n };\n dlg.addEventListener(\"transitionend\", onTransitionEnd);\n\n const update = (val: boolean) => {\n if (val) {\n // Cancel any in-flight close: a pending fallback timer or a leftover\n // `closing` flag would otherwise finalize-close the just-opened drawer\n // when the open slide's own transitionend (or the 350ms timer) fires.\n closing = false;\n if (closeTimer) {\n clearTimeout(closeTimer);\n closeTimer = null;\n }\n dlg.style.visibility = \"visible\";\n dlg.style.pointerEvents = \"auto\";\n dlg.style.display = \"\";\n // Guard for environments with HTMLDialogElement but no showModal()\n // implementation (e.g. jsdom in tests). Also guard against re-entering\n // on an already-open dialog — showModal() throws InvalidStateError in\n // real browsers when the dialog is already open.\n if (typeof dlg.showModal === \"function\" && !dlg.open) dlg.showModal();\n if (!scrollLocked) {\n lockScroll();\n scrollLocked = true;\n }\n requestAnimationFrame(() => {\n dlg.style.transform = \"translate(0, 0)\";\n });\n } else {\n closing = true;\n dlg.style.transform = translateOut[physical];\n if (!dlg.open) {\n finishClose();\n return;\n }\n closeTimer = setTimeout(finishClose, 350);\n }\n };\n let release = subscribeOpen(state, update);\n\n return {\n requestClose: () => dismissOpen(state, onDismiss),\n update(props) {\n onDismiss = props.onDismiss;\n if (props.state !== state) {\n release();\n state = props.state;\n release = subscribeOpen(state, update, false);\n }\n if (props.placement !== placement || props.size !== size) {\n placement = props.placement;\n size = props.size;\n physical = resolve(placement, size);\n if (!state.get()) dlg.style.transform = translateOut[physical];\n }\n },\n destroy() {\n if (closeTimer) {\n clearTimeout(closeTimer);\n closeTimer = null;\n }\n release();\n dlg.removeEventListener(\"cancel\", onCancel);\n dlg.removeEventListener(\"transitionend\", onTransitionEnd);\n if (scrollLocked) {\n unlockScroll();\n scrollLocked = false;\n }\n },\n };\n}\n\n/**\n * Edge-anchored modal drawer driven by an `open` State. Slides in/out from a\n * chosen edge via a 250 ms transform transition, calls `showModal()`/`close()`,\n * locks page scroll while open, and closes on backdrop click. A 350 ms fallback\n * ensures `close()` is always called even when `transitionend` doesn't fire\n * (reduced-motion, `display:none`, detached element). Apply to a `<dialog>`.\n *\n * Because the patch uses the native `<dialog>` `showModal()` API, the browser\n * traps focus inside the drawer while it is open and restores focus to the\n * previously focused element when `close()` is called. Sets `aria-modal=\"true\"`.\n * Escape key closes the drawer via the animated state path (not immediate close).\n *\n * `\"start\"` and `\"end\"` placements resolve to left/right based on the\n * document's `dir` attribute at mount time, enabling RTL-aware drawers:\n * `\"start\"` → left (LTR) / right (RTL); `\"end\"` → right (LTR) / left (RTL).\n *\n * @hostTag dialog\n * @param props.color - Theme color tone for the drawer surface. Defaults to \"neutral\".\n * @param props.open - Open state (`ValueOrState<boolean>`), including `Computed`/`ReadableState`. When the source is read-only, pass `onDismiss` so Escape/backdrop can close. Defaults to false.\n * @param props.onDismiss - Called when Escape/backdrop/`requestClose` request close. Optional. Required to close when `open` is a read-only `Computed`/`ReadableState`.\n * @param props.placement - Edge to anchor to. \"left\" | \"right\" | \"top\" | \"bottom\" | \"start\" | \"end\". Defaults to \"end\".\n * @param props.size - CSS length for the drawer's width (left/right/start/end) or height (top/bottom). Defaults to themeSpacing(80) for left/right, themeSpacing(64) for top/bottom.\n * @example { dialog: [...], $: [drawer({ open, placement: \"start\" })] }\n */\nfunction drawer(\n props: {\n color?: ThemeColor;\n open?: ValueOrState<boolean>;\n onDismiss?: () => void;\n placement?: Placement;\n size?: string;\n } = {},\n): PartialElement {\n const {\n color = \"neutral\",\n open = false,\n onDismiss,\n placement = \"end\",\n size,\n } = props;\n const state = asOpenState(open);\n\n // For static rendering / SSR assume LTR as fallback; corrected at mount time.\n const physicalFallback = resolvePhysical(placement, false);\n const defaultSize = isVertical(physicalFallback)\n ? themeSpacing(80)\n : themeSpacing(64);\n const drawerSize = size ?? defaultSize;\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"dialog\") {\n console.warn(`\"drawer\" patch must use dialog tag`);\n }\n },\n ...behavior<DrawerProps>(\"drawer\", attachDrawer, {\n state,\n onDismiss,\n placement,\n size,\n }),\n onClick: (e: MouseEvent, node) => {\n if (e.target !== node.domElement) return;\n const r = node.domElement!.getBoundingClientRect();\n const inside =\n e.clientX >= r.left &&\n e.clientX <= r.right &&\n e.clientY >= r.top &&\n e.clientY <= r.bottom;\n if (!inside) node.getBehavior<DrawerInstance>(\"drawer\")?.requestClose();\n },\n style: {\n transform: translateOut[physicalFallback],\n // Matches finishClose's inline defaults — a drawer that mounts\n // already-closed (the common case) must start out of the tab\n // order/accessibility tree from first paint, not just after its first\n // open->close cycle runs finishClose.\n visibility: \"hidden\",\n pointerEvents: \"none\",\n transition: \"transform 0.25s ease\",\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n color: (listener) => themeColor(listener, \"shift-10\", color),\n backgroundColor: (listener) => themeColor(listener, \"inherit\", color),\n border: \"none\",\n padding: (listener) => themeSpacing(themeDensity(listener) * 3),\n margin: marginMap[physicalFallback],\n width: isVertical(physicalFallback) ? drawerSize : \"100dvw\",\n height: isVertical(physicalFallback) ? \"100dvh\" : drawerSize,\n maxWidth: \"100dvw\",\n maxHeight: \"100dvh\",\n boxShadow: elevation(\"high\"),\n \"&::backdrop\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-2\", \"neutral\"),\n opacity: 0.75,\n },\n },\n };\n}\n\nexport { drawer };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport { type ThemeColor, themeColor, themeSize } from \"@domphy/theme\";\n\n/**\n * Italic emphasized inline text. Apply to an `<em>` element.\n *\n * @hostTag em\n * @param props.color - Theme color tone (`ValueOrState<ThemeColor>`) for the text. Defaults to \"neutral\".\n * @example { em: \"important\", $: [emphasis()] }\n */\nfunction emphasis(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"em\") {\n console.warn(`\"emphasis\" primitive patch must use em tag`);\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n fontStyle: \"italic\",\n color: (listener) =>\n themeColor(listener, \"shift-10\", color.get(listener)),\n },\n };\n}\n\nexport { emphasis };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport { type ThemeColor, themeColor, themeSpacing } from \"@domphy/theme\";\n\n/**\n * Styles a container as an empty-state placeholder: centered flex column with\n * muted coloring and comfortable padding. Provide the icon, title, and\n * description as child elements.\n *\n * @param props.color - Theme color tone for the muted text/icon. Defaults to `\"neutral\"`.\n * @example\n * { div: [\n * { span: \"📭\" },\n * { p: \"No items yet\", $: [paragraph()] },\n * { span: \"Add your first item to get started\", $: [small()] },\n * ], $: [empty()] }\n */\nfunction empty(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n style: {\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: themeSpacing(3),\n paddingBlock: themeSpacing(12),\n paddingInline: themeSpacing(6),\n textAlign: \"center\",\n // Body / description text sits in the muted zone.\n color: (listener) => themeColor(listener, \"muted\", color.get(listener)),\n // Icon area: slightly softer so it recedes behind the title.\n \"& > :first-child\": {\n color: (listener) =>\n themeColor(listener, \"shift-5\", color.get(listener)),\n opacity: 0.9,\n },\n // Title (typically second child): stronger body text for hierarchy.\n \"& > :nth-child(2)\": {\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n },\n },\n };\n}\n\nexport { empty };\n","import type { DomphyElement, ElementNode, PartialElement } from \"@domphy/core\";\n\nconst ORIGINAL_CHILDREN = \"errorBoundaryOriginal\";\n\nfunction restoreOriginalChildren(node: ElementNode): void {\n const original = node.getMetadata(ORIGINAL_CHILDREN);\n if (typeof original === \"function\") {\n node._childrenRelease?.();\n node._setupFunctionChildren(original);\n return;\n }\n if (original != null) {\n node.children.update(Array.isArray(original) ? original : [original]);\n return;\n }\n node.children.update([]);\n}\n\n/**\n * Catches errors thrown inside reactive child expressions and renders a\n * fallback element instead of crashing the whole tree. Apply to any container.\n *\n * Only errors in *reactive* children (functions returning element arrays) are\n * caught. Errors during static construction propagate normally — those are\n * programming errors, not runtime data errors.\n *\n * `reset()` restores the original children (including a reactive children\n * function) so the next evaluation runs again — it does not leave the host\n * empty.\n *\n * @hostTag any\n * @param props.fallback - Fallback element or factory `(error, reset) => element`. Defaults to a plain error message div.\n * @param props.onError - Optional callback for logging/telemetry.\n * @example { div: (l) => renderUserContent(l), $: [errorBoundary({ fallback: { p: \"Something went wrong.\" } })] }\n */\nfunction errorBoundary(\n props: {\n fallback?:\n | DomphyElement\n | ((error: unknown, reset: () => void) => DomphyElement);\n onError?: (error: unknown) => void;\n } = {},\n): PartialElement {\n return {\n _onSchedule: (node, element) => {\n if (node.getMetadata(ORIGINAL_CHILDREN) !== undefined) return;\n node.setMetadata(\n ORIGINAL_CHILDREN,\n (element as Record<string, unknown>)[node.tagName],\n );\n },\n _onError: (node, error) => {\n props.onError?.(error);\n const reset = () => restoreOriginalChildren(node);\n const fallbackEl =\n typeof props.fallback === \"function\"\n ? props.fallback(error, reset)\n : (props.fallback ??\n ({ div: \"An error occurred.\" } as DomphyElement));\n node.children.update([fallbackEl]);\n },\n };\n}\n\nexport { errorBoundary };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { elevation } from \"../utils/elevation.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\nconst SIZE_MAP = { small: 8, medium: 10, large: 14 } as const;\n\n/**\n * Floating Action Button — a circular elevated button typically used for the\n * primary action on a screen. Apply to a `<button>` element.\n *\n * @hostTag button\n * @param props.color - Button color tone. Optional `ValueOrState<ThemeColor>`, defaults to `\"primary\"`.\n * @param props.size - Button size preset. Optional `\"small\" | \"medium\" | \"large\"`, defaults to `\"medium\"`.\n * @example { button: \"+\", $: [fab()] }\n * @example { button: \"+\", $: [fab({ size: \"small\", color: \"neutral\" })] }\n */\nfunction fab(\n props: {\n color?: ValueOrState<ThemeColor>;\n size?: \"small\" | \"medium\" | \"large\";\n } = {},\n): PartialElement {\n const color = toState(props.color ?? \"primary\", \"color\");\n const dim = themeSpacing(SIZE_MAP[props.size ?? \"medium\"]);\n\n return {\n // Native `type` on the host still wins (mergePartial: native over patch).\n type: \"button\",\n _onInsert: (node) => {\n if (node.tagName !== \"button\") {\n console.warn('\"fab\" patch must use button tag');\n }\n },\n // Deep brand disc (shift-13) + light icon — mid-ramp shift-8 failed WCAG\n // (~2.2:1). tone-background-inherit wants inherit+dataTone; explicit fill\n // silences it the same way as button solid.\n _doctorDisable: [\n \"low-contrast\",\n \"color-shift-minimum\",\n \"tone-background-inherit\",\n ],\n style: {\n appearance: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n flexShrink: 0,\n width: dim,\n height: dim,\n borderRadius: \"50%\",\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-13\", color.get(listener)),\n color: (listener) => themeColor(listener, \"shift-0\", \"neutral\"),\n boxShadow: elevation(\"low\"),\n transition: \"background-color 200ms ease, box-shadow 200ms ease\",\n \"&:hover:not([disabled])\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-14\", color.get(listener)),\n boxShadow: elevation(\"medium\"),\n },\n \"&:active:not([disabled])\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-15\", color.get(listener)),\n boxShadow: elevation(\"low\"),\n },\n \"&:focus-visible\": {\n boxShadow: (listener) =>\n `${elevation(\"medium\")}, ${focusRing(listener, color.get(listener))}`,\n },\n \"&[disabled]\": { opacity: 0.5, cursor: \"not-allowed\" },\n },\n };\n}\n\nexport { fab };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * Lays out a figure as a column with block-level media (img/svg/video/canvas)\n * and a themed `<figcaption>`. Apply to a `<figure>` element.\n *\n * @hostTag figure\n * @param props.color - Theme color tone (`ValueOrState<ThemeColor>`) for the figure/caption text. Defaults to \"neutral\".\n * @example { figure: [{ img: null, src: \"chart.png\", alt: \"Quarterly revenue\" }, { figcaption: \"A caption\" }], $: [figure()] }\n */\nfunction figure(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"figure\") {\n console.warn(`\"figure\" primitive patch must use figure tag`);\n }\n },\n style: {\n display: \"flex\",\n flexDirection: \"column\",\n gap: themeSpacing(2),\n marginInline: 0,\n marginTop: themeSpacing(3),\n marginBottom: themeSpacing(3),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n \"& img, & svg, & video, & canvas\": {\n display: \"block\",\n maxWidth: \"100%\",\n borderRadius: themeSpacing(2),\n },\n \"& figcaption\": {\n fontSize: (listener) => themeSize(listener, \"decrease-1\"),\n color: (listener) => themeColor(listener, \"muted\", color.get(listener)),\n lineHeight: 1.45,\n },\n },\n };\n}\n\nexport { figure };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n themeWeight,\n} from \"@domphy/theme\";\n\n/**\n * Layout patch for a group of form fields. Arranges a `<legend>`, `<label>`s,\n * controls, and helper `<p>`s in a grid — labels beside controls (horizontal)\n * or stacked above them (vertical). Apply to a `<fieldset>` element.\n *\n * @hostTag fieldset\n * @param props.color - Theme color tone (`ValueOrState<ThemeColor>`) for legend/text/surface. Defaults to \"neutral\".\n * @param props.layout - Field arrangement, \"horizontal\" (label beside control) | \"vertical\" (label above). Defaults to \"horizontal\".\n * @example { fieldset: [{ legend: \"Profile\" }, { label: \"Name\" }, { input: null }], $: [formGroup({ layout: \"vertical\" })] }\n */\nfunction formGroup(\n props: {\n color?: ValueOrState<ThemeColor>;\n layout?: \"horizontal\" | \"vertical\";\n } = {},\n): PartialElement {\n const { layout = \"horizontal\" } = props;\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n const isVertical = layout === \"vertical\";\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"fieldset\") {\n console.warn(`\"formGroup\" patch must use fieldset tag`);\n }\n },\n style: {\n margin: 0,\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 3),\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 3),\n border: \"none\",\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 2),\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n display: \"grid\",\n gridTemplateColumns: isVertical\n ? `minmax(0, 1fr)`\n : `max-content minmax(0, 1fr)`,\n columnGap: themeSpacing(4),\n rowGap: themeSpacing(3),\n alignItems: \"start\",\n \"& > legend\": {\n gridColumn: \"1 / -1\",\n margin: 0,\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n fontWeight: themeWeight(\"semibold\"),\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 1),\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 2),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n },\n \"& > label\": {\n gridColumn: \"1\",\n alignSelf: \"start\",\n margin: 0,\n paddingBlock: (listener) =>\n isVertical ? 0 : themeSpacing(themeDensity(listener) * 1),\n },\n \"& > label:has(+ :not(legend, label, p) + p)\": {\n gridRow: isVertical ? \"auto\" : \"span 2\",\n },\n // Fixed-size controls are EXCLUDED from the stretch rather than\n // overriding it afterwards: a checkbox / switch / radio / colour swatch\n // dropped into a formGroup rendered as a full-column-wide pill\n // (observed in Chromium), and `width: auto` on an appearance:none\n // input collapses it to 0 instead of restoring its declared size.\n \"& > :not(legend, label, p, input[type=checkbox], input[type=radio], input[type=color])\":\n {\n gridColumn: isVertical ? \"1\" : \"2\",\n minWidth: 0,\n width: \"100%\",\n boxSizing: \"border-box\",\n },\n \"& > input[type=checkbox], & > input[type=radio], & > input[type=color]\":\n {\n gridColumn: isVertical ? \"1\" : \"2\",\n justifySelf: \"start\",\n },\n \"& > p\": {\n gridColumn: isVertical ? \"1\" : \"2\",\n minWidth: 0,\n margin: 0,\n marginBlockStart: `calc(${themeSpacing(2)} * -1)`,\n fontSize: (listener) => themeSize(listener, \"decrease-1\"),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n },\n },\n };\n}\n\nexport { formGroup };\n","import type { PartialElement } from \"@domphy/core\";\nimport { themeDensity, themeSpacing } from \"@domphy/theme\";\nimport type { FlexAlign } from \"./stack.js\";\n\n/**\n * A CSS grid with a column template and spacing between cells — the\n * general-purpose primitive for card/property/stat grids instead of\n * hand-rolling `display: \"grid\"; gridTemplateColumns: ...; gap: ...`.\n * Mirrors `row()`'s contract. Styles the host only; apply to any block\n * element.\n *\n * @param props.columns - Column count (expanded to `repeat(N, minmax(0, 1fr))`)\n * or a raw `grid-template-columns` value. Defaults to `1`.\n * @param props.gap - Spacing multiplier for gap between cells (default 4 = 1em at density 1).\n * @param props.align - Block-axis alignment of items (`alignItems`). Unset by default.\n * @example { div: [{ div: \"A\" }, { div: \"B\" }], $: [grid({ columns: 2 })] }\n * @example { div: [...], $: [grid({ columns: \"repeat(auto-fill, minmax(12em, 1fr))\", gap: 6 })] }\n */\nfunction grid(\n props: { columns?: number | string; gap?: number; align?: FlexAlign } = {},\n): PartialElement {\n const { columns = 1, gap = 4, align } = props;\n return {\n style: {\n display: \"grid\",\n gridTemplateColumns:\n typeof columns === \"number\"\n ? `repeat(${columns}, minmax(0, 1fr))`\n : columns,\n gap: (listener) => themeSpacing(themeDensity(listener) * gap),\n ...(align ? { alignItems: align } : {}),\n },\n };\n}\n\nexport { grid };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ElementSize,\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\nconst HeadingShift: Record<string, ElementSize> = {\n h6: \"decrease-1\",\n h5: \"inherit\",\n h4: \"increase-1\",\n h3: \"increase-2\",\n h2: \"increase-3\",\n h1: \"increase-4\",\n};\n\n/**\n * Styles a heading, scaling its font size by level (h1 largest … h6 smallest)\n * relative to the theme base size. Apply to a heading element `<h1>`–`<h6>`.\n *\n * @hostTag h1-h6\n * @param props.color - Theme color tone (`ValueOrState<ThemeColor>`) for the heading text. Defaults to \"neutral\".\n * @param props.size - Optional `ElementSize` (`\"inherit\"` | `\"increase-N\"` | `\"decrease-N\"`, N ≤ 7). When set, font size is `themeSize(listener, size)` including `\"inherit\"` (no tag bump). When omitted, follows the host tag (`h1` increase-4 … `h6` decrease-1).\n * @example { h2: \"Section title\", $: [heading()] }\n * @example { h3: \"Panel title\", $: [heading({ size: \"inherit\" })] }\n */\nfunction heading(\n props: { color?: ValueOrState<ThemeColor>; size?: ElementSize } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n const size = props.size;\n\n return {\n _onInsert: (node) => {\n if (![\"h1\", \"h2\", \"h3\", \"h4\", \"h5\", \"h6\"].includes(node.tagName)) {\n console.warn(\n `\"heading\" primitive patch must use heading tags [h1...h6]`,\n );\n }\n },\n style: {\n color: (listener) =>\n themeColor(listener, \"shift-11\", color.get(listener)),\n marginTop: 0,\n marginBottom: themeSpacing(2),\n fontSize: (listener) => {\n if (size !== undefined) {\n return themeSize(listener, size);\n }\n const offset = HeadingShift[listener.elementNode.tagName] || \"inherit\";\n return themeSize(listener, offset);\n },\n },\n };\n}\n\nexport { heading };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport { type ThemeColor, themeColor, themeSpacing } from \"@domphy/theme\";\n\n/**\n * A thematic break rendered as a thin 1px themed line with vertical margin.\n * Apply to an `<hr>` element.\n *\n * @hostTag hr\n * @param props.color - Theme color tone (`ValueOrState<ThemeColor>`) for the rule. Defaults to \"neutral\".\n * @example { hr: null, $: [horizontalRule()] }\n */\nfunction horizontalRule(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"hr\") {\n console.warn(`\"horizontalRule\" primitive patch must use hr tag`);\n }\n },\n // Soft rule surface — edge anchor (shift-3 = border) + inherit paint.\n dataTone: \"shift-3\",\n style: {\n border: 0,\n height: \"1px\",\n marginInline: 0,\n marginTop: themeSpacing(3),\n marginBottom: themeSpacing(3),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n },\n };\n}\n\nexport { horizontalRule };\n","import type { PartialElement } from \"@domphy/core\";\nimport { toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * Styles an inline icon container: square box that centers its content and\n * applies the themed icon color. Apply to a `<span>` element.\n *\n * @hostTag span\n * @param props.color - Optional theme color tone for the icon (`ValueOrState<ThemeColor>`). Defaults to `\"neutral\"`.\n * @example { span: null, $: [icon()] }\n */\nfunction icon(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"span\") {\n console.warn(`\"icon\" primitive patch should use span tag`);\n }\n },\n style: {\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n alignSelf: \"center\",\n justifySelf: \"center\",\n verticalAlign: \"middle\",\n width: themeSpacing(4),\n height: themeSpacing(4),\n flexShrink: \"0\",\n fontSize: (listener) => themeSize(listener),\n backgroundColor: \"transparent\",\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n },\n };\n}\n\nexport { icon };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport { type ThemeColor, themeColor, themeSpacing } from \"@domphy/theme\";\n\ntype ImageProps = { color?: ValueOrState<ThemeColor> } & (\n | { alt: string; decorative?: false }\n | { decorative: true; alt?: undefined }\n);\n\n/**\n * Styles a responsive image: full-width, cover-fit, rounded corners with a\n * themed placeholder background. Apply to an `<img>` element.\n *\n * `alt` is a required prop (WCAG 1.1.1) forwarded onto the host as the native\n * `alt` attribute, not left for the call site to declare separately — a\n * native `alt` on the host element still wins over this if both are given\n * (Domphy's usual native-over-patch merge), but every call site must now\n * make an explicit choice. Pass `decorative: true` for `alt=\"\"` (purely\n * decorative images the caller does not want announced).\n *\n * @hostTag img\n * @param props.alt - Accessible text alternative. Required unless `decorative: true`.\n * @param props.decorative - Marks the image as pure decoration — renders `alt=\"\"` so assistive tech skips it. Optional.\n * @param props.color - Optional theme color tone for the placeholder background (`ValueOrState<ThemeColor>`). Defaults to `\"neutral\"`.\n * @example { img: null, src: \"photo.jpg\", $: [image({ alt: \"A scenic mountain photo\" })] }\n * @example { img: null, src: \"divider.svg\", $: [image({ decorative: true })] }\n */\nfunction image(props: ImageProps): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n alt: props.decorative ? \"\" : props.alt,\n dataTone: \"shift-2\",\n _onInsert: (node) => {\n if (node.tagName !== \"img\") {\n console.warn(`\"image\" primitive patch must use img tag`);\n }\n },\n style: {\n display: \"block\",\n width: \"100%\",\n maxWidth: \"100%\",\n height: \"auto\",\n objectFit: \"cover\",\n borderRadius: themeSpacing(2),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n },\n };\n}\n\nexport { image };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * Styles a custom checkbox with themed box, check mark, indeterminate state,\n * hover, focus and disabled styling. Apply to an `<input>` element of\n * type `checkbox` (the patch sets `type: \"checkbox\"`).\n *\n * @hostTag input\n * @param props.color - Optional theme color tone for the box/border (`ValueOrState<ThemeColor>`). Defaults to `\"neutral\"`.\n * @param props.accentColor - Optional theme color tone for the checked/indeterminate fill and focus ring (`ValueOrState<ThemeColor>`). Defaults to `\"primary\"`.\n * @example { input: null, type: \"checkbox\", $: [inputCheckbox()] }\n */\nfunction inputCheckbox(\n props: {\n color?: ValueOrState<ThemeColor>;\n accentColor?: ValueOrState<ThemeColor>;\n } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n const accentColor = toState(props.accentColor ?? \"primary\", \"accentColor\");\n\n return {\n type: \"checkbox\",\n _onInsert: (node) => {\n if (node.tagName !== \"input\") {\n console.warn(`\"inputCheckbox\" primitive patch must use input tag`);\n }\n },\n style: {\n appearance: \"none\",\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n display: \"inline-flex\",\n position: \"relative\",\n width: themeSpacing(6),\n height: themeSpacing(6),\n justifyContent: \"center\",\n alignItems: \"center\",\n transition: \"background-color 300ms, outline-color 300ms\",\n margin: 0,\n padding: 0,\n \"&::before\": {\n content: `\"\"`,\n display: \"block\",\n borderRadius: themeSpacing(1),\n lineHeight: 1,\n cursor: \"pointer\",\n border: \"none\",\n outlineOffset: \"-1px\",\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", color.get(listener))}`,\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n width: themeSpacing(4),\n height: themeSpacing(4),\n },\n \"&:hover::before\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"hover\", color.get(listener)),\n },\n \"&:checked::before\": {\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"shift-6\", accentColor.get(listener))}`,\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-8\", accentColor.get(listener)),\n },\n \"&:checked:hover:not([disabled])::before\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-7\", accentColor.get(listener)),\n },\n \"&:checked::after\": {\n content: `\"\"`,\n display: \"block\",\n position: \"absolute\",\n top: \"25%\",\n insetInlineStart: \"37%\",\n width: \"20%\",\n height: \"30%\",\n border: (listener) =>\n `${themeSpacing(0.5)} solid ${themeColor(listener, \"inherit\", accentColor.get(listener))}`,\n borderTop: 0,\n borderInlineStart: 0,\n transform: \"rotate(45deg)\",\n },\n \"&:indeterminate::before\": {\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"shift-6\", accentColor.get(listener))}`,\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-3\", accentColor.get(listener)),\n },\n \"&:indeterminate::after\": {\n content: `\"\"`,\n position: \"absolute\",\n inset: \"30%\",\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-8\", accentColor.get(listener)),\n },\n \"&:indeterminate:hover:not([disabled])::after\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-7\", accentColor.get(listener)),\n },\n \"&:focus-visible\": {\n borderRadius: themeSpacing(1.5),\n boxShadow: (listener) => focusRing(listener, accentColor.get(listener)),\n },\n \"&[disabled]\": {\n cursor: \"not-allowed\",\n opacity: 0.7,\n },\n // Disabled keeps the control's SHAPE and only drops the colour family to\n // neutral (Radix / MUI do the same). The previous rule painted ::before\n // with a flat grey fill and removed its outline, so in Chromium a\n // disabled UNCHECKED box read as filled — more \"on\" than the enabled\n // unchecked box, and indistinguishable from the disabled checked one.\n \"&[disabled]::before\": {\n pointerEvents: \"none\",\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", \"neutral\")}`,\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", \"neutral\"),\n },\n \"&[disabled]:checked::before\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-8\", \"neutral\"),\n },\n \"&[disabled]:indeterminate::before\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-3\", \"neutral\"),\n },\n \"&[disabled]:checked::after\": {\n pointerEvents: \"none\",\n // Light end of the neutral ramp on the shift-8 fill, mirroring the\n // enabled check: `inherit` resolved to a mid grey that all but\n // disappeared against it.\n borderColor: (listener) => themeColor(listener, \"shift-0\", \"neutral\"),\n },\n \"&[disabled]:indeterminate::after\": {\n pointerEvents: \"none\",\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-8\", \"neutral\"),\n },\n },\n };\n}\n\nexport { inputCheckbox };\n","import type { PartialElement, ValueOrState } from \"@domphy/core\";\nimport { toState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * Styles a native color picker swatch with themed padding, rounded swatch and\n * disabled styling. Apply to an `<input>` element of type `color` (the patch\n * default is `type: \"color\"`; a native `type` wins).\n *\n * @hostTag input\n * @param props.color - Optional theme color tone used for the disabled state (`ValueOrState<ThemeColor>`). Defaults to `\"neutral\"`.\n * @param props.accentColor - Optional theme color tone (`ValueOrState<ThemeColor>`). Defaults to `\"primary\"`.\n * @example { input: null, type: \"color\", $: [inputColor()] }\n */\nfunction inputColor(\n props: {\n color?: ValueOrState<ThemeColor>;\n accentColor?: ValueOrState<ThemeColor>;\n } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n return {\n // Declared like any other attribute — the native element still wins over\n // this patch default if the host declares its own `type`.\n type: \"color\",\n _onInsert: (node) => {\n if (node.tagName !== \"input\") {\n console.warn(`\"inputColor\" primitive patch must use input tag`);\n }\n },\n style: {\n appearance: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 1),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 1),\n blockSize: (listener) => themeSpacing(6 + themeDensity(listener) * 2),\n inlineSize: (listener) => themeSpacing(6 + themeDensity(listener) * 2),\n backgroundColor: \"transparent\",\n transition: \"box-shadow 140ms ease\",\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, color.get(listener)),\n },\n \"&::-webkit-color-swatch-wrapper\": {\n margin: 0,\n padding: 0,\n },\n \"&::-webkit-color-swatch\": {\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n },\n \"&[disabled]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-2\", \"neutral\"),\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", \"neutral\")}`,\n },\n },\n };\n}\n\nexport { inputColor };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\ntype InputDateTimeMode = \"date\" | \"time\" | \"week\" | \"month\" | \"datetime-local\";\n\n/**\n * Styles a native date/time input with themed border, padding, hover, focus,\n * invalid and disabled states. The `mode` selects the input `type`. Apply to\n * an `<input>` element (the patch default `type` is the chosen `mode`; a native `type` wins).\n *\n * @hostTag input\n * @param props.mode - Input mode selecting the host `type`: `\"date\" | \"time\" | \"week\" | \"month\" | \"datetime-local\"`. Defaults to `\"datetime-local\"`.\n * @param props.color - Optional theme color tone for text/border (`ValueOrState<ThemeColor>`). Defaults to `\"neutral\"`.\n * @param props.accentColor - Optional theme color tone for the hover/focus ring (`ValueOrState<ThemeColor>`). Defaults to `\"primary\"`.\n * @example { input: null, type: \"datetime-local\", $: [inputDateTime()] }\n */\nfunction inputDateTime(\n props: {\n mode?: InputDateTimeMode;\n color?: ValueOrState<ThemeColor>;\n accentColor?: ValueOrState<ThemeColor>;\n } = {},\n): PartialElement {\n const { mode = \"datetime-local\" } = props;\n const color = toState(props.color ?? \"neutral\", \"color\");\n const accentColor = toState(props.accentColor ?? \"primary\", \"accentColor\");\n\n return {\n // Declared like any other attribute — the native element still wins over\n // this patch default if the host declares its own `type`.\n type: mode,\n _onInsert: (node) => {\n if (node.tagName !== \"input\") {\n console.warn(`\"inputDateTime\" primitive patch must use input tag`);\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n lineHeight: \"inherit\",\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n border: \"none\",\n outlineOffset: \"-1px\",\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", color.get(listener))}`,\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 3),\n height: (listener) => themeSpacing(6 + themeDensity(listener) * 2),\n transition: \"outline-color 140ms ease, box-shadow 140ms ease\",\n \"&::-webkit-calendar-picker-indicator\": {\n cursor: \"pointer\",\n opacity: 0.85,\n },\n \"&:hover:not([disabled]):not([aria-busy=true])\": {\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"shift-5\", accentColor.get(listener))}`,\n },\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, accentColor.get(listener)),\n },\n \"&[disabled]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n color: (listener) => themeColor(listener, \"muted\", \"neutral\"),\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-2\", \"neutral\"),\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", \"neutral\")}`,\n },\n \"&:invalid\": {\n outline: (listener) =>\n `${themeSpacing(0.5)} solid ${themeColor(listener, \"shift-6\", \"error\")}`,\n },\n },\n };\n}\n\nexport { inputDateTime };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * Styles a native file input with a themed upload button, border, hover, focus\n * and disabled states. Apply to an `<input>` element of type `file` (the patch\n * default is `type: \"file\"`; a native `type` wins).\n *\n * @hostTag input\n * @param props.color - Optional theme color tone for text/border and the upload button (`ValueOrState<ThemeColor>`). Defaults to `\"neutral\"`.\n * @param props.accentColor - Optional theme color tone for the hover/focus ring (`ValueOrState<ThemeColor>`). Defaults to `\"primary\"`.\n * @example { input: null, type: \"file\", $: [inputFile()] }\n */\nfunction inputFile(\n props: {\n color?: ValueOrState<ThemeColor>;\n accentColor?: ValueOrState<ThemeColor>;\n } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n const accentColor = toState(props.accentColor ?? \"primary\", \"accentColor\");\n\n return {\n // Declared like any other attribute — the native element still wins over\n // this patch default if the host declares its own `type`.\n type: \"file\",\n _onInsert: (node) => {\n if (node.tagName !== \"input\") {\n console.warn(`\"inputFile\" primitive patch must use input tag`);\n }\n },\n style: {\n display: \"inline-flex\",\n alignItems: \"center\",\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n lineHeight: \"inherit\",\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n border: \"none\",\n outlineOffset: \"-1px\",\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", color.get(listener))}`,\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n height: (listener) => themeSpacing(6 + themeDensity(listener) * 2),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 1),\n transition: \"outline-color 140ms ease, box-shadow 140ms ease\",\n \"&::-webkit-file-upload-button\": {\n marginTop: (listener) => themeSpacing(themeDensity(listener)),\n fontSize: \"inherit\",\n border: \"none\",\n borderRadius: themeSpacing(1),\n height: themeSpacing(6),\n paddingInline: themeSpacing(2),\n cursor: \"pointer\",\n color: (listener) =>\n themeColor(listener, \"shift-11\", color.get(listener)),\n backgroundColor: (listener) =>\n themeColor(listener, \"surface\", color.get(listener)),\n },\n \"&:hover:not([disabled]):not([aria-busy=true])\": {\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"shift-5\", accentColor.get(listener))}`,\n },\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, accentColor.get(listener)),\n },\n \"&[disabled]\": {\n opacity: 0.8,\n cursor: \"not-allowed\",\n color: (listener) => themeColor(listener, \"muted\", \"neutral\"),\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", \"neutral\")}`,\n backgroundColor: (listener) =>\n themeColor(listener, \"surface\", \"neutral\"),\n },\n \"&[disabled]::-webkit-file-upload-button\": {\n cursor: \"not-allowed\",\n color: (listener) => themeColor(listener, \"muted\", \"neutral\"),\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-3\", \"neutral\"),\n },\n },\n };\n}\n\nexport { inputFile };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { fieldTextStyle } from \"../utils/fieldText.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * Styles a native number input with themed border, padding, visible spin\n * buttons, hover, focus and disabled states. Apply to an `<input>` element of\n * type `number` (the patch default is `type: \"number\"`; a native `type` wins).\n *\n * @hostTag input\n * @param props.color - Optional theme color tone for text/border (`ValueOrState<ThemeColor>`). Defaults to `\"neutral\"`.\n * @param props.accentColor - Optional theme color tone for the hover/focus ring (`ValueOrState<ThemeColor>`). Defaults to `\"primary\"`.\n * @example { input: null, type: \"number\", $: [inputNumber()] }\n */\nfunction inputNumber(\n props: {\n color?: ValueOrState<ThemeColor>;\n accentColor?: ValueOrState<ThemeColor>;\n } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n const accentColor = toState(props.accentColor ?? \"primary\", \"accentColor\");\n\n return {\n // Declared like any other attribute — the native element still wins over\n // this patch default if the host declares its own `type`.\n type: \"number\",\n _onInsert: (node) => {\n if (node.tagName !== \"input\") {\n console.warn(`\"inputNumber\" primitive patch must use input tag`);\n }\n },\n style: {\n lineHeight: \"inherit\",\n minWidth: themeSpacing(10),\n paddingInlineStart: (listener) =>\n themeSpacing(themeDensity(listener) * 3),\n paddingInlineEnd: (listener) =>\n themeSpacing(themeDensity(listener) * 1.5),\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 1),\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n border: \"none\",\n outlineOffset: \"-1px\",\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", color.get(listener))}`,\n ...fieldTextStyle(color),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n transition: \"outline-color 140ms ease, box-shadow 140ms ease\",\n \"&::-webkit-inner-spin-button, &::-webkit-outer-spin-button\": {\n opacity: 1,\n },\n \"&:hover:not([disabled]):not([aria-busy=true])\": {\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"shift-5\", accentColor.get(listener))}`,\n },\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, accentColor.get(listener)),\n },\n \"&[disabled]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-2\", \"neutral\"),\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", \"neutral\")}`,\n color: (listener) => themeColor(listener, \"muted\", \"neutral\"),\n },\n },\n };\n}\n\nexport { inputNumber };\n","import type { PartialElement } from \"@domphy/core\";\nimport { themeSpacing } from \"@domphy/theme\";\n\n/**\n * Lays out a one-time-password container as a horizontal row of inputs and\n * wires keyboard navigation: auto-advance on input, backspace/arrow movement,\n * and paste distribution across the child inputs. Apply to a container element\n * (e.g. `<div>`) whose direct children are the OTP `<input>` boxes. Takes no\n * props.\n *\n * @example { div: [{ input: null }, { input: null }], $: [inputOTP()] }\n */\nfunction inputOTP(): PartialElement {\n return {\n // Group naming so aria-label on the host is valid (not a bare div).\n role: \"group\",\n ariaLabel: \"One-time password\",\n style: {\n display: \"flex\",\n alignItems: \"center\",\n gap: themeSpacing(2),\n // Tag selector, not \"& > *\": specificity (0,1,1) beats a single class\n // (0,1,0) on its own, so this reliably wins over a box's own\n // minWidth without needing !important — same cascade contract as\n // AGENTS.md's descendant-color-override rule.\n \"& > input\": {\n minWidth: themeSpacing(9),\n },\n },\n _onMount: (node) => {\n const container = node.domElement as HTMLElement;\n const getInputs = () =>\n Array.from(container.querySelectorAll(\"input\")) as HTMLInputElement[];\n\n const onInput = (e: Event) => {\n // An IME (Japanese/Chinese/Korean) fires `input` for each keystroke of\n // an unfinished composition. Advancing focus there tears the\n // composition apart mid-word; wait for the commit.\n if ((e as InputEvent).isComposing) return;\n const inputs = getInputs();\n const target = e.target as HTMLInputElement;\n const index = inputs.indexOf(target);\n if (target.value && index < inputs.length - 1) {\n inputs[index + 1].focus();\n }\n };\n\n const onKeydown = (e: KeyboardEvent) => {\n // keydown during composition reports key \"Process\"/229; leave it alone.\n if (e.isComposing) return;\n const inputs = getInputs();\n const target = e.target as HTMLInputElement;\n const index = inputs.indexOf(target);\n if (e.key === \"Backspace\" && !target.value && index > 0) {\n inputs[index - 1].focus();\n }\n // preventDefault: otherwise the caret ALSO moves inside the box the\n // key just left, so the next typed character lands mid-value.\n if (e.key === \"ArrowLeft\" && index > 0) {\n e.preventDefault();\n inputs[index - 1].focus();\n }\n if (e.key === \"ArrowRight\" && index < inputs.length - 1) {\n e.preventDefault();\n inputs[index + 1].focus();\n }\n };\n\n const onPaste = (e: ClipboardEvent) => {\n e.preventDefault();\n const text = e.clipboardData?.getData(\"text\") ?? \"\";\n const inputs = getInputs();\n const found = inputs.indexOf(e.target as HTMLInputElement);\n const startIdx = found === -1 ? 0 : found;\n [...text].forEach((char, i) => {\n const field = inputs[startIdx + i];\n if (!field) return;\n field.value = char;\n field.dispatchEvent(new Event(\"input\", { bubbles: true }));\n field.dispatchEvent(new Event(\"change\", { bubbles: true }));\n });\n const lastFilled = Math.min(\n startIdx + text.length - 1,\n inputs.length - 1,\n );\n inputs[lastFilled]?.focus();\n };\n\n container.addEventListener(\"input\", onInput);\n container.addEventListener(\"keydown\", onKeydown as EventListener);\n container.addEventListener(\"paste\", onPaste as EventListener);\n\n node.addHook(\"Remove\", () => {\n container.removeEventListener(\"input\", onInput);\n container.removeEventListener(\"keydown\", onKeydown as EventListener);\n container.removeEventListener(\"paste\", onPaste as EventListener);\n });\n },\n };\n}\n\nexport { inputOTP };\n","import type {\n DomphyElement,\n Listener,\n PartialElement,\n StyleObject,\n} from \"@domphy/core\";\nimport { isState, rawHtml, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { VALUE_TONE } from \"../utils/fieldText.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n// Tabler Icons (MIT) — eye and eye-off outlines.\nconst EYE_SVG =\n `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" ` +\n `stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" ` +\n `width=\"1em\" height=\"1em\">` +\n `<path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"/>` +\n `<path d=\"M10 12a2 2 0 1 0 4 0a2 2 0 0 0 -4 0\"/>` +\n `<path d=\"M21 12c-2.4 4 -5.4 6 -9 6c-3.6 0 -6.6 -2 -9 -6c2.4 -4 5.4 -6 9 -6c3.6 0 6.6 2 9 6\"/>` +\n `</svg>`;\n\nconst EYE_OFF_SVG =\n `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" ` +\n `stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" ` +\n `width=\"1em\" height=\"1em\">` +\n `<path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"/>` +\n `<path d=\"M10.585 10.587a2 2 0 0 0 2.829 2.828\"/>` +\n `<path d=\"M16.681 16.673a8.717 8.717 0 0 1 -4.681 1.327c-3.6 0 -6.6 -2 -9 -6` +\n `c1.272 -2.12 2.712 -3.678 4.32 -4.674m2.86 -1.146a9.055 9.055 0 0 1 1.82 -.18` +\n `c3.6 0 6.6 2 9 6c-.666 1.11 -1.379 2.067 -2.138 2.87\"/>` +\n `<path d=\"M3 3l18 18\"/>` +\n `</svg>`;\n\nconst HOST_FIELD_KEYS = [\n \"name\",\n \"value\",\n \"onInput\",\n \"disabled\",\n \"required\",\n] as const;\n\ntype HostFieldKey = (typeof HOST_FIELD_KEYS)[number];\n\ntype HostFields = {\n name?: string;\n value?: unknown;\n onInput?: (event: Event) => void;\n disabled?: unknown;\n required?: boolean;\n};\n\nfunction bindReadable<T>(\n value: T | ValueOrState<T> | ((listener: Listener) => T) | undefined,\n): T | ((listener: Listener) => T) | undefined {\n if (value == null) return undefined;\n if (typeof value === \"function\") return value as (listener: Listener) => T;\n if (isState(value)) {\n return (listener) => (value as { get: (l?: Listener) => T }).get(listener);\n }\n return value as T;\n}\n\n/**\n * Password input wrapper: a styled `<div>` that inserts an `<input type=\"password\">`\n * and a show/hide toggle button. The outer div carries the focus-ring outline via\n * `:focus-within`. Apply to an empty `<div>`. Host `value`/`name`/`onInput`/\n * `disabled`/`required` are forwarded onto the real input so the field\n * participates in FormData.\n *\n * @hostTag div\n * @param props.color - Base color tone for border/background/text. Defaults to `\"neutral\"`.\n * @param props.accentColor - Accent outline color on focus-within. Defaults to `\"primary\"`.\n * @param props.value - Forwarded onto the inner input. Optional.\n * @param props.name - Forwarded onto the inner input (FormData key). Optional.\n * @param props.onInput - Forwarded onto the inner input. Optional.\n * @param props.disabled - Forwarded onto the inner input. Optional.\n * @param props.required - Forwarded onto the inner input. Optional.\n * @param props.autocomplete - Native autocomplete token. Defaults to `\"current-password\"`.\n * @param props.ariaLabel - Accessible name for the inner input. Defaults to `\"Password\"`.\n * @example { div: null, name: \"password\", $: [inputPassword()] }\n */\nfunction inputPassword(\n props: {\n color?: ValueOrState<ThemeColor>;\n accentColor?: ValueOrState<ThemeColor>;\n value?: ValueOrState<string>;\n name?: string;\n onInput?: (event: Event) => void;\n disabled?: ValueOrState<boolean>;\n required?: boolean;\n autocomplete?: string;\n ariaLabel?: string;\n } = {},\n): PartialElement {\n const colorState = toState(props.color ?? \"neutral\", \"color\");\n const accentState = toState(props.accentColor ?? \"primary\", \"accentColor\");\n const visibleState = toState(false);\n const hostFields: HostFields = {};\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"div\") {\n console.warn('\"inputPassword\" patch must use div tag');\n }\n },\n // Lift form fields off the host before merge so they land on the real\n // <input> (a div is not form-associated; FormData would omit them).\n _onSchedule: (_node, element) => {\n const host = element as PartialElement & HostFields;\n for (const key of HOST_FIELD_KEYS) {\n if (host[key] !== undefined) {\n hostFields[key] = host[key] as never;\n delete (host as Record<HostFieldKey, unknown>)[key];\n }\n }\n },\n // Build the input/toggle as real child elements (not imperative DOM\n // mutation in _onMount) so generateHTML()/SSR emits the actual markup.\n _onInit: (node) => {\n const name = props.name ?? hostFields.name;\n const value = bindReadable<string>(\n (props.value ?? hostFields.value) as ValueOrState<string> | undefined,\n );\n const onInput = props.onInput ?? hostFields.onInput;\n const disabled = bindReadable<boolean>(\n (props.disabled ?? hostFields.disabled) as\n | ValueOrState<boolean>\n | undefined,\n );\n const required = props.required ?? hostFields.required;\n\n const field: DomphyElement<\"input\"> = {\n input: null,\n type: (l) => (visibleState.get(l) ? \"text\" : \"password\"),\n ariaLabel: props.ariaLabel ?? \"Password\",\n autocomplete: props.autocomplete ?? \"current-password\",\n ...(name != null ? { name } : {}),\n ...(value != null ? { value } : {}),\n ...(onInput != null ? { onInput } : {}),\n ...(disabled != null ? { disabled } : {}),\n ...(required != null ? { required } : {}),\n style: {\n flex: 1,\n minWidth: 0,\n border: \"none\",\n outline: \"none\",\n backgroundColor: \"transparent\",\n padding: 0,\n margin: 0,\n font: \"inherit\",\n color: \"inherit\",\n },\n };\n\n const toggle: DomphyElement<\"button\"> = {\n button: (l) => rawHtml(visibleState.get(l) ? EYE_OFF_SVG : EYE_SVG),\n type: \"button\",\n ariaLabel: (l) =>\n visibleState.get(l) ? \"Hide password\" : \"Show password\",\n onClick: () => visibleState.set(!visibleState.get()),\n style: {\n background: \"none\",\n border: \"none\",\n padding: 0,\n margin: 0,\n cursor: \"pointer\",\n color: \"inherit\",\n // A <button> gets the UA default 13.333px font unless told otherwise,\n // which shrank both the 1em glyph and the em-based 6U min box (20px\n // measured instead of 24px in Chromium).\n fontSize: (l) => themeSize(l, \"inherit\"),\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n flexShrink: 0,\n // WCAG 2.2 SC 2.5.8 Target Size (Minimum): the 1em eye glyph gave a\n // 13x13 hit area. Negative inline margin keeps the field's visual\n // padding while the button itself reaches 24x24.\n minWidth: themeSpacing(6),\n minHeight: themeSpacing(6),\n marginInlineEnd: (l) =>\n `calc(${themeSpacing(themeDensity(l) * 1)} * -1)`,\n opacity: 0.6,\n },\n };\n\n node.children.insert(field);\n node.children.insert(toggle);\n },\n style: {\n display: \"flex\",\n alignItems: \"center\",\n gap: (l) => themeSpacing(themeDensity(l) * 1),\n paddingBlock: (l) => themeSpacing(themeDensity(l) * 1),\n paddingInline: (l) => themeSpacing(themeDensity(l) * 3),\n borderRadius: (l) => themeSpacing(themeDensity(l) * 1.5),\n border: \"none\",\n outlineOffset: \"-1px\",\n outline: (l) =>\n `1px solid ${themeColor(l, \"border-strong\", colorState.get(l))}`,\n // Same tone as every other field's typed value; the inner <input>\n // inherits it. No `::placeholder` rule: this patch builds its own input\n // and never gives it a placeholder attribute, so there is nothing to paint.\n color: (l) => themeColor(l, VALUE_TONE, colorState.get(l)),\n backgroundColor: (l) => themeColor(l, \"inherit\", colorState.get(l)),\n fontSize: (l) => themeSize(l, \"inherit\"),\n transition: \"outline-color 140ms ease, box-shadow 140ms ease\",\n \"&:hover:not(:has([disabled])):not(:focus-within)\": {\n outline: (l) =>\n `1px solid ${themeColor(l, \"shift-5\", accentState.get(l))}`,\n },\n \"&:focus-within\": {\n boxShadow: (l) => focusRing(l, accentState.get(l)),\n },\n } as StyleObject,\n };\n}\n\nexport { inputPassword };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * Styles a custom radio button with a themed circular box, checked dot, hover,\n * focus and disabled states. Apply to an `<input>` element of type `radio`\n * (the patch sets `type: \"radio\"`).\n *\n * @hostTag input\n * @param props.color - Optional theme color tone for the box/border (`ValueOrState<ThemeColor>`). Defaults to `\"neutral\"`.\n * @param props.accentColor - Optional theme color tone for the checked dot and focus ring (`ValueOrState<ThemeColor>`). Defaults to `\"primary\"`.\n * @example { input: null, type: \"radio\", $: [inputRadio()] }\n */\nfunction inputRadio(\n props: {\n color?: ValueOrState<ThemeColor>;\n accentColor?: ValueOrState<ThemeColor>;\n } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n const accentColor = toState(props.accentColor ?? \"primary\", \"accentColor\");\n\n return {\n type: \"radio\",\n _onInsert: (node) => {\n if (node.tagName !== \"input\") {\n console.warn(\n `\"inputRadio\" primitive patch must use input tag and radio type`,\n );\n return;\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n appearance: \"none\",\n display: \"inline-flex\",\n position: \"relative\",\n width: themeSpacing(6),\n height: themeSpacing(6),\n justifyContent: \"center\",\n alignItems: \"center\",\n transition: \"background-color 300ms, outline-color 300ms\",\n margin: 0,\n padding: 0,\n \"&::before\": {\n content: `\"\"`,\n display: \"block\",\n borderRadius: \"50%\",\n lineHeight: 1,\n cursor: \"pointer\",\n border: \"none\",\n outlineOffset: \"-1px\",\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", color.get(listener))}`,\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n width: themeSpacing(4),\n height: themeSpacing(4),\n },\n \"&:hover::before\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"hover\", color.get(listener)),\n },\n \"&:checked::before\": {\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"shift-6\", accentColor.get(listener))}`,\n },\n \"&:checked::after\": {\n content: `\"\"`,\n position: \"absolute\",\n inset: \"30%\",\n borderRadius: \"50%\",\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-8\", accentColor.get(listener)),\n },\n \"&:checked:hover:not([disabled])::before\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-7\", accentColor.get(listener)),\n },\n \"&:focus-visible\": {\n borderRadius: \"50%\",\n boxShadow: (listener) => focusRing(listener, accentColor.get(listener)),\n },\n \"&[disabled]\": {\n cursor: \"not-allowed\",\n opacity: 0.7,\n },\n // Same fix as inputCheckbox: the old rule filled ::before with flat grey\n // and dropped its outline, so a disabled UNSELECTED radio rendered as a\n // solid dot-less disc that read as selected (observed in Chromium).\n \"&[disabled]::before\": {\n pointerEvents: \"none\",\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", \"neutral\")}`,\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", \"neutral\"),\n },\n \"&[disabled]:checked::after\": {\n pointerEvents: \"none\",\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-8\", \"neutral\"),\n },\n },\n };\n}\n\nexport { inputRadio };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * Styles a range slider with a themed track and thumb, hover, focus and\n * disabled states. Apply to an `<input>` element of type `range` (the patch\n * sets `type: \"range\"`).\n *\n * @hostTag input\n * @param props.color - Optional theme color tone for the slider track (`ValueOrState<ThemeColor>`). Defaults to `\"neutral\"`.\n * @param props.accentColor - Optional theme color tone for the thumb and focus ring (`ValueOrState<ThemeColor>`). Defaults to `\"primary\"`.\n * @example { input: null, type: \"range\", $: [inputRange()] }\n */\nfunction inputRange(\n props: {\n color?: ValueOrState<ThemeColor>;\n accentColor?: ValueOrState<ThemeColor>;\n } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n const accentColor = toState(props.accentColor ?? \"primary\", \"accentColor\");\n\n return {\n type: \"range\",\n _onInsert: (node) => {\n if (node.tagName !== \"input\") {\n console.warn(`\"inputRange\" primitive patch must use input tag`);\n }\n },\n style: {\n appearance: \"none\",\n // Without this the UA default font (13.333px on form controls) wins and\n // every em-derived dimension below shrinks by ~17% — the 6U host box\n // measured 20px instead of 24px in Chromium.\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n width: \"100%\",\n margin: 0,\n padding: 0,\n // WCAG 2.2 SC 2.5.8 Target Size (Minimum) is 24x24 CSS px; the visible\n // track stays 1.5U — only the pointer/drag box grows.\n height: themeSpacing(6),\n background: \"transparent\",\n cursor: \"pointer\",\n \"&::-webkit-slider-runnable-track\": {\n height: themeSpacing(1.5),\n borderRadius: themeSpacing(999),\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-3\", color.get(listener)),\n },\n \"&::-webkit-slider-thumb\": {\n appearance: \"none\",\n width: themeSpacing(4),\n height: themeSpacing(4),\n borderRadius: themeSpacing(999),\n border: \"none\",\n marginTop: `calc((${themeSpacing(1.5)} - ${themeSpacing(4)}) / 2)`,\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-9\", accentColor.get(listener)),\n },\n \"&:hover:not([disabled])::-webkit-slider-thumb\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-10\", accentColor.get(listener)),\n },\n // Firefox uses its own pseudo-elements; without these the slider fell\n // back to the unthemed native widget there (WebKit-only styling).\n \"&::-moz-range-track\": {\n height: themeSpacing(1.5),\n borderRadius: themeSpacing(999),\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-3\", color.get(listener)),\n },\n \"&::-moz-range-thumb\": {\n width: themeSpacing(4),\n height: themeSpacing(4),\n borderRadius: themeSpacing(999),\n border: \"none\",\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-9\", accentColor.get(listener)),\n },\n \"&:hover:not([disabled])::-moz-range-thumb\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-10\", accentColor.get(listener)),\n },\n borderRadius: themeSpacing(2),\n transition: \"box-shadow 140ms ease\",\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, accentColor.get(listener)),\n },\n \"&[disabled]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n },\n },\n };\n}\n\nexport { inputRange };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { fieldTextStyle } from \"../utils/fieldText.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * Styles a search input with themed border, padding, placeholder color, native\n * search decorations, hover, focus and disabled states. Apply to an `<input>`\n * element of type `search` (the patch default is `type: \"search\"`; a native `type` wins).\n *\n * @hostTag input\n * @param props.color - Optional theme color tone for text/border/placeholder (`ValueOrState<ThemeColor>`). Defaults to `\"neutral\"`.\n * @param props.accentColor - Optional theme color tone for the hover/focus ring (`ValueOrState<ThemeColor>`). Defaults to `\"primary\"`.\n * @example { input: null, type: \"search\", $: [inputSearch()] }\n */\nfunction inputSearch(\n props: {\n color?: ValueOrState<ThemeColor>;\n accentColor?: ValueOrState<ThemeColor>;\n } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n const accentColor = toState(props.accentColor ?? \"primary\", \"accentColor\");\n\n return {\n // Declared like any other attribute — the native element still wins over\n // this patch default if the host declares its own `type`.\n type: \"search\",\n _onInsert: (node) => {\n if (node.tagName !== \"input\") {\n console.warn(`\"inputSearch\" primitive patch must use input tag`);\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n lineHeight: \"inherit\",\n ...fieldTextStyle(color),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n border: \"none\",\n outlineOffset: \"-1px\",\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", color.get(listener))}`,\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n minWidth: themeSpacing(32),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 3),\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 1),\n transition: \"outline-color 140ms ease, box-shadow 140ms ease\",\n \"&::-webkit-search-decoration\": {\n display: \"none\",\n },\n \"&::-webkit-search-cancel-button\": {\n cursor: \"pointer\",\n },\n \"&:hover:not([disabled]):not([aria-busy=true])\": {\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"shift-5\", accentColor.get(listener))}`,\n },\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, accentColor.get(listener)),\n },\n \"&[disabled]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n color: (listener) => themeColor(listener, \"muted\", \"neutral\"),\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-2\", \"neutral\"),\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", \"neutral\")}`,\n },\n },\n };\n}\n\nexport { inputSearch };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * Styles a checkbox as a toggle switch: themed track and sliding knob that\n * animates and recolors on checked, plus a disabled state. Apply to an\n * `<input>` element of type `checkbox` (the patch sets `type: \"checkbox\"`).\n *\n * @hostTag input\n * @param props.accentColor - Optional theme color tone for the checked track (`ValueOrState<ThemeColor>`). Defaults to `\"primary\"`.\n * @example { input: null, type: \"checkbox\", $: [inputSwitch()] }\n */\nfunction inputSwitch(\n props: { accentColor?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const accentColor = toState(props.accentColor ?? \"primary\", \"accentColor\");\n\n return {\n role: \"switch\",\n dataTone: \"shift-2\",\n type: \"checkbox\",\n _onSchedule: (node) => {\n if (node.tagName !== \"input\") {\n console.warn(`\"inputSwitch\" primitive patch must use input tag`);\n return;\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n // The track is `::before` alone, filling the whole host box; painting\n // the host too would draw a second pill behind it.\n backgroundColor: \"transparent\",\n color: (listener) => themeColor(listener, \"text\"),\n appearance: \"none\",\n position: \"relative\",\n display: \"inline-flex\",\n width: themeSpacing(9),\n height: themeSpacing(6),\n cursor: \"pointer\",\n margin: `0`,\n transition: \"box-shadow 140ms ease\",\n borderRadius: themeSpacing(999),\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, accentColor.get(listener)),\n },\n \"&:checked\": {\n \"&::before\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"increase-3\", accentColor.get(listener)),\n },\n \"&::after\": {\n insetInlineStart: `calc(100% - ${themeSpacing(5.5)})`,\n },\n },\n \"&::after\": {\n content: `\"\"`,\n aspectRatio: `1/1`,\n position: \"absolute\",\n // INHERITED: buttonSwitch's thumb (themeSpacing(5)), inset 0.5 in a 6-high track.\n width: themeSpacing(5),\n height: themeSpacing(5),\n borderRadius: themeSpacing(999),\n insetInlineStart: themeSpacing(0.5),\n top: \"50%\",\n transform: \"translateY(-50%)\",\n transition: \"inset-inline-start 0.3s\",\n backgroundColor: (listener) => themeColor(listener, \"decrease-3\"),\n // The knob is near-white on a near-white OFF track, so its own\n // boundary is what makes the ON/OFF position identifiable\n // (WCAG 2.1 SC 1.4.11) — same treatment as buttonSwitch's thumb.\n outline: (listener) => `1px solid ${themeColor(listener, \"shift-7\")}`,\n outlineOffset: \"-1px\",\n },\n \"&::before\": {\n content: '\"\"',\n width: \"100%\",\n borderRadius: themeSpacing(999),\n display: \"inline-block\",\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n lineHeight: 1,\n // WCAG 2.1 SC 1.4.11 Non-text Contrast: the OFF track needs >= 3:1\n // against the surface behind it. The tone-inherited FILL measured\n // 1.38:1 on a light page and 1.18:1 on a dark one in Chromium, so the\n // 3:1 is carried by the boundary (shift-7 measures 3.32:1 / 3.50:1),\n // not by darkening the fill: a shift-7 FILLED off-track reads as the\n // ON state — every peer (Radix, shadcn, MUI) keeps the off-track at\n // the muted surface and only the on-track takes the accent.\n backgroundColor: (listener) => themeColor(listener, \"inherit\"),\n outline: (listener) => `1px solid ${themeColor(listener, \"shift-7\")}`,\n outlineOffset: \"-1px\",\n },\n \"&[disabled]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n },\n },\n };\n}\n\nexport { inputSwitch };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { fieldTextStyle } from \"../utils/fieldText.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * Themed single-line text input primitive. Sets `type` (default `\"text\"`) and\n * styles the field with themed border, focus ring, placeholder, disabled and\n * validation (`data-status`) states. Apply to an `<input>` element.\n *\n * @hostTag input\n * @param props - Optional configuration.\n * @param props.type - The input's `type` attribute (e.g. `\"email\"`, `\"url\"`, `\"tel\"`). Defaults to `\"text\"`.\n * @param props.color - Base color tone for text/border/background. Defaults to `\"neutral\"`.\n * @param props.accentColor - Accent color tone for the hover/focus outline. Defaults to `\"primary\"`.\n * @example { input: null, type: \"text\", placeholder: \"Name\", $: [inputText()] }\n */\nfunction inputText(\n props: {\n type?: string;\n color?: ValueOrState<ThemeColor>;\n accentColor?: ValueOrState<ThemeColor>;\n } = {},\n): PartialElement {\n const { type = \"text\" } = props;\n const color = toState(props.color ?? \"neutral\", \"color\");\n const accentColor = toState(props.accentColor ?? \"primary\", \"accentColor\");\n\n return {\n // Declared like any other attribute — the native element still wins over\n // this patch default if the host declares its own `type`.\n type,\n _onInsert: (node) => {\n if (node.tagName !== \"input\") {\n console.warn(\n `\"inputText\" primitive patch must use input tag and text type`,\n );\n }\n },\n style: {\n lineHeight: \"inherit\",\n minWidth: themeSpacing(10),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 3),\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 1),\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n border: \"none\",\n outlineOffset: \"-1px\",\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", color.get(listener))}`,\n ...fieldTextStyle(color),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n transition: \"outline-color 140ms ease, box-shadow 140ms ease\",\n \"&:hover:not([disabled]):not([aria-busy=true])\": {\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"shift-5\", accentColor.get(listener))}`,\n },\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, accentColor.get(listener)),\n },\n \"&[disabled]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-2\", \"neutral\"),\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", \"neutral\")}`,\n color: (listener) => themeColor(listener, \"muted\", \"neutral\"),\n },\n // `[placeholder]` is load-bearing: `:placeholder-shown` only matches an\n // input that HAS a placeholder, so on a field without one\n // `:not(:placeholder-shown)` is always true and a pristine untouched\n // `required` field painted itself red before the user typed a character.\n // Fields with no placeholder opt into the error look via `data-status`.\n \"&[placeholder]:invalid:not(:placeholder-shown)\": {\n outline: (listener) =>\n `${themeSpacing(0.5)} solid ${themeColor(listener, \"shift-6\", \"error\")}`,\n },\n \"&[data-status=error]\": {\n outline: (listener) =>\n `${themeSpacing(0.5)} solid ${themeColor(listener, \"shift-6\", \"error\")}`,\n },\n \"&[data-status=warning]\": {\n outline: (listener) =>\n `${themeSpacing(0.5)} solid ${themeColor(listener, \"shift-6\", \"warning\")}`,\n },\n },\n };\n}\n\nexport { inputText };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeFont,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * Renders keyboard-key styling (the theme's monospace stack, themed background,\n * border and padding) for a keystroke hint. Apply to a `<kbd>` element.\n *\n * @hostTag kbd\n * @param props - Optional configuration.\n * @param props.color - Color tone for text/background/border. Defaults to `\"neutral\"`.\n * @example { kbd: \"Ctrl\", $: [keyboard()] }\n */\nfunction keyboard(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"kbd\") {\n console.warn(`\"keyboard\" primitive patch must use kbd tag`);\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n // The theme owns the code stack; <code>/<kbd>/<pre> otherwise keep the\n // UA generic \"monospace\" (Courier New on Windows), so a theme that swaps\n // fontFamilies.monospace never reaches them.\n fontFamily: themeFont(\"monospace\"),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n // Bare themeSpacing(U) at snapshot time; n = U / 1.5 (light.densities[2]).\n paddingBlock: (listener) =>\n themeSpacing(themeDensity(listener) * (0.5 / 1.5)),\n paddingInline: (listener) =>\n themeSpacing(themeDensity(listener) * (1.5 / 1.5)),\n borderRadius: (listener) =>\n themeSpacing(themeDensity(listener) * (1 / 1.5)),\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", color.get(listener))}`,\n },\n };\n}\n\nexport { keyboard };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * Themed form-label primitive: inline-flex layout with gap, themed text color,\n * focus-within highlighting and a disabled (`aria-disabled`) state. Apply to a\n * `<label>` element.\n *\n * @hostTag label\n * @param props - Optional configuration.\n * @param props.color - Base color tone for the label text. Defaults to `\"neutral\"`.\n * @param props.accentColor - Accent color tone applied on focus-within. Defaults to `\"primary\"`.\n * @example { label: \"Email\", htmlFor: \"email\", $: [label()] }\n */\nfunction label(\n props: {\n color?: ValueOrState<ThemeColor>;\n accentColor?: ValueOrState<ThemeColor>;\n } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n const accentColor = toState(props.accentColor ?? \"primary\", \"accentColor\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"label\") {\n console.warn(`\"label\" primitive patch must use label tag`);\n }\n },\n style: {\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: themeSpacing(2),\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n cursor: \"pointer\",\n \"&:focus-within\": {\n color: (listener) =>\n themeColor(listener, \"shift-10\", accentColor.get(listener)),\n },\n \"&[aria-disabled=true]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n color: (listener) => themeColor(listener, \"muted\", \"neutral\"),\n },\n },\n };\n}\n\nexport { label };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * Themed hyperlink primitive: styles text color, hover underline, visited,\n * focus ring and a disabled state. Apply to an `<a>` element.\n *\n * @hostTag a\n * @param props - Optional configuration.\n * @param props.color - Base color tone for the link text. Defaults to `\"primary\"`.\n * @param props.accentColor - Accent color tone for visited/focus states. Defaults to `\"secondary\"`.\n * @example { a: \"Home\", href: \"/\", $: [link()] }\n */\nfunction link(\n props: {\n color?: ValueOrState<ThemeColor>;\n accentColor?: ValueOrState<ThemeColor>;\n } = {},\n): PartialElement {\n const color = toState(props.color ?? \"primary\", \"color\");\n const accentColor = toState(props.accentColor ?? \"secondary\", \"accentColor\");\n return {\n // WAI-ARIA APG: an <a> with no `href` is not a native link — it is not\n // focusable and Enter/Space do nothing, even though it visually looks\n // and (via a caller's own onClick) behaves like one. Declared ON by\n // default (satisfies both APG for the scripted/no-href case AND, since\n // it is a plain declared value doctor's `missing-required-attribute`\n // rule can see, closes the \"onClick with no href/role\" diagnostic) and\n // corrected away in `_onInsert` once the real host attributes are known\n // — `href` lives on the HOST, not this patch, so its presence can't be\n // read until the merge completes. (A reactive `(listener) => …`\n // attribute function does NOT work for this: `attributes.has()` is a\n // plain imperative read, not a tracked reactive dependency, so it froze\n // at whatever `href` had been set to at the function's first,\n // merge-order-dependent evaluation — measured `false` even for a host\n // that DOES declare `href: \"/\"`.)\n role: \"link\",\n tabIndex: 0,\n _onInsert: (node) => {\n if (node.tagName !== \"a\") {\n console.warn(`\"link\" primitive patch must use a tag`);\n }\n // A real `href` makes both a no-op: `<a href>` is already natively\n // focusable with an implicit role=\"link\" — strip the redundant pair\n // rather than leave a harmless-but-confusing explicit restatement.\n // Only strip THIS patch's own default, never a caller's native\n // override: native wins over patch (AGENTS.md merge rule), so by the\n // time `_onInsert` runs, `role` already holds the caller's value if\n // one was declared (e.g. a search result row using `$: [link()]` but\n // declaring its own `role: \"option\"` for a listbox) — removing it\n // unconditionally here silently threw that override away.\n if (node.attributes.has(\"href\")) {\n if (node.attributes.get(\"role\") === \"link\") {\n node.attributes.remove(\"role\");\n }\n if (node.attributes.get(\"tabIndex\") === 0) {\n node.attributes.remove(\"tabIndex\");\n }\n }\n },\n // `<a disabled>` is not a native navigation block — stop click/Enter.\n onClick: (event, node) => {\n const el = node.domElement;\n if (\n el?.hasAttribute(\"disabled\") ||\n el?.getAttribute(\"aria-disabled\") === \"true\"\n ) {\n event.preventDefault();\n }\n },\n onKeyDown: (event, node) => {\n if (node.attributes.has(\"href\")) return;\n const key = (event as KeyboardEvent).key;\n if (key !== \"Enter\" && key !== \" \") return;\n event.preventDefault();\n node.domElement?.click();\n },\n style: {\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n backgroundColor: (listener) => themeColor(listener),\n // shift-13 (not \"text\"/shift-9): brand hues need extra depth for ≥4.5:1\n // on a light surface (primary orange failed at 2.57 with shift-9).\n color: (listener) =>\n themeColor(listener, \"shift-13\", color.get(listener)),\n textDecoration: \"none\",\n \"&:visited\": {\n color: (listener) =>\n themeColor(listener, \"shift-13\", accentColor.get(listener)),\n },\n \"&:hover:not([disabled])\": {\n color: (listener) =>\n themeColor(listener, \"shift-14\", color.get(listener)),\n textDecoration: \"underline\",\n },\n borderRadius: themeSpacing(1),\n // Kill the browser default outline so only the shared focusRing shows.\n outline: \"none\",\n transition: \"color 140ms ease, box-shadow 140ms ease\",\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, accentColor.get(listener)),\n },\n // `disabled` is not a valid attribute on `<a>`; WAI-ARIA's disabled link\n // is `role=\"link\"` + `aria-disabled=\"true\"` (focusable, not operable).\n // Both selectors are styled so either spelling gets the same look.\n \"&[disabled], &[aria-disabled=true]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n pointerEvents: \"none\",\n color: (listener) => themeColor(listener, \"muted\", \"neutral\"),\n },\n },\n };\n}\n\nexport { link };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n textToneOn,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { BUTTON_SIZE_FONT, type ButtonSize } from \"../utils/buttonSize.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\nimport type { ButtonVariant } from \"./button.js\";\n\nconst PADDING_STEPS: Record<ButtonSize, { block: number; inline: number }> = {\n small: { block: 0.5, inline: 2 },\n medium: { block: 1, inline: 3 },\n large: { block: 1.5, inline: 4 },\n};\n\nconst GHOST_PADDING: Record<ButtonSize, number> = {\n small: 0.5,\n medium: 1,\n large: 1.5,\n};\n\n/**\n * An `<a>` element styled to look like a button — same visual system as\n * `button()` (`variant` / `size` / color) while preserving link semantics\n * (href, middle-click, right-click). Apply to an `<a>` element.\n *\n * @hostTag a\n * @param props.color - Button color tone. Optional `ValueOrState<ThemeColor>`, default \"primary\".\n * @param props.variant - `\"outline\"` (default) | `\"solid\"` | `\"ghost\"` — matches `button()`.\n * @param props.size - `\"small\" | \"medium\" | \"large\"`, defaults to `\"medium\"`.\n * @example { a: \"Open app\", href: \"/app\", $: [linkButton({ color: \"primary\" })] }\n * @example { a: \"Get started\", href: \"/start\", $: [linkButton({ variant: \"solid\" })] }\n */\nfunction linkButton(\n props: {\n color?: ValueOrState<ThemeColor>;\n variant?: ButtonVariant;\n size?: ButtonSize;\n } = {},\n): PartialElement {\n const variant = props.variant ?? \"outline\";\n const color = toState(\n props.color ?? (variant === \"ghost\" ? \"neutral\" : \"primary\"),\n \"color\",\n );\n const size = props.size ?? \"medium\";\n const fontSize = BUTTON_SIZE_FONT[size];\n\n if (variant === \"ghost\") {\n const padding = GHOST_PADDING[size];\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"a\") {\n console.warn(`\"linkButton\" primitive patch must use a tag`);\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener, fontSize),\n textDecoration: \"none\",\n paddingBlock: (listener) =>\n themeSpacing(themeDensity(listener) * padding),\n paddingInline: (listener) =>\n themeSpacing(themeDensity(listener) * padding),\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n display: \"inline-flex\",\n justifyContent: \"center\",\n alignItems: \"center\",\n gap: (listener) => themeSpacing(themeDensity(listener) * 1),\n userSelect: \"none\",\n cursor: \"pointer\",\n lineHeight: \"inherit\",\n border: \"none\",\n background: \"none\",\n outline: \"none\",\n transition:\n \"background-color 140ms ease, color 140ms ease, box-shadow 140ms ease\",\n // Resting text uses the \"text\" alias (shift-9), matching buttonGhost:\n // a text-labeled ghost control fails WCAG AA at the previous shift-6\n // (~2.4:1 on an edge surface). Hover/active differentiate via\n // background only.\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n // Label tracks the +2 fill (textToneOn): holding it at \"text\" measured\n // 3.58:1 on the hover fill (light) / 4.37:1 (dark), below WCAG AA.\n \"&:hover:not([aria-disabled=true])\": {\n color: (listener) =>\n themeColor(listener, textToneOn(2), color.get(listener)),\n backgroundColor: (listener) =>\n themeColor(listener, \"hover\", color.get(listener)),\n textDecoration: \"none\",\n },\n \"&:active:not([aria-disabled=true])\": {\n color: (listener) =>\n themeColor(listener, textToneOn(2), color.get(listener)),\n backgroundColor: (listener) =>\n themeColor(listener, \"increase-2\", color.get(listener)),\n },\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, color.get(listener)),\n },\n \"&[aria-disabled=true]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n pointerEvents: \"none\",\n color: (listener) => themeColor(listener, \"border-strong\", \"neutral\"),\n },\n },\n };\n }\n\n const isSolid = variant === \"solid\";\n const padding = PADDING_STEPS[size];\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"a\") {\n console.warn(`\"linkButton\" primitive patch must use a tag`);\n }\n },\n // A solid CTA paints a fixed accent fill (that IS the variant), so its\n // backgroundColor deliberately resolves to a shifted tone rather than\n // \"inherit\". Measured with diagnose(): that is the only rule the solid\n // variant trips — the \"low-contrast\" and \"color-shift-minimum\" entries\n // this list also carried suppressed nothing and were reported as\n // `unused-doctor-disable`.\n ...(isSolid\n ? { _doctorDisable: [\"tone-background-inherit\"] as const }\n : {}),\n style: {\n fontSize: (listener) => themeSize(listener, fontSize),\n textDecoration: \"none\",\n paddingBlock: (listener) =>\n themeSpacing(themeDensity(listener) * padding.block),\n paddingInline: (listener) =>\n themeSpacing(themeDensity(listener) * padding.inline),\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n width: \"fit-content\",\n display: \"inline-flex\",\n justifyContent: \"center\",\n alignItems: \"center\",\n gap: (listener) => themeSpacing(themeDensity(listener) * 1),\n userSelect: \"none\",\n cursor: \"pointer\",\n lineHeight: \"inherit\",\n border: \"none\",\n outlineOffset: \"-1px\",\n outlineWidth: \"1px\",\n outline: isSolid\n ? \"none\"\n : (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", color.get(listener))}`,\n // Solid: deep brand (shift-13) + light-end text (not mid-ramp ~2.2:1).\n // Outline: shift-13 for ≥4.5:1 on light bg.\n color: (listener) =>\n isSolid\n ? themeColor(listener, \"shift-0\", \"neutral\")\n : themeColor(listener, \"shift-13\", color.get(listener)),\n backgroundColor: (listener) =>\n isSolid\n ? themeColor(listener, \"shift-13\", color.get(listener))\n : themeColor(listener, \"inherit\", color.get(listener)),\n transition:\n \"background-color 140ms ease, color 140ms ease, border-color 140ms ease, box-shadow 140ms ease\",\n \"&:hover:not([aria-disabled=true])\": {\n textDecoration: \"none\",\n color: (listener) =>\n isSolid\n ? themeColor(listener, \"shift-0\", \"neutral\")\n : themeColor(listener, \"shift-14\", color.get(listener)),\n backgroundColor: (listener) =>\n isSolid\n ? themeColor(listener, \"shift-14\", color.get(listener))\n : themeColor(listener, \"hover\", color.get(listener)),\n },\n \"&:active:not([aria-disabled=true])\": {\n backgroundColor: (listener) =>\n isSolid\n ? themeColor(listener, \"shift-15\", color.get(listener))\n : themeColor(listener, \"increase-2\", color.get(listener)),\n },\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, color.get(listener)),\n },\n \"&[aria-disabled=true]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n pointerEvents: \"none\",\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-2\", \"neutral\"),\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", \"neutral\")}`,\n color: (listener) => themeColor(listener, \"muted\", \"neutral\"),\n },\n },\n };\n}\n\nexport { linkButton };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n textToneOn,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * Styles a navigation/display list container. Sets `list-style: none` and\n * zero padding; pairs with `listItem` and `listItemButton`. Apply to `<ul>`.\n *\n * @hostTag ul\n * @param props.color - Surface color tone. Optional `ThemeColor`, defaults to `\"neutral\"`.\n * @example { ul: [...], $: [list()] }\n */\nfunction list(props: { color?: ThemeColor } = {}): PartialElement {\n const color = props.color ?? \"neutral\";\n return {\n style: {\n listStyle: \"none\",\n margin: 0,\n padding: 0,\n display: \"flex\",\n flexDirection: \"column\",\n backgroundColor: (listener) => themeColor(listener, \"inherit\", color),\n color: (listener) => themeColor(listener, \"text\", color),\n },\n };\n}\n\n/**\n * A non-interactive list row. Typically wraps an icon + text. Apply to `<li>`.\n *\n * @hostTag li\n * @param props.dense - Reduce vertical padding. Optional `boolean`, defaults to `false`.\n * @example { li: \"Item\", $: [listItem()] }\n */\nfunction listItem(props: { dense?: boolean } = {}): PartialElement {\n const { dense = false } = props;\n return {\n style: {\n display: \"flex\",\n alignItems: \"center\",\n gap: (listener) => themeSpacing(themeDensity(listener) * 2),\n paddingBlock: (listener) =>\n themeSpacing(dense ? 1 : themeDensity(listener) * 2),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 3),\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n color: (listener) => themeColor(listener, \"text\"),\n },\n };\n}\n\n/**\n * An interactive (clickable) list row with hover/focus-visible states. Apply\n * to `<button>` or `<a>` inside an `<li>`.\n *\n * @param props.color - Color tone. Optional `ValueOrState<ThemeColor>`, defaults to `\"neutral\"`.\n * @param props.accentColor - Focus/active accent. Optional `ThemeColor`, defaults to `\"primary\"`.\n * @param props.dense - Reduce vertical padding. Optional `boolean`, defaults to `false`.\n * @example { button: \"Action\", $: [listItemButton()] }\n */\nfunction listItemButton(\n props: {\n color?: ValueOrState<ThemeColor>;\n accentColor?: ThemeColor;\n dense?: boolean;\n } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n const accentColor = props.accentColor ?? \"primary\";\n const { dense = false } = props;\n\n return {\n // Native `type` on the host still wins (mergePartial: native over patch).\n type: \"button\",\n style: {\n cursor: \"pointer\",\n appearance: \"none\",\n border: \"none\",\n background: \"transparent\",\n textDecoration: \"none\",\n textAlign: \"start\",\n display: \"flex\",\n alignItems: \"center\",\n width: \"100%\",\n gap: (listener) => themeSpacing(themeDensity(listener) * 2),\n paddingBlock: (listener) =>\n themeSpacing(dense ? 1 : themeDensity(listener) * 2),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 3),\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n transition: \"background-color 150ms ease, box-shadow 140ms ease\",\n // The fill moves 2 steps off the surface, so the label moves with it —\n // keeping the resting \"text\" tone measured 3.58:1 on the hover fill.\n \"&:hover:not([disabled])\": {\n color: (listener) =>\n themeColor(listener, textToneOn(2), color.get(listener)),\n backgroundColor: (listener) =>\n themeColor(listener, \"hover\", color.get(listener)),\n },\n \"&:active:not([disabled])\": {\n color: (listener) =>\n themeColor(listener, textToneOn(2), color.get(listener)),\n backgroundColor: (listener) =>\n themeColor(listener, \"increase-2\", color.get(listener)),\n },\n \"&[aria-current=page], &[aria-selected=true]\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-3\", accentColor),\n color: (listener) => themeColor(listener, \"shift-12\", accentColor),\n },\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, accentColor),\n },\n \"&[disabled]\": { opacity: 0.5, cursor: \"not-allowed\" },\n },\n };\n}\n\nexport { list, listItem, listItemButton };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * Themed highlight primitive: gives marked/highlighted inline text a tinted\n * background, rounded corners and padding. Apply to a `<mark>` element.\n *\n * @hostTag mark\n * @param props - Optional configuration.\n * @param props.accentColor - Accent color tone for the highlight fill and text. Defaults to `\"highlight\"`.\n * @example { mark: \"important\", $: [mark()] }\n */\nfunction mark(\n props: { accentColor?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const accentColor = toState(props.accentColor ?? \"highlight\", \"accentColor\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"mark\") {\n console.warn(`\"mark\" primitive patch must use mark tag`);\n }\n },\n dataTone: \"shift-2\",\n style: {\n display: \"inline-flex\",\n alignItems: \"center\",\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n color: (listener) =>\n themeColor(listener, \"text\", accentColor.get(listener)),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", accentColor.get(listener)),\n // Bare themeSpacing(U) at snapshot time; n = U / 1.5 (light.densities[2]).\n height: (listener) => themeSpacing(themeDensity(listener) * (6 / 1.5)),\n borderRadius: (listener) =>\n themeSpacing(themeDensity(listener) * (1 / 1.5)),\n paddingInline: (listener) =>\n themeSpacing(themeDensity(listener) * (1.5 / 1.5)),\n },\n };\n}\n\nexport { mark };\n","import {\n type BehaviorInstance,\n behavior,\n type DomphyElement,\n type ElementNode,\n type Listener,\n type PartialElement,\n type State,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport {\n type ThemeColor,\n textToneOn,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { elevation } from \"../utils/elevation.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/** One item inside a menu. */\ntype MenuItem = {\n /** Button label — plain string (auto-wrapped) or any DomphyElement (e.g. icon + text). */\n label: string | DomphyElement;\n /** Stable key. Defaults to the item's zero-based index. */\n key?: string | number;\n /** Called when the item is clicked. */\n onClick?: () => void;\n};\n\n/**\n * All-in-one vertical menu. Generates `<button>` `[role=menuitem]` elements\n * from the `items` array with keyboard navigation (Arrow/Home/End/Enter/Space).\n * Apply to any wrapper element (`div`, `ul`, …).\n *\n * @param props.items - Item definitions `{ label, key?, onClick? }`. Pass `[]`\n * to keep the wrapper's own children (escape hatch for fully custom rows —\n * only the menu container styling and `role=\"menu\"` semantics apply then).\n * @param props.activeKey - Currently selected key (value or State). Defaults to `null`.\n * @param props.selectable - Whether items track and update the active selection. Defaults to `true`.\n * @param props.color - Background color tone for the menu. Defaults to `\"neutral\"`.\n * @param props.accentColor - Accent color for the active/focus item. Defaults to `\"primary\"`.\n * @example\n * { div: null, $: [menu({ items: [\n * { label: \"Profile\", key: \"profile\", onClick: () => navigate(\"/profile\") },\n * { label: \"Settings\", key: \"settings\", onClick: () => navigate(\"/settings\") },\n * ] })] }\n */\nfunction menu(\n props: {\n items: MenuItem[];\n activeKey?: ValueOrState<number | string | null>;\n selectable?: boolean;\n color?: ThemeColor;\n accentColor?: ThemeColor;\n } = { items: [] },\n): PartialElement {\n const {\n items = [],\n selectable = true,\n color = \"neutral\",\n accentColor = \"primary\",\n } = props;\n const activeKey = toState(props.activeKey ?? null);\n const activeKeyIsCallerOwned = props.activeKey !== undefined;\n\n type MenuInner = {\n items: MenuItem[];\n activeKey: State<number | string | null>;\n activeKeyIsCallerOwned: boolean;\n selectable: boolean;\n color: ThemeColor;\n accentColor: ThemeColor;\n // Roving-tabindex cursor (WAI-ARIA APG menu pattern): exactly one item is\n // in the page tab order at a time; Arrow/Home/End move it. Kept on the\n // shared `inner` record (not a factory-scope variable) so every generation\n // of a reused node reads the same cursor.\n focusedKey: State<number | string | null>;\n };\n\n // The item that owns tabindex=\"0\": the roving cursor if one has been set,\n // otherwise the selected item, otherwise the first item.\n const tabbableKey = (\n inner: MenuInner,\n listener: Listener,\n ): number | string | null => {\n const focused = inner.focusedKey.get(listener);\n if (focused !== null) return focused;\n const active = inner.selectable ? inner.activeKey.get(listener) : null;\n if (active !== null) return active;\n const first = inner.items[0];\n return first ? (first.key ?? 0) : null;\n };\n\n const buildItems = (\n node: ElementNode,\n inner: MenuInner,\n ): DomphyElement<\"button\">[] => {\n const id = node.nodeId;\n return inner.items.map((item, index) => {\n const key = item.key ?? index;\n return {\n button:\n typeof item.label === \"string\"\n ? [{ span: item.label } as DomphyElement<\"span\">]\n : [item.label],\n _key: key,\n type: \"button\",\n id: `menuitem${id}${key}`,\n role: \"menuitem\",\n tabIndex: (l: Listener) => (tabbableKey(inner, l) === key ? 0 : -1),\n onFocus: () => inner.focusedKey.set(key),\n ...(inner.selectable\n ? {\n ariaCurrent: (l: Listener) =>\n inner.activeKey.get(l) === key || undefined,\n }\n : {}),\n onClick: () => {\n if (inner.selectable) inner.activeKey.set(key);\n item.onClick?.();\n },\n onKeyDown: (e: Event) => {\n const k = (e as KeyboardEvent).key;\n if (k === \"Enter\" || k === \" \") {\n e.preventDefault();\n (e.target as HTMLElement).click();\n return;\n }\n if (![\"ArrowDown\", \"ArrowUp\", \"Home\", \"End\"].includes(k)) return;\n e.preventDefault();\n const keys = inner.items.map((it, i) => it.key ?? i);\n const idx = keys.indexOf(key);\n let next = idx;\n if (k === \"ArrowDown\") next = (idx + 1) % keys.length;\n else if (k === \"ArrowUp\")\n next = (idx - 1 + keys.length) % keys.length;\n else if (k === \"Home\") next = 0;\n else if (k === \"End\") next = keys.length - 1;\n // Resolved through the event target's own [role=menu] — shadow-root\n // safe, unlike a document.getElementById lookup (a menu rendered\n // inside a shadow root is invisible to the document-level id map,\n // so arrow keys silently did nothing there). Same resolution the\n // tabs patch already uses for its tablist.\n const list = (e.target as HTMLElement).closest(\"[role=menu]\");\n list?.querySelectorAll<HTMLElement>(\"[role=menuitem]\")[next]?.focus();\n },\n style: {\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n gap: themeSpacing(2),\n width: \"100%\",\n fontSize: (l: Listener) => themeSize(l, \"inherit\"),\n height: (l: Listener) => themeSpacing(6 + themeDensity(l) * 2),\n paddingInline: (l: Listener) => themeSpacing(themeDensity(l) * 3),\n border: \"none\",\n outline: \"none\",\n // Menu panel is a light (shift-0) surface: \"text\" resolves to a\n // dark-on-light reading tone in both light and dark themes.\n color: (l: Listener) => themeColor(l, \"text\", inner.color),\n backgroundColor: (l: Listener) =>\n themeColor(l, \"inherit\", inner.color),\n transition:\n \"background-color 140ms ease, box-shadow 140ms ease, color 140ms ease\",\n // Label tracks the hover fill (+2) — a fixed \"text\" label measured\n // 3.58:1 against it (light) / 4.37:1 (dark), below WCAG AA.\n \"&:hover:not([disabled]):not([aria-current=true])\": {\n backgroundColor: (l: Listener) =>\n themeColor(l, \"hover\", inner.color),\n color: (l: Listener) => themeColor(l, textToneOn(2), inner.color),\n },\n \"&[aria-current=true]\": {\n backgroundColor: (l: Listener) =>\n themeColor(l, \"shift-3\", inner.accentColor),\n color: (l: Listener) =>\n themeColor(l, \"shift-13\", inner.accentColor),\n },\n \"&:focus-visible\": {\n boxShadow: (l: Listener) => focusRing(l, inner.accentColor),\n },\n },\n } as DomphyElement<\"button\">;\n });\n };\n\n const attachMenu = (\n _node: ElementNode,\n initial: MenuInner,\n ): BehaviorInstance<MenuInner> => {\n // WAI-ARIA APG: when a menu opens, focus starts on the first item, not\n // wherever a PREVIOUS open left the roving cursor. attach() runs exactly\n // once per real DOM node — a genuine reopen (the menu's floating\n // container, e.g. popover, unmounts and remounts the panel on every\n // close/open) gets a fresh node and refires attach here, while an\n // in-place re-render (same node, e.g. mid-navigation Arrow presses)\n // never does — so this only resets on a real reopen, never mid-session.\n initial.focusedKey.set(null);\n let current = initial;\n return {\n update(next) {\n if (\n next.activeKey !== current.activeKey &&\n !next.activeKeyIsCallerOwned\n ) {\n next.activeKey.set(current.activeKey.get());\n }\n // Carry the roving cursor across generations too — a fresh factory\n // closure brings a fresh `toState(null)`, which would drop\n // tabindex=\"0\" back onto the first item mid-keyboard-navigation.\n if (next.focusedKey !== current.focusedKey) {\n next.focusedKey.set(current.focusedKey.get());\n }\n current = next;\n // Empty items = the caller renders its own rows; leave children alone.\n if (current.items.length === 0) return;\n _node.children.update(buildItems(_node, current));\n },\n };\n };\n\n const inner: MenuInner = {\n items,\n activeKey,\n activeKeyIsCallerOwned,\n selectable,\n color,\n accentColor,\n focusedKey: toState<number | string | null>(null),\n };\n\n return {\n role: \"menu\",\n dataTone: \"shift-0\",\n _onSchedule: (node, element) => {\n // Empty items = the caller renders its own rows; leave children alone.\n if (items.length === 0) return;\n (element as Record<string, unknown>)[node.tagName] = buildItems(\n node,\n inner,\n );\n },\n ...behavior<MenuInner>(\"menu\", attachMenu, inner),\n style: {\n display: \"flex\",\n flexDirection: \"column\",\n paddingBlock: (l: Listener) => themeSpacing(themeDensity(l) * 2),\n paddingInline: (l: Listener) => themeSpacing(themeDensity(l) * 2),\n fontSize: (l: Listener) => themeSize(l, \"inherit\"),\n backgroundColor: (l: Listener) => themeColor(l, \"inherit\", color),\n color: (l: Listener) => themeColor(l, \"text\", color),\n borderRadius: (l: Listener) => themeSpacing(themeDensity(l) * 2),\n outline: (l: Listener) =>\n `1px solid ${themeColor(l, \"border-strong\", color)}`,\n outlineOffset: \"-1px\",\n boxShadow: elevation(\"medium\"),\n },\n };\n}\n\nexport { menu };\nexport type { MenuItem };\n","import {\n type BehaviorInstance,\n behavior,\n type PartialElement,\n type State,\n} from \"@domphy/core\";\nimport { prefersReducedMotion } from \"../utils/reducedMotion.js\";\n\n/**\n * One keyframe. Shorthands `x`/`y` (px), `scale`, `rotate` (deg) compose into a\n * single `transform`; any other key is a raw CSS property (e.g. `opacity`,\n * `backgroundColor`).\n */\nexport type MotionKeyframe = {\n x?: number | string;\n y?: number | string;\n scale?: number | string;\n rotate?: number | string;\n} & Record<string, string | number>;\n\nexport interface MotionProps {\n /** Starting keyframe applied before the enter animation. */\n initial?: MotionKeyframe;\n /** Target keyframe. Pass a `State` to re-animate whenever it changes. */\n animate?: MotionKeyframe | State<MotionKeyframe>;\n /** Keyframe animated to before the element is removed. */\n exit?: MotionKeyframe;\n transition?: {\n /** ms, default 300. */\n duration?: number;\n /** ms, default 0. */\n delay?: number;\n /** CSS easing, default \"ease\". */\n easing?: string;\n iterations?: number;\n };\n}\n\ntype MotionInstance = BehaviorInstance<MotionProps> & {\n play: (props: MotionProps, mode: \"enter\" | \"update\") => void;\n getExit: () => MotionKeyframe | undefined;\n getTransition: () => MotionProps[\"transition\"];\n};\n\nconst isMotionState = (value: unknown): value is State<MotionKeyframe> =>\n !!value &&\n typeof (value as State<MotionKeyframe>).get === \"function\" &&\n (value as { _isState?: boolean })._isState === true;\n\nconst toStyles = (frame: MotionKeyframe): Keyframe => {\n const out: Record<string, string | number> = {};\n const transforms: string[] = [];\n for (const key in frame) {\n const value = frame[key];\n if (key === \"x\") {\n transforms.push(\n `translateX(${typeof value === \"number\" ? `${value}px` : value})`,\n );\n } else if (key === \"y\") {\n transforms.push(\n `translateY(${typeof value === \"number\" ? `${value}px` : value})`,\n );\n } else if (key === \"scale\") {\n transforms.push(`scale(${value})`);\n } else if (key === \"rotate\") {\n transforms.push(\n `rotate(${typeof value === \"number\" ? `${value}deg` : value})`,\n );\n } else {\n out[key] = value;\n }\n }\n if (transforms.length) out.transform = transforms.join(\" \");\n return out as Keyframe;\n};\n\nfunction toOptions(\n transition: MotionProps[\"transition\"] = {},\n): KeyframeAnimationOptions {\n return {\n duration: transition.duration ?? 300,\n delay: transition.delay ?? 0,\n easing: transition.easing ?? \"ease\",\n iterations: transition.iterations ?? 1,\n fill: \"both\",\n };\n}\n\nfunction attachMotion(\n node: { domElement?: HTMLElement | null },\n initial: MotionProps,\n): MotionInstance {\n const el = node.domElement as HTMLElement | null;\n let current = initial;\n let release: (() => void) | undefined;\n\n const bindAnimate = (animate: MotionProps[\"animate\"]) => {\n release?.();\n release = undefined;\n if (!el || !isMotionState(animate)) return;\n release = animate.addListener((next: MotionKeyframe) => {\n if (prefersReducedMotion()) {\n Object.assign(el.style, toStyles(next));\n } else if (typeof el.animate === \"function\") {\n el.animate([toStyles(next)], toOptions(current.transition));\n }\n });\n };\n\n const play = (props: MotionProps, mode: \"enter\" | \"update\") => {\n if (!el) return;\n const target = isMotionState(props.animate)\n ? props.animate.get()\n : props.animate;\n if (prefersReducedMotion()) {\n if (target) Object.assign(el.style, toStyles(target));\n else if (mode === \"enter\" && props.initial) {\n Object.assign(el.style, toStyles(props.initial));\n }\n return;\n }\n if (typeof el.animate !== \"function\") return;\n if (target) {\n const frames =\n mode === \"enter\" && props.initial\n ? [toStyles(props.initial), toStyles(target)]\n : [toStyles(target)];\n el.animate(frames, toOptions(props.transition));\n } else if (mode === \"enter\" && props.initial) {\n Object.assign(el.style, toStyles(props.initial));\n }\n };\n\n play(initial, \"enter\");\n bindAnimate(initial.animate);\n\n return {\n play,\n getExit: () => current.exit,\n getTransition: () => current.transition,\n update(next) {\n current = next;\n play(next, \"update\");\n bindAnimate(next.animate);\n },\n destroy() {\n release?.();\n },\n };\n}\n\n/**\n * Animation primitive driven by the Web Animations API. Runs an enter\n * animation on mount (`initial` -> `animate`), re-animates whenever `animate`\n * is a `State` that changes, and plays the `exit` keyframe before removal.\n * Has no host-tag restriction; apply to any element you want to animate.\n *\n * Later generations route a fresh `animate`/`exit`/`transition` into the same\n * `behavior()` instance via `update()`, so a reused node is not stuck on\n * generation-1 keyframes.\n *\n * @param props - Optional configuration (see {@link MotionProps}).\n * @param props.initial - Starting keyframe applied before the enter animation.\n * @param props.animate - Target keyframe, or a `State` to re-animate on change.\n * @param props.exit - Keyframe animated to before the element is removed.\n * @param props.transition - Timing options.\n * @param props.transition.duration - Duration in ms. Defaults to `300`.\n * @param props.transition.delay - Delay in ms. Defaults to `0`.\n * @param props.transition.easing - CSS easing. Defaults to `\"ease\"`.\n * @param props.transition.iterations - Number of iterations. Defaults to `1`.\n * @example { div: \"Hello\", $: [motion({ initial: { opacity: 0 }, animate: { opacity: 1 } })] }\n */\nfunction motion(props: MotionProps = {}): PartialElement {\n return {\n ...behavior<MotionProps>(\n \"motion\",\n (node, next) => attachMotion(node, next),\n props,\n ),\n _onBeforeRemove: (node, done) => {\n const el = node.domElement as HTMLElement | null;\n const inst = node.getBehavior<MotionInstance>(\"motion\");\n const exit = inst?.getExit() ?? props.exit;\n if (!el || !exit || typeof el.animate !== \"function\") return done();\n if (prefersReducedMotion()) {\n Object.assign(el.style, toStyles(exit));\n return done();\n }\n el.animate(\n [toStyles(exit)],\n toOptions(inst?.getTransition() ?? props.transition),\n ).finished.then(done, done);\n },\n };\n}\n\nexport { motion };\n","/**\n * True when the user has asked for reduced motion (WCAG 2.3.3 Animation from\n * Interactions). Shared by every animating patch — `motion()` swaps the\n * keyframe in directly and `transitionGroup()` skips its FLIP capture.\n * Returns false where `matchMedia` is missing (SSR, jsdom without a stub).\n */\nfunction prefersReducedMotion(): boolean {\n if (typeof matchMedia !== \"function\") return false;\n try {\n return matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n } catch {\n return false;\n }\n}\n\nexport { prefersReducedMotion };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * Themed ordered-list primitive: decimal markers positioned outside, reset\n * margins and themed text color. Apply to an `<ol>` element.\n *\n * @hostTag ol\n * @param props - Optional configuration.\n * @param props.color - Color tone for the list text. Defaults to `\"neutral\"`.\n * @example { ol: [{ li: \"First\" }, { li: \"Second\" }], $: [orderedList()] }\n */\nfunction orderedList(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"ol\") {\n console.warn(`\"orderedList\" primitive patch must use ol tag`);\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n backgroundColor: (listener) => themeColor(listener),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n marginTop: 0,\n marginBottom: 0,\n paddingInlineStart: themeSpacing(3),\n listStyleType: \"decimal\",\n listStylePosition: \"outside\",\n },\n };\n}\n\nexport { orderedList };\n","import {\n behavior,\n type DomphyElement,\n type ElementNode,\n isState,\n type PartialElement,\n type State,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n themeWeight,\n} from \"@domphy/theme\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\nfunction getPages(current: number, total: number): (number | \"...\")[] {\n if (total <= 7) return Array.from({ length: total }, (_, i) => i + 1);\n const pages: (number | \"...\")[] = [1];\n if (current > 3) pages.push(\"...\");\n const start = Math.max(2, current - 1);\n const end = Math.min(total - 1, current + 1);\n for (let i = start; i <= end; i++) pages.push(i);\n if (current < total - 2) pages.push(\"...\");\n pages.push(total);\n return pages;\n}\n\nfunction persistValue<T>(\n node: ElementNode,\n key: string,\n incoming: ValueOrState<T> | undefined,\n fallback: T,\n): State<T> {\n if (isState(incoming)) {\n node.setMetadata(key, incoming);\n return incoming as State<T>;\n }\n let stored = node.getMetadata(key) as State<T> | undefined;\n if (!stored) {\n stored = toState((incoming as T | undefined) ?? fallback);\n node.setMetadata(key, stored);\n }\n return stored;\n}\n\nfunction persistTotal(node: ElementNode, total: number): State<number> {\n let stored = node.getMetadata(\"paginationTotal\") as State<number> | undefined;\n if (!stored) {\n stored = toState(total);\n node.setMetadata(\"paginationTotal\", stored);\n }\n return stored;\n}\n\n/**\n * Themed pagination control. Renders previous/next buttons plus truncated page\n * numbers (with ellipses), tracks the current page in a `State`, and updates it\n * on click. Apply to a `<div>` element.\n *\n * @hostTag div\n * @param props - Configuration.\n * @param props.total - Required. Total number of pages.\n * @param props.value - Current page, accepts a value or `State`. Defaults to `1`.\n * @param props.color - Base color tone for the page buttons. Defaults to `\"neutral\"`.\n * @param props.accentColor - Accent color tone for the active page. Defaults to `\"primary\"`.\n * @example { div: null, $: [pagination({ total: 10, value: 1 })] }\n */\nfunction pagination(props: {\n value?: ValueOrState<number>;\n total: number;\n color?: ThemeColor;\n accentColor?: ThemeColor;\n}): PartialElement {\n const { total, color = \"neutral\", accentColor = \"primary\" } = props;\n\n const buttonBase = {\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n minWidth: (listener: any) => themeSpacing(6 + themeDensity(listener) * 2),\n height: (listener: any) => themeSpacing(6 + themeDensity(listener) * 2),\n paddingInline: (listener: any) => themeSpacing(themeDensity(listener) * 2),\n borderRadius: (listener: any) => themeSpacing(themeDensity(listener) * 1.5),\n border: \"none\",\n cursor: \"pointer\",\n fontSize: (listener: any) => themeSize(listener, \"inherit\"),\n backgroundColor: \"transparent\",\n // Page numbers: shift-13 for readable inactive digits (catalog contrast).\n color: (listener: any) => themeColor(listener, \"shift-13\", color),\n transition:\n \"background-color 140ms ease, box-shadow 140ms ease, color 140ms ease\",\n \"&:hover:not([disabled])\": {\n color: (listener: any) => themeColor(listener, \"shift-13\", color),\n backgroundColor: (listener: any) => themeColor(listener, \"hover\", color),\n },\n \"&:focus-visible\": {\n boxShadow: (listener: any) => focusRing(listener, accentColor),\n },\n \"&[disabled]\": {\n opacity: 0.4,\n cursor: \"not-allowed\",\n },\n };\n\n const activeStyle = {\n ...buttonBase,\n // Deep accent fill + light text (mid-ramp + mid text failed catalog).\n backgroundColor: (listener: any) =>\n themeColor(listener, \"shift-13\", accentColor),\n color: (listener: any) => themeColor(listener, \"shift-0\", \"neutral\"),\n fontWeight: themeWeight(\"bold\"),\n cursor: \"default\",\n \"&:hover:not([disabled])\": {\n backgroundColor: (listener: any) =>\n themeColor(listener, \"shift-13\", accentColor),\n },\n };\n\n return {\n role: \"navigation\",\n ariaLabel: \"Pagination\",\n _onInsert: (node) => {\n if (node.tagName !== \"div\")\n console.warn('\"pagination\" patch must use div tag');\n },\n _onInit: (node) => {\n const state = persistValue(node, \"paginationPage\", props.value, 1);\n const totalState = persistTotal(node, total);\n const content: DomphyElement<\"div\"> = {\n div: (listener) => {\n const page = state.get(listener);\n const pageCount = totalState.get(listener);\n const items: DomphyElement[] = [];\n\n // Prev button\n items.push({\n button: \"‹\",\n _key: \"prev\",\n type: \"button\",\n ariaLabel: \"Previous page\",\n disabled: page <= 1,\n onClick: () => page > 1 && state.set(page - 1),\n style: buttonBase,\n });\n\n // Page buttons. Keyed by page number (or a running ellipsis index —\n // there can be up to two \"...\" spans) so the list survives length\n // changes across pages without the unkeyed-reuse footgun.\n let ellipsisIndex = 0;\n for (const p of getPages(page, pageCount)) {\n if (p === \"...\") {\n items.push({\n span: \"…\",\n _key: `ellipsis-${ellipsisIndex++}`,\n ariaHidden: \"true\",\n style: {\n display: \"inline-flex\",\n alignItems: \"center\",\n paddingInline: (listener: any) =>\n themeSpacing(themeDensity(listener) * 2),\n color: (listener: any) =>\n themeColor(listener, \"shift-7\", color),\n },\n });\n } else {\n const isActive = p === page;\n items.push({\n button: String(p),\n _key: `page-${p}`,\n type: \"button\",\n ariaLabel: `Page ${p}`,\n ariaCurrent: isActive ? \"page\" : undefined,\n // The current page stays enabled (shadcn PaginationLink /\n // MUI Pagination parity). `disabled` on the just-clicked\n // button pulls it out of the tab order the instant it becomes\n // current, so the browser drops focus to <body> and a keyboard\n // user is stranded outside the control after every page\n // change. `aria-current=\"page\"` already conveys the state.\n onClick: () => state.set(p),\n style: isActive ? activeStyle : buttonBase,\n });\n }\n }\n\n // Next button\n items.push({\n button: \"›\",\n _key: \"next\",\n type: \"button\",\n ariaLabel: \"Next page\",\n disabled: page >= pageCount,\n onClick: () => page < pageCount && state.set(page + 1),\n style: buttonBase,\n });\n\n return items;\n },\n style: {\n display: \"flex\",\n alignItems: \"center\",\n gap: themeSpacing(1),\n },\n };\n node.children.insert(content);\n },\n ...behavior<{ total: number }>(\n \"pagination-total\",\n (node) => ({\n update(snapshot) {\n persistTotal(node, snapshot.total).set(snapshot.total);\n },\n }),\n { total },\n ),\n style: {\n display: \"inline-flex\",\n },\n };\n}\n\nexport { pagination };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * A padded section for side-panel/inspector UIs — density-aware padding on\n * all sides, with an optional bottom divider for sections stacked one after\n * another. A thin wrapper: it does not impose flex layout on its children —\n * pair it with `stack()` or `row()` for that. No host-tag check; apply to\n * any block element.\n *\n * @param props.padding - Spacing multiplier for padding on all sides (default 4 = 1em at density 1).\n * @param props.divider - Adds a bottom border, for sections stacked one after another. Defaults to `false`.\n * @param props.color - Theme color tone for the divider border. Defaults to `\"neutral\"`.\n * @example { div: [{ h3: \"Parameters\" }, { p: \"...\" }], $: [panelSection()] }\n * @example\n * { div: [\n * { div: \"Section A\", $: [panelSection({ divider: true })] },\n * { div: \"Section B\", $: [panelSection()] },\n * ], $: [stack({ gap: 0 })] }\n */\nfunction panelSection(\n props: {\n padding?: number;\n divider?: boolean;\n color?: ValueOrState<ThemeColor>;\n } = {},\n): PartialElement {\n const { padding = 4, divider = false } = props;\n const color = toState(props.color ?? \"neutral\", \"color\");\n return {\n style: {\n padding: (listener) => themeSpacing(themeDensity(listener) * padding),\n ...(divider\n ? {\n borderBottom: (listener) =>\n `1px solid ${themeColor(listener, \"border\", color.get(listener))}`,\n // Declaring a theme token makes this a themed surface, so the text\n // tone has to be declared with it (doctor `missing-color`): CSS\n // inheritance carries the parent's COMPUTED color and does not\n // re-run themeColor() when the tone context shifts, so a divided\n // section dropped into a darker panel kept the lighter surface's\n // text. Always the neutral body tone — `color` names the DIVIDER's\n // role, and a primary rule should not tint the prose.\n color: (listener) => themeColor(listener, \"text\"),\n }\n : {}),\n },\n };\n}\n\nexport { panelSection };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport { type ThemeColor, themeColor, themeSize } from \"@domphy/theme\";\n\n/**\n * Themed paragraph primitive: comfortable line-height, reset margins and themed\n * text color. Apply to a `<p>` element.\n *\n * @hostTag p\n * @param props - Optional configuration.\n * @param props.color - Color tone for the paragraph text. Defaults to `\"neutral\"`.\n * @example { p: \"Hello world\", $: [paragraph()] }\n */\nfunction paragraph(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"p\") {\n console.warn(`\"paragraph\" primitive patch must use p tag`);\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n lineHeight: 1.5,\n marginTop: 0,\n marginBottom: 0,\n },\n };\n}\n\nexport { paragraph };\n","import {\n type DomphyElement,\n type Listener,\n merge,\n type PartialElement,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport type { Placement } from \"@domphy/floating\";\nimport { themeColor, themeDensity, themeSpacing } from \"@domphy/theme\";\nimport { elevation } from \"../utils/elevation.js\";\nimport { createFloating, floatingPanelId } from \"../utils/floating.js\";\n\n// `aria-haspopup` must name the role the popup ACTUALLY has — a trigger that\n// says \"dialog\" while it opens a `role=menu` panel is an ARIA contract break\n// (axe `aria-allowed-attr` passes it, but a screen reader announces the wrong\n// kind of popup and readers that pre-announce \"menu\" say \"dialog\"). The\n// popover's own panel chrome is `role=dialog`, but content that already owns a\n// surface keeps its own role: `menu()` is `role=menu`, `selectList()` is\n// `role=listbox`. Only these five values are legal for aria-haspopup.\nconst HASPOPUP_ROLES = new Set([\"dialog\", \"grid\", \"listbox\", \"menu\", \"tree\"]);\ntype HaspopupRole = \"dialog\" | \"grid\" | \"listbox\" | \"menu\" | \"tree\";\n\n// Mirrors core's own precedence: patches merge in `$` order (later wins) and\n// the element's own keys win over all of them.\nfunction panelHaspopup(content: DomphyElement): HaspopupRole {\n let role: unknown;\n for (const patch of content.$ ?? []) {\n const declared = (patch as { role?: unknown } | null)?.role;\n if (typeof declared === \"string\") role = declared;\n }\n const own = (content as { role?: unknown }).role;\n if (typeof own === \"string\") role = own;\n if (typeof role !== \"string\") return \"dialog\";\n // Aliases with no aria-haspopup value of their own.\n if (role === \"alertdialog\" || role === \"menubar\") {\n return role === \"menubar\" ? \"menu\" : \"dialog\";\n }\n if (role === \"treegrid\") return \"grid\";\n // Anything else (a bare card, `command()`'s role=group) has no matching\n // value; \"dialog\" is what the popover's own chrome would have given it.\n return HASPOPUP_ROLES.has(role) ? (role as HaspopupRole) : \"dialog\";\n}\n\nfunction contentOwnsSurface(content: DomphyElement): boolean {\n const record = content as DomphyElement & { dataTone?: string };\n if (typeof record.dataTone === \"string\") return true;\n const patches = content.$;\n if (!patches) return false;\n return patches.some(\n (patch) =>\n patch != null &&\n typeof (patch as { dataTone?: unknown }).dataTone === \"string\",\n );\n}\n\n/**\n * Floating popover primitive. Attaches to its host as the anchor/trigger and\n * shows a floating `content` element (with `role=\"dialog\"`) on click or hover,\n * positioned via `@domphy/floating`. Returns the anchor partial, which merges\n * trigger wiring (haspopup/expanded, focus/blur dismissal). Apply to the\n * trigger element you want the popover anchored to.\n *\n * @param props - Configuration.\n * @param props.openOn - Interaction that opens the popover: `\"click\"` or `\"hover\"`. Defaults to `\"click\"`.\n * @param props.open - Open state (`ValueOrState<boolean>`), including `Computed`/`ReadableState`. When the source is read-only, pass `onDismiss` so Escape/outside click can close. Defaults to `false`.\n * @param props.onDismiss - Called when the panel requests close. Optional. Required to close when `open` is a read-only `Computed`/`ReadableState`.\n * @param props.placement - Floating placement (e.g. `\"bottom\"`, `\"top-start\"`), value or `State`. Defaults to `\"bottom\"`.\n * @param props.content - The floating content element to display.\n * @example { button: \"Open\", $: [popover({ openOn: \"click\", content: { div: \"Hi\" } })] }\n */\nfunction popover(props: {\n openOn?: \"click\" | \"hover\";\n open?: ValueOrState<boolean>;\n onDismiss?: () => void;\n placement?: ValueOrState<Placement>;\n content: DomphyElement;\n}): PartialElement {\n const { open = false, placement = \"bottom\", openOn = \"click\" } = props;\n\n const openState = toState(open);\n const placeState = toState(placement);\n\n const { show, hide, anchorPartial } = createFloating({\n kind: \"popover\",\n open: openState,\n onDismiss: props.onDismiss,\n placement: placeState,\n content: props.content,\n // Hovering the panel itself (not just the trigger) must keep it open —\n // handled generically inside floating.ts's behavior instance.\n keepOpenOnContentHover: openOn === \"hover\",\n });\n\n // Page-matching card (shift-0), same as menu/selectList/dialog — not the\n // inverted tooltip/toast surface (shift-17). A dark shift-14 panel wrapping\n // a light menu is the menubar recipe (`popover` + `menu`) rendered as two\n // stacked cards.\n const popoverPartial: PartialElement = {\n role: \"dialog\",\n dataTone: \"shift-0\",\n style: {\n backgroundColor: (l: Listener) => themeColor(l, \"inherit\"),\n color: (l: Listener) => themeColor(l, \"text\"),\n borderRadius: (l: Listener) => themeSpacing(themeDensity(l) * 2),\n outline: (l: Listener) => `1px solid ${themeColor(l, \"border-strong\")}`,\n outlineOffset: \"-1px\",\n boxShadow: elevation(\"medium\"),\n },\n };\n\n // Content that already owns a surface (`menu()`, `card()`, an authored\n // dataTone) must keep it: stamping this partial on top overwrites\n // `role=menu` with `role=dialog` and comma-joins a second box-shadow\n // (merge concatenates boxShadow).\n if (!contentOwnsSurface(props.content)) {\n props.content.$ ||= [];\n props.content.$.push(popoverPartial);\n }\n\n const triggerPartial: PartialElement = {\n // Read AFTER the popoverPartial push above, so unstyled content that got\n // the popover's own `role=dialog` chrome resolves to \"dialog\" too.\n ariaHaspopup: panelHaspopup(props.content),\n ariaExpanded: (listener) => openState.get(listener),\n // Declared as a reactive attribute (listener.elementNode is the anchor) so\n // it is present from first render — before the panel's first show() — and\n // is re-declared on every patch: attributes set imperatively (the old\n // _onMount attributes.set) are stripped by patch() on ancestor re-render.\n ariaControls: (listener) =>\n listener?.elementNode\n ? floatingPanelId(\"popover\", listener.elementNode)\n : undefined,\n onMouseEnter: (_e, node) => openOn === \"hover\" && show(node),\n onMouseLeave: (_e, node) => openOn === \"hover\" && hide(node),\n onClick: (_e, node) => {\n if (openOn === \"click\") {\n if (openState.get()) {\n hide(node);\n } else {\n show(node);\n }\n }\n },\n onKeyDown: (e, node) => {\n if ((e as KeyboardEvent).key === \"Escape\" && openState.get()) hide(node);\n },\n onFocus: (_e, node) => openOn === \"hover\" && show(node),\n onBlur: (e, node) => {\n // Docs: focus has no effect when openOn is click — only hover-mode\n // blur dismisses (and even then, not when focus moved INTO the panel).\n if (openOn !== \"hover\") return;\n const related = (e as FocusEvent).relatedTarget as Node | null;\n const root = node.getRoot().domElement as Element;\n // Tabbing from the trigger INTO the panel must not close the popover.\n // The id is deterministic and selector-safe ([a-z0-9-] only — nodeId is\n // a letter + hex hash), so this lookup works for every generation —\n // the old factory-scope `popoverId` was null in any generation whose\n // content _onInsert had never run, letting the guard fall through.\n const floatingEl = root.querySelector(\n `#${floatingPanelId(\"popover\", node)}`,\n );\n if (related && floatingEl?.contains(related)) return;\n hide(node);\n },\n };\n merge(anchorPartial, triggerPartial);\n\n return anchorPartial;\n}\n\nexport { popover };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport type { Placement } from \"@domphy/floating\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * Renders a small rotated arrow (via a `::after` pseudo-element) that points from a\n * popover/tooltip toward its anchor, positioned and oriented based on the floating placement.\n * The arrow direction is computed by flipping the given placement. No host-tag check is\n * performed; apply it to the popover container element.\n *\n * @param props.placement - Floating placement the popover sits at; the arrow is drawn on the\n * opposite (flipped) side. Accepts a value or reactive state. Defaults to `\"bottom-end\"`.\n * One of: `top` | `bottom` | `left` | `right` | `top-start` | `top-end` | `bottom-start` |\n * `bottom-end` | `left-start` | `left-end` | `right-start` | `right-end`.\n * @param props.sideOffset - CSS length used to offset the arrow toward the start/end edge.\n * Defaults to `themeSpacing(6)`.\n * @param props.color - Theme color tone for the arrow fill and border. Defaults to `\"neutral\"`.\n * @param props.bordered - Whether the arrow draws a 1px border (set to `0px` when false).\n * Defaults to `true`.\n * @example { div: [...], $: [popoverArrow({ placement: \"top\" })] }\n */\nfunction popoverArrow(\n props: {\n placement?: ValueOrState<Placement>;\n sideOffset?: string;\n color?: ThemeColor;\n bordered?: boolean;\n } = {},\n): PartialElement {\n const {\n placement = \"bottom-end\",\n color = \"neutral\",\n sideOffset = themeSpacing(6),\n bordered = true,\n } = props;\n\n const place = toState(placement);\n\n const flipMap: Record<Placement, Placement> = {\n top: \"bottom\",\n bottom: \"top\",\n left: \"right\",\n right: \"left\",\n \"top-start\": \"bottom-end\",\n \"top-end\": \"bottom-start\",\n \"bottom-start\": \"top-end\",\n \"bottom-end\": \"top-start\",\n \"left-start\": \"right-end\",\n \"left-end\": \"right-start\",\n \"right-start\": \"left-end\",\n \"right-end\": \"left-start\",\n };\n\n const getFlipped = (listener: any) =>\n flipMap[place.get(listener)] ?? flipMap[\"bottom-end\"];\n const start = (pos: string) =>\n pos.includes(\"start\") ? sideOffset : pos.includes(\"end\") ? \"auto\" : \"50%\";\n const end = (pos: string) =>\n pos.includes(\"end\") ? sideOffset : pos.includes(\"start\") ? \"auto\" : \"50%\";\n\n return {\n style: {\n fontSize: (listener) => themeSize(listener),\n backgroundColor: (listener) => themeColor(listener),\n color: (listener) => themeColor(listener, \"text\", color),\n position: \"relative\",\n \"&::after\": {\n content: `\"\"`,\n position: \"absolute\",\n width: themeSpacing(1.5),\n height: themeSpacing(1.5),\n backgroundColor: (listener) => themeColor(listener, \"inherit\", color),\n borderWidth: bordered ? \"1px\" : 0,\n borderColor: (listener) => themeColor(listener, \"border-strong\", color),\n borderTopStyle: (listener) => {\n const pos = getFlipped(listener);\n\n return pos.includes(\"top\") || pos.includes(\"right\")\n ? `solid`\n : \"none\";\n },\n borderBottomStyle: (listener) => {\n const pos = getFlipped(listener);\n\n return pos.includes(\"bottom\") || pos.includes(\"left\")\n ? `solid`\n : \"none\";\n },\n borderLeftStyle: (listener) => {\n const pos = getFlipped(listener);\n return pos.includes(\"top\") || pos.includes(\"left\") ? `solid` : \"none\";\n },\n borderRightStyle: (listener) => {\n const pos = getFlipped(listener);\n return pos.includes(\"bottom\") || pos.includes(\"right\")\n ? `solid`\n : \"none\";\n },\n top: (listener) => {\n const pos = getFlipped(listener);\n return pos.includes(\"top\")\n ? 0\n : pos.includes(\"bottom\")\n ? \"auto\"\n : start(pos);\n },\n right: (listener) => {\n const pos = getFlipped(listener);\n return pos.includes(\"right\")\n ? 0\n : pos.includes(\"left\")\n ? \"auto\"\n : end(pos);\n },\n bottom: (listener) => {\n const pos = getFlipped(listener);\n return pos.includes(\"bottom\")\n ? 0\n : pos.includes(\"top\")\n ? \"auto\"\n : end(pos);\n },\n left: (listener) => {\n const pos = getFlipped(listener);\n return pos.includes(\"left\")\n ? 0\n : pos.includes(\"right\")\n ? \"auto\"\n : start(pos);\n },\n transform: (listener) => {\n const pos = getFlipped(listener);\n const x =\n pos.includes(\"right\") ||\n (pos.includes(\"end\") && !pos.includes(\"left\"))\n ? \"50%\"\n : \"-50%\";\n const y =\n pos.includes(\"bottom\") ||\n (pos.includes(\"end\") && !pos.includes(\"top\"))\n ? \"50%\"\n : \"-50%\";\n return `translate(${x},${y}) rotate(45deg)`;\n },\n },\n },\n };\n}\n\nexport { popoverArrow };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeFont,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * Styles a preformatted text block: inherited font size, the theme's monospace\n * stack, themed foreground/background,\n * no border, density-scaled padding and rounded corners.\n *\n * @hostTag pre\n * @param props.color - Theme color tone for text and background. Accepts a value or reactive\n * state. Defaults to `\"neutral\"`.\n * @example { pre: \"const x = 1\", $: [preformated()] }\n */\nfunction preformated(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n dataTone: \"shift-2\",\n _onInsert: (node) => {\n if (node.tagName !== \"pre\") {\n console.warn(`\"preformated\" primitive patch must use pre tag`);\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n // The theme owns the code stack; <code>/<kbd>/<pre> otherwise keep the\n // UA generic \"monospace\" (Courier New on Windows), so a theme that swaps\n // fontFamilies.monospace never reaches them.\n fontFamily: themeFont(\"monospace\"),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n border: \"none\",\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 2),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 3),\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 2),\n },\n };\n}\n\nexport { preformated };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport { type ThemeColor, themeColor, themeSpacing } from \"@domphy/theme\";\n\n/**\n * Styles a native progress bar: full-width, pill-shaped track with a themed fill,\n * including the WebKit progress-bar/value pseudo-elements and a width transition.\n *\n * @hostTag progress\n * @param props.color - Theme color tone for the track/background. Accepts a value or reactive\n * state. Defaults to `\"neutral\"`.\n * @param props.accentColor - Theme color tone for the filled value. Accepts a value or reactive\n * state. Defaults to `\"primary\"`.\n * @example { progress: null, value: 40, max: 100, $: [progress()] }\n */\nfunction progress(\n props: {\n color?: ValueOrState<ThemeColor>;\n accentColor?: ValueOrState<ThemeColor>;\n } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n const accentColor = toState(props.accentColor ?? \"primary\", \"accentColor\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"progress\") {\n console.warn(`\"progress\" primitive patch must use progress tag`);\n }\n },\n // Track surface — shift via dataTone, paint with inherit.\n dataTone: \"shift-3\",\n style: {\n appearance: \"none\",\n width: \"100%\",\n height: themeSpacing(2),\n border: 0,\n borderRadius: themeSpacing(999),\n overflow: \"hidden\",\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n \"&::-webkit-progress-bar\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n borderRadius: themeSpacing(999),\n },\n \"&::-webkit-progress-value\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-9\", accentColor.get(listener)),\n borderRadius: themeSpacing(999),\n transition: \"width 220ms ease\",\n },\n },\n };\n}\n\nexport { progress };\n","import {\n behavior,\n type DomphyElement,\n type ElementNode,\n isState,\n type Listener,\n type PartialElement,\n rawHtml,\n type State,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { horizontalArrowStep } from \"../utils/direction.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\nconst STAR_FILLED =\n `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\" width=\"1em\" height=\"1em\">` +\n `<path d=\"M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z\"/>` +\n `</svg>`;\nconst STAR_EMPTY =\n `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\" width=\"1em\" height=\"1em\">` +\n `<path d=\"M22 9.24l-7.19-.62L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21 12 17.27 18.18 21l-1.63-7.03L22 9.24zM12 15.4l-3.76 2.27 1-4.28-3.32-2.88 4.38-.38L12 6.1l1.71 4.04 4.38.38-3.32 2.88 1 4.28L12 15.4z\"/>` +\n `</svg>`;\n\ntype RatingProps = {\n value?: ValueOrState<number>;\n max?: number;\n onChange?: (value: number) => void;\n readOnly?: boolean;\n color?: ThemeColor;\n};\n\ntype RatingLive = {\n valueState: State<number>;\n onChange?: (value: number) => void;\n readOnly: boolean;\n max: number;\n color: ThemeColor;\n};\n\nfunction applyRatingProps(live: RatingLive, next: RatingProps): void {\n live.onChange = next.onChange;\n live.readOnly = next.readOnly ?? false;\n live.max = next.max ?? 5;\n live.color = next.color ?? \"warning\";\n if (isState(next.value)) {\n if (next.value !== live.valueState) {\n live.valueState.set(next.value.get());\n }\n } else if (next.value !== undefined) {\n // Plain number stays live. Omitted value leaves the internal state\n // alone so an uncontrolled click is not reset on a later factory call.\n live.valueState.set(next.value);\n }\n}\n\nfunction insertStar(\n node: ElementNode,\n index: number,\n live: RatingLive,\n hoveredState: State<number>,\n): void {\n const activeCount = (listener: Listener) => {\n const hovered = hoveredState.get(listener);\n return hovered > 0 ? hovered : live.valueState.get(listener);\n };\n\n const star: DomphyElement<\"button\"> = {\n button: (listener) =>\n rawHtml(index <= activeCount(listener) ? STAR_FILLED : STAR_EMPTY),\n _key: index,\n type: \"button\",\n ariaLabel: `${index} star${index > 1 ? \"s\" : \"\"}`,\n // WAI-ARIA APG radio group: the stars ARE the radios. Without a role and\n // aria-checked a screen reader read five identically-shaped buttons and\n // could not tell which rating was chosen, and Tab stopped on every star\n // instead of entering the group once (roving tabindex).\n role: \"radio\",\n ariaChecked: (listener: Listener) =>\n live.valueState.get(listener) === index,\n tabindex: (listener: Listener) => {\n const current = live.valueState.get(listener);\n return (current === 0 ? 1 : current) === index ? 0 : -1;\n },\n onClick: () => {\n if (live.readOnly) return;\n const next = index === live.valueState.get() ? 0 : index;\n live.valueState.set(next);\n live.onChange?.(next);\n hoveredState.set(0);\n },\n onMouseEnter: () => {\n if (live.readOnly) return;\n hoveredState.set(index);\n },\n onMouseLeave: () => hoveredState.set(0),\n onKeyDown: (e: KeyboardEvent) => {\n if (live.readOnly) return;\n const current = live.valueState.get();\n let next = current;\n if (e.key === \"ArrowUp\") {\n next = Math.min(live.max, current + 1);\n e.preventDefault();\n } else if (e.key === \"ArrowDown\") {\n next = Math.max(0, current - 1);\n e.preventDefault();\n } else if (e.key === \"ArrowRight\" || e.key === \"ArrowLeft\") {\n const step = horizontalArrowStep(e.key, e.target as Element);\n next =\n step > 0 ? Math.min(live.max, current + 1) : Math.max(0, current - 1);\n e.preventDefault();\n } else if (e.key === \"Home\") {\n next = 1;\n e.preventDefault();\n } else if (e.key === \"End\") {\n next = live.max;\n e.preventDefault();\n } else {\n return;\n }\n live.valueState.set(next);\n live.onChange?.(next);\n const target = next > 0 ? next - 1 : 0;\n (node.domElement?.children[target] as HTMLElement)?.focus();\n },\n style: {\n background: \"none\",\n border: \"none\",\n outline: \"none\",\n borderRadius: themeSpacing(1),\n padding: 0,\n cursor: \"inherit\",\n color: \"inherit\",\n fontSize: \"inherit\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n // WCAG 2.2 SC 2.5.8 Target Size (Minimum) is 24x24 CSS px. The glyph is\n // 1em, so an unpadded star measured 16x16 — a miss on touch.\n minWidth: themeSpacing(6),\n minHeight: themeSpacing(6),\n transition: \"box-shadow 140ms ease\",\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, live.color),\n },\n },\n };\n node.children.insert(star);\n}\n\nfunction syncStars(\n node: ElementNode,\n live: RatingLive,\n hoveredState: State<number>,\n): void {\n const children = node.children.items;\n while (children.length > live.max) {\n node.children.remove(children[children.length - 1]);\n }\n for (let index = children.length + 1; index <= live.max; index++) {\n insertStar(node, index, live, hoveredState);\n }\n}\n\n/**\n * Interactive star rating applied to a container `<div>`. Manages its own star\n * children: click to set, Arrow keys to adjust, hover to preview. In `readOnly`\n * mode stars are non-interactive. Apply to a `<div>` element.\n *\n * Star insert runs in `_onInit` (SSR markup). `onChange`/`readOnly`/`max` and\n * a plain-number `value` stay live via `behavior()` `update()` so a reused\n * node picks up the latest factory props.\n *\n * @hostTag div\n * @param props.value - Current rating (0 – max). `ValueOrState<number>`, defaults to `0`.\n * @param props.max - Total number of stars. Optional `number`, defaults to `5`.\n * @param props.onChange - Called with the new value when the user picks a star.\n * @param props.readOnly - Disable interaction. Optional `boolean`, defaults to `false`.\n * @param props.color - Star color tone. Optional `ThemeColor`, defaults to `\"warning\"`.\n * @example { div: null, $: [rating({ value: ratingState, onChange: (v) => ratingState.set(v) })] }\n */\nfunction rating(props: RatingProps = {}): PartialElement {\n const live: RatingLive = {\n valueState: toState(props.value ?? 0),\n onChange: props.onChange,\n readOnly: props.readOnly ?? false,\n max: props.max ?? 5,\n color: props.color ?? \"warning\",\n };\n const hoveredState = toState(0);\n\n return {\n role: \"radiogroup\",\n ariaLabel: \"Rating\",\n ariaReadonly: live.readOnly ? \"true\" : undefined,\n style: {\n display: \"inline-flex\",\n gap: themeSpacing(0.5),\n // 1.5× inherited control size (theme-owned type scale, not a px/rem literal).\n fontSize: (listener) => themeSize(listener, \"increase-1\"),\n cursor: live.readOnly ? \"default\" : \"pointer\",\n color: (listener) => themeColor(listener, \"muted\", live.color),\n },\n ...behavior<RatingProps>(\n \"rating\",\n (node, initial) => {\n applyRatingProps(live, initial);\n syncStars(node, live, hoveredState);\n return {\n update(next) {\n applyRatingProps(live, next);\n syncStars(node, live, hoveredState);\n },\n };\n },\n {\n value: props.value,\n max: props.max ?? 5,\n onChange: props.onChange,\n readOnly: props.readOnly ?? false,\n color: props.color ?? \"warning\",\n },\n ),\n // Build stars as real child elements (not imperative DOM mutation in\n // _onMount) so generateHTML()/SSR emits the actual star markup.\n _onInit: (node) => {\n syncStars(node, live, hoveredState);\n },\n };\n}\n\nexport { rating };\n","/**\n * True when the element resolves to right-to-left text direction (inherited\n * `dir` attribute or `direction` CSS). Same technique @domphy/floating's\n * vendored floating-ui platform uses internally for RTL-aware placement\n * (packages/floating/src/dom/platform/isRTL.ts) — reading the resolved CSS\n * `direction` picks up an ancestor `dir` attribute without walking the tree.\n */\nfunction isRTL(element: Element | null | undefined): boolean {\n if (!element || typeof getComputedStyle !== \"function\") return false;\n return getComputedStyle(element).direction === \"rtl\";\n}\n\n/**\n * Maps a horizontal arrow key to a directional step (+1 toward the end of\n * the list, -1 toward the start), mirrored when the element resolves to RTL.\n * ArrowUp/ArrowDown and Home/End are direction-agnostic and are not covered\n * here — callers keep handling those directly.\n */\nfunction horizontalArrowStep(\n key: string,\n element: Element | null | undefined,\n): 1 | -1 | 0 {\n if (key !== \"ArrowRight\" && key !== \"ArrowLeft\") return 0;\n const forward = key === \"ArrowRight\";\n return forward !== isRTL(element) ? 1 : -1;\n}\n\nexport { horizontalArrowStep, isRTL };\n","import type { PartialElement, StyleObject } from \"@domphy/core\";\nimport { toState, type ValueOrState } from \"@domphy/core\";\nimport { type ThemeColor, themeColor, themeSpacing } from \"@domphy/theme\";\n\n/**\n * Circular ring progress indicator rendered via CSS `conic-gradient` and a\n * circular `mask`. Progress starts at 12 o'clock and advances clockwise.\n * Exposes `role=\"progressbar\"` with `aria-valuenow/min/max`. Apply to a `<div>`.\n *\n * @hostTag div\n * @param props.value - Progress percentage 0–100. Accepts a value or reactive state. Defaults to `0`.\n * @param props.color - Theme color for the filled arc. Accepts a value or reactive state. Defaults to `\"primary\"`.\n * @param props.trackColor - Theme color for the background track. Accepts a value or reactive state. Defaults to `\"neutral\"`.\n * @param props.size - Diameter in `themeSpacing` units. Defaults to `16` (= `4em`).\n * @param props.thickness - Ring stroke as a fraction of the radius (0–0.5). Defaults to `0.25`.\n * @example { div: null, $: [ringProgress({ value: 65 })] }\n * @example { div: null, $: [ringProgress({ value: loadingState, color: \"success\", size: 20 })] }\n */\nfunction ringProgress(\n props: {\n value?: ValueOrState<number>;\n color?: ValueOrState<ThemeColor>;\n trackColor?: ValueOrState<ThemeColor>;\n size?: number;\n thickness?: number;\n } = {},\n): PartialElement {\n const { size = 16, thickness = 0.25 } = props;\n const value = toState(props.value ?? 0, \"value\");\n const color = toState(props.color ?? \"primary\", \"color\");\n const trackColor = toState(props.trackColor ?? \"neutral\", \"trackColor\");\n\n // Mask cuts the center to create a donut shape.\n // Uses `closest-side` so the gradient circle matches the visible element circle\n // exactly, making `holePercent` directly represent the fraction of outer radius.\n const holePercent = Math.round((1 - thickness) * 100);\n const mask = `radial-gradient(circle closest-side, transparent ${holePercent}%, black ${holePercent}%)`;\n\n return {\n role: \"progressbar\",\n ariaValuenow: (l) => String(Math.round(value.get(l))),\n ariaValuemin: \"0\",\n ariaValuemax: \"100\",\n _onInsert: (node) => {\n if (node.tagName !== \"div\") {\n console.warn('\"ringProgress\" patch must use div tag');\n }\n },\n style: {\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: themeSpacing(size),\n height: themeSpacing(size),\n borderRadius: \"50%\",\n // Text color tracks the filled arc so any overlay label inherits it.\n color: (l) => themeColor(l, \"shift-9\", color.get(l)),\n // Fill arc from 12 o'clock clockwise; `from -90deg` rotates the start point.\n background: (l) =>\n `conic-gradient(from -90deg, ${themeColor(l, \"shift-9\", color.get(l))} ${value.get(l)}%, ${themeColor(l, \"shift-3\", trackColor.get(l))} 0%)`,\n WebkitMask: mask,\n mask,\n } as StyleObject,\n };\n}\n\nexport { ringProgress };\n","import type { PartialElement } from \"@domphy/core\";\nimport { themeDensity, themeSpacing } from \"@domphy/theme\";\nimport type { FlexAlign, FlexJustify } from \"./stack.js\";\n\n/**\n * A horizontal flex row with spacing between children, vertically centered by\n * default. The general-purpose primitive for icon+label rows, field rows,\n * and button groups — instead of hand-rolling `display: flex; alignItems:\n * center; gap: ...`. `toolbar()` is a semantic alias of this same shape for\n * headers/nav bars. Styles the host only; apply to any block element.\n *\n * @param props.gap - Spacing multiplier for gap between items (default 4).\n * Bounded-control mode (`density: true`, default): `themeSpacing(themeDensity(l) * gap)`\n * — at default density 1.5, gap 4 = 1.5em.\n * Structural/page-column mode (`density: false`): bare `themeSpacing(gap)` with no\n * density multiply — gap 4 = 1em, matching AGENTS.md \"bare themeSpacing(n)\".\n * @param props.align - Cross-axis alignment (`alignItems`). Defaults to `\"center\"`.\n * @param props.justify - Main-axis distribution (`justifyContent`). Unset by default (flex-start).\n * @param props.wrap - Allow items to wrap onto multiple lines. Defaults to `false`.\n * @param props.density - When true (default), gap is multiplied by theme density\n * (bounded controls). When false, gap is structural `themeSpacing(n)` — use this\n * for page/form columns.\n * @example { div: [{ span: \"Icon\" }, { span: \"Label\" }], $: [row()] }\n * @example { div: [...], $: [row({ justify: \"space-between\", wrap: true })] }\n * @example { div: [...], $: [row({ gap: 4, density: false })] }\n */\nfunction row(\n props: {\n gap?: number;\n align?: FlexAlign;\n justify?: FlexJustify;\n wrap?: boolean;\n density?: boolean;\n } = {},\n): PartialElement {\n const {\n gap = 4,\n align = \"center\",\n justify,\n wrap = false,\n density = true,\n } = props;\n return {\n style: {\n display: \"flex\",\n alignItems: align,\n gap: density\n ? (listener) => themeSpacing(themeDensity(listener) * gap)\n : () => themeSpacing(gap),\n ...(justify ? { justifyContent: justify } : {}),\n ...(wrap ? { flexWrap: \"wrap\" } : {}),\n },\n };\n}\n\nexport { row };\nexport type { FlexJustify };\n","import type { PartialElement, StyleObject } from \"@domphy/core\";\nimport { toState, type ValueOrState } from \"@domphy/core\";\nimport { type ThemeColor, themeColor, themeSpacing } from \"@domphy/theme\";\n\n/**\n * Applies thin, themed overlay scrollbars to any scrollable container.\n * Covers WebKit (Chrome/Safari/Edge) via `::-webkit-scrollbar` pseudo-elements\n * and Firefox via `scrollbar-width`/`scrollbar-color`. Sets `overflow: auto`.\n * No host-tag check; apply to any block element.\n *\n * Pass `label` when the scrollable content is NOT itself keyboard-reachable —\n * a wide table, a code block, a diagram. Such a region can only be scrolled\n * with a pointer, which fails WCAG 2.1.1 (axe `scrollable-region-focusable`),\n * so `label` makes the host a named, tabbable region: `role=\"region\"` +\n * `aria-label` + `tabindex=\"0\"`, the wrapper pattern GOV.UK and shadcn use\n * around overflowing tables. Leave it off when the content already holds\n * focusable elements (a nav list, a form) — those are reachable by Tab\n * already, and a region tab stop in front of them is one keystroke of noise\n * per list.\n *\n * @param props.color - Theme color for the scrollbar thumb. Accepts a value or\n * reactive state. Defaults to `\"neutral\"`.\n * @param props.label - Accessible name for the scroll region. Setting it makes\n * the host a tabbable `role=\"region\"`. Optional; a host-declared\n * `role`/`ariaLabel`/`tabIndex` still wins (native over patch).\n * @example { div: [...], style: { maxHeight: \"300px\" }, $: [scrollArea()] }\n * @example { div: [wideTable], $: [scrollArea({ label: \"Quarterly revenue\" })] }\n */\nfunction scrollArea(\n props: { color?: ValueOrState<ThemeColor>; label?: string } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n // `role=\"region\"` with no accessible name is dropped from the\n // accessibility tree, and a tab stop with no name is a dead end — so the\n // three only ever ship together, or not at all.\n ...(props.label\n ? { role: \"region\", ariaLabel: props.label, tabIndex: 0 }\n : {}),\n style: {\n overflow: \"auto\",\n // Container text color so theme token usage also carries a reactive `color`.\n color: (l) => themeColor(l, \"text\", color.get(l)),\n \"&::-webkit-scrollbar\": {\n width: themeSpacing(2),\n height: themeSpacing(2),\n },\n \"&::-webkit-scrollbar-track\": {\n background: \"transparent\",\n },\n \"&::-webkit-scrollbar-thumb\": {\n backgroundColor: (l) => themeColor(l, \"shift-5\", color.get(l)),\n borderRadius: themeSpacing(999),\n // Transparent border creates visual padding around the thumb.\n border: `${themeSpacing(0.5)} solid transparent`,\n backgroundClip: \"content-box\",\n },\n \"&::-webkit-scrollbar-thumb:hover\": {\n backgroundColor: (l) => themeColor(l, \"shift-7\", color.get(l)),\n },\n // Firefox thin scrollbar with matching thumb/track colors.\n scrollbarWidth: \"thin\",\n scrollbarColor: (l) =>\n `${themeColor(l, \"shift-5\", color.get(l))} transparent`,\n } as StyleObject,\n };\n}\n\nexport { scrollArea };\n","import {\n behavior,\n type DomphyElement,\n type ElementNode,\n isState,\n type Listener,\n type PartialElement,\n type State,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport {\n type ThemeColor,\n textToneOn,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { horizontalArrowStep } from \"../utils/direction.js\";\nimport { elevation } from \"../utils/elevation.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/** One item inside a segmented control. */\ntype SegmentedItem = {\n /** Button label — plain string (auto-wrapped) or any DomphyElement. */\n label: string | DomphyElement;\n /** Stable key. Defaults to the item's zero-based index. */\n key?: string;\n};\n\ntype SegmentedLive = {\n items: SegmentedItem[];\n color: ThemeColor;\n accentColor: ThemeColor;\n};\n\nfunction persistValue<T>(\n node: ElementNode,\n key: string,\n incoming: ValueOrState<T> | undefined,\n fallback: T,\n): State<T> {\n if (isState(incoming)) {\n node.setMetadata(key, incoming);\n return incoming as State<T>;\n }\n let stored = node.getMetadata(key) as State<T> | undefined;\n if (!stored) {\n stored = toState((incoming as T | undefined) ?? fallback);\n node.setMetadata(key, stored);\n }\n return stored;\n}\n\nfunction moveSegment(\n e: Event,\n items: SegmentedItem[],\n key: string,\n value: State<string>,\n): void {\n const k = (e as KeyboardEvent).key;\n // WAI-ARIA APG radio group: both axes navigate (Right/Down = next,\n // Left/Up = previous), Home/End jump to the ends.\n if (\n ![\n \"ArrowLeft\",\n \"ArrowRight\",\n \"ArrowUp\",\n \"ArrowDown\",\n \"Home\",\n \"End\",\n ].includes(k)\n )\n return;\n e.preventDefault();\n const keys = items.map((item, index) => item.key ?? String(index));\n const idx = keys.indexOf(key);\n let next = idx;\n if (k === \"ArrowDown\") next = (idx + 1) % keys.length;\n else if (k === \"ArrowUp\") next = (idx - 1 + keys.length) % keys.length;\n else if (k === \"ArrowRight\" || k === \"ArrowLeft\") {\n const step = horizontalArrowStep(k, e.target as Element);\n next = (idx + step + keys.length) % keys.length;\n } else if (k === \"Home\") next = 0;\n else if (k === \"End\") next = keys.length - 1;\n value.set(keys[next]);\n const group = (e.target as HTMLElement).closest(\"[role=radiogroup]\");\n group?.querySelectorAll<HTMLElement>(\"[role=radio]\")[next]?.focus();\n}\n\nfunction buildSegmentButtons(\n items: SegmentedItem[],\n value: State<string>,\n color: ThemeColor,\n accentColor: ThemeColor,\n): DomphyElement<\"button\">[] {\n return items.map((item, index) => {\n const key = item.key ?? String(index);\n const labelEl: DomphyElement =\n typeof item.label === \"string\"\n ? ({ span: item.label } as DomphyElement<\"span\">)\n : item.label;\n\n return {\n button: [labelEl],\n _key: key,\n type: \"button\",\n role: \"radio\",\n ariaChecked: (l: Listener) => value.get(l) === key,\n tabIndex: (l: Listener) => {\n const current = value.get(l);\n if (current === key) return 0;\n if (current === \"\" && key === (items[0]?.key ?? \"\")) return 0;\n return -1;\n },\n onClick: () => value.set(key),\n onKeyDown: (e: Event) => moveSegment(e, items, key, value),\n style: {\n cursor: \"pointer\",\n fontSize: (l: Listener) => themeSize(l, \"inherit\"),\n height: themeSpacing(6),\n paddingBlock: themeSpacing(1),\n paddingInline: themeSpacing(3),\n border: \"none\",\n borderRadius: themeSpacing(10),\n color: (l: Listener) => themeColor(l, \"text\", color),\n backgroundColor: \"transparent\",\n transition:\n \"background-color 140ms ease, color 140ms ease, box-shadow 140ms ease\",\n // Labels track their fill (+3 hover, +2 press) off the track's own\n // shift-2 anchor: the resting \"text\" tone measured 3.20:1 on the hover\n // fill and 3.78:1 on the pressed fill (light), below WCAG AA.\n \"&:hover:not([disabled]):not([aria-checked=true])\": {\n backgroundColor: (l: Listener) => themeColor(l, \"shift-3\", color),\n color: (l: Listener) => themeColor(l, textToneOn(3), color),\n },\n \"&:active:not([disabled]):not([aria-checked=true])\": {\n backgroundColor: (l: Listener) => themeColor(l, \"increase-2\", color),\n color: (l: Listener) => themeColor(l, textToneOn(3), color),\n },\n \"&[aria-checked=true]\": {\n backgroundColor: (l: Listener) =>\n themeColor(l, \"shift-0\", accentColor),\n color: (l: Listener) => themeColor(l, \"shift-10\", accentColor),\n // Selected segment sits slightly above the track.\n boxShadow: elevation(\"low\"),\n },\n \"&:focus-visible\": {\n boxShadow: (l: Listener) => focusRing(l, accentColor),\n },\n \"&[aria-checked=true]:focus-visible\": {\n boxShadow: (l: Listener) =>\n `${elevation(\"low\")}, ${focusRing(l, accentColor)}`,\n },\n \"&[disabled]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n },\n },\n } as DomphyElement<\"button\">;\n });\n}\n\n/**\n * All-in-one single-select segmented control. Generates `<button>` option\n * elements from the `items` array. Apply to any wrapper element.\n *\n * @param props.items - Item definitions `{ label, key? }`.\n * @param props.value - Initially selected key (value or State). Defaults to the first item's key.\n * @param props.color - Theme color for the control background. Defaults to `\"neutral\"`.\n * @param props.accentColor - Theme color for the selected item. Defaults to `\"primary\"`.\n * @example\n * { div: null, $: [segmented({ items: [\n * { label: \"Day\", key: \"day\" },\n * { label: \"Month\", key: \"month\" },\n * { label: \"Year\", key: \"year\" },\n * ] })] }\n */\nfunction segmented(\n props: {\n items: SegmentedItem[];\n value?: ValueOrState<string>;\n color?: ThemeColor;\n accentColor?: ThemeColor;\n } = { items: [] },\n): PartialElement {\n const { items = [], color = \"neutral\", accentColor = \"primary\" } = props;\n const live: SegmentedLive = { items, color, accentColor };\n\n return {\n role: \"radiogroup\",\n _onSchedule: (node, element) => {\n const value = persistValue(\n node,\n \"segmentedValue\",\n props.value,\n items[0]?.key ?? \"\",\n );\n // Publish the SAME state the buttons write to. A declared `_context`\n // could not: the partial is node-agnostic, so it had to allocate its\n // own `toState()` that never saw a click — and because ElementNode.patch\n // re-merges `element._context` on every re-render, merging one State\n // instance into another also clobbered the live notifier's listeners.\n node.setContext(\"segmented\", { value });\n (element as Record<string, unknown>)[node.tagName] = buildSegmentButtons(\n items,\n value,\n color,\n accentColor,\n );\n },\n ...behavior<SegmentedLive>(\n \"segmented-items\",\n (node) => ({\n update(snapshot) {\n const value = persistValue(\n node,\n \"segmentedValue\",\n props.value,\n snapshot.items[0]?.key ?? \"\",\n );\n node.children.update(\n buildSegmentButtons(\n snapshot.items,\n value,\n snapshot.color,\n snapshot.accentColor,\n ),\n !!node.domElement,\n true,\n );\n },\n }),\n live,\n ),\n // Track is a soft surface anchor — shift via dataTone, paint with inherit.\n dataTone: \"shift-2\",\n style: {\n display: \"inline-flex\",\n paddingBlock: themeSpacing(1),\n paddingInline: themeSpacing(1),\n gap: themeSpacing(0.5),\n borderRadius: themeSpacing(10),\n backgroundColor: (l: Listener) => themeColor(l, \"inherit\", color),\n color: (l: Listener) => themeColor(l, \"text\", color),\n },\n };\n}\n\nexport { segmented };\nexport type { SegmentedItem };\n","import type { Listener, PartialElement } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeColorToken,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { isRTL } from \"../utils/direction.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * Styles a native `<select>` control: removes the default appearance, applies themed\n * colors, outline, density-scaled padding/radius, a custom chevron background icon, and\n * hover/focus/disabled/optgroup/option states.\n *\n * @hostTag select\n * @param props.color - Theme color tone for text, background and outline. Defaults to `\"neutral\"`.\n * @param props.accentColor - Theme color tone for hover/focus outlines. Defaults to `\"primary\"`.\n * @example { select: [{ option: \"A\" }], $: [select()] }\n */\nfunction select(\n props: { color?: ThemeColor; accentColor?: ThemeColor } = {},\n): PartialElement {\n const { color = \"neutral\", accentColor = \"primary\" } = props;\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"select\") {\n console.warn(`\"select\" primitive patch must use select tag`);\n }\n },\n style: {\n appearance: \"none\",\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n lineHeight: \"inherit\",\n color: (listener) => themeColor(listener, \"text\", color),\n backgroundColor: (listener) => themeColor(listener, \"inherit\", color),\n border: \"none\",\n outlineOffset: \"-1px\",\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", color)}`,\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 1),\n paddingInlineStart: (listener) =>\n themeSpacing(themeDensity(listener) * 3),\n paddingInlineEnd: (listener) => themeSpacing(themeDensity(listener) * 5),\n backgroundImage: (l: Listener) => {\n const svg = `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 10 6\"><path d=\"M1 1l4 4 4-4\" stroke=\"${themeColorToken(l, \"shift-7\")}\" stroke-width=\"1.5\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>`;\n return `url(\"data:image/svg+xml,${encodeURIComponent(svg)}\")`;\n },\n backgroundRepeat: \"no-repeat\",\n // background-position has no logical (\"inline-end\") keyword support in\n // Chrome 88-class embedded browsers, so the physical side is picked at\n // paint time from the resolved CSS `direction` (same technique\n // @domphy/floating's platform.isRTL uses) instead of a fixed \"right\".\n backgroundPosition: (l: Listener) =>\n `${isRTL(l.elementNode?.domElement) ? \"left\" : \"right\"} ${themeSpacing(2)} center`,\n backgroundSize: `${themeSpacing(2.5)} ${themeSpacing(1.5)}`,\n transition: \"outline-color 140ms ease, box-shadow 140ms ease\",\n \"&:not([multiple])\": {\n height: (listener) => themeSpacing(6 + themeDensity(listener) * 2),\n },\n \"&:hover:not([disabled]):not([aria-busy=true])\": {\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"shift-5\", accentColor)}`,\n },\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, accentColor),\n },\n \"& optgroup\": {\n color: (listener) => themeColor(listener, \"shift-11\", color),\n },\n \"& option[disabled]\": {\n color: (listener) => themeColor(listener, \"shift-7\", \"neutral\"),\n },\n \"&[disabled]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n color: (listener) => themeColor(listener, \"muted\", \"neutral\"),\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", \"neutral\")}`,\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-2\", \"neutral\"),\n },\n },\n };\n}\n\nexport { select };\n","import {\n type BehaviorInstance,\n behavior,\n type DomphyElement,\n type ElementNode,\n merge,\n type PartialElement,\n type State,\n type StyleObject,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport type { Placement } from \"@domphy/floating\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { elevation } from \"../utils/elevation.js\";\nimport { createFloating, floatingPanelId } from \"../utils/floating.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\nimport { subscribeOpen } from \"../utils/openState.js\";\nimport { enabledOptionsIn } from \"../utils/optionList.js\";\nimport { tag } from \"./tag.js\";\n\n// Typeahead (Radix Select character-search parity): printable characters\n// accumulate into a buffer that resets after 1s of idle; the buffer is a\n// case-insensitive prefix match against option labels. CLOSED trigger: the\n// match becomes the selection (native <select> behavior). OPEN panel: focus\n// moves to the matching [role=option] — focus is the keyboard highlight.\n// A buffer of one repeated character (\"aaa\") cycles through that char's\n// matches instead of pinning the first; disabled options are skipped.\nconst TYPEAHEAD_RESET_MS = 1000;\n\ntype TypeaheadMeta = {\n buffer: string;\n timer: ReturnType<typeof setTimeout> | null;\n};\n\n// The buffer lives on the NODE (not the factory closure): a selectBox inside\n// a reactive parent gets a fresh closure per ancestor re-render, and a\n// closure-local buffer would silently reset mid-typing on the reused node.\nfunction resolveTypeahead(node: ElementNode): TypeaheadMeta {\n let meta = node.getMetadata(\"selectBoxTypeahead\") as\n | TypeaheadMeta\n | undefined;\n if (!meta) {\n meta = { buffer: \"\", timer: null };\n node.setMetadata(\"selectBoxTypeahead\", meta);\n }\n return meta;\n}\n\nconst matchesPrefix = (label: string, needle: string) =>\n label.trim().toLowerCase().startsWith(needle);\n\n/**\n * A clickable select trigger box that renders the currently selected option(s) as removable\n * tags and toggles a floating popover (the dropdown content) anchored to itself. Selected\n * labels are derived from `options` matching the bound `value`; removing a tag updates the value.\n * Keyboard: Enter/Space toggle, ArrowDown/ArrowUp/Home/End open the listbox and move focus to\n * the first/last option (and move between options while open), Escape closes, and printable\n * characters typeahead-search options (closed: selects the match; open: focuses the matching\n * `[role=option]` in the panel; a repeated character cycles matches).\n *\n * @hostTag div\n * @param props.multiple - Whether multiple selection is allowed (renders removable tags and\n * keeps the popover open on click). Defaults to `false`.\n * @param props.value - Bound selection value(s). Accepts a value or reactive state of an array of\n * `number | string | null | undefined`, or a single `number | string | null | undefined`.\n * @param props.options - List of `{ label, value }` options used to resolve selected labels.\n * Defaults to `[]`.\n * @param props.placement - Floating placement of the dropdown popover. Accepts a value or\n * reactive state. Defaults to `\"bottom\"`.\n * @param props.content - Required. The popover/dropdown content element shown when open.\n * @param props.color - Theme color tone for the box text/background. Defaults to `\"neutral\"`.\n * @param props.open - Whether the popover is open. Accepts a value or reactive state (`ValueOrState<boolean>`, including `Computed`/`ReadableState`). Defaults to `false`. When the source is read-only, pass `onDismiss` so dismiss can close.\n * @param props.onDismiss - Called when the popover requests close. Optional. Required to close when `open` is a read-only `Computed`/`ReadableState`.\n * @example { div: null, $: [selectBox({ content: { div: [...] }, options: [{ label: \"A\", value: \"a\" }] })] }\n */\nfunction selectBox(props: {\n multiple?: boolean;\n value?: ValueOrState<\n | Array<number | string | null | undefined>\n | number\n | string\n | null\n | undefined\n >;\n options?: Array<{ label: string; value: string }>;\n placement?: ValueOrState<Placement>;\n content: DomphyElement;\n color?: ThemeColor;\n open?: ValueOrState<boolean>;\n onDismiss?: () => void;\n}): PartialElement {\n const {\n options = [],\n placement = \"bottom\",\n color = \"neutral\",\n open = false,\n multiple = false,\n } = props;\n\n const state = toState(props.value);\n const openState = toState(open);\n const { show, hide, anchorPartial } = createFloating({\n kind: \"selectBox\",\n open: openState,\n onDismiss: props.onDismiss,\n placement: toState(placement),\n content: props.content,\n });\n\n const popoverPartial: PartialElement = {\n onClick: (_e, node) => !multiple && hide(node),\n dataTone: \"shift-0\",\n style: {\n backgroundColor: (listener) => themeColor(listener, \"inherit\"),\n // Surface contract (dataTone-surface-contract): a tone-anchored panel\n // must declare BOTH background and text color. Page-matching shift-0\n // (same as menu/selectList/dialog), not the inverted tooltip surface.\n color: (listener) => themeColor(listener, \"text\"),\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 2),\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\")}`,\n outlineOffset: \"-1px\",\n boxShadow: elevation(\"medium\"),\n },\n };\n\n merge(props.content, popoverPartial);\n\n type InnerProps = {\n options: Array<{ label: string; value: string }>;\n multiple: boolean;\n color: ThemeColor;\n state: State<\n | Array<number | string | null | undefined>\n | number\n | string\n | null\n | undefined\n >;\n };\n\n const buildWrap = (inner: InnerProps): DomphyElement<\"div\"> => ({\n div: (listener) => {\n const val = inner.state.get(listener);\n const vals = Array.isArray(val) ? val : [val];\n const opts = inner.options.filter((opt) => vals.includes(opt.value));\n return opts.map((opt) => ({\n span: opt.label,\n $: [tag({ color: inner.color, removable: inner.multiple })],\n _key: opt.value,\n _onRemove: (_node: ElementNode) => {\n const cur = inner.state.get();\n const curVals = Array.isArray(cur) ? cur : [cur];\n const filter = curVals.filter((v) => v !== opt.value);\n inner.multiple\n ? inner.state.set(filter as any)\n : inner.state.set(filter[0] as any);\n },\n })) as DomphyElement<\"span\">[];\n },\n _key: \"selectBoxWrap\",\n style: {\n display: \"flex\",\n flexWrap: \"wrap\",\n gap: themeSpacing(1),\n flex: 1,\n } as StyleObject,\n });\n\n const attachInner = (\n node: ElementNode,\n _inner: InnerProps,\n ): BehaviorInstance<InnerProps> => {\n return {\n update(next) {\n node.children.update([buildWrap(next)]);\n },\n };\n };\n\n const toggle = (node?: ElementNode) =>\n openState.get() ? hide(node) : show(node);\n\n const panelOf = (node: ElementNode): Element | null => {\n const root = node.getRoot().domElement as Element | null;\n return (\n root?.querySelector(`#${floatingPanelId(\"selectBox\", node)}`) ?? null\n );\n };\n\n // WAI-ARIA APG \"Select-Only Combobox\": Down/Up/Home/End move focus into the\n // listbox. Measured in Chromium before this: with the panel open, every\n // arrow key was swallowed by the typeahead branch's `key.length === 1`\n // guard and focus never left the trigger, so the dropdown was reachable\n // only by mouse or by guessing an option's first letter. Once focus is on\n // an option, selectList's own listbox handler takes over.\n const moveIntoPanel = (node: ElementNode, toLast: boolean): void => {\n const options = enabledOptionsIn(panelOf(node));\n if (!options.length) return;\n const target = options[toLast ? options.length - 1 : 0]!;\n target.focus();\n target.scrollIntoView?.({ block: \"nearest\" });\n };\n\n // show() is debounced by 100ms and flips `openState` only AFTER mounting the\n // panel, so waiting on that flip is exact where a fixed delay is not. The\n // extra frame is required too: floating.ts drives the panel's `visibility`\n // from the same state and that style write has not landed when the listener\n // runs, so `focus()` would hit a `visibility: hidden` element and do nothing.\n const openThenMove = (node: ElementNode, toLast: boolean): void => {\n let release: (() => void) | undefined;\n release = subscribeOpen(\n openState,\n (isOpen) => {\n if (!isOpen) return;\n release?.();\n requestAnimationFrame(() => moveIntoPanel(node, toLast));\n },\n false,\n );\n show(node);\n };\n\n const typeahead = (key: string, node: ElementNode) => {\n const meta = resolveTypeahead(node);\n if (meta.timer) clearTimeout(meta.timer);\n meta.buffer += key.toLowerCase();\n meta.timer = setTimeout(() => {\n meta.buffer = \"\";\n }, TYPEAHEAD_RESET_MS);\n // \"aaa\" cycles through the a* matches rather than matching \"aaa\" literally.\n const repeated = meta.buffer.length > 1 && new Set(meta.buffer).size === 1;\n const needle = repeated ? meta.buffer[0]! : meta.buffer;\n\n if (openState.get()) {\n // Panel is portaled under the root (see floating.ts); its id is\n // deterministic, same lookup pattern as popover's onBlur guard.\n const matches = enabledOptionsIn(panelOf(node)).filter((el) =>\n matchesPrefix(el.textContent ?? \"\", needle),\n );\n if (!matches.length) return;\n const active = node.domElement?.ownerDocument\n ?.activeElement as HTMLElement | null;\n const from = repeated && active ? matches.indexOf(active) : -1;\n const target = matches[(from + 1) % matches.length]!;\n target.focus();\n target.scrollIntoView?.({ block: \"nearest\" });\n return;\n }\n\n // Closed trigger: selection follows typeahead. Single-select only — a\n // multi-select tag set has no \"current option\" to move from.\n if (multiple) return;\n const matches = options.filter((opt) => matchesPrefix(opt.label, needle));\n if (!matches.length) return;\n const from = repeated\n ? matches.findIndex((opt) => opt.value === state.get())\n : -1;\n const next = matches[(from + 1) % matches.length]!;\n state.set(next.value as any);\n };\n\n const partial: PartialElement = {\n _onInsert: (node) => {\n if (node.tagName !== \"div\") {\n console.warn(`\"selectBox\" patch must use div tag`);\n }\n },\n _onSchedule: (node, element) => {\n (element as Record<string, unknown>)[node.tagName] = [\n buildWrap({ options, multiple, color, state }),\n ];\n },\n ...behavior<InnerProps>(\"selectBoxInner\", attachInner, {\n options,\n multiple,\n color,\n state,\n }),\n onClick: (_e, node) => toggle(node),\n // Focusable trigger: click + Enter/Space/ArrowDown open.\n // Escape dismiss composes with createFloating's hide path.\n tabindex: 0,\n // WAI-ARIA APG \"Select-Only Combobox\": a non-editable div trigger that\n // owns a listbox is role=combobox, not role=button. role=button also makes\n // its subtree presentational, which broke the removable `tag()` buttons the\n // multi-select trigger renders (axe `nested-interactive`).\n role: \"combobox\",\n // role=combobox takes its name from the author only — never from its\n // content the way role=button did — so without a default every selectBox\n // failed axe `aria-input-field-name`. A host-declared aria-label/\n // aria-labelledby still wins (native over patch).\n ariaLabel: \"Select\",\n // Reactive boolean (same pattern as popover) — do NOT pin a static\n // ariaExpanded or patch re-apply will overwrite after keyboard open.\n ariaExpanded: (listener) => openState.get(listener),\n ariaHaspopup: \"listbox\",\n ariaControls: (listener) =>\n listener?.elementNode\n ? floatingPanelId(\"selectBox\", listener.elementNode)\n : undefined,\n onKeyDown: (e, node) => {\n const key = (e as KeyboardEvent).key;\n if (key === \"Escape\") {\n hide(node);\n return;\n }\n if (key === \"Enter\" || key === \" \") {\n e.preventDefault();\n toggle(node);\n return;\n }\n if (\n key === \"ArrowDown\" ||\n key === \"ArrowUp\" ||\n key === \"Home\" ||\n key === \"End\"\n ) {\n e.preventDefault();\n const toLast = key === \"ArrowUp\" || key === \"End\";\n openState.get()\n ? moveIntoPanel(node, toLast)\n : openThenMove(node, toLast);\n return;\n }\n // Character typeahead (Radix Select parity) — modifier chords are\n // shortcuts, not search input.\n const kb = e as KeyboardEvent;\n if (key.length === 1 && !kb.ctrlKey && !kb.metaKey && !kb.altKey) {\n typeahead(key, node);\n }\n },\n style: {\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n minHeight: (listener) => themeSpacing(6 + themeDensity(listener) * 2),\n minWidth: themeSpacing(32),\n outlineOffset: \"-1px\",\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", \"neutral\")}`,\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 2),\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n color: (listener) => themeColor(listener, \"text\", color),\n backgroundColor: (listener) => themeColor(listener, \"inherit\", color),\n transition:\n \"background-color 140ms ease, outline-color 140ms ease, box-shadow 140ms ease\",\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, color),\n },\n },\n };\n\n merge(anchorPartial, partial);\n return anchorPartial;\n}\n\nexport { selectBox };\n","import type { PartialElement } from \"@domphy/core\";\nimport {\n type ThemeColor,\n textToneOn,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * A single selectable option row (`role=\"option\"`) for use inside a `selectList`. Reads the\n * `select` context to reflect/toggle selection: it sets `aria-selected` from the bound value and\n * toggles the value (single or multiple) on click. Styles hover/selected/focus states.\n *\n * @hostTag div\n * @param props.accentColor - Theme color tone for the selected/focus state. Defaults to `\"primary\"`.\n * @param props.color - Theme color tone for text/background. Defaults to `\"neutral\"`.\n * @param props.value - The option value compared against and written to the select state.\n * Defaults to `null`.\n * @example { div: \"Option A\", $: [selectItem({ value: \"a\" })] }\n */\nfunction selectItem(\n props: {\n accentColor?: ThemeColor;\n color?: ThemeColor;\n value?: number | string;\n } = {},\n): PartialElement {\n const { accentColor = \"primary\", color = \"neutral\", value = null } = props;\n\n const partial: PartialElement = {\n role: \"option\",\n // Programmatically focusable (not tabbable): selectBox typeahead and\n // keyboard navigation move focus between options roving-style.\n tabindex: -1,\n // aria-selected and the click toggler must be DECLARED on the partial, not\n // wired imperatively in _onInit: hooks run once per real DOM node, but\n // patch() resets _events and strips undeclared attributes on every\n // ancestor re-render — so imperative wiring was lost on the first reuse\n // while the (once-run) hook never re-installed it. The reactive reader\n // resolves the `select` context lazily through listener.elementNode, so\n // every generation re-binds to whatever context is actually live.\n ariaSelected: (listener) => {\n const select = listener?.elementNode?.getContext(\"select\");\n if (!select) return undefined;\n const val = select.value.get(listener);\n return select.multiple ? val.includes(value) : val === value;\n },\n onClick: (_e, node) => {\n const select = node.getContext(\"select\");\n if (!select) return;\n const state = select.value;\n const val = state.get();\n if (select.multiple) {\n val.includes(value)\n ? state.set(val.filter((v: number | string) => v !== value))\n : state.set(val.concat([value]));\n } else {\n val !== value && state.set(value);\n }\n },\n _onInit: (node) => {\n if (node.tagName !== \"div\") {\n console.warn(`\"selectItem\" patch must use div tag`);\n }\n },\n style: {\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n height: (listener) => themeSpacing(6 + themeDensity(listener) * 2),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 3),\n border: \"none\",\n outline: \"none\",\n color: (listener) => themeColor(listener, \"text\", color),\n backgroundColor: (listener) => themeColor(listener, \"inherit\", color),\n // Label tracks the hover fill (+2): a fixed \"text\" label measured\n // 3.58:1 against it (light) / 4.37:1 (dark), below WCAG AA.\n \"&:hover:not([disabled]):not([aria-selected=true])\": {\n backgroundColor: (listener) => themeColor(listener, \"hover\", color),\n color: (listener) => themeColor(listener, textToneOn(2), color),\n },\n // Selected row uses the same fill/text pairing as button({variant:\"solid\"}):\n // deep brand fill + light-end neutral text. The old shift-6 / shift-11\n // pairing measured ~2.6:1 in Chromium (axe `color-contrast`), below the\n // WCAG AA 4.5:1 floor for the label of the CHOSEN option.\n \"&[aria-selected=true]\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-13\", accentColor),\n color: (listener) => themeColor(listener, \"shift-0\", \"neutral\"),\n },\n transition: \"background-color 140ms ease, box-shadow 140ms ease\",\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, accentColor),\n },\n },\n };\n return partial;\n}\n\nexport { selectItem };\n","import {\n type DomphyElement,\n type ElementNode,\n type PartialElement,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { enabledOptionsIn } from \"../utils/optionList.js\";\n\n// WAI-ARIA APG Listbox keyboard model: Down/Up move to the next/previous\n// option, Home/End to the first/last, Enter/Space choose the focused option.\n// Focus IS the highlight here (options carry tabindex=-1), matching the\n// selectBox typeahead which already moves focus between options.\nfunction onListboxKey(event: Event, node: ElementNode): void {\n const key = (event as KeyboardEvent).key;\n const host = node.domElement as HTMLElement | null;\n if (!host) return;\n const options = enabledOptionsIn(host);\n if (!options.length) return;\n const active = host.ownerDocument.activeElement as HTMLElement | null;\n const current = active ? options.indexOf(active) : -1;\n\n if (key === \"Enter\" || key === \" \") {\n if (current === -1) return;\n event.preventDefault();\n options[current]!.click();\n return;\n }\n\n let next: number;\n if (key === \"ArrowDown\") next = Math.min(options.length - 1, current + 1);\n else if (key === \"ArrowUp\") next = current <= 0 ? 0 : current - 1;\n else if (key === \"Home\") next = 0;\n else if (key === \"End\") next = options.length - 1;\n else return;\n\n event.preventDefault();\n const target = options[next]!;\n target.focus();\n target.scrollIntoView?.({ block: \"nearest\" });\n}\n\n/**\n * Container for a list of `selectItem`s that owns the selection state. It exposes a `select`\n * context (`{ value, multiple }`) consumed by child items, and injects hidden `<input>`(s)\n * carrying the selected value(s) under `name` for form submission.\n *\n * @hostTag div\n * @param props.multiple - Whether multiple selection is allowed; also sets the default empty\n * value (`[]` vs `null`). Defaults to `false`.\n * @param props.value - Bound selection value(s). Accepts a value or reactive state of an array of\n * `number | string | null`, or a single `number | string | null`. Defaults to `[]` when\n * `multiple`, otherwise `null`.\n * @param props.color - Theme color tone for the background. Defaults to `\"neutral\"`.\n * @param props.name - Name attribute for the hidden inputs (form field name).\n * @example { div: [{ div: \"A\", $: [selectItem({ value: \"a\" })] }], $: [selectList({ name: \"pick\" })] }\n */\nfunction selectList(\n props: {\n multiple?: boolean;\n value?: ValueOrState<\n Array<number | string | null> | number | string | null\n >;\n color?: ThemeColor;\n name?: string;\n } = {},\n): PartialElement {\n const { color = \"neutral\", multiple = false } = props;\n const state = toState(props.value ?? (multiple ? [] : null));\n\n // type=hidden form fields (not a visible input) — avoid axe label/listbox noise.\n const inputs: DomphyElement<\"div\"> = {\n div: (listener) => {\n const val = state.get(listener);\n const vals = Array.isArray(val) ? val : [val];\n return vals.map((v) => ({\n input: null,\n type: \"hidden\",\n name: props.name,\n // Preserve a legitimate numeric 0 (and other falsy-but-valid values);\n // `v || \"\"` would drop them.\n value: v == null ? \"\" : String(v),\n }));\n },\n // Keep out of the a11y tree; listbox children must be options.\n ariaHidden: \"true\",\n hidden: true,\n };\n\n const partial: PartialElement = {\n dataTone: \"shift-0\",\n // selectItem uses role=option; options require a listbox parent (WAI-ARIA).\n role: \"listbox\",\n ariaLabel: \"Options\",\n ariaMultiselectable: multiple ? \"true\" : undefined,\n // Without a tab stop the whole listbox was keyboard-unreachable: its\n // options are tabindex=-1 by design (roving focus), so Tab skipped the\n // entire widget. APG's listbox example puts tabindex=0 on the container.\n tabindex: 0,\n onKeyDown: onListboxKey,\n // Published from _onSchedule (runs once per node), NOT as a declared\n // `_context`: ElementNode.patch re-merges `element._context` on every\n // re-render, and merging a freshly-built State into the live one\n // overwrote its value and its notifier's listeners — an uncontrolled\n // selection silently snapped back to the initial value whenever a\n // reactive ancestor re-rendered. Same fix as segmented/toggleGroup.\n _onSchedule: (node) => {\n node.setContext(\"select\", { value: state, multiple });\n },\n _onInit: (node) => {\n if (node.tagName !== \"div\") {\n console.warn(`\"selectList\" patch must use a div tag`);\n }\n node.children.insert(inputs);\n },\n style: {\n display: \"flex\",\n flexDirection: \"column\",\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 2),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 2),\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n backgroundColor: (listener) => themeColor(listener, \"inherit\", color),\n color: (listener) => themeColor(listener, \"text\", color),\n },\n };\n return partial;\n}\n\nexport { selectList };\n","import {\n hashString,\n type PartialElement,\n type StyleObject,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * A loading placeholder block with a left-to-right shimmer gradient. Marked\n * `aria-hidden`, themed background/foreground, fixed height, slight rounding.\n * No host-tag check; typically applied to a block-level element such as a\n * `div` or `span`.\n *\n * @param props.color - Theme color tone for the placeholder. Accepts a value or reactive state.\n * Defaults to `\"neutral\"`.\n * @example { div: null, $: [skeleton()] }\n */\nfunction skeleton(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n // Shimmer sweeps left→right over a near-white base (reads as loading, not\n // a flat opacity blink). Base + highlight are both theme tokens so the\n // effect adapts to light/dark surfaces. Highlight stays close to the base\n // (shift-2) — a deeper step reads as dirty banding on light themes.\n const keyframes = {\n \"0%\": { backgroundPosition: \"200% 0\" },\n \"100%\": { backgroundPosition: \"-200% 0\" },\n };\n const animationName = hashString(JSON.stringify(keyframes));\n return {\n ariaHidden: \"true\",\n dataTone: \"shift-1\",\n style: {\n fontSize: (listener) => themeSize(listener),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n height: themeSpacing(6),\n display: \"block\",\n borderRadius: themeSpacing(1),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n backgroundImage: (listener) =>\n `linear-gradient(90deg, ${themeColor(listener, \"inherit\", color.get(listener))} 0%, ${themeColor(listener, \"shift-2\", color.get(listener))} 50%, ${themeColor(listener, \"inherit\", color.get(listener))} 100%)`,\n backgroundSize: \"200% 100%\",\n animation: `${animationName} 1.6s ease-in-out infinite`,\n [`@keyframes ${animationName}`]: keyframes,\n } as StyleObject,\n };\n}\n\nexport { skeleton };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport { type ThemeColor, themeColor, themeSize } from \"@domphy/theme\";\n\n/**\n * Styles small/secondary text: one step smaller font size (`data-size=\"decrease-1\"`) with a\n * themed foreground color.\n *\n * The tone is `shift-10`, one step ABOVE the `\"text\"` floor, because this text renders below\n * the WCAG large-text threshold and so must always clear 4.5:1. Measured in Chromium on the\n * built bundle: 6.01–7.73:1 (light) and 6.33–7.73:1 (dark) on every edge-anchored surface.\n * Three things at the CALL SITE forfeit that guarantee, all measured in Chromium:\n * 1. A host-declared `style.color` wins over the patch (native beats patch) — `\"text\"` /\n * `shift-9` on a `shift-1` surface is 4.23:1. Pass `color` for a different family\n * instead of restyling.\n * 2. An ancestor's scoped `\"& small\": { color: … }` also wins: that descendant selector is\n * specificity (0,1,1) and this patch's own generated class is only (0,1,0). Measured\n * inside a correctly tone-anchored `dataTone: \"shift-1\"` card, with no inline style on\n * the `<small>` at all: `& small { color: themeColor(l, \"shift-8\") }` resolves to\n * `var(--neutral-9)` = #707070 on the card's #ededed = 4.23:1 (6.27:1 once the `color`\n * line is dropped). The specificity is deliberately NOT escalated here — a patch that\n * outranked descendant rules would leave an author no way to restyle short of\n * `!important`. Scope layout there (`display: block`) and leave the colour to the patch.\n * 3. A surface tinted with a fixed `themeColor(l, \"shift-N\")` background and no `dataTone`:\n * every child still resolves against the page root, and even `shift-10` drops to 4.34:1\n * (shift-2 tint) and 3.67:1 (shift-3). Shift the surface with `dataTone` + `\"inherit\"`\n * instead — `@domphy/doctor`'s `tone-background-inherit` rule flags exactly this.\n *\n * @hostTag small\n * @param props.color - Theme color tone for the text. Accepts a value or reactive state.\n * Defaults to `\"neutral\"`.\n * @example { small: \"fine print\", $: [small()] }\n */\nfunction small(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"small\") {\n console.warn('\"small\" patch must use small tag');\n }\n },\n dataSize: \"decrease-1\",\n style: {\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n // shift-10 (not muted/shift-8) keeps WCAG AA ≥4.5:1 on light surfaces for small type.\n color: (listener) =>\n themeColor(listener, \"shift-10\", color.get(listener)),\n },\n };\n}\n\nexport { small };\n","import type { PartialElement, StyleObject } from \"@domphy/core\";\nimport { hashString, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\nconst keyframes = { to: { transform: \"rotate(360deg)\" } };\nconst animationName = hashString(JSON.stringify(keyframes));\n\n/**\n * A circular loading spinner: a themed ring with a contrasting top border that rotates\n * continuously. Marked `role=\"status\"` with `aria-label=\"loading\"`.\n *\n * @hostTag span\n * @param props.color - Theme color tone for the ring/highlight. Accepts a value or reactive\n * state. Defaults to `\"neutral\"`.\n * @example { span: null, $: [spinner()] }\n */\nfunction spinner(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n role: \"status\",\n ariaLabel: \"loading\",\n _onInsert: (node) => {\n if (node.tagName !== \"span\") {\n console.warn(`\"spinner\" patch must use span tag`);\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener),\n backgroundColor: (listener) => themeColor(listener),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n display: \"inline-block\",\n margin: 0,\n flexShrink: 0,\n width: themeSpacing(6),\n height: themeSpacing(6),\n borderRadius: \"50%\",\n border: (listener) =>\n `${themeSpacing(0.5)} solid ${themeColor(listener, \"border-strong\", color.get(listener))}`,\n borderTopColor: (listener) =>\n themeColor(listener, \"shift-9\", color.get(listener)),\n boxSizing: \"border-box\",\n padding: 0,\n animation: `${animationName} 0.7s linear infinite`,\n [`@keyframes ${animationName}`]: keyframes,\n } as StyleObject,\n };\n}\n\nexport { spinner };\n","import { ElementNode, merge, type PartialElement, toState } from \"@domphy/core\";\nimport { themeColor, themeSpacing } from \"@domphy/theme\";\nimport { horizontalArrowStep } from \"../utils/direction.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * Root of a resizable split layout. Lays out children as a flex row (horizontal) or column\n * (vertical) and provides a `splitter` context (`{ direction, size, min, max }`) consumed by\n * `splitterPanel` and `splitterHandle`. `size` is a reactive state holding the first panel's\n * percentage. No host-tag check; typically applied to a `div`.\n *\n * @param props.direction - Split orientation, `\"horizontal\"` | `\"vertical\"`. Defaults to `\"horizontal\"`.\n * @param props.defaultSize - Initial size (percentage) of the resizable panel. Defaults to `50`.\n * @param props.min - Minimum panel size (percentage). Defaults to `10`.\n * @param props.max - Maximum panel size (percentage). Defaults to `90`.\n * @example { div: [...], $: [splitter({ direction: \"vertical\" })] }\n */\nfunction splitter(\n props: {\n direction?: \"horizontal\" | \"vertical\";\n defaultSize?: number;\n min?: number;\n max?: number;\n } = {},\n): PartialElement {\n const {\n direction = \"horizontal\",\n defaultSize = 50,\n min = 10,\n max = 90,\n } = props;\n return {\n _onSchedule: (_node, element) => {\n merge(element, {\n _context: {\n splitter: {\n direction,\n size: toState(defaultSize),\n min,\n max,\n // Legacy bookkeeping kept on the context object for compatibility.\n // First-vs-second assignment uses sibling order (see splitterPanel).\n panelCount: 0,\n },\n },\n });\n },\n style: {\n display: \"flex\",\n flexDirection: direction === \"horizontal\" ? \"row\" : \"column\",\n overflow: \"hidden\",\n },\n };\n}\n\n/**\n * The resizable panel inside a `splitter`. Reads the `splitter` context and binds its\n * width (horizontal) or height (vertical) to the context `size` state, updating reactively as\n * the handle is dragged. Intended for exactly two panels either side of one `splitterHandle`:\n * the first `splitterPanel` mounted takes `size`%, and the second takes the complementary\n * `100 - size`% — so the pair always sums to the full width/height instead of both tracking\n * the same number (which would make them grow and shrink together instead of trading space).\n * Warns if used outside a `splitter`. Takes no props.\n *\n * @example { div: [...], $: [splitterPanel()] }\n */\nfunction isFirstSplitterPanel(node: ElementNode): boolean {\n const parent = node.parent;\n if (!parent) return true;\n for (const item of parent.children.items) {\n if (item instanceof ElementNode && item.getMetadata(\"splitterPanel\")) {\n return item === node;\n }\n }\n return true;\n}\n\nfunction splitterPanel(): PartialElement {\n return {\n _metadata: { splitterPanel: true },\n _onMount: (node) => {\n const ctx = node.getContext(\"splitter\");\n if (!ctx) {\n console.warn(`\"splitterPanel\" patch must be used inside a \"splitter\"`);\n return;\n }\n const el = node.domElement as HTMLElement;\n const prop = ctx.direction === \"horizontal\" ? \"width\" : \"height\";\n\n const apply = (size: number) => {\n el.style[prop] = `${isFirstSplitterPanel(node) ? size : 100 - size}%`;\n };\n apply(ctx.size.get());\n el.style.flexShrink = \"0\";\n el.style.overflow = \"auto\";\n\n const release = ctx.size.addListener(apply);\n node.addHook(\"Remove\", () => {\n ctx.panelCount = Math.max(0, (ctx.panelCount ?? 1) - 1);\n release();\n });\n },\n };\n}\n\n/**\n * The draggable divider inside a `splitter`. Reads the `splitter` context, shows the\n * appropriate resize cursor, and updates the context `size` state (clamped to `min`/`max`)\n * via mouse drag or keyboard: Arrow keys move by 1%, Home/End jump to min/max, hold Shift\n * for 10× step. Sets `role=\"separator\"`, `tabindex=\"0\"`, and `aria-value*` attributes.\n * Warns if used outside a `splitter`. Drag works with mouse, pen and touch\n * (Pointer Events).\n *\n * @param props.label - Accessible name for the separator (WCAG 4.1.2 — a\n * focusable `role=\"separator\"` with `aria-value*` is a widget and needs a\n * name). Defaults to `\"Resize\"`. A native `ariaLabel`/`ariaLabelledby` on\n * the host element wins.\n * @example { div: null, $: [splitterHandle()] }\n */\nfunction splitterHandle(props: { label?: string } = {}): PartialElement {\n const { label = \"Resize\" } = props;\n return {\n role: \"separator\",\n tabindex: 0,\n ariaLabel: label,\n _onMount: (node) => {\n const ctx = node.getContext(\"splitter\");\n if (!ctx) {\n console.warn(`\"splitterHandle\" patch must be used inside a \"splitter\"`);\n return;\n }\n const handle = node.domElement as HTMLElement;\n const isHorizontal = ctx.direction === \"horizontal\";\n\n handle.style.cursor = isHorizontal ? \"col-resize\" : \"row-resize\";\n handle.setAttribute(\n \"aria-orientation\",\n isHorizontal ? \"vertical\" : \"horizontal\",\n );\n handle.setAttribute(\"aria-valuemin\", String(ctx.min));\n handle.setAttribute(\"aria-valuemax\", String(ctx.max));\n handle.setAttribute(\"aria-valuenow\", String(Math.round(ctx.size.get())));\n\n const releaseAriaValue = ctx.size.addListener((size: number) => {\n handle.setAttribute(\"aria-valuenow\", String(Math.round(size)));\n });\n\n const onKeydown = (e: KeyboardEvent) => {\n const step = e.shiftKey ? 10 : 1;\n let next: number | null = null;\n if (isHorizontal) {\n // Move the divider toward the physically-pressed arrow: the\n // first panel's share grows when that moves the divider right in\n // LTR, or left in RTL (both panels are laid out with `flexDirection:\n // row`, which itself flips source order under RTL).\n const dir = horizontalArrowStep(e.key, handle);\n if (dir !== 0)\n next = Math.min(\n Math.max(ctx.size.get() + dir * step, ctx.min),\n ctx.max,\n );\n } else {\n if (e.key === \"ArrowDown\")\n next = Math.min(ctx.size.get() + step, ctx.max);\n else if (e.key === \"ArrowUp\")\n next = Math.max(ctx.size.get() - step, ctx.min);\n }\n if (e.key === \"Home\") next = ctx.min;\n else if (e.key === \"End\") next = ctx.max;\n if (next !== null) {\n e.preventDefault();\n ctx.size.set(next);\n }\n };\n\n let cancelDrag: (() => void) | null = null;\n\n // Pointer Events, not mouse events: a touch drag never fires\n // mousemove/mouseup, so the handle was mouse-and-pen only — every peer\n // resizable splitter (react-resizable-panels, MUI, Mantine) drags on\n // touch. `touch-action: none` (set in the style block) is required or\n // the browser claims the gesture for scrolling and fires pointercancel.\n const onPointerdown = (e: PointerEvent) => {\n e.preventDefault();\n const container = handle.parentElement!;\n handle.setPointerCapture?.(e.pointerId);\n\n const onPointermove = (move: PointerEvent) => {\n if (move.pointerId !== e.pointerId) return;\n const rect = container.getBoundingClientRect();\n const raw = isHorizontal\n ? ((move.clientX - rect.left) / rect.width) * 100\n : ((move.clientY - rect.top) / rect.height) * 100;\n ctx.size.set(Math.min(Math.max(raw, ctx.min), ctx.max));\n };\n\n cancelDrag = () => {\n document.removeEventListener(\"pointermove\", onPointermove);\n document.removeEventListener(\"pointerup\", onPointerup);\n document.removeEventListener(\"pointercancel\", onPointerup);\n cancelDrag = null;\n // releasePointerCapture throws NotFoundError once the pointer is no\n // longer active — which is exactly the pointercancel path. Ask\n // first, and only after the listeners are already detached so a\n // throw could not leak them or strand `cancelDrag`.\n if (handle.hasPointerCapture?.(e.pointerId))\n handle.releasePointerCapture(e.pointerId);\n };\n\n function onPointerup(up: PointerEvent) {\n if (up.pointerId !== e.pointerId) return;\n cancelDrag?.();\n }\n\n document.addEventListener(\"pointermove\", onPointermove);\n document.addEventListener(\"pointerup\", onPointerup);\n document.addEventListener(\"pointercancel\", onPointerup);\n };\n\n handle.addEventListener(\"keydown\", onKeydown);\n handle.addEventListener(\"pointerdown\", onPointerdown);\n node.addHook(\"Remove\", () => {\n cancelDrag?.();\n releaseAriaValue();\n handle.removeEventListener(\"keydown\", onKeydown);\n handle.removeEventListener(\"pointerdown\", onPointerdown);\n });\n },\n // Soft divider surface — shift via dataTone, paint with inherit.\n dataTone: \"shift-2\",\n style: {\n flexShrink: 0,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n // Hand the drag gesture to the pointer handler instead of the browser's\n // scroller — without this a touch drag is swallowed by panning.\n touchAction: \"none\",\n backgroundColor: (listener) => themeColor(listener, \"inherit\"),\n color: (listener) => themeColor(listener, \"text\"),\n \"&:hover\": {\n backgroundColor: (listener) => themeColor(listener, \"increase-1\"),\n },\n transition: \"background-color 140ms ease, box-shadow 140ms ease\",\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, \"primary\"),\n },\n \"&::after\": {\n content: '\"\"',\n // A small grip dot so the handle is visibly draggable. Without an\n // explicit size the pseudo-element collapses to 0x0 and is invisible.\n width: themeSpacing(1),\n height: themeSpacing(1),\n borderRadius: themeSpacing(999),\n backgroundColor: (listener) => themeColor(listener, \"shift-4\"),\n },\n },\n };\n}\n\nexport { splitter, splitterPanel, splitterHandle };\n","import type { PartialElement } from \"@domphy/core\";\nimport { themeDensity, themeSpacing } from \"@domphy/theme\";\n\ntype FlexAlign = \"flex-start\" | \"center\" | \"flex-end\" | \"stretch\" | \"baseline\";\n\ntype FlexJustify =\n | \"flex-start\"\n | \"center\"\n | \"flex-end\"\n | \"space-between\"\n | \"space-around\"\n | \"space-evenly\";\n\n/**\n * A vertical flex column with spacing between children. The general-purpose\n * primitive for stacking blocks — form sections, panel content, card bodies —\n * instead of hand-rolling `display: flex; flexDirection: column; gap: ...`.\n * Styles the host only; apply to any block element.\n *\n * @param props.gap - Spacing multiplier for gap between children (default 3).\n * Bounded-control mode (`density: true`, default): `themeSpacing(themeDensity(l) * gap)`\n * — at default density 1.5, gap 3 = 1.125em.\n * Structural/page-column mode (`density: false`): bare `themeSpacing(gap)` with no\n * density multiply — gap 3 = 0.75em, matching AGENTS.md \"bare themeSpacing(n)\".\n * @param props.align - Cross-axis alignment (`alignItems`). Unset by default (flex default, stretch).\n * @param props.justify - Main-axis distribution (`justifyContent`). Unset by default (flex-start).\n * @param props.density - When true (default), gap is multiplied by theme density\n * (bounded controls). When false, gap is structural `themeSpacing(n)` — use this\n * for page/form columns.\n * @example { div: [{ h3: \"Title\" }, { p: \"Body\" }], $: [stack()] }\n * @example { div: [...], $: [stack({ gap: 2, align: \"center\" })] }\n * @example { div: [...], $: [stack({ gap: 3, density: false, justify: \"space-between\" })] }\n */\nfunction stack(\n props: {\n gap?: number;\n align?: FlexAlign;\n justify?: FlexJustify;\n density?: boolean;\n } = {},\n): PartialElement {\n const { gap = 3, align, justify, density = true } = props;\n return {\n style: {\n display: \"flex\",\n flexDirection: \"column\",\n gap: density\n ? (listener) => themeSpacing(themeDensity(listener) * gap)\n : () => themeSpacing(gap),\n ...(align ? { alignItems: align } : {}),\n ...(justify ? { justifyContent: justify } : {}),\n },\n };\n}\n\nexport { stack };\nexport type { FlexAlign, FlexJustify };\n","import {\n behavior,\n type DomphyElement,\n type ElementNode,\n isState,\n type Listener,\n type PartialElement,\n type State,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n themeWeight,\n} from \"@domphy/theme\";\n\n/** One step entry. */\ntype StepItem = {\n /** Step label — plain string (auto-wrapped) or any DomphyElement. */\n label: string | DomphyElement;\n /** Stable key. Defaults to the item's zero-based index. */\n key?: string | number;\n};\n\ntype StepsLive = {\n items: StepItem[];\n direction: \"horizontal\" | \"vertical\";\n color: ThemeColor;\n accentColor: ThemeColor;\n};\n\nfunction persistValue<T>(\n node: ElementNode,\n key: string,\n incoming: ValueOrState<T> | undefined,\n fallback: T,\n): State<T> {\n if (isState(incoming)) {\n node.setMetadata(key, incoming);\n return incoming as State<T>;\n }\n let stored = node.getMetadata(key) as State<T> | undefined;\n if (!stored) {\n stored = toState((incoming as T | undefined) ?? fallback);\n node.setMetadata(key, stored);\n }\n return stored;\n}\n\nfunction stepConnectorStyle(\n direction: \"horizontal\" | \"vertical\",\n color: ThemeColor,\n accentColor: ThemeColor,\n) {\n if (direction === \"vertical\") {\n // Outgoing track: from this badge's bottom through the host gap to the\n // next badge. Incoming-from-current-item cannot span the previous\n // item's variable label height.\n return {\n \"&:not(:last-child)::after\": {\n content: '\"\"',\n position: \"absolute\",\n insetInlineStart: themeSpacing(3),\n top: themeSpacing(6),\n bottom: `-${themeSpacing(2)}`,\n width: \"2px\",\n height: \"auto\",\n insetInlineEnd: \"auto\",\n backgroundColor: (l: Listener) => themeColor(l, \"shift-3\", color),\n zIndex: \"0\",\n },\n \"&[data-status=done]:not(:last-child)::after\": {\n backgroundColor: (l: Listener) => themeColor(l, \"shift-9\", accentColor),\n },\n };\n }\n return {\n \"&:not(:first-child)::after\": {\n content: '\"\"',\n position: \"absolute\",\n top: themeSpacing(3),\n insetInlineEnd: `calc(50% + ${themeSpacing(3)})`,\n insetInlineStart: `calc(-50% + ${themeSpacing(3)})`,\n height: \"2px\",\n backgroundColor: (l: Listener) => themeColor(l, \"shift-3\", color),\n zIndex: \"0\",\n },\n \"&[data-status=done]:not(:first-child)::after\": {\n backgroundColor: (l: Listener) => themeColor(l, \"shift-9\", accentColor),\n },\n \"&[data-status=active]:not(:first-child)::after\": {\n backgroundColor: (l: Listener) => themeColor(l, \"shift-9\", accentColor),\n },\n };\n}\n\nfunction buildStepItems(\n items: StepItem[],\n current: State<number>,\n direction: \"horizontal\" | \"vertical\",\n color: ThemeColor,\n accentColor: ThemeColor,\n): DomphyElement<\"li\">[] {\n const vertical = direction === \"vertical\";\n const connector = stepConnectorStyle(direction, color, accentColor);\n\n return items.map((item, index) => {\n const labelEl: DomphyElement =\n typeof item.label === \"string\"\n ? ({ span: item.label } as DomphyElement<\"span\">)\n : item.label;\n\n return {\n li: [labelEl],\n _key: item.key ?? index,\n dataStep: String(index + 1),\n dataStatus: (l: Listener) => {\n const cur = current.get(l);\n if (index < cur) return \"done\";\n if (index === cur) return \"active\";\n return \"pending\";\n },\n ariaCurrent: (l: Listener) =>\n current.get(l) === index ? \"step\" : undefined,\n style: {\n position: \"relative\",\n display: \"flex\",\n flexDirection: vertical ? \"row\" : \"column\",\n alignItems: vertical ? \"flex-start\" : \"center\",\n gap: themeSpacing(1),\n flex: vertical ? \"none\" : \"1\",\n fontSize: (l: Listener) => themeSize(l, \"decrease-1\"),\n textAlign: vertical ? \"start\" : \"center\",\n \"&::before\": {\n content: \"attr(data-step)\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: themeSpacing(6),\n height: themeSpacing(6),\n borderRadius: themeSpacing(999),\n fontSize: (l: Listener) => themeSize(l, \"decrease-1\"),\n fontWeight: themeWeight(\"bold\"),\n flexShrink: \"0\",\n border: (l: Listener) =>\n `2px solid ${themeColor(l, \"border-strong\", color)}`,\n backgroundColor: (l: Listener) => themeColor(l, \"inherit\"),\n color: (l: Listener) => themeColor(l, \"muted\"),\n transition:\n \"background-color 200ms ease, color 200ms ease, border-color 200ms ease\",\n zIndex: \"1\",\n },\n ...connector,\n \"&[data-status=active]::before\": {\n backgroundColor: (l: Listener) =>\n themeColor(l, \"shift-9\", accentColor),\n borderColor: (l: Listener) => themeColor(l, \"shift-9\", accentColor),\n color: (l: Listener) => themeColor(l, \"shift-0\", accentColor),\n boxShadow: (l: Listener) =>\n `0 0 0 3px ${themeColor(l, \"shift-3\", accentColor)}`,\n },\n // Completed steps: filled accent + check, matching active track.\n \"&[data-status=done]::before\": {\n content: '\"✓\"',\n backgroundColor: (l: Listener) =>\n themeColor(l, \"shift-9\", accentColor),\n borderColor: (l: Listener) => themeColor(l, \"shift-9\", accentColor),\n color: (l: Listener) => themeColor(l, \"shift-0\", accentColor),\n },\n \"&[data-status=pending]\": {\n color: (l: Listener) => themeColor(l, \"muted\"),\n },\n \"&[data-status=active]\": {\n color: (l: Listener) => themeColor(l, \"shift-11\", accentColor),\n fontWeight: themeWeight(\"bold\"),\n },\n \"&[data-status=done]\": {\n color: (l: Listener) => themeColor(l, \"text\", color),\n },\n },\n } as DomphyElement<\"li\">;\n });\n}\n\n/**\n * All-in-one step-progress indicator. Generates `<li>` step elements from the\n * `items` array. Apply to an `<ol>` or `<ul>` element.\n *\n * @param props.items - Step definitions `{ label, key? }`.\n * @param props.current - Zero-based index of the active step (value or State). Defaults to `0`.\n * @param props.direction - `\"horizontal\"` (default) or `\"vertical\"` layout.\n * @param props.color - Theme color for pending/track elements. Defaults to `\"neutral\"`.\n * @param props.accentColor - Theme color for active/completed elements. Defaults to `\"primary\"`.\n * @example\n * { ol: null, $: [steps({ current: 1, items: [\n * { label: \"Cart\" },\n * { label: \"Shipping\" },\n * { label: \"Payment\" },\n * ] })] }\n */\nfunction steps(\n props: {\n items: StepItem[];\n current?: ValueOrState<number>;\n direction?: \"horizontal\" | \"vertical\";\n color?: ThemeColor;\n accentColor?: ThemeColor;\n } = { items: [] },\n): PartialElement {\n const {\n items = [],\n direction = \"horizontal\",\n color = \"neutral\",\n accentColor = \"primary\",\n } = props;\n const live: StepsLive = { items, direction, color, accentColor };\n\n return {\n // Publish current/direction/colors so descendants can read the indicator.\n _context: {\n steps: {\n current: toState(props.current ?? 0),\n direction,\n color,\n accentColor,\n },\n },\n _onSchedule: (node, element) => {\n const current = persistValue(node, \"stepsCurrent\", props.current, 0);\n (element as Record<string, unknown>)[node.tagName] = buildStepItems(\n items,\n current,\n direction,\n color,\n accentColor,\n );\n },\n ...behavior<StepsLive>(\n \"steps-items\",\n (node) => ({\n update(snapshot) {\n const current = persistValue(node, \"stepsCurrent\", props.current, 0);\n node.children.update(\n buildStepItems(\n snapshot.items,\n current,\n snapshot.direction,\n snapshot.color,\n snapshot.accentColor,\n ),\n !!node.domElement,\n true,\n );\n },\n }),\n live,\n ),\n style: {\n display: \"flex\",\n flexDirection: direction === \"vertical\" ? \"column\" : \"row\",\n alignItems: direction === \"vertical\" ? \"flex-start\" : \"center\",\n gap: themeSpacing(2),\n listStyle: \"none\",\n margin: \"0\",\n padding: \"0\",\n },\n };\n}\n\nexport { steps };\nexport type { StepItem };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeWeight,\n} from \"@domphy/theme\";\n\n/**\n * Styles strongly emphasized (bold) text: inherited font size, the theme's `bold` weight, and a\n * themed foreground color.\n *\n * @hostTag strong\n * @param props.color - Theme color tone for the text. Accepts a value or reactive state.\n * Defaults to `\"neutral\"`.\n * @example { strong: \"important\", $: [strong()] }\n */\nfunction strong(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"strong\") {\n console.warn(`\"strong\" primitive patch must use strong tag`);\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n fontWeight: themeWeight(\"bold\"),\n color: (listener) =>\n themeColor(listener, \"shift-11\", color.get(listener)),\n backgroundColor: (listener) => themeColor(listener),\n },\n };\n}\n\nexport { strong };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport { type ThemeColor, themeColor, themeSize } from \"@domphy/theme\";\n\n/**\n * Renders subscript text (shrunk, baseline-lowered) for the host `<sub>` element.\n *\n * @hostTag sub\n * @param props.color - Theme color for the text. Optional, accepts a value or state. Defaults to `\"neutral\"`.\n * @example { sub: \"2\", $: [subscript()] }\n */\nfunction subscript(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"sub\") {\n console.warn(`\"subscript\" primitive patch must use sub tag`);\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener, \"decrease-1\"),\n verticalAlign: \"sub\",\n lineHeight: 0,\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n },\n };\n}\n\nexport { subscript };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport { type ThemeColor, themeColor, themeSize } from \"@domphy/theme\";\n\n/**\n * Renders superscript text (shrunk, baseline-raised) for the host `<sup>` element.\n *\n * @hostTag sup\n * @param props.color - Theme color for the text. Optional, accepts a value or state. Defaults to `\"neutral\"`.\n * @example { sup: \"2\", $: [superscript()] }\n */\nfunction superscript(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"sup\") {\n console.warn(`\"superscript\" primitive patch must use sup tag`);\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener, \"decrease-1\"),\n verticalAlign: \"super\",\n lineHeight: 0,\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n },\n };\n}\n\nexport { superscript };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n textToneOn,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n themeWeight,\n} from \"@domphy/theme\";\n\n/**\n * Styles a data table (header/body/footer cells, caption, row hover, borders)\n * on the host `<table>` element.\n *\n * @hostTag table\n * @param props.color - Theme color applied across cells and text. Optional, accepts a value or state. Defaults to `\"neutral\"`.\n * @example { table: null, $: [table()] }\n */\nfunction table(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"table\") {\n console.warn(`\"table\" primitive patch must use table tag`);\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n width: \"100%\",\n borderCollapse: \"collapse\",\n \"& caption\": {\n captionSide: \"bottom\",\n },\n \"& th, & thead td\": {\n textAlign: \"start\",\n fontWeight: themeWeight(\"medium\"),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 3),\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 1),\n color: (listener) =>\n themeColor(listener, \"shift-10\", color.get(listener)),\n backgroundColor: (listener) => themeColor(listener, \"inherit\"),\n },\n \"& td\": {\n textAlign: \"start\",\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 3),\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 1),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n boxShadow: (listener) =>\n `inset 0 1px 0 ${themeColor(listener, \"shift-3\", color.get(listener))}`,\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n },\n \"& tfoot th, & tfoot td\": {\n textAlign: \"start\",\n fontWeight: themeWeight(\"medium\"),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 3),\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 1),\n color: (l) => themeColor(l, \"shift-10\", color.get(l)),\n backgroundColor: (l) => themeColor(l, \"inherit\"),\n boxShadow: (l) =>\n `inset 0 -1px 0 ${themeColor(l, \"shift-4\", color.get(l))}`,\n },\n \"& tr\": {\n backgroundColor: (listener) => themeColor(listener, \"inherit\"),\n },\n\n // No !important needed: \".scope tbody tr:hover\" (two classes + two\n // elements) already out-specifies any row's own auto-scope class rule.\n \"& tbody tr:hover\": {\n backgroundColor: (listener) => themeColor(listener, \"hover\"),\n color: (listener) => themeColor(listener, textToneOn(2)),\n },\n // Cell text tracks the hover fill (+2) — measured in Chromium (axe\n // color-contrast) at 3.57:1 light / 4.37:1 dark while the cells kept the\n // resting \"text\" tone. It has to be set on the CELLS: `& td` declares its\n // own `color`, and a direct declaration beats anything inherited from the\n // row however specific that row's selector is.\n \"& tbody tr:hover td, & tbody tr:hover th\": {\n color: (listener) => themeColor(listener, textToneOn(2)),\n },\n },\n };\n}\n\nexport { table };\n","import {\n behavior,\n type DomphyElement,\n type ElementNode,\n isState,\n type Listener,\n type PartialElement,\n type State,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { horizontalArrowStep } from \"../utils/direction.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/** One tab entry: a trigger label and its panel content. */\ntype TabItem = {\n /** Tab button label — a plain string (auto-wrapped in span) or any DomphyElement. */\n label: string | DomphyElement;\n /** Panel content rendered when this tab is active. */\n content: DomphyElement;\n /** Stable identity key. Defaults to the item's zero-based index. */\n key?: string | number;\n};\n\ntype TabsLive = {\n items: TabItem[];\n accentColor: ThemeColor;\n color: ThemeColor;\n};\n\nfunction persistValue<T>(\n node: ElementNode,\n key: string,\n incoming: ValueOrState<T> | undefined,\n fallback: T,\n): State<T> {\n if (isState(incoming)) {\n node.setMetadata(key, incoming);\n return incoming as State<T>;\n }\n let stored = node.getMetadata(key) as State<T> | undefined;\n if (!stored) {\n stored = toState((incoming as T | undefined) ?? fallback);\n node.setMetadata(key, stored);\n }\n return stored;\n}\n\nfunction buildTabsChildren(\n node: ElementNode,\n items: TabItem[],\n activeKey: State<string | number>,\n accentColor: ThemeColor,\n color: ThemeColor,\n): DomphyElement[] {\n const id = node.nodeId;\n\n const buttons: DomphyElement<\"button\">[] = items.map((item, index) => {\n const key = item.key ?? index;\n const labelEl: DomphyElement =\n typeof item.label === \"string\"\n ? ({ span: item.label } as DomphyElement<\"span\">)\n : item.label;\n\n return {\n button: [labelEl],\n _key: key,\n type: \"button\",\n role: \"tab\",\n id: `tab${id}${key}`,\n ariaControls: `panel${id}${key}`,\n ariaSelected: (l: Listener) => activeKey.get(l) === key,\n // Roving tabindex (APG tabs pattern): only the selected tab is in\n // the tab order; arrow keys move both selection and focus.\n tabIndex: (l: Listener) => (activeKey.get(l) === key ? 0 : -1),\n onClick: () => activeKey.set(key),\n onKeyDown: (e: Event) => {\n const k = (e as KeyboardEvent).key;\n if (![\"ArrowLeft\", \"ArrowRight\", \"Home\", \"End\"].includes(k)) return;\n e.preventDefault();\n const keys = items.map((it, i) => it.key ?? i);\n const idx = keys.indexOf(key);\n let next = idx;\n if (k === \"ArrowRight\" || k === \"ArrowLeft\") {\n const step = horizontalArrowStep(k, e.target as Element);\n next = (idx + step + keys.length) % keys.length;\n } else if (k === \"Home\") next = 0;\n else if (k === \"End\") next = keys.length - 1;\n activeKey.set(keys[next]);\n // Focus must follow selection: without this the next arrow key\n // fires on the OLD tab and re-navigates from its stale position,\n // making later tabs unreachable by keyboard. Resolved via the\n // event target's own tablist — shadow-root safe (unlike a\n // document.getElementById lookup).\n const list = (e.target as HTMLElement).closest(\"[role=tablist]\");\n list?.querySelectorAll<HTMLElement>(\"[role=tab]\")[next]?.focus();\n },\n style: {\n cursor: \"pointer\",\n fontSize: (l: Listener) => themeSize(l, \"inherit\"),\n height: (l: Listener) => themeSpacing(6 + themeDensity(l) * 2),\n paddingInline: (l: Listener) => themeSpacing(themeDensity(l) * 4),\n border: \"none\",\n outline: \"none\",\n // Resting tabs: shift-13 for ≥4.5:1 on surface (catalog low-contrast).\n color: (l: Listener) => themeColor(l, \"shift-13\"),\n backgroundColor: (l: Listener) => themeColor(l, \"inherit\"),\n boxShadow: (l: Listener) =>\n `inset 0 ${themeSpacing(-0.5)} 0 0 ${themeColor(l, \"shift-1\", color)}`,\n transition: \"box-shadow 140ms ease, color 140ms ease\",\n \"&:hover:not([disabled]):not([aria-selected=true])\": {\n color: (l: Listener) => themeColor(l, \"shift-13\"),\n boxShadow: (l: Listener) =>\n `inset 0 ${themeSpacing(-0.5)} 0 0 ${themeColor(l, \"shift-2\", color)}`,\n },\n \"&[aria-selected=true]:not([disabled])\": {\n color: (l: Listener) => themeColor(l, \"shift-13\", accentColor),\n boxShadow: (l: Listener) =>\n `inset 0 ${themeSpacing(-0.5)} 0 0 ${themeColor(l, \"shift-8\", accentColor)}`,\n },\n // Focus ring must compose with the selected underline (both use\n // box-shadow) so keyboard focus doesn't erase the active indicator.\n \"&:focus-visible\": {\n boxShadow: (l: Listener) => focusRing(l, accentColor),\n },\n \"&[aria-selected=true]:focus-visible\": {\n boxShadow: (l: Listener) =>\n `${focusRing(l, accentColor)}, inset 0 ${themeSpacing(-0.5)} 0 0 ${themeColor(l, \"shift-6\", accentColor)}`,\n },\n },\n } as DomphyElement<\"button\">;\n });\n\n const tablist: DomphyElement<\"div\"> = {\n div: buttons,\n _key: \"tablist\",\n role: \"tablist\",\n ariaOrientation: \"horizontal\",\n style: { display: \"flex\" },\n } as DomphyElement<\"div\">;\n\n const panels: DomphyElement<\"div\">[] = items.map((item, index) => {\n const key = item.key ?? index;\n return {\n div: [item.content],\n _key: key,\n role: \"tabpanel\",\n id: `panel${id}${key}`,\n ariaLabelledby: `tab${id}${key}`,\n // WAI-ARIA APG tabs pattern: the panel is the Tab stop after the\n // tablist, so panel content with no focusable element of its own is\n // still reachable and scrollable by keyboard (Radix Tabs.Content and\n // React Aria TabPanel both set tabindex=0 unconditionally).\n tabIndex: 0,\n hidden: (l: Listener) => activeKey.get(l) !== key,\n style: {\n paddingBlock: (l: Listener) => themeSpacing(themeDensity(l) * 2),\n paddingInline: (l: Listener) => themeSpacing(themeDensity(l) * 2),\n },\n } as DomphyElement<\"div\">;\n });\n\n return [tablist, ...panels];\n}\n\n/**\n * All-in-one tabs patch. Generates a `[role=tablist]` button row and\n * `[role=tabpanel]` panels from the `items` array. Apply to any wrapper\n * element (`div`, `section`, …). No companion `tab()` / `tabPanel()` needed.\n *\n * To control the active tab programmatically, pass an external `State` as\n * `activeKey` and call `.set()` on it from outside.\n *\n * @param props.items - Tab definitions `{ label, content, key? }`.\n * @param props.activeKey - Initially active key (value or State). Defaults to the first item's key.\n * @param props.accentColor - Theme color for the active underline indicator. Defaults to `\"primary\"`.\n * @param props.color - Theme color for the resting underline. Defaults to `\"neutral\"`.\n * @example\n * { div: null, $: [tabs({ items: [\n * { label: \"Overview\", content: { p: \"Overview content\" } },\n * { label: \"API\", content: { p: \"API content\" } },\n * ] })] }\n */\nfunction tabs(\n props: {\n items: TabItem[];\n activeKey?: ValueOrState<string | number>;\n accentColor?: ThemeColor;\n color?: ThemeColor;\n } = { items: [] },\n): PartialElement {\n const { items = [], accentColor = \"primary\", color = \"neutral\" } = props;\n const live: TabsLive = { items, accentColor, color };\n\n return {\n _onSchedule: (node, element) => {\n const activeKey = persistValue(\n node,\n \"tabsActiveKey\",\n props.activeKey,\n items[0]?.key ?? 0,\n );\n (element as Record<string, unknown>)[node.tagName] = buildTabsChildren(\n node,\n items,\n activeKey,\n accentColor,\n color,\n );\n },\n ...behavior<TabsLive>(\n \"tabs-items\",\n (node) => ({\n update(snapshot) {\n const activeKey = persistValue(\n node,\n \"tabsActiveKey\",\n props.activeKey,\n snapshot.items[0]?.key ?? 0,\n );\n node.children.update(\n buildTabsChildren(\n node,\n snapshot.items,\n activeKey,\n snapshot.accentColor,\n snapshot.color,\n ),\n !!node.domElement,\n true,\n );\n },\n }),\n live,\n ),\n };\n}\n\nexport { tabs };\nexport type { TabItem };\n","import {\n type BehaviorInstance,\n behavior,\n type PartialElement,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { fieldTextStyle } from \"../utils/fieldText.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * Styles a multi-line text input (border, focus/hover/invalid/disabled states)\n * on the host `<textarea>` element, with optional auto-resize to content.\n *\n * @hostTag textarea\n * @param props.color - Theme color for the border and text. Optional, accepts a value or state. Defaults to `\"neutral\"`.\n * @param props.accentColor - Theme color for hover/focus outline. Optional, accepts a value or state. Defaults to `\"primary\"`.\n * @param props.autoResize - When true, grows the textarea height to fit its content on input and when `value` updates, and remeasures when the host becomes visible (IntersectionObserver) and when its box size changes (ResizeObserver). Optional. Defaults to `false`.\n * @example { textarea: null, $: [textarea({ autoResize: true })] }\n */\nfunction textarea(\n props: {\n color?: ValueOrState<ThemeColor>;\n accentColor?: ValueOrState<ThemeColor>;\n autoResize?: boolean;\n } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n const accentColor = toState(props.accentColor ?? \"primary\", \"accentColor\");\n const { autoResize = false } = props;\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"textarea\") {\n console.warn(`\"textarea\" primitive patch must use textarea tag`);\n }\n },\n // Resize on mount, on input, and when the host `value` attribute updates\n // (controlled writes skip the input event).\n ...behavior(\n \"textarea-auto-resize\",\n (node, initial) => {\n const el = node.domElement as HTMLTextAreaElement;\n let enabled = initial.autoResize;\n let measuring = false;\n let intersectionObserver: IntersectionObserver | undefined;\n let resizeObserver: ResizeObserver | undefined;\n const resize = () => {\n if (!enabled || measuring) return;\n measuring = true;\n // Unobserve during the height write so ResizeObserver cannot\n // re-enter from the measure itself (jsdom may deliver RO sync).\n resizeObserver?.unobserve(el);\n el.style.overflow = \"hidden\";\n el.style.height = \"auto\";\n el.style.height = `${el.scrollHeight}px`;\n measuring = false;\n if (enabled) resizeObserver?.observe(el);\n };\n const observe = () => {\n if (typeof IntersectionObserver !== \"undefined\") {\n if (!intersectionObserver) {\n intersectionObserver = new IntersectionObserver((entries) => {\n if (entries.some((entry) => entry.isIntersecting)) resize();\n });\n }\n intersectionObserver.observe(el);\n }\n if (typeof ResizeObserver !== \"undefined\") {\n if (!resizeObserver) {\n resizeObserver = new ResizeObserver(() => {\n if (measuring) return;\n resize();\n });\n }\n resizeObserver.observe(el);\n }\n };\n const unobserve = () => {\n intersectionObserver?.unobserve(el);\n resizeObserver?.unobserve(el);\n };\n el.addEventListener(\"input\", resize);\n node.attributes.addListener(\"value\", resize);\n if (enabled) {\n observe();\n resize();\n }\n return {\n resize,\n update(next) {\n enabled = next.autoResize;\n node.attributes.addListener(\"value\", resize);\n if (enabled) {\n observe();\n resize();\n } else {\n unobserve();\n }\n },\n destroy() {\n el.removeEventListener(\"input\", resize);\n intersectionObserver?.disconnect();\n resizeObserver?.disconnect();\n },\n };\n },\n { autoResize },\n ),\n _onUpdate: (node) => {\n node\n .getBehavior<\n BehaviorInstance<{ autoResize: boolean }> & { resize: () => void }\n >(\"textarea-auto-resize\")\n ?.resize();\n },\n style: {\n lineHeight: \"inherit\",\n resize: \"vertical\",\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 2),\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n border: \"none\",\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n ...fieldTextStyle(color),\n outlineOffset: \"-1px\",\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", color.get(listener))}`,\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n transition: \"outline-color 140ms ease, box-shadow 140ms ease\",\n \"&:hover:not([disabled]):not([aria-busy=true])\": {\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"shift-5\", accentColor.get(listener))}`,\n },\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, accentColor.get(listener)),\n },\n // Same gate as inputText: a bare `:invalid` painted a pristine untouched\n // `required` textarea red on first paint. `[placeholder]` +\n // `:not(:placeholder-shown)` means \"the user left content behind that is\n // invalid\"; a textarea with no placeholder uses `data-status` instead.\n \"&[placeholder]:invalid:not(:placeholder-shown)\": {\n outline: (listener) =>\n `${themeSpacing(0.5)} solid ${themeColor(listener, \"shift-5\", \"error\")}`,\n },\n // Explicit validation state, mirroring inputText's contract.\n \"&[data-status=error]\": {\n outline: (listener) =>\n `${themeSpacing(0.5)} solid ${themeColor(listener, \"shift-6\", \"error\")}`,\n },\n \"&[data-status=warning]\": {\n outline: (listener) =>\n `${themeSpacing(0.5)} solid ${themeColor(listener, \"shift-6\", \"warning\")}`,\n },\n \"&[disabled]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n color: (listener) => themeColor(listener, \"muted\", \"neutral\"),\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", \"neutral\")}`,\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-2\", \"neutral\"),\n },\n },\n };\n}\n\nexport { textarea };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * Container for a vertical timeline. Sets list reset styles. Apply to `<ol>` or `<ul>`.\n *\n * @example { ol: [...], $: [timeline()] }\n */\nfunction timeline(): PartialElement {\n return {\n style: {\n listStyle: \"none\",\n margin: 0,\n padding: 0,\n display: \"flex\",\n flexDirection: \"column\",\n },\n };\n}\n\n/**\n * A single event row in a `timeline`. Uses a 2-column grid: the left column holds\n * a dot (`::before`) and optional connector line (`::after`); the right column holds\n * the user's content. Apply to `<li>`.\n *\n * @param props.active - Full-opacity dot (accent color). `ValueOrState<boolean>`, defaults to `false`.\n * @param props.last - Suppress the vertical connector below this item. `boolean`, defaults to `false`.\n * @param props.color - Dot/connector color tone. `ThemeColor`, defaults to `\"neutral\"`.\n * @param props.accentColor - Active dot color tone. `ThemeColor`, defaults to `\"primary\"`.\n * @example { li: [{ b: \"2024\" }, { p: \"Event\" }], $: [timelineItem({ active: true })] }\n */\nfunction timelineItem(\n props: {\n active?: ValueOrState<boolean>;\n last?: boolean;\n color?: ThemeColor;\n accentColor?: ThemeColor;\n } = {},\n): PartialElement {\n const { last = false } = props;\n const color = props.color ?? \"neutral\";\n const accentColor = props.accentColor ?? \"primary\";\n const activeState = toState(props.active ?? false);\n\n return {\n style: {\n display: \"grid\",\n gridTemplateColumns: \"2rem 1fr\",\n columnGap: (listener) => themeSpacing(themeDensity(listener) * 2),\n paddingBottom: (listener) =>\n last ? \"0\" : themeSpacing(themeDensity(listener) * 4),\n position: \"relative\",\n\n // Dot\n \"&::before\": {\n content: '\"\"',\n display: \"block\",\n width: \"0.75rem\",\n height: \"0.75rem\",\n borderRadius: \"50%\",\n justifySelf: \"center\",\n marginTop: themeSpacing(1),\n transition: \"background-color 200ms ease, opacity 200ms ease\",\n backgroundColor: (listener) =>\n themeColor(\n listener,\n \"shift-8\",\n activeState.get(listener) ? accentColor : color,\n ),\n opacity: (listener) => (activeState.get(listener) ? \"1\" : \"0.4\"),\n },\n\n // Vertical connector to the next item\n ...(last\n ? {}\n : {\n \"&::after\": {\n content: '\"\"',\n position: \"absolute\",\n insetInlineStart: \"calc(1rem - 1px)\",\n top: \"1.25rem\",\n bottom: (listener) => themeSpacing(themeDensity(listener) * -4),\n width: \"2px\",\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-3\", color),\n },\n }),\n },\n };\n}\n\nexport { timeline, timelineItem };\n","import type {\n BehaviorInstance,\n DomphyElement,\n ElementNode,\n PartialElement,\n State,\n} from \"@domphy/core\";\nimport { behavior, toState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { elevation } from \"../utils/elevation.js\";\n\ntype ToastPosition =\n | \"top-left\"\n | \"top-center\"\n | \"top-right\"\n | \"bottom-left\"\n | \"bottom-center\"\n | \"bottom-right\";\n\n// The open state must live on the NODE, not in the factory closure: a toast\n// inside a reactive parent gets a fresh toast() closure per ancestor\n// re-render (fresh `toState(false)`), while `_onMount` (which flips the state\n// to visible via rAF) runs ONCE for the first generation. The reused node's\n// re-patched style bindings would read the new generation's still-false\n// state and snap the visible toast back to opacity 0 / translated out.\n// Resolving through node metadata gives every generation the SAME state.\nfunction resolveOpenState(node: ElementNode): State<boolean> {\n let state = node.getMetadata(\"toastOpen\") as State<boolean> | undefined;\n if (!state) {\n state = toState(false);\n node.setMetadata(\"toastOpen\", state);\n }\n return state;\n}\n\nconst readOpen = (listener: any): boolean => {\n const node = listener?.elementNode as ElementNode | undefined;\n return node ? resolveOpenState(node).get(listener) : false;\n};\n\n// Radix Toast Provider's documented default `duration` (ms) before a toast\n// dismisses itself. Sonner defaults to 4000ms instead; Radix's value is used\n// here since this patch's semantics (role=\"status\", one component owning its\n// own exit animation) already track Radix's Toast.Root more closely.\nconst DEFAULT_DURATION_MS = 5000;\n\ntype AutoDismissProps = {\n duration: number;\n onDismiss?: () => void;\n};\n\ntype AutoDismissInstance = BehaviorInstance<AutoDismissProps> & {\n pause: () => void;\n resume: () => void;\n};\n\n// Lives in a behavior() instance (not `_onMount`) for the same reason\n// resolveOpenState lives on node metadata above: a reactive ancestor\n// re-render gives the toast() factory a fresh closure over `duration`/\n// `onDismiss` on every generation, but `_onMount` only ever fires for the\n// FIRST one — a closure-captured timer would keep calling generation-1's\n// stale `onDismiss` (or never adopt a later `duration`) for the node's whole\n// life. `update()` routes every later generation's props into this SAME\n// instance instead.\nfunction _attachAutoDismiss(\n node: ElementNode,\n initial: AutoDismissProps,\n): AutoDismissInstance {\n let { duration, onDismiss } = initial;\n let timer: ReturnType<typeof setTimeout> | null = null;\n let remaining = duration;\n let startedAt = 0;\n let dismissed = false;\n\n const clearTimer = () => {\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n };\n const dismiss = () => {\n if (dismissed) return;\n dismissed = true;\n clearTimer();\n onDismiss?.();\n node.remove();\n };\n // duration <= 0 or non-finite (e.g. Infinity, Radix's \"never auto-dismiss\"\n // convention) means no timer at all.\n const arm = (ms: number) => {\n clearTimer();\n if (dismissed || !Number.isFinite(ms) || ms <= 0) return;\n startedAt = Date.now();\n timer = setTimeout(dismiss, ms);\n };\n\n arm(duration);\n\n // Pause/resume on hover/focus (Radix/Sonner parity): a toast whose\n // countdown elapses while the pointer is over it (or focus is inside it,\n // e.g. an action button) would otherwise vanish out from under the user\n // mid-read or mid-interaction. Wired directly on the node's own element —\n // pointerenter/pointerleave bracket a hover, focusin/focusout (which\n // bubble, unlike focus/blur) bracket focus landing anywhere inside.\n const pause = () => {\n if (!timer) return;\n remaining -= Date.now() - startedAt;\n clearTimer();\n };\n const resume = () => {\n if (dismissed || timer) return;\n arm(remaining);\n };\n const element = node.domElement;\n element?.addEventListener(\"pointerenter\", pause);\n element?.addEventListener(\"pointerleave\", resume);\n element?.addEventListener(\"focusin\", pause);\n element?.addEventListener(\"focusout\", resume);\n\n return {\n pause,\n resume,\n update(next) {\n duration = next.duration;\n onDismiss = next.onDismiss;\n // A running countdown keeps its own schedule — a new `duration` from a\n // later generation only takes effect on the next pause/resume cycle\n // (Radix: changing `duration` does not reset an in-flight toast).\n if (!timer && !dismissed) remaining = duration;\n },\n destroy() {\n clearTimer();\n element?.removeEventListener(\"pointerenter\", pause);\n element?.removeEventListener(\"pointerleave\", resume);\n element?.removeEventListener(\"focusin\", pause);\n element?.removeEventListener(\"focusout\", resume);\n },\n };\n}\n\n/**\n * Renders a transient notification surface as a fixed-position overlay (portaled\n * into a corner stack), animating in on mount and out before removal. Auto-dismisses\n * after `duration` (Radix/Sonner semantics), paused while hovered or focused. No host\n * tag check; typically applied to a `<div>`.\n *\n * @param props.position - Corner of the screen for the toast stack. Optional, one of `\"top-left\" | \"top-center\" | \"top-right\" | \"bottom-left\" | \"bottom-center\" | \"bottom-right\"`. Defaults to `\"top-center\"`.\n * @param props.color - Theme color for the toast surface. Optional. Defaults to `\"neutral\"`.\n * @param props.duration - Milliseconds before the toast dismisses itself (calls `onDismiss` then removes itself). Pass `Infinity` or `0` to disable. Optional. Defaults to `5000`.\n * @param props.onDismiss - Called once, right before the toast removes itself, when `duration` elapses without the pointer/focus inside it. Optional — a caller tracking its own toast list should use this to drop the entry from state.\n * @example { div: \"Saved!\", $: [toast({ position: \"top-right\" })] }\n */\nfunction toast(\n props: {\n position?: ToastPosition;\n color?: ThemeColor;\n duration?: number;\n onDismiss?: () => void;\n } = {},\n): PartialElement {\n const {\n position = \"top-center\",\n color = \"neutral\",\n duration = DEFAULT_DURATION_MS,\n onDismiss,\n } = props;\n\n const isTop = position.startsWith(\"top\");\n const isCenter = position.endsWith(\"center\");\n const isRight = position.endsWith(\"right\");\n\n const overlayEle: DomphyElement<\"div\"> = {\n div: [],\n id: `domphy-toast-${position}`,\n style: {\n position: \"fixed\",\n display: \"flex\",\n flexDirection: isTop ? \"column\" : \"column-reverse\",\n alignItems: isCenter ? \"center\" : isRight ? \"end\" : \"start\",\n inset: 0,\n gap: themeSpacing(4),\n zIndex: 30,\n padding: themeSpacing(6),\n pointerEvents: \"none\",\n },\n };\n\n return {\n ...behavior(\"toastAutoDismiss\", _attachAutoDismiss, {\n duration,\n onDismiss,\n }),\n _portal: (rootNode) => {\n let overlay = rootNode.domElement!.querySelector(\n `#domphy-toast-${position}`,\n );\n if (!overlay) {\n const overlayNode = rootNode.children!.insert(\n overlayEle,\n ) as ElementNode;\n overlay = overlayNode.domElement!;\n }\n return overlay;\n },\n role: \"status\",\n ariaAtomic: \"true\",\n // Toast is rendered as an overlay surface, so it uses the inverted branch.\n dataTone: \"shift-17\",\n style: {\n minWidth: themeSpacing(32),\n pointerEvents: \"auto\",\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 2),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 4),\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 2),\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n color: (listener) => themeColor(listener, \"text\", color),\n backgroundColor: (listener) => themeColor(listener, \"inherit\", color),\n boxShadow: elevation(\"medium\"),\n opacity: (listener) => Number(readOpen(listener)),\n transform: (listener) =>\n readOpen(listener)\n ? \"translateY(0)\"\n : isTop\n ? \"translateY(-100%)\"\n : \"translateY(100%)\",\n transition: \"opacity 300ms ease, transform 300ms ease\",\n },\n _onMount: (node) =>\n requestAnimationFrame(() => resolveOpenState(node).set(true)),\n _onBeforeRemove: (node, done) => {\n let finished = false;\n let timer: ReturnType<typeof setTimeout> | null = null;\n let overlayRemoved = false;\n const rootNode = node.getRoot();\n const overlayEl = node.domElement?.parentElement ?? null;\n // The #domphy-toast-{position} overlay is inserted into the root on\n // first use and shared by every toast at that position — remove it once\n // its LAST toast is gone instead of leaking one empty fixed container\n // per used position for the app's whole lifetime.\n const removeOverlayIfEmpty = () => {\n if (overlayRemoved) return;\n if (\n !overlayEl ||\n overlayEl.id !== `domphy-toast-${position}` ||\n overlayEl.childElementCount > 0\n ) {\n return;\n }\n overlayRemoved = true;\n const item = rootNode.children?.items.find(\n (it) => (it as ElementNode).domElement === overlayEl,\n );\n if (item) rootNode.children!.remove(item);\n else overlayEl.remove();\n };\n const finish = () => {\n if (finished) return;\n finished = true;\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n node.domElement!.removeEventListener(\"transitionend\", onEnd);\n done();\n removeOverlayIfEmpty();\n };\n const onEnd = (e: Event) => {\n if ((e as TransitionEvent).propertyName === \"transform\") finish();\n };\n node.domElement!.addEventListener(\"transitionend\", onEnd);\n // Fallback: if transitionend never fires (reduced-motion, display:none,\n // early detach), unblock removal after the transition duration + buffer.\n timer = setTimeout(finish, 350);\n // If the node is detached before the exit animation settles, clear the\n // pending fallback timer and the transitionend listener so they cannot\n // fire on a removed node.\n node.addHook(\"Remove\", () => {\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n node.domElement?.removeEventListener(\"transitionend\", onEnd);\n removeOverlayIfEmpty();\n });\n resolveOpenState(node).set(false);\n },\n };\n}\n\nexport { toast };\n","import {\n behavior,\n type DomphyElement,\n type ElementNode,\n isState,\n type Listener,\n type PartialElement,\n type State,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { horizontalArrowStep } from \"../utils/direction.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/** One item inside a toggle group. */\ntype ToggleItem = {\n /** Button label — plain string (auto-wrapped) or any DomphyElement. */\n label: string | DomphyElement;\n /** Stable key. Defaults to the item's zero-based index as a string. */\n key?: string;\n};\n\ntype ToggleLive = {\n items: ToggleItem[];\n multiple: boolean;\n color: ThemeColor;\n accentColor: ThemeColor;\n};\n\nfunction persistValue<T>(\n node: ElementNode,\n key: string,\n incoming: ValueOrState<T> | undefined,\n fallback: T,\n): State<T> {\n if (isState(incoming)) {\n node.setMetadata(key, incoming);\n return incoming as State<T>;\n }\n let stored = node.getMetadata(key) as State<T> | undefined;\n if (!stored) {\n stored = toState((incoming as T | undefined) ?? fallback);\n node.setMetadata(key, stored);\n }\n return stored;\n}\n\nfunction isPressed(val: string | string[], key: string): boolean {\n return Array.isArray(val) ? val.includes(key) : val === key;\n}\n\nfunction moveToggle(\n e: Event,\n items: ToggleItem[],\n key: string,\n value: State<string | string[]>,\n multiple: boolean,\n): void {\n const k = (e as KeyboardEvent).key;\n // WAI-ARIA APG toolbar/radio navigation: both axes move (Right/Down = next,\n // Left/Up = previous), Home/End jump to the ends.\n if (\n ![\n \"ArrowLeft\",\n \"ArrowRight\",\n \"ArrowUp\",\n \"ArrowDown\",\n \"Home\",\n \"End\",\n ].includes(k)\n )\n return;\n e.preventDefault();\n const keys = items.map((item, index) => item.key ?? String(index));\n const idx = keys.indexOf(key);\n let next = idx;\n if (k === \"ArrowDown\") next = (idx + 1) % keys.length;\n else if (k === \"ArrowUp\") next = (idx - 1 + keys.length) % keys.length;\n else if (k === \"ArrowRight\" || k === \"ArrowLeft\") {\n const step = horizontalArrowStep(k, e.target as Element);\n next = (idx + step + keys.length) % keys.length;\n } else if (k === \"Home\") next = 0;\n else if (k === \"End\") next = keys.length - 1;\n if (!multiple) value.set(keys[next]);\n const group = (e.target as HTMLElement).closest(\"[role=group]\");\n group?.querySelectorAll<HTMLElement>(\"button\")[next]?.focus();\n}\n\nfunction buildToggleButtons(\n items: ToggleItem[],\n value: State<string | string[]>,\n focusedKey: State<string | null>,\n multiple: boolean,\n color: ThemeColor,\n accentColor: ThemeColor,\n): DomphyElement<\"button\">[] {\n return items.map((item, index) => {\n const key = item.key ?? String(index);\n const labelEl: DomphyElement =\n typeof item.label === \"string\"\n ? ({ span: item.label } as DomphyElement<\"span\">)\n : item.label;\n\n return {\n button: [labelEl],\n _key: key,\n type: \"button\",\n role: \"button\",\n ariaPressed: (l: Listener) => isPressed(value.get(l), key),\n // Roving tab stop: the last-focused item, like single-select mode and\n // the menu/tabs patches (WAI-ARIA APG). Falls back to the first\n // selected item, then the first item, until focus has landed once.\n tabIndex: (l: Listener) => {\n const val = value.get(l);\n if (multiple) {\n const focused = focusedKey.get(l);\n if (focused !== null) return key === focused ? 0 : -1;\n const arr = Array.isArray(val) ? val : [];\n const fallback = arr[0] ?? items[0]?.key ?? \"0\";\n return key === fallback ? 0 : -1;\n }\n if (val === key) return 0;\n if (val === \"\" && key === (items[0]?.key ?? \"0\")) return 0;\n return -1;\n },\n onFocus: () => focusedKey.set(key),\n onClick: () => {\n const val = value.get();\n if (multiple) {\n const arr = Array.isArray(val) ? [...val] : [];\n value.set(\n arr.includes(key) ? arr.filter((v) => v !== key) : [...arr, key],\n );\n } else {\n value.set(val === key ? \"\" : key);\n }\n },\n onKeyDown: (e: Event) => moveToggle(e, items, key, value, multiple),\n style: {\n cursor: \"pointer\",\n fontSize: (l: Listener) => themeSize(l, \"inherit\"),\n height: themeSpacing(6),\n paddingBlock: themeSpacing(1),\n paddingInline: themeSpacing(2),\n border: \"none\",\n borderRadius: themeSpacing(1.5),\n // Unpressed: shift-13 for readable resting labels (catalog contrast).\n color: (l: Listener) => themeColor(l, \"shift-13\", color),\n backgroundColor: (l: Listener) => themeColor(l, \"inherit\", color),\n transition:\n \"background-color 140ms ease, color 140ms ease, box-shadow 140ms ease\",\n \"&:hover:not([disabled]):not([aria-pressed=true])\": {\n color: (l: Listener) => themeColor(l, \"shift-13\", color),\n backgroundColor: (l: Listener) => themeColor(l, \"hover\", color),\n },\n \"&:active:not([disabled])\": {\n backgroundColor: (l: Listener) => themeColor(l, \"increase-2\", color),\n },\n \"&[aria-pressed=true]\": {\n backgroundColor: (l: Listener) =>\n themeColor(l, \"shift-3\", accentColor),\n color: (l: Listener) => themeColor(l, \"shift-13\", accentColor),\n },\n \"&:focus-visible\": {\n boxShadow: (l: Listener) => focusRing(l, accentColor),\n },\n \"&[disabled]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n },\n },\n } as DomphyElement<\"button\">;\n });\n}\n\n/**\n * All-in-one toggle group — single or multi-select button group. Generates\n * `<button>` toggle elements from the `items` array. Apply to any wrapper element.\n *\n * @param props.items - Item definitions `{ label, key? }`.\n * @param props.value - Selected key(s) (value or State). Defaults to `[]` (multiple) or `\"\"` (single).\n * @param props.multiple - Allow multiple items selected at once. Defaults to `false`.\n * @param props.color - Theme color for the group background/border. Defaults to `\"neutral\"`.\n * @param props.accentColor - Theme color for the pressed state. Defaults to `\"primary\"`.\n * @example\n * { div: null, $: [toggleGroup({ multiple: true, items: [\n * { label: \"Bold\", key: \"bold\" },\n * { label: \"Italic\", key: \"italic\" },\n * ] })] }\n */\nfunction toggleGroup(\n props: {\n items: ToggleItem[];\n value?: ValueOrState<string | string[]>;\n multiple?: boolean;\n color?: ThemeColor;\n accentColor?: ThemeColor;\n } = { items: [] },\n): PartialElement {\n const {\n items = [],\n multiple = false,\n color = \"neutral\",\n accentColor = \"primary\",\n } = props;\n const live: ToggleLive = { items, multiple, color, accentColor };\n\n return {\n role: \"group\",\n _onSchedule: (node, element) => {\n const value = persistValue(\n node,\n \"toggleGroupValue\",\n props.value,\n multiple ? [] : \"\",\n );\n // Publish the SAME state the buttons write to — see segmented.ts for why\n // a declared `_context` could not (disconnected State + notifier clobber\n // when ElementNode.patch re-merges `element._context`).\n node.setContext(\"toggleGroup\", { value, multiple });\n const focusedKey = persistValue<string | null>(\n node,\n \"toggleGroupFocusedKey\",\n undefined,\n null,\n );\n (element as Record<string, unknown>)[node.tagName] = buildToggleButtons(\n items,\n value,\n focusedKey,\n multiple,\n color,\n accentColor,\n );\n },\n ...behavior<ToggleLive>(\n \"toggle-items\",\n (node) => ({\n update(snapshot) {\n const value = persistValue(\n node,\n \"toggleGroupValue\",\n props.value,\n snapshot.multiple ? [] : \"\",\n );\n const focusedKey = persistValue<string | null>(\n node,\n \"toggleGroupFocusedKey\",\n undefined,\n null,\n );\n node.children.update(\n buildToggleButtons(\n snapshot.items,\n value,\n focusedKey,\n snapshot.multiple,\n snapshot.color,\n snapshot.accentColor,\n ),\n !!node.domElement,\n true,\n );\n },\n }),\n live,\n ),\n style: {\n display: \"flex\",\n paddingBlock: themeSpacing(1),\n paddingInline: themeSpacing(1),\n gap: themeSpacing(1),\n borderRadius: themeSpacing(2),\n fontSize: (l: Listener) => themeSize(l, \"inherit\"),\n backgroundColor: (l: Listener) => themeColor(l, \"inherit\", color),\n color: (l: Listener) => themeColor(l, \"text\", color),\n outline: (l: Listener) => `1px solid ${themeColor(l, \"border\", color)}`,\n outlineOffset: \"-1px\",\n },\n };\n}\n\nexport { toggleGroup };\nexport type { ToggleItem };\n","import type { DomphyElement, PartialElement } from \"@domphy/core\";\nimport { row } from \"./row.js\";\nimport type { FlexAlign, FlexJustify } from \"./stack.js\";\n\n/**\n * A horizontal flex row with vertically centered items. Useful for headers,\n * toolbars, navigation bars, and action strips. A semantic alias of `row()`;\n * wrap/justify/align/density are forwarded so callers do not drop down to\n * hand-rolled flex.\n *\n * @param props.gap - Spacing multiplier for gap between items (default 4).\n * Bounded-control mode (`density: true`, default): `themeSpacing(themeDensity(l) * gap)`.\n * Structural mode (`density: false`): bare `themeSpacing(gap)`.\n * @param props.wrap - Allow items to wrap onto multiple lines. Defaults to `false`.\n * @param props.justify - Main-axis distribution (`justifyContent`). Unset by default.\n * @param props.align - Cross-axis alignment (`alignItems`). Defaults to `\"center\"` (row default).\n * @param props.density - When true (default), gap is multiplied by theme density.\n * When false, gap is structural `themeSpacing(n)`.\n * @example { header: [...], $: [toolbar()] }\n * @example { nav: [...], $: [toolbar({ gap: 3 })] }\n * @example { header: [...], $: [toolbar({ wrap: true, justify: \"space-between\" })] }\n */\nfunction toolbar(\n props: {\n gap?: number;\n wrap?: boolean;\n justify?: FlexJustify;\n align?: FlexAlign;\n density?: boolean;\n } = {},\n): PartialElement {\n return row(props);\n}\n\n/**\n * A flex spacer that expands to fill available space in a toolbar, pushing\n * subsequent items to the far end.\n *\n * @example { header: [logo, toolbarSpacer(), nav, actions], $: [toolbar()] }\n */\nfunction toolbarSpacer(): DomphyElement {\n return { div: null, style: { flex: \"1 1 0\" } };\n}\n\nexport { toolbar, toolbarSpacer };\n","import {\n type DomphyElement,\n merge,\n type PartialElement,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport type { Placement } from \"@domphy/floating\";\nimport {\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { elevation } from \"../utils/elevation.js\";\nimport { createFloating, floatingPanelId } from \"../utils/floating.js\";\nimport { popoverArrow } from \"./popoverArrow.js\";\n\n/**\n * Attaches a floating tooltip to the host element, shown on hover/focus and\n * hidden on leave/blur/Escape. Returns the anchor (trigger) partial; the tooltip\n * surface is positioned via the floating utility and linked with\n * `aria-describedby`. No host tag check; applied to the trigger element.\n *\n * @param props.open - Controlled open state (`ValueOrState<boolean>`), including `Computed`/`ReadableState`. When the source is read-only, pass `onDismiss` so leave/blur/Escape can close. Optional. Defaults to `false`.\n * @param props.onDismiss - Called when the tooltip requests close. Optional. Required to close when `open` is a read-only `Computed`/`ReadableState`.\n * @param props.placement - Floating placement relative to the trigger. Optional, accepts a value or state (`Placement`). Defaults to `\"top\"`.\n * @param props.content - Tooltip text content. Optional, accepts a value or state (string only). Defaults to `\"Tooltip Content\"`.\n * @param props.openDelay - Hover/focus-intent delay before showing, in ms (Radix `delayDuration` parity). Optional. Defaults to 100.\n * @param props.closeDelay - Delay before hiding after leave/blur, in ms. Optional. Defaults to 100.\n * @example { button: \"Hover me\", $: [tooltip({ content: \"Help text\" })] }\n */\nfunction tooltip(\n props: {\n open?: ValueOrState<boolean>;\n onDismiss?: () => void;\n placement?: ValueOrState<Placement>;\n content?: ValueOrState<string>;\n openDelay?: number;\n closeDelay?: number;\n } = {},\n): PartialElement {\n const {\n open = false,\n placement = \"top\",\n content = \"Tooltip Content\",\n openDelay,\n closeDelay,\n } = props;\n\n const placeState = toState(placement);\n const contentState = toState(content);\n\n // The tooltip id is NOT pre-generated here: a factory-scope id (previously\n // Math.random()-based) churns per generation and mismatches SSR/hydration.\n // Instead the shared floating behavior stamps a deterministic id derived\n // from the anchor's nodeId when the panel mounts (see floating.ts), and the\n // trigger references the same id via _onSchedule below.\n const contentElement: DomphyElement<\"span\"> = {\n span: (listener) => contentState.get(listener),\n };\n\n const { show, hide, anchorPartial, openState } = createFloating({\n kind: \"tooltip\",\n open,\n onDismiss: props.onDismiss,\n placement: placeState,\n content: contentElement,\n openDelay,\n closeDelay,\n });\n\n const tooltipPartial: PartialElement = {\n role: \"tooltip\",\n dataSize: \"decrease-1\",\n dataTone: \"shift-17\",\n style: {\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 1),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 3),\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n color: (listener) => themeColor(listener, \"text\"),\n backgroundColor: (listener) => themeColor(listener),\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n boxShadow: elevation(\"low\"),\n },\n $: [popoverArrow({ placement: placeState, bordered: false })],\n };\n contentElement.$ ||= [];\n contentElement.$.push(tooltipPartial);\n\n const triggerPartial: PartialElement = {\n // Declared as a reactive attribute (listener.elementNode is the anchor) so\n // it is re-declared on every patch (patch() strips attributes that are no\n // longer declared, so imperative wiring would not survive re-render).\n // Only points at the panel while it is actually open — Radix sets\n // aria-describedby the same way; a dangling reference to a closed panel's\n // id (removed from the DOM between shows) is an id-not-found reference\n // for the whole time the tooltip is hidden.\n ariaDescribedby: (listener) =>\n listener?.elementNode && openState.get(listener)\n ? floatingPanelId(\"tooltip\", listener.elementNode)\n : undefined,\n onMouseEnter: (_e, node) => show(node),\n onMouseLeave: (_e, node) => hide(node),\n onFocus: (_e, node) => show(node),\n onBlur: (_e, node) => hide(node),\n onKeyDown: (e, node) => (e as KeyboardEvent).key === \"Escape\" && hide(node),\n };\n\n merge(anchorPartial, triggerPartial);\n\n return anchorPartial;\n}\n\nexport { tooltip };\n","import { ElementNode, type PartialElement } from \"@domphy/core\";\nimport { prefersReducedMotion } from \"../utils/reducedMotion.js\";\n\ntype RectMap = Map<string, DOMRect>;\n\nfunction getItemId(node: ElementNode, index: number): string {\n if (node.key !== undefined && node.key !== null) {\n return String(node.key);\n }\n return `index-${index}`;\n}\n\n/**\n * Animates child reordering using the FLIP technique: records each child's\n * position before an update and smoothly transitions it from its old to new\n * position afterward. No host tag check; applied to the list container.\n *\n * @param props.duration - Transition duration in milliseconds. Optional. Defaults to `300`.\n * @param props.delay - Transition delay in milliseconds. Optional. Defaults to `0`.\n * @example { ul: null, $: [transitionGroup({ duration: 300 })] }\n */\nfunction transitionGroup(\n props: { duration?: number; delay?: number } = {},\n): PartialElement {\n const { duration = 300, delay = 0 } = props;\n\n let previousRects: RectMap = new Map();\n // Cancels any in-flight animation for a given DOM element before starting a new one.\n const cancelMap = new Map<HTMLElement, () => void>();\n // Pending fallback timers and queued rAF callbacks, tracked so a removal of\n // the container mid-animation can clear them instead of firing on a detached node.\n const pendingTimers = new Set<ReturnType<typeof setTimeout>>();\n const pendingFrames = new Set<number>();\n\n return {\n _onMount: (node) => {\n node.addHook(\"Remove\", () => {\n // Stop every in-flight animation: removes transitionend listeners.\n for (const cancel of Array.from(cancelMap.values())) cancel();\n cancelMap.clear();\n // Clear queued fallback timers.\n for (const timer of pendingTimers) clearTimeout(timer);\n pendingTimers.clear();\n // Cancel queued animation frames.\n for (const frame of pendingFrames) cancelAnimationFrame(frame);\n pendingFrames.clear();\n });\n },\n _onBeforeUpdate: (node) => {\n previousRects = new Map();\n // A FLIP reorder is exactly the large motion prefers-reduced-motion\n // exists for (WCAG 2.3.3 Animation from Interactions); with no captured\n // rects _onUpdate is a no-op per item, so the reorder lands instantly —\n // the same degradation motion() and every peer (framer-motion Reorder,\n // React Aria, Mantine Transition) applies.\n if (prefersReducedMotion()) return;\n node.children.items.forEach((item, index) => {\n if (!(item instanceof ElementNode)) return;\n const dom = item.domElement as HTMLElement | undefined;\n if (!dom) return;\n previousRects.set(getItemId(item, index), dom.getBoundingClientRect());\n });\n },\n _onUpdate: (node) => {\n node.children.items.forEach((item, index) => {\n if (!(item instanceof ElementNode)) return;\n const dom = item.domElement as HTMLElement | undefined;\n if (!dom) return;\n\n const key = getItemId(item, index);\n const prev = previousRects.get(key);\n if (!prev) return;\n\n const next = dom.getBoundingClientRect();\n const deltaX = prev.left - next.left;\n const deltaY = prev.top - next.top;\n if (Math.abs(deltaX) < 0.5 && Math.abs(deltaY) < 0.5) return;\n\n // Cancel any in-flight animation on this element before starting a new one.\n cancelMap.get(dom)?.();\n\n dom.style.transition = \"none\";\n dom.style.transform = `translate(${deltaX}px, ${deltaY}px)`;\n dom.getBoundingClientRect();\n\n const frame = requestAnimationFrame(() => {\n pendingFrames.delete(frame);\n dom.style.transition = `transform ${duration}ms ease ${delay}ms`;\n dom.style.transform = \"translate(0px, 0px)\";\n });\n pendingFrames.add(frame);\n\n let cancelled = false;\n let timer: ReturnType<typeof setTimeout> | null = null;\n const finish = () => {\n if (cancelled) return;\n cancelled = true;\n if (timer) {\n pendingTimers.delete(timer);\n timer = null;\n }\n cancelMap.delete(dom);\n dom.removeEventListener(\"transitionend\", onEnd);\n dom.style.transition = \"\";\n dom.style.transform = \"\";\n };\n\n const onEnd = (event: Event) => {\n if ((event as TransitionEvent).propertyName === \"transform\") finish();\n };\n\n cancelMap.set(dom, () => {\n cancelled = true;\n if (timer) {\n clearTimeout(timer);\n pendingTimers.delete(timer);\n timer = null;\n }\n cancelMap.delete(dom);\n dom.removeEventListener(\"transitionend\", onEnd);\n });\n\n dom.addEventListener(\"transitionend\", onEnd);\n timer = setTimeout(finish, duration + delay + 34);\n pendingTimers.add(timer);\n });\n previousRects.clear();\n },\n };\n}\n\nexport { transitionGroup };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * Styles a bulleted list (disc markers, reset margins, themed text) on the host\n * `<ul>` element.\n *\n * @hostTag ul\n * @param props.color - Theme color for the list text. Optional, accepts a value or state. Defaults to `\"neutral\"`.\n * @example { ul: null, $: [unorderedList()] }\n */\nfunction unorderedList(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"ul\") {\n console.warn(`\"unorderedList\" primitive patch must use ul tag`);\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n backgroundColor: (listener) => themeColor(listener),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n marginTop: 0,\n marginBottom: 0,\n paddingInlineStart: themeSpacing(3),\n listStyleType: \"disc\",\n listStylePosition: \"outside\",\n },\n };\n}\n\nexport { unorderedList };\n","import type { PartialElement } from \"@domphy/core\";\n\n/**\n * Visually hides an element while keeping it in the accessibility tree — the\n * classic \"sr-only\" recipe for screen-reader-only labels, live-region text,\n * and skip links (before focus). Styles the host only; apply to any element.\n *\n * @example { span: \"Opens in a new tab\", $: [visuallyHidden()] }\n */\nfunction visuallyHidden(): PartialElement {\n return {\n style: {\n position: \"absolute\",\n width: \"1px\",\n height: \"1px\",\n padding: \"0\",\n margin: \"-1px\",\n overflow: \"hidden\",\n clip: \"rect(0, 0, 0, 0)\",\n whiteSpace: \"nowrap\",\n border: \"0\",\n },\n };\n}\n\nexport { visuallyHidden };\n"],"mappings":"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","names":["index_exports","__export","abbreviation","accordion","alert","avatar","badge","blockquote","breadcrumb","breadcrumbEllipsis","button","buttonGhost","buttonSwitch","card","code","combobox","command","commandItem","commandSearch","datePicker","descriptionList","details","dialog","divider","drawer","elevation","emphasis","empty","errorBoundary","fab","figure","focusRing","formGroup","grid","heading","horizontalRule","icon","image","inputCheckbox","inputColor","inputDateTime","inputFile","inputNumber","inputOTP","inputPassword","inputRadio","inputRange","inputSearch","inputSwitch","inputText","keyboard","label","link","linkButton","list","listItem","listItemButton","mark","menu","motion","orderedList","pagination","panelSection","paragraph","popover","popoverArrow","preformated","progress","rating","ringProgress","row","scrollArea","segmented","select","selectBox","selectItem","selectList","skeleton","small","spinner","splitter","splitterHandle","splitterPanel","stack","steps","strong","subscript","superscript","table","tabs","tag","textarea","timeline","timelineItem","toast","toggleGroup","toolbar","toolbarSpacer","tooltip","transitionGroup","unorderedList","visuallyHidden","__toCommonJS","import_core","import_theme","abbreviation","props","_a","_b","color","accentColor","node","listener","import_core","import_theme","import_theme","focusRing","listener","color","gap","ring","accordion","props","_a","_b","type","color","accentColor","node","el","handler","event","summary","item","detail","onKeyDown","key","summaries","index","next","listener","focusRing","import_core","import_theme","alert","props","_a","color","listener","import_core","import_theme","avatar","props","_a","color","listener","import_core","import_theme","badge","props","_a","label","state","color","l","import_core","import_theme","blockquote","props","_a","color","node","listener","import_core","import_theme","breadcrumb","props","_a","separator","color","node","listener","import_core","import_theme","breadcrumbEllipsis","props","_a","color","node","listener","focusRing","import_core","import_theme","BUTTON_SIZE_FONT","import_core","import_theme","PADDING_STEPS","buttonGhost","props","_a","_b","_c","color","padding","fontSize","BUTTON_SIZE_FONT","node","listener","focusRing","PADDING_STEPS","button","props","_a","_b","_c","_d","variant","buttonGhost","color","isSolid","padding","fontSize","BUTTON_SIZE_FONT","__spreadProps","__spreadValues","node","listener","focusRing","import_core","import_theme","buttonSwitch","props","_a","_b","checked","check","color","accentColor","node","listener","focusRing","import_core","import_theme","SHADOWS","elevation","level","card","props","_a","color","listener","elevation","import_core","import_theme","code","props","_a","color","node","listener","import_core","import_theme","import_core","import_theme","PLACEHOLDER_TONE","VALUE_TONE","fieldTextStyle","color","colorState","listener","import_core","import_floating","import_core","isWritableState","source","subscribeOpen","onChange","emitCurrent","skipInitial","release","value","writeOpen","dismissOpen","onDismiss","asOpenState","open","FLOATING_DEFAULT_DELAY_MS","floatingPanelId","kind","node","OVERLAY_ATTRIBUTE","OVERLAY_SELECTOR","OVERLAY_KIND_ATTRIBUTE","hasOpenFloatingPanel","dialogElement","overlay","child","attachFloating","initialProps","_a","_b","_c","_d","openState","onDismiss","placement","content","keepOpenOnContentHover","openDelay","closeDelay","behaviorKey","timer","cleanup","floating","floatingNode","mounted","reference","rootNode","panelId","floatingPartial","listener","event","isTopLayer","hide","show","mountedNode","dataTheme","rNode","dialogHost","overlayEle","wireContent","target","ensureMounted","instance","detachPanel","instantShow","x","y","resolved","writeOpen","focusIsInsidePanel","active","focusReference","instantHide","restoreFocus","dismissOpen","handleOutside","handleEscape","escapeTarget","onOpen","val","release","destroyed","updating","stampPanelBehavior","__spreadProps","__spreadValues","props","subscribeOpen","createFloating","asOpenState","anchorPartial","e","enabledOptionsIn","root","el","import_core","import_theme","xSvg","DEFAULT_DENSITY","TAG_HEIGHT","TAG_PAD_INLINE","TAG_PAD_END_REMOVABLE","TAG_REMOVE","TAG_REMOVE_RADIUS","tag","props","_a","removable","color","__spreadProps","__spreadValues","node","initial","removeHost","makeButton","e","event","listener","focusRing","findButton","item","sync","next","existing","combobox","props","options","placement","color","open","multiple","state","openState","show","hide","anchorPartial","createFloating","popoverPartial","_e","node","listener","elevation","inputStyle","__spreadProps","__spreadValues","fieldTextStyle","readQuery","_a","_b","findComboboxAnchor","from","current","moveIntoPanel","toLast","anchor","root","panel","floatingPanelId","enabledOptionsIn","target","openThenMove","release","subscribeOpen","isOpen","inputAria","event","key","buildInput","custom","buildWrap","inner","val","vals","items","opt","tag","_node","cur","filter","v","partial","element","_inner","query","next","focusRing","import_core","import_theme","visibleItems","host","el","onCommandKey","event","node","_a","key","items","active","current","next","target","command","_node","element","commandSearch","props","color","accentColor","ctx","input","onInput","__spreadProps","__spreadValues","listener","fieldTextStyle","focusRing","commandItem","applyFilter","q","_b","text","release","import_core","import_theme","atMidnight","date","addDays","count","addMonths","sameDay","a","b","isoOf","startOfWeek","weekStart","localeWeekStart","locale","_a","_b","localeObject","info","attachDatePicker","_node","initialProps","current","releaseOnChange","subscribe","props","value","carryForward","next","prev","datePicker","_c","_d","mode","time","min","max","disabledDate","format","onChange","accentColor","placeState","selection","primaryDate","base","viewYear","viewMonth","focused","hovered","hour","minute","dateFormatter","__spreadValues","monthFormatter","weekdayFormatter","fullDateFormatter","formatOne","formatDisplay","start","end","weekdayNames","_unused","index","isDisabled","withTime","result","selectDate","node","hide","reapplyTime","inSelectedRange","listener","tail","low","high","day","isSelectedEnd","goToDate","shiftMonth","delta","shiftYear","focusActiveCell","root","calendar","buildCalendar","openState","show","anchorPartial","createFloating","triggerPartial","floatingPanelId","_e","openAndFocus","event","key","isSelectedPrimary","navButton","label","ariaLabel","onClick","navButtonStyle","header","weekdayHeader","name","gridRowStyle","grid","buildWeeks","onGridKey","children","buildTimeRow","buildFooter","elevation","first","month","weeks","week","cells","buildDayCell","disabled","selected","within","outside","isFocused","isToday","l","focusRing","numberSelect","state","timeSelectStyle","action","today","keyboard","import_core","import_theme","descriptionList","props","_a","color","node","listener","import_core","import_theme","details","props","_a","_b","duration","color","accentColor","node","listener","focusRing","import_core","import_theme","lockCount","lockScroll","unlockScroll","FOCUSABLE","attachDialog","node","initialProps","state","onDismiss","previousFocus","closing","scrollLocked","closeTimer","dlg","finalizeClose","unlockScroll","trapFocus","e","focusables","el","first","last","onCancel","hasOpenFloatingPanel","dismissOpen","update","val","lockScroll","_a","focusable","release","subscribeOpen","props","dialog","color","open","labelledBy","describedBy","asOpenState","__spreadProps","__spreadValues","r","listener","elevation","import_core","import_theme","divider","props","_a","color","node","listener","import_core","import_theme","translateOut","marginMap","isVertical","p","resolvePhysical","placement","isRTL","attachDrawer","node","initialProps","state","onDismiss","size","dlg","onCancel","e","hasOpenFloatingPanel","dismissOpen","resolve","nextPlacement","nextSize","physical","drawerSize","closing","scrollLocked","closeTimer","finishClose","unlockScroll","onTransitionEnd","update","val","lockScroll","release","subscribeOpen","props","drawer","color","open","asOpenState","physicalFallback","defaultSize","__spreadProps","__spreadValues","_a","r","listener","elevation","import_core","import_theme","emphasis","props","_a","color","node","listener","import_core","import_theme","empty","props","_a","color","listener","ORIGINAL_CHILDREN","restoreOriginalChildren","node","_a","original","errorBoundary","props","element","error","_b","reset","fallbackEl","import_core","import_theme","SIZE_MAP","fab","props","_a","_b","color","dim","node","listener","elevation","focusRing","import_core","import_theme","figure","props","_a","color","node","listener","import_core","import_theme","formGroup","props","_a","layout","color","isVertical","node","listener","import_theme","grid","props","columns","gap","align","__spreadValues","listener","import_core","import_theme","HeadingShift","heading","props","_a","color","size","node","listener","offset","import_core","import_theme","horizontalRule","props","_a","color","node","listener","import_core","import_theme","icon","props","_a","color","node","listener","import_core","import_theme","image","props","_a","color","node","listener","import_core","import_theme","inputCheckbox","props","_a","_b","color","accentColor","node","listener","focusRing","import_core","import_theme","inputColor","props","_a","color","node","listener","focusRing","import_core","import_theme","inputDateTime","props","_a","_b","mode","color","accentColor","node","listener","focusRing","import_core","import_theme","inputFile","props","_a","_b","color","accentColor","node","listener","focusRing","import_core","import_theme","inputNumber","props","_a","_b","color","accentColor","node","__spreadProps","__spreadValues","listener","fieldTextStyle","focusRing","import_theme","inputOTP","node","container","getInputs","onInput","e","inputs","target","index","onKeydown","onPaste","_a","_b","_c","text","found","startIdx","char","i","field","lastFilled","import_core","import_theme","EYE_SVG","EYE_OFF_SVG","HOST_FIELD_KEYS","bindReadable","value","listener","inputPassword","props","_a","_b","colorState","accentState","visibleState","hostFields","node","_node","element","host","key","_c","_d","_e","_f","_g","name","onInput","disabled","required","field","__spreadProps","__spreadValues","l","toggle","VALUE_TONE","focusRing","import_core","import_theme","inputRadio","props","_a","_b","color","accentColor","node","listener","focusRing","import_core","import_theme","inputRange","props","_a","_b","color","accentColor","node","listener","focusRing","import_core","import_theme","inputSearch","props","_a","_b","color","accentColor","node","__spreadProps","__spreadValues","listener","fieldTextStyle","focusRing","import_core","import_theme","inputSwitch","props","_a","accentColor","node","listener","focusRing","import_core","import_theme","inputText","props","_a","_b","type","color","accentColor","node","__spreadProps","__spreadValues","listener","fieldTextStyle","focusRing","import_core","import_theme","keyboard","props","_a","color","node","listener","import_core","import_theme","label","props","_a","_b","color","accentColor","node","listener","import_core","import_theme","link","props","_a","_b","color","accentColor","node","event","el","key","listener","focusRing","import_core","import_theme","PADDING_STEPS","GHOST_PADDING","linkButton","props","_a","_b","_c","variant","color","size","fontSize","BUTTON_SIZE_FONT","padding","node","listener","focusRing","isSolid","__spreadProps","__spreadValues","import_core","import_theme","list","props","_a","color","listener","listItem","dense","listItemButton","_b","accentColor","focusRing","import_core","import_theme","mark","props","_a","accentColor","node","listener","import_core","import_theme","menu","props","_a","items","selectable","color","accentColor","activeKey","activeKeyIsCallerOwned","tabbableKey","inner","listener","focused","active","first","buildItems","node","id","item","index","key","__spreadProps","__spreadValues","l","e","k","keys","it","i","idx","next","list","focusRing","attachMenu","_node","initial","current","element","elevation","import_core","prefersReducedMotion","e","isMotionState","value","toStyles","frame","out","transforms","key","toOptions","transition","_a","_b","_c","_d","attachMotion","node","initial","el","current","release","bindAnimate","animate","next","prefersReducedMotion","play","props","mode","target","frames","motion","__spreadProps","__spreadValues","done","inst","exit","import_core","import_theme","orderedList","props","_a","color","node","listener","import_core","import_theme","getPages","current","total","_","i","pages","start","end","persistValue","node","key","incoming","fallback","stored","persistTotal","pagination","props","color","accentColor","buttonBase","listener","focusRing","activeStyle","__spreadProps","__spreadValues","state","totalState","content","page","pageCount","items","ellipsisIndex","p","isActive","snapshot","import_core","import_theme","panelSection","props","_a","padding","divider","color","__spreadValues","listener","import_core","import_theme","paragraph","props","_a","color","node","listener","import_core","import_theme","HASPOPUP_ROLES","panelHaspopup","content","_a","role","patch","declared","own","contentOwnsSurface","patches","popover","props","open","placement","openOn","openState","placeState","show","hide","anchorPartial","createFloating","popoverPartial","l","elevation","triggerPartial","listener","floatingPanelId","_e","node","e","related","floatingEl","import_core","import_theme","popoverArrow","props","placement","color","sideOffset","bordered","place","flipMap","getFlipped","listener","_a","start","pos","end","x","y","import_core","import_theme","preformated","props","_a","color","node","listener","import_core","import_theme","progress","props","_a","_b","color","accentColor","node","listener","import_core","import_theme","isRTL","element","horizontalArrowStep","key","STAR_FILLED","STAR_EMPTY","applyRatingProps","live","next","_a","_b","_c","insertStar","node","index","hoveredState","activeCount","listener","hovered","star","current","e","horizontalArrowStep","target","focusRing","syncStars","children","rating","props","_d","_e","_f","_g","__spreadProps","__spreadValues","initial","import_core","import_theme","ringProgress","props","_a","_b","_c","size","thickness","value","color","trackColor","holePercent","mask","l","node","import_theme","row","props","gap","align","justify","wrap","density","__spreadValues","listener","import_core","import_theme","scrollArea","props","_a","color","__spreadProps","__spreadValues","l","import_core","import_theme","persistValue","node","key","incoming","fallback","stored","moveSegment","e","items","value","_a","k","keys","item","index","idx","next","step","horizontalArrowStep","group","buildSegmentButtons","color","accentColor","l","_b","current","elevation","focusRing","segmented","props","__spreadProps","__spreadValues","element","snapshot","import_theme","select","props","color","accentColor","node","listener","l","svg","_a","isRTL","focusRing","import_core","import_theme","TYPEAHEAD_RESET_MS","resolveTypeahead","node","meta","matchesPrefix","label","needle","selectBox","props","options","placement","color","open","multiple","state","openState","show","hide","anchorPartial","createFloating","popoverPartial","_e","listener","elevation","buildWrap","inner","val","vals","opt","tag","_node","cur","filter","v","attachInner","_inner","next","toggle","panelOf","_a","root","floatingPanelId","moveIntoPanel","toLast","enabledOptionsIn","target","openThenMove","release","subscribeOpen","isOpen","typeahead","key","_b","_c","repeated","matches","el","active","from","partial","__spreadProps","__spreadValues","element","e","kb","focusRing","import_theme","selectItem","props","accentColor","color","value","listener","_a","select","val","_e","node","state","v","focusRing","import_core","import_theme","onListboxKey","event","node","_a","key","host","options","enabledOptionsIn","active","current","next","target","selectList","props","color","multiple","state","inputs","listener","val","v","import_core","import_theme","skeleton","props","_a","color","keyframes","animationName","listener","import_core","import_theme","small","props","_a","color","node","listener","import_core","import_theme","keyframes","animationName","spinner","props","_a","color","node","listener","import_core","import_theme","splitter","props","direction","defaultSize","min","max","_node","element","isFirstSplitterPanel","node","parent","item","splitterPanel","ctx","el","prop","apply","size","release","_a","splitterHandle","label","handle","isHorizontal","releaseAriaValue","onKeydown","e","step","next","dir","horizontalArrowStep","cancelDrag","onPointerdown","container","onPointermove","move","rect","raw","onPointerup","up","listener","focusRing","import_theme","stack","props","gap","align","justify","density","__spreadValues","listener","import_core","import_theme","persistValue","node","key","incoming","fallback","stored","stepConnectorStyle","direction","color","accentColor","l","buildStepItems","items","current","vertical","connector","item","index","_a","cur","__spreadProps","__spreadValues","steps","props","live","element","snapshot","import_core","import_theme","strong","props","_a","color","node","listener","import_core","import_theme","subscript","props","_a","color","node","listener","import_core","import_theme","superscript","props","_a","color","node","listener","import_core","import_theme","table","props","_a","color","node","listener","l","import_core","import_theme","persistValue","node","key","incoming","fallback","stored","buildTabsChildren","items","activeKey","accentColor","color","id","tablist","item","index","_a","l","e","k","keys","it","i","idx","next","step","horizontalArrowStep","list","focusRing","panels","tabs","props","__spreadValues","element","_b","snapshot","import_core","import_theme","textarea","props","_a","_b","color","accentColor","autoResize","__spreadProps","__spreadValues","node","initial","el","enabled","measuring","intersectionObserver","resizeObserver","resize","observe","entries","entry","unobserve","next","listener","fieldTextStyle","focusRing","import_core","import_theme","timeline","timelineItem","props","_a","_b","_c","last","color","accentColor","activeState","__spreadValues","listener","import_core","import_theme","resolveOpenState","node","state","readOpen","listener","DEFAULT_DURATION_MS","_attachAutoDismiss","initial","duration","onDismiss","timer","remaining","startedAt","dismissed","clearTimer","dismiss","arm","ms","pause","resume","element","next","toast","props","position","color","isTop","isCenter","isRight","overlayEle","__spreadProps","__spreadValues","rootNode","overlay","elevation","done","_a","_b","finished","overlayRemoved","overlayEl","removeOverlayIfEmpty","item","it","finish","onEnd","e","import_core","import_theme","persistValue","node","key","incoming","fallback","stored","isPressed","val","moveToggle","e","items","value","multiple","_a","k","keys","item","index","idx","next","step","horizontalArrowStep","group","buildToggleButtons","focusedKey","color","accentColor","l","_b","_c","_d","_e","focused","arr","v","focusRing","toggleGroup","props","__spreadProps","__spreadValues","element","snapshot","toolbar","props","row","toolbarSpacer","import_core","import_theme","tooltip","props","open","placement","content","openDelay","closeDelay","placeState","contentState","contentElement","listener","show","hide","anchorPartial","openState","createFloating","tooltipPartial","elevation","popoverArrow","floatingPanelId","_e","node","e","import_core","getItemId","node","index","transitionGroup","props","duration","delay","previousRects","cancelMap","pendingTimers","pendingFrames","cancel","timer","frame","prefersReducedMotion","item","dom","_a","key","prev","next","deltaX","deltaY","cancelled","finish","onEnd","event","import_core","import_theme","unorderedList","props","_a","color","node","listener","visuallyHidden"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/patches/abbreviation.ts","../src/patches/accordion.ts","../src/utils/focusRing.ts","../src/patches/alert.ts","../src/patches/avatar.ts","../src/patches/badge.ts","../src/patches/blockquote.ts","../src/patches/breadcrumb.ts","../src/patches/breadcrumbEllipsis.ts","../src/patches/button.ts","../src/utils/buttonSize.ts","../src/patches/buttonGhost.ts","../src/patches/buttonSwitch.ts","../src/patches/card.ts","../src/utils/elevation.ts","../src/patches/code.ts","../src/patches/combobox.ts","../src/utils/fieldText.ts","../src/utils/floating.ts","../src/utils/openState.ts","../src/utils/optionList.ts","../src/patches/tag.ts","../src/patches/command.ts","../src/patches/datePicker.ts","../src/patches/descriptionList.ts","../src/patches/details.ts","../src/patches/dialog.ts","../src/utils/scrollLock.ts","../src/patches/divider.ts","../src/patches/drawer.ts","../src/patches/emphasis.ts","../src/patches/empty.ts","../src/patches/errorBoundary.ts","../src/patches/fab.ts","../src/patches/figure.ts","../src/patches/formGroup.ts","../src/patches/grid.ts","../src/patches/heading.ts","../src/patches/horizontalRule.ts","../src/patches/icon.ts","../src/patches/image.ts","../src/patches/inputCheckbox.ts","../src/patches/inputColor.ts","../src/patches/inputDateTime.ts","../src/patches/inputFile.ts","../src/patches/inputNumber.ts","../src/patches/inputOTP.ts","../src/patches/inputPassword.ts","../src/patches/inputRadio.ts","../src/patches/inputRange.ts","../src/patches/inputSearch.ts","../src/patches/inputSwitch.ts","../src/patches/inputText.ts","../src/patches/keyboard.ts","../src/patches/label.ts","../src/patches/link.ts","../src/patches/linkButton.ts","../src/patches/list.ts","../src/patches/mark.ts","../src/patches/menu.ts","../src/patches/motion.ts","../src/utils/reducedMotion.ts","../src/patches/orderedList.ts","../src/patches/pagination.ts","../src/patches/panelSection.ts","../src/patches/paragraph.ts","../src/patches/popover.ts","../src/patches/popoverArrow.ts","../src/patches/preformated.ts","../src/patches/progress.ts","../src/patches/rating.ts","../src/utils/direction.ts","../src/patches/ringProgress.ts","../src/patches/row.ts","../src/patches/scrollArea.ts","../src/patches/segmented.ts","../src/patches/select.ts","../src/patches/selectBox.ts","../src/patches/selectItem.ts","../src/patches/selectList.ts","../src/patches/skeleton.ts","../src/patches/small.ts","../src/patches/spinner.ts","../src/patches/splitter.ts","../src/patches/stack.ts","../src/patches/steps.ts","../src/patches/strong.ts","../src/patches/subscript.ts","../src/patches/superscript.ts","../src/patches/table.ts","../src/patches/tabs.ts","../src/patches/textarea.ts","../src/patches/timeline.ts","../src/patches/toast.ts","../src/patches/toggleGroup.ts","../src/patches/toolbar.ts","../src/patches/tooltip.ts","../src/patches/transitionGroup.ts","../src/patches/unorderedList.ts","../src/patches/visuallyHidden.ts"],"sourcesContent":["export * from \"./classes.js\";\nexport * from \"./patches.js\";\nexport * from \"./types.js\";\nexport * from \"./utils.js\";\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * Styles an abbreviation/acronym with a dotted underline and a \"help\" cursor,\n * shifting to the accent color on hover. Apply to an `<abbr>` element.\n *\n * @hostTag abbr\n * @param props.color - Base text/decoration color tone. Optional `ValueOrState<ThemeColor>`, default \"neutral\".\n * @param props.accentColor - Hover color tone. Optional `ValueOrState<ThemeColor>`, default \"primary\".\n * @example { abbr: \"HTML\", title: \"HyperText Markup Language\", $: [abbreviation({ accentColor: \"primary\" })] }\n */\nfunction abbreviation(\n props: {\n color?: ValueOrState<ThemeColor>;\n accentColor?: ValueOrState<ThemeColor>;\n } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n const accentColor = toState(props.accentColor ?? \"primary\", \"accentColor\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"abbr\") {\n console.warn(`\"abbreviation\" primitive patch must use abbr tag`);\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener),\n backgroundColor: (listener) => themeColor(listener),\n color: (listener) =>\n themeColor(listener, \"shift-10\", color.get(listener)),\n textDecorationLine: \"underline\",\n textDecorationStyle: \"dotted\",\n textDecorationColor: (listener) =>\n themeColor(listener, \"shift-7\", color.get(listener)),\n textUnderlineOffset: themeSpacing(0.72),\n cursor: \"help\",\n \"&:hover\": {\n color: (listener) =>\n themeColor(listener, \"shift-11\", accentColor.get(listener)),\n textDecorationColor: (listener) =>\n themeColor(listener, \"shift-9\", accentColor.get(listener)),\n },\n },\n };\n}\n\nexport { abbreviation };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * Container patch that groups `<details>` elements into a bordered accordion.\n * In `type: \"single\"` mode (default), opening one item closes all siblings.\n *\n * @param props.type - `\"single\"` (default) or `\"multiple\"`. Single mode auto-closes siblings.\n * @param props.color - Theme color tone for borders and backgrounds. Defaults to `\"neutral\"`.\n * @param props.accentColor - Accent color for focus rings on summary. Defaults to `\"primary\"`.\n * @example\n * { div: [\n * { details: [{ summary: \"Section A\" }, { p: \"Content A\" }], $: [details()] },\n * { details: [{ summary: \"Section B\" }, { p: \"Content B\" }], $: [details()] },\n * ], $: [accordion()] }\n */\nfunction accordion(\n props: {\n type?: \"single\" | \"multiple\";\n color?: ValueOrState<ThemeColor>;\n accentColor?: ValueOrState<ThemeColor>;\n } = {},\n): PartialElement {\n const { type = \"single\" } = props;\n const color = toState(props.color ?? \"neutral\", \"color\");\n const accentColor = toState(props.accentColor ?? \"primary\", \"accentColor\");\n\n return {\n _onMount: (node) => {\n const el = node.domElement;\n if (!el) return;\n\n if (type === \"single\") {\n const handler = (event: Event) => {\n const summary = (event.target as Element).closest(\"summary\");\n if (!summary) return;\n const item = summary.closest(\"details\") as HTMLDetailsElement | null;\n if (!item || item.parentElement !== el) return;\n if (!item.open) {\n Array.from(el.querySelectorAll(\":scope > details\")).forEach(\n (detail) => {\n if (detail !== item)\n (detail as HTMLDetailsElement).open = false;\n },\n );\n }\n };\n el.addEventListener(\"click\", handler);\n node.addHook(\"Remove\", () => el.removeEventListener(\"click\", handler));\n }\n\n // WAI-ARIA APG accordion pattern (optional, both modes): ArrowUp/Down\n // moves focus between headers, Home/End jump to the first/last. Tab\n // already reaches every summary; this is an accelerator on top of it.\n const onKeyDown = (event: Event) => {\n const key = (event as KeyboardEvent).key;\n if (![\"ArrowUp\", \"ArrowDown\", \"Home\", \"End\"].includes(key)) return;\n const summary = (event.target as Element).closest(\"summary\");\n if (!summary) return;\n const item = summary.closest(\"details\") as HTMLDetailsElement | null;\n if (!item || item.parentElement !== el) return;\n const summaries = Array.from(\n el.querySelectorAll<HTMLElement>(\":scope > details > summary\"),\n );\n const index = summaries.indexOf(summary as HTMLElement);\n if (index === -1) return;\n let next = index;\n if (key === \"ArrowDown\") next = (index + 1) % summaries.length;\n else if (key === \"ArrowUp\")\n next = (index - 1 + summaries.length) % summaries.length;\n else if (key === \"Home\") next = 0;\n else if (key === \"End\") next = summaries.length - 1;\n event.preventDefault();\n summaries[next]?.focus();\n };\n el.addEventListener(\"keydown\", onKeyDown);\n node.addHook(\"Remove\", () =>\n el.removeEventListener(\"keydown\", onKeyDown),\n );\n },\n style: {\n display: \"flex\",\n flexDirection: \"column\",\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", color.get(listener))}`,\n outlineOffset: \"-1px\",\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n overflow: \"hidden\",\n \"& > details\": {\n borderBottom: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", color.get(listener))}`,\n },\n \"& > details:last-child\": {\n borderBottom: \"none\",\n },\n \"& > details > summary:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, accentColor.get(listener)),\n },\n },\n };\n}\n\nexport { accordion };\n","import type { Listener } from \"@domphy/core\";\nimport { type ThemeColor, themeColor } from \"@domphy/theme\";\n\n/**\n * Shared `:focus-visible` ring — ring-offset pattern used by Radix / shadcn /\n * Vercel / Linear:\n *\n * 1. 2px \"gap\" in the surface tone (reads as space between control + ring)\n * 2. 2px accent halo outside that gap\n *\n * Implemented as a layered `box-shadow` so it composes with a control's own\n * resting outline / elevation instead of replacing them. Prefer this over a\n * flush `0 0 0 2px` ring (looks like a thick pastel border glued to the edge)\n * and over the browser default outline.\n *\n * Accent at `shift-9` stays legible on both light and dark surfaces; the\n * washed `shift-6` flush ring is what made focus look broken in product UIs.\n */\nfunction focusRing(listener: Listener, color: ThemeColor = \"primary\"): string {\n const gap = themeColor(listener, \"surface\");\n const ring = themeColor(listener, \"shift-9\", color);\n return `0 0 0 2px ${gap}, 0 0 0 4px ${ring}`;\n}\n\nexport { focusRing };\n","import type { PartialElement } from \"@domphy/core\";\nimport { toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * A semantic alert surface block with a colored inset bar, padding, and\n * `role=\"alert\"`. Typically applied to a `<div>` (any block container).\n *\n * @param props.color - Surface/accent color tone. Optional `ValueOrState<ThemeColor>`, default \"primary\".\n * @example { div: \"Saved successfully\", $: [alert({ color: \"success\" })] }\n */\nfunction alert(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"primary\", \"color\");\n\n return {\n role: \"alert\",\n // Alert is a semantic surface block, so it should shift the local surface context.\n dataTone: \"shift-2\",\n style: {\n display: \"flex\",\n alignItems: \"flex-start\",\n gap: themeSpacing(3),\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 2),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 4),\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n boxShadow: (listener) =>\n `inset ${themeSpacing(1)} 0 0 0 ${themeColor(listener, \"shift-8\", color.get(listener))}`,\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n color: (listener) =>\n themeColor(listener, \"shift-10\", color.get(listener)),\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n },\n };\n}\n\nexport { alert };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n themeWeight,\n} from \"@domphy/theme\";\n\n/**\n * A circular avatar container that centers initials/text and cover-fits any\n * child `<img>`. Typically applied to an inline-flex container such as a `<span>`.\n *\n * @param props.color - Background/foreground color tone. Optional `ValueOrState<ThemeColor>`, default \"primary\".\n * @example { span: \"JD\", $: [avatar({ color: \"primary\" })] }\n */\nfunction avatar(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"primary\", \"color\");\n\n return {\n dataTone: \"shift-2\",\n style: {\n position: \"relative\",\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n overflow: \"hidden\",\n borderRadius: \"50%\",\n flexShrink: 0,\n width: themeSpacing(9),\n height: themeSpacing(9),\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n fontWeight: themeWeight(\"semibold\"),\n userSelect: \"none\",\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n color: (listener) =>\n themeColor(listener, \"shift-11\", color.get(listener)),\n // Hairline so the circle separates from same-tone surfaces.\n boxShadow: (listener) =>\n `0 0 0 1px ${themeColor(listener, \"border\", color.get(listener))}`,\n \"& img\": {\n position: \"absolute\",\n inset: 0,\n width: \"100%\",\n height: \"100%\",\n objectFit: \"cover\",\n },\n },\n };\n}\n\nexport { avatar };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n themeWeight,\n} from \"@domphy/theme\";\n\n/**\n * Renders a small count/label bubble pinned to the top-right corner of its host\n * (via a `::after` pseudo-element). Typically applied to an inline container such\n * as a `<span>` wrapping an icon or element.\n *\n * @param props.color - Badge color tone. Optional `ValueOrState<ThemeColor>`, default \"danger\".\n * @param props.label - Text/number shown in the badge. Optional `ValueOrState<string | number>`, default 999.\n * @example { span: \"🔔\", $: [badge({ label: 3, color: \"danger\" })] }\n */\nfunction badge(\n props: {\n color?: ValueOrState<ThemeColor>;\n label?: ValueOrState<string | number>;\n } = {},\n): PartialElement {\n const { label = 999 } = props;\n const state = toState(label);\n const color = toState(props.color ?? \"danger\", \"color\");\n return {\n style: {\n position: \"relative\",\n \"&::after\": {\n content: (l) => `\"${state.get(l)}\"`,\n position: \"absolute\",\n top: 0,\n insetInlineEnd: 0,\n transform: \"translate(50%,-50%)\",\n // Bare themeSpacing(U) at snapshot time; n = U / 1.5 (light.densities[2]).\n paddingInline: (l) => themeSpacing(themeDensity(l) * (1.5 / 1.5)),\n minWidth: themeSpacing(5),\n height: (l) => themeSpacing(themeDensity(l) * (5 / 1.5)),\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n fontSize: (l) => themeSize(l, \"decrease-2\"),\n fontWeight: themeWeight(\"semibold\"),\n lineHeight: 1,\n borderRadius: (l) => themeSpacing(themeDensity(l) * 999),\n backgroundColor: (l) => themeColor(l, \"shift-9\", color.get(l)),\n color: (l) => themeColor(l, \"shift-0\", color.get(l)),\n // Hairline ring so the pill pops on same-hue surfaces.\n boxShadow: (l) => `0 0 0 1px ${themeColor(l, \"shift-0\", color.get(l))}`,\n },\n },\n };\n}\n\nexport { badge };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * Styles a quotation block with a colored inset side bar, padded surface, and\n * shifted tone. Apply to a `<blockquote>` element.\n *\n * @hostTag blockquote\n * @param props.color - Surface/bar color tone. Optional `ValueOrState<ThemeColor>`, default \"neutral\".\n * @example { blockquote: \"Design is how it works.\", $: [blockquote({ color: \"primary\" })] }\n */\nfunction blockquote(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"blockquote\") {\n console.warn(`\"blockquote\" primitive patch must use blockquote tag`);\n }\n },\n dataTone: \"shift-2\",\n style: {\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n boxShadow: (listener) =>\n `inset ${themeSpacing(1)} 0 0 0 ${themeColor(listener, \"shift-4\", color.get(listener))}`,\n border: \"none\",\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 2),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 4),\n margin: 0,\n },\n };\n}\n\nexport { blockquote };\n","import type { PartialElement } from \"@domphy/core\";\nimport { toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * A horizontal breadcrumb navigation that lays out its children with a\n * separator between items and marks the `[aria-current=page]` item\n * non-interactive. Apply to a `<nav>` element.\n *\n * Does not paint `color` on any crumb — each composed child (`link()` for\n * non-current items, `strong()` for the current one, or any other patch) owns\n * its own color; wrap the current crumb in `strong()` for the usual \"reads\n * stronger\" emphasis rather than relying on breadcrumb to repaint it.\n *\n * @hostTag nav\n * @param props.color - Color tone for the nav's own background/inherited text\n * color and the separator glyphs. Optional `ValueOrState<ThemeColor>`, default \"neutral\".\n * @param props.separator - String inserted between items via `::after`. Optional `string`, default \"/\".\n * @example\n * { nav: [\n * { a: \"Home\", href: \"#\", $: [link()] },\n * { strong: \"Settings\", ariaCurrent: \"page\", $: [strong()] },\n * ], $: [breadcrumb({ separator: \"›\" })] }\n */\nfunction breadcrumb(\n props: { color?: ValueOrState<ThemeColor>; separator?: string } = {},\n): PartialElement {\n const { separator = \"/\" } = props;\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"nav\")\n console.warn('\"breadcrumb\" patch must use nav tag');\n },\n // The `::after` separator glyph below sits at \"muted\" (shift-8, an 8-step\n // gap) — WCAG 1.4.3 exempts pure decoration, and the hierarchy it hints at\n // is already carried by the links themselves. Measured 4.06:1 light /\n // 4.24:1 dark. Declared here so the decision lives with the patch instead\n // of surfacing as an un-actionable info at all 26 breadcrumb call sites.\n _doctorDisable: \"low-contrast\",\n ariaLabel: \"breadcrumb\",\n style: {\n display: \"flex\",\n alignItems: \"center\",\n flexWrap: \"wrap\",\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n gap: themeSpacing(1),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n // No `color` here: `color` inherits from the nav's own style above, so a\n // plain crumb (no patch of its own) already reads at \"text\" tone without\n // this rule repeating it — and repeating it at (0,1,0)+combinator\n // specificity used to tie (or beat, depending on injection order) a\n // composed crumb's own generated class, silently forcing link()'s\n // themed color or strong()'s emphasis color back to plain \"text\" (measured:\n // packages/blocks' shadcn sidebar breadcrumb, doctor's\n // descendant-color-override rule, 10 call sites).\n \"& > *\": {\n display: \"inline-flex\",\n alignItems: \"center\",\n },\n \"& > *:not(:last-child)::after\": {\n content: `\"${separator}\"`,\n // shift-4 measured 1.94:1 on the page surface (light) — the glyph was\n // all but invisible. \"muted\" is the de-emphasis tone shadcn's\n // breadcrumb separator uses (4.06:1 light / 4.24:1 dark).\n color: (listener) => themeColor(listener, \"muted\", color.get(listener)),\n paddingInlineStart: themeSpacing(1),\n },\n // No `color` here either, same reasoning as \"& > *\" above: the composed\n // crumb owns its own color (strong()'s shift-11, link()'s shift-13, or\n // nav's inherited \"text\" for a bare crumb) and breadcrumb does not\n // silently repaint it — measured via getComputedStyle in real Chromium\n // that a `color` here, even boosted to (0,3,0) specificity so it always\n // wins, forced strong()'s current-crumb text from its own shift-11 down\n // to breadcrumb's shift-10. A bare-text current crumb that wants visual\n // emphasis is the CALLER's recipe to add (wrap it in strong()), not\n // something breadcrumb prescribes for every consumer. `pointerEvents`\n // stays: the current item should not be clickable regardless of what\n // colors it.\n \"& > [aria-current=page]\": {\n pointerEvents: \"none\",\n },\n },\n };\n}\n\nexport { breadcrumb };\n","import type { PartialElement } from \"@domphy/core\";\nimport { toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n textToneOn,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * An ellipsis trigger button for collapsed breadcrumb items, with hover and\n * focus-visible states. Apply to a `<button>` element.\n *\n * @hostTag button\n * @param props.color - Color tone for the trigger. Optional `ValueOrState<ThemeColor>`, default \"neutral\".\n * @example { button: \"…\", $: [breadcrumbEllipsis({ color: \"neutral\" })] }\n */\nfunction breadcrumbEllipsis(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n // Native `type` on the host still wins (mergePartial: native over patch).\n type: \"button\",\n _onInsert: (node) => {\n if (node.tagName !== \"button\") {\n console.warn('\"breadcrumbEllipsis\" patch must use button tag');\n }\n },\n ariaLabel: \"More breadcrumb items\",\n style: {\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n paddingInline: themeSpacing(1),\n border: \"none\",\n background: \"none\",\n cursor: \"pointer\",\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n borderRadius: themeSpacing(1),\n transition:\n \"color 140ms ease, background-color 140ms ease, box-shadow 140ms ease\",\n \"&:hover\": {\n // Tracks the +2 hover fill; shift-10 left a gap of 8 (4.34:1).\n color: (listener) =>\n themeColor(listener, textToneOn(2), color.get(listener)),\n backgroundColor: (listener) =>\n themeColor(listener, \"hover\", color.get(listener)),\n },\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, color.get(listener)),\n },\n },\n };\n}\n\nexport { breadcrumbEllipsis };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { BUTTON_SIZE_FONT, type ButtonSize } from \"../utils/buttonSize.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\nimport { buttonGhost } from \"./buttonGhost.js\";\n\ntype ButtonVariant = \"solid\" | \"outline\" | \"ghost\";\n\nconst PADDING_STEPS: Record<ButtonSize, { block: number; inline: number }> = {\n small: { block: 0.5, inline: 2 },\n medium: { block: 1, inline: 3 },\n large: { block: 1.5, inline: 4 },\n};\n\n/**\n * A themed button control with density-aware padding/radius and hover, pressed\n * (`:active` ±2), focus-visible, `[disabled]`, and `[aria-busy=true]` states.\n * Apply to a `<button>` element.\n *\n * @hostTag button\n * @param props.color - Button color tone. Optional `ValueOrState<ThemeColor>`, default \"primary\".\n * @param props.variant - Visual style: `\"outline\"` (tinted background + outline, default,\n * backward compatible), `\"solid\"` (filled background, readable contrast text), or `\"ghost\"`\n * (no background/border — delegates to `buttonGhost()` so the two stay visually identical).\n * @param props.size - Button size preset. Optional `\"small\" | \"medium\" | \"large\"`, defaults to `\"medium\"`.\n * @example { button: \"Save\", $: [button({ color: \"primary\" })] }\n * @example { button: \"Delete\", $: [button({ color: \"error\", variant: \"solid\" })] }\n */\nfunction button(\n props: {\n color?: ValueOrState<ThemeColor>;\n variant?: ButtonVariant;\n size?: ButtonSize;\n } = {},\n): PartialElement {\n const variant = props.variant ?? \"outline\";\n if (variant === \"ghost\") {\n return buttonGhost({ color: props.color, size: props.size });\n }\n\n const color = toState(props.color ?? \"primary\", \"color\");\n const isSolid = variant === \"solid\";\n const padding = PADDING_STEPS[props.size ?? \"medium\"];\n const fontSize = BUTTON_SIZE_FONT[props.size ?? \"medium\"];\n\n return {\n // Native `type` on the host still wins (mergePartial: native over patch).\n type: \"button\",\n _onInsert: (node) => {\n if (node.tagName !== \"button\") {\n console.warn(`\"button\" primitive patch must use button tag`);\n }\n },\n // Solid: deep brand fill (shift-13) + light-end neutral text (shift-0).\n // Mid-ramp shift-8 failed WCAG (~2.2:1 white-on-medium). NOT dataTone-17\n // (that collapsed every color into a near-black pill). Outline text:\n // shift-13 for ≥4.5:1 on light surfaces (shift-9 failed at ~2.57).\n ...(isSolid\n ? {\n _doctorDisable: [\n \"low-contrast\",\n \"color-shift-minimum\",\n \"tone-background-inherit\",\n ] as const,\n }\n : {}),\n style: {\n appearance: \"none\",\n fontSize: (listener) => themeSize(listener, fontSize),\n // Single-line bounded control: block/radius = 1D, inline = 3D.\n paddingBlock: (listener) =>\n themeSpacing(themeDensity(listener) * padding.block),\n paddingInline: (listener) =>\n themeSpacing(themeDensity(listener) * padding.inline),\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n width: \"fit-content\",\n display: \"flex\",\n justifyContent: \"center\",\n alignItems: \"center\",\n gap: (listener) => themeSpacing(themeDensity(listener) * 1),\n userSelect: \"none\",\n cursor: \"pointer\",\n lineHeight: \"inherit\",\n border: \"none\",\n outlineOffset: \"-1px\",\n outlineWidth: \"1px\",\n outline: isSolid\n ? \"none\"\n : (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", color.get(listener))}`,\n color: (listener) =>\n isSolid\n ? themeColor(listener, \"shift-0\", \"neutral\")\n : themeColor(listener, \"shift-13\", color.get(listener)),\n backgroundColor: (listener) =>\n isSolid\n ? themeColor(listener, \"shift-13\", color.get(listener))\n : themeColor(listener, \"inherit\", color.get(listener)),\n transition:\n \"background-color 140ms ease, color 140ms ease, border-color 140ms ease, box-shadow 140ms ease\",\n \"&:hover:not([disabled]):not([aria-busy=true])\": {\n color: (listener) =>\n isSolid\n ? themeColor(listener, \"shift-0\", \"neutral\")\n : themeColor(listener, \"shift-14\", color.get(listener)),\n backgroundColor: (listener) =>\n isSolid\n ? themeColor(listener, \"shift-14\", color.get(listener))\n : themeColor(listener, \"hover\", color.get(listener)),\n },\n // Pressed: solid steps deeper on the brand ramp; outline uses +2 surface.\n \"&:active:not([disabled]):not([aria-busy=true])\": {\n backgroundColor: (listener) =>\n isSolid\n ? themeColor(listener, \"shift-15\", color.get(listener))\n : themeColor(listener, \"increase-2\", color.get(listener)),\n },\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, color.get(listener)),\n },\n \"&[disabled]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-2\", \"neutral\"),\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", \"neutral\")}`,\n color: (listener) => themeColor(listener, \"muted\", \"neutral\"),\n },\n \"&[aria-busy=true]\": {\n opacity: 0.7,\n cursor: \"wait\",\n pointerEvents: \"none\",\n },\n },\n };\n}\n\nexport { button };\nexport type { ButtonVariant };\n","/**\n * The `fontSize` step for `button()`/`buttonGhost()`'s `size` prop. Padding stays\n * per-component (button and buttonGhost start from different base paddings) so\n * only the part that's genuinely identical — the font-size step — lives here.\n */\nconst BUTTON_SIZE_FONT = {\n small: \"decrease-1\",\n medium: \"inherit\",\n large: \"increase-1\",\n} as const;\n\ntype ButtonSize = keyof typeof BUTTON_SIZE_FONT;\n\nexport { BUTTON_SIZE_FONT };\nexport type { ButtonSize };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n textToneOn,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { BUTTON_SIZE_FONT, type ButtonSize } from \"../utils/buttonSize.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\nconst PADDING_STEPS: Record<ButtonSize, number> = {\n small: 0.5,\n medium: 1,\n large: 1.5,\n};\n\n/**\n * A transparent button with no border or background — suitable for icon\n * actions, inline controls, and delete/close triggers. Apply to a `<button>`\n * element.\n *\n * @hostTag button\n * @param props.color - Text color tone. Optional `ValueOrState<ThemeColor>`, defaults to `\"neutral\"`.\n * @param props.size - Button size preset. Optional `\"small\" | \"medium\" | \"large\"`, defaults to `\"medium\"`.\n * @example { button: \"×\", $: [buttonGhost()] }\n * @example { button: [{ span: \"🗑\", $: [icon()] }], $: [buttonGhost({ color: \"error\" })] }\n */\nfunction buttonGhost(\n props: { color?: ValueOrState<ThemeColor>; size?: ButtonSize } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n const padding = PADDING_STEPS[props.size ?? \"medium\"];\n const fontSize = BUTTON_SIZE_FONT[props.size ?? \"medium\"];\n\n return {\n // Native `type` on the host still wins (mergePartial: native over patch).\n type: \"button\",\n _onInsert: (node) => {\n if (node.tagName !== \"button\") {\n console.warn(`\"buttonGhost\" primitive patch must use button tag`);\n }\n },\n style: {\n appearance: \"none\",\n fontSize: (listener) => themeSize(listener, fontSize),\n paddingBlock: (listener) =>\n themeSpacing(themeDensity(listener) * padding),\n paddingInline: (listener) =>\n themeSpacing(themeDensity(listener) * padding),\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n display: \"inline-flex\",\n // Same as button(): without it a flex/grid parent stretches the control\n // to the full column. Measured in Chromium inside a `stack()`: an\n // outline button was 88px wide and the ghost button next to it 1232px,\n // although `button({ variant: \"ghost\" })` documents the two as visually\n // identical.\n width: \"fit-content\",\n justifyContent: \"center\",\n alignItems: \"center\",\n gap: (listener) => themeSpacing(themeDensity(listener) * 1),\n userSelect: \"none\",\n cursor: \"pointer\",\n lineHeight: \"inherit\",\n border: \"none\",\n background: \"none\",\n outline: \"none\",\n transition:\n \"background-color 140ms ease, color 140ms ease, box-shadow 140ms ease\",\n // Resting text uses the \"text\" alias (shift-9) — NOT the semantic-zone\n // shift-6 the patch previously used. A ghost button's label is essential\n // interactive content, and shift-6 on an edge surface measures ~2.4:1,\n // failing WCAG AA (axe color-contrast). shadcn's ghost variant likewise\n // rests at full foreground; hover/active keep the same text color and\n // differentiate via background only.\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n // Hover/active paint a fill 2 steps off the surface, so the label moves\n // with it (textToneOn) — a fixed \"text\" label measured 3.58:1 on the\n // hover fill (light) / 4.37:1 (dark), below WCAG AA.\n \"&:hover:not([disabled]):not([aria-busy=true])\": {\n color: (listener) =>\n themeColor(listener, textToneOn(2), color.get(listener)),\n backgroundColor: (listener) =>\n themeColor(listener, \"hover\", color.get(listener)),\n },\n \"&:active:not([disabled]):not([aria-busy=true])\": {\n color: (listener) =>\n themeColor(listener, textToneOn(2), color.get(listener)),\n backgroundColor: (listener) =>\n themeColor(listener, \"increase-2\", color.get(listener)),\n },\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, color.get(listener)),\n },\n \"&[disabled]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n color: (listener) => themeColor(listener, \"border-strong\", \"neutral\"),\n },\n \"&[aria-busy=true]\": {\n opacity: 0.7,\n cursor: \"wait\",\n pointerEvents: \"none\",\n },\n },\n };\n}\n\nexport { buttonGhost };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n textToneOn,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * A pill-shaped toggle switch with `role=\"switch\"`; clicking flips the bound\n * `checked` state and slides the thumb. Apply to a `<button>` element.\n *\n * @hostTag button\n * @param props.checked - Toggle state. Optional `ValueOrState<boolean>`, default false.\n * @param props.accentColor - Color tone when checked (on). Optional `ValueOrState<ThemeColor>`, default \"primary\".\n * @param props.color - Color tone when unchecked (off track). Optional `ValueOrState<ThemeColor>`, default \"neutral\".\n * @example { button: [{ span: null }], $: [buttonSwitch({ checked: true })] }\n */\nfunction buttonSwitch(\n props: {\n checked?: ValueOrState<boolean>;\n accentColor?: ValueOrState<ThemeColor>;\n color?: ValueOrState<ThemeColor>;\n } = {},\n): PartialElement {\n const { checked = false } = props;\n\n const check = toState(checked);\n const color = toState(props.color ?? \"neutral\", \"color\");\n const accentColor = toState(props.accentColor ?? \"primary\", \"accentColor\");\n\n return {\n // Native `type` on the host still wins (mergePartial: native over patch).\n type: \"button\",\n _onSchedule: (node) => {\n if (node.tagName !== \"button\") {\n console.warn(`\"buttonSwitch\" primitive patch must use button tag`);\n }\n },\n role: \"switch\",\n // A <button> is not a labelable element, so <label for> cannot name it and\n // the thumb span carries no text — the control had NO accessible name at\n // all (axe `button-name`). A host-declared aria-label/aria-labelledby\n // still wins over this default.\n ariaLabel: \"Toggle\",\n ariaChecked: (listener) => check.get(listener),\n dataTone: \"shift-2\",\n onClick: () => check.set(!check.get()),\n style: {\n position: \"relative\",\n display: \"inline-flex\",\n alignItems: \"center\",\n fontSize: (listener) => themeSize(listener),\n border: \"none\",\n outlineWidth: \"1px\",\n // WCAG 2.1 SC 1.4.11 Non-text Contrast: the OFF track is tone-inherited\n // and sits at ~1.4:1 against the page, so the boundary has to carry the\n // 3:1. \"border\" (shift-3) measured 1.64:1 in Chromium; shift-7 measures\n // 3.32:1 (light) / 3.50:1 (dark).\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"shift-7\", color.get(listener))}`,\n minWidth: themeSpacing(12),\n minHeight: themeSpacing(6),\n // A switch is a fixed-size track, never a full-width bar. Measured in\n // Chromium: inside a `stack()` the 48px pill stretched to 1232px and the\n // thumb (absolutely positioned from the left edge) floated alone at the\n // far end of it. `inline-flex` does not survive flex/grid blockification.\n width: \"fit-content\",\n flexShrink: 0,\n borderRadius: themeSpacing(999),\n paddingInlineStart: themeSpacing(7),\n paddingInlineEnd: themeSpacing(2),\n cursor: \"pointer\",\n transition:\n \"padding-inline-start 0.3s, padding-inline-end 0.3s, background-color 140ms ease, box-shadow 140ms ease\",\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, accentColor.get(listener)),\n },\n \"& > :first-child\": {\n content: '\"\"',\n position: \"absolute\",\n display: \"inline-flex\",\n alignItems: \"center\",\n insetInlineStart: themeSpacing(0.5),\n top: \"50%\",\n transform: \"translateY(-50%)\",\n transition: \"inset-inline-start 0.3s\",\n width: themeSpacing(5),\n height: themeSpacing(5),\n borderRadius: themeSpacing(999),\n color: (listener) => themeColor(listener, \"text\"),\n backgroundColor: (listener) =>\n themeColor(listener, \"decrease-2\", color.get(listener)),\n // The thumb is tone-inherited too — same 1.4:1 problem as the track.\n // Its own boundary makes the ON/OFF position identifiable on either\n // track colour (SC 1.4.11), the way Radix rings its switch thumb.\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"shift-7\", color.get(listener))}`,\n outlineOffset: \"-1px\",\n },\n \"&[aria-checked=true]\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"increase-3\", accentColor.get(listener)),\n outline: \"none\",\n // Host label tracks the ON fill (+3 off this element's own shift-2\n // anchor). `decrease-2` pinned it to the light end of the ramp and\n // measured 2.48:1 (light) / 1.87:1 (dark) on that fill.\n color: (listener) =>\n themeColor(listener, textToneOn(3), accentColor.get(listener)),\n paddingInlineStart: themeSpacing(2),\n paddingInlineEnd: themeSpacing(7),\n },\n \"&[aria-checked=true] > :first-child\": {\n insetInlineStart: `calc(100% - ${themeSpacing(5.5)})`,\n },\n \"&[disabled]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n },\n },\n };\n}\n\nexport { buttonSwitch };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSpacing,\n themeWeight,\n} from \"@domphy/theme\";\nimport { elevation } from \"../utils/elevation.js\";\n\n/**\n * A grid-based card surface that auto-places known child elements into named\n * regions: `<img>` (image), headings (title), `<p>` (description), `<aside>`\n * (aside), `<div>` (content), and `<footer>` (footer). Typically applied to a\n * `<div>` (any block container).\n *\n * @param props.color - Surface/border color tone. Optional `ValueOrState<ThemeColor>`, default \"neutral\".\n * @example { div: [{ h3: \"Title\", $: [heading()] }, { p: \"Body\", $: [paragraph()] }], $: [card({ color: \"neutral\" })] }\n */\nfunction card(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n return {\n style: {\n display: \"grid\",\n gridTemplateColumns: \"1fr auto\",\n gridTemplateAreas:\n '\"image image\" \"title aside\" \"desc aside\" \"content content\" \"footer footer\"',\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 2),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n color: (listener) =>\n themeColor(listener, \"shift-10\", color.get(listener)),\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", color.get(listener))}`,\n outlineOffset: \"-1px\",\n // Soft lift so cards separate from the page without looking like dialogs.\n boxShadow: elevation(\"low\"),\n overflow: \"hidden\",\n \"& > img\": {\n gridArea: \"image\",\n width: \"100%\",\n height: \"auto\",\n display: \"block\",\n },\n \"& > :is(h1,h2,h3,h4,h5,h6)\": {\n gridArea: \"title\",\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 2),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 4),\n fontWeight: themeWeight(\"semibold\"),\n color: (listener) =>\n themeColor(listener, \"shift-11\", color.get(listener)),\n margin: 0,\n },\n \"& > p\": {\n gridArea: \"desc\",\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 4),\n paddingBottom: (listener) => themeSpacing(themeDensity(listener) * 2),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n margin: 0,\n },\n \"& > aside\": {\n gridArea: \"aside\",\n alignSelf: \"center\",\n padding: (listener) => themeSpacing(themeDensity(listener) * 2),\n height: \"auto\",\n },\n // No `color` here: it repeated the exact same shift-10 the card's own\n // top-level `color` above already sets (and this content area inherits),\n // at (0,1,0)+combinator specificity that used to silently outrank a\n // composed child's own generated-class color — e.g. a `chart()`-mounted\n // div's own styling (packages/blocks' chart-bar/-line-interactive\n // recipes, doctor's descendant-color-override rule).\n \"& > div\": {\n gridArea: \"content\",\n padding: (listener) => themeSpacing(themeDensity(listener) * 4),\n },\n \"& > footer\": {\n gridArea: \"footer\",\n display: \"flex\",\n gap: themeSpacing(2),\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 2),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 4),\n borderTop: (listener) =>\n `1px solid ${themeColor(listener, \"border\", color.get(listener))}`,\n },\n },\n };\n}\n\nexport { card };\n","/** Named elevation levels for floating/raised surfaces. */\ntype ElevationLevel = \"low\" | \"medium\" | \"high\";\n\n// Layered soft shadows (a tight contact shadow + a broad ambient one), black at\n// low alpha so the same value reads correctly on both light and dark surfaces\n// without a theme/context lookup.\nconst SHADOWS: Record<ElevationLevel, string> = {\n low: \"0 1px 2px rgba(0,0,0,0.08), 0 4px 10px rgba(0,0,0,0.10)\",\n medium: \"0 2px 4px rgba(0,0,0,0.10), 0 10px 24px rgba(0,0,0,0.14)\",\n high: \"0 6px 12px rgba(0,0,0,0.14), 0 24px 48px rgba(0,0,0,0.20)\",\n};\n\n/**\n * Shared box-shadow value for a named elevation level. Used by floating/raised\n * surface patches (popover, menu, dialog, drawer, toast, tooltip, combobox/\n * selectBox dropdown, datePicker popup, fab) so elevation reads consistently\n * across the library instead of each patch picking its own shadow.\n */\nfunction elevation(level: ElevationLevel): string {\n return SHADOWS[level];\n}\n\nexport { elevation };\nexport type { ElevationLevel };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeFont,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * Styles an inline code snippet in the theme's monospace stack, with a subtle\n * surface background, rounded corners, and shifted tone. Apply to a `<code>` element.\n *\n * @hostTag code\n * @param props.color - Surface/text color tone. Optional `ValueOrState<ThemeColor>`, default \"neutral\".\n * @example { code: \"npm install\", $: [code({ color: \"neutral\" })] }\n */\nfunction code(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n dataTone: \"shift-2\",\n _onInsert: (node) => {\n if (node.tagName !== \"code\") {\n console.warn(`\"code\" primitive patch must use code tag`);\n }\n },\n style: {\n display: \"inline-flex\",\n alignItems: \"center\",\n whiteSpace: \"nowrap\",\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n // The theme owns the code stack; <code>/<kbd>/<pre> otherwise keep the\n // UA generic \"monospace\" (Courier New on Windows), so a theme that swaps\n // fontFamilies.monospace never reaches them.\n fontFamily: themeFont(\"monospace\"),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n // Bare themeSpacing(U) at snapshot time; n = U / 1.5 (light.densities[2]).\n height: (listener) => themeSpacing(themeDensity(listener) * (6 / 1.5)),\n paddingInline: (listener) =>\n themeSpacing(themeDensity(listener) * (1.5 / 1.5)),\n borderRadius: (listener) =>\n themeSpacing(themeDensity(listener) * (1 / 1.5)),\n },\n };\n}\n\nexport { code };\n","import {\n type BehaviorInstance,\n behavior,\n type DomphyElement,\n type ElementNode,\n merge,\n type PartialElement,\n type State,\n type StyleObject,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport type { Placement } from \"@domphy/floating\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { elevation } from \"../utils/elevation.js\";\nimport { fieldTextStyle } from \"../utils/fieldText.js\";\nimport { createFloating, floatingPanelId } from \"../utils/floating.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\nimport { subscribeOpen } from \"../utils/openState.js\";\nimport { enabledOptionsIn } from \"../utils/optionList.js\";\nimport { tag } from \"./tag.js\";\n\n/**\n * A combobox/multi-select control: renders selected options as removable tags\n * plus an input, and shows a floating popover (`content`) anchored to the host.\n * Apply to a `<div>` element.\n *\n * @hostTag div\n * @param props.multiple - Allow selecting multiple values (popover stays open on click). Optional `boolean`, default false.\n * @param props.value - Selected value(s). Optional `ValueOrState<Array<number | string | null | undefined> | number | string | null | undefined>`, no default.\n * @param props.options - Available `{ label, value }` options used to render selected tags. Optional `Array<{ label: string; value: string }>`, default `[]`.\n * @param props.placement - Floating popover placement. Optional `ValueOrState<Placement>`, default \"bottom\".\n * @param props.content - The floating popover content element. Required `DomphyElement`.\n * @param props.color - Color tone for the control. Optional `ThemeColor`, default \"neutral\".\n * @param props.open - Whether the popover is open. Optional `ValueOrState<boolean>` (including `Computed`/`ReadableState`), default false. When the source is read-only, pass `onDismiss` so dismiss can close.\n * @param props.onDismiss - Called when the popover requests close. Optional. Required to close when `open` is a read-only `Computed`/`ReadableState`.\n * @param props.input - Custom input element; when omitted a default `<input>` is created. Optional `DomphyElement`.\n * @example { div: null, $: [combobox({ options: [{ label: \"A\", value: \"a\" }], content: { div: null } })] }\n */\nfunction combobox(props: {\n multiple?: boolean;\n value?: ValueOrState<\n | Array<number | string | null | undefined>\n | number\n | string\n | null\n | undefined\n >;\n options?: Array<{ label: string; value: string }>;\n placement?: ValueOrState<Placement>;\n content: DomphyElement;\n color?: ThemeColor;\n open?: ValueOrState<boolean>;\n onDismiss?: () => void;\n input?: DomphyElement;\n}): PartialElement {\n const {\n options = [],\n placement = \"bottom\",\n color = \"neutral\",\n open = false,\n multiple = false,\n } = props;\n\n const state = toState(props.value);\n const openState = toState(open);\n const { show, hide, anchorPartial } = createFloating({\n kind: \"combobox\",\n open: openState,\n onDismiss: props.onDismiss,\n placement: toState(placement),\n content: props.content,\n });\n\n const popoverPartial: PartialElement = {\n onClick: (_e, node) => !multiple && hide(node),\n dataTone: \"shift-0\",\n style: {\n backgroundColor: (listener) => themeColor(listener, \"inherit\"),\n // Surface contract (dataTone-surface-contract): a tone-anchored panel\n // must declare BOTH background and text color. Page-matching shift-0\n // (same as menu/selectList/dialog), not the inverted tooltip surface.\n color: (listener) => themeColor(listener, \"text\"),\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 2),\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\")}`,\n outlineOffset: \"-1px\",\n boxShadow: elevation(\"medium\"),\n },\n };\n\n merge(props.content, popoverPartial);\n\n const inputStyle: StyleObject = {\n border: \"none\",\n outline: \"none\",\n padding: 0,\n margin: 0,\n flex: 1,\n height: themeSpacing(6),\n marginInlineStart: themeSpacing(2),\n fontSize: (listener: any) => themeSize(listener, \"inherit\"),\n // Without an explicit rule the placeholder falls back to the UA default\n // (`darkgray` on the Chrome 88-class engines Domphy ships into — 2.3:1 on\n // a light field).\n ...fieldTextStyle(color),\n backgroundColor: (listener: any) => themeColor(listener, \"inherit\", color),\n };\n\n type InnerProps = {\n options: Array<{ label: string; value: string }>;\n multiple: boolean;\n color: ThemeColor;\n state: State<\n | Array<number | string | null | undefined>\n | number\n | string\n | null\n | undefined\n >;\n input?: DomphyElement;\n };\n\n type ComboboxInner = BehaviorInstance<InnerProps> & {\n query: State<string>;\n };\n\n const readQuery = (listener?: { elementNode?: ElementNode }) =>\n listener?.elementNode?.getBehavior<ComboboxInner>(\"comboboxInner\")?.query;\n\n const findComboboxAnchor = (from: ElementNode): ElementNode => {\n let current: ElementNode | null = from;\n while (current) {\n if (current._behaviorInstances.has(\"floating:combobox\")) return current;\n current = current.parent;\n }\n return from;\n };\n\n // WAI-ARIA APG \"Combobox with List Autocomplete\": Down/Up move into the\n // popup, Enter with nothing highlighted just closes it. Escape is already\n // handled document-wide by createFloating. Without this the popup was\n // mouse-only — Tab from the input skipped straight past every option.\n const moveIntoPanel = (node: ElementNode, toLast: boolean): void => {\n const anchor = findComboboxAnchor(node);\n const root = anchor.getRoot().domElement as Element | null;\n const panel =\n root?.querySelector(`#${floatingPanelId(\"combobox\", anchor)}`) ?? null;\n const options = enabledOptionsIn(panel);\n if (!options.length) return;\n const target = options[toLast ? options.length - 1 : 0]!;\n target.focus();\n target.scrollIntoView?.({ block: \"nearest\" });\n };\n\n // show() is debounced by 100ms and flips `openState` only AFTER mounting the\n // panel, so waiting on that flip is exact where a fixed delay is not: a bare\n // requestAnimationFrame (~16ms) ran while the panel did not exist yet, and\n // in Chromium the first ArrowDown left focus on the input — only a SECOND\n // press reached an option. The extra frame after the flip is also required:\n // floating.ts drives the panel's `visibility` from the same state and that\n // style write has not landed when the listener runs, so `focus()` would hit\n // a `visibility: hidden` element and do nothing.\n const openThenMove = (node: ElementNode, toLast: boolean): void => {\n let release: (() => void) | undefined;\n release = subscribeOpen(\n openState,\n (isOpen) => {\n if (!isOpen) return;\n release?.();\n requestAnimationFrame(() => moveIntoPanel(node, toLast));\n },\n false,\n );\n show(node);\n };\n\n const onInputKey = (event: Event, node: ElementNode): void => {\n const key = (event as KeyboardEvent).key;\n if (key !== \"ArrowDown\" && key !== \"ArrowUp\") return;\n event.preventDefault();\n if (openState.get()) {\n moveIntoPanel(node, key === \"ArrowUp\");\n return;\n }\n openThenMove(node, key === \"ArrowUp\");\n };\n\n const inputAria: PartialElement = {\n role: \"combobox\",\n ariaHaspopup: \"listbox\",\n // The popup filters an existing list; it does not complete inline.\n ariaAutocomplete: \"list\",\n ariaExpanded: (listener) => openState.get(listener),\n ariaControls: (listener) =>\n listener?.elementNode\n ? floatingPanelId(\"combobox\", findComboboxAnchor(listener.elementNode))\n : undefined,\n onKeyDown: onInputKey,\n };\n\n const buildInput = (custom?: DomphyElement): DomphyElement => {\n if (custom) {\n merge(custom, {\n onClick: (_e: Event, node: ElementNode) => show(node),\n style: inputStyle,\n _key: \"combobox-input\",\n ...inputAria,\n });\n return custom;\n }\n return {\n input: null,\n // Accessible name for the filter field (critical for axe label rule).\n ariaLabel: \"Filter options\",\n // Click / typing / ArrowDown open the popup — NOT plain focus. Escape\n // returns focus to this input (floating.ts), so an onFocus that re-opens\n // made Escape un-dismissable: measured in Chromium, the panel was back\n // within 100ms of every Escape and never closed again. MUI Autocomplete\n // defaults `openOnFocus` to false for the same reason.\n onClick: (_e: Event, node: ElementNode) => show(node),\n value: (listener: { elementNode?: ElementNode }) =>\n readQuery(listener)?.get(listener as never) ?? \"\",\n onInput: (event: Event, node: ElementNode) => {\n node\n .getBehavior<ComboboxInner>(\"comboboxInner\")\n ?.query.set((event.target as HTMLInputElement).value);\n show(node);\n },\n style: inputStyle,\n _key: \"combobox-input\",\n ...inputAria,\n };\n };\n\n const buildWrap = (inner: InnerProps): DomphyElement<\"div\"> => ({\n div: (listener) => {\n openState.get(listener);\n const val = inner.state.get(listener);\n const vals = Array.isArray(val) ? val : [val];\n const opts = inner.options.filter((opt) => vals.includes(opt.value));\n const items: DomphyElement[] = opts.map((opt) => {\n return {\n span: opt.label,\n $: [tag({ color: inner.color, removable: true })],\n _key: opt.value,\n _onRemove: (_node: ElementNode) => {\n const cur = inner.state.get();\n const curVals = Array.isArray(cur) ? cur : [cur];\n const filter = curVals.filter((v) => v !== opt.value);\n inner.multiple\n ? inner.state.set(filter as any)\n : inner.state.set(filter[0] as any);\n },\n };\n });\n items.push(buildInput(inner.input));\n return items;\n },\n _key: \"comboboxWrap\",\n style: {\n display: \"flex\",\n flexWrap: \"wrap\",\n gap: themeSpacing(1),\n },\n });\n\n const attachInner = (\n node: ElementNode,\n _inner: InnerProps,\n ): ComboboxInner => {\n let query = node.getMetadata(\"comboboxQuery\") as State<string> | undefined;\n if (!query) {\n query = toState(\"\");\n node.setMetadata(\"comboboxQuery\", query);\n }\n return {\n query,\n update(next) {\n node.children.update([buildWrap(next)]);\n },\n };\n };\n\n const partial: PartialElement = {\n _onInsert: (node) => {\n if (node.tagName !== \"div\") {\n console.warn(`\"combobox\" primitive patch must use div tag`);\n }\n },\n _onSchedule: (node, element) => {\n (element as Record<string, unknown>)[node.tagName] = [\n buildWrap({\n options,\n multiple,\n color,\n state,\n input: props.input,\n }),\n ];\n },\n ...behavior<InnerProps>(\"comboboxInner\", attachInner, {\n options,\n multiple,\n color,\n state,\n input: props.input,\n }),\n style: {\n minWidth: themeSpacing(32),\n outlineOffset: \"-1px\",\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", \"neutral\")}`,\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 1),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 1),\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n color: (listener) => themeColor(listener, \"text\", color),\n backgroundColor: (listener) => themeColor(listener, \"inherit\", color),\n transition:\n \"background-color 140ms ease, outline-color 140ms ease, box-shadow 140ms ease\",\n \"&:focus-within\": {\n boxShadow: (listener) => focusRing(listener, color),\n },\n },\n };\n\n merge(anchorPartial, partial);\n return anchorPartial;\n}\n\nexport { combobox };\n","import {\n type Listener,\n type StyleObject,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport { type ThemeColor, themeColor } from \"@domphy/theme\";\n\n/**\n * Tone of an editable field's PLACEHOLDER.\n *\n * MEASURED — `packages/ui/tests/field-text-contrast.test.ts` sweeps all 10\n * built-in roles x the 8 edge anchors (shift-0..3, shift-14..17) x both built-in\n * themes, resolving tones through `resolveToneStep()` so the numbers are the\n * ones the browser paints:\n *\n * shift-7 worst 2.83:1 fails 142/160\n * \"muted\" worst 3.55:1 fails 40/160\n * \"text\" worst 4.53:1 fails 0/160 <- lowest tone clearing AA\n *\n * WCAG 2.1 SC 1.4.3 covers placeholder text: its only relevant exception is\n * \"inactive user interface components\", and an editable field is not inactive.\n * So `\"text\"` is the floor, not a preference.\n */\nconst PLACEHOLDER_TONE = \"text\";\n\n/**\n * Tone of the value the user has typed.\n *\n * The placeholder is pinned at the AA floor, so the hint/value distinction has\n * to be made by painting the VALUE stronger — the inverse of MUI/Carbon, whose\n * placeholders sit below AA. Two ramp steps, not one:\n *\n * \"text\" vs shift-10 worst CIELAB dE 5.27\n * \"text\" vs shift-11 worst CIELAB dE 10.67 (~4.6x the ~2.3 JND)\n *\n * shift-11 also clears AAA on every edge anchor (worst 7.34:1), so the value is\n * never the weaker of the two.\n */\nconst VALUE_TONE = \"shift-11\";\n\n/**\n * The `color` + `::placeholder` pair every editable text field paints. Keeping\n * it in one place is what stops the two tones drifting apart per patch (they\n * had, across `inputText` / `inputSearch` / `textarea` / `command`) and keeps\n * the placeholder in the field's own `color` role rather than always neutral.\n */\nfunction fieldTextStyle(\n color: ValueOrState<ThemeColor> = \"neutral\",\n): StyleObject {\n const colorState = toState(color, \"color\");\n return {\n color: (listener: Listener) =>\n themeColor(listener, VALUE_TONE, colorState.get(listener)),\n \"&::placeholder\": {\n color: (listener: Listener) =>\n themeColor(listener, PLACEHOLDER_TONE, colorState.get(listener)),\n },\n };\n}\n\nexport { fieldTextStyle, PLACEHOLDER_TONE, VALUE_TONE };\n","import {\n type BehaviorInstance,\n behavior,\n type DomphyElement,\n type ElementNode,\n merge,\n type PartialElement,\n type ReadableState,\n type State,\n type ValueOrState,\n} from \"@domphy/core\";\nimport {\n autoUpdate,\n computePosition,\n flip,\n offset,\n type Placement,\n shift,\n} from \"@domphy/floating\";\nimport {\n asOpenState,\n dismissOpen,\n subscribeOpen,\n writeOpen,\n} from \"./openState.js\";\n\ntype FloatingProps = {\n kind: string;\n openState: ReadableState<boolean>;\n // Lives on the behavior instance so a reused node gets the latest callback\n // via update() — do not close over factory-generation onDismiss.\n onDismiss?: () => void;\n placement: State<Placement>;\n content: DomphyElement;\n // popover's openOn === \"hover\" case: hovering the floating PANEL itself\n // (not just the anchor) must keep it open, so the pointer can travel from\n // trigger to panel without the debounced hide() firing first.\n keepOpenOnContentHover: boolean;\n // Hover-intent debounce, in ms. Configurable per consumer (Radix Tooltip\n // parity: `delayDuration`) instead of the single fixed value every floating\n // consumer used to share.\n openDelay: number;\n closeDelay: number;\n};\n\n// The previous fixed debounce, kept as the default when a consumer does not\n// pass its own delay — INHERITED from the pre-existing behavior this file\n// hard-coded before openDelay/closeDelay became configurable.\nconst FLOATING_DEFAULT_DELAY_MS = 100;\n\n// The panel id every floating component gets, derived deterministically from\n// the ANCHOR's nodeId (stable across generations — a reused node keeps its\n// nodeId — and across SSR/hydration, unlike Math.random()). The anchor's\n// trigger partial references the same id via _onSchedule (aria-controls /\n// aria-describedby), so trigger and panel agree without any factory-scope\n// mutable variable that a fresh generation would lose.\nfunction floatingPanelId(kind: string, node: ElementNode): string {\n return `domphy-${kind}-${node.nodeId}`;\n}\n\n// The overlay container every floating panel portals into. Marked with a data\n// ATTRIBUTE, not an id: there is one container per app root and one more per\n// open <dialog>, so a document can legitimately hold several at once and a\n// fixed `id=\"domphy-floating\"` made every one after the first a duplicate id —\n// invalid HTML, and `document.getElementById`/`querySelector(\"#…\")` silently\n// resolved to whichever happened to come first in document order. Every lookup\n// below is `:scope >` scoped to one parent anyway, so uniqueness was never\n// what the selector needed.\nconst OVERLAY_ATTRIBUTE = \"data-domphy-floating\";\nconst OVERLAY_SELECTOR = `:scope > [${OVERLAY_ATTRIBUTE}]`;\n// Stamped on every floating panel element with its `kind` (\"tooltip\",\n// \"popover\", \"menu\", ...) so hasOpenFloatingPanel can tell a hover tooltip\n// apart from a layer the user is actually inside.\nconst OVERLAY_KIND_ATTRIBUTE = \"data-domphy-floating-kind\";\n\n/**\n * True while a popover/select/datePicker panel is mounted inside this\n * `<dialog>` (they portal into the dialog's own overlay container, see\n * `_portal`). A hover-only tooltip does NOT count: Radix's DismissableLayer\n * and React Aria's overlay stack both treat a hover tooltip as decoration,\n * not a layer the user is \"inside\" — it never consumes a Dismiss keypress.\n * Before this exclusion, a tooltip left open by a lingering hover cost the\n * dialog's Escape an extra press before it closed.\n *\n * Escape must dismiss only the TOP layer — Radix's DismissableLayer and React\n * Aria's overlay stack both stop at the innermost open layer. The browser\n * fires the dialog's `cancel` event for the same keypress that the panel's own\n * dismiss handler sees, so a modal dialog with an open dropdown closed\n * entirely on one Escape. The panel's `hide()` is debounced, so it is still\n * mounted when `cancel` arrives; the next Escape closes the dialog.\n */\nfunction hasOpenFloatingPanel(dialogElement: Element): boolean {\n const overlay = dialogElement.querySelector(OVERLAY_SELECTOR);\n if (!overlay) return false;\n return Array.from(overlay.children).some(\n (child) => child.getAttribute(OVERLAY_KIND_ATTRIBUTE) !== \"tooltip\",\n );\n}\n\ntype FloatingInstance = BehaviorInstance<FloatingProps> & {\n show: () => void;\n hide: () => void;\n panelId: string;\n};\n\n// The per-anchor persistent state a floating component needs (position\n// cleanup, the inserted panel node, debounce timer) used to live in\n// createFloating()'s own closure — but that closure is recreated fresh every\n// time a reactive ancestor re-renders the anchor (popover()/tooltip() called\n// again on the SAME reused DOM element). Only the FIRST-ever generation's\n// _onMount ever fires (ElementNode hooks run once per node), so imperative,\n// document-level listeners (outside-click, Escape-inside-panel) that closed\n// over that generation's `openState`/`reference`/`floating` kept acting on an\n// orphaned copy forever, while live-rebound trigger events (onClick etc.)\n// moved on to whatever generation was actually current — the trigger opened\n// the panel, but nothing could ever close it again from outside.\n//\n// Fixed by moving all of this into ONE `behavior()` instance per (anchor,\n// kind): `attach` runs once, and every later generation's `show`/`hide`\n// calls and `_behaviors` re-declaration route into that SAME instance via\n// `getBehavior`/`update()` — so there is exactly one canonical `openState`/\n// `reference`/`floating` for the anchor's whole lifetime, not one per\n// generation.\nfunction attachFloating(\n node: ElementNode,\n initialProps: FloatingProps,\n): FloatingInstance {\n let {\n openState,\n onDismiss,\n placement,\n content,\n keepOpenOnContentHover,\n openDelay,\n closeDelay,\n } = initialProps;\n const { kind } = initialProps;\n const behaviorKey = `floating:${kind}`;\n\n let timer: ReturnType<typeof setTimeout> | null = null;\n let cleanup: (() => void) | null = null;\n let floating: HTMLElement | null = null;\n let floatingNode: ElementNode | null = null;\n let mounted = false;\n\n const reference = node.domElement as HTMLElement;\n const rootNode = node.getRoot();\n const panelId = floatingPanelId(kind, node);\n\n const floatingPartial: PartialElement = {\n style: {\n position: \"fixed\",\n pointerEvents: \"auto\",\n visibility: (listener) =>\n openState.get(listener) ? \"visible\" : \"hidden\",\n },\n // Escape must dismiss the panel from INSIDE it too: the content is\n // portaled as a DOM sibling of the anchor, so a keydown on a focused\n // element within the panel (menu item, calendar cell, footer button)\n // never bubbles to the anchor's own Escape handler.\n //\n // Top-layer gated, like the document-level handler below. A nested\n // popover's TRIGGER is an ordinary element inside the outer panel, so an\n // Escape pressed there bubbles into this handler on the OUTER panel:\n // measured in Chromium, `outer trigger -> click -> inner trigger ->\n // Escape` removed BOTH panels at once and returned focus two levels, to\n // the outer trigger. Only the innermost open layer dismisses, and it\n // stops the event so no ancestor panel sees the same keypress.\n onKeyDown: (event) => {\n if ((event as KeyboardEvent).key !== \"Escape\") return;\n if (!isTopLayer()) return;\n event.stopPropagation();\n hide();\n },\n onMouseEnter: () => keepOpenOnContentHover && show(),\n onMouseLeave: () => keepOpenOnContentHover && hide(),\n _onMount: (mountedNode) => {\n floating = mountedNode.domElement as HTMLElement;\n // Stamped as a plain DOM property (not node.attributes.set) so a later\n // floatingNode.patch(content) — which strips undeclared ATTRIBUTES from\n // its own bookkeeping — never removes it. A consumer-declared id on the\n // content element wins.\n if (!floating.id) floating.id = panelId;\n floating.setAttribute(OVERLAY_KIND_ATTRIBUTE, kind);\n // Propagate data-theme from the trigger's ancestor so floating content\n // inherits CSS variable scope. Stamped on the PANEL, not the shared\n // overlay: the one overlay serves every floating component under the\n // root, so an overlay-level stamp would let whichever anchor opened\n // FIRST permanently impose its theme on later panels anchored under a\n // different [data-theme] scope. Skipped when the content declares its\n // own data-theme.\n if (reference && floating && !floating.hasAttribute(\"data-theme\")) {\n const dataTheme = reference\n .closest(\"[data-theme]\")\n ?.getAttribute(\"data-theme\");\n if (dataTheme) floating.setAttribute(\"data-theme\", dataTheme);\n }\n },\n _portal: (rNode) => {\n // showModal() puts the dialog in the top layer, above every z-index.\n // A panel portaled to the root overlay (z-index 20) would paint UNDER\n // an open dialog — drop it into the ancestor dialog instead so it\n // shares the top layer.\n const dialogHost = reference.closest(\"dialog\");\n if (dialogHost) {\n let overlay = dialogHost.querySelector(OVERLAY_SELECTOR);\n if (!overlay) {\n overlay = dialogHost.ownerDocument.createElement(\"div\");\n overlay.setAttribute(OVERLAY_ATTRIBUTE, \"\");\n Object.assign((overlay as HTMLElement).style, {\n position: \"fixed\",\n inset: \"0\",\n zIndex: \"20\",\n pointerEvents: \"none\",\n });\n dialogHost.appendChild(overlay);\n }\n return overlay;\n }\n // `:scope >` is load-bearing. The in-dialog branch above creates a\n // SECOND overlay container inside the <dialog>. A plain descendant\n // `querySelector(\"[data-domphy-floating]\")` returns the first match in\n // document order — the dialog's copy — so\n // once any popover/tooltip/select had been opened inside a modal\n // dialog, every later floating panel in the whole app was portaled\n // into that dialog. Measured: with the dialog closed (display:none,\n // set by dialog.ts's finalizeClose) the panel reported\n // aria-expanded=\"true\" and visibility:visible while its items had a\n // 0x0 rect and could not take focus. The root's own overlay is always\n // inserted as a DIRECT child of the root, so scoping is exact.\n let overlay = rNode.domElement!.querySelector(OVERLAY_SELECTOR);\n if (!overlay) {\n const overlayEle: DomphyElement<\"div\"> = {\n div: [],\n [OVERLAY_ATTRIBUTE]: \"\",\n style: {\n position: \"fixed\",\n inset: 0,\n zIndex: 20,\n pointerEvents: \"none\",\n },\n };\n const overlayNode = rNode.children!.insert(overlayEle) as ElementNode;\n overlay = overlayNode.domElement!;\n }\n return overlay;\n },\n };\n\n // Later generations declare their OWN fresh `content` object (a new object\n // literal at the popover()/tooltip() call site) — wire it every time, not\n // just at attach, so the panel wiring (theming, portal, dismiss handlers)\n // is present regardless of which generation's content ends up mounted.\n const wireContent = (target: DomphyElement) => merge(target, floatingPartial);\n wireContent(content);\n\n const ensureMounted = () => {\n if (mounted) return;\n mounted = true;\n floatingNode = rootNode.children!.insert(content) as ElementNode;\n // Expose THIS instance on the panel node too: the panel is portaled as a\n // child of the ROOT (not of the anchor), so getBehavior's ancestor walk\n // from a panel descendant (a selectBox/combobox option, a datePicker day\n // cell) never reaches the anchor's registration. Registering the same\n // instance on the panel lets panel-originated events resolve it via\n // `node.getBehavior(behaviorKey)` — the documented walk-up pattern. The\n // registration must be withdrawn again before the panel node is removed\n // (see detachPanel): its lifetime is owned by the ANCHOR, not the panel.\n floatingNode._behaviorInstances.set(behaviorKey, instance);\n };\n\n // ElementNode teardown DESTROYS every instance in the removed node's\n // `_behaviorInstances` (BeforeRemove hook + _dispose). The panel carries a\n // registration of the ANCHOR's instance, so removing the panel used to\n // destroy the anchor's behavior with it: measured in Chromium, after the\n // FIRST close of any popover/menu/select/tooltip the document-level\n // outside-click and Escape listeners were gone, and the component could\n // then only be closed by clicking its own trigger again. Withdraw the\n // borrowed registration first so only the panel's own state dies with it.\n const detachPanel = () => {\n if (!floatingNode) return;\n floatingNode._behaviorInstances.delete(behaviorKey);\n floatingNode.remove();\n floatingNode = null;\n };\n\n const instantShow = () => {\n // A re-render can detach the panel DOM without going through\n // instantHide (overlay reconcile, in-place patch). If we still think\n // we are mounted, skip insert and the panel never comes back.\n if (mounted && (!floating || !floating.isConnected)) {\n cleanup?.();\n cleanup = null;\n floatingNode = null;\n floating = null;\n mounted = false;\n }\n ensureMounted();\n if (reference && floating) {\n cleanup?.();\n cleanup = autoUpdate(reference, floating, () => {\n computePosition(reference as HTMLElement, floating as HTMLElement, {\n placement: placement.get() as Placement,\n // rootBoundary deliberately stays at the upstream default\n // ('viewport', i.e. the VISUAL viewport): with strategy \"fixed\" the\n // 1.8.0 'layoutViewport' option would stop clamping flip/shift to\n // the visible area, letting a panel land (partly) outside the\n // visible viewport during mobile pinch-zoom — a worse failure than\n // the jumpiness it fixes. Pinch-zoom/keyboard drift is already\n // handled by autoUpdate's post-1.8.0 observeMove re-anchoring.\n middleware: [offset(12), flip(), shift()],\n strategy: \"fixed\",\n }).then(({ x, y, placement: resolved }) => {\n // Teardown can run while computePosition's async work is in\n // flight (it nulls `floating` and removes the panel) — skip the\n // late positioning instead of dereferencing null.\n if (!floating) return;\n Object.assign(floating.style, {\n left: `${x}px`,\n top: `${y}px`,\n });\n placement.set(resolved);\n });\n });\n writeOpen(openState, true);\n }\n };\n // True only while the panel itself owns the focus. Shadow-root aware:\n // `document.activeElement` reports the shadow HOST for focus inside a shadow\n // tree, so `floating.contains(...)` would say false for a panel rendered in\n // one — ask the panel's own root instead.\n const focusIsInsidePanel = (): boolean => {\n if (!floating) return false;\n const root = floating.getRootNode() as Document | ShadowRoot;\n const active = (root as DocumentOrShadowRoot).activeElement;\n return !!active && floating.contains(active);\n };\n\n // The anchor is not always the focusable element: combobox anchors its panel\n // to the WRAPPER div and the tab stop is the `<input>` inside it, so a bare\n // reference.focus() was a no-op there and focus still ended on <body>\n // (measured). Fall back to the anchor's first tab stop.\n const focusReference = (): void => {\n if (!reference) return;\n reference.focus?.();\n const root = reference.getRootNode() as Document | ShadowRoot;\n const active = (root as DocumentOrShadowRoot).activeElement;\n if (active && reference.contains(active)) return;\n reference\n .querySelector<HTMLElement>(\n 'input, button, select, textarea, a[href], [tabindex]:not([tabindex=\"-1\"])',\n )\n ?.focus?.();\n };\n\n // Fully unmounts (not just CSS-hides) the panel — mirrors show()'s own\n // insert-on-demand: a closed floating component holds no DOM/listeners.\n // ensureMounted() re-inserts a fresh panel node next time show() runs.\n // Visual unmount runs even when the source is read-only (Computed).\n const instantHide = () => {\n cleanup?.();\n cleanup = null;\n // WCAG 2.4.3 Focus Order: removing the panel while it holds the focus\n // drops the caret to <body> and strands a keyboard user at the top of the\n // document (measured: selectBox trigger -> ArrowDown -> Escape left\n // document.activeElement === BODY). Radix DismissableLayer and React Aria\n // both return focus to the trigger. The containment test IS the\n // \"don't steal focus\" guard Radix gets from its pointer/focus-outside\n // tracking: if the dismissal happened because the user clicked or tabbed\n // to something else, the focus already left the panel and we leave it\n // alone. With nested panels only the innermost one contains the focus, so\n // Escape returns focus exactly one level.\n const restoreFocus = focusIsInsidePanel();\n detachPanel();\n floating = null;\n mounted = false;\n if (restoreFocus) focusReference();\n dismissOpen(openState, onDismiss);\n };\n const show = () => {\n timer && clearTimeout(timer);\n timer = setTimeout(instantShow, openDelay);\n };\n const hide = () => {\n timer && clearTimeout(timer);\n timer = setTimeout(instantHide, closeDelay);\n };\n\n const handleOutside = (event: MouseEvent) => {\n if (!openState.get() || !reference || !floating) return;\n const target = event.target as Node;\n if (!reference.contains(target) && !floating.contains(target)) hide();\n };\n rootNode.domElement?.addEventListener(\"click\", handleOutside);\n\n // Escape must dismiss an open panel from ANYWHERE, not just from the\n // trigger or inside the panel (peer parity: Radix DismissableLayer closes\n // on a document-level Escape) — a hover-opened tooltip with focus sitting\n // on <body> otherwise ignores Escape entirely. Keyboard events target the\n // FOCUSED element and bubble UP, so unlike the outside-click listener this\n // one must live on the document (keydown is composed, so panels inside a\n // shadow root still reach it). Idempotent alongside the trigger/panel-level\n // Escape handlers: hide() is debounced and re-arming it on an\n // already-closed panel is a no-op.\n // ...but only for the TOP layer. Panels portal as siblings of one another in\n // the shared overlay container in mount order, so the last element\n // child is the innermost open layer — the same stack Radix's DismissableLayer\n // keeps. Without this, a document-level Escape closed every open panel at\n // once: measured with a popover opened from inside another popover, one\n // Escape removed both, and because the outer's hide() ran first it tore out\n // the inner's trigger, so the restored focus landed on a detached element and\n // fell through to <body>. The panel's own `onKeyDown` above still closes\n // whichever layer actually holds the focus.\n const isTopLayer = () =>\n !!floating && floating.parentElement?.lastElementChild === floating;\n const handleEscape = (event: Event) => {\n if (\n (event as KeyboardEvent).key === \"Escape\" &&\n openState.get() &&\n isTopLayer()\n )\n hide();\n };\n const escapeTarget: EventTarget | null =\n rootNode.domElement?.ownerDocument ?? rootNode.domElement ?? null;\n escapeTarget?.addEventListener(\"keydown\", handleEscape);\n\n // Caller-driven open (open.set(true) / open:true) must insert the panel —\n // show()/hide() are only the trigger-event path. Guard with `mounted` so\n // instantShow/instantHide's own writeOpen/dismissOpen does not recurse\n // (writable State.set notifies listeners).\n const onOpen = (val: boolean) => {\n if (val) {\n if (!mounted) instantShow();\n } else if (mounted) {\n instantHide();\n }\n };\n let release = () => {};\n let destroyed = false;\n let updating = false;\n let instance: FloatingInstance;\n\n // Stamped after `instance` exists. The panel is patched in place on every\n // generation; patch() prunes _behaviorInstances keys absent from the new\n // descriptor and destroy()s them. The instance is SHARED with the anchor —\n // pruning it unmounts the live panel. Declaring the key on the content\n // keeps prune from treating it as leftover.\n const stampPanelBehavior = (target: DomphyElement) => {\n target._behaviors = {\n ...(target._behaviors ?? {}),\n [behaviorKey]: { attach: () => instance, props: {} },\n };\n };\n\n instance = {\n show,\n hide,\n panelId,\n update(props) {\n if (updating) return;\n onDismiss = props.onDismiss;\n if (props.openState !== openState) {\n release();\n openState = props.openState;\n // emitCurrent false: a fresh uncontrolled toState(false) on a reused\n // node is not a caller close.\n release = subscribeOpen(openState, onOpen, false);\n // Show if the new object is already true (open:true / caller-owned).\n if (openState.get()) instantShow();\n }\n placement = props.placement;\n content = props.content;\n keepOpenOnContentHover = props.keepOpenOnContentHover;\n openDelay = props.openDelay;\n closeDelay = props.closeDelay;\n wireContent(content);\n stampPanelBehavior(content);\n // Reflect the new generation's declared content into the already-\n // mounted panel in place (same DOM node, no flicker/teardown) — the\n // ordinary reused-node \"patch, don't recreate\" contract, applied to\n // the imperatively-inserted panel too.\n if (floatingNode) {\n updating = true;\n try {\n floatingNode.patch(content);\n } finally {\n updating = false;\n }\n }\n },\n destroy() {\n if (destroyed) return;\n destroyed = true;\n if (timer) clearTimeout(timer);\n timer = null;\n cleanup?.();\n cleanup = null;\n detachPanel();\n floating = null;\n mounted = false;\n release();\n release = () => {};\n rootNode.domElement?.removeEventListener(\"click\", handleOutside);\n escapeTarget?.removeEventListener(\"keydown\", handleEscape);\n },\n };\n stampPanelBehavior(content);\n // After `instance` exists: ensureMounted registers it on the panel node.\n // subscribeOpen notifies immediately (replaces onOpen(openState.get())).\n release = subscribeOpen(openState, onOpen);\n return instance;\n}\n\nfunction createFloating(props: {\n kind: string;\n open?: ValueOrState<boolean>;\n onDismiss?: () => void;\n placement: State<Placement>;\n content: DomphyElement;\n keepOpenOnContentHover?: boolean;\n // Hover-intent debounce, in ms. Defaults to FLOATING_DEFAULT_DELAY_MS.\n openDelay?: number;\n closeDelay?: number;\n}) {\n const { kind, placement, onDismiss } = props;\n const openState = asOpenState(props.open);\n const behaviorKey = `floating:${kind}`;\n\n // Trigger event handlers ARE live-rebound on every patch and already\n // receive the current ElementNode as their 2nd argument (unlike lifecycle\n // hooks) — so show(node)/hide(node) just forward to whatever instance is\n // attached there, regardless of which generation's closure is calling.\n const show = (node?: ElementNode) =>\n node?.getBehavior<FloatingInstance>(behaviorKey)?.show();\n const hide = (node?: ElementNode) =>\n node?.getBehavior<FloatingInstance>(behaviorKey)?.hide();\n\n // Plain spread, NOT merge(): merge() defensively deep-clones its `target`\n // argument, which would snapshot `props.content` right now — but the\n // caller (popover()/tooltip()) hasn't finished mutating it yet (it pushes\n // its OWN partial onto `content.$` right after this call returns). A\n // premature clone silently drops that later mutation, so the panel loses\n // its role/style/dismiss wiring. Spread keeps the `_behaviors` record's\n // `props.content` a live reference to the SAME object the caller mutates.\n const anchorPartial: PartialElement = {\n onKeyDown: (e: Event, node: ElementNode) =>\n (e as KeyboardEvent).key === \"Escape\" && hide(node),\n ...behavior<FloatingProps>(behaviorKey, attachFloating, {\n kind,\n openState,\n onDismiss,\n placement,\n content: props.content,\n keepOpenOnContentHover: !!props.keepOpenOnContentHover,\n openDelay: props.openDelay ?? FLOATING_DEFAULT_DELAY_MS,\n closeDelay: props.closeDelay ?? FLOATING_DEFAULT_DELAY_MS,\n }),\n };\n\n return { show, hide, anchorPartial, openState };\n}\n\nexport { createFloating, floatingPanelId, hasOpenFloatingPanel };\n","import {\n effect,\n type ReadableState,\n type State,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\n\nexport function isWritableState<T>(\n source: ReadableState<T>,\n): source is State<T> {\n return typeof (source as State<T>).set === \"function\";\n}\n\n/**\n * Subscribe to overlay `open`. Writable State uses `addListener` (no\n * fabricated `.set()`, existing listenerCount-on-remove tests). Computed has\n * no `addListener` — `effect()` reads `get()`.\n *\n * `emitCurrent` (default true) delivers the value once on subscribe, matching\n * first-attach `update(state.get())`. Pass false when re-subscribing on a\n * reused node so a fresh uncontrolled `toState(false)` is not a caller close.\n */\nexport function subscribeOpen(\n source: ReadableState<boolean>,\n onChange: (open: boolean) => void,\n emitCurrent = true,\n): () => void {\n if (typeof (source as State<boolean>).addListener === \"function\") {\n if (emitCurrent) onChange(source.get());\n return (source as State<boolean>).addListener(onChange);\n }\n if (emitCurrent) {\n return effect(() => {\n onChange(source.get());\n });\n }\n let skipInitial = true;\n const release = effect(() => {\n const value = source.get();\n if (skipInitial) return;\n onChange(value);\n });\n skipInitial = false;\n return release;\n}\n\nexport function writeOpen(\n source: ReadableState<boolean>,\n value: boolean,\n): void {\n if (isWritableState(source)) source.set(value);\n}\n\nexport function dismissOpen(\n source: ReadableState<boolean>,\n onDismiss?: () => void,\n): void {\n onDismiss?.();\n writeOpen(source, false);\n}\n\nexport function asOpenState(\n open: ValueOrState<boolean> | undefined,\n): ReadableState<boolean> {\n return toState(open ?? false);\n}\n","/**\n * Every `[role=option]` under `root` that is not disabled, in DOM order.\n *\n * Lives in `utils/` rather than in one of the patch modules because\n * `patches.ts` re-exports each patch module with `export *` — an export there\n * would put this internal DOM walk in the public API. Shared by `selectList`\n * (its own listbox key model), `selectBox` (typeahead + arrow entry into the\n * panel) and `combobox` (arrow entry into the popup).\n */\nfunction enabledOptionsIn(root: Element | null): HTMLElement[] {\n if (!root) return [];\n return Array.from(root.querySelectorAll<HTMLElement>(\"[role=option]\")).filter(\n (el) =>\n el.getAttribute(\"aria-disabled\") !== \"true\" &&\n !el.hasAttribute(\"disabled\"),\n );\n}\n\nexport { enabledOptionsIn };\n","import {\n behavior,\n type DomphyElement,\n ElementNode,\n type PartialElement,\n rawHtml,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\nconst xSvg = `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"/><path d=\"M6.707 5.293l5.293 5.292l5.293 -5.292a1 1 0 0 1 1.414 1.414l-5.292 5.293l5.292 5.293a1 1 0 0 1 -1.414 1.414l-5.293 -5.292l-5.293 5.292a1 1 0 1 1 -1.414 -1.414l5.292 -5.293l-5.292 -5.293a1 1 0 0 1 1.414 -1.414\" /></svg>`;\n\n// Compact-chip chrome was bare `themeSpacing(U)` (catalog snapshots). Default\n// density is 1.5 (`light.densities[2]`, density.ts origin index 2). n = U / 1.5\n// keeps those pixels at default while dataDensity still scales. Height 6U must\n// stay below selectBox/combobox minHeight `(6 + 2d)U` or the chip fills the trigger.\nconst DEFAULT_DENSITY = 1.5;\nconst TAG_HEIGHT = 6 / DEFAULT_DENSITY;\nconst TAG_PAD_INLINE = 2.5 / DEFAULT_DENSITY;\nconst TAG_PAD_END_REMOVABLE = 1 / DEFAULT_DENSITY;\nconst TAG_REMOVE = 4 / DEFAULT_DENSITY;\nconst TAG_REMOVE_RADIUS = 1 / DEFAULT_DENSITY;\n\ntype TagRemoveProps = { removable: boolean };\n\n/**\n * Styles an inline chip/tag (rounded, bordered, optional remove button).\n * No host tag check; typically applied to a `<span>`. When `removable` is true,\n * a close button is inserted that removes the host node on click or Enter/Space.\n *\n * @hostTag span\n * @param props.color - Theme color for the chip background/border/text. Optional, accepts a value or state. Defaults to `\"neutral\"`.\n * @param props.removable - When true, renders a remove (x) button that removes the tag on click or Enter/Space. Optional. Defaults to `false`.\n * @example { span: \"Label\", $: [tag({ removable: true })] }\n */\nfunction tag(\n props: { color?: ValueOrState<ThemeColor>; removable?: boolean } = {},\n): PartialElement {\n const { removable = false } = props;\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n dataTone: \"shift-2\",\n // _onInit would miss/orphan the button when a reused node is re-patched\n // with a flipped `removable`. behavior() attaches once and routes later\n // generations through update().\n ...behavior<TagRemoveProps>(\n \"tag-remove\",\n (node, initial) => {\n const removeHost = () => node.remove();\n const makeButton = (): DomphyElement<\"span\"> => ({\n span: rawHtml(xSvg),\n _key: \"tag-remove\",\n onClick: (e) => {\n (e as Event).stopPropagation();\n removeHost();\n },\n onKeyDown: (e) => {\n const event = e as KeyboardEvent;\n if (event.key !== \"Enter\" && event.key !== \" \") return;\n event.preventDefault();\n event.stopPropagation();\n removeHost();\n },\n tabindex: 0,\n role: \"button\",\n ariaLabel: \"Remove\",\n style: {\n display: \"inline-flex\",\n alignItems: \"center\",\n cursor: \"pointer\",\n borderRadius: (listener) =>\n themeSpacing(themeDensity(listener) * TAG_REMOVE_RADIUS),\n width: (listener) =>\n themeSpacing(themeDensity(listener) * TAG_REMOVE),\n height: (listener) =>\n themeSpacing(themeDensity(listener) * TAG_REMOVE),\n flexShrink: 0,\n transition: \"background-color 140ms ease, box-shadow 140ms ease\",\n \"&:hover\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-4\", color.get(listener)),\n },\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, color.get(listener)),\n },\n },\n });\n const findButton = () =>\n node.children.items.find(\n (item) => item instanceof ElementNode && item.key === \"tag-remove\",\n ) ?? null;\n // attach() runs from the host Mount hook, which fires bottom-up: the\n // children walk has already finished by then (both on a fresh render\n // and on hydration), so the button always has to be materialized here.\n // The list-only insert this used to do on first paint relied on the\n // old top-down Mount and left the button DOM-less after hydration.\n const sync = (next: TagRemoveProps) => {\n const existing = findButton();\n if (next.removable && !existing) {\n node.children.insert(makeButton());\n } else if (!next.removable && existing) {\n node.children.remove(existing);\n }\n };\n sync(initial);\n return {\n update: sync,\n };\n },\n { removable },\n ),\n style: {\n display: \"inline-flex\",\n // A chip hugs its label. Measured in Chromium: inside a `stack()` the\n // pill stretched to the full 1232px column (shadcn's badge carries the\n // same `w-fit` for this reason) — `inline-flex` is blockified by a\n // flex/grid parent.\n width: \"fit-content\",\n alignItems: \"center\",\n whiteSpace: \"nowrap\",\n userSelect: \"none\",\n height: (listener) => themeSpacing(themeDensity(listener) * TAG_HEIGHT),\n paddingBlock: 0,\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 999),\n paddingInlineStart: (listener) =>\n themeSpacing(themeDensity(listener) * TAG_PAD_INLINE),\n paddingInlineEnd: (listener) =>\n themeSpacing(\n themeDensity(listener) *\n (removable ? TAG_PAD_END_REMOVABLE : TAG_PAD_INLINE),\n ),\n gap: themeSpacing(1.5),\n fontSize: (listener) => themeSize(listener, \"decrease-1\"),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n border: \"none\",\n outlineOffset: \"-1px\",\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", color.get(listener))}`,\n },\n };\n}\n\nexport { tag };\n","import {\n type ElementNode,\n merge,\n type PartialElement,\n toState,\n} from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { fieldTextStyle } from \"../utils/fieldText.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n// Items opt in with `data-command-item`; `commandItem` hides non-matching\n// rows with the `hidden` attribute, so the filter and the keyboard walk\n// agree on what is currently on screen.\nfunction visibleItems(host: HTMLElement): HTMLElement[] {\n return Array.from(\n host.querySelectorAll<HTMLElement>(\"[data-command-item]\"),\n ).filter((el) => !el.hidden && !el.hasAttribute(\"disabled\"));\n}\n\n// Arrow-key navigation over the filtered result list is what makes a command\n// palette usable from the search field (cmdk / shadcn Command parity): without\n// it the only way to reach a result was Tab, which also walked every hidden\n// row's siblings. Enter runs the highlighted item.\nfunction onCommandKey(event: Event, node: ElementNode): void {\n const key = (event as KeyboardEvent).key;\n const host = node.domElement as HTMLElement | null;\n if (!host) return;\n const items = visibleItems(host);\n if (!items.length) return;\n const active = host.ownerDocument.activeElement as HTMLElement | null;\n const current = active ? items.indexOf(active) : -1;\n\n if (key === \"Enter\") {\n if (current === -1) return;\n event.preventDefault();\n items[current]!.click();\n return;\n }\n\n let next: number;\n // Wraps at both ends — the search field stays focused until Down is pressed,\n // so there is no \"above the first item\" position to fall back to.\n if (key === \"ArrowDown\") next = (current + 1) % items.length;\n else if (key === \"ArrowUp\")\n next = current <= 0 ? items.length - 1 : current - 1;\n else if (key === \"Home\") next = 0;\n else if (key === \"End\") next = items.length - 1;\n else return;\n\n event.preventDefault();\n const target = items[next]!;\n target.focus();\n target.scrollIntoView?.({ block: \"nearest\" });\n}\n\n/**\n * Command-palette container patch. Sets up a vertical flex column and provides a\n * shared `command` context (a query State) consumed by `commandSearch` and\n * `commandItem` descendants to filter the list. Typically applied to a `<div>`.\n *\n * @example { div: [...], $: [command()] }\n */\nfunction command(): PartialElement {\n return {\n // Group (not listbox): search input + option buttons share one container;\n // listbox forbids non-option children (aria-required-children).\n role: \"group\",\n ariaLabel: \"Commands\",\n onKeyDown: onCommandKey,\n _onSchedule: (_node, element) => {\n merge(element, {\n _context: {\n command: {\n query: toState(\"\"),\n },\n },\n });\n },\n style: {\n display: \"flex\",\n flexDirection: \"column\",\n overflow: \"hidden\",\n },\n };\n}\n\n/**\n * Search input for a command palette. Wires the input's value into the parent\n * `command` context's query State so descendant `commandItem`s filter live.\n * Apply to an `<input>` element used inside a `command()`.\n *\n * @hostTag input\n * @param props.color - Base theme color tone. Defaults to \"neutral\".\n * @param props.accentColor - Accent color used for the focus border. Defaults to \"primary\".\n * @example { input: null, $: [commandSearch({ accentColor: \"primary\" })] }\n */\nfunction commandSearch(\n props: { color?: ThemeColor; accentColor?: ThemeColor } = {},\n): PartialElement {\n const { color = \"neutral\", accentColor = \"primary\" } = props;\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"input\") {\n console.warn(`\"commandSearch\" patch must use input tag`);\n }\n },\n _onMount: (node) => {\n const ctx = node.getContext(\"command\");\n if (!ctx) {\n console.warn(`\"commandSearch\" patch must be used inside a \"command\"`);\n return;\n }\n const input = node.domElement as HTMLInputElement;\n const onInput = () => ctx.query.set(input.value);\n input.addEventListener(\"input\", onInput);\n node.addHook(\"Remove\", () => input.removeEventListener(\"input\", onInput));\n },\n style: {\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 3),\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 2),\n border: \"none\",\n borderBottom: (listener) =>\n `1px solid ${themeColor(listener, \"border\", color)}`,\n outline: \"none\",\n ...fieldTextStyle(color),\n backgroundColor: (listener) => themeColor(listener, \"inherit\", color),\n transition: \"border-bottom-color 140ms ease, box-shadow 140ms ease\",\n \"&:focus-visible\": {\n borderBottomColor: (listener) =>\n themeColor(listener, \"shift-6\", accentColor),\n boxShadow: (listener) => focusRing(listener, accentColor),\n },\n },\n };\n}\n\n/**\n * Selectable item in a command palette. On mount, immediately hides itself if\n * the current query doesn't match its text content, and subscribes to future\n * query changes — so items added dynamically after a search is typed are\n * correctly filtered. Apply to a `<button>` inside a `command()`. Uses native\n * button semantics (not `role=option`) so the search input may sit as a\n * sibling without a listbox parent requirement. A non-focusable host (a bare\n * `<div>`) still filters, but the container's arrow-key walk calls `focus()`\n * on it and that is a no-op — give such a host a `tabindex` of its own.\n *\n * @param props.color - Base theme color tone. Defaults to \"neutral\".\n * @param props.accentColor - Accent color used for the focus ring. Defaults to \"primary\".\n * @example { button: \"Open file\", $: [commandItem({ color: \"neutral\" })] }\n */\nfunction commandItem(\n props: { color?: ThemeColor; accentColor?: ThemeColor } = {},\n): PartialElement {\n const { color = \"neutral\", accentColor = \"primary\" } = props;\n return {\n // Native `type` on the host still wins (mergePartial: native over patch).\n type: \"button\",\n // Marker the container's keyboard walk looks for.\n dataCommandItem: \"\",\n _onMount: (node) => {\n const ctx = node.getContext(\"command\");\n if (!ctx) {\n console.warn(`\"commandItem\" patch must be used inside a \"command\"`);\n return;\n }\n const el = node.domElement as HTMLElement;\n // Read the label AT FILTER TIME. Captured once in _onMount it was the\n // empty string — _onMount fires before the child text node is attached —\n // so the first keystroke hid every item in the palette. Reading late\n // also keeps a reactive label in sync.\n const applyFilter = (q: string) => {\n if (q.length === 0) {\n el.hidden = false;\n return;\n }\n const text = el.textContent?.toLowerCase() ?? \"\";\n el.hidden = !text.includes(q.toLowerCase());\n };\n applyFilter(ctx.query.get());\n const release = ctx.query.addListener(applyFilter);\n node.addHook(\"Remove\", release);\n },\n style: {\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n width: \"100%\",\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n height: (listener) => themeSpacing(6 + themeDensity(listener) * 2),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 3),\n border: \"none\",\n outline: \"none\",\n // shift-13: menu-row labels need ≥4.5:1 on light surface (visual catalog).\n color: (listener) => themeColor(listener, \"shift-13\", color),\n backgroundColor: (listener) => themeColor(listener, \"inherit\", color),\n transition: \"background-color 140ms ease, box-shadow 140ms ease\",\n \"&:hover:not([disabled])\": {\n color: (listener) => themeColor(listener, \"shift-13\", color),\n backgroundColor: (listener) => themeColor(listener, \"hover\", color),\n },\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, accentColor),\n },\n },\n };\n}\n\nexport { command, commandSearch, commandItem };\n","import {\n type BehaviorInstance,\n behavior,\n type DomphyElement,\n type ElementNode,\n type Listener,\n merge,\n type PartialElement,\n type State,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport type { Placement } from \"@domphy/floating\";\nimport {\n type ThemeColor,\n textToneOn,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n themeWeight,\n} from \"@domphy/theme\";\nimport { elevation } from \"../utils/elevation.js\";\nimport { createFloating, floatingPanelId } from \"../utils/floating.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/** A single date selection, or a `[start, end]` tuple in range mode. */\nexport type DatePickerValue = Date | null | [Date | null, Date | null];\n\nexport interface DatePickerProps {\n /** Controlled value: a `Date` in single mode, a `[start, end]` tuple in range mode. */\n value?: ValueOrState<DatePickerValue>;\n /** Selection mode. */\n mode?: \"single\" | \"range\";\n /** Also pick hour + minute. The chosen time applies to the selected date(s). */\n time?: boolean;\n /** Earliest selectable day (inclusive). */\n min?: Date;\n /** Latest selectable day (inclusive). */\n max?: Date;\n /** Disable arbitrary days. */\n disabledDate?: (date: Date) => boolean;\n /** BCP-47 locale for month/weekday names, first-day-of-week, and formatting. */\n locale?: string;\n /** Override the first day of the week (0 = Sunday … 6 = Saturday). */\n weekStartsOn?: number;\n /** Override the input display string. */\n format?: (value: DatePickerValue) => string;\n /** Called whenever the selection changes. */\n onChange?: (value: DatePickerValue) => void;\n /** Accent color for the selected/active days. */\n accentColor?: ValueOrState<ThemeColor>;\n /** Popover placement relative to the input. */\n placement?: ValueOrState<Placement>;\n}\n\n// --- date helpers (no third-party library) -----------------------------------\n\nconst atMidnight = (date: Date): Date =>\n new Date(date.getFullYear(), date.getMonth(), date.getDate());\nconst addDays = (date: Date, count: number): Date =>\n new Date(date.getFullYear(), date.getMonth(), date.getDate() + count);\nconst addMonths = (date: Date, count: number): Date =>\n new Date(date.getFullYear(), date.getMonth() + count, date.getDate());\nconst sameDay = (a: Date | null, b: Date | null): boolean =>\n !!a &&\n !!b &&\n a.getFullYear() === b.getFullYear() &&\n a.getMonth() === b.getMonth() &&\n a.getDate() === b.getDate();\nconst isoOf = (date: Date): string =>\n `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, \"0\")}-${String(\n date.getDate(),\n ).padStart(2, \"0\")}`;\nconst startOfWeek = (date: Date, weekStart: number): Date =>\n addDays(date, -((date.getDay() - weekStart + 7) % 7));\n\n/** Resolves the locale's first day of week, falling back to Sunday. */\nfunction localeWeekStart(locale: string): number {\n try {\n const localeObject = new Intl.Locale(locale) as Intl.Locale & {\n weekInfo?: { firstDay: number };\n getWeekInfo?: () => { firstDay: number };\n };\n const info = localeObject.getWeekInfo?.() ?? localeObject.weekInfo;\n if (info?.firstDay) return info.firstDay % 7; // Intl uses 1=Mon … 7=Sun\n } catch {\n // unsupported locale or engine — fall through to Sunday\n }\n return 0;\n}\n\n// --- per-node state preservation (reused-node lifecycle) -------------------\n\ntype DatePickerStates = {\n selection: State<DatePickerValue>;\n // When the caller passed `value`, each generation's toState(Date) is a\n // new object whose current value IS the caller's Date — copying the\n // previous internal selection onto it would overwrite that Date.\n selectionIsCallerOwned: boolean;\n viewYear: State<number>;\n viewMonth: State<number>;\n focused: State<Date>;\n hovered: State<Date | null>;\n hour: State<number>;\n minute: State<number>;\n open: State<boolean>;\n onChange?: (value: DatePickerValue) => void;\n};\n\n// Every ancestor re-render re-invokes datePicker() on the SAME reused input\n// node, allocating a fresh set of internal states with INITIAL values —\n// without carry-forward the user's uncontrolled selection, calendar view and\n// time silently reset on the next re-render, and the onChange subscription\n// (wired to the first generation's selection object) goes stale. ONE\n// behavior instance per node copies the live values into each new\n// generation's states (update() runs during patch(), before the fresh\n// input/calendar bindings evaluate) and keeps exactly one onChange\n// subscription on the CURRENT generation's selection.\nfunction attachDatePicker(\n _node: ElementNode,\n initialProps: DatePickerStates,\n): BehaviorInstance<DatePickerStates> {\n let current = initialProps;\n let releaseOnChange: (() => void) | null = null;\n const subscribe = (props: DatePickerStates) => {\n releaseOnChange?.();\n releaseOnChange = props.onChange\n ? props.selection.addListener((value) => props.onChange!(value))\n : null;\n };\n const carryForward = (next: State<any>, prev: State<any>) => {\n if (next !== prev) next.set(prev.get());\n };\n subscribe(current);\n return {\n update(next) {\n if (!next.selectionIsCallerOwned) {\n carryForward(next.selection, current.selection);\n }\n carryForward(next.viewYear, current.viewYear);\n carryForward(next.viewMonth, current.viewMonth);\n carryForward(next.focused, current.focused);\n carryForward(next.hovered, current.hovered);\n carryForward(next.hour, current.hour);\n carryForward(next.minute, current.minute);\n carryForward(next.open, current.open);\n if (\n next.selection !== current.selection ||\n next.onChange !== current.onChange\n ) {\n // Re-subscribe AFTER the carry-forward so it never fires onChange.\n subscribe(next);\n }\n current = next;\n },\n destroy() {\n releaseOnChange?.();\n releaseOnChange = null;\n },\n };\n}\n\n/**\n * A native, themeable date picker patch for an `<input>`. Opens a calendar\n * popover (rendered with Domphy elements, positioned via `@domphy/floating`)\n * supporting single/range selection, optional time, min/max + disabled days,\n * localized names, and keyboard navigation. The input is read-only and shows the\n * formatted selection; compose with `inputText()` for the input's look.\n *\n * @hostTag input\n * @param props.value - Controlled value (`ValueOrState<DatePickerValue>`): a `Date`/`null` in single mode, a `[start, end]` tuple in range mode.\n * @param props.mode - Selection mode, \"single\" | \"range\". Defaults to \"single\".\n * @param props.time - When true, also pick hour + minute (applied to the selected date(s)). Defaults to false.\n * @param props.min - Earliest selectable day (inclusive), a `Date`.\n * @param props.max - Latest selectable day (inclusive), a `Date`.\n * @param props.disabledDate - Predicate `(date: Date) => boolean` to disable arbitrary days.\n * @param props.locale - BCP-47 locale for names/first-day-of-week/formatting. Defaults to `navigator.language` (or \"en-US\" in non-browser).\n * @param props.weekStartsOn - Override first day of week (0 = Sunday … 6 = Saturday). Defaults to the locale's first day.\n * @param props.format - Override the input display string, `(value: DatePickerValue) => string`.\n * @param props.onChange - Called with the new value whenever the selection changes, `(value: DatePickerValue) => void`.\n * @param props.accentColor - Accent color (`ValueOrState<ThemeColor>`) for selected/active days. Defaults to \"primary\".\n * @param props.placement - Popover placement (`ValueOrState<Placement>`) relative to the input. Defaults to \"bottom-start\".\n * @example { input: null, $: [inputText(), datePicker({ mode: \"range\" })] }\n */\nfunction datePicker(props: DatePickerProps = {}): PartialElement {\n const {\n mode = \"single\",\n time = false,\n min,\n max,\n disabledDate,\n locale = typeof navigator !== \"undefined\" ? navigator.language : \"en-US\",\n format,\n onChange,\n } = props;\n\n const weekStart = props.weekStartsOn ?? localeWeekStart(locale);\n const accentColor = toState(props.accentColor ?? \"primary\", \"accentColor\");\n const placeState = toState(props.placement ?? \"bottom-start\");\n\n const selection = toState<DatePickerValue>(\n props.value ?? (mode === \"range\" ? [null, null] : null),\n );\n\n const primaryDate = ((): Date => {\n const current = selection.get();\n const base =\n mode === \"range\" ? (current as [Date | null, Date | null])?.[0] : current;\n return base instanceof Date ? base : new Date();\n })();\n\n const viewYear = toState(primaryDate.getFullYear(), \"viewYear\");\n const viewMonth = toState(primaryDate.getMonth(), \"viewMonth\");\n const focused = toState<Date>(atMidnight(primaryDate), \"focused\");\n const hovered = toState<Date | null>(null, \"hovered\");\n const hour = toState(primaryDate.getHours(), \"hour\");\n const minute = toState(primaryDate.getMinutes(), \"minute\");\n\n // --- formatting -----------------------------------------------------------\n const dateFormatter = new Intl.DateTimeFormat(locale, {\n dateStyle: \"medium\",\n ...(time ? { timeStyle: \"short\" as const } : {}),\n });\n const monthFormatter = new Intl.DateTimeFormat(locale, {\n month: \"long\",\n year: \"numeric\",\n });\n const weekdayFormatter = new Intl.DateTimeFormat(locale, {\n weekday: \"short\",\n });\n const fullDateFormatter = new Intl.DateTimeFormat(locale, {\n dateStyle: \"full\",\n });\n\n const formatOne = (date: Date | null): string =>\n date ? dateFormatter.format(date) : \"\";\n const formatDisplay = (value: DatePickerValue): string => {\n if (format) return format(value);\n if (mode === \"range\") {\n const [start, end] = (value as [Date | null, Date | null]) ?? [\n null,\n null,\n ];\n return start ? `${formatOne(start)} – ${formatOne(end)}` : \"\";\n }\n return formatOne(value as Date | null);\n };\n\n // 2023-01-01 is a Sunday, so index 0 maps to Sunday before the week-start shift.\n const weekdayNames = Array.from({ length: 7 }, (_unused, index) =>\n weekdayFormatter.format(new Date(2023, 0, 1 + ((index + weekStart) % 7))),\n );\n\n // --- selection logic ------------------------------------------------------\n const isDisabled = (date: Date): boolean =>\n (!!min && atMidnight(date) < atMidnight(min)) ||\n (!!max && atMidnight(date) > atMidnight(max)) ||\n (!!disabledDate && disabledDate(date));\n\n const withTime = (date: Date): Date => {\n if (!time) return atMidnight(date);\n const result = atMidnight(date);\n result.setHours(hour.get(), minute.get(), 0, 0);\n return result;\n };\n\n const selectDate = (date: Date, node?: ElementNode): void => {\n if (isDisabled(date)) return;\n if (mode === \"single\") {\n selection.set(withTime(date));\n // Close via the cell's node: the floating behavior instance is\n // registered on the panel node (floating.ts), so getBehavior's\n // ancestor walk from any panel descendant resolves it.\n if (!time) hide(node);\n return;\n }\n const [start, end] = (selection.get() as [Date | null, Date | null]) ?? [\n null,\n null,\n ];\n if (!start || (start && end)) {\n selection.set([withTime(date), null]);\n } else if (atMidnight(date) < atMidnight(start)) {\n selection.set([withTime(date), withTime(start)]);\n if (!time) hide(node);\n } else {\n selection.set([start, withTime(date)]);\n if (!time) hide(node);\n }\n };\n\n const reapplyTime = (): void => {\n if (!time) return;\n if (mode === \"single\") {\n const current = selection.get() as Date | null;\n if (current) selection.set(withTime(current));\n } else {\n const [start, end] = (selection.get() as [Date | null, Date | null]) ?? [\n null,\n null,\n ];\n selection.set([\n start ? withTime(start) : start,\n end ? withTime(end) : end,\n ]);\n }\n };\n\n const inSelectedRange = (date: Date, listener?: Listener): boolean => {\n if (mode !== \"range\") return false;\n const [start, end] = (selection.get(listener) as [\n Date | null,\n Date | null,\n ]) ?? [null, null];\n const tail = end ?? hovered.get(listener);\n if (!start || !tail) return false;\n const low = atMidnight(start) <= atMidnight(tail) ? start : tail;\n const high = atMidnight(start) <= atMidnight(tail) ? tail : start;\n const day = atMidnight(date);\n return day >= atMidnight(low) && day <= atMidnight(high);\n };\n\n const isSelectedEnd = (date: Date, listener?: Listener): boolean => {\n const current = selection.get(listener);\n if (mode === \"range\") {\n const [start, end] = (current as [Date | null, Date | null]) ?? [\n null,\n null,\n ];\n return sameDay(date, start) || sameDay(date, end);\n }\n return sameDay(date, current as Date | null);\n };\n\n // --- view navigation ------------------------------------------------------\n const goToDate = (date: Date): void => {\n viewYear.set(date.getFullYear());\n viewMonth.set(date.getMonth());\n };\n const shiftMonth = (delta: number): void => {\n const next = addMonths(new Date(viewYear.get(), viewMonth.get(), 1), delta);\n goToDate(next);\n };\n const shiftYear = (delta: number): void =>\n viewYear.set(viewYear.get() + delta);\n\n const focusActiveCell = (node?: ElementNode): void => {\n // Resolve the panel from the caller's live node (trigger or grid cell):\n // the old factory-scope `contentElement` was only ever assigned by the\n // first panel generation's _onMount, so later generations (reused node,\n // fresh closure) could never move focus into the grid.\n const root = node?.getRoot()?.domElement;\n setTimeout(() => {\n root\n ?.querySelector<HTMLElement>(`[data-date=\"${isoOf(focused.get())}\"]`)\n ?.focus();\n }, 0);\n };\n\n // --- floating popover ------------------------------------------------------\n const calendar = buildCalendar();\n const openState = toState(false);\n const { show, hide, anchorPartial } = createFloating({\n kind: \"datePicker\",\n open: openState,\n placement: placeState,\n content: calendar,\n });\n\n // Move focus into the grid when the popover opens.\n const triggerPartial: PartialElement = {\n type: \"text\",\n readonly: true,\n value: (listener) => formatDisplay(selection.get(listener)),\n role: \"combobox\",\n ariaHaspopup: \"dialog\",\n ariaExpanded: (listener) => openState.get(listener),\n ariaControls: (listener) =>\n listener?.elementNode\n ? floatingPanelId(\"datePicker\", listener.elementNode)\n : undefined,\n ariaLabel: \"Choose date\",\n style: { cursor: \"pointer\" },\n onClick: (_e, node) => {\n openAndFocus(node);\n },\n // NOT on focus. The APG combobox contract is \"Escape dismisses the popup\n // and returns focus to the combobox\" — and floating.ts now does return the\n // focus — so an onFocus that re-opens makes Escape permanently\n // un-dismissable (measured in Chromium: panel back within 100ms of every\n // Escape). It also popped the calendar over the next fields whenever a\n // keyboard user merely Tabbed through the form. Click, ArrowDown and Enter\n // cover every path, as in the APG Date Picker Combobox example, React Aria\n // and MUI.\n onKeyDown: (event, node) => {\n const key = (event as KeyboardEvent).key;\n if (key === \"ArrowDown\" || key === \"Enter\") {\n event.preventDefault();\n openAndFocus(node);\n }\n },\n ...behavior<DatePickerStates>(\"datePicker\", attachDatePicker, {\n selection,\n selectionIsCallerOwned: props.value !== undefined,\n viewYear,\n viewMonth,\n focused,\n hovered,\n hour,\n minute,\n open: openState,\n onChange,\n }),\n };\n function openAndFocus(node?: ElementNode): void {\n const current = isSelectedPrimary() ?? new Date();\n focused.set(atMidnight(current));\n goToDate(current);\n show(node);\n focusActiveCell(node);\n }\n function isSelectedPrimary(): Date | null {\n const current = selection.get();\n if (mode === \"range\")\n return (current as [Date | null, Date | null])?.[0] ?? null;\n return (current as Date | null) ?? null;\n }\n merge(anchorPartial, triggerPartial);\n return anchorPartial;\n\n // --- calendar builder -----------------------------------------------------\n function buildCalendar(): DomphyElement<\"div\"> {\n const navButton = (label: string, ariaLabel: string, onClick: () => void) =>\n ({\n button: label,\n type: \"button\",\n ariaLabel,\n onClick,\n style: navButtonStyle(),\n }) as DomphyElement;\n\n const header: DomphyElement<\"div\"> = {\n div: [\n navButton(\"«\", \"Previous year\", () => shiftYear(-1)),\n navButton(\"‹\", \"Previous month\", () => shiftMonth(-1)),\n {\n div: (listener) =>\n monthFormatter.format(\n new Date(viewYear.get(listener), viewMonth.get(listener), 1),\n ),\n ariaLive: \"polite\",\n style: {\n flex: \"1\",\n textAlign: \"center\",\n fontWeight: themeWeight(\"bold\"),\n fontSize: (listener) => themeSize(listener),\n },\n },\n navButton(\"›\", \"Next month\", () => shiftMonth(1)),\n navButton(\"»\", \"Next year\", () => shiftYear(1)),\n ],\n style: {\n display: \"flex\",\n alignItems: \"center\",\n gap: themeSpacing(1),\n marginBottom: themeSpacing(2),\n },\n };\n\n const weekdayHeader: DomphyElement<\"div\"> = {\n div: weekdayNames.map((name, index) => ({\n div: name,\n style: {\n textAlign: \"center\",\n fontSize: (listener) => themeSize(listener, \"decrease-1\"),\n fontWeight: themeWeight(\"bold\"),\n color: (listener) => themeColor(listener, \"shift-7\"),\n paddingBlock: themeSpacing(1),\n },\n _key: index,\n })),\n role: \"row\",\n style: gridRowStyle(),\n };\n\n const grid: DomphyElement<\"div\"> = {\n div: (listener) => buildWeeks(listener),\n role: \"grid\",\n ariaLabel: \"Calendar\",\n onKeyDown: onGridKey,\n onMouseLeave: () => mode === \"range\" && hovered.set(null),\n style: {\n display: \"flex\",\n flexDirection: \"column\",\n gap: themeSpacing(0.5),\n },\n };\n\n const children: DomphyElement[] = [header, weekdayHeader, grid];\n if (time) children.push(buildTimeRow());\n children.push(buildFooter());\n\n return {\n div: children,\n role: \"dialog\",\n ariaModal: \"false\",\n // Surface contract (same as popover/combobox): page-matching shift-0\n // (menu/selectList/dialog), inherit background + \"text\" color. The\n // previous `themeColor(l, \"base\")` resolved to the ramp's MID anchor\n // (var(--neutral-8), gray) with text only 2 tone steps away — an\n // unreadable washed-out panel, invisible to doctor because the calendar\n // is mounted imperatively at runtime. shift-14 inverted the panel in\n // light theme (a dark calendar on a light page).\n dataTone: \"shift-0\",\n style: {\n minWidth: themeSpacing(70),\n padding: themeSpacing(3),\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 2),\n backgroundColor: (listener) => themeColor(listener, \"inherit\"),\n color: (listener) => themeColor(listener, \"text\"),\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\")}`,\n outlineOffset: \"-1px\",\n boxShadow: elevation(\"medium\"),\n },\n };\n }\n\n function buildWeeks(listener: Listener): DomphyElement[] {\n const first = new Date(viewYear.get(listener), viewMonth.get(listener), 1);\n const month = viewMonth.get(listener);\n const start = startOfWeek(first, weekStart);\n const weeks: DomphyElement[] = [];\n for (let week = 0; week < 6; week++) {\n const cells: DomphyElement[] = [];\n for (let day = 0; day < 7; day++) {\n const date = addDays(start, week * 7 + day);\n cells.push(buildDayCell(date, month, listener));\n }\n weeks.push({\n div: cells,\n role: \"row\",\n style: gridRowStyle(),\n _key: week,\n });\n }\n return weeks;\n }\n\n function buildDayCell(\n date: Date,\n month: number,\n listener: Listener,\n ): DomphyElement {\n const disabled = isDisabled(date);\n const selected = isSelectedEnd(date, listener);\n const within = inSelectedRange(date, listener);\n const outside = date.getMonth() !== month;\n const isFocused = sameDay(date, focused.get(listener));\n const isToday = sameDay(date, new Date());\n\n return {\n button: String(date.getDate()),\n type: \"button\",\n role: \"gridcell\",\n tabIndex: isFocused ? 0 : -1,\n ariaSelected: selected,\n ariaDisabled: disabled,\n disabled,\n ariaLabel: fullDateFormatter.format(date),\n dataDate: isoOf(date),\n onClick: (_e: Event, node: ElementNode) => selectDate(date, node),\n onMouseEnter: () => mode === \"range\" && hovered.set(date),\n style: {\n appearance: \"none\",\n border: \"none\",\n cursor: disabled ? \"not-allowed\" : \"pointer\",\n aspectRatio: \"1\",\n borderRadius: themeSpacing(1),\n fontSize: (l: Listener) => themeSize(l),\n opacity: disabled ? 0.35 : outside ? 0.5 : 1,\n // Selected day: the deep-fill + light-text pairing the rest of the\n // library uses for a chosen row (selectItem, pagination, solid\n // button). The old shift-7 fill under shift-0 text measured 3.73:1\n // (light) / 2.92:1 (dark) — a gap of 7, below the ramp's K=9 span.\n backgroundColor: (l: Listener) =>\n selected\n ? themeColor(l, \"shift-13\", accentColor.get(l))\n : within\n ? themeColor(l, \"hover\", accentColor.get(l))\n : \"transparent\",\n // An in-range day sits on a +2 accent fill, so its number tracks it\n // (3.51:1 at the plain \"text\" tone, light).\n color: (l: Listener) =>\n selected\n ? themeColor(l, \"shift-0\", \"neutral\")\n : within\n ? themeColor(l, textToneOn(2))\n : themeColor(l, \"text\"),\n outline: isToday\n ? (l: Listener) =>\n `1px solid ${themeColor(l, \"shift-6\", accentColor.get(l))}`\n : \"none\",\n outlineOffset: \"-2px\",\n \"&:hover:not([disabled])\": {\n backgroundColor: (l: Listener) =>\n selected\n ? themeColor(l, \"shift-13\", accentColor.get(l))\n : themeColor(l, \"shift-3\", accentColor.get(l)),\n // Unselected hover paints a +3 fill; the day number follows it\n // (2.93:1 at the plain \"text\" tone, light).\n ...(selected\n ? {}\n : { color: (l: Listener) => themeColor(l, textToneOn(3)) }),\n },\n transition: \"background-color 140ms ease, box-shadow 140ms ease\",\n \"&:focus-visible\": {\n boxShadow: (l: Listener) => focusRing(l, accentColor.get(l)),\n },\n },\n _key: isoOf(date),\n } as DomphyElement;\n }\n\n function buildTimeRow(): DomphyElement<\"div\"> {\n const numberSelect = (\n count: number,\n state: ReturnType<typeof toState<number>>,\n ariaLabel: string,\n ): DomphyElement => ({\n select: Array.from({ length: count }, (_unused, value) => ({\n option: String(value).padStart(2, \"0\"),\n value: String(value),\n selected: (listener) => state.get(listener) === value,\n _key: value,\n })) as DomphyElement[],\n ariaLabel,\n onChange: (event) => {\n state.set(Number((event.target as HTMLSelectElement).value));\n reapplyTime();\n },\n style: timeSelectStyle(),\n });\n\n return {\n div: [\n numberSelect(24, hour, \"Hour\"),\n { span: \":\", style: { fontWeight: themeWeight(\"bold\") } },\n numberSelect(60, minute, \"Minute\"),\n ],\n style: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: themeSpacing(1),\n marginTop: themeSpacing(3),\n },\n };\n }\n\n function buildFooter(): DomphyElement<\"div\"> {\n const action = (\n label: string,\n onClick: (node: ElementNode) => void,\n ): DomphyElement => ({\n button: label,\n type: \"button\",\n onClick: (_e: Event, node: ElementNode) => onClick(node),\n style: {\n appearance: \"none\",\n border: \"none\",\n background: \"transparent\",\n cursor: \"pointer\",\n fontSize: (l: Listener) => themeSize(l, \"decrease-1\"),\n color: (l: Listener) => themeColor(l, \"muted\", accentColor.get(l)),\n padding: themeSpacing(1),\n },\n });\n return {\n div: [\n action(\"Today\", (node) => {\n const today = new Date();\n focused.set(atMidnight(today));\n goToDate(today);\n focusActiveCell(node);\n }),\n action(\"Clear\", () => {\n selection.set(mode === \"range\" ? [null, null] : null);\n hovered.set(null);\n }),\n ],\n style: {\n display: \"flex\",\n justifyContent: \"space-between\",\n marginTop: themeSpacing(2),\n paddingTop: themeSpacing(2),\n borderTop: (l: Listener) => `1px solid ${themeColor(l, \"border\")}`,\n },\n };\n }\n\n function onGridKey(event: Event, node: ElementNode): void {\n const keyboard = event as KeyboardEvent;\n const current = focused.get();\n let next: Date | null = null;\n switch (keyboard.key) {\n case \"ArrowLeft\":\n next = addDays(current, -1);\n break;\n case \"ArrowRight\":\n next = addDays(current, 1);\n break;\n case \"ArrowUp\":\n next = addDays(current, -7);\n break;\n case \"ArrowDown\":\n next = addDays(current, 7);\n break;\n case \"Home\":\n next = startOfWeek(current, weekStart);\n break;\n case \"End\":\n next = addDays(startOfWeek(current, weekStart), 6);\n break;\n case \"PageUp\":\n next = addMonths(current, keyboard.shiftKey ? -12 : -1);\n break;\n case \"PageDown\":\n next = addMonths(current, keyboard.shiftKey ? 12 : 1);\n break;\n case \"Enter\":\n case \" \":\n keyboard.preventDefault();\n selectDate(current, node);\n return;\n default:\n return;\n }\n keyboard.preventDefault();\n focused.set(next);\n goToDate(next);\n focusActiveCell(node);\n }\n}\n\n// --- shared style fragments --------------------------------------------------\n\nfunction gridRowStyle() {\n return {\n display: \"grid\",\n gridTemplateColumns: \"repeat(7, 1fr)\",\n gap: themeSpacing(0.5),\n };\n}\n\nfunction navButtonStyle() {\n return {\n appearance: \"none\" as const,\n border: \"none\",\n background: \"transparent\",\n cursor: \"pointer\",\n fontSize: (l: Listener) => themeSize(l),\n color: (l: Listener) => themeColor(l, \"muted\"),\n width: themeSpacing(7),\n height: themeSpacing(7),\n borderRadius: themeSpacing(1),\n \"&:hover\": {\n backgroundColor: (l: Listener) => themeColor(l, \"shift-3\"),\n // The chevron glyph tracks the +3 hover fill: \"muted\" on it measured\n // 2.48:1 (light) / 2.98:1 (dark).\n color: (l: Listener) => themeColor(l, textToneOn(3)),\n },\n };\n}\n\nfunction timeSelectStyle() {\n return {\n fontSize: (l: Listener) => themeSize(l),\n padding: themeSpacing(1),\n borderRadius: themeSpacing(1),\n // outline, not border — bounded control, keep the geometry formula exact.\n border: \"none\",\n outlineOffset: \"-1px\",\n outline: (l: Listener) => `1px solid ${themeColor(l, \"border-strong\")}`,\n backgroundColor: (l: Listener) => themeColor(l, \"inherit\"),\n color: (l: Listener) => themeColor(l, \"text\"),\n };\n}\n\nexport { datePicker };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n themeWeight,\n} from \"@domphy/theme\";\n\n/**\n * Styles a description list as a two-column grid (terms in the first column,\n * descriptions in the second), theming the nested `<dt>`/`<dd>` elements.\n * Apply to a `<dl>` element.\n *\n * @hostTag dl\n * @param props.color - Theme color tone (`ValueOrState<ThemeColor>`) for the term/description text. Defaults to \"neutral\".\n * @example { dl: [{ dt: \"Name\" }, { dd: \"Domphy\" }], $: [descriptionList()] }\n */\nfunction descriptionList(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"dl\") {\n console.warn(`\"descriptionList\" primitive patch must use dl tag`);\n }\n },\n style: {\n display: \"grid\",\n gridTemplateColumns: `minmax(${themeSpacing(24)}, max-content) 1fr`,\n columnGap: themeSpacing(4),\n margin: 0,\n \"& dt\": {\n margin: 0,\n fontWeight: themeWeight(\"semibold\"),\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n color: (listener) =>\n themeColor(listener, \"shift-10\", color.get(listener)),\n },\n \"& dd\": {\n margin: 0,\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n },\n },\n };\n}\n\nexport { descriptionList };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n textToneOn,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n themeWeight,\n} from \"@domphy/theme\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * Styles a native disclosure widget: a themed `<summary>` header with an\n * animated rotating chevron and an expand/collapse transition on the body\n * content. Apply to a `<details>` element.\n *\n * @hostTag details\n * @param props.color - Theme color tone (`ValueOrState<ThemeColor>`) for the body/summary. Defaults to \"neutral\".\n * @param props.accentColor - Accent color (`ValueOrState<ThemeColor>`) for the summary's focus ring. Defaults to \"primary\".\n * @param props.duration - Open/close transition duration in milliseconds. Defaults to 240.\n * @example { details: [{ summary: \"More\" }, { div: \"Body\" }], $: [details()] }\n */\nfunction details(\n props: {\n color?: ValueOrState<ThemeColor>;\n accentColor?: ValueOrState<ThemeColor>;\n duration?: number;\n } = {},\n): PartialElement {\n const { duration = 240 } = props;\n const color = toState(props.color ?? \"neutral\", \"color\");\n const accentColor = toState(props.accentColor ?? \"primary\", \"accentColor\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"details\") {\n console.warn(`\"details\" primitive patch must use details tag`);\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n\n overflow: \"hidden\",\n \"& > summary\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-2\", color.get(listener)),\n // shift-11 on a shift-2 header band = the design system's 9-step\n // contrast span. shift-10 was a gap of 8 and measured 4.33:1\n // (#636363 on #dbdbdb) — an axe `color-contrast` WCAG AA failure.\n color: (listener) =>\n themeColor(listener, \"shift-11\", color.get(listener)),\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n listStyle: \"none\",\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n gap: themeSpacing(2),\n cursor: \"pointer\",\n userSelect: \"none\",\n fontWeight: themeWeight(\"medium\"),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 4),\n height: themeSpacing(10),\n },\n \"& > summary::-webkit-details-marker\": {\n display: \"none\",\n },\n \"& > summary::marker\": {\n content: `\"\"`,\n },\n \"& > summary::after\": {\n content: `\"\"`,\n width: themeSpacing(2),\n height: themeSpacing(2),\n flexShrink: 0,\n marginTop: themeSpacing(-0.5),\n borderInlineEnd: (listener) =>\n `${themeSpacing(0.5)} solid ${themeColor(listener, \"shift-9\", color.get(listener))}`,\n borderBottom: (listener) =>\n `${themeSpacing(0.5)} solid ${themeColor(listener, \"shift-9\", color.get(listener))}`,\n transform: \"rotate(45deg)\",\n transition: `transform ${duration}ms ease`,\n },\n \"&[open] > summary::after\": {\n transform: \"rotate(-135deg)\",\n },\n \"& > summary:hover\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-3\", color.get(listener)),\n // Summary text tracks the +3 hover fill: inherited shift-9 body text\n // measured 3.02:1 on it (light) / 3.63:1 (dark), below WCAG AA.\n color: (listener) =>\n themeColor(listener, textToneOn(3), color.get(listener)),\n },\n \"& > summary:focus-visible\": {\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 2),\n boxShadow: (listener) => focusRing(listener, accentColor.get(listener)),\n },\n \"& > :not(summary)\": {\n maxHeight: 0,\n opacity: 0,\n overflow: \"hidden\",\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 3),\n paddingTop: 0,\n paddingBottom: 0,\n transition: `max-height ${duration}ms ease, opacity ${duration}ms ease, padding ${duration}ms ease`,\n },\n \"&[open] > :not(summary)\": {\n // Non-clipping open state: a bounded max-height here (previously\n // themeSpacing(250) ≈ 1000px) silently CUT OFF body content taller\n // than the cap while fully open. CSS cannot transition max-height\n // to/from `none`, so the open transition is carried by opacity +\n // padding (both still animate over `duration`); max-height jumps\n // straight to none and tall content is never clipped.\n maxHeight: \"none\",\n opacity: 1,\n paddingTop: (listener) => themeSpacing(themeDensity(listener) * 1),\n paddingBottom: (listener) => themeSpacing(themeDensity(listener) * 3),\n },\n },\n };\n}\n\nexport { details };\n","import {\n type BehaviorInstance,\n behavior,\n type ElementNode,\n type PartialElement,\n type ReadableState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { elevation } from \"../utils/elevation.js\";\nimport { hasOpenFloatingPanel } from \"../utils/floating.js\";\nimport { asOpenState, dismissOpen, subscribeOpen } from \"../utils/openState.js\";\nimport { lockScroll, unlockScroll } from \"../utils/scrollLock.js\";\n\nconst FOCUSABLE =\n 'button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), details, [tabindex]:not([tabindex=\"-1\"])';\n\ntype DialogProps = {\n state: ReadableState<boolean>;\n // Lives on the behavior instance so a reused node gets the latest callback\n // via update() — do not close over factory-generation onDismiss.\n onDismiss?: () => void;\n};\n\ntype DialogInstance = BehaviorInstance<DialogProps> & {\n // Close via the instance's CURRENT state — routing through the behavior\n // guarantees the state being set is the one the open/close subscription\n // listens to, even when a re-rendered generation's closure would otherwise\n // set its own fresh (unsubscribed) default state.\n requestClose: () => void;\n onTransitionEnd: (e: Event) => void;\n};\n\n// All close-finalization state (closing flag, previousFocus, scrollLocked,\n// the fallback timer) lives in ONE behavior instance per dialog node. It used\n// to be factory-scope variables captured by _onMount — but _onMount runs once\n// for the FIRST generation only, while onTransitionEnd (live-rebound every\n// patch) belongs to the LATEST generation: gen-1's update() set gen-1's\n// `closing = true` and the live gen-N handler read gen-N's `closing` (false)\n// and early-returned, so every close fell back to the 350ms timer and focus\n// restore scrolled through stale closures. behavior() attaches once and\n// routes every later generation's props into the same instance (floating.ts\n// pattern).\nfunction attachDialog(\n node: ElementNode,\n initialProps: DialogProps,\n): DialogInstance {\n let { state, onDismiss } = initialProps;\n let previousFocus: HTMLElement | null = null;\n let closing = false;\n let scrollLocked = false;\n let closeTimer: ReturnType<typeof setTimeout> | null = null;\n\n const dlg = node.domElement as HTMLDialogElement;\n dlg.setAttribute(\"aria-modal\", \"true\");\n\n const finalizeClose = () => {\n closing = false;\n // Guard for environments with HTMLDialogElement but no close()\n // implementation (e.g. jsdom in tests).\n if (typeof dlg.close === \"function\") dlg.close();\n // visibility/pointer-events/display (not just opacity) must reflect the\n // closed state: opacity alone leaves a closed dialog's content fully\n // reachable by Tab and exposed to the accessibility tree (opacity, unlike\n // visibility, never removes an element from either) — and a consumer\n // that sets its own `style: { display: ... }` on the dialog (a common\n // pattern for centering content) overrides the UA stylesheet's\n // `dialog:not([open]) { display: none }`, so `dlg.close()` alone doesn't\n // reliably hide it either. visibility+pointer-events still leave the\n // node in the layout and in the document for password-managers / autofocus.\n // Set INLINE so it always wins regardless of what the consumer's own\n // style object declares. Do not put `display: none` on the patch CSS\n // class — native `style.display` would lose to that class on reopen.\n dlg.style.visibility = \"hidden\";\n dlg.style.pointerEvents = \"none\";\n dlg.style.display = \"none\";\n if (scrollLocked) {\n unlockScroll();\n scrollLocked = false;\n }\n previousFocus?.focus();\n previousFocus = null;\n };\n\n const trapFocus = (e: KeyboardEvent) => {\n if (e.key !== \"Tab\") return;\n const focusables = Array.from(\n dlg.querySelectorAll<HTMLElement>(FOCUSABLE),\n ).filter(\n // getClientRects() is empty only when the element (or an ancestor) has\n // `display: none` or the element itself has no layout box — unlike\n // `offsetParent`, which is ALSO null for a `position: fixed`\n // descendant even though it is fully visible, so the trap silently\n // skipped fixed-position focusables inside the dialog.\n (el) =>\n !el.closest(\"[aria-hidden='true']\") && el.getClientRects().length > 0,\n );\n if (!focusables.length) {\n e.preventDefault();\n return;\n }\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n if (e.shiftKey) {\n if (document.activeElement === first || document.activeElement === dlg) {\n e.preventDefault();\n last.focus();\n }\n } else {\n if (document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n };\n\n const onCancel = (e: Event) => {\n e.preventDefault();\n // Top-layer-only dismissal: an open popover/select/datePicker inside this\n // dialog owns the Escape (see hasOpenFloatingPanel).\n if (hasOpenFloatingPanel(dlg)) return;\n dismissOpen(state, onDismiss);\n };\n dlg.addEventListener(\"cancel\", onCancel);\n\n const update = (val: boolean) => {\n if (val) {\n // Cancel any in-flight close: a pending fallback timer or a true\n // `closing` flag left over from the previous close (e.g. reopening\n // within the 350ms window, or the mount-time close of an\n // initially-closed dialog) would otherwise finalize-close the\n // just-opened dialog on the open fade's own transitionend.\n closing = false;\n if (closeTimer) {\n clearTimeout(closeTimer);\n closeTimer = null;\n }\n previousFocus = document.activeElement as HTMLElement;\n dlg.style.visibility = \"visible\";\n dlg.style.pointerEvents = \"auto\";\n // Drop the closed-state inline display so the consumer's own\n // `style.display` (or the UA open-dialog rule) can apply.\n dlg.style.display = \"\";\n // Guard for environments with HTMLDialogElement but no showModal()\n // implementation (e.g. jsdom in tests). Also guard against re-entering\n // on an already-open dialog — showModal() throws InvalidStateError in\n // real browsers when the dialog is already open.\n if (typeof dlg.showModal === \"function\" && !dlg.open) dlg.showModal();\n if (!scrollLocked) {\n lockScroll();\n scrollLocked = true;\n }\n dlg.addEventListener(\"keydown\", trapFocus);\n requestAnimationFrame(() => {\n dlg.style.opacity = \"1\";\n // `[autofocus]` wins over \"first focusable\" — that is what the HTML\n // dialog focusing steps do, and what Radix Dialog / MUI Dialog /\n // Mantine Modal all honour. Without it the initial focus landed on\n // whatever happened to come first in the DOM (typically a close or\n // cancel button) and there was no way for a consumer to redirect it.\n const focusable =\n dlg.querySelector<HTMLElement>(\"[autofocus]:not([disabled])\") ??\n dlg.querySelector<HTMLElement>(FOCUSABLE);\n focusable?.focus();\n });\n } else {\n closing = true;\n dlg.style.opacity = \"0\";\n dlg.removeEventListener(\"keydown\", trapFocus);\n // Mounted already-closed (never opened): no fade to play — hide now\n // so a consumer `display: flex` cannot keep the closed node in layout\n // for the 350ms timer (or forever, if transitionend also never fires).\n if (!dlg.open) {\n finalizeClose();\n return;\n }\n // Fallback: if transitionend never fires (reduced-motion, display:none),\n // unblock close after the transition duration + buffer.\n closeTimer = setTimeout(() => {\n closeTimer = null;\n if (!closing) return;\n finalizeClose();\n }, 350);\n }\n };\n let release = subscribeOpen(state, update);\n\n return {\n requestClose: () => dismissOpen(state, onDismiss),\n onTransitionEnd: (e: Event) => {\n if (!closing) return;\n // Guard against bubbled transitionend from nested content (e.g. an\n // accordion/details transition inside the dialog) prematurely\n // triggering close-finalization.\n if (e.target !== dlg) return;\n if ((e as TransitionEvent).propertyName !== \"opacity\") return;\n finalizeClose();\n },\n update(props) {\n onDismiss = props.onDismiss;\n // Re-subscribe when a later generation brings a genuinely different\n // state object (e.g. the default `toState(false)` allocated per\n // factory call); a caller-owned state arrives as the SAME object and\n // keeps its existing subscription untouched.\n if (props.state !== state) {\n release();\n state = props.state;\n release = subscribeOpen(state, update, false);\n }\n },\n destroy() {\n if (closeTimer) {\n clearTimeout(closeTimer);\n closeTimer = null;\n }\n release();\n dlg.removeEventListener(\"cancel\", onCancel);\n if (scrollLocked) {\n unlockScroll();\n scrollLocked = false;\n }\n dlg.removeEventListener(\"keydown\", trapFocus);\n previousFocus?.focus();\n previousFocus = null;\n },\n };\n}\n\n/**\n * Modal dialog patch driven by an `open` State. Calls `showModal()`/`close()`,\n * fades via opacity, locks page scroll while open, traps Tab focus within the\n * dialog, restores focus to the previously focused element on close, sets\n * `aria-modal`, and closes on outside (backdrop) click. Apply to a `<dialog>`.\n * Closed state is inline `visibility`/`pointer-events`/`display:none` so a\n * consumer `style.display` cannot keep the node in layout.\n *\n * Accessible name/description: pass `labelledBy`/`describedBy` the `id` of a\n * heading/paragraph inside the dialog (Radix Title/Description parity). The\n * native `ariaLabelledby`/`ariaDescribedby` attributes on the host element\n * remain an equivalent escape hatch (the native element always wins).\n *\n * @hostTag dialog\n * @param props.color - Theme color tone for the dialog surface. Defaults to \"neutral\".\n * @param props.open - Open state (`ValueOrState<boolean>`), including `Computed`/`ReadableState`. When the source is read-only, pass `onDismiss` so Escape/backdrop can close. Defaults to false.\n * @param props.onDismiss - Called when Escape/backdrop/`requestClose` request close. Optional. Required to close when `open` is a read-only `Computed`/`ReadableState`.\n * @param props.labelledBy - `id` of the element labeling the dialog (wired to `aria-labelledby`). Optional.\n * @param props.describedBy - `id` of the element describing the dialog (wired to `aria-describedby`). Optional.\n * @example { dialog: [{ h2: \"Confirm\", id: \"dlg-title\" }], $: [dialog({ open, labelledBy: \"dlg-title\" })] }\n */\nfunction dialog(\n props: {\n color?: ThemeColor;\n open?: ValueOrState<boolean>;\n onDismiss?: () => void;\n labelledBy?: string;\n describedBy?: string;\n } = {},\n): PartialElement {\n const {\n color = \"neutral\",\n open = false,\n labelledBy,\n describedBy,\n onDismiss,\n } = props;\n const state = asOpenState(open);\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"dialog\") {\n console.warn(`\"dialog\" primitive patch must use dialog tag`);\n }\n },\n ...behavior<DialogProps>(\"dialog\", attachDialog, { state, onDismiss }),\n ariaLabelledby: labelledBy,\n ariaDescribedby: describedBy,\n onClick: (e: MouseEvent, node) => {\n if (e.target !== node.domElement) return;\n const r = node.domElement!.getBoundingClientRect();\n const inside =\n e.clientX >= r.left &&\n e.clientX <= r.right &&\n e.clientY >= r.top &&\n e.clientY <= r.bottom;\n if (!inside) node.getBehavior<DialogInstance>(\"dialog\")?.requestClose();\n },\n onTransitionEnd: (e, node) =>\n node.getBehavior<DialogInstance>(\"dialog\")?.onTransitionEnd(e),\n style: {\n opacity: \"0\",\n // Matches finalizeClose's inline defaults — a dialog that mounts\n // already-closed (the common case: `open` defaults to false) must\n // start out of the tab order/accessibility tree from first paint, not\n // just after its first open->close cycle runs finalizeClose.\n visibility: \"hidden\",\n pointerEvents: \"none\",\n transition: \"opacity 200ms ease\",\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n color: (listener) => themeColor(listener, \"shift-10\", color),\n backgroundColor: (listener) => themeColor(listener, \"inherit\", color),\n border: \"none\",\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 2),\n padding: (listener) => themeSpacing(themeDensity(listener) * 3),\n boxShadow: elevation(\"high\"),\n \"&::backdrop\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-2\", \"neutral\"),\n opacity: 0.75,\n },\n },\n };\n}\n\nexport { dialog };\n","// Shared page-scroll lock for modal-like patches (dialog, drawer). A\n// module-level counter (not a plain boolean) is required because two\n// overlays can be open at once (e.g. a dialog opened from within a drawer);\n// without a counter, closing the inner one would clear `overflow` while the\n// outer one is still open.\nlet lockCount = 0;\n\nfunction lockScroll(): void {\n lockCount++;\n if (lockCount === 1) document.body.style.overflow = \"hidden\";\n}\n\nfunction unlockScroll(): void {\n lockCount = Math.max(0, lockCount - 1);\n if (lockCount === 0) document.body.style.overflow = \"\";\n}\n\n// Test-only: reset the module-level counter so a test that unmounts its tree\n// via `document.body.innerHTML = \"\"` (skipping the Remove hook / unlockScroll\n// call) doesn't leak a locked count into the next test.\nfunction _resetScrollLock(): void {\n lockCount = 0;\n}\n\nexport { lockScroll, unlockScroll, _resetScrollLock };\n","import type { PartialElement } from \"@domphy/core\";\nimport { toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * A horizontal separator (`role=\"separator\"`) with a line on each side of its\n * content, suitable for labelled dividers (\"or\"). Apply to a `<div>` element.\n *\n * @hostTag div\n * @param props.color - Theme color tone (`ValueOrState<ThemeColor>`) for the label text and rules. Defaults to \"neutral\".\n * @example { div: \"or\", $: [divider()] }\n */\nfunction divider(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n role: \"separator\",\n _onInsert: (node) => {\n if (node.tagName !== \"div\") {\n console.warn(`\"divider\" patch should be used with <div>`);\n }\n },\n style: {\n display: \"flex\",\n justifyContent: \"center\",\n alignItems: \"baseline\",\n gap: themeSpacing(2),\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n backgroundColor: (listener) => themeColor(listener),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n minHeight: \"1lh\",\n \"&::before\": {\n content: `\"\"`,\n flex: 1,\n borderColor: (listener) =>\n themeColor(listener, \"border-strong\", color.get(listener)),\n borderWidth: \"1px\",\n borderBottomStyle: \"solid\",\n },\n \"&::after\": {\n content: `\"\"`,\n flex: 1,\n borderColor: (listener) =>\n themeColor(listener, \"border-strong\", color.get(listener)),\n borderWidth: \"1px\",\n borderBottomStyle: \"solid\",\n },\n },\n };\n}\n\nexport { divider };\n","import {\n type BehaviorInstance,\n behavior,\n type ElementNode,\n type PartialElement,\n type ReadableState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { elevation } from \"../utils/elevation.js\";\nimport { hasOpenFloatingPanel } from \"../utils/floating.js\";\nimport { asOpenState, dismissOpen, subscribeOpen } from \"../utils/openState.js\";\nimport { lockScroll, unlockScroll } from \"../utils/scrollLock.js\";\n\ntype PhysicalPlacement = \"left\" | \"right\" | \"top\" | \"bottom\";\ntype Placement = PhysicalPlacement | \"start\" | \"end\";\n\nconst translateOut: Record<PhysicalPlacement, string> = {\n left: \"translateX(-100%)\",\n right: \"translateX(100%)\",\n top: \"translateY(-100%)\",\n bottom: \"translateY(100%)\",\n};\n\nconst marginMap: Record<PhysicalPlacement, string> = {\n left: \"0 auto 0 0\",\n right: \"0 0 0 auto\",\n top: \"0 0 auto 0\",\n bottom: \"auto 0 0 0\",\n};\n\nconst isVertical = (p: PhysicalPlacement) => p === \"left\" || p === \"right\";\n\nfunction resolvePhysical(\n placement: Placement,\n isRTL: boolean,\n): PhysicalPlacement {\n if (placement === \"start\") return isRTL ? \"right\" : \"left\";\n if (placement === \"end\") return isRTL ? \"left\" : \"right\";\n return placement;\n}\n\ntype DrawerProps = {\n state: ReadableState<boolean>;\n // Lives on the behavior instance so a reused node gets the latest callback\n // via update() — do not close over factory-generation onDismiss.\n onDismiss?: () => void;\n placement: Placement;\n size?: string;\n};\n\ntype DrawerInstance = BehaviorInstance<DrawerProps> & {\n requestClose: () => void;\n};\n\nfunction attachDrawer(\n node: ElementNode,\n initialProps: DrawerProps,\n): DrawerInstance {\n let { state, onDismiss, placement, size } = initialProps;\n\n const dlg = node.domElement as HTMLDialogElement;\n dlg.setAttribute(\"aria-modal\", \"true\");\n\n const onCancel = (e: Event) => {\n e.preventDefault();\n // Top-layer-only dismissal: an open popover/select/datePicker inside this\n // drawer owns the Escape (see hasOpenFloatingPanel).\n if (hasOpenFloatingPanel(dlg)) return;\n dismissOpen(state, onDismiss);\n };\n dlg.addEventListener(\"cancel\", onCancel);\n\n const resolve = (nextPlacement: Placement, nextSize?: string) => {\n const isLogical = nextPlacement === \"start\" || nextPlacement === \"end\";\n const isRTL =\n isLogical &&\n (dlg.ownerDocument.documentElement.dir === \"rtl\" ||\n dlg.ownerDocument.dir === \"rtl\");\n const physical = resolvePhysical(nextPlacement, isRTL);\n const drawerSize =\n nextSize ?? (isVertical(physical) ? themeSpacing(80) : themeSpacing(64));\n dlg.style.margin = marginMap[physical];\n dlg.style.width = isVertical(physical) ? drawerSize : \"100dvw\";\n dlg.style.height = isVertical(physical) ? \"100dvh\" : drawerSize;\n return physical;\n };\n\n let physical = resolve(placement, size);\n\n let closing = false;\n let scrollLocked = false;\n let closeTimer: ReturnType<typeof setTimeout> | null = null;\n\n const finishClose = () => {\n closeTimer = null;\n if (!closing) return;\n closing = false;\n // Guard for environments with HTMLDialogElement but no close()\n // implementation (e.g. jsdom in tests).\n if (typeof dlg.close === \"function\") dlg.close();\n // Same fix as dialog.ts: the closed state was only ever represented\n // by an off-screen `transform`, never visibility/pointer-events/display\n // — a closed drawer stayed fully reachable by Tab and exposed to the\n // accessibility tree (a CSS transform, like opacity, does neither),\n // and a consumer's own `style: { display: ... }` overrides the UA\n // stylesheet's `dialog:not([open])` rule anyway. Set INLINE so it\n // always wins. Do not put `display: none` on the patch CSS class —\n // native `style.display` would lose to that class on reopen.\n dlg.style.visibility = \"hidden\";\n dlg.style.pointerEvents = \"none\";\n dlg.style.display = \"none\";\n if (scrollLocked) {\n unlockScroll();\n scrollLocked = false;\n }\n };\n\n const onTransitionEnd = (e: Event) => {\n if (e.target !== dlg) return;\n if ((e as TransitionEvent).propertyName !== \"transform\") return;\n finishClose();\n };\n dlg.addEventListener(\"transitionend\", onTransitionEnd);\n\n const update = (val: boolean) => {\n if (val) {\n // Cancel any in-flight close: a pending fallback timer or a leftover\n // `closing` flag would otherwise finalize-close the just-opened drawer\n // when the open slide's own transitionend (or the 350ms timer) fires.\n closing = false;\n if (closeTimer) {\n clearTimeout(closeTimer);\n closeTimer = null;\n }\n dlg.style.visibility = \"visible\";\n dlg.style.pointerEvents = \"auto\";\n dlg.style.display = \"\";\n // Guard for environments with HTMLDialogElement but no showModal()\n // implementation (e.g. jsdom in tests). Also guard against re-entering\n // on an already-open dialog — showModal() throws InvalidStateError in\n // real browsers when the dialog is already open.\n if (typeof dlg.showModal === \"function\" && !dlg.open) dlg.showModal();\n if (!scrollLocked) {\n lockScroll();\n scrollLocked = true;\n }\n requestAnimationFrame(() => {\n dlg.style.transform = \"translate(0, 0)\";\n });\n } else {\n closing = true;\n dlg.style.transform = translateOut[physical];\n if (!dlg.open) {\n finishClose();\n return;\n }\n closeTimer = setTimeout(finishClose, 350);\n }\n };\n let release = subscribeOpen(state, update);\n\n return {\n requestClose: () => dismissOpen(state, onDismiss),\n update(props) {\n onDismiss = props.onDismiss;\n if (props.state !== state) {\n release();\n state = props.state;\n release = subscribeOpen(state, update, false);\n }\n if (props.placement !== placement || props.size !== size) {\n placement = props.placement;\n size = props.size;\n physical = resolve(placement, size);\n if (!state.get()) dlg.style.transform = translateOut[physical];\n }\n },\n destroy() {\n if (closeTimer) {\n clearTimeout(closeTimer);\n closeTimer = null;\n }\n release();\n dlg.removeEventListener(\"cancel\", onCancel);\n dlg.removeEventListener(\"transitionend\", onTransitionEnd);\n if (scrollLocked) {\n unlockScroll();\n scrollLocked = false;\n }\n },\n };\n}\n\n/**\n * Edge-anchored modal drawer driven by an `open` State. Slides in/out from a\n * chosen edge via a 250 ms transform transition, calls `showModal()`/`close()`,\n * locks page scroll while open, and closes on backdrop click. A 350 ms fallback\n * ensures `close()` is always called even when `transitionend` doesn't fire\n * (reduced-motion, `display:none`, detached element). Apply to a `<dialog>`.\n *\n * Because the patch uses the native `<dialog>` `showModal()` API, the browser\n * traps focus inside the drawer while it is open and restores focus to the\n * previously focused element when `close()` is called. Sets `aria-modal=\"true\"`.\n * Escape key closes the drawer via the animated state path (not immediate close).\n *\n * `\"start\"` and `\"end\"` placements resolve to left/right based on the\n * document's `dir` attribute at mount time, enabling RTL-aware drawers:\n * `\"start\"` → left (LTR) / right (RTL); `\"end\"` → right (LTR) / left (RTL).\n *\n * @hostTag dialog\n * @param props.color - Theme color tone for the drawer surface. Defaults to \"neutral\".\n * @param props.open - Open state (`ValueOrState<boolean>`), including `Computed`/`ReadableState`. When the source is read-only, pass `onDismiss` so Escape/backdrop can close. Defaults to false.\n * @param props.onDismiss - Called when Escape/backdrop/`requestClose` request close. Optional. Required to close when `open` is a read-only `Computed`/`ReadableState`.\n * @param props.placement - Edge to anchor to. \"left\" | \"right\" | \"top\" | \"bottom\" | \"start\" | \"end\". Defaults to \"end\".\n * @param props.size - CSS length for the drawer's width (left/right/start/end) or height (top/bottom). Defaults to themeSpacing(80) for left/right, themeSpacing(64) for top/bottom.\n * @example { dialog: [...], $: [drawer({ open, placement: \"start\" })] }\n */\nfunction drawer(\n props: {\n color?: ThemeColor;\n open?: ValueOrState<boolean>;\n onDismiss?: () => void;\n placement?: Placement;\n size?: string;\n } = {},\n): PartialElement {\n const {\n color = \"neutral\",\n open = false,\n onDismiss,\n placement = \"end\",\n size,\n } = props;\n const state = asOpenState(open);\n\n // For static rendering / SSR assume LTR as fallback; corrected at mount time.\n const physicalFallback = resolvePhysical(placement, false);\n const defaultSize = isVertical(physicalFallback)\n ? themeSpacing(80)\n : themeSpacing(64);\n const drawerSize = size ?? defaultSize;\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"dialog\") {\n console.warn(`\"drawer\" patch must use dialog tag`);\n }\n },\n ...behavior<DrawerProps>(\"drawer\", attachDrawer, {\n state,\n onDismiss,\n placement,\n size,\n }),\n onClick: (e: MouseEvent, node) => {\n if (e.target !== node.domElement) return;\n const r = node.domElement!.getBoundingClientRect();\n const inside =\n e.clientX >= r.left &&\n e.clientX <= r.right &&\n e.clientY >= r.top &&\n e.clientY <= r.bottom;\n if (!inside) node.getBehavior<DrawerInstance>(\"drawer\")?.requestClose();\n },\n style: {\n transform: translateOut[physicalFallback],\n // Matches finishClose's inline defaults — a drawer that mounts\n // already-closed (the common case) must start out of the tab\n // order/accessibility tree from first paint, not just after its first\n // open->close cycle runs finishClose.\n visibility: \"hidden\",\n pointerEvents: \"none\",\n transition: \"transform 0.25s ease\",\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n color: (listener) => themeColor(listener, \"shift-10\", color),\n backgroundColor: (listener) => themeColor(listener, \"inherit\", color),\n border: \"none\",\n padding: (listener) => themeSpacing(themeDensity(listener) * 3),\n margin: marginMap[physicalFallback],\n width: isVertical(physicalFallback) ? drawerSize : \"100dvw\",\n height: isVertical(physicalFallback) ? \"100dvh\" : drawerSize,\n maxWidth: \"100dvw\",\n maxHeight: \"100dvh\",\n boxShadow: elevation(\"high\"),\n \"&::backdrop\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-2\", \"neutral\"),\n opacity: 0.75,\n },\n },\n };\n}\n\nexport { drawer };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport { type ThemeColor, themeColor, themeSize } from \"@domphy/theme\";\n\n/**\n * Italic emphasized inline text. Apply to an `<em>` element.\n *\n * @hostTag em\n * @param props.color - Theme color tone (`ValueOrState<ThemeColor>`) for the text. Defaults to \"neutral\".\n * @example { em: \"important\", $: [emphasis()] }\n */\nfunction emphasis(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"em\") {\n console.warn(`\"emphasis\" primitive patch must use em tag`);\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n fontStyle: \"italic\",\n color: (listener) =>\n themeColor(listener, \"shift-10\", color.get(listener)),\n },\n };\n}\n\nexport { emphasis };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport { type ThemeColor, themeColor, themeSpacing } from \"@domphy/theme\";\n\n/**\n * Styles a container as an empty-state placeholder: centered flex column with\n * muted coloring and comfortable padding. Provide the icon, title, and\n * description as child elements.\n *\n * @param props.color - Theme color tone for the muted text/icon. Defaults to `\"neutral\"`.\n * @example\n * { div: [\n * { span: \"📭\" },\n * { p: \"No items yet\", $: [paragraph()] },\n * { span: \"Add your first item to get started\", $: [small()] },\n * ], $: [empty()] }\n */\nfunction empty(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n style: {\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: themeSpacing(3),\n paddingBlock: themeSpacing(12),\n paddingInline: themeSpacing(6),\n textAlign: \"center\",\n // Body / description text sits in the muted zone.\n color: (listener) => themeColor(listener, \"muted\", color.get(listener)),\n // Icon area: slightly softer so it recedes behind the title.\n \"& > :first-child\": {\n color: (listener) =>\n themeColor(listener, \"shift-5\", color.get(listener)),\n opacity: 0.9,\n },\n // Title (typically second child): stronger body text for hierarchy.\n \"& > :nth-child(2)\": {\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n },\n },\n };\n}\n\nexport { empty };\n","import type { DomphyElement, ElementNode, PartialElement } from \"@domphy/core\";\n\nconst ORIGINAL_CHILDREN = \"errorBoundaryOriginal\";\n\nfunction restoreOriginalChildren(node: ElementNode): void {\n const original = node.getMetadata(ORIGINAL_CHILDREN);\n if (typeof original === \"function\") {\n node._childrenRelease?.();\n node._setupFunctionChildren(original);\n return;\n }\n if (original != null) {\n node.children.update(Array.isArray(original) ? original : [original]);\n return;\n }\n node.children.update([]);\n}\n\n/**\n * Catches errors thrown inside reactive child expressions and renders a\n * fallback element instead of crashing the whole tree. Apply to any container.\n *\n * Only errors in *reactive* children (functions returning element arrays) are\n * caught. Errors during static construction propagate normally — those are\n * programming errors, not runtime data errors.\n *\n * `reset()` restores the original children (including a reactive children\n * function) so the next evaluation runs again — it does not leave the host\n * empty.\n *\n * @hostTag any\n * @param props.fallback - Fallback element or factory `(error, reset) => element`. Defaults to a plain error message div.\n * @param props.onError - Optional callback for logging/telemetry.\n * @example { div: (l) => renderUserContent(l), $: [errorBoundary({ fallback: { p: \"Something went wrong.\" } })] }\n */\nfunction errorBoundary(\n props: {\n fallback?:\n | DomphyElement\n | ((error: unknown, reset: () => void) => DomphyElement);\n onError?: (error: unknown) => void;\n } = {},\n): PartialElement {\n return {\n _onSchedule: (node, element) => {\n if (node.getMetadata(ORIGINAL_CHILDREN) !== undefined) return;\n node.setMetadata(\n ORIGINAL_CHILDREN,\n (element as Record<string, unknown>)[node.tagName],\n );\n },\n _onError: (node, error) => {\n props.onError?.(error);\n const reset = () => restoreOriginalChildren(node);\n const fallbackEl =\n typeof props.fallback === \"function\"\n ? props.fallback(error, reset)\n : (props.fallback ??\n ({ div: \"An error occurred.\" } as DomphyElement));\n node.children.update([fallbackEl]);\n },\n };\n}\n\nexport { errorBoundary };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { elevation } from \"../utils/elevation.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\nconst SIZE_MAP = { small: 8, medium: 10, large: 14 } as const;\n\n/**\n * Floating Action Button — a circular elevated button typically used for the\n * primary action on a screen. Apply to a `<button>` element.\n *\n * @hostTag button\n * @param props.color - Button color tone. Optional `ValueOrState<ThemeColor>`, defaults to `\"primary\"`.\n * @param props.size - Button size preset. Optional `\"small\" | \"medium\" | \"large\"`, defaults to `\"medium\"`.\n * @example { button: \"+\", $: [fab()] }\n * @example { button: \"+\", $: [fab({ size: \"small\", color: \"neutral\" })] }\n */\nfunction fab(\n props: {\n color?: ValueOrState<ThemeColor>;\n size?: \"small\" | \"medium\" | \"large\";\n } = {},\n): PartialElement {\n const color = toState(props.color ?? \"primary\", \"color\");\n const dim = themeSpacing(SIZE_MAP[props.size ?? \"medium\"]);\n\n return {\n // Native `type` on the host still wins (mergePartial: native over patch).\n type: \"button\",\n _onInsert: (node) => {\n if (node.tagName !== \"button\") {\n console.warn('\"fab\" patch must use button tag');\n }\n },\n // Deep brand disc (shift-13) + light icon — mid-ramp shift-8 failed WCAG\n // (~2.2:1). tone-background-inherit wants inherit+dataTone; explicit fill\n // silences it the same way as button solid.\n _doctorDisable: [\n \"low-contrast\",\n \"color-shift-minimum\",\n \"tone-background-inherit\",\n ],\n style: {\n appearance: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n flexShrink: 0,\n width: dim,\n height: dim,\n borderRadius: \"50%\",\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-13\", color.get(listener)),\n color: (listener) => themeColor(listener, \"shift-0\", \"neutral\"),\n boxShadow: elevation(\"low\"),\n transition: \"background-color 200ms ease, box-shadow 200ms ease\",\n \"&:hover:not([disabled])\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-14\", color.get(listener)),\n boxShadow: elevation(\"medium\"),\n },\n \"&:active:not([disabled])\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-15\", color.get(listener)),\n boxShadow: elevation(\"low\"),\n },\n \"&:focus-visible\": {\n boxShadow: (listener) =>\n `${elevation(\"medium\")}, ${focusRing(listener, color.get(listener))}`,\n },\n \"&[disabled]\": { opacity: 0.5, cursor: \"not-allowed\" },\n },\n };\n}\n\nexport { fab };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * Lays out a figure as a column with block-level media (img/svg/video/canvas)\n * and a themed `<figcaption>`. Apply to a `<figure>` element.\n *\n * @hostTag figure\n * @param props.color - Theme color tone (`ValueOrState<ThemeColor>`) for the figure/caption text. Defaults to \"neutral\".\n * @example { figure: [{ img: null, src: \"chart.png\", alt: \"Quarterly revenue\" }, { figcaption: \"A caption\" }], $: [figure()] }\n */\nfunction figure(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"figure\") {\n console.warn(`\"figure\" primitive patch must use figure tag`);\n }\n },\n style: {\n display: \"flex\",\n flexDirection: \"column\",\n gap: themeSpacing(2),\n marginInline: 0,\n marginTop: themeSpacing(3),\n marginBottom: themeSpacing(3),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n \"& img, & svg, & video, & canvas\": {\n display: \"block\",\n maxWidth: \"100%\",\n borderRadius: themeSpacing(2),\n },\n \"& figcaption\": {\n fontSize: (listener) => themeSize(listener, \"decrease-1\"),\n color: (listener) => themeColor(listener, \"muted\", color.get(listener)),\n lineHeight: 1.45,\n },\n },\n };\n}\n\nexport { figure };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n themeWeight,\n} from \"@domphy/theme\";\n\n/**\n * Layout patch for a group of form fields. Arranges a `<legend>`, `<label>`s,\n * controls, and helper `<p>`s in a grid — labels beside controls (horizontal)\n * or stacked above them (vertical). Apply to a `<fieldset>` element.\n *\n * @hostTag fieldset\n * @param props.color - Theme color tone (`ValueOrState<ThemeColor>`) for legend/text/surface. Defaults to \"neutral\".\n * @param props.layout - Field arrangement, \"horizontal\" (label beside control) | \"vertical\" (label above). Defaults to \"horizontal\".\n * @example { fieldset: [{ legend: \"Profile\" }, { label: \"Name\" }, { input: null }], $: [formGroup({ layout: \"vertical\" })] }\n */\nfunction formGroup(\n props: {\n color?: ValueOrState<ThemeColor>;\n layout?: \"horizontal\" | \"vertical\";\n } = {},\n): PartialElement {\n const { layout = \"horizontal\" } = props;\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n const isVertical = layout === \"vertical\";\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"fieldset\") {\n console.warn(`\"formGroup\" patch must use fieldset tag`);\n }\n },\n style: {\n margin: 0,\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 3),\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 3),\n border: \"none\",\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 2),\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n display: \"grid\",\n gridTemplateColumns: isVertical\n ? `minmax(0, 1fr)`\n : `max-content minmax(0, 1fr)`,\n columnGap: themeSpacing(4),\n rowGap: themeSpacing(3),\n alignItems: \"start\",\n \"& > legend\": {\n gridColumn: \"1 / -1\",\n margin: 0,\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n fontWeight: themeWeight(\"semibold\"),\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 1),\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 2),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n },\n \"& > label\": {\n gridColumn: \"1\",\n alignSelf: \"start\",\n margin: 0,\n paddingBlock: (listener) =>\n isVertical ? 0 : themeSpacing(themeDensity(listener) * 1),\n },\n \"& > label:has(+ :not(legend, label, p) + p)\": {\n gridRow: isVertical ? \"auto\" : \"span 2\",\n },\n // Fixed-size controls are EXCLUDED from the stretch rather than\n // overriding it afterwards: a checkbox / switch / radio / colour swatch\n // dropped into a formGroup rendered as a full-column-wide pill\n // (observed in Chromium), and `width: auto` on an appearance:none\n // input collapses it to 0 instead of restoring its declared size.\n \"& > :not(legend, label, p, input[type=checkbox], input[type=radio], input[type=color])\":\n {\n gridColumn: isVertical ? \"1\" : \"2\",\n minWidth: 0,\n width: \"100%\",\n boxSizing: \"border-box\",\n },\n \"& > input[type=checkbox], & > input[type=radio], & > input[type=color]\":\n {\n gridColumn: isVertical ? \"1\" : \"2\",\n justifySelf: \"start\",\n },\n \"& > p\": {\n gridColumn: isVertical ? \"1\" : \"2\",\n minWidth: 0,\n margin: 0,\n marginBlockStart: `calc(${themeSpacing(2)} * -1)`,\n fontSize: (listener) => themeSize(listener, \"decrease-1\"),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n },\n },\n };\n}\n\nexport { formGroup };\n","import type { PartialElement } from \"@domphy/core\";\nimport { themeDensity, themeSpacing } from \"@domphy/theme\";\nimport type { FlexAlign } from \"./stack.js\";\n\n/**\n * A CSS grid with a column template and spacing between cells — the\n * general-purpose primitive for card/property/stat grids instead of\n * hand-rolling `display: \"grid\"; gridTemplateColumns: ...; gap: ...`.\n * Mirrors `row()`'s contract. Styles the host only; apply to any block\n * element.\n *\n * @param props.columns - Column count (expanded to `repeat(N, minmax(0, 1fr))`)\n * or a raw `grid-template-columns` value. Defaults to `1`.\n * @param props.gap - Spacing multiplier for gap between cells (default 4 = 1em at density 1).\n * @param props.align - Block-axis alignment of items (`alignItems`). Unset by default.\n * @example { div: [{ div: \"A\" }, { div: \"B\" }], $: [grid({ columns: 2 })] }\n * @example { div: [...], $: [grid({ columns: \"repeat(auto-fill, minmax(12em, 1fr))\", gap: 6 })] }\n */\nfunction grid(\n props: { columns?: number | string; gap?: number; align?: FlexAlign } = {},\n): PartialElement {\n const { columns = 1, gap = 4, align } = props;\n return {\n style: {\n display: \"grid\",\n gridTemplateColumns:\n typeof columns === \"number\"\n ? `repeat(${columns}, minmax(0, 1fr))`\n : columns,\n gap: (listener) => themeSpacing(themeDensity(listener) * gap),\n ...(align ? { alignItems: align } : {}),\n },\n };\n}\n\nexport { grid };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ElementSize,\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\nconst HeadingShift: Record<string, ElementSize> = {\n h6: \"decrease-1\",\n h5: \"inherit\",\n h4: \"increase-1\",\n h3: \"increase-2\",\n h2: \"increase-3\",\n h1: \"increase-4\",\n};\n\n/**\n * Styles a heading, scaling its font size by level (h1 largest … h6 smallest)\n * relative to the theme base size. Apply to a heading element `<h1>`–`<h6>`.\n *\n * @hostTag h1-h6\n * @param props.color - Theme color tone (`ValueOrState<ThemeColor>`) for the heading text. Defaults to \"neutral\".\n * @param props.size - Optional `ElementSize` (`\"inherit\"` | `\"increase-N\"` | `\"decrease-N\"`, N ≤ 7). When set, font size is `themeSize(listener, size)` including `\"inherit\"` (no tag bump). When omitted, follows the host tag (`h1` increase-4 … `h6` decrease-1).\n * @example { h2: \"Section title\", $: [heading()] }\n * @example { h3: \"Panel title\", $: [heading({ size: \"inherit\" })] }\n */\nfunction heading(\n props: { color?: ValueOrState<ThemeColor>; size?: ElementSize } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n const size = props.size;\n\n return {\n _onInsert: (node) => {\n if (![\"h1\", \"h2\", \"h3\", \"h4\", \"h5\", \"h6\"].includes(node.tagName)) {\n console.warn(\n `\"heading\" primitive patch must use heading tags [h1...h6]`,\n );\n }\n },\n style: {\n color: (listener) =>\n themeColor(listener, \"shift-11\", color.get(listener)),\n marginTop: 0,\n marginBottom: themeSpacing(2),\n fontSize: (listener) => {\n if (size !== undefined) {\n return themeSize(listener, size);\n }\n const offset = HeadingShift[listener.elementNode.tagName] || \"inherit\";\n return themeSize(listener, offset);\n },\n },\n };\n}\n\nexport { heading };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport { type ThemeColor, themeColor, themeSpacing } from \"@domphy/theme\";\n\n/**\n * A thematic break rendered as a thin 1px themed line with vertical margin.\n * Apply to an `<hr>` element.\n *\n * @hostTag hr\n * @param props.color - Theme color tone (`ValueOrState<ThemeColor>`) for the rule. Defaults to \"neutral\".\n * @example { hr: null, $: [horizontalRule()] }\n */\nfunction horizontalRule(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"hr\") {\n console.warn(`\"horizontalRule\" primitive patch must use hr tag`);\n }\n },\n // Soft rule surface — edge anchor (shift-3 = border) + inherit paint.\n dataTone: \"shift-3\",\n style: {\n border: 0,\n height: \"1px\",\n marginInline: 0,\n marginTop: themeSpacing(3),\n marginBottom: themeSpacing(3),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n },\n };\n}\n\nexport { horizontalRule };\n","import type { PartialElement } from \"@domphy/core\";\nimport { toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * Styles an inline icon container: square box that centers its content and\n * applies the themed icon color. Apply to a `<span>` element.\n *\n * @hostTag span\n * @param props.color - Optional theme color tone for the icon (`ValueOrState<ThemeColor>`). Defaults to `\"neutral\"`.\n * @example { span: null, $: [icon()] }\n */\nfunction icon(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"span\") {\n console.warn(`\"icon\" primitive patch should use span tag`);\n }\n },\n style: {\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n alignSelf: \"center\",\n justifySelf: \"center\",\n verticalAlign: \"middle\",\n width: themeSpacing(4),\n height: themeSpacing(4),\n flexShrink: \"0\",\n fontSize: (listener) => themeSize(listener),\n backgroundColor: \"transparent\",\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n },\n };\n}\n\nexport { icon };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport { type ThemeColor, themeColor, themeSpacing } from \"@domphy/theme\";\n\ntype ImageProps = { color?: ValueOrState<ThemeColor> } & (\n | { alt: string; decorative?: false }\n | { decorative: true; alt?: undefined }\n);\n\n/**\n * Styles a responsive image: full-width, cover-fit, rounded corners with a\n * themed placeholder background. Apply to an `<img>` element.\n *\n * `alt` is a required prop (WCAG 1.1.1) forwarded onto the host as the native\n * `alt` attribute, not left for the call site to declare separately — a\n * native `alt` on the host element still wins over this if both are given\n * (Domphy's usual native-over-patch merge), but every call site must now\n * make an explicit choice. Pass `decorative: true` for `alt=\"\"` (purely\n * decorative images the caller does not want announced).\n *\n * @hostTag img\n * @param props.alt - Accessible text alternative. Required unless `decorative: true`.\n * @param props.decorative - Marks the image as pure decoration — renders `alt=\"\"` so assistive tech skips it. Optional.\n * @param props.color - Optional theme color tone for the placeholder background (`ValueOrState<ThemeColor>`). Defaults to `\"neutral\"`.\n * @example { img: null, src: \"photo.jpg\", $: [image({ alt: \"A scenic mountain photo\" })] }\n * @example { img: null, src: \"divider.svg\", $: [image({ decorative: true })] }\n */\nfunction image(props: ImageProps): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n alt: props.decorative ? \"\" : props.alt,\n dataTone: \"shift-2\",\n _onInsert: (node) => {\n if (node.tagName !== \"img\") {\n console.warn(`\"image\" primitive patch must use img tag`);\n }\n },\n style: {\n display: \"block\",\n width: \"100%\",\n maxWidth: \"100%\",\n height: \"auto\",\n objectFit: \"cover\",\n borderRadius: themeSpacing(2),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n },\n };\n}\n\nexport { image };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * Styles a custom checkbox with themed box, check mark, indeterminate state,\n * hover, focus and disabled styling. Apply to an `<input>` element of\n * type `checkbox` (the patch sets `type: \"checkbox\"`).\n *\n * @hostTag input\n * @param props.color - Optional theme color tone for the box/border (`ValueOrState<ThemeColor>`). Defaults to `\"neutral\"`.\n * @param props.accentColor - Optional theme color tone for the checked/indeterminate fill and focus ring (`ValueOrState<ThemeColor>`). Defaults to `\"primary\"`.\n * @example { input: null, type: \"checkbox\", $: [inputCheckbox()] }\n */\nfunction inputCheckbox(\n props: {\n color?: ValueOrState<ThemeColor>;\n accentColor?: ValueOrState<ThemeColor>;\n } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n const accentColor = toState(props.accentColor ?? \"primary\", \"accentColor\");\n\n return {\n type: \"checkbox\",\n _onInsert: (node) => {\n if (node.tagName !== \"input\") {\n console.warn(`\"inputCheckbox\" primitive patch must use input tag`);\n }\n },\n style: {\n appearance: \"none\",\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n display: \"inline-flex\",\n position: \"relative\",\n width: themeSpacing(6),\n height: themeSpacing(6),\n justifyContent: \"center\",\n alignItems: \"center\",\n transition: \"background-color 300ms, outline-color 300ms\",\n margin: 0,\n padding: 0,\n \"&::before\": {\n content: `\"\"`,\n display: \"block\",\n borderRadius: themeSpacing(1),\n lineHeight: 1,\n cursor: \"pointer\",\n border: \"none\",\n outlineOffset: \"-1px\",\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", color.get(listener))}`,\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n width: themeSpacing(4),\n height: themeSpacing(4),\n },\n \"&:hover::before\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"hover\", color.get(listener)),\n },\n \"&:checked::before\": {\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"shift-6\", accentColor.get(listener))}`,\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-8\", accentColor.get(listener)),\n },\n \"&:checked:hover:not([disabled])::before\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-7\", accentColor.get(listener)),\n },\n \"&:checked::after\": {\n content: `\"\"`,\n display: \"block\",\n position: \"absolute\",\n top: \"25%\",\n insetInlineStart: \"37%\",\n width: \"20%\",\n height: \"30%\",\n border: (listener) =>\n `${themeSpacing(0.5)} solid ${themeColor(listener, \"inherit\", accentColor.get(listener))}`,\n borderTop: 0,\n borderInlineStart: 0,\n transform: \"rotate(45deg)\",\n },\n \"&:indeterminate::before\": {\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"shift-6\", accentColor.get(listener))}`,\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-3\", accentColor.get(listener)),\n },\n \"&:indeterminate::after\": {\n content: `\"\"`,\n position: \"absolute\",\n inset: \"30%\",\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-8\", accentColor.get(listener)),\n },\n \"&:indeterminate:hover:not([disabled])::after\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-7\", accentColor.get(listener)),\n },\n \"&:focus-visible\": {\n borderRadius: themeSpacing(1.5),\n boxShadow: (listener) => focusRing(listener, accentColor.get(listener)),\n },\n \"&[disabled]\": {\n cursor: \"not-allowed\",\n opacity: 0.7,\n },\n // Disabled keeps the control's SHAPE and only drops the colour family to\n // neutral (Radix / MUI do the same). The previous rule painted ::before\n // with a flat grey fill and removed its outline, so in Chromium a\n // disabled UNCHECKED box read as filled — more \"on\" than the enabled\n // unchecked box, and indistinguishable from the disabled checked one.\n \"&[disabled]::before\": {\n pointerEvents: \"none\",\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", \"neutral\")}`,\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", \"neutral\"),\n },\n \"&[disabled]:checked::before\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-8\", \"neutral\"),\n },\n \"&[disabled]:indeterminate::before\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-3\", \"neutral\"),\n },\n \"&[disabled]:checked::after\": {\n pointerEvents: \"none\",\n // Light end of the neutral ramp on the shift-8 fill, mirroring the\n // enabled check: `inherit` resolved to a mid grey that all but\n // disappeared against it.\n borderColor: (listener) => themeColor(listener, \"shift-0\", \"neutral\"),\n },\n \"&[disabled]:indeterminate::after\": {\n pointerEvents: \"none\",\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-8\", \"neutral\"),\n },\n },\n };\n}\n\nexport { inputCheckbox };\n","import type { PartialElement, ValueOrState } from \"@domphy/core\";\nimport { toState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * Styles a native color picker swatch with themed padding, rounded swatch and\n * disabled styling. Apply to an `<input>` element of type `color` (the patch\n * default is `type: \"color\"`; a native `type` wins).\n *\n * @hostTag input\n * @param props.color - Optional theme color tone used for the disabled state (`ValueOrState<ThemeColor>`). Defaults to `\"neutral\"`.\n * @param props.accentColor - Optional theme color tone (`ValueOrState<ThemeColor>`). Defaults to `\"primary\"`.\n * @example { input: null, type: \"color\", $: [inputColor()] }\n */\nfunction inputColor(\n props: {\n color?: ValueOrState<ThemeColor>;\n accentColor?: ValueOrState<ThemeColor>;\n } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n return {\n // Declared like any other attribute — the native element still wins over\n // this patch default if the host declares its own `type`.\n type: \"color\",\n _onInsert: (node) => {\n if (node.tagName !== \"input\") {\n console.warn(`\"inputColor\" primitive patch must use input tag`);\n }\n },\n style: {\n appearance: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 1),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 1),\n blockSize: (listener) => themeSpacing(6 + themeDensity(listener) * 2),\n inlineSize: (listener) => themeSpacing(6 + themeDensity(listener) * 2),\n backgroundColor: \"transparent\",\n transition: \"box-shadow 140ms ease\",\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, color.get(listener)),\n },\n \"&::-webkit-color-swatch-wrapper\": {\n margin: 0,\n padding: 0,\n },\n \"&::-webkit-color-swatch\": {\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n },\n \"&[disabled]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-2\", \"neutral\"),\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", \"neutral\")}`,\n },\n },\n };\n}\n\nexport { inputColor };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\ntype InputDateTimeMode = \"date\" | \"time\" | \"week\" | \"month\" | \"datetime-local\";\n\n/**\n * Styles a native date/time input with themed border, padding, hover, focus,\n * invalid and disabled states. The `mode` selects the input `type`. Apply to\n * an `<input>` element (the patch default `type` is the chosen `mode`; a native `type` wins).\n *\n * @hostTag input\n * @param props.mode - Input mode selecting the host `type`: `\"date\" | \"time\" | \"week\" | \"month\" | \"datetime-local\"`. Defaults to `\"datetime-local\"`.\n * @param props.color - Optional theme color tone for text/border (`ValueOrState<ThemeColor>`). Defaults to `\"neutral\"`.\n * @param props.accentColor - Optional theme color tone for the hover/focus ring (`ValueOrState<ThemeColor>`). Defaults to `\"primary\"`.\n * @example { input: null, type: \"datetime-local\", $: [inputDateTime()] }\n */\nfunction inputDateTime(\n props: {\n mode?: InputDateTimeMode;\n color?: ValueOrState<ThemeColor>;\n accentColor?: ValueOrState<ThemeColor>;\n } = {},\n): PartialElement {\n const { mode = \"datetime-local\" } = props;\n const color = toState(props.color ?? \"neutral\", \"color\");\n const accentColor = toState(props.accentColor ?? \"primary\", \"accentColor\");\n\n return {\n // Declared like any other attribute — the native element still wins over\n // this patch default if the host declares its own `type`.\n type: mode,\n _onInsert: (node) => {\n if (node.tagName !== \"input\") {\n console.warn(`\"inputDateTime\" primitive patch must use input tag`);\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n lineHeight: \"inherit\",\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n border: \"none\",\n outlineOffset: \"-1px\",\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", color.get(listener))}`,\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 3),\n height: (listener) => themeSpacing(6 + themeDensity(listener) * 2),\n transition: \"outline-color 140ms ease, box-shadow 140ms ease\",\n \"&::-webkit-calendar-picker-indicator\": {\n cursor: \"pointer\",\n opacity: 0.85,\n },\n \"&:hover:not([disabled]):not([aria-busy=true])\": {\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"shift-5\", accentColor.get(listener))}`,\n },\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, accentColor.get(listener)),\n },\n \"&[disabled]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n color: (listener) => themeColor(listener, \"muted\", \"neutral\"),\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-2\", \"neutral\"),\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", \"neutral\")}`,\n },\n \"&:invalid\": {\n outline: (listener) =>\n `${themeSpacing(0.5)} solid ${themeColor(listener, \"shift-6\", \"error\")}`,\n },\n },\n };\n}\n\nexport { inputDateTime };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * Styles a native file input with a themed upload button, border, hover, focus\n * and disabled states. Apply to an `<input>` element of type `file` (the patch\n * default is `type: \"file\"`; a native `type` wins).\n *\n * @hostTag input\n * @param props.color - Optional theme color tone for text/border and the upload button (`ValueOrState<ThemeColor>`). Defaults to `\"neutral\"`.\n * @param props.accentColor - Optional theme color tone for the hover/focus ring (`ValueOrState<ThemeColor>`). Defaults to `\"primary\"`.\n * @example { input: null, type: \"file\", $: [inputFile()] }\n */\nfunction inputFile(\n props: {\n color?: ValueOrState<ThemeColor>;\n accentColor?: ValueOrState<ThemeColor>;\n } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n const accentColor = toState(props.accentColor ?? \"primary\", \"accentColor\");\n\n return {\n // Declared like any other attribute — the native element still wins over\n // this patch default if the host declares its own `type`.\n type: \"file\",\n _onInsert: (node) => {\n if (node.tagName !== \"input\") {\n console.warn(`\"inputFile\" primitive patch must use input tag`);\n }\n },\n style: {\n display: \"inline-flex\",\n alignItems: \"center\",\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n lineHeight: \"inherit\",\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n border: \"none\",\n outlineOffset: \"-1px\",\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", color.get(listener))}`,\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n height: (listener) => themeSpacing(6 + themeDensity(listener) * 2),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 1),\n transition: \"outline-color 140ms ease, box-shadow 140ms ease\",\n \"&::-webkit-file-upload-button\": {\n marginTop: (listener) => themeSpacing(themeDensity(listener)),\n fontSize: \"inherit\",\n border: \"none\",\n borderRadius: themeSpacing(1),\n height: themeSpacing(6),\n paddingInline: themeSpacing(2),\n cursor: \"pointer\",\n color: (listener) =>\n themeColor(listener, \"shift-11\", color.get(listener)),\n backgroundColor: (listener) =>\n themeColor(listener, \"surface\", color.get(listener)),\n },\n \"&:hover:not([disabled]):not([aria-busy=true])\": {\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"shift-5\", accentColor.get(listener))}`,\n },\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, accentColor.get(listener)),\n },\n \"&[disabled]\": {\n opacity: 0.8,\n cursor: \"not-allowed\",\n color: (listener) => themeColor(listener, \"muted\", \"neutral\"),\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", \"neutral\")}`,\n backgroundColor: (listener) =>\n themeColor(listener, \"surface\", \"neutral\"),\n },\n \"&[disabled]::-webkit-file-upload-button\": {\n cursor: \"not-allowed\",\n color: (listener) => themeColor(listener, \"muted\", \"neutral\"),\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-3\", \"neutral\"),\n },\n },\n };\n}\n\nexport { inputFile };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { fieldTextStyle } from \"../utils/fieldText.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * Styles a native number input with themed border, padding, visible spin\n * buttons, hover, focus and disabled states. Apply to an `<input>` element of\n * type `number` (the patch default is `type: \"number\"`; a native `type` wins).\n *\n * @hostTag input\n * @param props.color - Optional theme color tone for text/border (`ValueOrState<ThemeColor>`). Defaults to `\"neutral\"`.\n * @param props.accentColor - Optional theme color tone for the hover/focus ring (`ValueOrState<ThemeColor>`). Defaults to `\"primary\"`.\n * @example { input: null, type: \"number\", $: [inputNumber()] }\n */\nfunction inputNumber(\n props: {\n color?: ValueOrState<ThemeColor>;\n accentColor?: ValueOrState<ThemeColor>;\n } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n const accentColor = toState(props.accentColor ?? \"primary\", \"accentColor\");\n\n return {\n // Declared like any other attribute — the native element still wins over\n // this patch default if the host declares its own `type`.\n type: \"number\",\n _onInsert: (node) => {\n if (node.tagName !== \"input\") {\n console.warn(`\"inputNumber\" primitive patch must use input tag`);\n }\n },\n style: {\n lineHeight: \"inherit\",\n minWidth: themeSpacing(10),\n paddingInlineStart: (listener) =>\n themeSpacing(themeDensity(listener) * 3),\n paddingInlineEnd: (listener) =>\n themeSpacing(themeDensity(listener) * 1.5),\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 1),\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n border: \"none\",\n outlineOffset: \"-1px\",\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", color.get(listener))}`,\n ...fieldTextStyle(color),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n transition: \"outline-color 140ms ease, box-shadow 140ms ease\",\n \"&::-webkit-inner-spin-button, &::-webkit-outer-spin-button\": {\n opacity: 1,\n },\n \"&:hover:not([disabled]):not([aria-busy=true])\": {\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"shift-5\", accentColor.get(listener))}`,\n },\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, accentColor.get(listener)),\n },\n \"&[disabled]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-2\", \"neutral\"),\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", \"neutral\")}`,\n color: (listener) => themeColor(listener, \"muted\", \"neutral\"),\n },\n },\n };\n}\n\nexport { inputNumber };\n","import type { PartialElement } from \"@domphy/core\";\nimport { themeSpacing } from \"@domphy/theme\";\n\n/**\n * Lays out a one-time-password container as a horizontal row of inputs and\n * wires keyboard navigation: auto-advance on input, backspace/arrow movement,\n * and paste distribution across the child inputs. Apply to a container element\n * (e.g. `<div>`) whose direct children are the OTP `<input>` boxes. Takes no\n * props.\n *\n * @example { div: [{ input: null }, { input: null }], $: [inputOTP()] }\n */\nfunction inputOTP(): PartialElement {\n return {\n // Group naming so aria-label on the host is valid (not a bare div).\n role: \"group\",\n ariaLabel: \"One-time password\",\n style: {\n display: \"flex\",\n alignItems: \"center\",\n gap: themeSpacing(2),\n // Tag selector, not \"& > *\": specificity (0,1,1) beats a single class\n // (0,1,0) on its own, so this reliably wins over a box's own\n // minWidth without needing !important — same cascade contract as\n // AGENTS.md's descendant-color-override rule.\n \"& > input\": {\n minWidth: themeSpacing(9),\n },\n },\n _onMount: (node) => {\n const container = node.domElement as HTMLElement;\n const getInputs = () =>\n Array.from(container.querySelectorAll(\"input\")) as HTMLInputElement[];\n\n const onInput = (e: Event) => {\n // An IME (Japanese/Chinese/Korean) fires `input` for each keystroke of\n // an unfinished composition. Advancing focus there tears the\n // composition apart mid-word; wait for the commit.\n if ((e as InputEvent).isComposing) return;\n const inputs = getInputs();\n const target = e.target as HTMLInputElement;\n const index = inputs.indexOf(target);\n if (target.value && index < inputs.length - 1) {\n inputs[index + 1].focus();\n }\n };\n\n const onKeydown = (e: KeyboardEvent) => {\n // keydown during composition reports key \"Process\"/229; leave it alone.\n if (e.isComposing) return;\n const inputs = getInputs();\n const target = e.target as HTMLInputElement;\n const index = inputs.indexOf(target);\n if (e.key === \"Backspace\" && !target.value && index > 0) {\n inputs[index - 1].focus();\n }\n // preventDefault: otherwise the caret ALSO moves inside the box the\n // key just left, so the next typed character lands mid-value.\n if (e.key === \"ArrowLeft\" && index > 0) {\n e.preventDefault();\n inputs[index - 1].focus();\n }\n if (e.key === \"ArrowRight\" && index < inputs.length - 1) {\n e.preventDefault();\n inputs[index + 1].focus();\n }\n };\n\n const onPaste = (e: ClipboardEvent) => {\n e.preventDefault();\n const text = e.clipboardData?.getData(\"text\") ?? \"\";\n const inputs = getInputs();\n const found = inputs.indexOf(e.target as HTMLInputElement);\n const startIdx = found === -1 ? 0 : found;\n [...text].forEach((char, i) => {\n const field = inputs[startIdx + i];\n if (!field) return;\n field.value = char;\n field.dispatchEvent(new Event(\"input\", { bubbles: true }));\n field.dispatchEvent(new Event(\"change\", { bubbles: true }));\n });\n const lastFilled = Math.min(\n startIdx + text.length - 1,\n inputs.length - 1,\n );\n inputs[lastFilled]?.focus();\n };\n\n container.addEventListener(\"input\", onInput);\n container.addEventListener(\"keydown\", onKeydown as EventListener);\n container.addEventListener(\"paste\", onPaste as EventListener);\n\n node.addHook(\"Remove\", () => {\n container.removeEventListener(\"input\", onInput);\n container.removeEventListener(\"keydown\", onKeydown as EventListener);\n container.removeEventListener(\"paste\", onPaste as EventListener);\n });\n },\n };\n}\n\nexport { inputOTP };\n","import type {\n DomphyElement,\n Listener,\n PartialElement,\n StyleObject,\n} from \"@domphy/core\";\nimport { isState, rawHtml, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { VALUE_TONE } from \"../utils/fieldText.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n// Tabler Icons (MIT) — eye and eye-off outlines.\nconst EYE_SVG =\n `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" ` +\n `stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" ` +\n `width=\"1em\" height=\"1em\">` +\n `<path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"/>` +\n `<path d=\"M10 12a2 2 0 1 0 4 0a2 2 0 0 0 -4 0\"/>` +\n `<path d=\"M21 12c-2.4 4 -5.4 6 -9 6c-3.6 0 -6.6 -2 -9 -6c2.4 -4 5.4 -6 9 -6c3.6 0 6.6 2 9 6\"/>` +\n `</svg>`;\n\nconst EYE_OFF_SVG =\n `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" ` +\n `stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" ` +\n `width=\"1em\" height=\"1em\">` +\n `<path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"/>` +\n `<path d=\"M10.585 10.587a2 2 0 0 0 2.829 2.828\"/>` +\n `<path d=\"M16.681 16.673a8.717 8.717 0 0 1 -4.681 1.327c-3.6 0 -6.6 -2 -9 -6` +\n `c1.272 -2.12 2.712 -3.678 4.32 -4.674m2.86 -1.146a9.055 9.055 0 0 1 1.82 -.18` +\n `c3.6 0 6.6 2 9 6c-.666 1.11 -1.379 2.067 -2.138 2.87\"/>` +\n `<path d=\"M3 3l18 18\"/>` +\n `</svg>`;\n\nconst HOST_FIELD_KEYS = [\n \"name\",\n \"value\",\n \"onInput\",\n \"disabled\",\n \"required\",\n] as const;\n\ntype HostFieldKey = (typeof HOST_FIELD_KEYS)[number];\n\ntype HostFields = {\n name?: string;\n value?: unknown;\n onInput?: (event: Event) => void;\n disabled?: unknown;\n required?: boolean;\n};\n\nfunction bindReadable<T>(\n value: T | ValueOrState<T> | ((listener: Listener) => T) | undefined,\n): T | ((listener: Listener) => T) | undefined {\n if (value == null) return undefined;\n if (typeof value === \"function\") return value as (listener: Listener) => T;\n if (isState(value)) {\n return (listener) => (value as { get: (l?: Listener) => T }).get(listener);\n }\n return value as T;\n}\n\n/**\n * Password input wrapper: a styled `<div>` that inserts an `<input type=\"password\">`\n * and a show/hide toggle button. The outer div carries the focus-ring outline via\n * `:focus-within`. Apply to an empty `<div>`. Host `value`/`name`/`onInput`/\n * `disabled`/`required` are forwarded onto the real input so the field\n * participates in FormData.\n *\n * @hostTag div\n * @param props.color - Base color tone for border/background/text. Defaults to `\"neutral\"`.\n * @param props.accentColor - Accent outline color on focus-within. Defaults to `\"primary\"`.\n * @param props.value - Forwarded onto the inner input. Optional.\n * @param props.name - Forwarded onto the inner input (FormData key). Optional.\n * @param props.onInput - Forwarded onto the inner input. Optional.\n * @param props.disabled - Forwarded onto the inner input. Optional.\n * @param props.required - Forwarded onto the inner input. Optional.\n * @param props.autocomplete - Native autocomplete token. Defaults to `\"current-password\"`.\n * @param props.ariaLabel - Accessible name for the inner input. Defaults to `\"Password\"`.\n * @example { div: null, name: \"password\", $: [inputPassword()] }\n */\nfunction inputPassword(\n props: {\n color?: ValueOrState<ThemeColor>;\n accentColor?: ValueOrState<ThemeColor>;\n value?: ValueOrState<string>;\n name?: string;\n onInput?: (event: Event) => void;\n disabled?: ValueOrState<boolean>;\n required?: boolean;\n autocomplete?: string;\n ariaLabel?: string;\n } = {},\n): PartialElement {\n const colorState = toState(props.color ?? \"neutral\", \"color\");\n const accentState = toState(props.accentColor ?? \"primary\", \"accentColor\");\n const visibleState = toState(false);\n const hostFields: HostFields = {};\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"div\") {\n console.warn('\"inputPassword\" patch must use div tag');\n }\n },\n // Lift form fields off the host before merge so they land on the real\n // <input> (a div is not form-associated; FormData would omit them).\n _onSchedule: (_node, element) => {\n const host = element as PartialElement & HostFields;\n for (const key of HOST_FIELD_KEYS) {\n if (host[key] !== undefined) {\n hostFields[key] = host[key] as never;\n delete (host as Record<HostFieldKey, unknown>)[key];\n }\n }\n },\n // Build the input/toggle as real child elements (not imperative DOM\n // mutation in _onMount) so generateHTML()/SSR emits the actual markup.\n _onInit: (node) => {\n const name = props.name ?? hostFields.name;\n const value = bindReadable<string>(\n (props.value ?? hostFields.value) as ValueOrState<string> | undefined,\n );\n const onInput = props.onInput ?? hostFields.onInput;\n const disabled = bindReadable<boolean>(\n (props.disabled ?? hostFields.disabled) as\n | ValueOrState<boolean>\n | undefined,\n );\n const required = props.required ?? hostFields.required;\n\n const field: DomphyElement<\"input\"> = {\n input: null,\n type: (l) => (visibleState.get(l) ? \"text\" : \"password\"),\n ariaLabel: props.ariaLabel ?? \"Password\",\n autocomplete: props.autocomplete ?? \"current-password\",\n ...(name != null ? { name } : {}),\n ...(value != null ? { value } : {}),\n ...(onInput != null ? { onInput } : {}),\n ...(disabled != null ? { disabled } : {}),\n ...(required != null ? { required } : {}),\n style: {\n flex: 1,\n minWidth: 0,\n border: \"none\",\n outline: \"none\",\n backgroundColor: \"transparent\",\n padding: 0,\n margin: 0,\n font: \"inherit\",\n color: \"inherit\",\n },\n };\n\n const toggle: DomphyElement<\"button\"> = {\n button: (l) => rawHtml(visibleState.get(l) ? EYE_OFF_SVG : EYE_SVG),\n type: \"button\",\n ariaLabel: (l) =>\n visibleState.get(l) ? \"Hide password\" : \"Show password\",\n onClick: () => visibleState.set(!visibleState.get()),\n style: {\n background: \"none\",\n border: \"none\",\n padding: 0,\n margin: 0,\n cursor: \"pointer\",\n color: \"inherit\",\n // A <button> gets the UA default 13.333px font unless told otherwise,\n // which shrank both the 1em glyph and the em-based 6U min box (20px\n // measured instead of 24px in Chromium).\n fontSize: (l) => themeSize(l, \"inherit\"),\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n flexShrink: 0,\n // WCAG 2.2 SC 2.5.8 Target Size (Minimum): the 1em eye glyph gave a\n // 13x13 hit area. Negative inline margin keeps the field's visual\n // padding while the button itself reaches 24x24.\n minWidth: themeSpacing(6),\n minHeight: themeSpacing(6),\n marginInlineEnd: (l) =>\n `calc(${themeSpacing(themeDensity(l) * 1)} * -1)`,\n opacity: 0.6,\n },\n };\n\n node.children.insert(field);\n node.children.insert(toggle);\n },\n style: {\n display: \"flex\",\n alignItems: \"center\",\n gap: (l) => themeSpacing(themeDensity(l) * 1),\n paddingBlock: (l) => themeSpacing(themeDensity(l) * 1),\n paddingInline: (l) => themeSpacing(themeDensity(l) * 3),\n borderRadius: (l) => themeSpacing(themeDensity(l) * 1.5),\n border: \"none\",\n outlineOffset: \"-1px\",\n outline: (l) =>\n `1px solid ${themeColor(l, \"border-strong\", colorState.get(l))}`,\n // Same tone as every other field's typed value; the inner <input>\n // inherits it. No `::placeholder` rule: this patch builds its own input\n // and never gives it a placeholder attribute, so there is nothing to paint.\n color: (l) => themeColor(l, VALUE_TONE, colorState.get(l)),\n backgroundColor: (l) => themeColor(l, \"inherit\", colorState.get(l)),\n fontSize: (l) => themeSize(l, \"inherit\"),\n transition: \"outline-color 140ms ease, box-shadow 140ms ease\",\n \"&:hover:not(:has([disabled])):not(:focus-within)\": {\n outline: (l) =>\n `1px solid ${themeColor(l, \"shift-5\", accentState.get(l))}`,\n },\n \"&:focus-within\": {\n boxShadow: (l) => focusRing(l, accentState.get(l)),\n },\n } as StyleObject,\n };\n}\n\nexport { inputPassword };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * Styles a custom radio button with a themed circular box, checked dot, hover,\n * focus and disabled states. Apply to an `<input>` element of type `radio`\n * (the patch sets `type: \"radio\"`).\n *\n * @hostTag input\n * @param props.color - Optional theme color tone for the box/border (`ValueOrState<ThemeColor>`). Defaults to `\"neutral\"`.\n * @param props.accentColor - Optional theme color tone for the checked dot and focus ring (`ValueOrState<ThemeColor>`). Defaults to `\"primary\"`.\n * @example { input: null, type: \"radio\", $: [inputRadio()] }\n */\nfunction inputRadio(\n props: {\n color?: ValueOrState<ThemeColor>;\n accentColor?: ValueOrState<ThemeColor>;\n } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n const accentColor = toState(props.accentColor ?? \"primary\", \"accentColor\");\n\n return {\n type: \"radio\",\n _onInsert: (node) => {\n if (node.tagName !== \"input\") {\n console.warn(\n `\"inputRadio\" primitive patch must use input tag and radio type`,\n );\n return;\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n appearance: \"none\",\n display: \"inline-flex\",\n position: \"relative\",\n width: themeSpacing(6),\n height: themeSpacing(6),\n justifyContent: \"center\",\n alignItems: \"center\",\n transition: \"background-color 300ms, outline-color 300ms\",\n margin: 0,\n padding: 0,\n \"&::before\": {\n content: `\"\"`,\n display: \"block\",\n borderRadius: \"50%\",\n lineHeight: 1,\n cursor: \"pointer\",\n border: \"none\",\n outlineOffset: \"-1px\",\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", color.get(listener))}`,\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n width: themeSpacing(4),\n height: themeSpacing(4),\n },\n \"&:hover::before\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"hover\", color.get(listener)),\n },\n \"&:checked::before\": {\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"shift-6\", accentColor.get(listener))}`,\n },\n \"&:checked::after\": {\n content: `\"\"`,\n position: \"absolute\",\n inset: \"30%\",\n borderRadius: \"50%\",\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-8\", accentColor.get(listener)),\n },\n \"&:checked:hover:not([disabled])::before\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-7\", accentColor.get(listener)),\n },\n \"&:focus-visible\": {\n borderRadius: \"50%\",\n boxShadow: (listener) => focusRing(listener, accentColor.get(listener)),\n },\n \"&[disabled]\": {\n cursor: \"not-allowed\",\n opacity: 0.7,\n },\n // Same fix as inputCheckbox: the old rule filled ::before with flat grey\n // and dropped its outline, so a disabled UNSELECTED radio rendered as a\n // solid dot-less disc that read as selected (observed in Chromium).\n \"&[disabled]::before\": {\n pointerEvents: \"none\",\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", \"neutral\")}`,\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", \"neutral\"),\n },\n \"&[disabled]:checked::after\": {\n pointerEvents: \"none\",\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-8\", \"neutral\"),\n },\n },\n };\n}\n\nexport { inputRadio };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * Styles a range slider with a themed track and thumb, hover, focus and\n * disabled states. Apply to an `<input>` element of type `range` (the patch\n * sets `type: \"range\"`).\n *\n * @hostTag input\n * @param props.color - Optional theme color tone for the slider track (`ValueOrState<ThemeColor>`). Defaults to `\"neutral\"`.\n * @param props.accentColor - Optional theme color tone for the thumb and focus ring (`ValueOrState<ThemeColor>`). Defaults to `\"primary\"`.\n * @example { input: null, type: \"range\", $: [inputRange()] }\n */\nfunction inputRange(\n props: {\n color?: ValueOrState<ThemeColor>;\n accentColor?: ValueOrState<ThemeColor>;\n } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n const accentColor = toState(props.accentColor ?? \"primary\", \"accentColor\");\n\n return {\n type: \"range\",\n _onInsert: (node) => {\n if (node.tagName !== \"input\") {\n console.warn(`\"inputRange\" primitive patch must use input tag`);\n }\n },\n style: {\n appearance: \"none\",\n // Without this the UA default font (13.333px on form controls) wins and\n // every em-derived dimension below shrinks by ~17% — the 6U host box\n // measured 20px instead of 24px in Chromium.\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n width: \"100%\",\n margin: 0,\n padding: 0,\n // WCAG 2.2 SC 2.5.8 Target Size (Minimum) is 24x24 CSS px; the visible\n // track stays 1.5U — only the pointer/drag box grows.\n height: themeSpacing(6),\n background: \"transparent\",\n cursor: \"pointer\",\n \"&::-webkit-slider-runnable-track\": {\n height: themeSpacing(1.5),\n borderRadius: themeSpacing(999),\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-3\", color.get(listener)),\n },\n \"&::-webkit-slider-thumb\": {\n appearance: \"none\",\n width: themeSpacing(4),\n height: themeSpacing(4),\n borderRadius: themeSpacing(999),\n border: \"none\",\n marginTop: `calc((${themeSpacing(1.5)} - ${themeSpacing(4)}) / 2)`,\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-9\", accentColor.get(listener)),\n },\n \"&:hover:not([disabled])::-webkit-slider-thumb\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-10\", accentColor.get(listener)),\n },\n // Firefox uses its own pseudo-elements; without these the slider fell\n // back to the unthemed native widget there (WebKit-only styling).\n \"&::-moz-range-track\": {\n height: themeSpacing(1.5),\n borderRadius: themeSpacing(999),\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-3\", color.get(listener)),\n },\n \"&::-moz-range-thumb\": {\n width: themeSpacing(4),\n height: themeSpacing(4),\n borderRadius: themeSpacing(999),\n border: \"none\",\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-9\", accentColor.get(listener)),\n },\n \"&:hover:not([disabled])::-moz-range-thumb\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-10\", accentColor.get(listener)),\n },\n borderRadius: themeSpacing(2),\n transition: \"box-shadow 140ms ease\",\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, accentColor.get(listener)),\n },\n \"&[disabled]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n },\n },\n };\n}\n\nexport { inputRange };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { fieldTextStyle } from \"../utils/fieldText.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * Styles a search input with themed border, padding, placeholder color, native\n * search decorations, hover, focus and disabled states. Apply to an `<input>`\n * element of type `search` (the patch default is `type: \"search\"`; a native `type` wins).\n *\n * @hostTag input\n * @param props.color - Optional theme color tone for text/border/placeholder (`ValueOrState<ThemeColor>`). Defaults to `\"neutral\"`.\n * @param props.accentColor - Optional theme color tone for the hover/focus ring (`ValueOrState<ThemeColor>`). Defaults to `\"primary\"`.\n * @example { input: null, type: \"search\", $: [inputSearch()] }\n */\nfunction inputSearch(\n props: {\n color?: ValueOrState<ThemeColor>;\n accentColor?: ValueOrState<ThemeColor>;\n } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n const accentColor = toState(props.accentColor ?? \"primary\", \"accentColor\");\n\n return {\n // Declared like any other attribute — the native element still wins over\n // this patch default if the host declares its own `type`.\n type: \"search\",\n _onInsert: (node) => {\n if (node.tagName !== \"input\") {\n console.warn(`\"inputSearch\" primitive patch must use input tag`);\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n lineHeight: \"inherit\",\n ...fieldTextStyle(color),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n border: \"none\",\n outlineOffset: \"-1px\",\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", color.get(listener))}`,\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n minWidth: themeSpacing(32),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 3),\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 1),\n transition: \"outline-color 140ms ease, box-shadow 140ms ease\",\n \"&::-webkit-search-decoration\": {\n display: \"none\",\n },\n \"&::-webkit-search-cancel-button\": {\n cursor: \"pointer\",\n },\n \"&:hover:not([disabled]):not([aria-busy=true])\": {\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"shift-5\", accentColor.get(listener))}`,\n },\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, accentColor.get(listener)),\n },\n \"&[disabled]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n color: (listener) => themeColor(listener, \"muted\", \"neutral\"),\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-2\", \"neutral\"),\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", \"neutral\")}`,\n },\n },\n };\n}\n\nexport { inputSearch };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * Styles a checkbox as a toggle switch: themed track and sliding knob that\n * animates and recolors on checked, plus a disabled state. Apply to an\n * `<input>` element of type `checkbox` (the patch sets `type: \"checkbox\"`).\n *\n * @hostTag input\n * @param props.accentColor - Optional theme color tone for the checked track (`ValueOrState<ThemeColor>`). Defaults to `\"primary\"`.\n * @example { input: null, type: \"checkbox\", $: [inputSwitch()] }\n */\nfunction inputSwitch(\n props: { accentColor?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const accentColor = toState(props.accentColor ?? \"primary\", \"accentColor\");\n\n return {\n role: \"switch\",\n dataTone: \"shift-2\",\n type: \"checkbox\",\n _onSchedule: (node) => {\n if (node.tagName !== \"input\") {\n console.warn(`\"inputSwitch\" primitive patch must use input tag`);\n return;\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n // The track is `::before` alone, filling the whole host box; painting\n // the host too would draw a second pill behind it.\n backgroundColor: \"transparent\",\n color: (listener) => themeColor(listener, \"text\"),\n appearance: \"none\",\n position: \"relative\",\n display: \"inline-flex\",\n width: themeSpacing(12),\n height: themeSpacing(6),\n cursor: \"pointer\",\n margin: `0`,\n transition: \"box-shadow 140ms ease\",\n borderRadius: themeSpacing(999),\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, accentColor.get(listener)),\n },\n \"&:checked\": {\n \"&::before\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"increase-3\", accentColor.get(listener)),\n },\n \"&::after\": {\n insetInlineStart: `calc(100% - ${themeSpacing(5.5)})`,\n },\n },\n \"&::after\": {\n content: `\"\"`,\n aspectRatio: `1/1`,\n position: \"absolute\",\n // INHERITED: buttonSwitch's thumb (themeSpacing(5)), inset 0.5 in a 6-high track.\n width: themeSpacing(5),\n height: themeSpacing(5),\n borderRadius: themeSpacing(999),\n insetInlineStart: themeSpacing(0.5),\n top: \"50%\",\n transform: \"translateY(-50%)\",\n transition: \"inset-inline-start 0.3s\",\n backgroundColor: (listener) => themeColor(listener, \"decrease-3\"),\n // The knob is near-white on a near-white OFF track, so its own\n // boundary is what makes the ON/OFF position identifiable\n // (WCAG 2.1 SC 1.4.11) — same treatment as buttonSwitch's thumb.\n outline: (listener) => `1px solid ${themeColor(listener, \"shift-7\")}`,\n outlineOffset: \"-1px\",\n },\n \"&::before\": {\n content: '\"\"',\n width: \"100%\",\n borderRadius: themeSpacing(999),\n display: \"inline-block\",\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n lineHeight: 1,\n // WCAG 2.1 SC 1.4.11 Non-text Contrast: the OFF track needs >= 3:1\n // against the surface behind it. The tone-inherited FILL measured\n // 1.38:1 on a light page and 1.18:1 on a dark one in Chromium, so the\n // 3:1 is carried by the boundary (shift-7 measures 3.32:1 / 3.50:1),\n // not by darkening the fill: a shift-7 FILLED off-track reads as the\n // ON state — every peer (Radix, shadcn, MUI) keeps the off-track at\n // the muted surface and only the on-track takes the accent.\n backgroundColor: (listener) => themeColor(listener, \"inherit\"),\n outline: (listener) => `1px solid ${themeColor(listener, \"shift-7\")}`,\n outlineOffset: \"-1px\",\n },\n \"&[disabled]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n },\n },\n };\n}\n\nexport { inputSwitch };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { fieldTextStyle } from \"../utils/fieldText.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * Themed single-line text input primitive. Sets `type` (default `\"text\"`) and\n * styles the field with themed border, focus ring, placeholder, disabled and\n * validation (`data-status`) states. Apply to an `<input>` element.\n *\n * @hostTag input\n * @param props - Optional configuration.\n * @param props.type - The input's `type` attribute (e.g. `\"email\"`, `\"url\"`, `\"tel\"`). Defaults to `\"text\"`.\n * @param props.color - Base color tone for text/border/background. Defaults to `\"neutral\"`.\n * @param props.accentColor - Accent color tone for the hover/focus outline. Defaults to `\"primary\"`.\n * @example { input: null, type: \"text\", placeholder: \"Name\", $: [inputText()] }\n */\nfunction inputText(\n props: {\n type?: string;\n color?: ValueOrState<ThemeColor>;\n accentColor?: ValueOrState<ThemeColor>;\n } = {},\n): PartialElement {\n const { type = \"text\" } = props;\n const color = toState(props.color ?? \"neutral\", \"color\");\n const accentColor = toState(props.accentColor ?? \"primary\", \"accentColor\");\n\n return {\n // Declared like any other attribute — the native element still wins over\n // this patch default if the host declares its own `type`.\n type,\n _onInsert: (node) => {\n if (node.tagName !== \"input\") {\n console.warn(\n `\"inputText\" primitive patch must use input tag and text type`,\n );\n }\n },\n style: {\n lineHeight: \"inherit\",\n minWidth: themeSpacing(10),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 3),\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 1),\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n border: \"none\",\n outlineOffset: \"-1px\",\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", color.get(listener))}`,\n ...fieldTextStyle(color),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n transition: \"outline-color 140ms ease, box-shadow 140ms ease\",\n \"&:hover:not([disabled]):not([aria-busy=true])\": {\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"shift-5\", accentColor.get(listener))}`,\n },\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, accentColor.get(listener)),\n },\n \"&[disabled]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-2\", \"neutral\"),\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", \"neutral\")}`,\n color: (listener) => themeColor(listener, \"muted\", \"neutral\"),\n },\n // `[placeholder]` is load-bearing: `:placeholder-shown` only matches an\n // input that HAS a placeholder, so on a field without one\n // `:not(:placeholder-shown)` is always true and a pristine untouched\n // `required` field painted itself red before the user typed a character.\n // Fields with no placeholder opt into the error look via `data-status`.\n \"&[placeholder]:invalid:not(:placeholder-shown)\": {\n outline: (listener) =>\n `${themeSpacing(0.5)} solid ${themeColor(listener, \"shift-6\", \"error\")}`,\n },\n \"&[data-status=error]\": {\n outline: (listener) =>\n `${themeSpacing(0.5)} solid ${themeColor(listener, \"shift-6\", \"error\")}`,\n },\n \"&[data-status=warning]\": {\n outline: (listener) =>\n `${themeSpacing(0.5)} solid ${themeColor(listener, \"shift-6\", \"warning\")}`,\n },\n },\n };\n}\n\nexport { inputText };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeFont,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * Renders keyboard-key styling (the theme's monospace stack, themed background,\n * border and padding) for a keystroke hint. Apply to a `<kbd>` element.\n *\n * @hostTag kbd\n * @param props - Optional configuration.\n * @param props.color - Color tone for text/background/border. Defaults to `\"neutral\"`.\n * @example { kbd: \"Ctrl\", $: [keyboard()] }\n */\nfunction keyboard(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"kbd\") {\n console.warn(`\"keyboard\" primitive patch must use kbd tag`);\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n // The theme owns the code stack; <code>/<kbd>/<pre> otherwise keep the\n // UA generic \"monospace\" (Courier New on Windows), so a theme that swaps\n // fontFamilies.monospace never reaches them.\n fontFamily: themeFont(\"monospace\"),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n // Bare themeSpacing(U) at snapshot time; n = U / 1.5 (light.densities[2]).\n paddingBlock: (listener) =>\n themeSpacing(themeDensity(listener) * (0.5 / 1.5)),\n paddingInline: (listener) =>\n themeSpacing(themeDensity(listener) * (1.5 / 1.5)),\n borderRadius: (listener) =>\n themeSpacing(themeDensity(listener) * (1 / 1.5)),\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", color.get(listener))}`,\n },\n };\n}\n\nexport { keyboard };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * Themed form-label primitive: inline-flex layout with gap, themed text color,\n * focus-within highlighting and a disabled (`aria-disabled`) state. Apply to a\n * `<label>` element.\n *\n * @hostTag label\n * @param props - Optional configuration.\n * @param props.color - Base color tone for the label text. Defaults to `\"neutral\"`.\n * @param props.accentColor - Accent color tone applied on focus-within. Defaults to `\"primary\"`.\n * @example { label: \"Email\", htmlFor: \"email\", $: [label()] }\n */\nfunction label(\n props: {\n color?: ValueOrState<ThemeColor>;\n accentColor?: ValueOrState<ThemeColor>;\n } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n const accentColor = toState(props.accentColor ?? \"primary\", \"accentColor\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"label\") {\n console.warn(`\"label\" primitive patch must use label tag`);\n }\n },\n style: {\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: themeSpacing(2),\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n cursor: \"pointer\",\n \"&:focus-within\": {\n color: (listener) =>\n themeColor(listener, \"shift-10\", accentColor.get(listener)),\n },\n \"&[aria-disabled=true]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n color: (listener) => themeColor(listener, \"muted\", \"neutral\"),\n },\n },\n };\n}\n\nexport { label };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * Themed hyperlink primitive: styles text color, hover underline, visited,\n * focus ring and a disabled state. Apply to an `<a>` element.\n *\n * @hostTag a\n * @param props - Optional configuration.\n * @param props.color - Base color tone for the link text. Defaults to `\"primary\"`.\n * @param props.accentColor - Accent color tone for visited/focus states. Defaults to `\"secondary\"`.\n * @example { a: \"Home\", href: \"/\", $: [link()] }\n */\nfunction link(\n props: {\n color?: ValueOrState<ThemeColor>;\n accentColor?: ValueOrState<ThemeColor>;\n } = {},\n): PartialElement {\n const color = toState(props.color ?? \"primary\", \"color\");\n const accentColor = toState(props.accentColor ?? \"secondary\", \"accentColor\");\n return {\n // WAI-ARIA APG: an <a> with no `href` is not a native link — it is not\n // focusable and Enter/Space do nothing, even though it visually looks\n // and (via a caller's own onClick) behaves like one. Declared ON by\n // default (satisfies both APG for the scripted/no-href case AND, since\n // it is a plain declared value doctor's `missing-required-attribute`\n // rule can see, closes the \"onClick with no href/role\" diagnostic) and\n // corrected away in `_onInsert` once the real host attributes are known\n // — `href` lives on the HOST, not this patch, so its presence can't be\n // read until the merge completes. (A reactive `(listener) => …`\n // attribute function does NOT work for this: `attributes.has()` is a\n // plain imperative read, not a tracked reactive dependency, so it froze\n // at whatever `href` had been set to at the function's first,\n // merge-order-dependent evaluation — measured `false` even for a host\n // that DOES declare `href: \"/\"`.)\n role: \"link\",\n tabIndex: 0,\n _onInsert: (node) => {\n if (node.tagName !== \"a\") {\n console.warn(`\"link\" primitive patch must use a tag`);\n }\n // A real `href` makes both a no-op: `<a href>` is already natively\n // focusable with an implicit role=\"link\" — strip the redundant pair\n // rather than leave a harmless-but-confusing explicit restatement.\n // Only strip THIS patch's own default, never a caller's native\n // override: native wins over patch (AGENTS.md merge rule), so by the\n // time `_onInsert` runs, `role` already holds the caller's value if\n // one was declared (e.g. a search result row using `$: [link()]` but\n // declaring its own `role: \"option\"` for a listbox) — removing it\n // unconditionally here silently threw that override away.\n if (node.attributes.has(\"href\")) {\n if (node.attributes.get(\"role\") === \"link\") {\n node.attributes.remove(\"role\");\n }\n if (node.attributes.get(\"tabIndex\") === 0) {\n node.attributes.remove(\"tabIndex\");\n }\n }\n },\n // `<a disabled>` is not a native navigation block — stop click/Enter.\n onClick: (event, node) => {\n const el = node.domElement;\n if (\n el?.hasAttribute(\"disabled\") ||\n el?.getAttribute(\"aria-disabled\") === \"true\"\n ) {\n event.preventDefault();\n }\n },\n onKeyDown: (event, node) => {\n if (node.attributes.has(\"href\")) return;\n const key = (event as KeyboardEvent).key;\n if (key !== \"Enter\" && key !== \" \") return;\n event.preventDefault();\n node.domElement?.click();\n },\n style: {\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n backgroundColor: (listener) => themeColor(listener),\n // shift-13 (not \"text\"/shift-9): brand hues need extra depth for ≥4.5:1\n // on a light surface (primary orange failed at 2.57 with shift-9).\n color: (listener) =>\n themeColor(listener, \"shift-13\", color.get(listener)),\n textDecoration: \"none\",\n \"&:visited\": {\n color: (listener) =>\n themeColor(listener, \"shift-13\", accentColor.get(listener)),\n },\n \"&:hover:not([disabled])\": {\n color: (listener) =>\n themeColor(listener, \"shift-14\", color.get(listener)),\n textDecoration: \"underline\",\n },\n borderRadius: themeSpacing(1),\n // Kill the browser default outline so only the shared focusRing shows.\n outline: \"none\",\n transition: \"color 140ms ease, box-shadow 140ms ease\",\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, accentColor.get(listener)),\n },\n // `disabled` is not a valid attribute on `<a>`; WAI-ARIA's disabled link\n // is `role=\"link\"` + `aria-disabled=\"true\"` (focusable, not operable).\n // Both selectors are styled so either spelling gets the same look.\n \"&[disabled], &[aria-disabled=true]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n pointerEvents: \"none\",\n color: (listener) => themeColor(listener, \"muted\", \"neutral\"),\n },\n },\n };\n}\n\nexport { link };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n textToneOn,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { BUTTON_SIZE_FONT, type ButtonSize } from \"../utils/buttonSize.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\nimport type { ButtonVariant } from \"./button.js\";\n\nconst PADDING_STEPS: Record<ButtonSize, { block: number; inline: number }> = {\n small: { block: 0.5, inline: 2 },\n medium: { block: 1, inline: 3 },\n large: { block: 1.5, inline: 4 },\n};\n\nconst GHOST_PADDING: Record<ButtonSize, number> = {\n small: 0.5,\n medium: 1,\n large: 1.5,\n};\n\n/**\n * An `<a>` element styled to look like a button — same visual system as\n * `button()` (`variant` / `size` / color) while preserving link semantics\n * (href, middle-click, right-click). Apply to an `<a>` element.\n *\n * @hostTag a\n * @param props.color - Button color tone. Optional `ValueOrState<ThemeColor>`, default \"primary\".\n * @param props.variant - `\"outline\"` (default) | `\"solid\"` | `\"ghost\"` — matches `button()`.\n * @param props.size - `\"small\" | \"medium\" | \"large\"`, defaults to `\"medium\"`.\n * @example { a: \"Open app\", href: \"/app\", $: [linkButton({ color: \"primary\" })] }\n * @example { a: \"Get started\", href: \"/start\", $: [linkButton({ variant: \"solid\" })] }\n */\nfunction linkButton(\n props: {\n color?: ValueOrState<ThemeColor>;\n variant?: ButtonVariant;\n size?: ButtonSize;\n } = {},\n): PartialElement {\n const variant = props.variant ?? \"outline\";\n const color = toState(\n props.color ?? (variant === \"ghost\" ? \"neutral\" : \"primary\"),\n \"color\",\n );\n const size = props.size ?? \"medium\";\n const fontSize = BUTTON_SIZE_FONT[size];\n\n if (variant === \"ghost\") {\n const padding = GHOST_PADDING[size];\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"a\") {\n console.warn(`\"linkButton\" primitive patch must use a tag`);\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener, fontSize),\n textDecoration: \"none\",\n paddingBlock: (listener) =>\n themeSpacing(themeDensity(listener) * padding),\n paddingInline: (listener) =>\n themeSpacing(themeDensity(listener) * padding),\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n display: \"inline-flex\",\n justifyContent: \"center\",\n alignItems: \"center\",\n gap: (listener) => themeSpacing(themeDensity(listener) * 1),\n userSelect: \"none\",\n cursor: \"pointer\",\n lineHeight: \"inherit\",\n border: \"none\",\n background: \"none\",\n outline: \"none\",\n transition:\n \"background-color 140ms ease, color 140ms ease, box-shadow 140ms ease\",\n // Resting text uses the \"text\" alias (shift-9), matching buttonGhost:\n // a text-labeled ghost control fails WCAG AA at the previous shift-6\n // (~2.4:1 on an edge surface). Hover/active differentiate via\n // background only.\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n // Label tracks the +2 fill (textToneOn): holding it at \"text\" measured\n // 3.58:1 on the hover fill (light) / 4.37:1 (dark), below WCAG AA.\n \"&:hover:not([aria-disabled=true])\": {\n color: (listener) =>\n themeColor(listener, textToneOn(2), color.get(listener)),\n backgroundColor: (listener) =>\n themeColor(listener, \"hover\", color.get(listener)),\n textDecoration: \"none\",\n },\n \"&:active:not([aria-disabled=true])\": {\n color: (listener) =>\n themeColor(listener, textToneOn(2), color.get(listener)),\n backgroundColor: (listener) =>\n themeColor(listener, \"increase-2\", color.get(listener)),\n },\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, color.get(listener)),\n },\n \"&[aria-disabled=true]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n pointerEvents: \"none\",\n color: (listener) => themeColor(listener, \"border-strong\", \"neutral\"),\n },\n },\n };\n }\n\n const isSolid = variant === \"solid\";\n const padding = PADDING_STEPS[size];\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"a\") {\n console.warn(`\"linkButton\" primitive patch must use a tag`);\n }\n },\n // A solid CTA paints a fixed accent fill (that IS the variant), so its\n // backgroundColor deliberately resolves to a shifted tone rather than\n // \"inherit\". Measured with diagnose(): that is the only rule the solid\n // variant trips — the \"low-contrast\" and \"color-shift-minimum\" entries\n // this list also carried suppressed nothing and were reported as\n // `unused-doctor-disable`.\n ...(isSolid\n ? { _doctorDisable: [\"tone-background-inherit\"] as const }\n : {}),\n style: {\n fontSize: (listener) => themeSize(listener, fontSize),\n textDecoration: \"none\",\n paddingBlock: (listener) =>\n themeSpacing(themeDensity(listener) * padding.block),\n paddingInline: (listener) =>\n themeSpacing(themeDensity(listener) * padding.inline),\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n width: \"fit-content\",\n display: \"inline-flex\",\n justifyContent: \"center\",\n alignItems: \"center\",\n gap: (listener) => themeSpacing(themeDensity(listener) * 1),\n userSelect: \"none\",\n cursor: \"pointer\",\n lineHeight: \"inherit\",\n border: \"none\",\n outlineOffset: \"-1px\",\n outlineWidth: \"1px\",\n outline: isSolid\n ? \"none\"\n : (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", color.get(listener))}`,\n // Solid: deep brand (shift-13) + light-end text (not mid-ramp ~2.2:1).\n // Outline: shift-13 for ≥4.5:1 on light bg.\n color: (listener) =>\n isSolid\n ? themeColor(listener, \"shift-0\", \"neutral\")\n : themeColor(listener, \"shift-13\", color.get(listener)),\n backgroundColor: (listener) =>\n isSolid\n ? themeColor(listener, \"shift-13\", color.get(listener))\n : themeColor(listener, \"inherit\", color.get(listener)),\n transition:\n \"background-color 140ms ease, color 140ms ease, border-color 140ms ease, box-shadow 140ms ease\",\n \"&:hover:not([aria-disabled=true])\": {\n textDecoration: \"none\",\n color: (listener) =>\n isSolid\n ? themeColor(listener, \"shift-0\", \"neutral\")\n : themeColor(listener, \"shift-14\", color.get(listener)),\n backgroundColor: (listener) =>\n isSolid\n ? themeColor(listener, \"shift-14\", color.get(listener))\n : themeColor(listener, \"hover\", color.get(listener)),\n },\n \"&:active:not([aria-disabled=true])\": {\n backgroundColor: (listener) =>\n isSolid\n ? themeColor(listener, \"shift-15\", color.get(listener))\n : themeColor(listener, \"increase-2\", color.get(listener)),\n },\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, color.get(listener)),\n },\n \"&[aria-disabled=true]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n pointerEvents: \"none\",\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-2\", \"neutral\"),\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", \"neutral\")}`,\n color: (listener) => themeColor(listener, \"muted\", \"neutral\"),\n },\n },\n };\n}\n\nexport { linkButton };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n textToneOn,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * Styles a navigation/display list container. Sets `list-style: none` and\n * zero padding; pairs with `listItem` and `listItemButton`. Apply to `<ul>`.\n *\n * @hostTag ul\n * @param props.color - Surface color tone. Optional `ThemeColor`, defaults to `\"neutral\"`.\n * @example { ul: [...], $: [list()] }\n */\nfunction list(props: { color?: ThemeColor } = {}): PartialElement {\n const color = props.color ?? \"neutral\";\n return {\n style: {\n listStyle: \"none\",\n margin: 0,\n padding: 0,\n display: \"flex\",\n flexDirection: \"column\",\n backgroundColor: (listener) => themeColor(listener, \"inherit\", color),\n color: (listener) => themeColor(listener, \"text\", color),\n },\n };\n}\n\n/**\n * A non-interactive list row. Typically wraps an icon + text. Apply to `<li>`.\n *\n * @hostTag li\n * @param props.dense - Reduce vertical padding. Optional `boolean`, defaults to `false`.\n * @example { li: \"Item\", $: [listItem()] }\n */\nfunction listItem(props: { dense?: boolean } = {}): PartialElement {\n const { dense = false } = props;\n return {\n style: {\n display: \"flex\",\n alignItems: \"center\",\n gap: (listener) => themeSpacing(themeDensity(listener) * 2),\n paddingBlock: (listener) =>\n themeSpacing(dense ? 1 : themeDensity(listener) * 2),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 3),\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n color: (listener) => themeColor(listener, \"text\"),\n },\n };\n}\n\n/**\n * An interactive (clickable) list row with hover/focus-visible states. Apply\n * to `<button>` or `<a>` inside an `<li>`.\n *\n * @param props.color - Color tone. Optional `ValueOrState<ThemeColor>`, defaults to `\"neutral\"`.\n * @param props.accentColor - Focus/active accent. Optional `ThemeColor`, defaults to `\"primary\"`.\n * @param props.dense - Reduce vertical padding. Optional `boolean`, defaults to `false`.\n * @example { button: \"Action\", $: [listItemButton()] }\n */\nfunction listItemButton(\n props: {\n color?: ValueOrState<ThemeColor>;\n accentColor?: ThemeColor;\n dense?: boolean;\n } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n const accentColor = props.accentColor ?? \"primary\";\n const { dense = false } = props;\n\n return {\n // Native `type` on the host still wins (mergePartial: native over patch).\n type: \"button\",\n style: {\n cursor: \"pointer\",\n appearance: \"none\",\n border: \"none\",\n background: \"transparent\",\n textDecoration: \"none\",\n textAlign: \"start\",\n display: \"flex\",\n alignItems: \"center\",\n width: \"100%\",\n gap: (listener) => themeSpacing(themeDensity(listener) * 2),\n paddingBlock: (listener) =>\n themeSpacing(dense ? 1 : themeDensity(listener) * 2),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 3),\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n transition: \"background-color 150ms ease, box-shadow 140ms ease\",\n // The fill moves 2 steps off the surface, so the label moves with it —\n // keeping the resting \"text\" tone measured 3.58:1 on the hover fill.\n \"&:hover:not([disabled])\": {\n color: (listener) =>\n themeColor(listener, textToneOn(2), color.get(listener)),\n backgroundColor: (listener) =>\n themeColor(listener, \"hover\", color.get(listener)),\n },\n \"&:active:not([disabled])\": {\n color: (listener) =>\n themeColor(listener, textToneOn(2), color.get(listener)),\n backgroundColor: (listener) =>\n themeColor(listener, \"increase-2\", color.get(listener)),\n },\n \"&[aria-current=page], &[aria-selected=true]\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-3\", accentColor),\n color: (listener) => themeColor(listener, \"shift-12\", accentColor),\n },\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, accentColor),\n },\n \"&[disabled]\": { opacity: 0.5, cursor: \"not-allowed\" },\n },\n };\n}\n\nexport { list, listItem, listItemButton };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * Themed highlight primitive: gives marked/highlighted inline text a tinted\n * background, rounded corners and padding. Apply to a `<mark>` element.\n *\n * @hostTag mark\n * @param props - Optional configuration.\n * @param props.accentColor - Accent color tone for the highlight fill and text. Defaults to `\"highlight\"`.\n * @example { mark: \"important\", $: [mark()] }\n */\nfunction mark(\n props: { accentColor?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const accentColor = toState(props.accentColor ?? \"highlight\", \"accentColor\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"mark\") {\n console.warn(`\"mark\" primitive patch must use mark tag`);\n }\n },\n dataTone: \"shift-2\",\n style: {\n display: \"inline-flex\",\n alignItems: \"center\",\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n color: (listener) =>\n themeColor(listener, \"text\", accentColor.get(listener)),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", accentColor.get(listener)),\n // Bare themeSpacing(U) at snapshot time; n = U / 1.5 (light.densities[2]).\n height: (listener) => themeSpacing(themeDensity(listener) * (6 / 1.5)),\n borderRadius: (listener) =>\n themeSpacing(themeDensity(listener) * (1 / 1.5)),\n paddingInline: (listener) =>\n themeSpacing(themeDensity(listener) * (1.5 / 1.5)),\n },\n };\n}\n\nexport { mark };\n","import {\n type BehaviorInstance,\n behavior,\n type DomphyElement,\n type ElementNode,\n type Listener,\n type PartialElement,\n type State,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport {\n type ThemeColor,\n textToneOn,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { elevation } from \"../utils/elevation.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/** One item inside a menu. */\ntype MenuItem = {\n /** Button label — plain string (auto-wrapped) or any DomphyElement (e.g. icon + text). */\n label: string | DomphyElement;\n /** Stable key. Defaults to the item's zero-based index. */\n key?: string | number;\n /** Called when the item is clicked. */\n onClick?: () => void;\n};\n\n/**\n * All-in-one vertical menu. Generates `<button>` `[role=menuitem]` elements\n * from the `items` array with keyboard navigation (Arrow/Home/End/Enter/Space).\n * Apply to any wrapper element (`div`, `ul`, …).\n *\n * @param props.items - Item definitions `{ label, key?, onClick? }`. Pass `[]`\n * to keep the wrapper's own children (escape hatch for fully custom rows —\n * only the menu container styling and `role=\"menu\"` semantics apply then).\n * @param props.activeKey - Currently selected key (value or State). Defaults to `null`.\n * @param props.selectable - Whether items track and update the active selection. Defaults to `true`.\n * @param props.color - Background color tone for the menu. Defaults to `\"neutral\"`.\n * @param props.accentColor - Accent color for the active/focus item. Defaults to `\"primary\"`.\n * @example\n * { div: null, $: [menu({ items: [\n * { label: \"Profile\", key: \"profile\", onClick: () => navigate(\"/profile\") },\n * { label: \"Settings\", key: \"settings\", onClick: () => navigate(\"/settings\") },\n * ] })] }\n */\nfunction menu(\n props: {\n items: MenuItem[];\n activeKey?: ValueOrState<number | string | null>;\n selectable?: boolean;\n color?: ThemeColor;\n accentColor?: ThemeColor;\n } = { items: [] },\n): PartialElement {\n const {\n items = [],\n selectable = true,\n color = \"neutral\",\n accentColor = \"primary\",\n } = props;\n const activeKey = toState(props.activeKey ?? null);\n const activeKeyIsCallerOwned = props.activeKey !== undefined;\n\n type MenuInner = {\n items: MenuItem[];\n activeKey: State<number | string | null>;\n activeKeyIsCallerOwned: boolean;\n selectable: boolean;\n color: ThemeColor;\n accentColor: ThemeColor;\n // Roving-tabindex cursor (WAI-ARIA APG menu pattern): exactly one item is\n // in the page tab order at a time; Arrow/Home/End move it. Kept on the\n // shared `inner` record (not a factory-scope variable) so every generation\n // of a reused node reads the same cursor.\n focusedKey: State<number | string | null>;\n };\n\n // The item that owns tabindex=\"0\": the roving cursor if one has been set,\n // otherwise the selected item, otherwise the first item.\n const tabbableKey = (\n inner: MenuInner,\n listener: Listener,\n ): number | string | null => {\n const focused = inner.focusedKey.get(listener);\n if (focused !== null) return focused;\n const active = inner.selectable ? inner.activeKey.get(listener) : null;\n if (active !== null) return active;\n const first = inner.items[0];\n return first ? (first.key ?? 0) : null;\n };\n\n const buildItems = (\n node: ElementNode,\n inner: MenuInner,\n ): DomphyElement<\"button\">[] => {\n const id = node.nodeId;\n return inner.items.map((item, index) => {\n const key = item.key ?? index;\n return {\n button:\n typeof item.label === \"string\"\n ? [{ span: item.label } as DomphyElement<\"span\">]\n : [item.label],\n _key: key,\n type: \"button\",\n id: `menuitem${id}${key}`,\n role: \"menuitem\",\n tabIndex: (l: Listener) => (tabbableKey(inner, l) === key ? 0 : -1),\n onFocus: () => inner.focusedKey.set(key),\n ...(inner.selectable\n ? {\n ariaCurrent: (l: Listener) =>\n inner.activeKey.get(l) === key || undefined,\n }\n : {}),\n onClick: () => {\n if (inner.selectable) inner.activeKey.set(key);\n item.onClick?.();\n },\n onKeyDown: (e: Event) => {\n const k = (e as KeyboardEvent).key;\n if (k === \"Enter\" || k === \" \") {\n e.preventDefault();\n (e.target as HTMLElement).click();\n return;\n }\n if (![\"ArrowDown\", \"ArrowUp\", \"Home\", \"End\"].includes(k)) return;\n e.preventDefault();\n const keys = inner.items.map((it, i) => it.key ?? i);\n const idx = keys.indexOf(key);\n let next = idx;\n if (k === \"ArrowDown\") next = (idx + 1) % keys.length;\n else if (k === \"ArrowUp\")\n next = (idx - 1 + keys.length) % keys.length;\n else if (k === \"Home\") next = 0;\n else if (k === \"End\") next = keys.length - 1;\n // Resolved through the event target's own [role=menu] — shadow-root\n // safe, unlike a document.getElementById lookup (a menu rendered\n // inside a shadow root is invisible to the document-level id map,\n // so arrow keys silently did nothing there). Same resolution the\n // tabs patch already uses for its tablist.\n const list = (e.target as HTMLElement).closest(\"[role=menu]\");\n list?.querySelectorAll<HTMLElement>(\"[role=menuitem]\")[next]?.focus();\n },\n style: {\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n gap: themeSpacing(2),\n width: \"100%\",\n fontSize: (l: Listener) => themeSize(l, \"inherit\"),\n height: (l: Listener) => themeSpacing(6 + themeDensity(l) * 2),\n paddingInline: (l: Listener) => themeSpacing(themeDensity(l) * 3),\n border: \"none\",\n outline: \"none\",\n // Menu panel is a light (shift-0) surface: \"text\" resolves to a\n // dark-on-light reading tone in both light and dark themes.\n color: (l: Listener) => themeColor(l, \"text\", inner.color),\n backgroundColor: (l: Listener) =>\n themeColor(l, \"inherit\", inner.color),\n transition:\n \"background-color 140ms ease, box-shadow 140ms ease, color 140ms ease\",\n // Label tracks the hover fill (+2) — a fixed \"text\" label measured\n // 3.58:1 against it (light) / 4.37:1 (dark), below WCAG AA.\n \"&:hover:not([disabled]):not([aria-current=true])\": {\n backgroundColor: (l: Listener) =>\n themeColor(l, \"hover\", inner.color),\n color: (l: Listener) => themeColor(l, textToneOn(2), inner.color),\n },\n \"&[aria-current=true]\": {\n backgroundColor: (l: Listener) =>\n themeColor(l, \"shift-3\", inner.accentColor),\n color: (l: Listener) =>\n themeColor(l, \"shift-13\", inner.accentColor),\n },\n \"&:focus-visible\": {\n boxShadow: (l: Listener) => focusRing(l, inner.accentColor),\n },\n },\n } as DomphyElement<\"button\">;\n });\n };\n\n const attachMenu = (\n _node: ElementNode,\n initial: MenuInner,\n ): BehaviorInstance<MenuInner> => {\n // WAI-ARIA APG: when a menu opens, focus starts on the first item, not\n // wherever a PREVIOUS open left the roving cursor. attach() runs exactly\n // once per real DOM node — a genuine reopen (the menu's floating\n // container, e.g. popover, unmounts and remounts the panel on every\n // close/open) gets a fresh node and refires attach here, while an\n // in-place re-render (same node, e.g. mid-navigation Arrow presses)\n // never does — so this only resets on a real reopen, never mid-session.\n initial.focusedKey.set(null);\n let current = initial;\n return {\n update(next) {\n if (\n next.activeKey !== current.activeKey &&\n !next.activeKeyIsCallerOwned\n ) {\n next.activeKey.set(current.activeKey.get());\n }\n // Carry the roving cursor across generations too — a fresh factory\n // closure brings a fresh `toState(null)`, which would drop\n // tabindex=\"0\" back onto the first item mid-keyboard-navigation.\n if (next.focusedKey !== current.focusedKey) {\n next.focusedKey.set(current.focusedKey.get());\n }\n current = next;\n // Empty items = the caller renders its own rows; leave children alone.\n if (current.items.length === 0) return;\n _node.children.update(buildItems(_node, current));\n },\n };\n };\n\n const inner: MenuInner = {\n items,\n activeKey,\n activeKeyIsCallerOwned,\n selectable,\n color,\n accentColor,\n focusedKey: toState<number | string | null>(null),\n };\n\n return {\n role: \"menu\",\n dataTone: \"shift-0\",\n _onSchedule: (node, element) => {\n // Empty items = the caller renders its own rows; leave children alone.\n if (items.length === 0) return;\n (element as Record<string, unknown>)[node.tagName] = buildItems(\n node,\n inner,\n );\n },\n ...behavior<MenuInner>(\"menu\", attachMenu, inner),\n style: {\n display: \"flex\",\n flexDirection: \"column\",\n paddingBlock: (l: Listener) => themeSpacing(themeDensity(l) * 2),\n paddingInline: (l: Listener) => themeSpacing(themeDensity(l) * 2),\n fontSize: (l: Listener) => themeSize(l, \"inherit\"),\n backgroundColor: (l: Listener) => themeColor(l, \"inherit\", color),\n color: (l: Listener) => themeColor(l, \"text\", color),\n borderRadius: (l: Listener) => themeSpacing(themeDensity(l) * 2),\n outline: (l: Listener) =>\n `1px solid ${themeColor(l, \"border-strong\", color)}`,\n outlineOffset: \"-1px\",\n boxShadow: elevation(\"medium\"),\n },\n };\n}\n\nexport { menu };\nexport type { MenuItem };\n","import {\n type BehaviorInstance,\n behavior,\n type PartialElement,\n type State,\n} from \"@domphy/core\";\nimport { prefersReducedMotion } from \"../utils/reducedMotion.js\";\n\n/**\n * One keyframe. Shorthands `x`/`y` (px), `scale`, `rotate` (deg) compose into a\n * single `transform`; any other key is a raw CSS property (e.g. `opacity`,\n * `backgroundColor`).\n */\nexport type MotionKeyframe = {\n x?: number | string;\n y?: number | string;\n scale?: number | string;\n rotate?: number | string;\n} & Record<string, string | number>;\n\nexport interface MotionProps {\n /** Starting keyframe applied before the enter animation. */\n initial?: MotionKeyframe;\n /** Target keyframe. Pass a `State` to re-animate whenever it changes. */\n animate?: MotionKeyframe | State<MotionKeyframe>;\n /** Keyframe animated to before the element is removed. */\n exit?: MotionKeyframe;\n transition?: {\n /** ms, default 300. */\n duration?: number;\n /** ms, default 0. */\n delay?: number;\n /** CSS easing, default \"ease\". */\n easing?: string;\n iterations?: number;\n };\n}\n\ntype MotionInstance = BehaviorInstance<MotionProps> & {\n play: (props: MotionProps, mode: \"enter\" | \"update\") => void;\n getExit: () => MotionKeyframe | undefined;\n getTransition: () => MotionProps[\"transition\"];\n};\n\nconst isMotionState = (value: unknown): value is State<MotionKeyframe> =>\n !!value &&\n typeof (value as State<MotionKeyframe>).get === \"function\" &&\n (value as { _isState?: boolean })._isState === true;\n\nconst toStyles = (frame: MotionKeyframe): Keyframe => {\n const out: Record<string, string | number> = {};\n const transforms: string[] = [];\n for (const key in frame) {\n const value = frame[key];\n if (key === \"x\") {\n transforms.push(\n `translateX(${typeof value === \"number\" ? `${value}px` : value})`,\n );\n } else if (key === \"y\") {\n transforms.push(\n `translateY(${typeof value === \"number\" ? `${value}px` : value})`,\n );\n } else if (key === \"scale\") {\n transforms.push(`scale(${value})`);\n } else if (key === \"rotate\") {\n transforms.push(\n `rotate(${typeof value === \"number\" ? `${value}deg` : value})`,\n );\n } else {\n out[key] = value;\n }\n }\n if (transforms.length) out.transform = transforms.join(\" \");\n return out as Keyframe;\n};\n\nfunction toOptions(\n transition: MotionProps[\"transition\"] = {},\n): KeyframeAnimationOptions {\n return {\n duration: transition.duration ?? 300,\n delay: transition.delay ?? 0,\n easing: transition.easing ?? \"ease\",\n iterations: transition.iterations ?? 1,\n fill: \"both\",\n };\n}\n\nfunction attachMotion(\n node: { domElement?: HTMLElement | null },\n initial: MotionProps,\n): MotionInstance {\n const el = node.domElement as HTMLElement | null;\n let current = initial;\n let release: (() => void) | undefined;\n\n const bindAnimate = (animate: MotionProps[\"animate\"]) => {\n release?.();\n release = undefined;\n if (!el || !isMotionState(animate)) return;\n release = animate.addListener((next: MotionKeyframe) => {\n if (prefersReducedMotion()) {\n Object.assign(el.style, toStyles(next));\n } else if (typeof el.animate === \"function\") {\n el.animate([toStyles(next)], toOptions(current.transition));\n }\n });\n };\n\n const play = (props: MotionProps, mode: \"enter\" | \"update\") => {\n if (!el) return;\n const target = isMotionState(props.animate)\n ? props.animate.get()\n : props.animate;\n if (prefersReducedMotion()) {\n if (target) Object.assign(el.style, toStyles(target));\n else if (mode === \"enter\" && props.initial) {\n Object.assign(el.style, toStyles(props.initial));\n }\n return;\n }\n if (typeof el.animate !== \"function\") return;\n if (target) {\n const frames =\n mode === \"enter\" && props.initial\n ? [toStyles(props.initial), toStyles(target)]\n : [toStyles(target)];\n el.animate(frames, toOptions(props.transition));\n } else if (mode === \"enter\" && props.initial) {\n Object.assign(el.style, toStyles(props.initial));\n }\n };\n\n play(initial, \"enter\");\n bindAnimate(initial.animate);\n\n return {\n play,\n getExit: () => current.exit,\n getTransition: () => current.transition,\n update(next) {\n current = next;\n play(next, \"update\");\n bindAnimate(next.animate);\n },\n destroy() {\n release?.();\n },\n };\n}\n\n/**\n * Animation primitive driven by the Web Animations API. Runs an enter\n * animation on mount (`initial` -> `animate`), re-animates whenever `animate`\n * is a `State` that changes, and plays the `exit` keyframe before removal.\n * Has no host-tag restriction; apply to any element you want to animate.\n *\n * Later generations route a fresh `animate`/`exit`/`transition` into the same\n * `behavior()` instance via `update()`, so a reused node is not stuck on\n * generation-1 keyframes.\n *\n * @param props - Optional configuration (see {@link MotionProps}).\n * @param props.initial - Starting keyframe applied before the enter animation.\n * @param props.animate - Target keyframe, or a `State` to re-animate on change.\n * @param props.exit - Keyframe animated to before the element is removed.\n * @param props.transition - Timing options.\n * @param props.transition.duration - Duration in ms. Defaults to `300`.\n * @param props.transition.delay - Delay in ms. Defaults to `0`.\n * @param props.transition.easing - CSS easing. Defaults to `\"ease\"`.\n * @param props.transition.iterations - Number of iterations. Defaults to `1`.\n * @example { div: \"Hello\", $: [motion({ initial: { opacity: 0 }, animate: { opacity: 1 } })] }\n */\nfunction motion(props: MotionProps = {}): PartialElement {\n return {\n ...behavior<MotionProps>(\n \"motion\",\n (node, next) => attachMotion(node, next),\n props,\n ),\n _onBeforeRemove: (node, done) => {\n const el = node.domElement as HTMLElement | null;\n const inst = node.getBehavior<MotionInstance>(\"motion\");\n const exit = inst?.getExit() ?? props.exit;\n if (!el || !exit || typeof el.animate !== \"function\") return done();\n if (prefersReducedMotion()) {\n Object.assign(el.style, toStyles(exit));\n return done();\n }\n el.animate(\n [toStyles(exit)],\n toOptions(inst?.getTransition() ?? props.transition),\n ).finished.then(done, done);\n },\n };\n}\n\nexport { motion };\n","/**\n * True when the user has asked for reduced motion (WCAG 2.3.3 Animation from\n * Interactions). Shared by every animating patch — `motion()` swaps the\n * keyframe in directly and `transitionGroup()` skips its FLIP capture.\n * Returns false where `matchMedia` is missing (SSR, jsdom without a stub).\n */\nfunction prefersReducedMotion(): boolean {\n if (typeof matchMedia !== \"function\") return false;\n try {\n return matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n } catch {\n return false;\n }\n}\n\nexport { prefersReducedMotion };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * Themed ordered-list primitive: decimal markers positioned outside, reset\n * margins and themed text color. Apply to an `<ol>` element.\n *\n * @hostTag ol\n * @param props - Optional configuration.\n * @param props.color - Color tone for the list text. Defaults to `\"neutral\"`.\n * @example { ol: [{ li: \"First\" }, { li: \"Second\" }], $: [orderedList()] }\n */\nfunction orderedList(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"ol\") {\n console.warn(`\"orderedList\" primitive patch must use ol tag`);\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n backgroundColor: (listener) => themeColor(listener),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n marginTop: 0,\n marginBottom: 0,\n paddingInlineStart: themeSpacing(3),\n listStyleType: \"decimal\",\n listStylePosition: \"outside\",\n },\n };\n}\n\nexport { orderedList };\n","import {\n behavior,\n type DomphyElement,\n type ElementNode,\n isState,\n type PartialElement,\n type State,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n themeWeight,\n} from \"@domphy/theme\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\nfunction getPages(current: number, total: number): (number | \"...\")[] {\n if (total <= 7) return Array.from({ length: total }, (_, i) => i + 1);\n const pages: (number | \"...\")[] = [1];\n if (current > 3) pages.push(\"...\");\n const start = Math.max(2, current - 1);\n const end = Math.min(total - 1, current + 1);\n for (let i = start; i <= end; i++) pages.push(i);\n if (current < total - 2) pages.push(\"...\");\n pages.push(total);\n return pages;\n}\n\nfunction persistValue<T>(\n node: ElementNode,\n key: string,\n incoming: ValueOrState<T> | undefined,\n fallback: T,\n): State<T> {\n if (isState(incoming)) {\n node.setMetadata(key, incoming);\n return incoming as State<T>;\n }\n let stored = node.getMetadata(key) as State<T> | undefined;\n if (!stored) {\n stored = toState((incoming as T | undefined) ?? fallback);\n node.setMetadata(key, stored);\n }\n return stored;\n}\n\nfunction persistTotal(node: ElementNode, total: number): State<number> {\n let stored = node.getMetadata(\"paginationTotal\") as State<number> | undefined;\n if (!stored) {\n stored = toState(total);\n node.setMetadata(\"paginationTotal\", stored);\n }\n return stored;\n}\n\n/**\n * Themed pagination control. Renders previous/next buttons plus truncated page\n * numbers (with ellipses), tracks the current page in a `State`, and updates it\n * on click. Apply to a `<div>` element.\n *\n * @hostTag div\n * @param props - Configuration.\n * @param props.total - Required. Total number of pages.\n * @param props.value - Current page, accepts a value or `State`. Defaults to `1`.\n * @param props.color - Base color tone for the page buttons. Defaults to `\"neutral\"`.\n * @param props.accentColor - Accent color tone for the active page. Defaults to `\"primary\"`.\n * @example { div: null, $: [pagination({ total: 10, value: 1 })] }\n */\nfunction pagination(props: {\n value?: ValueOrState<number>;\n total: number;\n color?: ThemeColor;\n accentColor?: ThemeColor;\n}): PartialElement {\n const { total, color = \"neutral\", accentColor = \"primary\" } = props;\n\n const buttonBase = {\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n minWidth: (listener: any) => themeSpacing(6 + themeDensity(listener) * 2),\n height: (listener: any) => themeSpacing(6 + themeDensity(listener) * 2),\n paddingInline: (listener: any) => themeSpacing(themeDensity(listener) * 2),\n borderRadius: (listener: any) => themeSpacing(themeDensity(listener) * 1.5),\n border: \"none\",\n cursor: \"pointer\",\n fontSize: (listener: any) => themeSize(listener, \"inherit\"),\n backgroundColor: \"transparent\",\n // Page numbers: shift-13 for readable inactive digits (catalog contrast).\n color: (listener: any) => themeColor(listener, \"shift-13\", color),\n transition:\n \"background-color 140ms ease, box-shadow 140ms ease, color 140ms ease\",\n \"&:hover:not([disabled])\": {\n color: (listener: any) => themeColor(listener, \"shift-13\", color),\n backgroundColor: (listener: any) => themeColor(listener, \"hover\", color),\n },\n \"&:focus-visible\": {\n boxShadow: (listener: any) => focusRing(listener, accentColor),\n },\n \"&[disabled]\": {\n opacity: 0.4,\n cursor: \"not-allowed\",\n },\n };\n\n const activeStyle = {\n ...buttonBase,\n // Deep accent fill + light text (mid-ramp + mid text failed catalog).\n backgroundColor: (listener: any) =>\n themeColor(listener, \"shift-13\", accentColor),\n color: (listener: any) => themeColor(listener, \"shift-0\", \"neutral\"),\n fontWeight: themeWeight(\"bold\"),\n cursor: \"default\",\n \"&:hover:not([disabled])\": {\n backgroundColor: (listener: any) =>\n themeColor(listener, \"shift-13\", accentColor),\n },\n };\n\n return {\n role: \"navigation\",\n ariaLabel: \"Pagination\",\n _onInsert: (node) => {\n if (node.tagName !== \"div\")\n console.warn('\"pagination\" patch must use div tag');\n },\n _onInit: (node) => {\n const state = persistValue(node, \"paginationPage\", props.value, 1);\n const totalState = persistTotal(node, total);\n const content: DomphyElement<\"div\"> = {\n div: (listener) => {\n const page = state.get(listener);\n const pageCount = totalState.get(listener);\n const items: DomphyElement[] = [];\n\n // Prev button\n items.push({\n button: \"‹\",\n _key: \"prev\",\n type: \"button\",\n ariaLabel: \"Previous page\",\n disabled: page <= 1,\n onClick: () => page > 1 && state.set(page - 1),\n style: buttonBase,\n });\n\n // Page buttons. Keyed by page number (or a running ellipsis index —\n // there can be up to two \"...\" spans) so the list survives length\n // changes across pages without the unkeyed-reuse footgun.\n let ellipsisIndex = 0;\n for (const p of getPages(page, pageCount)) {\n if (p === \"...\") {\n items.push({\n span: \"…\",\n _key: `ellipsis-${ellipsisIndex++}`,\n ariaHidden: \"true\",\n style: {\n display: \"inline-flex\",\n alignItems: \"center\",\n paddingInline: (listener: any) =>\n themeSpacing(themeDensity(listener) * 2),\n color: (listener: any) =>\n themeColor(listener, \"shift-7\", color),\n },\n });\n } else {\n const isActive = p === page;\n items.push({\n button: String(p),\n _key: `page-${p}`,\n type: \"button\",\n ariaLabel: `Page ${p}`,\n ariaCurrent: isActive ? \"page\" : undefined,\n // The current page stays enabled (shadcn PaginationLink /\n // MUI Pagination parity). `disabled` on the just-clicked\n // button pulls it out of the tab order the instant it becomes\n // current, so the browser drops focus to <body> and a keyboard\n // user is stranded outside the control after every page\n // change. `aria-current=\"page\"` already conveys the state.\n onClick: () => state.set(p),\n style: isActive ? activeStyle : buttonBase,\n });\n }\n }\n\n // Next button\n items.push({\n button: \"›\",\n _key: \"next\",\n type: \"button\",\n ariaLabel: \"Next page\",\n disabled: page >= pageCount,\n onClick: () => page < pageCount && state.set(page + 1),\n style: buttonBase,\n });\n\n return items;\n },\n style: {\n display: \"flex\",\n alignItems: \"center\",\n gap: themeSpacing(1),\n },\n };\n node.children.insert(content);\n },\n ...behavior<{ total: number }>(\n \"pagination-total\",\n (node) => ({\n update(snapshot) {\n persistTotal(node, snapshot.total).set(snapshot.total);\n },\n }),\n { total },\n ),\n style: {\n display: \"inline-flex\",\n },\n };\n}\n\nexport { pagination };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * A padded section for side-panel/inspector UIs — density-aware padding on\n * all sides, with an optional bottom divider for sections stacked one after\n * another. A thin wrapper: it does not impose flex layout on its children —\n * pair it with `stack()` or `row()` for that. No host-tag check; apply to\n * any block element.\n *\n * @param props.padding - Spacing multiplier for padding on all sides (default 4 = 1em at density 1).\n * @param props.divider - Adds a bottom border, for sections stacked one after another. Defaults to `false`.\n * @param props.color - Theme color tone for the divider border. Defaults to `\"neutral\"`.\n * @example { div: [{ h3: \"Parameters\" }, { p: \"...\" }], $: [panelSection()] }\n * @example\n * { div: [\n * { div: \"Section A\", $: [panelSection({ divider: true })] },\n * { div: \"Section B\", $: [panelSection()] },\n * ], $: [stack({ gap: 0 })] }\n */\nfunction panelSection(\n props: {\n padding?: number;\n divider?: boolean;\n color?: ValueOrState<ThemeColor>;\n } = {},\n): PartialElement {\n const { padding = 4, divider = false } = props;\n const color = toState(props.color ?? \"neutral\", \"color\");\n return {\n style: {\n padding: (listener) => themeSpacing(themeDensity(listener) * padding),\n ...(divider\n ? {\n borderBottom: (listener) =>\n `1px solid ${themeColor(listener, \"border\", color.get(listener))}`,\n // Declaring a theme token makes this a themed surface, so the text\n // tone has to be declared with it (doctor `missing-color`): CSS\n // inheritance carries the parent's COMPUTED color and does not\n // re-run themeColor() when the tone context shifts, so a divided\n // section dropped into a darker panel kept the lighter surface's\n // text. Always the neutral body tone — `color` names the DIVIDER's\n // role, and a primary rule should not tint the prose.\n color: (listener) => themeColor(listener, \"text\"),\n }\n : {}),\n },\n };\n}\n\nexport { panelSection };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport { type ThemeColor, themeColor, themeSize } from \"@domphy/theme\";\n\n/**\n * Themed paragraph primitive: comfortable line-height, reset margins and themed\n * text color. Apply to a `<p>` element.\n *\n * @hostTag p\n * @param props - Optional configuration.\n * @param props.color - Color tone for the paragraph text. Defaults to `\"neutral\"`.\n * @example { p: \"Hello world\", $: [paragraph()] }\n */\nfunction paragraph(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"p\") {\n console.warn(`\"paragraph\" primitive patch must use p tag`);\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n lineHeight: 1.5,\n marginTop: 0,\n marginBottom: 0,\n },\n };\n}\n\nexport { paragraph };\n","import {\n type DomphyElement,\n type Listener,\n merge,\n type PartialElement,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport type { Placement } from \"@domphy/floating\";\nimport { themeColor, themeDensity, themeSpacing } from \"@domphy/theme\";\nimport { elevation } from \"../utils/elevation.js\";\nimport { createFloating, floatingPanelId } from \"../utils/floating.js\";\n\n// `aria-haspopup` must name the role the popup ACTUALLY has — a trigger that\n// says \"dialog\" while it opens a `role=menu` panel is an ARIA contract break\n// (axe `aria-allowed-attr` passes it, but a screen reader announces the wrong\n// kind of popup and readers that pre-announce \"menu\" say \"dialog\"). The\n// popover's own panel chrome is `role=dialog`, but content that already owns a\n// surface keeps its own role: `menu()` is `role=menu`, `selectList()` is\n// `role=listbox`. Only these five values are legal for aria-haspopup.\nconst HASPOPUP_ROLES = new Set([\"dialog\", \"grid\", \"listbox\", \"menu\", \"tree\"]);\ntype HaspopupRole = \"dialog\" | \"grid\" | \"listbox\" | \"menu\" | \"tree\";\n\n// Mirrors core's own precedence: patches merge in `$` order (later wins) and\n// the element's own keys win over all of them.\nfunction panelHaspopup(content: DomphyElement): HaspopupRole {\n let role: unknown;\n for (const patch of content.$ ?? []) {\n const declared = (patch as { role?: unknown } | null)?.role;\n if (typeof declared === \"string\") role = declared;\n }\n const own = (content as { role?: unknown }).role;\n if (typeof own === \"string\") role = own;\n if (typeof role !== \"string\") return \"dialog\";\n // Aliases with no aria-haspopup value of their own.\n if (role === \"alertdialog\" || role === \"menubar\") {\n return role === \"menubar\" ? \"menu\" : \"dialog\";\n }\n if (role === \"treegrid\") return \"grid\";\n // Anything else (a bare card, `command()`'s role=group) has no matching\n // value; \"dialog\" is what the popover's own chrome would have given it.\n return HASPOPUP_ROLES.has(role) ? (role as HaspopupRole) : \"dialog\";\n}\n\nfunction contentOwnsSurface(content: DomphyElement): boolean {\n const record = content as DomphyElement & { dataTone?: string };\n if (typeof record.dataTone === \"string\") return true;\n const patches = content.$;\n if (!patches) return false;\n return patches.some(\n (patch) =>\n patch != null &&\n typeof (patch as { dataTone?: unknown }).dataTone === \"string\",\n );\n}\n\n/**\n * Floating popover primitive. Attaches to its host as the anchor/trigger and\n * shows a floating `content` element (with `role=\"dialog\"`) on click or hover,\n * positioned via `@domphy/floating`. Returns the anchor partial, which merges\n * trigger wiring (haspopup/expanded, focus/blur dismissal). Apply to the\n * trigger element you want the popover anchored to.\n *\n * @param props - Configuration.\n * @param props.openOn - Interaction that opens the popover: `\"click\"` or `\"hover\"`. Defaults to `\"click\"`.\n * @param props.open - Open state (`ValueOrState<boolean>`), including `Computed`/`ReadableState`. When the source is read-only, pass `onDismiss` so Escape/outside click can close. Defaults to `false`.\n * @param props.onDismiss - Called when the panel requests close. Optional. Required to close when `open` is a read-only `Computed`/`ReadableState`.\n * @param props.placement - Floating placement (e.g. `\"bottom\"`, `\"top-start\"`), value or `State`. Defaults to `\"bottom\"`.\n * @param props.content - The floating content element to display.\n * @example { button: \"Open\", $: [popover({ openOn: \"click\", content: { div: \"Hi\" } })] }\n */\nfunction popover(props: {\n openOn?: \"click\" | \"hover\";\n open?: ValueOrState<boolean>;\n onDismiss?: () => void;\n placement?: ValueOrState<Placement>;\n content: DomphyElement;\n}): PartialElement {\n const { open = false, placement = \"bottom\", openOn = \"click\" } = props;\n\n const openState = toState(open);\n const placeState = toState(placement);\n\n const { show, hide, anchorPartial } = createFloating({\n kind: \"popover\",\n open: openState,\n onDismiss: props.onDismiss,\n placement: placeState,\n content: props.content,\n // Hovering the panel itself (not just the trigger) must keep it open —\n // handled generically inside floating.ts's behavior instance.\n keepOpenOnContentHover: openOn === \"hover\",\n });\n\n // Page-matching card (shift-0), same as menu/selectList/dialog — not the\n // inverted tooltip/toast surface (shift-17). A dark shift-14 panel wrapping\n // a light menu is the menubar recipe (`popover` + `menu`) rendered as two\n // stacked cards.\n const popoverPartial: PartialElement = {\n role: \"dialog\",\n dataTone: \"shift-0\",\n style: {\n backgroundColor: (l: Listener) => themeColor(l, \"inherit\"),\n color: (l: Listener) => themeColor(l, \"text\"),\n borderRadius: (l: Listener) => themeSpacing(themeDensity(l) * 2),\n outline: (l: Listener) => `1px solid ${themeColor(l, \"border-strong\")}`,\n outlineOffset: \"-1px\",\n boxShadow: elevation(\"medium\"),\n },\n };\n\n // Content that already owns a surface (`menu()`, `card()`, an authored\n // dataTone) must keep it: stamping this partial on top overwrites\n // `role=menu` with `role=dialog` and comma-joins a second box-shadow\n // (merge concatenates boxShadow).\n if (!contentOwnsSurface(props.content)) {\n props.content.$ ||= [];\n props.content.$.push(popoverPartial);\n }\n\n const triggerPartial: PartialElement = {\n // Read AFTER the popoverPartial push above, so unstyled content that got\n // the popover's own `role=dialog` chrome resolves to \"dialog\" too.\n ariaHaspopup: panelHaspopup(props.content),\n ariaExpanded: (listener) => openState.get(listener),\n // Declared as a reactive attribute (listener.elementNode is the anchor) so\n // it is present from first render — before the panel's first show() — and\n // is re-declared on every patch: attributes set imperatively (the old\n // _onMount attributes.set) are stripped by patch() on ancestor re-render.\n ariaControls: (listener) =>\n listener?.elementNode\n ? floatingPanelId(\"popover\", listener.elementNode)\n : undefined,\n onMouseEnter: (_e, node) => openOn === \"hover\" && show(node),\n onMouseLeave: (_e, node) => openOn === \"hover\" && hide(node),\n onClick: (_e, node) => {\n if (openOn === \"click\") {\n if (openState.get()) {\n hide(node);\n } else {\n show(node);\n }\n }\n },\n onKeyDown: (e, node) => {\n if ((e as KeyboardEvent).key === \"Escape\" && openState.get()) hide(node);\n },\n onFocus: (_e, node) => openOn === \"hover\" && show(node),\n onBlur: (e, node) => {\n // Docs: focus has no effect when openOn is click — only hover-mode\n // blur dismisses (and even then, not when focus moved INTO the panel).\n if (openOn !== \"hover\") return;\n const related = (e as FocusEvent).relatedTarget as Node | null;\n const root = node.getRoot().domElement as Element;\n // Tabbing from the trigger INTO the panel must not close the popover.\n // The id is deterministic and selector-safe ([a-z0-9-] only — nodeId is\n // a letter + hex hash), so this lookup works for every generation —\n // the old factory-scope `popoverId` was null in any generation whose\n // content _onInsert had never run, letting the guard fall through.\n const floatingEl = root.querySelector(\n `#${floatingPanelId(\"popover\", node)}`,\n );\n if (related && floatingEl?.contains(related)) return;\n hide(node);\n },\n };\n merge(anchorPartial, triggerPartial);\n\n return anchorPartial;\n}\n\nexport { popover };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport type { Placement } from \"@domphy/floating\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * Renders a small rotated arrow (via a `::after` pseudo-element) that points from a\n * popover/tooltip toward its anchor, positioned and oriented based on the floating placement.\n * The arrow direction is computed by flipping the given placement. No host-tag check is\n * performed; apply it to the popover container element.\n *\n * @param props.placement - Floating placement the popover sits at; the arrow is drawn on the\n * opposite (flipped) side. Accepts a value or reactive state. Defaults to `\"bottom-end\"`.\n * One of: `top` | `bottom` | `left` | `right` | `top-start` | `top-end` | `bottom-start` |\n * `bottom-end` | `left-start` | `left-end` | `right-start` | `right-end`.\n * @param props.sideOffset - CSS length used to offset the arrow toward the start/end edge.\n * Defaults to `themeSpacing(6)`.\n * @param props.color - Theme color tone for the arrow fill and border. Defaults to `\"neutral\"`.\n * @param props.bordered - Whether the arrow draws a 1px border (set to `0px` when false).\n * Defaults to `true`.\n * @example { div: [...], $: [popoverArrow({ placement: \"top\" })] }\n */\nfunction popoverArrow(\n props: {\n placement?: ValueOrState<Placement>;\n sideOffset?: string;\n color?: ThemeColor;\n bordered?: boolean;\n } = {},\n): PartialElement {\n const {\n placement = \"bottom-end\",\n color = \"neutral\",\n sideOffset = themeSpacing(6),\n bordered = true,\n } = props;\n\n const place = toState(placement);\n\n const flipMap: Record<Placement, Placement> = {\n top: \"bottom\",\n bottom: \"top\",\n left: \"right\",\n right: \"left\",\n \"top-start\": \"bottom-end\",\n \"top-end\": \"bottom-start\",\n \"bottom-start\": \"top-end\",\n \"bottom-end\": \"top-start\",\n \"left-start\": \"right-end\",\n \"left-end\": \"right-start\",\n \"right-start\": \"left-end\",\n \"right-end\": \"left-start\",\n };\n\n const getFlipped = (listener: any) =>\n flipMap[place.get(listener)] ?? flipMap[\"bottom-end\"];\n const start = (pos: string) =>\n pos.includes(\"start\") ? sideOffset : pos.includes(\"end\") ? \"auto\" : \"50%\";\n const end = (pos: string) =>\n pos.includes(\"end\") ? sideOffset : pos.includes(\"start\") ? \"auto\" : \"50%\";\n\n return {\n style: {\n fontSize: (listener) => themeSize(listener),\n backgroundColor: (listener) => themeColor(listener),\n color: (listener) => themeColor(listener, \"text\", color),\n position: \"relative\",\n \"&::after\": {\n content: `\"\"`,\n position: \"absolute\",\n width: themeSpacing(1.5),\n height: themeSpacing(1.5),\n backgroundColor: (listener) => themeColor(listener, \"inherit\", color),\n borderWidth: bordered ? \"1px\" : 0,\n borderColor: (listener) => themeColor(listener, \"border-strong\", color),\n borderTopStyle: (listener) => {\n const pos = getFlipped(listener);\n\n return pos.includes(\"top\") || pos.includes(\"right\")\n ? `solid`\n : \"none\";\n },\n borderBottomStyle: (listener) => {\n const pos = getFlipped(listener);\n\n return pos.includes(\"bottom\") || pos.includes(\"left\")\n ? `solid`\n : \"none\";\n },\n borderLeftStyle: (listener) => {\n const pos = getFlipped(listener);\n return pos.includes(\"top\") || pos.includes(\"left\") ? `solid` : \"none\";\n },\n borderRightStyle: (listener) => {\n const pos = getFlipped(listener);\n return pos.includes(\"bottom\") || pos.includes(\"right\")\n ? `solid`\n : \"none\";\n },\n top: (listener) => {\n const pos = getFlipped(listener);\n return pos.includes(\"top\")\n ? 0\n : pos.includes(\"bottom\")\n ? \"auto\"\n : start(pos);\n },\n right: (listener) => {\n const pos = getFlipped(listener);\n return pos.includes(\"right\")\n ? 0\n : pos.includes(\"left\")\n ? \"auto\"\n : end(pos);\n },\n bottom: (listener) => {\n const pos = getFlipped(listener);\n return pos.includes(\"bottom\")\n ? 0\n : pos.includes(\"top\")\n ? \"auto\"\n : end(pos);\n },\n left: (listener) => {\n const pos = getFlipped(listener);\n return pos.includes(\"left\")\n ? 0\n : pos.includes(\"right\")\n ? \"auto\"\n : start(pos);\n },\n transform: (listener) => {\n const pos = getFlipped(listener);\n const x =\n pos.includes(\"right\") ||\n (pos.includes(\"end\") && !pos.includes(\"left\"))\n ? \"50%\"\n : \"-50%\";\n const y =\n pos.includes(\"bottom\") ||\n (pos.includes(\"end\") && !pos.includes(\"top\"))\n ? \"50%\"\n : \"-50%\";\n return `translate(${x},${y}) rotate(45deg)`;\n },\n },\n },\n };\n}\n\nexport { popoverArrow };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeFont,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * Styles a preformatted text block: inherited font size, the theme's monospace\n * stack, themed foreground/background,\n * no border, density-scaled padding and rounded corners.\n *\n * @hostTag pre\n * @param props.color - Theme color tone for text and background. Accepts a value or reactive\n * state. Defaults to `\"neutral\"`.\n * @example { pre: \"const x = 1\", $: [preformated()] }\n */\nfunction preformated(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n dataTone: \"shift-2\",\n _onInsert: (node) => {\n if (node.tagName !== \"pre\") {\n console.warn(`\"preformated\" primitive patch must use pre tag`);\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n // The theme owns the code stack; <code>/<kbd>/<pre> otherwise keep the\n // UA generic \"monospace\" (Courier New on Windows), so a theme that swaps\n // fontFamilies.monospace never reaches them.\n fontFamily: themeFont(\"monospace\"),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n border: \"none\",\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 2),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 3),\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 2),\n },\n };\n}\n\nexport { preformated };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport { type ThemeColor, themeColor, themeSpacing } from \"@domphy/theme\";\n\n/**\n * Styles a native progress bar: full-width, pill-shaped track with a themed fill,\n * including the WebKit progress-bar/value pseudo-elements and a width transition.\n *\n * @hostTag progress\n * @param props.color - Theme color tone for the track/background. Accepts a value or reactive\n * state. Defaults to `\"neutral\"`.\n * @param props.accentColor - Theme color tone for the filled value. Accepts a value or reactive\n * state. Defaults to `\"primary\"`.\n * @example { progress: null, value: 40, max: 100, $: [progress()] }\n */\nfunction progress(\n props: {\n color?: ValueOrState<ThemeColor>;\n accentColor?: ValueOrState<ThemeColor>;\n } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n const accentColor = toState(props.accentColor ?? \"primary\", \"accentColor\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"progress\") {\n console.warn(`\"progress\" primitive patch must use progress tag`);\n }\n },\n // Track surface — shift via dataTone, paint with inherit.\n dataTone: \"shift-3\",\n style: {\n appearance: \"none\",\n width: \"100%\",\n height: themeSpacing(2),\n border: 0,\n borderRadius: themeSpacing(999),\n overflow: \"hidden\",\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n \"&::-webkit-progress-bar\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n borderRadius: themeSpacing(999),\n },\n \"&::-webkit-progress-value\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-9\", accentColor.get(listener)),\n borderRadius: themeSpacing(999),\n transition: \"width 220ms ease\",\n },\n },\n };\n}\n\nexport { progress };\n","import {\n behavior,\n type DomphyElement,\n type ElementNode,\n isState,\n type Listener,\n type PartialElement,\n rawHtml,\n type State,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { horizontalArrowStep } from \"../utils/direction.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\nconst STAR_FILLED =\n `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\" width=\"1em\" height=\"1em\">` +\n `<path d=\"M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z\"/>` +\n `</svg>`;\nconst STAR_EMPTY =\n `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\" width=\"1em\" height=\"1em\">` +\n `<path d=\"M22 9.24l-7.19-.62L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21 12 17.27 18.18 21l-1.63-7.03L22 9.24zM12 15.4l-3.76 2.27 1-4.28-3.32-2.88 4.38-.38L12 6.1l1.71 4.04 4.38.38-3.32 2.88 1 4.28L12 15.4z\"/>` +\n `</svg>`;\n\ntype RatingProps = {\n value?: ValueOrState<number>;\n max?: number;\n onChange?: (value: number) => void;\n readOnly?: boolean;\n color?: ThemeColor;\n};\n\ntype RatingLive = {\n valueState: State<number>;\n onChange?: (value: number) => void;\n readOnly: boolean;\n max: number;\n color: ThemeColor;\n};\n\nfunction applyRatingProps(live: RatingLive, next: RatingProps): void {\n live.onChange = next.onChange;\n live.readOnly = next.readOnly ?? false;\n live.max = next.max ?? 5;\n live.color = next.color ?? \"warning\";\n if (isState(next.value)) {\n if (next.value !== live.valueState) {\n live.valueState.set(next.value.get());\n }\n } else if (next.value !== undefined) {\n // Plain number stays live. Omitted value leaves the internal state\n // alone so an uncontrolled click is not reset on a later factory call.\n live.valueState.set(next.value);\n }\n}\n\nfunction insertStar(\n node: ElementNode,\n index: number,\n live: RatingLive,\n hoveredState: State<number>,\n): void {\n const activeCount = (listener: Listener) => {\n const hovered = hoveredState.get(listener);\n return hovered > 0 ? hovered : live.valueState.get(listener);\n };\n\n const star: DomphyElement<\"button\"> = {\n button: (listener) =>\n rawHtml(index <= activeCount(listener) ? STAR_FILLED : STAR_EMPTY),\n _key: index,\n type: \"button\",\n ariaLabel: `${index} star${index > 1 ? \"s\" : \"\"}`,\n // WAI-ARIA APG radio group: the stars ARE the radios. Without a role and\n // aria-checked a screen reader read five identically-shaped buttons and\n // could not tell which rating was chosen, and Tab stopped on every star\n // instead of entering the group once (roving tabindex).\n role: \"radio\",\n ariaChecked: (listener: Listener) =>\n live.valueState.get(listener) === index,\n tabindex: (listener: Listener) => {\n const current = live.valueState.get(listener);\n return (current === 0 ? 1 : current) === index ? 0 : -1;\n },\n onClick: () => {\n if (live.readOnly) return;\n const next = index === live.valueState.get() ? 0 : index;\n live.valueState.set(next);\n live.onChange?.(next);\n hoveredState.set(0);\n },\n onMouseEnter: () => {\n if (live.readOnly) return;\n hoveredState.set(index);\n },\n onMouseLeave: () => hoveredState.set(0),\n onKeyDown: (e: KeyboardEvent) => {\n if (live.readOnly) return;\n const current = live.valueState.get();\n let next = current;\n if (e.key === \"ArrowUp\") {\n next = Math.min(live.max, current + 1);\n e.preventDefault();\n } else if (e.key === \"ArrowDown\") {\n next = Math.max(0, current - 1);\n e.preventDefault();\n } else if (e.key === \"ArrowRight\" || e.key === \"ArrowLeft\") {\n const step = horizontalArrowStep(e.key, e.target as Element);\n next =\n step > 0 ? Math.min(live.max, current + 1) : Math.max(0, current - 1);\n e.preventDefault();\n } else if (e.key === \"Home\") {\n next = 1;\n e.preventDefault();\n } else if (e.key === \"End\") {\n next = live.max;\n e.preventDefault();\n } else {\n return;\n }\n live.valueState.set(next);\n live.onChange?.(next);\n const target = next > 0 ? next - 1 : 0;\n (node.domElement?.children[target] as HTMLElement)?.focus();\n },\n style: {\n background: \"none\",\n border: \"none\",\n outline: \"none\",\n borderRadius: themeSpacing(1),\n padding: 0,\n cursor: \"inherit\",\n color: \"inherit\",\n fontSize: \"inherit\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n // WCAG 2.2 SC 2.5.8 Target Size (Minimum) is 24x24 CSS px. The glyph is\n // 1em, so an unpadded star measured 16x16 — a miss on touch.\n minWidth: themeSpacing(6),\n minHeight: themeSpacing(6),\n transition: \"box-shadow 140ms ease\",\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, live.color),\n },\n },\n };\n node.children.insert(star);\n}\n\nfunction syncStars(\n node: ElementNode,\n live: RatingLive,\n hoveredState: State<number>,\n): void {\n const children = node.children.items;\n while (children.length > live.max) {\n node.children.remove(children[children.length - 1]);\n }\n for (let index = children.length + 1; index <= live.max; index++) {\n insertStar(node, index, live, hoveredState);\n }\n}\n\n/**\n * Interactive star rating applied to a container `<div>`. Manages its own star\n * children: click to set, Arrow keys to adjust, hover to preview. In `readOnly`\n * mode stars are non-interactive. Apply to a `<div>` element.\n *\n * Star insert runs in `_onInit` (SSR markup). `onChange`/`readOnly`/`max` and\n * a plain-number `value` stay live via `behavior()` `update()` so a reused\n * node picks up the latest factory props.\n *\n * @hostTag div\n * @param props.value - Current rating (0 – max). `ValueOrState<number>`, defaults to `0`.\n * @param props.max - Total number of stars. Optional `number`, defaults to `5`.\n * @param props.onChange - Called with the new value when the user picks a star.\n * @param props.readOnly - Disable interaction. Optional `boolean`, defaults to `false`.\n * @param props.color - Star color tone. Optional `ThemeColor`, defaults to `\"warning\"`.\n * @example { div: null, $: [rating({ value: ratingState, onChange: (v) => ratingState.set(v) })] }\n */\nfunction rating(props: RatingProps = {}): PartialElement {\n const live: RatingLive = {\n valueState: toState(props.value ?? 0),\n onChange: props.onChange,\n readOnly: props.readOnly ?? false,\n max: props.max ?? 5,\n color: props.color ?? \"warning\",\n };\n const hoveredState = toState(0);\n\n return {\n role: \"radiogroup\",\n ariaLabel: \"Rating\",\n ariaReadonly: live.readOnly ? \"true\" : undefined,\n style: {\n display: \"inline-flex\",\n gap: themeSpacing(0.5),\n // 1.5× inherited control size (theme-owned type scale, not a px/rem literal).\n fontSize: (listener) => themeSize(listener, \"increase-1\"),\n cursor: live.readOnly ? \"default\" : \"pointer\",\n color: (listener) => themeColor(listener, \"muted\", live.color),\n },\n ...behavior<RatingProps>(\n \"rating\",\n (node, initial) => {\n applyRatingProps(live, initial);\n syncStars(node, live, hoveredState);\n return {\n update(next) {\n applyRatingProps(live, next);\n syncStars(node, live, hoveredState);\n },\n };\n },\n {\n value: props.value,\n max: props.max ?? 5,\n onChange: props.onChange,\n readOnly: props.readOnly ?? false,\n color: props.color ?? \"warning\",\n },\n ),\n // Build stars as real child elements (not imperative DOM mutation in\n // _onMount) so generateHTML()/SSR emits the actual star markup.\n _onInit: (node) => {\n syncStars(node, live, hoveredState);\n },\n };\n}\n\nexport { rating };\n","/**\n * True when the element resolves to right-to-left text direction (inherited\n * `dir` attribute or `direction` CSS). Same technique @domphy/floating's\n * vendored floating-ui platform uses internally for RTL-aware placement\n * (packages/floating/src/dom/platform/isRTL.ts) — reading the resolved CSS\n * `direction` picks up an ancestor `dir` attribute without walking the tree.\n */\nfunction isRTL(element: Element | null | undefined): boolean {\n if (!element || typeof getComputedStyle !== \"function\") return false;\n return getComputedStyle(element).direction === \"rtl\";\n}\n\n/**\n * Maps a horizontal arrow key to a directional step (+1 toward the end of\n * the list, -1 toward the start), mirrored when the element resolves to RTL.\n * ArrowUp/ArrowDown and Home/End are direction-agnostic and are not covered\n * here — callers keep handling those directly.\n */\nfunction horizontalArrowStep(\n key: string,\n element: Element | null | undefined,\n): 1 | -1 | 0 {\n if (key !== \"ArrowRight\" && key !== \"ArrowLeft\") return 0;\n const forward = key === \"ArrowRight\";\n return forward !== isRTL(element) ? 1 : -1;\n}\n\nexport { horizontalArrowStep, isRTL };\n","import type { PartialElement, StyleObject } from \"@domphy/core\";\nimport { toState, type ValueOrState } from \"@domphy/core\";\nimport { type ThemeColor, themeColor, themeSpacing } from \"@domphy/theme\";\n\n/**\n * Circular ring progress indicator rendered via CSS `conic-gradient` and a\n * circular `mask`. Progress starts at 12 o'clock and advances clockwise.\n * Exposes `role=\"progressbar\"` with `aria-valuenow/min/max`. Apply to a `<div>`.\n *\n * @hostTag div\n * @param props.value - Progress percentage 0–100. Accepts a value or reactive state. Defaults to `0`.\n * @param props.color - Theme color for the filled arc. Accepts a value or reactive state. Defaults to `\"primary\"`.\n * @param props.trackColor - Theme color for the background track. Accepts a value or reactive state. Defaults to `\"neutral\"`.\n * @param props.size - Diameter in `themeSpacing` units. Defaults to `16` (= `4em`).\n * @param props.thickness - Ring stroke as a fraction of the radius (0–0.5). Defaults to `0.25`.\n * @example { div: null, $: [ringProgress({ value: 65 })] }\n * @example { div: null, $: [ringProgress({ value: loadingState, color: \"success\", size: 20 })] }\n */\nfunction ringProgress(\n props: {\n value?: ValueOrState<number>;\n color?: ValueOrState<ThemeColor>;\n trackColor?: ValueOrState<ThemeColor>;\n size?: number;\n thickness?: number;\n } = {},\n): PartialElement {\n const { size = 16, thickness = 0.25 } = props;\n const value = toState(props.value ?? 0, \"value\");\n const color = toState(props.color ?? \"primary\", \"color\");\n const trackColor = toState(props.trackColor ?? \"neutral\", \"trackColor\");\n\n // Mask cuts the center to create a donut shape.\n // Uses `closest-side` so the gradient circle matches the visible element circle\n // exactly, making `holePercent` directly represent the fraction of outer radius.\n const holePercent = Math.round((1 - thickness) * 100);\n const mask = `radial-gradient(circle closest-side, transparent ${holePercent}%, black ${holePercent}%)`;\n\n return {\n role: \"progressbar\",\n ariaValuenow: (l) => String(Math.round(value.get(l))),\n ariaValuemin: \"0\",\n ariaValuemax: \"100\",\n _onInsert: (node) => {\n if (node.tagName !== \"div\") {\n console.warn('\"ringProgress\" patch must use div tag');\n }\n },\n style: {\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: themeSpacing(size),\n height: themeSpacing(size),\n borderRadius: \"50%\",\n // Text color tracks the filled arc so any overlay label inherits it.\n color: (l) => themeColor(l, \"shift-9\", color.get(l)),\n // Fill arc from 12 o'clock clockwise; `from -90deg` rotates the start point.\n background: (l) =>\n `conic-gradient(from -90deg, ${themeColor(l, \"shift-9\", color.get(l))} ${value.get(l)}%, ${themeColor(l, \"shift-3\", trackColor.get(l))} 0%)`,\n WebkitMask: mask,\n mask,\n } as StyleObject,\n };\n}\n\nexport { ringProgress };\n","import type { PartialElement } from \"@domphy/core\";\nimport { themeDensity, themeSpacing } from \"@domphy/theme\";\nimport type { FlexAlign, FlexJustify } from \"./stack.js\";\n\n/**\n * A horizontal flex row with spacing between children, vertically centered by\n * default. The general-purpose primitive for icon+label rows, field rows,\n * and button groups — instead of hand-rolling `display: flex; alignItems:\n * center; gap: ...`. `toolbar()` is a semantic alias of this same shape for\n * headers/nav bars. Styles the host only; apply to any block element.\n *\n * @param props.gap - Spacing multiplier for gap between items (default 4).\n * Bounded-control mode (`density: true`, default): `themeSpacing(themeDensity(l) * gap)`\n * — at default density 1.5, gap 4 = 1.5em.\n * Structural/page-column mode (`density: false`): bare `themeSpacing(gap)` with no\n * density multiply — gap 4 = 1em, matching AGENTS.md \"bare themeSpacing(n)\".\n * @param props.align - Cross-axis alignment (`alignItems`). Defaults to `\"center\"`.\n * @param props.justify - Main-axis distribution (`justifyContent`). Unset by default (flex-start).\n * @param props.wrap - Allow items to wrap onto multiple lines. Defaults to `false`.\n * @param props.density - When true (default), gap is multiplied by theme density\n * (bounded controls). When false, gap is structural `themeSpacing(n)` — use this\n * for page/form columns.\n * @example { div: [{ span: \"Icon\" }, { span: \"Label\" }], $: [row()] }\n * @example { div: [...], $: [row({ justify: \"space-between\", wrap: true })] }\n * @example { div: [...], $: [row({ gap: 4, density: false })] }\n */\nfunction row(\n props: {\n gap?: number;\n align?: FlexAlign;\n justify?: FlexJustify;\n wrap?: boolean;\n density?: boolean;\n } = {},\n): PartialElement {\n const {\n gap = 4,\n align = \"center\",\n justify,\n wrap = false,\n density = true,\n } = props;\n return {\n style: {\n display: \"flex\",\n alignItems: align,\n gap: density\n ? (listener) => themeSpacing(themeDensity(listener) * gap)\n : () => themeSpacing(gap),\n ...(justify ? { justifyContent: justify } : {}),\n ...(wrap ? { flexWrap: \"wrap\" } : {}),\n },\n };\n}\n\nexport { row };\nexport type { FlexJustify };\n","import type { PartialElement, StyleObject } from \"@domphy/core\";\nimport { toState, type ValueOrState } from \"@domphy/core\";\nimport { type ThemeColor, themeColor, themeSpacing } from \"@domphy/theme\";\n\n/**\n * Applies thin, themed overlay scrollbars to any scrollable container.\n * Covers WebKit (Chrome/Safari/Edge) via `::-webkit-scrollbar` pseudo-elements\n * and Firefox via `scrollbar-width`/`scrollbar-color`. Sets `overflow: auto`.\n * No host-tag check; apply to any block element.\n *\n * Pass `label` when the scrollable content is NOT itself keyboard-reachable —\n * a wide table, a code block, a diagram. Such a region can only be scrolled\n * with a pointer, which fails WCAG 2.1.1 (axe `scrollable-region-focusable`),\n * so `label` makes the host a named, tabbable region: `role=\"region\"` +\n * `aria-label` + `tabindex=\"0\"`, the wrapper pattern GOV.UK and shadcn use\n * around overflowing tables. Leave it off when the content already holds\n * focusable elements (a nav list, a form) — those are reachable by Tab\n * already, and a region tab stop in front of them is one keystroke of noise\n * per list.\n *\n * @param props.color - Theme color for the scrollbar thumb. Accepts a value or\n * reactive state. Defaults to `\"neutral\"`.\n * @param props.label - Accessible name for the scroll region. Setting it makes\n * the host a tabbable `role=\"region\"`. Optional; a host-declared\n * `role`/`ariaLabel`/`tabIndex` still wins (native over patch).\n * @example { div: [...], style: { maxHeight: \"300px\" }, $: [scrollArea()] }\n * @example { div: [wideTable], $: [scrollArea({ label: \"Quarterly revenue\" })] }\n */\nfunction scrollArea(\n props: { color?: ValueOrState<ThemeColor>; label?: string } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n // `role=\"region\"` with no accessible name is dropped from the\n // accessibility tree, and a tab stop with no name is a dead end — so the\n // three only ever ship together, or not at all.\n ...(props.label\n ? { role: \"region\", ariaLabel: props.label, tabIndex: 0 }\n : {}),\n style: {\n overflow: \"auto\",\n // Container text color so theme token usage also carries a reactive `color`.\n color: (l) => themeColor(l, \"text\", color.get(l)),\n \"&::-webkit-scrollbar\": {\n width: themeSpacing(2),\n height: themeSpacing(2),\n },\n \"&::-webkit-scrollbar-track\": {\n background: \"transparent\",\n },\n \"&::-webkit-scrollbar-thumb\": {\n backgroundColor: (l) => themeColor(l, \"shift-5\", color.get(l)),\n borderRadius: themeSpacing(999),\n // Transparent border creates visual padding around the thumb.\n border: `${themeSpacing(0.5)} solid transparent`,\n backgroundClip: \"content-box\",\n },\n \"&::-webkit-scrollbar-thumb:hover\": {\n backgroundColor: (l) => themeColor(l, \"shift-7\", color.get(l)),\n },\n // Firefox thin scrollbar with matching thumb/track colors.\n scrollbarWidth: \"thin\",\n scrollbarColor: (l) =>\n `${themeColor(l, \"shift-5\", color.get(l))} transparent`,\n } as StyleObject,\n };\n}\n\nexport { scrollArea };\n","import {\n behavior,\n type DomphyElement,\n type ElementNode,\n isState,\n type Listener,\n type PartialElement,\n type State,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport {\n type ThemeColor,\n textToneOn,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { horizontalArrowStep } from \"../utils/direction.js\";\nimport { elevation } from \"../utils/elevation.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/** One item inside a segmented control. */\ntype SegmentedItem = {\n /** Button label — plain string (auto-wrapped) or any DomphyElement. */\n label: string | DomphyElement;\n /** Stable key. Defaults to the item's zero-based index. */\n key?: string;\n};\n\ntype SegmentedLive = {\n items: SegmentedItem[];\n color: ThemeColor;\n accentColor: ThemeColor;\n};\n\nfunction persistValue<T>(\n node: ElementNode,\n key: string,\n incoming: ValueOrState<T> | undefined,\n fallback: T,\n): State<T> {\n if (isState(incoming)) {\n node.setMetadata(key, incoming);\n return incoming as State<T>;\n }\n let stored = node.getMetadata(key) as State<T> | undefined;\n if (!stored) {\n stored = toState((incoming as T | undefined) ?? fallback);\n node.setMetadata(key, stored);\n }\n return stored;\n}\n\nfunction moveSegment(\n e: Event,\n items: SegmentedItem[],\n key: string,\n value: State<string>,\n): void {\n const k = (e as KeyboardEvent).key;\n // WAI-ARIA APG radio group: both axes navigate (Right/Down = next,\n // Left/Up = previous), Home/End jump to the ends.\n if (\n ![\n \"ArrowLeft\",\n \"ArrowRight\",\n \"ArrowUp\",\n \"ArrowDown\",\n \"Home\",\n \"End\",\n ].includes(k)\n )\n return;\n e.preventDefault();\n const keys = items.map((item, index) => item.key ?? String(index));\n const idx = keys.indexOf(key);\n let next = idx;\n if (k === \"ArrowDown\") next = (idx + 1) % keys.length;\n else if (k === \"ArrowUp\") next = (idx - 1 + keys.length) % keys.length;\n else if (k === \"ArrowRight\" || k === \"ArrowLeft\") {\n const step = horizontalArrowStep(k, e.target as Element);\n next = (idx + step + keys.length) % keys.length;\n } else if (k === \"Home\") next = 0;\n else if (k === \"End\") next = keys.length - 1;\n value.set(keys[next]);\n const group = (e.target as HTMLElement).closest(\"[role=radiogroup]\");\n group?.querySelectorAll<HTMLElement>(\"[role=radio]\")[next]?.focus();\n}\n\nfunction buildSegmentButtons(\n items: SegmentedItem[],\n value: State<string>,\n color: ThemeColor,\n accentColor: ThemeColor,\n): DomphyElement<\"button\">[] {\n return items.map((item, index) => {\n const key = item.key ?? String(index);\n const labelEl: DomphyElement =\n typeof item.label === \"string\"\n ? ({ span: item.label } as DomphyElement<\"span\">)\n : item.label;\n\n return {\n button: [labelEl],\n _key: key,\n type: \"button\",\n role: \"radio\",\n ariaChecked: (l: Listener) => value.get(l) === key,\n tabIndex: (l: Listener) => {\n const current = value.get(l);\n if (current === key) return 0;\n if (current === \"\" && key === (items[0]?.key ?? \"\")) return 0;\n return -1;\n },\n onClick: () => value.set(key),\n onKeyDown: (e: Event) => moveSegment(e, items, key, value),\n style: {\n cursor: \"pointer\",\n fontSize: (l: Listener) => themeSize(l, \"inherit\"),\n // Fixed height, label centred by flex: with a fixed height and block\n // padding the inherited line box overflowed the content box downward\n // whenever the host font was larger than the base size.\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: themeSpacing(6),\n paddingBlock: 0,\n paddingInline: themeSpacing(3),\n border: \"none\",\n borderRadius: themeSpacing(10),\n color: (l: Listener) => themeColor(l, \"text\", color),\n backgroundColor: \"transparent\",\n transition:\n \"background-color 140ms ease, color 140ms ease, box-shadow 140ms ease\",\n // Labels track their fill (+3 hover, +2 press) off the track's own\n // shift-2 anchor: the resting \"text\" tone measured 3.20:1 on the hover\n // fill and 3.78:1 on the pressed fill (light), below WCAG AA.\n \"&:hover:not([disabled]):not([aria-checked=true])\": {\n backgroundColor: (l: Listener) => themeColor(l, \"shift-3\", color),\n color: (l: Listener) => themeColor(l, textToneOn(3), color),\n },\n \"&:active:not([disabled]):not([aria-checked=true])\": {\n backgroundColor: (l: Listener) => themeColor(l, \"increase-2\", color),\n color: (l: Listener) => themeColor(l, textToneOn(3), color),\n },\n \"&[aria-checked=true]\": {\n backgroundColor: (l: Listener) =>\n themeColor(l, \"shift-0\", accentColor),\n color: (l: Listener) => themeColor(l, \"shift-10\", accentColor),\n // Selected segment sits slightly above the track.\n boxShadow: elevation(\"low\"),\n },\n \"&:focus-visible\": {\n boxShadow: (l: Listener) => focusRing(l, accentColor),\n },\n \"&[aria-checked=true]:focus-visible\": {\n boxShadow: (l: Listener) =>\n `${elevation(\"low\")}, ${focusRing(l, accentColor)}`,\n },\n \"&[disabled]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n },\n },\n } as DomphyElement<\"button\">;\n });\n}\n\n/**\n * All-in-one single-select segmented control. Generates `<button>` option\n * elements from the `items` array. Apply to any wrapper element.\n *\n * @param props.items - Item definitions `{ label, key? }`.\n * @param props.value - Initially selected key (value or State). Defaults to the first item's key.\n * @param props.color - Theme color for the control background. Defaults to `\"neutral\"`.\n * @param props.accentColor - Theme color for the selected item. Defaults to `\"primary\"`.\n * @example\n * { div: null, $: [segmented({ items: [\n * { label: \"Day\", key: \"day\" },\n * { label: \"Month\", key: \"month\" },\n * { label: \"Year\", key: \"year\" },\n * ] })] }\n */\nfunction segmented(\n props: {\n items: SegmentedItem[];\n value?: ValueOrState<string>;\n color?: ThemeColor;\n accentColor?: ThemeColor;\n } = { items: [] },\n): PartialElement {\n const { items = [], color = \"neutral\", accentColor = \"primary\" } = props;\n const live: SegmentedLive = { items, color, accentColor };\n\n return {\n role: \"radiogroup\",\n _onSchedule: (node, element) => {\n const value = persistValue(\n node,\n \"segmentedValue\",\n props.value,\n items[0]?.key ?? \"\",\n );\n // Publish the SAME state the buttons write to. A declared `_context`\n // could not: the partial is node-agnostic, so it had to allocate its\n // own `toState()` that never saw a click — and because ElementNode.patch\n // re-merges `element._context` on every re-render, merging one State\n // instance into another also clobbered the live notifier's listeners.\n node.setContext(\"segmented\", { value });\n (element as Record<string, unknown>)[node.tagName] = buildSegmentButtons(\n items,\n value,\n color,\n accentColor,\n );\n },\n ...behavior<SegmentedLive>(\n \"segmented-items\",\n (node) => ({\n update(snapshot) {\n const value = persistValue(\n node,\n \"segmentedValue\",\n props.value,\n snapshot.items[0]?.key ?? \"\",\n );\n node.children.update(\n buildSegmentButtons(\n snapshot.items,\n value,\n snapshot.color,\n snapshot.accentColor,\n ),\n !!node.domElement,\n true,\n );\n },\n }),\n live,\n ),\n // Track is a soft surface anchor — shift via dataTone, paint with inherit.\n dataTone: \"shift-2\",\n style: {\n display: \"inline-flex\",\n paddingBlock: themeSpacing(1),\n paddingInline: themeSpacing(1),\n gap: themeSpacing(0.5),\n borderRadius: themeSpacing(10),\n backgroundColor: (l: Listener) => themeColor(l, \"inherit\", color),\n color: (l: Listener) => themeColor(l, \"text\", color),\n },\n };\n}\n\nexport { segmented };\nexport type { SegmentedItem };\n","import type { Listener, PartialElement } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeColorToken,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { isRTL } from \"../utils/direction.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * Styles a native `<select>` control: removes the default appearance, applies themed\n * colors, outline, density-scaled padding/radius, a custom chevron background icon, and\n * hover/focus/disabled/optgroup/option states.\n *\n * @hostTag select\n * @param props.color - Theme color tone for text, background and outline. Defaults to `\"neutral\"`.\n * @param props.accentColor - Theme color tone for hover/focus outlines. Defaults to `\"primary\"`.\n * @example { select: [{ option: \"A\" }], $: [select()] }\n */\nfunction select(\n props: { color?: ThemeColor; accentColor?: ThemeColor } = {},\n): PartialElement {\n const { color = \"neutral\", accentColor = \"primary\" } = props;\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"select\") {\n console.warn(`\"select\" primitive patch must use select tag`);\n }\n },\n style: {\n appearance: \"none\",\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n lineHeight: \"inherit\",\n color: (listener) => themeColor(listener, \"text\", color),\n backgroundColor: (listener) => themeColor(listener, \"inherit\", color),\n border: \"none\",\n outlineOffset: \"-1px\",\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", color)}`,\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 1),\n paddingInlineStart: (listener) =>\n themeSpacing(themeDensity(listener) * 3),\n paddingInlineEnd: (listener) => themeSpacing(themeDensity(listener) * 5),\n backgroundImage: (l: Listener) => {\n const svg = `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 10 6\"><path d=\"M1 1l4 4 4-4\" stroke=\"${themeColorToken(l, \"shift-7\")}\" stroke-width=\"1.5\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>`;\n return `url(\"data:image/svg+xml,${encodeURIComponent(svg)}\")`;\n },\n backgroundRepeat: \"no-repeat\",\n // background-position has no logical (\"inline-end\") keyword support in\n // Chrome 88-class embedded browsers, so the physical side is picked at\n // paint time from the resolved CSS `direction` (same technique\n // @domphy/floating's platform.isRTL uses) instead of a fixed \"right\".\n backgroundPosition: (l: Listener) =>\n `${isRTL(l.elementNode?.domElement) ? \"left\" : \"right\"} ${themeSpacing(2)} center`,\n backgroundSize: `${themeSpacing(2.5)} ${themeSpacing(1.5)}`,\n transition: \"outline-color 140ms ease, box-shadow 140ms ease\",\n \"&:not([multiple])\": {\n height: (listener) => themeSpacing(6 + themeDensity(listener) * 2),\n },\n \"&:hover:not([disabled]):not([aria-busy=true])\": {\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"shift-5\", accentColor)}`,\n },\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, accentColor),\n },\n \"& optgroup\": {\n color: (listener) => themeColor(listener, \"shift-11\", color),\n },\n \"& option[disabled]\": {\n color: (listener) => themeColor(listener, \"shift-7\", \"neutral\"),\n },\n \"&[disabled]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n color: (listener) => themeColor(listener, \"muted\", \"neutral\"),\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", \"neutral\")}`,\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-2\", \"neutral\"),\n },\n },\n };\n}\n\nexport { select };\n","import {\n type BehaviorInstance,\n behavior,\n type DomphyElement,\n type ElementNode,\n merge,\n type PartialElement,\n type State,\n type StyleObject,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport type { Placement } from \"@domphy/floating\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { elevation } from \"../utils/elevation.js\";\nimport { createFloating, floatingPanelId } from \"../utils/floating.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\nimport { subscribeOpen } from \"../utils/openState.js\";\nimport { enabledOptionsIn } from \"../utils/optionList.js\";\nimport { tag } from \"./tag.js\";\n\n// Typeahead (Radix Select character-search parity): printable characters\n// accumulate into a buffer that resets after 1s of idle; the buffer is a\n// case-insensitive prefix match against option labels. CLOSED trigger: the\n// match becomes the selection (native <select> behavior). OPEN panel: focus\n// moves to the matching [role=option] — focus is the keyboard highlight.\n// A buffer of one repeated character (\"aaa\") cycles through that char's\n// matches instead of pinning the first; disabled options are skipped.\nconst TYPEAHEAD_RESET_MS = 1000;\n\ntype TypeaheadMeta = {\n buffer: string;\n timer: ReturnType<typeof setTimeout> | null;\n};\n\n// The buffer lives on the NODE (not the factory closure): a selectBox inside\n// a reactive parent gets a fresh closure per ancestor re-render, and a\n// closure-local buffer would silently reset mid-typing on the reused node.\nfunction resolveTypeahead(node: ElementNode): TypeaheadMeta {\n let meta = node.getMetadata(\"selectBoxTypeahead\") as\n | TypeaheadMeta\n | undefined;\n if (!meta) {\n meta = { buffer: \"\", timer: null };\n node.setMetadata(\"selectBoxTypeahead\", meta);\n }\n return meta;\n}\n\nconst matchesPrefix = (label: string, needle: string) =>\n label.trim().toLowerCase().startsWith(needle);\n\n/**\n * A clickable select trigger box that renders the currently selected option(s) as removable\n * tags and toggles a floating popover (the dropdown content) anchored to itself. Selected\n * labels are derived from `options` matching the bound `value`; removing a tag updates the value.\n * Keyboard: Enter/Space toggle, ArrowDown/ArrowUp/Home/End open the listbox and move focus to\n * the first/last option (and move between options while open), Escape closes, and printable\n * characters typeahead-search options (closed: selects the match; open: focuses the matching\n * `[role=option]` in the panel; a repeated character cycles matches).\n *\n * @hostTag div\n * @param props.multiple - Whether multiple selection is allowed (renders removable tags and\n * keeps the popover open on click). Defaults to `false`.\n * @param props.value - Bound selection value(s). Accepts a value or reactive state of an array of\n * `number | string | null | undefined`, or a single `number | string | null | undefined`.\n * @param props.options - List of `{ label, value }` options used to resolve selected labels.\n * Defaults to `[]`.\n * @param props.placement - Floating placement of the dropdown popover. Accepts a value or\n * reactive state. Defaults to `\"bottom\"`.\n * @param props.content - Required. The popover/dropdown content element shown when open.\n * @param props.color - Theme color tone for the box text/background. Defaults to `\"neutral\"`.\n * @param props.open - Whether the popover is open. Accepts a value or reactive state (`ValueOrState<boolean>`, including `Computed`/`ReadableState`). Defaults to `false`. When the source is read-only, pass `onDismiss` so dismiss can close.\n * @param props.onDismiss - Called when the popover requests close. Optional. Required to close when `open` is a read-only `Computed`/`ReadableState`.\n * @example { div: null, $: [selectBox({ content: { div: [...] }, options: [{ label: \"A\", value: \"a\" }] })] }\n */\nfunction selectBox(props: {\n multiple?: boolean;\n value?: ValueOrState<\n | Array<number | string | null | undefined>\n | number\n | string\n | null\n | undefined\n >;\n options?: Array<{ label: string; value: string }>;\n placement?: ValueOrState<Placement>;\n content: DomphyElement;\n color?: ThemeColor;\n open?: ValueOrState<boolean>;\n onDismiss?: () => void;\n}): PartialElement {\n const {\n options = [],\n placement = \"bottom\",\n color = \"neutral\",\n open = false,\n multiple = false,\n } = props;\n\n const state = toState(props.value);\n const openState = toState(open);\n const { show, hide, anchorPartial } = createFloating({\n kind: \"selectBox\",\n open: openState,\n onDismiss: props.onDismiss,\n placement: toState(placement),\n content: props.content,\n });\n\n const popoverPartial: PartialElement = {\n onClick: (_e, node) => !multiple && hide(node),\n dataTone: \"shift-0\",\n style: {\n backgroundColor: (listener) => themeColor(listener, \"inherit\"),\n // Surface contract (dataTone-surface-contract): a tone-anchored panel\n // must declare BOTH background and text color. Page-matching shift-0\n // (same as menu/selectList/dialog), not the inverted tooltip surface.\n color: (listener) => themeColor(listener, \"text\"),\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 2),\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\")}`,\n outlineOffset: \"-1px\",\n boxShadow: elevation(\"medium\"),\n },\n };\n\n merge(props.content, popoverPartial);\n\n type InnerProps = {\n options: Array<{ label: string; value: string }>;\n multiple: boolean;\n color: ThemeColor;\n state: State<\n | Array<number | string | null | undefined>\n | number\n | string\n | null\n | undefined\n >;\n };\n\n const buildWrap = (inner: InnerProps): DomphyElement<\"div\"> => ({\n div: (listener) => {\n const val = inner.state.get(listener);\n const vals = Array.isArray(val) ? val : [val];\n const opts = inner.options.filter((opt) => vals.includes(opt.value));\n return opts.map((opt) => ({\n span: opt.label,\n $: [tag({ color: inner.color, removable: inner.multiple })],\n _key: opt.value,\n _onRemove: (_node: ElementNode) => {\n const cur = inner.state.get();\n const curVals = Array.isArray(cur) ? cur : [cur];\n const filter = curVals.filter((v) => v !== opt.value);\n inner.multiple\n ? inner.state.set(filter as any)\n : inner.state.set(filter[0] as any);\n },\n })) as DomphyElement<\"span\">[];\n },\n _key: \"selectBoxWrap\",\n style: {\n display: \"flex\",\n flexWrap: \"wrap\",\n gap: themeSpacing(1),\n flex: 1,\n } as StyleObject,\n });\n\n const attachInner = (\n node: ElementNode,\n _inner: InnerProps,\n ): BehaviorInstance<InnerProps> => {\n return {\n update(next) {\n node.children.update([buildWrap(next)]);\n },\n };\n };\n\n const toggle = (node?: ElementNode) =>\n openState.get() ? hide(node) : show(node);\n\n const panelOf = (node: ElementNode): Element | null => {\n const root = node.getRoot().domElement as Element | null;\n return (\n root?.querySelector(`#${floatingPanelId(\"selectBox\", node)}`) ?? null\n );\n };\n\n // WAI-ARIA APG \"Select-Only Combobox\": Down/Up/Home/End move focus into the\n // listbox. Measured in Chromium before this: with the panel open, every\n // arrow key was swallowed by the typeahead branch's `key.length === 1`\n // guard and focus never left the trigger, so the dropdown was reachable\n // only by mouse or by guessing an option's first letter. Once focus is on\n // an option, selectList's own listbox handler takes over.\n const moveIntoPanel = (node: ElementNode, toLast: boolean): void => {\n const options = enabledOptionsIn(panelOf(node));\n if (!options.length) return;\n const target = options[toLast ? options.length - 1 : 0]!;\n target.focus();\n target.scrollIntoView?.({ block: \"nearest\" });\n };\n\n // show() is debounced by 100ms and flips `openState` only AFTER mounting the\n // panel, so waiting on that flip is exact where a fixed delay is not. The\n // extra frame is required too: floating.ts drives the panel's `visibility`\n // from the same state and that style write has not landed when the listener\n // runs, so `focus()` would hit a `visibility: hidden` element and do nothing.\n const openThenMove = (node: ElementNode, toLast: boolean): void => {\n let release: (() => void) | undefined;\n release = subscribeOpen(\n openState,\n (isOpen) => {\n if (!isOpen) return;\n release?.();\n requestAnimationFrame(() => moveIntoPanel(node, toLast));\n },\n false,\n );\n show(node);\n };\n\n const typeahead = (key: string, node: ElementNode) => {\n const meta = resolveTypeahead(node);\n if (meta.timer) clearTimeout(meta.timer);\n meta.buffer += key.toLowerCase();\n meta.timer = setTimeout(() => {\n meta.buffer = \"\";\n }, TYPEAHEAD_RESET_MS);\n // \"aaa\" cycles through the a* matches rather than matching \"aaa\" literally.\n const repeated = meta.buffer.length > 1 && new Set(meta.buffer).size === 1;\n const needle = repeated ? meta.buffer[0]! : meta.buffer;\n\n if (openState.get()) {\n // Panel is portaled under the root (see floating.ts); its id is\n // deterministic, same lookup pattern as popover's onBlur guard.\n const matches = enabledOptionsIn(panelOf(node)).filter((el) =>\n matchesPrefix(el.textContent ?? \"\", needle),\n );\n if (!matches.length) return;\n const active = node.domElement?.ownerDocument\n ?.activeElement as HTMLElement | null;\n const from = repeated && active ? matches.indexOf(active) : -1;\n const target = matches[(from + 1) % matches.length]!;\n target.focus();\n target.scrollIntoView?.({ block: \"nearest\" });\n return;\n }\n\n // Closed trigger: selection follows typeahead. Single-select only — a\n // multi-select tag set has no \"current option\" to move from.\n if (multiple) return;\n const matches = options.filter((opt) => matchesPrefix(opt.label, needle));\n if (!matches.length) return;\n const from = repeated\n ? matches.findIndex((opt) => opt.value === state.get())\n : -1;\n const next = matches[(from + 1) % matches.length]!;\n state.set(next.value as any);\n };\n\n const partial: PartialElement = {\n _onInsert: (node) => {\n if (node.tagName !== \"div\") {\n console.warn(`\"selectBox\" patch must use div tag`);\n }\n },\n _onSchedule: (node, element) => {\n (element as Record<string, unknown>)[node.tagName] = [\n buildWrap({ options, multiple, color, state }),\n ];\n },\n ...behavior<InnerProps>(\"selectBoxInner\", attachInner, {\n options,\n multiple,\n color,\n state,\n }),\n onClick: (_e, node) => toggle(node),\n // Focusable trigger: click + Enter/Space/ArrowDown open.\n // Escape dismiss composes with createFloating's hide path.\n tabindex: 0,\n // WAI-ARIA APG \"Select-Only Combobox\": a non-editable div trigger that\n // owns a listbox is role=combobox, not role=button. role=button also makes\n // its subtree presentational, which broke the removable `tag()` buttons the\n // multi-select trigger renders (axe `nested-interactive`).\n role: \"combobox\",\n // role=combobox takes its name from the author only — never from its\n // content the way role=button did — so without a default every selectBox\n // failed axe `aria-input-field-name`. A host-declared aria-label/\n // aria-labelledby still wins (native over patch).\n ariaLabel: \"Select\",\n // Reactive boolean (same pattern as popover) — do NOT pin a static\n // ariaExpanded or patch re-apply will overwrite after keyboard open.\n ariaExpanded: (listener) => openState.get(listener),\n ariaHaspopup: \"listbox\",\n ariaControls: (listener) =>\n listener?.elementNode\n ? floatingPanelId(\"selectBox\", listener.elementNode)\n : undefined,\n onKeyDown: (e, node) => {\n const key = (e as KeyboardEvent).key;\n if (key === \"Escape\") {\n hide(node);\n return;\n }\n if (key === \"Enter\" || key === \" \") {\n e.preventDefault();\n toggle(node);\n return;\n }\n if (\n key === \"ArrowDown\" ||\n key === \"ArrowUp\" ||\n key === \"Home\" ||\n key === \"End\"\n ) {\n e.preventDefault();\n const toLast = key === \"ArrowUp\" || key === \"End\";\n openState.get()\n ? moveIntoPanel(node, toLast)\n : openThenMove(node, toLast);\n return;\n }\n // Character typeahead (Radix Select parity) — modifier chords are\n // shortcuts, not search input.\n const kb = e as KeyboardEvent;\n if (key.length === 1 && !kb.ctrlKey && !kb.metaKey && !kb.altKey) {\n typeahead(key, node);\n }\n },\n style: {\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n minHeight: (listener) => themeSpacing(6 + themeDensity(listener) * 2),\n minWidth: themeSpacing(32),\n outlineOffset: \"-1px\",\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", \"neutral\")}`,\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 2),\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n color: (listener) => themeColor(listener, \"text\", color),\n backgroundColor: (listener) => themeColor(listener, \"inherit\", color),\n transition:\n \"background-color 140ms ease, outline-color 140ms ease, box-shadow 140ms ease\",\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, color),\n },\n },\n };\n\n merge(anchorPartial, partial);\n return anchorPartial;\n}\n\nexport { selectBox };\n","import type { PartialElement } from \"@domphy/core\";\nimport {\n type ThemeColor,\n textToneOn,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * A single selectable option row (`role=\"option\"`) for use inside a `selectList`. Reads the\n * `select` context to reflect/toggle selection: it sets `aria-selected` from the bound value and\n * toggles the value (single or multiple) on click. Styles hover/selected/focus states.\n *\n * @hostTag div\n * @param props.accentColor - Theme color tone for the selected/focus state. Defaults to `\"primary\"`.\n * @param props.color - Theme color tone for text/background. Defaults to `\"neutral\"`.\n * @param props.value - The option value compared against and written to the select state.\n * Defaults to `null`.\n * @example { div: \"Option A\", $: [selectItem({ value: \"a\" })] }\n */\nfunction selectItem(\n props: {\n accentColor?: ThemeColor;\n color?: ThemeColor;\n value?: number | string;\n } = {},\n): PartialElement {\n const { accentColor = \"primary\", color = \"neutral\", value = null } = props;\n\n const partial: PartialElement = {\n role: \"option\",\n // Programmatically focusable (not tabbable): selectBox typeahead and\n // keyboard navigation move focus between options roving-style.\n tabindex: -1,\n // aria-selected and the click toggler must be DECLARED on the partial, not\n // wired imperatively in _onInit: hooks run once per real DOM node, but\n // patch() resets _events and strips undeclared attributes on every\n // ancestor re-render — so imperative wiring was lost on the first reuse\n // while the (once-run) hook never re-installed it. The reactive reader\n // resolves the `select` context lazily through listener.elementNode, so\n // every generation re-binds to whatever context is actually live.\n ariaSelected: (listener) => {\n const select = listener?.elementNode?.getContext(\"select\");\n if (!select) return undefined;\n const val = select.value.get(listener);\n return select.multiple ? val.includes(value) : val === value;\n },\n onClick: (_e, node) => {\n const select = node.getContext(\"select\");\n if (!select) return;\n const state = select.value;\n const val = state.get();\n if (select.multiple) {\n val.includes(value)\n ? state.set(val.filter((v: number | string) => v !== value))\n : state.set(val.concat([value]));\n } else {\n val !== value && state.set(value);\n }\n },\n _onInit: (node) => {\n if (node.tagName !== \"div\") {\n console.warn(`\"selectItem\" patch must use div tag`);\n }\n },\n style: {\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n height: (listener) => themeSpacing(6 + themeDensity(listener) * 2),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 3),\n border: \"none\",\n outline: \"none\",\n color: (listener) => themeColor(listener, \"text\", color),\n backgroundColor: (listener) => themeColor(listener, \"inherit\", color),\n // Label tracks the hover fill (+2): a fixed \"text\" label measured\n // 3.58:1 against it (light) / 4.37:1 (dark), below WCAG AA.\n \"&:hover:not([disabled]):not([aria-selected=true])\": {\n backgroundColor: (listener) => themeColor(listener, \"hover\", color),\n color: (listener) => themeColor(listener, textToneOn(2), color),\n },\n // Selected row uses the same fill/text pairing as button({variant:\"solid\"}):\n // deep brand fill + light-end neutral text. The old shift-6 / shift-11\n // pairing measured ~2.6:1 in Chromium (axe `color-contrast`), below the\n // WCAG AA 4.5:1 floor for the label of the CHOSEN option.\n \"&[aria-selected=true]\": {\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-13\", accentColor),\n color: (listener) => themeColor(listener, \"shift-0\", \"neutral\"),\n },\n transition: \"background-color 140ms ease, box-shadow 140ms ease\",\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, accentColor),\n },\n },\n };\n return partial;\n}\n\nexport { selectItem };\n","import {\n type DomphyElement,\n type ElementNode,\n type PartialElement,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { enabledOptionsIn } from \"../utils/optionList.js\";\n\n// WAI-ARIA APG Listbox keyboard model: Down/Up move to the next/previous\n// option, Home/End to the first/last, Enter/Space choose the focused option.\n// Focus IS the highlight here (options carry tabindex=-1), matching the\n// selectBox typeahead which already moves focus between options.\nfunction onListboxKey(event: Event, node: ElementNode): void {\n const key = (event as KeyboardEvent).key;\n const host = node.domElement as HTMLElement | null;\n if (!host) return;\n const options = enabledOptionsIn(host);\n if (!options.length) return;\n const active = host.ownerDocument.activeElement as HTMLElement | null;\n const current = active ? options.indexOf(active) : -1;\n\n if (key === \"Enter\" || key === \" \") {\n if (current === -1) return;\n event.preventDefault();\n options[current]!.click();\n return;\n }\n\n let next: number;\n if (key === \"ArrowDown\") next = Math.min(options.length - 1, current + 1);\n else if (key === \"ArrowUp\") next = current <= 0 ? 0 : current - 1;\n else if (key === \"Home\") next = 0;\n else if (key === \"End\") next = options.length - 1;\n else return;\n\n event.preventDefault();\n const target = options[next]!;\n target.focus();\n target.scrollIntoView?.({ block: \"nearest\" });\n}\n\n/**\n * Container for a list of `selectItem`s that owns the selection state. It exposes a `select`\n * context (`{ value, multiple }`) consumed by child items, and injects hidden `<input>`(s)\n * carrying the selected value(s) under `name` for form submission.\n *\n * @hostTag div\n * @param props.multiple - Whether multiple selection is allowed; also sets the default empty\n * value (`[]` vs `null`). Defaults to `false`.\n * @param props.value - Bound selection value(s). Accepts a value or reactive state of an array of\n * `number | string | null`, or a single `number | string | null`. Defaults to `[]` when\n * `multiple`, otherwise `null`.\n * @param props.color - Theme color tone for the background. Defaults to `\"neutral\"`.\n * @param props.name - Name attribute for the hidden inputs (form field name).\n * @example { div: [{ div: \"A\", $: [selectItem({ value: \"a\" })] }], $: [selectList({ name: \"pick\" })] }\n */\nfunction selectList(\n props: {\n multiple?: boolean;\n value?: ValueOrState<\n Array<number | string | null> | number | string | null\n >;\n color?: ThemeColor;\n name?: string;\n } = {},\n): PartialElement {\n const { color = \"neutral\", multiple = false } = props;\n const state = toState(props.value ?? (multiple ? [] : null));\n\n // type=hidden form fields (not a visible input) — avoid axe label/listbox noise.\n const inputs: DomphyElement<\"div\"> = {\n div: (listener) => {\n const val = state.get(listener);\n const vals = Array.isArray(val) ? val : [val];\n return vals.map((v) => ({\n input: null,\n type: \"hidden\",\n name: props.name,\n // Preserve a legitimate numeric 0 (and other falsy-but-valid values);\n // `v || \"\"` would drop them.\n value: v == null ? \"\" : String(v),\n }));\n },\n // Keep out of the a11y tree; listbox children must be options.\n ariaHidden: \"true\",\n hidden: true,\n };\n\n const partial: PartialElement = {\n dataTone: \"shift-0\",\n // selectItem uses role=option; options require a listbox parent (WAI-ARIA).\n role: \"listbox\",\n ariaLabel: \"Options\",\n ariaMultiselectable: multiple ? \"true\" : undefined,\n // Without a tab stop the whole listbox was keyboard-unreachable: its\n // options are tabindex=-1 by design (roving focus), so Tab skipped the\n // entire widget. APG's listbox example puts tabindex=0 on the container.\n tabindex: 0,\n onKeyDown: onListboxKey,\n // Published from _onSchedule (runs once per node), NOT as a declared\n // `_context`: ElementNode.patch re-merges `element._context` on every\n // re-render, and merging a freshly-built State into the live one\n // overwrote its value and its notifier's listeners — an uncontrolled\n // selection silently snapped back to the initial value whenever a\n // reactive ancestor re-rendered. Same fix as segmented/toggleGroup.\n _onSchedule: (node) => {\n node.setContext(\"select\", { value: state, multiple });\n },\n _onInit: (node) => {\n if (node.tagName !== \"div\") {\n console.warn(`\"selectList\" patch must use a div tag`);\n }\n node.children.insert(inputs);\n },\n style: {\n display: \"flex\",\n flexDirection: \"column\",\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 2),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 2),\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n backgroundColor: (listener) => themeColor(listener, \"inherit\", color),\n color: (listener) => themeColor(listener, \"text\", color),\n },\n };\n return partial;\n}\n\nexport { selectList };\n","import {\n hashString,\n type PartialElement,\n type StyleObject,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * A loading placeholder block with a left-to-right shimmer gradient. Marked\n * `aria-hidden`, themed background/foreground, fixed height, slight rounding.\n * No host-tag check; typically applied to a block-level element such as a\n * `div` or `span`.\n *\n * @param props.color - Theme color tone for the placeholder. Accepts a value or reactive state.\n * Defaults to `\"neutral\"`.\n * @example { div: null, $: [skeleton()] }\n */\nfunction skeleton(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n // Shimmer sweeps left→right over a near-white base (reads as loading, not\n // a flat opacity blink). Base + highlight are both theme tokens so the\n // effect adapts to light/dark surfaces. Highlight stays close to the base\n // (shift-2) — a deeper step reads as dirty banding on light themes.\n const keyframes = {\n \"0%\": { backgroundPosition: \"200% 0\" },\n \"100%\": { backgroundPosition: \"-200% 0\" },\n };\n const animationName = hashString(JSON.stringify(keyframes));\n return {\n ariaHidden: \"true\",\n dataTone: \"shift-1\",\n style: {\n fontSize: (listener) => themeSize(listener),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n height: themeSpacing(6),\n display: \"block\",\n borderRadius: themeSpacing(1),\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n backgroundImage: (listener) =>\n `linear-gradient(90deg, ${themeColor(listener, \"inherit\", color.get(listener))} 0%, ${themeColor(listener, \"shift-2\", color.get(listener))} 50%, ${themeColor(listener, \"inherit\", color.get(listener))} 100%)`,\n backgroundSize: \"200% 100%\",\n animation: `${animationName} 1.6s ease-in-out infinite`,\n [`@keyframes ${animationName}`]: keyframes,\n } as StyleObject,\n };\n}\n\nexport { skeleton };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport { type ThemeColor, themeColor, themeSize } from \"@domphy/theme\";\n\n/**\n * Styles small/secondary text: one step smaller font size (`data-size=\"decrease-1\"`) with a\n * themed foreground color.\n *\n * The tone is `shift-10`, one step ABOVE the `\"text\"` floor, because this text renders below\n * the WCAG large-text threshold and so must always clear 4.5:1. Measured in Chromium on the\n * built bundle: 6.01–7.73:1 (light) and 6.33–7.73:1 (dark) on every edge-anchored surface.\n * Three things at the CALL SITE forfeit that guarantee, all measured in Chromium:\n * 1. A host-declared `style.color` wins over the patch (native beats patch) — `\"text\"` /\n * `shift-9` on a `shift-1` surface is 4.23:1. Pass `color` for a different family\n * instead of restyling.\n * 2. An ancestor's scoped `\"& small\": { color: … }` also wins: that descendant selector is\n * specificity (0,1,1) and this patch's own generated class is only (0,1,0). Measured\n * inside a correctly tone-anchored `dataTone: \"shift-1\"` card, with no inline style on\n * the `<small>` at all: `& small { color: themeColor(l, \"shift-8\") }` resolves to\n * `var(--neutral-9)` = #707070 on the card's #ededed = 4.23:1 (6.27:1 once the `color`\n * line is dropped). The specificity is deliberately NOT escalated here — a patch that\n * outranked descendant rules would leave an author no way to restyle short of\n * `!important`. Scope layout there (`display: block`) and leave the colour to the patch.\n * 3. A surface tinted with a fixed `themeColor(l, \"shift-N\")` background and no `dataTone`:\n * every child still resolves against the page root, and even `shift-10` drops to 4.34:1\n * (shift-2 tint) and 3.67:1 (shift-3). Shift the surface with `dataTone` + `\"inherit\"`\n * instead — `@domphy/doctor`'s `tone-background-inherit` rule flags exactly this.\n *\n * @hostTag small\n * @param props.color - Theme color tone for the text. Accepts a value or reactive state.\n * Defaults to `\"neutral\"`.\n * @example { small: \"fine print\", $: [small()] }\n */\nfunction small(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"small\") {\n console.warn('\"small\" patch must use small tag');\n }\n },\n dataSize: \"decrease-1\",\n style: {\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n // shift-10 (not muted/shift-8) keeps WCAG AA ≥4.5:1 on light surfaces for small type.\n color: (listener) =>\n themeColor(listener, \"shift-10\", color.get(listener)),\n },\n };\n}\n\nexport { small };\n","import type { PartialElement, StyleObject } from \"@domphy/core\";\nimport { hashString, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\nconst keyframes = { to: { transform: \"rotate(360deg)\" } };\nconst animationName = hashString(JSON.stringify(keyframes));\n\n/**\n * A circular loading spinner: a themed ring with a contrasting top border that rotates\n * continuously. Marked `role=\"status\"` with `aria-label=\"loading\"`.\n *\n * @hostTag span\n * @param props.color - Theme color tone for the ring/highlight. Accepts a value or reactive\n * state. Defaults to `\"neutral\"`.\n * @example { span: null, $: [spinner()] }\n */\nfunction spinner(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n role: \"status\",\n ariaLabel: \"loading\",\n _onInsert: (node) => {\n if (node.tagName !== \"span\") {\n console.warn(`\"spinner\" patch must use span tag`);\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener),\n backgroundColor: (listener) => themeColor(listener),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n display: \"inline-block\",\n margin: 0,\n flexShrink: 0,\n width: themeSpacing(6),\n height: themeSpacing(6),\n borderRadius: \"50%\",\n border: (listener) =>\n `${themeSpacing(0.5)} solid ${themeColor(listener, \"border-strong\", color.get(listener))}`,\n borderTopColor: (listener) =>\n themeColor(listener, \"shift-9\", color.get(listener)),\n boxSizing: \"border-box\",\n padding: 0,\n animation: `${animationName} 0.7s linear infinite`,\n [`@keyframes ${animationName}`]: keyframes,\n } as StyleObject,\n };\n}\n\nexport { spinner };\n","import { ElementNode, merge, type PartialElement, toState } from \"@domphy/core\";\nimport { themeColor, themeSpacing } from \"@domphy/theme\";\nimport { horizontalArrowStep } from \"../utils/direction.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * Root of a resizable split layout. Lays out children as a flex row (horizontal) or column\n * (vertical) and provides a `splitter` context (`{ direction, size, min, max }`) consumed by\n * `splitterPanel` and `splitterHandle`. `size` is a reactive state holding the first panel's\n * percentage. No host-tag check; typically applied to a `div`.\n *\n * @param props.direction - Split orientation, `\"horizontal\"` | `\"vertical\"`. Defaults to `\"horizontal\"`.\n * @param props.defaultSize - Initial size (percentage) of the resizable panel. Defaults to `50`.\n * @param props.min - Minimum panel size (percentage). Defaults to `10`.\n * @param props.max - Maximum panel size (percentage). Defaults to `90`.\n * @example { div: [...], $: [splitter({ direction: \"vertical\" })] }\n */\nfunction splitter(\n props: {\n direction?: \"horizontal\" | \"vertical\";\n defaultSize?: number;\n min?: number;\n max?: number;\n } = {},\n): PartialElement {\n const {\n direction = \"horizontal\",\n defaultSize = 50,\n min = 10,\n max = 90,\n } = props;\n return {\n _onSchedule: (_node, element) => {\n merge(element, {\n _context: {\n splitter: {\n direction,\n size: toState(defaultSize),\n min,\n max,\n // Legacy bookkeeping kept on the context object for compatibility.\n // First-vs-second assignment uses sibling order (see splitterPanel).\n panelCount: 0,\n },\n },\n });\n },\n style: {\n display: \"flex\",\n flexDirection: direction === \"horizontal\" ? \"row\" : \"column\",\n overflow: \"hidden\",\n },\n };\n}\n\n/**\n * The resizable panel inside a `splitter`. Reads the `splitter` context and binds its\n * width (horizontal) or height (vertical) to the context `size` state, updating reactively as\n * the handle is dragged. Intended for exactly two panels either side of one `splitterHandle`:\n * the first `splitterPanel` mounted takes `size`%, and the second takes the complementary\n * `100 - size`% — so the pair always sums to the full width/height instead of both tracking\n * the same number (which would make them grow and shrink together instead of trading space).\n * Warns if used outside a `splitter`. Takes no props.\n *\n * @example { div: [...], $: [splitterPanel()] }\n */\nfunction isFirstSplitterPanel(node: ElementNode): boolean {\n const parent = node.parent;\n if (!parent) return true;\n for (const item of parent.children.items) {\n if (item instanceof ElementNode && item.getMetadata(\"splitterPanel\")) {\n return item === node;\n }\n }\n return true;\n}\n\nfunction splitterPanel(): PartialElement {\n return {\n _metadata: { splitterPanel: true },\n _onMount: (node) => {\n const ctx = node.getContext(\"splitter\");\n if (!ctx) {\n console.warn(`\"splitterPanel\" patch must be used inside a \"splitter\"`);\n return;\n }\n const el = node.domElement as HTMLElement;\n const prop = ctx.direction === \"horizontal\" ? \"width\" : \"height\";\n\n const apply = (size: number) => {\n el.style[prop] = `${isFirstSplitterPanel(node) ? size : 100 - size}%`;\n };\n apply(ctx.size.get());\n el.style.flexShrink = \"0\";\n el.style.overflow = \"auto\";\n\n const release = ctx.size.addListener(apply);\n node.addHook(\"Remove\", () => {\n ctx.panelCount = Math.max(0, (ctx.panelCount ?? 1) - 1);\n release();\n });\n },\n };\n}\n\n/**\n * The draggable divider inside a `splitter`. Reads the `splitter` context, shows the\n * appropriate resize cursor, and updates the context `size` state (clamped to `min`/`max`)\n * via mouse drag or keyboard: Arrow keys move by 1%, Home/End jump to min/max, hold Shift\n * for 10× step. Sets `role=\"separator\"`, `tabindex=\"0\"`, and `aria-value*` attributes.\n * Warns if used outside a `splitter`. Drag works with mouse, pen and touch\n * (Pointer Events).\n *\n * @param props.label - Accessible name for the separator (WCAG 4.1.2 — a\n * focusable `role=\"separator\"` with `aria-value*` is a widget and needs a\n * name). Defaults to `\"Resize\"`. A native `ariaLabel`/`ariaLabelledby` on\n * the host element wins.\n * @example { div: null, $: [splitterHandle()] }\n */\nfunction splitterHandle(props: { label?: string } = {}): PartialElement {\n const { label = \"Resize\" } = props;\n return {\n role: \"separator\",\n tabindex: 0,\n ariaLabel: label,\n _onMount: (node) => {\n const ctx = node.getContext(\"splitter\");\n if (!ctx) {\n console.warn(`\"splitterHandle\" patch must be used inside a \"splitter\"`);\n return;\n }\n const handle = node.domElement as HTMLElement;\n const isHorizontal = ctx.direction === \"horizontal\";\n\n handle.style.cursor = isHorizontal ? \"col-resize\" : \"row-resize\";\n handle.setAttribute(\n \"aria-orientation\",\n isHorizontal ? \"vertical\" : \"horizontal\",\n );\n handle.setAttribute(\"aria-valuemin\", String(ctx.min));\n handle.setAttribute(\"aria-valuemax\", String(ctx.max));\n handle.setAttribute(\"aria-valuenow\", String(Math.round(ctx.size.get())));\n\n const releaseAriaValue = ctx.size.addListener((size: number) => {\n handle.setAttribute(\"aria-valuenow\", String(Math.round(size)));\n });\n\n const onKeydown = (e: KeyboardEvent) => {\n const step = e.shiftKey ? 10 : 1;\n let next: number | null = null;\n if (isHorizontal) {\n // Move the divider toward the physically-pressed arrow: the\n // first panel's share grows when that moves the divider right in\n // LTR, or left in RTL (both panels are laid out with `flexDirection:\n // row`, which itself flips source order under RTL).\n const dir = horizontalArrowStep(e.key, handle);\n if (dir !== 0)\n next = Math.min(\n Math.max(ctx.size.get() + dir * step, ctx.min),\n ctx.max,\n );\n } else {\n if (e.key === \"ArrowDown\")\n next = Math.min(ctx.size.get() + step, ctx.max);\n else if (e.key === \"ArrowUp\")\n next = Math.max(ctx.size.get() - step, ctx.min);\n }\n if (e.key === \"Home\") next = ctx.min;\n else if (e.key === \"End\") next = ctx.max;\n if (next !== null) {\n e.preventDefault();\n ctx.size.set(next);\n }\n };\n\n let cancelDrag: (() => void) | null = null;\n\n // Pointer Events, not mouse events: a touch drag never fires\n // mousemove/mouseup, so the handle was mouse-and-pen only — every peer\n // resizable splitter (react-resizable-panels, MUI, Mantine) drags on\n // touch. `touch-action: none` (set in the style block) is required or\n // the browser claims the gesture for scrolling and fires pointercancel.\n const onPointerdown = (e: PointerEvent) => {\n e.preventDefault();\n const container = handle.parentElement!;\n handle.setPointerCapture?.(e.pointerId);\n\n const onPointermove = (move: PointerEvent) => {\n if (move.pointerId !== e.pointerId) return;\n const rect = container.getBoundingClientRect();\n const raw = isHorizontal\n ? ((move.clientX - rect.left) / rect.width) * 100\n : ((move.clientY - rect.top) / rect.height) * 100;\n ctx.size.set(Math.min(Math.max(raw, ctx.min), ctx.max));\n };\n\n cancelDrag = () => {\n document.removeEventListener(\"pointermove\", onPointermove);\n document.removeEventListener(\"pointerup\", onPointerup);\n document.removeEventListener(\"pointercancel\", onPointerup);\n cancelDrag = null;\n // releasePointerCapture throws NotFoundError once the pointer is no\n // longer active — which is exactly the pointercancel path. Ask\n // first, and only after the listeners are already detached so a\n // throw could not leak them or strand `cancelDrag`.\n if (handle.hasPointerCapture?.(e.pointerId))\n handle.releasePointerCapture(e.pointerId);\n };\n\n function onPointerup(up: PointerEvent) {\n if (up.pointerId !== e.pointerId) return;\n cancelDrag?.();\n }\n\n document.addEventListener(\"pointermove\", onPointermove);\n document.addEventListener(\"pointerup\", onPointerup);\n document.addEventListener(\"pointercancel\", onPointerup);\n };\n\n handle.addEventListener(\"keydown\", onKeydown);\n handle.addEventListener(\"pointerdown\", onPointerdown);\n node.addHook(\"Remove\", () => {\n cancelDrag?.();\n releaseAriaValue();\n handle.removeEventListener(\"keydown\", onKeydown);\n handle.removeEventListener(\"pointerdown\", onPointerdown);\n });\n },\n // Soft divider surface — shift via dataTone, paint with inherit.\n dataTone: \"shift-2\",\n style: {\n flexShrink: 0,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n // Hand the drag gesture to the pointer handler instead of the browser's\n // scroller — without this a touch drag is swallowed by panning.\n touchAction: \"none\",\n backgroundColor: (listener) => themeColor(listener, \"inherit\"),\n color: (listener) => themeColor(listener, \"text\"),\n \"&:hover\": {\n backgroundColor: (listener) => themeColor(listener, \"increase-1\"),\n },\n transition: \"background-color 140ms ease, box-shadow 140ms ease\",\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, \"primary\"),\n },\n \"&::after\": {\n content: '\"\"',\n // A small grip dot so the handle is visibly draggable. Without an\n // explicit size the pseudo-element collapses to 0x0 and is invisible.\n width: themeSpacing(1),\n height: themeSpacing(1),\n borderRadius: themeSpacing(999),\n backgroundColor: (listener) => themeColor(listener, \"shift-4\"),\n },\n },\n };\n}\n\nexport { splitter, splitterPanel, splitterHandle };\n","import type { PartialElement } from \"@domphy/core\";\nimport { themeDensity, themeSpacing } from \"@domphy/theme\";\n\ntype FlexAlign = \"flex-start\" | \"center\" | \"flex-end\" | \"stretch\" | \"baseline\";\n\ntype FlexJustify =\n | \"flex-start\"\n | \"center\"\n | \"flex-end\"\n | \"space-between\"\n | \"space-around\"\n | \"space-evenly\";\n\n/**\n * A vertical flex column with spacing between children. The general-purpose\n * primitive for stacking blocks — form sections, panel content, card bodies —\n * instead of hand-rolling `display: flex; flexDirection: column; gap: ...`.\n * Styles the host only; apply to any block element.\n *\n * @param props.gap - Spacing multiplier for gap between children (default 3).\n * Bounded-control mode (`density: true`, default): `themeSpacing(themeDensity(l) * gap)`\n * — at default density 1.5, gap 3 = 1.125em.\n * Structural/page-column mode (`density: false`): bare `themeSpacing(gap)` with no\n * density multiply — gap 3 = 0.75em, matching AGENTS.md \"bare themeSpacing(n)\".\n * @param props.align - Cross-axis alignment (`alignItems`). Unset by default (flex default, stretch).\n * @param props.justify - Main-axis distribution (`justifyContent`). Unset by default (flex-start).\n * @param props.density - When true (default), gap is multiplied by theme density\n * (bounded controls). When false, gap is structural `themeSpacing(n)` — use this\n * for page/form columns.\n * @example { div: [{ h3: \"Title\" }, { p: \"Body\" }], $: [stack()] }\n * @example { div: [...], $: [stack({ gap: 2, align: \"center\" })] }\n * @example { div: [...], $: [stack({ gap: 3, density: false, justify: \"space-between\" })] }\n */\nfunction stack(\n props: {\n gap?: number;\n align?: FlexAlign;\n justify?: FlexJustify;\n density?: boolean;\n } = {},\n): PartialElement {\n const { gap = 3, align, justify, density = true } = props;\n return {\n style: {\n display: \"flex\",\n flexDirection: \"column\",\n gap: density\n ? (listener) => themeSpacing(themeDensity(listener) * gap)\n : () => themeSpacing(gap),\n ...(align ? { alignItems: align } : {}),\n ...(justify ? { justifyContent: justify } : {}),\n },\n };\n}\n\nexport { stack };\nexport type { FlexAlign, FlexJustify };\n","import {\n behavior,\n type DomphyElement,\n type ElementNode,\n isState,\n type Listener,\n type PartialElement,\n type State,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n themeWeight,\n} from \"@domphy/theme\";\n\n/** One step entry. */\ntype StepItem = {\n /** Step label — plain string (auto-wrapped) or any DomphyElement. */\n label: string | DomphyElement;\n /** Stable key. Defaults to the item's zero-based index. */\n key?: string | number;\n};\n\ntype StepsLive = {\n items: StepItem[];\n direction: \"horizontal\" | \"vertical\";\n color: ThemeColor;\n accentColor: ThemeColor;\n};\n\nfunction persistValue<T>(\n node: ElementNode,\n key: string,\n incoming: ValueOrState<T> | undefined,\n fallback: T,\n): State<T> {\n if (isState(incoming)) {\n node.setMetadata(key, incoming);\n return incoming as State<T>;\n }\n let stored = node.getMetadata(key) as State<T> | undefined;\n if (!stored) {\n stored = toState((incoming as T | undefined) ?? fallback);\n node.setMetadata(key, stored);\n }\n return stored;\n}\n\nfunction stepConnectorStyle(\n direction: \"horizontal\" | \"vertical\",\n color: ThemeColor,\n accentColor: ThemeColor,\n) {\n if (direction === \"vertical\") {\n // Outgoing track: from this badge's bottom through the host gap to the\n // next badge. Incoming-from-current-item cannot span the previous\n // item's variable label height.\n return {\n \"&:not(:last-child)::after\": {\n content: '\"\"',\n position: \"absolute\",\n insetInlineStart: themeSpacing(3),\n top: themeSpacing(6),\n bottom: `-${themeSpacing(2)}`,\n width: \"2px\",\n height: \"auto\",\n insetInlineEnd: \"auto\",\n backgroundColor: (l: Listener) => themeColor(l, \"shift-3\", color),\n zIndex: \"0\",\n },\n \"&[data-status=done]:not(:last-child)::after\": {\n backgroundColor: (l: Listener) => themeColor(l, \"shift-9\", accentColor),\n },\n };\n }\n return {\n \"&:not(:first-child)::after\": {\n content: '\"\"',\n position: \"absolute\",\n top: themeSpacing(3),\n insetInlineEnd: `calc(50% + ${themeSpacing(3)})`,\n insetInlineStart: `calc(-50% + ${themeSpacing(3)})`,\n height: \"2px\",\n backgroundColor: (l: Listener) => themeColor(l, \"shift-3\", color),\n zIndex: \"0\",\n },\n \"&[data-status=done]:not(:first-child)::after\": {\n backgroundColor: (l: Listener) => themeColor(l, \"shift-9\", accentColor),\n },\n \"&[data-status=active]:not(:first-child)::after\": {\n backgroundColor: (l: Listener) => themeColor(l, \"shift-9\", accentColor),\n },\n };\n}\n\nfunction buildStepItems(\n items: StepItem[],\n current: State<number>,\n direction: \"horizontal\" | \"vertical\",\n color: ThemeColor,\n accentColor: ThemeColor,\n): DomphyElement<\"li\">[] {\n const vertical = direction === \"vertical\";\n const connector = stepConnectorStyle(direction, color, accentColor);\n\n return items.map((item, index) => {\n const labelEl: DomphyElement =\n typeof item.label === \"string\"\n ? ({ span: item.label } as DomphyElement<\"span\">)\n : item.label;\n\n return {\n li: [labelEl],\n _key: item.key ?? index,\n dataStep: String(index + 1),\n dataStatus: (l: Listener) => {\n const cur = current.get(l);\n if (index < cur) return \"done\";\n if (index === cur) return \"active\";\n return \"pending\";\n },\n ariaCurrent: (l: Listener) =>\n current.get(l) === index ? \"step\" : undefined,\n style: {\n position: \"relative\",\n display: \"flex\",\n flexDirection: vertical ? \"row\" : \"column\",\n alignItems: vertical ? \"flex-start\" : \"center\",\n gap: themeSpacing(1),\n flex: vertical ? \"none\" : \"1\",\n fontSize: (l: Listener) => themeSize(l, \"decrease-1\"),\n textAlign: vertical ? \"start\" : \"center\",\n \"&::before\": {\n content: \"attr(data-step)\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: themeSpacing(6),\n height: themeSpacing(6),\n borderRadius: themeSpacing(999),\n fontSize: (l: Listener) => themeSize(l, \"decrease-1\"),\n fontWeight: themeWeight(\"bold\"),\n flexShrink: \"0\",\n border: (l: Listener) =>\n `2px solid ${themeColor(l, \"border-strong\", color)}`,\n backgroundColor: (l: Listener) => themeColor(l, \"inherit\"),\n color: (l: Listener) => themeColor(l, \"muted\"),\n transition:\n \"background-color 200ms ease, color 200ms ease, border-color 200ms ease\",\n zIndex: \"1\",\n },\n ...connector,\n \"&[data-status=active]::before\": {\n backgroundColor: (l: Listener) =>\n themeColor(l, \"shift-9\", accentColor),\n borderColor: (l: Listener) => themeColor(l, \"shift-9\", accentColor),\n color: (l: Listener) => themeColor(l, \"shift-0\", accentColor),\n boxShadow: (l: Listener) =>\n `0 0 0 3px ${themeColor(l, \"shift-3\", accentColor)}`,\n },\n // Completed steps: filled accent + check, matching active track.\n \"&[data-status=done]::before\": {\n content: '\"✓\"',\n backgroundColor: (l: Listener) =>\n themeColor(l, \"shift-9\", accentColor),\n borderColor: (l: Listener) => themeColor(l, \"shift-9\", accentColor),\n color: (l: Listener) => themeColor(l, \"shift-0\", accentColor),\n },\n \"&[data-status=pending]\": {\n color: (l: Listener) => themeColor(l, \"muted\"),\n },\n \"&[data-status=active]\": {\n color: (l: Listener) => themeColor(l, \"shift-11\", accentColor),\n fontWeight: themeWeight(\"bold\"),\n },\n \"&[data-status=done]\": {\n color: (l: Listener) => themeColor(l, \"text\", color),\n },\n },\n } as DomphyElement<\"li\">;\n });\n}\n\n/**\n * All-in-one step-progress indicator. Generates `<li>` step elements from the\n * `items` array. Apply to an `<ol>` or `<ul>` element.\n *\n * @param props.items - Step definitions `{ label, key? }`.\n * @param props.current - Zero-based index of the active step (value or State). Defaults to `0`.\n * @param props.direction - `\"horizontal\"` (default) or `\"vertical\"` layout.\n * @param props.color - Theme color for pending/track elements. Defaults to `\"neutral\"`.\n * @param props.accentColor - Theme color for active/completed elements. Defaults to `\"primary\"`.\n * @example\n * { ol: null, $: [steps({ current: 1, items: [\n * { label: \"Cart\" },\n * { label: \"Shipping\" },\n * { label: \"Payment\" },\n * ] })] }\n */\nfunction steps(\n props: {\n items: StepItem[];\n current?: ValueOrState<number>;\n direction?: \"horizontal\" | \"vertical\";\n color?: ThemeColor;\n accentColor?: ThemeColor;\n } = { items: [] },\n): PartialElement {\n const {\n items = [],\n direction = \"horizontal\",\n color = \"neutral\",\n accentColor = \"primary\",\n } = props;\n const live: StepsLive = { items, direction, color, accentColor };\n\n return {\n // Publish current/direction/colors so descendants can read the indicator.\n _context: {\n steps: {\n current: toState(props.current ?? 0),\n direction,\n color,\n accentColor,\n },\n },\n _onSchedule: (node, element) => {\n const current = persistValue(node, \"stepsCurrent\", props.current, 0);\n (element as Record<string, unknown>)[node.tagName] = buildStepItems(\n items,\n current,\n direction,\n color,\n accentColor,\n );\n },\n ...behavior<StepsLive>(\n \"steps-items\",\n (node) => ({\n update(snapshot) {\n const current = persistValue(node, \"stepsCurrent\", props.current, 0);\n node.children.update(\n buildStepItems(\n snapshot.items,\n current,\n snapshot.direction,\n snapshot.color,\n snapshot.accentColor,\n ),\n !!node.domElement,\n true,\n );\n },\n }),\n live,\n ),\n style: {\n display: \"flex\",\n flexDirection: direction === \"vertical\" ? \"column\" : \"row\",\n alignItems: direction === \"vertical\" ? \"flex-start\" : \"center\",\n gap: themeSpacing(2),\n listStyle: \"none\",\n margin: \"0\",\n padding: \"0\",\n },\n };\n}\n\nexport { steps };\nexport type { StepItem };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeWeight,\n} from \"@domphy/theme\";\n\n/**\n * Styles strongly emphasized (bold) text: inherited font size, the theme's `bold` weight, and a\n * themed foreground color.\n *\n * @hostTag strong\n * @param props.color - Theme color tone for the text. Accepts a value or reactive state.\n * Defaults to `\"neutral\"`.\n * @example { strong: \"important\", $: [strong()] }\n */\nfunction strong(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"strong\") {\n console.warn(`\"strong\" primitive patch must use strong tag`);\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n fontWeight: themeWeight(\"bold\"),\n color: (listener) =>\n themeColor(listener, \"shift-11\", color.get(listener)),\n backgroundColor: (listener) => themeColor(listener),\n },\n };\n}\n\nexport { strong };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport { type ThemeColor, themeColor, themeSize } from \"@domphy/theme\";\n\n/**\n * Renders subscript text (shrunk, baseline-lowered) for the host `<sub>` element.\n *\n * @hostTag sub\n * @param props.color - Theme color for the text. Optional, accepts a value or state. Defaults to `\"neutral\"`.\n * @example { sub: \"2\", $: [subscript()] }\n */\nfunction subscript(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"sub\") {\n console.warn(`\"subscript\" primitive patch must use sub tag`);\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener, \"decrease-1\"),\n verticalAlign: \"sub\",\n lineHeight: 0,\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n },\n };\n}\n\nexport { subscript };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport { type ThemeColor, themeColor, themeSize } from \"@domphy/theme\";\n\n/**\n * Renders superscript text (shrunk, baseline-raised) for the host `<sup>` element.\n *\n * @hostTag sup\n * @param props.color - Theme color for the text. Optional, accepts a value or state. Defaults to `\"neutral\"`.\n * @example { sup: \"2\", $: [superscript()] }\n */\nfunction superscript(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"sup\") {\n console.warn(`\"superscript\" primitive patch must use sup tag`);\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener, \"decrease-1\"),\n verticalAlign: \"super\",\n lineHeight: 0,\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n },\n };\n}\n\nexport { superscript };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n textToneOn,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n themeWeight,\n} from \"@domphy/theme\";\n\n/**\n * Styles a data table (header/body/footer cells, caption, row hover, borders)\n * on the host `<table>` element.\n *\n * @hostTag table\n * @param props.color - Theme color applied across cells and text. Optional, accepts a value or state. Defaults to `\"neutral\"`.\n * @example { table: null, $: [table()] }\n */\nfunction table(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"table\") {\n console.warn(`\"table\" primitive patch must use table tag`);\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n width: \"100%\",\n borderCollapse: \"collapse\",\n \"& caption\": {\n captionSide: \"bottom\",\n },\n \"& th, & thead td\": {\n textAlign: \"start\",\n fontWeight: themeWeight(\"medium\"),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 3),\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 1),\n color: (listener) =>\n themeColor(listener, \"shift-10\", color.get(listener)),\n backgroundColor: (listener) => themeColor(listener, \"inherit\"),\n },\n \"& td\": {\n textAlign: \"start\",\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 3),\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 1),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n boxShadow: (listener) =>\n `inset 0 1px 0 ${themeColor(listener, \"shift-3\", color.get(listener))}`,\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n },\n \"& tfoot th, & tfoot td\": {\n textAlign: \"start\",\n fontWeight: themeWeight(\"medium\"),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 3),\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 1),\n color: (l) => themeColor(l, \"shift-10\", color.get(l)),\n backgroundColor: (l) => themeColor(l, \"inherit\"),\n boxShadow: (l) =>\n `inset 0 -1px 0 ${themeColor(l, \"shift-4\", color.get(l))}`,\n },\n \"& tr\": {\n backgroundColor: (listener) => themeColor(listener, \"inherit\"),\n },\n\n // No !important needed: \".scope tbody tr:hover\" (two classes + two\n // elements) already out-specifies any row's own auto-scope class rule.\n \"& tbody tr:hover\": {\n backgroundColor: (listener) => themeColor(listener, \"hover\"),\n color: (listener) => themeColor(listener, textToneOn(2)),\n },\n // Cell text tracks the hover fill (+2) — measured in Chromium (axe\n // color-contrast) at 3.57:1 light / 4.37:1 dark while the cells kept the\n // resting \"text\" tone. It has to be set on the CELLS: `& td` declares its\n // own `color`, and a direct declaration beats anything inherited from the\n // row however specific that row's selector is.\n \"& tbody tr:hover td, & tbody tr:hover th\": {\n color: (listener) => themeColor(listener, textToneOn(2)),\n },\n },\n };\n}\n\nexport { table };\n","import {\n behavior,\n type DomphyElement,\n type ElementNode,\n isState,\n type Listener,\n type PartialElement,\n type State,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { horizontalArrowStep } from \"../utils/direction.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/** One tab entry: a trigger label and its panel content. */\ntype TabItem = {\n /** Tab button label — a plain string (auto-wrapped in span) or any DomphyElement. */\n label: string | DomphyElement;\n /** Panel content rendered when this tab is active. */\n content: DomphyElement;\n /** Stable identity key. Defaults to the item's zero-based index. */\n key?: string | number;\n};\n\ntype TabsLive = {\n items: TabItem[];\n accentColor: ThemeColor;\n color: ThemeColor;\n};\n\nfunction persistValue<T>(\n node: ElementNode,\n key: string,\n incoming: ValueOrState<T> | undefined,\n fallback: T,\n): State<T> {\n if (isState(incoming)) {\n node.setMetadata(key, incoming);\n return incoming as State<T>;\n }\n let stored = node.getMetadata(key) as State<T> | undefined;\n if (!stored) {\n stored = toState((incoming as T | undefined) ?? fallback);\n node.setMetadata(key, stored);\n }\n return stored;\n}\n\nfunction buildTabsChildren(\n node: ElementNode,\n items: TabItem[],\n activeKey: State<string | number>,\n accentColor: ThemeColor,\n color: ThemeColor,\n): DomphyElement[] {\n const id = node.nodeId;\n\n const buttons: DomphyElement<\"button\">[] = items.map((item, index) => {\n const key = item.key ?? index;\n const labelEl: DomphyElement =\n typeof item.label === \"string\"\n ? ({ span: item.label } as DomphyElement<\"span\">)\n : item.label;\n\n return {\n button: [labelEl],\n _key: key,\n type: \"button\",\n role: \"tab\",\n id: `tab${id}${key}`,\n ariaControls: `panel${id}${key}`,\n ariaSelected: (l: Listener) => activeKey.get(l) === key,\n // Roving tabindex (APG tabs pattern): only the selected tab is in\n // the tab order; arrow keys move both selection and focus.\n tabIndex: (l: Listener) => (activeKey.get(l) === key ? 0 : -1),\n onClick: () => activeKey.set(key),\n onKeyDown: (e: Event) => {\n const k = (e as KeyboardEvent).key;\n if (![\"ArrowLeft\", \"ArrowRight\", \"Home\", \"End\"].includes(k)) return;\n e.preventDefault();\n const keys = items.map((it, i) => it.key ?? i);\n const idx = keys.indexOf(key);\n let next = idx;\n if (k === \"ArrowRight\" || k === \"ArrowLeft\") {\n const step = horizontalArrowStep(k, e.target as Element);\n next = (idx + step + keys.length) % keys.length;\n } else if (k === \"Home\") next = 0;\n else if (k === \"End\") next = keys.length - 1;\n activeKey.set(keys[next]);\n // Focus must follow selection: without this the next arrow key\n // fires on the OLD tab and re-navigates from its stale position,\n // making later tabs unreachable by keyboard. Resolved via the\n // event target's own tablist — shadow-root safe (unlike a\n // document.getElementById lookup).\n const list = (e.target as HTMLElement).closest(\"[role=tablist]\");\n list?.querySelectorAll<HTMLElement>(\"[role=tab]\")[next]?.focus();\n },\n style: {\n cursor: \"pointer\",\n fontSize: (l: Listener) => themeSize(l, \"inherit\"),\n height: (l: Listener) => themeSpacing(6 + themeDensity(l) * 2),\n paddingInline: (l: Listener) => themeSpacing(themeDensity(l) * 4),\n border: \"none\",\n outline: \"none\",\n // Resting tabs: shift-13 for ≥4.5:1 on surface (catalog low-contrast).\n color: (l: Listener) => themeColor(l, \"shift-13\"),\n backgroundColor: (l: Listener) => themeColor(l, \"inherit\"),\n boxShadow: (l: Listener) =>\n `inset 0 ${themeSpacing(-0.5)} 0 0 ${themeColor(l, \"shift-1\", color)}`,\n transition: \"box-shadow 140ms ease, color 140ms ease\",\n \"&:hover:not([disabled]):not([aria-selected=true])\": {\n color: (l: Listener) => themeColor(l, \"shift-13\"),\n boxShadow: (l: Listener) =>\n `inset 0 ${themeSpacing(-0.5)} 0 0 ${themeColor(l, \"shift-2\", color)}`,\n },\n \"&[aria-selected=true]:not([disabled])\": {\n color: (l: Listener) => themeColor(l, \"shift-13\", accentColor),\n boxShadow: (l: Listener) =>\n `inset 0 ${themeSpacing(-0.5)} 0 0 ${themeColor(l, \"shift-8\", accentColor)}`,\n },\n // Focus ring must compose with the selected underline (both use\n // box-shadow) so keyboard focus doesn't erase the active indicator.\n \"&:focus-visible\": {\n boxShadow: (l: Listener) => focusRing(l, accentColor),\n },\n \"&[aria-selected=true]:focus-visible\": {\n boxShadow: (l: Listener) =>\n `${focusRing(l, accentColor)}, inset 0 ${themeSpacing(-0.5)} 0 0 ${themeColor(l, \"shift-6\", accentColor)}`,\n },\n },\n } as DomphyElement<\"button\">;\n });\n\n const tablist: DomphyElement<\"div\"> = {\n div: buttons,\n _key: \"tablist\",\n role: \"tablist\",\n ariaOrientation: \"horizontal\",\n style: { display: \"flex\" },\n } as DomphyElement<\"div\">;\n\n const panels: DomphyElement<\"div\">[] = items.map((item, index) => {\n const key = item.key ?? index;\n return {\n div: [item.content],\n _key: key,\n role: \"tabpanel\",\n id: `panel${id}${key}`,\n ariaLabelledby: `tab${id}${key}`,\n // WAI-ARIA APG tabs pattern: the panel is the Tab stop after the\n // tablist, so panel content with no focusable element of its own is\n // still reachable and scrollable by keyboard (Radix Tabs.Content and\n // React Aria TabPanel both set tabindex=0 unconditionally).\n tabIndex: 0,\n hidden: (l: Listener) => activeKey.get(l) !== key,\n style: {\n paddingBlock: (l: Listener) => themeSpacing(themeDensity(l) * 2),\n paddingInline: (l: Listener) => themeSpacing(themeDensity(l) * 2),\n },\n } as DomphyElement<\"div\">;\n });\n\n return [tablist, ...panels];\n}\n\n/**\n * All-in-one tabs patch. Generates a `[role=tablist]` button row and\n * `[role=tabpanel]` panels from the `items` array. Apply to any wrapper\n * element (`div`, `section`, …). No companion `tab()` / `tabPanel()` needed.\n *\n * To control the active tab programmatically, pass an external `State` as\n * `activeKey` and call `.set()` on it from outside.\n *\n * @param props.items - Tab definitions `{ label, content, key? }`.\n * @param props.activeKey - Initially active key (value or State). Defaults to the first item's key.\n * @param props.accentColor - Theme color for the active underline indicator. Defaults to `\"primary\"`.\n * @param props.color - Theme color for the resting underline. Defaults to `\"neutral\"`.\n * @example\n * { div: null, $: [tabs({ items: [\n * { label: \"Overview\", content: { p: \"Overview content\" } },\n * { label: \"API\", content: { p: \"API content\" } },\n * ] })] }\n */\nfunction tabs(\n props: {\n items: TabItem[];\n activeKey?: ValueOrState<string | number>;\n accentColor?: ThemeColor;\n color?: ThemeColor;\n } = { items: [] },\n): PartialElement {\n const { items = [], accentColor = \"primary\", color = \"neutral\" } = props;\n const live: TabsLive = { items, accentColor, color };\n\n return {\n _onSchedule: (node, element) => {\n const activeKey = persistValue(\n node,\n \"tabsActiveKey\",\n props.activeKey,\n items[0]?.key ?? 0,\n );\n (element as Record<string, unknown>)[node.tagName] = buildTabsChildren(\n node,\n items,\n activeKey,\n accentColor,\n color,\n );\n },\n ...behavior<TabsLive>(\n \"tabs-items\",\n (node) => ({\n update(snapshot) {\n const activeKey = persistValue(\n node,\n \"tabsActiveKey\",\n props.activeKey,\n snapshot.items[0]?.key ?? 0,\n );\n node.children.update(\n buildTabsChildren(\n node,\n snapshot.items,\n activeKey,\n snapshot.accentColor,\n snapshot.color,\n ),\n !!node.domElement,\n true,\n );\n },\n }),\n live,\n ),\n };\n}\n\nexport { tabs };\nexport type { TabItem };\n","import {\n type BehaviorInstance,\n behavior,\n type PartialElement,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { fieldTextStyle } from \"../utils/fieldText.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/**\n * Styles a multi-line text input (border, focus/hover/invalid/disabled states)\n * on the host `<textarea>` element, with optional auto-resize to content.\n *\n * @hostTag textarea\n * @param props.color - Theme color for the border and text. Optional, accepts a value or state. Defaults to `\"neutral\"`.\n * @param props.accentColor - Theme color for hover/focus outline. Optional, accepts a value or state. Defaults to `\"primary\"`.\n * @param props.autoResize - When true, grows the textarea height to fit its content on input and when `value` updates, and remeasures when the host becomes visible (IntersectionObserver) and when its box size changes (ResizeObserver). Optional. Defaults to `false`.\n * @example { textarea: null, $: [textarea({ autoResize: true })] }\n */\nfunction textarea(\n props: {\n color?: ValueOrState<ThemeColor>;\n accentColor?: ValueOrState<ThemeColor>;\n autoResize?: boolean;\n } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n const accentColor = toState(props.accentColor ?? \"primary\", \"accentColor\");\n const { autoResize = false } = props;\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"textarea\") {\n console.warn(`\"textarea\" primitive patch must use textarea tag`);\n }\n },\n // Resize on mount, on input, and when the host `value` attribute updates\n // (controlled writes skip the input event).\n ...behavior(\n \"textarea-auto-resize\",\n (node, initial) => {\n const el = node.domElement as HTMLTextAreaElement;\n let enabled = initial.autoResize;\n let measuring = false;\n let intersectionObserver: IntersectionObserver | undefined;\n let resizeObserver: ResizeObserver | undefined;\n const resize = () => {\n if (!enabled || measuring) return;\n measuring = true;\n // Unobserve during the height write so ResizeObserver cannot\n // re-enter from the measure itself (jsdom may deliver RO sync).\n resizeObserver?.unobserve(el);\n el.style.overflow = \"hidden\";\n el.style.height = \"auto\";\n el.style.height = `${el.scrollHeight}px`;\n measuring = false;\n if (enabled) resizeObserver?.observe(el);\n };\n const observe = () => {\n if (typeof IntersectionObserver !== \"undefined\") {\n if (!intersectionObserver) {\n intersectionObserver = new IntersectionObserver((entries) => {\n if (entries.some((entry) => entry.isIntersecting)) resize();\n });\n }\n intersectionObserver.observe(el);\n }\n if (typeof ResizeObserver !== \"undefined\") {\n if (!resizeObserver) {\n resizeObserver = new ResizeObserver(() => {\n if (measuring) return;\n resize();\n });\n }\n resizeObserver.observe(el);\n }\n };\n const unobserve = () => {\n intersectionObserver?.unobserve(el);\n resizeObserver?.unobserve(el);\n };\n el.addEventListener(\"input\", resize);\n node.attributes.addListener(\"value\", resize);\n if (enabled) {\n observe();\n resize();\n }\n return {\n resize,\n update(next) {\n enabled = next.autoResize;\n node.attributes.addListener(\"value\", resize);\n if (enabled) {\n observe();\n resize();\n } else {\n unobserve();\n }\n },\n destroy() {\n el.removeEventListener(\"input\", resize);\n intersectionObserver?.disconnect();\n resizeObserver?.disconnect();\n },\n };\n },\n { autoResize },\n ),\n _onUpdate: (node) => {\n node\n .getBehavior<\n BehaviorInstance<{ autoResize: boolean }> & { resize: () => void }\n >(\"textarea-auto-resize\")\n ?.resize();\n },\n style: {\n lineHeight: \"inherit\",\n resize: \"vertical\",\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 2),\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n border: \"none\",\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n ...fieldTextStyle(color),\n outlineOffset: \"-1px\",\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", color.get(listener))}`,\n backgroundColor: (listener) =>\n themeColor(listener, \"inherit\", color.get(listener)),\n transition: \"outline-color 140ms ease, box-shadow 140ms ease\",\n \"&:hover:not([disabled]):not([aria-busy=true])\": {\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"shift-5\", accentColor.get(listener))}`,\n },\n \"&:focus-visible\": {\n boxShadow: (listener) => focusRing(listener, accentColor.get(listener)),\n },\n // Same gate as inputText: a bare `:invalid` painted a pristine untouched\n // `required` textarea red on first paint. `[placeholder]` +\n // `:not(:placeholder-shown)` means \"the user left content behind that is\n // invalid\"; a textarea with no placeholder uses `data-status` instead.\n \"&[placeholder]:invalid:not(:placeholder-shown)\": {\n outline: (listener) =>\n `${themeSpacing(0.5)} solid ${themeColor(listener, \"shift-5\", \"error\")}`,\n },\n // Explicit validation state, mirroring inputText's contract.\n \"&[data-status=error]\": {\n outline: (listener) =>\n `${themeSpacing(0.5)} solid ${themeColor(listener, \"shift-6\", \"error\")}`,\n },\n \"&[data-status=warning]\": {\n outline: (listener) =>\n `${themeSpacing(0.5)} solid ${themeColor(listener, \"shift-6\", \"warning\")}`,\n },\n \"&[disabled]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n color: (listener) => themeColor(listener, \"muted\", \"neutral\"),\n outline: (listener) =>\n `1px solid ${themeColor(listener, \"border-strong\", \"neutral\")}`,\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-2\", \"neutral\"),\n },\n },\n };\n}\n\nexport { textarea };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * Container for a vertical timeline. Sets list reset styles. Apply to `<ol>` or `<ul>`.\n *\n * @example { ol: [...], $: [timeline()] }\n */\nfunction timeline(): PartialElement {\n return {\n style: {\n listStyle: \"none\",\n margin: 0,\n padding: 0,\n display: \"flex\",\n flexDirection: \"column\",\n },\n };\n}\n\n/**\n * A single event row in a `timeline`. Uses a 2-column grid: the left column holds\n * a dot (`::before`) and optional connector line (`::after`); the right column holds\n * the user's content. Apply to `<li>`.\n *\n * @param props.active - Full-opacity dot (accent color). `ValueOrState<boolean>`, defaults to `false`.\n * @param props.last - Suppress the vertical connector below this item. `boolean`, defaults to `false`.\n * @param props.color - Dot/connector color tone. `ThemeColor`, defaults to `\"neutral\"`.\n * @param props.accentColor - Active dot color tone. `ThemeColor`, defaults to `\"primary\"`.\n * @example { li: [{ b: \"2024\" }, { p: \"Event\" }], $: [timelineItem({ active: true })] }\n */\nfunction timelineItem(\n props: {\n active?: ValueOrState<boolean>;\n last?: boolean;\n color?: ThemeColor;\n accentColor?: ThemeColor;\n } = {},\n): PartialElement {\n const { last = false } = props;\n const color = props.color ?? \"neutral\";\n const accentColor = props.accentColor ?? \"primary\";\n const activeState = toState(props.active ?? false);\n\n return {\n style: {\n display: \"grid\",\n gridTemplateColumns: \"2rem 1fr\",\n columnGap: (listener) => themeSpacing(themeDensity(listener) * 2),\n paddingBottom: (listener) =>\n last ? \"0\" : themeSpacing(themeDensity(listener) * 4),\n position: \"relative\",\n\n // Dot\n \"&::before\": {\n content: '\"\"',\n display: \"block\",\n width: \"0.75rem\",\n height: \"0.75rem\",\n borderRadius: \"50%\",\n justifySelf: \"center\",\n marginTop: themeSpacing(1),\n transition: \"background-color 200ms ease, opacity 200ms ease\",\n backgroundColor: (listener) =>\n themeColor(\n listener,\n \"shift-8\",\n activeState.get(listener) ? accentColor : color,\n ),\n opacity: (listener) => (activeState.get(listener) ? \"1\" : \"0.4\"),\n },\n\n // Vertical connector to the next item\n ...(last\n ? {}\n : {\n \"&::after\": {\n content: '\"\"',\n position: \"absolute\",\n insetInlineStart: \"calc(1rem - 1px)\",\n top: \"1.25rem\",\n bottom: (listener) => themeSpacing(themeDensity(listener) * -4),\n width: \"2px\",\n backgroundColor: (listener) =>\n themeColor(listener, \"shift-3\", color),\n },\n }),\n },\n };\n}\n\nexport { timeline, timelineItem };\n","import type {\n BehaviorInstance,\n DomphyElement,\n ElementNode,\n PartialElement,\n State,\n} from \"@domphy/core\";\nimport { behavior, toState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { elevation } from \"../utils/elevation.js\";\n\ntype ToastPosition =\n | \"top-left\"\n | \"top-center\"\n | \"top-right\"\n | \"bottom-left\"\n | \"bottom-center\"\n | \"bottom-right\";\n\n// The open state must live on the NODE, not in the factory closure: a toast\n// inside a reactive parent gets a fresh toast() closure per ancestor\n// re-render (fresh `toState(false)`), while `_onMount` (which flips the state\n// to visible via rAF) runs ONCE for the first generation. The reused node's\n// re-patched style bindings would read the new generation's still-false\n// state and snap the visible toast back to opacity 0 / translated out.\n// Resolving through node metadata gives every generation the SAME state.\nfunction resolveOpenState(node: ElementNode): State<boolean> {\n let state = node.getMetadata(\"toastOpen\") as State<boolean> | undefined;\n if (!state) {\n state = toState(false);\n node.setMetadata(\"toastOpen\", state);\n }\n return state;\n}\n\nconst readOpen = (listener: any): boolean => {\n const node = listener?.elementNode as ElementNode | undefined;\n return node ? resolveOpenState(node).get(listener) : false;\n};\n\n// Radix Toast Provider's documented default `duration` (ms) before a toast\n// dismisses itself. Sonner defaults to 4000ms instead; Radix's value is used\n// here since this patch's semantics (role=\"status\", one component owning its\n// own exit animation) already track Radix's Toast.Root more closely.\nconst DEFAULT_DURATION_MS = 5000;\n\ntype AutoDismissProps = {\n duration: number;\n onDismiss?: () => void;\n};\n\ntype AutoDismissInstance = BehaviorInstance<AutoDismissProps> & {\n pause: () => void;\n resume: () => void;\n};\n\n// Lives in a behavior() instance (not `_onMount`) for the same reason\n// resolveOpenState lives on node metadata above: a reactive ancestor\n// re-render gives the toast() factory a fresh closure over `duration`/\n// `onDismiss` on every generation, but `_onMount` only ever fires for the\n// FIRST one — a closure-captured timer would keep calling generation-1's\n// stale `onDismiss` (or never adopt a later `duration`) for the node's whole\n// life. `update()` routes every later generation's props into this SAME\n// instance instead.\nfunction _attachAutoDismiss(\n node: ElementNode,\n initial: AutoDismissProps,\n): AutoDismissInstance {\n let { duration, onDismiss } = initial;\n let timer: ReturnType<typeof setTimeout> | null = null;\n let remaining = duration;\n let startedAt = 0;\n let dismissed = false;\n\n const clearTimer = () => {\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n };\n const dismiss = () => {\n if (dismissed) return;\n dismissed = true;\n clearTimer();\n onDismiss?.();\n node.remove();\n };\n // duration <= 0 or non-finite (e.g. Infinity, Radix's \"never auto-dismiss\"\n // convention) means no timer at all.\n const arm = (ms: number) => {\n clearTimer();\n if (dismissed || !Number.isFinite(ms) || ms <= 0) return;\n startedAt = Date.now();\n timer = setTimeout(dismiss, ms);\n };\n\n arm(duration);\n\n // Pause/resume on hover/focus (Radix/Sonner parity): a toast whose\n // countdown elapses while the pointer is over it (or focus is inside it,\n // e.g. an action button) would otherwise vanish out from under the user\n // mid-read or mid-interaction. Wired directly on the node's own element —\n // pointerenter/pointerleave bracket a hover, focusin/focusout (which\n // bubble, unlike focus/blur) bracket focus landing anywhere inside.\n const pause = () => {\n if (!timer) return;\n remaining -= Date.now() - startedAt;\n clearTimer();\n };\n const resume = () => {\n if (dismissed || timer) return;\n arm(remaining);\n };\n const element = node.domElement;\n element?.addEventListener(\"pointerenter\", pause);\n element?.addEventListener(\"pointerleave\", resume);\n element?.addEventListener(\"focusin\", pause);\n element?.addEventListener(\"focusout\", resume);\n\n return {\n pause,\n resume,\n update(next) {\n duration = next.duration;\n onDismiss = next.onDismiss;\n // A running countdown keeps its own schedule — a new `duration` from a\n // later generation only takes effect on the next pause/resume cycle\n // (Radix: changing `duration` does not reset an in-flight toast).\n if (!timer && !dismissed) remaining = duration;\n },\n destroy() {\n clearTimer();\n element?.removeEventListener(\"pointerenter\", pause);\n element?.removeEventListener(\"pointerleave\", resume);\n element?.removeEventListener(\"focusin\", pause);\n element?.removeEventListener(\"focusout\", resume);\n },\n };\n}\n\n/**\n * Renders a transient notification surface as a fixed-position overlay (portaled\n * into a corner stack), animating in on mount and out before removal. Auto-dismisses\n * after `duration` (Radix/Sonner semantics), paused while hovered or focused. No host\n * tag check; typically applied to a `<div>`.\n *\n * @param props.position - Corner of the screen for the toast stack. Optional, one of `\"top-left\" | \"top-center\" | \"top-right\" | \"bottom-left\" | \"bottom-center\" | \"bottom-right\"`. Defaults to `\"top-center\"`.\n * @param props.color - Theme color for the toast surface. Optional. Defaults to `\"neutral\"`.\n * @param props.duration - Milliseconds before the toast dismisses itself (calls `onDismiss` then removes itself). Pass `Infinity` or `0` to disable. Optional. Defaults to `5000`.\n * @param props.onDismiss - Called once, right before the toast removes itself, when `duration` elapses without the pointer/focus inside it. Optional — a caller tracking its own toast list should use this to drop the entry from state.\n * @example { div: \"Saved!\", $: [toast({ position: \"top-right\" })] }\n */\nfunction toast(\n props: {\n position?: ToastPosition;\n color?: ThemeColor;\n duration?: number;\n onDismiss?: () => void;\n } = {},\n): PartialElement {\n const {\n position = \"top-center\",\n color = \"neutral\",\n duration = DEFAULT_DURATION_MS,\n onDismiss,\n } = props;\n\n const isTop = position.startsWith(\"top\");\n const isCenter = position.endsWith(\"center\");\n const isRight = position.endsWith(\"right\");\n\n const overlayEle: DomphyElement<\"div\"> = {\n div: [],\n id: `domphy-toast-${position}`,\n style: {\n position: \"fixed\",\n display: \"flex\",\n flexDirection: isTop ? \"column\" : \"column-reverse\",\n alignItems: isCenter ? \"center\" : isRight ? \"end\" : \"start\",\n inset: 0,\n gap: themeSpacing(4),\n zIndex: 30,\n padding: themeSpacing(6),\n pointerEvents: \"none\",\n },\n };\n\n return {\n ...behavior(\"toastAutoDismiss\", _attachAutoDismiss, {\n duration,\n onDismiss,\n }),\n _portal: (rootNode) => {\n let overlay = rootNode.domElement!.querySelector(\n `#domphy-toast-${position}`,\n );\n if (!overlay) {\n const overlayNode = rootNode.children!.insert(\n overlayEle,\n ) as ElementNode;\n overlay = overlayNode.domElement!;\n }\n return overlay;\n },\n role: \"status\",\n ariaAtomic: \"true\",\n // Toast is rendered as an overlay surface, so it uses the inverted branch.\n dataTone: \"shift-17\",\n style: {\n minWidth: themeSpacing(32),\n pointerEvents: \"auto\",\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 2),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 4),\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 2),\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n color: (listener) => themeColor(listener, \"text\", color),\n backgroundColor: (listener) => themeColor(listener, \"inherit\", color),\n boxShadow: elevation(\"medium\"),\n opacity: (listener) => Number(readOpen(listener)),\n transform: (listener) =>\n readOpen(listener)\n ? \"translateY(0)\"\n : isTop\n ? \"translateY(-100%)\"\n : \"translateY(100%)\",\n transition: \"opacity 300ms ease, transform 300ms ease\",\n },\n _onMount: (node) =>\n requestAnimationFrame(() => resolveOpenState(node).set(true)),\n _onBeforeRemove: (node, done) => {\n let finished = false;\n let timer: ReturnType<typeof setTimeout> | null = null;\n let overlayRemoved = false;\n const rootNode = node.getRoot();\n const overlayEl = node.domElement?.parentElement ?? null;\n // The #domphy-toast-{position} overlay is inserted into the root on\n // first use and shared by every toast at that position — remove it once\n // its LAST toast is gone instead of leaking one empty fixed container\n // per used position for the app's whole lifetime.\n const removeOverlayIfEmpty = () => {\n if (overlayRemoved) return;\n if (\n !overlayEl ||\n overlayEl.id !== `domphy-toast-${position}` ||\n overlayEl.childElementCount > 0\n ) {\n return;\n }\n overlayRemoved = true;\n const item = rootNode.children?.items.find(\n (it) => (it as ElementNode).domElement === overlayEl,\n );\n if (item) rootNode.children!.remove(item);\n else overlayEl.remove();\n };\n const finish = () => {\n if (finished) return;\n finished = true;\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n node.domElement!.removeEventListener(\"transitionend\", onEnd);\n done();\n removeOverlayIfEmpty();\n };\n const onEnd = (e: Event) => {\n if ((e as TransitionEvent).propertyName === \"transform\") finish();\n };\n node.domElement!.addEventListener(\"transitionend\", onEnd);\n // Fallback: if transitionend never fires (reduced-motion, display:none,\n // early detach), unblock removal after the transition duration + buffer.\n timer = setTimeout(finish, 350);\n // If the node is detached before the exit animation settles, clear the\n // pending fallback timer and the transitionend listener so they cannot\n // fire on a removed node.\n node.addHook(\"Remove\", () => {\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n node.domElement?.removeEventListener(\"transitionend\", onEnd);\n removeOverlayIfEmpty();\n });\n resolveOpenState(node).set(false);\n },\n };\n}\n\nexport { toast };\n","import {\n behavior,\n type DomphyElement,\n type ElementNode,\n isState,\n type Listener,\n type PartialElement,\n type State,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { horizontalArrowStep } from \"../utils/direction.js\";\nimport { focusRing } from \"../utils/focusRing.js\";\n\n/** One item inside a toggle group. */\ntype ToggleItem = {\n /** Button label — plain string (auto-wrapped) or any DomphyElement. */\n label: string | DomphyElement;\n /** Stable key. Defaults to the item's zero-based index as a string. */\n key?: string;\n};\n\ntype ToggleLive = {\n items: ToggleItem[];\n multiple: boolean;\n color: ThemeColor;\n accentColor: ThemeColor;\n};\n\nfunction persistValue<T>(\n node: ElementNode,\n key: string,\n incoming: ValueOrState<T> | undefined,\n fallback: T,\n): State<T> {\n if (isState(incoming)) {\n node.setMetadata(key, incoming);\n return incoming as State<T>;\n }\n let stored = node.getMetadata(key) as State<T> | undefined;\n if (!stored) {\n stored = toState((incoming as T | undefined) ?? fallback);\n node.setMetadata(key, stored);\n }\n return stored;\n}\n\nfunction isPressed(val: string | string[], key: string): boolean {\n return Array.isArray(val) ? val.includes(key) : val === key;\n}\n\nfunction moveToggle(\n e: Event,\n items: ToggleItem[],\n key: string,\n value: State<string | string[]>,\n multiple: boolean,\n): void {\n const k = (e as KeyboardEvent).key;\n // WAI-ARIA APG toolbar/radio navigation: both axes move (Right/Down = next,\n // Left/Up = previous), Home/End jump to the ends.\n if (\n ![\n \"ArrowLeft\",\n \"ArrowRight\",\n \"ArrowUp\",\n \"ArrowDown\",\n \"Home\",\n \"End\",\n ].includes(k)\n )\n return;\n e.preventDefault();\n const keys = items.map((item, index) => item.key ?? String(index));\n const idx = keys.indexOf(key);\n let next = idx;\n if (k === \"ArrowDown\") next = (idx + 1) % keys.length;\n else if (k === \"ArrowUp\") next = (idx - 1 + keys.length) % keys.length;\n else if (k === \"ArrowRight\" || k === \"ArrowLeft\") {\n const step = horizontalArrowStep(k, e.target as Element);\n next = (idx + step + keys.length) % keys.length;\n } else if (k === \"Home\") next = 0;\n else if (k === \"End\") next = keys.length - 1;\n if (!multiple) value.set(keys[next]);\n const group = (e.target as HTMLElement).closest(\"[role=group]\");\n group?.querySelectorAll<HTMLElement>(\"button\")[next]?.focus();\n}\n\nfunction buildToggleButtons(\n items: ToggleItem[],\n value: State<string | string[]>,\n focusedKey: State<string | null>,\n multiple: boolean,\n color: ThemeColor,\n accentColor: ThemeColor,\n): DomphyElement<\"button\">[] {\n return items.map((item, index) => {\n const key = item.key ?? String(index);\n const labelEl: DomphyElement =\n typeof item.label === \"string\"\n ? ({ span: item.label } as DomphyElement<\"span\">)\n : item.label;\n\n return {\n button: [labelEl],\n _key: key,\n type: \"button\",\n role: \"button\",\n ariaPressed: (l: Listener) => isPressed(value.get(l), key),\n // Roving tab stop: the last-focused item, like single-select mode and\n // the menu/tabs patches (WAI-ARIA APG). Falls back to the first\n // selected item, then the first item, until focus has landed once.\n tabIndex: (l: Listener) => {\n const val = value.get(l);\n if (multiple) {\n const focused = focusedKey.get(l);\n if (focused !== null) return key === focused ? 0 : -1;\n const arr = Array.isArray(val) ? val : [];\n const fallback = arr[0] ?? items[0]?.key ?? \"0\";\n return key === fallback ? 0 : -1;\n }\n if (val === key) return 0;\n if (val === \"\" && key === (items[0]?.key ?? \"0\")) return 0;\n return -1;\n },\n onFocus: () => focusedKey.set(key),\n onClick: () => {\n const val = value.get();\n if (multiple) {\n const arr = Array.isArray(val) ? [...val] : [];\n value.set(\n arr.includes(key) ? arr.filter((v) => v !== key) : [...arr, key],\n );\n } else {\n value.set(val === key ? \"\" : key);\n }\n },\n onKeyDown: (e: Event) => moveToggle(e, items, key, value, multiple),\n style: {\n cursor: \"pointer\",\n fontSize: (l: Listener) => themeSize(l, \"inherit\"),\n // Fixed height, label centred by flex: with a fixed height and block\n // padding the inherited line box overflowed the content box downward\n // whenever the host font was larger than the base size.\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: themeSpacing(6),\n paddingBlock: 0,\n paddingInline: themeSpacing(2),\n border: \"none\",\n borderRadius: themeSpacing(1.5),\n // Unpressed: shift-13 for readable resting labels (catalog contrast).\n color: (l: Listener) => themeColor(l, \"shift-13\", color),\n backgroundColor: (l: Listener) => themeColor(l, \"inherit\", color),\n transition:\n \"background-color 140ms ease, color 140ms ease, box-shadow 140ms ease\",\n \"&:hover:not([disabled]):not([aria-pressed=true])\": {\n color: (l: Listener) => themeColor(l, \"shift-13\", color),\n backgroundColor: (l: Listener) => themeColor(l, \"hover\", color),\n },\n \"&:active:not([disabled])\": {\n backgroundColor: (l: Listener) => themeColor(l, \"increase-2\", color),\n },\n \"&[aria-pressed=true]\": {\n backgroundColor: (l: Listener) =>\n themeColor(l, \"shift-3\", accentColor),\n color: (l: Listener) => themeColor(l, \"shift-13\", accentColor),\n },\n \"&:focus-visible\": {\n boxShadow: (l: Listener) => focusRing(l, accentColor),\n },\n \"&[disabled]\": {\n opacity: 0.7,\n cursor: \"not-allowed\",\n },\n },\n } as DomphyElement<\"button\">;\n });\n}\n\n/**\n * All-in-one toggle group — single or multi-select button group. Generates\n * `<button>` toggle elements from the `items` array. Apply to any wrapper element.\n *\n * @param props.items - Item definitions `{ label, key? }`.\n * @param props.value - Selected key(s) (value or State). Defaults to `[]` (multiple) or `\"\"` (single).\n * @param props.multiple - Allow multiple items selected at once. Defaults to `false`.\n * @param props.color - Theme color for the group background/border. Defaults to `\"neutral\"`.\n * @param props.accentColor - Theme color for the pressed state. Defaults to `\"primary\"`.\n * @example\n * { div: null, $: [toggleGroup({ multiple: true, items: [\n * { label: \"Bold\", key: \"bold\" },\n * { label: \"Italic\", key: \"italic\" },\n * ] })] }\n */\nfunction toggleGroup(\n props: {\n items: ToggleItem[];\n value?: ValueOrState<string | string[]>;\n multiple?: boolean;\n color?: ThemeColor;\n accentColor?: ThemeColor;\n } = { items: [] },\n): PartialElement {\n const {\n items = [],\n multiple = false,\n color = \"neutral\",\n accentColor = \"primary\",\n } = props;\n const live: ToggleLive = { items, multiple, color, accentColor };\n\n return {\n role: \"group\",\n _onSchedule: (node, element) => {\n const value = persistValue(\n node,\n \"toggleGroupValue\",\n props.value,\n multiple ? [] : \"\",\n );\n // Publish the SAME state the buttons write to — see segmented.ts for why\n // a declared `_context` could not (disconnected State + notifier clobber\n // when ElementNode.patch re-merges `element._context`).\n node.setContext(\"toggleGroup\", { value, multiple });\n const focusedKey = persistValue<string | null>(\n node,\n \"toggleGroupFocusedKey\",\n undefined,\n null,\n );\n (element as Record<string, unknown>)[node.tagName] = buildToggleButtons(\n items,\n value,\n focusedKey,\n multiple,\n color,\n accentColor,\n );\n },\n ...behavior<ToggleLive>(\n \"toggle-items\",\n (node) => ({\n update(snapshot) {\n const value = persistValue(\n node,\n \"toggleGroupValue\",\n props.value,\n snapshot.multiple ? [] : \"\",\n );\n const focusedKey = persistValue<string | null>(\n node,\n \"toggleGroupFocusedKey\",\n undefined,\n null,\n );\n node.children.update(\n buildToggleButtons(\n snapshot.items,\n value,\n focusedKey,\n snapshot.multiple,\n snapshot.color,\n snapshot.accentColor,\n ),\n !!node.domElement,\n true,\n );\n },\n }),\n live,\n ),\n style: {\n display: \"flex\",\n paddingBlock: themeSpacing(1),\n paddingInline: themeSpacing(1),\n gap: themeSpacing(1),\n borderRadius: themeSpacing(2),\n fontSize: (l: Listener) => themeSize(l, \"inherit\"),\n backgroundColor: (l: Listener) => themeColor(l, \"inherit\", color),\n color: (l: Listener) => themeColor(l, \"text\", color),\n outline: (l: Listener) => `1px solid ${themeColor(l, \"border\", color)}`,\n outlineOffset: \"-1px\",\n },\n };\n}\n\nexport { toggleGroup };\nexport type { ToggleItem };\n","import type { DomphyElement, PartialElement } from \"@domphy/core\";\nimport { row } from \"./row.js\";\nimport type { FlexAlign, FlexJustify } from \"./stack.js\";\n\n/**\n * A horizontal flex row with vertically centered items. Useful for headers,\n * toolbars, navigation bars, and action strips. A semantic alias of `row()`;\n * wrap/justify/align/density are forwarded so callers do not drop down to\n * hand-rolled flex.\n *\n * @param props.gap - Spacing multiplier for gap between items (default 4).\n * Bounded-control mode (`density: true`, default): `themeSpacing(themeDensity(l) * gap)`.\n * Structural mode (`density: false`): bare `themeSpacing(gap)`.\n * @param props.wrap - Allow items to wrap onto multiple lines. Defaults to `false`.\n * @param props.justify - Main-axis distribution (`justifyContent`). Unset by default.\n * @param props.align - Cross-axis alignment (`alignItems`). Defaults to `\"center\"` (row default).\n * @param props.density - When true (default), gap is multiplied by theme density.\n * When false, gap is structural `themeSpacing(n)`.\n * @example { header: [...], $: [toolbar()] }\n * @example { nav: [...], $: [toolbar({ gap: 3 })] }\n * @example { header: [...], $: [toolbar({ wrap: true, justify: \"space-between\" })] }\n */\nfunction toolbar(\n props: {\n gap?: number;\n wrap?: boolean;\n justify?: FlexJustify;\n align?: FlexAlign;\n density?: boolean;\n } = {},\n): PartialElement {\n return row(props);\n}\n\n/**\n * A flex spacer that expands to fill available space in a toolbar, pushing\n * subsequent items to the far end.\n *\n * @example { header: [logo, toolbarSpacer(), nav, actions], $: [toolbar()] }\n */\nfunction toolbarSpacer(): DomphyElement {\n return { div: null, style: { flex: \"1 1 0\" } };\n}\n\nexport { toolbar, toolbarSpacer };\n","import {\n type DomphyElement,\n merge,\n type PartialElement,\n toState,\n type ValueOrState,\n} from \"@domphy/core\";\nimport type { Placement } from \"@domphy/floating\";\nimport {\n themeColor,\n themeDensity,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\nimport { elevation } from \"../utils/elevation.js\";\nimport { createFloating, floatingPanelId } from \"../utils/floating.js\";\nimport { popoverArrow } from \"./popoverArrow.js\";\n\n/**\n * Attaches a floating tooltip to the host element, shown on hover/focus and\n * hidden on leave/blur/Escape. Returns the anchor (trigger) partial; the tooltip\n * surface is positioned via the floating utility and linked with\n * `aria-describedby`. No host tag check; applied to the trigger element.\n *\n * @param props.open - Controlled open state (`ValueOrState<boolean>`), including `Computed`/`ReadableState`. When the source is read-only, pass `onDismiss` so leave/blur/Escape can close. Optional. Defaults to `false`.\n * @param props.onDismiss - Called when the tooltip requests close. Optional. Required to close when `open` is a read-only `Computed`/`ReadableState`.\n * @param props.placement - Floating placement relative to the trigger. Optional, accepts a value or state (`Placement`). Defaults to `\"top\"`.\n * @param props.content - Tooltip text content. Optional, accepts a value or state (string only). Defaults to `\"Tooltip Content\"`.\n * @param props.openDelay - Hover/focus-intent delay before showing, in ms (Radix `delayDuration` parity). Optional. Defaults to 100.\n * @param props.closeDelay - Delay before hiding after leave/blur, in ms. Optional. Defaults to 100.\n * @example { button: \"Hover me\", $: [tooltip({ content: \"Help text\" })] }\n */\nfunction tooltip(\n props: {\n open?: ValueOrState<boolean>;\n onDismiss?: () => void;\n placement?: ValueOrState<Placement>;\n content?: ValueOrState<string>;\n openDelay?: number;\n closeDelay?: number;\n } = {},\n): PartialElement {\n const {\n open = false,\n placement = \"top\",\n content = \"Tooltip Content\",\n openDelay,\n closeDelay,\n } = props;\n\n const placeState = toState(placement);\n const contentState = toState(content);\n\n // The tooltip id is NOT pre-generated here: a factory-scope id (previously\n // Math.random()-based) churns per generation and mismatches SSR/hydration.\n // Instead the shared floating behavior stamps a deterministic id derived\n // from the anchor's nodeId when the panel mounts (see floating.ts), and the\n // trigger references the same id via _onSchedule below.\n const contentElement: DomphyElement<\"span\"> = {\n span: (listener) => contentState.get(listener),\n };\n\n const { show, hide, anchorPartial, openState } = createFloating({\n kind: \"tooltip\",\n open,\n onDismiss: props.onDismiss,\n placement: placeState,\n content: contentElement,\n openDelay,\n closeDelay,\n });\n\n const tooltipPartial: PartialElement = {\n role: \"tooltip\",\n dataSize: \"decrease-1\",\n dataTone: \"shift-17\",\n style: {\n paddingBlock: (listener) => themeSpacing(themeDensity(listener) * 1),\n paddingInline: (listener) => themeSpacing(themeDensity(listener) * 3),\n borderRadius: (listener) => themeSpacing(themeDensity(listener) * 1.5),\n color: (listener) => themeColor(listener, \"text\"),\n backgroundColor: (listener) => themeColor(listener),\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n boxShadow: elevation(\"low\"),\n },\n $: [popoverArrow({ placement: placeState, bordered: false })],\n };\n contentElement.$ ||= [];\n contentElement.$.push(tooltipPartial);\n\n const triggerPartial: PartialElement = {\n // Declared as a reactive attribute (listener.elementNode is the anchor) so\n // it is re-declared on every patch (patch() strips attributes that are no\n // longer declared, so imperative wiring would not survive re-render).\n // Only points at the panel while it is actually open — Radix sets\n // aria-describedby the same way; a dangling reference to a closed panel's\n // id (removed from the DOM between shows) is an id-not-found reference\n // for the whole time the tooltip is hidden.\n ariaDescribedby: (listener) =>\n listener?.elementNode && openState.get(listener)\n ? floatingPanelId(\"tooltip\", listener.elementNode)\n : undefined,\n onMouseEnter: (_e, node) => show(node),\n onMouseLeave: (_e, node) => hide(node),\n onFocus: (_e, node) => show(node),\n onBlur: (_e, node) => hide(node),\n onKeyDown: (e, node) => (e as KeyboardEvent).key === \"Escape\" && hide(node),\n };\n\n merge(anchorPartial, triggerPartial);\n\n return anchorPartial;\n}\n\nexport { tooltip };\n","import { ElementNode, type PartialElement } from \"@domphy/core\";\nimport { prefersReducedMotion } from \"../utils/reducedMotion.js\";\n\ntype RectMap = Map<string, DOMRect>;\n\nfunction getItemId(node: ElementNode, index: number): string {\n if (node.key !== undefined && node.key !== null) {\n return String(node.key);\n }\n return `index-${index}`;\n}\n\n/**\n * Animates child reordering using the FLIP technique: records each child's\n * position before an update and smoothly transitions it from its old to new\n * position afterward. No host tag check; applied to the list container.\n *\n * @param props.duration - Transition duration in milliseconds. Optional. Defaults to `300`.\n * @param props.delay - Transition delay in milliseconds. Optional. Defaults to `0`.\n * @example { ul: null, $: [transitionGroup({ duration: 300 })] }\n */\nfunction transitionGroup(\n props: { duration?: number; delay?: number } = {},\n): PartialElement {\n const { duration = 300, delay = 0 } = props;\n\n let previousRects: RectMap = new Map();\n // Cancels any in-flight animation for a given DOM element before starting a new one.\n const cancelMap = new Map<HTMLElement, () => void>();\n // Pending fallback timers and queued rAF callbacks, tracked so a removal of\n // the container mid-animation can clear them instead of firing on a detached node.\n const pendingTimers = new Set<ReturnType<typeof setTimeout>>();\n const pendingFrames = new Set<number>();\n\n return {\n _onMount: (node) => {\n node.addHook(\"Remove\", () => {\n // Stop every in-flight animation: removes transitionend listeners.\n for (const cancel of Array.from(cancelMap.values())) cancel();\n cancelMap.clear();\n // Clear queued fallback timers.\n for (const timer of pendingTimers) clearTimeout(timer);\n pendingTimers.clear();\n // Cancel queued animation frames.\n for (const frame of pendingFrames) cancelAnimationFrame(frame);\n pendingFrames.clear();\n });\n },\n _onBeforeUpdate: (node) => {\n previousRects = new Map();\n // A FLIP reorder is exactly the large motion prefers-reduced-motion\n // exists for (WCAG 2.3.3 Animation from Interactions); with no captured\n // rects _onUpdate is a no-op per item, so the reorder lands instantly —\n // the same degradation motion() and every peer (framer-motion Reorder,\n // React Aria, Mantine Transition) applies.\n if (prefersReducedMotion()) return;\n node.children.items.forEach((item, index) => {\n if (!(item instanceof ElementNode)) return;\n const dom = item.domElement as HTMLElement | undefined;\n if (!dom) return;\n previousRects.set(getItemId(item, index), dom.getBoundingClientRect());\n });\n },\n _onUpdate: (node) => {\n node.children.items.forEach((item, index) => {\n if (!(item instanceof ElementNode)) return;\n const dom = item.domElement as HTMLElement | undefined;\n if (!dom) return;\n\n const key = getItemId(item, index);\n const prev = previousRects.get(key);\n if (!prev) return;\n\n const next = dom.getBoundingClientRect();\n const deltaX = prev.left - next.left;\n const deltaY = prev.top - next.top;\n if (Math.abs(deltaX) < 0.5 && Math.abs(deltaY) < 0.5) return;\n\n // Cancel any in-flight animation on this element before starting a new one.\n cancelMap.get(dom)?.();\n\n dom.style.transition = \"none\";\n dom.style.transform = `translate(${deltaX}px, ${deltaY}px)`;\n dom.getBoundingClientRect();\n\n const frame = requestAnimationFrame(() => {\n pendingFrames.delete(frame);\n dom.style.transition = `transform ${duration}ms ease ${delay}ms`;\n dom.style.transform = \"translate(0px, 0px)\";\n });\n pendingFrames.add(frame);\n\n let cancelled = false;\n let timer: ReturnType<typeof setTimeout> | null = null;\n const finish = () => {\n if (cancelled) return;\n cancelled = true;\n if (timer) {\n pendingTimers.delete(timer);\n timer = null;\n }\n cancelMap.delete(dom);\n dom.removeEventListener(\"transitionend\", onEnd);\n dom.style.transition = \"\";\n dom.style.transform = \"\";\n };\n\n const onEnd = (event: Event) => {\n if ((event as TransitionEvent).propertyName === \"transform\") finish();\n };\n\n cancelMap.set(dom, () => {\n cancelled = true;\n if (timer) {\n clearTimeout(timer);\n pendingTimers.delete(timer);\n timer = null;\n }\n cancelMap.delete(dom);\n dom.removeEventListener(\"transitionend\", onEnd);\n });\n\n dom.addEventListener(\"transitionend\", onEnd);\n timer = setTimeout(finish, duration + delay + 34);\n pendingTimers.add(timer);\n });\n previousRects.clear();\n },\n };\n}\n\nexport { transitionGroup };\n","import { type PartialElement, toState, type ValueOrState } from \"@domphy/core\";\nimport {\n type ThemeColor,\n themeColor,\n themeSize,\n themeSpacing,\n} from \"@domphy/theme\";\n\n/**\n * Styles a bulleted list (disc markers, reset margins, themed text) on the host\n * `<ul>` element.\n *\n * @hostTag ul\n * @param props.color - Theme color for the list text. Optional, accepts a value or state. Defaults to `\"neutral\"`.\n * @example { ul: null, $: [unorderedList()] }\n */\nfunction unorderedList(\n props: { color?: ValueOrState<ThemeColor> } = {},\n): PartialElement {\n const color = toState(props.color ?? \"neutral\", \"color\");\n\n return {\n _onInsert: (node) => {\n if (node.tagName !== \"ul\") {\n console.warn(`\"unorderedList\" primitive patch must use ul tag`);\n }\n },\n style: {\n fontSize: (listener) => themeSize(listener, \"inherit\"),\n backgroundColor: (listener) => themeColor(listener),\n color: (listener) => themeColor(listener, \"text\", color.get(listener)),\n marginTop: 0,\n marginBottom: 0,\n paddingInlineStart: themeSpacing(3),\n listStyleType: \"disc\",\n listStylePosition: \"outside\",\n },\n };\n}\n\nexport { unorderedList };\n","import type { PartialElement } from \"@domphy/core\";\n\n/**\n * Visually hides an element while keeping it in the accessibility tree — the\n * classic \"sr-only\" recipe for screen-reader-only labels, live-region text,\n * and skip links (before focus). Styles the host only; apply to any element.\n *\n * @example { span: \"Opens in a new tab\", $: [visuallyHidden()] }\n */\nfunction visuallyHidden(): PartialElement {\n return {\n style: {\n position: \"absolute\",\n width: \"1px\",\n height: \"1px\",\n padding: \"0\",\n margin: \"-1px\",\n overflow: \"hidden\",\n clip: \"rect(0, 0, 0, 0)\",\n whiteSpace: \"nowrap\",\n border: \"0\",\n },\n };\n}\n\nexport { visuallyHidden };\n"],"mappings":"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","names":["index_exports","__export","abbreviation","accordion","alert","avatar","badge","blockquote","breadcrumb","breadcrumbEllipsis","button","buttonGhost","buttonSwitch","card","code","combobox","command","commandItem","commandSearch","datePicker","descriptionList","details","dialog","divider","drawer","elevation","emphasis","empty","errorBoundary","fab","figure","focusRing","formGroup","grid","heading","horizontalRule","icon","image","inputCheckbox","inputColor","inputDateTime","inputFile","inputNumber","inputOTP","inputPassword","inputRadio","inputRange","inputSearch","inputSwitch","inputText","keyboard","label","link","linkButton","list","listItem","listItemButton","mark","menu","motion","orderedList","pagination","panelSection","paragraph","popover","popoverArrow","preformated","progress","rating","ringProgress","row","scrollArea","segmented","select","selectBox","selectItem","selectList","skeleton","small","spinner","splitter","splitterHandle","splitterPanel","stack","steps","strong","subscript","superscript","table","tabs","tag","textarea","timeline","timelineItem","toast","toggleGroup","toolbar","toolbarSpacer","tooltip","transitionGroup","unorderedList","visuallyHidden","__toCommonJS","import_core","import_theme","abbreviation","props","_a","_b","color","accentColor","node","listener","import_core","import_theme","import_theme","focusRing","listener","color","gap","ring","accordion","props","_a","_b","type","color","accentColor","node","el","handler","event","summary","item","detail","onKeyDown","key","summaries","index","next","listener","focusRing","import_core","import_theme","alert","props","_a","color","listener","import_core","import_theme","avatar","props","_a","color","listener","import_core","import_theme","badge","props","_a","label","state","color","l","import_core","import_theme","blockquote","props","_a","color","node","listener","import_core","import_theme","breadcrumb","props","_a","separator","color","node","listener","import_core","import_theme","breadcrumbEllipsis","props","_a","color","node","listener","focusRing","import_core","import_theme","BUTTON_SIZE_FONT","import_core","import_theme","PADDING_STEPS","buttonGhost","props","_a","_b","_c","color","padding","fontSize","BUTTON_SIZE_FONT","node","listener","focusRing","PADDING_STEPS","button","props","_a","_b","_c","_d","variant","buttonGhost","color","isSolid","padding","fontSize","BUTTON_SIZE_FONT","__spreadProps","__spreadValues","node","listener","focusRing","import_core","import_theme","buttonSwitch","props","_a","_b","checked","check","color","accentColor","node","listener","focusRing","import_core","import_theme","SHADOWS","elevation","level","card","props","_a","color","listener","elevation","import_core","import_theme","code","props","_a","color","node","listener","import_core","import_theme","import_core","import_theme","PLACEHOLDER_TONE","VALUE_TONE","fieldTextStyle","color","colorState","listener","import_core","import_floating","import_core","isWritableState","source","subscribeOpen","onChange","emitCurrent","skipInitial","release","value","writeOpen","dismissOpen","onDismiss","asOpenState","open","FLOATING_DEFAULT_DELAY_MS","floatingPanelId","kind","node","OVERLAY_ATTRIBUTE","OVERLAY_SELECTOR","OVERLAY_KIND_ATTRIBUTE","hasOpenFloatingPanel","dialogElement","overlay","child","attachFloating","initialProps","_a","_b","_c","_d","openState","onDismiss","placement","content","keepOpenOnContentHover","openDelay","closeDelay","behaviorKey","timer","cleanup","floating","floatingNode","mounted","reference","rootNode","panelId","floatingPartial","listener","event","isTopLayer","hide","show","mountedNode","dataTheme","rNode","dialogHost","overlayEle","wireContent","target","ensureMounted","instance","detachPanel","instantShow","x","y","resolved","writeOpen","focusIsInsidePanel","active","focusReference","instantHide","restoreFocus","dismissOpen","handleOutside","handleEscape","escapeTarget","onOpen","val","release","destroyed","updating","stampPanelBehavior","__spreadProps","__spreadValues","props","subscribeOpen","createFloating","asOpenState","anchorPartial","e","enabledOptionsIn","root","el","import_core","import_theme","xSvg","DEFAULT_DENSITY","TAG_HEIGHT","TAG_PAD_INLINE","TAG_PAD_END_REMOVABLE","TAG_REMOVE","TAG_REMOVE_RADIUS","tag","props","_a","removable","color","__spreadProps","__spreadValues","node","initial","removeHost","makeButton","e","event","listener","focusRing","findButton","item","sync","next","existing","combobox","props","options","placement","color","open","multiple","state","openState","show","hide","anchorPartial","createFloating","popoverPartial","_e","node","listener","elevation","inputStyle","__spreadProps","__spreadValues","fieldTextStyle","readQuery","_a","_b","findComboboxAnchor","from","current","moveIntoPanel","toLast","anchor","root","panel","floatingPanelId","enabledOptionsIn","target","openThenMove","release","subscribeOpen","isOpen","inputAria","event","key","buildInput","custom","buildWrap","inner","val","vals","items","opt","tag","_node","cur","filter","v","partial","element","_inner","query","next","focusRing","import_core","import_theme","visibleItems","host","el","onCommandKey","event","node","_a","key","items","active","current","next","target","command","_node","element","commandSearch","props","color","accentColor","ctx","input","onInput","__spreadProps","__spreadValues","listener","fieldTextStyle","focusRing","commandItem","applyFilter","q","_b","text","release","import_core","import_theme","atMidnight","date","addDays","count","addMonths","sameDay","a","b","isoOf","startOfWeek","weekStart","localeWeekStart","locale","_a","_b","localeObject","info","attachDatePicker","_node","initialProps","current","releaseOnChange","subscribe","props","value","carryForward","next","prev","datePicker","_c","_d","mode","time","min","max","disabledDate","format","onChange","accentColor","placeState","selection","primaryDate","base","viewYear","viewMonth","focused","hovered","hour","minute","dateFormatter","__spreadValues","monthFormatter","weekdayFormatter","fullDateFormatter","formatOne","formatDisplay","start","end","weekdayNames","_unused","index","isDisabled","withTime","result","selectDate","node","hide","reapplyTime","inSelectedRange","listener","tail","low","high","day","isSelectedEnd","goToDate","shiftMonth","delta","shiftYear","focusActiveCell","root","calendar","buildCalendar","openState","show","anchorPartial","createFloating","triggerPartial","floatingPanelId","_e","openAndFocus","event","key","isSelectedPrimary","navButton","label","ariaLabel","onClick","navButtonStyle","header","weekdayHeader","name","gridRowStyle","grid","buildWeeks","onGridKey","children","buildTimeRow","buildFooter","elevation","first","month","weeks","week","cells","buildDayCell","disabled","selected","within","outside","isFocused","isToday","l","focusRing","numberSelect","state","timeSelectStyle","action","today","keyboard","import_core","import_theme","descriptionList","props","_a","color","node","listener","import_core","import_theme","details","props","_a","_b","duration","color","accentColor","node","listener","focusRing","import_core","import_theme","lockCount","lockScroll","unlockScroll","FOCUSABLE","attachDialog","node","initialProps","state","onDismiss","previousFocus","closing","scrollLocked","closeTimer","dlg","finalizeClose","unlockScroll","trapFocus","e","focusables","el","first","last","onCancel","hasOpenFloatingPanel","dismissOpen","update","val","lockScroll","_a","focusable","release","subscribeOpen","props","dialog","color","open","labelledBy","describedBy","asOpenState","__spreadProps","__spreadValues","r","listener","elevation","import_core","import_theme","divider","props","_a","color","node","listener","import_core","import_theme","translateOut","marginMap","isVertical","p","resolvePhysical","placement","isRTL","attachDrawer","node","initialProps","state","onDismiss","size","dlg","onCancel","e","hasOpenFloatingPanel","dismissOpen","resolve","nextPlacement","nextSize","physical","drawerSize","closing","scrollLocked","closeTimer","finishClose","unlockScroll","onTransitionEnd","update","val","lockScroll","release","subscribeOpen","props","drawer","color","open","asOpenState","physicalFallback","defaultSize","__spreadProps","__spreadValues","_a","r","listener","elevation","import_core","import_theme","emphasis","props","_a","color","node","listener","import_core","import_theme","empty","props","_a","color","listener","ORIGINAL_CHILDREN","restoreOriginalChildren","node","_a","original","errorBoundary","props","element","error","_b","reset","fallbackEl","import_core","import_theme","SIZE_MAP","fab","props","_a","_b","color","dim","node","listener","elevation","focusRing","import_core","import_theme","figure","props","_a","color","node","listener","import_core","import_theme","formGroup","props","_a","layout","color","isVertical","node","listener","import_theme","grid","props","columns","gap","align","__spreadValues","listener","import_core","import_theme","HeadingShift","heading","props","_a","color","size","node","listener","offset","import_core","import_theme","horizontalRule","props","_a","color","node","listener","import_core","import_theme","icon","props","_a","color","node","listener","import_core","import_theme","image","props","_a","color","node","listener","import_core","import_theme","inputCheckbox","props","_a","_b","color","accentColor","node","listener","focusRing","import_core","import_theme","inputColor","props","_a","color","node","listener","focusRing","import_core","import_theme","inputDateTime","props","_a","_b","mode","color","accentColor","node","listener","focusRing","import_core","import_theme","inputFile","props","_a","_b","color","accentColor","node","listener","focusRing","import_core","import_theme","inputNumber","props","_a","_b","color","accentColor","node","__spreadProps","__spreadValues","listener","fieldTextStyle","focusRing","import_theme","inputOTP","node","container","getInputs","onInput","e","inputs","target","index","onKeydown","onPaste","_a","_b","_c","text","found","startIdx","char","i","field","lastFilled","import_core","import_theme","EYE_SVG","EYE_OFF_SVG","HOST_FIELD_KEYS","bindReadable","value","listener","inputPassword","props","_a","_b","colorState","accentState","visibleState","hostFields","node","_node","element","host","key","_c","_d","_e","_f","_g","name","onInput","disabled","required","field","__spreadProps","__spreadValues","l","toggle","VALUE_TONE","focusRing","import_core","import_theme","inputRadio","props","_a","_b","color","accentColor","node","listener","focusRing","import_core","import_theme","inputRange","props","_a","_b","color","accentColor","node","listener","focusRing","import_core","import_theme","inputSearch","props","_a","_b","color","accentColor","node","__spreadProps","__spreadValues","listener","fieldTextStyle","focusRing","import_core","import_theme","inputSwitch","props","_a","accentColor","node","listener","focusRing","import_core","import_theme","inputText","props","_a","_b","type","color","accentColor","node","__spreadProps","__spreadValues","listener","fieldTextStyle","focusRing","import_core","import_theme","keyboard","props","_a","color","node","listener","import_core","import_theme","label","props","_a","_b","color","accentColor","node","listener","import_core","import_theme","link","props","_a","_b","color","accentColor","node","event","el","key","listener","focusRing","import_core","import_theme","PADDING_STEPS","GHOST_PADDING","linkButton","props","_a","_b","_c","variant","color","size","fontSize","BUTTON_SIZE_FONT","padding","node","listener","focusRing","isSolid","__spreadProps","__spreadValues","import_core","import_theme","list","props","_a","color","listener","listItem","dense","listItemButton","_b","accentColor","focusRing","import_core","import_theme","mark","props","_a","accentColor","node","listener","import_core","import_theme","menu","props","_a","items","selectable","color","accentColor","activeKey","activeKeyIsCallerOwned","tabbableKey","inner","listener","focused","active","first","buildItems","node","id","item","index","key","__spreadProps","__spreadValues","l","e","k","keys","it","i","idx","next","list","focusRing","attachMenu","_node","initial","current","element","elevation","import_core","prefersReducedMotion","e","isMotionState","value","toStyles","frame","out","transforms","key","toOptions","transition","_a","_b","_c","_d","attachMotion","node","initial","el","current","release","bindAnimate","animate","next","prefersReducedMotion","play","props","mode","target","frames","motion","__spreadProps","__spreadValues","done","inst","exit","import_core","import_theme","orderedList","props","_a","color","node","listener","import_core","import_theme","getPages","current","total","_","i","pages","start","end","persistValue","node","key","incoming","fallback","stored","persistTotal","pagination","props","color","accentColor","buttonBase","listener","focusRing","activeStyle","__spreadProps","__spreadValues","state","totalState","content","page","pageCount","items","ellipsisIndex","p","isActive","snapshot","import_core","import_theme","panelSection","props","_a","padding","divider","color","__spreadValues","listener","import_core","import_theme","paragraph","props","_a","color","node","listener","import_core","import_theme","HASPOPUP_ROLES","panelHaspopup","content","_a","role","patch","declared","own","contentOwnsSurface","patches","popover","props","open","placement","openOn","openState","placeState","show","hide","anchorPartial","createFloating","popoverPartial","l","elevation","triggerPartial","listener","floatingPanelId","_e","node","e","related","floatingEl","import_core","import_theme","popoverArrow","props","placement","color","sideOffset","bordered","place","flipMap","getFlipped","listener","_a","start","pos","end","x","y","import_core","import_theme","preformated","props","_a","color","node","listener","import_core","import_theme","progress","props","_a","_b","color","accentColor","node","listener","import_core","import_theme","isRTL","element","horizontalArrowStep","key","STAR_FILLED","STAR_EMPTY","applyRatingProps","live","next","_a","_b","_c","insertStar","node","index","hoveredState","activeCount","listener","hovered","star","current","e","horizontalArrowStep","target","focusRing","syncStars","children","rating","props","_d","_e","_f","_g","__spreadProps","__spreadValues","initial","import_core","import_theme","ringProgress","props","_a","_b","_c","size","thickness","value","color","trackColor","holePercent","mask","l","node","import_theme","row","props","gap","align","justify","wrap","density","__spreadValues","listener","import_core","import_theme","scrollArea","props","_a","color","__spreadProps","__spreadValues","l","import_core","import_theme","persistValue","node","key","incoming","fallback","stored","moveSegment","e","items","value","_a","k","keys","item","index","idx","next","step","horizontalArrowStep","group","buildSegmentButtons","color","accentColor","l","_b","current","elevation","focusRing","segmented","props","__spreadProps","__spreadValues","element","snapshot","import_theme","select","props","color","accentColor","node","listener","l","svg","_a","isRTL","focusRing","import_core","import_theme","TYPEAHEAD_RESET_MS","resolveTypeahead","node","meta","matchesPrefix","label","needle","selectBox","props","options","placement","color","open","multiple","state","openState","show","hide","anchorPartial","createFloating","popoverPartial","_e","listener","elevation","buildWrap","inner","val","vals","opt","tag","_node","cur","filter","v","attachInner","_inner","next","toggle","panelOf","_a","root","floatingPanelId","moveIntoPanel","toLast","enabledOptionsIn","target","openThenMove","release","subscribeOpen","isOpen","typeahead","key","_b","_c","repeated","matches","el","active","from","partial","__spreadProps","__spreadValues","element","e","kb","focusRing","import_theme","selectItem","props","accentColor","color","value","listener","_a","select","val","_e","node","state","v","focusRing","import_core","import_theme","onListboxKey","event","node","_a","key","host","options","enabledOptionsIn","active","current","next","target","selectList","props","color","multiple","state","inputs","listener","val","v","import_core","import_theme","skeleton","props","_a","color","keyframes","animationName","listener","import_core","import_theme","small","props","_a","color","node","listener","import_core","import_theme","keyframes","animationName","spinner","props","_a","color","node","listener","import_core","import_theme","splitter","props","direction","defaultSize","min","max","_node","element","isFirstSplitterPanel","node","parent","item","splitterPanel","ctx","el","prop","apply","size","release","_a","splitterHandle","label","handle","isHorizontal","releaseAriaValue","onKeydown","e","step","next","dir","horizontalArrowStep","cancelDrag","onPointerdown","container","onPointermove","move","rect","raw","onPointerup","up","listener","focusRing","import_theme","stack","props","gap","align","justify","density","__spreadValues","listener","import_core","import_theme","persistValue","node","key","incoming","fallback","stored","stepConnectorStyle","direction","color","accentColor","l","buildStepItems","items","current","vertical","connector","item","index","_a","cur","__spreadProps","__spreadValues","steps","props","live","element","snapshot","import_core","import_theme","strong","props","_a","color","node","listener","import_core","import_theme","subscript","props","_a","color","node","listener","import_core","import_theme","superscript","props","_a","color","node","listener","import_core","import_theme","table","props","_a","color","node","listener","l","import_core","import_theme","persistValue","node","key","incoming","fallback","stored","buildTabsChildren","items","activeKey","accentColor","color","id","tablist","item","index","_a","l","e","k","keys","it","i","idx","next","step","horizontalArrowStep","list","focusRing","panels","tabs","props","__spreadValues","element","_b","snapshot","import_core","import_theme","textarea","props","_a","_b","color","accentColor","autoResize","__spreadProps","__spreadValues","node","initial","el","enabled","measuring","intersectionObserver","resizeObserver","resize","observe","entries","entry","unobserve","next","listener","fieldTextStyle","focusRing","import_core","import_theme","timeline","timelineItem","props","_a","_b","_c","last","color","accentColor","activeState","__spreadValues","listener","import_core","import_theme","resolveOpenState","node","state","readOpen","listener","DEFAULT_DURATION_MS","_attachAutoDismiss","initial","duration","onDismiss","timer","remaining","startedAt","dismissed","clearTimer","dismiss","arm","ms","pause","resume","element","next","toast","props","position","color","isTop","isCenter","isRight","overlayEle","__spreadProps","__spreadValues","rootNode","overlay","elevation","done","_a","_b","finished","overlayRemoved","overlayEl","removeOverlayIfEmpty","item","it","finish","onEnd","e","import_core","import_theme","persistValue","node","key","incoming","fallback","stored","isPressed","val","moveToggle","e","items","value","multiple","_a","k","keys","item","index","idx","next","step","horizontalArrowStep","group","buildToggleButtons","focusedKey","color","accentColor","l","_b","_c","_d","_e","focused","arr","v","focusRing","toggleGroup","props","__spreadProps","__spreadValues","element","snapshot","toolbar","props","row","toolbarSpacer","import_core","import_theme","tooltip","props","open","placement","content","openDelay","closeDelay","placeState","contentState","contentElement","listener","show","hide","anchorPartial","openState","createFloating","tooltipPartial","elevation","popoverArrow","floatingPanelId","_e","node","e","import_core","getItemId","node","index","transitionGroup","props","duration","delay","previousRects","cancelMap","pendingTimers","pendingFrames","cancel","timer","frame","prefersReducedMotion","item","dom","_a","key","prev","next","deltaX","deltaY","cancelled","finish","onEnd","event","import_core","import_theme","unorderedList","props","_a","color","node","listener","visuallyHidden"]}
|