@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 @@
1
+ {"version":3,"file":"detail-row.d.ts","sourceRoot":"","sources":["../../../src/components/data/detail-row.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;AAEhE,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,SAAS,CAAC;IACjB,QAAQ,EAAE,SAAS,CAAC;IACpB,OAAO,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACvC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAED,wBAAgB,SAAS,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAkB,EAAE,SAAS,EAAE,EAAE,cAAc,+BA8B3F;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,EACzB,QAAQ,EACR,OAAkB,EAClB,SAAS,GACV,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,OAAO,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACvC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC,+BAMA"}
@@ -0,0 +1,27 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cn } from "../../lib/cn.js";
3
+ export function DetailRow({ label, children, variant = "inline", className }) {
4
+ if (variant === "divided") {
5
+ return (_jsxs("div", { className: cn("flex flex-col gap-0.5 border-edge-subtle border-b py-2 last:border-b-0", className), children: [_jsx("dt", { className: "text-caption text-subtle-foreground", children: label }), _jsx("dd", { className: "text-body text-foreground", children: children })] }));
6
+ }
7
+ if (variant === "stacked") {
8
+ return (_jsxs("div", { className: cn("flex flex-col gap-1", className), children: [_jsx("dt", { className: "text-muted-foreground", children: label }), _jsx("dd", { className: "text-caption", children: children })] }));
9
+ }
10
+ return (_jsxs("div", { className: cn("flex items-center justify-between gap-3", className), children: [_jsx("dt", { className: "text-muted-foreground", children: label }), _jsx("dd", { children: children })] }));
11
+ }
12
+ /**
13
+ * The `<dl>` a group of [`DetailRow`]s belongs in.
14
+ *
15
+ * Exists so a caller cannot pair the rows with the wrong container — every
16
+ * one of the eight original sites wrapped its rows in a `<dl>` with its own
17
+ * spacing (`gap-2`, `gap-3`, or none), which is the same one-decision-in-
18
+ * many-places problem the rows themselves had, one level up.
19
+ *
20
+ * `divided` rows carry their own vertical rhythm through padding and the
21
+ * hairline rule, so the list adds no gap for them — passing `gap` there
22
+ * would double-space rows that are already separated by a border.
23
+ */
24
+ export function DetailList({ children, variant = "inline", className, }) {
25
+ return (_jsx("dl", { className: cn("flex flex-col text-body", variant !== "divided" && "gap-3", className), children: children }));
26
+ }
27
+ //# sourceMappingURL=detail-row.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detail-row.js","sourceRoot":"","sources":["../../../src/components/data/detail-row.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAqDlC,MAAM,UAAU,SAAS,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,GAAG,QAAQ,EAAE,SAAS,EAAkB;IAC1F,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,CACL,eACE,SAAS,EAAE,EAAE,CACX,wEAAwE,EACxE,SAAS,CACV,aAED,aAAI,SAAS,EAAC,qCAAqC,YAAE,KAAK,GAAM,EAChE,aAAI,SAAS,EAAC,2BAA2B,YAAE,QAAQ,GAAM,IACrD,CACP,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,CACL,eAAK,SAAS,EAAE,EAAE,CAAC,qBAAqB,EAAE,SAAS,CAAC,aAClD,aAAI,SAAS,EAAC,uBAAuB,YAAE,KAAK,GAAM,EAClD,aAAI,SAAS,EAAC,cAAc,YAAE,QAAQ,GAAM,IACxC,CACP,CAAC;IACJ,CAAC;IAED,OAAO,CACL,eAAK,SAAS,EAAE,EAAE,CAAC,yCAAyC,EAAE,SAAS,CAAC,aACtE,aAAI,SAAS,EAAC,uBAAuB,YAAE,KAAK,GAAM,EAClD,uBAAK,QAAQ,GAAM,IACf,CACP,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,UAAU,CAAC,EACzB,QAAQ,EACR,OAAO,GAAG,QAAQ,EAClB,SAAS,GAKV;IACC,OAAO,CACL,aAAI,SAAS,EAAE,EAAE,CAAC,yBAAyB,EAAE,OAAO,KAAK,SAAS,IAAI,OAAO,EAAE,SAAS,CAAC,YACtF,QAAQ,GACN,CACN,CAAC;AACJ,CAAC"}
@@ -0,0 +1,33 @@
1
+ export interface IdDisplayProps {
2
+ value: string;
3
+ /** `table` (default): a truncated prefix plus a hover-reveal copy
4
+ * button — enough to disambiguate visually within one screen of rows.
5
+ * `full`: the whole value, selectable, with an always-visible copy —
6
+ * detail views only. Copy always copies the FULL value in both. */
7
+ variant?: "table" | "full";
8
+ /** How many leading characters the `table` variant shows. Seven is the
9
+ * default because it is what makes two 23-character CUIDs distinguishable
10
+ * in a list without dominating the column; an id family with a shared
11
+ * prefix (`ord_`, `pi_`) needs more. */
12
+ truncateTo?: number;
13
+ className?: string | undefined;
14
+ }
15
+ /**
16
+ * An opaque machine identifier — a CUID, a ULID, a provider's reference.
17
+ *
18
+ * Two rules, both learned the hard way and both enforced here rather than
19
+ * left to each call site:
20
+ *
21
+ * - **Never truncate in the middle.** `abc…xyz` makes two ids that differ
22
+ * only in the middle look identical, which is precisely the comparison
23
+ * a human scanning a column is making.
24
+ * - **Never decorate.** A displayed `msg_abc…` gets pasted into a filter
25
+ * that expects the bare value and returns nothing, or worse, a 400. If
26
+ * the prefix is part of the id, it is part of `value`.
27
+ *
28
+ * For a value that must be read in full — a config key, a role name, an
29
+ * enum literal — use `Code` instead. This component's truncation is wrong
30
+ * for anything a human is meant to read rather than match.
31
+ */
32
+ export declare function IdDisplay({ value, variant, truncateTo, className }: IdDisplayProps): import("react").JSX.Element;
33
+ //# sourceMappingURL=id-display.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"id-display.d.ts","sourceRoot":"","sources":["../../../src/components/data/id-display.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd;;;uEAGmE;IACnE,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC3B;;;4CAGwC;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,SAAS,CAAC,EAAE,KAAK,EAAE,OAAiB,EAAE,UAAc,EAAE,SAAS,EAAE,EAAE,cAAc,+BAahG"}
@@ -0,0 +1,25 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cn } from "../../lib/cn.js";
3
+ import { CopyButton } from "./copy-button.js";
4
+ /**
5
+ * An opaque machine identifier — a CUID, a ULID, a provider's reference.
6
+ *
7
+ * Two rules, both learned the hard way and both enforced here rather than
8
+ * left to each call site:
9
+ *
10
+ * - **Never truncate in the middle.** `abc…xyz` makes two ids that differ
11
+ * only in the middle look identical, which is precisely the comparison
12
+ * a human scanning a column is making.
13
+ * - **Never decorate.** A displayed `msg_abc…` gets pasted into a filter
14
+ * that expects the bare value and returns nothing, or worse, a 400. If
15
+ * the prefix is part of the id, it is part of `value`.
16
+ *
17
+ * For a value that must be read in full — a config key, a role name, an
18
+ * enum literal — use `Code` instead. This component's truncation is wrong
19
+ * for anything a human is meant to read rather than match.
20
+ */
21
+ export function IdDisplay({ value, variant = "table", truncateTo = 7, className }) {
22
+ const shown = variant === "table" ? value.slice(0, truncateTo) : value;
23
+ return (_jsxs("span", { className: cn("group inline-flex items-center gap-1.5 font-mono tabular-nums", className), children: [_jsx("span", { className: variant === "full" ? "select-all" : undefined, title: value, children: shown }), _jsx(CopyButton, { value: value, revealOnGroupHover: variant === "table" })] }));
24
+ }
25
+ //# sourceMappingURL=id-display.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"id-display.js","sourceRoot":"","sources":["../../../src/components/data/id-display.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAiB3C;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,SAAS,CAAC,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,EAAE,UAAU,GAAG,CAAC,EAAE,SAAS,EAAkB;IAC/F,MAAM,KAAK,GAAG,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAEvE,OAAO,CACL,gBACE,SAAS,EAAE,EAAE,CAAC,+DAA+D,EAAE,SAAS,CAAC,aAEzF,eAAM,SAAS,EAAE,OAAO,KAAK,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,KAAK,YACzE,KAAK,GACD,EACP,KAAC,UAAU,IAAC,KAAK,EAAE,KAAK,EAAE,kBAAkB,EAAE,OAAO,KAAK,OAAO,GAAI,IAChE,CACR,CAAC;AACJ,CAAC"}
@@ -0,0 +1,47 @@
1
+ export interface MaskedValueProps {
2
+ /** The full value. Present in the DOM only while revealed. */
3
+ value: string;
4
+ /** Trailing characters left visible while masked, so the value stays
5
+ * recognisable without being readable. `0` masks everything. */
6
+ reveal?: number;
7
+ /** Leading characters left visible — for a prefixed credential like
8
+ * `whsec_…` or `sk_live_…`, where the prefix says what kind of thing it
9
+ * is and is not itself secret. */
10
+ prefix?: number;
11
+ /** Allow revealing at all. `false` gives a permanently masked value with
12
+ * no toggle — for something displayed for recognition only. */
13
+ revealable?: boolean;
14
+ /** Offer a copy button. Copies the full value whether or not it is
15
+ * currently revealed — the point of masking is the screen, not the
16
+ * clipboard. */
17
+ copyable?: boolean;
18
+ /** Names the value in the toggle's and copy button's accessible names,
19
+ * e.g. `"signing secret"`. */
20
+ label?: string;
21
+ className?: string | undefined;
22
+ }
23
+ /**
24
+ * A secret or sensitive value, masked by default with an explicit reveal.
25
+ *
26
+ * # What this is and is not
27
+ *
28
+ * It is a **shoulder-surfing and screen-share control**, not a security
29
+ * boundary. Whoever renders this already received the value over the
30
+ * wire; anyone with the session and dev tools can read it regardless.
31
+ * Withholding data that has already crossed the wire to an authorised,
32
+ * authenticated session would be theatre. What masking buys is real but
33
+ * narrow: the value does not end up in a screenshot, a recording, or the
34
+ * eyeline of the person sitting behind the operator.
35
+ *
36
+ * If a value must genuinely never reach the client, that is an API
37
+ * decision — do not send it — and no component can substitute for it.
38
+ *
39
+ * # Why it is shared
40
+ *
41
+ * Both applications this package serves had hand-rolled one: a console
42
+ * masking a webhook signing secret as `whsec_••••••••••<last 4>`, and a
43
+ * payments dashboard rendering a masked payer reference and a TOTP
44
+ * enrolment secret as plain text because no such component existed.
45
+ */
46
+ export declare function MaskedValue({ value, reveal, prefix, revealable, copyable, label, className, }: MaskedValueProps): import("react").JSX.Element;
47
+ //# sourceMappingURL=masked-value.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"masked-value.d.ts","sourceRoot":"","sources":["../../../src/components/data/masked-value.tsx"],"names":[],"mappings":"AAOA,MAAM,WAAW,gBAAgB;IAC/B,8DAA8D;IAC9D,KAAK,EAAE,MAAM,CAAC;IACd;oEACgE;IAChE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;sCAEkC;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;mEAC+D;IAC/D,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;oBAEgB;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;kCAC8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAeD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,MAAU,EACV,MAAU,EACV,UAAiB,EACjB,QAAe,EACf,KAAe,EACf,SAAS,GACV,EAAE,gBAAgB,+BAqBlB"}
@@ -0,0 +1,46 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Eye, EyeOff } from "lucide-react";
4
+ import { useState } from "react";
5
+ import { cn } from "../../lib/cn.js";
6
+ import { CopyButton } from "./copy-button.js";
7
+ const DOT = "•";
8
+ function mask(value, prefix, reveal) {
9
+ const head = value.slice(0, prefix);
10
+ const tail = reveal > 0 ? value.slice(-reveal) : "";
11
+ const hiddenCount = Math.max(value.length - head.length - tail.length, 0);
12
+ // A fixed run of dots, not one per character: the exact length of a
13
+ // secret is information, and padding it out to the real length leaks it
14
+ // to anyone looking over a shoulder.
15
+ const dots = DOT.repeat(hiddenCount === 0 ? 0 : Math.min(Math.max(hiddenCount, 6), 12));
16
+ return `${head}${dots}${tail}`;
17
+ }
18
+ /**
19
+ * A secret or sensitive value, masked by default with an explicit reveal.
20
+ *
21
+ * # What this is and is not
22
+ *
23
+ * It is a **shoulder-surfing and screen-share control**, not a security
24
+ * boundary. Whoever renders this already received the value over the
25
+ * wire; anyone with the session and dev tools can read it regardless.
26
+ * Withholding data that has already crossed the wire to an authorised,
27
+ * authenticated session would be theatre. What masking buys is real but
28
+ * narrow: the value does not end up in a screenshot, a recording, or the
29
+ * eyeline of the person sitting behind the operator.
30
+ *
31
+ * If a value must genuinely never reach the client, that is an API
32
+ * decision — do not send it — and no component can substitute for it.
33
+ *
34
+ * # Why it is shared
35
+ *
36
+ * Both applications this package serves had hand-rolled one: a console
37
+ * masking a webhook signing secret as `whsec_••••••••••<last 4>`, and a
38
+ * payments dashboard rendering a masked payer reference and a TOTP
39
+ * enrolment secret as plain text because no such component existed.
40
+ */
41
+ export function MaskedValue({ value, reveal = 4, prefix = 0, revealable = true, copyable = true, label = "value", className, }) {
42
+ const [revealed, setRevealed] = useState(false);
43
+ const shown = revealed ? value : mask(value, prefix, reveal);
44
+ return (_jsxs("span", { className: cn("group inline-flex items-center gap-1.5", className), children: [_jsx("span", { className: cn("font-mono", revealed && "select-all break-all"), children: shown }), revealable && (_jsx("button", { type: "button", onClick: () => setRevealed((previous) => !previous), "aria-label": revealed ? `Hide ${label}` : `Reveal ${label}`, "aria-pressed": revealed, className: "shrink-0 text-subtle-foreground transition-colors hover:text-foreground", children: revealed ? _jsx(EyeOff, { size: 12, strokeWidth: 1.5 }) : _jsx(Eye, { size: 12, strokeWidth: 1.5 }) })), copyable && _jsx(CopyButton, { value: value, label: `Copy ${label}` })] }));
45
+ }
46
+ //# sourceMappingURL=masked-value.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"masked-value.js","sourceRoot":"","sources":["../../../src/components/data/masked-value.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAyB3C,MAAM,GAAG,GAAG,GAAG,CAAC;AAEhB,SAAS,IAAI,CAAC,KAAa,EAAE,MAAc,EAAE,MAAc;IACzD,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IACpC,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACpD,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC1E,oEAAoE;IACpE,wEAAwE;IACxE,qCAAqC;IACrC,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IACxF,OAAO,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,EAAE,CAAC;AACjC,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,WAAW,CAAC,EAC1B,KAAK,EACL,MAAM,GAAG,CAAC,EACV,MAAM,GAAG,CAAC,EACV,UAAU,GAAG,IAAI,EACjB,QAAQ,GAAG,IAAI,EACf,KAAK,GAAG,OAAO,EACf,SAAS,GACQ;IACjB,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAChD,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAE7D,OAAO,CACL,gBAAM,SAAS,EAAE,EAAE,CAAC,wCAAwC,EAAE,SAAS,CAAC,aACtE,eAAM,SAAS,EAAE,EAAE,CAAC,WAAW,EAAE,QAAQ,IAAI,sBAAsB,CAAC,YAAG,KAAK,GAAQ,EACnF,UAAU,IAAI,CACb,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,gBACvC,QAAQ,CAAC,CAAC,CAAC,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,EAAE,kBAC5C,QAAQ,EACtB,SAAS,EAAC,yEAAyE,YAElF,QAAQ,CAAC,CAAC,CAAC,KAAC,MAAM,IAAC,IAAI,EAAE,EAAE,EAAE,WAAW,EAAE,GAAG,GAAI,CAAC,CAAC,CAAC,KAAC,GAAG,IAAC,IAAI,EAAE,EAAE,EAAE,WAAW,EAAE,GAAG,GAAI,GACjF,CACV,EACA,QAAQ,IAAI,KAAC,UAAU,IAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,KAAK,EAAE,GAAI,IAC5D,CACR,CAAC;AACJ,CAAC"}
@@ -0,0 +1,28 @@
1
+ import { type FormatMoneyOptions, type MinorUnits } from "../../lib/money.js";
2
+ export interface MoneyProps extends FormatMoneyOptions {
3
+ /** An integer count of the currency's smallest unit. */
4
+ amount: MinorUnits;
5
+ /** ISO 4217 code, e.g. `"XAF"`. */
6
+ currency: string;
7
+ /** Tint by sign: credits green, debits red. Off by default — in a
8
+ * ledger where most rows are one direction, colouring every row is
9
+ * noise, and colour alone is not an accessible way to convey sign. The
10
+ * minus sign is always rendered regardless. */
11
+ tone?: "none" | "signed";
12
+ className?: string | undefined;
13
+ }
14
+ /**
15
+ * An amount of money, right-alignable and vertically comparable.
16
+ *
17
+ * `tabular-nums` is the whole reason this is a component and not a call to
18
+ * [`formatMoney`] in a `<span>`: without fixed-width digits, a column of
19
+ * amounts does not line up at the decimal point, and scanning it for an
20
+ * outlier — the actual job — stops working.
21
+ *
22
+ * `<data value>` rather than `<span>`: the machine-readable amount stays
23
+ * in the DOM in minor units, so a copy-paste or a scraper gets the exact
24
+ * integer rather than a locale-formatted string it would have to parse
25
+ * back.
26
+ */
27
+ export declare function Money({ amount, currency, tone, className, ...options }: MoneyProps): import("react").JSX.Element;
28
+ //# sourceMappingURL=money.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"money.d.ts","sourceRoot":"","sources":["../../../src/components/data/money.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,kBAAkB,EAAe,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAExF,MAAM,WAAW,UAAW,SAAQ,kBAAkB;IACpD,wDAAwD;IACxD,MAAM,EAAE,UAAU,CAAC;IACnB,mCAAmC;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB;;;mDAG+C;IAC/C,IAAI,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,KAAK,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAa,EAAE,SAAS,EAAE,GAAG,OAAO,EAAE,EAAE,UAAU,+BAgB3F"}
@@ -0,0 +1,22 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { cn } from "../../lib/cn.js";
3
+ import { formatMoney } from "../../lib/money.js";
4
+ /**
5
+ * An amount of money, right-alignable and vertically comparable.
6
+ *
7
+ * `tabular-nums` is the whole reason this is a component and not a call to
8
+ * [`formatMoney`] in a `<span>`: without fixed-width digits, a column of
9
+ * amounts does not line up at the decimal point, and scanning it for an
10
+ * outlier — the actual job — stops working.
11
+ *
12
+ * `<data value>` rather than `<span>`: the machine-readable amount stays
13
+ * in the DOM in minor units, so a copy-paste or a scraper gets the exact
14
+ * integer rather than a locale-formatted string it would have to parse
15
+ * back.
16
+ */
17
+ export function Money({ amount, currency, tone = "none", className, ...options }) {
18
+ const formatted = formatMoney(amount, currency, options);
19
+ const negative = String(amount).trim().startsWith("-");
20
+ return (_jsx("data", { value: `${String(amount)} ${currency}`, className: cn("font-mono tabular-nums whitespace-nowrap", tone === "signed" && (negative ? "text-state-danger-fg" : "text-state-success-fg"), className), children: formatted }));
21
+ }
22
+ //# sourceMappingURL=money.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"money.js","sourceRoot":"","sources":["../../../src/components/data/money.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAA2B,WAAW,EAAmB,MAAM,iBAAiB,CAAC;AAexF;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,KAAK,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,GAAG,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,EAAc;IAC1F,MAAM,SAAS,GAAG,WAAW,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IACzD,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IAEvD,OAAO,CACL,eACE,KAAK,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,QAAQ,EAAE,EACtC,SAAS,EAAE,EAAE,CACX,0CAA0C,EAC1C,IAAI,KAAK,QAAQ,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,uBAAuB,CAAC,EAClF,SAAS,CACV,YAEA,SAAS,GACL,CACR,CAAC;AACJ,CAAC"}
@@ -0,0 +1,45 @@
1
+ export interface PhoneDisplayProps {
2
+ /** E.164, e.g. `+237677123456`. Stored form, and what gets copied. */
3
+ value: string;
4
+ /**
5
+ * Regroups the E.164 digits for reading. Return `null` — or omit the
6
+ * prop — to render the value verbatim.
7
+ *
8
+ * Grouping is a per-country convention (`+237 6 77 12 34 56` in
9
+ * Cameroon, `+1 (415) 555-0132` in the NANP) and getting it wrong is
10
+ * worse than not grouping at all, because a mis-grouped number reads as
11
+ * a different number. This component therefore ships no default
12
+ * grouping and no built-in country table: a caller that knows its
13
+ * market passes a formatter, and everyone else gets the raw E.164,
14
+ * which is always correct if less pretty.
15
+ */
16
+ format?: ((e164: string) => string | null) | undefined;
17
+ /**
18
+ * A short mono tag after the number — a carrier, a line type, a region.
19
+ * Renders an em dash when absent, so a column of numbers stays aligned
20
+ * whether or not each row could be classified.
21
+ */
22
+ tag?: string | undefined;
23
+ /** Hover text for the tag. Say where it came from and how much to trust
24
+ * it: a carrier inferred from a number prefix is a guess, and number
25
+ * portability means it is wrong for a real fraction of subscribers. */
26
+ tagTitle?: string | undefined;
27
+ className?: string | undefined;
28
+ }
29
+ /**
30
+ * A phone number, never truncated.
31
+ *
32
+ * Truncation is banned rather than discouraged: a half-shown phone number
33
+ * is worse than useless in an investigation, and unlike an opaque id
34
+ * (where a prefix is enough to match rows by eye) there is no prefix of a
35
+ * phone number that identifies it.
36
+ *
37
+ * Copy always copies the raw E.164 — the form that pastes into a query —
38
+ * not the grouped form on screen.
39
+ *
40
+ * Previously this was `MsisdnDisplay`, with Cameroon's `+237` grouping and
41
+ * a four-entry Cameroonian carrier table compiled in. Both are now the
42
+ * caller's: an application knows its market, a component library does not.
43
+ */
44
+ export declare function PhoneDisplay({ value, format, tag, tagTitle, className }: PhoneDisplayProps): import("react").JSX.Element;
45
+ //# sourceMappingURL=phone-display.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"phone-display.d.ts","sourceRoot":"","sources":["../../../src/components/data/phone-display.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,iBAAiB;IAChC,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAC;IACd;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,SAAS,CAAC;IACvD;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB;;2EAEuE;IACvE,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,iBAAiB,+BAY1F"}
@@ -0,0 +1,23 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cn } from "../../lib/cn.js";
3
+ import { CopyButton } from "./copy-button.js";
4
+ /**
5
+ * A phone number, never truncated.
6
+ *
7
+ * Truncation is banned rather than discouraged: a half-shown phone number
8
+ * is worse than useless in an investigation, and unlike an opaque id
9
+ * (where a prefix is enough to match rows by eye) there is no prefix of a
10
+ * phone number that identifies it.
11
+ *
12
+ * Copy always copies the raw E.164 — the form that pastes into a query —
13
+ * not the grouped form on screen.
14
+ *
15
+ * Previously this was `MsisdnDisplay`, with Cameroon's `+237` grouping and
16
+ * a four-entry Cameroonian carrier table compiled in. Both are now the
17
+ * caller's: an application knows its market, a component library does not.
18
+ */
19
+ export function PhoneDisplay({ value, format, tag, tagTitle, className }) {
20
+ const formatted = format?.(value) ?? value;
21
+ return (_jsxs("span", { className: cn("group inline-flex items-center gap-1.5 whitespace-nowrap", className), children: [_jsx("span", { className: "font-mono tabular-nums", children: formatted }), _jsx("span", { className: "font-mono text-micro text-subtle-foreground", title: tagTitle, children: tag ?? "—" }), _jsx(CopyButton, { value: value, revealOnGroupHover: true })] }));
22
+ }
23
+ //# sourceMappingURL=phone-display.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"phone-display.js","sourceRoot":"","sources":["../../../src/components/data/phone-display.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AA+B3C;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,YAAY,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAqB;IACzF,MAAM,SAAS,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC;IAE3C,OAAO,CACL,gBAAM,SAAS,EAAE,EAAE,CAAC,0DAA0D,EAAE,SAAS,CAAC,aACxF,eAAM,SAAS,EAAC,wBAAwB,YAAE,SAAS,GAAQ,EAC3D,eAAM,SAAS,EAAC,6CAA6C,EAAC,KAAK,EAAE,QAAQ,YAC1E,GAAG,IAAI,GAAG,GACN,EACP,KAAC,UAAU,IAAC,KAAK,EAAE,KAAK,EAAE,kBAAkB,SAAG,IAC1C,CACR,CAAC;AACJ,CAAC"}
@@ -0,0 +1,33 @@
1
+ import type { ReactNode } from "react";
2
+ import type { StatusHue } from "../status/status-tokens.js";
3
+ export interface StatTileProps {
4
+ label: ReactNode;
5
+ /** The number itself. Pass a `Money` or a formatted string — this
6
+ * component does no formatting, because a tile has no way to know
7
+ * whether it is showing a count, a currency or a rate. */
8
+ value: ReactNode;
9
+ /** One line under the value: the comparison, the window, the caveat.
10
+ * A bare number with no denominator is the most common way a dashboard
11
+ * misleads, so this slot exists to make the denominator easy. */
12
+ caption?: ReactNode;
13
+ /** Tints the value. Leave unset unless the number's own colour carries
14
+ * meaning — a wall of coloured tiles makes the one that matters harder
15
+ * to find, which is the opposite of the point. */
16
+ tone?: StatusHue | undefined;
17
+ /** Top-right slot — a sparkline, a `StateChip`, a refresh button. */
18
+ action?: ReactNode;
19
+ className?: string | undefined;
20
+ }
21
+ /**
22
+ * One headline number with its label and context.
23
+ *
24
+ * Borders, not shadows, and no card chrome of its own beyond a hairline:
25
+ * tiles appear in rows of three to six, and six shadowed boxes is visual
26
+ * noise where six outlined ones read as one instrument panel.
27
+ *
28
+ * `<dl>`/`<dt>`/`<dd>` rather than divs — a tile *is* a term and its
29
+ * definition, and the semantics make a row of them navigable rather than
30
+ * an undifferentiated wall of text to a screen reader.
31
+ */
32
+ export declare function StatTile({ label, value, caption, tone, action, className }: StatTileProps): import("react").JSX.Element;
33
+ //# sourceMappingURL=stat-tile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stat-tile.d.ts","sourceRoot":"","sources":["../../../src/components/data/stat-tile.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAGzD,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,SAAS,CAAC;IACjB;;8DAE0D;IAC1D,KAAK,EAAE,SAAS,CAAC;IACjB;;qEAEiE;IACjE,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB;;sDAEkD;IAClD,IAAI,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IAC7B,qEAAqE;IACrE,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,aAAa,+BAgCzF"}
@@ -0,0 +1,18 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cn } from "../../lib/cn.js";
3
+ import { HUE_CLASSES } from "../status/status-tokens.js";
4
+ /**
5
+ * One headline number with its label and context.
6
+ *
7
+ * Borders, not shadows, and no card chrome of its own beyond a hairline:
8
+ * tiles appear in rows of three to six, and six shadowed boxes is visual
9
+ * noise where six outlined ones read as one instrument panel.
10
+ *
11
+ * `<dl>`/`<dt>`/`<dd>` rather than divs — a tile *is* a term and its
12
+ * definition, and the semantics make a row of them navigable rather than
13
+ * an undifferentiated wall of text to a screen reader.
14
+ */
15
+ export function StatTile({ label, value, caption, tone, action, className }) {
16
+ return (_jsxs("div", { className: cn("relative flex flex-col rounded-box border border-edge bg-base-300 p-4", className), children: [action != null && _jsx("div", { className: "absolute top-4 right-4", children: action }), _jsxs("dl", { className: "flex flex-col gap-1", children: [_jsx("dt", { className: cn("text-caption text-muted-foreground", action != null && "pr-20"), children: label }), _jsx("dd", { className: cn("font-mono text-metric tabular-nums", tone === undefined ? "text-foreground" : HUE_CLASSES[tone].fg), children: value }), caption != null && _jsx("dd", { className: "text-caption text-subtle-foreground", children: caption })] })] }));
17
+ }
18
+ //# sourceMappingURL=stat-tile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stat-tile.js","sourceRoot":"","sources":["../../../src/components/data/stat-tile.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAElC,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAqBtD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAiB;IACxF,OAAO,CACL,eACE,SAAS,EAAE,EAAE,CACX,uEAAuE,EACvE,SAAS,CACV,aASA,MAAM,IAAI,IAAI,IAAI,cAAK,SAAS,EAAC,wBAAwB,YAAE,MAAM,GAAO,EACzE,cAAI,SAAS,EAAC,qBAAqB,aACjC,aAAI,SAAS,EAAE,EAAE,CAAC,oCAAoC,EAAE,MAAM,IAAI,IAAI,IAAI,OAAO,CAAC,YAC/E,KAAK,GACH,EACL,aACE,SAAS,EAAE,EAAE,CACX,oCAAoC,EACpC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,EAAE,CAC9D,YAEA,KAAK,GACH,EACJ,OAAO,IAAI,IAAI,IAAI,aAAI,SAAS,EAAC,qCAAqC,YAAE,OAAO,GAAM,IACnF,IACD,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,14 @@
1
+ export interface TimestampDisplayProps {
2
+ /** ISO-8601. */
3
+ value: string;
4
+ className?: string;
5
+ }
6
+ /**
7
+ * Relative for anything under 24h (`2m`, `47m`, `6h`), absolute otherwise
8
+ * — design doc §7.2. Renders the absolute value on the server and on
9
+ * first client render (so server/client markup matches and Next doesn't
10
+ * warn/flash), then upgrades to relative once mounted, driven by the
11
+ * shared interval above rather than its own timer.
12
+ */
13
+ export declare function TimestampDisplay({ value, className }: TimestampDisplayProps): import("react").JSX.Element;
14
+ //# sourceMappingURL=timestamp-display.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timestamp-display.d.ts","sourceRoot":"","sources":["../../../src/components/data/timestamp-display.tsx"],"names":[],"mappings":"AAiEA,MAAM,WAAW,qBAAqB;IACpC,gBAAgB;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,qBAAqB,+BA2B3E"}
@@ -0,0 +1,77 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { useEffect, useState, useSyncExternalStore } from "react";
4
+ import { cn } from "../../lib/cn.js";
5
+ // A single shared 30s interval drives every `TimestampDisplay` instance's
6
+ // relative-time re-render (design doc §7.2: "a table of 200 rows must not
7
+ // run 200 timers"). Lazily started on the first mounted instance, torn
8
+ // down when the last one unmounts.
9
+ let tick = 0;
10
+ const listeners = new Set();
11
+ let timer = null;
12
+ function subscribe(listener) {
13
+ listeners.add(listener);
14
+ timer ??= setInterval(() => {
15
+ tick += 1;
16
+ for (const l of listeners)
17
+ l();
18
+ }, 30_000);
19
+ return () => {
20
+ listeners.delete(listener);
21
+ if (listeners.size === 0 && timer !== null) {
22
+ clearInterval(timer);
23
+ timer = null;
24
+ }
25
+ };
26
+ }
27
+ function useSharedTick() {
28
+ return useSyncExternalStore(subscribe, () => tick, () => 0);
29
+ }
30
+ function pad(n) {
31
+ return String(n).padStart(2, "0");
32
+ }
33
+ /** `2026-08-08 14:03:07` + a zone suffix — ISO-ordered so it sorts and
34
+ * compares visually (design doc §7.2). Only UTC is implemented (`Z`
35
+ * suffix, always): the Africa/Douala toggle lives on the top bar, which
36
+ * this screen doesn't build. "A bare local time with no zone label never
37
+ * appears anywhere in this product" still holds — the suffix is always
38
+ * present, just not yet switchable. */
39
+ function formatAbsolute(date) {
40
+ const y = date.getUTCFullYear();
41
+ const mo = pad(date.getUTCMonth() + 1);
42
+ const d = pad(date.getUTCDate());
43
+ const h = pad(date.getUTCHours());
44
+ const mi = pad(date.getUTCMinutes());
45
+ const s = pad(date.getUTCSeconds());
46
+ return `${y}-${mo}-${d} ${h}:${mi}:${s}Z`;
47
+ }
48
+ function formatRelative(diffMs) {
49
+ const minutes = Math.floor(diffMs / 60_000);
50
+ if (minutes < 1)
51
+ return "just now";
52
+ if (minutes < 60)
53
+ return `${minutes}m`;
54
+ const hours = Math.floor(minutes / 60);
55
+ return `${hours}h`;
56
+ }
57
+ /**
58
+ * Relative for anything under 24h (`2m`, `47m`, `6h`), absolute otherwise
59
+ * — design doc §7.2. Renders the absolute value on the server and on
60
+ * first client render (so server/client markup matches and Next doesn't
61
+ * warn/flash), then upgrades to relative once mounted, driven by the
62
+ * shared interval above rather than its own timer.
63
+ */
64
+ export function TimestampDisplay({ value, className }) {
65
+ useSharedTick();
66
+ const [hydrated, setHydrated] = useState(false);
67
+ useEffect(() => setHydrated(true), []);
68
+ const date = new Date(value);
69
+ const absolute = formatAbsolute(date);
70
+ if (!hydrated) {
71
+ return (_jsx("span", { className: cn("font-mono text-subtle-foreground tabular-nums", className), children: absolute }));
72
+ }
73
+ const diffMs = Date.now() - date.getTime();
74
+ const display = diffMs >= 0 && diffMs < 24 * 3600 * 1000 ? formatRelative(diffMs) : absolute;
75
+ return (_jsx("span", { title: absolute, className: cn("font-mono text-subtle-foreground tabular-nums", className), children: display }));
76
+ }
77
+ //# sourceMappingURL=timestamp-display.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timestamp-display.js","sourceRoot":"","sources":["../../../src/components/data/timestamp-display.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAClE,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAElC,0EAA0E;AAC1E,0EAA0E;AAC1E,uEAAuE;AACvE,mCAAmC;AAEnC,IAAI,IAAI,GAAG,CAAC,CAAC;AACb,MAAM,SAAS,GAAG,IAAI,GAAG,EAAc,CAAC;AACxC,IAAI,KAAK,GAA0C,IAAI,CAAC;AAExD,SAAS,SAAS,CAAC,QAAoB;IACrC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACxB,KAAK,KAAK,WAAW,CAAC,GAAG,EAAE;QACzB,IAAI,IAAI,CAAC,CAAC;QACV,KAAK,MAAM,CAAC,IAAI,SAAS;YAAE,CAAC,EAAE,CAAC;IACjC,CAAC,EAAE,MAAM,CAAC,CAAC;IACX,OAAO,GAAG,EAAE;QACV,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC3B,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YAC3C,aAAa,CAAC,KAAK,CAAC,CAAC;YACrB,KAAK,GAAG,IAAI,CAAC;QACf,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,aAAa;IACpB,OAAO,oBAAoB,CACzB,SAAS,EACT,GAAG,EAAE,CAAC,IAAI,EACV,GAAG,EAAE,CAAC,CAAC,CACR,CAAC;AACJ,CAAC;AAED,SAAS,GAAG,CAAC,CAAS;IACpB,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AACpC,CAAC;AAED;;;;;uCAKuC;AACvC,SAAS,cAAc,CAAC,IAAU;IAChC,MAAM,CAAC,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;IAChC,MAAM,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC;IACvC,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;IACjC,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;IAClC,MAAM,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC;IACrC,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC;IACpC,OAAO,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC;AAC5C,CAAC;AAED,SAAS,cAAc,CAAC,MAAc;IACpC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IAC5C,IAAI,OAAO,GAAG,CAAC;QAAE,OAAO,UAAU,CAAC;IACnC,IAAI,OAAO,GAAG,EAAE;QAAE,OAAO,GAAG,OAAO,GAAG,CAAC;IACvC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IACvC,OAAO,GAAG,KAAK,GAAG,CAAC;AACrB,CAAC;AAQD;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,EAAE,KAAK,EAAE,SAAS,EAAyB;IAC1E,aAAa,EAAE,CAAC;IAChB,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAChD,SAAS,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;IAEvC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7B,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IAEtC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,CACL,eAAM,SAAS,EAAE,EAAE,CAAC,+CAA+C,EAAE,SAAS,CAAC,YAC5E,QAAQ,GACJ,CACR,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;IAC3C,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IAE7F,OAAO,CACL,eACE,KAAK,EAAE,QAAQ,EACf,SAAS,EAAE,EAAE,CAAC,+CAA+C,EAAE,SAAS,CAAC,YAExE,OAAO,GACH,CACR,CAAC;AACJ,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { ReactNode } from "react";
2
+ export interface InlineBannerProps {
3
+ /** `'neutral'` — a standing notice (scope, caveat). `'danger'` — an
4
+ * error. `'warning'` — recoverable, needs attention (a stale write).
5
+ * `'success'` — a positive confirmation (a verified audit chain).
6
+ * `'uncertain'` — degraded or unknown, neither failure nor success (a
7
+ * stalled live feed, a UCS-2 volume spike). `'plain'` — a caption-only
8
+ * note with no border or fill, for something that doesn't need the
9
+ * weight of a bordered box.
10
+ *
11
+ * The last three were added after the R6 factorization, not with it:
12
+ * four route groups had hand-rolled boxes in exactly these tones because
13
+ * the variant they needed did not exist, and the agents doing the
14
+ * factorization were deliberately barred from editing this package. Two
15
+ * of them flagged the gap rather than inventing a competing component,
16
+ * which is the behaviour the constraint was for. */
17
+ variant?: "neutral" | "danger" | "warning" | "success" | "uncertain" | "plain";
18
+ children: ReactNode;
19
+ className?: string;
20
+ }
21
+ export declare function InlineBanner({ variant, children, className }: InlineBannerProps): import("react").JSX.Element;
22
+ //# sourceMappingURL=inline-banner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inline-banner.d.ts","sourceRoot":"","sources":["../../../src/components/patterns/inline-banner.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAiBvC,MAAM,WAAW,iBAAiB;IAChC;;;;;;;;;;;;;wDAaoD;IACpD,OAAO,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,OAAO,CAAC;IAC/E,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,YAAY,CAAC,EAAE,OAAmB,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,iBAAiB,+BAsB3F"}
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { cn } from "../../lib/cn.js";
3
+ export function InlineBanner({ variant = "neutral", children, className }) {
4
+ return (_jsx("div", { className: cn("text-caption", variant === "neutral" &&
5
+ "rounded-sm border border-edge bg-surface-2 px-3 py-2 text-muted-foreground", variant === "danger" &&
6
+ "rounded-sm border border-state-danger-border bg-state-danger-bg px-3 py-2 text-state-danger-fg", variant === "warning" &&
7
+ "rounded-sm border border-state-warning-border bg-state-warning-bg px-3 py-2 text-state-warning-fg", variant === "success" &&
8
+ "rounded-sm border border-state-success-border bg-state-success-bg px-3 py-2 text-state-success-fg", variant === "uncertain" &&
9
+ "rounded-sm border border-state-uncertain-border bg-state-uncertain-bg px-3 py-2 text-state-uncertain-fg", variant === "plain" && "text-subtle-foreground", className), children: children }));
10
+ }
11
+ //# sourceMappingURL=inline-banner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inline-banner.js","sourceRoot":"","sources":["../../../src/components/patterns/inline-banner.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAoClC,MAAM,UAAU,YAAY,CAAC,EAAE,OAAO,GAAG,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAqB;IAC1F,OAAO,CACL,cACE,SAAS,EAAE,EAAE,CACX,cAAc,EACd,OAAO,KAAK,SAAS;YACnB,4EAA4E,EAC9E,OAAO,KAAK,QAAQ;YAClB,gGAAgG,EAClG,OAAO,KAAK,SAAS;YACnB,mGAAmG,EACrG,OAAO,KAAK,SAAS;YACnB,mGAAmG,EACrG,OAAO,KAAK,WAAW;YACrB,yGAAyG,EAC3G,OAAO,KAAK,OAAO,IAAI,wBAAwB,EAC/C,SAAS,CACV,YAEA,QAAQ,GACL,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { ReactNode } from "react";
2
+ export interface InlineEmptyStateProps {
3
+ message: ReactNode;
4
+ action?: {
5
+ label: string;
6
+ onClick: () => void;
7
+ };
8
+ /** `'standalone'` is the one exception (§5.3): a screen with nothing else
9
+ * to do may centre a single line plus one primary action. Still no
10
+ * illustration, still no card. */
11
+ variant?: "inline" | "standalone";
12
+ className?: string;
13
+ }
14
+ /**
15
+ * Enforces the binding rule: empty states are inline status lines, not
16
+ * centred placards. Use inside a table body (spanning all columns) or in
17
+ * the panel where the missing list would be.
18
+ */
19
+ export declare function InlineEmptyState({ message, action, variant, className, }: InlineEmptyStateProps): import("react").JSX.Element;
20
+ //# sourceMappingURL=inline-empty-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inline-empty-state.d.ts","sourceRoot":"","sources":["../../../src/components/patterns/inline-empty-state.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,SAAS,CAAC;IACnB,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC;IAChD;;sCAEkC;IAClC,OAAO,CAAC,EAAE,QAAQ,GAAG,YAAY,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,OAAO,EACP,MAAM,EACN,OAAkB,EAClB,SAAS,GACV,EAAE,qBAAqB,+BAqBvB"}
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cn } from "../../lib/cn.js";
3
+ /**
4
+ * Enforces the binding rule: empty states are inline status lines, not
5
+ * centred placards. Use inside a table body (spanning all columns) or in
6
+ * the panel where the missing list would be.
7
+ */
8
+ export function InlineEmptyState({ message, action, variant = "inline", className, }) {
9
+ return (_jsxs("div", { className: cn("flex items-center gap-3 text-body text-muted-foreground", variant === "standalone" ? "justify-center py-16 text-center" : "py-3 text-left", className), children: [_jsx("span", { children: message }), action != null && (_jsx("button", { type: "button", onClick: action.onClick, className: "text-foreground underline decoration-edge-strong underline-offset-2 hover:decoration-foreground", children: action.label }))] }));
10
+ }
11
+ //# sourceMappingURL=inline-empty-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inline-empty-state.js","sourceRoot":"","sources":["../../../src/components/patterns/inline-empty-state.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAYlC;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,EAC/B,OAAO,EACP,MAAM,EACN,OAAO,GAAG,QAAQ,EAClB,SAAS,GACa;IACtB,OAAO,CACL,eACE,SAAS,EAAE,EAAE,CACX,yDAAyD,EACzD,OAAO,KAAK,YAAY,CAAC,CAAC,CAAC,kCAAkC,CAAC,CAAC,CAAC,gBAAgB,EAChF,SAAS,CACV,aAED,yBAAO,OAAO,GAAQ,EACrB,MAAM,IAAI,IAAI,IAAI,CACjB,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,MAAM,CAAC,OAAO,EACvB,SAAS,EAAC,iGAAiG,YAE1G,MAAM,CAAC,KAAK,GACN,CACV,IACG,CACP,CAAC;AACJ,CAAC"}