@cueplusplus/ui 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 (372) hide show
  1. package/dist/charts/_token.js +39 -0
  2. package/dist/charts/container.d.ts +58 -0
  3. package/dist/charts/container.js +77 -0
  4. package/dist/charts/index.d.ts +5 -0
  5. package/dist/charts/index.js +5 -0
  6. package/dist/charts/ramps.d.ts +140 -0
  7. package/dist/charts/ramps.js +615 -0
  8. package/dist/charts/theme.d.ts +112 -0
  9. package/dist/charts/theme.js +165 -0
  10. package/dist/charts/tones.d.ts +111 -0
  11. package/dist/charts/tones.js +127 -0
  12. package/dist/chat/_glyphs.js +55 -0
  13. package/dist/chat/agent-color.d.ts +84 -0
  14. package/dist/chat/agent-color.js +101 -0
  15. package/dist/chat/agent-pile.d.ts +55 -0
  16. package/dist/chat/agent-pile.js +121 -0
  17. package/dist/chat/ask-box.d.ts +88 -0
  18. package/dist/chat/ask-box.js +341 -0
  19. package/dist/chat/composer.d.ts +66 -0
  20. package/dist/chat/composer.js +144 -0
  21. package/dist/chat/delegation-card.d.ts +60 -0
  22. package/dist/chat/delegation-card.js +129 -0
  23. package/dist/chat/index.d.ts +8 -0
  24. package/dist/chat/index.js +8 -0
  25. package/dist/chat/message-list.d.ts +39 -0
  26. package/dist/chat/message-list.js +105 -0
  27. package/dist/chat/message.d.ts +47 -0
  28. package/dist/chat/message.js +108 -0
  29. package/dist/chrome/_glyphs.js +101 -0
  30. package/dist/chrome/_tabs-scroll.d.ts +62 -0
  31. package/dist/chrome/_tabs-scroll.js +68 -0
  32. package/dist/chrome/_tree.d.ts +75 -0
  33. package/dist/chrome/_tree.js +49 -0
  34. package/dist/chrome/empty-state.d.ts +37 -0
  35. package/dist/chrome/empty-state.js +57 -0
  36. package/dist/chrome/eyebrow.d.ts +29 -0
  37. package/dist/chrome/eyebrow.js +36 -0
  38. package/dist/chrome/index.d.ts +17 -0
  39. package/dist/chrome/index.js +17 -0
  40. package/dist/chrome/navigation-menu.d.ts +80 -0
  41. package/dist/chrome/navigation-menu.js +121 -0
  42. package/dist/chrome/page-shell.d.ts +38 -0
  43. package/dist/chrome/page-shell.js +66 -0
  44. package/dist/chrome/panel.d.ts +55 -0
  45. package/dist/chrome/panel.js +67 -0
  46. package/dist/chrome/row.d.ts +82 -0
  47. package/dist/chrome/row.js +106 -0
  48. package/dist/chrome/scroll-area.d.ts +39 -0
  49. package/dist/chrome/scroll-area.js +70 -0
  50. package/dist/chrome/section-header.d.ts +42 -0
  51. package/dist/chrome/section-header.js +79 -0
  52. package/dist/chrome/segmented-control.d.ts +58 -0
  53. package/dist/chrome/segmented-control.js +76 -0
  54. package/dist/chrome/status-bar.d.ts +46 -0
  55. package/dist/chrome/status-bar.js +56 -0
  56. package/dist/chrome/tabs.d.ts +80 -0
  57. package/dist/chrome/tabs.js +176 -0
  58. package/dist/chrome/title-bar.d.ts +37 -0
  59. package/dist/chrome/title-bar.js +45 -0
  60. package/dist/chrome/toolbar.d.ts +46 -0
  61. package/dist/chrome/toolbar.js +62 -0
  62. package/dist/chrome/tree.d.ts +98 -0
  63. package/dist/chrome/tree.js +248 -0
  64. package/dist/color/_checker.js +14 -0
  65. package/dist/color/_convert.d.ts +52 -0
  66. package/dist/color/_convert.js +66 -0
  67. package/dist/color/_glyphs.js +28 -0
  68. package/dist/color/_thumb.js +15 -0
  69. package/dist/color/_value.js +28 -0
  70. package/dist/color/color-area.d.ts +27 -0
  71. package/dist/color/color-area.js +40 -0
  72. package/dist/color/color-field.d.ts +32 -0
  73. package/dist/color/color-field.js +43 -0
  74. package/dist/color/color-picker.d.ts +71 -0
  75. package/dist/color/color-picker.js +178 -0
  76. package/dist/color/color-slider.d.ts +31 -0
  77. package/dist/color/color-slider.js +51 -0
  78. package/dist/color/color-swatch.d.ts +32 -0
  79. package/dist/color/color-swatch.js +44 -0
  80. package/dist/color/index.d.ts +7 -0
  81. package/dist/color/index.js +7 -0
  82. package/dist/configurator/_export.d.ts +78 -0
  83. package/dist/configurator/_export.js +261 -0
  84. package/dist/configurator/_glyphs.js +92 -0
  85. package/dist/configurator/_overrides.d.ts +247 -0
  86. package/dist/configurator/_overrides.js +514 -0
  87. package/dist/configurator/configurator.d.ts +71 -0
  88. package/dist/configurator/configurator.js +279 -0
  89. package/dist/configurator/export-dialog.d.ts +30 -0
  90. package/dist/configurator/export-dialog.js +121 -0
  91. package/dist/configurator/index.d.ts +8 -0
  92. package/dist/configurator/index.js +8 -0
  93. package/dist/configurator/panel-sections.d.ts +86 -0
  94. package/dist/configurator/panel-sections.js +316 -0
  95. package/dist/configurator/token-editor.d.ts +74 -0
  96. package/dist/configurator/token-editor.js +149 -0
  97. package/dist/configurator/use-zoom.d.ts +87 -0
  98. package/dist/configurator/use-zoom.js +113 -0
  99. package/dist/date/_glyphs.js +34 -0
  100. package/dist/date/_segments.js +55 -0
  101. package/dist/date/_trigger.js +31 -0
  102. package/dist/date/calendar.d.ts +25 -0
  103. package/dist/date/calendar.js +125 -0
  104. package/dist/date/date-field.d.ts +34 -0
  105. package/dist/date/date-field.js +41 -0
  106. package/dist/date/date-picker.d.ts +69 -0
  107. package/dist/date/date-picker.js +89 -0
  108. package/dist/date/date-range-picker.d.ts +65 -0
  109. package/dist/date/date-range-picker.js +92 -0
  110. package/dist/date/index.d.ts +6 -0
  111. package/dist/date/index.js +6 -0
  112. package/dist/date/time-field.d.ts +29 -0
  113. package/dist/date/time-field.js +36 -0
  114. package/dist/dmx/_ramp.d.ts +77 -0
  115. package/dist/dmx/_ramp.js +169 -0
  116. package/dist/dmx/_readout.js +53 -0
  117. package/dist/dmx/_universe.d.ts +105 -0
  118. package/dist/dmx/_universe.js +112 -0
  119. package/dist/dmx/channel-matrix.d.ts +81 -0
  120. package/dist/dmx/channel-matrix.js +285 -0
  121. package/dist/dmx/dmx-bar.d.ts +50 -0
  122. package/dist/dmx/dmx-bar.js +107 -0
  123. package/dist/dmx/dmx-strip.d.ts +41 -0
  124. package/dist/dmx/dmx-strip.js +196 -0
  125. package/dist/dmx/index.d.ts +7 -0
  126. package/dist/dmx/index.js +7 -0
  127. package/dist/dmx/universe-grid.d.ts +61 -0
  128. package/dist/dmx/universe-grid.js +182 -0
  129. package/dist/flow/_frame.d.ts +52 -0
  130. package/dist/flow/_frame.js +38 -0
  131. package/dist/flow/controls.d.ts +41 -0
  132. package/dist/flow/controls.js +53 -0
  133. package/dist/flow/flow.css +121 -0
  134. package/dist/flow/handles.d.ts +40 -0
  135. package/dist/flow/handles.js +61 -0
  136. package/dist/flow/index.d.ts +7 -0
  137. package/dist/flow/index.js +7 -0
  138. package/dist/flow/node-card.d.ts +71 -0
  139. package/dist/flow/node-card.js +102 -0
  140. package/dist/flow/signal-edge.d.ts +60 -0
  141. package/dist/flow/signal-edge.js +108 -0
  142. package/dist/flow/use-flow-theme.d.ts +69 -0
  143. package/dist/flow/use-flow-theme.js +109 -0
  144. package/dist/forms/_chassis.d.ts +64 -0
  145. package/dist/forms/_chassis.js +59 -0
  146. package/dist/forms/_glyphs.js +143 -0
  147. package/dist/forms/_listbox.js +55 -0
  148. package/dist/forms/autocomplete.d.ts +61 -0
  149. package/dist/forms/autocomplete.js +88 -0
  150. package/dist/forms/button-group.d.ts +47 -0
  151. package/dist/forms/button-group.js +52 -0
  152. package/dist/forms/checkbox.d.ts +51 -0
  153. package/dist/forms/checkbox.js +98 -0
  154. package/dist/forms/combobox.d.ts +73 -0
  155. package/dist/forms/combobox.js +108 -0
  156. package/dist/forms/env-var-input.d.ts +74 -0
  157. package/dist/forms/env-var-input.js +116 -0
  158. package/dist/forms/field.d.ts +89 -0
  159. package/dist/forms/field.js +102 -0
  160. package/dist/forms/file-upload.d.ts +113 -0
  161. package/dist/forms/file-upload.js +232 -0
  162. package/dist/forms/index.d.ts +26 -0
  163. package/dist/forms/index.js +26 -0
  164. package/dist/forms/input-group.d.ts +31 -0
  165. package/dist/forms/input-group.js +54 -0
  166. package/dist/forms/input.d.ts +33 -0
  167. package/dist/forms/input.js +36 -0
  168. package/dist/forms/multi-select.d.ts +62 -0
  169. package/dist/forms/multi-select.js +107 -0
  170. package/dist/forms/number-field.d.ts +38 -0
  171. package/dist/forms/number-field.js +64 -0
  172. package/dist/forms/otp-field.d.ts +54 -0
  173. package/dist/forms/otp-field.js +59 -0
  174. package/dist/forms/password-input.d.ts +46 -0
  175. package/dist/forms/password-input.js +62 -0
  176. package/dist/forms/radio-group.d.ts +50 -0
  177. package/dist/forms/radio-group.js +64 -0
  178. package/dist/forms/rating.d.ts +69 -0
  179. package/dist/forms/rating.js +103 -0
  180. package/dist/forms/scrub-input.d.ts +81 -0
  181. package/dist/forms/scrub-input.js +249 -0
  182. package/dist/forms/search-input.d.ts +54 -0
  183. package/dist/forms/search-input.js +112 -0
  184. package/dist/forms/select.d.ts +75 -0
  185. package/dist/forms/select.js +91 -0
  186. package/dist/forms/slider.d.ts +44 -0
  187. package/dist/forms/slider.js +65 -0
  188. package/dist/forms/switch.d.ts +36 -0
  189. package/dist/forms/switch.js +71 -0
  190. package/dist/forms/tags-input.d.ts +69 -0
  191. package/dist/forms/tags-input.js +148 -0
  192. package/dist/forms/textarea.d.ts +27 -0
  193. package/dist/forms/textarea.js +37 -0
  194. package/dist/forms/toggle-group.d.ts +41 -0
  195. package/dist/forms/toggle-group.js +56 -0
  196. package/dist/forms/toggle.d.ts +41 -0
  197. package/dist/forms/toggle.js +100 -0
  198. package/dist/index.d.ts +112 -0
  199. package/dist/index.js +104 -0
  200. package/dist/instruments/_ansi.js +116 -0
  201. package/dist/instruments/_glyphs.js +90 -0
  202. package/dist/instruments/_motion.js +56 -0
  203. package/dist/instruments/_rem.js +21 -0
  204. package/dist/instruments/app-window-frame.d.ts +48 -0
  205. package/dist/instruments/app-window-frame.js +76 -0
  206. package/dist/instruments/copy-button.d.ts +41 -0
  207. package/dist/instruments/copy-button.js +112 -0
  208. package/dist/instruments/data-table.d.ts +168 -0
  209. package/dist/instruments/data-table.js +212 -0
  210. package/dist/instruments/group-bar.d.ts +63 -0
  211. package/dist/instruments/group-bar.js +122 -0
  212. package/dist/instruments/index.d.ts +13 -0
  213. package/dist/instruments/index.js +13 -0
  214. package/dist/instruments/log-viewer.d.ts +74 -0
  215. package/dist/instruments/log-viewer.js +215 -0
  216. package/dist/instruments/meter.d.ts +77 -0
  217. package/dist/instruments/meter.js +96 -0
  218. package/dist/instruments/progress.d.ts +45 -0
  219. package/dist/instruments/progress.js +61 -0
  220. package/dist/instruments/seam-grid.d.ts +66 -0
  221. package/dist/instruments/seam-grid.js +78 -0
  222. package/dist/instruments/sparkline.d.ts +39 -0
  223. package/dist/instruments/sparkline.js +85 -0
  224. package/dist/instruments/stat.d.ts +35 -0
  225. package/dist/instruments/stat.js +59 -0
  226. package/dist/instruments/table.d.ts +51 -0
  227. package/dist/instruments/table.js +92 -0
  228. package/dist/instruments/terminal-frame.d.ts +89 -0
  229. package/dist/instruments/terminal-frame.js +256 -0
  230. package/dist/instruments/two-step-button.d.ts +47 -0
  231. package/dist/instruments/two-step-button.js +147 -0
  232. package/dist/instruments/usage-chart.d.ts +55 -0
  233. package/dist/instruments/usage-chart.js +235 -0
  234. package/dist/layout/_collapse.js +46 -0
  235. package/dist/layout/_glyphs.js +45 -0
  236. package/dist/layout/accordion.d.ts +52 -0
  237. package/dist/layout/accordion.js +81 -0
  238. package/dist/layout/breadcrumb.d.ts +35 -0
  239. package/dist/layout/breadcrumb.js +67 -0
  240. package/dist/layout/card.d.ts +51 -0
  241. package/dist/layout/card.js +76 -0
  242. package/dist/layout/carousel.d.ts +96 -0
  243. package/dist/layout/carousel.js +211 -0
  244. package/dist/layout/collapsible.d.ts +74 -0
  245. package/dist/layout/collapsible.js +126 -0
  246. package/dist/layout/container.d.ts +27 -0
  247. package/dist/layout/container.js +40 -0
  248. package/dist/layout/description-list.d.ts +24 -0
  249. package/dist/layout/description-list.js +37 -0
  250. package/dist/layout/grid.d.ts +40 -0
  251. package/dist/layout/grid.js +48 -0
  252. package/dist/layout/index.d.ts +15 -0
  253. package/dist/layout/index.js +15 -0
  254. package/dist/layout/item.d.ts +65 -0
  255. package/dist/layout/item.js +100 -0
  256. package/dist/layout/link.d.ts +48 -0
  257. package/dist/layout/link.js +63 -0
  258. package/dist/layout/pagination.d.ts +54 -0
  259. package/dist/layout/pagination.js +121 -0
  260. package/dist/layout/resizable.d.ts +38 -0
  261. package/dist/layout/resizable.js +68 -0
  262. package/dist/layout/sidebar.d.ts +67 -0
  263. package/dist/layout/sidebar.js +129 -0
  264. package/dist/layout/stack.d.ts +46 -0
  265. package/dist/layout/stack.js +62 -0
  266. package/dist/layout/stepper.d.ts +49 -0
  267. package/dist/layout/stepper.js +81 -0
  268. package/dist/layout/timeline.d.ts +43 -0
  269. package/dist/layout/timeline.js +63 -0
  270. package/dist/lib/aria-class.js +24 -0
  271. package/dist/lib/cn.js +18 -0
  272. package/dist/lib/compose.js +38 -0
  273. package/dist/lib/cva.d.ts +18 -0
  274. package/dist/lib/cva.js +65 -0
  275. package/dist/midi/_notes.d.ts +101 -0
  276. package/dist/midi/_notes.js +183 -0
  277. package/dist/midi/_ruler.d.ts +100 -0
  278. package/dist/midi/_ruler.js +105 -0
  279. package/dist/midi/_time.d.ts +107 -0
  280. package/dist/midi/_time.js +130 -0
  281. package/dist/midi/index.d.ts +9 -0
  282. package/dist/midi/index.js +9 -0
  283. package/dist/midi/musical-time-input.d.ts +48 -0
  284. package/dist/midi/musical-time-input.js +154 -0
  285. package/dist/midi/piano-keyboard.d.ts +50 -0
  286. package/dist/midi/piano-keyboard.js +193 -0
  287. package/dist/midi/spectrum-visualizer.d.ts +65 -0
  288. package/dist/midi/spectrum-visualizer.js +213 -0
  289. package/dist/midi/threshold-rail.d.ts +72 -0
  290. package/dist/midi/threshold-rail.js +214 -0
  291. package/dist/midi/timeline-ruler.d.ts +83 -0
  292. package/dist/midi/timeline-ruler.js +152 -0
  293. package/dist/overlays/_debounce.js +34 -0
  294. package/dist/overlays/_glyphs.js +59 -0
  295. package/dist/overlays/_surface.d.ts +70 -0
  296. package/dist/overlays/_surface.js +70 -0
  297. package/dist/overlays/_wheel.js +42 -0
  298. package/dist/overlays/alert-dialog.d.ts +67 -0
  299. package/dist/overlays/alert-dialog.js +117 -0
  300. package/dist/overlays/command-palette.d.ts +93 -0
  301. package/dist/overlays/command-palette.js +193 -0
  302. package/dist/overlays/context-menu.d.ts +64 -0
  303. package/dist/overlays/context-menu.js +78 -0
  304. package/dist/overlays/dialog.d.ts +72 -0
  305. package/dist/overlays/dialog.js +124 -0
  306. package/dist/overlays/drawer.d.ts +75 -0
  307. package/dist/overlays/drawer.js +151 -0
  308. package/dist/overlays/dropdown-menu.d.ts +79 -0
  309. package/dist/overlays/dropdown-menu.js +156 -0
  310. package/dist/overlays/hover-card.d.ts +58 -0
  311. package/dist/overlays/hover-card.js +91 -0
  312. package/dist/overlays/index.d.ts +15 -0
  313. package/dist/overlays/index.js +15 -0
  314. package/dist/overlays/info-tip.d.ts +41 -0
  315. package/dist/overlays/info-tip.js +45 -0
  316. package/dist/overlays/menubar.d.ts +72 -0
  317. package/dist/overlays/menubar.js +100 -0
  318. package/dist/overlays/popover.d.ts +66 -0
  319. package/dist/overlays/popover.js +114 -0
  320. package/dist/overlays/sheet.d.ts +78 -0
  321. package/dist/overlays/sheet.js +131 -0
  322. package/dist/overlays/toast.d.ts +106 -0
  323. package/dist/overlays/toast.js +146 -0
  324. package/dist/overlays/tooltip.d.ts +57 -0
  325. package/dist/overlays/tooltip.js +95 -0
  326. package/dist/primitives/avatar.d.ts +51 -0
  327. package/dist/primitives/avatar.js +93 -0
  328. package/dist/primitives/button.d.ts +46 -0
  329. package/dist/primitives/button.js +94 -0
  330. package/dist/primitives/chip.d.ts +47 -0
  331. package/dist/primitives/chip.js +152 -0
  332. package/dist/primitives/icon-button.d.ts +41 -0
  333. package/dist/primitives/icon-button.js +59 -0
  334. package/dist/primitives/index.d.ts +10 -0
  335. package/dist/primitives/index.js +10 -0
  336. package/dist/primitives/kbd.d.ts +17 -0
  337. package/dist/primitives/kbd.js +24 -0
  338. package/dist/primitives/separator.d.ts +25 -0
  339. package/dist/primitives/separator.js +30 -0
  340. package/dist/primitives/skeleton.d.ts +20 -0
  341. package/dist/primitives/skeleton.js +27 -0
  342. package/dist/primitives/spinner.d.ts +26 -0
  343. package/dist/primitives/spinner.js +31 -0
  344. package/dist/primitives/status-dot.d.ts +44 -0
  345. package/dist/primitives/status-dot.js +50 -0
  346. package/dist/styles.css +19 -0
  347. package/dist/system/density.d.ts +33 -0
  348. package/dist/system/density.js +49 -0
  349. package/dist/system/index.d.ts +8 -0
  350. package/dist/system/index.js +7 -0
  351. package/dist/system/portal.d.ts +51 -0
  352. package/dist/system/portal.js +122 -0
  353. package/dist/system/prepaint.d.ts +38 -0
  354. package/dist/system/prepaint.js +37 -0
  355. package/dist/system/theme-provider.d.ts +72 -0
  356. package/dist/system/theme-provider.js +252 -0
  357. package/dist/system/use-density.d.ts +33 -0
  358. package/dist/system/use-density.js +84 -0
  359. package/dist/system/use-isomorphic-layout-effect.js +15 -0
  360. package/dist/system/use-theme.d.ts +19 -0
  361. package/dist/system/use-theme.js +25 -0
  362. package/dist/theming/_presets.d.ts +11 -0
  363. package/dist/theming/_presets.js +487 -0
  364. package/dist/theming/contrast.d.ts +110 -0
  365. package/dist/theming/contrast.js +167 -0
  366. package/dist/theming/create-theme.d.ts +165 -0
  367. package/dist/theming/create-theme.js +442 -0
  368. package/dist/theming/index.d.ts +5 -0
  369. package/dist/theming/index.js +5 -0
  370. package/dist/theming/serialize.d.ts +145 -0
  371. package/dist/theming/serialize.js +165 -0
  372. package/package.json +216 -0
