@burtson-labs/ui 0.14.0 → 0.14.1

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 (239) hide show
  1. package/LICENSES/DEPENDENCIES.txt +1 -1
  2. package/README.md +15 -11
  3. package/dist/components/accordion.d.ts +3 -3
  4. package/dist/components/accordion.js +13 -10
  5. package/dist/components/accordion.js.map +1 -1
  6. package/dist/components/alert-dialog.d.ts +12 -10
  7. package/dist/components/alert-dialog.js +29 -20
  8. package/dist/components/alert-dialog.js.map +1 -1
  9. package/dist/components/alert.d.ts +5 -3
  10. package/dist/components/alert.js +11 -7
  11. package/dist/components/alert.js.map +1 -1
  12. package/dist/components/app-shell.d.ts +7 -6
  13. package/dist/components/app-shell.js +21 -14
  14. package/dist/components/app-shell.js.map +1 -1
  15. package/dist/components/attachment.d.ts +3 -3
  16. package/dist/components/attachment.js +10 -7
  17. package/dist/components/attachment.js.map +1 -1
  18. package/dist/components/audio-player.d.ts +2 -2
  19. package/dist/components/audio-player.js +8 -6
  20. package/dist/components/audio-player.js.map +1 -1
  21. package/dist/components/avatar.d.ts +3 -3
  22. package/dist/components/avatar.js +10 -7
  23. package/dist/components/avatar.js.map +1 -1
  24. package/dist/components/badge.d.ts +1 -1
  25. package/dist/components/badge.js +12 -10
  26. package/dist/components/badge.js.map +1 -1
  27. package/dist/components/breadcrumb.d.ts +8 -8
  28. package/dist/components/breadcrumb.js +24 -17
  29. package/dist/components/breadcrumb.js.map +1 -1
  30. package/dist/components/button.d.ts +8 -1
  31. package/dist/components/button.js +12 -3
  32. package/dist/components/button.js.map +1 -1
  33. package/dist/components/card.d.ts +8 -8
  34. package/dist/components/card.js +32 -23
  35. package/dist/components/card.js.map +1 -1
  36. package/dist/components/chat-history.d.ts +1 -1
  37. package/dist/components/chat-history.js +10 -9
  38. package/dist/components/chat-history.js.map +1 -1
  39. package/dist/components/chat-layout.d.ts +1 -1
  40. package/dist/components/chat-layout.js +7 -3
  41. package/dist/components/chat-layout.js.map +1 -1
  42. package/dist/components/checkbox-card.d.ts +2 -2
  43. package/dist/components/checkbox-card.js +9 -7
  44. package/dist/components/checkbox-card.js.map +1 -1
  45. package/dist/components/checkbox.d.ts +23 -2
  46. package/dist/components/checkbox.js +48 -6
  47. package/dist/components/checkbox.js.map +1 -1
  48. package/dist/components/collapsible.d.ts +2 -2
  49. package/dist/components/collapsible.js +7 -5
  50. package/dist/components/collapsible.js.map +1 -1
  51. package/dist/components/combobox.d.ts +14 -4
  52. package/dist/components/combobox.js +18 -8
  53. package/dist/components/combobox.js.map +1 -1
  54. package/dist/components/command.d.ts +68 -12
  55. package/dist/components/command.js +38 -25
  56. package/dist/components/command.js.map +1 -1
  57. package/dist/components/composer.d.ts +2 -2
  58. package/dist/components/composer.js +9 -7
  59. package/dist/components/composer.js.map +1 -1
  60. package/dist/components/connection-status.d.ts +3 -3
  61. package/dist/components/connection-status.js +18 -14
  62. package/dist/components/connection-status.js.map +1 -1
  63. package/dist/components/context-menu.d.ts +14 -13
  64. package/dist/components/context-menu.js +33 -23
  65. package/dist/components/context-menu.js.map +1 -1
  66. package/dist/components/conversation.d.ts +1 -1
  67. package/dist/components/conversation.js +6 -5
  68. package/dist/components/conversation.js.map +1 -1
  69. package/dist/components/copy-button.d.ts +1 -1
  70. package/dist/components/copy-button.js +3 -2
  71. package/dist/components/copy-button.js.map +1 -1
  72. package/dist/components/data-table.d.ts +7 -2
  73. package/dist/components/data-table.js +16 -42
  74. package/dist/components/data-table.js.map +1 -1
  75. package/dist/components/dialog.d.ts +18 -9
  76. package/dist/components/dialog.js +38 -22
  77. package/dist/components/dialog.js.map +1 -1
  78. package/dist/components/dropdown-menu.d.ts +14 -13
  79. package/dist/components/dropdown-menu.js +33 -23
  80. package/dist/components/dropdown-menu.js.map +1 -1
  81. package/dist/components/editor-tabs.d.ts +1 -1
  82. package/dist/components/editor-tabs.js +6 -5
  83. package/dist/components/editor-tabs.js.map +1 -1
  84. package/dist/components/empty-state.d.ts +5 -5
  85. package/dist/components/empty-state.js +16 -11
  86. package/dist/components/empty-state.js.map +1 -1
  87. package/dist/components/error-summary.d.ts +21 -0
  88. package/dist/components/error-summary.js +62 -0
  89. package/dist/components/error-summary.js.map +1 -0
  90. package/dist/components/field.d.ts +66 -7
  91. package/dist/components/field.js +151 -20
  92. package/dist/components/field.js.map +1 -1
  93. package/dist/components/form-actions.d.ts +18 -0
  94. package/dist/components/form-actions.js +30 -0
  95. package/dist/components/form-actions.js.map +1 -0
  96. package/dist/components/icon-button.d.ts +3 -1
  97. package/dist/components/icon-button.js +5 -3
  98. package/dist/components/icon-button.js.map +1 -1
  99. package/dist/components/input.d.ts +42 -7
  100. package/dist/components/input.js +53 -10
  101. package/dist/components/input.js.map +1 -1
  102. package/dist/components/kbd.d.ts +2 -2
  103. package/dist/components/kbd.js +7 -5
  104. package/dist/components/kbd.js.map +1 -1
  105. package/dist/components/label.d.ts +6 -1
  106. package/dist/components/label.js +10 -4
  107. package/dist/components/label.js.map +1 -1
  108. package/dist/components/markdown.d.ts +4 -3
  109. package/dist/components/markdown.js +7 -6
  110. package/dist/components/markdown.js.map +1 -1
  111. package/dist/components/menubar.d.ts +16 -14
  112. package/dist/components/menubar.js +39 -27
  113. package/dist/components/menubar.js.map +1 -1
  114. package/dist/components/message-actions.d.ts +3 -3
  115. package/dist/components/message-actions.js +15 -12
  116. package/dist/components/message-actions.js.map +1 -1
  117. package/dist/components/message.d.ts +1 -1
  118. package/dist/components/message.js +5 -3
  119. package/dist/components/message.js.map +1 -1
  120. package/dist/components/mobile-nav.d.ts +1 -1
  121. package/dist/components/mobile-nav.js +6 -5
  122. package/dist/components/mobile-nav.js.map +1 -1
  123. package/dist/components/native-select.d.ts +16 -0
  124. package/dist/components/native-select.js +33 -0
  125. package/dist/components/native-select.js.map +1 -0
  126. package/dist/components/navigation-menu.d.ts +12 -11
  127. package/dist/components/navigation-menu.js +32 -23
  128. package/dist/components/navigation-menu.js.map +1 -1
  129. package/dist/components/number-input.d.ts +23 -0
  130. package/dist/components/number-input.js +45 -0
  131. package/dist/components/number-input.js.map +1 -0
  132. package/dist/components/onboarding-checklist.d.ts +1 -1
  133. package/dist/components/onboarding-checklist.js +4 -3
  134. package/dist/components/onboarding-checklist.js.map +1 -1
  135. package/dist/components/page-header.d.ts +7 -6
  136. package/dist/components/page-header.js +22 -15
  137. package/dist/components/page-header.js.map +1 -1
  138. package/dist/components/pagination.d.ts +1 -1
  139. package/dist/components/pagination.js +3 -2
  140. package/dist/components/pagination.js.map +1 -1
  141. package/dist/components/popover.d.ts +13 -10
  142. package/dist/components/popover.js +23 -17
  143. package/dist/components/popover.js.map +1 -1
  144. package/dist/components/progress.d.ts +1 -1
  145. package/dist/components/progress.js +6 -5
  146. package/dist/components/progress.js.map +1 -1
  147. package/dist/components/radio-group.d.ts +22 -3
  148. package/dist/components/radio-group.js +51 -10
  149. package/dist/components/radio-group.js.map +1 -1
  150. package/dist/components/reasoning.d.ts +3 -3
  151. package/dist/components/reasoning.js +9 -7
  152. package/dist/components/reasoning.js.map +1 -1
  153. package/dist/components/scroll-area.d.ts +3 -2
  154. package/dist/components/scroll-area.js +10 -7
  155. package/dist/components/scroll-area.js.map +1 -1
  156. package/dist/components/secret-input.d.ts +3 -2
  157. package/dist/components/secret-input.js +6 -4
  158. package/dist/components/secret-input.js.map +1 -1
  159. package/dist/components/select.d.ts +11 -6
  160. package/dist/components/select.js +24 -18
  161. package/dist/components/select.js.map +1 -1
  162. package/dist/components/separator.d.ts +1 -1
  163. package/dist/components/separator.js +4 -3
  164. package/dist/components/separator.js.map +1 -1
  165. package/dist/components/sheet.d.ts +10 -8
  166. package/dist/components/sheet.js +31 -20
  167. package/dist/components/sheet.js.map +1 -1
  168. package/dist/components/skeleton.d.ts +2 -1
  169. package/dist/components/skeleton.js +6 -4
  170. package/dist/components/skeleton.js.map +1 -1
  171. package/dist/components/slider.d.ts +10 -6
  172. package/dist/components/slider.js +15 -7
  173. package/dist/components/slider.js.map +1 -1
  174. package/dist/components/source.d.ts +2 -2
  175. package/dist/components/source.js +9 -7
  176. package/dist/components/source.js.map +1 -1
  177. package/dist/components/spinner.d.ts +4 -2
  178. package/dist/components/spinner.js +4 -3
  179. package/dist/components/spinner.js.map +1 -1
  180. package/dist/components/stat-card.d.ts +27 -2
  181. package/dist/components/stat-card.js +69 -9
  182. package/dist/components/stat-card.js.map +1 -1
  183. package/dist/components/status.d.ts +7 -6
  184. package/dist/components/status.js +11 -5
  185. package/dist/components/status.js.map +1 -1
  186. package/dist/components/steps.d.ts +1 -1
  187. package/dist/components/steps.js +4 -3
  188. package/dist/components/steps.js.map +1 -1
  189. package/dist/components/switch.d.ts +46 -2
  190. package/dist/components/switch.js +85 -8
  191. package/dist/components/switch.js.map +1 -1
  192. package/dist/components/table.d.ts +29 -12
  193. package/dist/components/table.js +79 -34
  194. package/dist/components/table.js.map +1 -1
  195. package/dist/components/tabs.d.ts +9 -4
  196. package/dist/components/tabs.js +22 -13
  197. package/dist/components/tabs.js.map +1 -1
  198. package/dist/components/textarea.d.ts +6 -1
  199. package/dist/components/textarea.js +3 -3
  200. package/dist/components/textarea.js.map +1 -1
  201. package/dist/components/toast.d.ts +10 -6
  202. package/dist/components/toast.js +27 -18
  203. package/dist/components/toast.js.map +1 -1
  204. package/dist/components/toaster.d.ts +4 -2
  205. package/dist/components/toaster.js +6 -2
  206. package/dist/components/toaster.js.map +1 -1
  207. package/dist/components/tool-call.d.ts +2 -2
  208. package/dist/components/tool-call.js +10 -8
  209. package/dist/components/tool-call.js.map +1 -1
  210. package/dist/components/toolbar.d.ts +9 -4
  211. package/dist/components/toolbar.js +14 -9
  212. package/dist/components/toolbar.js.map +1 -1
  213. package/dist/components/tooltip.d.ts +3 -2
  214. package/dist/components/tooltip.js +7 -4
  215. package/dist/components/tooltip.js.map +1 -1
  216. package/dist/components/tour.js +2 -2
  217. package/dist/components/tour.js.map +1 -1
  218. package/dist/components/tree-view.d.ts +1 -1
  219. package/dist/components/tree-view.js +9 -5
  220. package/dist/components/tree-view.js.map +1 -1
  221. package/dist/components/voice-recorder.d.ts +1 -1
  222. package/dist/components/voice-recorder.js +4 -2
  223. package/dist/components/voice-recorder.js.map +1 -1
  224. package/dist/index.d.ts +6 -1
  225. package/dist/index.js +17 -12
  226. package/dist/lib/media.d.ts +18 -0
  227. package/dist/lib/media.js +34 -0
  228. package/dist/lib/media.js.map +1 -0
  229. package/dist/lib/utils.d.ts +32 -0
  230. package/dist/lib/utils.js +33 -1
  231. package/dist/lib/utils.js.map +1 -1
  232. package/dist/mui/index.js +20 -8
  233. package/dist/mui/index.js.map +1 -1
  234. package/dist/styles.css +1 -1
  235. package/dist/theme.css +36 -17
  236. package/dist/tokens.d.ts +78 -36
  237. package/dist/tokens.js +63 -32
  238. package/dist/tokens.js.map +1 -1
  239. package/package.json +5 -3
