@avenue-ticketing/ui 0.3.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.
- package/dist/react/avatar.d.ts +42 -0
- package/dist/react/avatar.js +159 -0
- package/dist/react/avatar.js.map +1 -0
- package/dist/react/badge.d.ts +12 -0
- package/dist/react/badge.js +35 -1
- package/dist/react/badge.js.map +1 -1
- package/dist/react/button.d.ts +1 -1
- package/dist/react/button.js +3 -3
- package/dist/react/button.js.map +1 -1
- package/dist/react/calendar.d.ts +13 -0
- package/dist/react/calendar.js +4639 -0
- package/dist/react/calendar.js.map +1 -0
- package/dist/react/card.d.ts +11 -0
- package/dist/react/card.js +113 -0
- package/dist/react/card.js.map +1 -0
- package/dist/react/checkbox.d.ts +11 -0
- package/dist/react/checkbox.js +131 -0
- package/dist/react/checkbox.js.map +1 -0
- package/dist/react/datetime-picker.d.ts +21 -0
- package/dist/react/datetime-picker.js +6124 -0
- package/dist/react/datetime-picker.js.map +1 -0
- package/dist/react/dialog.d.ts +7 -0
- package/dist/react/dialog.js +211 -90
- package/dist/react/dialog.js.map +1 -1
- package/dist/react/dropdown.d.ts +126 -0
- package/dist/react/dropdown.js +1269 -0
- package/dist/react/dropdown.js.map +1 -0
- package/dist/react/input.d.ts +7 -0
- package/dist/react/input.js +15 -2
- package/dist/react/input.js.map +1 -1
- package/dist/react/pagination.d.ts +28 -0
- package/dist/react/pagination.js +262 -0
- package/dist/react/pagination.js.map +1 -0
- package/dist/react/popover.d.ts +76 -0
- package/dist/react/popover.js +564 -0
- package/dist/react/popover.js.map +1 -0
- package/dist/react/scroll-header.js +13 -1
- package/dist/react/scroll-header.js.map +1 -1
- package/dist/react/scroll-wheel.d.ts +45 -0
- package/dist/react/scroll-wheel.js +557 -0
- package/dist/react/scroll-wheel.js.map +1 -0
- package/dist/react/select.d.ts +62 -0
- package/dist/react/select.js +889 -0
- package/dist/react/select.js.map +1 -0
- package/dist/react/sheet.js +1 -1
- package/dist/react/sheet.js.map +1 -1
- package/dist/react/switch.d.ts +38 -0
- package/dist/react/switch.js +117 -0
- package/dist/react/switch.js.map +1 -0
- package/dist/react/table-pagination.d.ts +15 -0
- package/dist/react/table-pagination.js +1153 -0
- package/dist/react/table-pagination.js.map +1 -0
- package/dist/react/table-view/column-menu.d.ts +15 -0
- package/dist/react/table-view/column-menu.js +918 -0
- package/dist/react/table-view/column-menu.js.map +1 -0
- package/dist/react/table-view/index.d.ts +70 -0
- package/dist/react/table-view/index.js +2155 -0
- package/dist/react/table-view/index.js.map +1 -0
- package/dist/react/table.d.ts +86 -0
- package/dist/react/table.js +414 -0
- package/dist/react/table.js.map +1 -0
- package/dist/react/tabs.d.ts +9 -3
- package/dist/react/tabs.js +217 -57
- package/dist/react/tabs.js.map +1 -1
- package/dist/react/textarea.d.ts +6 -0
- package/dist/react/textarea.js +33 -0
- package/dist/react/textarea.js.map +1 -0
- package/dist/react/time-picker.d.ts +22 -0
- package/dist/react/time-picker.js +856 -0
- package/dist/react/time-picker.js.map +1 -0
- package/dist/react/tooltip.d.ts +45 -0
- package/dist/react/tooltip.js +540 -0
- package/dist/react/tooltip.js.map +1 -0
- package/package.json +1 -1
package/dist/react/tabs.js
CHANGED
|
@@ -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: {
|
|
42
|
-
|
|
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,35 +75,84 @@ 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")
|
|
122
|
+
if (!row || variant !== "pill" && variant !== "underline" && variant !== "box")
|
|
123
|
+
return;
|
|
56
124
|
const tab = row.querySelector(
|
|
57
|
-
'[role="tab"][aria-selected="true"]'
|
|
125
|
+
'[role="tab"][aria-selected="true"]:not(:disabled)'
|
|
58
126
|
);
|
|
59
127
|
if (!tab) {
|
|
60
128
|
row.style.setProperty("--tab-indicator-start", "0px");
|
|
61
129
|
row.style.setProperty("--tab-indicator-end", "0px");
|
|
62
130
|
return;
|
|
63
131
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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"
|
|
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,13 +161,13 @@ 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;
|
|
92
168
|
const tabs = Array.from(
|
|
93
169
|
row.querySelectorAll('[role="tab"][data-tab-value]')
|
|
94
|
-
);
|
|
170
|
+
).filter((t) => !t.disabled);
|
|
95
171
|
if (tabs.length === 0) return;
|
|
96
172
|
const values = tabs.map((t) => t.dataset.tabValue);
|
|
97
173
|
let idx = activeValue ? values.indexOf(activeValue) : 0;
|
|
@@ -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
|
|
115
|
-
|
|
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
|
-
"
|
|
126
|
-
|
|
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 === "
|
|
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:
|
|
260
|
+
clipPath: isVertical ? pillClipVertical : pillClipHorizontal
|
|
138
261
|
},
|
|
139
262
|
className: cn(
|
|
140
|
-
"pointer-events-none absolute
|
|
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:
|
|
291
|
+
clipPath: isVertical ? underlineClipVertical : underlineClipHorizontal
|
|
153
292
|
},
|
|
154
293
|
className: cn(
|
|
155
|
-
"pointer-events-none absolute
|
|
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,67 +310,84 @@ 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;
|
|
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";
|
|
180
326
|
return /* @__PURE__ */ jsxs(
|
|
181
327
|
"button",
|
|
182
328
|
{
|
|
183
329
|
type: "button",
|
|
184
330
|
role: "tab",
|
|
185
331
|
"aria-selected": isActive,
|
|
186
|
-
|
|
332
|
+
"aria-disabled": disabled || void 0,
|
|
333
|
+
tabIndex: value !== void 0 ? isActive && !disabled ? 0 : -1 : void 0,
|
|
187
334
|
disabled,
|
|
188
335
|
"data-tab-value": value,
|
|
189
336
|
onClick: (e) => {
|
|
337
|
+
if (disabled) return;
|
|
190
338
|
if (value) onValueChange(value);
|
|
191
339
|
onClick?.(e);
|
|
192
340
|
},
|
|
193
341
|
className: cn(
|
|
194
|
-
"relative z-1 inline-flex shrink-0
|
|
342
|
+
"relative z-1 inline-flex shrink-0 select-none touch-manipulation [-webkit-tap-highlight-color:transparent]",
|
|
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",
|
|
195
346
|
variant === "pill" && [
|
|
196
347
|
"h-9 rounded-full px-4 font-semibold leading-5 text-[13px] md:text-[15px]",
|
|
197
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))]",
|
|
198
|
-
"active:scale-[0.96]
|
|
199
|
-
|
|
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",
|
|
351
|
+
showSelected ? [
|
|
352
|
+
"text-background",
|
|
353
|
+
"**:data-[slot=badge]:border-none **:data-[slot=badge]:bg-background/20 **:data-[slot=badge]:text-background"
|
|
354
|
+
] : "bg-primary/4 text-primary/50 enabled:[@media(hover:hover)_and_(pointer:fine)]:hover:bg-primary/10 enabled:active:bg-primary/10"
|
|
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 ? [
|
|
200
362
|
"text-background",
|
|
201
363
|
"**:data-[slot=badge]:border-none **:data-[slot=badge]:bg-background/20 **:data-[slot=badge]:text-background"
|
|
202
|
-
] : "bg-
|
|
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"
|
|
203
365
|
],
|
|
204
366
|
variant === "underline" && [
|
|
205
|
-
"h-auto rounded-none border-0 bg-transparent
|
|
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",
|
|
206
369
|
"transition-[color,transform] duration-200 ease-in-out",
|
|
207
|
-
"motion-reduce:transition-colors motion-reduce:active:scale-100",
|
|
208
|
-
"active:scale-[0.98]",
|
|
370
|
+
"motion-reduce:transition-colors motion-reduce:enabled:active:scale-100",
|
|
371
|
+
"enabled:active:scale-[0.98]",
|
|
209
372
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
210
|
-
|
|
373
|
+
showSelected ? "text-primary" : "text-primary/50 enabled:[@media(hover:hover)_and_(pointer:fine)]:hover:text-primary/70"
|
|
211
374
|
],
|
|
212
|
-
"disabled:
|
|
375
|
+
"disabled:opacity-50",
|
|
213
376
|
className
|
|
214
377
|
),
|
|
215
378
|
...props,
|
|
216
379
|
children: [
|
|
217
|
-
icon && iconPosition === "left" && /* @__PURE__ */
|
|
218
|
-
"span",
|
|
219
|
-
{
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
}
|
|
224
|
-
),
|
|
225
|
-
children,
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
{
|
|
229
|
-
className: "flex size-4 shrink-0 items-center justify-center",
|
|
230
|
-
"aria-hidden": true,
|
|
231
|
-
children: icon
|
|
232
|
-
}
|
|
233
|
-
)
|
|
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 })
|
|
234
391
|
]
|
|
235
392
|
}
|
|
236
393
|
);
|
|
@@ -241,15 +398,18 @@ var TabsContent = ({
|
|
|
241
398
|
className,
|
|
242
399
|
...props
|
|
243
400
|
}) => {
|
|
244
|
-
const { value: activeValue } = useTabs();
|
|
401
|
+
const { value: activeValue, alignment } = useTabs();
|
|
402
|
+
const isVertical = alignment === "vertical";
|
|
245
403
|
if (activeValue !== value) return null;
|
|
246
404
|
return /* @__PURE__ */ jsx(
|
|
247
405
|
"div",
|
|
248
406
|
{
|
|
249
407
|
role: "tabpanel",
|
|
250
408
|
className: cn(
|
|
251
|
-
"animate-in fade-in-0
|
|
409
|
+
"animate-in fade-in-0 duration-200",
|
|
410
|
+
isVertical ? "slide-in-from-left-1" : "slide-in-from-top-1",
|
|
252
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",
|
|
253
413
|
className
|
|
254
414
|
),
|
|
255
415
|
...props,
|
package/dist/react/tabs.js.map
CHANGED
|
@@ -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\"]',\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 );\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\n return (\n <button\n type=\"button\"\n role=\"tab\"\n aria-selected={isActive}\n tabIndex={value !== undefined ? (isActive ? 0 : -1) : undefined}\n disabled={disabled}\n data-tab-value={value}\n onClick={(e) => {\n if (value) onValueChange(value);\n onClick?.(e);\n }}\n className={cn(\n \"relative z-1 inline-flex shrink-0 cursor-pointer select-none items-center justify-center gap-2 whitespace-nowrap touch-manipulation [-webkit-tap-highlight-color:transparent]\",\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 \"active:scale-[0.96] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n isActive\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 [@media(hover:hover)_and_(pointer:fine)]:hover:bg-primary/10 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:active:scale-100\",\n \"active:scale-[0.98]\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n isActive\n ? \"text-primary\"\n : \"text-primary/50 [@media(hover:hover)_and_(pointer:fine)]:hover:text-primary/70\",\n ],\n \"disabled:cursor-not-allowed 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 };
|