@avenue-ticketing/ui 0.4.0 → 0.5.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 (73) hide show
  1. package/dist/react/avatar.d.ts +42 -0
  2. package/dist/react/avatar.js +159 -0
  3. package/dist/react/avatar.js.map +1 -0
  4. package/dist/react/badge.d.ts +12 -0
  5. package/dist/react/badge.js +35 -1
  6. package/dist/react/badge.js.map +1 -1
  7. package/dist/react/button.d.ts +1 -1
  8. package/dist/react/button.js +3 -3
  9. package/dist/react/button.js.map +1 -1
  10. package/dist/react/calendar.d.ts +13 -0
  11. package/dist/react/calendar.js +4639 -0
  12. package/dist/react/calendar.js.map +1 -0
  13. package/dist/react/card.d.ts +11 -0
  14. package/dist/react/card.js +113 -0
  15. package/dist/react/card.js.map +1 -0
  16. package/dist/react/checkbox.d.ts +11 -0
  17. package/dist/react/checkbox.js +131 -0
  18. package/dist/react/checkbox.js.map +1 -0
  19. package/dist/react/datetime-picker.d.ts +21 -0
  20. package/dist/react/datetime-picker.js +6124 -0
  21. package/dist/react/datetime-picker.js.map +1 -0
  22. package/dist/react/dialog.js +1 -1
  23. package/dist/react/dialog.js.map +1 -1
  24. package/dist/react/dropdown.d.ts +26 -9
  25. package/dist/react/dropdown.js +194 -96
  26. package/dist/react/dropdown.js.map +1 -1
  27. package/dist/react/input.d.ts +7 -0
  28. package/dist/react/input.js +15 -2
  29. package/dist/react/input.js.map +1 -1
  30. package/dist/react/pagination.d.ts +28 -0
  31. package/dist/react/pagination.js +262 -0
  32. package/dist/react/pagination.js.map +1 -0
  33. package/dist/react/popover.d.ts +76 -0
  34. package/dist/react/popover.js +564 -0
  35. package/dist/react/popover.js.map +1 -0
  36. package/dist/react/scroll-header.js +13 -1
  37. package/dist/react/scroll-header.js.map +1 -1
  38. package/dist/react/scroll-wheel.d.ts +45 -0
  39. package/dist/react/scroll-wheel.js +557 -0
  40. package/dist/react/scroll-wheel.js.map +1 -0
  41. package/dist/react/select.d.ts +62 -0
  42. package/dist/react/select.js +889 -0
  43. package/dist/react/select.js.map +1 -0
  44. package/dist/react/sheet.js +1 -1
  45. package/dist/react/sheet.js.map +1 -1
  46. package/dist/react/switch.d.ts +38 -0
  47. package/dist/react/switch.js +117 -0
  48. package/dist/react/switch.js.map +1 -0
  49. package/dist/react/table-pagination.d.ts +15 -0
  50. package/dist/react/table-pagination.js +1153 -0
  51. package/dist/react/table-pagination.js.map +1 -0
  52. package/dist/react/table-view/column-menu.d.ts +15 -0
  53. package/dist/react/table-view/column-menu.js +918 -0
  54. package/dist/react/table-view/column-menu.js.map +1 -0
  55. package/dist/react/table-view/index.d.ts +70 -0
  56. package/dist/react/table-view/index.js +2155 -0
  57. package/dist/react/table-view/index.js.map +1 -0
  58. package/dist/react/table.d.ts +86 -0
  59. package/dist/react/table.js +414 -0
  60. package/dist/react/table.js.map +1 -0
  61. package/dist/react/tabs.d.ts +9 -3
  62. package/dist/react/tabs.js +204 -48
  63. package/dist/react/tabs.js.map +1 -1
  64. package/dist/react/textarea.d.ts +6 -0
  65. package/dist/react/textarea.js +33 -0
  66. package/dist/react/textarea.js.map +1 -0
  67. package/dist/react/time-picker.d.ts +22 -0
  68. package/dist/react/time-picker.js +856 -0
  69. package/dist/react/time-picker.js.map +1 -0
  70. package/dist/react/tooltip.d.ts +45 -0
  71. package/dist/react/tooltip.js +540 -0
  72. package/dist/react/tooltip.js.map +1 -0
  73. package/package.json +1 -1
@@ -1,11 +1,12 @@
1
1
  import * as React from 'react';
2
2
  import { clsx } from 'clsx';
3
3
  import { twMerge } from 'tailwind-merge';
4
- import { jsx, jsxs } from 'react/jsx-runtime';
4
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
5
 
6
6
  function cn(...inputs) {
7
7
  return twMerge(clsx(inputs));
8
8
  }
9
+ var MD_UP = "(min-width: 768px)";
9
10
  var TabsContext = React.createContext(null);