@@ -1,29 +1,58 @@
1
1
  "use client";
2
- import { cn } from "../lib/utils.js";
2
+ import { cn, focusRingClasses } from "../lib/utils.js";
3
3
  import * as React from "react";
4
- import { jsx } from "react/jsx-runtime";
4
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
5
  //#region src/components/table.tsx
6
- /** True while the element's content is larger than its box. */
7
- function useOverflows(ref, enabled) {
6
+ /** How a box overflows sideways: more to the `end`, more to the `start`, or `both`. */
7
+ function overflowState(el) {
8
+ const max = el.scrollWidth - el.clientWidth;
9
+ if (max <= 1) return void 0;
10
+ if (el.scrollLeft <= 1) return "end";
11
+ if (el.scrollLeft >= max - 1) return "start";
12
+ return "both";
13
+ }
14
+ /**
15
+ * Tracks whether the element's content is larger than its box, and which way
16
+ * it scrolls sideways. Nothing is measured on the server or in jsdom.
17
+ */
18
+ function useOverflow(ref) {
8
19
  const [overflows, setOverflows] = React.useState(false);
20
+ const [horizontal, setHorizontal] = React.useState();
9
21
  React.useEffect(() => {
10
22
  const el = ref.current;
11
- if (!enabled || !el) return;
12
- const update = () => setOverflows(el.scrollWidth > el.clientWidth || el.scrollHeight > el.clientHeight);
23
+ if (!el) return;
24
+ const update = () => {
25
+ setOverflows(el.scrollWidth > el.clientWidth || el.scrollHeight > el.clientHeight);
26
+ setHorizontal(overflowState(el));
27
+ };
13
28
  update();
14
- if (typeof ResizeObserver === "undefined") return;
29
+ el.addEventListener("scroll", update, { passive: true });
30
+ if (typeof ResizeObserver === "undefined") return () => el.removeEventListener("scroll", update);
15
31
  const ro = new ResizeObserver(update);
16
32
  ro.observe(el);
17
33
  if (el.firstElementChild) ro.observe(el.firstElementChild);
18
- return () => ro.disconnect();
19
- }, [ref, enabled]);
20
- return overflows;
34
+ return () => {
35
+ ro.disconnect();
36
+ el.removeEventListener("scroll", update);
37
+ };
38
+ }, [ref]);
39
+ return {
40
+ overflows,
41
+ horizontal
42
+ };
21
43
  }
22
44
  function assignRef(ref, node) {
23
45
  if (typeof ref === "function") ref(node);
24
46
  else if (ref) ref.current = node;
25
47
  }
26
- function Table({ className, density = "default", stickyHeader = false, containerClassName, containerProps, scrollLabel, ...props }) {
48
+ /**
49
+ * The scroll container fades on the side with more to see (never over a
50
+ * pinned column), shows its focus outline inside the box (the frame around
51
+ * it would clip an offset one), and drops the fade while focused so the
52
+ * whole outline shows.
53
+ */
54
+ var containerClasses = cn("group/table relative w-full overflow-auto", "data-[overflow=end]:[mask-image:linear-gradient(to_right,#000_calc(100%-2rem),transparent)]", "data-[overflow=start]:[mask-image:linear-gradient(to_left,#000_calc(100%-2rem),transparent)]", "data-[overflow=both]:[mask-image:linear-gradient(to_right,transparent,#000_2rem,#000_calc(100%-2rem),transparent)]", "data-[pinned]:data-[overflow=start]:[mask-image:none] data-[pinned]:data-[overflow=both]:[mask-image:linear-gradient(to_right,#000_calc(100%-2rem),transparent)]", focusRingClasses, "focus-visible:outline-offset-[-2px] focus-visible:[mask-image:none]");
55
+ var Table = React.forwardRef(function Table({ className, density = "default", stickyHeader = false, containerClassName, containerProps, scrollLabel, pinFirstColumn = false, overflowHint = "Swipe for more", ...props }, ref) {
27
56
  const { className: containerPropsClassName, ref: containerRef, ...wrapperProps } = containerProps ?? {};
28
57
  const local = React.useRef(null);
29
58
  const setRef = React.useCallback((node) => {
@@ -31,78 +60,94 @@ function Table({ className, density = "default", stickyHeader = false, container
31
60
  assignRef(containerRef, node);
32
61
  }, [containerRef]);
33
62
  const named = Boolean(scrollLabel || wrapperProps["aria-label"] || wrapperProps["aria-labelledby"]);
34
- const overflows = useOverflows(local, named);
35
- return /* @__PURE__ */ jsx("div", {
63
+ const { overflows, horizontal } = useOverflow(local);
64
+ const hint = overflowHint !== false && (horizontal === "end" || horizontal === "both");
65
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
36
66
  "data-slot": "table-container",
37
67
  "data-density": density,
38
68
  "data-sticky": stickyHeader || void 0,
69
+ "data-pinned": pinFirstColumn || void 0,
70
+ "data-overflow": horizontal,
39
71
  role: named ? "region" : void 0,
40
72
  "aria-label": scrollLabel,
41
73
  tabIndex: named && overflows ? 0 : void 0,
42
74
  ...wrapperProps,
43
75
  ref: setRef,
44
- className: cn("group/table relative w-full overflow-auto", containerClassName, containerPropsClassName),
76
+ className: cn(containerClasses, containerClassName, containerPropsClassName),
45
77
  children: /* @__PURE__ */ jsx("table", {
78
+ ref,
46
79
  "data-slot": "table",
47
80
  className: cn("w-full caption-bottom text-[13px]", className),
48
81
  ...props
49
82
  })
50
- });
51
- }
52
- function TableHeader({ className, ...props }) {
83
+ }), hint && /* @__PURE__ */ jsxs("p", {
84
+ "data-slot": "table-overflow-hint",
85
+ "aria-hidden": true,
86
+ className: "hidden w-full px-3 py-1.5 text-right text-[11.5px] text-muted-foreground pointer-coarse:block",
87
+ children: [overflowHint, " →"]
88
+ })] });
89
+ });
90
+ var TableHeader = React.forwardRef(function TableHeader({ className, ...props }, ref) {
53
91
  return /* @__PURE__ */ jsx("thead", {
92
+ ref,
54
93
  "data-slot": "table-header",
55
94
  className: cn("bg-surface-muted [&_tr]:border-b group-data-[sticky]/table:sticky group-data-[sticky]/table:top-0 group-data-[sticky]/table:z-10", className),
56
95
  ...props
57
96
  });
58
- }
59
- function TableBody({ className, ...props }) {
97
+ });
98
+ var TableBody = React.forwardRef(function TableBody({ className, ...props }, ref) {
60
99
  return /* @__PURE__ */ jsx("tbody", {
100
+ ref,
61
101
  "data-slot": "table-body",
62
102
  className: cn("[&_tr:last-child]:border-0", className),
63
103
  ...props
64
104
  });
65
- }
66
- function TableFooter({ className, ...props }) {
105
+ });
106
+ var TableFooter = React.forwardRef(function TableFooter({ className, ...props }, ref) {
67
107
  return /* @__PURE__ */ jsx("tfoot", {
108
+ ref,
68
109
  "data-slot": "table-footer",
69
110
  className: cn("border-t bg-surface-muted font-medium [&>tr]:last:border-b-0", className),
70
111
  ...props
71
112
  });
72
- }
73
- /** Set `data-state="selected"` (or `selected`) to mark a chosen row. */
74
- function TableRow({ className, selected, ...props }) {
113
+ });
114
+ /** Set `selected` to mark a chosen row: a soft fill and a brand bar on its left edge. */
115
+ var TableRow = React.forwardRef(function TableRow({ className, selected, ...props }, ref) {
75
116
  return /* @__PURE__ */ jsx("tr", {
117
+ ref,
76
118
  "data-slot": "table-row",
77
119
  "data-state": selected ? "selected" : void 0,
78
120
  "aria-selected": selected || void 0,
79
121
  className: cn("border-b transition-colors hover:bg-muted/60 data-[state=selected]:bg-brand-soft/60 data-[state=selected]:shadow-[inset_2px_0_0_var(--color-brand)]", className),
80
122
  ...props
81
123
  });
82
- }
124
+ });
83
125
  /** `numeric` right-aligns with tabular figures, for counts, money and durations. */
84
- function TableHead({ className, numeric, ...props }) {
126
+ var TableHead = React.forwardRef(function TableHead({ className, numeric, ...props }, ref) {
85
127
  return /* @__PURE__ */ jsx("th", {
128
+ ref,
86
129
  "data-slot": "table-head",
87
- className: cn("h-9 px-3 text-left align-middle text-[11px] font-semibold tracking-[0.06em] whitespace-nowrap text-muted-foreground uppercase group-data-[density=compact]/table:h-8 [&:has([role=checkbox])]:w-10 [&:has([role=checkbox])]:pr-0", numeric && "text-right tabular-nums", className),
130
+ className: cn("h-9 px-3 text-left align-middle text-[11px] font-semibold tracking-[0.06em] whitespace-nowrap text-muted-foreground uppercase group-data-[density=compact]/table:h-8 [&:has([role=checkbox])]:w-10 [&:has([role=checkbox])]:pr-0", "first:group-data-[pinned]/table:sticky first:group-data-[pinned]/table:left-0 first:group-data-[pinned]/table:z-[2] first:group-data-[pinned]/table:bg-surface-muted first:group-data-[pinned]/table:shadow-[inset_-1px_0_0_var(--border)]", numeric && "text-right tabular-nums", className),
88
131
  ...props
89
132
  });
90
- }
91
- function TableCell({ className, numeric, ...props }) {
133
+ });
134
+ var TableCell = React.forwardRef(function TableCell({ className, numeric, ...props }, ref) {
92
135
  return /* @__PURE__ */ jsx("td", {
136
+ ref,
93
137
  "data-slot": "table-cell",
94
- className: cn("h-10 px-3 align-middle whitespace-nowrap group-data-[density=compact]/table:h-8 [&:has([role=checkbox])]:pr-0", numeric && "text-right font-mono text-[12.5px] tabular-nums", className),
138
+ className: cn("h-10 px-3 align-middle whitespace-nowrap group-data-[density=compact]/table:h-8 pointer-coarse:group-data-[density=default]/table:h-11 [&:has([role=checkbox])]:pr-0", "first:group-data-[pinned]/table:sticky first:group-data-[pinned]/table:left-0 first:group-data-[pinned]/table:z-[1] first:group-data-[pinned]/table:bg-surface first:group-data-[pinned]/table:shadow-[inset_-1px_0_0_var(--border)] first:group-data-[pinned]/table:max-w-[min(11rem,45vw)] first:group-data-[pinned]/table:whitespace-normal", numeric && "text-right font-mono text-[12.5px] tabular-nums", className),
95
139
  ...props
96
140
  });
97
- }
98
- function TableCaption({ className, ...props }) {
141
+ });
142
+ var TableCaption = React.forwardRef(function TableCaption({ className, ...props }, ref) {
99
143
  return /* @__PURE__ */ jsx("caption", {
144
+ ref,
100
145
  "data-slot": "table-caption",
101
146
  className: cn("mt-3 text-xs text-muted-foreground", className),
102
147
  ...props
103
148
  });
104
- }
149
+ });
105
150
  //#endregion
