@vipengele/react-ui 0.0.0 → 0.1.0

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.
Files changed (95) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +463 -3
  3. package/dist/Avatar/Avatar.d.ts +21 -0
  4. package/dist/Avatar/Avatar.d.ts.map +1 -0
  5. package/dist/Avatar/Avatar.stylesheet.d.ts +17 -0
  6. package/dist/Avatar/Avatar.stylesheet.d.ts.map +1 -0
  7. package/dist/Button/Button.d.ts +39 -0
  8. package/dist/Button/Button.d.ts.map +1 -0
  9. package/dist/Button/Button.stylesheet.d.ts +17 -0
  10. package/dist/Button/Button.stylesheet.d.ts.map +1 -0
  11. package/dist/ButtonGroup/ButtonGroup.d.ts +16 -0
  12. package/dist/ButtonGroup/ButtonGroup.d.ts.map +1 -0
  13. package/dist/ButtonGroup/ButtonGroup.stylesheet.d.ts +12 -0
  14. package/dist/ButtonGroup/ButtonGroup.stylesheet.d.ts.map +1 -0
  15. package/dist/Card/Card.d.ts +36 -0
  16. package/dist/Card/Card.d.ts.map +1 -0
  17. package/dist/Card/Card.stylesheet.d.ts +17 -0
  18. package/dist/Card/Card.stylesheet.d.ts.map +1 -0
  19. package/dist/Dropdown/Dropdown.d.ts +205 -0
  20. package/dist/Dropdown/Dropdown.d.ts.map +1 -0
  21. package/dist/Dropdown/Dropdown.stylesheet.d.ts +24 -0
  22. package/dist/Dropdown/Dropdown.stylesheet.d.ts.map +1 -0
  23. package/dist/FieldSet/FieldSet.d.ts +22 -0
  24. package/dist/FieldSet/FieldSet.d.ts.map +1 -0
  25. package/dist/FieldSet/FieldSet.stylesheet.d.ts +34 -0
  26. package/dist/FieldSet/FieldSet.stylesheet.d.ts.map +1 -0
  27. package/dist/FieldShell/FieldShell.d.ts +42 -0
  28. package/dist/FieldShell/FieldShell.d.ts.map +1 -0
  29. package/dist/FieldShell/FieldShell.stylesheet.d.ts +32 -0
  30. package/dist/FieldShell/FieldShell.stylesheet.d.ts.map +1 -0
  31. package/dist/FormField/FormField.d.ts +45 -0
  32. package/dist/FormField/FormField.d.ts.map +1 -0
  33. package/dist/FormField/FormField.stylesheet.d.ts +24 -0
  34. package/dist/FormField/FormField.stylesheet.d.ts.map +1 -0
  35. package/dist/PasswordInput/PasswordInput.d.ts +15 -0
  36. package/dist/PasswordInput/PasswordInput.d.ts.map +1 -0
  37. package/dist/PasswordInput/PasswordInput.stylesheet.d.ts +24 -0
  38. package/dist/PasswordInput/PasswordInput.stylesheet.d.ts.map +1 -0
  39. package/dist/Popover/Popover.d.ts +47 -0
  40. package/dist/Popover/Popover.d.ts.map +1 -0
  41. package/dist/Popover/Popover.stylesheet.d.ts +21 -0
  42. package/dist/Popover/Popover.stylesheet.d.ts.map +1 -0
  43. package/dist/Progress/Progress.d.ts +18 -0
  44. package/dist/Progress/Progress.d.ts.map +1 -0
  45. package/dist/Progress/Progress.stylesheet.d.ts +18 -0
  46. package/dist/Progress/Progress.stylesheet.d.ts.map +1 -0
  47. package/dist/RadioButton/RadioButton.d.ts +18 -0
  48. package/dist/RadioButton/RadioButton.d.ts.map +1 -0
  49. package/dist/RadioButton/RadioButton.stylesheet.d.ts +15 -0
  50. package/dist/RadioButton/RadioButton.stylesheet.d.ts.map +1 -0
  51. package/dist/RadioGroup/RadioGroup.d.ts +40 -0
  52. package/dist/RadioGroup/RadioGroup.d.ts.map +1 -0
  53. package/dist/RadioGroup/RadioGroup.stylesheet.d.ts +11 -0
  54. package/dist/RadioGroup/RadioGroup.stylesheet.d.ts.map +1 -0
  55. package/dist/Skeleton/Skeleton.d.ts +18 -0
  56. package/dist/Skeleton/Skeleton.d.ts.map +1 -0
  57. package/dist/Skeleton/Skeleton.stylesheet.d.ts +25 -0
  58. package/dist/Skeleton/Skeleton.stylesheet.d.ts.map +1 -0
  59. package/dist/Slider/Slider.d.ts +12 -0
  60. package/dist/Slider/Slider.d.ts.map +1 -0
  61. package/dist/Slider/Slider.stylesheet.d.ts +18 -0
  62. package/dist/Slider/Slider.stylesheet.d.ts.map +1 -0
  63. package/dist/Spinner/Spinner.d.ts +19 -0
  64. package/dist/Spinner/Spinner.d.ts.map +1 -0
  65. package/dist/Spinner/Spinner.stylesheet.d.ts +14 -0
  66. package/dist/Spinner/Spinner.stylesheet.d.ts.map +1 -0
  67. package/dist/Tabs/Tabs.d.ts +46 -0
  68. package/dist/Tabs/Tabs.d.ts.map +1 -0
  69. package/dist/Tabs/Tabs.stylesheet.d.ts +15 -0
  70. package/dist/Tabs/Tabs.stylesheet.d.ts.map +1 -0
  71. package/dist/TextField/TextField.d.ts +24 -0
  72. package/dist/TextField/TextField.d.ts.map +1 -0
  73. package/dist/TextField/TextField.stylesheet.d.ts +29 -0
  74. package/dist/TextField/TextField.stylesheet.d.ts.map +1 -0
  75. package/dist/Toggle/Toggle.d.ts +12 -0
  76. package/dist/Toggle/Toggle.d.ts.map +1 -0
  77. package/dist/Toggle/Toggle.stylesheet.d.ts +16 -0
  78. package/dist/Toggle/Toggle.stylesheet.d.ts.map +1 -0
  79. package/dist/Tooltip/Tooltip.d.ts +34 -0
  80. package/dist/Tooltip/Tooltip.d.ts.map +1 -0
  81. package/dist/Tooltip/Tooltip.stylesheet.d.ts +22 -0
  82. package/dist/Tooltip/Tooltip.stylesheet.d.ts.map +1 -0
  83. package/dist/Typography/Typography.d.ts +28 -0
  84. package/dist/Typography/Typography.d.ts.map +1 -0
  85. package/dist/Typography/Typography.stylesheet.d.ts +16 -0
  86. package/dist/Typography/Typography.stylesheet.d.ts.map +1 -0
  87. package/dist/index.d.ts +22 -0
  88. package/dist/index.d.ts.map +1 -0
  89. package/dist/index.js +2947 -0
  90. package/dist/index.js.map +1 -0
  91. package/dist/internal/listbox.stylesheet.d.ts +24 -0
  92. package/dist/internal/listbox.stylesheet.d.ts.map +1 -0
  93. package/dist/internal/useListboxKeyboard.d.ts +90 -0
  94. package/dist/internal/useListboxKeyboard.d.ts.map +1 -0
  95. package/package.json +50 -5
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/Avatar/Avatar.stylesheet.ts","../src/Avatar/Avatar.tsx","../src/Spinner/Spinner.stylesheet.ts","../src/Spinner/Spinner.tsx","../src/Button/Button.stylesheet.ts","../src/Button/Button.tsx","../src/ButtonGroup/ButtonGroup.stylesheet.ts","../src/ButtonGroup/ButtonGroup.tsx","../src/Card/Card.stylesheet.ts","../src/Card/Card.tsx","../src/FieldShell/FieldShell.stylesheet.ts","../src/FieldShell/FieldShell.tsx","../src/internal/listbox.stylesheet.ts","../src/internal/useListboxKeyboard.ts","../src/Tooltip/Tooltip.stylesheet.ts","../src/Tooltip/Tooltip.tsx","../src/Dropdown/Dropdown.stylesheet.ts","../src/Dropdown/Dropdown.tsx","../src/FieldSet/FieldSet.stylesheet.ts","../src/FieldSet/FieldSet.tsx","../src/FormField/FormField.stylesheet.ts","../src/FormField/FormField.tsx","../src/TextField/TextField.stylesheet.ts","../src/TextField/TextField.tsx","../src/PasswordInput/PasswordInput.stylesheet.ts","../src/PasswordInput/PasswordInput.tsx","../src/Popover/Popover.stylesheet.ts","../src/Popover/Popover.tsx","../src/Progress/Progress.stylesheet.ts","../src/Progress/Progress.tsx","../src/RadioGroup/RadioGroup.stylesheet.ts","../src/RadioGroup/RadioGroup.tsx","../src/RadioButton/RadioButton.stylesheet.ts","../src/RadioButton/RadioButton.tsx","../src/Skeleton/Skeleton.stylesheet.ts","../src/Skeleton/Skeleton.tsx","../src/Slider/Slider.stylesheet.ts","../src/Slider/Slider.tsx","../src/Tabs/Tabs.stylesheet.ts","../src/Tabs/Tabs.tsx","../src/Toggle/Toggle.stylesheet.ts","../src/Toggle/Toggle.tsx","../src/Typography/Typography.stylesheet.ts","../src/Typography/Typography.tsx"],"names":["size","jsxs","Fragment","jsx","VIEWPORT_PADDING","useState","useFloating","offset","flip","autoUpdate","useDismiss","useRole","useInteractions","isValidElement","Children","useRef","createPortal","useId","cloneElement","shift","useClick","FloatingFocusManager","createContext","useContext","useMemo"],"mappings":"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AA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;ACJjC,IAAM,cAAA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","file":"index.js","sourcesContent":["/**\n * `<Avatar>`'s own styles, injected as an inline `<style>` rather than a `.css` import so the\n * package can stay `\"sideEffects\": false` (same approach as `@vipengele/react-tokens`'s base stylesheet\n * and `Button`'s stylesheet).\n *\n * Every `--vpg-*` property is *read* here through `var()` and never assigned inline by the\n * component: an inline style declaration always wins over a stylesheet rule for the same\n * property on the same element, so an inline `--vpg-surface-raised` would permanently\n * shadow the dark-mode reassignment in `@vipengele/react-tokens`'s base stylesheet and this avatar\n * would stop adapting to colour mode.\n *\n * The circle takes steps of the size scale and the initials steps of the type scale. The `xl`\n * circle takes the size scale's display step, past the range a pointer targets, and the `sm`\n * initials sit on the type scale's floor rather than under it.\n */\nexport const avatarStylesheet = `\n.vpg-avatar {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: none;\n box-sizing: border-box;\n overflow: hidden;\n background-color: var(--vpg-surface-raised);\n color: var(--vpg-ink-muted);\n font-family: inherit;\n font-weight: 500;\n line-height: 1;\n /* The fallback content is centred text or a glyph; without this, a long initials string\n would be selectable and could wrap out of the frame. */\n user-select: none;\n}\n\n.vpg-avatar-circle {\n border-radius: 50%;\n}\n\n.vpg-avatar-square {\n border-radius: var(--vpg-radius);\n}\n\n.vpg-avatar-sm {\n width: var(--vpg-size-xs);\n height: var(--vpg-size-xs);\n font-size: var(--vpg-font-size-xs);\n}\n\n.vpg-avatar-md {\n width: var(--vpg-size-md);\n height: var(--vpg-size-md);\n font-size: var(--vpg-font-size-xs);\n}\n\n.vpg-avatar-lg {\n width: var(--vpg-size-xl);\n height: var(--vpg-size-xl);\n font-size: var(--vpg-font-size-sm);\n}\n\n.vpg-avatar-xl {\n width: var(--vpg-size-2xl);\n height: var(--vpg-size-2xl);\n font-size: var(--vpg-font-size-lg);\n}\n\n.vpg-avatar-image {\n width: 100%;\n height: 100%;\n /* \\`cover\\` rather than \\`contain\\`: a non-square photo is cropped to the frame instead of\n letterboxed against the surface colour. */\n object-fit: cover;\n display: block;\n}\n\n.vpg-avatar-icon {\n /* Proportional to the frame, so one rule sizes the glyph across the whole size scale. */\n width: 60%;\n height: 60%;\n}\n`;\n","import { User } from \"@vipengele/react-icons\";\nimport { type HTMLAttributes, useState } from \"react\";\nimport { avatarStylesheet } from \"./Avatar.stylesheet.js\";\n\nexport type AvatarSize = \"sm\" | \"md\" | \"lg\" | \"xl\";\n\nexport type AvatarShape = \"circle\" | \"square\";\n\nexport interface AvatarProps extends Omit<HTMLAttributes<HTMLSpanElement>, \"children\"> {\n /** The image to render. An image that fails to load falls through to the initials, and then\n * to the generic person icon, so a dead URL degrades instead of leaving a blank frame. */\n src?: string;\n /** The person the avatar stands for: the source of the initials, and the accessible name\n * when no `alt` is given. */\n name?: string;\n /** Overrides `name` as the accessible name. */\n alt?: string;\n size?: AvatarSize;\n shape?: AvatarShape;\n}\n\n/**\n * Initials are the first character of the first word plus the first character of the last word,\n * upper-cased — \"Ada Lovelace\" gives \"AL\", \"Ada\" gives \"A\", and a middle name is skipped rather\n * than producing a third letter that wouldn't fit the frame. Words are whitespace-separated, so\n * a name that is only whitespace yields nothing and the caller falls through to the icon.\n */\nfunction initialsFrom(name: string): string {\n const words = name.split(/\\s+/).filter((word) => word.length > 0);\n const picked = words.length > 1 ? [...words.slice(0, 1), ...words.slice(-1)] : words.slice(0, 1);\n return picked\n .map((word) => word.slice(0, 1))\n .join(\"\")\n .toUpperCase();\n}\n\n/**\n * The library's person atom: an image, the person's initials, or a generic person glyph, in\n * that order of preference, framed as a circle or a rounded square.\n */\nexport function Avatar({ src, name, alt, size = \"md\", shape = \"circle\", className, ...rest }: AvatarProps) {\n // Keyed on the URL rather than a boolean, so swapping `src` to a fresh image retries it\n // instead of inheriting the previous URL's failure.\n const [failedSrc, setFailedSrc] = useState<string | undefined>(undefined);\n\n const classes = [\"vpg-avatar\", `vpg-avatar-${size}`, `vpg-avatar-${shape}`, className].filter(Boolean).join(\" \");\n\n const label = alt ?? name;\n const showImage = src !== undefined && src !== failedSrc;\n const initials = name === undefined ? \"\" : initialsFrom(name);\n\n // The role and the label travel as one object because a `<span>` only supports `aria-label`\n // once it has a role that takes one. The image carries the accessible name itself; on the\n // fallback paths the root is the only element left to carry it, and with neither an image nor\n // a name there is nothing to announce, so the frame stays out of the accessibility tree.\n const labelling = showImage || label === undefined ? undefined : { role: \"img\", \"aria-label\": label };\n\n return (\n <>\n {/*\n React 19 hoists and de-duplicates this by `href`, so N avatars on a page inject one\n stylesheet.\n */}\n <style href=\"vpg-avatar\" precedence=\"vpg-avatar\">\n {avatarStylesheet}\n </style>\n <span {...rest} {...labelling} className={classes}>\n {showImage ? (\n <img src={src} alt={label ?? \"\"} className=\"vpg-avatar-image\" onError={() => setFailedSrc(src)} />\n ) : initials ? (\n // The root already announces `label`; repeating the initials would read them out as a\n // second, meaningless word.\n <span aria-hidden=\"true\">{initials}</span>\n ) : (\n <User className=\"vpg-avatar-icon\" aria-hidden=\"true\" />\n )}\n </span>\n </>\n );\n}\n","/**\n * `<Spinner>`'s own styles, injected as an inline `<style>` rather than a `.css` import so the\n * package can stay `\"sideEffects\": false` (same approach as `@vipengele/react-tokens`'s base stylesheet\n * and `@vipengele/react-icons`'s icon stylesheet).\n *\n * Every `--vpg-*` property this component depends on is *read* here through `var()` and\n * never assigned inline by the component: an inline style declaration always wins over a\n * stylesheet rule for the same property on the same element, so an inline `--vpg-accent`\n * would permanently shadow the dark-mode reassignment in `@vipengele/react-tokens`'s base stylesheet.\n *\n * A spinner is glyph-sized, so every size takes a step of the icon scale.\n */\nexport const spinnerStylesheet = `\n@keyframes vpg-spinner-rotate {\n to { transform: rotate(360deg); }\n}\n\n.vpg-spinner {\n display: inline-block;\n flex: none;\n vertical-align: middle;\n /* The track's stroke is \\`currentColor\\`, so this one declaration colours the whole spinner\n and a caller's \\`color\\` prop overrides it inline without touching any theme property. */\n color: var(--vpg-accent);\n animation: vpg-spinner-rotate 0.7s linear infinite;\n}\n\n.vpg-spinner circle {\n fill: none;\n stroke: currentColor;\n stroke-width: 3;\n stroke-linecap: round;\n /* Circumference of r=10 is ~62.8; a 44/62.8 dash leaves the gap that makes the rotation\n readable. Without the gap the ring is closed and spinning it looks static. */\n stroke-dasharray: 44 62.8;\n}\n\n.vpg-spinner-sm {\n width: var(--vpg-icon-md);\n height: var(--vpg-icon-md);\n}\n\n.vpg-spinner-md {\n width: var(--vpg-icon-lg);\n height: var(--vpg-icon-lg);\n}\n\n.vpg-spinner-lg {\n width: var(--vpg-icon-xl);\n height: var(--vpg-icon-xl);\n}\n\n@media (prefers-reduced-motion: reduce) {\n /* Slowed, not stopped: a spinner that doesn't move reports nothing about the wait it exists\n to report. */\n .vpg-spinner {\n animation-duration: 2.4s;\n }\n}\n`;\n","import { spinnerStylesheet } from \"./Spinner.stylesheet.js\";\n\n/** Spinner's size scale, shared with `Button` so a spinner sits inside a button of the\n * same size without a per-call-site size prop. */\nexport type SpinnerSize = \"sm\" | \"md\" | \"lg\";\n\nexport interface SpinnerProps {\n size?: SpinnerSize;\n /** Inline stroke colour override. A deliberate escape hatch: it wins over the stylesheet's\n * `var(--vpg-accent)`, so this instance stops adapting to light/dark on its own. Leave it\n * unset unless the spinner sits on a ground the theme doesn't know about. */\n color?: string;\n /** Announced by the `role=\"status\"` region while the spinner is mounted. */\n label?: string;\n className?: string;\n}\n\nconst SIZE_CLASS: Record<SpinnerSize, string> = {\n sm: \"vpg-spinner-sm\",\n md: \"vpg-spinner-md\",\n lg: \"vpg-spinner-lg\",\n};\n\n/**\n * An indeterminate loading indicator, rotated by a CSS `@keyframes` rule in its own stylesheet\n * and stroked in `var(--vpg-accent)` by default.\n */\nexport function Spinner({ size = \"md\", color, label = \"Loading\", className }: SpinnerProps) {\n const classes = [\"vpg-spinner\", SIZE_CLASS[size], className].filter(Boolean).join(\" \");\n\n return (\n <>\n {/*\n React 19 hoists and de-duplicates this by `href`, so N spinners on a page inject one\n stylesheet.\n */}\n <style href=\"vpg-spinner\" precedence=\"vpg-spinner\">\n {spinnerStylesheet}\n </style>\n <svg className={classes} viewBox=\"0 0 24 24\" role=\"status\" aria-label={label} style={color === undefined ? undefined : { color }}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n </svg>\n </>\n );\n}\n","/**\n * `<Button>`'s own styles, injected as an inline `<style>` rather than a `.css` import so the\n * package can stay `\"sideEffects\": false` (same approach as `@vipengele/react-tokens`'s base stylesheet\n * and `@vipengele/react-icons`'s icon stylesheet).\n *\n * Every `--vpg-*` property is *read* here through `var()` and never assigned inline by the\n * component: an inline style declaration always wins over a stylesheet rule for the same\n * property on the same element, so an inline `--vpg-accent` would permanently shadow the\n * dark-mode reassignment in `@vipengele/react-tokens`'s base stylesheet and this button would stop\n * adapting to colour mode.\n *\n * Heights come from the size scale, paddings from the spacing scale and label sizes from the\n * type scale. The danger variant reads the `--vpg-danger` ramp, which is derived exactly as the\n * accent ramp is, so both variants shift by the same amount on hover and press.\n */\nexport const buttonStylesheet = `\n.vpg-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--vpg-space-2);\n box-sizing: border-box;\n border: 1px solid transparent;\n border-radius: var(--vpg-radius);\n font-family: inherit;\n font-weight: 500;\n line-height: 1;\n white-space: nowrap;\n text-decoration: none;\n cursor: pointer;\n /* Colour and background come from the variant rules below; every variant animates the same\n two properties, so the transition belongs here rather than four times over. */\n transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;\n}\n\n.vpg-button:focus-visible {\n /* Offset rather than inset so the ring stays legible against a same-coloured surface. */\n outline: var(--vpg-focus-ring-width) solid var(--vpg-accent-ring);\n outline-offset: var(--vpg-focus-ring-offset);\n}\n\n.vpg-button:disabled {\n /* Pointer events stay on: a disabled button that swallows them gives no cursor feedback and\n no tooltip target. \\`cursor\\` is what communicates the state. */\n cursor: not-allowed;\n opacity: 0.55;\n}\n\n.vpg-button-primary {\n background-color: var(--vpg-accent);\n color: var(--vpg-accent-contrast);\n}\n\n.vpg-button-primary:hover:not(:disabled) {\n background-color: var(--vpg-accent-hover);\n}\n\n.vpg-button-primary:active:not(:disabled) {\n background-color: var(--vpg-accent-press);\n}\n\n.vpg-button-secondary {\n background-color: var(--vpg-surface-raised);\n border-color: var(--vpg-border);\n color: var(--vpg-ink);\n}\n\n.vpg-button-secondary:hover:not(:disabled) {\n background-color: var(--vpg-surface-hover);\n border-color: var(--vpg-border-strong);\n}\n\n.vpg-button-secondary:active:not(:disabled) {\n background-color: var(--vpg-surface-press);\n}\n\n.vpg-button-ghost {\n background-color: transparent;\n color: var(--vpg-ink);\n}\n\n.vpg-button-ghost:hover:not(:disabled) {\n background-color: var(--vpg-accent-wash);\n}\n\n.vpg-button-ghost:active:not(:disabled) {\n background-color: var(--vpg-surface-press);\n}\n\n.vpg-button-danger {\n background-color: var(--vpg-danger);\n color: var(--vpg-danger-contrast);\n}\n\n.vpg-button-danger:hover:not(:disabled) {\n background-color: var(--vpg-danger-hover);\n}\n\n.vpg-button-danger:active:not(:disabled) {\n background-color: var(--vpg-danger-press);\n}\n\n.vpg-button-sm {\n min-height: var(--vpg-size-sm);\n padding: 0 var(--vpg-space-3);\n font-size: var(--vpg-font-size-xs);\n}\n\n.vpg-button-md {\n min-height: var(--vpg-size-md);\n padding: 0 var(--vpg-space-4);\n font-size: var(--vpg-font-size-sm);\n}\n\n.vpg-button-lg {\n min-height: var(--vpg-size-xl);\n padding: 0 var(--vpg-space-5);\n font-size: var(--vpg-font-size-md);\n}\n\n/* Square: the horizontal padding is dropped and the min-height doubles as a width floor, so the\n button stays square at every size without a second per-size scale. */\n.vpg-button-icon-only {\n padding: 0;\n aspect-ratio: 1;\n}\n\n.vpg-button-icon-only.vpg-button-sm {\n min-width: var(--vpg-size-sm);\n}\n\n.vpg-button-icon-only.vpg-button-md {\n min-width: var(--vpg-size-md);\n}\n\n.vpg-button-icon-only.vpg-button-lg {\n min-width: var(--vpg-size-xl);\n}\n\n.vpg-button-icon {\n flex: none;\n width: 1em;\n height: 1em;\n}\n\n/* Keeps the button's accessible name intact while \\`loading\\` swaps its visible content for a\n spinner: the label stays in the accessibility tree, but takes up no visual space. */\n.vpg-button-visually-hidden {\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 white-space: nowrap;\n border: 0;\n}\n`;\n","import type { IconComponent } from \"@vipengele/react-icons\";\nimport type { ButtonHTMLAttributes, ReactNode } from \"react\";\nimport { Spinner } from \"../Spinner/Spinner.js\";\nimport { buttonStylesheet } from \"./Button.stylesheet.js\";\n\nexport type ButtonVariant = \"primary\" | \"secondary\" | \"ghost\" | \"danger\";\n\n/** Shared with `Spinner`'s size scale, so a loading button holds its height. */\nexport type ButtonSize = \"sm\" | \"md\" | \"lg\";\n\ninterface ButtonOwnProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, \"children\"> {\n variant?: ButtonVariant;\n size?: ButtonSize;\n /** Disables interaction and replaces the button's content with an inline `<Spinner>`. The\n * button keeps its own text colour, so the spinner reads on every variant. */\n loading?: boolean;\n /** Rendered before the label. Pass the component itself — `<Button leadingIcon={Plus} />` —\n * so a bundler only ever sees the icons actually referenced. */\n leadingIcon?: IconComponent;\n /** Rendered after the label, under the same rules as `leadingIcon`. */\n trailingIcon?: IconComponent;\n}\n\n/**\n * A square button carrying an icon and no text. `aria-label` is required rather than optional:\n * without visible text, it is the button's only accessible name, and a runtime warning would\n * land too late to stop the button shipping nameless.\n */\ninterface IconOnlyButtonProps extends ButtonOwnProps {\n iconOnly: true;\n \"aria-label\": string;\n children?: never;\n}\n\ninterface LabelledButtonProps extends ButtonOwnProps {\n iconOnly?: false;\n children?: ReactNode;\n}\n\nexport type ButtonProps = IconOnlyButtonProps | LabelledButtonProps;\n\n/**\n * The library's action atom, styled entirely from `--vpg-*` custom properties read through\n * `var()` in its own stylesheet, so a themed instance follows colour mode without re-rendering.\n */\nexport function Button({\n variant = \"primary\",\n size = \"md\",\n loading = false,\n iconOnly = false,\n leadingIcon: LeadingIcon,\n trailingIcon: TrailingIcon,\n className,\n disabled = false,\n children,\n ...rest\n}: ButtonProps) {\n const classes = [\"vpg-button\", `vpg-button-${variant}`, `vpg-button-${size}`, iconOnly ? \"vpg-button-icon-only\" : undefined, className]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <>\n {/*\n React 19 hoists and de-duplicates this by `href`, so N buttons on a page inject one\n stylesheet.\n */}\n <style href=\"vpg-button\" precedence=\"vpg-button\">\n {buttonStylesheet}\n </style>\n <button type=\"button\" {...rest} className={classes} disabled={disabled || loading} aria-busy={loading || undefined}>\n {loading ? (\n <>\n {/*\n The spinner is decorative here: its own `role=\"status\"`/`aria-label` would\n otherwise become the button's computed accessible name, replacing \"Save\" with\n \"Loading\" and making concurrent loading buttons indistinguishable.\n `color=\"currentColor\"` rather than a class: the spinner's own stylesheet strokes\n it in `var(--vpg-accent)`, and two single-class rules are settled by\n injection order, which nothing here controls.\n */}\n <span aria-hidden=\"true\">\n <Spinner size={size} color=\"currentColor\" />\n </span>\n {children ? <span className=\"vpg-button-visually-hidden\">{children}</span> : null}\n </>\n ) : (\n <>\n {LeadingIcon ? <LeadingIcon className=\"vpg-button-icon\" /> : null}\n {children}\n {TrailingIcon ? <TrailingIcon className=\"vpg-button-icon\" /> : null}\n </>\n )}\n </button>\n </>\n );\n}\n","/**\n * `<ButtonGroup>`'s own styles, injected as an inline `<style>` rather than a `.css` import so\n * the package can stay `\"sideEffects\": false` (same approach as `Button`'s and `Typography`'s\n * stylesheets).\n *\n * `ButtonGroup` never touches its `<Button>` children — no `cloneElement`, no context — so the\n * attached look is entirely a set of descendant/sibling selectors here, targeting `.vpg-\n * button` directly. That makes `Button`'s rendered class name a contract: renaming it without a\n * matching change here silently breaks the segmented styling with no type error to catch it.\n */\nexport const buttonGroupStylesheet = `\n.vpg-button-group {\n display: inline-flex;\n}\n\n.vpg-button-group-horizontal {\n flex-direction: row;\n}\n\n.vpg-button-group-vertical {\n flex-direction: column;\n}\n\n/* Adjacent buttons overlap their shared border by one pixel rather than doubling it, and only\n the outer corners of the group stay rounded. */\n.vpg-button-group-horizontal > .vpg-button {\n border-radius: 0;\n}\n\n.vpg-button-group-horizontal > .vpg-button:first-child {\n border-top-left-radius: var(--vpg-radius);\n border-bottom-left-radius: var(--vpg-radius);\n}\n\n.vpg-button-group-horizontal > .vpg-button:last-child {\n border-top-right-radius: var(--vpg-radius);\n border-bottom-right-radius: var(--vpg-radius);\n}\n\n.vpg-button-group-horizontal > .vpg-button + .vpg-button {\n margin-left: -1px;\n}\n\n.vpg-button-group-vertical > .vpg-button {\n border-radius: 0;\n}\n\n.vpg-button-group-vertical > .vpg-button:first-child {\n border-top-left-radius: var(--vpg-radius);\n border-top-right-radius: var(--vpg-radius);\n}\n\n.vpg-button-group-vertical > .vpg-button:last-child {\n border-bottom-left-radius: var(--vpg-radius);\n border-bottom-right-radius: var(--vpg-radius);\n}\n\n.vpg-button-group-vertical > .vpg-button + .vpg-button {\n margin-top: -1px;\n}\n\n/* A focused or hovered button's border should read as whole rather than being clipped under\n its neighbour's overlap. */\n.vpg-button-group > .vpg-button:focus-visible,\n.vpg-button-group > .vpg-button:hover {\n position: relative;\n z-index: 1;\n}\n`;\n","import type { HTMLAttributes, ReactNode } from \"react\";\nimport { buttonGroupStylesheet } from \"./ButtonGroup.stylesheet.js\";\n\nexport type ButtonGroupOrientation = \"horizontal\" | \"vertical\";\n\ninterface ButtonGroupOwnProps extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n orientation?: ButtonGroupOrientation;\n children?: ReactNode;\n}\n\nexport type ButtonGroupProps = ButtonGroupOwnProps;\n\n/**\n * Groups plain `<Button>` children into a single attached control. Children are rendered\n * unmodified — no `cloneElement`, no context — the segmented look comes entirely from\n * `ButtonGroup`'s own stylesheet targeting `.vpg-button` as a descendant, which makes\n * `Button`'s rendered class name a contract this component depends on.\n */\nexport function ButtonGroup({ orientation = \"horizontal\", className, children, ...rest }: ButtonGroupProps) {\n const classes = [\"vpg-button-group\", `vpg-button-group-${orientation}`, className].filter(Boolean).join(\" \");\n\n return (\n <>\n {/*\n React 19 hoists and de-duplicates this by `href`, so N groups on a page inject one\n stylesheet.\n */}\n <style href=\"vpg-button-group\" precedence=\"vpg-button-group\">\n {buttonGroupStylesheet}\n </style>\n {/* biome-ignore lint/a11y/useSemanticElements: <fieldset> implies form-control semantics\n and an optional <legend>, neither of which fits a plain toolbar of buttons. */}\n <div {...rest} role=\"group\" className={classes}>\n {children}\n </div>\n </>\n );\n}\n","/**\n * `<Card>`'s own styles, injected as an inline `<style>` rather than a `.css` import so the\n * package can stay `\"sideEffects\": false` (same approach as `Button`'s and `Avatar`'s\n * stylesheets).\n *\n * Every `--vpg-*` property is *read* here through `var()` and never assigned inline by the\n * component: an inline style declaration always wins over a stylesheet rule for the same\n * property on the same element, so an inline `--vpg-surface-raised` would permanently\n * shadow the dark-mode reassignment in `@vipengele/react-tokens`'s base stylesheet and this card would\n * stop adapting to colour mode.\n *\n * `.vpg-card` lays its children out as a column and orders them by CSS `order` rather than\n * by DOM position, so `Card.Header`/`Card.Content`/`Card.Footer` render header-above-content-\n * above-footer regardless of the order a consumer writes them in JSX.\n */\nexport const cardStylesheet = `\n.vpg-card {\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n background-color: var(--vpg-surface-raised);\n border: 1px solid var(--vpg-border);\n border-radius: var(--vpg-radius);\n color: var(--vpg-ink);\n}\n\n.vpg-card-interactive {\n cursor: pointer;\n text-align: left;\n}\n\n.vpg-card-interactive:hover {\n background-color: var(--vpg-surface-hover);\n}\n\n.vpg-card-interactive:active {\n background-color: var(--vpg-surface-press);\n}\n\n.vpg-card-interactive:focus-visible {\n /* Offset rather than inset so the ring stays legible against a same-coloured surface. */\n outline: var(--vpg-focus-ring-width) solid var(--vpg-accent-ring);\n outline-offset: var(--vpg-focus-ring-offset);\n}\n\n.vpg-card-header {\n order: 1;\n padding: 1rem 1rem 0;\n}\n\n.vpg-card-content {\n order: 2;\n padding: 1rem;\n}\n\n.vpg-card-footer {\n order: 3;\n padding: 0 1rem 1rem;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n`;\n","import { Children, type HTMLAttributes, isValidElement, type KeyboardEvent, type MouseEvent, type ReactNode } from \"react\";\nimport { cardStylesheet } from \"./Card.stylesheet.js\";\n\nexport interface CardHeaderProps extends HTMLAttributes<HTMLDivElement> {\n children?: ReactNode;\n}\n\nexport interface CardContentProps extends HTMLAttributes<HTMLDivElement> {\n children?: ReactNode;\n}\n\nexport interface CardFooterProps extends HTMLAttributes<HTMLDivElement> {\n children?: ReactNode;\n}\n\nfunction CardHeader({ className, children, ...rest }: CardHeaderProps) {\n const classes = [\"vpg-card-header\", className].filter(Boolean).join(\" \");\n return (\n <div {...rest} className={classes}>\n {children}\n </div>\n );\n}\n\nfunction CardContent({ className, children, ...rest }: CardContentProps) {\n const classes = [\"vpg-card-content\", className].filter(Boolean).join(\" \");\n return (\n <div {...rest} className={classes}>\n {children}\n </div>\n );\n}\n\nfunction CardFooter({ className, children, ...rest }: CardFooterProps) {\n const classes = [\"vpg-card-footer\", className].filter(Boolean).join(\" \");\n return (\n <div {...rest} className={classes}>\n {children}\n </div>\n );\n}\n\nexport interface CardProps extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n /** Any mix of `Card.Header`, `Card.Content`, and `Card.Footer`, in any order — `Card.Content`\n * is required, and at most one of each is allowed. Anything else throws at render. */\n children: ReactNode;\n /** Makes the card itself the interactive element: `role=\"button\"`, focusable, `Enter`/`Space`\n * activate it. Renders as a `<div>` rather than a `<button>` because a `<button>`'s content\n * model forbids interactive content, and `Card.Footer`'s canonical content is a `<Button>`. */\n onClick?: (event: MouseEvent<HTMLDivElement>) => void;\n}\n\n/**\n * Validates that `children` is some mix of at most one `Card.Header`, exactly one\n * `Card.Content`, and at most one `Card.Footer` — falsy children (`null`/`undefined`/`false`/\n * `true`, the shape `cond && <Card.Footer />` produces) are skipped rather than treated as\n * invalid. Throws unconditionally, not gated on `NODE_ENV`, because an inconsistent Card is the\n * exact failure this compound API exists to prevent.\n */\nfunction validateChildren(children: ReactNode): void {\n let headerCount = 0;\n let contentCount = 0;\n let footerCount = 0;\n\n Children.forEach(children, (child) => {\n if (child === null || child === undefined || typeof child === \"boolean\") {\n return;\n }\n\n if (!isValidElement(child)) {\n throw new Error(\"Card only accepts Card.Header, Card.Content, and Card.Footer as children.\");\n }\n\n if (child.type === CardHeader) {\n headerCount += 1;\n if (headerCount > 1) {\n throw new Error(\"Card accepts at most one Card.Header child.\");\n }\n } else if (child.type === CardContent) {\n contentCount += 1;\n if (contentCount > 1) {\n throw new Error(\"Card accepts at most one Card.Content child.\");\n }\n } else if (child.type === CardFooter) {\n footerCount += 1;\n if (footerCount > 1) {\n throw new Error(\"Card accepts at most one Card.Footer child.\");\n }\n } else {\n throw new Error(\"Card only accepts Card.Header, Card.Content, and Card.Footer as children.\");\n }\n });\n\n if (contentCount === 0) {\n throw new Error(\"Card requires a Card.Content child.\");\n }\n}\n\n/** Elements `Card`'s own click/keydown activation defers to, rather than intercepting: a click or\n * a Space/Enter keypress that originated inside one of these (a `Card.Footer` `<Button>`, an\n * `<input>` in `Card.Content`) is that control's to handle, not the Card's. */\n// biome-ignore lint/security/noSecrets: a CSS selector, read as a high-entropy string\nconst INTERACTIVE_DESCENDANT_SELECTOR = \"button, a[href], input, select, textarea, [role='button']\";\n\n/** Whether `target` is, or is inside, an interactive element other than `root` itself — `root`\n * matching its own `[role=\"button\"]` selector is not a \"descendant\" to defer to. A mouse or\n * keyboard event's `target` inside a `Card` is always the element the pointer or focus landed\n * on, never a bare text node — DOM hit-testing resolves clicks to an `Element`. */\nfunction isInteractiveDescendant(target: EventTarget, root: HTMLElement): boolean {\n const closest = (target as HTMLElement).closest(INTERACTIVE_DESCENDANT_SELECTOR);\n return closest !== null && closest !== root;\n}\n\nfunction CardImpl({ className, children, onClick, onKeyDown, ...rest }: CardProps) {\n validateChildren(children);\n\n const interactive = onClick !== undefined;\n\n const classes = [\"vpg-card\", interactive ? \"vpg-card-interactive\" : \"\", className].filter(Boolean).join(\" \");\n\n // A click that bubbled up from a nested interactive element (a footer `Button`, say) is not\n // the Card being activated — the descendant already handled it, and firing `onClick` again\n // would double-activate both.\n function handleClick(event: MouseEvent<HTMLDivElement>) {\n if (isInteractiveDescendant(event.target, event.currentTarget)) {\n return;\n }\n onClick?.(event);\n }\n\n // Enter/Space activation matches native `<button>` behaviour; the element itself has to be a\n // `<div>` (see `CardProps.onClick`'s doc comment), so nothing supplies this for free. Only\n // wired up when interactive — a non-interactive card forwards a caller's own `onKeyDown`\n // through `rest` unmodified. Same descendant guard as `handleClick`: Space typed into a nested\n // `<input>`, or Enter on a nested link, is not the Card's to intercept.\n //\n // Dispatches a real click via `.click()` rather than calling `onClick` directly with the\n // keyboard event cast to a `MouseEvent` — a consumer reading `clientX`/`clientY`/`button` off\n // that event would get `undefined` on keyboard activation. `.click()` makes the browser fire an\n // actual `MouseEvent`, which re-enters `handleClick` (and its own descendant guard) for free.\n function handleKeyDown(event: KeyboardEvent<HTMLDivElement>) {\n onKeyDown?.(event);\n if (event.key !== \"Enter\" && event.key !== \" \") {\n return;\n }\n if (isInteractiveDescendant(event.target, event.currentTarget)) {\n return;\n }\n event.preventDefault();\n event.currentTarget.click();\n }\n\n const interactiveProps = interactive\n ? { role: \"button\" as const, tabIndex: 0, onClick: handleClick, onKeyDown: handleKeyDown }\n : { onKeyDown };\n\n return (\n <>\n {/*\n React 19 hoists and de-duplicates this by `href`, so N cards on a page inject one\n stylesheet.\n */}\n <style href=\"vpg-card\" precedence=\"vpg-card\">\n {cardStylesheet}\n </style>\n <div {...rest} {...interactiveProps} className={classes}>\n {children}\n </div>\n </>\n );\n}\n\ntype CardComponent = typeof CardImpl & {\n Header: typeof CardHeader;\n Content: typeof CardContent;\n Footer: typeof CardFooter;\n};\n\n/**\n * A structured content surface: `Card.Header`, `Card.Content` (required), and `Card.Footer`, in\n * any order in JSX — layout is CSS-driven (`order`), not JSX-order-dependent. Passing `onClick`\n * makes the whole card an interactive element.\n */\n// The `@__PURE__` annotation tells Rollup/esbuild this call has no side effect it can't see, so\n// an unused `Card` export (importing only `Button`, say) is tree-shaken out entirely instead of\n// keeping the whole module \"just in case\" `Object.assign` does something observable.\nexport const Card = /* @__PURE__ */ Object.assign(CardImpl, {\n Header: CardHeader,\n Content: CardContent,\n Footer: CardFooter,\n}) as CardComponent;\n","/**\n * `<FieldShell>`'s own styles — the bordered box a text-entry control composes, its two adornment\n * slots, and the states it reads out of the control it wraps.\n *\n * Injected as an inline `<style>` rather than a `.css` import so the package can stay\n * `\"sideEffects\": false` (same approach as `TextField`'s and `Dropdown`'s stylesheets).\n *\n * Every `--vpg-*` property is *read* here through `var()` and never assigned inline by the\n * component: an inline style declaration always wins over a stylesheet rule for the same property\n * on the same element, so an inline `--vpg-surface` would permanently shadow the dark-mode\n * reassignment in `@vipengele/react-tokens`'s base stylesheet and the shell would stop adapting to colour\n * mode.\n *\n * Every measurement is a scale step: the minimum height is the size scale's default control step,\n * the horizontal padding and the gap between the slots and the centre are spacing steps, and the\n * corner is the radius ladder's inner step, which is the step a field takes (ADR-0012). A literal\n * here is one more measurement agreeing with nothing, which is the drift `FieldShell` exists to\n * end (ADR-0011).\n *\n * The step is a floor rather than a fixed height: a single-line control sits at exactly the step,\n * and a centre that wraps onto a second line — a row of chips beside a trigger — grows the box\n * instead of overflowing it.\n *\n * The state rules match `> ` — a direct child of the shell — so each reads the wrapped control and\n * nothing deeper. An adornment slot holds an arbitrary subtree that can carry its own interactive\n * elements, a reveal or clear button among them, and an unscoped `:has(:disabled)`,\n * `:has([aria-invalid=\"true\"])` or `:has([aria-expanded=\"true\"])` treats one of those as the\n * field's own state: the whole field dims because a button beside the control is off, or takes the\n * accent border because a menu beside the control is open.\n */\nexport const fieldShellStylesheet = `\n.vpg-field-shell {\n display: flex;\n align-items: center;\n gap: var(--vpg-space-2);\n box-sizing: border-box;\n width: 100%;\n min-height: var(--vpg-size-md);\n padding: 0 var(--vpg-space-3);\n background-color: var(--vpg-surface);\n border: 1px solid var(--vpg-border-strong);\n border-radius: var(--vpg-radius-sm);\n color: var(--vpg-ink);\n transition: border-color var(--vpg-duration-fast) var(--vpg-ease-standard),\n box-shadow var(--vpg-duration-fast) var(--vpg-ease-standard),\n opacity var(--vpg-duration-fast) var(--vpg-ease-standard),\n background-color var(--vpg-duration-fast) var(--vpg-ease-standard);\n}\n\n/* The centre is whatever the caller passes as children — one control, or a pair of siblings such\n as a chip row beside a trigger. \\`min-width: 0\\` is what stops a flex item propagating its\n content's intrinsic width, so a wide centre shrinks inside the field rather than growing the\n field past what contains it. */\n.vpg-field-shell > *:not(.vpg-field-shell-leading, .vpg-field-shell-trailing) {\n flex: 0 1 auto;\n min-width: 0;\n}\n\n/* The centre's free space goes to its last element, and only to that one. A centre of one control\n is that element, so a lone \\`<input>\\` fills the field. A centre of several — a chip row, then a\n trigger — sizes every earlier element to its content and leaves the remainder to the trigger,\n where the caret goes; splitting the space evenly instead would stretch the chip row to half the\n field whatever it holds.\n\n \\`of\\` counts among the centre elements only, so the rule finds the last one whether or not a\n trailing slot follows it. */\n.vpg-field-shell > *:nth-last-child(1 of :not(.vpg-field-shell-leading, .vpg-field-shell-trailing)) {\n flex: 1;\n}\n\n.vpg-field-shell-leading,\n.vpg-field-shell-trailing {\n display: flex;\n align-items: center;\n flex: none;\n color: var(--vpg-ink-muted);\n}\n\n.vpg-field-shell:has(> :focus-visible) {\n border-color: var(--vpg-accent);\n box-shadow: 0 0 0 var(--vpg-focus-ring-width) var(--vpg-accent-ring);\n}\n\n/* The field whose control has its listbox open takes the accent border, so a pointer-opened\n combobox — which \\`:focus-visible\\` does not match — still reads as the field the listbox belongs\n to. Border only: the ring is keyboard focus's, and an open listbox does not claim it. The\n \\`:not()\\` hands an invalid field to the danger border outright, so which of the two wins never\n depends on the order these rules sit in or on the order stylesheets are injected. */\n.vpg-field-shell:has(> [aria-expanded=\"true\"]):not(:has(> [aria-invalid=\"true\"])) {\n border-color: var(--vpg-accent);\n}\n\n.vpg-field-shell:has(> [aria-invalid=\"true\"]) {\n border-color: var(--vpg-danger);\n}\n\n.vpg-field-shell:has(> [aria-invalid=\"true\"]):has(> :focus-visible) {\n box-shadow: 0 0 0 var(--vpg-focus-ring-width) var(--vpg-danger-ring);\n}\n\n.vpg-field-shell:has(> :disabled) {\n cursor: not-allowed;\n opacity: 0.55;\n}\n\n.vpg-field-shell:hover:not(:has(> :disabled)) {\n background-color: var(--vpg-surface-hover);\n}\n`;\n","import type { HTMLAttributes, ReactNode, Ref } from \"react\";\nimport { fieldShellStylesheet } from \"./FieldShell.stylesheet.js\";\n\nexport interface FieldShellProps extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n /**\n * A ref to `.vpg-field-shell`, the bordered box itself. A floating surface anchored to the\n * field — a listbox, a popover — positions against the whole field rather than the control\n * inside it, so the ref lands on the element whose border the surface has to align with and\n * whose width it has to match. `HTMLAttributes` carries no `ref`, so the prop is declared here.\n */\n ref?: Ref<HTMLDivElement>;\n /**\n * An adornment rendered in `.vpg-field-shell-leading`, before the centre — an icon, a\n * prefix, a currency symbol. Absent, the slot element is not rendered at all, so a shell with\n * no adornment holds no empty wrapper.\n */\n leading?: ReactNode;\n /**\n * An adornment rendered in `.vpg-field-shell-trailing`, after the centre — a unit, a\n * spinner, an interactive button. A disabled button here is the adornment's own state and\n * leaves the field undimmed; only the control dims the shell.\n */\n trailing?: ReactNode;\n /**\n * The control the shell decorates, and any sibling that belongs inside the field's boundary —\n * a chip row beside a trigger, for instance. The shell renders no field element of its own and\n * needs no knowledge of what it wraps.\n */\n children: ReactNode;\n}\n\n/**\n * The chrome of a text-entry control: a bordered, rounded, surface-filled box that takes a focus\n * ring, an accent border while the control's listbox is open (`aria-expanded=\"true\"`), a danger\n * border when the control is invalid and a dimmed treatment when it is disabled.\n * It owns the box, its states, its height, its horizontal padding and its width; the control it\n * wraps keeps its own element, class name, `className` and prop spread (ADR-0011).\n *\n * The DOM this renders is part of the component's API — `.vpg-field-shell` is the bordered\n * box, and each slot is a child of it, the leading one before the centre and the trailing one\n * after. Consumers style around those class names, so the shape is a commitment; the selectors\n * that read focus, openness, invalidity and disabledness out of the control are internal mechanics.\n */\nexport function FieldShell({ leading, trailing, className, children, ref, ...rest }: FieldShellProps) {\n const classes = [\"vpg-field-shell\", className].filter(Boolean).join(\" \");\n // React renders `false`, `null`, `undefined` and `\"\"` as nothing, but renders `0` as the\n // character \"0\" — so a slot is absent exactly when its value is one of the former, never by a\n // loose falsiness check that would also drop a present `0`.\n const hasLeading = leading !== undefined && leading !== null && leading !== \"\" && leading !== false;\n const hasTrailing = trailing !== undefined && trailing !== null && trailing !== \"\" && trailing !== false;\n\n return (\n <>\n {/*\n React 19 hoists and de-duplicates this by `href`, so N shells on a page inject one\n stylesheet.\n */}\n <style href=\"vpg-field-shell\" precedence=\"vpg-field-shell\">\n {fieldShellStylesheet}\n </style>\n <div {...rest} ref={ref} className={classes}>\n {hasLeading ? <span className=\"vpg-field-shell-leading\">{leading}</span> : null}\n {children}\n {hasTrailing ? <span className=\"vpg-field-shell-trailing\">{trailing}</span> : null}\n </div>\n </>\n );\n}\n","/**\n * The floating listbox, the panel a search row turns it into, its options, a group's heading and\n * the line between two groups, the option checkbox and\n * the multi-select chip row — the parts every combobox-shaped component in this package renders\n * identically. It lives here, injected\n * under its own `<style href>` by each component that needs it, rather than being duplicated per\n * component or imported from one component's directory into another's.\n *\n * Injected as an inline `<style>` rather than a `.css` import so the package can stay\n * `\"sideEffects\": false` (same approach as `Card`'s and `Popover`'s stylesheets).\n *\n * Every `--vpg-*` property is *read* here through `var()` and never assigned inline by a\n * component: an inline style declaration always wins over a stylesheet rule for the same property\n * on the same element, so an inline `--vpg-surface-raised` would permanently shadow the\n * dark-mode reassignment in `@vipengele/react-tokens`'s base stylesheet and the listbox would stop\n * adapting to colour mode. The only inline styles any of these elements carry are floating-ui's\n * computed `position`/`top`/`left`/`width`, which are plain CSS properties holding a per-instance\n * coordinate and the panel's match to the field it anchors to.\n *\n * An option's own text is a control's text, so it takes the type scale's `sm` step rather than the\n * prose `md` one. The panel carries the elevation family's medium step, one below the popover's.\n */\nexport const listboxStylesheet = `\n.vpg-listbox {\n position: absolute;\n z-index: var(--vpg-layer-listbox);\n box-sizing: border-box;\n margin: 0;\n padding: var(--vpg-space-1);\n /* The size of a container, not steps of anything: no scale carries a measurement this large,\n and a \\`--vpg-*\\` name the theme never assigns advertises a theming hook that doesn't\n exist. Width is floating-ui's inline style, matching the field exactly — this rule must\n never impose a floor wider than a narrow field, or the panel outgrows what it's anchored to. */\n max-height: 16rem;\n overflow-y: auto;\n background-color: var(--vpg-surface-raised);\n border: 1px solid var(--vpg-border);\n border-radius: var(--vpg-radius);\n box-shadow: var(--vpg-shadow-med);\n color: var(--vpg-ink);\n font-family: var(--vpg-font-sans);\n font-size: var(--vpg-font-size-sm);\n line-height: 1.5;\n}\n\n.vpg-listbox:focus-visible {\n /* The listbox takes DOM focus from nothing — the highlight is virtual — but it is still a\n focus target for a stray programmatic focus() call, and an invisible one reads as broken. */\n outline: var(--vpg-focus-ring-width) solid var(--vpg-accent-ring);\n outline-offset: var(--vpg-focus-ring-offset);\n}\n\n/* A search row turns the listbox into a panel holding two parts, and the floating element is then\n the panel rather than the listbox: it draws the surface \\`.vpg-listbox\\` draws for a listbox\n that is the floating element itself, and holds the search row still while the options scroll\n under it. \\`overflow: hidden\\` keeps the scrolling options inside the panel's rounded corners. */\n.vpg-listbox-panel {\n position: absolute;\n z-index: var(--vpg-layer-listbox);\n box-sizing: border-box;\n overflow: hidden;\n background-color: var(--vpg-surface-raised);\n border: 1px solid var(--vpg-border);\n border-radius: var(--vpg-radius);\n box-shadow: var(--vpg-shadow-med);\n color: var(--vpg-ink);\n font-family: var(--vpg-font-sans);\n font-size: var(--vpg-font-size-sm);\n line-height: 1.5;\n}\n\n/* The scrolling half of the panel, at the same height \\`.vpg-listbox\\` stands at — the size of\n a container, not a step of anything, so no \\`--vpg-*\\` name stands for it. The search row\n above it is outside this box and so never scrolls out of reach. */\n.vpg-listbox-options {\n padding: var(--vpg-space-1);\n max-height: 16rem;\n overflow-y: auto;\n}\n\n/* The panel's first row: the magnifier, then the input. Its lower border is the divider between\n the search and the options under it. The row stands at the same height as an option, so the\n panel's first two rows read as one rhythm. */\n.vpg-listbox-search {\n display: flex;\n align-items: center;\n gap: var(--vpg-space-2);\n box-sizing: border-box;\n min-height: var(--vpg-size-md);\n padding-inline: var(--vpg-space-3);\n border-bottom: 1px solid var(--vpg-border);\n}\n\n.vpg-listbox-search-icon {\n flex: none;\n width: var(--vpg-icon-md);\n height: var(--vpg-icon-md);\n color: var(--vpg-ink-muted);\n}\n\n/* The input carries none of a field's chrome: the panel's own border is the box around it, and a\n border or focus ring here would draw a second box inside that one. The panel opens with the\n caret already in this input, which is what marks it as the focused element. */\n.vpg-listbox-search-input {\n flex: 1;\n min-width: 0;\n appearance: none;\n padding: 0;\n background: none;\n border: none;\n outline: none;\n color: inherit;\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\n.vpg-listbox-search-input::placeholder {\n color: var(--vpg-ink-subtle);\n}\n\n/* Not an option: it carries no role, is never highlighted and cannot be selected — it exists so\n a query matching nothing says so instead of leaving the panel blank. Its padding is an option's\n block padding, so the message stands as tall as the option it stands in for. */\n.vpg-listbox-empty {\n padding: var(--vpg-space-2);\n color: var(--vpg-ink-subtle);\n}\n\n/* A heading, never a row the keyboard can reach: it is the group's name, and the options under it\n keep the indices they hold with no group around them. Its inline padding is an option's, so the\n heading and the labels beneath it share one left edge, and it takes the type scale's smallest\n step to read as a label over the rows rather than as one of them. */\n.vpg-listbox-group-label {\n padding-block: var(--vpg-space-1);\n padding-inline: var(--vpg-space-3);\n color: var(--vpg-ink-subtle);\n font-size: var(--vpg-font-size-xs);\n font-weight: var(--vpg-font-weight-medium);\n}\n\n/* The line between one group and the next, drawn by the group that follows another. A rule rather\n than a border on the group itself: the line spans the padding the options sit inside, so it\n reaches the full width of the list rather than stopping at an option's edge. */\n.vpg-listbox-separator {\n height: 1px;\n margin-block: var(--vpg-space-1);\n margin-inline: calc(var(--vpg-space-1) * -1);\n background-color: var(--vpg-border);\n}\n\n.vpg-listbox-option {\n display: flex;\n align-items: center;\n gap: var(--vpg-space-2);\n box-sizing: border-box;\n /* A row's height is a token read, not the sum of a padding and a line-height: min-height\n plus centred content holds it at the control scale's md step regardless of what the label's\n font metrics or an icon's box happen to add up to. */\n min-height: var(--vpg-size-md);\n padding-inline: var(--vpg-space-3);\n border-radius: var(--vpg-radius-sm);\n cursor: pointer;\n transition: background-color var(--vpg-duration-fast) var(--vpg-ease-standard);\n /* The highlight moves with the keyboard, not with the pointer, so an option must never look\n selectable-by-drag. */\n user-select: none;\n}\n\n/* The highlight is virtual — the option never takes DOM focus, so :focus/:hover cannot express\n it and the component sets this attribute from its own highlighted index instead. Highlight\n (background) and selection (a checkbox fill or a trailing check, never colour) read on\n different visual channels, so a row can carry both at once without either one washing out the\n other. */\n.vpg-listbox-option[data-highlighted] {\n background-color: var(--vpg-surface-hover);\n}\n\n.vpg-listbox-option[aria-disabled=\"true\"] {\n color: var(--vpg-ink-subtle);\n cursor: default;\n}\n\n.vpg-listbox-option-icon {\n flex: none;\n width: var(--vpg-icon-md);\n height: var(--vpg-icon-md);\n color: var(--vpg-ink-muted);\n}\n\n/* A single-select row's only selection signal: colour alone would fail WCAG 1.4.1, and\n \\`aria-selected\\` reaches assistive technology but not a sighted reader. Trailing edge matches\n the shadcn/Radix select convention. A multi-select row already carries the checkbox as its\n one encoding, so this mark never renders alongside it — \\`Dropdown\\` renders it only for a\n selected option outside \\`multiple\\`. */\n.vpg-listbox-option-check {\n flex: none;\n width: var(--vpg-icon-md);\n height: var(--vpg-icon-md);\n color: var(--vpg-accent);\n}\n\n.vpg-listbox-option-label {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* A drawn box rather than an <input type=\"checkbox\">: the option already carries\n role=\"option\" + aria-selected, and a real checkbox inside it would be an interactive\n element nested in one. */\n.vpg-listbox-checkbox {\n display: flex;\n align-items: center;\n justify-content: center;\n flex: none;\n box-sizing: border-box;\n width: 1.125rem;\n height: 1.125rem;\n border: 1px solid var(--vpg-border-strong);\n border-radius: var(--vpg-radius-sm);\n color: var(--vpg-accent-contrast);\n transition: background-color var(--vpg-duration-fast) var(--vpg-ease-standard),\n border-color var(--vpg-duration-fast) var(--vpg-ease-standard);\n}\n\n.vpg-listbox-checkbox[data-checked] {\n background-color: var(--vpg-accent);\n border-color: var(--vpg-accent);\n}\n\n/* The row of chips a multi-select field shows beside its control. It is a direct child of the\n field's shell, sitting before the control, within the width the shell leaves it. Wrapping is\n the shape it takes when the field asks for more than one row: each further line grows the field\n downwards rather than overflowing it, because the shell's height is a floor.\n\n One row of chips stands the field at the control step, the same height it has with no chips,\n so selecting the first option never makes the field jump. The field's content box is the\n control step less its border — 30px at the default scale — and a chip is 24px, leaving 3px on\n each side. The spacing scale's smallest step is 4px, which would grow the field to 34px, so the\n row pads each edge by half of it: 2px, which a single row fits inside and the shell centres, and\n which keeps the top and bottom rows of a wrapped field clear of its border. The rows themselves\n are a whole step apart. */\n.vpg-listbox-chips {\n display: flex;\n flex-wrap: wrap;\n gap: var(--vpg-space-1);\n padding-block: calc(var(--vpg-space-1) / 2);\n}\n\n/* One row, with the chips that do not fit measured out of it and an indicator standing for them.\n Which chips those are is the component's read, not a rule here: the attribute says the row\n collapses, and each chip the read excluded carries \\`data-hidden\\`.\n\n \\`nowrap\\` is what holds the field at the control step in the one case the read cannot resolve:\n a chip too wide to share the row with the indicator still shows, and wrapping would put the two\n on separate rows rather than shrinking the chip to the room the indicator leaves. */\n.vpg-listbox-chips[data-collapsing] {\n flex-wrap: nowrap;\n}\n\n.vpg-listbox-chips[data-collapsing] > [data-hidden] {\n display: none;\n}\n\n/* The read that decides which chips fit needs every one of them on the row at its own width: a\n hidden chip has no width to weigh, a shrunk one reports the row's constraint rather than its\n label, and the row itself shrinks to whatever is left in it once some are hidden. This\n attribute is set and removed inside one synchronous measurement, so the state it describes\n never paints. */\n.vpg-listbox-chips[data-collapsing][data-measuring] > * {\n display: inline-flex;\n flex: none;\n}\n\n/* A chip's height is a token read, not the sum of a padding and a line-height: a fixed height\n plus centred content holds it at the control scale's xs step regardless of the label's font\n metrics. Its end carries no padding, so the remove button's round hover fill sits concentric\n with the chip's own rounded end. */\n.vpg-listbox-chip {\n display: inline-flex;\n align-items: center;\n gap: var(--vpg-space-1);\n box-sizing: border-box;\n height: var(--vpg-size-xs);\n padding-inline: var(--vpg-space-2) 0;\n background-color: var(--vpg-accent-wash);\n border: 1px solid transparent;\n border-radius: var(--vpg-radius-full);\n color: var(--vpg-ink);\n font-family: var(--vpg-font-sans);\n font-size: var(--vpg-font-size-sm);\n line-height: 1.5;\n}\n\n/* A chip never outgrows the row that holds it: a label too long for the field is cut short\n rather than pushing the chip, and the field with it, past the field's border.\n\n \\`min-width\\` is what lets it be cut short at all. A flex item's automatic minimum size is its\n content's, which for a chip is its label's longest word — so a chip holding one long word takes\n the whole row and pushes the overflow indicator out past the field's border. The label carries\n the ellipsis that keeps the shorter box readable. */\n.vpg-listbox-chips > .vpg-listbox-chip {\n min-width: 0;\n max-width: 100%;\n}\n\n/* The indicator standing for the chips the row has no width for. A chip's box without a chip's\n remove button: the selection it covers is unpicked in the listbox, since the chip carrying it\n is not on screen to remove it from — so it pads both ends alike and keeps its own width, which\n is the width the read reserves before any chip is counted onto the row. */\n.vpg-listbox-overflow-chip {\n display: inline-flex;\n align-items: center;\n flex: none;\n box-sizing: border-box;\n height: var(--vpg-size-xs);\n padding-inline: var(--vpg-space-2);\n background-color: var(--vpg-accent-wash);\n border: 1px solid transparent;\n border-radius: var(--vpg-radius-full);\n color: var(--vpg-ink-muted);\n font-family: var(--vpg-font-sans);\n font-size: var(--vpg-font-size-sm);\n line-height: 1.5;\n white-space: nowrap;\n}\n\n.vpg-listbox-chip-label {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* A square as tall as the chip's inside: the glyph plus a spacing step on every side, which at the\n default scale is 22px — the whole of the chip's height inside its border, so the target is as\n large as a 24px chip allows. */\n.vpg-listbox-chip-remove {\n display: flex;\n align-items: center;\n justify-content: center;\n flex: none;\n appearance: none;\n padding: var(--vpg-space-1);\n background: none;\n border: none;\n border-radius: var(--vpg-radius-full);\n color: var(--vpg-ink-muted);\n cursor: pointer;\n transition: background-color var(--vpg-duration-fast) var(--vpg-ease-standard),\n color var(--vpg-duration-fast) var(--vpg-ease-standard);\n}\n\n.vpg-listbox-chip-remove-icon {\n flex: none;\n width: var(--vpg-icon-sm);\n height: var(--vpg-icon-sm);\n}\n\n.vpg-listbox-chip-remove:hover {\n background-color: var(--vpg-accent-wash);\n color: var(--vpg-ink);\n}\n\n.vpg-listbox-chip-remove:focus-visible {\n outline: var(--vpg-focus-ring-width) solid var(--vpg-accent-ring);\n outline-offset: var(--vpg-focus-ring-offset);\n}\n`;\n","import {\n autoUpdate,\n flip,\n offset,\n size,\n type UseFloatingReturn,\n type UseInteractionsReturn,\n useClick,\n useDismiss,\n useFloating,\n useInteractions,\n useListNavigation,\n useRole,\n useTypeahead,\n} from \"@floating-ui/react\";\nimport { type MouseEvent, type RefObject, useCallback, useMemo, useRef } from \"react\";\n\n/** Gap between the field and its listbox, in pixels. */\nconst LISTBOX_OFFSET = 4;\n\n/** Minimum gap `flip` wants between the listbox and the viewport's edge before it keeps the\n * listbox on its side of the field, in pixels. */\nconst VIEWPORT_PADDING = 12;\n\n/** The same props without the highlight's id, for an element that does not hold real focus. */\nfunction withoutActiveDescendant(props: Record<string, unknown>): Record<string, unknown> {\n const rest = { ...props };\n delete rest[\"aria-activedescendant\"];\n return rest;\n}\n\nexport interface UseListboxKeyboardOptions {\n /** The option elements, in the order they are rendered — each option registers itself at its\n * own index. Arrow-key navigation and type-ahead both read the list from here, so it must hold\n * the elements currently in the document, not a snapshot. */\n listRef: RefObject<Array<HTMLElement | null>>;\n /** The highlighted option's index, or `null` for none. State lives in the calling component,\n * never in this hook: `Dropdown` re-scopes it on every query change through its own\n * `applyQuery`, which a hook owning the state would make impossible without widening this\n * signature. */\n activeIndex: number | null;\n /** Called with the new highlighted index on every arrow-key move, `Home`/`End` jump, hover, and\n * type-ahead match. */\n onNavigate: (index: number | null) => void;\n /** Indices of options excluded from arrow-key traversal and from type-ahead matching. */\n disabledIndices: number[];\n /** Whether typing a character jumps the highlight to the next matching label. Off for a\n * filtering combobox, where typing goes to the text input instead. */\n typeahead: boolean;\n /** `\"select\"` puts `role=\"combobox\"` and `aria-haspopup=\"listbox\"` on the reference element —\n * what a component rendering its own non-input trigger wants. `\"combobox\"` leaves the role to\n * the reference element itself, for a component whose trigger is already an `<input>`. */\n role: \"select\" | \"combobox\";\n /** Whether the caller renders a search input inside the floating element and gives it real\n * focus, with `getSearchProps()` and a non-modal `FloatingFocusManager`. Off, the reference\n * element keeps real focus and `getSearchProps()` is never called. */\n search?: boolean;\n open: boolean;\n onOpenChange: (open: boolean) => void;\n}\n\nexport interface UseListboxKeyboardReturn\n extends UseInteractionsReturn,\n Pick<UseFloatingReturn, \"refs\" | \"floatingStyles\" | \"context\" | \"elements\"> {\n /** The nearest `.vpg-root` ancestor of the reference element, or `null` when there is none\n * to portal the listbox into. */\n themeRoot: Element | null;\n /** A callback ref for the field — the bordered box around the reference element. The listbox is\n * positioned against it and sized to its width, and a press anywhere inside it is not a press\n * outside the listbox. Left unattached, the listbox anchors to the reference element and only a\n * press outside the reference and the listbox closes it. */\n fieldRef: (node: HTMLElement | null) => void;\n /** The field's `mousedown` handler. A press on the field outside the reference element keeps\n * focus where it is, so the reference element never loses focus to the field's own padding, a\n * chip row or an adornment. A primary press there that does not land on a button also focuses\n * the reference element and opens the listbox; a button — a chip's remove button — keeps its\n * press for its own `click`. */\n onFieldMouseDown: (event: MouseEvent<HTMLElement>) => void;\n /** Props for the search input inside the floating element, in `search` mode: the listbox role\n * wiring and the arrow, `Home` and `End` handling, so the input is what drives the list and\n * what carries `aria-activedescendant`. `useClick` is left out of them: its press handler\n * toggles the listbox, and a press on the input to place the caret would close the popover the\n * input lives in. */\n getSearchProps: UseInteractionsReturn[\"getReferenceProps\"];\n}\n\n/**\n * The floating-listbox glue shared by every combobox-shaped component in this package: positions\n * the listbox, and composes `@floating-ui/react`'s `useListNavigation({ virtual: true })`,\n * `useTypeahead` and `useRole` into one set of prop getters.\n *\n * Virtual focus is the whole point — the highlighted option is tracked through\n * `aria-activedescendant`, and real DOM focus never enters the listbox itself (see\n * `docs/adr/0004-aria-activedescendant-for-dropdown-and-autocomplete.md`). The element holding\n * real focus is the reference element, and in `search` mode a search input inside the floating\n * element instead — a `role=\"combobox\"` of its own, taking `getSearchProps()`. That mode is the\n * only one where the caller wraps the floating element in a **non-modal** `FloatingFocusManager`:\n * the manager moves real focus into the floating element, which is what puts the caret in the\n * search input, and what returns focus to the reference element when the listbox closes. Modal\n * would be wrong — the trigger and the page behind it stay reachable.\n *\n * Two elements anchor the listbox. The reference element — the trigger or input the consumer\n * focuses — carries the interactions, and stays `elements.domReference` for the whole lifecycle,\n * `search` mode included: floating-ui reads it for its typeable-combobox handling, its focus\n * restore and `useClick`'s space key, none of which a reference that moved between open and shut\n * would survive.\n *\n * The field around it is only the position reference: the listbox sits below the field's border\n * and matches its width, where\n * anchoring to the reference element would start it wherever that element starts — after the\n * field's padding and any chips beside it — and size it to nothing in particular.\n *\n * The field is also one press target. A non-focusable part of it — its padding, the gaps in a chip\n * row, a chevron — takes focus off the reference element when pressed and hands it to `<body>`.\n * Since that press is not outside the listbox, the listbox would stay open with nothing left to\n * receive the arrow keys; `onFieldMouseDown` keeps focus on the reference element instead.\n *\n * `useClick`'s keyboard handlers are switched off. They toggle the listbox on `Enter` and `Space`,\n * which are the keys that select the highlighted option once it is open — the caller owns both\n * keys and decides what they mean for the current open state.\n */\nexport function useListboxKeyboard({\n listRef,\n activeIndex,\n onNavigate,\n disabledIndices,\n typeahead,\n role,\n search = false,\n open,\n onOpenChange,\n}: UseListboxKeyboardOptions): UseListboxKeyboardReturn {\n const { refs, floatingStyles, context, elements } = useFloating({\n open,\n onOpenChange: (next) => {\n onOpenChange(next);\n },\n placement: \"bottom-start\",\n // The listbox's left edge and width are the field's wherever the field is, flush against the\n // viewport's edge or partly scrolled past it. At `bottom-start` with equal widths the listbox\n // overflows horizontally exactly where the field does, so nothing slides it sideways: a\n // `shift` would only pull it off the field's edge. `flip` alone moves it, from below the field\n // to above it. `size` runs last so it reads the placement `flip` settled on. Its width is the\n // field's border box, written straight onto the element because floating-ui computes it\n // outside render; `autoUpdate` observes the field's size, so a field that grows as its chips\n // wrap re-runs the whole chain.\n middleware: [\n offset(LISTBOX_OFFSET),\n flip({ padding: VIEWPORT_PADDING }),\n size({\n apply({ rects, elements: { floating } }) {\n floating.style.width = `${rects.reference.width}px`;\n },\n }),\n ],\n whileElementsMounted: autoUpdate,\n });\n\n const fieldElementRef = useRef<HTMLElement | null>(null);\n const fieldRef = useCallback(\n (node: HTMLElement | null) => {\n fieldElementRef.current = node;\n refs.setPositionReference(node);\n },\n [refs],\n );\n\n function onFieldMouseDown(event: MouseEvent<HTMLElement>) {\n const reference = refs.domReference.current as HTMLElement;\n const target = event.target as Element;\n // A press on the reference element is the reference element's own, and `useClick` handles it.\n if (reference.contains(target)) {\n return;\n }\n // Stops the press moving focus, not the `click` that follows it, so a button pressed here\n // still acts.\n event.preventDefault();\n if (event.button !== 0 || target.closest(\"button\") !== null) {\n return;\n }\n reference.focus();\n onOpenChange(true);\n }\n\n const disabledIndicesRef = useRef(disabledIndices);\n disabledIndicesRef.current = disabledIndices;\n\n // `useTypeahead` matches against a ref of label strings, which this reads straight off the\n // rendered options rather than taking as a second list the caller has to keep in step with\n // `listRef`. A getter rather than a stored array because the labels are read at keypress time:\n // an array computed during render is one commit behind the options that are actually mounted.\n // A disabled option's label is `null`, which is how `useTypeahead` is told to skip it.\n const labelsRef = useMemo<RefObject<Array<string | null>>>(\n () => ({\n get current(): Array<string | null> {\n return listRef.current.map((item, index) =>\n item !== null && !disabledIndicesRef.current.includes(index) ? item.textContent : null,\n );\n },\n }),\n [listRef],\n );\n\n const click = useClick(context, { keyboardHandlers: false });\n // The field holds more than the reference element — its padding, a chip row, an adornment such\n // as a chevron — and a press on any of those belongs to the control. Counted as an outside\n // press, it closes the listbox and drops the highlight, so a handler on that press reopening the\n // listbox leaves `Enter` with nothing to select. Returning `true` only lets floating-ui carry on\n // with its own checks, which still exempt the reference and floating elements; so with no field\n // attached, a press outside those two closes the listbox exactly as it would without this.\n const dismiss = useDismiss(context, {\n outsidePress: (event) => {\n const field = fieldElementRef.current;\n return field === null || !field.contains(event.target as Node);\n },\n // In `search` mode the press that closes the listbox is the `click`, not the `pointerdown`\n // that starts it. Real focus is inside the floating element, and `FloatingFocusManager`\n // returns it to the reference element as the floating element unmounts; closing on\n // `pointerdown` puts that return before `mousedown`'s own default action, which then blanks\n // focus to `<body>` when the press landed on something unfocusable. Closing on `click`\n // leaves the browser's focus move first and the return last. Where the press landed on\n // something focusable, the manager sees focus already outside and leaves it there.\n outsidePressEvent: search ? \"click\" : \"pointerdown\",\n });\n const listboxRole = useRole(context, { role });\n const listNavigation = useListNavigation(context, {\n listRef,\n activeIndex,\n onNavigate,\n disabledIndices,\n virtual: true,\n loop: true,\n });\n // `ignoreKeys: [\" \"]` keeps `Space` out of the typed string: it is the caller's selection key,\n // and a type-ahead search that starts with a space matches no label anyway.\n const typeaheadInteraction = useTypeahead(context, {\n listRef: labelsRef,\n activeIndex,\n onMatch: onNavigate,\n enabled: typeahead,\n ignoreKeys: [\" \"],\n });\n\n const {\n getReferenceProps: getMergedReferenceProps,\n getFloatingProps: getMergedFloatingProps,\n getItemProps,\n } = useInteractions([click, dismiss, listboxRole, listNavigation, typeaheadInteraction]);\n\n // The search input drives the list, so it takes the same navigation and listbox-role props the\n // reference element takes in every other mode — floating-ui's own prop getter, not keys\n // forwarded by hand. `useClick` is the one it must not take: its reference handler toggles the\n // listbox on a press, so a press placing the caret in the input would close the popover the\n // input lives in. `useDismiss` is left out for having nothing to add here — its `Escape` is\n // already on the document, and it answers the input's `Escape` wherever focus sits.\n const searchInteractions = useInteractions([listboxRole, listNavigation]);\n const getSearchProps = useCallback<UseInteractionsReturn[\"getReferenceProps\"]>(\n (userProps) => searchInteractions.getReferenceProps({ \"aria-autocomplete\": \"list\", ...userProps }),\n [searchInteractions],\n );\n\n // `aria-activedescendant` names the highlight to whichever element holds real focus, and\n // floating-ui offers it to the reference and floating elements alike. In `search` mode that is\n // the search input alone: a second copy on the trigger or on the listbox states a focused\n // highlight on an element that has no focus.\n const getReferenceProps = useCallback<UseInteractionsReturn[\"getReferenceProps\"]>(\n (userProps) => (search ? withoutActiveDescendant(getMergedReferenceProps(userProps)) : getMergedReferenceProps(userProps)),\n [getMergedReferenceProps, search],\n );\n const getFloatingProps = useCallback<UseInteractionsReturn[\"getFloatingProps\"]>(\n (userProps) => (search ? withoutActiveDescendant(getMergedFloatingProps(userProps)) : getMergedFloatingProps(userProps)),\n [getMergedFloatingProps, search],\n );\n\n // `ThemeProvider` assigns every `--vpg-*` property on `.vpg-root`, so a listbox\n // portaled to `document.body` would resolve every `var()` to nothing. `null` means there is no\n // themed root to portal into — an unthemed page, or a test rendering the component on its own —\n // and the caller renders the listbox inline instead.\n const themeRoot = elements.domReference?.closest(\".vpg-root\") ?? null;\n\n return {\n refs,\n floatingStyles,\n context,\n elements,\n themeRoot,\n fieldRef,\n onFieldMouseDown,\n getReferenceProps,\n getFloatingProps,\n getItemProps,\n getSearchProps,\n };\n}\n","/**\n * `<Tooltip>`'s own styles, injected as an inline `<style>` rather than a `.css` import so the\n * package can stay `\"sideEffects\": false` (same approach as `Button`'s and `Avatar`'s\n * stylesheets).\n *\n * Every `--vpg-*` property is *read* here through `var()` and never assigned inline by the\n * component: an inline style declaration always wins over a stylesheet rule for the same\n * property on the same element, so an inline `--vpg-ink` would permanently shadow the\n * dark-mode reassignment in `@vipengele/react-tokens`'s base stylesheet and this tooltip would stop\n * adapting to colour mode. The component's only inline style is floating-ui's computed\n * `position`/`top`/`left`, which are plain CSS properties carrying a per-instance coordinate.\n *\n * The bubble inverts the surface: `--vpg-ink` as background against `--vpg-surface` as\n * text. Both flip together with colour mode, so a small floating label keeps the widest contrast\n * the theme offers in either mode without hard-coding a colour.\n *\n * The label takes a step of the type scale, and the bubble the top step of the stacking family:\n * a tooltip can be triggered from inside any other floating surface and must never be occluded by\n * its own trigger.\n */\nexport const tooltipStylesheet = `\n.vpg-tooltip-trigger {\n /* Inline-flex rather than inline: the wrapper exists only to carry the ref and the hover/focus\n handlers, and must not add a baseline gap under the element it wraps. */\n display: inline-flex;\n}\n\n.vpg-tooltip {\n position: absolute;\n z-index: var(--vpg-layer-tooltip);\n box-sizing: border-box;\n /* The size of a container, not a step of anything: no scale carries a measurement this large,\n and a \\`--vpg-*\\` name the theme never assigns advertises a theming hook that doesn't\n exist. */\n max-width: 16rem;\n padding: 0.25rem 0.5rem;\n border-radius: var(--vpg-radius-sm);\n background-color: var(--vpg-ink);\n color: var(--vpg-surface);\n font-family: var(--vpg-font-sans);\n font-size: var(--vpg-font-size-xs);\n line-height: 1.4;\n /* A tooltip that could be hovered would sit between the pointer and the trigger and flicker\n the trigger's own hover state off. */\n pointer-events: none;\n /* Long content wraps against max-width instead of stretching off-screen; an explicit newline\n in the content is still honoured. */\n white-space: pre-line;\n overflow-wrap: break-word;\n}\n`;\n","import { autoUpdate, flip, offset, shift, useDismiss, useFloating, useFocus, useHover, useInteractions, useRole } from \"@floating-ui/react\";\nimport { cloneElement, Fragment, isValidElement, type ReactNode, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { tooltipStylesheet } from \"./Tooltip.stylesheet.js\";\n\nexport type TooltipPlacement = \"top\" | \"bottom\" | \"left\" | \"right\";\n\nexport interface TooltipProps {\n /** The label the bubble shows. */\n content: ReactNode;\n /** The element the bubble describes. It is wrapped in a `<span>` that carries the ref and the\n * hover/focus handlers — not cloned for those, so it can be any node, including a component\n * that doesn't forward a ref or spread unknown props. When it is a single element, it is\n * additionally cloned with just `aria-describedby` merged on, so the description is announced\n * on the actual focusable control rather than the (never-focused) wrapper. */\n children: ReactNode;\n /** Preferred side of the trigger. Floating-ui flips to the opposite side when the bubble\n * wouldn't fit there. */\n placement?: TooltipPlacement;\n /** Suppresses the tooltip entirely: no hover or focus handler is registered and the bubble\n * never renders. Lives on `Tooltip` rather than being read off the trigger's props, because\n * the trigger is wrapped rather than cloned — its props are never inspected. */\n disabled?: boolean;\n /** Composed onto the bubble, not onto the trigger wrapper. */\n className?: string;\n}\n\n/** Gap between the trigger and the bubble, in pixels. */\nconst TOOLTIP_OFFSET = 8;\n\n/** Minimum gap kept between the bubble and the viewport edge when it has to shift, in pixels. */\nconst VIEWPORT_PADDING = 8;\n\n/**\n * A small floating label describing its trigger, shown on hover and on keyboard focus and\n * dismissed on `Escape`.\n *\n * The bubble portals into the nearest ancestor `.vpg-root` rather than `document.body`:\n * `ThemeProvider` assigns every `--vpg-*` property on `.vpg-root`, so a bubble outside\n * that subtree would resolve every `var()` to nothing and lose colour-mode adaptation entirely.\n * With no `.vpg-root` ancestor — an unthemed page, or a test rendering the component on its\n * own — the bubble renders inline as the trigger's sibling instead. It is positioned by the same\n * computed coordinates either way; only the `--vpg-*` values it inherits differ.\n */\nexport function Tooltip({ content, children, placement = \"top\", disabled = false, className }: TooltipProps) {\n const [requestedOpen, setRequestedOpen] = useState(false);\n const enabled = !disabled;\n const open = requestedOpen && enabled;\n\n const { refs, floatingStyles, context, elements } = useFloating({\n open,\n onOpenChange: setRequestedOpen,\n placement,\n middleware: [offset(TOOLTIP_OFFSET), flip(), shift({ padding: VIEWPORT_PADDING })],\n whileElementsMounted: autoUpdate,\n });\n\n // `useRole` with `role: \"tooltip\"` is what pairs `role`/`id` on the bubble with\n // `aria-describedby` on the trigger wrapper, off a `useId`-generated id it owns; setting\n // either half by hand would leave the other pointing at a different id.\n const hover = useHover(context, { enabled });\n const focus = useFocus(context, { enabled });\n const dismiss = useDismiss(context, { enabled, referencePress: false });\n const tooltipRole = useRole(context, { enabled, role: \"tooltip\" });\n const { getReferenceProps, getFloatingProps } = useInteractions([hover, focus, dismiss, tooltipRole]);\n\n // `aria-describedby` has to sit on the element that actually receives focus, or a screen\n // reader never announces it — the wrapper `<span>` itself is never focused. When `children` is\n // a single element, it is cloned with just this one plain prop merged on (not the ref or the\n // hover/focus handlers, which a component that doesn't forward refs — `Button` included —\n // can't accept; see `wrap-trigger-never-clone.md`). Anything else (plain text, a fragment,\n // multiple nodes) has no single focusable target to clone onto, so the description falls back\n // to the wrapper.\n const { \"aria-describedby\": describedBy, ...referenceProps } = getReferenceProps() as Record<string, unknown> & {\n \"aria-describedby\"?: string;\n };\n // A `Fragment` passes `isValidElement` too, but wraps zero or more children rather than\n // naming one DOM node to clone the prop onto — excluded the same as text, arrays, and\n // everything else that falls back to the wrapper.\n const hasSingleElementChild = isValidElement<{ \"aria-describedby\"?: string }>(children) && children.type !== Fragment;\n const trigger = hasSingleElementChild ? cloneElement(children, { \"aria-describedby\": describedBy }) : children;\n\n const bubble = open ? (\n <div\n ref={refs.setFloating}\n className={[\"vpg-tooltip\", className].filter(Boolean).join(\" \")}\n style={floatingStyles}\n {...getFloatingProps()}\n >\n {content}\n </div>\n ) : null;\n\n const themeRoot = elements.domReference?.closest(\".vpg-root\") ?? null;\n\n return (\n <>\n {/*\n React 19 hoists and de-duplicates this by `href`, so N tooltips on a page inject one\n stylesheet.\n */}\n <style href=\"vpg-tooltip\" precedence=\"vpg-tooltip\">\n {tooltipStylesheet}\n </style>\n <span\n ref={refs.setReference}\n className=\"vpg-tooltip-trigger\"\n aria-describedby={hasSingleElementChild ? undefined : describedBy}\n {...referenceProps}\n >\n {trigger}\n </span>\n {bubble !== null && themeRoot !== null ? createPortal(bubble, themeRoot) : bubble}\n </>\n );\n}\n","/**\n * `<Dropdown>`'s own styles — the wrapper, the `role=\"combobox\"` trigger and the clear button in\n * the field's trailing slot. The field's box is\n * `FieldShell`'s, composed with the extra class `.vpg-dropdown-control`; the floating listbox,\n * its options, the chip row and its chips are styled by the shared\n * `internal/listbox.stylesheet.ts`, which every combobox-shaped component in this package injects.\n *\n * Injected as an inline `<style>` rather than a `.css` import so the package can stay\n * `\"sideEffects\": false` (same approach as `Card`'s and `Popover`'s stylesheets).\n *\n * Every `--vpg-*` property is *read* here through `var()` and never assigned inline by the\n * component: an inline style declaration always wins over a stylesheet rule for the same property\n * on the same element, so an inline `--vpg-ink` would permanently shadow the dark-mode\n * reassignment in `@vipengele/react-tokens`'s base stylesheet and the trigger would stop adapting to\n * colour mode.\n *\n * Nothing here draws the field's chrome. The border, fill, corner radius, height, horizontal\n * padding, focus ring, danger border and hover fill are the shell's, read off the trigger as its\n * direct child; a second copy of any of them here draws a box inside the field's box, or a ring\n * inside its ring (ADR-0011). The trigger carries `outline: none` for the same reason — the shell\n * draws the focus ring, and the trigger's native outline would sit inside it.\n */\nexport const dropdownStylesheet = `\n/* A block box the width of its container, like \\`TextField\\`: the field never widens as options\n are selected and never narrows below its container either. \\`box-sizing: border-box\\` keeps\n that width inclusive of the field's own border and padding.\n\n \\`min-width: 0\\` is what makes that hold in a flex or grid container. The initial \\`auto\\`\n resolves there to the automatic minimum size — the root's min-content, which a row of chips\n and a long trigger label make wide — and that floor outranks \\`width: 100%\\`, so the field\n pushes its track open and overflows whatever width the container was given. */\n.vpg-dropdown {\n display: block;\n box-sizing: border-box;\n width: 100%;\n min-width: 0;\n color: var(--vpg-ink);\n font-family: var(--vpg-font-sans);\n}\n\n/* \\`align-self: stretch\\` gives the trigger the field's full height, so a click anywhere across it\n opens the listbox; a percentage height would collapse, because the shell's height is a floor\n rather than a definite length. */\n.vpg-dropdown-trigger {\n display: flex;\n align-items: center;\n align-self: stretch;\n gap: var(--vpg-space-2);\n outline: none;\n color: inherit;\n font-size: var(--vpg-font-size-sm);\n line-height: 1.5;\n cursor: pointer;\n user-select: none;\n}\n\n/* The shell lets every centre element shrink to nothing, which beside a row of chips would leave\n the trigger — the only thing that opens the listbox — with no width at all. A square of the\n field's own height keeps it a target and keeps room for the chevron. Qualified by both classes\n the shell element carries, so it outranks the shell's own \\`min-width: 0\\` whichever stylesheet\n the page injects first. */\n.vpg-field-shell.vpg-dropdown-control > .vpg-dropdown-trigger {\n min-width: var(--vpg-size-md);\n}\n\n.vpg-dropdown-trigger-icon,\n.vpg-dropdown-chevron {\n flex: none;\n}\n\n/* Matches \\`.vpg-listbox-option-icon\\`: the same icon at the same size in the trigger as in\n the list it came from, rather than lucide's own 24px default. */\n.vpg-dropdown-trigger-icon {\n width: var(--vpg-icon-md);\n height: var(--vpg-icon-md);\n}\n\n/* \\`margin-left: auto\\` is what sets the chevron against the field's trailing edge. A \\`multiple\\`\n trigger holding a selection contains the chevron and nothing else, so no sibling claims the\n trigger's free space and the chevron would otherwise sit at its leading edge, floating\n mid-field. The margin is inert wherever a \\`flex: 1\\` sibling has already absorbed that space —\n single-select's value and either mode's placeholder — since there is none left for it to take. */\n.vpg-dropdown-chevron {\n margin-left: auto;\n color: var(--vpg-ink-muted);\n}\n\n/* Takes the trigger's free space, so the chevron's auto margin resolves to nothing and the label\n keeps the field's leading edge. */\n.vpg-dropdown-value {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.vpg-dropdown-placeholder {\n flex: 1;\n color: var(--vpg-ink-subtle);\n}\n\n/* The clear button stands in the shell's trailing slot, a subtree the shell's \\`> \\` state rules do\n not reach into — so its focus ring is its own, and the field takes none from it. It carries no\n \\`opacity\\` either: the shell already dims for a disabled control, and a second fade here reads\n as more faded than the field around it. */\n.vpg-dropdown-clear {\n display: flex;\n align-items: center;\n justify-content: center;\n flex: none;\n appearance: none;\n padding: var(--vpg-space-1);\n background: none;\n border: none;\n border-radius: var(--vpg-radius-full);\n color: var(--vpg-ink-muted);\n cursor: pointer;\n transition: background-color var(--vpg-duration-fast) var(--vpg-ease-standard),\n color var(--vpg-duration-fast) var(--vpg-ease-standard);\n}\n\n.vpg-dropdown-clear-icon {\n flex: none;\n width: var(--vpg-icon-sm);\n height: var(--vpg-icon-sm);\n}\n\n.vpg-dropdown-clear:hover {\n background-color: var(--vpg-accent-wash);\n color: var(--vpg-ink);\n}\n\n.vpg-dropdown-clear:focus-visible {\n outline: var(--vpg-focus-ring-width) solid var(--vpg-accent-ring);\n outline-offset: var(--vpg-focus-ring-offset);\n}\n\n/* Names every selection to a screen reader while taking no space in the field, which is the only\n route to the chips the row has no width for: those are out of the flow altogether. */\n.vpg-dropdown-selection-description {\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 white-space: nowrap;\n border: 0;\n}\n`;\n","import { FloatingFocusManager } from \"@floating-ui/react\";\nimport { Check, ChevronDown, type IconComponent, Search, X } from \"@vipengele/react-icons\";\nimport {\n type ChangeEvent,\n Children,\n createContext,\n isValidElement,\n type KeyboardEvent,\n type ReactNode,\n useContext,\n useEffect,\n useId,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\";\nimport { createPortal, flushSync } from \"react-dom\";\nimport { FieldShell } from \"../FieldShell/FieldShell.js\";\nimport { listboxStylesheet } from \"../internal/listbox.stylesheet.js\";\nimport { useListboxKeyboard } from \"../internal/useListboxKeyboard.js\";\nimport { Tooltip } from \"../Tooltip/Tooltip.js\";\nimport { dropdownStylesheet } from \"./Dropdown.stylesheet.js\";\n\nexport interface DropdownOptionProps {\n /** This option's identity. A selection carrying the same string is this option, whatever label\n * the selection itself carries. */\n value: string;\n /** The option's text. A plain string rather than children: it is also what the trigger shows\n * for the current selection, what a chip shows in `multiple` mode, and what type-ahead matches\n * a keystroke against. */\n label: string;\n /** Rendered before the label, and — for the selected option in single-select — in the trigger\n * too. */\n icon?: IconComponent;\n /** Skipped by arrow-key and type-ahead traversal, and not selectable by click or `Enter`. */\n disabled?: boolean;\n}\n\nexport interface DropdownGroupProps {\n /** The heading drawn above the group's options, and the group's accessible name. */\n label: string;\n /** `Dropdown.Option` children, and nothing else: a group heads one run of options rather than a\n * tree, so a `Dropdown.Group` among them throws. Falsy children are skipped, as directly under\n * `Dropdown`. */\n children?: ReactNode;\n}\n\n/**\n * A selection, as `Dropdown` takes it and hands it back. The `value` string is the identity: a\n * consumer that re-creates this object on every render keeps its selection, because nothing in\n * `Dropdown` compares object references.\n *\n * The `label` and `icon` are what renders when no `Dropdown.Option` child carries this `value` —\n * a matching option's own label and icon win over them.\n */\nexport interface DropdownValue {\n value: string;\n label: string;\n icon?: IconComponent;\n}\n\n/**\n * One search result from `loadOptions`, in async mode — a plain data object rather than\n * `Dropdown.Option` JSX, since a result that hasn't come back from the API yet has no element for\n * a consumer to have declared. `Dropdown` renders each one as a `Dropdown.Option` itself; the\n * fields are exactly that component's own props, so a declared and a loaded list mean the same\n * thing per entry.\n */\nexport interface DropdownAsyncOption {\n value: string;\n label: string;\n icon?: IconComponent;\n disabled?: boolean;\n /** The heading this result belongs under. Results carrying the same string are one group,\n * however far apart they arrive in the array; the groups stand in the order their first result\n * arrives, after every result carrying no group at all. */\n group?: string;\n}\n\n/** What `Dropdown` reads off each `Dropdown.Option` child, in the order the listbox draws them. */\ninterface OptionDescriptor {\n value: string;\n label: string;\n icon?: IconComponent;\n disabled: boolean;\n /** The `Dropdown.Group` heading this option stands under, or `undefined` for an option outside\n * every group. A group is drawn from these; it takes no place in the flat list this array is. */\n group?: string;\n}\n\ninterface DropdownContextValue {\n multiple: boolean;\n /** Where each value the search query matches stands in the listbox. A value absent from this\n * map renders nothing: the listbox holds the matches alone, and their positions in it are the\n * indices the arrow keys travel. A map rather than a list of values, because every option asks\n * this question once per render — a scan per option is quadratic over a query that matches them\n * all. */\n optionIndices: ReadonlyMap<string, number>;\n /** The group headings the listbox draws, in the order their options stand in it. A group absent\n * from this list has no matching option and renders nothing — heading, separator and all. */\n visibleGroups: string[];\n selectedValues: string[];\n highlightedValue: string | null;\n select: (option: DropdownValue) => void;\n registerOption: (index: number, node: HTMLElement | null) => void;\n getItemProps: (userProps?: Record<string, unknown> & { active?: boolean; selected?: boolean }) => Record<string, unknown>;\n}\n\n/** `Dropdown.Option` and `Dropdown.Group` render inside the floating listbox, which `Dropdown`\n * positions and portals itself — so the selection state, the highlight, the visible groups and\n * floating-ui's item props reach them through context rather than as props the consumer\n * arranges. */\nconst DropdownContext = createContext<DropdownContextValue | null>(null);\n\nfunction useDropdownContext(component: string): DropdownContextValue {\n const context = useContext(DropdownContext);\n if (context === null) {\n throw new Error(`${component} must be rendered inside <Dropdown>.`);\n }\n return context;\n}\n\nfunction DropdownOption({ value, label, icon: OptionIcon, disabled = false }: DropdownOptionProps) {\n const { multiple, optionIndices, selectedValues, highlightedValue, select, registerOption, getItemProps } =\n useDropdownContext(\"Dropdown.Option\");\n\n // One lookup answers both questions this option has: whether it is among the matches at all,\n // and — if it is — which `listRef` slot it registers its node in.\n const index = optionIndices.get(value);\n if (index === undefined) {\n return null;\n }\n\n const selected = selectedValues.includes(value);\n const highlighted = highlightedValue === value;\n\n return (\n <div\n {...getItemProps({\n active: highlighted,\n selected,\n onClick: () => {\n if (!disabled) {\n select(toValue({ value, label, icon: OptionIcon, disabled }));\n }\n },\n })}\n ref={(node) => {\n registerOption(index, node);\n }}\n className=\"vpg-listbox-option\"\n aria-disabled={disabled ? true : undefined}\n data-highlighted={highlighted ? \"\" : undefined}\n >\n {multiple ? (\n <span className=\"vpg-listbox-checkbox\" data-checked={selected ? \"\" : undefined}>\n {selected ? <Check size={12} aria-hidden=\"true\" /> : null}\n </span>\n ) : null}\n {OptionIcon ? <OptionIcon className=\"vpg-listbox-option-icon\" aria-hidden=\"true\" /> : null}\n <span className=\"vpg-listbox-option-label\">{label}</span>\n {!multiple && selected ? <Check className=\"vpg-listbox-option-check\" aria-hidden=\"true\" /> : null}\n </div>\n );\n}\n\n/**\n * A heading and the options standing under it. The heading is not an option: it carries no place\n * in the flat list the arrow keys, `Home`/`End` and the highlight travel, so the index of every\n * option is the index it would hold with no group around it at all.\n *\n * The separator is the group's own leading edge, drawn for every group but the first one showing —\n * which puts a line between each pair of groups and none at either end of the list, without the\n * consumer declaring one.\n */\nfunction DropdownGroup({ label, children }: DropdownGroupProps) {\n const { visibleGroups } = useDropdownContext(\"Dropdown.Group\");\n const headingId = useId();\n\n const position = visibleGroups.indexOf(label);\n if (position === -1) {\n return null;\n }\n\n return (\n <>\n {position > 0 ? <div className=\"vpg-listbox-separator\" aria-hidden=\"true\" /> : null}\n {/* biome-ignore lint/a11y/useSemanticElements: a <fieldset> implies form-control semantics\n and carries its own chrome; what a listbox owns between itself and its options is a\n plain role=\"group\". */}\n <div role=\"group\" className=\"vpg-listbox-group\" aria-labelledby={headingId}>\n <div id={headingId} className=\"vpg-listbox-group-label\">\n {label}\n </div>\n {children}\n </div>\n </>\n );\n}\n\ninterface DropdownBaseProps {\n /**\n * `Dropdown.Option` children, directly beneath `Dropdown` — there is no list layer, since the\n * listbox's positioning is `Dropdown`'s own business. Falsy children (what\n * `condition && <Dropdown.Option />` produces) are skipped; anything else throws at render.\n *\n * Ignored when `loadOptions` is provided — the two are alternate option sources, not\n * combinable, since an async result has no consumer-declared element to fall back to.\n */\n children?: ReactNode;\n /**\n * Switches `Dropdown` into async mode: instead of filtering `children`, it calls this with the\n * current query (debounced by `debounceMs`) and renders whatever it resolves to. A rejection is\n * not the consumer's to catch — it surfaces as `errorMessage` in the listbox. Filtering is the\n * API's job in this mode; results are rendered as returned, unfiltered again client-side.\n */\n loadOptions?: (query: string) => Promise<DropdownAsyncOption[]>;\n /** How long to wait, after the query stops changing, before calling `loadOptions`. Only reads\n * in async mode. */\n debounceMs?: number;\n /** Shown, non-interactively, in the listbox while `loadOptions` is pending. */\n loadingMessage?: string;\n /** Shown, non-interactively, in the listbox when `loadOptions` rejects. */\n errorMessage?: string;\n /** Shown in the trigger while nothing is selected. */\n placeholder?: string;\n /** Whether the listbox opens with a search row above it, filtering the options as the consumer\n * types. Off, the trigger keeps real focus and a keystroke jumps the highlight to the next\n * matching label instead. */\n searchable?: boolean;\n /** The search input's hint, and its accessible name — the input is a `role=\"combobox\"` of its\n * own, and this is the only text naming it. */\n searchPlaceholder?: string;\n /** Whether `multiple`'s chips wrap onto further rows, growing the field downwards, instead of\n * keeping to one row with an indicator standing for the chips that do not fit. Only reads in\n * `multiple` mode; a wrapping field measures nothing and observes nothing. */\n wrapChips?: boolean;\n /** Whether the field offers a \"Clear selection\" button emptying the whole selection at once.\n * The button is in the shell's trailing slot and shows only while something is selected, so an\n * empty field carries no control with nothing to do. */\n clearable?: boolean;\n /** Composed onto the root wrapper. */\n className?: string;\n /** Lands on the trigger, not the wrapper — `FormField` clones it on, and it is the trigger that\n * a `<label>` and a role query have to resolve to. */\n id?: string;\n \"aria-label\"?: string;\n \"aria-labelledby\"?: string;\n \"aria-describedby\"?: string;\n \"aria-invalid\"?: boolean;\n}\n\nexport interface DropdownSingleProps extends DropdownBaseProps {\n multiple?: false;\n /** Makes the selection controlled; pair it with `onChange`. `null` selects nothing. */\n value?: DropdownValue | null;\n /** The initially selected value when the selection is uncontrolled. */\n defaultValue?: DropdownValue | null;\n /** Reports the option that was picked, or `null` for a selection that has been emptied — the\n * same `DropdownValue | null` that `value` and `defaultValue` take, so a controlled consumer\n * hands straight back what it is given. */\n onChange?: (value: DropdownValue | null) => void;\n}\n\nexport interface DropdownMultipleProps extends DropdownBaseProps {\n multiple: true;\n /** Makes the selection controlled; pair it with `onChange`. */\n value?: DropdownValue[];\n /** The initially selected values when the selection is uncontrolled. */\n defaultValue?: DropdownValue[];\n onChange?: (value: DropdownValue[]) => void;\n}\n\nexport type DropdownProps = DropdownSingleProps | DropdownMultipleProps;\n\n/** Whether a child is one React renders nothing for — `null`/`undefined`/`false`/`true`, the\n * shape `condition && <Dropdown.Option />` produces. Skipped rather than treated as invalid,\n * matching `Card`'s carve-out. */\nfunction isFalsyChild(child: ReactNode): boolean {\n return child === null || child === undefined || typeof child === \"boolean\";\n}\n\n/** One `Dropdown.Option` element's props, as the descriptor the flat list holds for it. */\nfunction toDescriptor(props: DropdownOptionProps, group?: string): OptionDescriptor {\n const { value, label, icon, disabled = false } = props;\n return { value, label, icon, disabled, group };\n}\n\n/**\n * Reads the options a `Dropdown.Group` heads, tagged with its heading. The group is a rendering\n * layer over one flat list, not a level of it, so a `Dropdown.Group` here — like any other child\n * that is neither an `Option` nor falsy — throws.\n */\nfunction readGroupOptions(children: ReactNode, group: string): OptionDescriptor[] {\n const options: OptionDescriptor[] = [];\n\n Children.forEach(children, (child) => {\n if (isFalsyChild(child)) {\n return;\n }\n if (!isValidElement(child) || child.type !== DropdownOption) {\n throw new Error(\"Dropdown.Group only accepts Dropdown.Option as children.\");\n }\n options.push(toDescriptor(child.props as DropdownOptionProps, group));\n });\n\n return options;\n}\n\n/**\n * Reads the options the children declare, in the order the listbox draws them — a group's own\n * options flattened in place, so an option's index here is the index it would hold with no group\n * around it. Throws unconditionally, not gated on `NODE_ENV`: an unrecognised child is an option\n * the keyboard, the type-ahead and the selection never see, which is the exact failure this\n * compound API exists to prevent.\n */\nfunction readOptions(children: ReactNode): OptionDescriptor[] {\n const options: OptionDescriptor[] = [];\n\n Children.forEach(children, (child) => {\n if (isFalsyChild(child)) {\n return;\n }\n if (isValidElement(child) && child.type === DropdownGroup) {\n const { label, children: groupChildren } = child.props as DropdownGroupProps;\n options.push(...readGroupOptions(groupChildren, label));\n return;\n }\n if (!isValidElement(child) || child.type !== DropdownOption) {\n throw new Error(\"Dropdown only accepts Dropdown.Option and Dropdown.Group as children.\");\n }\n options.push(toDescriptor(child.props as DropdownOptionProps));\n });\n\n return options;\n}\n\n/** The headings the listbox draws for a list of options, in the order their options stand in it.\n * A heading appears once however many options carry it, and an option carrying none contributes\n * nothing. */\nfunction groupsOf(options: OptionDescriptor[]): string[] {\n const groups: string[] = [];\n for (const option of options) {\n if (option.group !== undefined && !groups.includes(option.group)) {\n groups.push(option.group);\n }\n }\n return groups;\n}\n\n/** Async results in the order they render: everything carrying no group first, in the order the\n * API returned it, then each group's own results, the groups themselves standing in the order\n * their first result arrived in. Sorting here rather than at render keeps the flat list the\n * highlight, `listRef` and `disabledIndices` index into in the order the listbox draws. */\nfunction inGroupOrder(options: OptionDescriptor[]): OptionDescriptor[] {\n return [\n ...options.filter((option) => option.group === undefined),\n ...groupsOf(options).flatMap((group) => options.filter((option) => option.group === group)),\n ];\n}\n\n/** Whatever `defaultValue`/`value` holds, as the array the selection is tracked as internally. */\nfunction toSelection(value: DropdownValue | DropdownValue[] | null | undefined): DropdownValue[] {\n if (value === null || value === undefined) {\n return [];\n }\n return Array.isArray(value) ? value : [value];\n}\n\n/** Case-insensitive substring matching, the whole of the filter: a query is a fragment of a label\n * wherever it appears in it, not a prefix. */\nfunction matchesQuery(label: string, query: string): boolean {\n return label.toLowerCase().includes(query.toLowerCase());\n}\n\n/** Where the highlight goes for a freshly filtered list: the top match, so `Enter` selects it\n * without an arrow key first. `null` when every match is disabled, or there are none. */\nfunction firstEnabledIndex(options: OptionDescriptor[]): number | null {\n const index = options.findIndex((option) => !option.disabled);\n return index === -1 ? null : index;\n}\n\n/** Whether a key types a character, as opposed to naming a command or completing a chord. A\n * character is the first thing typed into a search, wherever the focus that received it sat. */\nfunction isPrintable(event: KeyboardEvent<HTMLElement>): boolean {\n return event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey;\n}\n\n/** An option as the value object `onChange` reports for it. `icon` is left off entirely when the\n * option has none, so the reported object is the literal a consumer would have written. */\nfunction toValue({ value, label, icon }: OptionDescriptor): DropdownValue {\n return icon === undefined ? { value, label } : { value, label, icon };\n}\n\n/**\n * The selection as it renders. A `Dropdown.Option` carrying the same `value` supplies the label\n * and icon; the value object's own stand in only when no option carries it, which is what lets a\n * selection outlive the option list it came from.\n */\nfunction resolveSelection(selection: DropdownValue[], options: OptionDescriptor[]): DropdownValue[] {\n return selection.map((selected) => {\n const option = options.find((candidate) => candidate.value === selected.value);\n return option === undefined ? selected : toValue(option);\n });\n}\n\n/** The border-box width of every element in `row` matching `selector`, in document order. */\nfunction widthsOf(row: HTMLElement, selector: string): number[] {\n return Array.from(row.querySelectorAll(selector), (box) => box.getBoundingClientRect().width);\n}\n\n/** How many of `widths`, laid end to end with `gap` between each pair, stand inside `available`.\n * Counting stops at the first box that does not fit: a row shows a prefix of its boxes, so a\n * later narrow one never takes the place of an earlier wide one. */\nfunction countFitting(widths: number[], gap: number, available: number): number {\n let used = 0;\n let fitting = 0;\n for (const width of widths) {\n used += fitting === 0 ? width : gap + width;\n if (used > available) {\n break;\n }\n fitting += 1;\n }\n return fitting;\n}\n\n/**\n * How many of a chip row's chips have no room on its single line. What fits is measured rather\n * than capped at a number: a count that suits one field is wrong for a narrower one, where it\n * already overflows, and for a wider one, where it leaves room the field could have used.\n *\n * The read happens with the row marked `data-measuring`, which puts every chip back on it at its\n * own width — a hidden chip has no width to weigh, and the row itself shrinks to whatever is left\n * in it once some are hidden, so both reads have to see an uncollapsed row.\n *\n * The indicator is measured as it currently reads. Its own width is the reservation, so a row\n * showing no indicator yet reserves the width of the one it would show, and a hidden count\n * crossing a digit boundary is a fraction of a character out until the next measurement.\n */\nfunction measureHiddenChips(row: HTMLElement): number {\n row.setAttribute(\"data-measuring\", \"\");\n const chips = widthsOf(row, \".vpg-listbox-chip\");\n const indicator = widthsOf(row, \".vpg-listbox-overflow-chip\");\n const available = row.clientWidth;\n row.removeAttribute(\"data-measuring\");\n\n // An engine that lays nothing out reports every box at zero width, and a row measuring zero has\n // no answer to give: every chip stays on screen rather than collapsing into an indicator\n // standing for the whole selection.\n if (available === 0) {\n return 0;\n }\n\n const gap = Number.parseFloat(getComputedStyle(row).columnGap);\n if (countFitting(chips, gap, available) === chips.length) {\n return 0;\n }\n\n // The indicator is on the row from here on, so it takes its width off the row before any chip\n // is counted onto it; its place at the head of this list is that reservation, not the end it\n // renders at. One chip shows whatever it costs — a row of nothing but an indicator says how\n // many selections there are and names none of them — and shrinks to the room left.\n const showing = Math.max(countFitting([...indicator, ...chips], gap, available) - 1, 1);\n return chips.length - showing;\n}\n\nfunction DropdownImpl(props: DropdownProps) {\n const {\n children,\n loadOptions,\n debounceMs = 300,\n loadingMessage = \"Loading…\",\n errorMessage = \"Something went wrong.\",\n placeholder = \"Select…\",\n searchable = true,\n searchPlaceholder = \"Search\",\n wrapChips = false,\n clearable = false,\n className,\n id,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-describedby\": ariaDescribedBy,\n \"aria-invalid\": ariaInvalid,\n } = props;\n\n const isAsync = loadOptions !== undefined;\n const multiple = props.multiple === true;\n const controlled = props.value !== undefined;\n // Selection is an array in both modes; only what `onChange` reports differs. The public\n // `value`/`onChange` types are a discriminated union on `multiple`, which no single internal\n // call signature can express — so the handler is widened once, here, and every call site below\n // passes the shape its own mode promises.\n const emitChange = props.onChange as ((next: DropdownValue[] | DropdownValue | null) => void) | undefined;\n\n const [uncontrolledSelection, setUncontrolledSelection] = useState(() => toSelection(props.defaultValue));\n const selection = controlled ? toSelection(props.value) : uncontrolledSelection;\n // Identity is the `value` string throughout: every membership test below runs over these\n // strings, so a value object re-created between renders is the same selection as before.\n const selectedValues = selection.map((selected) => selected.value);\n\n const selectionDescriptionId = useId();\n const [open, setOpen] = useState(false);\n const [highlightedIndex, setHighlightedIndex] = useState<number | null>(null);\n const [query, setQuery] = useState(\"\");\n const listRef = useRef<Array<HTMLElement | null>>([]);\n const searchRef = useRef<HTMLInputElement>(null);\n const chipsRef = useRef<HTMLSpanElement>(null);\n /** How many chips at the end of the selection the row has no width for. Written only by the\n * measurement below, so it is zero until a layout has been read and zero wherever there is no\n * layout to read. */\n const [hiddenChipCount, setHiddenChipCount] = useState(0);\n\n const [asyncOptions, setAsyncOptions] = useState<OptionDescriptor[]>([]);\n const [asyncStatus, setAsyncStatus] = useState<\"idle\" | \"loading\" | \"error\">(\"idle\");\n const searchTokenRef = useRef(0);\n\n /** The `loadOptions` of the latest render, for the search below to call without taking it as a\n * dependency. An inline arrow — the documented form — carries a fresh identity out of every\n * render of whatever holds the `Dropdown`, and a search keyed off that identity restarts the\n * debounce and abandons the request in flight for a query that has not changed at all. */\n const loadOptionsRef = useRef(loadOptions);\n useEffect(() => {\n loadOptionsRef.current = loadOptions;\n });\n\n // Debounced by `debounceMs` after the query settles, and guarded against a response the query\n // has moved past: the token is taken as this search becomes the current one, so every re-run —\n // a new query, a new debounce — invalidates whatever is already in flight. A request that\n // resolves against a stale token publishes nothing, whether a faster later search has already\n // answered or the later search is still inside its debounce window with no answer yet.\n //\n // `loadOptions` is deliberately absent from the dependencies: the effect calls whatever the\n // latest render passed, through the ref above, rather than restarting whenever that function's\n // identity changes.\n useEffect(() => {\n if (!isAsync) {\n return;\n }\n const token = ++searchTokenRef.current;\n const timer = setTimeout(() => {\n setAsyncStatus(\"loading\");\n // The `isAsync` gate above is what makes this defined: the two are the same condition on\n // the same prop.\n const load = loadOptionsRef.current as (query: string) => Promise<DropdownAsyncOption[]>;\n load(query).then(\n (results) => {\n if (searchTokenRef.current !== token) {\n return;\n }\n const loaded = inGroupOrder(\n results.map((result) => ({\n value: result.value,\n label: result.label,\n icon: result.icon,\n disabled: result.disabled ?? false,\n group: result.group,\n })),\n );\n setAsyncOptions(loaded);\n setAsyncStatus(\"idle\");\n setHighlightedIndex(firstEnabledIndex(loaded));\n },\n () => {\n if (searchTokenRef.current !== token) {\n return;\n }\n setAsyncOptions([]);\n setAsyncStatus(\"error\");\n setHighlightedIndex(null);\n },\n );\n }, debounceMs);\n return () => {\n clearTimeout(timer);\n };\n }, [isAsync, query, debounceMs]);\n\n // `children` goes unread in async mode, so a mistaken non-Option child there never throws — the\n // same as any other prop the current mode doesn't consult.\n const options = isAsync ? [] : readOptions(children);\n // The listbox holds the matches alone, so every index below — the highlight's, the disabled\n // ones, the slots in `listRef` — is an index into this list rather than into the full option\n // set. With no search row every option matches, and the two lists are the same list. Async\n // results are shown as the API returned them: re-filtering them by the query would hide a\n // result whose label doesn't literally contain what the API matched more loosely.\n const matches = isAsync ? asyncOptions : searchable ? options.filter((option) => matchesQuery(option.label, query)) : options;\n /** Where each match stands in the listbox, by value — built once here so neither an option's\n * visibility test nor its `listRef` slot costs a scan of the whole match list. */\n const optionIndices = new Map(matches.map((option, index) => [option.value, index]));\n // Read off the matches, so a group the query leaves no option in draws neither a heading nor a\n // separator.\n const visibleGroups = groupsOf(matches);\n // Resolved against every option, not the matches: a selection filtered out of the listbox still\n // shows its label in the trigger and in its chip.\n const selectedEntries = resolveSelection(selection, options);\n const disabledIndices = matches.flatMap((option, index) => (option.disabled ? [index] : []));\n const highlighted = highlightedIndex === null ? undefined : matches[highlightedIndex];\n\n // A query that matches fewer options, or a consumer that conditionally renders fewer\n // `Dropdown.Option` children (a supported pattern — falsy children are skipped, not errors),\n // shrinks the match list between renders. Without this, a slot at the end left behind by a\n // longer render points `aria-activedescendant` and keyboard navigation at an option that is not\n // rendered.\n listRef.current.length = matches.length;\n\n // One row unless the consumer asks for more. `wrapChips` is not a second layout the measurement\n // feeds: it switches the measurement off, so a wrapping field installs no observer and hides\n // nothing.\n const collapseChips = multiple && !wrapChips;\n const visibleChipCount = selectedEntries.length - hiddenChipCount;\n // The labels, not just how many there are: an async selection whose label resolves later is the\n // same count of chips at a different width, and the row it fits on is a different row.\n const chipLabels = JSON.stringify(selectedEntries.map((selected) => selected.label));\n /** The selections the row has no width for, in the order they would have stood on it. */\n const hiddenLabels = selectedEntries.slice(visibleChipCount).map((selected) => selected.label);\n\n /** Whether the field offers the clear button. An empty selection has nothing to clear, so the\n * button goes rather than sitting there inert. */\n const showClear = clearable && selectedEntries.length > 0;\n\n /** Whether the trigger is described by the selection. A chip row names what it holds in the\n * accessibility tree, and the trigger beside it reports a count — so a screen reader reaches\n * every selection through this description, including the ones no chip on the row carries. */\n const describesSelection = multiple && selectedEntries.length > 0;\n // Merged, never replaced: `FormField` forwards a hint's id and an error's id through this same\n // attribute, and a description of the selection written over them costs the field its guidance\n // and its validation message.\n const describedBy = [ariaDescribedBy, describesSelection ? selectionDescriptionId : null].filter(Boolean).join(\" \");\n\n /**\n * Collapses the chip row to the chips that fit, before the browser's next paint.\n *\n * `useLayoutEffect` rather than `useEffect`: React flushes a state update made from a layout\n * effect before it yields to paint, so the first frame the user sees is the collapsed row\n * rather than the full one collapsing.\n *\n * `chipLabels` is in the dependencies as what has to be re-measured against, not as a value the\n * body reads: the labels are in the DOM the measurement reads, and a selection whose labels\n * change without its length changing is a different row of chips at the same count.\n */\n // biome-ignore lint/correctness/useExhaustiveDependencies: `chipLabels` is a re-measure trigger, explained above\n useLayoutEffect(() => {\n if (!collapseChips) {\n // A row that stops collapsing shows every chip again, whatever the last measurement of it\n // concluded.\n setHiddenChipCount(0);\n return;\n }\n const row = chipsRef.current;\n if (row === null) {\n return;\n }\n function measure() {\n setHiddenChipCount(measureHiddenChips(row as HTMLElement));\n }\n measure();\n // The field, not the row: the row's own width answers the collapse this callback causes, so\n // observing it would feed every collapse back in as a resize of its own. The field's width\n // answers what contains it and nothing else.\n const observer = new ResizeObserver(() => {\n // An observer callback runs after layout and before paint, but a React update scheduled\n // from one lands in a later task — after the paint it was meant to precede. Flushing it\n // here puts the resized field and its recollapsed row in the same frame.\n flushSync(measure);\n });\n observer.observe(row.parentElement as HTMLElement);\n return () => {\n observer.disconnect();\n };\n }, [collapseChips, chipLabels]);\n\n function handleOpenChange(next: boolean) {\n setOpen(next);\n if (!next) {\n // The highlight is meaningless with no listbox to point at, and a stale one would be\n // announced as `aria-activedescendant` the moment the listbox reopened.\n setHighlightedIndex(null);\n // The query belongs to the panel it filters: kept, the next open shows a list already\n // narrowed by a search the consumer has finished with.\n setQuery(\"\");\n }\n }\n\n /** Moves the query, and the highlight with it. The highlight is an index into the matches, so a\n * new query re-scopes it to that list's top selectable option — `Enter` acts on the best match\n * with no arrow key first, and no index survives pointing at an option the query dropped. */\n function applyQuery(next: string) {\n setQuery(next);\n if (isAsync) {\n // The debounced search resolves the new highlight once `loadOptions` returns for this\n // query — the options on screen are the previous query's, about to be replaced, so there is\n // nothing correct to highlight in the meantime.\n setHighlightedIndex(null);\n return;\n }\n setHighlightedIndex(firstEnabledIndex(options.filter((option) => matchesQuery(option.label, next))));\n }\n\n function commit(next: DropdownValue[], reported: DropdownValue[] | DropdownValue | null) {\n // The internal state is kept only while `value` is absent. Writing it in the controlled form\n // too would leave a stale value behind for the moment `value` is later withdrawn.\n if (!controlled) {\n setUncontrolledSelection(next);\n }\n emitChange?.(reported);\n }\n\n function select(option: DropdownValue) {\n if (multiple) {\n const next = selectedValues.includes(option.value)\n ? selection.filter((selected) => selected.value !== option.value)\n : [...selection, option];\n commit(next, next);\n if (searchable) {\n // The panel stays open, so the query goes: the next character searches every option\n // rather than narrowing what is left of the picked option's own match. The highlight\n // follows that option into the unfiltered list, where a second `Enter` toggles it back\n // instead of acting on whichever option the full list happens to start with. In async\n // mode the loaded results are that list — they stay on screen until the debounced search\n // for the cleared query resolves and replaces them.\n setQuery(\"\");\n setHighlightedIndex((isAsync ? asyncOptions : options).findIndex((candidate) => candidate.value === option.value));\n }\n return;\n }\n commit([option], option);\n handleOpenChange(false);\n }\n\n function remove(value: string) {\n const next = selection.filter((selected) => selected.value !== value);\n commit(next, next);\n }\n\n const {\n refs,\n floatingStyles,\n context: floatingContext,\n themeRoot,\n fieldRef,\n onFieldMouseDown,\n getReferenceProps,\n getFloatingProps,\n getItemProps,\n getSearchProps,\n } = useListboxKeyboard({\n listRef,\n activeIndex: highlightedIndex,\n onNavigate: setHighlightedIndex,\n disabledIndices,\n // A search input owns every keystroke once one exists: type-ahead is the trigger's own way of\n // reaching an option by its label, for the mode with no input to type into.\n typeahead: !searchable,\n role: \"select\",\n search: searchable,\n open,\n onOpenChange: handleOpenChange,\n });\n\n /** Empties the selection, as each mode expresses emptiness: `null` for a single selection and an\n * empty array for a `multiple` one. Focus goes to the trigger: the button shows only while\n * something is selected, so it leaves the field along with the selection it just emptied, and\n * focus left on it falls to `<body>` with nothing answering the keyboard. */\n function clear() {\n commit([], multiple ? [] : null);\n // The button only exists inside a field that has a trigger, so the reference is always there\n // to take focus back.\n (refs.domReference.current as HTMLElement).focus();\n }\n\n /** `Enter`/`Space` opens the closed listbox and selects the highlighted option in the open one.\n * Both keys are the trigger's own — `useClick`'s handlers for them are switched off in\n * `useListboxKeyboard`, so nothing else on this element acts on them. Every other character\n * belongs to the search row, which is why the two keys are settled first: `Space` is a printable\n * character too, and on a trigger it is the selection key. */\n function handleTriggerKeyDown(event: KeyboardEvent<HTMLDivElement>) {\n if (event.key !== \"Enter\" && event.key !== \" \") {\n // A character typed at a closed search row is the first character of the search: it opens\n // the panel and seeds the query, and the focus manager puts the caret after it. A trigger\n // types nothing itself, so the character is lost otherwise.\n if (searchable && !open && isPrintable(event)) {\n event.preventDefault();\n handleOpenChange(true);\n applyQuery(event.key);\n }\n return;\n }\n event.preventDefault();\n if (!open) {\n handleOpenChange(true);\n return;\n }\n // Pointer hover moves the highlight onto whatever option it passes over, disabled ones\n // included, so a highlighted option is not automatically a selectable one.\n if (highlighted === undefined || highlighted.disabled) {\n return;\n }\n select(toValue(highlighted));\n }\n\n function handleSearchChange(event: ChangeEvent<HTMLInputElement>) {\n applyQuery(event.target.value);\n }\n\n /** `Enter` selects the highlighted option, and `Backspace` with no character to delete removes\n * the last selection — the chip the field ends with. `Space` belongs to the query here: it is a\n * character in a search, not the selection key it is on a trigger with no input to type into.\n *\n * `Backspace` is `multiple`'s alone: it peels the last chip off a row of them, and a single\n * selection has no last selection distinct from its only one. Emptying that one is `clearable`'s\n * button, where dropping the whole selection is what the control says it does. */\n function handleSearchKeyDown(event: KeyboardEvent<HTMLInputElement>) {\n const last = selection.at(-1);\n if (multiple && event.key === \"Backspace\" && query === \"\" && last !== undefined) {\n remove(last.value);\n return;\n }\n if (event.key !== \"Enter\") {\n return;\n }\n event.preventDefault();\n if (highlighted === undefined || highlighted.disabled) {\n return;\n }\n select(toValue(highlighted));\n }\n\n const context: DropdownContextValue = {\n multiple,\n optionIndices,\n visibleGroups,\n selectedValues,\n highlightedValue: highlighted === undefined ? null : highlighted.value,\n select,\n registerOption(index, node) {\n // A detaching ref reports `null` for an option a shorter render has already dropped, whose\n // index now belongs to another option or is past the length trim above — writing it back\n // would undo that trim.\n if (node !== null) {\n listRef.current[index] = node;\n }\n },\n getItemProps,\n };\n\n /** What the trigger shows: the selected option in single-select, and the placeholder in either\n * mode while nothing is selected.\n *\n * A `multiple` selection shows in the trigger as nothing at all — the trigger is the click\n * target and holds the chevron, and the chips beside it carry the whole selection. Naming each\n * one, the chip row already says everything a count could, and the overflow indicator counts\n * the chips it has no room for; a count in the trigger takes width off that same row, so it\n * pushes more chips into the overflow it describes. A screen reader hears more than a count\n * either way: the trigger's description names every selection, hidden chips included. */\n function renderTriggerContent(): ReactNode {\n const placeholderContent = <span className=\"vpg-dropdown-placeholder\">{placeholder}</span>;\n\n if (multiple) {\n return selectedEntries.length === 0 ? placeholderContent : null;\n }\n\n const selected = selectedEntries[0];\n if (selected === undefined) {\n return placeholderContent;\n }\n const SelectedIcon = selected.icon;\n return (\n <>\n {SelectedIcon ? <SelectedIcon className=\"vpg-dropdown-trigger-icon\" aria-hidden=\"true\" /> : null}\n <span className=\"vpg-dropdown-value\">{selected.label}</span>\n </>\n );\n }\n\n /**\n * The indicator standing for the chips the row has no width for: it counts them, and names them\n * in a tooltip on hover. It is a `<span>` and takes no tab stop — the selections behind it are\n * unpicked in the listbox, since the chips carrying them are not on screen to remove them from,\n * so a stop here would be a stop with nothing to do.\n *\n * `Tooltip` wraps its child in a span of its own, which becomes the row's flex item — so it goes\n * on only while there are labels for it to name. With nothing hidden the indicator is the row's\n * own direct child, which is what `data-hidden` has to be on to take it off the row.\n */\n function renderOverflowIndicator(): ReactNode {\n const indicator = (\n <span className=\"vpg-listbox-overflow-chip\" data-hidden={hiddenChipCount === 0 ? \"\" : undefined}>\n and {hiddenChipCount} more\n </span>\n );\n if (hiddenChipCount === 0) {\n return indicator;\n }\n return <Tooltip content={hiddenLabels.join(\", \")}>{indicator}</Tooltip>;\n }\n\n /**\n * The control emptying the whole selection at once. A real `<button>`, so it is a tab stop and\n * carries its name into the accessibility tree; `onFieldMouseDown` skips a press that lands on\n * a button, so pressing this one does not also open the listbox the way a press anywhere else\n * in the field does.\n */\n function renderClearButton(): ReactNode {\n return (\n <button type=\"button\" className=\"vpg-dropdown-clear\" aria-label=\"Clear selection\" onClick={clear}>\n <X className=\"vpg-dropdown-clear-icon\" aria-hidden=\"true\" />\n </button>\n );\n }\n\n /** One loaded result as the `Dropdown.Option` element a consumer would have declared for it. */\n function renderAsyncOption(option: OptionDescriptor): ReactNode {\n return <DropdownOption key={option.value} value={option.value} label={option.label} icon={option.icon} disabled={option.disabled} />;\n }\n\n /** The loaded results as the `Dropdown.Option` elements a consumer would have declared for\n * them, or the message standing in for them: a search in flight, a search that rejected, or one\n * the API matched nothing for. */\n function renderAsyncRows(): ReactNode {\n if (asyncStatus === \"loading\") {\n return <div className=\"vpg-listbox-empty\">{loadingMessage}</div>;\n }\n if (asyncStatus === \"error\") {\n return <div className=\"vpg-listbox-empty\">{errorMessage}</div>;\n }\n if (matches.length === 0) {\n return <div className=\"vpg-listbox-empty\">No results</div>;\n }\n // The matches are already in the order they render — everything ungrouped, then the groups —\n // so each run below is a contiguous slice of the flat list the indices travel.\n return (\n <>\n {matches.filter((option) => option.group === undefined).map(renderAsyncOption)}\n {visibleGroups.map((group) => (\n <DropdownGroup key={group} label={group}>\n {matches.filter((option) => option.group === group).map(renderAsyncOption)}\n </DropdownGroup>\n ))}\n </>\n );\n }\n\n /** The options, or — for a query that matches none of them — the message standing in for them.\n * A listbox left blank reads as a control that has stopped answering. */\n const optionRows = isAsync ? (\n renderAsyncRows()\n ) : searchable && matches.length === 0 ? (\n <div className=\"vpg-listbox-empty\">No results</div>\n ) : (\n children\n );\n\n /** The search row and the listbox are siblings inside the floating element, so no key travelling\n * from the input reaches the listbox by bubbling: the arrow keys arrive through\n * `getSearchProps()` alone. `getFloatingProps()` goes on the listbox rather than on the panel\n * around it — it carries the id every `aria-controls` points at, and on the panel that id would\n * name a box holding the search input too. */\n function renderSearchPanel(): ReactNode {\n return (\n <div ref={refs.setFloating} className=\"vpg-listbox-panel\" style={floatingStyles}>\n {/* Non-modal: the trigger and the page behind the panel stay reachable, and the manager's\n one job here is to put real focus in the search input and hand it back to the trigger as\n the panel unmounts. */}\n <FloatingFocusManager context={floatingContext} modal={false} initialFocus={searchRef}>\n {/* The one element the focus manager holds. */}\n <div>\n <div className=\"vpg-listbox-search\">\n <Search className=\"vpg-listbox-search-icon\" aria-hidden=\"true\" />\n <input\n ref={searchRef}\n type=\"text\"\n // The role and its required `aria-expanded` are stated here as well as in\n // `getSearchProps()`, which sets both to the same values: the spread alone leaves\n // the element's semantics invisible to a reader and to static analysis. The panel\n // holding this input exists only while the listbox is open, so `aria-expanded` is\n // true for the whole of its life. `aria-controls`, `aria-autocomplete` and\n // `aria-activedescendant` come from the spread. The trigger is a `combobox` too —\n // it holds the accessible name and description, and this input holds the live\n // navigation state.\n role=\"combobox\"\n aria-expanded={true}\n className=\"vpg-listbox-search-input\"\n // The browser's own suggestion list would float over the options this input filters.\n autoComplete=\"off\"\n placeholder={searchPlaceholder}\n aria-label={searchPlaceholder}\n value={query}\n {...getSearchProps({ onChange: handleSearchChange, onKeyDown: handleSearchKeyDown })}\n />\n </div>\n <div\n // Stated here as well as in `getFloatingProps()`, which sets the same value: the\n // spread alone leaves the element's role invisible to a reader and to static analysis.\n role=\"listbox\"\n className=\"vpg-listbox-options\"\n aria-multiselectable={multiple ? true : undefined}\n {...getFloatingProps()}\n >\n {optionRows}\n </div>\n </div>\n </FloatingFocusManager>\n </div>\n );\n }\n\n /** The floating element. With no search row the listbox is that element itself: nothing else is\n * in the popover to position, and nothing in it takes real focus. */\n function renderFloating(): ReactNode {\n if (searchable) {\n return renderSearchPanel();\n }\n return (\n <div\n ref={refs.setFloating}\n // Stated here as well as in `getFloatingProps()`, which sets the same value: the spread\n // alone leaves the element's role invisible to a reader and to static analysis.\n role=\"listbox\"\n className=\"vpg-listbox\"\n style={floatingStyles}\n aria-multiselectable={multiple ? true : undefined}\n {...getFloatingProps()}\n >\n {optionRows}\n </div>\n );\n }\n\n const listbox = open ? renderFloating() : null;\n\n return (\n <DropdownContext.Provider value={context}>\n {/*\n React 19 hoists and de-duplicates these by `href`, so N dropdowns on a page inject one of\n each — and the listbox sheet is injected identically by every component in this package\n that renders a floating listbox.\n */}\n <style href=\"vpg-dropdown\" precedence=\"vpg-dropdown\">\n {dropdownStylesheet}\n </style>\n <style href=\"vpg-listbox\" precedence=\"vpg-listbox\">\n {listboxStylesheet}\n </style>\n <div className={[\"vpg-dropdown\", className].filter(Boolean).join(\" \")}>\n {/* The chips sit beside the trigger, never inside it: floating-ui merges its own click\n and keyboard handlers into the trigger's, so a nested remove button's click could not\n be reliably intercepted before those ran. As siblings, each remove button is an\n ordinary interactive element needing no guard at all.\n\n The trigger is a direct child of the shell and the last element of its centre. The\n shell reads focus and invalidity off its direct children only, so a wrapper around the\n trigger would silently cost the field its focus ring and danger border; and the last\n centre element is the one the shell hands its free space to, so the chip row sizes to\n its chips and the trigger takes the rest.\n\n A press on the field's padding or a gap in the chip row lands on the field rather than\n the trigger. The field's handler keeps focus on the trigger and opens the listbox, as a\n click on the trigger would; left to the browser, focus moves to `<body>` and an open\n listbox stops answering the arrow keys. */}\n <FieldShell\n ref={fieldRef}\n className=\"vpg-dropdown-control\"\n onMouseDown={onFieldMouseDown}\n // In the shell's trailing slot rather than beside the trigger: the shell reads focus,\n // invalidity and openness off its direct children, and a button among them would give\n // the whole field a focus ring of its own the moment the button took focus. A slot is a\n // subtree those `> ` rules do not reach into, which is why the button draws its own.\n trailing={showClear ? renderClearButton() : undefined}\n >\n {multiple && selectedEntries.length > 0 ? (\n <span ref={chipsRef} className=\"vpg-listbox-chips\" data-collapsing={collapseChips ? \"\" : undefined}>\n {selectedEntries.map((selected, index) => (\n <span key={selected.value} className=\"vpg-listbox-chip\" data-hidden={index >= visibleChipCount ? \"\" : undefined}>\n <span className=\"vpg-listbox-chip-label\">{selected.label}</span>\n <button\n type=\"button\"\n className=\"vpg-listbox-chip-remove\"\n aria-label={`Remove ${selected.label}`}\n onClick={() => {\n remove(selected.value);\n }}\n >\n <X className=\"vpg-listbox-chip-remove-icon\" aria-hidden=\"true\" />\n </button>\n </span>\n ))}\n {/* On the row for the whole of a collapsing field's life, whether or not it shows\n anything: the width it would take is what the measurement reserves before it\n counts a chip onto the row, and an indicator absent from the DOM has no width to\n read. */}\n {collapseChips ? renderOverflowIndicator() : null}\n </span>\n ) : null}\n <div\n ref={refs.setReference}\n // The role and its required `aria-expanded` are stated here as well as in\n // `getReferenceProps()`, which sets both to the same values: the spread alone leaves\n // the element's semantics invisible to a reader and to static analysis.\n // `aria-haspopup`, `aria-controls` and `aria-activedescendant` come from the spread.\n // A `<button>` is not an option here — only `combobox` and a handful of other roles\n // may carry `aria-activedescendant`.\n role=\"combobox\"\n aria-expanded={open}\n className=\"vpg-dropdown-trigger\"\n tabIndex={0}\n id={id}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-describedby={describedBy === \"\" ? undefined : describedBy}\n aria-invalid={ariaInvalid}\n {...getReferenceProps({ onKeyDown: handleTriggerKeyDown })}\n >\n {renderTriggerContent()}\n {/* Inside the trigger rather than in the shell's trailing slot, so a click on the\n chevron is a click on the combobox and opens it. */}\n <ChevronDown size={16} className=\"vpg-dropdown-chevron\" aria-hidden=\"true\" />\n </div>\n </FieldShell>\n {/* Outside the shell, which reads focus and invalidity off its direct children: a third\n one here would be a child with no state to report, and the shell hands its free space\n to the last of them. */}\n {describesSelection ? (\n <span id={selectionDescriptionId} className=\"vpg-dropdown-selection-description\">\n Selected: {selectedEntries.map((selected) => selected.label).join(\", \")}\n </span>\n ) : null}\n </div>\n {listbox !== null && themeRoot !== null ? createPortal(listbox, themeRoot) : listbox}\n </DropdownContext.Provider>\n );\n}\n\ntype DropdownComponent = typeof DropdownImpl & {\n Option: typeof DropdownOption;\n Group: typeof DropdownGroup;\n};\n\n/**\n * A select-only combobox: a trigger showing the current selection, and a floating listbox of\n * `Dropdown.Option` children.\n *\n * A `Dropdown.Group label` heads a run of those options, and an async result carries its heading\n * as a `group` string instead. A group is drawn over the same flat list of options — its heading\n * takes no index, so the arrow keys, `Home`/`End` and the wrap at either end reach exactly the\n * options they reach with no group declared. Each group is a `role=\"group\"` named by its heading,\n * with a separator drawn between one group and the next; a group the query leaves no option in\n * renders nothing at all.\n *\n * The trigger is a `<div role=\"combobox\" tabIndex={0}>` rather than a `<button>` — only\n * `combobox`, `textbox`, `listbox`, `group`, `application` and the composite-derived roles may\n * carry `aria-activedescendant`, and the highlighted option is tracked virtually through exactly\n * that attribute rather than by moving real DOM focus into the listbox (see\n * `docs/adr/0004-aria-activedescendant-for-dropdown-and-autocomplete.md`).\n *\n * `searchable` (default `true`) opens the listbox under a search row — a magnifier and an input,\n * then a divider — that filters the options by a case-insensitive substring of their labels, and\n * says so when the query matches none. The input is a `role=\"combobox\"` of its own holding the\n * live navigation state, while the trigger keeps the accessible name and description; a non-modal\n * `FloatingFocusManager` puts real focus in the input and returns it to the trigger as the panel\n * closes. Every keystroke belongs to that search: a character typed on the closed trigger opens\n * the panel and seeds the query with it, a pick clears the query, `multiple`'s `Backspace` with no\n * character to delete removes the last selection, and the query clears as the panel closes.\n * `searchable={false}` leaves real focus on the trigger throughout, with a keystroke there jumping\n * the highlight to the next matching label instead.\n *\n * Selection is a `DropdownValue` object — `{ value, label, icon? }` — controlled through\n * `value`/`onChange` or left to `Dropdown` itself, seeded by `defaultValue`. `multiple` switches\n * both to arrays and gives each option a checkbox and each selected value a removable chip beside\n * the trigger; selecting in `multiple` mode toggles the option and leaves the listbox open.\n *\n * `clearable` adds a \"Clear selection\" button to the field's trailing slot while anything is\n * selected, reporting `null` in single mode and `[]` in `multiple`. Pressing it empties the\n * selection without opening the listbox and leaves focus on the trigger.\n *\n * Those chips keep to one row. Which of them fit is measured against the width the field has, and\n * re-measured before paint whenever that width changes; the rest give way to an indicator reading\n * \"and N more\" that names them in a tooltip on hover, and a single chip wider than the field shows\n * alone with its label ellipsised. The indicator takes no tab stop: a selection it stands for is\n * removed by unchecking it in the listbox. The trigger is described by the whole selection,\n * merged with whatever `aria-describedby` it is given rather than written over it. `wrapChips`\n * switches the measurement off and wraps the chips onto further rows instead, growing the field\n * downwards.\n *\n * Passing `loadOptions` switches to async mode: `children` goes unread, and `Dropdown` calls\n * `loadOptions(query)` itself (debounced by `debounceMs`, default 300ms) and renders whatever it\n * resolves to, showing `loadingMessage` while pending and `errorMessage` on a rejection. Results\n * are rendered as returned — filtering the query is the API's job in this mode, not `Dropdown`'s.\n * A response the query has moved past is discarded rather than applied — a slow earlier search\n * resolving after a faster later one, and equally one resolving while the next query is still\n * settling. The search is keyed off the query alone, so `loadOptions` may be an inline arrow with\n * a fresh identity on every render. A selection carries its own label, so the trigger and a chip\n * render it with nothing fetched and no option child to match against.\n *\n * The listbox portals into the nearest ancestor `.vpg-root` — the subtree `ThemeProvider`\n * establishes — rather than `document.body`, so it keeps every `--vpg-*` value. With no\n * `.vpg-root` ancestor it renders inline beside the trigger instead, positioned identically\n * but inheriting whatever theme surrounds it.\n */\n// The `@__PURE__` annotation tells Rollup/esbuild this call has no side effect it can't see, so\n// an unused `Dropdown` export (importing only `Button`, say) is tree-shaken out entirely instead\n// of keeping the whole module \"just in case\" `Object.assign` does something observable.\nexport const Dropdown = /* @__PURE__ */ Object.assign(DropdownImpl, {\n Option: DropdownOption,\n Group: DropdownGroup,\n}) as DropdownComponent;\n","/**\n * `<FieldSet>`'s own styles, injected as an inline `<style>` rather than a `.css` import so the\n * package can stay `\"sideEffects\": false` (same approach as `FormField`'s and `Card`'s\n * stylesheets).\n *\n * Every `--vpg-*` property is *read* here through `var()` and never assigned inline by the\n * component: an inline style declaration always wins over a stylesheet rule for the same\n * property on the same element, so an inline theme property would permanently shadow\n * `@vipengele/react-tokens`'s dark-mode reassignment and this fieldset would stop adapting to colour\n * mode.\n *\n * Reads the same raised-surface tokens as `Card` — `--vpg-surface-raised`,\n * `--vpg-border` — so a group of fields reads as the same material as a card, rather than as\n * bare unstyled markup. `FieldSet` is an outer container (a field sits inside it, never the other\n * way around), so per ADR-0012 its corner takes the outer step of the radius ladder,\n * `--vpg-radius-lg`, not the inner step a field itself takes. The legend takes the same\n * type-scale step as `FormField`'s label.\n *\n * A native `<legend>` inside a bordered `<fieldset>` is not a normal flow child: the browser lifts\n * it out of the box's padding and straddles it across the border-block-start, cutting a notch the\n * border does not paint through. That notch — not the surface, border or radius — is what reads as\n * unstyled browser chrome unless the legend settles into it deliberately: no margin fighting the\n * browser's own placement, and no padding on the legend either — the browser already anchors the\n * rendered legend's inline-start edge at the fieldset's own padding edge, the same edge every\n * child's content starts from, so a legend with `padding: 0` sets its text flush with the labels\n * beneath it. Padding on the legend only pushes its text past that edge, out of line with them.\n * The fieldset itself stays a plain block box (not flex) so the browser's own\n * `max(padding-top, legend-block-size)` rule is the only thing sizing the gap above the first\n * child; a flex `gap` would additionally count the legend as a flex item and double that space.\n * The gap between the remaining children comes from a sibling-combinator margin instead of `gap`,\n * since `gap` cannot skip the pair the legend is one half of.\n */\nexport const fieldSetStylesheet = `\n.vpg-fieldset {\n box-sizing: border-box;\n margin: 0;\n padding: var(--vpg-space-5);\n background-color: var(--vpg-surface-raised);\n border: 1px solid var(--vpg-border);\n border-radius: var(--vpg-radius-lg);\n}\n\n.vpg-fieldset:disabled {\n opacity: 0.55;\n}\n\n.vpg-fieldset > *:not(.vpg-fieldset-legend) ~ *:not(.vpg-fieldset-legend) {\n margin-top: var(--vpg-space-5);\n}\n\n.vpg-fieldset-legend {\n padding: 0;\n margin: 0;\n font-size: var(--vpg-font-size-sm);\n font-weight: 600;\n color: var(--vpg-ink);\n}\n`;\n","import type { FieldsetHTMLAttributes, ReactNode } from \"react\";\nimport { fieldSetStylesheet } from \"./FieldSet.stylesheet.js\";\n\nexport interface FieldSetProps extends Omit<FieldsetHTMLAttributes<HTMLFieldSetElement>, \"children\"> {\n /** The group's accessible name, rendered in a native `<legend>` — a `<fieldset>` derives its\n * own accessible name from this automatically, with no id/aria wiring required. */\n legend: ReactNode;\n /** Grouped content, laid out with spacing between each child — typically one or more\n * `FormField`s, but not restricted to them. `FieldSet` carries no form-state logic of its\n * own. */\n children: ReactNode;\n}\n\n/**\n * A native `<fieldset>` + `<legend>` pair with spacing between `children`, for grouping related\n * controls. Purely a layout wrapper: `disabled` forwards straight to the native `<fieldset>`,\n * which natively disables every descendant form control without `FieldSet` doing anything\n * itself.\n *\n * A `<legend>` names its own `<fieldset>` automatically, but that does not extend to a\n * `role=\"radiogroup\"` element nested inside it — `RadioGroup` carries its own `aria-label` for\n * that reason.\n */\nexport function FieldSet({ legend, children, className, ...rest }: FieldSetProps) {\n const classes = [\"vpg-fieldset\", className].filter(Boolean).join(\" \");\n\n return (\n <fieldset {...rest} className={classes}>\n {/*\n React 19 hoists and de-duplicates this by `href`, so N fieldsets on a page inject one\n stylesheet.\n */}\n <style href=\"vpg-fieldset\" precedence=\"vpg-fieldset\">\n {fieldSetStylesheet}\n </style>\n <legend className=\"vpg-fieldset-legend\">{legend}</legend>\n {children}\n </fieldset>\n );\n}\n","/**\n * `<FormField>`'s own styles, injected as an inline `<style>` rather than a `.css` import so the\n * package can stay `\"sideEffects\": false` (same approach as `Card`'s and `Toggle`'s\n * stylesheets).\n *\n * Every `--vpg-*` property is *read* here through `var()` and never assigned inline by the\n * component: an inline style declaration always wins over a stylesheet rule for the same\n * property on the same element, so an inline theme property would permanently shadow\n * `@vipengele/react-tokens`'s dark-mode reassignment and this field would stop adapting to colour mode.\n *\n * The label, help and error text take steps of the type scale, and the error its colour from the\n * danger family — the same mode-resolved red `Button`'s danger variant and an invalid field's\n * border read.\n *\n * The vertical rhythm is two spacing steps, not one, because the label-to-control relationship and\n * the control-to-hint relationship read differently: `--vpg-space-2` gives the label room to\n * read as a heading for the control beneath it, while `--vpg-space-1` keeps a hint or error\n * pinned tight under the control it describes. Both are tighter than the gap `FieldSet` puts\n * between sibling fields (`--vpg-space-5`), so a column of fields reads as grouped units\n * rather than an undifferentiated stack. `gap` cannot express this — it is uniform across every\n * pair of flex children — so the rhythm is margins on the label and on the hint/error text instead.\n */\nexport const formFieldStylesheet = `\n.vpg-form-field {\n display: flex;\n flex-direction: column;\n}\n\n.vpg-form-field-label {\n margin: 0 0 var(--vpg-space-2);\n font-size: var(--vpg-font-size-sm);\n font-weight: 500;\n color: var(--vpg-ink);\n}\n\n.vpg-form-field-hint {\n margin-top: var(--vpg-space-1);\n font-size: var(--vpg-font-size-xs);\n color: var(--vpg-ink-muted);\n}\n\n.vpg-form-field-error {\n margin-top: var(--vpg-space-1);\n font-size: var(--vpg-font-size-xs);\n color: var(--vpg-danger);\n}\n`;\n","import { cloneElement, Fragment, isValidElement, type ReactElement, type ReactNode, useId } from \"react\";\nimport { formFieldStylesheet } from \"./FormField.stylesheet.js\";\n\n/** The subset of ARIA/labelling attributes `FormField` clones onto its single child. Every\n * focusable control this package ships (native inputs, `Toggle`, `RadioButton`, and\n * `Dropdown`'s trigger div) accepts all four as plain optional props. */\ninterface CloneableControlProps {\n id?: string;\n \"aria-describedby\"?: string;\n \"aria-invalid\"?: boolean;\n \"aria-labelledby\"?: string;\n}\n\nexport interface FormFieldProps {\n /** The field's accessible name, rendered in a `<label>` and referenced from the control via\n * `aria-labelledby` (applied unconditionally — see `children`'s doc comment). */\n label: ReactNode;\n /** Supplementary guidance, rendered below the control and wired into `aria-describedby`. */\n hint?: ReactNode;\n /** A validation message. Rendered below the control (after `hint`, when both are present) and\n * wired into `aria-describedby`; its presence also sets `aria-invalid` on the control. */\n error?: ReactNode;\n /**\n * Exactly one focusable control — a native input, `Toggle`, `RadioButton`, or `Dropdown`'s\n * trigger. Not a group-shaped component like\n * `RadioGroup`, which gets its accessible name from its own `aria-label` rather than a\n * wrapping `FormField`.\n *\n * `FormField` clones `id`, `aria-describedby`, `aria-invalid`, and `aria-labelledby` onto this\n * element. `aria-labelledby` is applied unconditionally, regardless of what element the child\n * renders as: a `<label htmlFor>` only associates with labelable elements (`input`/`select`/\n * `textarea`/`button`/`meter`/`output`/`progress`), so a non-labelable trigger (Dropdown's\n * `<div role=\"combobox\">`) would otherwise get no accessible name at all. Anything that isn't a\n * single valid element — text, an array, a `Fragment`, `null`/`undefined` — throws, since there\n * is no single node to attach the label and description to.\n */\n children: ReactElement<CloneableControlProps>;\n}\n\n/**\n * Labels a single focusable control and wires up its description/validation state via\n * `cloneElement` — the narrow labelling-attribute carve-out in\n * `.agents/rules/wrap-trigger-never-clone.md`, not the span-wrap pattern: there is no\n * floating-UI trigger here, just ARIA attributes that must land on the actual focusable element\n * rather than an ancestor a screen reader never focuses.\n */\nexport function FormField({ label, hint, error, children }: FormFieldProps) {\n const generatedId = useId();\n const labelId = `${generatedId}-label`;\n const hintId = `${generatedId}-hint`;\n const errorId = `${generatedId}-error`;\n\n if (!isValidElement(children) || children.type === Fragment) {\n throw new Error(\"FormField requires exactly one focusable element as its child.\");\n }\n\n const hasHint = hint !== undefined && hint !== null && hint !== \"\";\n const hasError = error !== undefined && error !== null && error !== \"\";\n\n const describedByIds = [hasHint ? hintId : null, hasError ? errorId : null].filter((id): id is string => id !== null);\n const mergedDescribedBy = [children.props[\"aria-describedby\"], ...describedByIds].filter(Boolean).join(\" \");\n\n const childId = children.props.id ?? generatedId;\n\n const cloneProps: CloneableControlProps = {\n id: childId,\n \"aria-labelledby\": labelId,\n };\n if (mergedDescribedBy) {\n cloneProps[\"aria-describedby\"] = mergedDescribedBy;\n }\n if (hasError) {\n cloneProps[\"aria-invalid\"] = true;\n }\n\n const control = cloneElement(children, cloneProps);\n\n return (\n <div className=\"vpg-form-field\">\n {/*\n React 19 hoists and de-duplicates this by `href`, so N form fields on a page inject one\n stylesheet.\n */}\n <style href=\"vpg-form-field\" precedence=\"vpg-form-field\">\n {formFieldStylesheet}\n </style>\n <label htmlFor={childId} id={labelId} className=\"vpg-form-field-label\">\n {label}\n </label>\n {control}\n {hasHint ? (\n <span id={hintId} className=\"vpg-form-field-hint\">\n {hint}\n </span>\n ) : null}\n {hasError ? (\n <span id={errorId} className=\"vpg-form-field-error\">\n {error}\n </span>\n ) : null}\n </div>\n );\n}\n","/**\n * `<TextField>`'s own styles, injected as an inline `<style>` rather than a `.css` import so the\n * package can stay `\"sideEffects\": false` (same approach as every other component's stylesheet).\n *\n * Every `--vpg-*` property is *read* here through `var()` and never assigned inline by the\n * component: an inline style declaration always wins over a stylesheet rule for the same\n * property on the same element, so an inline `--vpg-ink` would permanently shadow\n * `@vipengele/react-tokens`'s dark-mode reassignment and this field would stop adapting to colour mode.\n *\n * This is the styling of an input sitting inside a `FieldShell`, so it carries nothing the shell\n * owns: no border, no background, no radius, no width, no box-shadow, and no rule for the hover,\n * focus, invalid or disabled states. Redeclaring one of those means the treatment is applied\n * twice — a ring drawn on the input inside the ring drawn on the shell, an opacity multiplied\n * into itself. `outline: none` is here for the same reason: the shell draws the focus ring, and\n * the input's native outline would sit inside it.\n *\n * Height is the shell's too, and `align-self: stretch` is how the control takes it rather than\n * restating it: the shell centres its children, and a centred input is only as tall as its own\n * text, so the top and bottom few pixels of the field focus nothing when clicked. Stretching\n * fills whatever box the input is handed — the shell's content box when it is a direct child,\n * and its own flex line when it sits inside a wrapping row of chips. A `height` here cannot do\n * either: the shell's height is a floor, not a fixed length, so a percentage resolves against an\n * indefinite containing block and collapses to the input's own text.\n *\n * Typography stays the input's own concern. A native input inherits neither font nor colour from\n * its ancestors, so both are declared here or the field renders in the UA's form defaults.\n */\nexport const textFieldStylesheet = `\n.vpg-text-field {\n box-sizing: border-box;\n align-self: stretch;\n min-width: 0;\n padding: 0;\n border: none;\n outline: none;\n background: none;\n color: inherit;\n font-family: var(--vpg-font-sans);\n font-size: var(--vpg-font-size-sm);\n line-height: 1.5;\n}\n\n.vpg-text-field::placeholder {\n color: var(--vpg-ink-subtle);\n}\n`;\n","import type { InputHTMLAttributes, ReactNode } from \"react\";\nimport { FieldShell } from \"../FieldShell/FieldShell.js\";\nimport { textFieldStylesheet } from \"./TextField.stylesheet.js\";\n\nexport interface TextFieldProps extends Omit<InputHTMLAttributes<HTMLInputElement>, \"type\"> {\n /** The native input `type` — `\"text\"`, `\"email\"`, `\"password\"`, etc. Defaults to `\"text\"`. */\n type?: string;\n /** An adornment rendered before the input, inside the field's border — an icon, a prefix, a\n * currency symbol. Passed straight to `FieldShell`'s slot of the same name. */\n leading?: ReactNode;\n /** An adornment rendered after the input, inside the field's border — a unit, a spinner, an\n * interactive button. Passed straight to `FieldShell`'s slot of the same name. */\n trailing?: ReactNode;\n}\n\n/**\n * A native `<input>` for free-text entry, wrapped in the `FieldShell` that draws the field's\n * chrome. No custom keyboard handling: the native element handles focus, typing and form\n * participation, and the shell reads focus, `aria-invalid` and disabledness off it, so a text\n * field and any other shell-composing control read as the same kind of control side by side in a\n * form.\n *\n * `.vpg-text-field`, the caller's `className` and the prop spread all land on the `<input>`.\n * The border, background and states belong to the shell, so a `className` passed here cannot\n * restyle them — that is a rule on `.vpg-field-shell` (ADR-0011).\n */\nexport function TextField({ className, type = \"text\", leading, trailing, ...rest }: TextFieldProps) {\n const classes = [\"vpg-text-field\", className].filter(Boolean).join(\" \");\n\n return (\n <>\n {/*\n React 19 hoists and de-duplicates this by `href`, so N text fields on a page inject one\n stylesheet.\n */}\n <style href=\"vpg-text-field\" precedence=\"vpg-text-field\">\n {textFieldStylesheet}\n </style>\n <FieldShell leading={leading} trailing={trailing}>\n <input type={type} {...rest} className={classes} />\n </FieldShell>\n </>\n );\n}\n","/**\n * `<PasswordInput>`'s own styles, injected as an inline `<style>` rather than a `.css` import so\n * the package can stay `\"sideEffects\": false` (same approach as every other component's\n * stylesheet). This styles only the reveal button; the field's chrome and the input's own\n * typography come from `FieldShell` and `TextField`, both already injected by the `TextField`\n * this component composes.\n *\n * Every `--vpg-*` property is *read* here through `var()` and never assigned inline by the\n * component: an inline style declaration always wins over a stylesheet rule for the same\n * property on the same element, so an inline `--vpg-accent-ring` would permanently shadow\n * the dark-mode reassignment in `@vipengele/react-tokens`'s base stylesheet and the button would stop\n * adapting to colour mode.\n *\n * The button sits in `FieldShell`'s trailing slot, a direct child of the shell whose own state\n * selectors read `> :focus-visible` and `> :disabled` off the shell's direct children only — the\n * slot span, not the button inside it. So the button needs its own focus-visible ring; neither\n * that ring nor the pointer cursor is inherited from the shell. Dimming is: `PasswordInput`\n * disables the button exactly when it disables the input, so the shell's own `opacity` on\n * `.vpg-field-shell` already fades the button along with the rest of the field, and this\n * rule carries no `opacity` of its own — one would compound onto the shell's and read as more\n * faded than the field around it.\n */\nexport const passwordInputStylesheet = `\n.vpg-password-input-toggle {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n border: none;\n border-radius: var(--vpg-radius-sm);\n padding: 0 var(--vpg-space-1);\n margin: 0;\n background: none;\n color: var(--vpg-ink-muted);\n font-family: inherit;\n font-size: var(--vpg-font-size-xs);\n line-height: 1;\n cursor: pointer;\n transition: color var(--vpg-duration-fast) var(--vpg-ease-standard);\n}\n\n.vpg-password-input-toggle:hover:not(:disabled) {\n color: var(--vpg-ink);\n}\n\n.vpg-password-input-toggle:focus-visible {\n outline: var(--vpg-focus-ring-width) solid var(--vpg-accent-ring);\n outline-offset: var(--vpg-focus-ring-offset);\n}\n\n.vpg-password-input-toggle:disabled {\n cursor: not-allowed;\n}\n`;\n","import { useState } from \"react\";\nimport { TextField, type TextFieldProps } from \"../TextField/TextField.js\";\nimport { passwordInputStylesheet } from \"./PasswordInput.stylesheet.js\";\n\nexport type PasswordInputProps = Omit<TextFieldProps, \"type\" | \"trailing\">;\n\n/**\n * A `TextField` whose native `type` toggles between `\"password\"` and `\"text\"` from a reveal\n * button in the shell's trailing slot, so a consumer can check what they typed without retyping\n * it. Composes `TextField` rather than `FieldShell` directly, reusing the one definition of \"an\n * input inside a shell\" this package has (ADR-0011).\n *\n * Presentational only: no validation, no strength meter, no required indicator. The reveal\n * button is a real `<button type=\"button\">`, so it is reachable by keyboard and never removed\n * from the accessibility tree, and toggling it never moves focus — the click handler only flips\n * state, so a keyboard user stays on the button across a toggle.\n */\nexport function PasswordInput({ className, disabled, ...rest }: PasswordInputProps) {\n const [revealed, setRevealed] = useState(false);\n const label = revealed ? \"Hide password\" : \"Show password\";\n\n return (\n <>\n {/*\n React 19 hoists and de-duplicates this by `href`, so N password inputs on a page inject\n one stylesheet.\n */}\n <style href=\"vpg-password-input\" precedence=\"vpg-password-input\">\n {passwordInputStylesheet}\n </style>\n <TextField\n {...rest}\n className={className}\n disabled={disabled}\n type={revealed ? \"text\" : \"password\"}\n trailing={\n <button\n type=\"button\"\n className=\"vpg-password-input-toggle\"\n aria-pressed={revealed}\n aria-label={label}\n disabled={disabled}\n onClick={() => setRevealed((current) => !current)}\n >\n {revealed ? \"Hide\" : \"Show\"}\n </button>\n }\n />\n </>\n );\n}\n","/**\n * `<Popover>`'s own styles, injected as an inline `<style>` rather than a `.css` import so the\n * package can stay `\"sideEffects\": false` (same approach as `Button`'s and `Card`'s stylesheets).\n *\n * Every `--vpg-*` property is *read* here through `var()` and never assigned inline by the\n * component: an inline style declaration always wins over a stylesheet rule for the same property\n * on the same element, so an inline `--vpg-surface-raised` would permanently shadow the\n * dark-mode reassignment in `@vipengele/react-tokens`'s base stylesheet and this panel would stop adapting\n * to colour mode. The component's only inline style is floating-ui's computed\n * `position`/`top`/`left`, which are plain CSS properties carrying a per-instance coordinate.\n *\n * The panel reads the same raised-surface tokens as `Card` — `--vpg-surface-raised`,\n * `--vpg-border`, `--vpg-radius` — so a floating panel and a card in the page body read as\n * the same material.\n *\n * The panel sits above a listbox and below a tooltip in the stacking family — it is a surface\n * over the page that can contain the control a listbox belongs to — and carries the elevation\n * family's high step, whose two layers re-derive their inks when the colour mode flips.\n */\nexport const popoverStylesheet = `\n.vpg-popover-trigger {\n /* Inline-flex rather than inline: the wrapper exists only to carry the ref and the click\n handler, and must not add a baseline gap under the element it wraps. */\n display: inline-flex;\n}\n\n.vpg-popover {\n position: absolute;\n z-index: var(--vpg-layer-popover);\n box-sizing: border-box;\n /* The size of a container, not a step of anything: no scale carries a measurement this large,\n and a \\`--vpg-*\\` name the theme never assigns advertises a theming hook that doesn't\n exist. */\n max-width: 20rem;\n padding: 1rem;\n background-color: var(--vpg-surface-raised);\n border: 1px solid var(--vpg-border);\n border-radius: var(--vpg-radius);\n box-shadow: var(--vpg-shadow-high);\n color: var(--vpg-ink);\n font-family: var(--vpg-font-sans);\n font-size: var(--vpg-font-size-sm);\n line-height: 1.5;\n /* The panel holds interactive content, so unlike a tooltip it must stay hit-testable. */\n overflow-wrap: break-word;\n}\n\n.vpg-popover:focus-visible {\n /* The panel itself takes focus when it holds nothing tabbable; the ring is what makes that\n visible. Offset rather than inset so it stays legible against the panel's own surface. */\n outline: var(--vpg-focus-ring-width) solid var(--vpg-accent-ring);\n outline-offset: var(--vpg-focus-ring-offset);\n}\n`;\n","import {\n autoUpdate,\n FloatingFocusManager,\n flip,\n offset,\n shift,\n useClick,\n useDismiss,\n useFloating,\n useInteractions,\n useRole,\n} from \"@floating-ui/react\";\nimport { type AriaAttributes, cloneElement, Fragment, isValidElement, type ReactNode, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { popoverStylesheet } from \"./Popover.stylesheet.js\";\n\n/** Deliberately a copy of `TooltipPlacement` rather than an import of it: one directory per\n * component, with no edge between two components that merely happen to accept the same four\n * sides. */\nexport type PopoverPlacement = \"top\" | \"bottom\" | \"left\" | \"right\";\n\nexport interface PopoverProps {\n /** What the panel holds. A plain node rather than a render prop taking a `close` callback:\n * content that has to close the popover itself belongs in the controlled form, where the\n * consumer already owns the state and the `onOpenChange` handler. */\n content: ReactNode;\n /** The element the panel hangs off. It is wrapped in a `<span>` that carries the ref and the\n * click handler — not cloned for those, so it can be any node, including a component that\n * doesn't forward a ref or spread unknown props. When it is a single element, it is\n * additionally cloned with `aria-haspopup`/`aria-expanded`/`aria-controls` merged on, so\n * assistive tech operating the actual control gets its dialog semantics. */\n children: ReactNode;\n /** Controls the panel. Supplying it hands the state to the caller: the popover then opens and\n * closes only when this prop changes, and reports every request through `onOpenChange`. */\n open?: boolean;\n /** Seeds the uncontrolled state. Ignored once `open` is supplied. */\n defaultOpen?: boolean;\n /** Fired for every open/close request — a trigger click, an outside press, `Escape` — in both\n * the controlled and the uncontrolled form. */\n onOpenChange?: (open: boolean) => void;\n /** Preferred side of the trigger. Floating-ui flips to the opposite side when the panel\n * wouldn't fit there. */\n placement?: PopoverPlacement;\n /** Composed onto the panel, not onto the trigger wrapper. */\n className?: string;\n}\n\n/** Gap between the trigger and the panel, in pixels. */\nconst POPOVER_OFFSET = 10;\n\n/** Minimum gap kept between the panel and the viewport edge when it has to shift, in pixels. */\nconst VIEWPORT_PADDING = 12;\n\n/**\n * A floating panel of interactive content, opened by clicking its trigger and dismissed by an\n * outside press, by `Escape`, or by clicking the trigger again.\n *\n * Focus is trapped inside the panel while it is open and returned to the trigger when it closes —\n * the panel holds real interactive content, so keyboard users must be able to reach it and must\n * not fall out the back of it into the page behind.\n *\n * The panel portals into the nearest ancestor `.vpg-root` rather than `document.body`:\n * `ThemeProvider` assigns every `--vpg-*` property on `.vpg-root`, so a panel outside that\n * subtree would resolve every `var()` to nothing and lose colour-mode adaptation entirely. With no\n * `.vpg-root` ancestor — an unthemed page, or a test rendering the component on its own — the\n * panel renders inline as the trigger's sibling instead. It is positioned by the same computed\n * coordinates either way; only the `--vpg-*` values it inherits differ.\n */\nexport function Popover({ content, children, open, defaultOpen = false, onOpenChange, placement = \"bottom\", className }: PopoverProps) {\n const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);\n const isOpen = open ?? uncontrolledOpen;\n\n const handleOpenChange = (next: boolean) => {\n // The internal state is kept only while `open` is absent. Writing it in the controlled form\n // too would leave a stale value behind for the moment `open` is later withdrawn.\n if (open === undefined) {\n setUncontrolledOpen(next);\n }\n onOpenChange?.(next);\n };\n\n const { refs, floatingStyles, context, elements } = useFloating({\n open: isOpen,\n onOpenChange: handleOpenChange,\n placement,\n middleware: [offset(POPOVER_OFFSET), flip(), shift({ padding: VIEWPORT_PADDING })],\n whileElementsMounted: autoUpdate,\n });\n\n // `useRole` with `role: \"dialog\"` is what pairs `role`/`id` on the panel with\n // `aria-expanded`/`aria-haspopup`/`aria-controls` on the trigger wrapper, off a `useId`-generated\n // id it owns; setting either half by hand would leave the other pointing at a different id.\n const click = useClick(context);\n const dismiss = useDismiss(context);\n const dialogRole = useRole(context, { role: \"dialog\" });\n const { getReferenceProps, getFloatingProps } = useInteractions([click, dismiss, dialogRole]);\n\n // `aria-haspopup`/`aria-expanded`/`aria-controls` describe the operable trigger control to\n // assistive tech, not an inert wrapper — the wrapper `<span>` never receives focus, so\n // attributes on it are invisible to a screen reader operating the actual control. When\n // `children` is a single element (and not a `Fragment`, which names no single DOM node), it is\n // cloned with just these plain props merged on — not the ref or the click/dismiss handlers,\n // which a component that doesn't forward refs (`Button` included) can't accept; see\n // `wrap-trigger-never-clone.md`. The click handler stays on the wrapper regardless: a click\n // anywhere inside it, nested child included, bubbles up to it either way.\n const {\n \"aria-haspopup\": ariaHaspopup,\n \"aria-expanded\": ariaExpanded,\n \"aria-controls\": ariaControls,\n ...referenceProps\n } = getReferenceProps() as Record<string, unknown> & {\n \"aria-haspopup\"?: AriaAttributes[\"aria-haspopup\"];\n \"aria-expanded\"?: AriaAttributes[\"aria-expanded\"];\n \"aria-controls\"?: AriaAttributes[\"aria-controls\"];\n };\n const hasSingleElementChild =\n isValidElement<{\n \"aria-haspopup\"?: AriaAttributes[\"aria-haspopup\"];\n \"aria-expanded\"?: AriaAttributes[\"aria-expanded\"];\n \"aria-controls\"?: AriaAttributes[\"aria-controls\"];\n }>(children) && children.type !== Fragment;\n const trigger = hasSingleElementChild\n ? cloneElement(children, {\n \"aria-haspopup\": ariaHaspopup,\n \"aria-expanded\": ariaExpanded,\n \"aria-controls\": ariaControls,\n })\n : children;\n\n const panel = isOpen ? (\n <FloatingFocusManager context={context} modal>\n <div\n ref={refs.setFloating}\n className={[\"vpg-popover\", className].filter(Boolean).join(\" \")}\n style={floatingStyles}\n {...getFloatingProps()}\n >\n {content}\n </div>\n </FloatingFocusManager>\n ) : null;\n\n const themeRoot = elements.domReference?.closest(\".vpg-root\") ?? null;\n\n return (\n <>\n {/*\n React 19 hoists and de-duplicates this by `href`, so N popovers on a page inject one\n stylesheet.\n */}\n <style href=\"vpg-popover\" precedence=\"vpg-popover\">\n {popoverStylesheet}\n </style>\n {/* biome-ignore lint/a11y/useAriaPropsSupportedByRole: aria-expanded here only reaches a bare span in the fallback case (non-single-element children), the least-wrong place left per wrap-trigger-never-clone.md */}\n <span\n ref={refs.setReference}\n className=\"vpg-popover-trigger\"\n aria-haspopup={hasSingleElementChild ? undefined : ariaHaspopup}\n aria-expanded={hasSingleElementChild ? undefined : ariaExpanded}\n aria-controls={hasSingleElementChild ? undefined : ariaControls}\n {...referenceProps}\n >\n {trigger}\n </span>\n {panel !== null && themeRoot !== null ? createPortal(panel, themeRoot) : panel}\n </>\n );\n}\n","/**\n * `<Progress>`'s own styles, injected as an inline `<style>` rather than a `.css` import so the\n * package can stay `\"sideEffects\": false` (same approach as `Skeleton`'s and `Avatar`'s\n * stylesheets).\n *\n * Every `--vpg-*` property this component depends on is *read* here through `var()` and\n * never assigned inline by the component: an inline style declaration always wins over a\n * stylesheet rule for the same property on the same element, so an inline `--vpg-accent`\n * would permanently shadow the dark-mode reassignment in `@vipengele/react-tokens`'s base stylesheet.\n * The per-instance fill width is an unprefixed inline `width`, not a `--vpg-*` custom\n * property, so it carries no such risk.\n *\n * The indeterminate sweep animates a translated fill's own width and position rather than\n * `background-position`, since there is no filled/unfilled boundary to hold still against —\n * unlike a determinate bar, the whole fill segment travels the track.\n */\nexport const progressStylesheet = `\n@keyframes vpg-progress-sweep {\n 0% { left: -40%; width: 40%; }\n 50% { width: 60%; }\n 100% { left: 100%; width: 40%; }\n}\n\n.vpg-progress {\n position: relative;\n display: block;\n overflow: hidden;\n box-sizing: border-box;\n border-radius: var(--vpg-radius-sm);\n background-color: var(--vpg-surface-raised);\n}\n\n.vpg-progress-sm {\n height: 0.25rem;\n}\n\n.vpg-progress-md {\n height: 0.5rem;\n}\n\n.vpg-progress-lg {\n height: 0.75rem;\n}\n\n.vpg-progress-fill {\n height: 100%;\n border-radius: inherit;\n background-color: var(--vpg-accent);\n}\n\n.vpg-progress-determinate .vpg-progress-fill {\n transition: width 0.2s ease-out;\n}\n\n.vpg-progress-indeterminate .vpg-progress-fill {\n position: absolute;\n top: 0;\n animation: vpg-progress-sweep 1.5s ease-in-out infinite;\n}\n\n@media (prefers-reduced-motion: reduce) {\n /* Slowed, not stopped: a bar that never moves at all reports nothing about the wait it exists\n to report. */\n .vpg-progress-indeterminate .vpg-progress-fill {\n animation-duration: 3s;\n }\n}\n`;\n","import type { HTMLAttributes } from \"react\";\nimport { progressStylesheet } from \"./Progress.stylesheet.js\";\n\nexport type ProgressSize = \"sm\" | \"md\" | \"lg\";\n\nexport interface ProgressProps extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n /** The current amount of progress. Omitted (the default) renders the indeterminate, looping\n * sweep variant — a progress bar with no known value has nothing to report as a percentage. */\n value?: number;\n /** The value that represents completion. */\n max?: number;\n size?: ProgressSize;\n}\n\n/**\n * Clamps `value` into `[0, max]` — a caller passing a value outside that range (a stale total, a\n * count that overshoots its max) still renders a bar that reads as complete or empty rather than\n * overflowing the track or reporting an invalid `aria-valuenow`.\n */\nfunction clamp(value: number, max: number): number {\n if (value < 0) return 0;\n if (value > max) return max;\n return value;\n}\n\n/**\n * The library's progress atom: a linear track with a filled bar. Determinate when `value` is\n * given (`aria-valuenow`/`-valuemin`/`-valuemax` report the exact position), indeterminate\n * otherwise (a looping sweep, with no `aria-value*` — per ARIA, a progressbar with no known value\n * should not report a fake one).\n */\nexport function Progress({ value, max = 100, size = \"md\", className, style, ...rest }: ProgressProps) {\n const determinate = value !== undefined;\n // A non-positive `max` has nothing left to divide by — read as already complete rather than\n // rendering a `NaN%` width the browser silently ignores.\n const percentage = determinate ? (max <= 0 ? 100 : (clamp(value, max) / max) * 100) : undefined;\n\n const classes = [\n \"vpg-progress\",\n `vpg-progress-${size}`,\n determinate ? \"vpg-progress-determinate\" : \"vpg-progress-indeterminate\",\n className,\n ]\n .filter(Boolean)\n .join(\" \");\n\n const labelling = determinate ? { \"aria-valuenow\": clamp(value, max), \"aria-valuemin\": 0, \"aria-valuemax\": max } : undefined;\n\n return (\n <>\n {/*\n React 19 hoists and de-duplicates this by `href`, so N progress bars on a page inject one\n stylesheet.\n */}\n <style href=\"vpg-progress\" precedence=\"vpg-progress\">\n {progressStylesheet}\n </style>\n <div {...rest} role=\"progressbar\" {...labelling} className={classes} style={style}>\n <div className=\"vpg-progress-fill\" style={determinate ? { width: `${percentage}%` } : undefined} />\n </div>\n </>\n );\n}\n","/**\n * `<RadioGroup>`'s own styles, injected as an inline `<style>` rather than a `.css` import so the\n * package can stay `\"sideEffects\": false` (same approach as `Toggle`'s and `Tabs`' stylesheets).\n *\n * Every `--vpg-*` property is *read* here through `var()` and never assigned inline by the\n * component: an inline style declaration always wins over a stylesheet rule for the same property\n * on the same element, so an inline theme property would permanently shadow\n * `@vipengele/react-tokens`' dark-mode reassignment and this group would stop adapting to colour mode.\n */\nexport const radioGroupStylesheet = `\n.vpg-radio-group {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n`;\n","import { createContext, type HTMLAttributes, type ReactNode, useContext, useId, useMemo, useState } from \"react\";\nimport { radioGroupStylesheet } from \"./RadioGroup.stylesheet.js\";\n\nexport interface RadioGroupContextValue {\n name: string;\n value: string | undefined;\n onChange: (value: string) => void;\n}\n\n/**\n * Read by `RadioButton` to pick up a shared `name`, the group's selected value, and a change\n * handler. Unlike `Tabs`' context, `useContext` returning `null` is a normal, supported outcome\n * here — `RadioButton` is usable standalone outside any `RadioGroup`, so nothing reading this\n * context throws when it is absent.\n */\nexport const RadioGroupContext = createContext<RadioGroupContextValue | null>(null);\n\nexport function useRadioGroupContext(): RadioGroupContextValue | null {\n return useContext(RadioGroupContext);\n}\n\nexport interface RadioGroupProps extends Omit<HTMLAttributes<HTMLDivElement>, \"onChange\"> {\n /** Makes the selection controlled; pair it with `onChange`. */\n value?: string;\n /** The initially selected value when the selection is uncontrolled. */\n defaultValue?: string;\n onChange?: (value: string) => void;\n /** The shared `name` every child `RadioButton` receives through context. Auto-generated via\n * `useId` when omitted, so native radio grouping works without the consumer naming anything. */\n name?: string;\n /**\n * The group's accessible name. Required for `role=\"radiogroup\"` to have one: a `<legend>` on\n * an ancestor `FieldSet` names the `<fieldset>` itself, not a `role=\"radiogroup\"` element\n * nested inside it.\n */\n \"aria-label\"?: string;\n children?: ReactNode;\n}\n\n/**\n * A compound context provider grouping `RadioButton`s: `role=\"radiogroup\"` on its own wrapper,\n * controlled through `value`/`onChange` or left to `RadioGroup` itself, seeded by\n * `defaultValue` — the same controlled/uncontrolled duality as `Tabs`. Every child `RadioButton`\n * reads its `name`, `checked`, and `onChange` from context, so native radio grouping and\n * browser-native arrow-key behavior work without any hand-written keyboard code.\n */\nexport function RadioGroup({ value, defaultValue, onChange, name, className, children, ...rest }: RadioGroupProps) {\n const generatedName = useId();\n const resolvedName = name ?? generatedName;\n const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);\n const controlled = value !== undefined;\n const selectedValue = controlled ? value : uncontrolledValue;\n\n const classes = [\"vpg-radio-group\", className].filter(Boolean).join(\" \");\n\n const context = useMemo<RadioGroupContextValue>(\n () => ({\n name: resolvedName,\n value: selectedValue,\n onChange(next: string) {\n if (!controlled) {\n setUncontrolledValue(next);\n }\n onChange?.(next);\n },\n }),\n [resolvedName, selectedValue, controlled, onChange],\n );\n\n return (\n <>\n {/*\n React 19 hoists and de-duplicates this by `href`, so N radio groups on a page inject one\n stylesheet.\n */}\n <style href=\"vpg-radio-group\" precedence=\"vpg-radio-group\">\n {radioGroupStylesheet}\n </style>\n <RadioGroupContext.Provider value={context}>\n <div {...rest} role=\"radiogroup\" className={classes}>\n {children}\n </div>\n </RadioGroupContext.Provider>\n </>\n );\n}\n","/**\n * `<RadioButton>`'s own styles, injected as an inline `<style>` rather than a `.css` import so\n * the package can stay `\"sideEffects\": false` (same approach as `Toggle.stylesheet.ts`).\n *\n * Every `--vpg-*` property is *read* here through `var()` and never assigned inline by the\n * component: an inline style declaration always wins over a stylesheet rule for the same\n * property on the same element, so an inline theme property would permanently shadow\n * `@vipengele/react-tokens`' dark-mode reassignment and this radio would stop adapting to colour mode.\n *\n * The indicator is a glyph rather than a pointer target — the label row around it is what a\n * pointer aims at — so it takes a step of the icon scale. The dot is written as a fraction of the\n * indicator so the two stay in proportion.\n */\nexport const radioButtonStylesheet = `\n.vpg-radio-button {\n appearance: none;\n -webkit-appearance: none;\n box-sizing: border-box;\n position: relative;\n display: inline-block;\n flex: none;\n width: var(--vpg-icon-md);\n height: var(--vpg-icon-md);\n margin: 0;\n padding: 0;\n border: 1px solid var(--vpg-border);\n border-radius: var(--vpg-radius-full);\n background-color: var(--vpg-surface);\n cursor: pointer;\n transition: border-color 120ms ease;\n}\n\n.vpg-radio-button::before {\n content: \"\";\n position: absolute;\n inset: 0;\n margin: auto;\n width: calc(var(--vpg-icon-md) * 0.5);\n height: calc(var(--vpg-icon-md) * 0.5);\n border-radius: var(--vpg-radius-full);\n background-color: var(--vpg-accent);\n transform: scale(0);\n transition: transform 120ms ease;\n}\n\n.vpg-radio-button:checked {\n border-color: var(--vpg-accent);\n}\n\n.vpg-radio-button:checked::before {\n transform: scale(1);\n}\n\n.vpg-radio-button:focus-visible {\n outline: var(--vpg-focus-ring-width) solid var(--vpg-accent-ring);\n outline-offset: var(--vpg-focus-ring-offset);\n}\n\n.vpg-radio-button:disabled {\n cursor: not-allowed;\n opacity: 0.55;\n}\n`;\n","import type { ChangeEvent, InputHTMLAttributes } from \"react\";\nimport { useRadioGroupContext } from \"../RadioGroup/RadioGroup.js\";\nimport { radioButtonStylesheet } from \"./RadioButton.stylesheet.js\";\n\nexport interface RadioButtonProps extends Omit<InputHTMLAttributes<HTMLInputElement>, \"type\" | \"value\"> {\n /** This radio's own value. Compared against `RadioGroup`'s selected value when rendered inside\n * one; required for a `RadioGroup`-provided `checked`/`onChange` to do anything meaningful. */\n value?: string;\n}\n\n/**\n * A single styled native `<input type=\"radio\">`. No custom keyboard or roving-tabindex code:\n * native radios sharing a `name` get browser-native grouping and arrow-key behavior for free.\n *\n * Usable standalone outside any `RadioGroup` — pass `name`/`checked`/`onChange` manually, the\n * same as a plain `<input type=\"radio\">` — or nested inside one, where `name`, the selected\n * state, and the change handler come from context instead. An explicit `checked` prop always\n * wins over context, so a `RadioButton` inside a group can still be driven manually if a caller\n * needs that.\n */\nexport function RadioButton({ className, name, checked, onChange, value, ...rest }: RadioButtonProps) {\n const context = useRadioGroupContext();\n const manualChecked = checked !== undefined;\n\n const resolvedName = name ?? context?.name;\n const resolvedChecked = manualChecked ? checked : context ? value !== undefined && context.value === value : undefined;\n\n function handleChange(event: ChangeEvent<HTMLInputElement>) {\n onChange?.(event);\n if (!manualChecked && context && value !== undefined) {\n context.onChange(value);\n }\n }\n\n const classes = [\"vpg-radio-button\", className].filter(Boolean).join(\" \");\n\n return (\n <>\n {/*\n React 19 hoists and de-duplicates this by `href`, so N radio buttons on a page inject\n one stylesheet.\n */}\n <style href=\"vpg-radio-button\" precedence=\"vpg-radio-button\">\n {radioButtonStylesheet}\n </style>\n <input\n {...rest}\n type=\"radio\"\n name={resolvedName}\n value={value}\n checked={resolvedChecked}\n onChange={handleChange}\n className={classes}\n />\n </>\n );\n}\n","/**\n * `<Skeleton>`'s own styles, injected as an inline `<style>` rather than a `.css` import so the\n * package can stay `\"sideEffects\": false` (same approach as `Spinner`'s and `Avatar`'s\n * stylesheets).\n *\n * Every `--vpg-*` property this component depends on is *read* here through `var()` and\n * never assigned inline by the component: an inline style declaration always wins over a\n * stylesheet rule for the same property on the same element, so an inline `--vpg-surface-*`\n * would permanently shadow the dark-mode reassignment in `@vipengele/react-tokens`'s base stylesheet.\n *\n * The shimmer sweeps a gradient across the element by animating `background-position` rather\n * than `opacity`: an opacity pulse reads as the whole placeholder flashing, while a moving\n * highlight reads as light travelling across a surface, which is the effect a loading\n * placeholder is meant to suggest.\n *\n * The gradient computes its own lightness swing from `--vpg-surface` directly, at wider\n * `--vpg-lift`/`--vpg-sink` multiples than `--vpg-surface-raised`/`-hover` use —\n * rather than reading those two properties as-is. Their swing is tuned for a static hover/press\n * affordance, and reads as barely-there motion once animated against `--vpg-surface-dark`'s\n * low base lightness, where the same absolute delta is far less perceptible than it is against\n * the light surface. Scoped to this component alone so the shared ramp (Button's secondary\n * variant, ButtonGroup's hover state, …) keeps its own tuning.\n */\nexport const skeletonStylesheet = `\n@keyframes vpg-skeleton-shimmer {\n 0% { background-position: 200% 0; }\n 100% { background-position: -200% 0; }\n}\n\n.vpg-skeleton {\n display: block;\n flex: none;\n box-sizing: border-box;\n background-image: linear-gradient(\n 90deg,\n oklch(from var(--vpg-surface) calc(l + var(--vpg-lift) * 2.5) c h) 25%,\n oklch(from var(--vpg-surface) calc(l - var(--vpg-sink) * 1.5) c h) 50%,\n oklch(from var(--vpg-surface) calc(l + var(--vpg-lift) * 2.5) c h) 75%\n );\n background-size: 200% 100%;\n animation: vpg-skeleton-shimmer 1.5s ease-in-out infinite;\n}\n\n.vpg-skeleton-text {\n width: 100%;\n height: 1em;\n border-radius: var(--vpg-radius-sm);\n}\n\n.vpg-skeleton-rect {\n width: 100%;\n height: 1.25rem;\n border-radius: var(--vpg-radius);\n}\n\n.vpg-skeleton-circle {\n width: 2.5rem;\n /* Falls back to a square only when the caller sets a width but no height, so a single\n \\`width\\` prop is enough to draw a circle without a matching \\`height\\`. Explicit \\`height\\`\n (set inline, per-instance) still wins over this and sizes the other axis. */\n aspect-ratio: 1;\n border-radius: 50%;\n}\n\n@media (prefers-reduced-motion: reduce) {\n /* Slowed, not stopped: a placeholder that never moves at all reports nothing about the wait\n it exists to report. */\n .vpg-skeleton {\n animation-duration: 3s;\n }\n}\n`;\n","import type { CSSProperties, HTMLAttributes } from \"react\";\nimport { skeletonStylesheet } from \"./Skeleton.stylesheet.js\";\n\nexport type SkeletonVariant = \"rect\" | \"circle\" | \"text\";\n\nexport interface SkeletonProps extends HTMLAttributes<HTMLDivElement> {\n variant?: SkeletonVariant;\n /** A number is treated as pixels, matching React's own inline-style convention; a string\n * carries its own unit. Neither is a `--vpg-*` custom property, so both are safe to set\n * as an inline style — they're the per-instance dimensions the caller controls, not a\n * theme-controlled colour. */\n width?: string | number;\n /** Same convention as `width`. Left unset, the variant's own stylesheet rule sizes it. */\n height?: string | number;\n}\n\nfunction toDimension(value: string | number | undefined): string | undefined {\n if (value === undefined) return undefined;\n return typeof value === \"number\" ? `${value}px` : value;\n}\n\n/**\n * A shimmering placeholder that stands in for content still loading, shaped to match what it\n * will become: a line of text, a rectangular block, or a circular avatar/icon slot.\n */\nexport function Skeleton({ variant = \"text\", width, height, className, style, ...rest }: SkeletonProps) {\n const classes = [\"vpg-skeleton\", `vpg-skeleton-${variant}`, className].filter(Boolean).join(\" \");\n\n const dimensions: CSSProperties = {\n width: toDimension(width),\n height: toDimension(height),\n };\n\n return (\n <>\n {/*\n React 19 hoists and de-duplicates this by `href`, so N skeletons on a page inject one\n stylesheet.\n */}\n <style href=\"vpg-skeleton\" precedence=\"vpg-skeleton\">\n {skeletonStylesheet}\n </style>\n {/* Decorative by construction: it stands in for content that isn't there yet, so nothing\n about it is meant to reach the accessibility tree. */}\n <div {...rest} aria-hidden=\"true\" className={classes} style={{ ...dimensions, ...style }} />\n </>\n );\n}\n","/**\n * `<Slider>`'s own styles, injected as an inline `<style>` rather than a `.css` import so the\n * package can stay `\"sideEffects\": false` (same approach as `Toggle.stylesheet.ts`).\n *\n * Every `--vpg-*` property is *read* here through `var()` and never assigned inline by the\n * component: an inline style declaration always wins over a stylesheet rule for the same\n * property on the same element, so an inline theme property would permanently shadow\n * `@vipengele/react-tokens`' dark-mode reassignment and this slider would stop adapting to colour mode.\n *\n * The track takes a step of the spacing scale and the thumb one of the icon scale, a thumb being\n * glyph-sized rather than a control in its own right.\n *\n * `-webkit-` and `-moz-` pseudo-elements can't be grouped in one selector — an invalid selector\n * in a comma-separated list drops the whole rule in some engines — so track and thumb styling is\n * duplicated per vendor prefix.\n */\nexport const sliderStylesheet = `\n.vpg-slider {\n appearance: none;\n -webkit-appearance: none;\n box-sizing: border-box;\n display: block;\n width: 100%;\n margin: 0;\n padding: 0;\n background: transparent;\n cursor: pointer;\n}\n\n.vpg-slider::-webkit-slider-runnable-track {\n box-sizing: border-box;\n width: 100%;\n height: var(--vpg-space-1);\n border-radius: var(--vpg-radius-full);\n background-color: var(--vpg-surface-sunken);\n border: 1px solid var(--vpg-border);\n}\n\n.vpg-slider::-moz-range-track {\n box-sizing: border-box;\n width: 100%;\n height: var(--vpg-space-1);\n border-radius: var(--vpg-radius-full);\n background-color: var(--vpg-surface-sunken);\n border: 1px solid var(--vpg-border);\n}\n\n.vpg-slider::-webkit-slider-thumb {\n -webkit-appearance: none;\n box-sizing: border-box;\n width: var(--vpg-icon-md);\n height: var(--vpg-icon-md);\n margin-top: calc((var(--vpg-space-1) - var(--vpg-icon-md)) / 2);\n border-radius: var(--vpg-radius-full);\n border: 1px solid var(--vpg-accent);\n background-color: var(--vpg-accent);\n cursor: pointer;\n transition: background-color 120ms ease, border-color 120ms ease;\n}\n\n.vpg-slider::-moz-range-thumb {\n box-sizing: border-box;\n width: var(--vpg-icon-md);\n height: var(--vpg-icon-md);\n border-radius: var(--vpg-radius-full);\n border: 1px solid var(--vpg-accent);\n background-color: var(--vpg-accent);\n cursor: pointer;\n transition: background-color 120ms ease, border-color 120ms ease;\n}\n\n.vpg-slider:focus-visible::-webkit-slider-thumb {\n outline: var(--vpg-focus-ring-width) solid var(--vpg-accent-ring);\n outline-offset: var(--vpg-focus-ring-offset);\n}\n\n.vpg-slider:focus-visible::-moz-range-thumb {\n outline: var(--vpg-focus-ring-width) solid var(--vpg-accent-ring);\n outline-offset: var(--vpg-focus-ring-offset);\n}\n\n.vpg-slider:disabled {\n cursor: not-allowed;\n opacity: 0.55;\n}\n\n.vpg-slider:disabled::-webkit-slider-thumb {\n cursor: not-allowed;\n}\n\n.vpg-slider:disabled::-moz-range-thumb {\n cursor: not-allowed;\n}\n`;\n","import type { InputHTMLAttributes } from \"react\";\nimport { sliderStylesheet } from \"./Slider.stylesheet.js\";\n\nexport interface SliderProps extends Omit<InputHTMLAttributes<HTMLInputElement>, \"type\"> {}\n\n/**\n * A native `<input type=\"range\">` styled as a single-thumb slider. It forwards every `<input>`\n * prop except `type`, so `min`/`max`/`step`, `value`/`onChange` (controlled) or `defaultValue`\n * (uncontrolled), and `disabled` all work exactly as they do on a plain range input. No custom\n * keyboard or pointer handling: the native element already handles arrow-key stepping, dragging,\n * touch, and form participation for free.\n */\nexport function Slider({ className, ...rest }: SliderProps) {\n const classes = [\"vpg-slider\", className].filter(Boolean).join(\" \");\n\n return (\n <>\n {/*\n React 19 hoists and de-duplicates this by `href`, so N sliders on a page inject one\n stylesheet.\n */}\n <style href=\"vpg-slider\" precedence=\"vpg-slider\">\n {sliderStylesheet}\n </style>\n <input type=\"range\" {...rest} className={classes} />\n </>\n );\n}\n","/**\n * `<Tabs>`'s own styles, injected as an inline `<style>` rather than a `.css` import so the\n * package can stay `\"sideEffects\": false` (same approach as `Card`'s and `Button`'s stylesheets).\n *\n * Every `--vpg-*` property is *read* here through `var()` and never assigned inline by the\n * component: an inline style declaration always wins over a stylesheet rule for the same property\n * on the same element, so an inline `--vpg-accent` would permanently shadow the dark-mode\n * reassignment in `@vipengele/react-tokens`'s base stylesheet and these tabs would stop adapting to\n * colour mode.\n *\n * The selected indicator is a border on the tab itself, matched by a transparent border of the\n * same width on every unselected tab, so selection never shifts the row's layout.\n */\nexport const tabsStylesheet = `\n.vpg-tabs {\n display: flex;\n flex-direction: column;\n color: var(--vpg-ink);\n font-family: var(--vpg-font-sans);\n}\n\n/* A vertical tablist sits beside its panel, not above it. */\n.vpg-tabs-vertical {\n flex-direction: row;\n}\n\n.vpg-tabs-list {\n display: flex;\n}\n\n.vpg-tabs-list-horizontal {\n flex-direction: row;\n border-bottom: 1px solid var(--vpg-border);\n}\n\n.vpg-tabs-list-vertical {\n flex-direction: column;\n border-right: 1px solid var(--vpg-border);\n}\n\n.vpg-tabs-tab {\n appearance: none;\n background: none;\n cursor: pointer;\n box-sizing: border-box;\n padding: 0.5rem 0.75rem;\n border: none;\n color: var(--vpg-ink-muted);\n font: inherit;\n font-size: var(--vpg-font-size-sm);\n line-height: 1.5;\n}\n\n.vpg-tabs-list-horizontal .vpg-tabs-tab {\n border-bottom: 2px solid transparent;\n margin-bottom: -1px;\n}\n\n.vpg-tabs-list-vertical .vpg-tabs-tab {\n text-align: left;\n border-right: 2px solid transparent;\n margin-right: -1px;\n}\n\n.vpg-tabs-tab:hover:not(:disabled) {\n color: var(--vpg-ink);\n background-color: var(--vpg-surface-hover);\n}\n\n.vpg-tabs-tab:focus-visible {\n /* Inset so the ring stays inside the list's own border rather than straddling it. */\n outline: var(--vpg-focus-ring-width) solid var(--vpg-accent-ring);\n outline-offset: calc(var(--vpg-focus-ring-offset) * -1);\n}\n\n.vpg-tabs-tab:disabled {\n cursor: not-allowed;\n color: var(--vpg-ink-subtle);\n}\n\n.vpg-tabs-tab-selected {\n color: var(--vpg-accent);\n}\n\n/* Scoped by orientation to outweigh the transparent placeholder border above, which is itself\n orientation-scoped and would otherwise win on specificity. */\n.vpg-tabs-list-horizontal .vpg-tabs-tab-selected {\n border-bottom-color: var(--vpg-accent);\n}\n\n.vpg-tabs-list-vertical .vpg-tabs-tab-selected {\n border-right-color: var(--vpg-accent);\n}\n\n.vpg-tabs-panel {\n padding: 1rem 0;\n}\n\n.vpg-tabs-vertical .vpg-tabs-panel {\n padding: 0 1rem;\n}\n`;\n","import {\n Children,\n createContext,\n type HTMLAttributes,\n isValidElement,\n type KeyboardEvent,\n type MouseEvent,\n type ReactNode,\n useContext,\n useId,\n useMemo,\n useState,\n} from \"react\";\nimport { tabsStylesheet } from \"./Tabs.stylesheet.js\";\n\nexport type TabsOrientation = \"horizontal\" | \"vertical\";\n\ninterface TabsContextValue {\n activeValue: string | undefined;\n /** The value whose `Tabs.Tab` gets `tabIndex={0}` — `activeValue`, unless that tab is disabled. */\n tabStopValue: string | undefined;\n activate: (value: string) => void;\n orientation: TabsOrientation;\n baseId: string;\n}\n\n/** The one piece of React context in this package: `Tabs.List`/`Tabs.Tab`/`Tabs.Panel` are\n * arranged by the consumer, so the active value, the orientation and the id pairing can't reach\n * them as props. */\nconst TabsContext = createContext<TabsContextValue | null>(null);\n\n/** The traversal set: tabs a keyboard user can reach, in DOM order. */\n// biome-ignore lint/security/noSecrets: a CSS selector, read as a high-entropy string\nconst ENABLED_TAB_SELECTOR = '[role=\"tab\"]:not([disabled])';\n\nfunction useTabsContext(component: string): TabsContextValue {\n const context = useContext(TabsContext);\n if (context === null) {\n throw new Error(`${component} must be rendered inside <Tabs>.`);\n }\n return context;\n}\n\nfunction tabId(baseId: string, value: string): string {\n return `${baseId}-tab-${value}`;\n}\n\nfunction panelId(baseId: string, value: string): string {\n return `${baseId}-panel-${value}`;\n}\n\nexport interface TabsListProps extends HTMLAttributes<HTMLDivElement> {\n children?: ReactNode;\n}\n\nfunction TabsList({ className, children, onKeyDown, ...rest }: TabsListProps) {\n const { orientation, activate } = useTabsContext(\"Tabs.List\");\n\n const classes = [\"vpg-tabs-list\", `vpg-tabs-list-${orientation}`, className].filter(Boolean).join(\" \");\n\n /**\n * Arrow keys move focus and activate in one step (automatic activation), wrapping at both ends.\n * Only the pair matching `orientation` is handled — the off-axis pair is left alone so it keeps\n * whatever meaning the surrounding page gives it. Disabled tabs are excluded from the traversal\n * set outright, so every move lands on a tab that can take focus.\n */\n function handleKeyDown(event: KeyboardEvent<HTMLDivElement>) {\n onKeyDown?.(event);\n\n const [previousKey, nextKey] = orientation === \"vertical\" ? [\"ArrowUp\", \"ArrowDown\"] : [\"ArrowLeft\", \"ArrowRight\"];\n\n const tabs = Array.from(event.currentTarget.querySelectorAll<HTMLButtonElement>(ENABLED_TAB_SELECTOR));\n const current = tabs.indexOf(event.target as HTMLButtonElement);\n\n let next: number;\n if (event.key === nextKey) {\n next = (current + 1) % tabs.length;\n } else if (event.key === previousKey) {\n next = (current - 1 + tabs.length) % tabs.length;\n } else if (event.key === \"Home\") {\n next = 0;\n } else if (event.key === \"End\") {\n next = tabs.length - 1;\n } else {\n return;\n }\n\n event.preventDefault();\n // Every index above is taken modulo `tabs.length`, so it names an element of `tabs`, and\n // `Tabs.Tab` always renders `data-value`.\n const target = tabs[next] as HTMLButtonElement;\n target.focus();\n activate(target.dataset.value as string);\n }\n\n return (\n <div {...rest} role=\"tablist\" aria-orientation={orientation} className={classes} onKeyDown={handleKeyDown}>\n {children}\n </div>\n );\n}\n\nexport interface TabsTabProps extends Omit<HTMLAttributes<HTMLButtonElement>, \"children\"> {\n /** Pairs this tab with the `Tabs.Panel` carrying the same `value`. */\n value: string;\n /** Skipped entirely by arrow-key and `Home`/`End` traversal, and not clickable. */\n disabled?: boolean;\n children?: ReactNode;\n}\n\nfunction TabsTab({ value, disabled = false, className, children, onClick, ...rest }: TabsTabProps) {\n const { activeValue, tabStopValue, activate, baseId } = useTabsContext(\"Tabs.Tab\");\n const selected = activeValue === value;\n\n const classes = [\"vpg-tabs-tab\", selected ? \"vpg-tabs-tab-selected\" : \"\", className].filter(Boolean).join(\" \");\n\n function handleClick(event: MouseEvent<HTMLButtonElement>) {\n onClick?.(event);\n activate(value);\n }\n\n return (\n <button\n {...rest}\n type=\"button\"\n role=\"tab\"\n id={tabId(baseId, value)}\n // Inactive panels unmount, so only the selected tab has a panel to point at: an\n // `aria-controls` naming an id that is not in the document resolves to nothing.\n aria-controls={selected ? panelId(baseId, value) : undefined}\n aria-selected={selected}\n // Roving tabindex: `tabStopValue` is the list's single tab stop (normally the selected\n // tab, falling back to the first enabled one if that tab is disabled), and every other\n // tab is reachable only by the arrow keys.\n tabIndex={tabStopValue === value ? 0 : -1}\n disabled={disabled}\n data-value={value}\n className={classes}\n onClick={handleClick}\n >\n {children}\n </button>\n );\n}\n\nexport interface TabsPanelProps extends HTMLAttributes<HTMLDivElement> {\n /** Pairs this panel with the `Tabs.Tab` carrying the same `value`. */\n value: string;\n children?: ReactNode;\n}\n\nfunction TabsPanel({ value, className, children, ...rest }: TabsPanelProps) {\n const { activeValue, baseId } = useTabsContext(\"Tabs.Panel\");\n if (activeValue !== value) {\n return null;\n }\n\n const classes = [\"vpg-tabs-panel\", className].filter(Boolean).join(\" \");\n\n return (\n <div\n {...rest}\n role=\"tabpanel\"\n id={panelId(baseId, value)}\n aria-labelledby={tabId(baseId, value)}\n // biome-ignore lint/a11y/noNoninteractiveTabindex: the tabs pattern makes the panel the keyboard's next stop after the tablist, so a panel holding nothing focusable is still reachable\n tabIndex={0}\n className={classes}\n >\n {children}\n </div>\n );\n}\n\nexport interface TabsProps extends Omit<HTMLAttributes<HTMLDivElement>, \"onChange\"> {\n /** Makes the selection controlled; pair it with `onChange`. */\n value?: string;\n /** The initially selected value when the selection is uncontrolled. Left out, the first\n * `Tabs.Tab` in `children` is selected. */\n defaultValue?: string;\n onChange?: (value: string) => void;\n /** `horizontal` (the default) traverses with Left/Right, `vertical` with Up/Down. */\n orientation?: TabsOrientation;\n children?: ReactNode;\n}\n\n/**\n * The value of the first `Tabs.Tab` anywhere under `children` — the first enabled one when\n * `skipDisabled` is set. This is what an uncontrolled `Tabs` selects when given no\n * `defaultValue`: skipping disabled tabs there means the initial selection is never one a\n * keyboard user can't have reached on their own. The search walks the element tree rather than\n * only `Tabs`' direct children because tabs live inside a `Tabs.List`; a tab produced by a\n * consumer's own component rather than written as JSX is out of scope, the same limit `Card`'s\n * child inspection carries.\n */\nfunction firstTabValue(children: ReactNode, skipDisabled = false): string | undefined {\n let found: string | undefined;\n\n Children.forEach(children, (child) => {\n if (found !== undefined || !isValidElement(child)) {\n return;\n }\n if (child.type === TabsTab) {\n const props = child.props as TabsTabProps;\n if (skipDisabled && props.disabled) {\n return;\n }\n found = props.value;\n return;\n }\n found = firstTabValue((child.props as { children?: ReactNode }).children, skipDisabled);\n });\n\n return found;\n}\n\n/** Whether the `Tabs.Tab` carrying `value` is disabled — used to keep the roving tab stop off a\n * disabled tab even when it is the selected one (a controlled `Tabs` can be pointed at a\n * disabled value; an uncontrolled one no longer picks one by default, but nothing stops a caller\n * from passing `defaultValue` explicitly). Same element-tree walk as `firstTabValue`. */\nfunction isTabDisabled(children: ReactNode, value: string | undefined): boolean {\n if (value === undefined) {\n return false;\n }\n\n let disabled = false;\n\n Children.forEach(children, (child) => {\n if (disabled || !isValidElement(child)) {\n return;\n }\n if (child.type === TabsTab) {\n const props = child.props as TabsTabProps;\n if (props.value === value) {\n disabled = props.disabled ?? false;\n }\n return;\n }\n disabled = isTabDisabled((child.props as { children?: ReactNode }).children, value);\n });\n\n return disabled;\n}\n\nfunction TabsImpl({ value, defaultValue, onChange, orientation = \"horizontal\", className, children, ...rest }: TabsProps) {\n const baseId = useId();\n const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);\n const controlled = value !== undefined;\n // Falls back to the first tab regardless of `disabled` when every tab is disabled, rather than\n // selecting nothing — a tablist always has something selected, even one no keyboard user can\n // currently reach.\n const activeValue = controlled ? value : (uncontrolledValue ?? firstTabValue(children, true) ?? firstTabValue(children));\n\n // The roving tab stop follows `activeValue` unless that tab is disabled (a controlled `Tabs`,\n // or an explicit `defaultValue`, can point at one) — a disabled selected tab would otherwise\n // be the list's only `tabIndex={0}` element, and disabled buttons refuse focus, leaving the\n // whole tablist unreachable by the Tab key.\n const tabStopValue = isTabDisabled(children, activeValue) ? (firstTabValue(children, true) ?? activeValue) : activeValue;\n\n const classes = [\"vpg-tabs\", `vpg-tabs-${orientation}`, className].filter(Boolean).join(\" \");\n\n const context = useMemo<TabsContextValue>(\n () => ({\n activeValue,\n tabStopValue,\n activate(next: string) {\n if (!controlled) {\n setUncontrolledValue(next);\n }\n onChange?.(next);\n },\n orientation,\n baseId,\n }),\n [activeValue, tabStopValue, controlled, onChange, orientation, baseId],\n );\n\n return (\n <>\n {/*\n React 19 hoists and de-duplicates this by `href`, so N tab sets on a page inject one\n stylesheet.\n */}\n <style href=\"vpg-tabs\" precedence=\"vpg-tabs\">\n {tabsStylesheet}\n </style>\n <TabsContext.Provider value={context}>\n <div {...rest} className={classes}>\n {children}\n </div>\n </TabsContext.Provider>\n </>\n );\n}\n\ntype TabsComponent = typeof TabsImpl & {\n List: typeof TabsList;\n Tab: typeof TabsTab;\n Panel: typeof TabsPanel;\n};\n\n/**\n * A tabbed interface: `Tabs.List` holding `Tabs.Tab`s, paired by `value` with the `Tabs.Panel`s\n * beside it. Selection is controlled through `value`/`onChange` or left to `Tabs` itself, seeded\n * by `defaultValue` or by the first tab. Only the selected panel is mounted, so a panel's own\n * state does not survive a switch away from it.\n */\n// The `@__PURE__` annotation tells Rollup/esbuild this call has no side effect it can't see, so\n// an unused `Tabs` export (importing only `Button`, say) is tree-shaken out entirely instead of\n// keeping the whole module \"just in case\" `Object.assign` does something observable.\nexport const Tabs = /* @__PURE__ */ Object.assign(TabsImpl, {\n List: TabsList,\n Tab: TabsTab,\n Panel: TabsPanel,\n}) as TabsComponent;\n","/**\n * `<Toggle>`'s own styles, injected as an inline `<style>` rather than a `.css` import so the\n * package can stay `\"sideEffects\": false` (same approach as `Button.stylesheet.ts`).\n *\n * Every `--vpg-*` property is *read* here through `var()` and never assigned inline by the\n * component: an inline style declaration always wins over a stylesheet rule for the same\n * property on the same element, so an inline theme property would permanently shadow\n * `@vipengele/react-tokens`' dark-mode reassignment and this toggle would stop adapting to colour mode.\n *\n * The track is a glyph rather than a pointer target — the label row around it is what a pointer\n * aims at — so its height and thumb take steps of the icon scale rather than of the size scale.\n * The thumb takes the accent's contrast colour: the thumb sits on the accent once the switch is\n * on, and a near-white thumb is invisible on a light accent.\n */\nexport const toggleStylesheet = `\n.vpg-toggle {\n appearance: none;\n -webkit-appearance: none;\n box-sizing: border-box;\n display: inline-block;\n flex: none;\n /* A ratio of the track's own height: the width is a function of thumb travel, so binding it to\n a control-height step would restretch every switch when that step moves. */\n width: calc(var(--vpg-icon-lg) * 1.8);\n height: var(--vpg-icon-lg);\n margin: 0;\n padding: 0;\n border: 1px solid var(--vpg-border);\n border-radius: var(--vpg-radius-full);\n background-color: var(--vpg-surface-sunken);\n cursor: pointer;\n transition: background-color 120ms ease, border-color 120ms ease;\n}\n\n.vpg-toggle::before {\n content: \"\";\n display: block;\n box-sizing: border-box;\n width: var(--vpg-icon-sm);\n height: var(--vpg-icon-sm);\n margin: 1px;\n border-radius: var(--vpg-radius-full);\n background-color: var(--vpg-surface-raised);\n transform: translateX(0);\n transition: transform 120ms ease, background-color 120ms ease;\n}\n\n.vpg-toggle:checked {\n background-color: var(--vpg-accent);\n border-color: var(--vpg-accent);\n}\n\n.vpg-toggle:checked::before {\n background-color: var(--vpg-accent-contrast);\n transform: translateX(calc(var(--vpg-icon-lg) * 1.8 - var(--vpg-icon-sm) - 4px));\n}\n\n.vpg-toggle:focus-visible {\n outline: var(--vpg-focus-ring-width) solid var(--vpg-accent-ring);\n outline-offset: var(--vpg-focus-ring-offset);\n}\n\n.vpg-toggle:disabled {\n cursor: not-allowed;\n opacity: 0.55;\n}\n`;\n","import type { InputHTMLAttributes } from \"react\";\nimport { toggleStylesheet } from \"./Toggle.stylesheet.js\";\n\nexport interface ToggleProps extends Omit<InputHTMLAttributes<HTMLInputElement>, \"type\" | \"role\"> {}\n\n/**\n * A native `<input type=\"checkbox\" role=\"switch\">` styled as a switch. No custom keyboard\n * handling and no hand-set `aria-checked`: the native element's own `checked` state already\n * exposes it, and a hand-set `aria-checked` would go stale in the uncontrolled\n * (`defaultChecked`) case, where a click updates the DOM's `checked` property without\n * triggering a re-render.\n */\nexport function Toggle({ className, ...rest }: ToggleProps) {\n const classes = [\"vpg-toggle\", className].filter(Boolean).join(\" \");\n\n return (\n <>\n {/*\n React 19 hoists and de-duplicates this by `href`, so N toggles on a page inject one\n stylesheet.\n */}\n <style href=\"vpg-toggle\" precedence=\"vpg-toggle\">\n {toggleStylesheet}\n </style>\n {/* biome-ignore lint/a11y/useAriaPropsForRole: hand-setting aria-checked here would go stale in the uncontrolled (defaultChecked) case, where a click updates the DOM's checked property without a re-render; the native input's own checked state already exposes it */}\n <input type=\"checkbox\" role=\"switch\" {...rest} className={classes} />\n </>\n );\n}\n","/**\n * `<Typography>`'s own styles, injected as an inline `<style>` rather than a `.css` import so\n * the package can stay `\"sideEffects\": false` (same approach as `@vipengele/react-tokens`'s base\n * stylesheet and `Button`'s stylesheet).\n *\n * Every `--vpg-*` property is *read* here through `var()` and never assigned inline by the\n * component: an inline style declaration always wins over a stylesheet rule for the same\n * property on the same element, so an inline `--vpg-ink` would permanently shadow the\n * dark-mode reassignment in `@vipengele/react-tokens`'s base stylesheet and this text would stop\n * adapting to colour mode.\n *\n * Every variant takes a step of the type scale: the four heading roles the scale's top four steps\n * below `display`, which takes the step above them so the two remain distinguishable.\n */\nexport const typographyStylesheet = `\n.vpg-typography {\n margin: 0;\n font-family: inherit;\n}\n\n.vpg-typography-display {\n font-size: var(--vpg-font-size-5xl);\n line-height: 1.1;\n letter-spacing: -0.02em;\n}\n\n.vpg-typography-h1 {\n font-size: var(--vpg-font-size-4xl);\n line-height: 1.15;\n letter-spacing: -0.01em;\n}\n\n.vpg-typography-h2 {\n font-size: var(--vpg-font-size-3xl);\n line-height: 1.2;\n}\n\n.vpg-typography-h3 {\n font-size: var(--vpg-font-size-2xl);\n line-height: 1.25;\n}\n\n.vpg-typography-h4 {\n font-size: var(--vpg-font-size-xl);\n line-height: 1.3;\n}\n\n.vpg-typography-body-lg {\n font-size: var(--vpg-font-size-lg);\n line-height: 1.5;\n}\n\n.vpg-typography-body-md {\n font-size: var(--vpg-font-size-md);\n line-height: 1.5;\n}\n\n.vpg-typography-body-sm {\n font-size: var(--vpg-font-size-sm);\n line-height: 1.5;\n}\n\n.vpg-typography-caption {\n font-size: var(--vpg-font-size-xs);\n line-height: 1.4;\n}\n\n.vpg-typography-weight-regular {\n font-weight: 400;\n}\n\n.vpg-typography-weight-medium {\n font-weight: 500;\n}\n\n.vpg-typography-weight-bold {\n font-weight: 700;\n}\n\n.vpg-typography-color-primary {\n color: var(--vpg-ink);\n}\n\n.vpg-typography-color-secondary {\n color: var(--vpg-ink-muted);\n}\n\n.vpg-typography-color-subtle {\n color: var(--vpg-ink-subtle);\n}\n\n.vpg-typography-color-accent {\n color: var(--vpg-accent);\n}\n`;\n","import type { ComponentPropsWithoutRef, ElementType, ReactNode } from \"react\";\nimport { typographyStylesheet } from \"./Typography.stylesheet.js\";\n\nexport type TypographyVariant = \"display\" | \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"body-lg\" | \"body-md\" | \"body-sm\" | \"caption\";\n\nexport type TypographyWeight = \"regular\" | \"medium\" | \"bold\";\n\n/** A curated set of `--vpg-*` ink tokens — no arbitrary CSS colour is accepted, so text\n * always tracks light/dark mode through the same variables the rest of the library reads. */\nexport type TypographyColor = \"primary\" | \"secondary\" | \"subtle\" | \"accent\";\n\n/** The element each variant renders when a caller doesn't override it with `as`, chosen for\n * the semantic level a reader would expect from the variant's name. */\nconst VARIANT_ELEMENT: Record<TypographyVariant, ElementType> = {\n display: \"h1\",\n h1: \"h1\",\n h2: \"h2\",\n h3: \"h3\",\n h4: \"h4\",\n \"body-lg\": \"p\",\n \"body-md\": \"p\",\n \"body-sm\": \"p\",\n caption: \"span\",\n};\n\ninterface TypographyOwnProps {\n variant?: TypographyVariant;\n weight?: TypographyWeight;\n color?: TypographyColor;\n className?: string;\n children?: ReactNode;\n}\n\n/**\n * `as` overrides only the rendered tag, never the visual style: `<Typography variant=\"h1\"\n * as=\"div\">` keeps the h1 look but renders a `<div>`, which is how a heading-styled label can\n * sit somewhere an `<h1>` would break document outline rules.\n */\nexport type TypographyProps<C extends ElementType = \"p\"> = TypographyOwnProps & {\n as?: C;\n} & Omit<ComponentPropsWithoutRef<C>, keyof TypographyOwnProps | \"as\">;\n\n/**\n * The library's text atom. Visual style comes from `variant`/`weight`/`color`; the rendered\n * tag comes from `variant`'s default or from `as`, independently of one another.\n */\nexport function Typography<C extends ElementType = \"p\">({\n variant = \"body-md\",\n weight = \"regular\",\n color = \"primary\",\n as,\n className,\n children,\n ...rest\n}: TypographyProps<C>) {\n const Component = as ?? VARIANT_ELEMENT[variant];\n\n const classes = [\n \"vpg-typography\",\n `vpg-typography-${variant}`,\n `vpg-typography-weight-${weight}`,\n `vpg-typography-color-${color}`,\n className,\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <>\n {/*\n React 19 hoists and de-duplicates this by `href`, so N Typography instances on a page\n inject one stylesheet.\n */}\n <style href=\"vpg-typography\" precedence=\"vpg-typography\">\n {typographyStylesheet}\n </style>\n <Component {...rest} className={classes}>\n {children}\n </Component>\n </>\n );\n}\n"]}