@epilot/spark-ui 0.20.0 → 0.20.2

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 (314) hide show
  1. package/dist/components/accordion.cjs +7 -7
  2. package/dist/components/accordion.cjs.map +1 -1
  3. package/dist/components/accordion.d.ts +1 -1
  4. package/dist/components/accordion.js +1 -1
  5. package/dist/components/alert-dialog.cjs +10 -10
  6. package/dist/components/alert-dialog.cjs.map +1 -1
  7. package/dist/components/alert-dialog.js +1 -1
  8. package/dist/components/attachment.cjs +10 -10
  9. package/dist/components/attachment.cjs.map +1 -1
  10. package/dist/components/attachment.d.cts +2 -2
  11. package/dist/components/attachment.d.ts +2 -2
  12. package/dist/components/autocomplete.cjs +13 -13
  13. package/dist/components/autocomplete.cjs.map +1 -1
  14. package/dist/components/autocomplete.js +1 -1
  15. package/dist/components/avatar.cjs +2 -2
  16. package/dist/components/avatar.cjs.map +1 -1
  17. package/dist/components/avatar.js +1 -1
  18. package/dist/components/badge.cjs +2 -2
  19. package/dist/components/badge.cjs.map +1 -1
  20. package/dist/components/badge.js +2 -2
  21. package/dist/components/badge.js.map +1 -1
  22. package/dist/components/bar-chart-with-total.d.cts +1 -1
  23. package/dist/components/bar-chart-with-total.d.ts +1 -1
  24. package/dist/components/bar-chart.cjs +4 -4
  25. package/dist/components/bar-chart.cjs.map +1 -1
  26. package/dist/components/bar-chart.js +2 -2
  27. package/dist/components/bar-chart.js.map +1 -1
  28. package/dist/components/box.cjs +2 -2
  29. package/dist/components/box.cjs.map +1 -1
  30. package/dist/components/box.js +1 -1
  31. package/dist/components/breadcrumbs.cjs +7 -7
  32. package/dist/components/breadcrumbs.cjs.map +1 -1
  33. package/dist/components/bubble.cjs +5 -5
  34. package/dist/components/bubble.cjs.map +1 -1
  35. package/dist/components/bubble.d.cts +1 -1
  36. package/dist/components/bubble.d.ts +1 -1
  37. package/dist/components/button-group.cjs +5 -5
  38. package/dist/components/button-group.cjs.map +1 -1
  39. package/dist/components/button-group.js +1 -1
  40. package/dist/components/button.cjs +2 -2
  41. package/dist/components/button.cjs.map +1 -1
  42. package/dist/components/button.d.cts +3 -3
  43. package/dist/components/button.d.ts +3 -3
  44. package/dist/components/button.js +1 -1
  45. package/dist/components/button.js.map +1 -1
  46. package/dist/components/calendar.cjs +12 -11
  47. package/dist/components/calendar.cjs.map +1 -1
  48. package/dist/components/calendar.js +5 -4
  49. package/dist/components/calendar.js.map +1 -1
  50. package/dist/components/callout.cjs +8 -8
  51. package/dist/components/callout.cjs.map +1 -1
  52. package/dist/components/callout.d.ts +1 -1
  53. package/dist/components/callout.js +1 -1
  54. package/dist/components/card.cjs +16 -16
  55. package/dist/components/card.cjs.map +1 -1
  56. package/dist/components/card.js +2 -2
  57. package/dist/components/card.js.map +1 -1
  58. package/dist/components/chart.cjs +2 -2
  59. package/dist/components/chart.cjs.map +1 -1
  60. package/dist/components/checkbox.cjs +2 -2
  61. package/dist/components/checkbox.cjs.map +1 -1
  62. package/dist/components/checkbox.js +1 -1
  63. package/dist/components/checkbox.js.map +1 -1
  64. package/dist/components/circular-gauge.cjs +3 -3
  65. package/dist/components/circular-gauge.cjs.map +1 -1
  66. package/dist/components/circular-gauge.js +1 -1
  67. package/dist/components/circular-gauge.js.map +1 -1
  68. package/dist/components/day-of-week-picker.cjs +4 -4
  69. package/dist/components/day-of-week-picker.cjs.map +1 -1
  70. package/dist/components/dialog.cjs +9 -9
  71. package/dist/components/dialog.cjs.map +1 -1
  72. package/dist/components/dialog.js +1 -1
  73. package/dist/components/donut-chart.cjs.map +1 -1
  74. package/dist/components/donut-chart.js.map +1 -1
  75. package/dist/components/drawer.cjs +8 -8
  76. package/dist/components/drawer.cjs.map +1 -1
  77. package/dist/components/drawer.js +2 -2
  78. package/dist/components/drawer.js.map +1 -1
  79. package/dist/components/dropdown-menu.cjs +11 -11
  80. package/dist/components/dropdown-menu.cjs.map +1 -1
  81. package/dist/components/dropdown-menu.js +1 -1
  82. package/dist/components/empty-state.d.ts +1 -1
  83. package/dist/components/energy-breakdown.cjs +80 -0
  84. package/dist/components/energy-breakdown.cjs.map +1 -0
  85. package/dist/components/energy-breakdown.d.cts +24 -0
  86. package/dist/components/energy-breakdown.d.ts +24 -0
  87. package/dist/components/energy-breakdown.js +79 -0
  88. package/dist/components/energy-breakdown.js.map +1 -0
  89. package/dist/components/energy-history-chart.cjs +63 -0
  90. package/dist/components/energy-history-chart.cjs.map +1 -0
  91. package/dist/components/energy-history-chart.d.cts +64 -0
  92. package/dist/components/energy-history-chart.d.ts +64 -0
  93. package/dist/components/energy-history-chart.js +62 -0
  94. package/dist/components/energy-history-chart.js.map +1 -0
  95. package/dist/components/entity-card.cjs +11 -11
  96. package/dist/components/entity-card.cjs.map +1 -1
  97. package/dist/components/entity-card.d.ts +1 -1
  98. package/dist/components/field.cjs +16 -16
  99. package/dist/components/field.cjs.map +1 -1
  100. package/dist/components/field.js +1 -1
  101. package/dist/components/field.js.map +1 -1
  102. package/dist/components/hero-metric.cjs +4 -4
  103. package/dist/components/hero-metric.cjs.map +1 -1
  104. package/dist/components/icon.cjs +6 -6
  105. package/dist/components/icon.cjs.map +1 -1
  106. package/dist/components/icon.js +5 -5
  107. package/dist/components/icon.js.map +1 -1
  108. package/dist/components/info-block.cjs +9 -9
  109. package/dist/components/info-block.cjs.map +1 -1
  110. package/dist/components/info-block.d.cts +1 -1
  111. package/dist/components/info-block.d.ts +1 -1
  112. package/dist/components/input-date.cjs +5 -4
  113. package/dist/components/input-date.cjs.map +1 -1
  114. package/dist/components/input-date.d.cts +3 -1
  115. package/dist/components/input-date.d.ts +3 -1
  116. package/dist/components/input-date.js +3 -2
  117. package/dist/components/input-date.js.map +1 -1
  118. package/dist/components/input-group.cjs +5 -5
  119. package/dist/components/input-group.cjs.map +1 -1
  120. package/dist/components/input-otp.cjs +3 -3
  121. package/dist/components/input-otp.cjs.map +1 -1
  122. package/dist/components/input-otp.js +1 -1
  123. package/dist/components/input.cjs +3 -3
  124. package/dist/components/input.cjs.map +1 -1
  125. package/dist/components/input.js +1 -1
  126. package/dist/components/label.cjs +2 -2
  127. package/dist/components/label.cjs.map +1 -1
  128. package/dist/components/layout.cjs +2 -2
  129. package/dist/components/layout.cjs.map +1 -1
  130. package/dist/components/line-chart.cjs +7 -7
  131. package/dist/components/line-chart.cjs.map +1 -1
  132. package/dist/components/line-chart.js +5 -5
  133. package/dist/components/line-chart.js.map +1 -1
  134. package/dist/components/list.cjs +11 -11
  135. package/dist/components/list.cjs.map +1 -1
  136. package/dist/components/list.d.cts +7 -2
  137. package/dist/components/list.d.ts +7 -2
  138. package/dist/components/list.js +2 -2
  139. package/dist/components/list.js.map +1 -1
  140. package/dist/components/marker.cjs +4 -4
  141. package/dist/components/marker.cjs.map +1 -1
  142. package/dist/components/marker.d.cts +1 -1
  143. package/dist/components/marker.d.ts +1 -1
  144. package/dist/components/message-scroller.cjs +8 -8
  145. package/dist/components/message-scroller.cjs.map +1 -1
  146. package/dist/components/message-scroller.js +4 -4
  147. package/dist/components/message-scroller.js.map +1 -1
  148. package/dist/components/message.cjs +7 -7
  149. package/dist/components/message.cjs.map +1 -1
  150. package/dist/components/number-flow.d.cts +2 -12
  151. package/dist/components/number-flow.d.ts +2 -12
  152. package/dist/components/page-header.cjs +6 -6
  153. package/dist/components/page-header.cjs.map +1 -1
  154. package/dist/components/page-header.js +1 -1
  155. package/dist/components/period-tabs.cjs +6 -6
  156. package/dist/components/period-tabs.cjs.map +1 -1
  157. package/dist/components/pill.cjs +4 -4
  158. package/dist/components/pill.cjs.map +1 -1
  159. package/dist/components/pill.js +4 -4
  160. package/dist/components/pill.js.map +1 -1
  161. package/dist/components/popover.cjs +2 -2
  162. package/dist/components/popover.cjs.map +1 -1
  163. package/dist/components/power-history-chart.cjs +498 -0
  164. package/dist/components/power-history-chart.cjs.map +1 -0
  165. package/dist/components/power-history-chart.d.cts +71 -0
  166. package/dist/components/power-history-chart.d.ts +71 -0
  167. package/dist/components/power-history-chart.js +496 -0
  168. package/dist/components/power-history-chart.js.map +1 -0
  169. package/dist/components/power-network.cjs +559 -0
  170. package/dist/components/power-network.cjs.map +1 -0
  171. package/dist/components/power-network.d.cts +80 -0
  172. package/dist/components/power-network.d.ts +80 -0
  173. package/dist/components/power-network.js +553 -0
  174. package/dist/components/power-network.js.map +1 -0
  175. package/dist/components/progress.cjs +3 -3
  176. package/dist/components/progress.cjs.map +1 -1
  177. package/dist/components/progress.js +1 -1
  178. package/dist/components/progress.js.map +1 -1
  179. package/dist/components/radio-card-group.cjs +3 -3
  180. package/dist/components/radio-card-group.cjs.map +1 -1
  181. package/dist/components/radio.cjs +3 -3
  182. package/dist/components/radio.cjs.map +1 -1
  183. package/dist/components/radio.js +1 -1
  184. package/dist/components/sankey-chart.cjs +15 -5
  185. package/dist/components/sankey-chart.cjs.map +1 -1
  186. package/dist/components/sankey-chart.d.cts +3 -2
  187. package/dist/components/sankey-chart.d.ts +3 -2
  188. package/dist/components/sankey-chart.js +13 -4
  189. package/dist/components/sankey-chart.js.map +1 -1
  190. package/dist/components/schedule-editor.cjs +9 -9
  191. package/dist/components/schedule-editor.cjs.map +1 -1
  192. package/dist/components/schedule-list.cjs +11 -11
  193. package/dist/components/schedule-list.cjs.map +1 -1
  194. package/dist/components/schedule-list.js +1 -1
  195. package/dist/components/scroll-area.cjs +3 -3
  196. package/dist/components/scroll-area.cjs.map +1 -1
  197. package/dist/components/segmented-control.cjs +8 -8
  198. package/dist/components/segmented-control.cjs.map +1 -1
  199. package/dist/components/segmented-control.d.cts +2 -16
  200. package/dist/components/segmented-control.d.ts +2 -16
  201. package/dist/components/segmented-control.js +5 -5
  202. package/dist/components/segmented-control.js.map +1 -1
  203. package/dist/components/select.cjs +13 -13
  204. package/dist/components/select.cjs.map +1 -1
  205. package/dist/components/select.js +2 -2
  206. package/dist/components/separator.cjs +3 -3
  207. package/dist/components/separator.cjs.map +1 -1
  208. package/dist/components/series-legend.cjs +4 -4
  209. package/dist/components/series-legend.cjs.map +1 -1
  210. package/dist/components/sheet.cjs +9 -9
  211. package/dist/components/sheet.cjs.map +1 -1
  212. package/dist/components/sheet.js +1 -1
  213. package/dist/components/skeleton.cjs +3 -3
  214. package/dist/components/skeleton.cjs.map +1 -1
  215. package/dist/components/slider.cjs +11 -11
  216. package/dist/components/slider.cjs.map +1 -1
  217. package/dist/components/slider.js.map +1 -1
  218. package/dist/components/solar-forecast-chart.cjs +108 -0
  219. package/dist/components/solar-forecast-chart.cjs.map +1 -0
  220. package/dist/components/solar-forecast-chart.d.cts +77 -0
  221. package/dist/components/solar-forecast-chart.d.ts +77 -0
  222. package/dist/components/solar-forecast-chart.js +103 -0
  223. package/dist/components/solar-forecast-chart.js.map +1 -0
  224. package/dist/components/sortable-list.cjs +3 -3
  225. package/dist/components/sortable-list.cjs.map +1 -1
  226. package/dist/components/spinner.cjs +2 -2
  227. package/dist/components/spinner.cjs.map +1 -1
  228. package/dist/components/stat-card.cjs +8 -8
  229. package/dist/components/stat-card.cjs.map +1 -1
  230. package/dist/components/stepper.cjs +3 -3
  231. package/dist/components/stepper.cjs.map +1 -1
  232. package/dist/components/stepper.js +1 -1
  233. package/dist/components/switch.cjs +3 -3
  234. package/dist/components/switch.cjs.map +1 -1
  235. package/dist/components/switch.js +2 -2
  236. package/dist/components/switch.js.map +1 -1
  237. package/dist/components/table.cjs +9 -9
  238. package/dist/components/table.cjs.map +1 -1
  239. package/dist/components/table.js +1 -1
  240. package/dist/components/tabs.cjs +10 -10
  241. package/dist/components/tabs.cjs.map +1 -1
  242. package/dist/components/tabs.d.cts +1 -8
  243. package/dist/components/tabs.d.ts +1 -8
  244. package/dist/components/tabs.js +3 -3
  245. package/dist/components/tabs.js.map +1 -1
  246. package/dist/components/textarea.cjs +3 -3
  247. package/dist/components/textarea.cjs.map +1 -1
  248. package/dist/components/textarea.js +1 -1
  249. package/dist/components/theme.cjs +2 -2
  250. package/dist/components/theme.cjs.map +1 -1
  251. package/dist/components/theme.js +1 -1
  252. package/dist/components/thumbnail.cjs +3 -3
  253. package/dist/components/thumbnail.cjs.map +1 -1
  254. package/dist/components/time-picker.cjs +3 -3
  255. package/dist/components/time-picker.cjs.map +1 -1
  256. package/dist/components/toast.cjs +40 -15
  257. package/dist/components/toast.cjs.map +1 -1
  258. package/dist/components/toast.d.cts +15 -2
  259. package/dist/components/toast.d.ts +15 -2
  260. package/dist/components/toast.js +33 -8
  261. package/dist/components/toast.js.map +1 -1
  262. package/dist/components/toggle-group.cjs +40 -0
  263. package/dist/components/toggle-group.cjs.map +1 -0
  264. package/dist/components/toggle-group.d.cts +28 -0
  265. package/dist/components/toggle-group.d.ts +28 -0
  266. package/dist/components/toggle-group.js +37 -0
  267. package/dist/components/toggle-group.js.map +1 -0
  268. package/dist/components/toggle.cjs +69 -0
  269. package/dist/components/toggle.cjs.map +1 -0
  270. package/dist/components/toggle.d.cts +23 -0
  271. package/dist/components/toggle.d.ts +23 -0
  272. package/dist/components/toggle.js +66 -0
  273. package/dist/components/toggle.js.map +1 -0
  274. package/dist/components/tooltip.cjs +4 -4
  275. package/dist/components/tooltip.cjs.map +1 -1
  276. package/dist/components/tooltip.js +2 -2
  277. package/dist/components/tooltip.js.map +1 -1
  278. package/dist/components/typography.cjs +6 -6
  279. package/dist/components/typography.cjs.map +1 -1
  280. package/dist/components/wizard-layout.cjs +8 -8
  281. package/dist/components/wizard-layout.cjs.map +1 -1
  282. package/dist/lib/generate-radix-colors.cjs +1 -1
  283. package/dist/lib/generate-radix-colors.cjs.map +1 -1
  284. package/dist/lib/generate-radix-colors.js +1 -1
  285. package/dist/lib/generate-radix-colors.js.map +1 -1
  286. package/dist/lib/input-box-variants.cjs +9 -9
  287. package/dist/lib/input-box-variants.cjs.map +1 -1
  288. package/dist/lib/toggle-group-context.cjs +12 -0
  289. package/dist/lib/toggle-group-context.cjs.map +1 -0
  290. package/dist/lib/toggle-group-context.d.cts +17 -0
  291. package/dist/lib/toggle-group-context.d.ts +17 -0
  292. package/dist/lib/toggle-group-context.js +9 -0
  293. package/dist/lib/toggle-group-context.js.map +1 -0
  294. package/dist/number-flow-Bch81ixZ.d.cts +14 -0
  295. package/dist/number-flow-Bch81ixZ.d.ts +14 -0
  296. package/dist/styles/spark-default.css +11 -0
  297. package/dist/styles/theme.css +15 -4
  298. package/dist/utils/build-sankey-nodes.cjs +72 -0
  299. package/dist/utils/build-sankey-nodes.cjs.map +1 -0
  300. package/dist/utils/build-sankey-nodes.d.cts +27 -0
  301. package/dist/utils/build-sankey-nodes.d.ts +27 -0
  302. package/dist/utils/build-sankey-nodes.js +71 -0
  303. package/dist/utils/build-sankey-nodes.js.map +1 -0
  304. package/dist/utils/cn.cjs +2 -2
  305. package/dist/utils/cn.d.cts +1 -1
  306. package/dist/utils/cn.d.ts +1 -1
  307. package/dist/utils/cn.js +1 -1
  308. package/dist/utils/format.cjs +14 -0
  309. package/dist/utils/format.cjs.map +1 -1
  310. package/dist/utils/format.d.cts +8 -1
  311. package/dist/utils/format.d.ts +8 -1
  312. package/dist/utils/format.js +12 -1
  313. package/dist/utils/format.js.map +1 -1
  314. package/package.json +1 -1