106
- export { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow };
151
+ export { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, overflowState };
107
152
 
108
153
  //# sourceMappingURL=table.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"table.js","names":[],"sources":["../../src/components/table.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nexport interface TableProps extends React.ComponentProps<'table'> {\n /** `compact` for dense ops screens (32px rows), `default` 40px. */\n density?: 'compact' | 'default';\n /** Keep the header visible while the container scrolls; give it a height. */\n stickyHeader?: boolean;\n containerClassName?: string;\n /**\n * Props for the scrolling wrapper (`tabIndex`, `role`, `aria-*`, `ref`, ...).\n * Anything set here wins over what `scrollLabel` sets.\n */\n containerProps?: React.ComponentProps<'div'>;\n /**\n * Accessible name for the scroll container. With it (or an `aria-label` /\n * `aria-labelledby` in `containerProps`) the wrapper becomes a named region\n * that joins the tab order while its content overflows, so keyboard users\n * can scroll it (WCAG 2.1.1, axe scrollable-region-focusable).\n */\n scrollLabel?: string;\n}\n\n/** True while the element's content is larger than its box. */\nfunction useOverflows(ref: React.RefObject<HTMLElement | null>, enabled: boolean): boolean {\n const [overflows, setOverflows] = React.useState(false);\n React.useEffect(() => {\n const el = ref.current;\n if (!enabled || !el) return;\n const update = () =>\n setOverflows(el.scrollWidth > el.clientWidth || el.scrollHeight > el.clientHeight);\n update();\n if (typeof ResizeObserver === 'undefined') return;\n const ro = new ResizeObserver(update);\n ro.observe(el);\n if (el.firstElementChild) ro.observe(el.firstElementChild);\n return () => ro.disconnect();\n }, [ref, enabled]);\n return overflows;\n}\n\nfunction assignRef<T>(ref: React.Ref<T> | undefined, node: T | null) {\n if (typeof ref === 'function') ref(node);\n else if (ref) ref.current = node;\n}\n\nfunction Table({\n className,\n density = 'default',\n stickyHeader = false,\n containerClassName,\n containerProps,\n scrollLabel,\n ...props\n}: TableProps) {\n const {\n className: containerPropsClassName,\n ref: containerRef,\n ...wrapperProps\n } = containerProps ?? {};\n const local = React.useRef<HTMLDivElement | null>(null);\n const setRef = React.useCallback(\n (node: HTMLDivElement | null) => {\n local.current = node;\n assignRef(containerRef, node);\n },\n [containerRef],\n );\n const named = Boolean(\n scrollLabel || wrapperProps['aria-label'] || wrapperProps['aria-labelledby'],\n );\n const overflows = useOverflows(local, named);\n return (\n <div\n data-slot=\"table-container\"\n data-density={density}\n data-sticky={stickyHeader || undefined}\n role={named ? 'region' : undefined}\n aria-label={scrollLabel}\n // A scrollable region must be reachable by keyboard; only while it scrolls.\n tabIndex={named && overflows ? 0 : undefined}\n {...wrapperProps}\n ref={setRef}\n className={cn(\n 'group/table relative w-full overflow-auto',\n containerClassName,\n containerPropsClassName,\n )}\n >\n <table\n data-slot=\"table\"\n className={cn('w-full caption-bottom text-[13px]', className)}\n {...props}\n />\n </div>\n );\n}\n\nfunction TableHeader({ className, ...props }: React.ComponentProps<'thead'>) {\n return (\n <thead\n data-slot=\"table-header\"\n className={cn(\n 'bg-surface-muted [&_tr]:border-b group-data-[sticky]/table:sticky group-data-[sticky]/table:top-0 group-data-[sticky]/table:z-10',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction TableBody({ className, ...props }: React.ComponentProps<'tbody'>) {\n return (\n <tbody\n data-slot=\"table-body\"\n className={cn('[&_tr:last-child]:border-0', className)}\n {...props}\n />\n );\n}\n\nfunction TableFooter({ className, ...props }: React.ComponentProps<'tfoot'>) {\n return (\n <tfoot\n data-slot=\"table-footer\"\n className={cn('border-t bg-surface-muted font-medium [&>tr]:last:border-b-0', className)}\n {...props}\n />\n );\n}\n\n/** Set `data-state=\"selected\"` (or `selected`) to mark a chosen row. */\nfunction TableRow({\n className,\n selected,\n ...props\n}: React.ComponentProps<'tr'> & { selected?: boolean }) {\n return (\n <tr\n data-slot=\"table-row\"\n data-state={selected ? 'selected' : undefined}\n aria-selected={selected || undefined}\n className={cn(\n 'border-b transition-colors hover:bg-muted/60 data-[state=selected]:bg-brand-soft/60 data-[state=selected]:shadow-[inset_2px_0_0_var(--color-brand)]',\n className,\n )}\n {...props}\n />\n );\n}\n\n/** `numeric` right-aligns with tabular figures, for counts, money and durations. */\nfunction TableHead({\n className,\n numeric,\n ...props\n}: React.ComponentProps<'th'> & { numeric?: boolean }) {\n return (\n <th\n data-slot=\"table-head\"\n className={cn(\n 'h-9 px-3 text-left align-middle text-[11px] font-semibold tracking-[0.06em] whitespace-nowrap text-muted-foreground uppercase group-data-[density=compact]/table:h-8 [&:has([role=checkbox])]:w-10 [&:has([role=checkbox])]:pr-0',\n numeric && 'text-right tabular-nums',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction TableCell({\n className,\n numeric,\n ...props\n}: React.ComponentProps<'td'> & { numeric?: boolean }) {\n return (\n <td\n data-slot=\"table-cell\"\n className={cn(\n 'h-10 px-3 align-middle whitespace-nowrap group-data-[density=compact]/table:h-8 [&:has([role=checkbox])]:pr-0',\n numeric && 'text-right font-mono text-[12.5px] tabular-nums',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction TableCaption({ className, ...props }: React.ComponentProps<'caption'>) {\n return (\n <caption\n data-slot=\"table-caption\"\n className={cn('mt-3 text-xs text-muted-foreground', className)}\n {...props}\n />\n );\n}\n\nexport { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow };\n"],"mappings":"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"}