10
11
  function useTabs() {
11
12
  const context = React.useContext(TabsContext);
@@ -21,11 +22,21 @@ var Tabs = ({
21
22
  children,
22
23
  className,
23
24
  variant = "pill",
25
+ alignment = "horizontal",
24
26
  ...props
25
27
  }) => {
26
28
  const [internalValue, setInternalValue] = React.useState(defaultValue);
29
+ const [isMdUp, setIsMdUp] = React.useState(false);
27
30
  const isControlled = controlledValue !== void 0;
28
31
  const value = isControlled ? controlledValue : internalValue;
32
+ React.useEffect(() => {
33
+ const mq = window.matchMedia(MD_UP);
34
+ const sync = () => setIsMdUp(mq.matches);
35
+ sync();
36
+ mq.addEventListener("change", sync);
37
+ return () => mq.removeEventListener("change", sync);
38
+ }, []);
39
+ const effectiveAlignment = alignment === "vertical" && isMdUp ? "vertical" : "horizontal";
29
40
  const handleValueChange = React.useCallback(
30
41
  (newValue) => {
31
42
  if (!isControlled) {
@@ -38,8 +49,24 @@ var Tabs = ({
38
49
  return /* @__PURE__ */ jsx(
39
50
  TabsContext.Provider,
40
51
  {
41
- value: { value, onValueChange: handleValueChange, variant },
42
- children: /* @__PURE__ */ jsx("div", { className: cn("flex flex-col gap-4", className), ...props, children })
52
+ value: {
53
+ value,
54
+ onValueChange: handleValueChange,
55
+ variant,
56
+ alignment: effectiveAlignment
57
+ },
58
+ children: /* @__PURE__ */ jsx(
59
+ "div",
60
+ {
61
+ className: cn(
62
+ "flex gap-4",
63
+ effectiveAlignment === "vertical" ? "flex-col md:flex-row md:items-stretch" : "flex-col",
64
+ className
65
+ ),
66
+ ...props,
67
+ children
68
+ }
69
+ )
43
70
  }
44
71
  );
45
72
  };
@@ -48,11 +75,52 @@ var TabsList = ({
48
75
  className,
49
76
  ...props
50
77
  }) => {
51
- const { value: activeValue, onValueChange, variant } = useTabs();
78
+ const { value: activeValue, onValueChange, variant, alignment } = useTabs();
79
+ const isVertical = alignment === "vertical";
52
80
  const rowRef = React.useRef(null);
81
+ const scrollRef = React.useRef(null);
82
+ const [scrollEdgesX, setScrollEdgesX] = React.useState("none");
83
+ const [scrollEdgesY, setScrollEdgesY] = React.useState("none");
84
+ const updateScrollEdges = React.useCallback(() => {
85
+ const el = scrollRef.current;
86
+ if (!el) return;
87
+ if (isVertical) {
88
+ const scrollRange = el.scrollHeight - el.clientHeight;
89
+ if (scrollRange < 8) {
90
+ setScrollEdgesY((prev) => prev === "none" ? prev : "none");
91
+ return;
92
+ }
93
+ const canUp = el.scrollTop > 1;
94
+ const canDown = el.scrollTop < scrollRange - 1;
95
+ const next = canUp && canDown ? "both" : canUp ? "up" : canDown ? "down" : "none";
96
+ setScrollEdgesY((prev) => prev === next ? prev : next);
97
+ } else {
98
+ const scrollRange = el.scrollWidth - el.clientWidth;
99
+ if (scrollRange < 8) {
100
+ setScrollEdgesX((prev) => prev === "none" ? prev : "none");
101
+ return;
102
+ }
103
+ const canLeft = el.scrollLeft > 1;
104
+ const canRight = el.scrollLeft < scrollRange - 1;
105
+ const next = canLeft && canRight ? "both" : canLeft ? "left" : canRight ? "right" : "none";
106
+ setScrollEdgesX((prev) => prev === next ? prev : next);
107
+ }
108
+ }, [isVertical]);
109
+ React.useEffect(() => {
110
+ const el = scrollRef.current;
111
+ if (!el) return;
112
+ updateScrollEdges();
113
+ el.addEventListener("scroll", updateScrollEdges, { passive: true });
114
+ window.addEventListener("resize", updateScrollEdges, { passive: true });
115
+ return () => {
116
+ el.removeEventListener("scroll", updateScrollEdges);
117
+ window.removeEventListener("resize", updateScrollEdges);
118
+ };
119
+ }, [updateScrollEdges, children, isVertical]);
53
120
  const updateIndicatorClip = React.useCallback(() => {
54
121
  const row = rowRef.current;
55
- if (!row || variant !== "pill" && variant !== "underline") return;
122
+ if (!row || variant !== "pill" && variant !== "underline" && variant !== "box")
123
+ return;
56
124
  const tab = row.querySelector(
57
125
  '[role="tab"][aria-selected="true"]:not(:disabled)'
58
126
  );
@@ -61,22 +129,30 @@ var TabsList = ({
61
129
  row.style.setProperty("--tab-indicator-end", "0px");
62
130
  return;
63
131
  }
64
- const start = tab.offsetLeft;
65
- const end = tab.offsetLeft + tab.offsetWidth;
66
- row.style.setProperty("--tab-indicator-start", `${start}px`);
67
- row.style.setProperty("--tab-indicator-end", `${end}px`);
68
- }, [variant]);
132
+ if (isVertical) {
133
+ const start = tab.offsetTop;
134
+ const end = tab.offsetTop + tab.offsetHeight;
135
+ row.style.setProperty("--tab-indicator-start", `${start}px`);
136
+ row.style.setProperty("--tab-indicator-end", `${end}px`);
137
+ } else {
138
+ const start = tab.offsetLeft;
139
+ const end = tab.offsetLeft + tab.offsetWidth;
140
+ row.style.setProperty("--tab-indicator-start", `${start}px`);
141
+ row.style.setProperty("--tab-indicator-end", `${end}px`);
142
+ }
143
+ }, [variant, isVertical]);
69
144
  React.useLayoutEffect(() => {
70
- if (variant === "pill" || variant === "underline") updateIndicatorClip();
145
+ if (variant === "pill" || variant === "underline" || variant === "box")
146
+ updateIndicatorClip();
71
147
  }, [activeValue, children, updateIndicatorClip, variant]);
72
148
  React.useEffect(() => {
73
- if (variant !== "pill" && variant !== "underline") return;
149
+ if (variant !== "pill" && variant !== "underline" && variant !== "box") return;
74
150
  const onResize = () => updateIndicatorClip();
75
151
  window.addEventListener("resize", onResize, { passive: true });
76
152
  return () => window.removeEventListener("resize", onResize);
77
153
  }, [updateIndicatorClip, activeValue, variant]);
78
154
  React.useEffect(() => {
79
- if (variant !== "pill" && variant !== "underline") return;
155
+ if (variant !== "pill" && variant !== "underline" && variant !== "box") return;
80
156
  const el = rowRef.current;
81
157
  if (!el || typeof ResizeObserver === "undefined") return;
82
158
  const ro = new ResizeObserver(() => updateIndicatorClip());
@@ -85,7 +161,7 @@ var TabsList = ({
85
161
  }, [updateIndicatorClip, variant]);
86
162
  const handleKeyDown = React.useCallback(
87
163
  (e) => {
88
- const dir = e.key === "ArrowRight" ? 1 : e.key === "ArrowLeft" ? -1 : 0;
164
+ const dir = isVertical ? e.key === "ArrowDown" ? 1 : e.key === "ArrowUp" ? -1 : 0 : e.key === "ArrowRight" ? 1 : e.key === "ArrowLeft" ? -1 : 0;
89
165
  if (!dir) return;
90
166
  const row = rowRef.current;
91
167
  if (!row) return;
@@ -104,28 +180,75 @@ var TabsList = ({
104
180
  tabs[next]?.focus();
105
181
  }
106
182
  },
107
- [activeValue, onValueChange]
183
+ [activeValue, onValueChange, isVertical]
108
184
  );
185
+ const maskStyle = React.useMemo(() => {
186
+ const fade = "24px";
187
+ if (isVertical) {
188
+ if (scrollEdgesY === "none") return void 0;
189
+ const masks2 = {
190
+ down: `linear-gradient(to bottom, black calc(100% - ${fade}), transparent)`,
191
+ up: `linear-gradient(to top, black calc(100% - ${fade}), transparent)`,
192
+ both: `linear-gradient(to bottom, transparent, black ${fade}, black calc(100% - ${fade}), transparent)`,
193
+ none: ""
194
+ };
195
+ return {
196
+ WebkitMaskImage: masks2[scrollEdgesY],
197
+ maskImage: masks2[scrollEdgesY]
198
+ };
199
+ }
200
+ if (scrollEdgesX === "none") return void 0;
201
+ const masks = {
202
+ right: `linear-gradient(to right, black calc(100% - ${fade}), transparent)`,
203
+ left: `linear-gradient(to left, black calc(100% - ${fade}), transparent)`,
204
+ both: `linear-gradient(to right, transparent, black ${fade}, black calc(100% - ${fade}), transparent)`,
205
+ none: ""
206
+ };
207
+ return {
208
+ WebkitMaskImage: masks[scrollEdgesX],
209
+ maskImage: masks[scrollEdgesX]
210
+ };
211
+ }, [scrollEdgesX, scrollEdgesY, isVertical]);
212
+ const pillClipHorizontal = "inset(0 calc(100% - var(--tab-indicator-end, 0px)) 0 var(--tab-indicator-start, 0px) round 9999px)";
213
+ const pillClipVertical = "inset(var(--tab-indicator-start, 0px) 0 calc(100% - var(--tab-indicator-end, 0px)) 0 round 9999px)";
214
+ const boxClipHorizontal = "inset(0 calc(100% - var(--tab-indicator-end, 0px)) 0 var(--tab-indicator-start, 0px) round 12px)";
215
+ const boxClipVertical = "inset(var(--tab-indicator-start, 0px) 0 calc(100% - var(--tab-indicator-end, 0px)) 0 round 12px)";
216
+ const underlineClipHorizontal = "inset(0 calc(100% - var(--tab-indicator-end, 0px)) 0 var(--tab-indicator-start, 0px))";
217
+ const underlineClipVertical = "inset(var(--tab-indicator-start, 0px) 0 calc(100% - var(--tab-indicator-end, 0px)) 0)";
109
218
  return /* @__PURE__ */ jsx(
110
219
  "div",
111
220
  {
221
+ ref: scrollRef,
112
222
  onKeyDown: handleKeyDown,
113
223
  className: cn(
114
- "max-w-full overflow-x-auto no-scrollbar",
115
- variant === "pill" ? "pb-1" : "pb-0",
224
+ isVertical ? "max-h-72 min-h-0 w-full max-w-52 shrink-0 overflow-x-hidden overflow-y-auto md:max-h-none md:max-w-56" : "max-w-full overflow-x-auto",
225
+ "[scrollbar-width:none] [-ms-overflow-style:none] [&::-webkit-scrollbar]:hidden",
226
+ variant === "pill" && !isVertical && "pb-1",
227
+ variant === "box" && !isVertical && "pb-1",
228
+ variant === "underline" && !isVertical && "pb-0",
229
+ variant === "underline" && isVertical && "pr-0",
116
230
  className
117
231
  ),
232
+ style: maskStyle,
118
233
  ...props,
119
234
  children: /* @__PURE__ */ jsxs(
120
235
  "div",
121
236
  {
122
237
  ref: rowRef,
123
238
  role: "tablist",
239
+ "aria-orientation": isVertical ? "vertical" : "horizontal",
124
240
  className: cn(
125
- "inline-flex w-max min-w-full items-center",
126
- (variant === "pill" || variant === "underline") && "relative",
241
+ "flex",
242
+ isVertical ? "w-full flex-col items-stretch" : cn(
243
+ "inline-flex w-max min-w-full",
244
+ variant === "box" ? "items-stretch" : "items-center"
245
+ ),
246
+ (variant === "pill" || variant === "underline" || variant === "box") && "relative",
127
247
  variant === "pill" && "gap-1",
128
- variant === "underline" && "gap-2 rounded-none border-b border-border bg-transparent py-0"
248
+ variant === "box" && "gap-2",
249
+ variant === "pill" && isVertical && "px-1 py-1",
250
+ variant === "box" && isVertical && "px-1 py-1",
251
+ variant === "underline" && (isVertical ? "gap-0 rounded-none border-l border-border bg-transparent py-0 pl-0" : "gap-2 rounded-none border-b border-border bg-transparent py-0")
129
252
  ),
130
253
  children: [
131
254
  variant === "pill" && /* @__PURE__ */ jsx(
@@ -134,10 +257,26 @@ var TabsList = ({
134
257
  "aria-hidden": "true",
135
258
  "data-slot": "tabs-indicator",
136
259
  style: {
137
- clipPath: "inset(0 calc(100% - var(--tab-indicator-end, 0px)) 0 var(--tab-indicator-start, 0px) round 9999px)"
260
+ clipPath: isVertical ? pillClipVertical : pillClipHorizontal
138
261
  },
139
262
  className: cn(
140
- "pointer-events-none absolute inset-x-0 top-0 z-0 h-9 rounded-full bg-primary",
263
+ "pointer-events-none absolute z-0 bg-primary",
264
+ "motion-reduce:transition-none",
265
+ "motion-safe:transition-[clip-path] motion-safe:duration-300 motion-safe:ease-[cubic-bezier(0,0.55,0.45,1)]",
266
+ isVertical ? "inset-y-0 left-0 right-0" : "inset-x-0 top-0 h-9 rounded-full"
267
+ )
268
+ }
269
+ ),
270
+ variant === "box" && /* @__PURE__ */ jsx(
271
+ "div",
272
+ {
273
+ "aria-hidden": "true",
274
+ "data-slot": "tabs-box-indicator",
275
+ style: {
276
+ clipPath: isVertical ? boxClipVertical : boxClipHorizontal
277
+ },
278
+ className: cn(
279
+ "pointer-events-none absolute inset-y-0 left-0 right-0 z-0 bg-primary",
141
280
  "motion-reduce:transition-none",
142
281
  "motion-safe:transition-[clip-path] motion-safe:duration-300 motion-safe:ease-[cubic-bezier(0,0.55,0.45,1)]"
143
282
  )
@@ -149,12 +288,13 @@ var TabsList = ({
149
288
  "aria-hidden": "true",
150
289
  "data-slot": "tabs-underline-indicator",
151
290
  style: {
152
- clipPath: "inset(0 calc(100% - var(--tab-indicator-end, 0px)) 0 var(--tab-indicator-start, 0px))"
291
+ clipPath: isVertical ? underlineClipVertical : underlineClipHorizontal
153
292
  },
154
293
  className: cn(
155
- "pointer-events-none absolute inset-x-0 bottom-0 z-0 h-0.5 bg-primary",
294
+ "pointer-events-none absolute z-0 bg-primary",
156
295
  "motion-reduce:transition-none",
157
- "motion-safe:transition-[clip-path] motion-safe:duration-300 motion-safe:ease-[cubic-bezier(0,0.55,0.45,1)]"
296
+ "motion-safe:transition-[clip-path] motion-safe:duration-300 motion-safe:ease-[cubic-bezier(0,0.55,0.45,1)]",
297
+ isVertical ? "inset-y-0 left-0 w-0.5" : "inset-x-0 bottom-0 h-0.5"
158
298
  )
159
299
  }
160
300
  ),
@@ -170,14 +310,19 @@ var TabsTrigger = ({
170
310
  children,
171
311
  icon,
172
312
  iconPosition = "left",
313
+ layout = "row",
173
314
  onClick,
174
315
  className,
175
316
  disabled,
176
317
  ...props
177
318
  }) => {
178
- const { value: activeValue, onValueChange, variant } = useTabs();
319
+ const { value: activeValue, onValueChange, variant, alignment } = useTabs();
320
+ const isVertical = alignment === "vertical";
179
321
  const isActive = value ? activeValue === value : false;
180
322
  const showSelected = isActive && !disabled;
323
+ const isStacked = layout === "stacked" && Boolean(icon);
324
+ const iconWrapClass = "inline-flex shrink-0 items-center justify-center [&_svg]:shrink-0";
325
+ const labelWrapClass = "block min-w-0 w-full text-left leading-snug";
181
326
  return /* @__PURE__ */ jsxs(
182
327
  "button",
183
328
  {
@@ -194,19 +339,33 @@ var TabsTrigger = ({
194
339
  onClick?.(e);
195
340
  },
196
341
  className: cn(
197
- "relative z-1 inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap touch-manipulation [-webkit-tap-highlight-color:transparent]",
342
+ "relative z-1 inline-flex shrink-0 select-none touch-manipulation [-webkit-tap-highlight-color:transparent]",
198
343
  "cursor-pointer disabled:cursor-not-allowed",
344
+ isStacked ? "flex-col items-start justify-start gap-1.5 whitespace-normal" : "items-center justify-center gap-2 whitespace-nowrap",
345
+ isVertical && "w-full justify-start",
199
346
  variant === "pill" && [
200
347
  "h-9 rounded-full px-4 font-semibold leading-5 text-[13px] md:text-[15px]",
201
348
  "[transition:background-color_var(--duration-short-s,0.1s)_var(--ease-out,cubic-bezier(0,.55,.45,1)),border-color_var(--duration-short-s,0.1s)_var(--ease-out,cubic-bezier(0,.55,.45,1)),scale_var(--duration-short-s,0.1s)_var(--ease-out,cubic-bezier(0,.55,.45,1)),color_var(--duration-short-m,0.2s)_var(--ease-in-out,cubic-bezier(.85,0,.15,1))]",
202
- "enabled:active:scale-[0.96] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
349
+ !isVertical && "enabled:active:scale-[0.96]",
350
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
203
351
  showSelected ? [
204
352
  "text-background",
205
353
  "**:data-[slot=badge]:border-none **:data-[slot=badge]:bg-background/20 **:data-[slot=badge]:text-background"
206
354
  ] : "bg-primary/4 text-primary/50 enabled:[@media(hover:hover)_and_(pointer:fine)]:hover:bg-primary/10 enabled:active:bg-primary/10"
207
355
  ],
356
+ variant === "box" && [
357
+ "min-h-11 rounded-xl px-4 pt-1.5 pb-2 font-semibold leading-5 text-[13px] md:text-[15px]",
358
+ isVertical ? "justify-start text-left" : "justify-center text-center",
359
+ "[transition:background-color_var(--duration-short-s,0.1s)_var(--ease-out,cubic-bezier(0,.55,.45,1)),color_var(--duration-short-m,0.2s)_var(--ease-in-out,cubic-bezier(.85,0,.15,1))]",
360
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
361
+ showSelected ? [
362
+ "text-background",
363
+ "**:data-[slot=badge]:border-none **:data-[slot=badge]:bg-background/20 **:data-[slot=badge]:text-background"
364
+ ] : "bg-transparent text-primary/55 enabled:[@media(hover:hover)_and_(pointer:fine)]:hover:bg-primary/[0.07] enabled:[@media(hover:hover)_and_(pointer:fine)]:hover:text-primary/75"
365
+ ],
208
366
  variant === "underline" && [
209
- "h-auto rounded-none border-0 bg-transparent px-2 py-2 text-sm font-medium shadow-none",
367
+ "h-auto rounded-none border-0 bg-transparent py-2 text-sm font-medium shadow-none",
368
+ isVertical ? isStacked ? "pl-6 pr-2" : "pl-5 pr-2" : "px-2",
210
369
  "transition-[color,transform] duration-200 ease-in-out",
211
370
  "motion-reduce:transition-colors motion-reduce:enabled:active:scale-100",
212
371
  "enabled:active:scale-[0.98]",
@@ -218,23 +377,17 @@ var TabsTrigger = ({
218
377
  ),
219
378
  ...props,
220
379
  children: [
221
- icon && iconPosition === "left" && /* @__PURE__ */ jsx(
222
- "span",
223
- {
224
- className: "flex size-4 shrink-0 items-center justify-center",
225
- "aria-hidden": true,
226
- children: icon
227
- }
228
- ),
229
- children,
230
- icon && iconPosition === "right" && /* @__PURE__ */ jsx(
231
- "span",
232
- {
233
- className: "flex size-4 shrink-0 items-center justify-center",
234
- "aria-hidden": true,
235
- children: icon
236
- }
237
- )
380
+ isStacked && icon && iconPosition === "left" && /* @__PURE__ */ jsxs(Fragment, { children: [
381
+ /* @__PURE__ */ jsx("span", { className: iconWrapClass, "aria-hidden": true, children: icon }),
382
+ /* @__PURE__ */ jsx("span", { className: labelWrapClass, children })
383
+ ] }),
384
+ isStacked && icon && iconPosition === "right" && /* @__PURE__ */ jsxs(Fragment, { children: [
385
+ /* @__PURE__ */ jsx("span", { className: labelWrapClass, children }),
386
+ /* @__PURE__ */ jsx("span", { className: iconWrapClass, "aria-hidden": true, children: icon })
387
+ ] }),
388
+ !isStacked && icon && iconPosition === "left" && /* @__PURE__ */ jsx("span", { className: iconWrapClass, "aria-hidden": true, children: icon }),
389
+ !isStacked && children,
390
+ !isStacked && icon && iconPosition === "right" && /* @__PURE__ */ jsx("span", { className: iconWrapClass, "aria-hidden": true, children: icon })
238
391
  ]
239
392
  }
240
393
  );
@@ -245,15 +398,18 @@ var TabsContent = ({
245
398
  className,
246
399
  ...props
247
400
  }) => {
248
- const { value: activeValue } = useTabs();
401
+ const { value: activeValue, alignment } = useTabs();
402
+ const isVertical = alignment === "vertical";
249
403
  if (activeValue !== value) return null;
250
404
  return /* @__PURE__ */ jsx(
251
405
  "div",
252
406
  {
253
407
  role: "tabpanel",
254
408
  className: cn(
255
- "animate-in fade-in-0 slide-in-from-top-1 duration-200",
409
+ "animate-in fade-in-0 duration-200",
410
+ isVertical ? "slide-in-from-left-1" : "slide-in-from-top-1",
256
411
  "ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
412
+ isVertical && "min-w-0 flex-1",
257
413
  className
258
414
  ),
259
415
  ...props,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/lib/utils.ts","../../src/react/tabs.tsx"],"names":[],"mappings":"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","file":"tabs.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\n\n//////////////////////////////////////////////// CONTEXT\n\nexport type TabsVariant = \"pill\" | \"underline\";\n\ninterface TabsProps extends React.HTMLAttributes<HTMLDivElement> {\n defaultValue?: string;\n value?: string;\n onValueChange?: (value: string) => void;\n /** `pill` — segmented control with sliding primary fill (default). `underline` — bottom border row + clip-path sliding primary underline. */\n variant?: TabsVariant;\n children: React.ReactNode;\n}\n\nconst TabsContext = React.createContext<{\n value?: string;\n onValueChange: (value: string) => void;\n variant: TabsVariant;\n} | null>(null);\n\nfunction useTabs() {\n const context = React.useContext(TabsContext);\n if (!context) {\n throw new Error(\"Tabs components must be used within a <Tabs />\");\n }\n return context;\n}\n\nexport const Tabs: React.FC<TabsProps> = ({\n defaultValue,\n value: controlledValue,\n onValueChange,\n children,\n className,\n variant = \"pill\",\n ...props\n}) => {\n const [internalValue, setInternalValue] = React.useState(defaultValue);\n const isControlled = controlledValue !== undefined;\n const value = isControlled ? controlledValue : internalValue;\n\n const handleValueChange = React.useCallback(\n (newValue: string) => {\n if (!isControlled) {\n setInternalValue(newValue);\n }\n onValueChange?.(newValue);\n },\n [isControlled, onValueChange],\n );\n\n return (\n <TabsContext.Provider\n value={{ value, onValueChange: handleValueChange, variant }}\n >\n <div className={cn(\"flex flex-col gap-4\", className)} {...props}>\n {children}\n </div>\n </TabsContext.Provider>\n );\n};\n\ninterface TabsListProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport const TabsList: React.FC<TabsListProps> = ({\n children,\n className,\n ...props\n}) => {\n const { value: activeValue, onValueChange, variant } = useTabs();\n const rowRef = React.useRef<HTMLDivElement>(null);\n\n /** Drives horizontal `clip-path` via `--tab-indicator-start` / `--tab-indicator-end` (px from row left). */\n const updateIndicatorClip = React.useCallback(() => {\n const row = rowRef.current;\n if (!row || (variant !== \"pill\" && variant !== \"underline\")) return;\n\n const tab = row.querySelector<HTMLElement>(\n '[role=\"tab\"][aria-selected=\"true\"]:not(:disabled)',\n );\n if (!tab) {\n row.style.setProperty(\"--tab-indicator-start\", \"0px\");\n row.style.setProperty(\"--tab-indicator-end\", \"0px\");\n return;\n }\n\n const start = tab.offsetLeft;\n const end = tab.offsetLeft + tab.offsetWidth;\n row.style.setProperty(\"--tab-indicator-start\", `${start}px`);\n row.style.setProperty(\"--tab-indicator-end\", `${end}px`);\n }, [variant]);\n\n React.useLayoutEffect(() => {\n if (variant === \"pill\" || variant === \"underline\") updateIndicatorClip();\n }, [activeValue, children, updateIndicatorClip, variant]);\n\n React.useEffect(() => {\n if (variant !== \"pill\" && variant !== \"underline\") return;\n const onResize = () => updateIndicatorClip();\n window.addEventListener(\"resize\", onResize, { passive: true });\n return () => window.removeEventListener(\"resize\", onResize);\n }, [updateIndicatorClip, activeValue, variant]);\n\n React.useEffect(() => {\n if (variant !== \"pill\" && variant !== \"underline\") return;\n const el = rowRef.current;\n if (!el || typeof ResizeObserver === \"undefined\") return;\n const ro = new ResizeObserver(() => updateIndicatorClip());\n ro.observe(el);\n return () => ro.disconnect();\n }, [updateIndicatorClip, variant]);\n\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent<HTMLDivElement>) => {\n const dir = e.key === \"ArrowRight\" ? 1 : e.key === \"ArrowLeft\" ? -1 : 0;\n if (!dir) return;\n const row = rowRef.current;\n if (!row) return;\n const tabs = Array.from(\n row.querySelectorAll<HTMLButtonElement>('[role=\"tab\"][data-tab-value]'),\n ).filter((t) => !t.disabled);\n if (tabs.length === 0) return;\n const values = tabs.map((t) => t.dataset.tabValue!);\n let idx = activeValue ? values.indexOf(activeValue) : 0;\n if (idx < 0) idx = 0;\n const next = (idx + dir + values.length) % values.length;\n const nextValue = values[next];\n if (nextValue) {\n e.preventDefault();\n onValueChange(nextValue);\n tabs[next]?.focus();\n }\n },\n [activeValue, onValueChange],\n );\n\n return (\n <div\n onKeyDown={handleKeyDown}\n className={cn(\n \"max-w-full overflow-x-auto no-scrollbar\",\n variant === \"pill\" ? \"pb-1\" : \"pb-0\",\n className,\n )}\n {...props}\n >\n <div\n ref={rowRef}\n role=\"tablist\"\n className={cn(\n \"inline-flex w-max min-w-full items-center\",\n (variant === \"pill\" || variant === \"underline\") && \"relative\",\n variant === \"pill\" && \"gap-1\",\n variant === \"underline\" &&\n \"gap-2 rounded-none border-b border-border bg-transparent py-0\",\n )}\n >\n {variant === \"pill\" && (\n <div\n aria-hidden=\"true\"\n data-slot=\"tabs-indicator\"\n style={{\n clipPath:\n \"inset(0 calc(100% - var(--tab-indicator-end, 0px)) 0 var(--tab-indicator-start, 0px) round 9999px)\",\n }}\n className={cn(\n \"pointer-events-none absolute inset-x-0 top-0 z-0 h-9 rounded-full bg-primary\",\n \"motion-reduce:transition-none\",\n \"motion-safe:transition-[clip-path] motion-safe:duration-300 motion-safe:ease-[cubic-bezier(0,0.55,0.45,1)]\",\n )}\n />\n )}\n {variant === \"underline\" && (\n <div\n aria-hidden=\"true\"\n data-slot=\"tabs-underline-indicator\"\n style={{\n clipPath:\n \"inset(0 calc(100% - var(--tab-indicator-end, 0px)) 0 var(--tab-indicator-start, 0px))\",\n }}\n className={cn(\n \"pointer-events-none absolute inset-x-0 bottom-0 z-0 h-0.5 bg-primary\",\n \"motion-reduce:transition-none\",\n \"motion-safe:transition-[clip-path] motion-safe:duration-300 motion-safe:ease-[cubic-bezier(0,0.55,0.45,1)]\",\n )}\n />\n )}\n {children}\n </div>\n </div>\n );\n};\n\ninterface TabsTriggerProps extends Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n \"onClick\"\n> {\n value?: string;\n icon?: React.ReactNode;\n iconPosition?: \"left\" | \"right\";\n onClick?: React.MouseEventHandler<HTMLButtonElement>;\n}\n\nexport const TabsTrigger: React.FC<TabsTriggerProps> = ({\n value,\n children,\n icon,\n iconPosition = \"left\",\n onClick,\n className,\n disabled,\n ...props\n}) => {\n const { value: activeValue, onValueChange, variant } = useTabs();\n const isActive = value ? activeValue === value : false;\n const showSelected = isActive && !disabled;\n\n return (\n <button\n type=\"button\"\n role=\"tab\"\n aria-selected={isActive}\n aria-disabled={disabled || undefined}\n tabIndex={\n value !== undefined ? (isActive && !disabled ? 0 : -1) : undefined\n }\n disabled={disabled}\n data-tab-value={value}\n onClick={(e) => {\n if (disabled) return;\n if (value) onValueChange(value);\n onClick?.(e);\n }}\n className={cn(\n \"relative z-1 inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap touch-manipulation [-webkit-tap-highlight-color:transparent]\",\n \"cursor-pointer disabled:cursor-not-allowed\",\n variant === \"pill\" && [\n \"h-9 rounded-full px-4 font-semibold leading-5 text-[13px] md:text-[15px]\",\n \"[transition:background-color_var(--duration-short-s,0.1s)_var(--ease-out,cubic-bezier(0,.55,.45,1)),border-color_var(--duration-short-s,0.1s)_var(--ease-out,cubic-bezier(0,.55,.45,1)),scale_var(--duration-short-s,0.1s)_var(--ease-out,cubic-bezier(0,.55,.45,1)),color_var(--duration-short-m,0.2s)_var(--ease-in-out,cubic-bezier(.85,0,.15,1))]\",\n \"enabled:active:scale-[0.96] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n showSelected\n ? [\n \"text-background\",\n \"**:data-[slot=badge]:border-none **:data-[slot=badge]:bg-background/20 **:data-[slot=badge]:text-background\",\n ]\n : \"bg-primary/4 text-primary/50 enabled:[@media(hover:hover)_and_(pointer:fine)]:hover:bg-primary/10 enabled:active:bg-primary/10\",\n ],\n variant === \"underline\" && [\n \"h-auto rounded-none border-0 bg-transparent px-2 py-2 text-sm font-medium shadow-none\",\n \"transition-[color,transform] duration-200 ease-in-out\",\n \"motion-reduce:transition-colors motion-reduce:enabled:active:scale-100\",\n \"enabled:active:scale-[0.98]\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n showSelected\n ? \"text-primary\"\n : \"text-primary/50 enabled:[@media(hover:hover)_and_(pointer:fine)]:hover:text-primary/70\",\n ],\n \"disabled:opacity-50\",\n className,\n )}\n {...props}\n >\n {icon && iconPosition === \"left\" && (\n <span\n className=\"flex size-4 shrink-0 items-center justify-center\"\n aria-hidden\n >\n {icon}\n </span>\n )}\n {children}\n {icon && iconPosition === \"right\" && (\n <span\n className=\"flex size-4 shrink-0 items-center justify-center\"\n aria-hidden\n >\n {icon}\n </span>\n )}\n </button>\n );\n};\n\ninterface TabsContentProps extends React.HTMLAttributes<HTMLDivElement> {\n value: string;\n}\n\nexport const TabsContent: React.FC<TabsContentProps> = ({\n value,\n children,\n className,\n ...props\n}) => {\n const { value: activeValue } = useTabs();\n\n if (activeValue !== value) return null;\n\n return (\n <div\n role=\"tabpanel\"\n className={cn(\n \"animate-in fade-in-0 slide-in-from-top-1 duration-200\",\n \"ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n className,\n )}\n {...props}\n >\n {children}\n </div>\n );\n};\n"]}
1
+ {"version":3,"sources":["../../src/lib/utils.ts","../../src/react/tabs.tsx"],"names":["masks"],"mappings":"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","file":"tabs.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\n\nconst MD_UP = \"(min-width: 768px)\";\n\n//////////////////////////////////////////////// CONTEXT\n\nexport type TabsVariant = \"pill\" | \"underline\" | \"box\";\nexport type TabsAlignment = \"horizontal\" | \"vertical\";\nexport type TabsTriggerLayout = \"row\" | \"stacked\";\n\ninterface TabsProps extends React.HTMLAttributes<HTMLDivElement> {\n defaultValue?: string;\n value?: string;\n onValueChange?: (value: string) => void;\n /** `pill` — compact pill track (default). `box` — larger padding, `rounded-xl` sliding fill. `underline` — border row + clip-path bar. */\n variant?: TabsVariant;\n /** Tab list layout: row (default) or stacked sidebar with panel beside it from `md` up; below `md`, vertical is shown as horizontal. */\n alignment?: TabsAlignment;\n children: React.ReactNode;\n}\n\nconst TabsContext = React.createContext<{\n value?: string;\n onValueChange: (value: string) => void;\n variant: TabsVariant;\n alignment: TabsAlignment;\n} | null>(null);\n\nfunction useTabs() {\n const context = React.useContext(TabsContext);\n if (!context) {\n throw new Error(\"Tabs components must be used within a <Tabs />\");\n }\n return context;\n}\n\nexport const Tabs: React.FC<TabsProps> = ({\n defaultValue,\n value: controlledValue,\n onValueChange,\n children,\n className,\n variant = \"pill\",\n alignment = \"horizontal\",\n ...props\n}) => {\n const [internalValue, setInternalValue] = React.useState(defaultValue);\n const [isMdUp, setIsMdUp] = React.useState(false);\n const isControlled = controlledValue !== undefined;\n const value = isControlled ? controlledValue : internalValue;\n\n React.useEffect(() => {\n const mq = window.matchMedia(MD_UP);\n const sync = () => setIsMdUp(mq.matches);\n sync();\n mq.addEventListener(\"change\", sync);\n return () => mq.removeEventListener(\"change\", sync);\n }, []);\n\n const effectiveAlignment: TabsAlignment =\n alignment === \"vertical\" && isMdUp ? \"vertical\" : \"horizontal\";\n\n const handleValueChange = React.useCallback(\n (newValue: string) => {\n if (!isControlled) {\n setInternalValue(newValue);\n }\n onValueChange?.(newValue);\n },\n [isControlled, onValueChange],\n );\n\n return (\n <TabsContext.Provider\n value={{\n value,\n onValueChange: handleValueChange,\n variant,\n alignment: effectiveAlignment,\n }}\n >\n <div\n className={cn(\n \"flex gap-4\",\n effectiveAlignment === \"vertical\"\n ? \"flex-col md:flex-row md:items-stretch\"\n : \"flex-col\",\n className,\n )}\n {...props}\n >\n {children}\n </div>\n </TabsContext.Provider>\n );\n};\n\ninterface TabsListProps extends React.HTMLAttributes<HTMLDivElement> {}\n\ntype ScrollFadeX = \"none\" | \"right\" | \"left\" | \"both\";\ntype ScrollFadeY = \"none\" | \"down\" | \"up\" | \"both\";\n\nexport const TabsList: React.FC<TabsListProps> = ({\n children,\n className,\n ...props\n}) => {\n const { value: activeValue, onValueChange, variant, alignment } = useTabs();\n const isVertical = alignment === \"vertical\";\n const rowRef = React.useRef<HTMLDivElement>(null);\n const scrollRef = React.useRef<HTMLDivElement>(null);\n const [scrollEdgesX, setScrollEdgesX] = React.useState<ScrollFadeX>(\"none\");\n const [scrollEdgesY, setScrollEdgesY] = React.useState<ScrollFadeY>(\"none\");\n\n const updateScrollEdges = React.useCallback(() => {\n const el = scrollRef.current;\n if (!el) return;\n if (isVertical) {\n const scrollRange = el.scrollHeight - el.clientHeight;\n if (scrollRange < 8) {\n setScrollEdgesY((prev) => (prev === \"none\" ? prev : \"none\"));\n return;\n }\n const canUp = el.scrollTop > 1;\n const canDown = el.scrollTop < scrollRange - 1;\n const next: ScrollFadeY =\n canUp && canDown\n ? \"both\"\n : canUp\n ? \"up\"\n : canDown\n ? \"down\"\n : \"none\";\n setScrollEdgesY((prev) => (prev === next ? prev : next));\n } else {\n const scrollRange = el.scrollWidth - el.clientWidth;\n if (scrollRange < 8) {\n setScrollEdgesX((prev) => (prev === \"none\" ? prev : \"none\"));\n return;\n }\n const canLeft = el.scrollLeft > 1;\n const canRight = el.scrollLeft < scrollRange - 1;\n const next: ScrollFadeX =\n canLeft && canRight\n ? \"both\"\n : canLeft\n ? \"left\"\n : canRight\n ? \"right\"\n : \"none\";\n setScrollEdgesX((prev) => (prev === next ? prev : next));\n }\n }, [isVertical]);\n\n React.useEffect(() => {\n const el = scrollRef.current;\n if (!el) return;\n updateScrollEdges();\n el.addEventListener(\"scroll\", updateScrollEdges, { passive: true });\n window.addEventListener(\"resize\", updateScrollEdges, { passive: true });\n return () => {\n el.removeEventListener(\"scroll\", updateScrollEdges);\n window.removeEventListener(\"resize\", updateScrollEdges);\n };\n }, [updateScrollEdges, children, isVertical]);\n\n const updateIndicatorClip = React.useCallback(() => {\n const row = rowRef.current;\n if (!row || (variant !== \"pill\" && variant !== \"underline\" && variant !== \"box\"))\n return;\n\n const tab = row.querySelector<HTMLElement>(\n '[role=\"tab\"][aria-selected=\"true\"]:not(:disabled)',\n );\n if (!tab) {\n row.style.setProperty(\"--tab-indicator-start\", \"0px\");\n row.style.setProperty(\"--tab-indicator-end\", \"0px\");\n return;\n }\n\n if (isVertical) {\n const start = tab.offsetTop;\n const end = tab.offsetTop + tab.offsetHeight;\n row.style.setProperty(\"--tab-indicator-start\", `${start}px`);\n row.style.setProperty(\"--tab-indicator-end\", `${end}px`);\n } else {\n const start = tab.offsetLeft;\n const end = tab.offsetLeft + tab.offsetWidth;\n row.style.setProperty(\"--tab-indicator-start\", `${start}px`);\n row.style.setProperty(\"--tab-indicator-end\", `${end}px`);\n }\n }, [variant, isVertical]);\n\n React.useLayoutEffect(() => {\n if (variant === \"pill\" || variant === \"underline\" || variant === \"box\")\n updateIndicatorClip();\n }, [activeValue, children, updateIndicatorClip, variant]);\n\n React.useEffect(() => {\n if (variant !== \"pill\" && variant !== \"underline\" && variant !== \"box\") return;\n const onResize = () => updateIndicatorClip();\n window.addEventListener(\"resize\", onResize, { passive: true });\n return () => window.removeEventListener(\"resize\", onResize);\n }, [updateIndicatorClip, activeValue, variant]);\n\n React.useEffect(() => {\n if (variant !== \"pill\" && variant !== \"underline\" && variant !== \"box\") return;\n const el = rowRef.current;\n if (!el || typeof ResizeObserver === \"undefined\") return;\n const ro = new ResizeObserver(() => updateIndicatorClip());\n ro.observe(el);\n return () => ro.disconnect();\n }, [updateIndicatorClip, variant]);\n\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent<HTMLDivElement>) => {\n const dir = isVertical\n ? e.key === \"ArrowDown\"\n ? 1\n : e.key === \"ArrowUp\"\n ? -1\n : 0\n : e.key === \"ArrowRight\"\n ? 1\n : e.key === \"ArrowLeft\"\n ? -1\n : 0;\n if (!dir) return;\n const row = rowRef.current;\n if (!row) return;\n const tabs = Array.from(\n row.querySelectorAll<HTMLButtonElement>('[role=\"tab\"][data-tab-value]'),\n ).filter((t) => !t.disabled);\n if (tabs.length === 0) return;\n const values = tabs.map((t) => t.dataset.tabValue!);\n let idx = activeValue ? values.indexOf(activeValue) : 0;\n if (idx < 0) idx = 0;\n const next = (idx + dir + values.length) % values.length;\n const nextValue = values[next];\n if (nextValue) {\n e.preventDefault();\n onValueChange(nextValue);\n tabs[next]?.focus();\n }\n },\n [activeValue, onValueChange, isVertical],\n );\n\n const maskStyle = React.useMemo<React.CSSProperties | undefined>(() => {\n const fade = \"24px\";\n if (isVertical) {\n if (scrollEdgesY === \"none\") return undefined;\n const masks: Record<ScrollFadeY, string> = {\n down: `linear-gradient(to bottom, black calc(100% - ${fade}), transparent)`,\n up: `linear-gradient(to top, black calc(100% - ${fade}), transparent)`,\n both: `linear-gradient(to bottom, transparent, black ${fade}, black calc(100% - ${fade}), transparent)`,\n none: \"\",\n };\n return {\n WebkitMaskImage: masks[scrollEdgesY],\n maskImage: masks[scrollEdgesY],\n };\n }\n if (scrollEdgesX === \"none\") return undefined;\n const masks: Record<ScrollFadeX, string> = {\n right: `linear-gradient(to right, black calc(100% - ${fade}), transparent)`,\n left: `linear-gradient(to left, black calc(100% - ${fade}), transparent)`,\n both: `linear-gradient(to right, transparent, black ${fade}, black calc(100% - ${fade}), transparent)`,\n none: \"\",\n };\n return {\n WebkitMaskImage: masks[scrollEdgesX],\n maskImage: masks[scrollEdgesX],\n };\n }, [scrollEdgesX, scrollEdgesY, isVertical]);\n\n const pillClipHorizontal =\n \"inset(0 calc(100% - var(--tab-indicator-end, 0px)) 0 var(--tab-indicator-start, 0px) round 9999px)\";\n const pillClipVertical =\n \"inset(var(--tab-indicator-start, 0px) 0 calc(100% - var(--tab-indicator-end, 0px)) 0 round 9999px)\";\n const boxClipHorizontal =\n \"inset(0 calc(100% - var(--tab-indicator-end, 0px)) 0 var(--tab-indicator-start, 0px) round 12px)\";\n const boxClipVertical =\n \"inset(var(--tab-indicator-start, 0px) 0 calc(100% - var(--tab-indicator-end, 0px)) 0 round 12px)\";\n const underlineClipHorizontal =\n \"inset(0 calc(100% - var(--tab-indicator-end, 0px)) 0 var(--tab-indicator-start, 0px))\";\n const underlineClipVertical =\n \"inset(var(--tab-indicator-start, 0px) 0 calc(100% - var(--tab-indicator-end, 0px)) 0)\";\n\n return (\n <div\n ref={scrollRef}\n onKeyDown={handleKeyDown}\n className={cn(\n isVertical\n ? \"max-h-72 min-h-0 w-full max-w-52 shrink-0 overflow-x-hidden overflow-y-auto md:max-h-none md:max-w-56\"\n : \"max-w-full overflow-x-auto\",\n \"[scrollbar-width:none] [-ms-overflow-style:none] [&::-webkit-scrollbar]:hidden\",\n variant === \"pill\" && !isVertical && \"pb-1\",\n variant === \"box\" && !isVertical && \"pb-1\",\n variant === \"underline\" && !isVertical && \"pb-0\",\n variant === \"underline\" && isVertical && \"pr-0\",\n className,\n )}\n style={maskStyle}\n {...props}\n >\n <div\n ref={rowRef}\n role=\"tablist\"\n aria-orientation={isVertical ? \"vertical\" : \"horizontal\"}\n className={cn(\n \"flex\",\n isVertical\n ? \"w-full flex-col items-stretch\"\n : cn(\n \"inline-flex w-max min-w-full\",\n variant === \"box\" ? \"items-stretch\" : \"items-center\",\n ),\n (variant === \"pill\" || variant === \"underline\" || variant === \"box\") &&\n \"relative\",\n variant === \"pill\" && \"gap-1\",\n variant === \"box\" && \"gap-2\",\n variant === \"pill\" && isVertical && \"px-1 py-1\",\n variant === \"box\" && isVertical && \"px-1 py-1\",\n variant === \"underline\" &&\n (isVertical\n ? \"gap-0 rounded-none border-l border-border bg-transparent py-0 pl-0\"\n : \"gap-2 rounded-none border-b border-border bg-transparent py-0\"),\n )}\n >\n {variant === \"pill\" && (\n <div\n aria-hidden=\"true\"\n data-slot=\"tabs-indicator\"\n style={{\n clipPath: isVertical ? pillClipVertical : pillClipHorizontal,\n }}\n className={cn(\n \"pointer-events-none absolute z-0 bg-primary\",\n \"motion-reduce:transition-none\",\n \"motion-safe:transition-[clip-path] motion-safe:duration-300 motion-safe:ease-[cubic-bezier(0,0.55,0.45,1)]\",\n isVertical\n ? \"inset-y-0 left-0 right-0\"\n : \"inset-x-0 top-0 h-9 rounded-full\",\n )}\n />\n )}\n {variant === \"box\" && (\n <div\n aria-hidden=\"true\"\n data-slot=\"tabs-box-indicator\"\n style={{\n clipPath: isVertical ? boxClipVertical : boxClipHorizontal,\n }}\n className={cn(\n \"pointer-events-none absolute inset-y-0 left-0 right-0 z-0 bg-primary\",\n \"motion-reduce:transition-none\",\n \"motion-safe:transition-[clip-path] motion-safe:duration-300 motion-safe:ease-[cubic-bezier(0,0.55,0.45,1)]\",\n )}\n />\n )}\n {variant === \"underline\" && (\n <div\n aria-hidden=\"true\"\n data-slot=\"tabs-underline-indicator\"\n style={{\n clipPath: isVertical\n ? underlineClipVertical\n : underlineClipHorizontal,\n }}\n className={cn(\n \"pointer-events-none absolute z-0 bg-primary\",\n \"motion-reduce:transition-none\",\n \"motion-safe:transition-[clip-path] motion-safe:duration-300 motion-safe:ease-[cubic-bezier(0,0.55,0.45,1)]\",\n isVertical\n ? \"inset-y-0 left-0 w-0.5\"\n : \"inset-x-0 bottom-0 h-0.5\",\n )}\n />\n )}\n {children}\n </div>\n </div>\n );\n};\n\ninterface TabsTriggerProps extends Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n \"onClick\"\n> {\n value?: string;\n icon?: React.ReactNode;\n iconPosition?: \"left\" | \"right\";\n /** `stacked` — icon above label (needs `icon`). `row` — default inline row. */\n layout?: TabsTriggerLayout;\n onClick?: React.MouseEventHandler<HTMLButtonElement>;\n}\n\nexport const TabsTrigger: React.FC<TabsTriggerProps> = ({\n value,\n children,\n icon,\n iconPosition = \"left\",\n layout = \"row\",\n onClick,\n className,\n disabled,\n ...props\n}) => {\n const { value: activeValue, onValueChange, variant, alignment } = useTabs();\n const isVertical = alignment === \"vertical\";\n const isActive = value ? activeValue === value : false;\n const showSelected = isActive && !disabled;\n const isStacked = layout === \"stacked\" && Boolean(icon);\n const iconWrapClass =\n \"inline-flex shrink-0 items-center justify-center [&_svg]:shrink-0\";\n const labelWrapClass = \"block min-w-0 w-full text-left leading-snug\";\n\n return (\n <button\n type=\"button\"\n role=\"tab\"\n aria-selected={isActive}\n aria-disabled={disabled || undefined}\n tabIndex={\n value !== undefined ? (isActive && !disabled ? 0 : -1) : undefined\n }\n disabled={disabled}\n data-tab-value={value}\n onClick={(e) => {\n if (disabled) return;\n if (value) onValueChange(value);\n onClick?.(e);\n }}\n className={cn(\n \"relative z-1 inline-flex shrink-0 select-none touch-manipulation [-webkit-tap-highlight-color:transparent]\",\n \"cursor-pointer disabled:cursor-not-allowed\",\n isStacked\n ? \"flex-col items-start justify-start gap-1.5 whitespace-normal\"\n : \"items-center justify-center gap-2 whitespace-nowrap\",\n isVertical && \"w-full justify-start\",\n variant === \"pill\" && [\n \"h-9 rounded-full px-4 font-semibold leading-5 text-[13px] md:text-[15px]\",\n \"[transition:background-color_var(--duration-short-s,0.1s)_var(--ease-out,cubic-bezier(0,.55,.45,1)),border-color_var(--duration-short-s,0.1s)_var(--ease-out,cubic-bezier(0,.55,.45,1)),scale_var(--duration-short-s,0.1s)_var(--ease-out,cubic-bezier(0,.55,.45,1)),color_var(--duration-short-m,0.2s)_var(--ease-in-out,cubic-bezier(.85,0,.15,1))]\",\n !isVertical && \"enabled:active:scale-[0.96]\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n showSelected\n ? [\n \"text-background\",\n \"**:data-[slot=badge]:border-none **:data-[slot=badge]:bg-background/20 **:data-[slot=badge]:text-background\",\n ]\n : \"bg-primary/4 text-primary/50 enabled:[@media(hover:hover)_and_(pointer:fine)]:hover:bg-primary/10 enabled:active:bg-primary/10\",\n ],\n variant === \"box\" && [\n \"min-h-11 rounded-xl px-4 pt-1.5 pb-2 font-semibold leading-5 text-[13px] md:text-[15px]\",\n isVertical\n ? \"justify-start text-left\"\n : \"justify-center text-center\",\n \"[transition:background-color_var(--duration-short-s,0.1s)_var(--ease-out,cubic-bezier(0,.55,.45,1)),color_var(--duration-short-m,0.2s)_var(--ease-in-out,cubic-bezier(.85,0,.15,1))]\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n showSelected\n ? [\n \"text-background\",\n \"**:data-[slot=badge]:border-none **:data-[slot=badge]:bg-background/20 **:data-[slot=badge]:text-background\",\n ]\n : \"bg-transparent text-primary/55 enabled:[@media(hover:hover)_and_(pointer:fine)]:hover:bg-primary/[0.07] enabled:[@media(hover:hover)_and_(pointer:fine)]:hover:text-primary/75\",\n ],\n variant === \"underline\" && [\n \"h-auto rounded-none border-0 bg-transparent py-2 text-sm font-medium shadow-none\",\n isVertical\n ? isStacked\n ? \"pl-6 pr-2\"\n : \"pl-5 pr-2\"\n : \"px-2\",\n \"transition-[color,transform] duration-200 ease-in-out\",\n \"motion-reduce:transition-colors motion-reduce:enabled:active:scale-100\",\n \"enabled:active:scale-[0.98]\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n showSelected\n ? \"text-primary\"\n : \"text-primary/50 enabled:[@media(hover:hover)_and_(pointer:fine)]:hover:text-primary/70\",\n ],\n \"disabled:opacity-50\",\n className,\n )}\n {...props}\n >\n {isStacked && icon && iconPosition === \"left\" && (\n <>\n <span className={iconWrapClass} aria-hidden>\n {icon}\n </span>\n <span className={labelWrapClass}>{children}</span>\n </>\n )}\n {isStacked && icon && iconPosition === \"right\" && (\n <>\n <span className={labelWrapClass}>{children}</span>\n <span className={iconWrapClass} aria-hidden>\n {icon}\n </span>\n </>\n )}\n {!isStacked && icon && iconPosition === \"left\" && (\n <span className={iconWrapClass} aria-hidden>\n {icon}\n </span>\n )}\n {!isStacked && children}\n {!isStacked && icon && iconPosition === \"right\" && (\n <span className={iconWrapClass} aria-hidden>\n {icon}\n </span>\n )}\n </button>\n );\n};\n\ninterface TabsContentProps extends React.HTMLAttributes<HTMLDivElement> {\n value: string;\n}\n\nexport const TabsContent: React.FC<TabsContentProps> = ({\n value,\n children,\n className,\n ...props\n}) => {\n const { value: activeValue, alignment } = useTabs();\n const isVertical = alignment === \"vertical\";\n\n if (activeValue !== value) return null;\n\n return (\n <div\n role=\"tabpanel\"\n className={cn(\n \"animate-in fade-in-0 duration-200\",\n isVertical ? \"slide-in-from-left-1\" : \"slide-in-from-top-1\",\n \"ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n isVertical && \"min-w-0 flex-1\",\n className,\n )}\n {...props}\n >\n {children}\n </div>\n );\n};\n"]}
@@ -0,0 +1,6 @@
1
+ import * as React from 'react';
2
+
3
+ type TextareaProps = React.ComponentProps<"textarea">;
4
+ declare const Textarea: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.TextareaHTMLAttributes<HTMLTextAreaElement>, HTMLTextAreaElement>, "ref"> & React.RefAttributes<HTMLTextAreaElement>>;
5
+
6
+ export { Textarea, type TextareaProps };
@@ -0,0 +1,33 @@
1
+ import * as React from 'react';
2
+ import { clsx } from 'clsx';
3
+ import { twMerge } from 'tailwind-merge';
4
+ import { jsx } from 'react/jsx-runtime';
5
+
6
+ // src/react/textarea.tsx
7
+ function cn(...inputs) {
8
+ return twMerge(clsx(inputs));
9
+ }
10
+ var Textarea = React.forwardRef(
11
+ ({ className, ...props }, ref) => {
12
+ return /* @__PURE__ */ jsx(
13
+ "textarea",
14
+ {
15
+ ref,
16
+ "data-slot": "textarea",
17
+ className: cn(
18
+ "border-input bg-background text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground flex min-h-20 w-full min-w-0 rounded-md border px-3 py-2 text-sm outline-none transition-[color,box-shadow]",
19
+ "disabled:cursor-not-allowed disabled:opacity-50",
20
+ "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
21
+ "aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40",
22
+ className
23
+ ),
24
+ ...props
25
+ }
26
+ );
27
+ }
28
+ );
29
+ Textarea.displayName = "Textarea";
30
+
31
+ export { Textarea };
32
+ //# sourceMappingURL=textarea.js.map
33
+ //# sourceMappingURL=textarea.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/lib/utils.ts","../../src/react/textarea.tsx"],"names":[],"mappings":";;;;;;AAGO,SAAS,MAAM,MAAA,EAAsB;AAC1C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC7B;ACCA,IAAM,QAAA,GAAiB,KAAA,CAAA,UAAA;AAAA,EACrB,CAAC,EAAE,SAAA,EAAW,GAAG,KAAA,IAAS,GAAA,KAAQ;AAChC,IAAA,uBACE,GAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,WAAA,EAAU,UAAA;AAAA,QACV,SAAA,EAAW,EAAA;AAAA,UACT,iPAAA;AAAA,UACA,iDAAA;AAAA,UACA,+EAAA;AAAA,UACA,wGAAA;AAAA,UACA;AAAA,SACF;AAAA,QACC,GAAG;AAAA;AAAA,KACN;AAAA,EAEJ;AACF;AACA,QAAA,CAAS,WAAA,GAAc,UAAA","file":"textarea.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nexport type TextareaProps = React.ComponentProps<\"textarea\">;\n\nconst Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\n ({ className, ...props }, ref) => {\n return (\n <textarea\n ref={ref}\n data-slot=\"textarea\"\n className={cn(\n \"border-input bg-background text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground flex min-h-20 w-full min-w-0 rounded-md border px-3 py-2 text-sm outline-none transition-[color,box-shadow]\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n \"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]\",\n \"aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40\",\n className,\n )}\n {...props}\n />\n );\n },\n);\nTextarea.displayName = \"Textarea\";\n\nexport { Textarea };\n"]}
@@ -0,0 +1,22 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ /** When no time base exists yet, use today at local midnight. */
4
+ declare function baseDateForTimePick(value: Date | undefined): Date;
5
+ type TimePickerProps = {
6
+ value: Date | undefined;
7
+ onChange: (next: Date) => void;
8
+ disabled?: boolean;
9
+ /**
10
+ * `vertical` (default): three columns with `scrollTop`.
11
+ * `horizontal`: three stacked strips with `scrollLeft` — use on narrow viewports (e.g. under a calendar).
12
+ */
13
+ orientation?: "vertical" | "horizontal";
14
+ className?: string;
15
+ };
16
+ /**
17
+ * Three linked scroll columns (12h clock, 5‑minute steps, AM/PM) sharing a center highlight.
18
+ * Built from {@link ScrollWheel}; use inside popovers or any fixed-height row.
19
+ */
20
+ declare function TimePicker({ value, onChange, disabled, orientation, className, }: TimePickerProps): react_jsx_runtime.JSX.Element;
21
+
22
+ export { TimePicker, type TimePickerProps, baseDateForTimePick };