@@ -1,47 +1,47 @@
1
1
  "use client";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  let react_jsx_runtime = require("react/jsx-runtime");
4
- let cnfast = require("cnfast");
4
+ let cn = require("cn");
5
5
  //#region src/components/stat-card.tsx
6
6
  const StatCardContainer = ({ className, ...rest }) => {
7
7
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8
- className: (0, cnfast.cn)("flex w-full flex-col gap-3 p-4 text-left", className),
8
+ className: (0, cn.cn)("flex w-full flex-col gap-3 p-4 text-left", className),
9
9
  ...rest
10
10
  });
11
11
  };
12
12
  const StatCardLabel = ({ className, ...rest }) => {
13
13
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
14
- className: (0, cnfast.cn)("text-xs font-medium text-gray-light", className),
14
+ className: (0, cn.cn)("text-xs font-medium text-gray-light", className),
15
15
  ...rest
16
16
  });
17
17
  };
18
18
  const StatCardContent = ({ className, ...rest }) => {
19
19
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
20
- className: (0, cnfast.cn)("flex items-end justify-between gap-px", className),
20
+ className: (0, cn.cn)("flex items-end justify-between gap-px", className),
21
21
  ...rest
22
22
  });
23
23
  };
24
24
  const StatCardValueContainer = ({ className, ...rest }) => {
25
25
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
26
- className: (0, cnfast.cn)("flex flex-col gap-0.5", className),
26
+ className: (0, cn.cn)("flex flex-col gap-0.5", className),
27
27
  ...rest
28
28
  });
29
29
  };
30
30
  const StatCardValue = ({ className, ...rest }) => {
31
31
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
32
- className: (0, cnfast.cn)("text-lg font-bold text-gray tabular-nums", className),
32
+ className: (0, cn.cn)("text-lg font-bold text-gray tabular-nums", className),
33
33
  ...rest
34
34
  });
35
35
  };
36
36
  const StatCardSecondaryValue = ({ className, ...rest }) => {
37
37
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
38
- className: (0, cnfast.cn)("text-xs text-gray-light", className),
38
+ className: (0, cn.cn)("text-xs text-gray-light", className),
39
39
  ...rest
40
40
  });
41
41
  };
42
42
  const StatCardIcon = ({ className, ...rest }) => {
43
43
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
44
- className: (0, cnfast.cn)("flex size-10 shrink-0 items-center justify-center rounded-[max(var(--spark-rounded-md),var(--spark-rounded-full))]", className),
44
+ className: (0, cn.cn)("flex size-10 shrink-0 items-center justify-center rounded-[max(var(--spark-rounded-md),var(--spark-rounded-full))]", className),
45
45
  ...rest
46
46
  });
47
47
  };
@@ -1 +1 @@
1
- {"version":3,"file":"stat-card.cjs","names":[],"sources":["../../src/components/stat-card.tsx"],"sourcesContent":["import { cn } from '../utils/cn'\n\nconst StatCardContainer = ({\n className,\n ...rest\n}: React.ComponentProps<'div'>) => {\n return (\n <div\n className={cn('flex w-full flex-col gap-3 p-4 text-left', className)}\n {...rest}\n />\n )\n}\n\nconst StatCardLabel = ({\n className,\n ...rest\n}: React.ComponentProps<'span'>) => {\n return (\n <span\n className={cn('text-xs font-medium text-gray-light', className)}\n {...rest}\n />\n )\n}\n\nconst StatCardContent = ({\n className,\n ...rest\n}: React.ComponentProps<'div'>) => {\n return (\n <div\n className={cn('flex items-end justify-between gap-px', className)}\n {...rest}\n />\n )\n}\n\nconst StatCardValueContainer = ({\n className,\n ...rest\n}: React.ComponentProps<'div'>) => {\n return <div className={cn('flex flex-col gap-0.5', className)} {...rest} />\n}\n\nconst StatCardValue = ({\n className,\n ...rest\n}: React.ComponentProps<'span'>) => {\n return (\n <span\n className={cn('text-lg font-bold text-gray tabular-nums', className)}\n {...rest}\n />\n )\n}\n\nconst StatCardSecondaryValue = ({\n className,\n ...rest\n}: React.ComponentProps<'span'>) => {\n return <span className={cn('text-xs text-gray-light', className)} {...rest} />\n}\n\nconst StatCardIcon = ({ className, ...rest }: React.ComponentProps<'div'>) => {\n return (\n <div\n className={cn(\n // max() pill escape (matches Icon): a tile stays rounded-md at low Roundness but\n // becomes a circle at large/full, same as it did pre-harmonization via clamping.\n 'flex size-10 shrink-0 items-center justify-center rounded-[max(var(--spark-rounded-md),var(--spark-rounded-full))]',\n className,\n )}\n {...rest}\n />\n )\n}\n\nexport {\n StatCardContainer,\n StatCardLabel,\n StatCardContent,\n StatCardValueContainer,\n StatCardValue,\n StatCardSecondaryValue,\n StatCardIcon,\n}\n"],"mappings":";;;;;AAEA,MAAM,qBAAqB,EACzB,WACA,GAAG,WAC8B;CACjC,OACE,iBAAA,GAAA,kBAAA,KAAC,OAAD;EACE,YAAA,GAAA,OAAA,IAAc,4CAA4C,SAAS;EACnE,GAAI;CACL,CAAA;AAEL;AAEA,MAAM,iBAAiB,EACrB,WACA,GAAG,WAC+B;CAClC,OACE,iBAAA,GAAA,kBAAA,KAAC,QAAD;EACE,YAAA,GAAA,OAAA,IAAc,uCAAuC,SAAS;EAC9D,GAAI;CACL,CAAA;AAEL;AAEA,MAAM,mBAAmB,EACvB,WACA,GAAG,WAC8B;CACjC,OACE,iBAAA,GAAA,kBAAA,KAAC,OAAD;EACE,YAAA,GAAA,OAAA,IAAc,yCAAyC,SAAS;EAChE,GAAI;CACL,CAAA;AAEL;AAEA,MAAM,0BAA0B,EAC9B,WACA,GAAG,WAC8B;CACjC,OAAO,iBAAA,GAAA,kBAAA,KAAC,OAAD;EAAK,YAAA,GAAA,OAAA,IAAc,yBAAyB,SAAS;EAAG,GAAI;CAAO,CAAA;AAC5E;AAEA,MAAM,iBAAiB,EACrB,WACA,GAAG,WAC+B;CAClC,OACE,iBAAA,GAAA,kBAAA,KAAC,QAAD;EACE,YAAA,GAAA,OAAA,IAAc,4CAA4C,SAAS;EACnE,GAAI;CACL,CAAA;AAEL;AAEA,MAAM,0BAA0B,EAC9B,WACA,GAAG,WAC+B;CAClC,OAAO,iBAAA,GAAA,kBAAA,KAAC,QAAD;EAAM,YAAA,GAAA,OAAA,IAAc,2BAA2B,SAAS;EAAG,GAAI;CAAO,CAAA;AAC/E;AAEA,MAAM,gBAAgB,EAAE,WAAW,GAAG,WAAwC;CAC5E,OACE,iBAAA,GAAA,kBAAA,KAAC,OAAD;EACE,YAAA,GAAA,OAAA,IAGE,sHACA,SACF;EACA,GAAI;CACL,CAAA;AAEL"}
1
+ {"version":3,"file":"stat-card.cjs","names":[],"sources":["../../src/components/stat-card.tsx"],"sourcesContent":["import { cn } from '../utils/cn'\n\nconst StatCardContainer = ({\n className,\n ...rest\n}: React.ComponentProps<'div'>) => {\n return (\n <div\n className={cn('flex w-full flex-col gap-3 p-4 text-left', className)}\n {...rest}\n />\n )\n}\n\nconst StatCardLabel = ({\n className,\n ...rest\n}: React.ComponentProps<'span'>) => {\n return (\n <span\n className={cn('text-xs font-medium text-gray-light', className)}\n {...rest}\n />\n )\n}\n\nconst StatCardContent = ({\n className,\n ...rest\n}: React.ComponentProps<'div'>) => {\n return (\n <div\n className={cn('flex items-end justify-between gap-px', className)}\n {...rest}\n />\n )\n}\n\nconst StatCardValueContainer = ({\n className,\n ...rest\n}: React.ComponentProps<'div'>) => {\n return <div className={cn('flex flex-col gap-0.5', className)} {...rest} />\n}\n\nconst StatCardValue = ({\n className,\n ...rest\n}: React.ComponentProps<'span'>) => {\n return (\n <span\n className={cn('text-lg font-bold text-gray tabular-nums', className)}\n {...rest}\n />\n )\n}\n\nconst StatCardSecondaryValue = ({\n className,\n ...rest\n}: React.ComponentProps<'span'>) => {\n return <span className={cn('text-xs text-gray-light', className)} {...rest} />\n}\n\nconst StatCardIcon = ({ className, ...rest }: React.ComponentProps<'div'>) => {\n return (\n <div\n className={cn(\n // max() pill escape (matches Icon): a tile stays rounded-md at low Roundness but\n // becomes a circle at large/full, same as it did pre-harmonization via clamping.\n 'flex size-10 shrink-0 items-center justify-center rounded-[max(var(--spark-rounded-md),var(--spark-rounded-full))]',\n className,\n )}\n {...rest}\n />\n )\n}\n\nexport {\n StatCardContainer,\n StatCardLabel,\n StatCardContent,\n StatCardValueContainer,\n StatCardValue,\n StatCardSecondaryValue,\n StatCardIcon,\n}\n"],"mappings":";;;;;AAEA,MAAM,qBAAqB,EACzB,WACA,GAAG,WAC8B;CACjC,OACE,iBAAA,GAAA,kBAAA,KAAC,OAAD;EACE,YAAA,GAAA,GAAA,IAAc,4CAA4C,SAAS;EACnE,GAAI;CACL,CAAA;AAEL;AAEA,MAAM,iBAAiB,EACrB,WACA,GAAG,WAC+B;CAClC,OACE,iBAAA,GAAA,kBAAA,KAAC,QAAD;EACE,YAAA,GAAA,GAAA,IAAc,uCAAuC,SAAS;EAC9D,GAAI;CACL,CAAA;AAEL;AAEA,MAAM,mBAAmB,EACvB,WACA,GAAG,WAC8B;CACjC,OACE,iBAAA,GAAA,kBAAA,KAAC,OAAD;EACE,YAAA,GAAA,GAAA,IAAc,yCAAyC,SAAS;EAChE,GAAI;CACL,CAAA;AAEL;AAEA,MAAM,0BAA0B,EAC9B,WACA,GAAG,WAC8B;CACjC,OAAO,iBAAA,GAAA,kBAAA,KAAC,OAAD;EAAK,YAAA,GAAA,GAAA,IAAc,yBAAyB,SAAS;EAAG,GAAI;CAAO,CAAA;AAC5E;AAEA,MAAM,iBAAiB,EACrB,WACA,GAAG,WAC+B;CAClC,OACE,iBAAA,GAAA,kBAAA,KAAC,QAAD;EACE,YAAA,GAAA,GAAA,IAAc,4CAA4C,SAAS;EACnE,GAAI;CACL,CAAA;AAEL;AAEA,MAAM,0BAA0B,EAC9B,WACA,GAAG,WAC+B;CAClC,OAAO,iBAAA,GAAA,kBAAA,KAAC,QAAD;EAAM,YAAA,GAAA,GAAA,IAAc,2BAA2B,SAAS;EAAG,GAAI;CAAO,CAAA;AAC/E;AAEA,MAAM,gBAAgB,EAAE,WAAW,GAAG,WAAwC;CAC5E,OACE,iBAAA,GAAA,kBAAA,KAAC,OAAD;EACE,YAAA,GAAA,GAAA,IAGE,sHACA,SACF;EACA,GAAI;CACL,CAAA;AAEL"}
@@ -1,11 +1,11 @@
1
1
  "use client";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const require_chunk = require("../chunk-DY84GLCh.cjs");
4
- let _epilot_spark_icons = require("@epilot/spark-icons");
5
4
  let react = require("react");
6
5
  react = require_chunk.__toESM(react);
6
+ let _epilot_spark_icons = require("@epilot/spark-icons");
7
7
  let react_jsx_runtime = require("react/jsx-runtime");
8
- let cnfast = require("cnfast");
8
+ let cn = require("cn");
9
9
  //#region src/components/stepper.tsx