1
+ {"version":3,"file":"table.js","names":["_Fragment"],"sources":["../../src/components/table.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { cn, focusRingClasses } from '../lib/utils';\n\nexport interface TableProps extends React.ComponentProps<'table'> {\n /** `compact` for dense ops screens (32px rows), `default` 40px. */\n density?: 'compact' | 'default';\n /** Keep the header visible while the container scrolls; give it a height. */\n stickyHeader?: boolean;\n containerClassName?: string;\n /**\n * Props for the scrolling wrapper (`tabIndex`, `role`, `aria-*`, `ref`, ...).\n * Anything set here wins over what `scrollLabel` sets.\n */\n containerProps?: React.ComponentProps<'div'>;\n /**\n * Accessible name for the scroll container. With it (or an `aria-label` /\n * `aria-labelledby` in `containerProps`) the wrapper becomes a named region\n * that joins the tab order while its content overflows, so keyboard users\n * can scroll it (WCAG 2.1.1, axe scrollable-region-focusable).\n */\n scrollLabel?: string;\n /**\n * Keep the first column in view while the table scrolls sideways (a name\n * column beside numbers). The pinned cells take the surface colour.\n */\n pinFirstColumn?: boolean;\n /**\n * The line under a table that scrolls sideways, until it is scrolled to the\n * end. Shown on touch screens only (a mouse has a scrollbar). `false`\n * turns it off.\n */\n overflowHint?: React.ReactNode | false;\n}\n\n/** How a box overflows sideways: more to the `end`, more to the `start`, or `both`. */\nexport function overflowState(el: {\n scrollLeft: number;\n scrollWidth: number;\n clientWidth: number;\n}): 'start' | 'end' | 'both' | undefined {\n const max = el.scrollWidth - el.clientWidth;\n if (max <= 1) return undefined;\n if (el.scrollLeft <= 1) return 'end';\n if (el.scrollLeft >= max - 1) return 'start';\n return 'both';\n}\n\n/**\n * Tracks whether the element's content is larger than its box, and which way\n * it scrolls sideways. Nothing is measured on the server or in jsdom.\n */\nfunction useOverflow(ref: React.RefObject<HTMLElement | null>) {\n const [overflows, setOverflows] = React.useState(false);\n const [horizontal, setHorizontal] = React.useState<ReturnType<typeof overflowState>>();\n React.useEffect(() => {\n const el = ref.current;\n if (!el) return;\n const update = () => {\n setOverflows(el.scrollWidth > el.clientWidth || el.scrollHeight > el.clientHeight);\n setHorizontal(overflowState(el));\n };\n update();\n el.addEventListener('scroll', update, { passive: true });\n if (typeof ResizeObserver === 'undefined')\n return () => el.removeEventListener('scroll', update);\n const ro = new ResizeObserver(update);\n ro.observe(el);\n if (el.firstElementChild) ro.observe(el.firstElementChild);\n return () => {\n ro.disconnect();\n el.removeEventListener('scroll', update);\n };\n }, [ref]);\n return { overflows, horizontal };\n}\n\nfunction assignRef<T>(ref: React.Ref<T> | undefined, node: T | null) {\n if (typeof ref === 'function') ref(node);\n else if (ref) ref.current = node;\n}\n\n/**\n * The scroll container fades on the side with more to see (never over a\n * pinned column), shows its focus outline inside the box (the frame around\n * it would clip an offset one), and drops the fade while focused so the\n * whole outline shows.\n */\nconst containerClasses = cn(\n 'group/table relative w-full overflow-auto',\n 'data-[overflow=end]:[mask-image:linear-gradient(to_right,#000_calc(100%-2rem),transparent)]',\n 'data-[overflow=start]:[mask-image:linear-gradient(to_left,#000_calc(100%-2rem),transparent)]',\n 'data-[overflow=both]:[mask-image:linear-gradient(to_right,transparent,#000_2rem,#000_calc(100%-2rem),transparent)]',\n 'data-[pinned]:data-[overflow=start]:[mask-image:none] data-[pinned]:data-[overflow=both]:[mask-image:linear-gradient(to_right,#000_calc(100%-2rem),transparent)]',\n focusRingClasses,\n 'focus-visible:outline-offset-[-2px] focus-visible:[mask-image:none]',\n);\n\nconst Table = React.forwardRef<HTMLTableElement, TableProps>(function Table(\n {\n className,\n density = 'default',\n stickyHeader = false,\n containerClassName,\n containerProps,\n scrollLabel,\n pinFirstColumn = false,\n overflowHint = 'Swipe for more',\n ...props\n },\n ref,\n) {\n const {\n className: containerPropsClassName,\n ref: containerRef,\n ...wrapperProps\n } = containerProps ?? {};\n const local = React.useRef<HTMLDivElement | null>(null);\n const setRef = React.useCallback(\n (node: HTMLDivElement | null) => {\n local.current = node;\n assignRef(containerRef, node);\n },\n [containerRef],\n );\n const named = Boolean(\n scrollLabel || wrapperProps['aria-label'] || wrapperProps['aria-labelledby'],\n );\n const { overflows, horizontal } = useOverflow(local);\n const hint = overflowHint !== false && (horizontal === 'end' || horizontal === 'both');\n return (\n <>\n <div\n data-slot=\"table-container\"\n data-density={density}\n data-sticky={stickyHeader || undefined}\n data-pinned={pinFirstColumn || undefined}\n data-overflow={horizontal}\n role={named ? 'region' : undefined}\n aria-label={scrollLabel}\n // A scrollable region must be reachable by keyboard; only while it scrolls.\n tabIndex={named && overflows ? 0 : undefined}\n {...wrapperProps}\n ref={setRef}\n className={cn(containerClasses, containerClassName, containerPropsClassName)}\n >\n <table\n ref={ref}\n data-slot=\"table\"\n className={cn('w-full caption-bottom text-[13px]', className)}\n {...props}\n />\n </div>\n {hint && (\n <p\n data-slot=\"table-overflow-hint\"\n aria-hidden\n className=\"hidden w-full px-3 py-1.5 text-right text-[11.5px] text-muted-foreground pointer-coarse:block\"\n >\n {overflowHint} →\n </p>\n )}\n </>\n );\n});\n\nconst TableHeader = React.forwardRef<HTMLTableSectionElement, React.ComponentProps<'thead'>>(\n function TableHeader({ className, ...props }, ref) {\n return (\n <thead\n ref={ref}\n data-slot=\"table-header\"\n className={cn(\n 'bg-surface-muted [&_tr]:border-b group-data-[sticky]/table:sticky group-data-[sticky]/table:top-0 group-data-[sticky]/table:z-10',\n className,\n )}\n {...props}\n />\n );\n },\n);\n\nconst TableBody = React.forwardRef<HTMLTableSectionElement, React.ComponentProps<'tbody'>>(\n function TableBody({ className, ...props }, ref) {\n return (\n <tbody\n ref={ref}\n data-slot=\"table-body\"\n className={cn('[&_tr:last-child]:border-0', className)}\n {...props}\n />\n );\n },\n);\n\nconst TableFooter = React.forwardRef<HTMLTableSectionElement, React.ComponentProps<'tfoot'>>(\n function TableFooter({ className, ...props }, ref) {\n return (\n <tfoot\n ref={ref}\n data-slot=\"table-footer\"\n className={cn('border-t bg-surface-muted font-medium [&>tr]:last:border-b-0', className)}\n {...props}\n />\n );\n },\n);\n\n/** Set `selected` to mark a chosen row: a soft fill and a brand bar on its left edge. */\nconst TableRow = React.forwardRef<\n HTMLTableRowElement,\n React.ComponentProps<'tr'> & { selected?: boolean }\n>(function TableRow({ className, selected, ...props }, ref) {\n return (\n <tr\n ref={ref}\n data-slot=\"table-row\"\n data-state={selected ? 'selected' : undefined}\n aria-selected={selected || undefined}\n className={cn(\n 'border-b transition-colors hover:bg-muted/60 data-[state=selected]:bg-brand-soft/60 data-[state=selected]:shadow-[inset_2px_0_0_var(--color-brand)]',\n className,\n )}\n {...props}\n />\n );\n});\n\n// Pinned first cells (Table `pinFirstColumn`): sticky, with the surface\n// behind them so scrolled columns pass underneath, and a hairline on their\n// right edge.\n\n/** `numeric` right-aligns with tabular figures, for counts, money and durations. */\nconst TableHead = React.forwardRef<\n HTMLTableCellElement,\n React.ComponentProps<'th'> & { numeric?: boolean }\n>(function TableHead({ className, numeric, ...props }, ref) {\n return (\n <th\n ref={ref}\n data-slot=\"table-head\"\n className={cn(\n 'h-9 px-3 text-left align-middle text-[11px] font-semibold tracking-[0.06em] whitespace-nowrap text-muted-foreground uppercase group-data-[density=compact]/table:h-8 [&:has([role=checkbox])]:w-10 [&:has([role=checkbox])]:pr-0',\n 'first:group-data-[pinned]/table:sticky first:group-data-[pinned]/table:left-0 first:group-data-[pinned]/table:z-[2] first:group-data-[pinned]/table:bg-surface-muted first:group-data-[pinned]/table:shadow-[inset_-1px_0_0_var(--border)]',\n numeric && 'text-right tabular-nums',\n className,\n )}\n {...props}\n />\n );\n});\n\nconst TableCell = React.forwardRef<\n HTMLTableCellElement,\n React.ComponentProps<'td'> & { numeric?: boolean }\n>(function TableCell({ className, numeric, ...props }, ref) {\n return (\n <td\n ref={ref}\n data-slot=\"table-cell\"\n className={cn(\n 'h-10 px-3 align-middle whitespace-nowrap group-data-[density=compact]/table:h-8 pointer-coarse:group-data-[density=default]/table:h-11 [&:has([role=checkbox])]:pr-0',\n 'first:group-data-[pinned]/table:sticky first:group-data-[pinned]/table:left-0 first:group-data-[pinned]/table:z-[1] first:group-data-[pinned]/table:bg-surface first:group-data-[pinned]/table:shadow-[inset_-1px_0_0_var(--border)] first:group-data-[pinned]/table:max-w-[min(11rem,45vw)] first:group-data-[pinned]/table:whitespace-normal',\n numeric && 'text-right font-mono text-[12.5px] tabular-nums',\n className,\n )}\n {...props}\n />\n );\n});\n\nconst TableCaption = React.forwardRef<HTMLTableCaptionElement, React.ComponentProps<'caption'>>(\n function TableCaption({ className, ...props }, ref) {\n return (\n <caption\n ref={ref}\n data-slot=\"table-caption\"\n className={cn('mt-3 text-xs text-muted-foreground', className)}\n {...props}\n />\n );\n },\n);\n\nexport { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow };\n"],"mappings":"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"}
@@ -1,7 +1,12 @@
1
1
  import * as React from 'react';
2
2
  import * as TabsPrimitive from '../primitives/vendor/radix/react-tabs';
