@nocoo/basalt 2.2.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (320) hide show
  1. package/README.md +2 -0
  2. package/ai/COMPATIBILITY.md +11 -1
  3. package/ai/DESIGN.md +398 -0
  4. package/ai/INTEGRATION.md +255 -129
  5. package/ai/RECIPES.md +51 -26
  6. package/ai/USAGE.md +4 -4
  7. package/ai/registry.json +3018 -271
  8. package/dist/charts/config.d.ts +11 -11
  9. package/dist/charts/config.js +4 -4
  10. package/dist/charts/config.js.map +1 -1
  11. package/dist/charts/date-navigation.js +10 -10
  12. package/dist/charts/date-navigation.js.map +1 -1
  13. package/dist/charts/donut.js +1 -1
  14. package/dist/charts/donut.js.map +1 -1
  15. package/dist/charts/frame.d.ts +1 -1
  16. package/dist/charts/frame.js +4 -4
  17. package/dist/charts/frame.js.map +1 -1
  18. package/dist/charts/gauge.js +5 -5
  19. package/dist/charts/gauge.js.map +1 -1
  20. package/dist/charts/heatmap-calendar.js +11 -11
  21. package/dist/charts/heatmap-calendar.js.map +1 -1
  22. package/dist/charts/heatmap-matrix.js +8 -8
  23. package/dist/charts/heatmap-matrix.js.map +1 -1
  24. package/dist/charts/item-list.js +1 -1
  25. package/dist/charts/item-list.js.map +1 -1
  26. package/dist/charts/legend.js +19 -19
  27. package/dist/charts/legend.js.map +1 -1
  28. package/dist/charts/palette.js +2 -2
  29. package/dist/charts/palette.js.map +1 -1
  30. package/dist/charts/slot-bar.js +2 -2
  31. package/dist/charts/slot-bar.js.map +1 -1
  32. package/dist/charts/sparkline.js +38 -23
  33. package/dist/charts/sparkline.js.map +1 -1
  34. package/dist/charts/stat-card.d.ts +2 -2
  35. package/dist/charts/stat-card.js +61 -58
  36. package/dist/charts/stat-card.js.map +1 -1
  37. package/dist/charts/timeline.js +18 -9
  38. package/dist/charts/timeline.js.map +1 -1
  39. package/dist/charts/tooltip.js +16 -16
  40. package/dist/charts/tooltip.js.map +1 -1
  41. package/dist/components/accordion.js +1 -1
  42. package/dist/components/accordion.js.map +1 -1
  43. package/dist/components/alert-dialog.js +4 -4
  44. package/dist/components/alert-dialog.js.map +1 -1
  45. package/dist/components/app-header.js +8 -8
  46. package/dist/components/app-header.js.map +1 -1
  47. package/dist/components/app-shell.js +1 -1
  48. package/dist/components/app-shell.js.map +1 -1
  49. package/dist/components/approval-card.d.ts +13 -0
  50. package/dist/components/approval-card.js +161 -0
  51. package/dist/components/approval-card.js.map +1 -0
  52. package/dist/components/avatar.d.ts +12 -0
  53. package/dist/components/avatar.js +39 -18
  54. package/dist/components/avatar.js.map +1 -1
  55. package/dist/components/badge.js +8 -8
  56. package/dist/components/badge.js.map +1 -1
  57. package/dist/components/banner.d.ts +2 -2
  58. package/dist/components/banner.js +9 -8
  59. package/dist/components/banner.js.map +1 -1
  60. package/dist/components/basalt-mark.js +1 -1
  61. package/dist/components/basalt-mark.js.map +1 -1
  62. package/dist/components/battery-meter.js +5 -5
  63. package/dist/components/battery-meter.js.map +1 -1
  64. package/dist/components/breadcrumbs.js +6 -6
  65. package/dist/components/breadcrumbs.js.map +1 -1
  66. package/dist/components/button.js +10 -10
  67. package/dist/components/button.js.map +1 -1
  68. package/dist/components/chat-bubble.js +4 -3
  69. package/dist/components/chat-bubble.js.map +1 -1
  70. package/dist/components/chat-composer.d.ts +21 -3
  71. package/dist/components/chat-composer.js +126 -60
  72. package/dist/components/chat-composer.js.map +1 -1
  73. package/dist/components/chat-header.js +6 -6
  74. package/dist/components/chat-header.js.map +1 -1
  75. package/dist/components/chat-inbox.js +34 -30
  76. package/dist/components/chat-inbox.js.map +1 -1
  77. package/dist/components/chat-markdown.d.ts +8 -0
  78. package/dist/components/chat-markdown.js +122 -0
  79. package/dist/components/chat-markdown.js.map +1 -0
  80. package/dist/components/chat-message.d.ts +26 -0
  81. package/dist/components/chat-message.js +145 -0
  82. package/dist/components/chat-message.js.map +1 -0
  83. package/dist/components/checkbox.js +11 -11
  84. package/dist/components/checkbox.js.map +1 -1
  85. package/dist/components/clipboard-text.js +3 -3
  86. package/dist/components/clipboard-text.js.map +1 -1
  87. package/dist/components/code.d.ts +22 -20
  88. package/dist/components/code.js +94 -32
  89. package/dist/components/code.js.map +1 -1
  90. package/dist/components/collapsible.js +8 -4
  91. package/dist/components/collapsible.js.map +1 -1
  92. package/dist/components/command-palette.js +73 -47
  93. package/dist/components/command-palette.js.map +1 -1
  94. package/dist/components/context-cards.d.ts +15 -0
  95. package/dist/components/context-cards.js +148 -0
  96. package/dist/components/context-cards.js.map +1 -0
  97. package/dist/components/context-menu.d.ts +1 -1
  98. package/dist/components/context-menu.js +18 -14
  99. package/dist/components/context-menu.js.map +1 -1
  100. package/dist/components/data-table.d.ts +14 -2
  101. package/dist/components/data-table.js +185 -135
  102. package/dist/components/data-table.js.map +1 -1
  103. package/dist/components/date-picker.js +13 -13
  104. package/dist/components/date-picker.js.map +1 -1
  105. package/dist/components/delete-resource.js +1 -1
  106. package/dist/components/delete-resource.js.map +1 -1
  107. package/dist/components/description-list.js +3 -3
  108. package/dist/components/description-list.js.map +1 -1
  109. package/dist/components/dialog.d.ts +2 -2
  110. package/dist/components/dialog.js +8 -8
  111. package/dist/components/dialog.js.map +1 -1
  112. package/dist/components/diff-table.d.ts +15 -0
  113. package/dist/components/diff-table.js +151 -0
  114. package/dist/components/diff-table.js.map +1 -0
  115. package/dist/components/dock.js +2 -2
  116. package/dist/components/dock.js.map +1 -1
  117. package/dist/components/dropdown-menu.js +23 -18
  118. package/dist/components/dropdown-menu.js.map +1 -1
  119. package/dist/components/editable-nav-item.js +63 -58
  120. package/dist/components/editable-nav-item.js.map +1 -1
  121. package/dist/components/empty.js +6 -6
  122. package/dist/components/empty.js.map +1 -1
  123. package/dist/components/fab.js +1 -1
  124. package/dist/components/fab.js.map +1 -1
  125. package/dist/components/field.js +3 -3
  126. package/dist/components/field.js.map +1 -1
  127. package/dist/components/file-dropzone.js +7 -7
  128. package/dist/components/file-dropzone.js.map +1 -1
  129. package/dist/components/filter-bar.js +6 -6
  130. package/dist/components/filter-bar.js.map +1 -1
  131. package/dist/components/flow.js +4 -3
  132. package/dist/components/flow.js.map +1 -1
  133. package/dist/components/grid.d.ts +3 -1
  134. package/dist/components/grid.js +15 -8
  135. package/dist/components/grid.js.map +1 -1
  136. package/dist/components/hover-card.js +1 -1
  137. package/dist/components/hover-card.js.map +1 -1
  138. package/dist/components/icon-picker.d.ts +8 -2
  139. package/dist/components/icon-picker.js +75 -47
  140. package/dist/components/icon-picker.js.map +1 -1
  141. package/dist/components/inline-editable.js +6 -6
  142. package/dist/components/inline-editable.js.map +1 -1
  143. package/dist/components/input-area.js +3 -3
  144. package/dist/components/input-area.js.map +1 -1
  145. package/dist/components/input-group.js +5 -5
  146. package/dist/components/input-group.js.map +1 -1
  147. package/dist/components/input.js +4 -4
  148. package/dist/components/input.js.map +1 -1
  149. package/dist/components/label.js +3 -3
  150. package/dist/components/label.js.map +1 -1
  151. package/dist/components/layer-card.d.ts +9 -4
  152. package/dist/components/layer-card.js +72 -67
  153. package/dist/components/layer-card.js.map +1 -1
  154. package/dist/components/loader.d.ts +16 -10
  155. package/dist/components/loader.js +46 -53
  156. package/dist/components/loader.js.map +1 -1
  157. package/dist/components/loading-screen.js +3 -3
  158. package/dist/components/loading-screen.js.map +1 -1
  159. package/dist/components/menu-bar.js +32 -27
  160. package/dist/components/menu-bar.js.map +1 -1
  161. package/dist/components/meter.d.ts +5 -5
  162. package/dist/components/meter.js +25 -12
  163. package/dist/components/meter.js.map +1 -1
  164. package/dist/components/multi-select.js +66 -62
  165. package/dist/components/multi-select.js.map +1 -1
  166. package/dist/components/navigation-menu.d.ts +2 -2
  167. package/dist/components/navigation-menu.js +22 -8
  168. package/dist/components/navigation-menu.js.map +1 -1
  169. package/dist/components/overlay.js +2 -2
  170. package/dist/components/overlay.js.map +1 -1
  171. package/dist/components/page-header.d.ts +3 -1
  172. package/dist/components/page-header.js +12 -12
  173. package/dist/components/page-header.js.map +1 -1
  174. package/dist/components/pagination.js +3 -3
  175. package/dist/components/pagination.js.map +1 -1
  176. package/dist/components/popover.js +18 -23
  177. package/dist/components/popover.js.map +1 -1
  178. package/dist/components/prompt-bar.d.ts +16 -0
  179. package/dist/components/prompt-bar.js +49 -0
  180. package/dist/components/prompt-bar.js.map +1 -0
  181. package/dist/components/radio.js +9 -9
  182. package/dist/components/radio.js.map +1 -1
  183. package/dist/components/recommendation-card.d.ts +13 -0
  184. package/dist/components/recommendation-card.js +123 -0
  185. package/dist/components/recommendation-card.js.map +1 -0
  186. package/dist/components/resource-list.js +1 -1
  187. package/dist/components/resource-list.js.map +1 -1
  188. package/dist/components/responsive-master-detail.js +4 -4
  189. package/dist/components/responsive-master-detail.js.map +1 -1
  190. package/dist/components/scroll-area.js +3 -3
  191. package/dist/components/scroll-area.js.map +1 -1
  192. package/dist/components/section-rule.d.ts +5 -3
  193. package/dist/components/section-rule.js +12 -12
  194. package/dist/components/section-rule.js.map +1 -1
  195. package/dist/components/segment-control.js +3 -3
  196. package/dist/components/segment-control.js.map +1 -1
  197. package/dist/components/select.js +47 -32
  198. package/dist/components/select.js.map +1 -1
  199. package/dist/components/sensitive-input.js +17 -19
  200. package/dist/components/sensitive-input.js.map +1 -1
  201. package/dist/components/sheet.d.ts +4 -4
  202. package/dist/components/sheet.js +11 -10
  203. package/dist/components/sheet.js.map +1 -1
  204. package/dist/components/sidebar.js +149 -137
  205. package/dist/components/sidebar.js.map +1 -1
  206. package/dist/components/skeleton-line.d.ts +1 -1
  207. package/dist/components/skeleton-line.js +2 -2
  208. package/dist/components/skeleton-line.js.map +1 -1
  209. package/dist/components/slider.js +2 -2
  210. package/dist/components/slider.js.map +1 -1
  211. package/dist/components/stat-strip.js +5 -4
  212. package/dist/components/stat-strip.js.map +1 -1
  213. package/dist/components/switch.js +6 -6
  214. package/dist/components/switch.js.map +1 -1
  215. package/dist/components/table-of-contents.js +5 -5
  216. package/dist/components/table-of-contents.js.map +1 -1
  217. package/dist/components/table-pager.js +2 -2
  218. package/dist/components/table-pager.js.map +1 -1
  219. package/dist/components/table.d.ts +39 -2
  220. package/dist/components/table.js +48 -17
  221. package/dist/components/table.js.map +1 -1
  222. package/dist/components/tabs.js +7 -6
  223. package/dist/components/tabs.js.map +1 -1
  224. package/dist/components/tag-badge.d.ts +10 -10
  225. package/dist/components/tag-badge.js +11 -11
  226. package/dist/components/tag-badge.js.map +1 -1
  227. package/dist/components/tag-color-picker.d.ts +8 -1
  228. package/dist/components/tag-color-picker.js +33 -25
  229. package/dist/components/tag-color-picker.js.map +1 -1
  230. package/dist/components/text.js +5 -5
  231. package/dist/components/text.js.map +1 -1
  232. package/dist/components/theme-toggle.js +1 -1
  233. package/dist/components/theme-toggle.js.map +1 -1
  234. package/dist/components/thinking.d.ts +16 -0
  235. package/dist/components/thinking.js +85 -0
  236. package/dist/components/thinking.js.map +1 -0
  237. package/dist/components/toast.js +25 -20
  238. package/dist/components/toast.js.map +1 -1
  239. package/dist/components/toggle-group.js +6 -5
  240. package/dist/components/toggle-group.js.map +1 -1
  241. package/dist/components/toggle.js +6 -6
  242. package/dist/components/toggle.js.map +1 -1
  243. package/dist/components/tool-chips.d.ts +12 -0
  244. package/dist/components/tool-chips.js +138 -0
  245. package/dist/components/tool-chips.js.map +1 -0
  246. package/dist/components/toolbar.js +3 -3
  247. package/dist/components/toolbar.js.map +1 -1
  248. package/dist/components/tooltip.js +1 -1
  249. package/dist/components/tooltip.js.map +1 -1
  250. package/dist/components/typeahead-field.js +59 -56
  251. package/dist/components/typeahead-field.js.map +1 -1
  252. package/dist/components/upload-queue.js +15 -14
  253. package/dist/components/upload-queue.js.map +1 -1
  254. package/dist/models/agent-feedback.d.ts +44 -0
  255. package/dist/models/agent-feedback.js +28 -0
  256. package/dist/models/agent-feedback.js.map +1 -0
  257. package/dist/models/avatar.d.ts +2 -0
  258. package/dist/models/avatar.js +15 -0
  259. package/dist/models/avatar.js.map +1 -0
  260. package/dist/models/code.d.ts +6 -0
  261. package/dist/models/code.js +24 -0
  262. package/dist/models/code.js.map +1 -0
  263. package/dist/models/context-cards.d.ts +13 -0
  264. package/dist/models/context-cards.js +17 -0
  265. package/dist/models/context-cards.js.map +1 -0
  266. package/dist/models/diff-table.d.ts +12 -0
  267. package/dist/models/diff-table.js +9 -0
  268. package/dist/models/diff-table.js.map +1 -0
  269. package/dist/models/recommendation.d.ts +26 -0
  270. package/dist/models/recommendation.js +23 -0
  271. package/dist/models/recommendation.js.map +1 -0
  272. package/dist/styles/base.css +14 -2
  273. package/dist/styles/standalone.css +1901 -943
  274. package/dist/styles/tailwind.css +180 -13
  275. package/dist/styles/tokens.css +681 -20
  276. package/dist/utils/cn.js +25 -4
  277. package/dist/utils/cn.js.map +1 -1
  278. package/dist/utils/control-surface.d.ts +1 -1
  279. package/dist/utils/control-surface.js +1 -1
  280. package/dist/utils/control-surface.js.map +1 -1
  281. package/dist/utils/navigation.d.ts +3 -0
  282. package/dist/utils/navigation.js +8 -0
  283. package/dist/utils/navigation.js.map +1 -0
  284. package/dist/utils/selection-indicator.d.ts +1 -1
  285. package/dist/utils/selection-indicator.js +49 -72
  286. package/dist/utils/selection-indicator.js.map +1 -1
  287. package/dist/utils/use-hover-highlight.d.ts +4 -0
  288. package/dist/utils/use-hover-highlight.js +82 -0
  289. package/dist/utils/use-hover-highlight.js.map +1 -0
  290. package/dist/viewmodels/use-approval-card.d.ts +20 -0
  291. package/dist/viewmodels/use-approval-card.js +83 -0
  292. package/dist/viewmodels/use-approval-card.js.map +1 -0
  293. package/dist/viewmodels/use-chat-composer.d.ts +16 -0
  294. package/dist/viewmodels/use-chat-composer.js +34 -0
  295. package/dist/viewmodels/use-chat-composer.js.map +1 -0
  296. package/dist/viewmodels/use-chat-message.d.ts +16 -0
  297. package/dist/viewmodels/use-chat-message.js +26 -0
  298. package/dist/viewmodels/use-chat-message.js.map +1 -0
  299. package/dist/viewmodels/use-code-block.d.ts +8 -0
  300. package/dist/viewmodels/use-code-block.js +38 -0
  301. package/dist/viewmodels/use-code-block.js.map +1 -0
  302. package/dist/viewmodels/use-context-cards.d.ts +17 -0
  303. package/dist/viewmodels/use-context-cards.js +18 -0
  304. package/dist/viewmodels/use-context-cards.js.map +1 -0
  305. package/dist/viewmodels/use-diff-table.d.ts +16 -0
  306. package/dist/viewmodels/use-diff-table.js +42 -0
  307. package/dist/viewmodels/use-diff-table.js.map +1 -0
  308. package/dist/viewmodels/use-loader.d.ts +4 -0
  309. package/dist/viewmodels/use-loader.js +22 -0
  310. package/dist/viewmodels/use-loader.js.map +1 -0
  311. package/dist/viewmodels/use-recommendation-card.d.ts +17 -0
  312. package/dist/viewmodels/use-recommendation-card.js +41 -0
  313. package/dist/viewmodels/use-recommendation-card.js.map +1 -0
  314. package/dist/viewmodels/use-thinking.d.ts +13 -0
  315. package/dist/viewmodels/use-thinking.js +18 -0
  316. package/dist/viewmodels/use-thinking.js.map +1 -0
  317. package/dist/viewmodels/use-tool-chips.d.ts +10 -0
  318. package/dist/viewmodels/use-tool-chips.js +20 -0
  319. package/dist/viewmodels/use-tool-chips.js.map +1 -0
  320. package/package.json +28 -26
