@inui/design-system 0.0.0-stage → 1.22.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 (312) hide show
  1. package/README.md +360 -2
  2. package/dist/components/ui/accordion.d.ts +44 -0
  3. package/dist/components/ui/accordion.d.ts.map +1 -0
  4. package/dist/components/ui/accordion.js +86 -0
  5. package/dist/components/ui/accordion.js.map +1 -0
  6. package/dist/components/ui/ai-avatar.d.ts +46 -0
  7. package/dist/components/ui/ai-avatar.d.ts.map +1 -0
  8. package/dist/components/ui/ai-avatar.js +43 -0
  9. package/dist/components/ui/ai-avatar.js.map +1 -0
  10. package/dist/components/ui/ai-label.d.ts +118 -0
  11. package/dist/components/ui/ai-label.d.ts.map +1 -0
  12. package/dist/components/ui/ai-label.js +184 -0
  13. package/dist/components/ui/ai-label.js.map +1 -0
  14. package/dist/components/ui/ai-sparkle.d.ts +91 -0
  15. package/dist/components/ui/ai-sparkle.d.ts.map +1 -0
  16. package/dist/components/ui/ai-sparkle.js +200 -0
  17. package/dist/components/ui/ai-sparkle.js.map +1 -0
  18. package/dist/components/ui/alert-dialog.d.ts +79 -0
  19. package/dist/components/ui/alert-dialog.d.ts.map +1 -0
  20. package/dist/components/ui/alert-dialog.js +147 -0
  21. package/dist/components/ui/alert-dialog.js.map +1 -0
  22. package/dist/components/ui/alert.d.ts +71 -0
  23. package/dist/components/ui/alert.d.ts.map +1 -0
  24. package/dist/components/ui/alert.js +108 -0
  25. package/dist/components/ui/alert.js.map +1 -0
  26. package/dist/components/ui/aspect-ratio.d.ts +30 -0
  27. package/dist/components/ui/aspect-ratio.d.ts.map +1 -0
  28. package/dist/components/ui/aspect-ratio.js +40 -0
  29. package/dist/components/ui/aspect-ratio.js.map +1 -0
  30. package/dist/components/ui/attachment.d.ts +74 -0
  31. package/dist/components/ui/attachment.d.ts.map +1 -0
  32. package/dist/components/ui/attachment.js +142 -0
  33. package/dist/components/ui/attachment.js.map +1 -0
  34. package/dist/components/ui/avatar.d.ts +82 -0
  35. package/dist/components/ui/avatar.d.ts.map +1 -0
  36. package/dist/components/ui/avatar.js +123 -0
  37. package/dist/components/ui/avatar.js.map +1 -0
  38. package/dist/components/ui/badge.d.ts +130 -0
  39. package/dist/components/ui/badge.d.ts.map +1 -0
  40. package/dist/components/ui/badge.js +226 -0
  41. package/dist/components/ui/badge.js.map +1 -0
  42. package/dist/components/ui/breadcrumb.d.ts +43 -0
  43. package/dist/components/ui/breadcrumb.d.ts.map +1 -0
  44. package/dist/components/ui/breadcrumb.js +98 -0
  45. package/dist/components/ui/breadcrumb.js.map +1 -0
  46. package/dist/components/ui/browser-tabs.d.ts +218 -0
  47. package/dist/components/ui/browser-tabs.d.ts.map +1 -0
  48. package/dist/components/ui/browser-tabs.js +528 -0
  49. package/dist/components/ui/browser-tabs.js.map +1 -0
  50. package/dist/components/ui/bubble.d.ts +80 -0
  51. package/dist/components/ui/bubble.d.ts.map +1 -0
  52. package/dist/components/ui/bubble.js +235 -0
  53. package/dist/components/ui/bubble.js.map +1 -0
  54. package/dist/components/ui/button-group.d.ts +60 -0
  55. package/dist/components/ui/button-group.d.ts.map +1 -0
  56. package/dist/components/ui/button-group.js +89 -0
  57. package/dist/components/ui/button-group.js.map +1 -0
  58. package/dist/components/ui/button.d.ts +157 -0
  59. package/dist/components/ui/button.d.ts.map +1 -0
  60. package/dist/components/ui/button.js +144 -0
  61. package/dist/components/ui/button.js.map +1 -0
  62. package/dist/components/ui/calendar.d.ts +57 -0
  63. package/dist/components/ui/calendar.d.ts.map +1 -0
  64. package/dist/components/ui/calendar.js +163 -0
  65. package/dist/components/ui/calendar.js.map +1 -0
  66. package/dist/components/ui/card.d.ts +96 -0
  67. package/dist/components/ui/card.d.ts.map +1 -0
  68. package/dist/components/ui/card.js +131 -0
  69. package/dist/components/ui/card.js.map +1 -0
  70. package/dist/components/ui/carousel.d.ts +86 -0
  71. package/dist/components/ui/carousel.d.ts.map +1 -0
  72. package/dist/components/ui/carousel.js +207 -0
  73. package/dist/components/ui/carousel.js.map +1 -0
  74. package/dist/components/ui/checkbox.d.ts +54 -0
  75. package/dist/components/ui/checkbox.d.ts.map +1 -0
  76. package/dist/components/ui/checkbox.js +78 -0
  77. package/dist/components/ui/checkbox.js.map +1 -0
  78. package/dist/components/ui/collapsible.d.ts +45 -0
  79. package/dist/components/ui/collapsible.d.ts.map +1 -0
  80. package/dist/components/ui/collapsible.js +65 -0
  81. package/dist/components/ui/collapsible.js.map +1 -0
  82. package/dist/components/ui/combobox.d.ts +111 -0
  83. package/dist/components/ui/combobox.d.ts.map +1 -0
  84. package/dist/components/ui/combobox.js +264 -0
  85. package/dist/components/ui/combobox.js.map +1 -0
  86. package/dist/components/ui/command.d.ts +71 -0
  87. package/dist/components/ui/command.d.ts.map +1 -0
  88. package/dist/components/ui/command.js +133 -0
  89. package/dist/components/ui/command.js.map +1 -0
  90. package/dist/components/ui/context-menu.d.ts +70 -0
  91. package/dist/components/ui/context-menu.d.ts.map +1 -0
  92. package/dist/components/ui/context-menu.js +163 -0
  93. package/dist/components/ui/context-menu.js.map +1 -0
  94. package/dist/components/ui/count-badge.d.ts +40 -0
  95. package/dist/components/ui/count-badge.d.ts.map +1 -0
  96. package/dist/components/ui/count-badge.js +43 -0
  97. package/dist/components/ui/count-badge.js.map +1 -0
  98. package/dist/components/ui/data-table.d.ts +1026 -0
  99. package/dist/components/ui/data-table.d.ts.map +1 -0
  100. package/dist/components/ui/data-table.js +3423 -0
  101. package/dist/components/ui/data-table.js.map +1 -0
  102. package/dist/components/ui/dialog.d.ts +73 -0
  103. package/dist/components/ui/dialog.d.ts.map +1 -0
  104. package/dist/components/ui/dialog.js +145 -0
  105. package/dist/components/ui/dialog.js.map +1 -0
  106. package/dist/components/ui/direction.d.ts +35 -0
  107. package/dist/components/ui/direction.d.ts.map +1 -0
  108. package/dist/components/ui/direction.js +35 -0
  109. package/dist/components/ui/direction.js.map +1 -0
  110. package/dist/components/ui/drawer.d.ts +53 -0
  111. package/dist/components/ui/drawer.d.ts.map +1 -0
  112. package/dist/components/ui/drawer.js +115 -0
  113. package/dist/components/ui/drawer.js.map +1 -0
  114. package/dist/components/ui/dropdown-menu.d.ts +75 -0
  115. package/dist/components/ui/dropdown-menu.d.ts.map +1 -0
  116. package/dist/components/ui/dropdown-menu.js +173 -0
  117. package/dist/components/ui/dropdown-menu.js.map +1 -0
  118. package/dist/components/ui/dropzone.d.ts +141 -0
  119. package/dist/components/ui/dropzone.d.ts.map +1 -0
  120. package/dist/components/ui/dropzone.js +257 -0
  121. package/dist/components/ui/dropzone.js.map +1 -0
  122. package/dist/components/ui/empty.d.ts +94 -0
  123. package/dist/components/ui/empty.d.ts.map +1 -0
  124. package/dist/components/ui/empty.js +149 -0
  125. package/dist/components/ui/empty.js.map +1 -0
  126. package/dist/components/ui/field.d.ts +122 -0
  127. package/dist/components/ui/field.d.ts.map +1 -0
  128. package/dist/components/ui/field.js +254 -0
  129. package/dist/components/ui/field.js.map +1 -0
  130. package/dist/components/ui/hover-card.d.ts +51 -0
  131. package/dist/components/ui/hover-card.d.ts.map +1 -0
  132. package/dist/components/ui/hover-card.js +101 -0
  133. package/dist/components/ui/hover-card.js.map +1 -0
  134. package/dist/components/ui/input-group.d.ts +62 -0
  135. package/dist/components/ui/input-group.d.ts.map +1 -0
  136. package/dist/components/ui/input-group.js +115 -0
  137. package/dist/components/ui/input-group.js.map +1 -0
  138. package/dist/components/ui/input-otp.d.ts +52 -0
  139. package/dist/components/ui/input-otp.d.ts.map +1 -0
  140. package/dist/components/ui/input-otp.js +89 -0
  141. package/dist/components/ui/input-otp.js.map +1 -0
  142. package/dist/components/ui/input.d.ts +47 -0
  143. package/dist/components/ui/input.d.ts.map +1 -0
  144. package/dist/components/ui/input.js +47 -0
  145. package/dist/components/ui/input.js.map +1 -0
  146. package/dist/components/ui/item.d.ts +74 -0
  147. package/dist/components/ui/item.d.ts.map +1 -0
  148. package/dist/components/ui/item.js +176 -0
  149. package/dist/components/ui/item.js.map +1 -0
  150. package/dist/components/ui/kbd.d.ts +41 -0
  151. package/dist/components/ui/kbd.d.ts.map +1 -0
  152. package/dist/components/ui/kbd.js +58 -0
  153. package/dist/components/ui/kbd.js.map +1 -0
  154. package/dist/components/ui/key-value-pair.d.ts +56 -0
  155. package/dist/components/ui/key-value-pair.d.ts.map +1 -0
  156. package/dist/components/ui/key-value-pair.js +110 -0
  157. package/dist/components/ui/key-value-pair.js.map +1 -0
  158. package/dist/components/ui/label.d.ts +83 -0
  159. package/dist/components/ui/label.d.ts.map +1 -0
  160. package/dist/components/ui/label.js +85 -0
  161. package/dist/components/ui/label.js.map +1 -0
  162. package/dist/components/ui/marker.d.ts +54 -0
  163. package/dist/components/ui/marker.d.ts.map +1 -0
  164. package/dist/components/ui/marker.js +79 -0
  165. package/dist/components/ui/marker.js.map +1 -0
  166. package/dist/components/ui/menubar.d.ts +72 -0
  167. package/dist/components/ui/menubar.d.ts.map +1 -0
  168. package/dist/components/ui/menubar.js +174 -0
  169. package/dist/components/ui/menubar.js.map +1 -0
  170. package/dist/components/ui/message-scroller.d.ts +53 -0
  171. package/dist/components/ui/message-scroller.d.ts.map +1 -0
  172. package/dist/components/ui/message-scroller.js +95 -0
  173. package/dist/components/ui/message-scroller.js.map +1 -0
  174. package/dist/components/ui/message.d.ts +63 -0
  175. package/dist/components/ui/message.d.ts.map +1 -0
  176. package/dist/components/ui/message.js +92 -0
  177. package/dist/components/ui/message.js.map +1 -0
  178. package/dist/components/ui/meta-list.d.ts +55 -0
  179. package/dist/components/ui/meta-list.d.ts.map +1 -0
  180. package/dist/components/ui/meta-list.js +75 -0
  181. package/dist/components/ui/meta-list.js.map +1 -0
  182. package/dist/components/ui/native-select.d.ts +51 -0
  183. package/dist/components/ui/native-select.d.ts.map +1 -0
  184. package/dist/components/ui/native-select.js +75 -0
  185. package/dist/components/ui/native-select.js.map +1 -0
  186. package/dist/components/ui/navigation-menu.d.ts +56 -0
  187. package/dist/components/ui/navigation-menu.d.ts.map +1 -0
  188. package/dist/components/ui/navigation-menu.js +116 -0
  189. package/dist/components/ui/navigation-menu.js.map +1 -0
  190. package/dist/components/ui/page-header.d.ts +223 -0
  191. package/dist/components/ui/page-header.d.ts.map +1 -0
  192. package/dist/components/ui/page-header.js +233 -0
  193. package/dist/components/ui/page-header.js.map +1 -0
  194. package/dist/components/ui/pagination.d.ts +68 -0
  195. package/dist/components/ui/pagination.d.ts.map +1 -0
  196. package/dist/components/ui/pagination.js +145 -0
  197. package/dist/components/ui/pagination.js.map +1 -0
  198. package/dist/components/ui/popover.d.ts +61 -0
  199. package/dist/components/ui/popover.d.ts.map +1 -0
  200. package/dist/components/ui/popover.js +144 -0
  201. package/dist/components/ui/popover.js.map +1 -0
  202. package/dist/components/ui/progress.d.ts +35 -0
  203. package/dist/components/ui/progress.d.ts.map +1 -0
  204. package/dist/components/ui/progress.js +46 -0
  205. package/dist/components/ui/progress.js.map +1 -0
  206. package/dist/components/ui/questionnaire.d.ts +92 -0
  207. package/dist/components/ui/questionnaire.d.ts.map +1 -0
  208. package/dist/components/ui/questionnaire.js +277 -0
  209. package/dist/components/ui/questionnaire.js.map +1 -0
  210. package/dist/components/ui/radio-group.d.ts +50 -0
  211. package/dist/components/ui/radio-group.d.ts.map +1 -0
  212. package/dist/components/ui/radio-group.js +65 -0
  213. package/dist/components/ui/radio-group.js.map +1 -0
  214. package/dist/components/ui/resizable.d.ts +44 -0
  215. package/dist/components/ui/resizable.d.ts.map +1 -0
  216. package/dist/components/ui/resizable.js +73 -0
  217. package/dist/components/ui/resizable.js.map +1 -0
  218. package/dist/components/ui/scroll-area.d.ts +55 -0
  219. package/dist/components/ui/scroll-area.d.ts.map +1 -0
  220. package/dist/components/ui/scroll-area.js +72 -0
  221. package/dist/components/ui/scroll-area.js.map +1 -0
  222. package/dist/components/ui/select.d.ts +274 -0
  223. package/dist/components/ui/select.d.ts.map +1 -0
  224. package/dist/components/ui/select.js +609 -0
  225. package/dist/components/ui/select.js.map +1 -0
  226. package/dist/components/ui/separator.d.ts +31 -0
  227. package/dist/components/ui/separator.d.ts.map +1 -0
  228. package/dist/components/ui/separator.js +38 -0
  229. package/dist/components/ui/separator.js.map +1 -0
  230. package/dist/components/ui/sheet.d.ts +59 -0
  231. package/dist/components/ui/sheet.d.ts.map +1 -0
  232. package/dist/components/ui/sheet.js +128 -0
  233. package/dist/components/ui/sheet.js.map +1 -0
  234. package/dist/components/ui/sidebar.d.ts +166 -0
  235. package/dist/components/ui/sidebar.d.ts.map +1 -0
  236. package/dist/components/ui/sidebar.js +512 -0
  237. package/dist/components/ui/sidebar.js.map +1 -0
  238. package/dist/components/ui/skeleton.d.ts +35 -0
  239. package/dist/components/ui/skeleton.d.ts.map +1 -0
  240. package/dist/components/ui/skeleton.js +46 -0
  241. package/dist/components/ui/skeleton.js.map +1 -0
  242. package/dist/components/ui/slider.d.ts +39 -0
  243. package/dist/components/ui/slider.d.ts.map +1 -0
  244. package/dist/components/ui/slider.js +75 -0
  245. package/dist/components/ui/slider.js.map +1 -0
  246. package/dist/components/ui/sonner.d.ts +56 -0
  247. package/dist/components/ui/sonner.d.ts.map +1 -0
  248. package/dist/components/ui/sonner.js +96 -0
  249. package/dist/components/ui/sonner.js.map +1 -0
  250. package/dist/components/ui/spinner.d.ts +37 -0
  251. package/dist/components/ui/spinner.d.ts.map +1 -0
  252. package/dist/components/ui/spinner.js +51 -0
  253. package/dist/components/ui/spinner.js.map +1 -0
  254. package/dist/components/ui/stepper.d.ts +84 -0
  255. package/dist/components/ui/stepper.d.ts.map +1 -0
  256. package/dist/components/ui/stepper.js +145 -0
  257. package/dist/components/ui/stepper.js.map +1 -0
  258. package/dist/components/ui/switch.d.ts +36 -0
  259. package/dist/components/ui/switch.d.ts.map +1 -0
  260. package/dist/components/ui/switch.js +44 -0
  261. package/dist/components/ui/switch.js.map +1 -0
  262. package/dist/components/ui/table.d.ts +80 -0
  263. package/dist/components/ui/table.d.ts.map +1 -0
  264. package/dist/components/ui/table.js +130 -0
  265. package/dist/components/ui/table.js.map +1 -0
  266. package/dist/components/ui/tabs.d.ts +87 -0
  267. package/dist/components/ui/tabs.d.ts.map +1 -0
  268. package/dist/components/ui/tabs.js +128 -0
  269. package/dist/components/ui/tabs.js.map +1 -0
  270. package/dist/components/ui/textarea.d.ts +35 -0
  271. package/dist/components/ui/textarea.d.ts.map +1 -0
  272. package/dist/components/ui/textarea.js +38 -0
  273. package/dist/components/ui/textarea.js.map +1 -0
  274. package/dist/components/ui/time-picker.d.ts +58 -0
  275. package/dist/components/ui/time-picker.d.ts.map +1 -0
  276. package/dist/components/ui/time-picker.js +188 -0
  277. package/dist/components/ui/time-picker.js.map +1 -0
  278. package/dist/components/ui/toggle-group.d.ts +52 -0
  279. package/dist/components/ui/toggle-group.d.ts.map +1 -0
  280. package/dist/components/ui/toggle-group.js +94 -0
  281. package/dist/components/ui/toggle-group.js.map +1 -0
  282. package/dist/components/ui/toggle.d.ts +50 -0
  283. package/dist/components/ui/toggle.d.ts.map +1 -0
  284. package/dist/components/ui/toggle.js +70 -0
  285. package/dist/components/ui/toggle.js.map +1 -0
  286. package/dist/components/ui/tooltip.d.ts +51 -0
  287. package/dist/components/ui/tooltip.d.ts.map +1 -0
  288. package/dist/components/ui/tooltip.js +78 -0
  289. package/dist/components/ui/tooltip.js.map +1 -0
  290. package/dist/hooks/use-dark-mode.d.ts +2 -0
  291. package/dist/hooks/use-dark-mode.d.ts.map +1 -0
  292. package/dist/hooks/use-dark-mode.js +36 -0
  293. package/dist/hooks/use-dark-mode.js.map +1 -0
  294. package/dist/hooks/use-mobile.d.ts +2 -0
  295. package/dist/hooks/use-mobile.d.ts.map +1 -0
  296. package/dist/hooks/use-mobile.js +20 -0
  297. package/dist/hooks/use-mobile.js.map +1 -0
  298. package/dist/index.d.ts +88 -0
  299. package/dist/index.d.ts.map +1 -0
  300. package/dist/index.js +77 -0
  301. package/dist/lib/scope.d.ts +64 -0
  302. package/dist/lib/scope.d.ts.map +1 -0
  303. package/dist/lib/scope.js +74 -0
  304. package/dist/lib/scope.js.map +1 -0
  305. package/dist/lib/utils.d.ts +3 -0
  306. package/dist/lib/utils.d.ts.map +1 -0
  307. package/dist/lib/utils.js +11 -0
  308. package/dist/lib/utils.js.map +1 -0
  309. package/dist/styles.css +2 -0
  310. package/dist/theme-tokens.css +537 -0
  311. package/dist/theme.css +417 -0
  312. package/package.json +103 -3