10
10
  const Stepper = react.forwardRef(({ value, onValueChange, onValueCommit, min = 0, max = 100, step = 1, formatValue = (v) => String(v), disabled, className, commitDelayMs = 400, "aria-label": ariaLabel, decreaseLabel, increaseLabel }, ref) => {
11
11
  const commitTimerRef = react.useRef(null);
@@ -40,7 +40,7 @@ const Stepper = react.forwardRef(({ value, onValueChange, onValueCommit, min = 0
40
40
  ref,
41
41
  role: "group",
42
42
  "aria-label": ariaLabel,
43
- className: (0, cnfast.cn)("inline-flex h-12 w-full items-center justify-between rounded-md bg-base-gray-soft px-2", className),
43
+ className: (0, cn.cn)("inline-flex h-12 w-full items-center justify-between rounded-md bg-base-gray-soft px-2", className),
44
44
  children: [
45
45
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
46
46
  type: "button",
@@ -1 +1 @@
1
- {"version":3,"file":"stepper.cjs","names":["React","ChevronLeft","ChevronRight"],"sources":["../../src/components/stepper.tsx"],"sourcesContent":["import { ChevronLeft, ChevronRight } from '@epilot/spark-icons'\nimport * as React from 'react'\nimport { cn } from '../utils/cn'\n\ninterface StepperProps {\n value: number\n onValueChange: (value: number) => void\n /**\n * Fires once after the user stops interacting (default: 400ms after the last\n * click). Use this for side effects like persisting the value, so rapid\n * clicks don't fan out into a request per click.\n */\n onValueCommit?: (value: number) => void\n min?: number\n max?: number\n step?: number\n formatValue?: (value: number) => string\n disabled?: boolean\n className?: string\n /** Delay (ms) after the last click before `onValueCommit` fires. */\n commitDelayMs?: number\n /** Accessible label, e.g. \"Sunshare percentage\". */\n 'aria-label'?: string\n /** Accessible label for the decrement button. */\n decreaseLabel: string\n /** Accessible label for the increment button. */\n increaseLabel: string\n}\n\nconst Stepper = React.forwardRef<HTMLDivElement, StepperProps>(\n (\n {\n value,\n onValueChange,\n onValueCommit,\n min = 0,\n max = 100,\n step = 1,\n formatValue = (v) => String(v),\n disabled,\n className,\n commitDelayMs = 400,\n 'aria-label': ariaLabel,\n decreaseLabel,\n increaseLabel,\n },\n ref,\n ) => {\n const commitTimerRef = React.useRef<ReturnType<typeof setTimeout> | null>(\n null,\n )\n\n React.useEffect(\n () => () => {\n if (commitTimerRef.current) clearTimeout(commitTimerRef.current)\n },\n [],\n )\n\n const scheduleCommit = (next: number) => {\n if (!onValueCommit) return\n if (commitTimerRef.current) clearTimeout(commitTimerRef.current)\n commitTimerRef.current = setTimeout(() => {\n commitTimerRef.current = null\n onValueCommit(next)\n }, commitDelayMs)\n }\n\n const decrement = () => {\n const next = Math.max(min, value - step)\n if (next !== value) {\n onValueChange(next)\n scheduleCommit(next)\n }\n }\n const increment = () => {\n const next = Math.min(max, value + step)\n if (next !== value) {\n onValueChange(next)\n scheduleCommit(next)\n }\n }\n\n const atMin = value <= min\n const atMax = value >= max\n\n return (\n <div\n ref={ref}\n role=\"group\"\n aria-label={ariaLabel}\n className={cn(\n 'inline-flex h-12 w-full items-center justify-between rounded-md bg-base-gray-soft px-2',\n className,\n )}\n >\n <button\n type=\"button\"\n aria-label={decreaseLabel}\n onClick={decrement}\n disabled={disabled || atMin}\n className=\"touch-target inline-flex size-8 items-center justify-center rounded-sm text-gray transition-colors hover:bg-gray-a3 disabled:opacity-40 disabled:hover:bg-transparent motion-reduce:transition-none\"\n >\n <ChevronLeft className=\"[--spark-icon-size:16px]\" />\n </button>\n <span\n className=\"text-base font-semibold text-gray tabular-nums select-none\"\n aria-live=\"polite\"\n >\n {formatValue(value)}\n </span>\n <button\n type=\"button\"\n aria-label={increaseLabel}\n onClick={increment}\n disabled={disabled || atMax}\n className=\"touch-target inline-flex size-8 items-center justify-center rounded-sm text-gray transition-colors hover:bg-gray-a3 disabled:opacity-40 disabled:hover:bg-transparent motion-reduce:transition-none\"\n >\n <ChevronRight className=\"[--spark-icon-size:16px]\" />\n </button>\n </div>\n )\n },\n)\n\nStepper.displayName = 'Stepper'\n\nexport { Stepper }\nexport type { StepperProps }\n"],"mappings":";;;;;;;;;AA6BA,MAAM,UAAUA,MAAM,YAElB,EACE,OACA,eACA,eACA,MAAM,GACN,MAAM,KACN,OAAO,GACP,eAAe,MAAM,OAAO,CAAC,GAC7B,UACA,WACA,gBAAgB,KAChB,cAAc,WACd,eACA,iBAEF,QACG;CACH,MAAM,iBAAiBA,MAAM,OAC3B,IACF;CAEA,MAAM,sBACQ;EACV,IAAI,eAAe,SAAS,aAAa,eAAe,OAAO;CACjE,GACA,CAAC,CACH;CAEA,MAAM,kBAAkB,SAAiB;EACvC,IAAI,CAAC,eAAe;EACpB,IAAI,eAAe,SAAS,aAAa,eAAe,OAAO;EAC/D,eAAe,UAAU,iBAAiB;GACxC,eAAe,UAAU;GACzB,cAAc,IAAI;EACpB,GAAG,aAAa;CAClB;CAEA,MAAM,kBAAkB;EACtB,MAAM,OAAO,KAAK,IAAI,KAAK,QAAQ,IAAI;EACvC,IAAI,SAAS,OAAO;GAClB,cAAc,IAAI;GAClB,eAAe,IAAI;EACrB;CACF;CACA,MAAM,kBAAkB;EACtB,MAAM,OAAO,KAAK,IAAI,KAAK,QAAQ,IAAI;EACvC,IAAI,SAAS,OAAO;GAClB,cAAc,IAAI;GAClB,eAAe,IAAI;EACrB;CACF;CAEA,MAAM,QAAQ,SAAS;CACvB,MAAM,QAAQ,SAAS;CAEvB,OACE,iBAAA,GAAA,kBAAA,MAAC,OAAD;EACO;EACL,MAAK;EACL,cAAY;EACZ,YAAA,GAAA,OAAA,IACE,0FACA,SACF;YAPF;GASE,iBAAA,GAAA,kBAAA,KAAC,UAAD;IACE,MAAK;IACL,cAAY;IACZ,SAAS;IACT,UAAU,YAAY;IACtB,WAAU;cAEV,iBAAA,GAAA,kBAAA,KAACC,oBAAAA,aAAD,EAAa,WAAU,2BAA4B,CAAA;GAC7C,CAAA;GACR,iBAAA,GAAA,kBAAA,KAAC,QAAD;IACE,WAAU;IACV,aAAU;cAET,YAAY,KAAK;GACd,CAAA;GACN,iBAAA,GAAA,kBAAA,KAAC,UAAD;IACE,MAAK;IACL,cAAY;IACZ,SAAS;IACT,UAAU,YAAY;IACtB,WAAU;cAEV,iBAAA,GAAA,kBAAA,KAACC,oBAAAA,cAAD,EAAc,WAAU,2BAA4B,CAAA;GAC9C,CAAA;EACL;;AAET,CACF;AAEA,QAAQ,cAAc"}
1
+ {"version":3,"file":"stepper.cjs","names":["React","ChevronLeft","ChevronRight"],"sources":["../../src/components/stepper.tsx"],"sourcesContent":["import { ChevronLeft, ChevronRight } from '@epilot/spark-icons'\nimport * as React from 'react'\nimport { cn } from '../utils/cn'\n\ninterface StepperProps {\n value: number\n onValueChange: (value: number) => void\n /**\n * Fires once after the user stops interacting (default: 400ms after the last\n * click). Use this for side effects like persisting the value, so rapid\n * clicks don't fan out into a request per click.\n */\n onValueCommit?: (value: number) => void\n min?: number\n max?: number\n step?: number\n formatValue?: (value: number) => string\n disabled?: boolean\n className?: string\n /** Delay (ms) after the last click before `onValueCommit` fires. */\n commitDelayMs?: number\n /** Accessible label, e.g. \"Sunshare percentage\". */\n 'aria-label'?: string\n /** Accessible label for the decrement button. */\n decreaseLabel: string\n /** Accessible label for the increment button. */\n increaseLabel: string\n}\n\nconst Stepper = React.forwardRef<HTMLDivElement, StepperProps>(\n (\n {\n value,\n onValueChange,\n onValueCommit,\n min = 0,\n max = 100,\n step = 1,\n formatValue = (v) => String(v),\n disabled,\n className,\n commitDelayMs = 400,\n 'aria-label': ariaLabel,\n decreaseLabel,\n increaseLabel,\n },\n ref,\n ) => {\n const commitTimerRef = React.useRef<ReturnType<typeof setTimeout> | null>(\n null,\n )\n\n React.useEffect(\n () => () => {\n if (commitTimerRef.current) clearTimeout(commitTimerRef.current)\n },\n [],\n )\n\n const scheduleCommit = (next: number) => {\n if (!onValueCommit) return\n if (commitTimerRef.current) clearTimeout(commitTimerRef.current)\n commitTimerRef.current = setTimeout(() => {\n commitTimerRef.current = null\n onValueCommit(next)\n }, commitDelayMs)\n }\n\n const decrement = () => {\n const next = Math.max(min, value - step)\n if (next !== value) {\n onValueChange(next)\n scheduleCommit(next)\n }\n }\n const increment = () => {\n const next = Math.min(max, value + step)\n if (next !== value) {\n onValueChange(next)\n scheduleCommit(next)\n }\n }\n\n const atMin = value <= min\n const atMax = value >= max\n\n return (\n <div\n ref={ref}\n role=\"group\"\n aria-label={ariaLabel}\n className={cn(\n 'inline-flex h-12 w-full items-center justify-between rounded-md bg-base-gray-soft px-2',\n className,\n )}\n >\n <button\n type=\"button\"\n aria-label={decreaseLabel}\n onClick={decrement}\n disabled={disabled || atMin}\n className=\"touch-target inline-flex size-8 items-center justify-center rounded-sm text-gray transition-colors hover:bg-gray-a3 disabled:opacity-40 disabled:hover:bg-transparent motion-reduce:transition-none\"\n >\n <ChevronLeft className=\"[--spark-icon-size:16px]\" />\n </button>\n <span\n className=\"text-base font-semibold text-gray tabular-nums select-none\"\n aria-live=\"polite\"\n >\n {formatValue(value)}\n </span>\n <button\n type=\"button\"\n aria-label={increaseLabel}\n onClick={increment}\n disabled={disabled || atMax}\n className=\"touch-target inline-flex size-8 items-center justify-center rounded-sm text-gray transition-colors hover:bg-gray-a3 disabled:opacity-40 disabled:hover:bg-transparent motion-reduce:transition-none\"\n >\n <ChevronRight className=\"[--spark-icon-size:16px]\" />\n </button>\n </div>\n )\n },\n)\n\nStepper.displayName = 'Stepper'\n\nexport { Stepper }\nexport type { StepperProps }\n"],"mappings":";;;;;;;;;AA6BA,MAAM,UAAUA,MAAM,YAElB,EACE,OACA,eACA,eACA,MAAM,GACN,MAAM,KACN,OAAO,GACP,eAAe,MAAM,OAAO,CAAC,GAC7B,UACA,WACA,gBAAgB,KAChB,cAAc,WACd,eACA,iBAEF,QACG;CACH,MAAM,iBAAiBA,MAAM,OAC3B,IACF;CAEA,MAAM,sBACQ;EACV,IAAI,eAAe,SAAS,aAAa,eAAe,OAAO;CACjE,GACA,CAAC,CACH;CAEA,MAAM,kBAAkB,SAAiB;EACvC,IAAI,CAAC,eAAe;EACpB,IAAI,eAAe,SAAS,aAAa,eAAe,OAAO;EAC/D,eAAe,UAAU,iBAAiB;GACxC,eAAe,UAAU;GACzB,cAAc,IAAI;EACpB,GAAG,aAAa;CAClB;CAEA,MAAM,kBAAkB;EACtB,MAAM,OAAO,KAAK,IAAI,KAAK,QAAQ,IAAI;EACvC,IAAI,SAAS,OAAO;GAClB,cAAc,IAAI;GAClB,eAAe,IAAI;EACrB;CACF;CACA,MAAM,kBAAkB;EACtB,MAAM,OAAO,KAAK,IAAI,KAAK,QAAQ,IAAI;EACvC,IAAI,SAAS,OAAO;GAClB,cAAc,IAAI;GAClB,eAAe,IAAI;EACrB;CACF;CAEA,MAAM,QAAQ,SAAS;CACvB,MAAM,QAAQ,SAAS;CAEvB,OACE,iBAAA,GAAA,kBAAA,MAAC,OAAD;EACO;EACL,MAAK;EACL,cAAY;EACZ,YAAA,GAAA,GAAA,IACE,0FACA,SACF;YAPF;GASE,iBAAA,GAAA,kBAAA,KAAC,UAAD;IACE,MAAK;IACL,cAAY;IACZ,SAAS;IACT,UAAU,YAAY;IACtB,WAAU;cAEV,iBAAA,GAAA,kBAAA,KAACC,oBAAAA,aAAD,EAAa,WAAU,2BAA4B,CAAA;GAC7C,CAAA;GACR,iBAAA,GAAA,kBAAA,KAAC,QAAD;IACE,WAAU;IACV,aAAU;cAET,YAAY,KAAK;GACd,CAAA;GACN,iBAAA,GAAA,kBAAA,KAAC,UAAD;IACE,MAAK;IACL,cAAY;IACZ,SAAS;IACT,UAAU,YAAY;IACtB,WAAU;cAEV,iBAAA,GAAA,kBAAA,KAACC,oBAAAA,cAAD,EAAc,WAAU,2BAA4B,CAAA;GAC9C,CAAA;EACL;;AAET,CACF;AAEA,QAAQ,cAAc"}
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { cn } from "../utils/cn.js";
3
- import { ChevronLeft, ChevronRight } from "@epilot/spark-icons";
4
3
  import * as React$1 from "react";
4
+ import { ChevronLeft, ChevronRight } from "@epilot/spark-icons";
5
5
  import { jsx, jsxs } from "react/jsx-runtime";
6
6
  //#region src/components/stepper.tsx
7
7
  const Stepper = React$1.forwardRef(({ value, onValueChange, onValueCommit, min = 0, max = 100, step = 1, formatValue = (v) => String(v), disabled, className, commitDelayMs = 400, "aria-label": ariaLabel, decreaseLabel, increaseLabel }, ref) => {
@@ -3,7 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const require_lib_accent_colors = require("../lib/accent-colors.cjs");
4
4
  let react_jsx_runtime = require("react/jsx-runtime");
5
5
  let _base_ui_react_switch = require("@base-ui/react/switch");
6
- let cnfast = require("cnfast");
6
+ let cn = require("cn");
7
7
  //#region src/components/switch.tsx
8
8
  function Switch({ className, styleVariant, color, size: _size, variant: _variant, render, nativeButton, ...props }) {
9
9
  const dataStyle = styleVariant !== void 0 || color !== void 0 ? styleVariant ?? "solid" : void 0;
@@ -14,11 +14,11 @@ function Switch({ className, styleVariant, color, size: _size, variant: _variant
14
14
  "data-accent-color": dataAccentColor,
15
15
  nativeButton: nativeButton ?? render === void 0,
16
16
  render: render ?? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {}),
17
- className: (0, cnfast.cn)("peer touch-target relative my-2 inline-flex h-6 w-10 shrink-0 cursor-pointer items-center p-[2px] transition-colors any-pointer-coarse:my-[calc((2.75rem-var(--spacing)*6)/2)]", "before:absolute before:inset-x-0 before:top-1/2 before:h-10 before:-translate-y-1/2 before:content-['']", "rounded-(--spark-rounded-xl)", "shadow-[0_1px_2px_0_rgb(0_0_0/0.05),inset_0_0_0_1px_var(--spark-switch-ring,transparent)]", "focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden", "data-disabled:pointer-events-none data-disabled:opacity-50", "data-unchecked:bg-gray-a5 data-unchecked:[--spark-switch-ring:var(--spark-switch-idle-border,transparent)]", "data-checked:bg-(--spark-switch-track,var(--spark-9)) data-checked:[--spark-switch-ring:var(--spark-style-border,transparent)]", className),
17
+ className: (0, cn.cn)("peer touch-target relative my-2 inline-flex h-6 w-10 shrink-0 cursor-pointer items-center p-[2px] transition-colors any-pointer-coarse:my-[calc((2.75rem-var(--spacing)*6)/2)]", "before:absolute before:inset-x-0 before:top-1/2 before:h-10 before:-translate-y-1/2 before:content-['']", "rounded-(--spark-rounded-xl)", "shadow-[0_1px_2px_0_rgb(0_0_0/0.05),inset_0_0_0_1px_var(--spark-switch-ring,transparent)]", "focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden", "data-disabled:pointer-events-none data-disabled:opacity-50", "data-unchecked:bg-gray-a5 data-unchecked:[--spark-switch-ring:var(--spark-switch-idle-border,transparent)]", "data-checked:bg-(--spark-switch-track,var(--spark-9)) data-checked:[--spark-switch-ring:var(--spark-style-border,transparent)]", className),
18
18
  ...props,
19
19
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_base_ui_react_switch.Switch.Thumb, {
20
20
  "data-slot": "switch-thumb",
21
- className: (0, cnfast.cn)("pointer-events-none block size-5 bg-(--spark-switch-thumb,var(--spark-on-solid,#fff)) shadow-xs transition-transform", "rounded-(--spark-rounded-lg)", "data-checked:translate-x-4 data-unchecked:translate-x-0")
21
+ className: (0, cn.cn)("pointer-events-none block size-5 bg-(--spark-switch-thumb,var(--spark-on-solid,#fff)) shadow-xs transition-transform motion-reduce:transition-none", "rounded-(--spark-rounded-lg)", "data-checked:translate-x-4 data-unchecked:translate-x-0")
22
22
  })
23
23
  });
24
24
  }
@@ -1 +1 @@
1
- {"version":3,"file":"switch.cjs","names":["accentByColor","SwitchPrimitive"],"sources":["../../src/components/switch.tsx"],"sourcesContent":["import { Switch as SwitchPrimitive } from '@base-ui/react/switch'\nimport { accentByColor } from '../lib/accent-colors'\nimport type { SparkStyle } from '../lib/theme-types'\nimport { cn } from '../utils/cn'\n\nexport type SparkSwitchColor = 'accent' | 'neutral' | 'danger'\n\ntype SwitchProps = SwitchPrimitive.Root.Props & {\n styleVariant?: SparkStyle\n color?: SparkSwitchColor\n /**\n * @deprecated The switch now renders a single size. Accepted for back-compat\n * but ignored.\n */\n size?: 'sm' | 'base' | 'lg'\n /**\n * @deprecated Use `color=\"danger\"` for a destructive/error switch. Accepted\n * for back-compat but ignored.\n */\n variant?: 'primary' | 'destructive'\n}\n\nfunction Switch({\n className,\n styleVariant,\n color,\n size: _size,\n variant: _variant,\n render,\n nativeButton,\n ...props\n}: SwitchProps) {\n const hasLook = styleVariant !== undefined || color !== undefined\n const dataStyle = hasLook ? (styleVariant ?? 'solid') : undefined\n const dataAccentColor = color ? accentByColor[color] : undefined\n return (\n <SwitchPrimitive.Root\n data-slot=\"switch\"\n data-style={dataStyle}\n data-accent-color={dataAccentColor}\n // a native button owns the caller's `id`; on Base UI's default <span> the\n // `id` lands on the hidden input and the control gets a generated one\n nativeButton={nativeButton ?? render === undefined}\n render={render ?? <button />}\n className={cn(\n 'peer touch-target relative my-2 inline-flex h-6 w-10 shrink-0 cursor-pointer items-center p-[2px] transition-colors any-pointer-coarse:my-[calc((2.75rem-var(--spacing)*6)/2)]',\n // both overlays are reserved as layout, so neither can bleed into a scroller;\n // the coarse margin tracks --spacing so the 44px reserve holds at any [data-scaling]\n \"before:absolute before:inset-x-0 before:top-1/2 before:h-10 before:-translate-y-1/2 before:content-['']\",\n 'rounded-(--spark-rounded-xl)',\n 'shadow-[0_1px_2px_0_rgb(0_0_0/0.05),inset_0_0_0_1px_var(--spark-switch-ring,transparent)]',\n 'focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden',\n 'data-disabled:pointer-events-none data-disabled:opacity-50',\n 'data-unchecked:bg-gray-a5 data-unchecked:[--spark-switch-ring:var(--spark-switch-idle-border,transparent)]',\n 'data-checked:bg-(--spark-switch-track,var(--spark-9)) data-checked:[--spark-switch-ring:var(--spark-style-border,transparent)]',\n className,\n )}\n {...props}\n >\n <SwitchPrimitive.Thumb\n data-slot=\"switch-thumb\"\n className={cn(\n 'pointer-events-none block size-5 bg-(--spark-switch-thumb,var(--spark-on-solid,#fff)) shadow-xs transition-transform',\n 'rounded-(--spark-rounded-lg)',\n 'data-checked:translate-x-4 data-unchecked:translate-x-0',\n )}\n />\n </SwitchPrimitive.Root>\n )\n}\n\nexport { Switch }\nexport type { SwitchProps }\n"],"mappings":";;;;;;;AAsBA,SAAS,OAAO,EACd,WACA,cACA,OACA,MAAM,OACN,SAAS,UACT,QACA,cACA,GAAG,SACW;CAEd,MAAM,YADU,iBAAiB,KAAA,KAAa,UAAU,KAAA,IAC3B,gBAAgB,UAAW,KAAA;CACxD,MAAM,kBAAkB,QAAQA,0BAAAA,cAAc,SAAS,KAAA;CACvD,OACE,iBAAA,GAAA,kBAAA,KAACC,sBAAAA,OAAgB,MAAjB;EACE,aAAU;EACV,cAAY;EACZ,qBAAmB;EAGnB,cAAc,gBAAgB,WAAW,KAAA;EACzC,QAAQ,UAAU,iBAAA,GAAA,kBAAA,KAAC,UAAD,CAAS,CAAA;EAC3B,YAAA,GAAA,OAAA,IACE,kLAGA,2GACA,gCACA,6FACA,iFACA,8DACA,8GACA,kIACA,SACF;EACA,GAAI;YAEJ,iBAAA,GAAA,kBAAA,KAACA,sBAAAA,OAAgB,OAAjB;GACE,aAAU;GACV,YAAA,GAAA,OAAA,IACE,wHACA,gCACA,yDACF;EACD,CAAA;CACmB,CAAA;AAE1B"}
1
+ {"version":3,"file":"switch.cjs","names":["accentByColor","SwitchPrimitive"],"sources":["../../src/components/switch.tsx"],"sourcesContent":["import { Switch as SwitchPrimitive } from '@base-ui/react/switch'\nimport { accentByColor } from '../lib/accent-colors'\nimport type { SparkStyle } from '../lib/theme-types'\nimport { cn } from '../utils/cn'\n\nexport type SparkSwitchColor = 'accent' | 'neutral' | 'danger'\n\ntype SwitchProps = SwitchPrimitive.Root.Props & {\n styleVariant?: SparkStyle\n color?: SparkSwitchColor\n /**\n * @deprecated The switch now renders a single size. Accepted for back-compat\n * but ignored.\n */\n size?: 'sm' | 'base' | 'lg'\n /**\n * @deprecated Use `color=\"danger\"` for a destructive/error switch. Accepted\n * for back-compat but ignored.\n */\n variant?: 'primary' | 'destructive'\n}\n\nfunction Switch({\n className,\n styleVariant,\n color,\n // oxlint-disable-next-line typescript/no-deprecated -- strips deprecated back-compat prop before DOM spread\n size: _size,\n // oxlint-disable-next-line typescript/no-deprecated -- strips deprecated back-compat prop before DOM spread\n variant: _variant,\n render,\n nativeButton,\n ...props\n}: SwitchProps) {\n const hasLook = styleVariant !== undefined || color !== undefined\n const dataStyle = hasLook ? (styleVariant ?? 'solid') : undefined\n const dataAccentColor = color ? accentByColor[color] : undefined\n return (\n <SwitchPrimitive.Root\n data-slot=\"switch\"\n data-style={dataStyle}\n data-accent-color={dataAccentColor}\n // a native button owns the caller's `id`; on Base UI's default <span> the\n // `id` lands on the hidden input and the control gets a generated one\n nativeButton={nativeButton ?? render === undefined}\n render={render ?? <button />}\n className={cn(\n 'peer touch-target relative my-2 inline-flex h-6 w-10 shrink-0 cursor-pointer items-center p-[2px] transition-colors any-pointer-coarse:my-[calc((2.75rem-var(--spacing)*6)/2)]',\n // both overlays are reserved as layout, so neither can bleed into a scroller;\n // the coarse margin tracks --spacing so the 44px reserve holds at any [data-scaling]\n \"before:absolute before:inset-x-0 before:top-1/2 before:h-10 before:-translate-y-1/2 before:content-['']\",\n 'rounded-(--spark-rounded-xl)',\n 'shadow-[0_1px_2px_0_rgb(0_0_0/0.05),inset_0_0_0_1px_var(--spark-switch-ring,transparent)]',\n 'focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden',\n 'data-disabled:pointer-events-none data-disabled:opacity-50',\n 'data-unchecked:bg-gray-a5 data-unchecked:[--spark-switch-ring:var(--spark-switch-idle-border,transparent)]',\n 'data-checked:bg-(--spark-switch-track,var(--spark-9)) data-checked:[--spark-switch-ring:var(--spark-style-border,transparent)]',\n className,\n )}\n {...props}\n >\n <SwitchPrimitive.Thumb\n data-slot=\"switch-thumb\"\n className={cn(\n 'pointer-events-none block size-5 bg-(--spark-switch-thumb,var(--spark-on-solid,#fff)) shadow-xs transition-transform motion-reduce:transition-none',\n 'rounded-(--spark-rounded-lg)',\n 'data-checked:translate-x-4 data-unchecked:translate-x-0',\n )}\n />\n </SwitchPrimitive.Root>\n )\n}\n\nexport { Switch }\nexport type { SwitchProps }\n"],"mappings":";;;;;;;AAsBA,SAAS,OAAO,EACd,WACA,cACA,OAEA,MAAM,OAEN,SAAS,UACT,QACA,cACA,GAAG,SACW;CAEd,MAAM,YADU,iBAAiB,KAAA,KAAa,UAAU,KAAA,IAC3B,gBAAgB,UAAW,KAAA;CACxD,MAAM,kBAAkB,QAAQA,0BAAAA,cAAc,SAAS,KAAA;CACvD,OACE,iBAAA,GAAA,kBAAA,KAACC,sBAAAA,OAAgB,MAAjB;EACE,aAAU;EACV,cAAY;EACZ,qBAAmB;EAGnB,cAAc,gBAAgB,WAAW,KAAA;EACzC,QAAQ,UAAU,iBAAA,GAAA,kBAAA,KAAC,UAAD,CAAS,CAAA;EAC3B,YAAA,GAAA,GAAA,IACE,kLAGA,2GACA,gCACA,6FACA,iFACA,8DACA,8GACA,kIACA,SACF;EACA,GAAI;YAEJ,iBAAA,GAAA,kBAAA,KAACA,sBAAAA,OAAgB,OAAjB;GACE,aAAU;GACV,YAAA,GAAA,GAAA,IACE,sJACA,gCACA,yDACF;EACD,CAAA;CACmB,CAAA;AAE1B"}
@@ -1,6 +1,6 @@
1
1
  "use client";
2
- import { cn } from "../utils/cn.js";
3
2
  import { accentByColor } from "../lib/accent-colors.js";
3
+ import { cn } from "../utils/cn.js";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  import { Switch as Switch$1 } from "@base-ui/react/switch";
6
6
  //#region src/components/switch.tsx
@@ -17,7 +17,7 @@ function Switch({ className, styleVariant, color, size: _size, variant: _variant
17
17
  ...props,
18
18
  children: /* @__PURE__ */ jsx(Switch$1.Thumb, {
19
19
  "data-slot": "switch-thumb",
20
- className: cn("pointer-events-none block size-5 bg-(--spark-switch-thumb,var(--spark-on-solid,#fff)) shadow-xs transition-transform", "rounded-(--spark-rounded-lg)", "data-checked:translate-x-4 data-unchecked:translate-x-0")
20
+ className: cn("pointer-events-none block size-5 bg-(--spark-switch-thumb,var(--spark-on-solid,#fff)) shadow-xs transition-transform motion-reduce:transition-none", "rounded-(--spark-rounded-lg)", "data-checked:translate-x-4 data-unchecked:translate-x-0")
21
21
  })
22
22
  });
23
23
  }
@@ -1 +1 @@
1
- {"version":3,"file":"switch.js","names":["SwitchPrimitive"],"sources":["../../src/components/switch.tsx"],"sourcesContent":["import { Switch as SwitchPrimitive } from '@base-ui/react/switch'\nimport { accentByColor } from '../lib/accent-colors'\nimport type { SparkStyle } from '../lib/theme-types'\nimport { cn } from '../utils/cn'\n\nexport type SparkSwitchColor = 'accent' | 'neutral' | 'danger'\n\ntype SwitchProps = SwitchPrimitive.Root.Props & {\n styleVariant?: SparkStyle\n color?: SparkSwitchColor\n /**\n * @deprecated The switch now renders a single size. Accepted for back-compat\n * but ignored.\n */\n size?: 'sm' | 'base' | 'lg'\n /**\n * @deprecated Use `color=\"danger\"` for a destructive/error switch. Accepted\n * for back-compat but ignored.\n */\n variant?: 'primary' | 'destructive'\n}\n\nfunction Switch({\n className,\n styleVariant,\n color,\n size: _size,\n variant: _variant,\n render,\n nativeButton,\n ...props\n}: SwitchProps) {\n const hasLook = styleVariant !== undefined || color !== undefined\n const dataStyle = hasLook ? (styleVariant ?? 'solid') : undefined\n const dataAccentColor = color ? accentByColor[color] : undefined\n return (\n <SwitchPrimitive.Root\n data-slot=\"switch\"\n data-style={dataStyle}\n data-accent-color={dataAccentColor}\n // a native button owns the caller's `id`; on Base UI's default <span> the\n // `id` lands on the hidden input and the control gets a generated one\n nativeButton={nativeButton ?? render === undefined}\n render={render ?? <button />}\n className={cn(\n 'peer touch-target relative my-2 inline-flex h-6 w-10 shrink-0 cursor-pointer items-center p-[2px] transition-colors any-pointer-coarse:my-[calc((2.75rem-var(--spacing)*6)/2)]',\n // both overlays are reserved as layout, so neither can bleed into a scroller;\n // the coarse margin tracks --spacing so the 44px reserve holds at any [data-scaling]\n \"before:absolute before:inset-x-0 before:top-1/2 before:h-10 before:-translate-y-1/2 before:content-['']\",\n 'rounded-(--spark-rounded-xl)',\n 'shadow-[0_1px_2px_0_rgb(0_0_0/0.05),inset_0_0_0_1px_var(--spark-switch-ring,transparent)]',\n 'focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden',\n 'data-disabled:pointer-events-none data-disabled:opacity-50',\n 'data-unchecked:bg-gray-a5 data-unchecked:[--spark-switch-ring:var(--spark-switch-idle-border,transparent)]',\n 'data-checked:bg-(--spark-switch-track,var(--spark-9)) data-checked:[--spark-switch-ring:var(--spark-style-border,transparent)]',\n className,\n )}\n {...props}\n >\n <SwitchPrimitive.Thumb\n data-slot=\"switch-thumb\"\n className={cn(\n 'pointer-events-none block size-5 bg-(--spark-switch-thumb,var(--spark-on-solid,#fff)) shadow-xs transition-transform',\n 'rounded-(--spark-rounded-lg)',\n 'data-checked:translate-x-4 data-unchecked:translate-x-0',\n )}\n />\n </SwitchPrimitive.Root>\n )\n}\n\nexport { Switch }\nexport type { SwitchProps }\n"],"mappings":";;;;;;AAsBA,SAAS,OAAO,EACd,WACA,cACA,OACA,MAAM,OACN,SAAS,UACT,QACA,cACA,GAAG,SACW;CAEd,MAAM,YADU,iBAAiB,KAAA,KAAa,UAAU,KAAA,IAC3B,gBAAgB,UAAW,KAAA;CACxD,MAAM,kBAAkB,QAAQ,cAAc,SAAS,KAAA;CACvD,OACE,oBAACA,SAAgB,MAAjB;EACE,aAAU;EACV,cAAY;EACZ,qBAAmB;EAGnB,cAAc,gBAAgB,WAAW,KAAA;EACzC,QAAQ,UAAU,oBAAC,UAAD,CAAS,CAAA;EAC3B,WAAW,GACT,kLAGA,2GACA,gCACA,6FACA,iFACA,8DACA,8GACA,kIACA,SACF;EACA,GAAI;YAEJ,oBAACA,SAAgB,OAAjB;GACE,aAAU;GACV,WAAW,GACT,wHACA,gCACA,yDACF;EACD,CAAA;CACmB,CAAA;AAE1B"}
1
+ {"version":3,"file":"switch.js","names":["SwitchPrimitive"],"sources":["../../src/components/switch.tsx"],"sourcesContent":["import { Switch as SwitchPrimitive } from '@base-ui/react/switch'\nimport { accentByColor } from '../lib/accent-colors'\nimport type { SparkStyle } from '../lib/theme-types'\nimport { cn } from '../utils/cn'\n\nexport type SparkSwitchColor = 'accent' | 'neutral' | 'danger'\n\ntype SwitchProps = SwitchPrimitive.Root.Props & {\n styleVariant?: SparkStyle\n color?: SparkSwitchColor\n /**\n * @deprecated The switch now renders a single size. Accepted for back-compat\n * but ignored.\n */\n size?: 'sm' | 'base' | 'lg'\n /**\n * @deprecated Use `color=\"danger\"` for a destructive/error switch. Accepted\n * for back-compat but ignored.\n */\n variant?: 'primary' | 'destructive'\n}\n\nfunction Switch({\n className,\n styleVariant,\n color,\n // oxlint-disable-next-line typescript/no-deprecated -- strips deprecated back-compat prop before DOM spread\n size: _size,\n // oxlint-disable-next-line typescript/no-deprecated -- strips deprecated back-compat prop before DOM spread\n variant: _variant,\n render,\n nativeButton,\n ...props\n}: SwitchProps) {\n const hasLook = styleVariant !== undefined || color !== undefined\n const dataStyle = hasLook ? (styleVariant ?? 'solid') : undefined\n const dataAccentColor = color ? accentByColor[color] : undefined\n return (\n <SwitchPrimitive.Root\n data-slot=\"switch\"\n data-style={dataStyle}\n data-accent-color={dataAccentColor}\n // a native button owns the caller's `id`; on Base UI's default <span> the\n // `id` lands on the hidden input and the control gets a generated one\n nativeButton={nativeButton ?? render === undefined}\n render={render ?? <button />}\n className={cn(\n 'peer touch-target relative my-2 inline-flex h-6 w-10 shrink-0 cursor-pointer items-center p-[2px] transition-colors any-pointer-coarse:my-[calc((2.75rem-var(--spacing)*6)/2)]',\n // both overlays are reserved as layout, so neither can bleed into a scroller;\n // the coarse margin tracks --spacing so the 44px reserve holds at any [data-scaling]\n \"before:absolute before:inset-x-0 before:top-1/2 before:h-10 before:-translate-y-1/2 before:content-['']\",\n 'rounded-(--spark-rounded-xl)',\n 'shadow-[0_1px_2px_0_rgb(0_0_0/0.05),inset_0_0_0_1px_var(--spark-switch-ring,transparent)]',\n 'focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden',\n 'data-disabled:pointer-events-none data-disabled:opacity-50',\n 'data-unchecked:bg-gray-a5 data-unchecked:[--spark-switch-ring:var(--spark-switch-idle-border,transparent)]',\n 'data-checked:bg-(--spark-switch-track,var(--spark-9)) data-checked:[--spark-switch-ring:var(--spark-style-border,transparent)]',\n className,\n )}\n {...props}\n >\n <SwitchPrimitive.Thumb\n data-slot=\"switch-thumb\"\n className={cn(\n 'pointer-events-none block size-5 bg-(--spark-switch-thumb,var(--spark-on-solid,#fff)) shadow-xs transition-transform motion-reduce:transition-none',\n 'rounded-(--spark-rounded-lg)',\n 'data-checked:translate-x-4 data-unchecked:translate-x-0',\n )}\n />\n </SwitchPrimitive.Root>\n )\n}\n\nexport { Switch }\nexport type { SwitchProps }\n"],"mappings":";;;;;;AAsBA,SAAS,OAAO,EACd,WACA,cACA,OAEA,MAAM,OAEN,SAAS,UACT,QACA,cACA,GAAG,SACW;CAEd,MAAM,YADU,iBAAiB,KAAA,KAAa,UAAU,KAAA,IAC3B,gBAAgB,UAAW,KAAA;CACxD,MAAM,kBAAkB,QAAQ,cAAc,SAAS,KAAA;CACvD,OACE,oBAACA,SAAgB,MAAjB;EACE,aAAU;EACV,cAAY;EACZ,qBAAmB;EAGnB,cAAc,gBAAgB,WAAW,KAAA;EACzC,QAAQ,UAAU,oBAAC,UAAD,CAAS,CAAA;EAC3B,WAAW,GACT,kLAGA,2GACA,gCACA,6FACA,iFACA,8DACA,8GACA,kIACA,SACF;EACA,GAAI;YAEJ,oBAACA,SAAgB,OAAjB;GACE,aAAU;GACV,WAAW,GACT,sJACA,gCACA,yDACF;EACD,CAAA;CACmB,CAAA;AAE1B"}
@@ -2,11 +2,11 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const require_chunk = require("../chunk-DY84GLCh.cjs");
4
4
  const require_components_skeleton = require("./skeleton.cjs");
5
- let _epilot_spark_icons = require("@epilot/spark-icons");
6
5
  let react = require("react");
7
6
  react = require_chunk.__toESM(react);
7
+ let _epilot_spark_icons = require("@epilot/spark-icons");
8
8
  let react_jsx_runtime = require("react/jsx-runtime");
9
- let cnfast = require("cnfast");
9
+ let cn = require("cn");
10
10
  //#region src/components/table.tsx
11
11
  const TableContext = react.createContext({
12
12
  sort: null,
@@ -41,11 +41,11 @@ function Table({ children, className, containerProps, onSortChange, sort = null,
41
41
  "data-slot": "table-container",
42
42
  role: scrollRegion ? "region" : void 0,
43
43
  tabIndex: scrollRegion ? 0 : void 0,
44
- className: (0, cnfast.cn)("relative w-full overflow-x-auto", scrollRegion && "focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-accent-focus", containerClassName),
44
+ className: (0, cn.cn)("relative w-full overflow-x-auto", scrollRegion && "focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-accent-focus", containerClassName),
45
45
  ...container,
46
46
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("table", {
47
47
  "data-slot": "table",
48
- className: (0, cnfast.cn)("w-full border-separate border-spacing-0 text-sm text-gray-12", className),
48
+ className: (0, cn.cn)("w-full border-separate border-spacing-0 text-sm text-gray-12", className),
49
49
  ...props,
50
50
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TableContext.Provider, {
51
51
  value: context,
@@ -86,7 +86,7 @@ function TableRow({ className, onClick, onKeyDown, selected, skeleton, ...props
86
86
  tabIndex: interactive ? 0 : void 0,
87
87
  onClick: interactive ? onClick : void 0,
88
88
  onKeyDown: handleKeyDown,
89
- className: (0, cnfast.cn)("[&:last-child>td]:border-b-0", selected && !skeleton && "bg-spark-a3", interactive && [
89
+ className: (0, cn.cn)("[&:last-child>td]:border-b-0", selected && !skeleton && "bg-spark-a3", interactive && [
90
90
  "cursor-pointer transition-colors duration-150 touch-target-table-row motion-reduce:transition-none",
91
91
  "hover:bg-spark-a3 focus-visible:bg-spark-a3",
92
92
  "focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-accent-focus"
@@ -102,14 +102,14 @@ function TableHead({ align = "start", children, className, sortKey, ...props })
102
102
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
103
103
  "data-slot": "table-head",
104
104
  "aria-sort": sortKey == null ? void 0 : direction === "asc" ? "ascending" : direction === "desc" ? "descending" : "none",
105
- className: (0, cnfast.cn)("border-b border-gray-a6 px-3 text-left align-middle text-xs font-medium text-gray-11", rowHeight, align === "end" && "text-right", stickyHeader && "sticky top-0 z-10 bg-gray-2", className),
105
+ className: (0, cn.cn)("border-b border-gray-a6 px-3 text-left align-middle text-xs font-medium text-gray-11", rowHeight, align === "end" && "text-right", stickyHeader && "sticky top-0 z-10 bg-gray-2", className),
106
106
  ...props,
107
107
  children: sortKey == null ? children : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
108
108
  type: "button",
109
109
  "data-slot": "table-head-sort",
110
110
  onClick: () => onSortChange?.(nextSort(sort, sortKey)),
111
- className: (0, cnfast.cn)("touch-target -mx-1 inline-flex min-h-[1.5rem] cursor-pointer items-center gap-1 rounded-sm px-1 py-0.5 text-left transition-colors [--spark-icon-size:1rem] hover:text-gray-12 motion-reduce:transition-none", "focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-accent-focus", align === "end" && "flex-row-reverse"),
112
- children: [children, /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Indicator, { className: (0, cnfast.cn)(!direction && "text-gray-a9") })]
111
+ className: (0, cn.cn)("touch-target -mx-1 inline-flex min-h-[1.5rem] cursor-pointer items-center gap-1 rounded-sm px-1 py-0.5 text-left transition-colors [--spark-icon-size:1rem] hover:text-gray-12 motion-reduce:transition-none", "focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-accent-focus", align === "end" && "flex-row-reverse"),
112
+ children: [children, /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Indicator, { className: (0, cn.cn)(!direction && "text-gray-a9") })]
113
113
  })
114
114
  });
115
115
  }
@@ -117,7 +117,7 @@ function TableCell({ align = "start", children, className, ...props }) {
117
117
  const { skeleton } = react.useContext(TableRowContext);
118
118
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
119
119
  "data-slot": "table-cell",
120
- className: (0, cnfast.cn)("border-b border-gray-a6 px-3 align-middle", rowHeight, align === "end" && "text-right tabular-nums", className),
120
+ className: (0, cn.cn)("border-b border-gray-a6 px-3 align-middle", rowHeight, align === "end" && "text-right tabular-nums", className),
121
121
  ...props,
122
122
  children: skeleton ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_skeleton.Skeleton, { className: "h-4 w-2/3" }) : children
123
123
  });
@@ -1 +1 @@
1
- {"version":3,"file":"table.cjs","names":["React","SwapVert","ArrowUpward","ArrowDownward","Skeleton"],"sources":["../../src/components/table.tsx"],"sourcesContent":["import { ArrowDownward, ArrowUpward, SwapVert } from '@epilot/spark-icons'\nimport * as React from 'react'\nimport { cn } from '../utils/cn'\nimport { Skeleton } from './skeleton'\n\ntype SortDirection = 'asc' | 'desc'\n\ninterface TableSort {\n key: string\n direction: SortDirection\n}\n\ninterface TableContextValue {\n sort: TableSort | null\n onSortChange?: (sort: TableSort | null) => void\n stickyHeader: boolean\n}\n\nconst TableContext = React.createContext<TableContextValue>({\n sort: null,\n stickyHeader: false,\n})\n\nconst TableRowContext = React.createContext<{ skeleton: boolean }>({\n skeleton: false,\n})\n\n// Reads --spark-layout-gap like the collection primitives, so a nested <Theme spacing>\n// re-resolves it against the nearest <Theme> scope (an [[data-spacing=…]_&] variant would\n// match any ancestor, not the nearest). height, not min-height, which is inert on table boxes.\nconst rowHeight = 'h-[calc(var(--spark-layout-gap)*10)]'\n\n// A column the table isn't sorted by starts at asc; the sorted one steps asc → desc → off.\nfunction nextSort(current: TableSort | null, key: string): TableSort | null {\n if (current?.key !== key) return { key, direction: 'asc' }\n if (current.direction === 'asc') return { key, direction: 'desc' }\n return null\n}\n\ninterface TableProps extends React.ComponentProps<'table'> {\n stickyHeader?: boolean\n /** Controlled only — the table never reorders rows; sort app-side and pass the result back. */\n sort?: TableSort | null\n onSortChange?: (sort: TableSort | null) => void\n /** Spread onto the scroll wrapper; an `aria-label` here also makes it a focusable region. */\n containerProps?: React.ComponentProps<'div'>\n}\n\nfunction Table({\n children,\n className,\n containerProps,\n onSortChange,\n sort = null,\n stickyHeader = false,\n ...props\n}: TableProps) {\n const { className: containerClassName, ...container } = containerProps ?? {}\n // A scrolling box only reaches the keyboard once it is focusable, and a focusable box\n // has to say what it holds (WCAG 2.1.1 / 4.1.2) — so the label is what turns it on.\n const scrollRegion = container['aria-label'] != null\n\n const context = React.useMemo(\n () => ({ sort, onSortChange, stickyHeader }),\n [sort, onSortChange, stickyHeader],\n )\n\n return (\n <div\n data-slot=\"table-container\"\n role={scrollRegion ? 'region' : undefined}\n tabIndex={scrollRegion ? 0 : undefined}\n className={cn(\n 'relative w-full overflow-x-auto',\n // inset outline, not a ring: ring-offset paints outside the box and this box clips.\n scrollRegion &&\n 'focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-accent-focus',\n containerClassName,\n )}\n {...container}\n >\n <table\n data-slot=\"table\"\n className={cn(\n // border-separate, not collapse: under collapse Chromium drops the border of a\n // sticky <th>, so every rule lives on the cells instead.\n 'w-full border-separate border-spacing-0 text-sm text-gray-12',\n className,\n )}\n {...props}\n >\n <TableContext.Provider value={context}>\n {children}\n </TableContext.Provider>\n </table>\n </div>\n )\n}\n\nfunction TableHeader(props: React.ComponentProps<'thead'>) {\n return <thead data-slot=\"table-header\" {...props} />\n}\n\nfunction TableBody(props: React.ComponentProps<'tbody'>) {\n return <tbody data-slot=\"table-body\" {...props} />\n}\n\ninterface TableRowProps extends React.ComponentProps<'tr'> {\n selected?: boolean\n skeleton?: boolean\n}\n\nfunction TableRow({\n className,\n onClick,\n onKeyDown,\n selected,\n skeleton,\n ...props\n}: TableRowProps) {\n // A skeleton row is a decorative placeholder: never focusable, never clickable, even if\n // the caller passes a handler while the data loads (ListItem precedent).\n const interactive = !skeleton && onClick != null\n\n const rowContext = React.useMemo(\n () => ({ skeleton: skeleton ?? false }),\n [skeleton],\n )\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLTableRowElement>) => {\n onKeyDown?.(event)\n // a key pressed inside a nested button, link or input belongs to that control\n if (event.target !== event.currentTarget) return\n if (!interactive || event.defaultPrevented) return\n if (event.key !== 'Enter' && event.key !== ' ') return\n // Space would scroll the page.\n if (event.key === ' ') event.preventDefault()\n event.currentTarget.click()\n }\n\n return (\n <TableRowContext.Provider value={rowContext}>\n <tr\n data-slot=\"table-row\"\n data-selected={selected ? '' : undefined}\n aria-hidden={skeleton ? true : undefined}\n tabIndex={interactive ? 0 : undefined}\n onClick={interactive ? onClick : undefined}\n onKeyDown={handleKeyDown}\n className={cn(\n '[&:last-child>td]:border-b-0',\n selected && !skeleton && 'bg-spark-a3',\n interactive && [\n 'cursor-pointer transition-colors duration-150 touch-target-table-row motion-reduce:transition-none',\n 'hover:bg-spark-a3 focus-visible:bg-spark-a3',\n // the inset recipe: a ring-offset would be clipped by the scroll container.\n 'focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-accent-focus',\n ],\n className,\n )}\n {...props}\n />\n </TableRowContext.Provider>\n )\n}\n\n// `align` shadows the deprecated presentational HTML attribute of the same name, which\n// is why the native one is omitted rather than widened.\ninterface TableHeadProps extends Omit<React.ComponentProps<'th'>, 'align'> {\n /** Pair with the matching `TableCell align` so the column lines up. */\n align?: 'start' | 'end'\n /** Presence turns the header into a sort button with an indicator and `aria-sort`. */\n sortKey?: string\n}\n\nfunction TableHead({\n align = 'start',\n children,\n className,\n sortKey,\n ...props\n}: TableHeadProps) {\n const { onSortChange, sort, stickyHeader } = React.useContext(TableContext)\n const active = sortKey != null && sort?.key === sortKey\n const direction = active ? sort.direction : undefined\n const Indicator = !direction\n ? SwapVert\n : direction === 'asc'\n ? ArrowUpward\n : ArrowDownward\n\n return (\n <th\n data-slot=\"table-head\"\n aria-sort={\n sortKey == null\n ? undefined\n : direction === 'asc'\n ? 'ascending'\n : direction === 'desc'\n ? 'descending'\n : 'none'\n }\n className={cn(\n 'border-b border-gray-a6 px-3 text-left align-middle text-xs font-medium text-gray-11',\n rowHeight,\n align === 'end' && 'text-right',\n // opaque fill, so rows scrolling under a sticky header stay hidden; override via\n // className when the table sits on a non-default surface.\n stickyHeader && 'sticky top-0 z-10 bg-gray-2',\n className,\n )}\n {...props}\n >\n {sortKey == null ? (\n children\n ) : (\n // min-h is a HARD 24px floor (WCAG 2.5.8): unlike h-*, it must not shrink\n // with the scaling knob.\n <button\n type=\"button\"\n data-slot=\"table-head-sort\"\n onClick={() => onSortChange?.(nextSort(sort, sortKey))}\n className={cn(\n 'touch-target -mx-1 inline-flex min-h-[1.5rem] cursor-pointer items-center gap-1 rounded-sm px-1 py-0.5 text-left transition-colors [--spark-icon-size:1rem] hover:text-gray-12 motion-reduce:transition-none',\n // the inset recipe again: the first and the sticky header sit on the edge\n // the scroll container clips.\n 'focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-accent-focus',\n // indicator inboard, so the digits keep a clean alignment edge\n align === 'end' && 'flex-row-reverse',\n )}\n >\n {children}\n <Indicator className={cn(!direction && 'text-gray-a9')} />\n </button>\n )}\n </th>\n )\n}\n\n// `align` shadows the deprecated presentational HTML attribute of the same name, which\n// is why the native one is omitted rather than widened.\ninterface TableCellProps extends Omit<React.ComponentProps<'td'>, 'align'> {\n align?: 'start' | 'end'\n}\n\nfunction TableCell({\n align = 'start',\n children,\n className,\n ...props\n}: TableCellProps) {\n const { skeleton } = React.useContext(TableRowContext)\n\n return (\n <td\n data-slot=\"table-cell\"\n className={cn(\n 'border-b border-gray-a6 px-3 align-middle',\n rowHeight,\n align === 'end' && 'text-right tabular-nums',\n className,\n )}\n {...props}\n >\n {skeleton ? <Skeleton className=\"h-4 w-2/3\" /> : children}\n </td>\n )\n}\n\ninterface TableStatusProps extends React.ComponentProps<'tr'> {\n colSpan: number\n}\n\nfunction TableStatus({\n children,\n className,\n colSpan,\n ...props\n}: TableStatusProps) {\n return (\n <tr data-slot=\"table-status\" className={className} {...props}>\n <td\n data-slot=\"table-status-cell\"\n colSpan={colSpan}\n // an element child (EmptyState, Callout) owns its own alignment and most of its\n // vertical rhythm; the cell only keeps it off the header rule. Bare text takes both.\n className=\"px-3 py-3 [&:not(:has(>*))]:py-6 [&:not(:has(>*))]:text-center\"\n >\n {children}\n </td>\n </tr>\n )\n}\n\nexport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n TableStatus,\n}\nexport type {\n SortDirection,\n TableCellProps,\n TableHeadProps,\n TableProps,\n TableRowProps,\n TableSort,\n TableStatusProps,\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"table.cjs","names":["React","SwapVert","ArrowUpward","ArrowDownward","Skeleton"],"sources":["../../src/components/table.tsx"],"sourcesContent":["import { ArrowDownward, ArrowUpward, SwapVert } from '@epilot/spark-icons'\nimport * as React from 'react'\nimport { cn } from '../utils/cn'\nimport { Skeleton } from './skeleton'\n\ntype SortDirection = 'asc' | 'desc'\n\ninterface TableSort {\n key: string\n direction: SortDirection\n}\n\ninterface TableContextValue {\n sort: TableSort | null\n onSortChange?: (sort: TableSort | null) => void\n stickyHeader: boolean\n}\n\nconst TableContext = React.createContext<TableContextValue>({\n sort: null,\n stickyHeader: false,\n})\n\nconst TableRowContext = React.createContext<{ skeleton: boolean }>({\n skeleton: false,\n})\n\n// Reads --spark-layout-gap like the collection primitives, so a nested <Theme spacing>\n// re-resolves it against the nearest <Theme> scope (an [[data-spacing=…]_&] variant would\n// match any ancestor, not the nearest). height, not min-height, which is inert on table boxes.\nconst rowHeight = 'h-[calc(var(--spark-layout-gap)*10)]'\n\n// A column the table isn't sorted by starts at asc; the sorted one steps asc → desc → off.\nfunction nextSort(current: TableSort | null, key: string): TableSort | null {\n if (current?.key !== key) return { key, direction: 'asc' }\n if (current.direction === 'asc') return { key, direction: 'desc' }\n return null\n}\n\ninterface TableProps extends React.ComponentProps<'table'> {\n stickyHeader?: boolean\n /** Controlled only — the table never reorders rows; sort app-side and pass the result back. */\n sort?: TableSort | null\n onSortChange?: (sort: TableSort | null) => void\n /** Spread onto the scroll wrapper; an `aria-label` here also makes it a focusable region. */\n containerProps?: React.ComponentProps<'div'>\n}\n\nfunction Table({\n children,\n className,\n containerProps,\n onSortChange,\n sort = null,\n stickyHeader = false,\n ...props\n}: TableProps) {\n const { className: containerClassName, ...container } = containerProps ?? {}\n // A scrolling box only reaches the keyboard once it is focusable, and a focusable box\n // has to say what it holds (WCAG 2.1.1 / 4.1.2) — so the label is what turns it on.\n const scrollRegion = container['aria-label'] != null\n\n const context = React.useMemo(\n () => ({ sort, onSortChange, stickyHeader }),\n [sort, onSortChange, stickyHeader],\n )\n\n return (\n <div\n data-slot=\"table-container\"\n role={scrollRegion ? 'region' : undefined}\n tabIndex={scrollRegion ? 0 : undefined}\n className={cn(\n 'relative w-full overflow-x-auto',\n // inset outline, not a ring: ring-offset paints outside the box and this box clips.\n scrollRegion &&\n 'focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-accent-focus',\n containerClassName,\n )}\n {...container}\n >\n <table\n data-slot=\"table\"\n className={cn(\n // border-separate, not collapse: under collapse Chromium drops the border of a\n // sticky <th>, so every rule lives on the cells instead.\n 'w-full border-separate border-spacing-0 text-sm text-gray-12',\n className,\n )}\n {...props}\n >\n <TableContext.Provider value={context}>\n {children}\n </TableContext.Provider>\n </table>\n </div>\n )\n}\n\nfunction TableHeader(props: React.ComponentProps<'thead'>) {\n return <thead data-slot=\"table-header\" {...props} />\n}\n\nfunction TableBody(props: React.ComponentProps<'tbody'>) {\n return <tbody data-slot=\"table-body\" {...props} />\n}\n\ninterface TableRowProps extends React.ComponentProps<'tr'> {\n selected?: boolean\n skeleton?: boolean\n}\n\nfunction TableRow({\n className,\n onClick,\n onKeyDown,\n selected,\n skeleton,\n ...props\n}: TableRowProps) {\n // A skeleton row is a decorative placeholder: never focusable, never clickable, even if\n // the caller passes a handler while the data loads (ListItem precedent).\n const interactive = !skeleton && onClick != null\n\n const rowContext = React.useMemo(\n () => ({ skeleton: skeleton ?? false }),\n [skeleton],\n )\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLTableRowElement>) => {\n onKeyDown?.(event)\n // a key pressed inside a nested button, link or input belongs to that control\n if (event.target !== event.currentTarget) return\n if (!interactive || event.defaultPrevented) return\n if (event.key !== 'Enter' && event.key !== ' ') return\n // Space would scroll the page.\n if (event.key === ' ') event.preventDefault()\n event.currentTarget.click()\n }\n\n return (\n <TableRowContext.Provider value={rowContext}>\n <tr\n data-slot=\"table-row\"\n data-selected={selected ? '' : undefined}\n aria-hidden={skeleton ? true : undefined}\n tabIndex={interactive ? 0 : undefined}\n onClick={interactive ? onClick : undefined}\n onKeyDown={handleKeyDown}\n className={cn(\n '[&:last-child>td]:border-b-0',\n selected && !skeleton && 'bg-spark-a3',\n interactive && [\n 'cursor-pointer transition-colors duration-150 touch-target-table-row motion-reduce:transition-none',\n 'hover:bg-spark-a3 focus-visible:bg-spark-a3',\n // the inset recipe: a ring-offset would be clipped by the scroll container.\n 'focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-accent-focus',\n ],\n className,\n )}\n {...props}\n />\n </TableRowContext.Provider>\n )\n}\n\n// `align` shadows the deprecated presentational HTML attribute of the same name, which\n// is why the native one is omitted rather than widened.\ninterface TableHeadProps extends Omit<React.ComponentProps<'th'>, 'align'> {\n /** Pair with the matching `TableCell align` so the column lines up. */\n align?: 'start' | 'end'\n /** Presence turns the header into a sort button with an indicator and `aria-sort`. */\n sortKey?: string\n}\n\nfunction TableHead({\n align = 'start',\n children,\n className,\n sortKey,\n ...props\n}: TableHeadProps) {\n const { onSortChange, sort, stickyHeader } = React.useContext(TableContext)\n const active = sortKey != null && sort?.key === sortKey\n const direction = active ? sort.direction : undefined\n const Indicator = !direction\n ? SwapVert\n : direction === 'asc'\n ? ArrowUpward\n : ArrowDownward\n\n return (\n <th\n data-slot=\"table-head\"\n aria-sort={\n sortKey == null\n ? undefined\n : direction === 'asc'\n ? 'ascending'\n : direction === 'desc'\n ? 'descending'\n : 'none'\n }\n className={cn(\n 'border-b border-gray-a6 px-3 text-left align-middle text-xs font-medium text-gray-11',\n rowHeight,\n align === 'end' && 'text-right',\n // opaque fill, so rows scrolling under a sticky header stay hidden; override via\n // className when the table sits on a non-default surface.\n stickyHeader && 'sticky top-0 z-10 bg-gray-2',\n className,\n )}\n {...props}\n >\n {sortKey == null ? (\n children\n ) : (\n // min-h is a HARD 24px floor (WCAG 2.5.8): unlike h-*, it must not shrink\n // with the scaling knob.\n <button\n type=\"button\"\n data-slot=\"table-head-sort\"\n onClick={() => onSortChange?.(nextSort(sort, sortKey))}\n className={cn(\n 'touch-target -mx-1 inline-flex min-h-[1.5rem] cursor-pointer items-center gap-1 rounded-sm px-1 py-0.5 text-left transition-colors [--spark-icon-size:1rem] hover:text-gray-12 motion-reduce:transition-none',\n // the inset recipe again: the first and the sticky header sit on the edge\n // the scroll container clips.\n 'focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-accent-focus',\n // indicator inboard, so the digits keep a clean alignment edge\n align === 'end' && 'flex-row-reverse',\n )}\n >\n {children}\n <Indicator className={cn(!direction && 'text-gray-a9')} />\n </button>\n )}\n </th>\n )\n}\n\n// `align` shadows the deprecated presentational HTML attribute of the same name, which\n// is why the native one is omitted rather than widened.\ninterface TableCellProps extends Omit<React.ComponentProps<'td'>, 'align'> {\n align?: 'start' | 'end'\n}\n\nfunction TableCell({\n align = 'start',\n children,\n className,\n ...props\n}: TableCellProps) {\n const { skeleton } = React.useContext(TableRowContext)\n\n return (\n <td\n data-slot=\"table-cell\"\n className={cn(\n 'border-b border-gray-a6 px-3 align-middle',\n rowHeight,\n align === 'end' && 'text-right tabular-nums',\n className,\n )}\n {...props}\n >\n {skeleton ? <Skeleton className=\"h-4 w-2/3\" /> : children}\n </td>\n )\n}\n\ninterface TableStatusProps extends React.ComponentProps<'tr'> {\n colSpan: number\n}\n\nfunction TableStatus({\n children,\n className,\n colSpan,\n ...props\n}: TableStatusProps) {\n return (\n <tr data-slot=\"table-status\" className={className} {...props}>\n <td\n data-slot=\"table-status-cell\"\n colSpan={colSpan}\n // an element child (EmptyState, Callout) owns its own alignment and most of its\n // vertical rhythm; the cell only keeps it off the header rule. Bare text takes both.\n className=\"px-3 py-3 [&:not(:has(>*))]:py-6 [&:not(:has(>*))]:text-center\"\n >\n {children}\n </td>\n </tr>\n )\n}\n\nexport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n TableStatus,\n}\nexport type {\n SortDirection,\n TableCellProps,\n TableHeadProps,\n TableProps,\n TableRowProps,\n TableSort,\n TableStatusProps,\n}\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
  import { cn } from "../utils/cn.js";
3
3
  import { Skeleton } from "./skeleton.js";
4
- import { ArrowDownward, ArrowUpward, SwapVert } from "@epilot/spark-icons";
5
4
  import * as React$1 from "react";
5
+ import { ArrowDownward, ArrowUpward, SwapVert } from "@epilot/spark-icons";
6
6
  import { jsx, jsxs } from "react/jsx-runtime";
7
7
  //#region src/components/table.tsx
8
8
  const TableContext = React$1.createContext({
@@ -1,12 +1,12 @@
1
1
  "use client";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const require_chunk = require("../chunk-DY84GLCh.cjs");
4
- let _epilot_spark_icons = require("@epilot/spark-icons");
5
4
  let react = require("react");
6
5
  react = require_chunk.__toESM(react);
6
+ let _epilot_spark_icons = require("@epilot/spark-icons");
7
7
  let react_jsx_runtime = require("react/jsx-runtime");
8
8
  let _base_ui_react_tabs = require("@base-ui/react/tabs");
9
- let cnfast = require("cnfast");
9
+ let cn = require("cn");
10
10
  //#region src/components/tabs.tsx
11
11
  const useIsomorphicLayoutEffect = typeof window === "undefined" ? react.useEffect : react.useLayoutEffect;
12
12
  function setRef(ref, value) {
@@ -38,7 +38,7 @@ function Tabs(props) {
38
38
  }
39
39
  const REVEAL_PEEK = 40;
40
40
  const WORM_MS = 210;
41
- function TabsList({ className, style, variant = "underline", fill, ref, ...props }) {
41
+ const TabsList = react.forwardRef(function TabsList({ className, style, variant = "underline", fill, ...props }, ref) {
42
42
  const resolved = variant === "pill" ? "pill" : "underline";
43
43
  const wrapperRef = react.useRef(null);
44
44
  const scrollerRef = react.useRef(null);
@@ -123,11 +123,11 @@ function TabsList({ className, style, variant = "underline", fill, ref, ...props
123
123
  onClick: scrollByPage(dir),
124
124
  tabIndex: -1,
125
125
  type: "button",
126
- className: (0, cnfast.cn)("touch-target absolute top-1/2 z-1 hidden size-10 -translate-y-1/2 cursor-pointer items-center justify-center rounded-[max(var(--spark-rounded-md),var(--spark-rounded-full))] bg-gray-1/72 text-gray-a11 backdrop-blur-sm hover:text-gray-12", dir === 1 ? "right-0 group-data-overflow-end/tabs:flex" : "left-0 group-data-overflow-start/tabs:flex"),
126
+ className: (0, cn.cn)("touch-target absolute top-1/2 z-1 hidden size-10 -translate-y-1/2 cursor-pointer items-center justify-center rounded-[max(var(--spark-rounded-md),var(--spark-rounded-full))] bg-gray-1/72 text-gray-a11 backdrop-blur-sm hover:text-gray-12", dir === 1 ? "right-0 group-data-overflow-end/tabs:flex" : "left-0 group-data-overflow-start/tabs:flex"),
127
127
  children: dir === 1 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_epilot_spark_icons.ChevronRight, {}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_epilot_spark_icons.ChevronLeft, {})
128
128
  });
129
129
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
130
- className: (0, cnfast.cn)("group/tabs relative max-w-full", fill ? "block w-full" : "inline-block", className),
130
+ className: (0, cn.cn)("group/tabs relative max-w-full", fill ? "block w-full" : "inline-block", className),
131
131
  "data-fill": fill ? true : void 0,
132
132
  "data-slot": "tabs-list",
133
133
  "data-variant": resolved,
@@ -138,21 +138,21 @@ function TabsList({ className, style, variant = "underline", fill, ref, ...props
138
138
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_base_ui_react_tabs.Tabs.List, {
139
139
  "data-slot": "tabs-scroller",
140
140
  ref: scrollerCallbackRef,
141
- className: (0, cnfast.cn)("relative no-scrollbar flex w-full items-stretch overflow-x-auto scroll-smooth motion-reduce:scroll-auto", resolved === "underline" && "gap-2", resolved === "underline" && "after:pointer-events-none after:absolute after:bottom-0 after:left-(--tabs-indicator-x,0px) after:h-1 after:w-(--tabs-indicator-w,0px) after:rounded-full after:bg-(--spark-tabs-indicator,var(--spark-indicator)) after:transition-none after:duration-200 after:ease-out after:content-[''] data-indicator-ready:after:transition-[left,width] motion-reduce:after:transition-none!", resolved === "pill" && "gap-0 rounded-md bg-gray-a3 p-1"),
141
+ className: (0, cn.cn)("relative no-scrollbar flex w-full items-stretch overflow-x-auto scroll-smooth motion-reduce:scroll-auto", resolved === "underline" && "gap-2", resolved === "underline" && "after:pointer-events-none after:absolute after:bottom-0 after:left-(--tabs-indicator-x,0px) after:h-1 after:w-(--tabs-indicator-w,0px) after:rounded-full after:bg-(--spark-tabs-indicator,var(--spark-indicator)) after:transition-none after:duration-200 after:ease-out after:content-[''] data-indicator-ready:after:transition-[left,width] motion-reduce:after:transition-none!", resolved === "pill" && "gap-0 rounded-md bg-gray-a3 p-1"),
142
142
  ...props
143
143
  }),
144
144
  chevron(1)
145
145
  ]
146
146
  });
147
- }
147
+ });
148
148
  function TabsTrigger({ className, children, ...props }) {
149
149
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_base_ui_react_tabs.Tabs.Tab, {
150
150
  "data-slot": "tabs-trigger",
151
- className: (0, cnfast.cn)("group/trigger touch-target inline-flex min-w-(--tabs-trigger-minw,0px) shrink-0 cursor-pointer scroll-mx-10 items-center justify-center whitespace-nowrap text-gray-12 transition-colors motion-reduce:transition-none", "group-data-fill/tabs:shrink group-data-fill/tabs:grow group-data-fill/tabs:basis-0", "data-active:text-(--spark-tabs-ink,var(--spark-a11))", "focus-visible:outline-hidden", "group-data-[variant=pill]/tabs:focus-visible:ring-2 group-data-[variant=pill]/tabs:focus-visible:ring-offset-1", "data-disabled:pointer-events-none data-disabled:text-gray-a8", "[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*=size-])]:size-4", "group-data-[variant=underline]/tabs:min-h-12 group-data-[variant=underline]/tabs:px-1 group-data-[variant=underline]/tabs:text-base group-data-[variant=underline]/tabs:font-bold group-data-[variant=underline]/tabs:[--tabs-trigger-minw:5rem]", "group-data-[variant=underline]/tabs:border-b-2 group-data-[variant=underline]/tabs:border-gray-a5", "group-data-[variant=pill]/tabs:h-8 group-data-[variant=pill]/tabs:rounded-sm group-data-[variant=pill]/tabs:px-4 group-data-[variant=pill]/tabs:text-sm group-data-[variant=pill]/tabs:font-medium", "group-data-[variant=pill]/tabs:not-data-active:hover:bg-gray-a3", "group-data-[variant=pill]/tabs:data-active:bg-gray-1 group-data-[variant=pill]/tabs:data-active:shadow-sm dark:group-data-[variant=pill]/tabs:data-active:bg-gray-a4 dark:group-data-[variant=pill]/tabs:data-active:inset-ring dark:group-data-[variant=pill]/tabs:data-active:inset-ring-gray-a6", className),
151
+ className: (0, cn.cn)("group/trigger touch-target inline-flex min-w-(--tabs-trigger-minw,0px) shrink-0 cursor-pointer scroll-mx-10 items-center justify-center whitespace-nowrap text-gray-12 transition-colors motion-reduce:transition-none", "group-data-fill/tabs:shrink group-data-fill/tabs:grow group-data-fill/tabs:basis-0", "data-active:text-(--spark-tabs-ink,var(--spark-a11))", "focus-visible:outline-hidden", "group-data-[variant=pill]/tabs:focus-visible:ring-2 group-data-[variant=pill]/tabs:focus-visible:ring-offset-1", "data-disabled:pointer-events-none data-disabled:text-gray-a8", "[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*=size-])]:size-4", "group-data-[variant=underline]/tabs:min-h-12 group-data-[variant=underline]/tabs:px-1 group-data-[variant=underline]/tabs:text-base group-data-[variant=underline]/tabs:font-bold group-data-[variant=underline]/tabs:[--tabs-trigger-minw:5rem]", "group-data-[variant=underline]/tabs:border-b-2 group-data-[variant=underline]/tabs:border-gray-a5", "group-data-[variant=pill]/tabs:h-8 group-data-[variant=pill]/tabs:rounded-sm group-data-[variant=pill]/tabs:px-4 group-data-[variant=pill]/tabs:text-sm group-data-[variant=pill]/tabs:font-medium", "group-data-[variant=pill]/tabs:not-data-active:hover:bg-gray-a3", "group-data-[variant=pill]/tabs:data-active:bg-gray-1 group-data-[variant=pill]/tabs:data-active:shadow-sm dark:group-data-[variant=pill]/tabs:data-active:bg-gray-a4 dark:group-data-[variant=pill]/tabs:data-active:inset-ring dark:group-data-[variant=pill]/tabs:data-active:inset-ring-gray-a6", className),
152
152
  ...props,
153
153
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
154
154
  "data-slot": "tabs-trigger-inner",
155
- className: (0, cnfast.cn)("inline-flex items-center gap-1", "group-data-[variant=underline]/tabs:rounded-md group-data-[variant=underline]/tabs:px-2 group-data-[variant=underline]/tabs:py-1 group-data-[variant=underline]/tabs:transition-colors", "group-data-[variant=underline]/tabs:group-hover/trigger:bg-gray-a3", "group-data-[variant=underline]/tabs:group-focus-visible/trigger:ring-2 group-data-[variant=underline]/tabs:group-focus-visible/trigger:ring-offset-1"),
155
+ className: (0, cn.cn)("inline-flex items-center gap-1", "group-data-[variant=underline]/tabs:rounded-md group-data-[variant=underline]/tabs:px-2 group-data-[variant=underline]/tabs:py-1 group-data-[variant=underline]/tabs:transition-colors", "group-data-[variant=underline]/tabs:group-hover/trigger:bg-gray-a3", "group-data-[variant=underline]/tabs:group-focus-visible/trigger:ring-2 group-data-[variant=underline]/tabs:group-focus-visible/trigger:ring-offset-1"),
156
156
  children
157
157
  })
158
158
  });
@@ -164,7 +164,7 @@ const TabsTriggerPill = TabsTrigger;
164
164
  function TabsContent({ className, ...props }) {
165
165
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_base_ui_react_tabs.Tabs.Panel, {
166
166
  "data-slot": "tabs-content",
167
- className: (0, cnfast.cn)("focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:outline-hidden", className),
167
+ className: (0, cn.cn)("focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:outline-hidden", className),
168
168
  ...props
169
169
  });
170
170
  }
@@ -1 +1 @@
1
- {"version":3,"file":"tabs.cjs","names":["React","TabsPrimitive","ChevronRight","ChevronLeft"],"sources":["../../src/components/tabs.tsx"],"sourcesContent":["import { Tabs as TabsPrimitive } from '@base-ui/react/tabs'\nimport { ChevronLeft, ChevronRight } from '@epilot/spark-icons'\nimport * as React from 'react'\nimport { cn } from '../utils/cn'\n\n// useLayoutEffect warns during SSR; the isomorphic swap is the standard Radix idiom.\nconst useIsomorphicLayoutEffect =\n typeof window === 'undefined' ? React.useEffect : React.useLayoutEffect\n\n// Merge our internal scroller ref with a consumer-forwarded ref. Written locally\n// and React 19-correct: it propagates cleanup-returning callback refs and nulls\n// plain refs on unmount.\ntype PossibleRef<T> = React.Ref<T> | undefined\n\nfunction setRef<T>(ref: PossibleRef<T>, value: T | null) {\n if (typeof ref === 'function') return ref(value)\n if (ref) ref.current = value\n return undefined\n}\n\nfunction composeRefs<T>(...refs: PossibleRef<T>[]) {\n return (node: T) => {\n let hasCleanup = false\n const cleanups = refs.map((ref) => {\n const cleanup = setRef(ref, node)\n if (typeof cleanup === 'function') hasCleanup = true\n return cleanup\n })\n if (hasCleanup) {\n return () => {\n for (let i = 0; i < refs.length; i++) {\n const cleanup = cleanups[i]\n if (typeof cleanup === 'function') cleanup()\n else setRef(refs[i], null)\n }\n }\n }\n return undefined\n }\n}\n\ntype TabsProps = React.ComponentProps<typeof TabsPrimitive.Root>\n\nfunction Tabs(props: TabsProps) {\n return <TabsPrimitive.Root data-slot=\"tabs\" {...props} />\n}\n\ntype TabsListVariant = 'underline'\n\n/**\n * @deprecated Not part of Spark's tab design — use `'underline'`. `'pill'` (a\n * segmented control) and the old text-only `'default'` still render for\n * back-compat but are undocumented and may be removed.\n */\ntype TabsListVariantLegacy = 'default' | 'pill'\n\ntype TabsListProps = Omit<\n React.ComponentProps<typeof TabsPrimitive.List>,\n 'style'\n> & {\n /** `underline` — the Spark tab: bold label + a sliding accent bar. */\n variant?: TabsListVariant | TabsListVariantLegacy\n /**\n * Stretch the strip to its container's full width and divide it evenly\n * among the triggers, instead of shrinking to fit their labels. Each\n * trigger's `--tabs-trigger-minw` floor still applies — once there's no\n * longer room to keep every trigger at least that wide, the strip hands\n * over to the scroller exactly like the non-`fill` case.\n */\n fill?: boolean\n // style lands on the plain wrapper div, so no Base UI state-callback form\n style?: React.CSSProperties\n}\n\n// how much of a neighboring tab a scroll-into-view reveals (matches scroll-mx-10)\nconst REVEAL_PEEK = 40\n// worm indicator: the accent bar stretches across old+new, then contracts to the\n// new tab. WORM_MS must be >= the bar's CSS transition (200ms) so the stretch fully\n// settles before the contract begins — then contract sets left+width from rest in\n// one synced transition, pinning the leading edge so the motion never jiggles (a\n// contract that starts mid-stretch desyncs the two edges → wobble on big jumps).\nconst WORM_MS = 210\n\nfunction TabsList({\n className,\n style,\n variant = 'underline',\n fill,\n ref,\n ...props\n}: TabsListProps) {\n // 'underline' is the only real variant. Deprecated 'pill' still renders (a\n // segmented control, kept for back-compat); anything else (incl. the old\n // text-only 'default') folds into underline.\n const resolved = variant === 'pill' ? 'pill' : 'underline'\n const wrapperRef = React.useRef<HTMLDivElement | null>(null)\n const scrollerRef = React.useRef<HTMLDivElement | null>(null)\n // stable identity (keyed on the forwarded ref) so React doesn't detach/re-attach\n // the scroller ref on every render — TabsList re-renders on each selection.\n const scrollerCallbackRef = React.useMemo(\n () => composeRefs<HTMLDivElement>(scrollerRef, ref),\n [ref],\n )\n\n // Sliding underline + overflow state + travel-into-view. The bar lives on the\n // SCROLLER (::after scrolls with the content) and follows the active trigger via\n // two measured vars; useLayoutEffect measures before paint (no flash); the\n // MutationObserver tracks selection + children + text changes; the ResizeObserver\n // re-measures on container/scroller reflow. Together they cover everything that\n // moves a tab: selection, add/remove, a counter Badge growing, and resize.\n useIsomorphicLayoutEffect(() => {\n const wrapper = wrapperRef.current\n const scroller = scrollerRef.current\n if (!wrapper || !scroller) return\n // the edge chevrons show per side while more content hides in that direction\n const syncOverflow = () => {\n // 2px epsilon absorbs sub-pixel rounding at fractional browser zoom\n // (scrollWidth/clientWidth round to int, scrollLeft is fractional). Assumes\n // LTR (scrollLeft >= 0) — Spark's tab strips are LTR.\n const max = scroller.scrollWidth - scroller.clientWidth\n wrapper.toggleAttribute('data-overflow-start', scroller.scrollLeft > 2)\n wrapper.toggleAttribute(\n 'data-overflow-end',\n scroller.scrollLeft < max - 2,\n )\n }\n // scroller-local reveal — deliberately NOT scrollIntoView, which also scrolls\n // ancestors and would yank the page when the list is half off-screen. The peek\n // keeps the neighboring tab partially visible (\"there's more here\").\n const reveal = (el: HTMLElement) => {\n // jsdom (unit tests) doesn't implement Element.scrollTo\n if (typeof scroller.scrollTo !== 'function') return\n const start = el.offsetLeft - REVEAL_PEEK\n const end = el.offsetLeft + el.offsetWidth + REVEAL_PEEK\n if (start < scroller.scrollLeft) {\n scroller.scrollTo({ left: Math.max(0, start) })\n } else if (end > scroller.scrollLeft + scroller.clientWidth) {\n scroller.scrollTo({ left: end - scroller.clientWidth })\n }\n }\n // matchMedia guarded for jsdom (unit tests); read .matches live so toggling the\n // OS reduce-motion setting mid-session takes effect on the next selection.\n const motionQuery =\n typeof window.matchMedia === 'function'\n ? window.matchMedia('(prefers-reduced-motion: reduce)')\n : null\n const setBar = (x: number, w: number) => {\n scroller.style.setProperty('--tabs-indicator-x', `${x}px`)\n scroller.style.setProperty('--tabs-indicator-w', `${w}px`)\n }\n let lastActive: HTMLElement | null = null\n let mounted = false\n let wormTimer: ReturnType<typeof setTimeout> | undefined\n const measure = () => {\n const active = scroller.querySelector<HTMLElement>(\n '[data-slot=\"tabs-trigger\"][data-active]',\n )\n const changed = active !== lastActive\n if (resolved === 'underline') {\n if (!active) {\n // no selection → collapse the bar (width 0), forget the previous tab, and\n // cancel any pending contract, so a later selection never worms from a\n // stale/removed node\n clearTimeout(wormTimer)\n lastActive = null\n scroller.style.setProperty('--tabs-indicator-w', '0px')\n } else if (\n changed &&\n lastActive?.isConnected &&\n mounted &&\n !motionQuery?.matches\n ) {\n // worm: stretch across old + new (one edge holds, the other reaches),\n // then contract to the new tab (the trailing edge catches up). The union\n // makes it direction-agnostic. isConnected guards dynamic tab removal — a\n // detached old node reports offsets of 0 and would sweep the bar from x=0.\n const from = Math.min(lastActive.offsetLeft, active.offsetLeft)\n const to = Math.max(\n lastActive.offsetLeft + lastActive.offsetWidth,\n active.offsetLeft + active.offsetWidth,\n )\n setBar(from, to - from)\n clearTimeout(wormTimer)\n const el = active\n wormTimer = setTimeout(\n () => setBar(el.offsetLeft, el.offsetWidth),\n WORM_MS,\n )\n } else {\n // first paint, reduced motion, detached previous, or a resize (same tab)\n // → settle on the active tab, no worm\n clearTimeout(wormTimer)\n setBar(active.offsetLeft, active.offsetWidth)\n }\n }\n syncOverflow()\n // travel the active tab into view on selection change — and on mount, so a\n // defaulted off-screen tab is visible. reveal() is scroller-local, so it never\n // scrolls the page/ancestors.\n if (active && changed) {\n reveal(active)\n lastActive = active\n }\n mounted = true\n }\n measure()\n const readyFrame = requestAnimationFrame(() =>\n scroller.setAttribute('data-indicator-ready', ''),\n )\n scroller.addEventListener('scroll', syncOverflow, { passive: true })\n const mo = new MutationObserver(measure)\n mo.observe(scroller, {\n subtree: true,\n childList: true,\n // characterData catches a trigger's text growing (e.g. a counter Badge 9→120):\n // in overflow the scroller's border-box is pinned, so that only changes\n // scrollWidth (never reported by the ResizeObserver) yet shifts every tab.\n characterData: true,\n attributeFilter: ['data-active'],\n })\n const ro = new ResizeObserver(measure)\n ro.observe(scroller)\n return () => {\n cancelAnimationFrame(readyFrame)\n scroller.removeAttribute('data-indicator-ready')\n scroller.removeEventListener('scroll', syncOverflow)\n clearTimeout(wormTimer)\n mo.disconnect()\n ro.disconnect()\n }\n }, [resolved])\n\n const scrollByPage = (dir: 1 | -1) => () => {\n const scroller = scrollerRef.current\n if (typeof scroller?.scrollBy !== 'function') return\n // behavior omitted → follows the scroller's CSS scroll-behavior (smooth,\n // motion-reduce → auto)\n scroller.scrollBy({ left: dir * scroller.clientWidth * 0.6 })\n }\n const chevron = (dir: 1 | -1) => (\n <button\n aria-hidden=\"true\"\n data-slot={dir === 1 ? 'tabs-scroll-next' : 'tabs-scroll-prev'}\n onClick={scrollByPage(dir)}\n tabIndex={-1}\n type=\"button\"\n className={cn(\n 'touch-target absolute top-1/2 z-1 hidden size-10 -translate-y-1/2 cursor-pointer items-center justify-center rounded-[max(var(--spark-rounded-md),var(--spark-rounded-full))] bg-gray-1/72 text-gray-a11 backdrop-blur-sm hover:text-gray-12',\n dir === 1\n ? 'right-0 group-data-overflow-end/tabs:flex'\n : 'left-0 group-data-overflow-start/tabs:flex',\n )}\n >\n {dir === 1 ? <ChevronRight /> : <ChevronLeft />}\n </button>\n )\n\n return (\n // the wrapper is the public box (data-slot tabs-list, consumer className +\n // style) — group/tabs + data-variant here drive the trigger's group-data-[…]/tabs\n // styling, and data-overflow-start/end (set above) show/hide the chevrons.\n // className + style both land here so a consumer's layout (margin/width) moves\n // the whole control, not just the inner scroller (which would offset the chevrons).\n <div\n className={cn(\n 'group/tabs relative max-w-full',\n fill ? 'block w-full' : 'inline-block',\n className,\n )}\n data-fill={fill ? true : undefined}\n data-slot=\"tabs-list\"\n data-variant={resolved}\n ref={wrapperRef}\n style={style}\n >\n {chevron(-1)}\n <TabsPrimitive.List\n data-slot=\"tabs-scroller\"\n ref={scrollerCallbackRef}\n className={cn(\n 'relative no-scrollbar flex w-full items-stretch overflow-x-auto scroll-smooth motion-reduce:scroll-auto',\n resolved === 'underline' && 'gap-2',\n resolved === 'underline' &&\n // transition only once data-indicator-ready is set (a frame after the\n // first measure) so the bar appears in place instead of sweeping in\n \"after:pointer-events-none after:absolute after:bottom-0 after:left-(--tabs-indicator-x,0px) after:h-1 after:w-(--tabs-indicator-w,0px) after:rounded-full after:bg-(--spark-tabs-indicator,var(--spark-indicator)) after:transition-none after:duration-200 after:ease-out after:content-[''] data-indicator-ready:after:transition-[left,width] motion-reduce:after:transition-none!\",\n resolved === 'pill' && 'gap-0 rounded-md bg-gray-a3 p-1',\n )}\n {...props}\n />\n {chevron(1)}\n </div>\n )\n}\n\ntype TabsTriggerProps = React.ComponentProps<typeof TabsPrimitive.Tab>\n\nfunction TabsTrigger({ className, children, ...props }: TabsTriggerProps) {\n return (\n <TabsPrimitive.Tab\n data-slot=\"tabs-trigger\"\n className={cn(\n // touch-target on the base, not per-variant: pill is 32px and underline\n // 48px only at scaling=100% (min-h-12 tracks the knob), so both want the\n // coarse-pointer floor. The overlay never shrinks an already-large box.\n 'group/trigger touch-target inline-flex min-w-(--tabs-trigger-minw,0px) shrink-0 cursor-pointer scroll-mx-10 items-center justify-center whitespace-nowrap text-gray-12 transition-colors motion-reduce:transition-none',\n // fill: divide the strip evenly instead of sizing to each label — the\n // min-w floor above still applies, so a strip too narrow to keep every\n // trigger at least that wide still hands over to the scroller.\n 'group-data-fill/tabs:shrink group-data-fill/tabs:grow group-data-fill/tabs:basis-0',\n 'data-active:text-(--spark-tabs-ink,var(--spark-a11))',\n 'focus-visible:outline-hidden',\n 'group-data-[variant=pill]/tabs:focus-visible:ring-2 group-data-[variant=pill]/tabs:focus-visible:ring-offset-1',\n 'data-disabled:pointer-events-none data-disabled:text-gray-a8',\n '[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*=size-])]:size-4',\n 'group-data-[variant=underline]/tabs:min-h-12 group-data-[variant=underline]/tabs:px-1 group-data-[variant=underline]/tabs:text-base group-data-[variant=underline]/tabs:font-bold group-data-[variant=underline]/tabs:[--tabs-trigger-minw:5rem]',\n 'group-data-[variant=underline]/tabs:border-b-2 group-data-[variant=underline]/tabs:border-gray-a5',\n 'group-data-[variant=pill]/tabs:h-8 group-data-[variant=pill]/tabs:rounded-sm group-data-[variant=pill]/tabs:px-4 group-data-[variant=pill]/tabs:text-sm group-data-[variant=pill]/tabs:font-medium',\n 'group-data-[variant=pill]/tabs:not-data-active:hover:bg-gray-a3',\n 'group-data-[variant=pill]/tabs:data-active:bg-gray-1 group-data-[variant=pill]/tabs:data-active:shadow-sm dark:group-data-[variant=pill]/tabs:data-active:bg-gray-a4 dark:group-data-[variant=pill]/tabs:data-active:inset-ring dark:group-data-[variant=pill]/tabs:data-active:inset-ring-gray-a6',\n className,\n )}\n {...props}\n >\n {/* the Radix two-box anatomy: the hover paints this compact label box (with\n clearance above the bar/track), not the full 48px hit target */}\n <span\n data-slot=\"tabs-trigger-inner\"\n className={cn(\n 'inline-flex items-center gap-1',\n 'group-data-[variant=underline]/tabs:rounded-md group-data-[variant=underline]/tabs:px-2 group-data-[variant=underline]/tabs:py-1 group-data-[variant=underline]/tabs:transition-colors',\n 'group-data-[variant=underline]/tabs:group-hover/trigger:bg-gray-a3',\n 'group-data-[variant=underline]/tabs:group-focus-visible/trigger:ring-2 group-data-[variant=underline]/tabs:group-focus-visible/trigger:ring-offset-1',\n )}\n >\n {children}\n </span>\n </TabsPrimitive.Tab>\n )\n}\n\n/** @deprecated Use `TabsTrigger` — it adapts to the `TabsList` variant automatically. */\nconst TabsTriggerUnderline = TabsTrigger\n\n/** @deprecated Use `TabsTrigger` — it adapts to the `TabsList` variant automatically. */\nconst TabsTriggerPill = TabsTrigger\n\ntype TabsContentProps = React.ComponentProps<typeof TabsPrimitive.Panel>\n\nfunction TabsContent({ className, ...props }: TabsContentProps) {\n return (\n <TabsPrimitive.Panel\n data-slot=\"tabs-content\"\n className={cn(\n 'focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:outline-hidden',\n className,\n )}\n {...props}\n />\n )\n}\n\nexport {\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n TabsTriggerPill,\n TabsTriggerUnderline,\n}\nexport type { TabsListProps, TabsListVariant, TabsProps, TabsTriggerProps }\n"],"mappings":";;;;;;;;;;AAMA,MAAM,4BACJ,OAAO,WAAW,cAAcA,MAAM,YAAYA,MAAM;AAO1D,SAAS,OAAU,KAAqB,OAAiB;CACvD,IAAI,OAAO,QAAQ,YAAY,OAAO,IAAI,KAAK;CAC/C,IAAI,KAAK,IAAI,UAAU;AAEzB;AAEA,SAAS,YAAe,GAAG,MAAwB;CACjD,QAAQ,SAAY;EAClB,IAAI,aAAa;EACjB,MAAM,WAAW,KAAK,KAAK,QAAQ;GACjC,MAAM,UAAU,OAAO,KAAK,IAAI;GAChC,IAAI,OAAO,YAAY,YAAY,aAAa;GAChD,OAAO;EACT,CAAC;EACD,IAAI,YACF,aAAa;GACX,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;IACpC,MAAM,UAAU,SAAS;IACzB,IAAI,OAAO,YAAY,YAAY,QAAQ;SACtC,OAAO,KAAK,IAAI,IAAI;GAC3B;EACF;CAGJ;AACF;AAIA,SAAS,KAAK,OAAkB;CAC9B,OAAO,iBAAA,GAAA,kBAAA,KAACC,oBAAAA,KAAc,MAAf;EAAoB,aAAU;EAAO,GAAI;CAAQ,CAAA;AAC1D;AA8BA,MAAM,cAAc;AAMpB,MAAM,UAAU;AAEhB,SAAS,SAAS,EAChB,WACA,OACA,UAAU,aACV,MACA,KACA,GAAG,SACa;CAIhB,MAAM,WAAW,YAAY,SAAS,SAAS;CAC/C,MAAM,aAAaD,MAAM,OAA8B,IAAI;CAC3D,MAAM,cAAcA,MAAM,OAA8B,IAAI;CAG5D,MAAM,sBAAsBA,MAAM,cAC1B,YAA4B,aAAa,GAAG,GAClD,CAAC,GAAG,CACN;CAQA,gCAAgC;EAC9B,MAAM,UAAU,WAAW;EAC3B,MAAM,WAAW,YAAY;EAC7B,IAAI,CAAC,WAAW,CAAC,UAAU;EAE3B,MAAM,qBAAqB;GAIzB,MAAM,MAAM,SAAS,cAAc,SAAS;GAC5C,QAAQ,gBAAgB,uBAAuB,SAAS,aAAa,CAAC;GACtE,QAAQ,gBACN,qBACA,SAAS,aAAa,MAAM,CAC9B;EACF;EAIA,MAAM,UAAU,OAAoB;GAElC,IAAI,OAAO,SAAS,aAAa,YAAY;GAC7C,MAAM,QAAQ,GAAG,aAAa;GAC9B,MAAM,MAAM,GAAG,aAAa,GAAG,cAAc;GAC7C,IAAI,QAAQ,SAAS,YACnB,SAAS,SAAS,EAAE,MAAM,KAAK,IAAI,GAAG,KAAK,EAAE,CAAC;QACzC,IAAI,MAAM,SAAS,aAAa,SAAS,aAC9C,SAAS,SAAS,EAAE,MAAM,MAAM,SAAS,YAAY,CAAC;EAE1D;EAGA,MAAM,cACJ,OAAO,OAAO,eAAe,aACzB,OAAO,WAAW,kCAAkC,IACpD;EACN,MAAM,UAAU,GAAW,MAAc;GACvC,SAAS,MAAM,YAAY,sBAAsB,GAAG,EAAE,GAAG;GACzD,SAAS,MAAM,YAAY,sBAAsB,GAAG,EAAE,GAAG;EAC3D;EACA,IAAI,aAAiC;EACrC,IAAI,UAAU;EACd,IAAI;EACJ,MAAM,gBAAgB;GACpB,MAAM,SAAS,SAAS,cACtB,2CACF;GACA,MAAM,UAAU,WAAW;GAC3B,IAAI,aAAa,aACf,IAAI,CAAC,QAAQ;IAIX,aAAa,SAAS;IACtB,aAAa;IACb,SAAS,MAAM,YAAY,sBAAsB,KAAK;GACxD,OAAO,IACL,WACA,YAAY,eACZ,WACA,CAAC,aAAa,SACd;IAKA,MAAM,OAAO,KAAK,IAAI,WAAW,YAAY,OAAO,UAAU;IAK9D,OAAO,MAJI,KAAK,IACd,WAAW,aAAa,WAAW,aACnC,OAAO,aAAa,OAAO,WAEf,IAAI,IAAI;IACtB,aAAa,SAAS;IACtB,MAAM,KAAK;IACX,YAAY,iBACJ,OAAO,GAAG,YAAY,GAAG,WAAW,GAC1C,OACF;GACF,OAAO;IAGL,aAAa,SAAS;IACtB,OAAO,OAAO,YAAY,OAAO,WAAW;GAC9C;GAEF,aAAa;GAIb,IAAI,UAAU,SAAS;IACrB,OAAO,MAAM;IACb,aAAa;GACf;GACA,UAAU;EACZ;EACA,QAAQ;EACR,MAAM,aAAa,4BACjB,SAAS,aAAa,wBAAwB,EAAE,CAClD;EACA,SAAS,iBAAiB,UAAU,cAAc,EAAE,SAAS,KAAK,CAAC;EACnE,MAAM,KAAK,IAAI,iBAAiB,OAAO;EACvC,GAAG,QAAQ,UAAU;GACnB,SAAS;GACT,WAAW;GAIX,eAAe;GACf,iBAAiB,CAAC,aAAa;EACjC,CAAC;EACD,MAAM,KAAK,IAAI,eAAe,OAAO;EACrC,GAAG,QAAQ,QAAQ;EACnB,aAAa;GACX,qBAAqB,UAAU;GAC/B,SAAS,gBAAgB,sBAAsB;GAC/C,SAAS,oBAAoB,UAAU,YAAY;GACnD,aAAa,SAAS;GACtB,GAAG,WAAW;GACd,GAAG,WAAW;EAChB;CACF,GAAG,CAAC,QAAQ,CAAC;CAEb,MAAM,gBAAgB,cAAsB;EAC1C,MAAM,WAAW,YAAY;EAC7B,IAAI,OAAO,UAAU,aAAa,YAAY;EAG9C,SAAS,SAAS,EAAE,MAAM,MAAM,SAAS,cAAc,GAAI,CAAC;CAC9D;CACA,MAAM,WAAW,QACf,iBAAA,GAAA,kBAAA,KAAC,UAAD;EACE,eAAY;EACZ,aAAW,QAAQ,IAAI,qBAAqB;EAC5C,SAAS,aAAa,GAAG;EACzB,UAAU;EACV,MAAK;EACL,YAAA,GAAA,OAAA,IACE,gPACA,QAAQ,IACJ,8CACA,4CACN;YAEC,QAAQ,IAAI,iBAAA,GAAA,kBAAA,KAACE,oBAAAA,cAAD,CAAe,CAAA,IAAI,iBAAA,GAAA,kBAAA,KAACC,oBAAAA,aAAD,CAAc,CAAA;CACxC,CAAA;CAGV,OAME,iBAAA,GAAA,kBAAA,MAAC,OAAD;EACE,YAAA,GAAA,OAAA,IACE,kCACA,OAAO,iBAAiB,gBACxB,SACF;EACA,aAAW,OAAO,OAAO,KAAA;EACzB,aAAU;EACV,gBAAc;EACd,KAAK;EACE;YAVT;GAYG,QAAQ,EAAE;GACX,iBAAA,GAAA,kBAAA,KAACF,oBAAAA,KAAc,MAAf;IACE,aAAU;IACV,KAAK;IACL,YAAA,GAAA,OAAA,IACE,2GACA,aAAa,eAAe,SAC5B,aAAa,eAGX,yXACF,aAAa,UAAU,iCACzB;IACA,GAAI;GACL,CAAA;GACA,QAAQ,CAAC;EACP;;AAET;AAIA,SAAS,YAAY,EAAE,WAAW,UAAU,GAAG,SAA2B;CACxE,OACE,iBAAA,GAAA,kBAAA,KAACA,oBAAAA,KAAc,KAAf;EACE,aAAU;EACV,YAAA,GAAA,OAAA,IAIE,0NAIA,sFACA,wDACA,gCACA,kHACA,gEACA,mFACA,oPACA,qGACA,sMACA,mEACA,sSACA,SACF;EACA,GAAI;YAIJ,iBAAA,GAAA,kBAAA,KAAC,QAAD;GACE,aAAU;GACV,YAAA,GAAA,OAAA,IACE,kCACA,0LACA,sEACA,sJACF;GAEC;EACG,CAAA;CACW,CAAA;AAEvB;;AAGA,MAAM,uBAAuB;;AAG7B,MAAM,kBAAkB;AAIxB,SAAS,YAAY,EAAE,WAAW,GAAG,SAA2B;CAC9D,OACE,iBAAA,GAAA,kBAAA,KAACA,oBAAAA,KAAc,OAAf;EACE,aAAU;EACV,YAAA,GAAA,OAAA,IACE,iFACA,SACF;EACA,GAAI;CACL,CAAA;AAEL"}
1
+ {"version":3,"file":"tabs.cjs","names":["React","TabsPrimitive","ChevronRight","ChevronLeft"],"sources":["../../src/components/tabs.tsx"],"sourcesContent":["import { Tabs as TabsPrimitive } from '@base-ui/react/tabs'\nimport { ChevronLeft, ChevronRight } from '@epilot/spark-icons'\nimport * as React from 'react'\nimport { cn } from '../utils/cn'\n\n// useLayoutEffect warns during SSR; the isomorphic swap is the standard Radix idiom.\nconst useIsomorphicLayoutEffect =\n typeof window === 'undefined' ? React.useEffect : React.useLayoutEffect\n\n// Merge our internal scroller ref with a consumer-forwarded ref. Written locally\n// and React 19-correct: it propagates cleanup-returning callback refs and nulls\n// plain refs on unmount.\ntype PossibleRef<T> = React.Ref<T> | undefined\n\nfunction setRef<T>(ref: PossibleRef<T>, value: T | null) {\n if (typeof ref === 'function') return ref(value)\n if (ref) ref.current = value\n return undefined\n}\n\nfunction composeRefs<T>(...refs: PossibleRef<T>[]) {\n return (node: T) => {\n let hasCleanup = false\n const cleanups = refs.map((ref) => {\n const cleanup = setRef(ref, node)\n if (typeof cleanup === 'function') hasCleanup = true\n return cleanup\n })\n if (hasCleanup) {\n return () => {\n for (let i = 0; i < refs.length; i++) {\n const cleanup = cleanups[i]\n if (typeof cleanup === 'function') cleanup()\n else setRef(refs[i], null)\n }\n }\n }\n return undefined\n }\n}\n\ntype TabsProps = React.ComponentProps<typeof TabsPrimitive.Root>\n\nfunction Tabs(props: TabsProps) {\n return <TabsPrimitive.Root data-slot=\"tabs\" {...props} />\n}\n\ntype TabsListVariant = 'underline'\n\n/**\n * @deprecated Not part of Spark's tab design — use `'underline'`. `'pill'` (a\n * segmented control) and the old text-only `'default'` still render for\n * back-compat but are undocumented and may be removed.\n */\ntype TabsListVariantLegacy = 'default' | 'pill'\n\ntype TabsListProps = Omit<\n React.ComponentProps<typeof TabsPrimitive.List>,\n 'style'\n> & {\n /** `underline` — the Spark tab: bold label + a sliding accent bar. */\n // oxlint-disable-next-line typescript/no-deprecated -- public back-compat union, kept until removal\n variant?: TabsListVariant | TabsListVariantLegacy\n /**\n * Stretch the strip to its container's full width and divide it evenly\n * among the triggers, instead of shrinking to fit their labels. Each\n * trigger's `--tabs-trigger-minw` floor still applies — once there's no\n * longer room to keep every trigger at least that wide, the strip hands\n * over to the scroller exactly like the non-`fill` case.\n */\n fill?: boolean\n // style lands on the plain wrapper div, so no Base UI state-callback form\n style?: React.CSSProperties\n}\n\n// how much of a neighboring tab a scroll-into-view reveals (matches scroll-mx-10)\nconst REVEAL_PEEK = 40\n// worm indicator: the accent bar stretches across old+new, then contracts to the\n// new tab. WORM_MS must be >= the bar's CSS transition (200ms) so the stretch fully\n// settles before the contract begins — then contract sets left+width from rest in\n// one synced transition, pinning the leading edge so the motion never jiggles (a\n// contract that starts mid-stretch desyncs the two edges → wobble on big jumps).\nconst WORM_MS = 210\n\nconst TabsList = React.forwardRef<HTMLDivElement, Omit<TabsListProps, 'ref'>>(\n function TabsList(\n { className, style, variant = 'underline', fill, ...props },\n ref,\n ) {\n // 'underline' is the only real variant. Deprecated 'pill' still renders (a\n // segmented control, kept for back-compat); anything else (incl. the old\n // text-only 'default') folds into underline.\n const resolved = variant === 'pill' ? 'pill' : 'underline'\n const wrapperRef = React.useRef<HTMLDivElement | null>(null)\n const scrollerRef = React.useRef<HTMLDivElement | null>(null)\n // stable identity (keyed on the forwarded ref) so React doesn't detach/re-attach\n // the scroller ref on every render — TabsList re-renders on each selection.\n const scrollerCallbackRef = React.useMemo(\n () => composeRefs<HTMLDivElement>(scrollerRef, ref),\n [ref],\n )\n\n // Sliding underline + overflow state + travel-into-view. The bar lives on the\n // SCROLLER (::after scrolls with the content) and follows the active trigger via\n // two measured vars; useLayoutEffect measures before paint (no flash); the\n // MutationObserver tracks selection + children + text changes; the ResizeObserver\n // re-measures on container/scroller reflow. Together they cover everything that\n // moves a tab: selection, add/remove, a counter Badge growing, and resize.\n useIsomorphicLayoutEffect(() => {\n const wrapper = wrapperRef.current\n const scroller = scrollerRef.current\n if (!wrapper || !scroller) return\n // the edge chevrons show per side while more content hides in that direction\n const syncOverflow = () => {\n // 2px epsilon absorbs sub-pixel rounding at fractional browser zoom\n // (scrollWidth/clientWidth round to int, scrollLeft is fractional). Assumes\n // LTR (scrollLeft >= 0) — Spark's tab strips are LTR.\n const max = scroller.scrollWidth - scroller.clientWidth\n wrapper.toggleAttribute('data-overflow-start', scroller.scrollLeft > 2)\n wrapper.toggleAttribute(\n 'data-overflow-end',\n scroller.scrollLeft < max - 2,\n )\n }\n // scroller-local reveal — deliberately NOT scrollIntoView, which also scrolls\n // ancestors and would yank the page when the list is half off-screen. The peek\n // keeps the neighboring tab partially visible (\"there's more here\").\n const reveal = (el: HTMLElement) => {\n // jsdom (unit tests) doesn't implement Element.scrollTo\n if (typeof scroller.scrollTo !== 'function') return\n const start = el.offsetLeft - REVEAL_PEEK\n const end = el.offsetLeft + el.offsetWidth + REVEAL_PEEK\n if (start < scroller.scrollLeft) {\n scroller.scrollTo({ left: Math.max(0, start) })\n } else if (end > scroller.scrollLeft + scroller.clientWidth) {\n scroller.scrollTo({ left: end - scroller.clientWidth })\n }\n }\n // matchMedia guarded for jsdom (unit tests); read .matches live so toggling the\n // OS reduce-motion setting mid-session takes effect on the next selection.\n const motionQuery =\n typeof window.matchMedia === 'function'\n ? window.matchMedia('(prefers-reduced-motion: reduce)')\n : null\n const setBar = (x: number, w: number) => {\n scroller.style.setProperty('--tabs-indicator-x', `${x}px`)\n scroller.style.setProperty('--tabs-indicator-w', `${w}px`)\n }\n let lastActive: HTMLElement | null = null\n let mounted = false\n let wormTimer: ReturnType<typeof setTimeout> | undefined\n const measure = () => {\n const active = scroller.querySelector<HTMLElement>(\n '[data-slot=\"tabs-trigger\"][data-active]',\n )\n const changed = active !== lastActive\n if (resolved === 'underline') {\n if (!active) {\n // no selection → collapse the bar (width 0), forget the previous tab, and\n // cancel any pending contract, so a later selection never worms from a\n // stale/removed node\n clearTimeout(wormTimer)\n lastActive = null\n scroller.style.setProperty('--tabs-indicator-w', '0px')\n } else if (\n changed &&\n lastActive?.isConnected &&\n mounted &&\n !motionQuery?.matches\n ) {\n // worm: stretch across old + new (one edge holds, the other reaches),\n // then contract to the new tab (the trailing edge catches up). The union\n // makes it direction-agnostic. isConnected guards dynamic tab removal — a\n // detached old node reports offsets of 0 and would sweep the bar from x=0.\n const from = Math.min(lastActive.offsetLeft, active.offsetLeft)\n const to = Math.max(\n lastActive.offsetLeft + lastActive.offsetWidth,\n active.offsetLeft + active.offsetWidth,\n )\n setBar(from, to - from)\n clearTimeout(wormTimer)\n const el = active\n wormTimer = setTimeout(\n () => setBar(el.offsetLeft, el.offsetWidth),\n WORM_MS,\n )\n } else {\n // first paint, reduced motion, detached previous, or a resize (same tab)\n // → settle on the active tab, no worm\n clearTimeout(wormTimer)\n setBar(active.offsetLeft, active.offsetWidth)\n }\n }\n syncOverflow()\n // travel the active tab into view on selection change — and on mount, so a\n // defaulted off-screen tab is visible. reveal() is scroller-local, so it never\n // scrolls the page/ancestors.\n if (active && changed) {\n reveal(active)\n lastActive = active\n }\n mounted = true\n }\n measure()\n const readyFrame = requestAnimationFrame(() =>\n scroller.setAttribute('data-indicator-ready', ''),\n )\n scroller.addEventListener('scroll', syncOverflow, { passive: true })\n const mo = new MutationObserver(measure)\n mo.observe(scroller, {\n subtree: true,\n childList: true,\n // characterData catches a trigger's text growing (e.g. a counter Badge 9→120):\n // in overflow the scroller's border-box is pinned, so that only changes\n // scrollWidth (never reported by the ResizeObserver) yet shifts every tab.\n characterData: true,\n attributeFilter: ['data-active'],\n })\n const ro = new ResizeObserver(measure)\n ro.observe(scroller)\n return () => {\n cancelAnimationFrame(readyFrame)\n scroller.removeAttribute('data-indicator-ready')\n scroller.removeEventListener('scroll', syncOverflow)\n clearTimeout(wormTimer)\n mo.disconnect()\n ro.disconnect()\n }\n }, [resolved])\n\n const scrollByPage = (dir: 1 | -1) => () => {\n const scroller = scrollerRef.current\n if (typeof scroller?.scrollBy !== 'function') return\n // behavior omitted → follows the scroller's CSS scroll-behavior (smooth,\n // motion-reduce → auto)\n scroller.scrollBy({ left: dir * scroller.clientWidth * 0.6 })\n }\n const chevron = (dir: 1 | -1) => (\n <button\n aria-hidden=\"true\"\n data-slot={dir === 1 ? 'tabs-scroll-next' : 'tabs-scroll-prev'}\n onClick={scrollByPage(dir)}\n tabIndex={-1}\n type=\"button\"\n className={cn(\n 'touch-target absolute top-1/2 z-1 hidden size-10 -translate-y-1/2 cursor-pointer items-center justify-center rounded-[max(var(--spark-rounded-md),var(--spark-rounded-full))] bg-gray-1/72 text-gray-a11 backdrop-blur-sm hover:text-gray-12',\n dir === 1\n ? 'right-0 group-data-overflow-end/tabs:flex'\n : 'left-0 group-data-overflow-start/tabs:flex',\n )}\n >\n {dir === 1 ? <ChevronRight /> : <ChevronLeft />}\n </button>\n )\n\n return (\n // the wrapper is the public box (data-slot tabs-list, consumer className +\n // style) — group/tabs + data-variant here drive the trigger's group-data-[…]/tabs\n // styling, and data-overflow-start/end (set above) show/hide the chevrons.\n // className + style both land here so a consumer's layout (margin/width) moves\n // the whole control, not just the inner scroller (which would offset the chevrons).\n <div\n className={cn(\n 'group/tabs relative max-w-full',\n fill ? 'block w-full' : 'inline-block',\n className,\n )}\n data-fill={fill ? true : undefined}\n data-slot=\"tabs-list\"\n data-variant={resolved}\n ref={wrapperRef}\n style={style}\n >\n {chevron(-1)}\n <TabsPrimitive.List\n data-slot=\"tabs-scroller\"\n ref={scrollerCallbackRef}\n className={cn(\n 'relative no-scrollbar flex w-full items-stretch overflow-x-auto scroll-smooth motion-reduce:scroll-auto',\n resolved === 'underline' && 'gap-2',\n resolved === 'underline' &&\n // transition only once data-indicator-ready is set (a frame after the\n // first measure) so the bar appears in place instead of sweeping in\n \"after:pointer-events-none after:absolute after:bottom-0 after:left-(--tabs-indicator-x,0px) after:h-1 after:w-(--tabs-indicator-w,0px) after:rounded-full after:bg-(--spark-tabs-indicator,var(--spark-indicator)) after:transition-none after:duration-200 after:ease-out after:content-[''] data-indicator-ready:after:transition-[left,width] motion-reduce:after:transition-none!\",\n resolved === 'pill' && 'gap-0 rounded-md bg-gray-a3 p-1',\n )}\n {...props}\n />\n {chevron(1)}\n </div>\n )\n },\n)\n\ntype TabsTriggerProps = React.ComponentProps<typeof TabsPrimitive.Tab>\n\nfunction TabsTrigger({ className, children, ...props }: TabsTriggerProps) {\n return (\n <TabsPrimitive.Tab\n data-slot=\"tabs-trigger\"\n className={cn(\n // touch-target on the base, not per-variant: pill is 32px and underline\n // 48px only at scaling=100% (min-h-12 tracks the knob), so both want the\n // coarse-pointer floor. The overlay never shrinks an already-large box.\n 'group/trigger touch-target inline-flex min-w-(--tabs-trigger-minw,0px) shrink-0 cursor-pointer scroll-mx-10 items-center justify-center whitespace-nowrap text-gray-12 transition-colors motion-reduce:transition-none',\n // fill: divide the strip evenly instead of sizing to each label — the\n // min-w floor above still applies, so a strip too narrow to keep every\n // trigger at least that wide still hands over to the scroller.\n 'group-data-fill/tabs:shrink group-data-fill/tabs:grow group-data-fill/tabs:basis-0',\n 'data-active:text-(--spark-tabs-ink,var(--spark-a11))',\n 'focus-visible:outline-hidden',\n 'group-data-[variant=pill]/tabs:focus-visible:ring-2 group-data-[variant=pill]/tabs:focus-visible:ring-offset-1',\n 'data-disabled:pointer-events-none data-disabled:text-gray-a8',\n '[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*=size-])]:size-4',\n 'group-data-[variant=underline]/tabs:min-h-12 group-data-[variant=underline]/tabs:px-1 group-data-[variant=underline]/tabs:text-base group-data-[variant=underline]/tabs:font-bold group-data-[variant=underline]/tabs:[--tabs-trigger-minw:5rem]',\n 'group-data-[variant=underline]/tabs:border-b-2 group-data-[variant=underline]/tabs:border-gray-a5',\n 'group-data-[variant=pill]/tabs:h-8 group-data-[variant=pill]/tabs:rounded-sm group-data-[variant=pill]/tabs:px-4 group-data-[variant=pill]/tabs:text-sm group-data-[variant=pill]/tabs:font-medium',\n 'group-data-[variant=pill]/tabs:not-data-active:hover:bg-gray-a3',\n 'group-data-[variant=pill]/tabs:data-active:bg-gray-1 group-data-[variant=pill]/tabs:data-active:shadow-sm dark:group-data-[variant=pill]/tabs:data-active:bg-gray-a4 dark:group-data-[variant=pill]/tabs:data-active:inset-ring dark:group-data-[variant=pill]/tabs:data-active:inset-ring-gray-a6',\n className,\n )}\n {...props}\n >\n {/* the Radix two-box anatomy: the hover paints this compact label box (with\n clearance above the bar/track), not the full 48px hit target */}\n <span\n data-slot=\"tabs-trigger-inner\"\n className={cn(\n 'inline-flex items-center gap-1',\n 'group-data-[variant=underline]/tabs:rounded-md group-data-[variant=underline]/tabs:px-2 group-data-[variant=underline]/tabs:py-1 group-data-[variant=underline]/tabs:transition-colors',\n 'group-data-[variant=underline]/tabs:group-hover/trigger:bg-gray-a3',\n 'group-data-[variant=underline]/tabs:group-focus-visible/trigger:ring-2 group-data-[variant=underline]/tabs:group-focus-visible/trigger:ring-offset-1',\n )}\n >\n {children}\n </span>\n </TabsPrimitive.Tab>\n )\n}\n\n/** @deprecated Use `TabsTrigger` — it adapts to the `TabsList` variant automatically. */\nexport const TabsTriggerUnderline = TabsTrigger\n\n/** @deprecated Use `TabsTrigger` — it adapts to the `TabsList` variant automatically. */\nexport const TabsTriggerPill = TabsTrigger\n\ntype TabsContentProps = React.ComponentProps<typeof TabsPrimitive.Panel>\n\nfunction TabsContent({ className, ...props }: TabsContentProps) {\n return (\n <TabsPrimitive.Panel\n data-slot=\"tabs-content\"\n className={cn(\n 'focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:outline-hidden',\n className,\n )}\n {...props}\n />\n )\n}\n\nexport { Tabs, TabsContent, TabsList, TabsTrigger }\nexport type { TabsListProps, TabsListVariant, TabsProps, TabsTriggerProps }\n"],"mappings":"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"}
@@ -25,14 +25,7 @@ type TabsListProps = Omit<React$1.ComponentProps<typeof Tabs$1.List>, 'style'> &
25
25
  fill?: boolean;
26
26
  style?: React$1.CSSProperties;
27
27
  };
28
- declare function TabsList({
29
- className,
30
- style,
31
- variant,
32
- fill,
33
- ref,
34
- ...props
35
- }: TabsListProps): import("react/jsx-runtime").JSX.Element;
28
+ declare const TabsList: React$1.ForwardRefExoticComponent<Omit<TabsListProps, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
36
29
  type TabsTriggerProps = React$1.ComponentProps<typeof Tabs$1.Tab>;
37
30
  declare function TabsTrigger({
38
31
  className,