@vaam-apps/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 (285) hide show
  1. package/CHANGELOG.md +104 -0
  2. package/LICENSE +21 -0
  3. package/README.md +286 -0
  4. package/dist/components/data/code.d.ts +37 -0
  5. package/dist/components/data/code.d.ts.map +1 -0
  6. package/dist/components/data/code.js +37 -0
  7. package/dist/components/data/code.js.map +1 -0
  8. package/dist/components/data/copy-button.d.ts +39 -0
  9. package/dist/components/data/copy-button.d.ts.map +1 -0
  10. package/dist/components/data/copy-button.js +50 -0
  11. package/dist/components/data/copy-button.js.map +1 -0
  12. package/dist/components/data/detail-row.d.ts +69 -0
  13. package/dist/components/data/detail-row.d.ts.map +1 -0
  14. package/dist/components/data/detail-row.js +27 -0
  15. package/dist/components/data/detail-row.js.map +1 -0
  16. package/dist/components/data/id-display.d.ts +33 -0
  17. package/dist/components/data/id-display.d.ts.map +1 -0
  18. package/dist/components/data/id-display.js +25 -0
  19. package/dist/components/data/id-display.js.map +1 -0
  20. package/dist/components/data/masked-value.d.ts +47 -0
  21. package/dist/components/data/masked-value.d.ts.map +1 -0
  22. package/dist/components/data/masked-value.js +46 -0
  23. package/dist/components/data/masked-value.js.map +1 -0
  24. package/dist/components/data/money.d.ts +28 -0
  25. package/dist/components/data/money.d.ts.map +1 -0
  26. package/dist/components/data/money.js +22 -0
  27. package/dist/components/data/money.js.map +1 -0
  28. package/dist/components/data/phone-display.d.ts +45 -0
  29. package/dist/components/data/phone-display.d.ts.map +1 -0
  30. package/dist/components/data/phone-display.js +23 -0
  31. package/dist/components/data/phone-display.js.map +1 -0
  32. package/dist/components/data/stat-tile.d.ts +33 -0
  33. package/dist/components/data/stat-tile.d.ts.map +1 -0
  34. package/dist/components/data/stat-tile.js +18 -0
  35. package/dist/components/data/stat-tile.js.map +1 -0
  36. package/dist/components/data/timestamp-display.d.ts +14 -0
  37. package/dist/components/data/timestamp-display.d.ts.map +1 -0
  38. package/dist/components/data/timestamp-display.js +77 -0
  39. package/dist/components/data/timestamp-display.js.map +1 -0
  40. package/dist/components/patterns/inline-banner.d.ts +22 -0
  41. package/dist/components/patterns/inline-banner.d.ts.map +1 -0
  42. package/dist/components/patterns/inline-banner.js +11 -0
  43. package/dist/components/patterns/inline-banner.js.map +1 -0
  44. package/dist/components/patterns/inline-empty-state.d.ts +20 -0
  45. package/dist/components/patterns/inline-empty-state.d.ts.map +1 -0
  46. package/dist/components/patterns/inline-empty-state.js +11 -0
  47. package/dist/components/patterns/inline-empty-state.js.map +1 -0
  48. package/dist/components/patterns/live-row.d.ts +23 -0
  49. package/dist/components/patterns/live-row.d.ts.map +1 -0
  50. package/dist/components/patterns/live-row.js +48 -0
  51. package/dist/components/patterns/live-row.js.map +1 -0
  52. package/dist/components/patterns/payload-inspector.d.ts +25 -0
  53. package/dist/components/patterns/payload-inspector.d.ts.map +1 -0
  54. package/dist/components/patterns/payload-inspector.js +33 -0
  55. package/dist/components/patterns/payload-inspector.js.map +1 -0
  56. package/dist/components/patterns/route-skeleton.d.ts +15 -0
  57. package/dist/components/patterns/route-skeleton.d.ts.map +1 -0
  58. package/dist/components/patterns/route-skeleton.js +7 -0
  59. package/dist/components/patterns/route-skeleton.js.map +1 -0
  60. package/dist/components/patterns/screen-layout.d.ts +14 -0
  61. package/dist/components/patterns/screen-layout.d.ts.map +1 -0
  62. package/dist/components/patterns/screen-layout.js +11 -0
  63. package/dist/components/patterns/screen-layout.js.map +1 -0
  64. package/dist/components/patterns/stale-write-banner.d.ts +26 -0
  65. package/dist/components/patterns/stale-write-banner.d.ts.map +1 -0
  66. package/dist/components/patterns/stale-write-banner.js +28 -0
  67. package/dist/components/patterns/stale-write-banner.js.map +1 -0
  68. package/dist/components/patterns/state-timeline.d.ts +58 -0
  69. package/dist/components/patterns/state-timeline.d.ts.map +1 -0
  70. package/dist/components/patterns/state-timeline.js +103 -0
  71. package/dist/components/patterns/state-timeline.js.map +1 -0
  72. package/dist/components/primitives/badge.d.ts +27 -0
  73. package/dist/components/primitives/badge.d.ts.map +1 -0
  74. package/dist/components/primitives/badge.js +33 -0
  75. package/dist/components/primitives/badge.js.map +1 -0
  76. package/dist/components/primitives/button.d.ts +12 -0
  77. package/dist/components/primitives/button.d.ts.map +1 -0
  78. package/dist/components/primitives/button.js +42 -0
  79. package/dist/components/primitives/button.js.map +1 -0
  80. package/dist/components/primitives/calendar.d.ts +39 -0
  81. package/dist/components/primitives/calendar.d.ts.map +1 -0
  82. package/dist/components/primitives/calendar.js +102 -0
  83. package/dist/components/primitives/calendar.js.map +1 -0
  84. package/dist/components/primitives/card.d.ts +24 -0
  85. package/dist/components/primitives/card.d.ts.map +1 -0
  86. package/dist/components/primitives/card.js +28 -0
  87. package/dist/components/primitives/card.js.map +1 -0
  88. package/dist/components/primitives/checkbox.d.ts +42 -0
  89. package/dist/components/primitives/checkbox.d.ts.map +1 -0
  90. package/dist/components/primitives/checkbox.js +31 -0
  91. package/dist/components/primitives/checkbox.js.map +1 -0
  92. package/dist/components/primitives/chip-select.d.ts +38 -0
  93. package/dist/components/primitives/chip-select.d.ts.map +1 -0
  94. package/dist/components/primitives/chip-select.js +25 -0
  95. package/dist/components/primitives/chip-select.js.map +1 -0
  96. package/dist/components/primitives/command-menu.d.ts +54 -0
  97. package/dist/components/primitives/command-menu.d.ts.map +1 -0
  98. package/dist/components/primitives/command-menu.js +24 -0
  99. package/dist/components/primitives/command-menu.js.map +1 -0
  100. package/dist/components/primitives/confirm-dialog.d.ts +52 -0
  101. package/dist/components/primitives/confirm-dialog.d.ts.map +1 -0
  102. package/dist/components/primitives/confirm-dialog.js +30 -0
  103. package/dist/components/primitives/confirm-dialog.js.map +1 -0
  104. package/dist/components/primitives/date-picker.d.ts +68 -0
  105. package/dist/components/primitives/date-picker.d.ts.map +1 -0
  106. package/dist/components/primitives/date-picker.js +107 -0
  107. package/dist/components/primitives/date-picker.js.map +1 -0
  108. package/dist/components/primitives/dialog.d.ts +50 -0
  109. package/dist/components/primitives/dialog.d.ts.map +1 -0
  110. package/dist/components/primitives/dialog.js +90 -0
  111. package/dist/components/primitives/dialog.js.map +1 -0
  112. package/dist/components/primitives/drawer.d.ts +71 -0
  113. package/dist/components/primitives/drawer.d.ts.map +1 -0
  114. package/dist/components/primitives/drawer.js +93 -0
  115. package/dist/components/primitives/drawer.js.map +1 -0
  116. package/dist/components/primitives/dropdown-menu.d.ts +40 -0
  117. package/dist/components/primitives/dropdown-menu.d.ts.map +1 -0
  118. package/dist/components/primitives/dropdown-menu.js +53 -0
  119. package/dist/components/primitives/dropdown-menu.js.map +1 -0
  120. package/dist/components/primitives/form-field.d.ts +94 -0
  121. package/dist/components/primitives/form-field.d.ts.map +1 -0
  122. package/dist/components/primitives/form-field.js +27 -0
  123. package/dist/components/primitives/form-field.js.map +1 -0
  124. package/dist/components/primitives/inline-confirm.d.ts +62 -0
  125. package/dist/components/primitives/inline-confirm.d.ts.map +1 -0
  126. package/dist/components/primitives/inline-confirm.js +11 -0
  127. package/dist/components/primitives/inline-confirm.js.map +1 -0
  128. package/dist/components/primitives/input.d.ts +4 -0
  129. package/dist/components/primitives/input.d.ts.map +1 -0
  130. package/dist/components/primitives/input.js +13 -0
  131. package/dist/components/primitives/input.js.map +1 -0
  132. package/dist/components/primitives/label.d.ts +26 -0
  133. package/dist/components/primitives/label.d.ts.map +1 -0
  134. package/dist/components/primitives/label.js +33 -0
  135. package/dist/components/primitives/label.js.map +1 -0
  136. package/dist/components/primitives/pagination.d.ts +54 -0
  137. package/dist/components/primitives/pagination.d.ts.map +1 -0
  138. package/dist/components/primitives/pagination.js +31 -0
  139. package/dist/components/primitives/pagination.js.map +1 -0
  140. package/dist/components/primitives/popover.d.ts +12 -0
  141. package/dist/components/primitives/popover.d.ts.map +1 -0
  142. package/dist/components/primitives/popover.js +22 -0
  143. package/dist/components/primitives/popover.js.map +1 -0
  144. package/dist/components/primitives/progress.d.ts +25 -0
  145. package/dist/components/primitives/progress.d.ts.map +1 -0
  146. package/dist/components/primitives/progress.js +25 -0
  147. package/dist/components/primitives/progress.js.map +1 -0
  148. package/dist/components/primitives/radio-group.d.ts +47 -0
  149. package/dist/components/primitives/radio-group.d.ts.map +1 -0
  150. package/dist/components/primitives/radio-group.js +11 -0
  151. package/dist/components/primitives/radio-group.js.map +1 -0
  152. package/dist/components/primitives/select.d.ts +39 -0
  153. package/dist/components/primitives/select.d.ts.map +1 -0
  154. package/dist/components/primitives/select.js +142 -0
  155. package/dist/components/primitives/select.js.map +1 -0
  156. package/dist/components/primitives/separator.d.ts +9 -0
  157. package/dist/components/primitives/separator.d.ts.map +1 -0
  158. package/dist/components/primitives/separator.js +16 -0
  159. package/dist/components/primitives/separator.js.map +1 -0
  160. package/dist/components/primitives/side-nav.d.ts +65 -0
  161. package/dist/components/primitives/side-nav.d.ts.map +1 -0
  162. package/dist/components/primitives/side-nav.js +100 -0
  163. package/dist/components/primitives/side-nav.js.map +1 -0
  164. package/dist/components/primitives/skeleton.d.ts +22 -0
  165. package/dist/components/primitives/skeleton.d.ts.map +1 -0
  166. package/dist/components/primitives/skeleton.js +25 -0
  167. package/dist/components/primitives/skeleton.js.map +1 -0
  168. package/dist/components/primitives/spinner.d.ts +20 -0
  169. package/dist/components/primitives/spinner.d.ts.map +1 -0
  170. package/dist/components/primitives/spinner.js +21 -0
  171. package/dist/components/primitives/spinner.js.map +1 -0
  172. package/dist/components/primitives/switch.d.ts +29 -0
  173. package/dist/components/primitives/switch.d.ts.map +1 -0
  174. package/dist/components/primitives/switch.js +24 -0
  175. package/dist/components/primitives/switch.js.map +1 -0
  176. package/dist/components/primitives/table.d.ts +23 -0
  177. package/dist/components/primitives/table.d.ts.map +1 -0
  178. package/dist/components/primitives/table.js +81 -0
  179. package/dist/components/primitives/table.js.map +1 -0
  180. package/dist/components/primitives/tabs.d.ts +38 -0
  181. package/dist/components/primitives/tabs.d.ts.map +1 -0
  182. package/dist/components/primitives/tabs.js +84 -0
  183. package/dist/components/primitives/tabs.js.map +1 -0
  184. package/dist/components/primitives/textarea.d.ts +4 -0
  185. package/dist/components/primitives/textarea.d.ts.map +1 -0
  186. package/dist/components/primitives/textarea.js +11 -0
  187. package/dist/components/primitives/textarea.js.map +1 -0
  188. package/dist/components/primitives/toast.d.ts +24 -0
  189. package/dist/components/primitives/toast.d.ts.map +1 -0
  190. package/dist/components/primitives/toast.js +58 -0
  191. package/dist/components/primitives/toast.js.map +1 -0
  192. package/dist/components/primitives/tooltip.d.ts +30 -0
  193. package/dist/components/primitives/tooltip.d.ts.map +1 -0
  194. package/dist/components/primitives/tooltip.js +6 -0
  195. package/dist/components/primitives/tooltip.js.map +1 -0
  196. package/dist/components/status/state-chip.d.ts +53 -0
  197. package/dist/components/status/state-chip.d.ts.map +1 -0
  198. package/dist/components/status/state-chip.js +8 -0
  199. package/dist/components/status/state-chip.js.map +1 -0
  200. package/dist/components/status/state-mark.d.ts +21 -0
  201. package/dist/components/status/state-mark.d.ts.map +1 -0
  202. package/dist/components/status/state-mark.js +90 -0
  203. package/dist/components/status/state-mark.js.map +1 -0
  204. package/dist/components/status/status-pill.d.ts +62 -0
  205. package/dist/components/status/status-pill.d.ts.map +1 -0
  206. package/dist/components/status/status-pill.js +65 -0
  207. package/dist/components/status/status-pill.js.map +1 -0
  208. package/dist/components/status/status-tokens.d.ts +110 -0
  209. package/dist/components/status/status-tokens.d.ts.map +1 -0
  210. package/dist/components/status/status-tokens.js +102 -0
  211. package/dist/components/status/status-tokens.js.map +1 -0
  212. package/dist/index.d.ts +76 -0
  213. package/dist/index.d.ts.map +1 -0
  214. package/dist/index.js +95 -0
  215. package/dist/index.js.map +1 -0
  216. package/dist/lib/cn.d.ts +11 -0
  217. package/dist/lib/cn.d.ts.map +1 -0
  218. package/dist/lib/cn.js +78 -0
  219. package/dist/lib/cn.js.map +1 -0
  220. package/dist/lib/money.d.ts +73 -0
  221. package/dist/lib/money.d.ts.map +1 -0
  222. package/dist/lib/money.js +123 -0
  223. package/dist/lib/money.js.map +1 -0
  224. package/dist/lib/omit-undefined.d.ts +17 -0
  225. package/dist/lib/omit-undefined.d.ts.map +1 -0
  226. package/dist/lib/omit-undefined.js +24 -0
  227. package/dist/lib/omit-undefined.js.map +1 -0
  228. package/package.json +100 -0
  229. package/src/components/data/code.tsx +43 -0
  230. package/src/components/data/copy-button.tsx +97 -0
  231. package/src/components/data/detail-row.tsx +113 -0
  232. package/src/components/data/id-display.tsx +49 -0
  233. package/src/components/data/masked-value.tsx +96 -0
  234. package/src/components/data/money.tsx +46 -0
  235. package/src/components/data/phone-display.tsx +60 -0
  236. package/src/components/data/stat-tile.tsx +68 -0
  237. package/src/components/data/timestamp-display.tsx +106 -0
  238. package/src/components/patterns/inline-banner.tsx +60 -0
  239. package/src/components/patterns/inline-empty-state.tsx +45 -0
  240. package/src/components/patterns/live-row.tsx +75 -0
  241. package/src/components/patterns/payload-inspector.tsx +157 -0
  242. package/src/components/patterns/route-skeleton.tsx +77 -0
  243. package/src/components/patterns/screen-layout.tsx +44 -0
  244. package/src/components/patterns/stale-write-banner.tsx +44 -0
  245. package/src/components/patterns/state-timeline.tsx +229 -0
  246. package/src/components/primitives/badge.tsx +40 -0
  247. package/src/components/primitives/button.tsx +54 -0
  248. package/src/components/primitives/calendar.tsx +136 -0
  249. package/src/components/primitives/card.tsx +70 -0
  250. package/src/components/primitives/checkbox.tsx +101 -0
  251. package/src/components/primitives/chip-select.tsx +105 -0
  252. package/src/components/primitives/command-menu.tsx +92 -0
  253. package/src/components/primitives/confirm-dialog.tsx +109 -0
  254. package/src/components/primitives/date-picker.tsx +271 -0
  255. package/src/components/primitives/dialog.tsx +195 -0
  256. package/src/components/primitives/drawer.tsx +326 -0
  257. package/src/components/primitives/dropdown-menu.tsx +128 -0
  258. package/src/components/primitives/form-field.tsx +136 -0
  259. package/src/components/primitives/inline-confirm.tsx +118 -0
  260. package/src/components/primitives/input.tsx +21 -0
  261. package/src/components/primitives/label.tsx +43 -0
  262. package/src/components/primitives/pagination.tsx +110 -0
  263. package/src/components/primitives/popover.tsx +41 -0
  264. package/src/components/primitives/progress.tsx +66 -0
  265. package/src/components/primitives/radio-group.tsx +90 -0
  266. package/src/components/primitives/select.tsx +254 -0
  267. package/src/components/primitives/separator.tsx +49 -0
  268. package/src/components/primitives/side-nav.tsx +253 -0
  269. package/src/components/primitives/skeleton.tsx +25 -0
  270. package/src/components/primitives/spinner.tsx +39 -0
  271. package/src/components/primitives/switch.tsx +74 -0
  272. package/src/components/primitives/table.tsx +157 -0
  273. package/src/components/primitives/tabs.tsx +163 -0
  274. package/src/components/primitives/textarea.tsx +21 -0
  275. package/src/components/primitives/toast.tsx +117 -0
  276. package/src/components/primitives/tooltip.tsx +38 -0
  277. package/src/components/status/state-chip.tsx +70 -0
  278. package/src/components/status/state-mark.tsx +154 -0
  279. package/src/components/status/status-pill.tsx +153 -0
  280. package/src/components/status/status-tokens.ts +173 -0
  281. package/src/index.ts +96 -0
  282. package/src/lib/cn.ts +168 -0
  283. package/src/lib/money.ts +164 -0
  284. package/src/lib/omit-undefined.ts +25 -0
  285. package/src/styles/theme.css +381 -0