@@ -0,0 +1,226 @@
1
+ import { cn } from "../../lib/utils.js";
2
+ import * as React from "react";
3
+ import { Slot } from "radix-ui";
4
+ import { jsx } from "react/jsx-runtime";
5
+ import { cva } from "class-variance-authority";
6
+ //#region src/components/ui/badge.tsx
7
+ /**
8
+ * Badge — inline status/category/count label.
9
+ *
10
+ * cva-driven span, non-interactive by default. Styled on two axes — `tone`
11
+ * (what it means) × `emphasis` (how loudly it's drawn) — with the old single
12
+ * `variant` list kept as a deprecated alias.
13
+ */
14
+ var badgeVariants = cva("group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-colors focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!", {
15
+ variants: {
16
+ tone: {
17
+ default: "",
18
+ secondary: "",
19
+ destructive: ""
20
+ },
21
+ emphasis: {
22
+ filled: "",
23
+ outline: "",
24
+ ghost: ""
25
+ }
26
+ },
27
+ compoundVariants: [
28
+ {
29
+ tone: "default",
30
+ emphasis: "filled",
31
+ class: "bg-primary text-primary-foreground [a]:hover:bg-primary-hover [a]:active:bg-primary-active"
32
+ },
33
+ {
34
+ tone: "secondary",
35
+ emphasis: "filled",
36
+ class: "bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80"
37
+ },
38
+ {
39
+ tone: "destructive",
40
+ emphasis: "filled",
41
+ class: "bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20"
42
+ },
43
+ {
44
+ tone: "default",
45
+ emphasis: "outline",
46
+ class: "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground"
47
+ },
48
+ {
49
+ tone: "secondary",
50
+ emphasis: "outline",
51
+ class: "border-border text-muted-foreground [a]:hover:bg-muted"
52
+ },
53
+ {
54
+ tone: "destructive",
55
+ emphasis: "outline",
56
+ class: "border-destructive/40 text-destructive focus-visible:ring-destructive/20 [a]:hover:bg-destructive/10"
57
+ },
58
+ {
59
+ tone: "default",
60
+ emphasis: "ghost",
61
+ class: "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50"
62
+ },
63
+ {
64
+ tone: "secondary",
65
+ emphasis: "ghost",
66
+ class: "text-muted-foreground hover:bg-muted dark:hover:bg-muted/50"
67
+ },
68
+ {
69
+ tone: "destructive",
70
+ emphasis: "ghost",
71
+ class: "text-destructive hover:bg-destructive/10 dark:hover:bg-destructive/20"
72
+ }
73
+ ],
74
+ defaultVariants: {
75
+ tone: "default",
76
+ emphasis: "filled"
77
+ }
78
+ });
79
+ var LEGACY_VARIANT = {
80
+ default: {
81
+ tone: "default",
82
+ emphasis: "filled"
83
+ },
84
+ secondary: {
85
+ tone: "secondary",
86
+ emphasis: "filled"
87
+ },
88
+ destructive: {
89
+ tone: "destructive",
90
+ emphasis: "filled"
91
+ },
92
+ outline: {
93
+ tone: "default",
94
+ emphasis: "outline"
95
+ },
96
+ ghost: {
97
+ tone: "default",
98
+ emphasis: "ghost"
99
+ }
100
+ };
101
+ function Badge({ className, tone, emphasis, variant, asChild = false, truncate = false, maxWidth, style, children, title, ...props }) {
102
+ const Comp = asChild ? Slot.Root : "span";
103
+ const legacy = variant && variant !== "link" ? LEGACY_VARIANT[variant] : void 0;
104
+ const resolvedTone = tone ?? legacy?.tone ?? "default";
105
+ const resolvedEmphasis = emphasis ?? legacy?.emphasis ?? (variant === "link" ? "ghost" : "filled");
106
+ const truncating = !asChild && (truncate || maxWidth !== void 0);
107
+ const content = truncating ? React.Children.map(children, (child) => typeof child === "string" || typeof child === "number" ? /* @__PURE__ */ jsx("span", {
108
+ className: "min-w-0 truncate",
109
+ children: child
110
+ }) : child) : children;
111
+ const fullLabel = title ?? (truncating ? React.Children.toArray(children).filter((c) => typeof c === "string" || typeof c === "number").join("") || void 0 : void 0);
112
+ return /* @__PURE__ */ jsx(Comp, {
113
+ "data-slot": "badge",
114
+ "data-tone": resolvedTone,
115
+ "data-emphasis": resolvedEmphasis,
116
+ "data-variant": variant,
117
+ className: cn(badgeVariants({
118
+ tone: resolvedTone,
119
+ emphasis: resolvedEmphasis
120
+ }), variant === "link" && "text-primary underline-offset-4 hover:bg-transparent hover:text-primary hover:underline", truncating && "max-w-full min-w-0", className),
121
+ style: maxWidth !== void 0 ? {
122
+ maxWidth,
123
+ ...style
124
+ } : style,
125
+ title: fullLabel,
126
+ ...props,
127
+ children: content
128
+ });
129
+ }
130
+ /**
131
+ * WHEN TO USE
132
+ * - A status, category, count, or tag shown inline with other content
133
+ * (row status, list tag, small metadata chip).
134
+ * - An operational-status indicator (active, failed, expiring, pending) —
135
+ * emphasis="outline" with a small colored icon, not a filled badge. This
136
+ * is Badge's status-indicator convention; there's no separate component
137
+ * for it.
138
+ *
139
+ * NOT WHEN
140
+ * - Interactive filters or removable tags — those need their own
141
+ * click/remove handling, which Badge doesn't provide.
142
+ * - An action — use Button.
143
+ * - Long text — Badge is sized and padded for short labels only. When a user-supplied label might run long anyway (a role or tag name), cap it with `maxWidth` / `truncate`.
144
+ *
145
+ * KEY RULES
146
+ * - `truncate` / `maxWidth` ellipsize a long label and show the full text as a native `title`; icons are untouched. They don't apply with `asChild`.
147
+ * - Non-interactive by default; pass `asChild` to render as an `<a>` when
148
+ * the badge itself needs to link somewhere.
149
+ * - Two axes, not one list. tone: default | secondary | destructive — what the
150
+ * label means. emphasis: filled | outline | ghost — how loudly it's drawn.
151
+ * Every tone×emphasis pair is styled; omit both for a filled default badge.
152
+ * The old single `variant` prop (default, secondary, destructive, outline,
153
+ * ghost, link) still renders identically but is deprecated — it folded the
154
+ * two axes into one list. `link` has no new-axis equivalent: a Badge is
155
+ * non-interactive, so an underlined link look belongs on Button/anchor.
156
+ * - Custom semantic colors (success/warning/alert/info) aren't separate
157
+ * variants — apply the token utility directly, using each status's
158
+ * subtle `-light`/`-text` pair (not the solid `-foreground` pairing,
159
+ * which reads too loud for an inline tag), e.g. `className="bg-success-light
160
+ * text-success-text"`.
161
+ * - Status-indicator convention: emphasis="outline" + a leading icon colored
162
+ * with the matching semantic token, `data-icon="inline-start"`. Fixed
163
+ * icon/color pairing, don't substitute other icons for these:
164
+ * success -> CheckIcon text-success
165
+ * alert -> XIcon text-alert (text-destructive for a true error, not just "alert")
166
+ * warning -> TriangleAlertIcon text-warning
167
+ * info -> InfoIcon text-info
168
+ * default -> PenLineIcon text-muted-foreground
169
+ * - Flush status-indicator variant: the same icon/color pairing above, but
170
+ * `emphasis="ghost"` (no border, no fill) plus
171
+ * `className="px-0 has-data-[icon=inline-start]:pl-0 has-data-[icon=inline-end]:pr-0 hover:bg-transparent"`
172
+ * — the padding overrides zero out what `emphasis="outline"` needs for
173
+ * its own chip look but this doesn't, and `hover:bg-transparent` drops
174
+ * `ghost`'s subtle hover highlight (meant for when Badge is `asChild` as
175
+ * a real link), which a flush, non-interactive status doesn't need. For
176
+ * a status that needs to sit flush against other plain content instead
177
+ * of reading as its own separate chip: a `KeyValuePairValue` slot, a
178
+ * table cell (especially one with a `MetaList` underneath, where a
179
+ * padded chip would misalign against the MetaList's own flush left/right
180
+ * edges), or right-aligned in a flex row next to one.
181
+ * - An AI-assigned status/tag is a plain composition, not a variant: keep the Badge exactly
182
+ * as the status calls for and put `AILabel` (size="sm" — never the opt-in icon-only "xs" by
183
+ * default) beside it in an `inline-flex` span. Never restyle the Badge itself
184
+ * with the AI gradient — that would be indistinguishable from Button's AI Chip
185
+ * (variant="ai" rounded-full), and the two must read apart: the Chip is an action, a Badge
186
+ * is not. See AI/Badge.
187
+ *
188
+ * USAGE
189
+ * <Badge>Default</Badge>
190
+ * <Badge tone="destructive">Overdue</Badge>
191
+ * <Badge tone="secondary" emphasis="ghost">Draft</Badge>
192
+ * <Badge className="bg-success-light text-success-text">Success</Badge>
193
+ * <Badge><CheckIcon />Verified</Badge>
194
+ * <Badge maxWidth={120}>Regional Clinical Operations Lead</Badge>
195
+ *
196
+ * // Status indicator convention
197
+ * <Badge emphasis="outline">
198
+ * <CheckIcon className="text-success" data-icon="inline-start" />
199
+ * Active
200
+ * </Badge>
201
+ * <Badge emphasis="outline">
202
+ * <XIcon className="text-alert" data-icon="inline-start" />
203
+ * Failed
204
+ * </Badge>
205
+ * <Badge emphasis="outline">
206
+ * <TriangleAlertIcon className="text-warning" data-icon="inline-start" />
207
+ * Expiring soon
208
+ * </Badge>
209
+ * <Badge emphasis="outline">
210
+ * <PenLineIcon className="text-muted-foreground" data-icon="inline-start" />
211
+ * Draft
212
+ * </Badge>
213
+ *
214
+ * // Flush status indicator — KVP value, table cell, or right-aligned next to a MetaList
215
+ * <Badge
216
+ * emphasis="ghost"
217
+ * className="px-0 has-data-[icon=inline-start]:pl-0 has-data-[icon=inline-end]:pr-0 hover:bg-transparent"
218
+ * >
219
+ * <CheckIcon className="text-success" data-icon="inline-start" />
220
+ * Active
221
+ * </Badge>
222
+ */
223
+ //#endregion
224
+ export { Badge, badgeVariants };
225
+
226
+ //# sourceMappingURL=badge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"badge.js","names":[],"sources":["../../../src/components/ui/badge.tsx"],"sourcesContent":["/**\n * Badge — inline status/category/count label.\n *\n * cva-driven span, non-interactive by default. Styled on two axes — `tone`\n * (what it means) × `emphasis` (how loudly it's drawn) — with the old single\n * `variant` list kept as a deprecated alias.\n */\n\nimport * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Slot } from \"radix-ui\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst badgeVariants = cva(\n \"group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-colors focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!\",\n {\n // Two axes, not one list: `tone` is what the label means (neutral\n // primary, quieter secondary, destructive), `emphasis` is how loudly\n // it's drawn (filled surface, outlined, or bare text). Every\n // combination is defined below so the two never collide.\n variants: {\n tone: {\n default: \"\",\n secondary: \"\",\n destructive: \"\",\n },\n emphasis: {\n filled: \"\",\n outline: \"\",\n ghost: \"\",\n },\n },\n compoundVariants: [\n {\n tone: \"default\",\n emphasis: \"filled\",\n class:\n \"bg-primary text-primary-foreground [a]:hover:bg-primary-hover [a]:active:bg-primary-active\",\n },\n {\n tone: \"secondary\",\n emphasis: \"filled\",\n class:\n \"bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80\",\n },\n {\n tone: \"destructive\",\n emphasis: \"filled\",\n class:\n \"bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20\",\n },\n {\n tone: \"default\",\n emphasis: \"outline\",\n class:\n \"border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground\",\n },\n {\n tone: \"secondary\",\n emphasis: \"outline\",\n class: \"border-border text-muted-foreground [a]:hover:bg-muted\",\n },\n {\n tone: \"destructive\",\n emphasis: \"outline\",\n class:\n \"border-destructive/40 text-destructive focus-visible:ring-destructive/20 [a]:hover:bg-destructive/10\",\n },\n {\n tone: \"default\",\n emphasis: \"ghost\",\n class:\n \"hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50\",\n },\n {\n tone: \"secondary\",\n emphasis: \"ghost\",\n class: \"text-muted-foreground hover:bg-muted dark:hover:bg-muted/50\",\n },\n {\n tone: \"destructive\",\n emphasis: \"ghost\",\n class:\n \"text-destructive hover:bg-destructive/10 dark:hover:bg-destructive/20\",\n },\n ],\n defaultVariants: {\n tone: \"default\",\n emphasis: \"filled\",\n },\n }\n)\n\ntype BadgeTone = NonNullable<VariantProps<typeof badgeVariants>[\"tone\"]>\ntype BadgeEmphasis = NonNullable<VariantProps<typeof badgeVariants>[\"emphasis\"]>\n/**\n * @deprecated The single `variant` list mixed two axes (what the badge means\n * and how loudly it's drawn). Use `tone` + `emphasis` instead. Still accepted\n * so existing consumers render unchanged: default -> filled default,\n * secondary -> filled secondary, destructive -> filled destructive,\n * outline -> outline default, ghost -> ghost default. `link` (an interaction\n * affordance on a non-interactive label) has no new-axis equivalent and just\n * keeps its old underline look.\n */\ntype BadgeLegacyVariant =\n \"default\" | \"secondary\" | \"destructive\" | \"outline\" | \"ghost\" | \"link\"\n\nconst LEGACY_VARIANT: Record<\n Exclude<BadgeLegacyVariant, \"link\">,\n { tone: BadgeTone; emphasis: BadgeEmphasis }\n> = {\n default: { tone: \"default\", emphasis: \"filled\" },\n secondary: { tone: \"secondary\", emphasis: \"filled\" },\n destructive: { tone: \"destructive\", emphasis: \"filled\" },\n outline: { tone: \"default\", emphasis: \"outline\" },\n ghost: { tone: \"default\", emphasis: \"ghost\" },\n}\n\nfunction Badge({\n className,\n tone,\n emphasis,\n variant,\n asChild = false,\n truncate = false,\n maxWidth,\n style,\n children,\n title,\n ...props\n}: React.ComponentProps<\"span\"> &\n VariantProps<typeof badgeVariants> & {\n asChild?: boolean\n /** Cuts a label that's too long for its space off with an ellipsis instead of overflowing. Pair with `maxWidth` (or a width from the parent) — without one the badge just sizes to its text. Not applied with `asChild`. */\n truncate?: boolean\n /** Caps the badge's width (a number is px, or any CSS size) and implies `truncate`. */\n maxWidth?: number | string\n /** @deprecated use `tone` + `emphasis` */\n variant?: BadgeLegacyVariant\n }) {\n const Comp = asChild ? Slot.Root : \"span\"\n const legacy =\n variant && variant !== \"link\" ? LEGACY_VARIANT[variant] : undefined\n const resolvedTone = tone ?? legacy?.tone ?? \"default\"\n const resolvedEmphasis =\n emphasis ?? legacy?.emphasis ?? (variant === \"link\" ? \"ghost\" : \"filled\")\n\n const truncating = !asChild && (truncate || maxWidth !== undefined)\n // A flex container can't ellipsize its own bare text — each text run gets\n // its own `truncate` span, while icons (elements) keep their size.\n const content = truncating\n ? React.Children.map(children, (child) =>\n typeof child === \"string\" || typeof child === \"number\" ? (\n <span className=\"min-w-0 truncate\">{child}</span>\n ) : (\n child\n )\n )\n : children\n // Surfaces the full label on hover once it may be cut off.\n const fullLabel =\n title ??\n (truncating\n ? React.Children.toArray(children)\n .filter((c) => typeof c === \"string\" || typeof c === \"number\")\n .join(\"\") || undefined\n : undefined)\n\n return (\n <Comp\n data-slot=\"badge\"\n data-tone={resolvedTone}\n data-emphasis={resolvedEmphasis}\n data-variant={variant}\n className={cn(\n badgeVariants({ tone: resolvedTone, emphasis: resolvedEmphasis }),\n variant === \"link\" &&\n \"text-primary underline-offset-4 hover:bg-transparent hover:text-primary hover:underline\",\n truncating && \"max-w-full min-w-0\",\n className\n )}\n style={maxWidth !== undefined ? { maxWidth, ...style } : style}\n title={fullLabel}\n {...props}\n >\n {content}\n </Comp>\n )\n}\n\nexport { Badge, badgeVariants }\nexport type { BadgeTone, BadgeEmphasis }\n\n/**\n * WHEN TO USE\n * - A status, category, count, or tag shown inline with other content\n * (row status, list tag, small metadata chip).\n * - An operational-status indicator (active, failed, expiring, pending) —\n * emphasis=\"outline\" with a small colored icon, not a filled badge. This\n * is Badge's status-indicator convention; there's no separate component\n * for it.\n *\n * NOT WHEN\n * - Interactive filters or removable tags — those need their own\n * click/remove handling, which Badge doesn't provide.\n * - An action — use Button.\n * - Long text — Badge is sized and padded for short labels only. When a user-supplied label might run long anyway (a role or tag name), cap it with `maxWidth` / `truncate`.\n *\n * KEY RULES\n * - `truncate` / `maxWidth` ellipsize a long label and show the full text as a native `title`; icons are untouched. They don't apply with `asChild`.\n * - Non-interactive by default; pass `asChild` to render as an `<a>` when\n * the badge itself needs to link somewhere.\n * - Two axes, not one list. tone: default | secondary | destructive — what the\n * label means. emphasis: filled | outline | ghost — how loudly it's drawn.\n * Every tone×emphasis pair is styled; omit both for a filled default badge.\n * The old single `variant` prop (default, secondary, destructive, outline,\n * ghost, link) still renders identically but is deprecated — it folded the\n * two axes into one list. `link` has no new-axis equivalent: a Badge is\n * non-interactive, so an underlined link look belongs on Button/anchor.\n * - Custom semantic colors (success/warning/alert/info) aren't separate\n * variants — apply the token utility directly, using each status's\n * subtle `-light`/`-text` pair (not the solid `-foreground` pairing,\n * which reads too loud for an inline tag), e.g. `className=\"bg-success-light\n * text-success-text\"`.\n * - Status-indicator convention: emphasis=\"outline\" + a leading icon colored\n * with the matching semantic token, `data-icon=\"inline-start\"`. Fixed\n * icon/color pairing, don't substitute other icons for these:\n * success -> CheckIcon text-success\n * alert -> XIcon text-alert (text-destructive for a true error, not just \"alert\")\n * warning -> TriangleAlertIcon text-warning\n * info -> InfoIcon text-info\n * default -> PenLineIcon text-muted-foreground\n * - Flush status-indicator variant: the same icon/color pairing above, but\n * `emphasis=\"ghost\"` (no border, no fill) plus\n * `className=\"px-0 has-data-[icon=inline-start]:pl-0 has-data-[icon=inline-end]:pr-0 hover:bg-transparent\"`\n * — the padding overrides zero out what `emphasis=\"outline\"` needs for\n * its own chip look but this doesn't, and `hover:bg-transparent` drops\n * `ghost`'s subtle hover highlight (meant for when Badge is `asChild` as\n * a real link), which a flush, non-interactive status doesn't need. For\n * a status that needs to sit flush against other plain content instead\n * of reading as its own separate chip: a `KeyValuePairValue` slot, a\n * table cell (especially one with a `MetaList` underneath, where a\n * padded chip would misalign against the MetaList's own flush left/right\n * edges), or right-aligned in a flex row next to one.\n * - An AI-assigned status/tag is a plain composition, not a variant: keep the Badge exactly\n * as the status calls for and put `AILabel` (size=\"sm\" — never the opt-in icon-only \"xs\" by\n * default) beside it in an `inline-flex` span. Never restyle the Badge itself\n * with the AI gradient — that would be indistinguishable from Button's AI Chip\n * (variant=\"ai\" rounded-full), and the two must read apart: the Chip is an action, a Badge\n * is not. See AI/Badge.\n *\n * USAGE\n * <Badge>Default</Badge>\n * <Badge tone=\"destructive\">Overdue</Badge>\n * <Badge tone=\"secondary\" emphasis=\"ghost\">Draft</Badge>\n * <Badge className=\"bg-success-light text-success-text\">Success</Badge>\n * <Badge><CheckIcon />Verified</Badge>\n * <Badge maxWidth={120}>Regional Clinical Operations Lead</Badge>\n *\n * // Status indicator convention\n * <Badge emphasis=\"outline\">\n * <CheckIcon className=\"text-success\" data-icon=\"inline-start\" />\n * Active\n * </Badge>\n * <Badge emphasis=\"outline\">\n * <XIcon className=\"text-alert\" data-icon=\"inline-start\" />\n * Failed\n * </Badge>\n * <Badge emphasis=\"outline\">\n * <TriangleAlertIcon className=\"text-warning\" data-icon=\"inline-start\" />\n * Expiring soon\n * </Badge>\n * <Badge emphasis=\"outline\">\n * <PenLineIcon className=\"text-muted-foreground\" data-icon=\"inline-start\" />\n * Draft\n * </Badge>\n *\n * // Flush status indicator — KVP value, table cell, or right-aligned next to a MetaList\n * <Badge\n * emphasis=\"ghost\"\n * className=\"px-0 has-data-[icon=inline-start]:pl-0 has-data-[icon=inline-end]:pr-0 hover:bg-transparent\"\n * >\n * <CheckIcon className=\"text-success\" data-icon=\"inline-start\" />\n * Active\n * </Badge>\n */\n"],"mappings":";;;;;;;;;;;;;AAcA,IAAM,gBAAgB,IACpB,ifACA;CAKE,UAAU;EACR,MAAM;GACJ,SAAS;GACT,WAAW;GACX,aAAa;EACf;EACA,UAAU;GACR,QAAQ;GACR,SAAS;GACT,OAAO;EACT;CACF;CACA,kBAAkB;EAChB;GACE,MAAM;GACN,UAAU;GACV,OACE;EACJ;EACA;GACE,MAAM;GACN,UAAU;GACV,OACE;EACJ;EACA;GACE,MAAM;GACN,UAAU;GACV,OACE;EACJ;EACA;GACE,MAAM;GACN,UAAU;GACV,OACE;EACJ;EACA;GACE,MAAM;GACN,UAAU;GACV,OAAO;EACT;EACA;GACE,MAAM;GACN,UAAU;GACV,OACE;EACJ;EACA;GACE,MAAM;GACN,UAAU;GACV,OACE;EACJ;EACA;GACE,MAAM;GACN,UAAU;GACV,OAAO;EACT;EACA;GACE,MAAM;GACN,UAAU;GACV,OACE;EACJ;CACF;CACA,iBAAiB;EACf,MAAM;EACN,UAAU;CACZ;AACF,CACF;AAgBA,IAAM,iBAGF;CACF,SAAS;EAAE,MAAM;EAAW,UAAU;CAAS;CAC/C,WAAW;EAAE,MAAM;EAAa,UAAU;CAAS;CACnD,aAAa;EAAE,MAAM;EAAe,UAAU;CAAS;CACvD,SAAS;EAAE,MAAM;EAAW,UAAU;CAAU;CAChD,OAAO;EAAE,MAAM;EAAW,UAAU;CAAQ;AAC9C;AAEA,SAAS,MAAM,EACb,WACA,MACA,UACA,SACA,UAAU,OACV,WAAW,OACX,UACA,OACA,UACA,OACA,GAAG,SAUA;CACH,MAAM,OAAO,UAAU,KAAK,OAAO;CACnC,MAAM,SACJ,WAAW,YAAY,SAAS,eAAe,WAAW,KAAA;CAC5D,MAAM,eAAe,QAAQ,QAAQ,QAAQ;CAC7C,MAAM,mBACJ,YAAY,QAAQ,aAAa,YAAY,SAAS,UAAU;CAElE,MAAM,aAAa,CAAC,YAAY,YAAY,aAAa,KAAA;CAGzD,MAAM,UAAU,aACZ,MAAM,SAAS,IAAI,WAAW,UAC5B,OAAO,UAAU,YAAY,OAAO,UAAU,WAC5C,oBAAC,QAAD;EAAM,WAAU;EAAoB,UAAA;CAAY,CAAA,IAEhD,KAEJ,IACA;CAEJ,MAAM,YACJ,UACC,aACG,MAAM,SAAS,QAAQ,QAAQ,CAAC,CAC7B,QAAQ,MAAM,OAAO,MAAM,YAAY,OAAO,MAAM,QAAQ,CAAC,CAC7D,KAAK,EAAE,KAAK,KAAA,IACf,KAAA;CAEN,OACE,oBAAC,MAAD;EACE,aAAU;EACV,aAAW;EACX,iBAAe;EACf,gBAAc;EACd,WAAW,GACT,cAAc;GAAE,MAAM;GAAc,UAAU;EAAiB,CAAC,GAChE,YAAY,UACV,2FACF,cAAc,sBACd,SACF;EACA,OAAO,aAAa,KAAA,IAAY;GAAE;GAAU,GAAG;EAAM,IAAI;EACzD,OAAO;EACP,GAAI;EAEH,UAAA;CACG,CAAA;AAEV"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Breadcrumb — hierarchical location trail, plain markup (not a Radix primitive).
3
+ *
4
+ * An <ol> of BreadcrumbItem, ancestors as BreadcrumbLink and the current
5
+ * page as a non-interactive BreadcrumbPage.
6
+ */
7
+ import * as React from "react";
8
+ declare function Breadcrumb({ className, ...props }: React.ComponentProps<"nav">): React.JSX.Element;
9
+ declare function BreadcrumbList({ className, ...props }: React.ComponentProps<"ol">): React.JSX.Element;
10
+ declare function BreadcrumbItem({ className, ...props }: React.ComponentProps<"li">): React.JSX.Element;
11
+ declare function BreadcrumbLink({ asChild, className, ...props }: React.ComponentProps<"a"> & {
12
+ asChild?: boolean;
13
+ }): React.JSX.Element;
14
+ declare function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">): React.JSX.Element;
15
+ declare function BreadcrumbSeparator({ children, className, ...props }: React.ComponentProps<"li">): React.JSX.Element;
16
+ declare function BreadcrumbEllipsis({ className, ...props }: React.ComponentProps<"span">): React.JSX.Element;
17
+ export { Breadcrumb, BreadcrumbList, BreadcrumbItem, BreadcrumbLink, BreadcrumbPage, BreadcrumbSeparator, BreadcrumbEllipsis, };
18
+ /**
19
+ * WHEN TO USE
20
+ * - Showing position in a hierarchy at least two levels deep (e.g. Patients
21
+ * › James Wilson), typically placed above a PageHeader title
22
+ *
23
+ * NOT WHEN
24
+ * - Flat navigation with no hierarchy
25
+ * - As a substitute for Tabs
26
+ *
27
+ * KEY RULES
28
+ * - The current page is BreadcrumbPage — plain text, not a link
29
+ * (aria-current="page", aria-disabled)
30
+ * - BreadcrumbEllipsis collapses a long trail; pair it with a
31
+ * BreadcrumbSeparator on each side like any other item
32
+ * - BreadcrumbLink supports asChild to render a router Link instead of <a>
33
+ *
34
+ * USAGE
35
+ * <Breadcrumb>
36
+ * <BreadcrumbList>
37
+ * <BreadcrumbItem><BreadcrumbLink href="/patients">Patients</BreadcrumbLink></BreadcrumbItem>
38
+ * <BreadcrumbSeparator />
39
+ * <BreadcrumbItem><BreadcrumbPage>James Wilson</BreadcrumbPage></BreadcrumbItem>
40
+ * </BreadcrumbList>
41
+ * </Breadcrumb>
42
+ */
43
+ //# sourceMappingURL=breadcrumb.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"breadcrumb.d.ts","sourceRoot":"","sources":["../../../src/components/ui/breadcrumb.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAM9B,iBAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBASvE;AAED,iBAAS,cAAc,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,qBAW1E;AAED,iBAAS,cAAc,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,qBAQ1E;AAED,iBAAS,cAAc,CAAC,EACtB,OAAO,EACP,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,qBAUA;AAED,iBAAS,cAAc,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,qBAW5E;AAED,iBAAS,mBAAmB,CAAC,EAC3B,QAAQ,EACR,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,qBAY5B;AAED,iBAAS,kBAAkB,CAAC,EAC1B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,qBAgB9B;AAED,OAAO,EACL,UAAU,EACV,cAAc,EACd,cAAc,EACd,cAAc,EACd,cAAc,EACd,mBAAmB,EACnB,kBAAkB,GACnB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG"}
@@ -0,0 +1,98 @@
1
+ import { cn } from "../../lib/utils.js";
2
+ import "react";
3
+ import { Slot } from "radix-ui";
4
+ import { ChevronRightIcon, MoreHorizontalIcon } from "lucide-react";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ //#region src/components/ui/breadcrumb.tsx
7
+ function Breadcrumb({ className, ...props }) {
8
+ return /* @__PURE__ */ jsx("nav", {
9
+ "aria-label": "breadcrumb",
10
+ "data-slot": "breadcrumb",
11
+ className: cn(className),
12
+ ...props
13
+ });
14
+ }
15
+ function BreadcrumbList({ className, ...props }) {
16
+ return /* @__PURE__ */ jsx("ol", {
17
+ "data-slot": "breadcrumb-list",
18
+ className: cn("flex flex-wrap items-center gap-1.5 text-sm wrap-break-word text-muted-foreground", className),
19
+ ...props
20
+ });
21
+ }
22
+ function BreadcrumbItem({ className, ...props }) {
23
+ return /* @__PURE__ */ jsx("li", {
24
+ "data-slot": "breadcrumb-item",
25
+ className: cn("inline-flex items-center gap-1", className),
26
+ ...props
27
+ });
28
+ }
29
+ function BreadcrumbLink({ asChild, className, ...props }) {
30
+ const Comp = asChild ? Slot.Root : "a";
31
+ return /* @__PURE__ */ jsx(Comp, {
32
+ "data-slot": "breadcrumb-link",
33
+ className: cn("transition-colors hover:text-foreground", className),
34
+ ...props
35
+ });
36
+ }
37
+ function BreadcrumbPage({ className, ...props }) {
38
+ return /* @__PURE__ */ jsx("span", {
39
+ "data-slot": "breadcrumb-page",
40
+ role: "link",
41
+ "aria-disabled": "true",
42
+ "aria-current": "page",
43
+ className: cn("font-normal text-foreground", className),
44
+ ...props
45
+ });
46
+ }
47
+ function BreadcrumbSeparator({ children, className, ...props }) {
48
+ return /* @__PURE__ */ jsx("li", {
49
+ "data-slot": "breadcrumb-separator",
50
+ role: "presentation",
51
+ "aria-hidden": "true",
52
+ className: cn("[&>svg]:size-3.5", className),
53
+ ...props,
54
+ children: children ?? /* @__PURE__ */ jsx(ChevronRightIcon, {})
55
+ });
56
+ }
57
+ function BreadcrumbEllipsis({ className, ...props }) {
58
+ return /* @__PURE__ */ jsxs("span", {
59
+ "data-slot": "breadcrumb-ellipsis",
60
+ role: "presentation",
61
+ "aria-hidden": "true",
62
+ className: cn("flex size-5 items-center justify-center [&>svg]:size-4", className),
63
+ ...props,
64
+ children: [/* @__PURE__ */ jsx(MoreHorizontalIcon, {}), /* @__PURE__ */ jsx("span", {
65
+ className: "sr-only",
66
+ children: "More"
67
+ })]
68
+ });
69
+ }
70
+ /**
71
+ * WHEN TO USE
72
+ * - Showing position in a hierarchy at least two levels deep (e.g. Patients
73
+ * › James Wilson), typically placed above a PageHeader title
74
+ *
75
+ * NOT WHEN
76
+ * - Flat navigation with no hierarchy
77
+ * - As a substitute for Tabs
78
+ *
79
+ * KEY RULES
80
+ * - The current page is BreadcrumbPage — plain text, not a link
81
+ * (aria-current="page", aria-disabled)
82
+ * - BreadcrumbEllipsis collapses a long trail; pair it with a
83
+ * BreadcrumbSeparator on each side like any other item
84
+ * - BreadcrumbLink supports asChild to render a router Link instead of <a>
85
+ *
86
+ * USAGE
87
+ * <Breadcrumb>
88
+ * <BreadcrumbList>
89
+ * <BreadcrumbItem><BreadcrumbLink href="/patients">Patients</BreadcrumbLink></BreadcrumbItem>
90
+ * <BreadcrumbSeparator />
91
+ * <BreadcrumbItem><BreadcrumbPage>James Wilson</BreadcrumbPage></BreadcrumbItem>
92
+ * </BreadcrumbList>
93
+ * </Breadcrumb>
94
+ */
95
+ //#endregion
96
+ export { Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator };
97
+
98
+ //# sourceMappingURL=breadcrumb.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"breadcrumb.js","names":[],"sources":["../../../src/components/ui/breadcrumb.tsx"],"sourcesContent":["/**\n * Breadcrumb — hierarchical location trail, plain markup (not a Radix primitive).\n *\n * An <ol> of BreadcrumbItem, ancestors as BreadcrumbLink and the current\n * page as a non-interactive BreadcrumbPage.\n */\n\nimport * as React from \"react\"\nimport { Slot } from \"radix-ui\"\n\nimport { cn } from \"@/lib/utils\"\nimport { ChevronRightIcon, MoreHorizontalIcon } from \"lucide-react\"\n\nfunction Breadcrumb({ className, ...props }: React.ComponentProps<\"nav\">) {\n return (\n <nav\n aria-label=\"breadcrumb\"\n data-slot=\"breadcrumb\"\n className={cn(className)}\n {...props}\n />\n )\n}\n\nfunction BreadcrumbList({ className, ...props }: React.ComponentProps<\"ol\">) {\n return (\n <ol\n data-slot=\"breadcrumb-list\"\n className={cn(\n \"flex flex-wrap items-center gap-1.5 text-sm wrap-break-word text-muted-foreground\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction BreadcrumbItem({ className, ...props }: React.ComponentProps<\"li\">) {\n return (\n <li\n data-slot=\"breadcrumb-item\"\n className={cn(\"inline-flex items-center gap-1\", className)}\n {...props}\n />\n )\n}\n\nfunction BreadcrumbLink({\n asChild,\n className,\n ...props\n}: React.ComponentProps<\"a\"> & {\n asChild?: boolean\n}) {\n const Comp = asChild ? Slot.Root : \"a\"\n\n return (\n <Comp\n data-slot=\"breadcrumb-link\"\n className={cn(\"transition-colors hover:text-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction BreadcrumbPage({ className, ...props }: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"breadcrumb-page\"\n role=\"link\"\n aria-disabled=\"true\"\n aria-current=\"page\"\n className={cn(\"font-normal text-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction BreadcrumbSeparator({\n children,\n className,\n ...props\n}: React.ComponentProps<\"li\">) {\n return (\n <li\n data-slot=\"breadcrumb-separator\"\n role=\"presentation\"\n aria-hidden=\"true\"\n className={cn(\"[&>svg]:size-3.5\", className)}\n {...props}\n >\n {children ?? <ChevronRightIcon />}\n </li>\n )\n}\n\nfunction BreadcrumbEllipsis({\n className,\n ...props\n}: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"breadcrumb-ellipsis\"\n role=\"presentation\"\n aria-hidden=\"true\"\n className={cn(\n \"flex size-5 items-center justify-center [&>svg]:size-4\",\n className\n )}\n {...props}\n >\n <MoreHorizontalIcon />\n <span className=\"sr-only\">More</span>\n </span>\n )\n}\n\nexport {\n Breadcrumb,\n BreadcrumbList,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbPage,\n BreadcrumbSeparator,\n BreadcrumbEllipsis,\n}\n\n/**\n * WHEN TO USE\n * - Showing position in a hierarchy at least two levels deep (e.g. Patients\n * › James Wilson), typically placed above a PageHeader title\n *\n * NOT WHEN\n * - Flat navigation with no hierarchy\n * - As a substitute for Tabs\n *\n * KEY RULES\n * - The current page is BreadcrumbPage — plain text, not a link\n * (aria-current=\"page\", aria-disabled)\n * - BreadcrumbEllipsis collapses a long trail; pair it with a\n * BreadcrumbSeparator on each side like any other item\n * - BreadcrumbLink supports asChild to render a router Link instead of <a>\n *\n * USAGE\n * <Breadcrumb>\n * <BreadcrumbList>\n * <BreadcrumbItem><BreadcrumbLink href=\"/patients\">Patients</BreadcrumbLink></BreadcrumbItem>\n * <BreadcrumbSeparator />\n * <BreadcrumbItem><BreadcrumbPage>James Wilson</BreadcrumbPage></BreadcrumbItem>\n * </BreadcrumbList>\n * </Breadcrumb>\n */\n"],"mappings":";;;;;;AAaA,SAAS,WAAW,EAAE,WAAW,GAAG,SAAsC;CACxE,OACE,oBAAC,OAAD;EACE,cAAW;EACX,aAAU;EACV,WAAW,GAAG,SAAS;EACvB,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,eAAe,EAAE,WAAW,GAAG,SAAqC;CAC3E,OACE,oBAAC,MAAD;EACE,aAAU;EACV,WAAW,GACT,qFACA,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,eAAe,EAAE,WAAW,GAAG,SAAqC;CAC3E,OACE,oBAAC,MAAD;EACE,aAAU;EACV,WAAW,GAAG,kCAAkC,SAAS;EACzD,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,eAAe,EACtB,SACA,WACA,GAAG,SAGF;CACD,MAAM,OAAO,UAAU,KAAK,OAAO;CAEnC,OACE,oBAAC,MAAD;EACE,aAAU;EACV,WAAW,GAAG,2CAA2C,SAAS;EAClE,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,eAAe,EAAE,WAAW,GAAG,SAAuC;CAC7E,OACE,oBAAC,QAAD;EACE,aAAU;EACV,MAAK;EACL,iBAAc;EACd,gBAAa;EACb,WAAW,GAAG,+BAA+B,SAAS;EACtD,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,oBAAoB,EAC3B,UACA,WACA,GAAG,SAC0B;CAC7B,OACE,oBAAC,MAAD;EACE,aAAU;EACV,MAAK;EACL,eAAY;EACZ,WAAW,GAAG,oBAAoB,SAAS;EAC3C,GAAI;EAEH,UAAA,YAAY,oBAAC,kBAAD,CAAmB,CAAA;CAC9B,CAAA;AAER;AAEA,SAAS,mBAAmB,EAC1B,WACA,GAAG,SAC4B;CAC/B,OACE,qBAAC,QAAD;EACE,aAAU;EACV,MAAK;EACL,eAAY;EACZ,WAAW,GACT,0DACA,SACF;EACA,GAAI;EARN,UAAA,CAUE,oBAAC,oBAAD,CAAqB,CAAA,GACrB,oBAAC,QAAD;GAAM,WAAU;GAAU,UAAA;EAAU,CAAA,CAChC;;AAEV"}
@@ -0,0 +1,218 @@
1
+ /**
2
+ * BrowserTabs — persistent, closable document tabs, browser-style.
3
+ *
4
+ * The same Radix Tabs primitive `tabs.tsx` wraps, plus Popover for the "+"
5
+ * menu, Tooltip for truncated names, and Button for the per-tab close
6
+ * action — a different visual/interaction language from Tabs, not a
7
+ * variant of it: Tabs switches between named views of one entity (2-6 fixed
8
+ * tabs); this is for many independent, closable documents/views open at
9
+ * once (an IDE's editor tabs, a browser's own tab strip) — always
10
+ * horizontal, and always the topmost chrome of whatever surface it sits on.
11
+ * Each tab floats as a rounded pill on the strip's own bg-secondary track,
12
+ * flush against its bottom edge — the active tab's bg-card fill then
13
+ * touches the card content's own bg-card directly beneath it with no grey
14
+ * left in between, merging the two Chrome-style, rather than reading as a
15
+ * colored/selected state the way Tabs' own default variant does. Pinned
16
+ * tabs render icon-only — a fixed favicon-size square, falling back to a
17
+ * generic FileIcon when the tab itself has none — same as a real browser's
18
+ * own pinned tabs, and never part of the overflow behavior below. Once
19
+ * unpinned tabs stop fitting, they shrink together down to a floor, then
20
+ * the strip scrolls that pool horizontally past that — the same overflow
21
+ * model a real browser's own tab strip uses, not a "More" menu hiding the
22
+ * rest.
23
+ * An optional "+" pill at the strip's end, outside the scrolling region
24
+ * (`addViews` on BrowserTabsList) opens a popover of product-defined views
25
+ * the user can open as new tabs — a worklist's saved filters, for
26
+ * instance. `addTrigger`/`renderAddContent` swap its trigger or its
27
+ * popover content for something fully custom.
28
+ */
29
+ import * as React from "react";
30
+ import { Tabs as TabsPrimitive } from "radix-ui";
31
+ import { TabsContent as BrowserTabsContent } from "../../components/ui/tabs";
32
+ declare function BrowserTabs({ className, value, defaultValue, onValueChange, ...props }: React.ComponentProps<typeof TabsPrimitive.Root>): React.JSX.Element;
33
+ /** One entry in the "+" popover — a product-defined view the user can open as a new tab. */
34
+ type BrowserTabsAddView = {
35
+ id: string;
36
+ label: string;
37
+ /** A leading icon, same convention as BrowserTab's own `icon`. */
38
+ icon?: React.ComponentType<{
39
+ className?: string;
40
+ }>;
41
+ /** A muted line of secondary metadata under the label — a description, a count, a last-modified date. Same convention as DataTable's `FilterOption.description`. */
42
+ description?: string;
43
+ disabled?: boolean;
44
+ /** A hint that this view should open as a pinned tab (`"user"`/`"product"`, same meaning as `BrowserTab`'s own `pin`) — shown here as a small pin icon trailing the label. Purely informational: this component doesn't open tabs itself, so acting on it (passing the matching `pin` to the `BrowserTab` you add in `onAddView`) is the consumer's job. */
45
+ pin?: "user" | "product";
46
+ };
47
+ declare function BrowserTabsList({ className, children, addViews, onAddView, addLabel, addTrigger, renderAddContent, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, ...props }: React.ComponentProps<typeof TabsPrimitive.List> & {
48
+ /** Product-defined views the user can open as new tabs — rendered in the "+" pill's default popover list. Omit entirely (with `renderAddContent` covering the "+" pill's content instead) for a fully custom popover. Opening is the consumer's job — `onAddView` only reports the pick; add the tab to your own list (or, if that view is already open, just activate it). A view's own `pin` is a hint for *that*: open it pinned (`"user"`/`"product"`, same meaning as `BrowserTab`'s own `pin`) rather than as a regular tab — shown as a small pin icon next to it here, not enforced by this component. */
49
+ addViews?: BrowserTabsAddView[];
50
+ /** Fires with the picked view; the popover closes itself. */
51
+ onAddView?: (view: BrowserTabsAddView) => void;
52
+ /** Accessible name of the "+" pill (it's icon-only). Defaults to "Open a view in a new tab". Ignored when `addTrigger` is given — that node is responsible for its own accessible name. */
53
+ addLabel?: string;
54
+ /** A custom trigger in place of the default icon-only "+" pill — still opens the same popover (`addViews`' list, or `renderAddContent`). Needs its own accessible name (a plain icon button still needs `aria-label`, same as any custom Popover trigger). */
55
+ addTrigger?: React.ReactNode;
56
+ /** Replaces the "+" popover's default views list with fully custom content — a search box, a grouped menu, anything. Called with `close` to dismiss the popover from inside it (the default list's own item clicks do this automatically; custom content must call it itself). Takes over the popover entirely: `addViews`/`onAddView` don't render alongside it. */
57
+ renderAddContent?: (close: () => void) => React.ReactNode;
58
+ }): React.JSX.Element;
59
+ type BrowserTabProps = {
60
+ value: string;
61
+ /** A leading icon (e.g. a favicon-style entity icon) — rendered outside the truncating label, so it's never clipped. */
62
+ icon?: React.ComponentType<{
63
+ className?: string;
64
+ }>;
65
+ disabled?: boolean;
66
+ /** Groups this tab into the strip's pinned section, ahead of a divider from the rest. "user" tabs were pinned by the user and can still take `onClose` (closing is how the user unpins/removes them); "product" tabs are pinned by the product and never render a close button, regardless of `onClose`. */
67
+ pin?: "user" | "product";
68
+ /** Omit to render this tab with no close button — e.g. a pinned tab that can't be dismissed. Ignored when `pin="product"`. The close button is hover/focus-revealed over the end of the name (which truncates underneath it), so the tab is content-width at rest and never changes width on hover; it's also offered as "Close" in the tab's right-click menu. */
69
+ onClose?: () => void;
70
+ /** Accessible label for the close button. Defaults to "Close {children}" when `children` is a plain string; pass this explicitly when it isn't (an icon, a custom node). */
71
+ closeLabel?: string;
72
+ /** Enables "Pin tab" / "Unpin tab" in this tab's right-click menu (the item is always shown, disabled without a handler or on a `pin="product"` tab). Fires regardless of direction; read the tab's own current `pin` to decide whether you're pinning or unpinning it, then move it into (or to the front of) the appropriate section — BrowserTabs only renders what you give it, it doesn't reorder your list. There is no visible pin button on the tab itself. */
73
+ onPinToggle?: () => void;
74
+ /** Enables "Close other tabs" in this tab's right-click menu (the item is always shown, disabled without a handler). Like `onClose`, it only reports the intent — close every other UNPINNED tab in your own list and keep this one active. Pinned tabs (`pin="user"` or `"product"`) are never closed by "close others"; the user pinned them precisely so they'd survive that. */
75
+ onCloseOthers?: () => void;
76
+ className?: string;
77
+ children: React.ReactNode;
78
+ };
79
+ declare function BrowserTab(props: BrowserTabProps): React.JSX.Element;
80
+ export { BrowserTabs, BrowserTabsList, BrowserTab, BrowserTabsContent };
81
+ export type { BrowserTabsAddView };
82
+ /**
83
+ * WHEN TO USE
84
+ * - Many independent, addable/closable documents or views open at once —
85
+ * an IDE's editor tabs, a browser's own tab strip, a multi-record
86
+ * workspace where each record opens in its own tab.
87
+ * - Always as the topmost chrome of whatever surface hosts it (a Card,
88
+ * a page shell) — it's edge-to-edge and expects to sit flush at that
89
+ * surface's top.
90
+ *
91
+ * NOT WHEN
92
+ * - Switching between a fixed 2-6 named views of *one* entity (an
93
+ * Overview/History/Notes split) — use Tabs instead; it reads as
94
+ * neutral navigation, not as separate closable documents.
95
+ * - Vertical tab placement — not supported; always horizontal.
96
+ *
97
+ * KEY RULES
98
+ * - Composition mirrors Tabs: `BrowserTabs` (Root, controlled or
99
+ * uncontrolled via `value`/`onValueChange`/`defaultValue`) wraps
100
+ * `BrowserTabsList` (the strip) and one `BrowserTabsContent` per tab
101
+ * (re-exported directly from Tabs — same primitive, nothing about it
102
+ * is strip-specific).
103
+ * - `pin`: omit for a normal tab, `"user"` for one the user pinned
104
+ * (closable — closing is how they unpin it), `"product"` for one the
105
+ * product configured (never closable, no close button rendered even if
106
+ * `onClose` is passed). Pinned tabs of either kind render first, in a
107
+ * section separated from the rest by a divider, and are never subject
108
+ * to the overflow behavior below.
109
+ * - Pinned tabs render icon-only — a fixed favicon-size square, same as a
110
+ * real browser's own pinned tabs — falling back to `FileIcon`
111
+ * when the tab itself has no `icon`, so a pinned tab is never blank.
112
+ * The full name still surfaces via Tooltip on hover/focus; there's no
113
+ * hover-revealed close button at that width, so unpinning/closing goes
114
+ * through the right-click menu or Delete/Backspace on the focused tab.
115
+ * - Every tab has the same three-item right-click menu (ContextMenu):
116
+ * "Pin tab"/"Unpin tab", "Close", and "Close other tabs" — always
117
+ * visible, each disabled when the tab wasn't given the matching
118
+ * handler. `onPinToggle` drives the first (read the tab's current `pin`
119
+ * to know the direction, then move it into — or, unpinning, to the
120
+ * front of — the right section in your own list; always disabled on
121
+ * `pin="product"`), `onClose` the second, `onCloseOthers` the third
122
+ * (close every other UNPINNED tab yourself and keep this one active —
123
+ * "close others" never closes a pinned tab of either kind; pinning is
124
+ * exactly the promise that a tab survives bulk closing).
125
+ * No visible pin button on the tab; pinning is menu-only, and pinned
126
+ * tabs are identified by sitting in the pinned section ahead of the
127
+ * divider.
128
+ * - Each `BrowserTab` needs its own `onClose` to get a close button at
129
+ * all — omit it for a tab that can't be dismissed. A tab is exactly as
130
+ * wide as its name at rest (nothing reserved on the right); on hover
131
+ * the close button appears over the end of the name, which truncates
132
+ * underneath it, so the tab's width never changes between rest and
133
+ * hover. That button is pointer-only (a focusable control can't sit
134
+ * inside a `role="tab"`): keyboard users press Delete or Backspace on
135
+ * the focused tab, or use the right-click menu's "Close".
136
+ * - Closing a tab is entirely the consumer's responsibility: `onClose`
137
+ * only reports the intent. Removing it from whatever list backs your
138
+ * tabs, and deciding which tab becomes active next, is app logic this
139
+ * component has no way to know on its own.
140
+ * - Overflow is browser-style, not a "More" menu: once unpinned tabs stop
141
+ * fitting the available width, they shrink together (flex-shrink) down
142
+ * to `min-w-16` (64px) each; past that floor the strip scrolls that
143
+ * pool horizontally instead of shrinking further. Pinned tabs are
144
+ * already fixed-size icon-only squares (see above), so they never
145
+ * shrink, grow, or join the scrolling region. The active tab scrolls
146
+ * into view
147
+ * automatically whenever it changes, so switching tabs never leaves the
148
+ * newly-active one scrolled out of sight. Only the "+" pill is truly
149
+ * fixed-size, living outside the shrink pool entirely. A soft inset
150
+ * shadow fades in on
151
+ * whichever edge(s) still have more tabs scrolled past them (both at
152
+ * once, mid-strip) and disappears once there's nothing left that way —
153
+ * a direction-aware cue, not a static "this can scroll" marker.
154
+ * - A tab's name overflowing `max-w-52` is truncated in the strip but
155
+ * shown in full in a Tooltip on hover/focus.
156
+ * - `addViews` on `BrowserTabsList` adds a "+" pill that opens a popover of
157
+ * product-defined views the user can open as new tabs — a worklist's
158
+ * saved filters, a set of report layouts — `{ id, label, icon?,
159
+ * description?, disabled?, pin? }` each. Sits immediately after the
160
+ * last tab at rest; pins to the strip's own right edge once the tabs
161
+ * overflow into their shrink/scroll region instead, same as a real
162
+ * browser's "+" button. Each is the same full-width tab pill (icon +
163
+ * label) it will become as a tab; `description` grows that row to a
164
+ * second, muted line underneath (a filter's own scope, a last-modified
165
+ * date). Past `ADD_VIEWS_SEARCH_THRESHOLD` (6) views the popover grows
166
+ * a search box filtering by label and description. A `pin` hint renders
167
+ * a small pin icon trailing the label (purely visual — opening it
168
+ * pinned is still your own `onAddView` handler's job). `onAddView` only
169
+ * reports the pick: add a tab for that view to your own list and make
170
+ * it active — or, if that view is already open, just activate the
171
+ * existing tab instead of opening a duplicate. Icon-only by default;
172
+ * `addLabel` names it for assistive tech (default "Open a view in a new
173
+ * tab"). `addTrigger` swaps in a custom trigger node in place of the
174
+ * default "+" pill (still needs its own `aria-label`). `renderAddContent`
175
+ * replaces the *entire* popover body — search box, view list, and all —
176
+ * with something fully custom (a grouped menu, anything) — called with
177
+ * a `close` function to dismiss the popover
178
+ * from inside it; `addViews`/`onAddView` don't render alongside it.
179
+ * - Each `BrowserTab` floats as a rounded pill inset from the strip's
180
+ * `bg-secondary` track. Unlike Tabs' own default variant (a translucent
181
+ * `bg-primary/10` fill), the active tab here reads as merged into the
182
+ * card below it, Chrome-style: `bg-card`/`text-card-foreground` (matching
183
+ * the content surface exactly) plus squared-off bottom corners, sitting
184
+ * flush against the track's own bottom edge with nothing grey left
185
+ * between tab and content. Inactive tabs just fill `bg-muted` on hover
186
+ * and otherwise float clear of the track's edges.
187
+ * - A leading icon uses `icon`, not the `data-icon="inline-start"` slot
188
+ * convention Button/Tabs use — it needs to sit outside the label's own
189
+ * truncation, which a plain child node sharing that flex row wouldn't.
190
+ *
191
+ * USAGE
192
+ * <BrowserTabs value={activeId} onValueChange={setActiveId}>
193
+ * <BrowserTabsList
194
+ * addViews={worklistViews} // [{ id: "overdue", label: "Overdue", icon: ClockIcon }, ...]
195
+ * onAddView={(view) => openViewTab(view)} // add to openDocs (or activate if already open)
196
+ * >
197
+ * <BrowserTab value="home" pin="product">Home</BrowserTab>
198
+ * {openDocs.map((doc) => (
199
+ * <BrowserTab
200
+ * key={doc.id}
201
+ * value={doc.id}
202
+ * icon={doc.icon}
203
+ * pin={doc.pinnedByUser ? "user" : undefined}
204
+ * onClose={() => closeDoc(doc.id)}
205
+ * >
206
+ * {doc.title}
207
+ * </BrowserTab>
208
+ * ))}
209
+ * </BrowserTabsList>
210
+ * <BrowserTabsContent value="home">...</BrowserTabsContent>
211
+ * {openDocs.map((doc) => (
212
+ * <BrowserTabsContent key={doc.id} value={doc.id}>
213
+ * <DocView doc={doc} />
214
+ * </BrowserTabsContent>
215
+ * ))}
216
+ * </BrowserTabs>
217
+ */
218
+ //# sourceMappingURL=browser-tabs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-tabs.d.ts","sourceRoot":"","sources":["../../../src/components/ui/browser-tabs.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,IAAI,IAAI,aAAa,EAAE,MAAM,UAAU,CAAA;AA8BhD,OAAO,EAAE,WAAW,IAAI,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAYxE,iBAAS,WAAW,CAAC,EACnB,SAAS,EACT,KAAK,EACL,YAAY,EACZ,aAAa,EACb,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,aAAa,CAAC,IAAI,CAAC,qBAyBjD;AAgCD,4FAA4F;AAC5F,KAAK,kBAAkB,GAAG;IACxB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,kEAAkE;IAClE,IAAI,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAClD,oKAAoK;IACpK,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,4VAA4V;IAC5V,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACzB,CAAA;AAoBD,iBAAS,eAAe,CAAC,EACvB,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,QAAqC,EACrC,UAAU,EACV,gBAAgB,EAChB,YAAY,EAAE,SAAS,EACvB,iBAAiB,EAAE,cAAc,EACjC,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,aAAa,CAAC,IAAI,CAAC,GAAG;IACnD,klBAAklB;IACllB,QAAQ,CAAC,EAAE,kBAAkB,EAAE,CAAA;IAC/B,6DAA6D;IAC7D,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAA;IAC9C,2LAA2L;IAC3L,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,8PAA8P;IAC9P,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC5B,qWAAqW;IACrW,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,IAAI,KAAK,KAAK,CAAC,SAAS,CAAA;CAC1D,qBA2QA;AAkJD,KAAK,eAAe,GAAG;IACrB,KAAK,EAAE,MAAM,CAAA;IACb,wHAAwH;IACxH,IAAI,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAClD,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,4SAA4S;IAC5S,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACxB,mWAAmW;IACnW,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,4KAA4K;IAC5K,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,ucAAuc;IACvc,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;IACxB,oXAAoX;IACpX,aAAa,CAAC,EAAE,MAAM,IAAI,CAAA;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B,CAAA;AAqXD,iBAAS,UAAU,CAAC,KAAK,EAAE,eAAe,qBAazC;AAED,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,UAAU,EAAE,kBAAkB,EAAE,CAAA;AACvE,YAAY,EAAE,kBAAkB,EAAE,CAAA;AAElC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuIG"}