@@ -1,90 +1,95 @@
1
1
  "use client";
2
2
  import { cn as e } from "../utils/cn.js";
3
3
  import { BASALT_UI_CLASS as t } from "../utils/control-surface.js";
4
- import { Button as n } from "./button.js";
5
- import { Link as r } from "./link.js";
6
- import { InlineEditable as i } from "./inline-editable.js";
7
- import { useId as a, useLayoutEffect as o, useRef as s, useState as c } from "react";
8
- import { Folder as l, Pencil as u } from "lucide-react";
9
- import { Fragment as d, jsx as f, jsxs as p } from "react/jsx-runtime";
4
+ import { FOCUS_INSET as n } from "./overlay.js";
5
+ import { Button as r } from "./button.js";
6
+ import { Link as i } from "./link.js";
7
+ import { NAV_ROW_CLASS as a } from "../utils/navigation.js";
8
+ import { InlineEditable as o } from "./inline-editable.js";
9
+ import { useId as s, useLayoutEffect as c, useRef as l, useState as u } from "react";
10
+ import { Folder as d, Pencil as f } from "lucide-react";
11
+ import { Fragment as p, jsx as m, jsxs as h } from "react/jsx-runtime";
10
12
  //#region src/components/editable-nav-item.tsx
11
- function m({ label: l, href: m, onSelect: h, selected: g = !1, icon: _, count: v, actions: y, onRename: b, disabled: x = !1, renameLabel: S = "Rename", saveLabel: C = "Save", cancelLabel: w = "Cancel", className: T }) {
12
- let [E, D] = c(!1), O = a(), k = s(null), A = s(!1);
13
- o(() => {
14
- !E && A.current && (A.current = !1, k.current?.focus());
15
- }, [E]);
16
- let j = /* @__PURE__ */ p(d, { children: [
17
- /* @__PURE__ */ f("span", {
18
- className: "shrink-0",
13
+ function g({ label: d, href: g, onSelect: _, selected: v = !1, icon: y, count: b, actions: x, onRename: S, disabled: C = !1, renameLabel: w = "Rename", saveLabel: T = "Save", cancelLabel: E = "Cancel", className: D }) {
14
+ let [O, k] = u(!1), A = s(), j = l(null), M = l(!1);
15
+ c(() => {
16
+ !O && M.current && (M.current = !1, j.current?.focus());
17
+ }, [O]);
18
+ let N = /* @__PURE__ */ h(p, { children: [
19
+ y && /* @__PURE__ */ m("span", {
20
+ className: "flex size-basalt-icon-lg shrink-0 items-center justify-center [&>svg]:size-basalt-icon-lg",
19
21
  "aria-hidden": "true",
20
- children: _
22
+ children: y
21
23
  }),
22
- /* @__PURE__ */ f("span", {
24
+ /* @__PURE__ */ m("span", {
23
25
  className: "min-w-0 flex-1 truncate text-left",
24
- children: l
26
+ children: d
25
27
  }),
26
- v != null && /* @__PURE__ */ p("span", {
27
- id: O,
28
- className: "shrink-0 text-xs tabular-nums text-basalt-muted-foreground",
29
- children: [" ", v]
28
+ b != null && /* @__PURE__ */ h("span", {
29
+ id: A,
30
+ className: "shrink-0 text-basalt-sm tabular-nums text-basalt-muted-foreground",
31
+ children: [" ", b]
30
32
  })
31
33
  ] });
32
- return /* @__PURE__ */ f("div", {
33
- className: e(t, "min-w-0 rounded-basalt-md", g && "bg-basalt-accent", T),
34
- children: E && b ? /* @__PURE__ */ f(i, {
35
- className: "p-2",
36
- label: `${S} ${l}`,
37
- value: l,
34
+ return /* @__PURE__ */ m("div", {
35
+ "data-basalt-hover-item": O ? void 0 : "",
36
+ "data-hover-selected": v && !O,
37
+ "data-disabled": C ? "" : void 0,
38
+ className: e(t, "basalt-nav-item min-w-0 shrink-0 rounded-basalt-md data-disabled:cursor-default data-disabled:hover:bg-transparent", D),
39
+ children: O && S ? /* @__PURE__ */ m(o, {
40
+ className: "p-basalt-space-lg",
41
+ label: `${w} ${d}`,
42
+ value: d,
38
43
  editing: !0,
39
- onSave: b,
40
- saveLabel: C,
41
- cancelLabel: w,
42
- disabled: x,
44
+ onSave: S,
45
+ saveLabel: T,
46
+ cancelLabel: E,
47
+ disabled: C,
43
48
  onEditingChange: (e, t) => {
44
- A.current = !e && t !== "blur", D(e);
49
+ M.current = !e && t !== "blur", k(e);
45
50
  }
46
- }) : /* @__PURE__ */ p("div", {
47
- className: "flex min-w-0 items-center gap-1",
51
+ }) : /* @__PURE__ */ h("div", {
52
+ className: "flex min-w-0 items-center gap-basalt-nav-gap",
48
53
  children: [
49
- /* @__PURE__ */ f(n, {
50
- asChild: !!m,
54
+ /* @__PURE__ */ m(r, {
55
+ asChild: !!g,
51
56
  variant: "ghost",
52
- disabled: x,
53
- className: "min-w-0 flex-1 justify-start gap-2",
54
- "aria-current": g ? "page" : void 0,
55
- "aria-label": l,
56
- "aria-describedby": v == null ? void 0 : O,
57
- onClick: h,
58
- children: m ? /* @__PURE__ */ f(r, {
59
- href: m,
57
+ disabled: C,
58
+ className: e(a, n, "h-auto flex-1 justify-start hover:bg-transparent hover:border-transparent focus-visible:ring-offset-0"),
59
+ "aria-current": v ? "page" : void 0,
60
+ "aria-label": d,
61
+ "aria-describedby": b == null ? void 0 : A,
62
+ onClick: _,
63
+ children: g ? /* @__PURE__ */ m(i, {
64
+ href: g,
60
65
  className: "text-inherit no-underline hover:no-underline",
61
- children: j
62
- }) : j
66
+ children: N
67
+ }) : N
63
68
  }),
64
- b && /* @__PURE__ */ f(n, {
65
- ref: k,
69
+ S && /* @__PURE__ */ m(r, {
70
+ ref: j,
66
71
  size: "icon",
67
72
  variant: "ghost",
68
- disabled: x,
69
- "aria-label": `${S} ${l}`,
70
- onClick: () => D(!0),
71
- children: /* @__PURE__ */ f(u, {})
73
+ disabled: C,
74
+ "aria-label": `${w} ${d}`,
75
+ onClick: () => k(!0),
76
+ children: /* @__PURE__ */ m(f, {})
72
77
  }),
73
- y && /* @__PURE__ */ f("div", {
74
- className: "flex shrink-0 items-center gap-1",
75
- children: y
78
+ x && /* @__PURE__ */ m("div", {
79
+ className: "flex shrink-0 items-center gap-basalt-space-sm",
80
+ children: x
76
81
  })
77
82
  ]
78
83
  })
79
84
  });
80
85
  }
81
- function h({ icon: e = /* @__PURE__ */ f(l, { className: "size-4" }), ...t }) {
82
- return /* @__PURE__ */ f(m, {
86
+ function _({ icon: e = /* @__PURE__ */ m(d, { className: "size-basalt-icon-lg" }), ...t }) {
87
+ return /* @__PURE__ */ m(g, {
83
88
  icon: e,
84
89
  ...t
85
90
  });
86
91
  }
87
92
  //#endregion
88
- export { m as EditableNavItem, h as FolderNavItem };
93
+ export { g as EditableNavItem, _ as FolderNavItem };
89
94
 
90
95
  //# sourceMappingURL=editable-nav-item.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"editable-nav-item.js","names":["_Fragment","Fragment$1","EditableNavItem","editing","setEditing","useState","countId","useId","rename","useRef","restore","content","icon","label","count","cn","BASALT_UI_CLASS","selected","className","onRename","InlineEditable","renameLabel","next","reason","Button","href","onSelect","Link","Pencil","actions","FolderNavItem","Folder","props"],"sources":["../../src/components/editable-nav-item.tsx"],"sourcesContent":["import { Folder, Pencil } from \"lucide-react\";\nimport { type ReactNode, useId, useLayoutEffect, useRef, useState } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { Button } from \"./button\";\nimport { InlineEditable } from \"./inline-editable\";\nimport { Link } from \"./link\";\n\nexport interface EditableNavItemProps {\n\t/** Current display name. */\n\tlabel: string;\n\t/** Application route, interpreted by LinkProvider. */\n\thref?: string;\n\t/** Navigation/selection request. */\n\tonSelect?: () => void;\n\t/** Selected location. @default false */\n\tselected?: boolean;\n\t/** Caller-owned leading icon. */\n\ticon?: ReactNode;\n\t/** Caller-formatted count or status. */\n\tcount?: ReactNode;\n\t/** Separate row actions, never nested inside the navigation button/link. */\n\tactions?: ReactNode;\n\t/** Enable renaming; rejected promises keep the editor and draft available. */\n\tonRename?: (name: string) => void | Promise<void>;\n\t/** Disable navigation and renaming. Application action slots retain their own permissions. @default false */\n\tdisabled?: boolean;\n\t/** Rename action prefix. @default \"Rename\" */\n\trenameLabel?: string;\n\t/** Accessible save action. @default \"Save\" */\n\tsaveLabel?: string;\n\t/** Accessible cancel action. @default \"Cancel\" */\n\tcancelLabel?: string;\n\t/** Additional root classes. */\n\tclassName?: string;\n}\nexport function EditableNavItem({\n\tlabel,\n\thref,\n\tonSelect,\n\tselected = false,\n\ticon,\n\tcount,\n\tactions,\n\tonRename,\n\tdisabled = false,\n\trenameLabel = \"Rename\",\n\tsaveLabel = \"Save\",\n\tcancelLabel = \"Cancel\",\n\tclassName,\n}: EditableNavItemProps) {\n\tconst [editing, setEditing] = useState(false);\n\tconst countId = useId();\n\tconst rename = useRef<HTMLButtonElement>(null);\n\tconst restore = useRef(false);\n\tuseLayoutEffect(() => {\n\t\tif (!editing && restore.current) {\n\t\t\trestore.current = false;\n\t\t\trename.current?.focus();\n\t\t}\n\t}, [editing]);\n\tconst content = (\n\t\t<>\n\t\t\t<span className=\"shrink-0\" aria-hidden=\"true\">\n\t\t\t\t{icon}\n\t\t\t</span>\n\t\t\t<span className=\"min-w-0 flex-1 truncate text-left\">{label}</span>\n\t\t\t{count != null && (\n\t\t\t\t<span id={countId} className=\"shrink-0 text-xs tabular-nums text-basalt-muted-foreground\">\n\t\t\t\t\t{\" \"}\n\t\t\t\t\t{count}\n\t\t\t\t</span>\n\t\t\t)}\n\t\t</>\n\t);\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\tBASALT_UI_CLASS,\n\t\t\t\t\"min-w-0 rounded-basalt-md\",\n\t\t\t\tselected && \"bg-basalt-accent\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t{editing && onRename ? (\n\t\t\t\t<InlineEditable\n\t\t\t\t\tclassName=\"p-2\"\n\t\t\t\t\tlabel={`${renameLabel} ${label}`}\n\t\t\t\t\tvalue={label}\n\t\t\t\t\tediting\n\t\t\t\t\tonSave={onRename}\n\t\t\t\t\tsaveLabel={saveLabel}\n\t\t\t\t\tcancelLabel={cancelLabel}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tonEditingChange={(next, reason) => {\n\t\t\t\t\t\trestore.current = !next && reason !== \"blur\";\n\t\t\t\t\t\tsetEditing(next);\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t) : (\n\t\t\t\t<div className=\"flex min-w-0 items-center gap-1\">\n\t\t\t\t\t<Button\n\t\t\t\t\t\tasChild={!!href}\n\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\tclassName=\"min-w-0 flex-1 justify-start gap-2\"\n\t\t\t\t\t\taria-current={selected ? \"page\" : undefined}\n\t\t\t\t\t\taria-label={label}\n\t\t\t\t\t\taria-describedby={count != null ? countId : undefined}\n\t\t\t\t\t\tonClick={onSelect}\n\t\t\t\t\t>\n\t\t\t\t\t\t{href ? (\n\t\t\t\t\t\t\t<Link href={href} className=\"text-inherit no-underline hover:no-underline\">\n\t\t\t\t\t\t\t\t{content}\n\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\tcontent\n\t\t\t\t\t\t)}\n\t\t\t\t\t</Button>\n\t\t\t\t\t{onRename && (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tref={rename}\n\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\taria-label={`${renameLabel} ${label}`}\n\t\t\t\t\t\t\tonClick={() => setEditing(true)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Pencil />\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\t\t\t\t\t{actions && <div className=\"flex shrink-0 items-center gap-1\">{actions}</div>}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nexport type FolderNavItemProps = EditableNavItemProps;\n/** Folder presentation with an overridable icon; no tree, router or permission model. */\nexport function FolderNavItem({\n\ticon = <Folder className=\"size-4\" />,\n\t...props\n}: FolderNavItemProps) {\n\treturn <EditableNavItem icon={icon} {...props} />;\n}\n"],"mappings":";;;;;;;;;;AAoCA,SAAgBE,EAAgB,EAC/B,UACA,SACA,aACA,cAAW,IACX,SACA,UACA,YACA,aACA,cAAW,IACX,iBAAc,UACd,eAAY,QACZ,iBAAc,UACd,gBACwB;CACxB,IAAM,CAACC,GAASC,KAAcC,EAAS,EAAK,GACtCC,IAAUC,EAAM,GAChBC,IAASC,EAA0B,IAAI,GACvCC,IAAUD,EAAO,EAAK;CAC5B,QAAsB;EACrB,AAAI,CAACN,KAAWO,EAAQ,YACvB,EAAQ,UAAU,IAClBF,EAAO,SAAS,MAAM;CAExB,GAAG,CAACL,CAAO,CAAC;CACZ,IAAMQ,IACL,kBAAAX,GAAA,EAAA,UAAA;EACC,kBAAC,QAAD;GAAM,WAAU;GAAW,eAAY;GACrC,UAAAY;EACI,CAAA;EACN,kBAAC,QAAD;GAAM,WAAU;GAAqC,UAAAC;EAAY,CAAA;EAChEC,KAAS,QACT,kBAAC,QAAD;GAAM,IAAIR;GAAS,WAAU;GAA7B,UAAA,CACE,KACAQ,CACI;;CAEN,EAAA,CAAA;CAEH,OACC,kBAAC,OAAD;EACC,WAAWC,EACVC,GACA,6BACAC,KAAY,oBACZC,CACD;EAEC,UAAAf,KAAWgB,IACX,kBAACC,GAAD;GACC,WAAU;GACV,OAAO,GAAGC,EAAY,GAAGR;GACzB,OAAOA;GACP,SAAA;GACA,QAAQM;GACG;GACE;GACH;GACV,kBAAkB,GAAM,MAAW;IAElC,AADA,EAAQ,UAAU,CAACG,KAAQC,MAAW,QACtCnB,EAAWkB,CAAI;GAChB;EACA,CAAA,IAED,kBAAC,OAAD;GAAK,WAAU;GAAf,UAAA;IACC,kBAACE,GAAD;KACC,SAAS,CAAC,CAACC;KACX,SAAQ;KACE;KACV,WAAU;KACV,gBAAcR,IAAW,SAAS,KAAA;KAClC,cAAYJ;KACZ,oBAAkBC,KAAS,OAAiB,KAAA,IAAVR;KAClC,SAASoB;KAER,UAAAD,IACA,kBAACE,GAAD;MAAY;MAAM,WAAU;MAC1B,UAAAhB;KACI,CAAA,IAENA;IAEM,CAAA;IACPQ,KACA,kBAACK,GAAD;KACC,KAAKhB;KACL,MAAK;KACL,SAAQ;KACE;KACV,cAAY,GAAGa,EAAY,GAAGR;KAC9B,eAAeT,EAAW,EAAI;KAE9B,UAAA,kBAACwB,GAAD,CAAS,CAAA;IACF,CAAA;IAERC,KAAW,kBAAC,OAAD;KAAK,WAAU;KAAoC,UAAAA;IAAa,CAAA;GACxE;;CAEF,CAAA;AAEP;AAIA,SAAgBC,EAAc,EAC7B,UAAO,kBAACC,GAAD,EAAQ,WAAU,SAAU,CAAA,GACnC,GAAGC,KACmB;CACtB,OAAO,kBAAC9B,GAAD;EAAuB;EAAM,GAAI8B;CAAQ,CAAA;AACjD"}
1
+ {"version":3,"file":"editable-nav-item.js","names":["_Fragment","Fragment$1","EditableNavItem","editing","setEditing","useState","countId","useId","rename","useRef","restore","content","icon","label","count","selected","disabled","cn","BASALT_UI_CLASS","className","onRename","InlineEditable","renameLabel","next","reason","Button","href","NAV_ROW_CLASS","FOCUS_INSET","onSelect","Link","Pencil","actions","FolderNavItem","Folder","props"],"sources":["../../src/components/editable-nav-item.tsx"],"sourcesContent":["import { Folder, Pencil } from \"lucide-react\";\nimport { type ReactNode, useId, useLayoutEffect, useRef, useState } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { NAV_ROW_CLASS } from \"../utils/navigation\";\nimport { Button } from \"./button\";\nimport { InlineEditable } from \"./inline-editable\";\nimport { Link } from \"./link\";\nimport { FOCUS_INSET } from \"./overlay\";\n\nexport interface EditableNavItemProps {\n\t/** Current display name. */\n\tlabel: string;\n\t/** Application route, interpreted by LinkProvider. */\n\thref?: string;\n\t/** Navigation/selection request. */\n\tonSelect?: () => void;\n\t/** Selected location. @default false */\n\tselected?: boolean;\n\t/** Caller-owned leading icon. */\n\ticon?: ReactNode;\n\t/** Caller-formatted count or status. */\n\tcount?: ReactNode;\n\t/** Separate row actions, never nested inside the navigation button/link. */\n\tactions?: ReactNode;\n\t/** Enable renaming; rejected promises keep the editor and draft available. */\n\tonRename?: (name: string) => void | Promise<void>;\n\t/** Disable navigation and renaming. Application action slots retain their own permissions. @default false */\n\tdisabled?: boolean;\n\t/** Rename action prefix. @default \"Rename\" */\n\trenameLabel?: string;\n\t/** Accessible save action. @default \"Save\" */\n\tsaveLabel?: string;\n\t/** Accessible cancel action. @default \"Cancel\" */\n\tcancelLabel?: string;\n\t/** Additional root classes. */\n\tclassName?: string;\n}\nexport function EditableNavItem({\n\tlabel,\n\thref,\n\tonSelect,\n\tselected = false,\n\ticon,\n\tcount,\n\tactions,\n\tonRename,\n\tdisabled = false,\n\trenameLabel = \"Rename\",\n\tsaveLabel = \"Save\",\n\tcancelLabel = \"Cancel\",\n\tclassName,\n}: EditableNavItemProps) {\n\tconst [editing, setEditing] = useState(false);\n\tconst countId = useId();\n\tconst rename = useRef<HTMLButtonElement>(null);\n\tconst restore = useRef(false);\n\tuseLayoutEffect(() => {\n\t\tif (!editing && restore.current) {\n\t\t\trestore.current = false;\n\t\t\trename.current?.focus();\n\t\t}\n\t}, [editing]);\n\tconst content = (\n\t\t<>\n\t\t\t{icon && (\n\t\t\t\t<span\n\t\t\t\t\tclassName=\"flex size-basalt-icon-lg shrink-0 items-center justify-center [&>svg]:size-basalt-icon-lg\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t>\n\t\t\t\t\t{icon}\n\t\t\t\t</span>\n\t\t\t)}\n\t\t\t<span className=\"min-w-0 flex-1 truncate text-left\">{label}</span>\n\t\t\t{count != null && (\n\t\t\t\t<span\n\t\t\t\t\tid={countId}\n\t\t\t\t\tclassName=\"shrink-0 text-basalt-sm tabular-nums text-basalt-muted-foreground\"\n\t\t\t\t>\n\t\t\t\t\t{\" \"}\n\t\t\t\t\t{count}\n\t\t\t\t</span>\n\t\t\t)}\n\t\t</>\n\t);\n\treturn (\n\t\t<div\n\t\t\tdata-basalt-hover-item={editing ? undefined : \"\"}\n\t\t\tdata-hover-selected={selected && !editing}\n\t\t\tdata-disabled={disabled ? \"\" : undefined}\n\t\t\tclassName={cn(\n\t\t\t\tBASALT_UI_CLASS,\n\t\t\t\t\"basalt-nav-item min-w-0 shrink-0 rounded-basalt-md data-disabled:cursor-default data-disabled:hover:bg-transparent\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t{editing && onRename ? (\n\t\t\t\t<InlineEditable\n\t\t\t\t\tclassName=\"p-basalt-space-lg\"\n\t\t\t\t\tlabel={`${renameLabel} ${label}`}\n\t\t\t\t\tvalue={label}\n\t\t\t\t\tediting\n\t\t\t\t\tonSave={onRename}\n\t\t\t\t\tsaveLabel={saveLabel}\n\t\t\t\t\tcancelLabel={cancelLabel}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tonEditingChange={(next, reason) => {\n\t\t\t\t\t\trestore.current = !next && reason !== \"blur\";\n\t\t\t\t\t\tsetEditing(next);\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t) : (\n\t\t\t\t<div className=\"flex min-w-0 items-center gap-basalt-nav-gap\">\n\t\t\t\t\t<Button\n\t\t\t\t\t\tasChild={!!href}\n\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\tNAV_ROW_CLASS,\n\t\t\t\t\t\t\tFOCUS_INSET,\n\t\t\t\t\t\t\t\"h-auto flex-1 justify-start hover:bg-transparent hover:border-transparent focus-visible:ring-offset-0\",\n\t\t\t\t\t\t)}\n\t\t\t\t\t\taria-current={selected ? \"page\" : undefined}\n\t\t\t\t\t\taria-label={label}\n\t\t\t\t\t\taria-describedby={count != null ? countId : undefined}\n\t\t\t\t\t\tonClick={onSelect}\n\t\t\t\t\t>\n\t\t\t\t\t\t{href ? (\n\t\t\t\t\t\t\t<Link href={href} className=\"text-inherit no-underline hover:no-underline\">\n\t\t\t\t\t\t\t\t{content}\n\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\tcontent\n\t\t\t\t\t\t)}\n\t\t\t\t\t</Button>\n\t\t\t\t\t{onRename && (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tref={rename}\n\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\taria-label={`${renameLabel} ${label}`}\n\t\t\t\t\t\t\tonClick={() => setEditing(true)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Pencil />\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\t\t\t\t\t{actions && (\n\t\t\t\t\t\t<div className=\"flex shrink-0 items-center gap-basalt-space-sm\">{actions}</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nexport type FolderNavItemProps = EditableNavItemProps;\n/** Folder presentation with an overridable icon; no tree, router or permission model. */\nexport function FolderNavItem({\n\ticon = <Folder className=\"size-basalt-icon-lg\" />,\n\t...props\n}: FolderNavItemProps) {\n\treturn <EditableNavItem icon={icon} {...props} />;\n}\n"],"mappings":";;;;;;;;;;;;AAsCA,SAAgBE,EAAgB,EAC/B,UACA,SACA,aACA,cAAW,IACX,SACA,UACA,YACA,aACA,cAAW,IACX,iBAAc,UACd,eAAY,QACZ,iBAAc,UACd,gBACwB;CACxB,IAAM,CAACC,GAASC,KAAcC,EAAS,EAAK,GACtCC,IAAUC,EAAM,GAChBC,IAASC,EAA0B,IAAI,GACvCC,IAAUD,EAAO,EAAK;CAC5B,QAAsB;EACrB,AAAI,CAACN,KAAWO,EAAQ,YACvB,EAAQ,UAAU,IAClBF,EAAO,SAAS,MAAM;CAExB,GAAG,CAACL,CAAO,CAAC;CACZ,IAAMQ,IACL,kBAAAX,GAAA,EAAA,UAAA;EACEY,KACA,kBAAC,QAAD;GACC,WAAU;GACV,eAAY;GAEX,UAAAA;EACI,CAAA;EAEP,kBAAC,QAAD;GAAM,WAAU;GAAqC,UAAAC;EAAY,CAAA;EAChEC,KAAS,QACT,kBAAC,QAAD;GACC,IAAIR;GACJ,WAAU;GAFX,UAAA,CAIE,KACAQ,CACI;;CAEN,EAAA,CAAA;CAEH,OACC,kBAAC,OAAD;EACC,0BAAwBX,IAAU,KAAA,IAAY;EAC9C,uBAAqBY,KAAY,CAACZ;EAClC,iBAAea,IAAW,KAAK,KAAA;EAC/B,WAAWC,EACVC,GACA,sHACAC,CACD;EAEC,UAAAhB,KAAWiB,IACX,kBAACC,GAAD;GACC,WAAU;GACV,OAAO,GAAGC,EAAY,GAAGT;GACzB,OAAOA;GACP,SAAA;GACA,QAAQO;GACG;GACE;GACH;GACV,kBAAkB,GAAM,MAAW;IAElC,AADA,EAAQ,UAAU,CAACG,KAAQC,MAAW,QACtCpB,EAAWmB,CAAI;GAChB;EACA,CAAA,IAED,kBAAC,OAAD;GAAK,WAAU;GAAf,UAAA;IACC,kBAACE,GAAD;KACC,SAAS,CAAC,CAACC;KACX,SAAQ;KACE;KACV,WAAWT,EACVU,GACAC,GACA,uGACD;KACA,gBAAcb,IAAW,SAAS,KAAA;KAClC,cAAYF;KACZ,oBAAkBC,KAAS,OAAiB,KAAA,IAAVR;KAClC,SAASuB;KAER,UAAAH,IACA,kBAACI,GAAD;MAAY;MAAM,WAAU;MAC1B,UAAAnB;KACI,CAAA,IAENA;IAEM,CAAA;IACPS,KACA,kBAACK,GAAD;KACC,KAAKjB;KACL,MAAK;KACL,SAAQ;KACE;KACV,cAAY,GAAGc,EAAY,GAAGT;KAC9B,eAAeT,EAAW,EAAI;KAE9B,UAAA,kBAAC2B,GAAD,CAAS,CAAA;IACF,CAAA;IAERC,KACA,kBAAC,OAAD;KAAK,WAAU;KAAkD,UAAAA;IAAa,CAAA;GAE3E;;CAEF,CAAA;AAEP;AAIA,SAAgBC,EAAc,EAC7B,UAAO,kBAACC,GAAD,EAAQ,WAAU,sBAAuB,CAAA,GAChD,GAAGC,KACmB;CACtB,OAAO,kBAACjC,GAAD;EAAuB;EAAM,GAAIiC;CAAQ,CAAA;AACjD"}
@@ -5,27 +5,27 @@ import { jsx as n, jsxs as r } from "react/jsx-runtime";
5
5
  //#region src/components/empty.tsx
6
6
  function i({ title: i = "No results", description: a, icon: o, action: s, children: c, className: l, ...u }) {
7
7
  return /* @__PURE__ */ r("div", {
8
- className: e(t, "flex flex-col items-center gap-2 text-center", l),
8
+ className: e(t, "flex flex-col items-center gap-basalt-space-lg text-center", l),
9
9
  ...u,
10
10
  children: [
11
11
  o ? /* @__PURE__ */ n("div", {
12
- className: "text-basalt-muted-foreground [&_svg]:size-8",
12
+ className: "text-basalt-muted-foreground [&_svg]:size-basalt-8",
13
13
  children: o
14
14
  }) : null,
15
15
  /* @__PURE__ */ n("p", {
16
- className: "text-sm font-medium text-basalt-foreground",
16
+ className: "text-basalt-base font-medium text-basalt-foreground",
17
17
  children: i
18
18
  }),
19
19
  a ? /* @__PURE__ */ n("p", {
20
- className: "text-xs text-basalt-muted-foreground",
20
+ className: "text-basalt-sm text-basalt-muted-foreground",
21
21
  children: a
22
22
  }) : null,
23
23
  c == null ? null : /* @__PURE__ */ n("div", {
24
- className: "text-xs text-basalt-muted-foreground",
24
+ className: "text-basalt-sm text-basalt-muted-foreground",
25
25
  children: c
26
26
  }),
27
27
  s == null ? null : /* @__PURE__ */ n("div", {
28
- className: "mt-2 flex items-center justify-center gap-2",
28
+ className: "mt-basalt-space-lg flex items-center justify-center gap-basalt-space-lg",
29
29
  children: s
30
30
  })
31
31
  ]
@@ -1 +1 @@
1
- {"version":3,"file":"empty.js","names":["Empty","props","cn","BASALT_UI_CLASS","className","icon","title","description","children","action"],"sources":["../../src/components/empty.tsx"],"sourcesContent":["import type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\n\nexport interface EmptyProps extends Omit<HTMLAttributes<HTMLDivElement>, \"title\" | \"children\"> {\n\t/**\n\t * Primary title text displayed in the empty state.\n\t *\n\t * @default \"No results\"\n\t */\n\ttitle?: string;\n\n\t/**\n\t * Secondary supporting description text rendered below the title.\n\t */\n\tdescription?: string;\n\n\t/**\n\t * Visual icon element rendered above the title.\n\t */\n\ticon?: ReactNode;\n\n\t/**\n\t * Interactive call-to-action element (e.g. Button or Link) rendered below content.\n\t */\n\taction?: ReactNode;\n\n\t/**\n\t * Custom supporting content or custom layout rendered between description and action.\n\t */\n\tchildren?: ReactNode;\n}\n\nexport function Empty({\n\ttitle = \"No results\",\n\tdescription,\n\ticon,\n\taction,\n\tchildren,\n\tclassName,\n\t...props\n}: EmptyProps) {\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(BASALT_UI_CLASS, \"flex flex-col items-center gap-2 text-center\", className)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{icon ? <div className=\"text-basalt-muted-foreground [&_svg]:size-8\">{icon}</div> : null}\n\t\t\t<p className=\"text-sm font-medium text-basalt-foreground\">{title}</p>\n\t\t\t{description ? <p className=\"text-xs text-basalt-muted-foreground\">{description}</p> : null}\n\t\t\t{children !== undefined && children !== null ? (\n\t\t\t\t<div className=\"text-xs text-basalt-muted-foreground\">{children}</div>\n\t\t\t) : null}\n\t\t\t{action !== undefined && action !== null ? (\n\t\t\t\t<div className=\"mt-2 flex items-center justify-center gap-2\">{action}</div>\n\t\t\t) : null}\n\t\t</div>\n\t);\n}\n"],"mappings":";;;;;AAiCA,SAAgBA,EAAM,EACrB,WAAQ,cACR,gBACA,SACA,WACA,aACA,cACA,GAAGC,KACW;CACd,OACC,kBAAC,OAAD;EACC,WAAWC,EAAGC,GAAiB,gDAAgDC,CAAS;EACxF,GAAIH;EAFL,UAAA;GAIEI,IAAO,kBAAC,OAAD;IAAK,WAAU;IAA+C,UAAAA;GAAU,CAAA,IAAI;GACpF,kBAAC,KAAD;IAAG,WAAU;IAA8C,UAAAC;GAAS,CAAA;GACnEC,IAAc,kBAAC,KAAD;IAAG,WAAU;IAAwC,UAAAA;GAAe,CAAA,IAAI;GACtFC,KAAuC,OAEpC,OADH,kBAAC,OAAD;IAAK,WAAU;IAAwC;GAAc,CAAA;GAErEC,KAAmC,OAEhC,OADH,kBAAC,OAAD;IAAK,WAAU;IAA+C,UAAAA;GAAY,CAAA;EAEvE;;AAEP"}
1
+ {"version":3,"file":"empty.js","names":["Empty","props","cn","BASALT_UI_CLASS","className","icon","title","description","children","action"],"sources":["../../src/components/empty.tsx"],"sourcesContent":["import type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\n\nexport interface EmptyProps extends Omit<HTMLAttributes<HTMLDivElement>, \"title\" | \"children\"> {\n\t/**\n\t * Primary title text displayed in the empty state.\n\t *\n\t * @default \"No results\"\n\t */\n\ttitle?: string;\n\n\t/**\n\t * Secondary supporting description text rendered below the title.\n\t */\n\tdescription?: string;\n\n\t/**\n\t * Visual icon element rendered above the title.\n\t */\n\ticon?: ReactNode;\n\n\t/**\n\t * Interactive call-to-action element (e.g. Button or Link) rendered below content.\n\t */\n\taction?: ReactNode;\n\n\t/**\n\t * Custom supporting content or custom layout rendered between description and action.\n\t */\n\tchildren?: ReactNode;\n}\n\nexport function Empty({\n\ttitle = \"No results\",\n\tdescription,\n\ticon,\n\taction,\n\tchildren,\n\tclassName,\n\t...props\n}: EmptyProps) {\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\tBASALT_UI_CLASS,\n\t\t\t\t\"flex flex-col items-center gap-basalt-space-lg text-center\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{icon ? (\n\t\t\t\t<div className=\"text-basalt-muted-foreground [&_svg]:size-basalt-8\">{icon}</div>\n\t\t\t) : null}\n\t\t\t<p className=\"text-basalt-base font-medium text-basalt-foreground\">{title}</p>\n\t\t\t{description ? (\n\t\t\t\t<p className=\"text-basalt-sm text-basalt-muted-foreground\">{description}</p>\n\t\t\t) : null}\n\t\t\t{children !== undefined && children !== null ? (\n\t\t\t\t<div className=\"text-basalt-sm text-basalt-muted-foreground\">{children}</div>\n\t\t\t) : null}\n\t\t\t{action !== undefined && action !== null ? (\n\t\t\t\t<div className=\"mt-basalt-space-lg flex items-center justify-center gap-basalt-space-lg\">\n\t\t\t\t\t{action}\n\t\t\t\t</div>\n\t\t\t) : null}\n\t\t</div>\n\t);\n}\n"],"mappings":";;;;;AAiCA,SAAgBA,EAAM,EACrB,WAAQ,cACR,gBACA,SACA,WACA,aACA,cACA,GAAGC,KACW;CACd,OACC,kBAAC,OAAD;EACC,WAAWC,EACVC,GACA,8DACAC,CACD;EACA,GAAIH;EANL,UAAA;GAQEI,IACA,kBAAC,OAAD;IAAK,WAAU;IAAsD,UAAAA;GAAU,CAAA,IAC5E;GACJ,kBAAC,KAAD;IAAG,WAAU;IAAuD,UAAAC;GAAS,CAAA;GAC5EC,IACA,kBAAC,KAAD;IAAG,WAAU;IAA+C,UAAAA;GAAe,CAAA,IACxE;GACHC,KAAuC,OAEpC,OADH,kBAAC,OAAD;IAAK,WAAU;IAA+C;GAAc,CAAA;GAE5EC,KAAmC,OAIhC,OAHH,kBAAC,OAAD;IAAK,WAAU;IACb,UAAAA;GACG,CAAA;EAEF;;AAEP"}
@@ -15,7 +15,7 @@ var o = i.forwardRef(({ open: i = !1, placement: o = "fixed", className: s, chil
15
15
  inert: i || void 0,
16
16
  disabled: d,
17
17
  onClick: i ? void 0 : l,
18
- className: e(o === "absolute" ? "absolute" : "fixed", "right-4 bottom-4 h-16 w-16 rounded-full shadow-lg", t, "transition-[transform,opacity] duration-300 ease-in-out", n, i ? "pointer-events-none scale-75 opacity-0" : "hover:scale-[1.03] active:scale-[0.98]", s),
18
+ className: e(o === "absolute" ? "absolute" : "fixed", "right-basalt-4 bottom-basalt-4 h-basalt-16 w-basalt-16 rounded-basalt-full shadow-lg", t, "transition-[transform,opacity] basalt-motion duration-basalt-normal ease-basalt", n, i ? "pointer-events-none scale-75 opacity-0" : "hover:scale-[1.03] active:scale-[0.98]", s),
19
19
  children: c
20
20
  }));
21
21
  o.displayName = "Fab";
@@ -1 +1 @@
1
- {"version":3,"file":"fab.js","names":["React","Fab","ariaLabel","Button","open","onClick","cn","placement","OVERLAY_LAYER","OVERLAY_MOTION","className"],"sources":["../../src/components/fab.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { Button } from \"./button\";\nimport { OVERLAY_LAYER, OVERLAY_MOTION } from \"./overlay\";\n\nexport type FabPlacement = \"absolute\" | \"fixed\";\n\nexport interface FabProps {\n\t/**\n\t * When true, the launcher hides so a dock can take the corner.\n\t * @default false\n\t */\n\topen?: boolean;\n\t/**\n\t * Viewport pin versus containing frame.\n\t * @default \"fixed\"\n\t */\n\tplacement?: FabPlacement;\n\t/**\n\t * Accessible name.\n\t */\n\t\"aria-label\": string;\n\tonClick?: React.MouseEventHandler<HTMLButtonElement>;\n\tchildren?: React.ReactNode;\n\tclassName?: string;\n\tdisabled?: boolean;\n}\n\nexport const Fab = React.forwardRef<HTMLButtonElement, FabProps>(\n\t(\n\t\t{\n\t\t\topen = false,\n\t\t\tplacement = \"fixed\",\n\t\t\tclassName,\n\t\t\tchildren,\n\t\t\tonClick,\n\t\t\t\"aria-label\": ariaLabel,\n\t\t\tdisabled,\n\t\t},\n\t\tref,\n\t) => (\n\t\t<Button\n\t\t\tref={ref}\n\t\t\tsize=\"icon\"\n\t\t\taria-label={ariaLabel}\n\t\t\taria-expanded={open}\n\t\t\taria-hidden={open || undefined}\n\t\t\ttabIndex={open ? -1 : 0}\n\t\t\tinert={open || undefined}\n\t\t\tdisabled={disabled}\n\t\t\tonClick={open ? undefined : onClick}\n\t\t\tclassName={cn(\n\t\t\t\tplacement === \"absolute\" ? \"absolute\" : \"fixed\",\n\t\t\t\t\"right-4 bottom-4 h-16 w-16 rounded-full shadow-lg\",\n\t\t\t\tOVERLAY_LAYER,\n\t\t\t\t\"transition-[transform,opacity] duration-300 ease-in-out\",\n\t\t\t\tOVERLAY_MOTION,\n\t\t\t\topen ? \"pointer-events-none scale-75 opacity-0\" : \"hover:scale-[1.03] active:scale-[0.98]\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t{children}\n\t\t</Button>\n\t),\n);\nFab.displayName = \"Fab\";\n"],"mappings":";;;;;;;AA4BA,IAAaC,IAAMD,EAAM,YAEvB,EACC,UAAO,IACP,eAAY,SACZ,cACA,aACA,YACA,cAAcE,GACd,eAED,MAEA,kBAACC,GAAD;CACM;CACL,MAAK;CACL,cAAYD;CACZ,iBAAeE;CACf,eAAaA,KAAQ,KAAA;CACrB,UAAUA,IAAO,KAAK;CACtB,OAAOA,KAAQ,KAAA;CACL;CACV,SAASA,IAAO,KAAA,IAAYC;CAC5B,WAAWC,EACVC,MAAc,aAAa,aAAa,SACxC,qDACAC,GACA,2DACAC,GACAL,IAAO,2CAA2C,0CAClDM,CACD;CAEC;AACM,CAAA,CAEV;AACA,EAAI,cAAc"}
1
+ {"version":3,"file":"fab.js","names":["React","Fab","ariaLabel","Button","open","onClick","cn","placement","OVERLAY_LAYER","OVERLAY_MOTION","className"],"sources":["../../src/components/fab.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { Button } from \"./button\";\nimport { OVERLAY_LAYER, OVERLAY_MOTION } from \"./overlay\";\n\nexport type FabPlacement = \"absolute\" | \"fixed\";\n\nexport interface FabProps {\n\t/**\n\t * When true, the launcher hides so a dock can take the corner.\n\t * @default false\n\t */\n\topen?: boolean;\n\t/**\n\t * Viewport pin versus containing frame.\n\t * @default \"fixed\"\n\t */\n\tplacement?: FabPlacement;\n\t/**\n\t * Accessible name.\n\t */\n\t\"aria-label\": string;\n\tonClick?: React.MouseEventHandler<HTMLButtonElement>;\n\tchildren?: React.ReactNode;\n\tclassName?: string;\n\tdisabled?: boolean;\n}\n\nexport const Fab = React.forwardRef<HTMLButtonElement, FabProps>(\n\t(\n\t\t{\n\t\t\topen = false,\n\t\t\tplacement = \"fixed\",\n\t\t\tclassName,\n\t\t\tchildren,\n\t\t\tonClick,\n\t\t\t\"aria-label\": ariaLabel,\n\t\t\tdisabled,\n\t\t},\n\t\tref,\n\t) => (\n\t\t<Button\n\t\t\tref={ref}\n\t\t\tsize=\"icon\"\n\t\t\taria-label={ariaLabel}\n\t\t\taria-expanded={open}\n\t\t\taria-hidden={open || undefined}\n\t\t\ttabIndex={open ? -1 : 0}\n\t\t\tinert={open || undefined}\n\t\t\tdisabled={disabled}\n\t\t\tonClick={open ? undefined : onClick}\n\t\t\tclassName={cn(\n\t\t\t\tplacement === \"absolute\" ? \"absolute\" : \"fixed\",\n\t\t\t\t\"right-basalt-4 bottom-basalt-4 h-basalt-16 w-basalt-16 rounded-basalt-full shadow-lg\",\n\t\t\t\tOVERLAY_LAYER,\n\t\t\t\t\"transition-[transform,opacity] basalt-motion duration-basalt-normal ease-basalt\",\n\t\t\t\tOVERLAY_MOTION,\n\t\t\t\topen ? \"pointer-events-none scale-75 opacity-0\" : \"hover:scale-[1.03] active:scale-[0.98]\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t{children}\n\t\t</Button>\n\t),\n);\nFab.displayName = \"Fab\";\n"],"mappings":";;;;;;;AA4BA,IAAaC,IAAMD,EAAM,YAEvB,EACC,UAAO,IACP,eAAY,SACZ,cACA,aACA,YACA,cAAcE,GACd,eAED,MAEA,kBAACC,GAAD;CACM;CACL,MAAK;CACL,cAAYD;CACZ,iBAAeE;CACf,eAAaA,KAAQ,KAAA;CACrB,UAAUA,IAAO,KAAK;CACtB,OAAOA,KAAQ,KAAA;CACL;CACV,SAASA,IAAO,KAAA,IAAYC;CAC5B,WAAWC,EACVC,MAAc,aAAa,aAAa,SACxC,wFACAC,GACA,mFACAC,GACAL,IAAO,2CAA2C,0CAClDM,CACD;CAEC;AACM,CAAA,CAEV;AACA,EAAI,cAAc"}
@@ -16,7 +16,7 @@ var c = r.forwardRef(({ label: o, htmlFor: c, hint: l, error: u, required: d, la
16
16
  return /* @__PURE__ */ a("div", {
17
17
  ref: g,
18
18
  ...h,
19
- className: e(t, "flex flex-col gap-1.5", p),
19
+ className: e(t, "flex flex-col gap-basalt-field-gap", p),
20
20
  children: [
21
21
  /* @__PURE__ */ i(n, {
22
22
  htmlFor: y,
@@ -31,12 +31,12 @@ var c = r.forwardRef(({ label: o, htmlFor: c, hint: l, error: u, required: d, la
31
31
  }) : m,
32
32
  l && !C ? /* @__PURE__ */ i("p", {
33
33
  id: b,
34
- className: "text-xs text-basalt-muted-foreground",
34
+ className: "text-basalt-sm text-basalt-muted-foreground",
35
35
  children: l
36
36
  }) : null,
37
37
  C ? /* @__PURE__ */ i("p", {
38
38
  id: x,
39
- className: "text-xs text-basalt-destructive",
39
+ className: "text-basalt-sm text-basalt-destructive",
40
40
  role: "alert",
41
41
  children: S
42
42
  }) : null
@@ -1 +1 @@
1
- {"version":3,"file":"field.js","names":["React","isStructuredError","error","fieldErrorMessage","Field","props","generatedId","child","children","controlId","htmlFor","hintId","errorId","errorMessage","hasError","mergedDescribedBy","hint","cn","BASALT_UI_CLASS","className","Label","required","labelTooltip","label"],"sources":["../../src/components/field.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { Label } from \"./label\";\n\nexport type FieldError = Exclude<React.ReactNode, undefined> | { message: React.ReactNode };\n\ntype FieldControlProps = {\n\tid?: string;\n\t\"aria-describedby\"?: string;\n\t\"aria-invalid\"?: boolean | \"true\" | \"false\";\n};\n\nexport interface FieldProps\n\textends Omit<React.ComponentPropsWithoutRef<\"div\">, \"children\" | \"className\"> {\n\t/**\n\t * Visible label.\n\t */\n\tlabel: React.ReactNode;\n\t/**\n\t * Associates the label and described-by ids.\n\t */\n\thtmlFor?: string;\n\t/**\n\t * Supporting text when there is no error.\n\t */\n\thint?: React.ReactNode;\n\t/**\n\t * Replaces the hint and marks the control invalid.\n\t */\n\terror?: FieldError;\n\t/**\n\t * When false, show (optional) after the label.\n\t */\n\trequired?: boolean;\n\t/**\n\t * Info icon with hover text on the label.\n\t */\n\tlabelTooltip?: React.ReactNode;\n\t/**\n\t * Additional classes for the field root.\n\t */\n\tclassName?: string;\n\t/**\n\t * The control or content to render.\n\t */\n\tchildren: React.ReactNode;\n}\n\nfunction isStructuredError(error: FieldError): error is { message: React.ReactNode } {\n\treturn (\n\t\ttypeof error === \"object\" &&\n\t\terror !== null &&\n\t\t!Array.isArray(error) &&\n\t\t!React.isValidElement(error) &&\n\t\t\"message\" in error\n\t);\n}\n\nfunction fieldErrorMessage(error: FieldError | undefined): React.ReactNode | undefined {\n\tif (error == null) {\n\t\treturn undefined;\n\t}\n\treturn isStructuredError(error) ? error.message : error;\n}\n\nexport const Field = React.forwardRef<HTMLDivElement, FieldProps>(\n\t({ label, htmlFor, hint, error, required, labelTooltip, className, children, ...props }, ref) => {\n\t\tconst generatedId = React.useId();\n\t\tconst child = React.isValidElement(children)\n\t\t\t? (children as React.ReactElement<FieldControlProps>)\n\t\t\t: null;\n\t\tconst controlId = child ? (htmlFor ?? child.props.id ?? generatedId) : htmlFor;\n\t\tconst hintId = controlId ? `${controlId}-hint` : undefined;\n\t\tconst errorId = controlId ? `${controlId}-error` : undefined;\n\t\tconst errorMessage = fieldErrorMessage(error);\n\t\tconst hasError = Boolean(errorMessage);\n\t\tconst describedBy = [hasError ? errorId : null, !hasError && hint ? hintId : null]\n\t\t\t.filter(Boolean)\n\t\t\t.join(\" \");\n\t\tconst mergedDescribedBy = [describedBy, child?.props[\"aria-describedby\"]]\n\t\t\t.filter(Boolean)\n\t\t\t.join(\" \");\n\t\treturn (\n\t\t\t<div ref={ref} {...props} className={cn(BASALT_UI_CLASS, \"flex flex-col gap-1.5\", className)}>\n\t\t\t\t<Label htmlFor={controlId} showOptional={required === false} tooltip={labelTooltip}>\n\t\t\t\t\t{label}\n\t\t\t\t</Label>\n\t\t\t\t{child\n\t\t\t\t\t? React.cloneElement(child, {\n\t\t\t\t\t\t\tid: controlId,\n\t\t\t\t\t\t\t\"aria-invalid\": hasError ? true : child.props[\"aria-invalid\"],\n\t\t\t\t\t\t\t\"aria-describedby\": mergedDescribedBy || undefined,\n\t\t\t\t\t\t})\n\t\t\t\t\t: children}\n\t\t\t\t{hint && !hasError ? (\n\t\t\t\t\t<p id={hintId} className=\"text-xs text-basalt-muted-foreground\">\n\t\t\t\t\t\t{hint}\n\t\t\t\t\t</p>\n\t\t\t\t) : null}\n\t\t\t\t{hasError ? (\n\t\t\t\t\t<p id={errorId} className=\"text-xs text-basalt-destructive\" role=\"alert\">\n\t\t\t\t\t\t{errorMessage}\n\t\t\t\t\t</p>\n\t\t\t\t) : null}\n\t\t\t</div>\n\t\t);\n\t},\n);\nField.displayName = \"Field\";\n"],"mappings":";;;;;;;AAiDA,SAASC,EAAkB,GAA0D;CACpF,OACC,OAAOC,KAAU,cACjBA,KACA,CAAC,MAAM,QAAQA,CAAK,KACpB,CAACF,EAAM,eAAeE,CAAK,KAC3B,aAAaA;AAEf;AAEA,SAASC,EAAkB,GAA4D;CACtF,IAAID,KAAS,MAGb,OAAOD,EAAkBC,CAAK,IAAIA,EAAM,UAAUA;AACnD;AAEA,IAAaE,IAAQJ,EAAM,YACzB,EAAE,UAAO,YAAS,SAAM,UAAO,aAAU,iBAAc,cAAW,aAAU,GAAGK,KAAS,MAAQ;CAChG,IAAMC,IAAcN,EAAM,MAAM,GAC1BO,IAAQP,EAAM,eAAeQ,CAAQ,IACvCA,IACD,MACGC,IAAYF,IAASG,KAAWH,EAAM,MAAM,MAAMD,IAAeI,GACjEC,IAASF,IAAY,GAAGA,EAAU,SAAS,KAAA,GAC3CG,IAAUH,IAAY,GAAGA,EAAU,UAAU,KAAA,GAC7CI,IAAeV,EAAkBD,CAAK,GACtCY,IAAW,EAAQD,GAInBE,IAAoB,CAHN,CAACD,IAAWF,IAAU,MAAM,CAACE,KAAYE,IAAOL,IAAS,IAAI,CAAC,CAChF,OAAO,OAAO,CAAC,CACf,KAAK,GACoB,GAAaJ,GAAO,MAAM,mBAAmB,CAAC,CACvE,OAAO,OAAO,CAAC,CACf,KAAK,GAAG;CACV,OACC,kBAAC,OAAD;EAAU;EAAK,GAAIF;EAAO,WAAWY,EAAGC,GAAiB,yBAAyBC,CAAS;EAA3F,UAAA;GACC,kBAACC,GAAD;IAAO,SAASX;IAAW,cAAcY,MAAa;IAAO,SAASC;IACpE,UAAAC;GACK,CAAA;GACNhB,IACEP,EAAM,aAAaO,GAAO;IAC1B,IAAIE;IACJ,gBAAgBK,IAAW,KAAOP,EAAM,MAAM;IAC9C,oBAAoBQ,KAAqB,KAAA;GAC1C,CAAC,IACAP;GACFQ,KAAQ,CAACF,IACT,kBAAC,KAAD;IAAG,IAAIH;IAAQ,WAAU;IACvB,UAAAK;GACC,CAAA,IACA;GACHF,IACA,kBAAC,KAAD;IAAG,IAAIF;IAAS,WAAU;IAAkC,MAAK;IAC/D,UAAAC;GACC,CAAA,IACA;EACA;;AAEP,CACD;AACA,EAAM,cAAc"}
1
+ {"version":3,"file":"field.js","names":["React","isStructuredError","error","fieldErrorMessage","Field","props","generatedId","child","children","controlId","htmlFor","hintId","errorId","errorMessage","hasError","mergedDescribedBy","hint","cn","BASALT_UI_CLASS","className","Label","required","labelTooltip","label"],"sources":["../../src/components/field.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { Label } from \"./label\";\n\nexport type FieldError = Exclude<React.ReactNode, undefined> | { message: React.ReactNode };\n\ntype FieldControlProps = {\n\tid?: string;\n\t\"aria-describedby\"?: string;\n\t\"aria-invalid\"?: boolean | \"true\" | \"false\";\n};\n\nexport interface FieldProps\n\textends Omit<React.ComponentPropsWithoutRef<\"div\">, \"children\" | \"className\"> {\n\t/**\n\t * Visible label.\n\t */\n\tlabel: React.ReactNode;\n\t/**\n\t * Associates the label and described-by ids.\n\t */\n\thtmlFor?: string;\n\t/**\n\t * Supporting text when there is no error.\n\t */\n\thint?: React.ReactNode;\n\t/**\n\t * Replaces the hint and marks the control invalid.\n\t */\n\terror?: FieldError;\n\t/**\n\t * When false, show (optional) after the label.\n\t */\n\trequired?: boolean;\n\t/**\n\t * Info icon with hover text on the label.\n\t */\n\tlabelTooltip?: React.ReactNode;\n\t/**\n\t * Additional classes for the field root.\n\t */\n\tclassName?: string;\n\t/**\n\t * The control or content to render.\n\t */\n\tchildren: React.ReactNode;\n}\n\nfunction isStructuredError(error: FieldError): error is { message: React.ReactNode } {\n\treturn (\n\t\ttypeof error === \"object\" &&\n\t\terror !== null &&\n\t\t!Array.isArray(error) &&\n\t\t!React.isValidElement(error) &&\n\t\t\"message\" in error\n\t);\n}\n\nfunction fieldErrorMessage(error: FieldError | undefined): React.ReactNode | undefined {\n\tif (error == null) {\n\t\treturn undefined;\n\t}\n\treturn isStructuredError(error) ? error.message : error;\n}\n\nexport const Field = React.forwardRef<HTMLDivElement, FieldProps>(\n\t({ label, htmlFor, hint, error, required, labelTooltip, className, children, ...props }, ref) => {\n\t\tconst generatedId = React.useId();\n\t\tconst child = React.isValidElement(children)\n\t\t\t? (children as React.ReactElement<FieldControlProps>)\n\t\t\t: null;\n\t\tconst controlId = child ? (htmlFor ?? child.props.id ?? generatedId) : htmlFor;\n\t\tconst hintId = controlId ? `${controlId}-hint` : undefined;\n\t\tconst errorId = controlId ? `${controlId}-error` : undefined;\n\t\tconst errorMessage = fieldErrorMessage(error);\n\t\tconst hasError = Boolean(errorMessage);\n\t\tconst describedBy = [hasError ? errorId : null, !hasError && hint ? hintId : null]\n\t\t\t.filter(Boolean)\n\t\t\t.join(\" \");\n\t\tconst mergedDescribedBy = [describedBy, child?.props[\"aria-describedby\"]]\n\t\t\t.filter(Boolean)\n\t\t\t.join(\" \");\n\t\treturn (\n\t\t\t<div\n\t\t\t\tref={ref}\n\t\t\t\t{...props}\n\t\t\t\tclassName={cn(BASALT_UI_CLASS, \"flex flex-col gap-basalt-field-gap\", className)}\n\t\t\t>\n\t\t\t\t<Label htmlFor={controlId} showOptional={required === false} tooltip={labelTooltip}>\n\t\t\t\t\t{label}\n\t\t\t\t</Label>\n\t\t\t\t{child\n\t\t\t\t\t? React.cloneElement(child, {\n\t\t\t\t\t\t\tid: controlId,\n\t\t\t\t\t\t\t\"aria-invalid\": hasError ? true : child.props[\"aria-invalid\"],\n\t\t\t\t\t\t\t\"aria-describedby\": mergedDescribedBy || undefined,\n\t\t\t\t\t\t})\n\t\t\t\t\t: children}\n\t\t\t\t{hint && !hasError ? (\n\t\t\t\t\t<p id={hintId} className=\"text-basalt-sm text-basalt-muted-foreground\">\n\t\t\t\t\t\t{hint}\n\t\t\t\t\t</p>\n\t\t\t\t) : null}\n\t\t\t\t{hasError ? (\n\t\t\t\t\t<p id={errorId} className=\"text-basalt-sm text-basalt-destructive\" role=\"alert\">\n\t\t\t\t\t\t{errorMessage}\n\t\t\t\t\t</p>\n\t\t\t\t) : null}\n\t\t\t</div>\n\t\t);\n\t},\n);\nField.displayName = \"Field\";\n"],"mappings":";;;;;;;AAiDA,SAASC,EAAkB,GAA0D;CACpF,OACC,OAAOC,KAAU,cACjBA,KACA,CAAC,MAAM,QAAQA,CAAK,KACpB,CAACF,EAAM,eAAeE,CAAK,KAC3B,aAAaA;AAEf;AAEA,SAASC,EAAkB,GAA4D;CACtF,IAAID,KAAS,MAGb,OAAOD,EAAkBC,CAAK,IAAIA,EAAM,UAAUA;AACnD;AAEA,IAAaE,IAAQJ,EAAM,YACzB,EAAE,UAAO,YAAS,SAAM,UAAO,aAAU,iBAAc,cAAW,aAAU,GAAGK,KAAS,MAAQ;CAChG,IAAMC,IAAcN,EAAM,MAAM,GAC1BO,IAAQP,EAAM,eAAeQ,CAAQ,IACvCA,IACD,MACGC,IAAYF,IAASG,KAAWH,EAAM,MAAM,MAAMD,IAAeI,GACjEC,IAASF,IAAY,GAAGA,EAAU,SAAS,KAAA,GAC3CG,IAAUH,IAAY,GAAGA,EAAU,UAAU,KAAA,GAC7CI,IAAeV,EAAkBD,CAAK,GACtCY,IAAW,EAAQD,GAInBE,IAAoB,CAHN,CAACD,IAAWF,IAAU,MAAM,CAACE,KAAYE,IAAOL,IAAS,IAAI,CAAC,CAChF,OAAO,OAAO,CAAC,CACf,KAAK,GACoB,GAAaJ,GAAO,MAAM,mBAAmB,CAAC,CACvE,OAAO,OAAO,CAAC,CACf,KAAK,GAAG;CACV,OACC,kBAAC,OAAD;EACM;EACL,GAAIF;EACJ,WAAWY,EAAGC,GAAiB,sCAAsCC,CAAS;EAH/E,UAAA;GAKC,kBAACC,GAAD;IAAO,SAASX;IAAW,cAAcY,MAAa;IAAO,SAASC;IACpE,UAAAC;GACK,CAAA;GACNhB,IACEP,EAAM,aAAaO,GAAO;IAC1B,IAAIE;IACJ,gBAAgBK,IAAW,KAAOP,EAAM,MAAM;IAC9C,oBAAoBQ,KAAqB,KAAA;GAC1C,CAAC,IACAP;GACFQ,KAAQ,CAACF,IACT,kBAAC,KAAD;IAAG,IAAIH;IAAQ,WAAU;IACvB,UAAAK;GACC,CAAA,IACA;GACHF,IACA,kBAAC,KAAD;IAAG,IAAIF;IAAS,WAAU;IAAyC,MAAK;IACtE,UAAAC;GACC,CAAA,IACA;EACA;;AAEP,CACD;AACA,EAAM,cAAc"}
@@ -31,7 +31,7 @@ function u({ label: u, description: d, accept: f = "", multiple: p = !0, maxFile
31
31
  return /* @__PURE__ */ s("div", {
32
32
  role: "group",
33
33
  "aria-label": u,
34
- className: e(t, "min-w-0 space-y-2", C),
34
+ className: e(t, "min-w-0 space-y-basalt-space-lg", C),
35
35
  children: [
36
36
  /* @__PURE__ */ o("input", {
37
37
  ref: w,
@@ -65,30 +65,30 @@ function u({ label: u, description: d, accept: f = "", multiple: p = !0, maxFile
65
65
  onDrop: (e) => {
66
66
  e.preventDefault(), e.stopPropagation(), T.current = 0, D(!1), j(Array.from(e.dataTransfer.files));
67
67
  },
68
- className: e("flex w-full min-w-0 flex-col items-center gap-2 rounded-basalt-lg border-2 border-dashed px-4 py-7 text-center transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-basalt-ring disabled:cursor-not-allowed disabled:opacity-50", E && !_ ? "border-basalt-primary bg-basalt-accent" : "border-basalt-border bg-basalt-card hover:bg-basalt-accent"),
68
+ className: e("flex w-full min-w-0 flex-col items-center gap-basalt-space-lg rounded-basalt-lg border-2 border-dashed px-basalt-card py-basalt-card text-center transition-colors basalt-motion focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-basalt-ring disabled:cursor-not-allowed disabled:opacity-50", E && !_ ? "border-basalt-primary bg-basalt-selected" : "border-basalt-border bg-basalt-control hover:bg-basalt-hover"),
69
69
  children: [
70
70
  /* @__PURE__ */ o(a, {
71
- className: "size-6 text-basalt-muted-foreground",
71
+ className: "size-basalt-icon-display text-basalt-muted-foreground",
72
72
  "aria-hidden": "true"
73
73
  }),
74
74
  /* @__PURE__ */ o("span", {
75
- className: "text-sm font-medium",
75
+ className: "text-basalt-base font-medium",
76
76
  children: E && !_ ? x : u
77
77
  }),
78
78
  d && /* @__PURE__ */ o("span", {
79
79
  id: `${A}-description`,
80
- className: "text-xs text-basalt-muted-foreground",
80
+ className: "text-basalt-sm text-basalt-muted-foreground",
81
81
  children: d
82
82
  }),
83
83
  /* @__PURE__ */ o("span", {
84
- className: "rounded-basalt-md border border-basalt-border px-3 py-1 text-xs",
84
+ className: "rounded-basalt-md border border-basalt-border px-basalt-space-lg py-basalt-space-sm text-basalt-sm",
85
85
  children: b
86
86
  })
87
87
  ]
88
88
  }),
89
89
  O.length > 0 && /* @__PURE__ */ o("ul", {
90
90
  role: "alert",
91
- className: "space-y-1 text-xs text-basalt-destructive",
91
+ className: "space-y-basalt-space-sm text-basalt-sm text-basalt-destructive",
92
92
  children: O.map((e, t) => /* @__PURE__ */ o("li", {
93
93
  className: "break-words",
94
94
  children: S ? S(e) : `${e.file.name}: ${l[e.code]}`
@@ -1 +1 @@
1
- {"version":3,"file":"file-dropzone.js","names":["accepts","rules","accept","rule","file","REASONS","FileDropzone","input","useRef","depth","dragging","setDragging","useState","rejections","setRejections","id","useId","receive","disabled","accepted","rejected","limit","multiple","maxFiles","files","code","maxSize","fileCount","onFilesAccepted","onFilesRejected","label","cn","BASALT_UI_CLASS","className","event","browseLabel","description","Upload","dropLabel","formatRejection","item","index"],"sources":["../../src/components/file-dropzone.tsx"],"sourcesContent":["import { Upload } from \"lucide-react\";\nimport { useId, useRef, useState } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\n\nexport interface FileRejection {\n\t/** Original File; the component never creates preview URLs. */\n\tfile: File;\n\t/** Machine-readable reason for application handling. */\n\tcode: \"file-invalid-type\" | \"file-too-large\" | \"too-many-files\";\n}\n\nexport interface FileDropzoneProps {\n\t/** Visible and accessible upload field name. */\n\tlabel: string;\n\t/** Optional file requirements shown under the label. */\n\tdescription?: string;\n\t/** Accepted extensions/MIME types using native accept syntax, e.g. .pdf,image/*. */\n\taccept?: string;\n\t/** Allow multiple files. @default true */\n\tmultiple?: boolean;\n\t/** Maximum accepted file count including fileCount. @default Infinity */\n\tmaxFiles?: number;\n\t/** Number already held by the application. @default 0 */\n\tfileCount?: number;\n\t/** Maximum size of an individual file in bytes. @default Infinity */\n\tmaxSize?: number;\n\t/** Prevent both file browsing and drops. @default false */\n\tdisabled?: boolean;\n\t/** Accepted files from this gesture; transport and queue ownership belong to the caller. */\n\tonFilesAccepted: (files: File[]) => void;\n\t/** Rejected files from this gesture, with one primary reason per file. */\n\tonFilesRejected?: (rejections: FileRejection[]) => void;\n\t/** Browse action text. @default \"Browse files\" */\n\tbrowseLabel?: string;\n\t/** Text while a file is dragged over the field. @default \"Drop files here\" */\n\tdropLabel?: string;\n\t/** Localized rejection message; defaults to a name and reason. */\n\tformatRejection?: (rejection: FileRejection) => string;\n\t/** Additional root classes. */\n\tclassName?: string;\n}\n\nfunction accepts(file: File, accept: string) {\n\tconst rules = accept\n\t\t.split(\",\")\n\t\t.map((rule) => rule.trim().toLowerCase())\n\t\t.filter(Boolean);\n\treturn (\n\t\trules.length === 0 ||\n\t\trules.some((rule) =>\n\t\t\trule.startsWith(\".\")\n\t\t\t\t? file.name.toLowerCase().endsWith(rule)\n\t\t\t\t: rule.endsWith(\"/*\")\n\t\t\t\t\t? file.type.toLowerCase().startsWith(rule.slice(0, -1))\n\t\t\t\t\t: file.type.toLowerCase() === rule,\n\t\t)\n\t);\n}\n\nconst REASONS = {\n\t\"file-invalid-type\": \"File type is not accepted.\",\n\t\"file-too-large\": \"File exceeds the size limit.\",\n\t\"too-many-files\": \"File count limit reached.\",\n};\n\nexport function FileDropzone({\n\tlabel,\n\tdescription,\n\taccept = \"\",\n\tmultiple = true,\n\tmaxFiles = Infinity,\n\tfileCount = 0,\n\tmaxSize = Infinity,\n\tdisabled = false,\n\tonFilesAccepted,\n\tonFilesRejected,\n\tbrowseLabel = \"Browse files\",\n\tdropLabel = \"Drop files here\",\n\tformatRejection,\n\tclassName,\n}: FileDropzoneProps) {\n\tconst input = useRef<HTMLInputElement>(null);\n\tconst depth = useRef(0);\n\tconst [dragging, setDragging] = useState(false);\n\tconst [rejections, setRejections] = useState<FileRejection[]>([]);\n\tconst id = useId();\n\tfunction receive(files: File[]) {\n\t\tif (disabled) return;\n\t\tconst accepted: File[] = [];\n\t\tconst rejected: FileRejection[] = [];\n\t\tconst limit = Math.max(0, multiple ? maxFiles : Math.min(1, maxFiles));\n\t\tfor (const file of files) {\n\t\t\tconst code = !accepts(file, accept)\n\t\t\t\t? \"file-invalid-type\"\n\t\t\t\t: file.size > maxSize\n\t\t\t\t\t? \"file-too-large\"\n\t\t\t\t\t: accepted.length + fileCount >= limit\n\t\t\t\t\t\t? \"too-many-files\"\n\t\t\t\t\t\t: null;\n\t\t\tif (code) rejected.push({ file, code });\n\t\t\telse accepted.push(file);\n\t\t}\n\t\tsetRejections(rejected);\n\t\tif (accepted.length) onFilesAccepted(accepted);\n\t\tif (rejected.length) onFilesRejected?.(rejected);\n\t}\n\treturn (\n\t\t<div\n\t\t\trole=\"group\"\n\t\t\taria-label={label}\n\t\t\tclassName={cn(BASALT_UI_CLASS, \"min-w-0 space-y-2\", className)}\n\t\t>\n\t\t\t<input\n\t\t\t\tref={input}\n\t\t\t\ttype=\"file\"\n\t\t\t\taccept={accept}\n\t\t\t\tmultiple={multiple}\n\t\t\t\tdisabled={disabled}\n\t\t\t\ttabIndex={-1}\n\t\t\t\taria-label={label}\n\t\t\t\tclassName=\"hidden\"\n\t\t\t\tonChange={(event) => {\n\t\t\t\t\treceive(Array.from(event.currentTarget.files ?? []));\n\t\t\t\t\tevent.currentTarget.value = \"\";\n\t\t\t\t}}\n\t\t\t/>\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tdisabled={disabled}\n\t\t\t\taria-label={`${browseLabel}: ${label}`}\n\t\t\t\taria-describedby={description ? `${id}-description` : undefined}\n\t\t\t\tdata-drag-active={dragging && !disabled}\n\t\t\t\tonClick={() => input.current?.click()}\n\t\t\t\tonDragEnter={(event) => {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tdepth.current += 1;\n\t\t\t\t\tif (!disabled) setDragging(true);\n\t\t\t\t}}\n\t\t\t\tonDragOver={(event) => {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tif (!disabled) event.dataTransfer.dropEffect = \"copy\";\n\t\t\t\t}}\n\t\t\t\tonDragLeave={(event) => {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tdepth.current = Math.max(0, depth.current - 1);\n\t\t\t\t\tif (depth.current === 0) setDragging(false);\n\t\t\t\t}}\n\t\t\t\tonDrop={(event) => {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\tdepth.current = 0;\n\t\t\t\t\tsetDragging(false);\n\t\t\t\t\treceive(Array.from(event.dataTransfer.files));\n\t\t\t\t}}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"flex w-full min-w-0 flex-col items-center gap-2 rounded-basalt-lg border-2 border-dashed px-4 py-7 text-center transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-basalt-ring disabled:cursor-not-allowed disabled:opacity-50\",\n\t\t\t\t\tdragging && !disabled\n\t\t\t\t\t\t? \"border-basalt-primary bg-basalt-accent\"\n\t\t\t\t\t\t: \"border-basalt-border bg-basalt-card hover:bg-basalt-accent\",\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t<Upload className=\"size-6 text-basalt-muted-foreground\" aria-hidden=\"true\" />\n\t\t\t\t<span className=\"text-sm font-medium\">{dragging && !disabled ? dropLabel : label}</span>\n\t\t\t\t{description && (\n\t\t\t\t\t<span id={`${id}-description`} className=\"text-xs text-basalt-muted-foreground\">\n\t\t\t\t\t\t{description}\n\t\t\t\t\t</span>\n\t\t\t\t)}\n\t\t\t\t<span className=\"rounded-basalt-md border border-basalt-border px-3 py-1 text-xs\">\n\t\t\t\t\t{browseLabel}\n\t\t\t\t</span>\n\t\t\t</button>\n\t\t\t{rejections.length > 0 && (\n\t\t\t\t<ul role=\"alert\" className=\"space-y-1 text-xs text-basalt-destructive\">\n\t\t\t\t\t{rejections.map((item, index) => (\n\t\t\t\t\t\t<li key={`${item.file.name}-${index}`} className=\"break-words\">\n\t\t\t\t\t\t\t{formatRejection ? formatRejection(item) : `${item.file.name}: ${REASONS[item.code]}`}\n\t\t\t\t\t\t</li>\n\t\t\t\t\t))}\n\t\t\t\t</ul>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"file-dropzone.js","names":["accepts","rules","accept","rule","file","REASONS","FileDropzone","input","useRef","depth","dragging","setDragging","useState","rejections","setRejections","id","useId","receive","disabled","accepted","rejected","limit","multiple","maxFiles","files","code","maxSize","fileCount","onFilesAccepted","onFilesRejected","label","cn","BASALT_UI_CLASS","className","event","browseLabel","description","Upload","dropLabel","formatRejection","item","index"],"sources":["../../src/components/file-dropzone.tsx"],"sourcesContent":["import { Upload } from \"lucide-react\";\nimport { useId, useRef, useState } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\n\nexport interface FileRejection {\n\t/** Original File; the component never creates preview URLs. */\n\tfile: File;\n\t/** Machine-readable reason for application handling. */\n\tcode: \"file-invalid-type\" | \"file-too-large\" | \"too-many-files\";\n}\n\nexport interface FileDropzoneProps {\n\t/** Visible and accessible upload field name. */\n\tlabel: string;\n\t/** Optional file requirements shown under the label. */\n\tdescription?: string;\n\t/** Accepted extensions/MIME types using native accept syntax, e.g. .pdf,image/*. */\n\taccept?: string;\n\t/** Allow multiple files. @default true */\n\tmultiple?: boolean;\n\t/** Maximum accepted file count including fileCount. @default Infinity */\n\tmaxFiles?: number;\n\t/** Number already held by the application. @default 0 */\n\tfileCount?: number;\n\t/** Maximum size of an individual file in bytes. @default Infinity */\n\tmaxSize?: number;\n\t/** Prevent both file browsing and drops. @default false */\n\tdisabled?: boolean;\n\t/** Accepted files from this gesture; transport and queue ownership belong to the caller. */\n\tonFilesAccepted: (files: File[]) => void;\n\t/** Rejected files from this gesture, with one primary reason per file. */\n\tonFilesRejected?: (rejections: FileRejection[]) => void;\n\t/** Browse action text. @default \"Browse files\" */\n\tbrowseLabel?: string;\n\t/** Text while a file is dragged over the field. @default \"Drop files here\" */\n\tdropLabel?: string;\n\t/** Localized rejection message; defaults to a name and reason. */\n\tformatRejection?: (rejection: FileRejection) => string;\n\t/** Additional root classes. */\n\tclassName?: string;\n}\n\nfunction accepts(file: File, accept: string) {\n\tconst rules = accept\n\t\t.split(\",\")\n\t\t.map((rule) => rule.trim().toLowerCase())\n\t\t.filter(Boolean);\n\treturn (\n\t\trules.length === 0 ||\n\t\trules.some((rule) =>\n\t\t\trule.startsWith(\".\")\n\t\t\t\t? file.name.toLowerCase().endsWith(rule)\n\t\t\t\t: rule.endsWith(\"/*\")\n\t\t\t\t\t? file.type.toLowerCase().startsWith(rule.slice(0, -1))\n\t\t\t\t\t: file.type.toLowerCase() === rule,\n\t\t)\n\t);\n}\n\nconst REASONS = {\n\t\"file-invalid-type\": \"File type is not accepted.\",\n\t\"file-too-large\": \"File exceeds the size limit.\",\n\t\"too-many-files\": \"File count limit reached.\",\n};\n\nexport function FileDropzone({\n\tlabel,\n\tdescription,\n\taccept = \"\",\n\tmultiple = true,\n\tmaxFiles = Infinity,\n\tfileCount = 0,\n\tmaxSize = Infinity,\n\tdisabled = false,\n\tonFilesAccepted,\n\tonFilesRejected,\n\tbrowseLabel = \"Browse files\",\n\tdropLabel = \"Drop files here\",\n\tformatRejection,\n\tclassName,\n}: FileDropzoneProps) {\n\tconst input = useRef<HTMLInputElement>(null);\n\tconst depth = useRef(0);\n\tconst [dragging, setDragging] = useState(false);\n\tconst [rejections, setRejections] = useState<FileRejection[]>([]);\n\tconst id = useId();\n\tfunction receive(files: File[]) {\n\t\tif (disabled) return;\n\t\tconst accepted: File[] = [];\n\t\tconst rejected: FileRejection[] = [];\n\t\tconst limit = Math.max(0, multiple ? maxFiles : Math.min(1, maxFiles));\n\t\tfor (const file of files) {\n\t\t\tconst code = !accepts(file, accept)\n\t\t\t\t? \"file-invalid-type\"\n\t\t\t\t: file.size > maxSize\n\t\t\t\t\t? \"file-too-large\"\n\t\t\t\t\t: accepted.length + fileCount >= limit\n\t\t\t\t\t\t? \"too-many-files\"\n\t\t\t\t\t\t: null;\n\t\t\tif (code) rejected.push({ file, code });\n\t\t\telse accepted.push(file);\n\t\t}\n\t\tsetRejections(rejected);\n\t\tif (accepted.length) onFilesAccepted(accepted);\n\t\tif (rejected.length) onFilesRejected?.(rejected);\n\t}\n\treturn (\n\t\t<div\n\t\t\trole=\"group\"\n\t\t\taria-label={label}\n\t\t\tclassName={cn(BASALT_UI_CLASS, \"min-w-0 space-y-basalt-space-lg\", className)}\n\t\t>\n\t\t\t<input\n\t\t\t\tref={input}\n\t\t\t\ttype=\"file\"\n\t\t\t\taccept={accept}\n\t\t\t\tmultiple={multiple}\n\t\t\t\tdisabled={disabled}\n\t\t\t\ttabIndex={-1}\n\t\t\t\taria-label={label}\n\t\t\t\tclassName=\"hidden\"\n\t\t\t\tonChange={(event) => {\n\t\t\t\t\treceive(Array.from(event.currentTarget.files ?? []));\n\t\t\t\t\tevent.currentTarget.value = \"\";\n\t\t\t\t}}\n\t\t\t/>\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tdisabled={disabled}\n\t\t\t\taria-label={`${browseLabel}: ${label}`}\n\t\t\t\taria-describedby={description ? `${id}-description` : undefined}\n\t\t\t\tdata-drag-active={dragging && !disabled}\n\t\t\t\tonClick={() => input.current?.click()}\n\t\t\t\tonDragEnter={(event) => {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tdepth.current += 1;\n\t\t\t\t\tif (!disabled) setDragging(true);\n\t\t\t\t}}\n\t\t\t\tonDragOver={(event) => {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tif (!disabled) event.dataTransfer.dropEffect = \"copy\";\n\t\t\t\t}}\n\t\t\t\tonDragLeave={(event) => {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tdepth.current = Math.max(0, depth.current - 1);\n\t\t\t\t\tif (depth.current === 0) setDragging(false);\n\t\t\t\t}}\n\t\t\t\tonDrop={(event) => {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\tdepth.current = 0;\n\t\t\t\t\tsetDragging(false);\n\t\t\t\t\treceive(Array.from(event.dataTransfer.files));\n\t\t\t\t}}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"flex w-full min-w-0 flex-col items-center gap-basalt-space-lg rounded-basalt-lg border-2 border-dashed px-basalt-card py-basalt-card text-center transition-colors basalt-motion focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-basalt-ring disabled:cursor-not-allowed disabled:opacity-50\",\n\t\t\t\t\tdragging && !disabled\n\t\t\t\t\t\t? \"border-basalt-primary bg-basalt-selected\"\n\t\t\t\t\t\t: \"border-basalt-border bg-basalt-control hover:bg-basalt-hover\",\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t<Upload\n\t\t\t\t\tclassName=\"size-basalt-icon-display text-basalt-muted-foreground\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t/>\n\t\t\t\t<span className=\"text-basalt-base font-medium\">\n\t\t\t\t\t{dragging && !disabled ? dropLabel : label}\n\t\t\t\t</span>\n\t\t\t\t{description && (\n\t\t\t\t\t<span id={`${id}-description`} className=\"text-basalt-sm text-basalt-muted-foreground\">\n\t\t\t\t\t\t{description}\n\t\t\t\t\t</span>\n\t\t\t\t)}\n\t\t\t\t<span className=\"rounded-basalt-md border border-basalt-border px-basalt-space-lg py-basalt-space-sm text-basalt-sm\">\n\t\t\t\t\t{browseLabel}\n\t\t\t\t</span>\n\t\t\t</button>\n\t\t\t{rejections.length > 0 && (\n\t\t\t\t<ul role=\"alert\" className=\"space-y-basalt-space-sm text-basalt-sm text-basalt-destructive\">\n\t\t\t\t\t{rejections.map((item, index) => (\n\t\t\t\t\t\t<li key={`${item.file.name}-${index}`} className=\"break-words\">\n\t\t\t\t\t\t\t{formatRejection ? formatRejection(item) : `${item.file.name}: ${REASONS[item.code]}`}\n\t\t\t\t\t\t</li>\n\t\t\t\t\t))}\n\t\t\t\t</ul>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n"],"mappings":"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"}
@@ -9,9 +9,9 @@ function o({ label: r, children: o, chips: s, active: c = !1, onClear: l, clearL
9
9
  return /* @__PURE__ */ a("div", {
10
10
  role: "group",
11
11
  "aria-label": r,
12
- className: e(t, "min-w-0 space-y-3", d),
12
+ className: e(t, "min-w-0 space-y-basalt-space-lg", d),
13
13
  children: [/* @__PURE__ */ a("div", {
14
- className: "flex flex-wrap items-end gap-3 [&>*]:min-w-0",
14
+ className: "flex flex-wrap items-end gap-basalt-space-lg [&>*]:min-w-0",
15
15
  children: [o, c && l && /* @__PURE__ */ i(n, {
16
16
  size: "sm",
17
17
  variant: "ghost",
@@ -19,14 +19,14 @@ function o({ label: r, children: o, chips: s, active: c = !1, onClear: l, clearL
19
19
  children: u
20
20
  })]
21
21
  }), s != null && /* @__PURE__ */ i("div", {
22
- className: "flex flex-wrap items-center gap-2",
22
+ className: "flex flex-wrap items-center gap-basalt-space-lg",
23
23
  children: s
24
24
  })]
25
25
  });
26
26
  }
27
27
  function s({ label: n, value: o, onRemove: s, removeLabel: c, disabled: l = !1, className: u }) {
28
28
  return /* @__PURE__ */ a("span", {
29
- className: e(t, "inline-flex max-w-full items-center gap-1 rounded-full border border-basalt-border bg-basalt-accent py-1 pl-3 pr-1 text-xs", u),
29
+ className: e(t, "inline-flex max-w-full items-center gap-basalt-space-sm rounded-basalt-full border border-basalt-border bg-basalt-selected py-basalt-space-sm pl-basalt-space-lg pr-basalt-space-sm text-basalt-sm", u),
30
30
  children: [/* @__PURE__ */ a("span", {
31
31
  className: "min-w-0 break-words",
32
32
  children: [/* @__PURE__ */ a("span", {
@@ -38,9 +38,9 @@ function s({ label: n, value: o, onRemove: s, removeLabel: c, disabled: l = !1,
38
38
  disabled: l,
39
39
  "aria-label": c ?? `Remove ${n}`,
40
40
  onClick: s,
41
- className: "shrink-0 rounded-full p-1 focus-visible:outline-2 focus-visible:outline-basalt-ring disabled:opacity-50",
41
+ className: "shrink-0 rounded-basalt-full p-basalt-space-sm focus-visible:outline-2 focus-visible:outline-basalt-ring disabled:opacity-50",
42
42
  children: /* @__PURE__ */ i(r, {
43
- className: "size-3",
43
+ className: "size-basalt-icon-sm",
44
44
  "aria-hidden": "true"
45
45
  })
46
46
  })]
@@ -1 +1 @@
1
- {"version":3,"file":"filter-bar.js","names":["FilterBar","label","cn","BASALT_UI_CLASS","className","children","active","onClear","Button","clearLabel","chips","FilterChip","value","removeLabel","onRemove","X"],"sources":["../../src/components/filter-bar.tsx"],"sourcesContent":["import { X } from \"lucide-react\";\nimport type { ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { Button } from \"./button\";\n\nexport interface FilterBarProps {\n\t/** Accessible group name. */\n\tlabel: string;\n\t/** Application-owned search, select, and date controls. */\n\tchildren: ReactNode;\n\t/** Active chips, shown on their own wrapping row. */\n\tchips?: ReactNode;\n\t/** Whether the clear action is available. @default false */\n\tactive?: boolean;\n\t/** Requests clearing application-owned filters. */\n\tonClear?: () => void;\n\t/** Clear action text. @default \"Clear filters\" */\n\tclearLabel?: string;\n\t/** Additional root classes. */\n\tclassName?: string;\n}\n\n/** Layout only; URL serialization, query execution, and date presets belong to the caller. */\nexport function FilterBar({\n\tlabel,\n\tchildren,\n\tchips,\n\tactive = false,\n\tonClear,\n\tclearLabel = \"Clear filters\",\n\tclassName,\n}: FilterBarProps) {\n\treturn (\n\t\t<div\n\t\t\trole=\"group\"\n\t\t\taria-label={label}\n\t\t\tclassName={cn(BASALT_UI_CLASS, \"min-w-0 space-y-3\", className)}\n\t\t>\n\t\t\t<div className=\"flex flex-wrap items-end gap-3 [&>*]:min-w-0\">\n\t\t\t\t{children}\n\t\t\t\t{active && onClear && (\n\t\t\t\t\t<Button size=\"sm\" variant=\"ghost\" onClick={onClear}>\n\t\t\t\t\t\t{clearLabel}\n\t\t\t\t\t</Button>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t\t{chips != null && <div className=\"flex flex-wrap items-center gap-2\">{chips}</div>}\n\t\t</div>\n\t);\n}\n\nexport interface FilterChipProps {\n\t/** Filter dimension, e.g. Status. */\n\tlabel: string;\n\t/** Display value. */\n\tvalue: ReactNode;\n\t/** Requests removal from the application's filter state. */\n\tonRemove: () => void;\n\t/** Full accessible removal label; defaults to Remove plus the dimension label. */\n\tremoveLabel?: string;\n\t/** Disable removal. @default false */\n\tdisabled?: boolean;\n\t/** Additional root classes. */\n\tclassName?: string;\n}\n\nexport function FilterChip({\n\tlabel,\n\tvalue,\n\tonRemove,\n\tremoveLabel,\n\tdisabled = false,\n\tclassName,\n}: FilterChipProps) {\n\treturn (\n\t\t<span\n\t\t\tclassName={cn(\n\t\t\t\tBASALT_UI_CLASS,\n\t\t\t\t\"inline-flex max-w-full items-center gap-1 rounded-full border border-basalt-border bg-basalt-accent py-1 pl-3 pr-1 text-xs\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t<span className=\"min-w-0 break-words\">\n\t\t\t\t<span className=\"text-basalt-muted-foreground\">{label}: </span>\n\t\t\t\t{value}\n\t\t\t</span>\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tdisabled={disabled}\n\t\t\t\taria-label={removeLabel ?? `Remove ${label}`}\n\t\t\t\tonClick={onRemove}\n\t\t\t\tclassName=\"shrink-0 rounded-full p-1 focus-visible:outline-2 focus-visible:outline-basalt-ring disabled:opacity-50\"\n\t\t\t>\n\t\t\t\t<X className=\"size-3\" aria-hidden=\"true\" />\n\t\t\t</button>\n\t\t</span>\n\t);\n}\n"],"mappings":";;;;;;;AAwBA,SAAgBA,EAAU,EACzB,UACA,aACA,UACA,YAAS,IACT,YACA,gBAAa,iBACb,gBACkB;CAClB,OACC,kBAAC,OAAD;EACC,MAAK;EACL,cAAYC;EACZ,WAAWC,EAAGC,GAAiB,qBAAqBC,CAAS;EAH9D,UAAA,CAKC,kBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACEC,GACAC,KAAUC,KACV,kBAACC,GAAD;IAAQ,MAAK;IAAK,SAAQ;IAAQ,SAASD;IACzC,UAAAE;GACM,CAAA,CAEL;EACJ,CAAA,GAAAC,KAAS,QAAQ,kBAAC,OAAD;GAAK,WAAU;GAAqC,UAAAA;EAAW,CAAA,CAC7E;;AAEP;AAiBA,SAAgBC,EAAW,EAC1B,UACA,UACA,aACA,gBACA,cAAW,IACX,gBACmB;CACnB,OACC,kBAAC,QAAD;EACC,WAAWT,EACVC,GACA,8HACAC,CACD;EALD,UAAA,CAOC,kBAAC,QAAD;GAAM,WAAU;GAAhB,UAAA,CACC,kBAAC,QAAD;IAAM,WAAU;IAAhB,UAAA,CAAgDH,GAAM,IAAQ;GAC7D,CAAA,GAAAW,CACI;EACN,CAAA,GAAA,kBAAC,UAAD;GACC,MAAK;GACK;GACV,cAAYC,KAAe,UAAUZ;GACrC,SAASa;GACT,WAAU;GAEV,UAAA,kBAACC,GAAD;IAAG,WAAU;IAAS,eAAY;GAAQ,CAAA;EACnC,CAAA,CACH;;AAER"}
1
+ {"version":3,"file":"filter-bar.js","names":["FilterBar","label","cn","BASALT_UI_CLASS","className","children","active","onClear","Button","clearLabel","chips","FilterChip","value","removeLabel","onRemove","X"],"sources":["../../src/components/filter-bar.tsx"],"sourcesContent":["import { X } from \"lucide-react\";\nimport type { ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { Button } from \"./button\";\n\nexport interface FilterBarProps {\n\t/** Accessible group name. */\n\tlabel: string;\n\t/** Application-owned search, select, and date controls. */\n\tchildren: ReactNode;\n\t/** Active chips, shown on their own wrapping row. */\n\tchips?: ReactNode;\n\t/** Whether the clear action is available. @default false */\n\tactive?: boolean;\n\t/** Requests clearing application-owned filters. */\n\tonClear?: () => void;\n\t/** Clear action text. @default \"Clear filters\" */\n\tclearLabel?: string;\n\t/** Additional root classes. */\n\tclassName?: string;\n}\n\n/** Layout only; URL serialization, query execution, and date presets belong to the caller. */\nexport function FilterBar({\n\tlabel,\n\tchildren,\n\tchips,\n\tactive = false,\n\tonClear,\n\tclearLabel = \"Clear filters\",\n\tclassName,\n}: FilterBarProps) {\n\treturn (\n\t\t<div\n\t\t\trole=\"group\"\n\t\t\taria-label={label}\n\t\t\tclassName={cn(BASALT_UI_CLASS, \"min-w-0 space-y-basalt-space-lg\", className)}\n\t\t>\n\t\t\t<div className=\"flex flex-wrap items-end gap-basalt-space-lg [&>*]:min-w-0\">\n\t\t\t\t{children}\n\t\t\t\t{active && onClear && (\n\t\t\t\t\t<Button size=\"sm\" variant=\"ghost\" onClick={onClear}>\n\t\t\t\t\t\t{clearLabel}\n\t\t\t\t\t</Button>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t\t{chips != null && (\n\t\t\t\t<div className=\"flex flex-wrap items-center gap-basalt-space-lg\">{chips}</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nexport interface FilterChipProps {\n\t/** Filter dimension, e.g. Status. */\n\tlabel: string;\n\t/** Display value. */\n\tvalue: ReactNode;\n\t/** Requests removal from the application's filter state. */\n\tonRemove: () => void;\n\t/** Full accessible removal label; defaults to Remove plus the dimension label. */\n\tremoveLabel?: string;\n\t/** Disable removal. @default false */\n\tdisabled?: boolean;\n\t/** Additional root classes. */\n\tclassName?: string;\n}\n\nexport function FilterChip({\n\tlabel,\n\tvalue,\n\tonRemove,\n\tremoveLabel,\n\tdisabled = false,\n\tclassName,\n}: FilterChipProps) {\n\treturn (\n\t\t<span\n\t\t\tclassName={cn(\n\t\t\t\tBASALT_UI_CLASS,\n\t\t\t\t\"inline-flex max-w-full items-center gap-basalt-space-sm rounded-basalt-full border border-basalt-border bg-basalt-selected py-basalt-space-sm pl-basalt-space-lg pr-basalt-space-sm text-basalt-sm\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t<span className=\"min-w-0 break-words\">\n\t\t\t\t<span className=\"text-basalt-muted-foreground\">{label}: </span>\n\t\t\t\t{value}\n\t\t\t</span>\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tdisabled={disabled}\n\t\t\t\taria-label={removeLabel ?? `Remove ${label}`}\n\t\t\t\tonClick={onRemove}\n\t\t\t\tclassName=\"shrink-0 rounded-basalt-full p-basalt-space-sm focus-visible:outline-2 focus-visible:outline-basalt-ring disabled:opacity-50\"\n\t\t\t>\n\t\t\t\t<X className=\"size-basalt-icon-sm\" aria-hidden=\"true\" />\n\t\t\t</button>\n\t\t</span>\n\t);\n}\n"],"mappings":";;;;;;;AAwBA,SAAgBA,EAAU,EACzB,UACA,aACA,UACA,YAAS,IACT,YACA,gBAAa,iBACb,gBACkB;CAClB,OACC,kBAAC,OAAD;EACC,MAAK;EACL,cAAYC;EACZ,WAAWC,EAAGC,GAAiB,mCAAmCC,CAAS;EAH5E,UAAA,CAKC,kBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACEC,GACAC,KAAUC,KACV,kBAACC,GAAD;IAAQ,MAAK;IAAK,SAAQ;IAAQ,SAASD;IACzC,UAAAE;GACM,CAAA,CAEL;EACJ,CAAA,GAAAC,KAAS,QACT,kBAAC,OAAD;GAAK,WAAU;GAAmD,UAAAA;EAAW,CAAA,CAE1E;;AAEP;AAiBA,SAAgBC,EAAW,EAC1B,UACA,UACA,aACA,gBACA,cAAW,IACX,gBACmB;CACnB,OACC,kBAAC,QAAD;EACC,WAAWT,EACVC,GACA,sMACAC,CACD;EALD,UAAA,CAOC,kBAAC,QAAD;GAAM,WAAU;GAAhB,UAAA,CACC,kBAAC,QAAD;IAAM,WAAU;IAAhB,UAAA,CAAgDH,GAAM,IAAQ;GAC7D,CAAA,GAAAW,CACI;EACN,CAAA,GAAA,kBAAC,UAAD;GACC,MAAK;GACK;GACV,cAAYC,KAAe,UAAUZ;GACrC,SAASa;GACT,WAAU;GAEV,UAAA,kBAACC,GAAD;IAAG,WAAU;IAAsB,eAAY;GAAQ,CAAA;EAChD,CAAA,CACH;;AAER"}
@@ -8,10 +8,10 @@ function s() {
8
8
  let e = `flow-arrow-${i().replace(/:/g, "")}`;
9
9
  return /* @__PURE__ */ a("li", {
10
10
  "aria-hidden": "true",
11
- className: "flex w-10 shrink-0 items-center text-basalt-muted-foreground",
11
+ className: "flex w-basalt-10 shrink-0 items-center text-basalt-muted-foreground",
12
12
  children: /* @__PURE__ */ o("svg", {
13
13
  viewBox: "0 0 40 16",
14
- className: "h-4 w-10 overflow-visible",
14
+ className: "h-basalt-4 w-basalt-10 overflow-visible",
15
15
  overflow: "visible",
16
16
  "aria-hidden": "true",
17
17
  children: [/* @__PURE__ */ a("defs", { children: /* @__PURE__ */ a("marker", {
@@ -47,7 +47,8 @@ function c({ className: i, children: c, "aria-label": l = "Flow" }) {
47
47
  }
48
48
  function l({ children: e }) {
49
49
  return /* @__PURE__ */ a("li", {
50
- className: "rounded-basalt-md border border-basalt-border bg-basalt-secondary px-3 py-2 text-sm",
50
+ "data-basalt-surface": "",
51
+ className: "rounded-basalt-md border border-basalt-border px-basalt-layout py-basalt-layout-sm text-basalt-base",
51
52
  children: e
52
53
  });
53
54
  }
@@ -1 +1 @@
1
- {"version":3,"file":"flow.js","names":["FlowArrow","id","useId","Flow","ariaLabel","nodes","Children","children","cn","BASALT_UI_CLASS","className","Fragment","child","index","FlowNode"],"sources":["../../src/components/flow.tsx"],"sourcesContent":["import { Children, Fragment, type ReactNode, useId } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\n\nfunction FlowArrow() {\n\tconst id = `flow-arrow-${useId().replace(/:/g, \"\")}`;\n\treturn (\n\t\t<li aria-hidden=\"true\" className=\"flex w-10 shrink-0 items-center text-basalt-muted-foreground\">\n\t\t\t<svg\n\t\t\t\tviewBox=\"0 0 40 16\"\n\t\t\t\tclassName=\"h-4 w-10 overflow-visible\"\n\t\t\t\toverflow=\"visible\"\n\t\t\t\taria-hidden=\"true\"\n\t\t\t>\n\t\t\t\t<defs>\n\t\t\t\t\t<marker\n\t\t\t\t\t\tid={id}\n\t\t\t\t\t\tmarkerWidth=\"8\"\n\t\t\t\t\t\tmarkerHeight=\"8\"\n\t\t\t\t\t\trefX=\"0\"\n\t\t\t\t\t\trefY=\"4\"\n\t\t\t\t\t\torient=\"auto\"\n\t\t\t\t\t\tmarkerUnits=\"userSpaceOnUse\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<path\n\t\t\t\t\t\t\td=\"M 0,1.5 Q 0,0 1.5,0 Q 3.5,1 5.8,3.2 Q 6.5,4 5.8,4.8 Q 3.5,7 1.5,8 Q 0,8 0,6.5 Z\"\n\t\t\t\t\t\t\tfill=\"currentColor\"\n\t\t\t\t\t\t\tstroke=\"none\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t</marker>\n\t\t\t\t</defs>\n\t\t\t\t<path\n\t\t\t\t\td=\"M 0 8 L 32 8\"\n\t\t\t\t\tfill=\"none\"\n\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\t\tmarkerEnd={`url(#${id})`}\n\t\t\t\t/>\n\t\t\t</svg>\n\t\t</li>\n\t);\n}\n\nexport type FlowProps = {\n\t/**\n\t * Accessible name for the step list.\n\t * @default \"Flow\"\n\t */\n\t\"aria-label\"?: string;\n\t/**\n\t * Additional classes for the list.\n\t */\n\tclassName?: string;\n\t/**\n\t * Step nodes.\n\t */\n\tchildren: ReactNode;\n};\n\nexport function Flow({ className, children, \"aria-label\": ariaLabel = \"Flow\" }: FlowProps) {\n\tconst nodes = Children.toArray(children);\n\treturn (\n\t\t<ol aria-label={ariaLabel} className={cn(BASALT_UI_CLASS, \"flex items-center\", className)}>\n\t\t\t{nodes.map((child, index) => (\n\t\t\t\t<Fragment key={index}>\n\t\t\t\t\t{child}\n\t\t\t\t\t{index < nodes.length - 1 ? <FlowArrow /> : null}\n\t\t\t\t</Fragment>\n\t\t\t))}\n\t\t</ol>\n\t);\n}\n\nexport type FlowNodeProps = {\n\t/**\n\t * Label for the step.\n\t */\n\tchildren: ReactNode;\n};\n\nexport function FlowNode({ children }: FlowNodeProps) {\n\treturn (\n\t\t<li className=\"rounded-basalt-md border border-basalt-border bg-basalt-secondary px-3 py-2 text-sm\">\n\t\t\t{children}\n\t\t</li>\n\t);\n}\n"],"mappings":";;;;;;AAIA,SAASA,IAAY;CACpB,IAAMC,IAAK,cAAcC,EAAM,CAAC,CAAC,QAAQ,MAAM,EAAE;CACjD,OACC,kBAAC,MAAD;EAAI,eAAY;EAAO,WAAU;EAChC,UAAA,kBAAC,OAAD;GACC,SAAQ;GACR,WAAU;GACV,UAAS;GACT,eAAY;GAJb,UAAA,CAMC,kBAAC,QAAD,EAAA,UACC,kBAAC,UAAD;IACK;IACJ,aAAY;IACZ,cAAa;IACb,MAAK;IACL,MAAK;IACL,QAAO;IACP,aAAY;IAEZ,UAAA,kBAAC,QAAD;KACC,GAAE;KACF,MAAK;KACL,QAAO;IACP,CAAA;GACM,CAAA,EACH,CAAA,GACN,kBAAC,QAAD;IACC,GAAE;IACF,MAAK;IACL,QAAO;IACP,aAAY;IACZ,WAAW,QAAQD,EAAG;GACtB,CAAA,CACG;;CACF,CAAA;AAEN;AAkBA,SAAgBE,EAAK,EAAE,cAAW,aAAU,cAAcC,IAAY,UAAqB;CAC1F,IAAMC,IAAQC,EAAS,QAAQC,CAAQ;CACvC,OACC,kBAAC,MAAD;EAAI,cAAYH;EAAW,WAAWI,EAAGC,GAAiB,qBAAqBC,CAAS;EACtF,UAAAL,EAAM,KAAK,GAAO,MAClB,kBAACM,GAAD,EAAA,UAAA,CACEC,GACAC,IAAQR,EAAM,SAAS,IAAI,kBAACL,GAAD,CAAY,CAAA,IAAI,IACnC,EAAA,GAHKa,CAGL,CACV;CACE,CAAA;AAEN;AASA,SAAgBC,EAAS,EAAE,eAA2B;CACrD,OACC,kBAAC,MAAD;EAAI,WAAU;EACZ;CACE,CAAA;AAEN"}
1
+ {"version":3,"file":"flow.js","names":["FlowArrow","id","useId","Flow","ariaLabel","nodes","Children","children","cn","BASALT_UI_CLASS","className","Fragment","child","index","FlowNode"],"sources":["../../src/components/flow.tsx"],"sourcesContent":["import { Children, Fragment, type ReactNode, useId } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\n\nfunction FlowArrow() {\n\tconst id = `flow-arrow-${useId().replace(/:/g, \"\")}`;\n\treturn (\n\t\t<li\n\t\t\taria-hidden=\"true\"\n\t\t\tclassName=\"flex w-basalt-10 shrink-0 items-center text-basalt-muted-foreground\"\n\t\t>\n\t\t\t<svg\n\t\t\t\tviewBox=\"0 0 40 16\"\n\t\t\t\tclassName=\"h-basalt-4 w-basalt-10 overflow-visible\"\n\t\t\t\toverflow=\"visible\"\n\t\t\t\taria-hidden=\"true\"\n\t\t\t>\n\t\t\t\t<defs>\n\t\t\t\t\t<marker\n\t\t\t\t\t\tid={id}\n\t\t\t\t\t\tmarkerWidth=\"8\"\n\t\t\t\t\t\tmarkerHeight=\"8\"\n\t\t\t\t\t\trefX=\"0\"\n\t\t\t\t\t\trefY=\"4\"\n\t\t\t\t\t\torient=\"auto\"\n\t\t\t\t\t\tmarkerUnits=\"userSpaceOnUse\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<path\n\t\t\t\t\t\t\td=\"M 0,1.5 Q 0,0 1.5,0 Q 3.5,1 5.8,3.2 Q 6.5,4 5.8,4.8 Q 3.5,7 1.5,8 Q 0,8 0,6.5 Z\"\n\t\t\t\t\t\t\tfill=\"currentColor\"\n\t\t\t\t\t\t\tstroke=\"none\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t</marker>\n\t\t\t\t</defs>\n\t\t\t\t<path\n\t\t\t\t\td=\"M 0 8 L 32 8\"\n\t\t\t\t\tfill=\"none\"\n\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\t\tmarkerEnd={`url(#${id})`}\n\t\t\t\t/>\n\t\t\t</svg>\n\t\t</li>\n\t);\n}\n\nexport type FlowProps = {\n\t/**\n\t * Accessible name for the step list.\n\t * @default \"Flow\"\n\t */\n\t\"aria-label\"?: string;\n\t/**\n\t * Additional classes for the list.\n\t */\n\tclassName?: string;\n\t/**\n\t * Step nodes.\n\t */\n\tchildren: ReactNode;\n};\n\nexport function Flow({ className, children, \"aria-label\": ariaLabel = \"Flow\" }: FlowProps) {\n\tconst nodes = Children.toArray(children);\n\treturn (\n\t\t<ol aria-label={ariaLabel} className={cn(BASALT_UI_CLASS, \"flex items-center\", className)}>\n\t\t\t{nodes.map((child, index) => (\n\t\t\t\t<Fragment key={index}>\n\t\t\t\t\t{child}\n\t\t\t\t\t{index < nodes.length - 1 ? <FlowArrow /> : null}\n\t\t\t\t</Fragment>\n\t\t\t))}\n\t\t</ol>\n\t);\n}\n\nexport type FlowNodeProps = {\n\t/**\n\t * Label for the step.\n\t */\n\tchildren: ReactNode;\n};\n\nexport function FlowNode({ children }: FlowNodeProps) {\n\treturn (\n\t\t<li\n\t\t\tdata-basalt-surface=\"\"\n\t\t\tclassName=\"rounded-basalt-md border border-basalt-border px-basalt-layout py-basalt-layout-sm text-basalt-base\"\n\t\t>\n\t\t\t{children}\n\t\t</li>\n\t);\n}\n"],"mappings":";;;;;;AAIA,SAASA,IAAY;CACpB,IAAMC,IAAK,cAAcC,EAAM,CAAC,CAAC,QAAQ,MAAM,EAAE;CACjD,OACC,kBAAC,MAAD;EACC,eAAY;EACZ,WAAU;EAEV,UAAA,kBAAC,OAAD;GACC,SAAQ;GACR,WAAU;GACV,UAAS;GACT,eAAY;GAJb,UAAA,CAMC,kBAAC,QAAD,EAAA,UACC,kBAAC,UAAD;IACK;IACJ,aAAY;IACZ,cAAa;IACb,MAAK;IACL,MAAK;IACL,QAAO;IACP,aAAY;IAEZ,UAAA,kBAAC,QAAD;KACC,GAAE;KACF,MAAK;KACL,QAAO;IACP,CAAA;GACM,CAAA,EACH,CAAA,GACN,kBAAC,QAAD;IACC,GAAE;IACF,MAAK;IACL,QAAO;IACP,aAAY;IACZ,WAAW,QAAQD,EAAG;GACtB,CAAA,CACG;;CACF,CAAA;AAEN;AAkBA,SAAgBE,EAAK,EAAE,cAAW,aAAU,cAAcC,IAAY,UAAqB;CAC1F,IAAMC,IAAQC,EAAS,QAAQC,CAAQ;CACvC,OACC,kBAAC,MAAD;EAAI,cAAYH;EAAW,WAAWI,EAAGC,GAAiB,qBAAqBC,CAAS;EACtF,UAAAL,EAAM,KAAK,GAAO,MAClB,kBAACM,GAAD,EAAA,UAAA,CACEC,GACAC,IAAQR,EAAM,SAAS,IAAI,kBAACL,GAAD,CAAY,CAAA,IAAI,IACnC,EAAA,GAHKa,CAGL,CACV;CACE,CAAA;AAEN;AASA,SAAgBC,EAAS,EAAE,eAA2B;CACrD,OACC,kBAAC,MAAD;EACC,uBAAoB;EACpB,WAAU;EAET;CACE,CAAA;AAEN"}
@@ -5,13 +5,15 @@ export type GridProps = {
5
5
  * @default 2
6
6
  */
7
7
  columns?: number;
8
+ /** Space between layout items: 12, 16, 24 or 32px reference. @default "md" */
9
+ gap?: "sm" | "md" | "lg" | "xl";
8
10
  /**
9
11
  * Additional classes for the grid.
10
12
  */
11
13
  className?: string;
12
14
  children?: ReactNode;
13
15
  };
14
- export declare function Grid({ className, columns, style, ...props }: GridProps & HTMLAttributes<HTMLDivElement>): import("react").JSX.Element;
16
+ export declare function Grid({ className, columns, gap, style, ...props }: GridProps & HTMLAttributes<HTMLDivElement>): import("react").JSX.Element;
15
17
  export interface GridItemProps extends HTMLAttributes<HTMLDivElement> {
16
18
  }
17
19
  export declare function GridItem({ className, ...props }: GridItemProps): import("react").JSX.Element;
@@ -2,23 +2,30 @@
2
2
  import { cn as e } from "../utils/cn.js";
3
3
  import { jsx as t } from "react/jsx-runtime";
4
4
  //#region src/components/grid.tsx
5
- function n({ className: n, columns: r = 2, style: i, ...a }) {
5
+ var n = {
6
+ sm: "gap-basalt-layout-sm",
7
+ md: "gap-basalt-layout",
8
+ lg: "gap-basalt-layout-lg",
9
+ xl: "gap-basalt-layout-xl"
10
+ };
11
+ function r({ className: r, columns: i = 2, gap: a = "md", style: o, ...s }) {
6
12
  return /* @__PURE__ */ t("div", {
7
- className: e("grid gap-3", n),
8
- ...a,
13
+ className: e("grid", n[a], r),
14
+ ...s,
9
15
  style: {
10
- gridTemplateColumns: `repeat(${r}, minmax(0, 1fr))`,
11
- ...i
16
+ gridTemplateColumns: `repeat(${i}, minmax(0, 1fr))`,
17
+ ...o
12
18
  }
13
19
  });
14
20
  }
15
- function r({ className: n, ...r }) {
21
+ function i({ className: n, ...r }) {
16
22
  return /* @__PURE__ */ t("div", {
17
- className: e("flex items-center justify-center rounded-basalt-lg bg-basalt-secondary px-6 py-8 text-sm", n),
23
+ "data-basalt-surface": "",
24
+ className: e("flex items-center justify-center rounded-basalt-lg p-basalt-card text-basalt-base", n),
18
25
  ...r
19
26
  });
20
27
  }
21
28
  //#endregion
22
- export { n as Grid, r as GridItem };
29
+ export { r as Grid, i as GridItem };
23
30
 
24
31
  //# sourceMappingURL=grid.js.map