@@ -0,0 +1,47 @@
1
+ import type { ReactNode } from "react";
2
+ /**
3
+ * A single-choice control over a small, fixed vocabulary.
4
+ *
5
+ * # Why this exists rather than reaching for `Select`
6
+ *
7
+ * Two reasons, and the second is a correctness one.
8
+ *
9
+ * The first is the one that prompted it: for a handful of options, a
10
+ * `Select` makes the reader click once to discover what the choices even
11
+ * are, and again to pick. A radio group shows the whole vocabulary and
12
+ * costs one click. `SenderIdRegistrationStatus` has four values and lives
13
+ * in a review drawer where seeing the other three *is* the decision.
14
+ *
15
+ * The second: this cannot hit the bug that made `Select` unusable inside a
16
+ * drawer for its entire existence (#315). Headless UI's `Listbox` portals
17
+ * its options to a top-level sibling of `<body>`, which lands outside
18
+ * vaul's Radix focus trap and stalls the enter transition —
19
+ * `opacity: 0`, `pointer-events: none`, measured live. `RadioGroup`
20
+ * renders inline with no portal and no transition, so there is no
21
+ * equivalent failure available to it. For a small vocabulary inside a
22
+ * drawer, that makes radio the *safer* control, not merely the friendlier
23
+ * one.
24
+ *
25
+ * Deliberately not built on `Select`'s CVA table: there are no visual
26
+ * variants to parameterise, and every option renders identically apart
27
+ * from its checked state.
28
+ */
29
+ export interface RadioGroupOption<T extends string> {
30
+ value: T;
31
+ label: ReactNode;
32
+ /** Optional one-line explanation rendered under the label. */
33
+ description?: ReactNode;
34
+ }
35
+ export interface RadioGroupProps<T extends string> {
36
+ value: T | undefined;
37
+ onValueChange: (value: T) => void;
38
+ options: readonly RadioGroupOption<T>[];
39
+ /** Accessible name. Pair with `FormField`'s label via `aria-labelledby`
40
+ * where one exists; supplied directly when the group stands alone. */
41
+ "aria-label"?: string | undefined;
42
+ "aria-labelledby"?: string | undefined;
43
+ disabled?: boolean | undefined;
44
+ className?: string | undefined;
45
+ }
46
+ export declare function RadioGroup<T extends string>({ value, onValueChange, options, disabled, className, ...aria }: RadioGroupProps<T>): import("react").JSX.Element;
47
+ //# sourceMappingURL=radio-group.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"radio-group.d.ts","sourceRoot":"","sources":["../../../src/components/primitives/radio-group.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,MAAM;IAChD,KAAK,EAAE,CAAC,CAAC;IACT,KAAK,EAAE,SAAS,CAAC;IACjB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,SAAS,CAAC;CACzB;AAED,MAAM,WAAW,eAAe,CAAC,CAAC,SAAS,MAAM;IAC/C,KAAK,EAAE,CAAC,GAAG,SAAS,CAAC;IACrB,aAAa,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;IAClC,OAAO,EAAE,SAAS,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC;IACxC;0EACsE;IACtE,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,iBAAiB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAED,wBAAgB,UAAU,CAAC,CAAC,SAAS,MAAM,EAAE,EAC3C,KAAK,EACL,aAAa,EACb,OAAO,EACP,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EACR,EAAE,eAAe,CAAC,CAAC,CAAC,+BA8BpB"}
@@ -0,0 +1,11 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { RadioGroup as HeadlessRadioGroup, Radio } from "@headlessui/react";
4
+ import { cn } from "../../lib/cn.js";
5
+ export function RadioGroup({ value, onValueChange, options, disabled, className, ...aria }) {
6
+ return (_jsx(HeadlessRadioGroup, { value: value ?? null, onChange: (next) => {
7
+ if (next !== null)
8
+ onValueChange(next);
9
+ }, disabled: disabled ?? false, className: cn("flex flex-wrap gap-2", className), ...aria, children: options.map((option) => (_jsxs(Radio, { value: option.value, className: cn("flex cursor-pointer flex-col gap-0.5 rounded-sm border border-edge bg-surface-2 px-3 py-2 text-body text-muted-foreground", "data-checked:border-state-success-border data-checked:bg-state-success-bg data-checked:text-state-success-fg", "data-focus:outline-none data-focus:ring-1 data-focus:ring-state-success-border", "data-disabled:cursor-not-allowed data-disabled:opacity-50"), children: [_jsx("span", { className: "font-medium", children: option.label }), option.description !== undefined && (_jsx("span", { className: "text-caption text-subtle-foreground", children: option.description }))] }, option.value))) }));
10
+ }
11
+ //# sourceMappingURL=radio-group.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"radio-group.js","sourceRoot":"","sources":["../../../src/components/primitives/radio-group.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,UAAU,IAAI,kBAAkB,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE5E,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAgDlC,MAAM,UAAU,UAAU,CAAmB,EAC3C,KAAK,EACL,aAAa,EACb,OAAO,EACP,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EACY;IACnB,OAAO,CACL,KAAC,kBAAkB,IACjB,KAAK,EAAE,KAAK,IAAI,IAAI,EACpB,QAAQ,EAAE,CAAC,IAAc,EAAE,EAAE;YAC3B,IAAI,IAAI,KAAK,IAAI;gBAAE,aAAa,CAAC,IAAI,CAAC,CAAC;QACzC,CAAC,EACD,QAAQ,EAAE,QAAQ,IAAI,KAAK,EAC3B,SAAS,EAAE,EAAE,CAAC,sBAAsB,EAAE,SAAS,CAAC,KAC5C,IAAI,YAEP,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CACvB,MAAC,KAAK,IAEJ,KAAK,EAAE,MAAM,CAAC,KAAK,EACnB,SAAS,EAAE,EAAE,CACX,2HAA2H,EAC3H,8GAA8G,EAC9G,gFAAgF,EAChF,2DAA2D,CAC5D,aAED,eAAM,SAAS,EAAC,aAAa,YAAE,MAAM,CAAC,KAAK,GAAQ,EAClD,MAAM,CAAC,WAAW,KAAK,SAAS,IAAI,CACnC,eAAM,SAAS,EAAC,qCAAqC,YAAE,MAAM,CAAC,WAAW,GAAQ,CAClF,KAZI,MAAM,CAAC,KAAK,CAaX,CACT,CAAC,GACiB,CACtB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,39 @@
1
+ import { type ReactNode } from "react";
2
+ /**
3
+ * Note the `| undefined` on the optional props below. This package
4
+ * compiles under `exactOptionalPropertyTypes`, where a bare `value?:
5
+ * string` means "you may omit this key" and NOT "you may pass
6
+ * `undefined`" — so the ordinary controlled pattern,
7
+ * `const [v, setV] = useState<string>()` followed by `value={v}`, is a
8
+ * type error. Found writing this component's own story, which is the
9
+ * first code outside the original application to use it.
10
+ */
11
+ export interface SelectProps {
12
+ value?: string | undefined;
13
+ defaultValue?: string | undefined;
14
+ onValueChange?: ((value: string) => void) | undefined;
15
+ disabled?: boolean | undefined;
16
+ children: ReactNode;
17
+ }
18
+ export declare function Select({ value, defaultValue, onValueChange, disabled, children }: SelectProps): import("react").JSX.Element;
19
+ export declare function SelectGroup({ children }: {
20
+ children: ReactNode;
21
+ }): import("react").JSX.Element;
22
+ export declare function SelectTrigger({ id, className, children, }: {
23
+ id?: string;
24
+ className?: string;
25
+ children: ReactNode;
26
+ }): import("react").JSX.Element;
27
+ export declare function SelectValue({ placeholder }: {
28
+ placeholder?: string;
29
+ }): import("react").JSX.Element;
30
+ export declare function SelectContent({ className, children, }: {
31
+ className?: string;
32
+ children: ReactNode;
33
+ }): import("react").JSX.Element;
34
+ export declare function SelectItem({ value, className, children, }: {
35
+ value: string;
36
+ className?: string;
37
+ children: ReactNode;
38
+ }): import("react").JSX.Element;
39
+ //# sourceMappingURL=select.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../../src/components/primitives/select.tsx"],"names":[],"mappings":"AAIA,OAAO,EAKL,KAAK,SAAS,EAIf,MAAM,OAAO,CAAC;AAuDf;;;;;;;;GAQG;AACH,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,aAAa,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACtD,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC/B,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,wBAAgB,MAAM,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,WAAW,+BA+B7F;AAOD,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,+BAEhE;AAED,wBAAgB,aAAa,CAAC,EAC5B,EAAE,EACF,SAAS,EACT,QAAQ,GACT,EAAE;IACD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;CACrB,+BAmBA;AAED,wBAAgB,WAAW,CAAC,EAAE,WAAW,EAAE,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,+BAMpE;AAED,wBAAgB,aAAa,CAAC,EAC5B,SAAS,EACT,QAAQ,GACT,EAAE;IACD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;CACrB,+BAqDA;AAED,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,SAAS,EACT,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;CACrB,+BAoBA"}
@@ -0,0 +1,142 @@
1
+ "use client";
2
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Listbox, ListboxButton, ListboxOption, ListboxOptions } from "@headlessui/react";
4
+ import { Check, ChevronDown } from "lucide-react";
5
+ import { Children, createContext, isValidElement, useContext, useMemo, useState, } from "react";
6
+ import { cn } from "../../lib/cn.js";
7
+ import { omitUndefined } from "../../lib/omit-undefined.js";
8
+ const SelectContext = createContext(null);
9
+ function useSelectContext(component) {
10
+ const ctx = useContext(SelectContext);
11
+ if (ctx === null) {
12
+ throw new Error(`<${component} /> must be rendered inside <Select>.`);
13
+ }
14
+ return ctx;
15
+ }
16
+ function findItemLabel(node, value) {
17
+ let found;
18
+ Children.forEach(node, (child) => {
19
+ if (found !== undefined || !isValidElement(child))
20
+ return;
21
+ const el = child;
22
+ if (el.type === SelectItem) {
23
+ if (el.props.value === value)
24
+ found = el.props.children;
25
+ return;
26
+ }
27
+ if (el.props?.children != null) {
28
+ found = findItemLabel(el.props.children, value);
29
+ }
30
+ });
31
+ return found;
32
+ }
33
+ export function Select({ value, defaultValue, onValueChange, disabled, children }) {
34
+ const [internalValue, setInternalValue] = useState(defaultValue);
35
+ const isControlled = value !== undefined;
36
+ const currentValue = isControlled ? value : internalValue;
37
+ function handleChange(next) {
38
+ if (!isControlled)
39
+ setInternalValue(next);
40
+ onValueChange?.(next);
41
+ }
42
+ const itemLabel = useMemo(() => (v) => findItemLabel(children, v), [children]);
43
+ return (_jsx(Listbox, { as: "div", className: "relative", value: currentValue ?? "", onChange: handleChange, ...omitUndefined({ disabled }), children: _jsx(SelectContext.Provider, { value: { value: currentValue, itemLabel }, children: children }) }));
44
+ }
45
+ // Unconsumed today (grepped across `admin/`) — kept for API parity. Radix's
46
+ // `SelectGroup` had no visual treatment of its own beyond semantic
47
+ // grouping; Headless UI's `Listbox` has no equivalent, so this stays a
48
+ // plain wrapper rather than reaching for `Menu`'s `MenuSection` (a
49
+ // different component family).
50
+ export function SelectGroup({ children }) {
51
+ return _jsx("fieldset", { className: "contents border-0 p-0 m-0 min-w-0", children: children });
52
+ }
53
+ export function SelectTrigger({ id, className, children, }) {
54
+ useSelectContext("SelectTrigger");
55
+ return (_jsxs(ListboxButton, { id: id, className: cn("select select-bordered flex w-full items-center justify-between font-sans text-prose", className), children: [children, _jsx(ChevronDown, { size: 14, strokeWidth: 1.5, className: "text-muted-foreground", "aria-hidden": "true" })] }));
56
+ }
57
+ export function SelectValue({ placeholder }) {
58
+ const { value, itemLabel } = useSelectContext("SelectValue");
59
+ if (value === undefined || value === "") {
60
+ return _jsx("span", { className: "text-subtle-foreground", children: placeholder });
61
+ }
62
+ return _jsx(_Fragment, { children: itemLabel(value) ?? value });
63
+ }
64
+ export function SelectContent({ className, children, }) {
65
+ useSelectContext("SelectContent");
66
+ return (_jsx(ListboxOptions
67
+ // `portal={false}` is a correctness fix, not a preference.
68
+ //
69
+ // Headless UI's `anchor` prop portals the options into
70
+ // `#headlessui-portal-root`, a top-level sibling of `<body>`. Inside a
71
+ // `vaul` drawer that is fatal: vaul's `Content` mounts a Radix
72
+ // `FocusScope` with `trapped: true`, a document-level `focusin`
73
+ // listener that force-refocuses back into the drawer the instant
74
+ // focus lands outside it. The portaled listbox is outside, so its
75
+ // enter transition stalls mid-flight and it never becomes usable.
76
+ //
77
+ // Measured on the live console rather than inferred — opening the
78
+ // registration status select inside its stacked drawer gave:
79
+ //
80
+ // parentChain [..., DIV#headlessui-portal-root, BODY]
81
+ // insideAnyDrawer false
82
+ // opacity "0"
83
+ // pointerEvents "none"
84
+ // rect [122, 10] (collapsed, not four options tall)
85
+ //
86
+ // — byte-for-byte the signature #274 recorded for a nested Dialog.
87
+ // #282 fixed that class for `Dialog` and never covered `Select`, so
88
+ // every select inside a drawer has been silently unusable since.
89
+ //
90
+ // Rendering inline keeps the options inside the drawer's own subtree,
91
+ // so the focus trap contains them instead of fighting them. The cost
92
+ // is losing `anchor`'s collision detection; `top-full` + `w-full`
93
+ // below reproduces the same "directly under the trigger, matching its
94
+ // width" placement, which is what every call site here wants anyway.
95
+ , {
96
+ // `portal={false}` is a correctness fix, not a preference.
97
+ //
98
+ // Headless UI's `anchor` prop portals the options into
99
+ // `#headlessui-portal-root`, a top-level sibling of `<body>`. Inside a
100
+ // `vaul` drawer that is fatal: vaul's `Content` mounts a Radix
101
+ // `FocusScope` with `trapped: true`, a document-level `focusin`
102
+ // listener that force-refocuses back into the drawer the instant
103
+ // focus lands outside it. The portaled listbox is outside, so its
104
+ // enter transition stalls mid-flight and it never becomes usable.
105
+ //
106
+ // Measured on the live console rather than inferred — opening the
107
+ // registration status select inside its stacked drawer gave:
108
+ //
109
+ // parentChain [..., DIV#headlessui-portal-root, BODY]
110
+ // insideAnyDrawer false
111
+ // opacity "0"
112
+ // pointerEvents "none"
113
+ // rect [122, 10] (collapsed, not four options tall)
114
+ //
115
+ // — byte-for-byte the signature #274 recorded for a nested Dialog.
116
+ // #282 fixed that class for `Dialog` and never covered `Select`, so
117
+ // every select inside a drawer has been silently unusable since.
118
+ //
119
+ // Rendering inline keeps the options inside the drawer's own subtree,
120
+ // so the focus trap contains them instead of fighting them. The cost
121
+ // is losing `anchor`'s collision detection; `top-full` + `w-full`
122
+ // below reproduces the same "directly under the trigger, matching its
123
+ // width" placement, which is what every call site here wants anyway.
124
+ portal: false,
125
+ // No `transition`, and no `data-closed:*` classes. Headless UI's
126
+ // transition machinery holds `data-closed` until it observes the
127
+ // enter transition finish; inside a drawer it never does. Measured
128
+ // after the portal fix, 1.4s after opening: `data-closed` and
129
+ // `data-enter` both still present, `opacity: 0`, on an element that
130
+ // was otherwise correct (inside the drawer, `pointer-events: auto`,
131
+ // full 146px height, all four options present).
132
+ //
133
+ // That is the same failure mode twice now — #274's nested Dialog was
134
+ // also a stalled enter transition, not a mispositioned element. A
135
+ // 100ms fade on a select dropdown is not worth a second component
136
+ // that silently does not open, so it is gone rather than debugged.
137
+ className: cn("absolute top-full left-0 z-50 mt-1 max-h-80 w-full min-w-[8rem] overflow-y-auto rounded-md border border-edge bg-surface-2 p-1 shadow-[var(--shadow-popover)] focus:outline-none", className), children: children }));
138
+ }
139
+ export function SelectItem({ value, className, children, }) {
140
+ return (_jsx(ListboxOption, { value: value, className: cn("relative flex cursor-pointer items-center rounded-sm py-1.5 pr-2 pl-7 text-body text-foreground outline-none", "data-focus:bg-surface-3", className), children: ({ selected }) => (_jsxs(_Fragment, { children: [_jsx("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: selected && _jsx(Check, { size: 14, strokeWidth: 1.5, "aria-hidden": "true" }) }), children] })) }));
141
+ }
142
+ //# sourceMappingURL=select.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select.js","sourceRoot":"","sources":["../../../src/components/primitives/select.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export interface SeparatorProps extends React.HTMLAttributes<HTMLDivElement> {
2
+ orientation?: "horizontal" | "vertical";
3
+ /** Matches Radix's own default: `true` renders a purely visual rule with
4
+ * no `separator` semantics exposed to assistive tech (`role="none"` on a
5
+ * `<div>`); `false` renders a native `<hr>` with `aria-orientation`. */
6
+ decorative?: boolean;
7
+ }
8
+ export declare const Separator: import("react").ForwardRefExoticComponent<SeparatorProps & import("react").RefAttributes<HTMLDivElement>>;
9
+ //# sourceMappingURL=separator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"separator.d.ts","sourceRoot":"","sources":["../../../src/components/primitives/separator.tsx"],"names":[],"mappings":"AAgBA,MAAM,WAAW,cAAe,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IAC1E,WAAW,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;IACxC;;4EAEwE;IACxE,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,SAAS,2GAuBrB,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ import { cn } from "../../lib/cn.js";
4
+ export const Separator = forwardRef(({ className, orientation = "horizontal", decorative = true, ...props }, ref) => {
5
+ const sharedClassName = cn("shrink-0 border-0 bg-edge", orientation === "horizontal" ? "h-px w-full" : "h-full w-px", className);
6
+ if (decorative) {
7
+ return _jsx("div", { ref: ref, role: "none", className: sharedClassName, ...props });
8
+ }
9
+ // No consumer forwards a ref through the non-decorative branch today
10
+ // (grepped across `admin/`) — the cast is a documented, zero-risk
11
+ // approximation rather than widening `Separator`'s public ref type to
12
+ // `HTMLDivElement | HTMLHRElement` for a case nothing exercises.
13
+ return (_jsx("hr", { ref: ref, "aria-orientation": orientation, className: sharedClassName, ...props }));
14
+ });
15
+ Separator.displayName = "Separator";
16
+ //# sourceMappingURL=separator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"separator.js","sourceRoot":"","sources":["../../../src/components/primitives/separator.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AACnC,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAuBlC,MAAM,CAAC,MAAM,SAAS,GAAG,UAAU,CACjC,CAAC,EAAE,SAAS,EAAE,WAAW,GAAG,YAAY,EAAE,UAAU,GAAG,IAAI,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE;IAC9E,MAAM,eAAe,GAAG,EAAE,CACxB,2BAA2B,EAC3B,WAAW,KAAK,YAAY,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,aAAa,EAC5D,SAAS,CACV,CAAC;IACF,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,cAAK,GAAG,EAAE,GAAG,EAAE,IAAI,EAAC,MAAM,EAAC,SAAS,EAAE,eAAe,KAAM,KAAK,GAAI,CAAC;IAC9E,CAAC;IACD,qEAAqE;IACrE,kEAAkE;IAClE,sEAAsE;IACtE,iEAAiE;IACjE,OAAO,CACL,aACE,GAAG,EAAE,GAA0C,sBAC7B,WAAW,EAC7B,SAAS,EAAE,eAAe,KACtB,KAAK,GACT,CACH,CAAC;AACJ,CAAC,CACF,CAAC;AACF,SAAS,CAAC,WAAW,GAAG,WAAW,CAAC"}
@@ -0,0 +1,65 @@
1
+ import type { ComponentType, ReactNode } from "react";
2
+ /**
3
+ * The console's information architecture (console-redesign.md §4), as data.
4
+ * `@vaam-apps/ui` owns the shape; `frontends/apps/admin/app/nav-groups.ts` owns the actual
5
+ * content (routes, groupings, icons) — this file never hardcodes a route.
6
+ */
7
+ export interface NavItem {
8
+ label: string;
9
+ href: string;
10
+ /** Any lucide-react icon component. Typed structurally so this file
11
+ * doesn't need to depend on `lucide-react`'s own exported icon type name. */
12
+ icon: ComponentType<{
13
+ size?: number;
14
+ className?: string;
15
+ "aria-hidden"?: boolean | "true";
16
+ }>;
17
+ }
18
+ export interface NavGroup {
19
+ /** Small-caps section header, e.g. "Messaging" (console-redesign.md §4). */
20
+ label: string;
21
+ items: NavItem[];
22
+ }
23
+ export interface SideNavProps {
24
+ /** Flat, ungrouped, always first — §4 ("Dashboard"). */
25
+ topItem: NavItem;
26
+ groups: NavGroup[];
27
+ /** De-emphasized footer utility rows (§1.1: "administrivia, not content"). */
28
+ footerItems: NavItem[];
29
+ /** Current pathname, for active-row highlighting. Plain string, not a
30
+ * `next/navigation` call — this package has no dependency on Next.js, so
31
+ * the caller (`frontends/apps/admin/app/console-shell.tsx`) resolves it via
32
+ * `usePathname()` and passes it down. */
33
+ currentPath: string;
34
+ /** App-specific account/sign-out markup (§4's footer "Signed in as
35
+ * <email> · Sign out" row) — rendered as-is, never built here, so this
36
+ * component stays free of any auth-specific knowledge. */
37
+ accountSlot?: ReactNode;
38
+ className?: string;
39
+ }
40
+ /**
41
+ * The console's side navigation (console-redesign.md §4, §6.2). A pure
42
+ * structural/layout component — routing, session data, and the drawer's
43
+ * own off-canvas/persistent CSS split all live at the call site
44
+ * (`frontends/apps/admin/app/console-shell.tsx`, D7): this component only ever decides
45
+ * "flat top item → grouped middle → de-emphasized footer" composition and
46
+ * the label/icon-only/accordion treatment per breakpoint.
47
+ *
48
+ * Breakpoint behaviour (§6.1 is the authoritative table here — see that
49
+ * section's own reasoning for why it supersedes §4's looser "Tablet
50
+ * (768–1024px)" prose, which pre-dates that table and was never updated to
51
+ * match it) — entirely CSS-driven (`lg:`/`xl:` Tailwind variants), never a
52
+ * JS breakpoint read:
53
+ * - `<1024px` (phone and tablet alike): off-canvas, full labels,
54
+ * collapsible accordion groups.
55
+ * - `1024–1279px`: persistent icon-only rail, tooltip on hover/focus.
56
+ * - `≥1280px`: persistent full sidebar with labels.
57
+ *
58
+ * This means the whole nav — every row, every group, every breakpoint's
59
+ * shape — is present in the server-rendered HTML on first paint. No
60
+ * `next/dynamic({ ssr: false })`, no client-only mount flash. Verify that
61
+ * claim directly, not by trusting this comment: `curl` a page and grep the
62
+ * raw HTML for a nav item's label.
63
+ */
64
+ export declare function SideNav({ topItem, groups, footerItems, currentPath, accountSlot, className, }: SideNavProps): import("react").JSX.Element;
65
+ //# sourceMappingURL=side-nav.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"side-nav.d.ts","sourceRoot":"","sources":["../../../src/components/primitives/side-nav.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGtD;;;;GAIG;AACH,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb;iFAC6E;IAC7E,IAAI,EAAE,aAAa,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,OAAO,GAAG,MAAM,CAAA;KAAE,CAAC,CAAC;CAC9F;AAED,MAAM,WAAW,QAAQ;IACvB,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,wDAAwD;IACxD,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,QAAQ,EAAE,CAAC;IACnB,8EAA8E;IAC9E,WAAW,EAAE,OAAO,EAAE,CAAC;IACvB;;;6CAGyC;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB;;8DAE0D;IAC1D,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA+ID;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,OAAO,CAAC,EACtB,OAAO,EACP,MAAM,EACN,WAAW,EACX,WAAW,EACX,WAAW,EACX,SAAS,GACV,EAAE,YAAY,+BAoCd"}
@@ -0,0 +1,100 @@
1
+ "use client";
2
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Disclosure, DisclosureButton, DisclosurePanel } from "@headlessui/react";
4
+ import { ChevronDown } from "lucide-react";
5
+ import { cn } from "../../lib/cn.js";
6
+ function isActive(href, currentPath) {
7
+ if (href === "/")
8
+ return currentPath === "/";
9
+ return currentPath === href || currentPath.startsWith(`${href}/`);
10
+ }
11
+ /**
12
+ * One nav row.
13
+ *
14
+ * **CSS-driven, not `useMediaQuery`-driven — found live, corrected after
15
+ * an earlier revision of this file used `@uidotdev/usehooks`' hook here
16
+ * and wrapped `SideNav` in `next/dynamic({ ssr: false })` to work around
17
+ * its SSR crash (see `console-shell.tsx`'s own history / this file's own
18
+ * git log for the full finding).** That fix traded a real cost — the
19
+ * sidebar never appeared in the server-rendered HTML, so every full page
20
+ * load painted an empty slab and popped the real nav in after hydration —
21
+ * for a problem the breakpoint switch itself never needed JS to solve:
22
+ * `variant="responsive"` below expresses "full label off-canvas and at
23
+ * `xl`, `sr-only` at the `lg` icon-rail band" purely with `lg:sr-only
24
+ * xl:not-sr-only`, no hook, no client-only state, no hydration boundary.
25
+ *
26
+ * - **`"responsive"`**: the label is visible off-canvas (`<1024px`, where
27
+ * this row is never reached without the group around it already being
28
+ * fully expanded) and at `≥1280px`, `sr-only` in the `1024–1279px` icon
29
+ * rail band — a daisyUI `.tooltip`/`data-tip` (D5) carries the label
30
+ * back on hover/focus there. Used for every row that can appear in the
31
+ * *persistent* sidebar: `topItem`, `footerItems`, and each group's own
32
+ * "always expanded" desktop rows (`GroupSection` below).
33
+ * - **`"always"`**: the label is always visible, no responsive classes at
34
+ * all. Used only inside the off-canvas accordion tree, which is itself
35
+ * gated to `<1024px` by its own `lg:hidden` wrapper — a per-row
36
+ * breakpoint switch would be redundant there, since that whole tree
37
+ * never renders at any width where a switch could matter.
38
+ */
39
+ function NavLink({ item, active, variant, dim = false, }) {
40
+ const Icon = item.icon;
41
+ const responsive = variant === "responsive";
42
+ return (_jsxs("a", { href: item.href, "aria-current": active ? "page" : undefined, "data-tip": item.label, className: cn("flex items-center gap-3 rounded-field px-3 py-2 transition-colors", dim ? "text-caption" : "text-body", responsive && "tooltip tooltip-right lg:justify-center lg:px-0 xl:justify-start xl:px-3", active && !dim && "bg-base-300 font-medium text-foreground", active && dim && "text-foreground", !active && "text-muted-foreground hover:bg-base-300/60 hover:text-foreground"), children: [_jsx(Icon, { size: 16, className: "shrink-0", "aria-hidden": "true" }), _jsx("span", { className: cn(responsive && "lg:sr-only xl:not-sr-only"), children: item.label })] }));
43
+ }
44
+ /**
45
+ * One group's worth of rows, rendered as **two parallel trees**, one per
46
+ * §6.1 regime, each visible only at its own breakpoint via a plain
47
+ * `hidden`/`lg:hidden` toggle — not one tree whose *content* changes based
48
+ * on a JS-read viewport width. The two regimes genuinely need different
49
+ * DOM, not just different visibility, because the off-canvas tree is
50
+ * interactive (a collapsible `Disclosure`) and the persistent tree is not
51
+ * (every group is always fully expanded there, matching §1.1's LottieFiles
52
+ * reference, which shows no user-collapsible groups on desktop at all) —
53
+ * duplicating ~4 rows per group across two trees is a irrelevant DOM cost
54
+ * next to the alternative (a client-only nav that never appears in the
55
+ * first paint).
56
+ *
57
+ * - **Off-canvas** (`lg:hidden`, so effectively `<1024px` — both the phone
58
+ * band and the tablet band §6.1 explicitly keeps behind the hamburger):
59
+ * a Headless UI `Disclosure`, collapsed by default, expanded only if it
60
+ * contains the current route — "roughly 6–8 tappable rows on open, not
61
+ * 18" (§4). `defaultOpen` is computed from `currentPath`, which is
62
+ * available identically on the server and the client, so this renders
63
+ * correctly on first paint with no hydration mismatch.
64
+ * - **Persistent** (`hidden lg:flex`, so `≥1024px`): always fully
65
+ * expanded. The header/rail-divider split (small-caps text at `≥1280px`,
66
+ * a hairline divider instead in the `1024–1279px` icon rail band) is the
67
+ * same CSS-toggle technique `NavLink`'s own `"responsive"` variant uses.
68
+ */
69
+ function GroupSection({ group, currentPath }) {
70
+ const hasActiveItem = group.items.some((item) => isActive(item.href, currentPath));
71
+ return (_jsxs(_Fragment, { children: [_jsx("div", { className: "lg:hidden", children: _jsx(Disclosure, { defaultOpen: hasActiveItem, children: ({ open }) => (_jsxs("div", { className: "flex flex-col gap-0.5", children: [_jsxs(DisclosureButton, { className: "flex items-center justify-between rounded-field px-3 py-1.5 text-left text-caption text-subtle-foreground uppercase tracking-wide hover:text-foreground", children: [group.label, _jsx(ChevronDown, { size: 14, "aria-hidden": "true", className: cn("transition-transform", open && "rotate-180") })] }), _jsx(DisclosurePanel, { className: "flex flex-col gap-0.5", children: group.items.map((item) => (_jsx(NavLink, { item: item, active: isActive(item.href, currentPath), variant: "always" }, item.href))) })] })) }) }), _jsxs("div", { className: "hidden lg:flex lg:flex-col lg:gap-0.5", children: [_jsx("p", { className: "hidden px-3 py-1.5 text-caption text-subtle-foreground uppercase tracking-wide xl:block", children: group.label }), _jsx("div", { className: "mx-3 my-1 border-edge-subtle border-t xl:hidden", "aria-hidden": "true" }), group.items.map((item) => (_jsx(NavLink, { item: item, active: isActive(item.href, currentPath), variant: "responsive" }, item.href)))] })] }));
72
+ }
73
+ /**
74
+ * The console's side navigation (console-redesign.md §4, §6.2). A pure
75
+ * structural/layout component — routing, session data, and the drawer's
76
+ * own off-canvas/persistent CSS split all live at the call site
77
+ * (`frontends/apps/admin/app/console-shell.tsx`, D7): this component only ever decides
78
+ * "flat top item → grouped middle → de-emphasized footer" composition and
79
+ * the label/icon-only/accordion treatment per breakpoint.
80
+ *
81
+ * Breakpoint behaviour (§6.1 is the authoritative table here — see that
82
+ * section's own reasoning for why it supersedes §4's looser "Tablet
83
+ * (768–1024px)" prose, which pre-dates that table and was never updated to
84
+ * match it) — entirely CSS-driven (`lg:`/`xl:` Tailwind variants), never a
85
+ * JS breakpoint read:
86
+ * - `<1024px` (phone and tablet alike): off-canvas, full labels,
87
+ * collapsible accordion groups.
88
+ * - `1024–1279px`: persistent icon-only rail, tooltip on hover/focus.
89
+ * - `≥1280px`: persistent full sidebar with labels.
90
+ *
91
+ * This means the whole nav — every row, every group, every breakpoint's
92
+ * shape — is present in the server-rendered HTML on first paint. No
93
+ * `next/dynamic({ ssr: false })`, no client-only mount flash. Verify that
94
+ * claim directly, not by trusting this comment: `curl` a page and grep the
95
+ * raw HTML for a nav item's label.
96
+ */
97
+ export function SideNav({ topItem, groups, footerItems, currentPath, accountSlot, className, }) {
98
+ return (_jsxs("nav", { "aria-label": "Primary", className: cn("flex h-full flex-col gap-4 overflow-y-auto bg-base-200 py-4", className), children: [_jsx("div", { className: "flex flex-col gap-0.5 px-2", children: _jsx(NavLink, { item: topItem, active: isActive(topItem.href, currentPath), variant: "responsive" }) }), _jsx("div", { className: "flex flex-1 flex-col gap-4 px-2", children: groups.map((group) => (_jsx(GroupSection, { group: group, currentPath: currentPath }, group.label))) }), _jsxs("div", { className: "flex flex-col gap-2 border-edge-subtle border-t px-2 pt-3", children: [_jsx("div", { className: "flex flex-col gap-0.5", children: footerItems.map((item) => (_jsx(NavLink, { item: item, active: isActive(item.href, currentPath), variant: "responsive", dim: true }, item.href))) }), accountSlot != null && _jsx("div", { className: "px-3 lg:hidden xl:block", children: accountSlot })] })] }));
99
+ }
100
+ //# sourceMappingURL=side-nav.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"side-nav.js","sourceRoot":"","sources":["../../../src/components/primitives/side-nav.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { HTMLAttributes } from "react";
2
+ /**
3
+ * Static — never shimmering (design doc §3.8 rule 2: "no skeleton
4
+ * shimmer"; §5.2: skeleton rows must match the real row height exactly so
5
+ * nothing shifts on load). House rule, not negotiable — see this repo's
6
+ * own AGENTS.md-lineage note; do not add animation here.
7
+ *
8
+ * Deliberately hand-rolled `<div>`, not daisyUI's own `.skeleton` class:
9
+ * read `daisyui/components/skeleton.css` directly before deciding this —
10
+ * daisyUI's `.skeleton` ships a `background-position` shimmer under
11
+ * `animation:1.8s ease-in-out infinite skeleton` (guarded only by
12
+ * `prefers-reduced-motion`, which is not the same thing as "off by
13
+ * default"), which is exactly the animation this house rule forbids.
14
+ * Radius stays `rounded-sm` (now `--radius-field`, 12px, via Phase 0's
15
+ * token rewrite) rather than moving to `--radius-box` — this component
16
+ * stands in for table cells and text lines across every screen, all
17
+ * field-scale content, not card-scale surfaces, so the token that already
18
+ * existed here is also the correct D8 tier, not a value left untouched by
19
+ * omission.
20
+ */
21
+ export declare function Skeleton({ className, ...props }: HTMLAttributes<HTMLDivElement>): import("react").JSX.Element;
22
+ //# sourceMappingURL=skeleton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skeleton.d.ts","sourceRoot":"","sources":["../../../src/components/primitives/skeleton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAG5C;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,QAAQ,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,cAAc,CAAC,cAAc,CAAC,+BAE/E"}
@@ -0,0 +1,25 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { cn } from "../../lib/cn.js";
3
+ /**
4
+ * Static — never shimmering (design doc §3.8 rule 2: "no skeleton
5
+ * shimmer"; §5.2: skeleton rows must match the real row height exactly so
6
+ * nothing shifts on load). House rule, not negotiable — see this repo's
7
+ * own AGENTS.md-lineage note; do not add animation here.
8
+ *
9
+ * Deliberately hand-rolled `<div>`, not daisyUI's own `.skeleton` class:
10
+ * read `daisyui/components/skeleton.css` directly before deciding this —
11
+ * daisyUI's `.skeleton` ships a `background-position` shimmer under
12
+ * `animation:1.8s ease-in-out infinite skeleton` (guarded only by
13
+ * `prefers-reduced-motion`, which is not the same thing as "off by
14
+ * default"), which is exactly the animation this house rule forbids.
15
+ * Radius stays `rounded-sm` (now `--radius-field`, 12px, via Phase 0's
16
+ * token rewrite) rather than moving to `--radius-box` — this component
17
+ * stands in for table cells and text lines across every screen, all
18
+ * field-scale content, not card-scale surfaces, so the token that already
19
+ * existed here is also the correct D8 tier, not a value left untouched by
20
+ * omission.
21
+ */
22
+ export function Skeleton({ className, ...props }) {
23
+ return _jsx("div", { className: cn("rounded-sm bg-surface-3", className), ...props });
24
+ }
25
+ //# sourceMappingURL=skeleton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skeleton.js","sourceRoot":"","sources":["../../../src/components/primitives/skeleton.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAElC;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,QAAQ,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAkC;IAC9E,OAAO,cAAK,SAAS,EAAE,EAAE,CAAC,yBAAyB,EAAE,SAAS,CAAC,KAAM,KAAK,GAAI,CAAC;AACjF,CAAC"}
@@ -0,0 +1,20 @@
1
+ export interface SpinnerProps {
2
+ size?: "xs" | "sm" | "md" | "lg";
3
+ /** Announced to assistive technology. `undefined` renders the spinner
4
+ * `aria-hidden`, which is correct when a visible sibling already says
5
+ * what is loading — two announcements of the same wait is worse than
6
+ * one. */
7
+ label?: string | undefined;
8
+ className?: string | undefined;
9
+ }
10
+ /**
11
+ * An indeterminate busy indicator, for a wait whose *shape* is unknown.
12
+ *
13
+ * Prefer `Skeleton` wherever the shape of what is arriving is known —
14
+ * a table, a card, a detail pane. A skeleton keeps the layout from
15
+ * jumping when content lands and tells the reader what to expect; a
16
+ * spinner tells them only that something is happening. This is for the
17
+ * rest: a button mid-submit, a poll with no placeholder to draw.
18
+ */
19
+ export declare function Spinner({ size, label, className }: SpinnerProps): import("react").JSX.Element;
20
+ //# sourceMappingURL=spinner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../../src/components/primitives/spinner.tsx"],"names":[],"mappings":"AAEA,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IACjC;;;cAGU;IACV,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AASD;;;;;;;;GAQG;AACH,wBAAgB,OAAO,CAAC,EAAE,IAAW,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,YAAY,+BAUtE"}
@@ -0,0 +1,21 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { cn } from "../../lib/cn.js";
3
+ const SIZE_CLASS = {
4
+ xs: "loading-xs",
5
+ sm: "loading-sm",
6
+ md: "loading-md",
7
+ lg: "loading-lg",
8
+ };
9
+ /**
10
+ * An indeterminate busy indicator, for a wait whose *shape* is unknown.
11
+ *
12
+ * Prefer `Skeleton` wherever the shape of what is arriving is known —
13
+ * a table, a card, a detail pane. A skeleton keeps the layout from
14
+ * jumping when content lands and tells the reader what to expect; a
15
+ * spinner tells them only that something is happening. This is for the
16
+ * rest: a button mid-submit, a poll with no placeholder to draw.
17
+ */
18
+ export function Spinner({ size = "sm", label, className }) {
19
+ return (_jsx("span", { className: cn("loading loading-spinner", SIZE_CLASS[size], className), role: label === undefined ? undefined : "status", "aria-hidden": label === undefined ? true : undefined, children: label !== undefined && _jsx("span", { className: "sr-only", children: label }) }));
20
+ }
21
+ //# sourceMappingURL=spinner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.js","sourceRoot":"","sources":["../../../src/components/primitives/spinner.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAYlC,MAAM,UAAU,GAAG;IACjB,EAAE,EAAE,YAAY;IAChB,EAAE,EAAE,YAAY;IAChB,EAAE,EAAE,YAAY;IAChB,EAAE,EAAE,YAAY;CACR,CAAC;AAEX;;;;;;;;GAQG;AACH,MAAM,UAAU,OAAO,CAAC,EAAE,IAAI,GAAG,IAAI,EAAE,KAAK,EAAE,SAAS,EAAgB;IACrE,OAAO,CACL,eACE,SAAS,EAAE,EAAE,CAAC,yBAAyB,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,EACrE,IAAI,EAAE,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,iBACnC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,YAElD,KAAK,KAAK,SAAS,IAAI,eAAM,SAAS,EAAC,SAAS,YAAE,KAAK,GAAQ,GAC3D,CACR,CAAC;AACJ,CAAC"}