3
- declare function Tabs({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Root>): React.JSX.Element;
4
- declare function TabsList({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.List>): React.JSX.Element;
5
- declare function TabsTrigger({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Trigger>): React.JSX.Element;
6
- declare function TabsContent({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Content>): React.JSX.Element;
3
+ declare const Tabs: React.ForwardRefExoticComponent<Omit<TabsPrimitive.TabsProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
4
+ /**
5
+ * A 36px strip with a 10px radius; a strip wider than its container scrolls
6
+ * sideways rather than pushing the layout.
7
+ */
8
+ declare const TabsList: React.ForwardRefExoticComponent<Omit<TabsPrimitive.TabsListProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
9
+ /** A 28px tab with a 6px radius (the strip's 10px less its 4px inset); 44px tall to a touch. */
10
+ declare const TabsTrigger: React.ForwardRefExoticComponent<Omit<TabsPrimitive.TabsTriggerProps & React.RefAttributes<HTMLButtonElement>, "ref"> & React.RefAttributes<HTMLButtonElement>>;
11
+ declare const TabsContent: React.ForwardRefExoticComponent<Omit<TabsPrimitive.TabsContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
7
12
  export { Tabs, TabsContent, TabsList, TabsTrigger };
@@ -1,37 +1,46 @@
1
1
  "use client";
2
- import { cn } from "../lib/utils.js";
2
+ import { cn, focusRingClasses, touchTargetRowClasses } from "../lib/utils.js";
3
3
  import { Content, List, Root, Trigger } from "../primitives/vendor/radix/react-tabs/tabs.js";
4
- import "react";
4
+ import * as React from "react";
5
5
  import { jsx } from "react/jsx-runtime";
6
6
  //#region src/components/tabs.tsx
7
- function Tabs({ className, ...props }) {
7
+ var Tabs = React.forwardRef(function Tabs({ className, ...props }, ref) {
8
8
  return /* @__PURE__ */ jsx(Root, {
9
+ ref,
9
10
  "data-slot": "tabs",
10
11
  className: cn("flex flex-col gap-3", className),
11
12
  ...props
12
13
  });
13
- }
14
- function TabsList({ className, ...props }) {
14
+ });
15
+ /**
16
+ * A 36px strip with a 10px radius; a strip wider than its container scrolls
17
+ * sideways rather than pushing the layout.
18
+ */
19
+ var TabsList = React.forwardRef(function TabsList({ className, ...props }, ref) {
15
20
  return /* @__PURE__ */ jsx(List, {
21
+ ref,
16
22
  "data-slot": "tabs-list",
17
- className: cn("inline-flex h-9 w-fit items-center gap-0.5 rounded-md border border-border bg-surface-muted p-1 text-muted-foreground", className),
23
+ className: cn("inline-flex h-9 w-fit max-w-full items-center gap-0.5 overflow-x-auto rounded-md border border-border bg-surface-muted p-1 text-muted-foreground [scrollbar-width:none]", className),
18
24
  ...props
19
25
  });
20
- }
21
- function TabsTrigger({ className, ...props }) {
26
+ });
27
+ /** A 28px tab with a 6px radius (the strip's 10px less its 4px inset); 44px tall to a touch. */
28
+ var TabsTrigger = React.forwardRef(function TabsTrigger({ className, ...props }, ref) {
22
29
  return /* @__PURE__ */ jsx(Trigger, {
30
+ ref,
23
31
  "data-slot": "tabs-trigger",
24
- className: cn("inline-flex h-7 min-w-0 items-center justify-center gap-1.5 rounded-sm px-2.5 text-[13px] font-semibold whitespace-nowrap outline-none transition-[background-color,color,box-shadow] focus-visible:ring-[3px] focus-visible:ring-ring/20 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-surface data-[state=active]:text-foreground data-[state=active]:shadow-xs hover:text-foreground [&_svg]:size-3.5", className),
32
+ className: cn("inline-flex h-7 min-w-0 shrink-0 items-center justify-center gap-1.5 rounded-xs px-2.5 text-[13px] font-semibold whitespace-nowrap transition-[background-color,color,box-shadow] disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-surface data-[state=active]:text-foreground data-[state=active]:shadow-xs hover:text-foreground [&_svg]:size-4", focusRingClasses, touchTargetRowClasses, className),
25
33
  ...props
26
34
  });
27
- }
28
- function TabsContent({ className, ...props }) {
35
+ });
36
+ var TabsContent = React.forwardRef(function TabsContent({ className, ...props }, ref) {
29
37
  return /* @__PURE__ */ jsx(Content, {
38
+ ref,
30
39
  "data-slot": "tabs-content",
31
- className: cn("min-w-0 flex-1 outline-none data-[state=active]:animate-fade-in", className),
40
+ className: cn("min-w-0 flex-1 data-[state=active]:animate-fade-in", focusRingClasses, className),
32
41
  ...props
33
42
  });
34
- }
43
+ });
35
44
  //#endregion
36
45
  export { Tabs, TabsContent, TabsList, TabsTrigger };
37
46
 
@@ -1 +1 @@
1
- {"version":3,"file":"tabs.js","names":["TabsPrimitive.Root","TabsPrimitive.List","TabsPrimitive.Trigger","TabsPrimitive.Content"],"sources":["../../src/components/tabs.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { cn } from '../lib/utils';\nimport * as TabsPrimitive from '../primitives/vendor/radix/react-tabs';\n\nfunction Tabs({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Root>) {\n return (\n <TabsPrimitive.Root\n data-slot=\"tabs\"\n className={cn('flex flex-col gap-3', className)}\n {...props}\n />\n );\n}\n\nfunction TabsList({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.List>) {\n return (\n <TabsPrimitive.List\n data-slot=\"tabs-list\"\n className={cn(\n 'inline-flex h-9 w-fit items-center gap-0.5 rounded-md border border-border bg-surface-muted p-1 text-muted-foreground',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction TabsTrigger({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Trigger>) {\n return (\n <TabsPrimitive.Trigger\n data-slot=\"tabs-trigger\"\n className={cn(\n 'inline-flex h-7 min-w-0 items-center justify-center gap-1.5 rounded-sm px-2.5 text-[13px] font-semibold whitespace-nowrap outline-none transition-[background-color,color,box-shadow] focus-visible:ring-[3px] focus-visible:ring-ring/20 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-surface data-[state=active]:text-foreground data-[state=active]:shadow-xs hover:text-foreground [&_svg]:size-3.5',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction TabsContent({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Content>) {\n return (\n <TabsPrimitive.Content\n data-slot=\"tabs-content\"\n className={cn('min-w-0 flex-1 outline-none data-[state=active]:animate-fade-in', className)}\n {...props}\n />\n );\n}\n\nexport { Tabs, TabsContent, TabsList, TabsTrigger };\n"],"mappings":";;;;;;AAKA,SAAS,KAAK,EAAE,WAAW,GAAG,SAA0D;CACtF,OACE,oBAACA,MAAD;EACE,aAAU;EACV,WAAW,GAAG,uBAAuB,SAAS;EAC9C,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,SAAS,EAAE,WAAW,GAAG,SAA0D;CAC1F,OACE,oBAACC,MAAD;EACE,aAAU;EACV,WAAW,GACT,yHACA,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,YAAY,EAAE,WAAW,GAAG,SAA6D;CAChG,OACE,oBAACC,SAAD;EACE,aAAU;EACV,WAAW,GACT,saACA,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,YAAY,EAAE,WAAW,GAAG,SAA6D;CAChG,OACE,oBAACC,SAAD;EACE,aAAU;EACV,WAAW,GAAG,mEAAmE,SAAS;EAC1F,GAAI;CACL,CAAA;AAEL"}
1
+ {"version":3,"file":"tabs.js","names":["TabsPrimitive.Root","TabsPrimitive.List","TabsPrimitive.Trigger","TabsPrimitive.Content"],"sources":["../../src/components/tabs.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { cn, focusRingClasses, touchTargetRowClasses } from '../lib/utils';\nimport * as TabsPrimitive from '../primitives/vendor/radix/react-tabs';\n\nconst Tabs = React.forwardRef<HTMLDivElement, React.ComponentProps<typeof TabsPrimitive.Root>>(\n function Tabs({ className, ...props }, ref) {\n return (\n <TabsPrimitive.Root\n ref={ref}\n data-slot=\"tabs\"\n className={cn('flex flex-col gap-3', className)}\n {...props}\n />\n );\n },\n);\n\n/**\n * A 36px strip with a 10px radius; a strip wider than its container scrolls\n * sideways rather than pushing the layout.\n */\nconst TabsList = React.forwardRef<HTMLDivElement, React.ComponentProps<typeof TabsPrimitive.List>>(\n function TabsList({ className, ...props }, ref) {\n return (\n <TabsPrimitive.List\n ref={ref}\n data-slot=\"tabs-list\"\n className={cn(\n 'inline-flex h-9 w-fit max-w-full items-center gap-0.5 overflow-x-auto rounded-md border border-border bg-surface-muted p-1 text-muted-foreground [scrollbar-width:none]',\n className,\n )}\n {...props}\n />\n );\n },\n);\n\n/** A 28px tab with a 6px radius (the strip's 10px less its 4px inset); 44px tall to a touch. */\nconst TabsTrigger = React.forwardRef<\n HTMLButtonElement,\n React.ComponentProps<typeof TabsPrimitive.Trigger>\n>(function TabsTrigger({ className, ...props }, ref) {\n return (\n <TabsPrimitive.Trigger\n ref={ref}\n data-slot=\"tabs-trigger\"\n className={cn(\n 'inline-flex h-7 min-w-0 shrink-0 items-center justify-center gap-1.5 rounded-xs px-2.5 text-[13px] font-semibold whitespace-nowrap transition-[background-color,color,box-shadow] disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-surface data-[state=active]:text-foreground data-[state=active]:shadow-xs hover:text-foreground [&_svg]:size-4',\n focusRingClasses,\n touchTargetRowClasses,\n className,\n )}\n {...props}\n />\n );\n});\n\nconst TabsContent = React.forwardRef<\n HTMLDivElement,\n React.ComponentProps<typeof TabsPrimitive.Content>\n>(function TabsContent({ className, ...props }, ref) {\n return (\n <TabsPrimitive.Content\n ref={ref}\n data-slot=\"tabs-content\"\n className={cn(\n 'min-w-0 flex-1 data-[state=active]:animate-fade-in',\n focusRingClasses,\n className,\n )}\n {...props}\n />\n );\n});\n\nexport { Tabs, TabsContent, TabsList, TabsTrigger };\n"],"mappings":";;;;;;AAKA,IAAM,OAAO,MAAM,WACjB,SAAS,KAAK,EAAE,WAAW,GAAG,SAAS,KAAK;CAC1C,OACE,oBAACA,MAAD;EACO;EACL,aAAU;EACV,WAAW,GAAG,uBAAuB,SAAS;EAC9C,GAAI;CACL,CAAA;AAEL,CACF;;;;;AAMA,IAAM,WAAW,MAAM,WACrB,SAAS,SAAS,EAAE,WAAW,GAAG,SAAS,KAAK;CAC9C,OACE,oBAACC,MAAD;EACO;EACL,aAAU;EACV,WAAW,GACT,2KACA,SACF;EACA,GAAI;CACL,CAAA;AAEL,CACF;;AAGA,IAAM,cAAc,MAAM,WAGxB,SAAS,YAAY,EAAE,WAAW,GAAG,SAAS,KAAK;CACnD,OACE,oBAACC,SAAD;EACO;EACL,aAAU;EACV,WAAW,GACT,4WACA,kBACA,uBACA,SACF;EACA,GAAI;CACL,CAAA;AAEL,CAAC;AAED,IAAM,cAAc,MAAM,WAGxB,SAAS,YAAY,EAAE,WAAW,GAAG,SAAS,KAAK;CACnD,OACE,oBAACC,SAAD;EACO;EACL,aAAU;EACV,WAAW,GACT,sDACA,kBACA,SACF;EACA,GAAI;CACL,CAAA;AAEL,CAAC"}
@@ -1,3 +1,8 @@
1
1
  import * as React from 'react';
2
- declare const Textarea: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.TextareaHTMLAttributes<HTMLTextAreaElement>, HTMLTextAreaElement>, "ref"> & React.RefAttributes<HTMLTextAreaElement>>;
2
+ import { type FieldWidth } from './input';
3
+ export interface TextareaProps extends React.ComponentProps<'textarea'> {
4
+ /** How wide the field is from 640px up; full width on phones. */
5
+ width?: FieldWidth;
6
+ }
7
+ declare const Textarea: React.ForwardRefExoticComponent<Omit<TextareaProps, "ref"> & React.RefAttributes<HTMLTextAreaElement>>;
3
8
  export { Textarea };
@@ -1,14 +1,14 @@
1
1
  "use client";
2
2
  import { cn } from "../lib/utils.js";
3
- import { fieldClasses } from "./input.js";
3
+ import { fieldClasses, fieldWidthClasses } from "./input.js";
4
4
  import * as React from "react";
5
5
  import { jsx } from "react/jsx-runtime";
6
6
  //#region src/components/textarea.tsx
7
- var Textarea = React.forwardRef(function Textarea({ className, ...props }, ref) {
7
+ var Textarea = React.forwardRef(function Textarea({ className, width, ...props }, ref) {
8
8
  return /* @__PURE__ */ jsx("textarea", {
9
9
  ref,
10
10
  "data-slot": "textarea",
11
- className: cn(fieldClasses, "min-h-24 resize-y py-2.5 leading-5", className),
11
+ className: cn(fieldClasses, "min-h-24 resize-y py-2.5 leading-5", width && fieldWidthClasses[width], className),
12
12
  ...props
13
13
  });
14
14
  });
@@ -1 +1 @@
1
- {"version":3,"file":"textarea.js","names":[],"sources":["../../src/components/textarea.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nimport { fieldClasses } from './input';\n\nconst Textarea = React.forwardRef<HTMLTextAreaElement, React.ComponentProps<'textarea'>>(\n function Textarea({ className, ...props }: React.ComponentProps<'textarea'>, ref) {\n return (\n <textarea\n ref={ref}\n data-slot=\"textarea\"\n className={cn(fieldClasses, 'min-h-24 resize-y py-2.5 leading-5', className)}\n {...props}\n />\n );\n },\n);\n\nexport { Textarea };\n"],"mappings":";;;;;;AAMA,IAAM,WAAW,MAAM,WACrB,SAAS,SAAS,EAAE,WAAW,GAAG,SAA2C,KAAK;CAChF,OACE,oBAAC,YAAD;EACO;EACL,aAAU;EACV,WAAW,GAAG,cAAc,sCAAsC,SAAS;EAC3E,GAAI;CACL,CAAA;AAEL,CACF"}
1
+ {"version":3,"file":"textarea.js","names":[],"sources":["../../src/components/textarea.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nimport { fieldClasses, type FieldWidth, fieldWidthClasses } from './input';\n\nexport interface TextareaProps extends React.ComponentProps<'textarea'> {\n /** How wide the field is from 640px up; full width on phones. */\n width?: FieldWidth;\n}\n\nconst Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(function Textarea(\n { className, width, ...props }: TextareaProps,\n ref,\n) {\n return (\n <textarea\n ref={ref}\n data-slot=\"textarea\"\n className={cn(\n fieldClasses,\n 'min-h-24 resize-y py-2.5 leading-5',\n width && fieldWidthClasses[width],\n className,\n )}\n {...props}\n />\n );\n});\n\nexport { Textarea };\n"],"mappings":";;;;;;AAWA,IAAM,WAAW,MAAM,WAA+C,SAAS,SAC7E,EAAE,WAAW,OAAO,GAAG,SACvB,KACA;CACA,OACE,oBAAC,YAAD;EACO;EACL,aAAU;EACV,WAAW,GACT,cACA,sCACA,SAAS,kBAAkB,QAC3B,SACF;EACA,GAAI;CACL,CAAA;AAEL,CAAC"}
@@ -7,14 +7,18 @@ import * as ToastPrimitive from '../primitives/vendor/radix/react-toast';
7
7
  * `open` state; Radix handles timing, swipe-to-dismiss and the live region.
8
8
  */
9
9
  declare const ToastProvider: React.FC<ToastPrimitive.ToastProviderProps>;
10
- declare function ToastViewport({ className, ...props }: React.ComponentProps<typeof ToastPrimitive.Viewport>): React.JSX.Element;
10
+ /** Bottom right, above every overlay (z 100), full width on phones. */
11
+ declare const ToastViewport: React.ForwardRefExoticComponent<Omit<ToastPrimitive.ToastViewportProps & React.RefAttributes<HTMLOListElement>, "ref"> & React.RefAttributes<HTMLOListElement>>;
11
12
  declare const toastVariants: (props?: ({
12
13
  variant?: "destructive" | "success" | "default" | null | undefined;
13
14
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
14
- declare function Toast({ className, variant, ...props }: React.ComponentProps<typeof ToastPrimitive.Root> & VariantProps<typeof toastVariants>): React.JSX.Element;
15
- declare function ToastTitle({ className, ...props }: React.ComponentProps<typeof ToastPrimitive.Title>): React.JSX.Element;
16
- declare function ToastDescription({ className, ...props }: React.ComponentProps<typeof ToastPrimitive.Description>): React.JSX.Element;
15
+ export interface ToastProps extends React.ComponentProps<typeof ToastPrimitive.Root>, VariantProps<typeof toastVariants> {
16
+ }
17
+ declare const Toast: React.ForwardRefExoticComponent<Omit<ToastProps, "ref"> & React.RefAttributes<HTMLLIElement>>;
18
+ declare const ToastTitle: React.ForwardRefExoticComponent<Omit<ToastPrimitive.ToastTitleProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
19
+ declare const ToastDescription: React.ForwardRefExoticComponent<Omit<ToastPrimitive.ToastDescriptionProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
17
20
  /** A button inside the toast; `altText` tells screen readers how to do it without the toast. */
18
- declare function ToastAction({ className, ...props }: React.ComponentProps<typeof ToastPrimitive.Action>): React.JSX.Element;
19
- declare function ToastClose({ className, ...props }: React.ComponentProps<typeof ToastPrimitive.Close>): React.JSX.Element;
21
+ declare const ToastAction: React.ForwardRefExoticComponent<Omit<ToastPrimitive.ToastActionProps & React.RefAttributes<HTMLButtonElement>, "ref"> & React.RefAttributes<HTMLButtonElement>>;
22
+ /** The dismiss X: 24px drawn, 44px to a touch. */
23
+ declare const ToastClose: React.ForwardRefExoticComponent<Omit<ToastPrimitive.ToastCloseProps & React.RefAttributes<HTMLButtonElement>, "ref"> & React.RefAttributes<HTMLButtonElement>>;
20
24
  export { Toast, ToastAction, ToastClose, ToastDescription, ToastProvider, ToastTitle, toastVariants, ToastViewport, };
@@ -1,7 +1,7 @@
1
1
  "use client";
2
- import { cn } from "../lib/utils.js";
2
+ import { cn, focusRingClasses, touchTargetClasses } from "../lib/utils.js";
3
3
  import { Action, Close, Description, Provider, Root, Title, Viewport } from "../primitives/vendor/radix/react-toast/toast.js";
4
- import "react";
4
+ import * as React from "react";
5
5
  import { jsx } from "react/jsx-runtime";
6
6
  import { cva } from "class-variance-authority";
7
7
  import X from "@burtson-labs/icons/react/x";
@@ -12,14 +12,16 @@ import X from "@burtson-labs/icons/react/x";
12
12
  * `open` state; Radix handles timing, swipe-to-dismiss and the live region.
13
13
  */
14
14
  var ToastProvider = Provider;
15
- function ToastViewport({ className, ...props }) {
15
+ /** Bottom right, above every overlay (z 100), full width on phones. */
16
+ var ToastViewport = React.forwardRef(function ToastViewport({ className, ...props }, ref) {
16
17
  return /* @__PURE__ */ jsx(Viewport, {
18
+ ref,
17
19
  "data-slot": "toast-viewport",
18
- className: cn("fixed right-0 bottom-0 z-[100] flex max-h-dvh w-full flex-col-reverse gap-2 p-4 outline-none sm:max-w-sm", className),
20
+ className: cn("fixed right-0 bottom-0 z-[100] flex max-h-dvh w-full flex-col-reverse gap-2 p-4 pb-[max(1rem,env(safe-area-inset-bottom))] outline-none sm:max-w-sm", className),
19
21
  ...props
20
22
  });
21
- }
22
- var toastVariants = cva("group pointer-events-auto relative grid w-full grid-cols-[1fr_auto] items-start gap-x-3 gap-y-1 overflow-hidden rounded-lg border p-4 pr-10 text-sm shadow-[0_16px_48px_rgb(0_0_0_/_0.18)] [--bl-ty:12px] [--bl-scale:0.98] data-[state=closed]:animate-out data-[state=open]:animate-in data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-(--radix-toast-swipe-end-x) data-[swipe=move]:translate-x-(--radix-toast-swipe-move-x) data-[swipe=move]:transition-none", {
23
+ });
24
+ var toastVariants = cva("group pointer-events-auto relative grid w-full grid-cols-[1fr_auto] items-start gap-x-3 gap-y-1 overflow-hidden rounded-lg border p-4 pr-10 text-sm shadow-lg [--bl-ty:12px] [--bl-scale:0.98] data-[state=closed]:animate-out data-[state=open]:animate-in data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-(--radix-toast-swipe-end-x) data-[swipe=move]:translate-x-(--radix-toast-swipe-move-x) data-[swipe=move]:transition-none", {
23
25
  variants: { variant: {
24
26
  default: "border-border-strong bg-surface-raised text-foreground",
25
27
  success: "border-success/30 bg-surface-raised text-foreground [&_[data-slot=toast-title]]:text-success",
@@ -27,44 +29,51 @@ var toastVariants = cva("group pointer-events-auto relative grid w-full grid-col
27
29
  } },
28
30
  defaultVariants: { variant: "default" }
29
31
  });
30
- function Toast({ className, variant, ...props }) {
32
+ var Toast = React.forwardRef(function Toast({ className, variant, ...props }, ref) {
31
33
  return /* @__PURE__ */ jsx(Root, {
34
+ ref,
32
35
  "data-slot": "toast",
36
+ "data-variant": variant ?? "default",
33
37
  className: cn(toastVariants({ variant }), className),
34
38
  ...props
35
39
  });
36
- }
37
- function ToastTitle({ className, ...props }) {
40
+ });
41
+ var ToastTitle = React.forwardRef(function ToastTitle({ className, ...props }, ref) {
38
42
  return /* @__PURE__ */ jsx(Title, {
43
+ ref,
39
44
  "data-slot": "toast-title",
40
45
  className: cn("col-start-1 font-semibold tracking-[-0.01em]", className),
41
46
  ...props
42
47
  });
43
- }
44
- function ToastDescription({ className, ...props }) {
48
+ });
49
+ var ToastDescription = React.forwardRef(function ToastDescription({ className, ...props }, ref) {
45
50
  return /* @__PURE__ */ jsx(Description, {
51
+ ref,
46
52
  "data-slot": "toast-description",
47
53
  className: cn("col-start-1 text-[13px] leading-5 text-muted-foreground", className),
48
54
  ...props
49
55
  });
50
- }
56
+ });
51
57
  /** A button inside the toast; `altText` tells screen readers how to do it without the toast. */
52
- function ToastAction({ className, ...props }) {
58
+ var ToastAction = React.forwardRef(function ToastAction({ className, ...props }, ref) {
53
59
  return /* @__PURE__ */ jsx(Action, {
60
+ ref,
54
61
  "data-slot": "toast-action",
55
- className: cn("col-start-2 row-span-2 row-start-1 inline-flex h-8 shrink-0 items-center justify-center self-center rounded-md border border-border-strong bg-surface px-3 text-[13px] font-semibold transition-colors outline-none hover:bg-muted focus-visible:ring-[3px] focus-visible:ring-ring/20", className),
62
+ className: cn("col-start-2 row-span-2 row-start-1 inline-flex h-8 shrink-0 items-center justify-center self-center rounded-md border border-border-strong bg-surface px-3 text-[13px] font-semibold transition-colors hover:bg-muted pointer-coarse:min-h-11", focusRingClasses, className),
56
63
  ...props
57
64
  });
58
- }
59
- function ToastClose({ className, ...props }) {
65
+ });
66
+ /** The dismiss X: 24px drawn, 44px to a touch. */
67
+ var ToastClose = React.forwardRef(function ToastClose({ className, ...props }, ref) {
60
68
  return /* @__PURE__ */ jsx(Close, {
69
+ ref,
61
70
  "data-slot": "toast-close",
62
71
  "aria-label": "Dismiss",
63
- className: cn("absolute top-3 right-3 grid size-6 place-items-center rounded-sm text-muted-foreground transition-colors outline-none hover:bg-muted hover:text-foreground focus-visible:ring-[3px] focus-visible:ring-ring/20 [&_svg]:size-3.5", className),
72
+ className: cn("absolute top-3 right-3 grid size-6 place-items-center rounded-sm text-muted-foreground transition-colors hover:bg-muted hover:text-foreground [&_svg]:size-4", focusRingClasses, touchTargetClasses, "absolute", className),
64
73
  ...props,
65
74
  children: /* @__PURE__ */ jsx(X, { "aria-hidden": true })
66
75
  });
67
- }
76
+ });
68
77
  //#endregion
69
78
  export { Toast, ToastAction, ToastClose, ToastDescription, ToastProvider, ToastTitle, ToastViewport, toastVariants };
70
79
 
@@ -1 +1 @@
1
- {"version":3,"file":"toast.js","names":["ToastPrimitive.Provider","ToastPrimitive.Viewport","ToastPrimitive.Root","ToastPrimitive.Title","ToastPrimitive.Description","ToastPrimitive.Action","ToastPrimitive.Close"],"sources":["../../src/components/toast.tsx"],"sourcesContent":["import X from '@burtson-labs/icons/react/x';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\nimport * as ToastPrimitive from '../primitives/vendor/radix/react-toast';\n\n/**\n * Brief, non-blocking notices (\"Message sent\", \"Update available\"). Put one\n * `ToastProvider` + `ToastViewport` near the root and render `Toast`s with\n * `open` state; Radix handles timing, swipe-to-dismiss and the live region.\n */\nconst ToastProvider = ToastPrimitive.Provider;\n\nfunction ToastViewport({\n className,\n ...props\n}: React.ComponentProps<typeof ToastPrimitive.Viewport>) {\n return (\n <ToastPrimitive.Viewport\n data-slot=\"toast-viewport\"\n className={cn(\n 'fixed right-0 bottom-0 z-[100] flex max-h-dvh w-full flex-col-reverse gap-2 p-4 outline-none sm:max-w-sm',\n className,\n )}\n {...props}\n />\n );\n}\n\nconst toastVariants = cva(\n 'group pointer-events-auto relative grid w-full grid-cols-[1fr_auto] items-start gap-x-3 gap-y-1 overflow-hidden rounded-lg border p-4 pr-10 text-sm shadow-[0_16px_48px_rgb(0_0_0_/_0.18)] [--bl-ty:12px] [--bl-scale:0.98] data-[state=closed]:animate-out data-[state=open]:animate-in data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-(--radix-toast-swipe-end-x) data-[swipe=move]:translate-x-(--radix-toast-swipe-move-x) data-[swipe=move]:transition-none',\n {\n variants: {\n variant: {\n default: 'border-border-strong bg-surface-raised text-foreground',\n success:\n 'border-success/30 bg-surface-raised text-foreground [&_[data-slot=toast-title]]:text-success',\n destructive:\n 'border-destructive/30 bg-surface-raised text-foreground [&_[data-slot=toast-title]]:text-destructive',\n },\n },\n defaultVariants: { variant: 'default' },\n },\n);\n\nfunction Toast({\n className,\n variant,\n ...props\n}: React.ComponentProps<typeof ToastPrimitive.Root> & VariantProps<typeof toastVariants>) {\n return (\n <ToastPrimitive.Root\n data-slot=\"toast\"\n className={cn(toastVariants({ variant }), className)}\n {...props}\n />\n );\n}\n\nfunction ToastTitle({ className, ...props }: React.ComponentProps<typeof ToastPrimitive.Title>) {\n return (\n <ToastPrimitive.Title\n data-slot=\"toast-title\"\n className={cn('col-start-1 font-semibold tracking-[-0.01em]', className)}\n {...props}\n />\n );\n}\n\nfunction ToastDescription({\n className,\n ...props\n}: React.ComponentProps<typeof ToastPrimitive.Description>) {\n return (\n <ToastPrimitive.Description\n data-slot=\"toast-description\"\n className={cn('col-start-1 text-[13px] leading-5 text-muted-foreground', className)}\n {...props}\n />\n );\n}\n\n/** A button inside the toast; `altText` tells screen readers how to do it without the toast. */\nfunction ToastAction({ className, ...props }: React.ComponentProps<typeof ToastPrimitive.Action>) {\n return (\n <ToastPrimitive.Action\n data-slot=\"toast-action\"\n className={cn(\n 'col-start-2 row-span-2 row-start-1 inline-flex h-8 shrink-0 items-center justify-center self-center rounded-md border border-border-strong bg-surface px-3 text-[13px] font-semibold transition-colors outline-none hover:bg-muted focus-visible:ring-[3px] focus-visible:ring-ring/20',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction ToastClose({ className, ...props }: React.ComponentProps<typeof ToastPrimitive.Close>) {\n return (\n <ToastPrimitive.Close\n data-slot=\"toast-close\"\n aria-label=\"Dismiss\"\n className={cn(\n 'absolute top-3 right-3 grid size-6 place-items-center rounded-sm text-muted-foreground transition-colors outline-none hover:bg-muted hover:text-foreground focus-visible:ring-[3px] focus-visible:ring-ring/20 [&_svg]:size-3.5',\n className,\n )}\n {...props}\n >\n <X aria-hidden />\n </ToastPrimitive.Close>\n );\n}\n\nexport {\n Toast,\n ToastAction,\n ToastClose,\n ToastDescription,\n ToastProvider,\n ToastTitle,\n toastVariants,\n ToastViewport,\n};\n"],"mappings":";;;;;;;;;;;;;AAYA,IAAM,gBAAgBA;AAEtB,SAAS,cAAc,EACrB,WACA,GAAG,SACoD;CACvD,OACE,oBAACC,UAAD;EACE,aAAU;EACV,WAAW,GACT,4GACA,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,IAAM,gBAAgB,IACpB,odACA;CACE,UAAU,EACR,SAAS;EACP,SAAS;EACT,SACE;EACF,aACE;CACJ,EACF;CACA,iBAAiB,EAAE,SAAS,UAAU;AACxC,CACF;AAEA,SAAS,MAAM,EACb,WACA,SACA,GAAG,SACqF;CACxF,OACE,oBAACC,MAAD;EACE,aAAU;EACV,WAAW,GAAG,cAAc,EAAE,QAAQ,CAAC,GAAG,SAAS;EACnD,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,WAAW,EAAE,WAAW,GAAG,SAA4D;CAC9F,OACE,oBAACC,OAAD;EACE,aAAU;EACV,WAAW,GAAG,gDAAgD,SAAS;EACvE,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,iBAAiB,EACxB,WACA,GAAG,SACuD;CAC1D,OACE,oBAACC,aAAD;EACE,aAAU;EACV,WAAW,GAAG,2DAA2D,SAAS;EAClF,GAAI;CACL,CAAA;AAEL;;AAGA,SAAS,YAAY,EAAE,WAAW,GAAG,SAA6D;CAChG,OACE,oBAACC,QAAD;EACE,aAAU;EACV,WAAW,GACT,0RACA,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,WAAW,EAAE,WAAW,GAAG,SAA4D;CAC9F,OACE,oBAACC,OAAD;EACE,aAAU;EACV,cAAW;EACX,WAAW,GACT,mOACA,SACF;EACA,GAAI;EAEJ,UAAA,oBAAC,GAAD,EAAG,eAAA,KAAa,CAAA;CACI,CAAA;AAE1B"}
1
+ {"version":3,"file":"toast.js","names":["ToastPrimitive.Provider","ToastPrimitive.Viewport","ToastPrimitive.Root","ToastPrimitive.Title","ToastPrimitive.Description","ToastPrimitive.Action","ToastPrimitive.Close"],"sources":["../../src/components/toast.tsx"],"sourcesContent":["import X from '@burtson-labs/icons/react/x';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport * as React from 'react';\n\nimport { cn, focusRingClasses, touchTargetClasses } from '../lib/utils';\nimport * as ToastPrimitive from '../primitives/vendor/radix/react-toast';\n\n/**\n * Brief, non-blocking notices (\"Message sent\", \"Update available\"). Put one\n * `ToastProvider` + `ToastViewport` near the root and render `Toast`s with\n * `open` state; Radix handles timing, swipe-to-dismiss and the live region.\n */\nconst ToastProvider = ToastPrimitive.Provider;\n\n/** Bottom right, above every overlay (z 100), full width on phones. */\nconst ToastViewport = React.forwardRef<\n HTMLOListElement,\n React.ComponentProps<typeof ToastPrimitive.Viewport>\n>(function ToastViewport({ className, ...props }, ref) {\n return (\n <ToastPrimitive.Viewport\n ref={ref}\n data-slot=\"toast-viewport\"\n className={cn(\n 'fixed right-0 bottom-0 z-[100] flex max-h-dvh w-full flex-col-reverse gap-2 p-4 pb-[max(1rem,env(safe-area-inset-bottom))] outline-none sm:max-w-sm',\n className,\n )}\n {...props}\n />\n );\n});\n\nconst toastVariants = cva(\n 'group pointer-events-auto relative grid w-full grid-cols-[1fr_auto] items-start gap-x-3 gap-y-1 overflow-hidden rounded-lg border p-4 pr-10 text-sm shadow-lg [--bl-ty:12px] [--bl-scale:0.98] data-[state=closed]:animate-out data-[state=open]:animate-in data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-(--radix-toast-swipe-end-x) data-[swipe=move]:translate-x-(--radix-toast-swipe-move-x) data-[swipe=move]:transition-none',\n {\n variants: {\n variant: {\n default: 'border-border-strong bg-surface-raised text-foreground',\n success:\n 'border-success/30 bg-surface-raised text-foreground [&_[data-slot=toast-title]]:text-success',\n destructive:\n 'border-destructive/30 bg-surface-raised text-foreground [&_[data-slot=toast-title]]:text-destructive',\n },\n },\n defaultVariants: { variant: 'default' },\n },\n);\n\nexport interface ToastProps\n extends React.ComponentProps<typeof ToastPrimitive.Root>, VariantProps<typeof toastVariants> {}\n\nconst Toast = React.forwardRef<HTMLLIElement, ToastProps>(function Toast(\n { className, variant, ...props },\n ref,\n) {\n return (\n <ToastPrimitive.Root\n ref={ref}\n data-slot=\"toast\"\n data-variant={variant ?? 'default'}\n className={cn(toastVariants({ variant }), className)}\n {...props}\n />\n );\n});\n\nconst ToastTitle = React.forwardRef<\n HTMLDivElement,\n React.ComponentProps<typeof ToastPrimitive.Title>\n>(function ToastTitle({ className, ...props }, ref) {\n return (\n <ToastPrimitive.Title\n ref={ref}\n data-slot=\"toast-title\"\n className={cn('col-start-1 font-semibold tracking-[-0.01em]', className)}\n {...props}\n />\n );\n});\n\nconst ToastDescription = React.forwardRef<\n HTMLDivElement,\n React.ComponentProps<typeof ToastPrimitive.Description>\n>(function ToastDescription({ className, ...props }, ref) {\n return (\n <ToastPrimitive.Description\n ref={ref}\n data-slot=\"toast-description\"\n className={cn('col-start-1 text-[13px] leading-5 text-muted-foreground', className)}\n {...props}\n />\n );\n});\n\n/** A button inside the toast; `altText` tells screen readers how to do it without the toast. */\nconst ToastAction = React.forwardRef<\n HTMLButtonElement,\n React.ComponentProps<typeof ToastPrimitive.Action>\n>(function ToastAction({ className, ...props }, ref) {\n return (\n <ToastPrimitive.Action\n ref={ref}\n data-slot=\"toast-action\"\n className={cn(\n 'col-start-2 row-span-2 row-start-1 inline-flex h-8 shrink-0 items-center justify-center self-center rounded-md border border-border-strong bg-surface px-3 text-[13px] font-semibold transition-colors hover:bg-muted pointer-coarse:min-h-11',\n focusRingClasses,\n className,\n )}\n {...props}\n />\n );\n});\n\n/** The dismiss X: 24px drawn, 44px to a touch. */\nconst ToastClose = React.forwardRef<\n HTMLButtonElement,\n React.ComponentProps<typeof ToastPrimitive.Close>\n>(function ToastClose({ className, ...props }, ref) {\n return (\n <ToastPrimitive.Close\n ref={ref}\n data-slot=\"toast-close\"\n aria-label=\"Dismiss\"\n className={cn(\n 'absolute top-3 right-3 grid size-6 place-items-center rounded-sm text-muted-foreground transition-colors hover:bg-muted hover:text-foreground [&_svg]:size-4',\n focusRingClasses,\n touchTargetClasses,\n 'absolute',\n className,\n )}\n {...props}\n >\n <X aria-hidden />\n </ToastPrimitive.Close>\n );\n});\n\nexport {\n Toast,\n ToastAction,\n ToastClose,\n ToastDescription,\n ToastProvider,\n ToastTitle,\n toastVariants,\n ToastViewport,\n};\n"],"mappings":";;;;;;;;;;;;;AAYA,IAAM,gBAAgBA;;AAGtB,IAAM,gBAAgB,MAAM,WAG1B,SAAS,cAAc,EAAE,WAAW,GAAG,SAAS,KAAK;CACrD,OACE,oBAACC,UAAD;EACO;EACL,aAAU;EACV,WAAW,GACT,uJACA,SACF;EACA,GAAI;CACL,CAAA;AAEL,CAAC;AAED,IAAM,gBAAgB,IACpB,ubACA;CACE,UAAU,EACR,SAAS;EACP,SAAS;EACT,SACE;EACF,aACE;CACJ,EACF;CACA,iBAAiB,EAAE,SAAS,UAAU;AACxC,CACF;AAKA,IAAM,QAAQ,MAAM,WAAsC,SAAS,MACjE,EAAE,WAAW,SAAS,GAAG,SACzB,KACA;CACA,OACE,oBAACC,MAAD;EACO;EACL,aAAU;EACV,gBAAc,WAAW;EACzB,WAAW,GAAG,cAAc,EAAE,QAAQ,CAAC,GAAG,SAAS;EACnD,GAAI;CACL,CAAA;AAEL,CAAC;AAED,IAAM,aAAa,MAAM,WAGvB,SAAS,WAAW,EAAE,WAAW,GAAG,SAAS,KAAK;CAClD,OACE,oBAACC,OAAD;EACO;EACL,aAAU;EACV,WAAW,GAAG,gDAAgD,SAAS;EACvE,GAAI;CACL,CAAA;AAEL,CAAC;AAED,IAAM,mBAAmB,MAAM,WAG7B,SAAS,iBAAiB,EAAE,WAAW,GAAG,SAAS,KAAK;CACxD,OACE,oBAACC,aAAD;EACO;EACL,aAAU;EACV,WAAW,GAAG,2DAA2D,SAAS;EAClF,GAAI;CACL,CAAA;AAEL,CAAC;;AAGD,IAAM,cAAc,MAAM,WAGxB,SAAS,YAAY,EAAE,WAAW,GAAG,SAAS,KAAK;CACnD,OACE,oBAACC,QAAD;EACO;EACL,aAAU;EACV,WAAW,GACT,iPACA,kBACA,SACF;EACA,GAAI;CACL,CAAA;AAEL,CAAC;;AAGD,IAAM,aAAa,MAAM,WAGvB,SAAS,WAAW,EAAE,WAAW,GAAG,SAAS,KAAK;CAClD,OACE,oBAACC,OAAD;EACO;EACL,aAAU;EACV,cAAW;EACX,WAAW,GACT,gKACA,kBACA,oBACA,YACA,SACF;EACA,GAAI;EAEJ,UAAA,oBAAC,GAAD,EAAG,eAAA,KAAa,CAAA;CACI,CAAA;AAE1B,CAAC"}
@@ -14,7 +14,9 @@ export interface ToastOptions {
14
14
  }
15
15
  /** Show a brief notice. Returns a function that closes it early. */
16
16
  declare function toast(options: ToastOptions | string): () => void;
17
- declare function Toaster({ className }: {
17
+ export interface ToasterProps {
18
+ /** Classes for the viewport (position, width). */
18
19
  className?: string;
19
- }): React.JSX.Element;
20
+ }
21
+ declare function Toaster({ className }: ToasterProps): React.JSX.Element;
20
22
  export { toast, Toaster };
@@ -37,8 +37,9 @@ var subscribe = (listener) => {
37
37
  };
38
38
  };
39
39
  var snapshot = () => records;
40
+ var serverSnapshot = () => [];
40
41
  function Toaster({ className }) {
41
- const list = React.useSyncExternalStore(subscribe, snapshot, snapshot);
42
+ const list = React.useSyncExternalStore(subscribe, snapshot, serverSnapshot);
42
43
  return /* @__PURE__ */ jsxs(ToastProvider, {
43
44
  swipeDirection: "right",
44
45
  children: [list.map((r) => /* @__PURE__ */ jsxs(Toast, {
@@ -53,7 +54,10 @@ function Toaster({ className }) {
53
54
  r.description && /* @__PURE__ */ jsx(ToastDescription, { children: r.description }),
54
55
  /* @__PURE__ */ jsx(ToastClose, {})
55
56
  ]
56
- }, r.id)), /* @__PURE__ */ jsx(ToastViewport, { className })]
57
+ }, r.id)), /* @__PURE__ */ jsx(ToastViewport, {
58
+ "data-slot": "toaster",
59
+ className
60
+ })]
57
61
  });
58
62
  }
59
63
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"toaster.js","names":[],"sources":["../../src/components/toaster.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n Toast,\n ToastClose,\n ToastDescription,\n ToastProvider,\n ToastTitle,\n ToastViewport,\n} from './toast';\n\n/**\n * Imperative toasts: call `toast({ title, description, variant })` from\n * anywhere (event handlers, data hooks) and one mounted `<Toaster />` renders\n * them on the Toast primitives. Mount the Toaster once near the root.\n */\nexport type ToastVariant = 'default' | 'success' | 'destructive';\n\nexport interface ToastOptions {\n title: string;\n description?: string;\n variant?: ToastVariant;\n /** Milliseconds before it closes (Radix pauses on hover and focus). */\n duration?: number;\n}\n\ninterface ToastRecord extends ToastOptions {\n id: number;\n open: boolean;\n}\n\nlet records: ToastRecord[] = [];\nlet nextId = 1;\nconst listeners = new Set<() => void>();\nconst emit = () => listeners.forEach((listener) => listener());\n\nfunction close(id: number) {\n records = records.map((r) => (r.id === id ? { ...r, open: false } : r));\n emit();\n // Leave time for the exit animation before dropping the record.\n setTimeout(() => {\n records = records.filter((r) => r.id !== id);\n emit();\n }, 400);\n}\n\n/** Show a brief notice. Returns a function that closes it early. */\nfunction toast(options: ToastOptions | string): () => void {\n const opts = typeof options === 'string' ? { title: options } : options;\n const id = nextId++;\n // Keep the stack short: the oldest go first.\n records = [...records.slice(-3), { ...opts, id, open: true }];\n emit();\n return () => close(id);\n}\n\nconst subscribe = (listener: () => void) => {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n};\nconst snapshot = () => records;\n\nfunction Toaster({ className }: { className?: string }) {\n const list = React.useSyncExternalStore(subscribe, snapshot, snapshot);\n return (\n <ToastProvider swipeDirection=\"right\">\n {list.map((r) => (\n <Toast\n key={r.id}\n open={r.open}\n variant={r.variant}\n duration={r.duration ?? (r.variant === 'destructive' ? 8000 : 4000)}\n onOpenChange={(open) => {\n if (!open) close(r.id);\n }}\n >\n <ToastTitle>{r.title}</ToastTitle>\n {r.description && <ToastDescription>{r.description}</ToastDescription>}\n <ToastClose />\n </Toast>\n ))}\n <ToastViewport className={className} />\n </ToastProvider>\n );\n}\n\nexport { toast, Toaster };\n"],"mappings":";;;;;AA+BA,IAAI,UAAyB,CAAC;AAC9B,IAAI,SAAS;AACb,IAAM,4BAAY,IAAI,IAAgB;AACtC,IAAM,aAAa,UAAU,SAAS,aAAa,SAAS,CAAC;AAE7D,SAAS,MAAM,IAAY;CACzB,UAAU,QAAQ,KAAK,MAAO,EAAE,OAAO,KAAK;EAAE,GAAG;EAAG,MAAM;CAAM,IAAI,CAAE;CACtE,KAAK;CAEL,iBAAiB;EACf,UAAU,QAAQ,QAAQ,MAAM,EAAE,OAAO,EAAE;EAC3C,KAAK;CACP,GAAG,GAAG;AACR;;AAGA,SAAS,MAAM,SAA4C;CACzD,MAAM,OAAO,OAAO,YAAY,WAAW,EAAE,OAAO,QAAQ,IAAI;CAChE,MAAM,KAAK;CAEX,UAAU,CAAC,GAAG,QAAQ,MAAM,EAAE,GAAG;EAAE,GAAG;EAAM;EAAI,MAAM;CAAK,CAAC;CAC5D,KAAK;CACL,aAAa,MAAM,EAAE;AACvB;AAEA,IAAM,aAAa,aAAyB;CAC1C,UAAU,IAAI,QAAQ;CACtB,aAAa;EACX,UAAU,OAAO,QAAQ;CAC3B;AACF;AACA,IAAM,iBAAiB;AAEvB,SAAS,QAAQ,EAAE,aAAqC;CACtD,MAAM,OAAO,MAAM,qBAAqB,WAAW,UAAU,QAAQ;CACrE,OACE,qBAAC,eAAD;EAAe,gBAAe;EAA9B,UAAA,CACG,KAAK,KAAK,MACT,qBAAC,OAAD;GAEE,MAAM,EAAE;GACR,SAAS,EAAE;GACX,UAAU,EAAE,aAAa,EAAE,YAAY,gBAAgB,MAAO;GAC9D,eAAe,SAAS;IACtB,IAAI,CAAC,MAAM,MAAM,EAAE,EAAE;GACvB;GAPF,UAAA;IASE,oBAAC,YAAD,EAAA,UAAa,EAAE,MAAkB,CAAA;IAChC,EAAE,eAAe,oBAAC,kBAAD,EAAA,UAAmB,EAAE,YAA8B,CAAA;IACrE,oBAAC,YAAD,CAAa,CAAA;GACR;EAXA,GAAA,EAAE,EAWF,CACR,GACD,oBAAC,eAAD,EAA0B,UAAY,CAAA,CACzB;;AAEnB"}
1
+ {"version":3,"file":"toaster.js","names":[],"sources":["../../src/components/toaster.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n Toast,\n ToastClose,\n ToastDescription,\n ToastProvider,\n ToastTitle,\n ToastViewport,\n} from './toast';\n\n/**\n * Imperative toasts: call `toast({ title, description, variant })` from\n * anywhere (event handlers, data hooks) and one mounted `<Toaster />` renders\n * them on the Toast primitives. Mount the Toaster once near the root.\n */\nexport type ToastVariant = 'default' | 'success' | 'destructive';\n\nexport interface ToastOptions {\n title: string;\n description?: string;\n variant?: ToastVariant;\n /** Milliseconds before it closes (Radix pauses on hover and focus). */\n duration?: number;\n}\n\ninterface ToastRecord extends ToastOptions {\n id: number;\n open: boolean;\n}\n\nlet records: ToastRecord[] = [];\nlet nextId = 1;\nconst listeners = new Set<() => void>();\nconst emit = () => listeners.forEach((listener) => listener());\n\nfunction close(id: number) {\n records = records.map((r) => (r.id === id ? { ...r, open: false } : r));\n emit();\n // Leave time for the exit animation before dropping the record.\n setTimeout(() => {\n records = records.filter((r) => r.id !== id);\n emit();\n }, 400);\n}\n\n/** Show a brief notice. Returns a function that closes it early. */\nfunction toast(options: ToastOptions | string): () => void {\n const opts = typeof options === 'string' ? { title: options } : options;\n const id = nextId++;\n // Keep the stack short: the oldest go first.\n records = [...records.slice(-3), { ...opts, id, open: true }];\n emit();\n return () => close(id);\n}\n\nconst subscribe = (listener: () => void) => {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n};\nconst snapshot = () => records;\nconst serverSnapshot = (): ToastRecord[] => [];\n\nexport interface ToasterProps {\n /** Classes for the viewport (position, width). */\n className?: string;\n}\n\nfunction Toaster({ className }: ToasterProps) {\n const list = React.useSyncExternalStore(subscribe, snapshot, serverSnapshot);\n return (\n <ToastProvider swipeDirection=\"right\">\n {list.map((r) => (\n <Toast\n key={r.id}\n open={r.open}\n variant={r.variant}\n duration={r.duration ?? (r.variant === 'destructive' ? 8000 : 4000)}\n onOpenChange={(open) => {\n if (!open) close(r.id);\n }}\n >\n <ToastTitle>{r.title}</ToastTitle>\n {r.description && <ToastDescription>{r.description}</ToastDescription>}\n <ToastClose />\n </Toast>\n ))}\n <ToastViewport data-slot=\"toaster\" className={className} />\n </ToastProvider>\n );\n}\n\nexport { toast, Toaster };\n"],"mappings":";;;;;AA+BA,IAAI,UAAyB,CAAC;AAC9B,IAAI,SAAS;AACb,IAAM,4BAAY,IAAI,IAAgB;AACtC,IAAM,aAAa,UAAU,SAAS,aAAa,SAAS,CAAC;AAE7D,SAAS,MAAM,IAAY;CACzB,UAAU,QAAQ,KAAK,MAAO,EAAE,OAAO,KAAK;EAAE,GAAG;EAAG,MAAM;CAAM,IAAI,CAAE;CACtE,KAAK;CAEL,iBAAiB;EACf,UAAU,QAAQ,QAAQ,MAAM,EAAE,OAAO,EAAE;EAC3C,KAAK;CACP,GAAG,GAAG;AACR;;AAGA,SAAS,MAAM,SAA4C;CACzD,MAAM,OAAO,OAAO,YAAY,WAAW,EAAE,OAAO,QAAQ,IAAI;CAChE,MAAM,KAAK;CAEX,UAAU,CAAC,GAAG,QAAQ,MAAM,EAAE,GAAG;EAAE,GAAG;EAAM;EAAI,MAAM;CAAK,CAAC;CAC5D,KAAK;CACL,aAAa,MAAM,EAAE;AACvB;AAEA,IAAM,aAAa,aAAyB;CAC1C,UAAU,IAAI,QAAQ;CACtB,aAAa;EACX,UAAU,OAAO,QAAQ;CAC3B;AACF;AACA,IAAM,iBAAiB;AACvB,IAAM,uBAAsC,CAAC;AAO7C,SAAS,QAAQ,EAAE,aAA2B;CAC5C,MAAM,OAAO,MAAM,qBAAqB,WAAW,UAAU,cAAc;CAC3E,OACE,qBAAC,eAAD;EAAe,gBAAe;EAA9B,UAAA,CACG,KAAK,KAAK,MACT,qBAAC,OAAD;GAEE,MAAM,EAAE;GACR,SAAS,EAAE;GACX,UAAU,EAAE,aAAa,EAAE,YAAY,gBAAgB,MAAO;GAC9D,eAAe,SAAS;IACtB,IAAI,CAAC,MAAM,MAAM,EAAE,EAAE;GACvB;GAPF,UAAA;IASE,oBAAC,YAAD,EAAA,UAAa,EAAE,MAAkB,CAAA;IAChC,EAAE,eAAe,oBAAC,kBAAD,EAAA,UAAmB,EAAE,YAA8B,CAAA;IACrE,oBAAC,YAAD,CAAa,CAAA;GACR;EAXA,GAAA,EAAE,EAWF,CACR,GACD,oBAAC,eAAD;GAAe,aAAU;GAAqB;EAAY,CAAA,CAC7C;;AAEnB"}