@@ -0,0 +1,62 @@
1
+ import { FormControlSize } from "./_chassis.js";
2
+ import { ComboboxOption } from "./combobox.js";
3
+ import * as React from "react";
4
+ //#region src/forms/multi-select.d.ts
5
+ interface MultiSelectProps {
6
+ /** The rows, in display order. Base UI filters them against what is typed. */
7
+ items: readonly ComboboxOption[];
8
+ /** Selected values. Use with `onValueChange` for a controlled field. */
9
+ value?: readonly string[];
10
+ /** Initially selected values for an uncontrolled field. */
11
+ defaultValue?: readonly string[];
12
+ /** Called with the full selection after every add or remove. */
13
+ onValueChange?: (value: string[]) => void;
14
+ /** Shown while nothing is selected — suppressed once chips fill the field. */
15
+ placeholder?: string;
16
+ /** Shown in place of the list when the query matches nothing. */
17
+ emptyMessage?: React.ReactNode;
18
+ /** Rung of the control ladder. Defaults to `"md"`. */
19
+ size?: FormControlSize;
20
+ /** Prevent opening and grey the field out. */
21
+ disabled?: boolean;
22
+ /** Require at least one value before the owning form submits. */
23
+ required?: boolean;
24
+ /** Name for the hidden input, when the field is part of a form. */
25
+ name?: string;
26
+ /** Id forwarded to the text input. */
27
+ id?: string;
28
+ /** Accessible name for the input, when no {@link FieldLabel} names it. */
29
+ "aria-label"?: string;
30
+ /** Id of the element naming the input. */
31
+ "aria-labelledby"?: string;
32
+ /**
33
+ * Accessible name for a chip's remove button, given the row's label. Defaults
34
+ * to ``(label) => `Remove ${label}` ``.
35
+ */
36
+ removeLabel?: (label: string) => string;
37
+ /** Extra classes for the field. */
38
+ className?: string;
39
+ /** Extra classes for the popup surface. */
40
+ popupClassName?: string;
41
+ /** Distance in px between the field and the popup. Defaults to `4`. */
42
+ sideOffset?: number;
43
+ }
44
+ /**
45
+ * Several values out of a known set, each shown as a removable chip.
46
+ *
47
+ * The chips live *inside* the field rather than under it, which is what makes
48
+ * the control honest about its own size: a selection of nine trusses is visibly
49
+ * nine trusses tall, and nothing is hidden behind a "+6 more" the user has to
50
+ * open something to read. That is also why the field takes `min-h-control-*`
51
+ * instead of a fixed height.
52
+ *
53
+ * Backspace in an empty input removes the last chip and the chips themselves are
54
+ * arrow-key navigable — both come from Base UI's `Combobox.Chips`, and both are
55
+ * the parts hand-rolled multi-selects forget.
56
+ *
57
+ * @example
58
+ * <MultiSelect aria-label="Trusses" items={trusses} value={picked} onValueChange={setPicked} />
59
+ */
60
+ declare const MultiSelect: React.ForwardRefExoticComponent<MultiSelectProps & React.RefAttributes<HTMLInputElement>>;
61
+ //#endregion
62
+ export { MultiSelect, MultiSelectProps };
@@ -0,0 +1,107 @@
1
+ "use client";
2
+ import { cn } from "../lib/cn.js";
3
+ import { bareControlClasses, controlGroupFocusClasses, controlSurface } from "./_chassis.js";
4
+ import { useCuePortalProps } from "../system/portal.js";
5
+ import { CrossGlyph, TickGlyph } from "./_glyphs.js";
6
+ import { chipFieldClasses, chipRemoveClasses, listboxEmptyClasses, listboxIndicatorClasses, listboxItemClasses, listboxListClasses, listboxPopupClasses, listboxPositionerClasses, valueChipClasses } from "./_listbox.js";
7
+ import * as React from "react";
8
+ import { jsx, jsxs } from "react/jsx-runtime";
9
+ import { Combobox } from "@base-ui/react/combobox";
10
+ //#region src/forms/multi-select.tsx
11
+ /** Horizontal padding and type size per rung; the height comes from the chips. */
12
+ const FIELD_SIZES = {
13
+ sm: "min-h-control-sm px-(--cue-space-2) text-(length:--cue-text-label)",
14
+ md: "min-h-control-md px-(--cue-space-3) text-(length:--cue-text-ui)",
15
+ lg: "min-h-control-lg px-(--cue-space-4) text-(length:--cue-text-body)"
16
+ };
17
+ /**
18
+ * Several values out of a known set, each shown as a removable chip.
19
+ *
20
+ * The chips live *inside* the field rather than under it, which is what makes
21
+ * the control honest about its own size: a selection of nine trusses is visibly
22
+ * nine trusses tall, and nothing is hidden behind a "+6 more" the user has to
23
+ * open something to read. That is also why the field takes `min-h-control-*`
24
+ * instead of a fixed height.
25
+ *
26
+ * Backspace in an empty input removes the last chip and the chips themselves are
27
+ * arrow-key navigable — both come from Base UI's `Combobox.Chips`, and both are
28
+ * the parts hand-rolled multi-selects forget.
29
+ *
30
+ * @example
31
+ * <MultiSelect aria-label="Trusses" items={trusses} value={picked} onValueChange={setPicked} />
32
+ */
33
+ const MultiSelect = React.forwardRef(function MultiSelect({ items, value, defaultValue, onValueChange, placeholder, emptyMessage = "No matches", size = "md", disabled, required, name, id, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, removeLabel = (label) => `Remove ${label}`, className, popupClassName, sideOffset = 4 }, ref) {
34
+ const portalProps = useCuePortalProps();
35
+ const resolve = React.useCallback((keys) => keys === void 0 ? void 0 : keys.map((key) => items.find((item) => item.value === key)).filter((item) => item !== void 0), [items]);
36
+ const handleValueChange = React.useCallback((next) => {
37
+ onValueChange?.(next.map((item) => item.value));
38
+ }, [onValueChange]);
39
+ return /* @__PURE__ */ jsxs(Combobox.Root, {
40
+ multiple: true,
41
+ items,
42
+ value: resolve(value),
43
+ defaultValue: resolve(defaultValue),
44
+ onValueChange: onValueChange === void 0 ? void 0 : handleValueChange,
45
+ disabled,
46
+ required,
47
+ name,
48
+ children: [/* @__PURE__ */ jsx(Combobox.InputGroup, {
49
+ "data-slot": "multi-select-group",
50
+ className: cn(controlSurface, FIELD_SIZES[size], controlGroupFocusClasses, className),
51
+ children: /* @__PURE__ */ jsx(Combobox.Chips, {
52
+ className: chipFieldClasses,
53
+ children: /* @__PURE__ */ jsx(Combobox.Value, { children: (selected) => /* @__PURE__ */ jsxs(React.Fragment, { children: [selected.map((item) => /* @__PURE__ */ jsxs(Combobox.Chip, {
54
+ "data-slot": "multi-select-chip",
55
+ className: valueChipClasses,
56
+ children: [/* @__PURE__ */ jsx("span", {
57
+ className: "truncate",
58
+ children: item.label
59
+ }), /* @__PURE__ */ jsx(Combobox.ChipRemove, {
60
+ "aria-label": removeLabel(item.label),
61
+ className: chipRemoveClasses,
62
+ children: /* @__PURE__ */ jsx(CrossGlyph, { className: "size-icon-sm" })
63
+ })]
64
+ }, item.value)), /* @__PURE__ */ jsx(Combobox.Input, {
65
+ ref,
66
+ id,
67
+ "data-slot": "multi-select-input",
68
+ placeholder: selected.length > 0 ? "" : placeholder,
69
+ "aria-label": ariaLabel,
70
+ "aria-labelledby": ariaLabelledBy,
71
+ className: cn(bareControlClasses, "h-control-sm w-auto min-w-[6ch]")
72
+ })] }) })
73
+ })
74
+ }), /* @__PURE__ */ jsx(Combobox.Portal, {
75
+ ...portalProps,
76
+ children: /* @__PURE__ */ jsx(Combobox.Positioner, {
77
+ className: listboxPositionerClasses,
78
+ sideOffset,
79
+ children: /* @__PURE__ */ jsxs(Combobox.Popup, {
80
+ "data-slot": "multi-select-popup",
81
+ className: cn(listboxPopupClasses, popupClassName),
82
+ children: [/* @__PURE__ */ jsx(Combobox.Empty, {
83
+ className: listboxEmptyClasses,
84
+ children: emptyMessage
85
+ }), /* @__PURE__ */ jsx(Combobox.List, {
86
+ className: listboxListClasses,
87
+ children: (item) => /* @__PURE__ */ jsxs(Combobox.Item, {
88
+ value: item,
89
+ disabled: item.disabled,
90
+ "data-slot": "multi-select-item",
91
+ className: listboxItemClasses,
92
+ children: [/* @__PURE__ */ jsx("span", {
93
+ className: listboxIndicatorClasses,
94
+ children: /* @__PURE__ */ jsx(Combobox.ItemIndicator, { children: /* @__PURE__ */ jsx(TickGlyph, { className: "size-icon-sm" }) })
95
+ }), /* @__PURE__ */ jsx("span", {
96
+ className: "truncate",
97
+ children: item.label
98
+ })]
99
+ }, item.value)
100
+ })]
101
+ })
102
+ })
103
+ })]
104
+ });
105
+ });
106
+ //#endregion
107
+ export { MultiSelect };
@@ -0,0 +1,38 @@
1
+ import * as React from "react";
2
+ import { NumberField } from "@base-ui/react/number-field";
3
+ //#region src/forms/number-field.d.ts
4
+ interface NumberFieldProps extends Omit<NumberField.Root.Props, "className"> {
5
+ /** Extra classes, merged over the group chassis. */
6
+ className?: string;
7
+ /** Rung of the control ladder. Defaults to `"md"`. */
8
+ size?: "sm" | "md";
9
+ /** Accessible name for the decrement button. Defaults to `"Decrease"`. */
10
+ decrementLabel?: string;
11
+ /** Accessible name for the increment button. Defaults to `"Increase"`. */
12
+ incrementLabel?: string;
13
+ /** Placeholder shown while the field is empty. */
14
+ placeholder?: string;
15
+ /** Accessible name for the text control, when no {@link FieldLabel} names it. */
16
+ "aria-label"?: string;
17
+ }
18
+ /**
19
+ * A numeric control with explicit − / + affordances and no native spinners.
20
+ *
21
+ * Native `<input type="number">` spinners are unusable at console density — a
22
+ * pair of 4px arrows that only appear on hover — so this is a text input with
23
+ * `inputMode="numeric"` flanked by real buttons, which is also what makes it
24
+ * touch-usable. Arrow keys step, Shift steps by `largeStep`, Alt by `smallStep`,
25
+ * and values typed out of range are clamped to `min`/`max` on blur.
26
+ *
27
+ * The group owns the rim; the input and both buttons render bare inside it, so
28
+ * the whole cluster reads as one field and focus feedback moves to
29
+ * `focus-within`.
30
+ *
31
+ * @example
32
+ * <NumberField aria-label="Fade time" defaultValue={3} min={0} max={600} step={0.5} />
33
+ * @example
34
+ * <Field><FieldLabel>Universe</FieldLabel><NumberField min={1} max={512} /></Field>
35
+ */
36
+ declare const NumberField$1: React.ForwardRefExoticComponent<Omit<NumberFieldProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
37
+ //#endregion
38
+ export { NumberField$1 as NumberField, NumberFieldProps };
@@ -0,0 +1,64 @@
1
+ "use client";
2
+ import { cn } from "../lib/cn.js";
3
+ import { bareControlClasses, controlGroupFocusClasses, controlSurface } from "./_chassis.js";
4
+ import * as React from "react";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ import { NumberField } from "@base-ui/react/number-field";
7
+ //#region src/forms/number-field.tsx
8
+ /** The − and + affordances: square, borderless, and quiet until hovered. */
9
+ const stepperClasses = "flex shrink-0 items-center justify-center border-0 bg-transparent p-0 font-mono text-fg-muted leading-none select-none outline-none transition-colors hover:bg-surface-2 hover:text-fg focus-visible:outline-2 focus-visible:outline-solid focus-visible:-outline-offset-1 focus-visible:outline-accent data-[disabled]:pointer-events-none data-[disabled]:opacity-40";
10
+ /**
11
+ * A numeric control with explicit − / + affordances and no native spinners.
12
+ *
13
+ * Native `<input type="number">` spinners are unusable at console density — a
14
+ * pair of 4px arrows that only appear on hover — so this is a text input with
15
+ * `inputMode="numeric"` flanked by real buttons, which is also what makes it
16
+ * touch-usable. Arrow keys step, Shift steps by `largeStep`, Alt by `smallStep`,
17
+ * and values typed out of range are clamped to `min`/`max` on blur.
18
+ *
19
+ * The group owns the rim; the input and both buttons render bare inside it, so
20
+ * the whole cluster reads as one field and focus feedback moves to
21
+ * `focus-within`.
22
+ *
23
+ * @example
24
+ * <NumberField aria-label="Fade time" defaultValue={3} min={0} max={600} step={0.5} />
25
+ * @example
26
+ * <Field><FieldLabel>Universe</FieldLabel><NumberField min={1} max={512} /></Field>
27
+ */
28
+ const NumberField$1 = React.forwardRef(function NumberField$2({ className, size = "md", decrementLabel = "Decrease", incrementLabel = "Increase", placeholder, "aria-label": ariaLabel, ...elementProps }, ref) {
29
+ const rung = size === "sm" ? "sm" : "md";
30
+ return /* @__PURE__ */ jsx(NumberField.Root, {
31
+ ref,
32
+ "data-slot": "number-field",
33
+ ...elementProps,
34
+ children: /* @__PURE__ */ jsxs(NumberField.Group, {
35
+ "data-slot": "number-field-group",
36
+ className: cn(controlSurface, "flex items-stretch overflow-hidden", rung === "sm" ? "h-control-sm text-(length:--cue-text-label)" : "h-control-md text-(length:--cue-text-ui)", controlGroupFocusClasses, className),
37
+ children: [
38
+ /* @__PURE__ */ jsx(NumberField.Decrement, {
39
+ "aria-label": decrementLabel,
40
+ className: cn(stepperClasses, rung === "sm" ? "w-control-sm" : "w-control-md"),
41
+ children: /* @__PURE__ */ jsx("span", {
42
+ "aria-hidden": "true",
43
+ children: "−"
44
+ })
45
+ }),
46
+ /* @__PURE__ */ jsx(NumberField.Input, {
47
+ "aria-label": ariaLabel,
48
+ placeholder,
49
+ className: cn(bareControlClasses, "w-full px-(--cue-space-2) text-center tabular-nums", "[appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none")
50
+ }),
51
+ /* @__PURE__ */ jsx(NumberField.Increment, {
52
+ "aria-label": incrementLabel,
53
+ className: cn(stepperClasses, rung === "sm" ? "w-control-sm" : "w-control-md"),
54
+ children: /* @__PURE__ */ jsx("span", {
55
+ "aria-hidden": "true",
56
+ children: "+"
57
+ })
58
+ })
59
+ ]
60
+ })
61
+ });
62
+ });
63
+ //#endregion
64
+ export { NumberField$1 as NumberField };
@@ -0,0 +1,54 @@
1
+ import { FormControlSize } from "./_chassis.js";
2
+ import * as React from "react";
3
+ import { OTPField } from "@base-ui/react/otp-field";
4
+ //#region src/forms/otp-field.d.ts
5
+ interface OTPFieldProps extends Omit<OTPField.Root.Props, "className" | "children" | "length"> {
6
+ /** How many characters the code has. Defaults to `6`. */
7
+ length?: number;
8
+ /** Rung of the control ladder. Defaults to `"md"`. */
9
+ size?: FormControlSize;
10
+ /**
11
+ * Insert a separator after every `groupSize` slots — `groupSize={3}` renders a
12
+ * six-character code as `123 456`, which is how people read one off a screen.
13
+ */
14
+ groupSize?: number;
15
+ /** What sits between groups. Defaults to `"–"`. Always `aria-hidden`. */
16
+ separator?: React.ReactNode;
17
+ /**
18
+ * Accessible name for the field. Names the group *and*, through a visually
19
+ * hidden `<label>`, the first slot — the ARIA pattern for a code field. Leave
20
+ * it off inside a {@link Field}, which supplies a real label.
21
+ */
22
+ "aria-label"?: string;
23
+ /** Id of the first slot. Generated when omitted, so the hidden label can target it. */
24
+ id?: string;
25
+ /**
26
+ * Accessible name for slot `index` (1-based here, since slot 0 is named by the
27
+ * field label) of `length`. Defaults to
28
+ * ``(index, length) => `Character ${index + 1} of ${length}` ``.
29
+ */
30
+ slotLabel?: (index: number, length: number) => string;
31
+ /** Extra classes for the row. */
32
+ className?: string;
33
+ /** Extra classes for every slot. */
34
+ slotClassName?: string;
35
+ }
36
+ /**
37
+ * A one-time code, one character per box.
38
+ *
39
+ * The boxes are not decoration: they tell the user how long the code is before
40
+ * they start typing, which is the whole reason this pattern beats a plain text
41
+ * input. Paste, arrow keys, Backspace across slot boundaries and the
42
+ * `one-time-code` autofill hint all come from Base UI.
43
+ *
44
+ * Slots ride the recessed chassis — sunken fill, hairline rim — so a code field
45
+ * reads as "type here" like every other input in the system, just squared off.
46
+ *
47
+ * @example
48
+ * <OTPField aria-label="Verification code" onValueComplete={submit} />
49
+ * @example
50
+ * <OTPField aria-label="Recovery code" length={8} groupSize={4} validationType="alphanumeric" />
51
+ */
52
+ declare const OTPField$1: React.ForwardRefExoticComponent<Omit<OTPFieldProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
53
+ //#endregion
54
+ export { OTPField$1 as OTPField, OTPFieldProps };
@@ -0,0 +1,59 @@
1
+ "use client";
2
+ import { cn } from "../lib/cn.js";
3
+ import { controlSurface } from "./_chassis.js";
4
+ import * as React from "react";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ import { OTPField } from "@base-ui/react/otp-field";
7
+ //#region src/forms/otp-field.tsx
8
+ /** One square slot per rung of the control ladder. */
9
+ const SLOT_SIZES = {
10
+ sm: "size-control-sm text-(length:--cue-text-ui)",
11
+ md: "size-control-md text-(length:--cue-text-body)",
12
+ lg: "size-control-lg text-(length:--cue-text-emphasis)"
13
+ };
14
+ /**
15
+ * A one-time code, one character per box.
16
+ *
17
+ * The boxes are not decoration: they tell the user how long the code is before
18
+ * they start typing, which is the whole reason this pattern beats a plain text
19
+ * input. Paste, arrow keys, Backspace across slot boundaries and the
20
+ * `one-time-code` autofill hint all come from Base UI.
21
+ *
22
+ * Slots ride the recessed chassis — sunken fill, hairline rim — so a code field
23
+ * reads as "type here" like every other input in the system, just squared off.
24
+ *
25
+ * @example
26
+ * <OTPField aria-label="Verification code" onValueComplete={submit} />
27
+ * @example
28
+ * <OTPField aria-label="Recovery code" length={8} groupSize={4} validationType="alphanumeric" />
29
+ */
30
+ const OTPField$1 = React.forwardRef(function OTPField$2({ length = 6, size = "md", groupSize, separator = "–", "aria-label": ariaLabel, id, slotLabel = (index, total) => `Character ${index + 1} of ${total}`, className, slotClassName, ...elementProps }, ref) {
31
+ const generatedId = React.useId();
32
+ const fieldId = id ?? generatedId;
33
+ const slotClasses = cn(controlSurface, "w-auto p-0 text-center tabular-nums", SLOT_SIZES[size], slotClassName);
34
+ return /* @__PURE__ */ jsxs(OTPField.Root, {
35
+ ref,
36
+ id: fieldId,
37
+ length,
38
+ "aria-label": ariaLabel,
39
+ "data-slot": "otp-field",
40
+ className: cn("flex items-center gap-(--cue-space-2)", className),
41
+ ...elementProps,
42
+ children: [ariaLabel === void 0 ? null : /* @__PURE__ */ jsx("label", {
43
+ htmlFor: fieldId,
44
+ className: "sr-only",
45
+ children: ariaLabel
46
+ }), Array.from({ length }, (_, index) => /* @__PURE__ */ jsxs(React.Fragment, { children: [groupSize !== void 0 && index > 0 && index % groupSize === 0 ? /* @__PURE__ */ jsx("span", {
47
+ "data-slot": "otp-field-separator",
48
+ "aria-hidden": "true",
49
+ className: "px-(--cue-space-1) font-mono text-fg-subtle select-none",
50
+ children: separator
51
+ }) : null, /* @__PURE__ */ jsx(OTPField.Input, {
52
+ "data-slot": "otp-field-slot",
53
+ "aria-label": index === 0 ? void 0 : slotLabel(index, length),
54
+ className: slotClasses
55
+ })] }, index))]
56
+ });
57
+ });
58
+ //#endregion
59
+ export { OTPField$1 as OTPField };
@@ -0,0 +1,46 @@
1
+ import { FormControlSize } from "./_chassis.js";
2
+ import { InputProps } from "./input.js";
3
+ import * as React from "react";
4
+ //#region src/forms/password-input.d.ts
5
+ interface PasswordInputProps extends Omit<InputProps, "type" | "size"> {
6
+ /** Reveal the value. Use with `onRevealedChange` for a controlled toggle. */
7
+ revealed?: boolean;
8
+ /** Initially revealed, for an uncontrolled toggle. Defaults to `false`. */
9
+ defaultRevealed?: boolean;
10
+ /** Called with the new reveal state. */
11
+ onRevealedChange?: (revealed: boolean) => void;
12
+ /**
13
+ * Offer the reveal affordance at all. Defaults to `true`. Switch it off for a
14
+ * value the product must never re-display — a stored secret the user is
15
+ * replacing rather than reading.
16
+ */
17
+ showReveal?: boolean;
18
+ /** Accessible name while masked. Defaults to `"Show password"`. */
19
+ revealLabel?: string;
20
+ /** Accessible name while revealed. Defaults to `"Hide password"`. */
21
+ hideLabel?: string;
22
+ /** Rung of the control ladder. Defaults to `"md"`. */
23
+ size?: FormControlSize;
24
+ /** Extra classes for the group that wraps the input and the reveal button. */
25
+ className?: string;
26
+ }
27
+ /**
28
+ * A masked text field with a reveal control.
29
+ *
30
+ * The reveal is a **toggle button carrying `aria-pressed`**, not a checkbox and
31
+ * not a bare icon: a screen-reader user needs to know both what it does and
32
+ * which way it currently is, and `aria-pressed` is the one attribute that says
33
+ * both. The label swaps with the state for the same reason.
34
+ *
35
+ * Revealing switches `type` between `password` and `text` rather than painting
36
+ * over the characters, so the browser's own autofill and password managers keep
37
+ * working.
38
+ *
39
+ * @example
40
+ * <PasswordInput aria-label="Service key" value={key} onValueChange={setKey} />
41
+ * @example
42
+ * <Field><FieldLabel>Token</FieldLabel><PasswordInput showReveal={false} /></Field>
43
+ */
44
+ declare const PasswordInput: React.ForwardRefExoticComponent<Omit<PasswordInputProps, "ref"> & React.RefAttributes<HTMLInputElement>>;
45
+ //#endregion
46
+ export { PasswordInput, PasswordInputProps };
@@ -0,0 +1,62 @@
1
+ "use client";
2
+ import { cn } from "../lib/cn.js";
3
+ import { InputGroup } from "./input-group.js";
4
+ import { Input } from "./input.js";
5
+ import { EyeGlyph, EyeOffGlyph } from "./_glyphs.js";
6
+ import * as React from "react";
7
+ import { jsx } from "react/jsx-runtime";
8
+ //#region src/forms/password-input.tsx
9
+ /**
10
+ * A masked text field with a reveal control.
11
+ *
12
+ * The reveal is a **toggle button carrying `aria-pressed`**, not a checkbox and
13
+ * not a bare icon: a screen-reader user needs to know both what it does and
14
+ * which way it currently is, and `aria-pressed` is the one attribute that says
15
+ * both. The label swaps with the state for the same reason.
16
+ *
17
+ * Revealing switches `type` between `password` and `text` rather than painting
18
+ * over the characters, so the browser's own autofill and password managers keep
19
+ * working.
20
+ *
21
+ * @example
22
+ * <PasswordInput aria-label="Service key" value={key} onValueChange={setKey} />
23
+ * @example
24
+ * <Field><FieldLabel>Token</FieldLabel><PasswordInput showReveal={false} /></Field>
25
+ */
26
+ const PasswordInput = React.forwardRef(function PasswordInput({ className, revealed: revealedProp, defaultRevealed = false, onRevealedChange, showReveal = true, revealLabel = "Show password", hideLabel = "Hide password", size, disabled, ...elementProps }, ref) {
27
+ const [uncontrolled, setUncontrolled] = React.useState(defaultRevealed);
28
+ const revealed = revealedProp ?? uncontrolled;
29
+ const toggle = React.useCallback(() => {
30
+ const next = !revealed;
31
+ if (revealedProp === void 0) setUncontrolled(next);
32
+ onRevealedChange?.(next);
33
+ }, [
34
+ onRevealedChange,
35
+ revealed,
36
+ revealedProp
37
+ ]);
38
+ return /* @__PURE__ */ jsx(InputGroup, {
39
+ size,
40
+ className,
41
+ trailing: showReveal ? /* @__PURE__ */ jsx("button", {
42
+ type: "button",
43
+ "aria-pressed": revealed,
44
+ "aria-label": revealed ? hideLabel : revealLabel,
45
+ disabled,
46
+ onClick: toggle,
47
+ className: "flex shrink-0 cursor-pointer items-center justify-center rounded-(--radius-control) text-fg-subtle outline-none transition-colors hover:text-fg focus-visible:outline-2 focus-visible:outline-solid focus-visible:outline-offset-1 focus-visible:outline-accent disabled:pointer-events-none disabled:opacity-40 aria-pressed:text-fg",
48
+ children: /* @__PURE__ */ jsx(revealed ? EyeOffGlyph : EyeGlyph, { className: "size-icon-md" })
49
+ }) : void 0,
50
+ children: /* @__PURE__ */ jsx(Input, {
51
+ ref,
52
+ type: revealed ? "text" : "password",
53
+ "data-slot": "password-input",
54
+ spellCheck: false,
55
+ disabled,
56
+ className: cn("[&::-ms-reveal]:hidden"),
57
+ ...elementProps
58
+ })
59
+ });
60
+ });
61
+ //#endregion
62
+ export { PasswordInput };
@@ -0,0 +1,50 @@
1
+ import * as React from "react";
2
+ import { Radio } from "@base-ui/react/radio";
3
+ import { RadioGroup } from "@base-ui/react/radio-group";
4
+ //#region src/forms/radio-group.d.ts
5
+ interface RadioGroupProps extends Omit<RadioGroup.Props, "className"> {
6
+ /** Extra classes, merged over the stack defaults. */
7
+ className?: string;
8
+ /** Lay the options out in a column (default) or a row. */
9
+ orientation?: "vertical" | "horizontal";
10
+ }
11
+ /**
12
+ * One-of-many selection: a roving-tabindex group of {@link Radio}s sharing a
13
+ * single value.
14
+ *
15
+ * Arrow keys move *and* select, per the WAI-ARIA radio group pattern that Base
16
+ * UI implements — so the whole group is one tab stop, which is what keeps a
17
+ * dense settings panel navigable.
18
+ *
19
+ * @example
20
+ * <RadioGroup aria-label="Blend mode" value={mode} onValueChange={setMode}>
21
+ * <Radio value="htp" label="HTP" />
22
+ * <Radio value="ltp" label="LTP" />
23
+ * </RadioGroup>
24
+ */
25
+ declare const RadioGroup$1: React.ForwardRefExoticComponent<Omit<RadioGroupProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
26
+ interface RadioProps extends Omit<Radio.Root.Props, "className"> {
27
+ /** Extra classes, merged over the dot defaults. */
28
+ className?: string;
29
+ /**
30
+ * Inline label rendered beside the dot and wrapped with it in a `<label>`, so
31
+ * the text is both the accessible name and part of the hit target.
32
+ */
33
+ label?: React.ReactNode;
34
+ /** Rung of the density icon ladder for the dot. Defaults to `"md"`. */
35
+ size?: "sm" | "md";
36
+ }
37
+ /**
38
+ * One option inside a {@link RadioGroup}.
39
+ *
40
+ * Round, to say "exactly one" the way a square {@link Checkbox} says "any
41
+ * number". Checked draws an accent rim with an accent core rather than a solid
42
+ * fill, so the selected option stays legible against the sunken field colour on
43
+ * every theme.
44
+ *
45
+ * @example
46
+ * <Radio value="htp" label="Highest takes precedence" />
47
+ */
48
+ declare const Radio$1: React.ForwardRefExoticComponent<Omit<RadioProps, "ref"> & React.RefAttributes<HTMLButtonElement>>;
49
+ //#endregion
50
+ export { Radio$1 as Radio, RadioGroup$1 as RadioGroup, RadioGroupProps, RadioProps };
@@ -0,0 +1,64 @@
1
+ "use client";
2
+ import { cn } from "../lib/cn.js";
3
+ import * as React from "react";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ import { Radio } from "@base-ui/react/radio";
6
+ import { RadioGroup } from "@base-ui/react/radio-group";
7
+ //#region src/forms/radio-group.tsx
8
+ /**
9
+ * One-of-many selection: a roving-tabindex group of {@link Radio}s sharing a
10
+ * single value.
11
+ *
12
+ * Arrow keys move *and* select, per the WAI-ARIA radio group pattern that Base
13
+ * UI implements — so the whole group is one tab stop, which is what keeps a
14
+ * dense settings panel navigable.
15
+ *
16
+ * @example
17
+ * <RadioGroup aria-label="Blend mode" value={mode} onValueChange={setMode}>
18
+ * <Radio value="htp" label="HTP" />
19
+ * <Radio value="ltp" label="LTP" />
20
+ * </RadioGroup>
21
+ */
22
+ const RadioGroup$1 = React.forwardRef(function RadioGroup$2({ className, orientation = "vertical", ...elementProps }, ref) {
23
+ return /* @__PURE__ */ jsx(RadioGroup, {
24
+ ref,
25
+ "data-slot": "radio-group",
26
+ "data-orientation": orientation,
27
+ className: cn("flex", orientation === "horizontal" ? "flex-row flex-wrap items-center gap-(--cue-space-5)" : "flex-col gap-(--cue-space-2)", className),
28
+ ...elementProps
29
+ });
30
+ });
31
+ /**
32
+ * One option inside a {@link RadioGroup}.
33
+ *
34
+ * Round, to say "exactly one" the way a square {@link Checkbox} says "any
35
+ * number". Checked draws an accent rim with an accent core rather than a solid
36
+ * fill, so the selected option stays legible against the sunken field colour on
37
+ * every theme.
38
+ *
39
+ * @example
40
+ * <Radio value="htp" label="Highest takes precedence" />
41
+ */
42
+ const Radio$1 = React.forwardRef(function Radio$2({ className, label, size = "md", ...elementProps }, ref) {
43
+ const labelId = React.useId();
44
+ const hasLabel = label !== void 0;
45
+ const dot = /* @__PURE__ */ jsx(Radio.Root, {
46
+ ref,
47
+ "data-slot": "radio",
48
+ "aria-labelledby": hasLabel ? labelId : void 0,
49
+ className: cn("flex shrink-0 items-center justify-center rounded-full border border-border bg-sunken text-accent outline-none transition-colors", size === "sm" ? "size-icon-sm" : "size-icon-md", "hover:border-border-strong", "data-[checked]:border-accent", "focus-visible:outline-2 focus-visible:outline-solid focus-visible:outline-offset-1 focus-visible:outline-accent", "data-[disabled]:pointer-events-none data-[disabled]:opacity-40", "data-[invalid]:border-danger", className),
50
+ ...elementProps,
51
+ children: /* @__PURE__ */ jsx(Radio.Indicator, { className: "block size-1/2 rounded-full bg-accent data-[unchecked]:hidden" })
52
+ });
53
+ if (!hasLabel) return dot;
54
+ return /* @__PURE__ */ jsxs("label", {
55
+ "data-slot": "radio-label",
56
+ className: "inline-flex cursor-pointer items-center gap-(--cue-space-3) font-mono text-(length:--cue-text-ui) text-fg-muted select-none has-[[data-disabled]]:cursor-default has-[[data-disabled]]:opacity-40",
57
+ children: [dot, /* @__PURE__ */ jsx("span", {
58
+ id: labelId,
59
+ children: label
60
+ })]
61
+ });
62
+ });
63
+ //#endregion
64
+ export { Radio$1 as Radio, RadioGroup$1 as RadioGroup };