@rdna/radiants 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +674 -0
- package/README.md +125 -0
- package/animations.css +68 -0
- package/assets/scrollbar-background.svg +9 -0
- package/base.css +144 -0
- package/dark.css +117 -0
- package/dist/chunk-SR2T7OEJ.mjs +46 -0
- package/dist/chunk-SR2T7OEJ.mjs.map +1 -0
- package/dist/components/core/index.d.mts +911 -0
- package/dist/components/core/index.mjs +2475 -0
- package/dist/components/core/index.mjs.map +1 -0
- package/dist/hooks/index.d.mts +22 -0
- package/dist/hooks/index.mjs +3 -0
- package/dist/hooks/index.mjs.map +1 -0
- package/dist/remotion/index.d.mts +252 -0
- package/dist/remotion/index.mjs +170 -0
- package/dist/remotion/index.mjs.map +1 -0
- package/dna.config.json +8 -0
- package/fonts/Joystix.woff2 +0 -0
- package/fonts/PixelCode-Black-Italic.woff2 +0 -0
- package/fonts/PixelCode-Black.woff2 +0 -0
- package/fonts/PixelCode-Bold-Italic.woff2 +0 -0
- package/fonts/PixelCode-Bold.woff2 +0 -0
- package/fonts/PixelCode-DemiBold-Italic.woff2 +0 -0
- package/fonts/PixelCode-DemiBold.woff2 +0 -0
- package/fonts/PixelCode-ExtraBlack-Italic.woff2 +0 -0
- package/fonts/PixelCode-ExtraBlack.woff2 +0 -0
- package/fonts/PixelCode-ExtraBold-Italic.woff2 +0 -0
- package/fonts/PixelCode-ExtraBold.woff2 +0 -0
- package/fonts/PixelCode-ExtraLight-Italic.woff2 +0 -0
- package/fonts/PixelCode-ExtraLight.woff2 +0 -0
- package/fonts/PixelCode-Italic.woff2 +0 -0
- package/fonts/PixelCode-Light-Italic.woff2 +0 -0
- package/fonts/PixelCode-Light.woff2 +0 -0
- package/fonts/PixelCode-Medium-Italic.woff2 +0 -0
- package/fonts/PixelCode-Medium.woff2 +0 -0
- package/fonts/PixelCode-Thin-Italic.woff2 +0 -0
- package/fonts/PixelCode-Thin.woff2 +0 -0
- package/fonts/PixelCode.woff2 +0 -0
- package/fonts.css +115 -0
- package/index.css +25 -0
- package/package.json +88 -0
- package/tokens.css +202 -0
- package/typography.css +175 -0
|
@@ -0,0 +1,2475 @@
|
|
|
1
|
+
import { useClickOutside, useEscapeKey, useLockBodyScroll } from '../../chunk-SR2T7OEJ.mjs';
|
|
2
|
+
import React14, { createContext, forwardRef, useState, useEffect, useCallback, useRef, useContext } from 'react';
|
|
3
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
4
|
+
import Link from 'next/link';
|
|
5
|
+
import { createPortal } from 'react-dom';
|
|
6
|
+
|
|
7
|
+
var AccordionContext = createContext(null);
|
|
8
|
+
var AccordionItemContext = createContext(null);
|
|
9
|
+
function useAccordionContext() {
|
|
10
|
+
const context = useContext(AccordionContext);
|
|
11
|
+
if (!context) {
|
|
12
|
+
throw new Error("Accordion components must be used within an Accordion");
|
|
13
|
+
}
|
|
14
|
+
return context;
|
|
15
|
+
}
|
|
16
|
+
function useAccordionItemContext() {
|
|
17
|
+
const context = useContext(AccordionItemContext);
|
|
18
|
+
if (!context) {
|
|
19
|
+
throw new Error("AccordionTrigger/AccordionContent must be used within an AccordionItem");
|
|
20
|
+
}
|
|
21
|
+
return context;
|
|
22
|
+
}
|
|
23
|
+
function Accordion({
|
|
24
|
+
type = "single",
|
|
25
|
+
defaultValue,
|
|
26
|
+
value: controlledValue,
|
|
27
|
+
onValueChange,
|
|
28
|
+
className = "",
|
|
29
|
+
children
|
|
30
|
+
}) {
|
|
31
|
+
const getInitialExpanded = () => {
|
|
32
|
+
const initial = controlledValue ?? defaultValue;
|
|
33
|
+
if (!initial) return /* @__PURE__ */ new Set();
|
|
34
|
+
return new Set(Array.isArray(initial) ? initial : [initial]);
|
|
35
|
+
};
|
|
36
|
+
const [expandedItems, setExpandedItems] = useState(getInitialExpanded);
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (controlledValue !== void 0) {
|
|
39
|
+
setExpandedItems(new Set(Array.isArray(controlledValue) ? controlledValue : [controlledValue]));
|
|
40
|
+
}
|
|
41
|
+
}, [controlledValue]);
|
|
42
|
+
const toggleItem = useCallback((itemValue) => {
|
|
43
|
+
setExpandedItems((prev) => {
|
|
44
|
+
const next = new Set(prev);
|
|
45
|
+
if (next.has(itemValue)) {
|
|
46
|
+
next.delete(itemValue);
|
|
47
|
+
} else {
|
|
48
|
+
if (type === "single") {
|
|
49
|
+
next.clear();
|
|
50
|
+
}
|
|
51
|
+
next.add(itemValue);
|
|
52
|
+
}
|
|
53
|
+
if (onValueChange) {
|
|
54
|
+
const newValue = Array.from(next);
|
|
55
|
+
onValueChange(type === "single" ? newValue[0] ?? "" : newValue);
|
|
56
|
+
}
|
|
57
|
+
return next;
|
|
58
|
+
});
|
|
59
|
+
}, [type, onValueChange]);
|
|
60
|
+
return /* @__PURE__ */ jsx(AccordionContext.Provider, { value: { type, expandedItems, toggleItem }, children: /* @__PURE__ */ jsx("div", { className: `space-y-0 ${className}`, children }) });
|
|
61
|
+
}
|
|
62
|
+
function AccordionItem({ value, className = "", children }) {
|
|
63
|
+
const { expandedItems } = useAccordionContext();
|
|
64
|
+
const isExpanded = expandedItems.has(value);
|
|
65
|
+
return /* @__PURE__ */ jsx(AccordionItemContext.Provider, { value: { value, isExpanded }, children: /* @__PURE__ */ jsx(
|
|
66
|
+
"div",
|
|
67
|
+
{
|
|
68
|
+
className: `
|
|
69
|
+
border border-edge-primary
|
|
70
|
+
bg-surface-primary
|
|
71
|
+
-mt-px first:mt-0
|
|
72
|
+
${className}
|
|
73
|
+
`.trim(),
|
|
74
|
+
"data-state": isExpanded ? "open" : "closed",
|
|
75
|
+
children
|
|
76
|
+
}
|
|
77
|
+
) });
|
|
78
|
+
}
|
|
79
|
+
function AccordionTrigger({ className = "", children }) {
|
|
80
|
+
const { toggleItem } = useAccordionContext();
|
|
81
|
+
const { value, isExpanded } = useAccordionItemContext();
|
|
82
|
+
return /* @__PURE__ */ jsxs(
|
|
83
|
+
"button",
|
|
84
|
+
{
|
|
85
|
+
type: "button",
|
|
86
|
+
onClick: () => toggleItem(value),
|
|
87
|
+
className: `
|
|
88
|
+
w-full flex items-center justify-between
|
|
89
|
+
px-4 py-3
|
|
90
|
+
font-joystix text-sm uppercase text-content-primary
|
|
91
|
+
bg-transparent
|
|
92
|
+
hover:bg-content-primary/5
|
|
93
|
+
transition-colors
|
|
94
|
+
cursor-pointer
|
|
95
|
+
${className}
|
|
96
|
+
`.trim(),
|
|
97
|
+
"aria-expanded": isExpanded,
|
|
98
|
+
children: [
|
|
99
|
+
/* @__PURE__ */ jsx("span", { children }),
|
|
100
|
+
/* @__PURE__ */ jsx(
|
|
101
|
+
"span",
|
|
102
|
+
{
|
|
103
|
+
className: "text-[1rem] font-mondwest select-none",
|
|
104
|
+
"aria-hidden": "true",
|
|
105
|
+
children: isExpanded ? "\u2212" : "+"
|
|
106
|
+
}
|
|
107
|
+
)
|
|
108
|
+
]
|
|
109
|
+
}
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
function AccordionContent({ className = "", children }) {
|
|
113
|
+
const { isExpanded } = useAccordionItemContext();
|
|
114
|
+
const contentRef = useRef(null);
|
|
115
|
+
const [height, setHeight] = useState(void 0);
|
|
116
|
+
const [isAnimating, setIsAnimating] = useState(false);
|
|
117
|
+
useEffect(() => {
|
|
118
|
+
const content = contentRef.current;
|
|
119
|
+
if (!content) return;
|
|
120
|
+
if (isExpanded) {
|
|
121
|
+
const scrollHeight = content.scrollHeight;
|
|
122
|
+
setHeight(scrollHeight);
|
|
123
|
+
setIsAnimating(true);
|
|
124
|
+
const timer = setTimeout(() => {
|
|
125
|
+
setIsAnimating(false);
|
|
126
|
+
setHeight(void 0);
|
|
127
|
+
}, 200);
|
|
128
|
+
return () => clearTimeout(timer);
|
|
129
|
+
} else {
|
|
130
|
+
const scrollHeight = content.scrollHeight;
|
|
131
|
+
setHeight(scrollHeight);
|
|
132
|
+
setIsAnimating(true);
|
|
133
|
+
requestAnimationFrame(() => {
|
|
134
|
+
setHeight(0);
|
|
135
|
+
});
|
|
136
|
+
const timer = setTimeout(() => {
|
|
137
|
+
setIsAnimating(false);
|
|
138
|
+
}, 200);
|
|
139
|
+
return () => clearTimeout(timer);
|
|
140
|
+
}
|
|
141
|
+
}, [isExpanded]);
|
|
142
|
+
return /* @__PURE__ */ jsx(
|
|
143
|
+
"div",
|
|
144
|
+
{
|
|
145
|
+
ref: contentRef,
|
|
146
|
+
className: `
|
|
147
|
+
overflow-hidden
|
|
148
|
+
transition-[height] duration-200 ease-out
|
|
149
|
+
${className}
|
|
150
|
+
`.trim(),
|
|
151
|
+
style: {
|
|
152
|
+
height: isAnimating ? height : isExpanded ? "auto" : 0
|
|
153
|
+
},
|
|
154
|
+
"aria-hidden": !isExpanded,
|
|
155
|
+
children: /* @__PURE__ */ jsx("div", { className: "px-4 pb-4", children })
|
|
156
|
+
}
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
var variantStyles = {
|
|
160
|
+
default: "bg-surface-primary border-edge-primary text-content-primary",
|
|
161
|
+
success: "bg-status-success/10 border-status-success text-content-primary",
|
|
162
|
+
warning: "bg-status-warning/10 border-status-warning text-content-primary",
|
|
163
|
+
error: "bg-status-error/10 border-status-error text-content-primary",
|
|
164
|
+
info: "bg-status-info/10 border-status-info text-content-primary"
|
|
165
|
+
};
|
|
166
|
+
function Alert({
|
|
167
|
+
variant = "default",
|
|
168
|
+
title,
|
|
169
|
+
children,
|
|
170
|
+
closable = false,
|
|
171
|
+
onClose,
|
|
172
|
+
icon,
|
|
173
|
+
closeIcon,
|
|
174
|
+
className = ""
|
|
175
|
+
}) {
|
|
176
|
+
return /* @__PURE__ */ jsx(
|
|
177
|
+
"div",
|
|
178
|
+
{
|
|
179
|
+
role: "alert",
|
|
180
|
+
className: `
|
|
181
|
+
p-4
|
|
182
|
+
border-2
|
|
183
|
+
rounded-sm
|
|
184
|
+
${variantStyles[variant]}
|
|
185
|
+
${className}
|
|
186
|
+
`.trim(),
|
|
187
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3", children: [
|
|
188
|
+
icon && /* @__PURE__ */ jsx("span", { className: "flex-shrink-0 mt-0.5", children: icon }),
|
|
189
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
190
|
+
title && /* @__PURE__ */ jsx("p", { className: "font-joystix text-xs uppercase mb-1", children: title }),
|
|
191
|
+
/* @__PURE__ */ jsx("div", { className: "font-mondwest text-base text-content-primary/80", children })
|
|
192
|
+
] }),
|
|
193
|
+
closable && /* @__PURE__ */ jsx(
|
|
194
|
+
"button",
|
|
195
|
+
{
|
|
196
|
+
onClick: onClose,
|
|
197
|
+
className: "text-content-primary/50 hover:text-content-primary flex-shrink-0 -mt-1",
|
|
198
|
+
"aria-label": "Close",
|
|
199
|
+
children: closeIcon || /* @__PURE__ */ jsx(
|
|
200
|
+
"svg",
|
|
201
|
+
{
|
|
202
|
+
width: "16",
|
|
203
|
+
height: "16",
|
|
204
|
+
viewBox: "0 0 16 16",
|
|
205
|
+
fill: "none",
|
|
206
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
207
|
+
children: /* @__PURE__ */ jsx(
|
|
208
|
+
"path",
|
|
209
|
+
{
|
|
210
|
+
d: "M12 4L4 12M4 4L12 12",
|
|
211
|
+
stroke: "currentColor",
|
|
212
|
+
strokeWidth: "2",
|
|
213
|
+
strokeLinecap: "round",
|
|
214
|
+
strokeLinejoin: "round"
|
|
215
|
+
}
|
|
216
|
+
)
|
|
217
|
+
}
|
|
218
|
+
)
|
|
219
|
+
}
|
|
220
|
+
)
|
|
221
|
+
] })
|
|
222
|
+
}
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
var baseStyles = `
|
|
226
|
+
inline-flex items-center justify-center
|
|
227
|
+
font-joystix uppercase
|
|
228
|
+
rounded-sm
|
|
229
|
+
whitespace-nowrap
|
|
230
|
+
`;
|
|
231
|
+
var sizeStyles = {
|
|
232
|
+
sm: "px-2 py-0.5 text-2xs",
|
|
233
|
+
md: "px-2.5 py-1 text-xs"
|
|
234
|
+
};
|
|
235
|
+
var variantStyles2 = {
|
|
236
|
+
default: "bg-surface-primary text-content-primary border border-edge-primary",
|
|
237
|
+
success: "bg-status-success text-content-primary border border-edge-primary",
|
|
238
|
+
warning: "bg-status-warning text-content-primary border border-edge-primary",
|
|
239
|
+
error: "bg-status-error text-content-primary border border-edge-primary",
|
|
240
|
+
info: "bg-status-info text-content-primary border border-edge-primary"
|
|
241
|
+
};
|
|
242
|
+
function Badge({
|
|
243
|
+
variant = "default",
|
|
244
|
+
size = "md",
|
|
245
|
+
children,
|
|
246
|
+
className = ""
|
|
247
|
+
}) {
|
|
248
|
+
const classes = [
|
|
249
|
+
baseStyles,
|
|
250
|
+
sizeStyles[size],
|
|
251
|
+
variantStyles2[variant],
|
|
252
|
+
className
|
|
253
|
+
].join(" ").replace(/\s+/g, " ").trim();
|
|
254
|
+
return /* @__PURE__ */ jsx("span", { className: classes, children });
|
|
255
|
+
}
|
|
256
|
+
function Breadcrumbs({
|
|
257
|
+
items,
|
|
258
|
+
separator = "/",
|
|
259
|
+
className = ""
|
|
260
|
+
}) {
|
|
261
|
+
if (items.length === 0) return null;
|
|
262
|
+
return /* @__PURE__ */ jsx(
|
|
263
|
+
"nav",
|
|
264
|
+
{
|
|
265
|
+
"aria-label": "Breadcrumb",
|
|
266
|
+
className: `flex items-center gap-2 ${className}`.trim(),
|
|
267
|
+
children: /* @__PURE__ */ jsx("ol", { className: "flex items-center gap-2", children: items.map((item, index) => {
|
|
268
|
+
const isLast = index === items.length - 1;
|
|
269
|
+
return /* @__PURE__ */ jsxs("li", { className: "flex items-center gap-2", children: [
|
|
270
|
+
index > 0 && /* @__PURE__ */ jsx(
|
|
271
|
+
"span",
|
|
272
|
+
{
|
|
273
|
+
className: "font-mondwest text-base text-content-primary/40",
|
|
274
|
+
"aria-hidden": "true",
|
|
275
|
+
children: separator
|
|
276
|
+
}
|
|
277
|
+
),
|
|
278
|
+
item.href && !isLast ? /* @__PURE__ */ jsx(
|
|
279
|
+
Link,
|
|
280
|
+
{
|
|
281
|
+
href: item.href,
|
|
282
|
+
className: "font-mondwest text-base text-content-primary/60 hover:text-content-primary hover:underline transition-colors",
|
|
283
|
+
children: item.label
|
|
284
|
+
}
|
|
285
|
+
) : /* @__PURE__ */ jsx(
|
|
286
|
+
"span",
|
|
287
|
+
{
|
|
288
|
+
className: `
|
|
289
|
+
font-mondwest text-base
|
|
290
|
+
${isLast ? "text-content-primary font-semibold" : "text-content-primary/60"}
|
|
291
|
+
`.trim(),
|
|
292
|
+
"aria-current": isLast ? "page" : void 0,
|
|
293
|
+
children: item.label
|
|
294
|
+
}
|
|
295
|
+
)
|
|
296
|
+
] }, index);
|
|
297
|
+
}) })
|
|
298
|
+
}
|
|
299
|
+
);
|
|
300
|
+
}
|
|
301
|
+
var baseStyles2 = `
|
|
302
|
+
inline-flex items-center
|
|
303
|
+
font-heading uppercase
|
|
304
|
+
whitespace-nowrap
|
|
305
|
+
cursor-pointer select-none
|
|
306
|
+
border border-edge-primary
|
|
307
|
+
rounded-sm
|
|
308
|
+
shadow-btn
|
|
309
|
+
hover:-translate-y-0.5
|
|
310
|
+
hover:shadow-btn-hover
|
|
311
|
+
active:translate-y-0.5
|
|
312
|
+
active:shadow-none
|
|
313
|
+
disabled:opacity-50 disabled:cursor-not-allowed
|
|
314
|
+
disabled:hover:translate-y-0 disabled:hover:shadow-btn
|
|
315
|
+
focus:outline-none focus-visible:ring-2 focus-visible:ring-edge-focus focus-visible:ring-offset-1
|
|
316
|
+
`;
|
|
317
|
+
var sizeStyles2 = {
|
|
318
|
+
sm: "h-8 px-3 text-xs gap-3",
|
|
319
|
+
md: "h-8 px-3 text-xs gap-3",
|
|
320
|
+
lg: "h-8 px-3 text-sm gap-3"
|
|
321
|
+
};
|
|
322
|
+
var iconOnlySizeStyles = {
|
|
323
|
+
sm: "w-8 h-8 p-0",
|
|
324
|
+
md: "w-8 h-8 p-0",
|
|
325
|
+
lg: "w-8 h-8 p-0"
|
|
326
|
+
};
|
|
327
|
+
var variantStyles3 = {
|
|
328
|
+
primary: `
|
|
329
|
+
bg-action-primary text-content-primary
|
|
330
|
+
hover:bg-action-primary
|
|
331
|
+
active:bg-action-primary
|
|
332
|
+
`,
|
|
333
|
+
secondary: `
|
|
334
|
+
bg-surface-secondary text-content-inverted
|
|
335
|
+
hover:bg-surface-primary hover:text-content-primary
|
|
336
|
+
active:bg-action-primary active:text-content-primary
|
|
337
|
+
`,
|
|
338
|
+
outline: `
|
|
339
|
+
bg-transparent text-content-primary
|
|
340
|
+
shadow-none
|
|
341
|
+
hover:bg-content-primary/5 hover:!translate-y-0 hover:shadow-none
|
|
342
|
+
active:bg-action-primary active:!translate-y-0 active:shadow-none
|
|
343
|
+
`,
|
|
344
|
+
ghost: `
|
|
345
|
+
bg-transparent text-content-primary
|
|
346
|
+
border-transparent
|
|
347
|
+
shadow-none
|
|
348
|
+
hover:bg-transparent hover:border-edge-primary hover:text-content-primary hover:shadow-none hover:translate-y-0
|
|
349
|
+
active:bg-action-primary active:text-content-primary active:border-edge-primary active:translate-y-0
|
|
350
|
+
`
|
|
351
|
+
};
|
|
352
|
+
function getButtonClasses(variant, size, iconOnly, fullWidth, className, hasIcon) {
|
|
353
|
+
let justifyClass = "justify-start";
|
|
354
|
+
if (iconOnly) {
|
|
355
|
+
justifyClass = "justify-center";
|
|
356
|
+
} else if (fullWidth && hasIcon) {
|
|
357
|
+
justifyClass = "justify-between";
|
|
358
|
+
}
|
|
359
|
+
return [
|
|
360
|
+
baseStyles2,
|
|
361
|
+
iconOnly ? iconOnlySizeStyles[size] : sizeStyles2[size],
|
|
362
|
+
justifyClass,
|
|
363
|
+
variantStyles3[variant],
|
|
364
|
+
fullWidth ? "w-full" : "",
|
|
365
|
+
className
|
|
366
|
+
].join(" ").replace(/\s+/g, " ").trim();
|
|
367
|
+
}
|
|
368
|
+
function Button(props) {
|
|
369
|
+
const {
|
|
370
|
+
variant = "primary",
|
|
371
|
+
size = "md",
|
|
372
|
+
fullWidth = false,
|
|
373
|
+
iconOnly = false,
|
|
374
|
+
icon,
|
|
375
|
+
loadingIndicator,
|
|
376
|
+
loading = false,
|
|
377
|
+
children,
|
|
378
|
+
className = "",
|
|
379
|
+
...rest
|
|
380
|
+
} = props;
|
|
381
|
+
const hasIcon = Boolean(icon || iconOnly);
|
|
382
|
+
const showLoading = Boolean(loading && hasIcon && loadingIndicator);
|
|
383
|
+
const classes = getButtonClasses(variant, size, iconOnly, fullWidth, className, hasIcon);
|
|
384
|
+
const content = showLoading ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
385
|
+
!iconOnly && children,
|
|
386
|
+
loadingIndicator
|
|
387
|
+
] }) : icon ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
388
|
+
!iconOnly && children,
|
|
389
|
+
icon
|
|
390
|
+
] }) : children;
|
|
391
|
+
if ("href" in props && props.href) {
|
|
392
|
+
const { href, asLink = true, target, ...linkRest } = rest;
|
|
393
|
+
if (asLink) {
|
|
394
|
+
return /* @__PURE__ */ jsx(
|
|
395
|
+
"a",
|
|
396
|
+
{
|
|
397
|
+
href,
|
|
398
|
+
target,
|
|
399
|
+
className: classes,
|
|
400
|
+
...linkRest,
|
|
401
|
+
children: content
|
|
402
|
+
}
|
|
403
|
+
);
|
|
404
|
+
}
|
|
405
|
+
const linkButtonDisabled = showLoading || Boolean(linkRest.disabled);
|
|
406
|
+
const { disabled: _2, ...linkButtonRest } = linkRest;
|
|
407
|
+
return /* @__PURE__ */ jsx(
|
|
408
|
+
"button",
|
|
409
|
+
{
|
|
410
|
+
type: "button",
|
|
411
|
+
className: classes,
|
|
412
|
+
onClick: () => window.open(href, target || "_self"),
|
|
413
|
+
disabled: linkButtonDisabled,
|
|
414
|
+
...linkButtonRest,
|
|
415
|
+
children: content
|
|
416
|
+
}
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
const buttonProps = rest;
|
|
420
|
+
const disabled = showLoading || Boolean(buttonProps.disabled);
|
|
421
|
+
const { disabled: _, ...buttonPropsWithoutDisabled } = buttonProps;
|
|
422
|
+
return /* @__PURE__ */ jsx("button", { className: classes, ...buttonPropsWithoutDisabled, disabled, children: content });
|
|
423
|
+
}
|
|
424
|
+
var baseStyles3 = `
|
|
425
|
+
border border-edge-primary
|
|
426
|
+
rounded-md
|
|
427
|
+
overflow-hidden
|
|
428
|
+
`;
|
|
429
|
+
var variantStyles4 = {
|
|
430
|
+
default: `
|
|
431
|
+
bg-surface-primary text-content-primary
|
|
432
|
+
`,
|
|
433
|
+
dark: `
|
|
434
|
+
bg-surface-secondary text-content-inverted
|
|
435
|
+
`,
|
|
436
|
+
raised: `
|
|
437
|
+
bg-surface-primary text-content-primary
|
|
438
|
+
shadow-card
|
|
439
|
+
`
|
|
440
|
+
};
|
|
441
|
+
function Card({
|
|
442
|
+
variant = "default",
|
|
443
|
+
children,
|
|
444
|
+
className = "",
|
|
445
|
+
noPadding = false
|
|
446
|
+
}) {
|
|
447
|
+
const classes = [
|
|
448
|
+
baseStyles3,
|
|
449
|
+
variantStyles4[variant],
|
|
450
|
+
noPadding ? "" : "p-4",
|
|
451
|
+
className
|
|
452
|
+
].join(" ").replace(/\s+/g, " ").trim();
|
|
453
|
+
return /* @__PURE__ */ jsx("div", { className: classes, children });
|
|
454
|
+
}
|
|
455
|
+
function CardHeader({ children, className = "" }) {
|
|
456
|
+
return /* @__PURE__ */ jsx("div", { className: `px-4 py-3 border-b border-edge-primary ${className}`, children });
|
|
457
|
+
}
|
|
458
|
+
function CardBody({ children, className = "" }) {
|
|
459
|
+
return /* @__PURE__ */ jsx("div", { className: `p-4 ${className}`, children });
|
|
460
|
+
}
|
|
461
|
+
function CardFooter({ children, className = "" }) {
|
|
462
|
+
return /* @__PURE__ */ jsx("div", { className: `px-4 py-3 border-t border-edge-primary ${className}`, children });
|
|
463
|
+
}
|
|
464
|
+
function CheckmarkIcon({ className = "" }) {
|
|
465
|
+
return /* @__PURE__ */ jsx(
|
|
466
|
+
"svg",
|
|
467
|
+
{
|
|
468
|
+
width: "14",
|
|
469
|
+
height: "14",
|
|
470
|
+
viewBox: "0 0 16 16",
|
|
471
|
+
fill: "none",
|
|
472
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
473
|
+
className,
|
|
474
|
+
children: /* @__PURE__ */ jsx(
|
|
475
|
+
"path",
|
|
476
|
+
{
|
|
477
|
+
d: "M13.5 4.5L6 12L2.5 8.5",
|
|
478
|
+
stroke: "currentColor",
|
|
479
|
+
strokeWidth: "2",
|
|
480
|
+
strokeLinecap: "round",
|
|
481
|
+
strokeLinejoin: "round"
|
|
482
|
+
}
|
|
483
|
+
)
|
|
484
|
+
}
|
|
485
|
+
);
|
|
486
|
+
}
|
|
487
|
+
var Checkbox = forwardRef(function Checkbox2({ label, className = "", disabled, ...props }, ref) {
|
|
488
|
+
return /* @__PURE__ */ jsxs(
|
|
489
|
+
"label",
|
|
490
|
+
{
|
|
491
|
+
className: `
|
|
492
|
+
inline-flex items-center gap-2 cursor-pointer
|
|
493
|
+
${disabled ? "opacity-50 cursor-not-allowed" : ""}
|
|
494
|
+
${className}
|
|
495
|
+
`,
|
|
496
|
+
children: [
|
|
497
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
498
|
+
/* @__PURE__ */ jsx(
|
|
499
|
+
"input",
|
|
500
|
+
{
|
|
501
|
+
ref,
|
|
502
|
+
type: "checkbox",
|
|
503
|
+
disabled,
|
|
504
|
+
className: "peer sr-only",
|
|
505
|
+
...props
|
|
506
|
+
}
|
|
507
|
+
),
|
|
508
|
+
/* @__PURE__ */ jsx(
|
|
509
|
+
"div",
|
|
510
|
+
{
|
|
511
|
+
className: `
|
|
512
|
+
w-5 h-5
|
|
513
|
+
bg-surface-primary
|
|
514
|
+
border border-edge-primary
|
|
515
|
+
rounded-xs
|
|
516
|
+
peer-checked:bg-action-primary
|
|
517
|
+
peer-focus:ring-2 peer-focus:ring-edge-focus peer-focus:ring-offset-1
|
|
518
|
+
flex items-center justify-center
|
|
519
|
+
`
|
|
520
|
+
}
|
|
521
|
+
),
|
|
522
|
+
/* @__PURE__ */ jsx("div", { className: "absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 opacity-0 peer-checked:opacity-100 transition-opacity pointer-events-none", children: /* @__PURE__ */ jsx(CheckmarkIcon, { className: "text-content-primary" }) })
|
|
523
|
+
] }),
|
|
524
|
+
label && /* @__PURE__ */ jsx("span", { className: "font-mondwest text-base text-content-primary select-none", children: label })
|
|
525
|
+
]
|
|
526
|
+
}
|
|
527
|
+
);
|
|
528
|
+
});
|
|
529
|
+
var Radio = forwardRef(function Radio2({ label, className = "", disabled, ...props }, ref) {
|
|
530
|
+
return /* @__PURE__ */ jsxs(
|
|
531
|
+
"label",
|
|
532
|
+
{
|
|
533
|
+
className: `
|
|
534
|
+
inline-flex items-center gap-2 cursor-pointer
|
|
535
|
+
${disabled ? "opacity-50 cursor-not-allowed" : ""}
|
|
536
|
+
${className}
|
|
537
|
+
`,
|
|
538
|
+
children: [
|
|
539
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
540
|
+
/* @__PURE__ */ jsx(
|
|
541
|
+
"input",
|
|
542
|
+
{
|
|
543
|
+
ref,
|
|
544
|
+
type: "radio",
|
|
545
|
+
disabled,
|
|
546
|
+
className: "peer sr-only",
|
|
547
|
+
...props
|
|
548
|
+
}
|
|
549
|
+
),
|
|
550
|
+
/* @__PURE__ */ jsx(
|
|
551
|
+
"div",
|
|
552
|
+
{
|
|
553
|
+
className: `
|
|
554
|
+
w-5 h-5
|
|
555
|
+
bg-surface-primary
|
|
556
|
+
border border-edge-primary
|
|
557
|
+
rounded-full
|
|
558
|
+
peer-checked:bg-action-primary
|
|
559
|
+
peer-focus:ring-2 peer-focus:ring-edge-focus peer-focus:ring-offset-1
|
|
560
|
+
flex items-center justify-center
|
|
561
|
+
`
|
|
562
|
+
}
|
|
563
|
+
),
|
|
564
|
+
/* @__PURE__ */ jsx(
|
|
565
|
+
"div",
|
|
566
|
+
{
|
|
567
|
+
className: "absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-2 h-2 bg-content-primary rounded-full opacity-0 peer-checked:opacity-100 pointer-events-none"
|
|
568
|
+
}
|
|
569
|
+
)
|
|
570
|
+
] }),
|
|
571
|
+
label && /* @__PURE__ */ jsx("span", { className: "font-mondwest text-base text-content-primary select-none", children: label })
|
|
572
|
+
]
|
|
573
|
+
}
|
|
574
|
+
);
|
|
575
|
+
});
|
|
576
|
+
var ContextMenuContext = createContext(null);
|
|
577
|
+
function useContextMenu() {
|
|
578
|
+
const context = useContext(ContextMenuContext);
|
|
579
|
+
if (!context) {
|
|
580
|
+
throw new Error("ContextMenu components must be used within a ContextMenu provider");
|
|
581
|
+
}
|
|
582
|
+
return context;
|
|
583
|
+
}
|
|
584
|
+
function ContextMenu({ children, className = "" }) {
|
|
585
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
586
|
+
const [position, setPosition] = useState({ x: 0, y: 0 });
|
|
587
|
+
const containerRef = useRef(null);
|
|
588
|
+
const open = (pos) => {
|
|
589
|
+
setPosition(pos);
|
|
590
|
+
setIsOpen(true);
|
|
591
|
+
};
|
|
592
|
+
const close = () => {
|
|
593
|
+
setIsOpen(false);
|
|
594
|
+
};
|
|
595
|
+
const handleContextMenu = (e) => {
|
|
596
|
+
e.preventDefault();
|
|
597
|
+
open({ x: e.clientX, y: e.clientY });
|
|
598
|
+
};
|
|
599
|
+
useEffect(() => {
|
|
600
|
+
const handleClickOutside = (e) => {
|
|
601
|
+
if (containerRef.current && !containerRef.current.contains(e.target)) {
|
|
602
|
+
close();
|
|
603
|
+
}
|
|
604
|
+
};
|
|
605
|
+
const handleEscape = (e) => {
|
|
606
|
+
if (e.key === "Escape") close();
|
|
607
|
+
};
|
|
608
|
+
if (isOpen) {
|
|
609
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
610
|
+
document.addEventListener("keydown", handleEscape);
|
|
611
|
+
}
|
|
612
|
+
return () => {
|
|
613
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
614
|
+
document.removeEventListener("keydown", handleEscape);
|
|
615
|
+
};
|
|
616
|
+
}, [isOpen]);
|
|
617
|
+
return /* @__PURE__ */ jsx(ContextMenuContext.Provider, { value: { isOpen, position, open, close }, children: /* @__PURE__ */ jsx(
|
|
618
|
+
"div",
|
|
619
|
+
{
|
|
620
|
+
ref: containerRef,
|
|
621
|
+
onContextMenu: handleContextMenu,
|
|
622
|
+
className,
|
|
623
|
+
children
|
|
624
|
+
}
|
|
625
|
+
) });
|
|
626
|
+
}
|
|
627
|
+
function ContextMenuContent({ children, className = "" }) {
|
|
628
|
+
const { isOpen, position, close } = useContextMenu();
|
|
629
|
+
if (!isOpen) return null;
|
|
630
|
+
return /* @__PURE__ */ jsx(
|
|
631
|
+
"div",
|
|
632
|
+
{
|
|
633
|
+
className: `
|
|
634
|
+
fixed z-[1000]
|
|
635
|
+
min-w-[160px]
|
|
636
|
+
bg-surface-primary
|
|
637
|
+
border border-edge-primary
|
|
638
|
+
rounded-sm
|
|
639
|
+
shadow-[2px_2px_0_0_var(--color-edge-primary)]
|
|
640
|
+
py-1
|
|
641
|
+
${className}
|
|
642
|
+
`,
|
|
643
|
+
style: {
|
|
644
|
+
left: position.x,
|
|
645
|
+
top: position.y
|
|
646
|
+
},
|
|
647
|
+
onClick: close,
|
|
648
|
+
children
|
|
649
|
+
}
|
|
650
|
+
);
|
|
651
|
+
}
|
|
652
|
+
function ContextMenuItem({
|
|
653
|
+
onClick,
|
|
654
|
+
disabled = false,
|
|
655
|
+
destructive = false,
|
|
656
|
+
icon,
|
|
657
|
+
children,
|
|
658
|
+
className = ""
|
|
659
|
+
}) {
|
|
660
|
+
const { close } = useContextMenu();
|
|
661
|
+
const handleClick = () => {
|
|
662
|
+
if (!disabled && onClick) {
|
|
663
|
+
onClick();
|
|
664
|
+
close();
|
|
665
|
+
}
|
|
666
|
+
};
|
|
667
|
+
return /* @__PURE__ */ jsxs(
|
|
668
|
+
"button",
|
|
669
|
+
{
|
|
670
|
+
type: "button",
|
|
671
|
+
onClick: handleClick,
|
|
672
|
+
disabled,
|
|
673
|
+
className: `
|
|
674
|
+
w-full flex items-center gap-2
|
|
675
|
+
px-3 py-1.5
|
|
676
|
+
font-mondwest text-base text-left
|
|
677
|
+
${destructive ? "text-status-error" : "text-content-primary"}
|
|
678
|
+
${disabled ? "opacity-50 cursor-not-allowed" : "hover:bg-action-primary cursor-pointer"}
|
|
679
|
+
${className}
|
|
680
|
+
`,
|
|
681
|
+
children: [
|
|
682
|
+
icon && /* @__PURE__ */ jsx("span", { className: "w-4 h-4 flex items-center justify-center", children: icon }),
|
|
683
|
+
/* @__PURE__ */ jsx("span", { children })
|
|
684
|
+
]
|
|
685
|
+
}
|
|
686
|
+
);
|
|
687
|
+
}
|
|
688
|
+
function ContextMenuSeparator({ className = "" }) {
|
|
689
|
+
return /* @__PURE__ */ jsx(
|
|
690
|
+
"div",
|
|
691
|
+
{
|
|
692
|
+
className: `my-1 border-t border-edge-primary/20 ${className}`
|
|
693
|
+
}
|
|
694
|
+
);
|
|
695
|
+
}
|
|
696
|
+
function Divider({
|
|
697
|
+
orientation = "horizontal",
|
|
698
|
+
variant = "solid",
|
|
699
|
+
className = ""
|
|
700
|
+
}) {
|
|
701
|
+
if (variant === "decorated") {
|
|
702
|
+
return /* @__PURE__ */ jsxs("div", { className: `flex items-center gap-4 ${className}`, children: [
|
|
703
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 h-[2px] bg-edge-primary/20" }),
|
|
704
|
+
/* @__PURE__ */ jsx("div", { className: "w-2 h-2 bg-action-primary border border-edge-primary rotate-45" }),
|
|
705
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 h-[2px] bg-edge-primary/20" })
|
|
706
|
+
] });
|
|
707
|
+
}
|
|
708
|
+
if (orientation === "horizontal") {
|
|
709
|
+
const borderStyle2 = variant === "dashed" ? "border-dashed" : "border-solid";
|
|
710
|
+
return /* @__PURE__ */ jsx(
|
|
711
|
+
"div",
|
|
712
|
+
{
|
|
713
|
+
className: `w-full border-t border-edge-primary/20 ${borderStyle2} ${className}`,
|
|
714
|
+
role: "separator",
|
|
715
|
+
"aria-orientation": "horizontal"
|
|
716
|
+
}
|
|
717
|
+
);
|
|
718
|
+
}
|
|
719
|
+
const borderStyle = variant === "dashed" ? "border-dashed" : "border-solid";
|
|
720
|
+
return /* @__PURE__ */ jsx(
|
|
721
|
+
"div",
|
|
722
|
+
{
|
|
723
|
+
className: `h-full border-l border-edge-primary/20 ${borderStyle} ${className}`,
|
|
724
|
+
role: "separator",
|
|
725
|
+
"aria-orientation": "vertical"
|
|
726
|
+
}
|
|
727
|
+
);
|
|
728
|
+
}
|
|
729
|
+
var DropdownContext = createContext(null);
|
|
730
|
+
function useDropdownContext() {
|
|
731
|
+
const context = useContext(DropdownContext);
|
|
732
|
+
if (!context) {
|
|
733
|
+
throw new Error("DropdownMenu components must be used within a DropdownMenu");
|
|
734
|
+
}
|
|
735
|
+
return context;
|
|
736
|
+
}
|
|
737
|
+
function DropdownMenu({
|
|
738
|
+
open: controlledOpen,
|
|
739
|
+
defaultOpen = false,
|
|
740
|
+
onOpenChange,
|
|
741
|
+
position = "bottom-start",
|
|
742
|
+
children
|
|
743
|
+
}) {
|
|
744
|
+
const [internalOpen, setInternalOpen] = useState(defaultOpen);
|
|
745
|
+
const isControlled = controlledOpen !== void 0;
|
|
746
|
+
const open = isControlled ? controlledOpen : internalOpen;
|
|
747
|
+
const triggerRef = useRef(null);
|
|
748
|
+
const setOpen = useCallback((newOpen) => {
|
|
749
|
+
if (!isControlled) {
|
|
750
|
+
setInternalOpen(newOpen);
|
|
751
|
+
}
|
|
752
|
+
onOpenChange?.(newOpen);
|
|
753
|
+
}, [isControlled, onOpenChange]);
|
|
754
|
+
return /* @__PURE__ */ jsx(DropdownContext.Provider, { value: { open, setOpen, triggerRef, position }, children: /* @__PURE__ */ jsx("div", { className: "relative inline-block", children }) });
|
|
755
|
+
}
|
|
756
|
+
function DropdownMenuTrigger({ children, asChild }) {
|
|
757
|
+
const { open, setOpen, triggerRef } = useDropdownContext();
|
|
758
|
+
const handleClick = () => {
|
|
759
|
+
setOpen(!open);
|
|
760
|
+
};
|
|
761
|
+
if (asChild && React14.isValidElement(children)) {
|
|
762
|
+
return React14.cloneElement(children, {
|
|
763
|
+
onClick: handleClick,
|
|
764
|
+
ref: triggerRef
|
|
765
|
+
});
|
|
766
|
+
}
|
|
767
|
+
return /* @__PURE__ */ jsx(
|
|
768
|
+
"button",
|
|
769
|
+
{
|
|
770
|
+
type: "button",
|
|
771
|
+
ref: triggerRef,
|
|
772
|
+
onClick: handleClick,
|
|
773
|
+
children
|
|
774
|
+
}
|
|
775
|
+
);
|
|
776
|
+
}
|
|
777
|
+
function DropdownMenuContent({ className = "", children }) {
|
|
778
|
+
const { open, setOpen, triggerRef, position } = useDropdownContext();
|
|
779
|
+
const contentRef = useRef(null);
|
|
780
|
+
const [mounted, setMounted] = useState(false);
|
|
781
|
+
const [coords, setCoords] = useState({ top: 0, left: 0 });
|
|
782
|
+
useEffect(() => {
|
|
783
|
+
setMounted(true);
|
|
784
|
+
}, []);
|
|
785
|
+
useEffect(() => {
|
|
786
|
+
if (!open || !triggerRef.current || !contentRef.current) return;
|
|
787
|
+
const trigger = triggerRef.current.getBoundingClientRect();
|
|
788
|
+
const content = contentRef.current.getBoundingClientRect();
|
|
789
|
+
const gap = 4;
|
|
790
|
+
let top = 0;
|
|
791
|
+
let left = 0;
|
|
792
|
+
switch (position) {
|
|
793
|
+
case "bottom-start":
|
|
794
|
+
top = trigger.bottom + gap;
|
|
795
|
+
left = trigger.left;
|
|
796
|
+
break;
|
|
797
|
+
case "bottom-end":
|
|
798
|
+
top = trigger.bottom + gap;
|
|
799
|
+
left = trigger.right - content.width;
|
|
800
|
+
break;
|
|
801
|
+
case "top-start":
|
|
802
|
+
top = trigger.top - content.height - gap;
|
|
803
|
+
left = trigger.left;
|
|
804
|
+
break;
|
|
805
|
+
case "top-end":
|
|
806
|
+
top = trigger.top - content.height - gap;
|
|
807
|
+
left = trigger.right - content.width;
|
|
808
|
+
break;
|
|
809
|
+
}
|
|
810
|
+
top = Math.max(8, Math.min(top, window.innerHeight - content.height - 8));
|
|
811
|
+
left = Math.max(8, Math.min(left, window.innerWidth - content.width - 8));
|
|
812
|
+
setCoords({ top, left });
|
|
813
|
+
}, [open, position, triggerRef]);
|
|
814
|
+
useClickOutside(open, [contentRef, triggerRef], () => setOpen(false));
|
|
815
|
+
useEscapeKey(open, () => setOpen(false));
|
|
816
|
+
if (!mounted || !open) return null;
|
|
817
|
+
return createPortal(
|
|
818
|
+
/* @__PURE__ */ jsx(
|
|
819
|
+
"div",
|
|
820
|
+
{
|
|
821
|
+
ref: contentRef,
|
|
822
|
+
role: "menu",
|
|
823
|
+
className: `
|
|
824
|
+
fixed z-50
|
|
825
|
+
min-w-[8rem]
|
|
826
|
+
bg-surface-primary
|
|
827
|
+
border-2 border-edge-primary
|
|
828
|
+
rounded-sm
|
|
829
|
+
shadow-[2px_2px_0_0_var(--color-edge-primary)]
|
|
830
|
+
py-1
|
|
831
|
+
animate-fadeIn
|
|
832
|
+
${className}
|
|
833
|
+
`.trim(),
|
|
834
|
+
style: { top: coords.top, left: coords.left },
|
|
835
|
+
children
|
|
836
|
+
}
|
|
837
|
+
),
|
|
838
|
+
document.body
|
|
839
|
+
);
|
|
840
|
+
}
|
|
841
|
+
function DropdownMenuItem({
|
|
842
|
+
children,
|
|
843
|
+
onClick,
|
|
844
|
+
disabled = false,
|
|
845
|
+
destructive = false,
|
|
846
|
+
className = ""
|
|
847
|
+
}) {
|
|
848
|
+
const { setOpen } = useDropdownContext();
|
|
849
|
+
const handleClick = () => {
|
|
850
|
+
if (disabled) return;
|
|
851
|
+
onClick?.();
|
|
852
|
+
setOpen(false);
|
|
853
|
+
};
|
|
854
|
+
return /* @__PURE__ */ jsx(
|
|
855
|
+
"button",
|
|
856
|
+
{
|
|
857
|
+
type: "button",
|
|
858
|
+
role: "menuitem",
|
|
859
|
+
onClick: handleClick,
|
|
860
|
+
disabled,
|
|
861
|
+
className: `
|
|
862
|
+
w-full px-4 py-2
|
|
863
|
+
text-left
|
|
864
|
+
font-mondwest text-base
|
|
865
|
+
${destructive ? "text-status-error" : "text-content-primary"}
|
|
866
|
+
${disabled ? "opacity-50 cursor-not-allowed" : "hover:bg-content-primary/5 cursor-pointer"}
|
|
867
|
+
transition-colors
|
|
868
|
+
${className}
|
|
869
|
+
`.trim(),
|
|
870
|
+
children
|
|
871
|
+
}
|
|
872
|
+
);
|
|
873
|
+
}
|
|
874
|
+
function DropdownMenuSeparator({ className = "" }) {
|
|
875
|
+
return /* @__PURE__ */ jsx(
|
|
876
|
+
"div",
|
|
877
|
+
{
|
|
878
|
+
role: "separator",
|
|
879
|
+
className: `h-px bg-edge-primary/20 my-1 ${className}`.trim()
|
|
880
|
+
}
|
|
881
|
+
);
|
|
882
|
+
}
|
|
883
|
+
function DropdownMenuLabel({ children, className = "" }) {
|
|
884
|
+
return /* @__PURE__ */ jsx(
|
|
885
|
+
"div",
|
|
886
|
+
{
|
|
887
|
+
className: `
|
|
888
|
+
px-4 py-1
|
|
889
|
+
font-joystix text-2xs uppercase
|
|
890
|
+
text-content-primary/50
|
|
891
|
+
${className}
|
|
892
|
+
`.trim(),
|
|
893
|
+
children
|
|
894
|
+
}
|
|
895
|
+
);
|
|
896
|
+
}
|
|
897
|
+
var baseStyles4 = `
|
|
898
|
+
font-sans
|
|
899
|
+
bg-surface-primary text-content-primary
|
|
900
|
+
border border-edge-primary
|
|
901
|
+
rounded-sm
|
|
902
|
+
placeholder:text-content-muted
|
|
903
|
+
focus:outline-none
|
|
904
|
+
focus:ring-2 focus:ring-edge-focus focus:ring-offset-0
|
|
905
|
+
disabled:opacity-50 disabled:cursor-not-allowed
|
|
906
|
+
`;
|
|
907
|
+
var sizeStyles3 = {
|
|
908
|
+
sm: "h-8 px-2 text-sm",
|
|
909
|
+
md: "h-10 px-3 text-base",
|
|
910
|
+
lg: "h-12 px-4 text-base"
|
|
911
|
+
};
|
|
912
|
+
var errorStyles = `
|
|
913
|
+
border-status-error
|
|
914
|
+
focus:ring-status-error
|
|
915
|
+
`;
|
|
916
|
+
var Input = forwardRef(function Input2({
|
|
917
|
+
size = "md",
|
|
918
|
+
error = false,
|
|
919
|
+
fullWidth = false,
|
|
920
|
+
iconName,
|
|
921
|
+
className = "",
|
|
922
|
+
...props
|
|
923
|
+
}, ref) {
|
|
924
|
+
const paddingLeft = iconName ? size === "sm" ? "pl-8" : size === "lg" ? "pl-12" : "pl-10" : "";
|
|
925
|
+
const classes = [
|
|
926
|
+
baseStyles4,
|
|
927
|
+
sizeStyles3[size],
|
|
928
|
+
error ? errorStyles : "",
|
|
929
|
+
fullWidth ? "w-full" : "",
|
|
930
|
+
paddingLeft,
|
|
931
|
+
className
|
|
932
|
+
].join(" ").replace(/\s+/g, " ").trim();
|
|
933
|
+
const input = /* @__PURE__ */ jsx("input", { ref, className: classes, ...props });
|
|
934
|
+
if (iconName) {
|
|
935
|
+
return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
936
|
+
/* @__PURE__ */ jsx("div", { className: "absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none", children: /* @__PURE__ */ jsx(
|
|
937
|
+
"div",
|
|
938
|
+
{
|
|
939
|
+
className: "text-content-muted",
|
|
940
|
+
"data-icon-slot": iconName,
|
|
941
|
+
style: {
|
|
942
|
+
width: size === "sm" ? 14 : size === "lg" ? 18 : 20,
|
|
943
|
+
height: size === "sm" ? 14 : size === "lg" ? 18 : 20
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
) }),
|
|
947
|
+
input
|
|
948
|
+
] });
|
|
949
|
+
}
|
|
950
|
+
return input;
|
|
951
|
+
});
|
|
952
|
+
var TextArea = forwardRef(function TextArea2({
|
|
953
|
+
error = false,
|
|
954
|
+
fullWidth = false,
|
|
955
|
+
className = "",
|
|
956
|
+
...props
|
|
957
|
+
}, ref) {
|
|
958
|
+
const classes = [
|
|
959
|
+
baseStyles4,
|
|
960
|
+
"px-3 py-2 text-base",
|
|
961
|
+
"resize-y min-h-24",
|
|
962
|
+
error ? errorStyles : "",
|
|
963
|
+
fullWidth ? "w-full" : "",
|
|
964
|
+
className
|
|
965
|
+
].join(" ").replace(/\s+/g, " ").trim();
|
|
966
|
+
return /* @__PURE__ */ jsx("textarea", { ref, className: classes, ...props });
|
|
967
|
+
});
|
|
968
|
+
function Label({ children, required, className = "", ...props }) {
|
|
969
|
+
return /* @__PURE__ */ jsxs(
|
|
970
|
+
"label",
|
|
971
|
+
{
|
|
972
|
+
className,
|
|
973
|
+
...props,
|
|
974
|
+
children: [
|
|
975
|
+
children,
|
|
976
|
+
required && /* @__PURE__ */ jsx("span", { className: "text-status-error ml-1", children: "*" })
|
|
977
|
+
]
|
|
978
|
+
}
|
|
979
|
+
);
|
|
980
|
+
}
|
|
981
|
+
var sizeStyles4 = {
|
|
982
|
+
sm: "h-2",
|
|
983
|
+
md: "h-4",
|
|
984
|
+
lg: "h-6"
|
|
985
|
+
};
|
|
986
|
+
var variantStyles5 = {
|
|
987
|
+
default: "bg-action-primary",
|
|
988
|
+
success: "bg-status-success",
|
|
989
|
+
warning: "bg-surface-tertiary",
|
|
990
|
+
error: "bg-status-error"
|
|
991
|
+
};
|
|
992
|
+
function Progress({
|
|
993
|
+
value,
|
|
994
|
+
max = 100,
|
|
995
|
+
variant = "default",
|
|
996
|
+
size = "md",
|
|
997
|
+
showLabel = false,
|
|
998
|
+
className = ""
|
|
999
|
+
}) {
|
|
1000
|
+
const percentage = Math.min(100, Math.max(0, value / max * 100));
|
|
1001
|
+
return /* @__PURE__ */ jsxs("div", { className: `w-full ${className}`, children: [
|
|
1002
|
+
/* @__PURE__ */ jsx(
|
|
1003
|
+
"div",
|
|
1004
|
+
{
|
|
1005
|
+
className: `
|
|
1006
|
+
w-full
|
|
1007
|
+
bg-surface-primary
|
|
1008
|
+
border border-edge-primary
|
|
1009
|
+
rounded-sm
|
|
1010
|
+
overflow-hidden
|
|
1011
|
+
${sizeStyles4[size]}
|
|
1012
|
+
`,
|
|
1013
|
+
role: "progressbar",
|
|
1014
|
+
"aria-valuenow": value,
|
|
1015
|
+
"aria-valuemin": 0,
|
|
1016
|
+
"aria-valuemax": max,
|
|
1017
|
+
children: /* @__PURE__ */ jsx(
|
|
1018
|
+
"div",
|
|
1019
|
+
{
|
|
1020
|
+
className: `
|
|
1021
|
+
h-full
|
|
1022
|
+
${variantStyles5[variant]}
|
|
1023
|
+
`,
|
|
1024
|
+
style: { width: `${percentage}%` }
|
|
1025
|
+
}
|
|
1026
|
+
)
|
|
1027
|
+
}
|
|
1028
|
+
),
|
|
1029
|
+
showLabel && /* @__PURE__ */ jsxs("div", { className: "mt-1 font-joystix text-2xs text-content-primary text-right", children: [
|
|
1030
|
+
Math.round(percentage),
|
|
1031
|
+
"%"
|
|
1032
|
+
] })
|
|
1033
|
+
] });
|
|
1034
|
+
}
|
|
1035
|
+
var LOADER_FRAMES = ["\uEE06", "\uEE07", "\uEE08", "\uEE09", "\uEE0A", "\uEE0B"];
|
|
1036
|
+
function Spinner({ size = 24, className = "", completed = false }) {
|
|
1037
|
+
const [frameIndex, setFrameIndex] = React14.useState(0);
|
|
1038
|
+
React14.useEffect(() => {
|
|
1039
|
+
if (completed) {
|
|
1040
|
+
setFrameIndex(0);
|
|
1041
|
+
return;
|
|
1042
|
+
}
|
|
1043
|
+
const interval = setInterval(() => {
|
|
1044
|
+
setFrameIndex((prev) => (prev + 1) % LOADER_FRAMES.length);
|
|
1045
|
+
}, 150);
|
|
1046
|
+
return () => clearInterval(interval);
|
|
1047
|
+
}, [completed]);
|
|
1048
|
+
const fontSize = size;
|
|
1049
|
+
const displayChar = completed ? "\u2713" : LOADER_FRAMES[frameIndex];
|
|
1050
|
+
return /* @__PURE__ */ jsx(
|
|
1051
|
+
"div",
|
|
1052
|
+
{
|
|
1053
|
+
className: `inline-block flex items-center justify-center ${className}`,
|
|
1054
|
+
style: {
|
|
1055
|
+
width: size,
|
|
1056
|
+
height: size,
|
|
1057
|
+
fontSize,
|
|
1058
|
+
fontFamily: "PixelCode, monospace",
|
|
1059
|
+
lineHeight: 1
|
|
1060
|
+
},
|
|
1061
|
+
"aria-label": completed ? "Completed" : "Loading",
|
|
1062
|
+
role: "status",
|
|
1063
|
+
children: displayChar
|
|
1064
|
+
}
|
|
1065
|
+
);
|
|
1066
|
+
}
|
|
1067
|
+
function Select({
|
|
1068
|
+
options,
|
|
1069
|
+
value,
|
|
1070
|
+
placeholder = "Select...",
|
|
1071
|
+
onChange,
|
|
1072
|
+
disabled = false,
|
|
1073
|
+
error = false,
|
|
1074
|
+
fullWidth = false,
|
|
1075
|
+
className = ""
|
|
1076
|
+
}) {
|
|
1077
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
1078
|
+
const containerRef = useRef(null);
|
|
1079
|
+
useEffect(() => {
|
|
1080
|
+
function handleClickOutside(event) {
|
|
1081
|
+
if (containerRef.current && !containerRef.current.contains(event.target)) {
|
|
1082
|
+
setIsOpen(false);
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
1086
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
1087
|
+
}, []);
|
|
1088
|
+
const selectedOption = options.find((opt) => opt.value === value);
|
|
1089
|
+
const handleSelect = (optionValue) => {
|
|
1090
|
+
onChange?.(optionValue);
|
|
1091
|
+
setIsOpen(false);
|
|
1092
|
+
};
|
|
1093
|
+
return /* @__PURE__ */ jsxs(
|
|
1094
|
+
"div",
|
|
1095
|
+
{
|
|
1096
|
+
ref: containerRef,
|
|
1097
|
+
className: `relative ${fullWidth ? "w-full" : "w-fit"} ${className}`,
|
|
1098
|
+
children: [
|
|
1099
|
+
/* @__PURE__ */ jsxs(
|
|
1100
|
+
"button",
|
|
1101
|
+
{
|
|
1102
|
+
type: "button",
|
|
1103
|
+
onClick: () => !disabled && setIsOpen(!isOpen),
|
|
1104
|
+
disabled,
|
|
1105
|
+
className: `
|
|
1106
|
+
flex items-center justify-between gap-2
|
|
1107
|
+
w-full h-10 px-3
|
|
1108
|
+
font-mondwest text-base
|
|
1109
|
+
bg-surface-primary text-content-primary
|
|
1110
|
+
border rounded-sm
|
|
1111
|
+
${error ? "border-status-error" : "border-edge-primary"}
|
|
1112
|
+
${disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"}
|
|
1113
|
+
${isOpen ? "shadow-[0_3px_0_0_var(--color-edge-primary)] -translate-y-0.5" : "shadow-[0_1px_0_0_var(--color-edge-primary)]"}
|
|
1114
|
+
`,
|
|
1115
|
+
children: [
|
|
1116
|
+
/* @__PURE__ */ jsx("span", { className: selectedOption ? "text-content-primary" : "text-content-primary/40", children: selectedOption?.label || placeholder }),
|
|
1117
|
+
/* @__PURE__ */ jsx("span", { className: `text-content-primary ${isOpen ? "rotate-180" : ""}`, children: "\u25BC" })
|
|
1118
|
+
]
|
|
1119
|
+
}
|
|
1120
|
+
),
|
|
1121
|
+
isOpen && /* @__PURE__ */ jsx(
|
|
1122
|
+
"div",
|
|
1123
|
+
{
|
|
1124
|
+
className: `
|
|
1125
|
+
absolute z-50 top-full left-0 right-0 mt-1
|
|
1126
|
+
bg-surface-primary
|
|
1127
|
+
border border-edge-primary
|
|
1128
|
+
rounded-sm
|
|
1129
|
+
shadow-[2px_2px_0_0_var(--color-edge-primary)]
|
|
1130
|
+
overflow-hidden
|
|
1131
|
+
`,
|
|
1132
|
+
children: options.map((option) => /* @__PURE__ */ jsx(
|
|
1133
|
+
"button",
|
|
1134
|
+
{
|
|
1135
|
+
type: "button",
|
|
1136
|
+
onClick: () => !option.disabled && handleSelect(option.value),
|
|
1137
|
+
disabled: option.disabled,
|
|
1138
|
+
className: `
|
|
1139
|
+
w-full px-3 py-2
|
|
1140
|
+
font-mondwest text-base text-left
|
|
1141
|
+
${option.value === value ? "bg-action-primary text-content-primary" : "text-content-primary"}
|
|
1142
|
+
${option.disabled ? "opacity-50 cursor-not-allowed" : "hover:bg-action-primary cursor-pointer"}
|
|
1143
|
+
`,
|
|
1144
|
+
children: option.label
|
|
1145
|
+
},
|
|
1146
|
+
option.value
|
|
1147
|
+
))
|
|
1148
|
+
}
|
|
1149
|
+
)
|
|
1150
|
+
]
|
|
1151
|
+
}
|
|
1152
|
+
);
|
|
1153
|
+
}
|
|
1154
|
+
var sizeStyles5 = {
|
|
1155
|
+
sm: {
|
|
1156
|
+
track: "h-1",
|
|
1157
|
+
thumb: "w-3 h-3"
|
|
1158
|
+
},
|
|
1159
|
+
md: {
|
|
1160
|
+
track: "h-2",
|
|
1161
|
+
thumb: "w-4 h-4"
|
|
1162
|
+
},
|
|
1163
|
+
lg: {
|
|
1164
|
+
track: "h-3",
|
|
1165
|
+
thumb: "w-5 h-5"
|
|
1166
|
+
}
|
|
1167
|
+
};
|
|
1168
|
+
function Slider({
|
|
1169
|
+
value,
|
|
1170
|
+
onChange,
|
|
1171
|
+
min = 0,
|
|
1172
|
+
max = 100,
|
|
1173
|
+
step = 1,
|
|
1174
|
+
size = "md",
|
|
1175
|
+
disabled = false,
|
|
1176
|
+
showValue = false,
|
|
1177
|
+
label,
|
|
1178
|
+
className = ""
|
|
1179
|
+
}) {
|
|
1180
|
+
const trackRef = useRef(null);
|
|
1181
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
1182
|
+
const styles = sizeStyles5[size];
|
|
1183
|
+
const percentage = (value - min) / (max - min) * 100;
|
|
1184
|
+
const snapToStep = useCallback((val) => {
|
|
1185
|
+
const stepped = Math.round((val - min) / step) * step + min;
|
|
1186
|
+
return Math.max(min, Math.min(max, stepped));
|
|
1187
|
+
}, [min, max, step]);
|
|
1188
|
+
const getValueFromPosition = useCallback((clientX) => {
|
|
1189
|
+
if (!trackRef.current) return value;
|
|
1190
|
+
const rect = trackRef.current.getBoundingClientRect();
|
|
1191
|
+
const percent = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));
|
|
1192
|
+
const newValue = min + percent * (max - min);
|
|
1193
|
+
return snapToStep(newValue);
|
|
1194
|
+
}, [min, max, value, snapToStep]);
|
|
1195
|
+
const handlePointerDown = useCallback((e) => {
|
|
1196
|
+
if (disabled) return;
|
|
1197
|
+
e.preventDefault();
|
|
1198
|
+
setIsDragging(true);
|
|
1199
|
+
const newValue = getValueFromPosition(e.clientX);
|
|
1200
|
+
onChange(newValue);
|
|
1201
|
+
}, [disabled, getValueFromPosition, onChange]);
|
|
1202
|
+
useEffect(() => {
|
|
1203
|
+
if (!isDragging) return;
|
|
1204
|
+
const handlePointerMove = (e) => {
|
|
1205
|
+
const newValue = getValueFromPosition(e.clientX);
|
|
1206
|
+
onChange(newValue);
|
|
1207
|
+
};
|
|
1208
|
+
const handlePointerUp = () => {
|
|
1209
|
+
setIsDragging(false);
|
|
1210
|
+
};
|
|
1211
|
+
document.addEventListener("pointermove", handlePointerMove);
|
|
1212
|
+
document.addEventListener("pointerup", handlePointerUp);
|
|
1213
|
+
return () => {
|
|
1214
|
+
document.removeEventListener("pointermove", handlePointerMove);
|
|
1215
|
+
document.removeEventListener("pointerup", handlePointerUp);
|
|
1216
|
+
};
|
|
1217
|
+
}, [isDragging, getValueFromPosition, onChange]);
|
|
1218
|
+
const handleKeyDown = (e) => {
|
|
1219
|
+
if (disabled) return;
|
|
1220
|
+
let newValue = value;
|
|
1221
|
+
switch (e.key) {
|
|
1222
|
+
case "ArrowRight":
|
|
1223
|
+
case "ArrowUp":
|
|
1224
|
+
newValue = Math.min(max, value + step);
|
|
1225
|
+
break;
|
|
1226
|
+
case "ArrowLeft":
|
|
1227
|
+
case "ArrowDown":
|
|
1228
|
+
newValue = Math.max(min, value - step);
|
|
1229
|
+
break;
|
|
1230
|
+
case "Home":
|
|
1231
|
+
newValue = min;
|
|
1232
|
+
break;
|
|
1233
|
+
case "End":
|
|
1234
|
+
newValue = max;
|
|
1235
|
+
break;
|
|
1236
|
+
default:
|
|
1237
|
+
return;
|
|
1238
|
+
}
|
|
1239
|
+
e.preventDefault();
|
|
1240
|
+
onChange(newValue);
|
|
1241
|
+
};
|
|
1242
|
+
return /* @__PURE__ */ jsxs("div", { className: `space-y-2 ${className}`.trim(), children: [
|
|
1243
|
+
(label || showValue) && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
1244
|
+
label && /* @__PURE__ */ jsx("span", { className: "font-mondwest text-base text-content-primary", children: label }),
|
|
1245
|
+
showValue && /* @__PURE__ */ jsx("span", { className: "font-mondwest text-sm text-content-primary/60", children: value })
|
|
1246
|
+
] }),
|
|
1247
|
+
/* @__PURE__ */ jsxs(
|
|
1248
|
+
"div",
|
|
1249
|
+
{
|
|
1250
|
+
ref: trackRef,
|
|
1251
|
+
role: "slider",
|
|
1252
|
+
tabIndex: disabled ? -1 : 0,
|
|
1253
|
+
"aria-valuemin": min,
|
|
1254
|
+
"aria-valuemax": max,
|
|
1255
|
+
"aria-valuenow": value,
|
|
1256
|
+
"aria-disabled": disabled,
|
|
1257
|
+
onPointerDown: handlePointerDown,
|
|
1258
|
+
onKeyDown: handleKeyDown,
|
|
1259
|
+
className: `
|
|
1260
|
+
relative w-full
|
|
1261
|
+
flex items-center
|
|
1262
|
+
${styles.track}
|
|
1263
|
+
bg-edge-primary/10
|
|
1264
|
+
border border-edge-primary
|
|
1265
|
+
rounded-sm
|
|
1266
|
+
${disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"}
|
|
1267
|
+
focus:outline-none focus:ring-2 focus:ring-edge-focus focus:ring-offset-2
|
|
1268
|
+
`.trim(),
|
|
1269
|
+
children: [
|
|
1270
|
+
/* @__PURE__ */ jsx(
|
|
1271
|
+
"div",
|
|
1272
|
+
{
|
|
1273
|
+
className: `
|
|
1274
|
+
absolute top-0 left-0 h-full
|
|
1275
|
+
bg-action-primary
|
|
1276
|
+
rounded-sm
|
|
1277
|
+
pointer-events-none
|
|
1278
|
+
`.trim(),
|
|
1279
|
+
style: { width: `${percentage}%` }
|
|
1280
|
+
}
|
|
1281
|
+
),
|
|
1282
|
+
/* @__PURE__ */ jsx(
|
|
1283
|
+
"div",
|
|
1284
|
+
{
|
|
1285
|
+
className: "absolute top-0 bottom-0 flex items-center pointer-events-none",
|
|
1286
|
+
style: { left: `calc(${percentage}% - ${parseInt(styles.thumb.split(" ")[0].replace("w-", "")) * 2}px)` },
|
|
1287
|
+
children: /* @__PURE__ */ jsx(
|
|
1288
|
+
"div",
|
|
1289
|
+
{
|
|
1290
|
+
className: `
|
|
1291
|
+
${styles.thumb}
|
|
1292
|
+
bg-surface-muted
|
|
1293
|
+
border border-edge-primary
|
|
1294
|
+
rounded
|
|
1295
|
+
${isDragging ? "scale-110" : ""}
|
|
1296
|
+
transition-transform
|
|
1297
|
+
pointer-events-auto
|
|
1298
|
+
`.trim()
|
|
1299
|
+
}
|
|
1300
|
+
)
|
|
1301
|
+
}
|
|
1302
|
+
)
|
|
1303
|
+
]
|
|
1304
|
+
}
|
|
1305
|
+
)
|
|
1306
|
+
] });
|
|
1307
|
+
}
|
|
1308
|
+
var sizeStyles6 = {
|
|
1309
|
+
sm: {
|
|
1310
|
+
track: "w-8 h-4",
|
|
1311
|
+
thumb: "w-3 h-3",
|
|
1312
|
+
translate: "translate-x-4"
|
|
1313
|
+
},
|
|
1314
|
+
md: {
|
|
1315
|
+
track: "w-10 h-5",
|
|
1316
|
+
thumb: "w-4 h-4",
|
|
1317
|
+
translate: "translate-x-5"
|
|
1318
|
+
},
|
|
1319
|
+
lg: {
|
|
1320
|
+
track: "w-12 h-6",
|
|
1321
|
+
thumb: "w-5 h-5",
|
|
1322
|
+
translate: "translate-x-6"
|
|
1323
|
+
}
|
|
1324
|
+
};
|
|
1325
|
+
function Switch({
|
|
1326
|
+
checked,
|
|
1327
|
+
onChange,
|
|
1328
|
+
size = "md",
|
|
1329
|
+
disabled = false,
|
|
1330
|
+
label,
|
|
1331
|
+
labelPosition = "right",
|
|
1332
|
+
className = "",
|
|
1333
|
+
id
|
|
1334
|
+
}) {
|
|
1335
|
+
const styles = sizeStyles6[size];
|
|
1336
|
+
const switchId = id || `switch-${Math.random().toString(36).slice(2)}`;
|
|
1337
|
+
const handleClick = () => {
|
|
1338
|
+
if (!disabled) {
|
|
1339
|
+
onChange(!checked);
|
|
1340
|
+
}
|
|
1341
|
+
};
|
|
1342
|
+
const handleKeyDown = (e) => {
|
|
1343
|
+
if (e.key === " " || e.key === "Enter") {
|
|
1344
|
+
e.preventDefault();
|
|
1345
|
+
handleClick();
|
|
1346
|
+
}
|
|
1347
|
+
};
|
|
1348
|
+
const switchElement = /* @__PURE__ */ jsx(
|
|
1349
|
+
"button",
|
|
1350
|
+
{
|
|
1351
|
+
type: "button",
|
|
1352
|
+
role: "switch",
|
|
1353
|
+
id: switchId,
|
|
1354
|
+
"aria-checked": checked,
|
|
1355
|
+
disabled,
|
|
1356
|
+
onClick: handleClick,
|
|
1357
|
+
onKeyDown: handleKeyDown,
|
|
1358
|
+
className: `
|
|
1359
|
+
relative inline-flex items-center
|
|
1360
|
+
${styles.track}
|
|
1361
|
+
rounded-full
|
|
1362
|
+
border border-edge-primary
|
|
1363
|
+
transition-colors
|
|
1364
|
+
${checked ? "bg-action-primary" : "bg-edge-primary/10"}
|
|
1365
|
+
${disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"}
|
|
1366
|
+
focus:outline-none focus:ring-2 focus:ring-edge-focus focus:ring-offset-2
|
|
1367
|
+
`.trim(),
|
|
1368
|
+
children: /* @__PURE__ */ jsx(
|
|
1369
|
+
"span",
|
|
1370
|
+
{
|
|
1371
|
+
className: `
|
|
1372
|
+
${styles.thumb}
|
|
1373
|
+
rounded-full
|
|
1374
|
+
bg-surface-secondary
|
|
1375
|
+
border border-edge-primary
|
|
1376
|
+
transform transition-transform
|
|
1377
|
+
${checked ? styles.translate : "translate-x-0.5"}
|
|
1378
|
+
`.trim(),
|
|
1379
|
+
"aria-hidden": "true"
|
|
1380
|
+
}
|
|
1381
|
+
)
|
|
1382
|
+
}
|
|
1383
|
+
);
|
|
1384
|
+
if (!label) {
|
|
1385
|
+
return /* @__PURE__ */ jsx("div", { className, children: switchElement });
|
|
1386
|
+
}
|
|
1387
|
+
return /* @__PURE__ */ jsxs("div", { className: `inline-flex items-center gap-2 ${className}`.trim(), children: [
|
|
1388
|
+
labelPosition === "left" && /* @__PURE__ */ jsx(
|
|
1389
|
+
"label",
|
|
1390
|
+
{
|
|
1391
|
+
htmlFor: switchId,
|
|
1392
|
+
className: `
|
|
1393
|
+
font-mondwest text-base text-content-primary
|
|
1394
|
+
${disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"}
|
|
1395
|
+
`.trim(),
|
|
1396
|
+
children: label
|
|
1397
|
+
}
|
|
1398
|
+
),
|
|
1399
|
+
switchElement,
|
|
1400
|
+
labelPosition === "right" && /* @__PURE__ */ jsx(
|
|
1401
|
+
"label",
|
|
1402
|
+
{
|
|
1403
|
+
htmlFor: switchId,
|
|
1404
|
+
className: `
|
|
1405
|
+
font-mondwest text-base text-content-primary
|
|
1406
|
+
${disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"}
|
|
1407
|
+
`.trim(),
|
|
1408
|
+
children: label
|
|
1409
|
+
}
|
|
1410
|
+
)
|
|
1411
|
+
] });
|
|
1412
|
+
}
|
|
1413
|
+
var TabsContext = createContext(null);
|
|
1414
|
+
function useTabsContext() {
|
|
1415
|
+
const context = useContext(TabsContext);
|
|
1416
|
+
if (!context) {
|
|
1417
|
+
throw new Error("Tab components must be used within a Tabs provider");
|
|
1418
|
+
}
|
|
1419
|
+
return context;
|
|
1420
|
+
}
|
|
1421
|
+
var triggerBaseStyles = `
|
|
1422
|
+
flex items-center justify-center gap-2
|
|
1423
|
+
px-4 py-2
|
|
1424
|
+
font-joystix text-xs uppercase
|
|
1425
|
+
cursor-pointer select-none
|
|
1426
|
+
text-content-primary
|
|
1427
|
+
transition-all duration-200 ease-out
|
|
1428
|
+
relative
|
|
1429
|
+
border border-edge-primary
|
|
1430
|
+
rounded-sm
|
|
1431
|
+
flex-1
|
|
1432
|
+
shadow-none
|
|
1433
|
+
`;
|
|
1434
|
+
var pillStyles = {
|
|
1435
|
+
inactive: `
|
|
1436
|
+
bg-transparent text-content-primary
|
|
1437
|
+
hover:bg-surface-secondary/5
|
|
1438
|
+
hover:translate-y-0
|
|
1439
|
+
hover:shadow-none
|
|
1440
|
+
`,
|
|
1441
|
+
active: `
|
|
1442
|
+
bg-action-primary text-content-primary
|
|
1443
|
+
hover:bg-action-primary
|
|
1444
|
+
hover:translate-y-0
|
|
1445
|
+
hover:shadow-none
|
|
1446
|
+
`
|
|
1447
|
+
};
|
|
1448
|
+
var lineStyles = {
|
|
1449
|
+
inactive: `
|
|
1450
|
+
bg-transparent
|
|
1451
|
+
hover:bg-surface-primary/50
|
|
1452
|
+
`,
|
|
1453
|
+
active: `
|
|
1454
|
+
border-b-0
|
|
1455
|
+
bg-surface-primary
|
|
1456
|
+
border-t border-l border-r border-edge-primary
|
|
1457
|
+
rounded-t-md
|
|
1458
|
+
mb-0
|
|
1459
|
+
relative
|
|
1460
|
+
z-10
|
|
1461
|
+
`
|
|
1462
|
+
};
|
|
1463
|
+
function Tabs({
|
|
1464
|
+
defaultValue,
|
|
1465
|
+
value,
|
|
1466
|
+
onValueChange,
|
|
1467
|
+
variant = "pill",
|
|
1468
|
+
layout = "bottom-tabs",
|
|
1469
|
+
children,
|
|
1470
|
+
className = ""
|
|
1471
|
+
}) {
|
|
1472
|
+
const [internalValue, setInternalValue] = useState(defaultValue || "");
|
|
1473
|
+
const isControlled = value !== void 0;
|
|
1474
|
+
const activeTab = isControlled ? value : internalValue;
|
|
1475
|
+
const setActiveTab = (newValue) => {
|
|
1476
|
+
if (isControlled) {
|
|
1477
|
+
onValueChange?.(newValue);
|
|
1478
|
+
} else {
|
|
1479
|
+
setInternalValue(newValue);
|
|
1480
|
+
}
|
|
1481
|
+
};
|
|
1482
|
+
return /* @__PURE__ */ jsx(TabsContext.Provider, { value: { activeTab, setActiveTab, variant, layout }, children: /* @__PURE__ */ jsx("div", { className, children }) });
|
|
1483
|
+
}
|
|
1484
|
+
function TabList({ children, className = "" }) {
|
|
1485
|
+
const { layout } = useTabsContext();
|
|
1486
|
+
const shrinkClass = layout === "bottom-tabs" ? "shrink-0" : "";
|
|
1487
|
+
return /* @__PURE__ */ jsx("div", { className: `flex items-center justify-between gap-4 px-2 py-2 bg-surface-primary border-t border-edge-primary ${shrinkClass} ${className}`, children: /* @__PURE__ */ jsx("div", { className: "flex gap-2 items-center overflow-x-auto w-full", children }) });
|
|
1488
|
+
}
|
|
1489
|
+
function TabTrigger({
|
|
1490
|
+
value,
|
|
1491
|
+
children,
|
|
1492
|
+
icon,
|
|
1493
|
+
className = ""
|
|
1494
|
+
}) {
|
|
1495
|
+
const { activeTab, setActiveTab, variant } = useTabsContext();
|
|
1496
|
+
const isActive = activeTab === value;
|
|
1497
|
+
const variantStyle = variant === "pill" ? isActive ? pillStyles.active : pillStyles.inactive : isActive ? lineStyles.active : lineStyles.inactive;
|
|
1498
|
+
const classes = [
|
|
1499
|
+
triggerBaseStyles,
|
|
1500
|
+
variantStyle,
|
|
1501
|
+
className
|
|
1502
|
+
].join(" ").replace(/\s+/g, " ").trim();
|
|
1503
|
+
return /* @__PURE__ */ jsxs(
|
|
1504
|
+
"button",
|
|
1505
|
+
{
|
|
1506
|
+
type: "button",
|
|
1507
|
+
role: "tab",
|
|
1508
|
+
"aria-selected": isActive,
|
|
1509
|
+
onClick: () => setActiveTab(value),
|
|
1510
|
+
className: classes,
|
|
1511
|
+
children: [
|
|
1512
|
+
icon,
|
|
1513
|
+
children
|
|
1514
|
+
]
|
|
1515
|
+
}
|
|
1516
|
+
);
|
|
1517
|
+
}
|
|
1518
|
+
function TabContent({
|
|
1519
|
+
value,
|
|
1520
|
+
children,
|
|
1521
|
+
className = ""
|
|
1522
|
+
}) {
|
|
1523
|
+
const { activeTab, variant } = useTabsContext();
|
|
1524
|
+
if (activeTab !== value) {
|
|
1525
|
+
return null;
|
|
1526
|
+
}
|
|
1527
|
+
const contentClasses = variant === "line" ? `bg-surface-primary border-r border-edge-primary ${className}` : className;
|
|
1528
|
+
return /* @__PURE__ */ jsx(
|
|
1529
|
+
"div",
|
|
1530
|
+
{
|
|
1531
|
+
role: "tabpanel",
|
|
1532
|
+
className: contentClasses,
|
|
1533
|
+
style: { height: "auto" },
|
|
1534
|
+
children
|
|
1535
|
+
}
|
|
1536
|
+
);
|
|
1537
|
+
}
|
|
1538
|
+
var positionStyles = {
|
|
1539
|
+
top: "bottom-full left-1/2 -translate-x-1/2 mb-2",
|
|
1540
|
+
bottom: "top-full left-1/2 -translate-x-1/2 mt-2",
|
|
1541
|
+
left: "right-full top-1/2 -translate-y-1/2 mr-2",
|
|
1542
|
+
right: "left-full top-1/2 -translate-y-1/2 ml-2"
|
|
1543
|
+
};
|
|
1544
|
+
var arrowStyles = {
|
|
1545
|
+
top: "top-full left-1/2 -translate-x-1/2 border-l-transparent border-r-transparent border-b-transparent border-t-surface-secondary",
|
|
1546
|
+
bottom: "bottom-full left-1/2 -translate-x-1/2 border-l-transparent border-r-transparent border-t-transparent border-b-surface-secondary",
|
|
1547
|
+
left: "left-full top-1/2 -translate-y-1/2 border-t-transparent border-b-transparent border-r-transparent border-l-surface-secondary",
|
|
1548
|
+
right: "right-full top-1/2 -translate-y-1/2 border-t-transparent border-b-transparent border-l-transparent border-r-surface-secondary"
|
|
1549
|
+
};
|
|
1550
|
+
var sizeStyles7 = {
|
|
1551
|
+
sm: "text-xs",
|
|
1552
|
+
md: "text-xs",
|
|
1553
|
+
lg: "text-sm"
|
|
1554
|
+
};
|
|
1555
|
+
function Tooltip({
|
|
1556
|
+
content,
|
|
1557
|
+
position = "top",
|
|
1558
|
+
delay = 0,
|
|
1559
|
+
size = "md",
|
|
1560
|
+
children,
|
|
1561
|
+
className = ""
|
|
1562
|
+
}) {
|
|
1563
|
+
const [isVisible, setIsVisible] = useState(false);
|
|
1564
|
+
const timeoutRef = useRef(null);
|
|
1565
|
+
const showTooltip = () => {
|
|
1566
|
+
if (delay > 0) {
|
|
1567
|
+
timeoutRef.current = setTimeout(() => setIsVisible(true), delay);
|
|
1568
|
+
} else {
|
|
1569
|
+
setIsVisible(true);
|
|
1570
|
+
}
|
|
1571
|
+
};
|
|
1572
|
+
const hideTooltip = () => {
|
|
1573
|
+
if (timeoutRef.current) {
|
|
1574
|
+
clearTimeout(timeoutRef.current);
|
|
1575
|
+
}
|
|
1576
|
+
setIsVisible(false);
|
|
1577
|
+
};
|
|
1578
|
+
return /* @__PURE__ */ jsxs(
|
|
1579
|
+
"div",
|
|
1580
|
+
{
|
|
1581
|
+
className: `relative inline-flex ${className}`,
|
|
1582
|
+
onMouseEnter: showTooltip,
|
|
1583
|
+
onMouseLeave: hideTooltip,
|
|
1584
|
+
onFocus: showTooltip,
|
|
1585
|
+
onBlur: hideTooltip,
|
|
1586
|
+
children: [
|
|
1587
|
+
children,
|
|
1588
|
+
isVisible && /* @__PURE__ */ jsxs(
|
|
1589
|
+
"div",
|
|
1590
|
+
{
|
|
1591
|
+
className: `
|
|
1592
|
+
absolute z-[1000]
|
|
1593
|
+
px-2 py-1
|
|
1594
|
+
bg-surface-secondary text-content-inverted
|
|
1595
|
+
font-joystix uppercase
|
|
1596
|
+
rounded-sm
|
|
1597
|
+
whitespace-nowrap
|
|
1598
|
+
pointer-events-none
|
|
1599
|
+
${sizeStyles7[size]}
|
|
1600
|
+
${positionStyles[position]}
|
|
1601
|
+
`,
|
|
1602
|
+
role: "tooltip",
|
|
1603
|
+
children: [
|
|
1604
|
+
content,
|
|
1605
|
+
/* @__PURE__ */ jsx(
|
|
1606
|
+
"div",
|
|
1607
|
+
{
|
|
1608
|
+
className: `
|
|
1609
|
+
absolute
|
|
1610
|
+
border-4 border-solid
|
|
1611
|
+
${arrowStyles[position]}
|
|
1612
|
+
`
|
|
1613
|
+
}
|
|
1614
|
+
)
|
|
1615
|
+
]
|
|
1616
|
+
}
|
|
1617
|
+
)
|
|
1618
|
+
]
|
|
1619
|
+
}
|
|
1620
|
+
);
|
|
1621
|
+
}
|
|
1622
|
+
var ToastContext = createContext(null);
|
|
1623
|
+
function useToast() {
|
|
1624
|
+
const context = useContext(ToastContext);
|
|
1625
|
+
if (!context) {
|
|
1626
|
+
throw new Error("useToast must be used within a ToastProvider");
|
|
1627
|
+
}
|
|
1628
|
+
return context;
|
|
1629
|
+
}
|
|
1630
|
+
function ToastProvider({
|
|
1631
|
+
children,
|
|
1632
|
+
defaultDuration = 5e3,
|
|
1633
|
+
renderIcon,
|
|
1634
|
+
renderCloseIcon
|
|
1635
|
+
}) {
|
|
1636
|
+
const [toasts, setToasts] = useState([]);
|
|
1637
|
+
const [mounted, setMounted] = useState(false);
|
|
1638
|
+
useEffect(() => {
|
|
1639
|
+
setMounted(true);
|
|
1640
|
+
}, []);
|
|
1641
|
+
const addToast = useCallback((toast) => {
|
|
1642
|
+
const id = `toast-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
1643
|
+
const duration = toast.duration ?? defaultDuration;
|
|
1644
|
+
setToasts((prev) => [...prev, { ...toast, id }]);
|
|
1645
|
+
if (duration > 0) {
|
|
1646
|
+
setTimeout(() => {
|
|
1647
|
+
setToasts((prev) => prev.filter((t) => t.id !== id));
|
|
1648
|
+
}, duration);
|
|
1649
|
+
}
|
|
1650
|
+
return id;
|
|
1651
|
+
}, [defaultDuration]);
|
|
1652
|
+
const removeToast = useCallback((id) => {
|
|
1653
|
+
setToasts((prev) => prev.filter((t) => t.id !== id));
|
|
1654
|
+
}, []);
|
|
1655
|
+
return /* @__PURE__ */ jsxs(ToastContext.Provider, { value: { toasts, addToast, removeToast }, children: [
|
|
1656
|
+
children,
|
|
1657
|
+
mounted && createPortal(
|
|
1658
|
+
/* @__PURE__ */ jsx(
|
|
1659
|
+
ToastViewport,
|
|
1660
|
+
{
|
|
1661
|
+
toasts,
|
|
1662
|
+
removeToast,
|
|
1663
|
+
renderIcon,
|
|
1664
|
+
renderCloseIcon
|
|
1665
|
+
}
|
|
1666
|
+
),
|
|
1667
|
+
document.body
|
|
1668
|
+
)
|
|
1669
|
+
] });
|
|
1670
|
+
}
|
|
1671
|
+
function ToastViewport({ toasts, removeToast, renderIcon, renderCloseIcon }) {
|
|
1672
|
+
if (toasts.length === 0) return null;
|
|
1673
|
+
return /* @__PURE__ */ jsx(
|
|
1674
|
+
"div",
|
|
1675
|
+
{
|
|
1676
|
+
className: "fixed bottom-4 right-4 z-[100] flex flex-col gap-2 max-w-sm w-full pointer-events-none",
|
|
1677
|
+
"aria-live": "polite",
|
|
1678
|
+
children: toasts.map((toast) => /* @__PURE__ */ jsx(
|
|
1679
|
+
Toast,
|
|
1680
|
+
{
|
|
1681
|
+
toast,
|
|
1682
|
+
onClose: () => removeToast(toast.id),
|
|
1683
|
+
renderIcon,
|
|
1684
|
+
renderCloseIcon
|
|
1685
|
+
},
|
|
1686
|
+
toast.id
|
|
1687
|
+
))
|
|
1688
|
+
}
|
|
1689
|
+
);
|
|
1690
|
+
}
|
|
1691
|
+
var variantStyles6 = {
|
|
1692
|
+
default: "bg-surface-primary border-edge-primary",
|
|
1693
|
+
success: "bg-status-success border-status-success",
|
|
1694
|
+
warning: "bg-status-warning border-surface-tertiary",
|
|
1695
|
+
error: "bg-status-error border-status-error",
|
|
1696
|
+
info: "bg-status-info border-status-info"
|
|
1697
|
+
};
|
|
1698
|
+
function Toast({ toast, onClose, renderIcon, renderCloseIcon }) {
|
|
1699
|
+
const variant = toast.variant || "default";
|
|
1700
|
+
const displayIcon = toast.icon ?? (renderIcon ? renderIcon(variant) : null);
|
|
1701
|
+
return /* @__PURE__ */ jsx(
|
|
1702
|
+
"div",
|
|
1703
|
+
{
|
|
1704
|
+
className: `
|
|
1705
|
+
pointer-events-auto
|
|
1706
|
+
p-4
|
|
1707
|
+
border-2
|
|
1708
|
+
rounded-sm
|
|
1709
|
+
shadow-[2px_2px_0_0_var(--color-edge-primary)]
|
|
1710
|
+
animate-slideIn
|
|
1711
|
+
${variantStyles6[variant]}
|
|
1712
|
+
`.trim(),
|
|
1713
|
+
role: "alert",
|
|
1714
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3", children: [
|
|
1715
|
+
displayIcon && /* @__PURE__ */ jsx("span", { className: "flex-shrink-0", children: displayIcon }),
|
|
1716
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
1717
|
+
/* @__PURE__ */ jsx("p", { className: "font-joystix text-xs uppercase text-content-primary", children: toast.title }),
|
|
1718
|
+
toast.description && /* @__PURE__ */ jsx("p", { className: "font-mondwest text-base text-content-primary/70 mt-1", children: toast.description })
|
|
1719
|
+
] }),
|
|
1720
|
+
/* @__PURE__ */ jsx(
|
|
1721
|
+
"button",
|
|
1722
|
+
{
|
|
1723
|
+
onClick: onClose,
|
|
1724
|
+
className: "text-content-primary/50 hover:text-content-primary flex-shrink-0 -mt-1",
|
|
1725
|
+
"aria-label": "Close",
|
|
1726
|
+
children: renderCloseIcon ? renderCloseIcon() : /* @__PURE__ */ jsx(
|
|
1727
|
+
"svg",
|
|
1728
|
+
{
|
|
1729
|
+
width: "16",
|
|
1730
|
+
height: "16",
|
|
1731
|
+
viewBox: "0 0 16 16",
|
|
1732
|
+
fill: "none",
|
|
1733
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1734
|
+
children: /* @__PURE__ */ jsx(
|
|
1735
|
+
"path",
|
|
1736
|
+
{
|
|
1737
|
+
d: "M12 4L4 12M4 4L12 12",
|
|
1738
|
+
stroke: "currentColor",
|
|
1739
|
+
strokeWidth: "2",
|
|
1740
|
+
strokeLinecap: "round",
|
|
1741
|
+
strokeLinejoin: "round"
|
|
1742
|
+
}
|
|
1743
|
+
)
|
|
1744
|
+
}
|
|
1745
|
+
)
|
|
1746
|
+
}
|
|
1747
|
+
)
|
|
1748
|
+
] })
|
|
1749
|
+
}
|
|
1750
|
+
);
|
|
1751
|
+
}
|
|
1752
|
+
function HelpPanel({
|
|
1753
|
+
isOpen,
|
|
1754
|
+
onClose,
|
|
1755
|
+
children,
|
|
1756
|
+
title = "Help",
|
|
1757
|
+
closeButton,
|
|
1758
|
+
className = ""
|
|
1759
|
+
}) {
|
|
1760
|
+
const panelRef = useRef(null);
|
|
1761
|
+
useEffect(() => {
|
|
1762
|
+
const handleEscape = (e) => {
|
|
1763
|
+
if (e.key === "Escape" && isOpen) {
|
|
1764
|
+
onClose();
|
|
1765
|
+
}
|
|
1766
|
+
};
|
|
1767
|
+
document.addEventListener("keydown", handleEscape);
|
|
1768
|
+
return () => document.removeEventListener("keydown", handleEscape);
|
|
1769
|
+
}, [isOpen, onClose]);
|
|
1770
|
+
useEffect(() => {
|
|
1771
|
+
const handleClickOutside = (e) => {
|
|
1772
|
+
if (panelRef.current && !panelRef.current.contains(e.target) && isOpen) {
|
|
1773
|
+
onClose();
|
|
1774
|
+
}
|
|
1775
|
+
};
|
|
1776
|
+
const timeoutId = setTimeout(() => {
|
|
1777
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
1778
|
+
}, 100);
|
|
1779
|
+
return () => {
|
|
1780
|
+
clearTimeout(timeoutId);
|
|
1781
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
1782
|
+
};
|
|
1783
|
+
}, [isOpen, onClose]);
|
|
1784
|
+
if (!isOpen) return null;
|
|
1785
|
+
return /* @__PURE__ */ jsx(
|
|
1786
|
+
"div",
|
|
1787
|
+
{
|
|
1788
|
+
className: `
|
|
1789
|
+
absolute inset-0 z-50
|
|
1790
|
+
bg-surface-secondary/20
|
|
1791
|
+
flex justify-center items-center
|
|
1792
|
+
`,
|
|
1793
|
+
children: /* @__PURE__ */ jsxs(
|
|
1794
|
+
"div",
|
|
1795
|
+
{
|
|
1796
|
+
ref: panelRef,
|
|
1797
|
+
className: `
|
|
1798
|
+
h-full w-full max-w-4xl
|
|
1799
|
+
bg-surface-primary
|
|
1800
|
+
border border-edge-primary
|
|
1801
|
+
shadow-card-lg
|
|
1802
|
+
flex flex-col
|
|
1803
|
+
animate-slide-in-right
|
|
1804
|
+
${className}
|
|
1805
|
+
`,
|
|
1806
|
+
children: [
|
|
1807
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4 py-3 border-b border-edge-primary", children: [
|
|
1808
|
+
/* @__PURE__ */ jsx("span", { className: "font-joystix text-xs text-content-primary uppercase", children: title }),
|
|
1809
|
+
closeButton ? /* @__PURE__ */ jsx("span", { onClick: onClose, className: "cursor-pointer", children: closeButton }) : /* @__PURE__ */ jsx(
|
|
1810
|
+
"button",
|
|
1811
|
+
{
|
|
1812
|
+
onClick: onClose,
|
|
1813
|
+
className: "text-content-primary/50 hover:text-content-primary p-1",
|
|
1814
|
+
"aria-label": "Close help panel",
|
|
1815
|
+
children: /* @__PURE__ */ jsx(
|
|
1816
|
+
"svg",
|
|
1817
|
+
{
|
|
1818
|
+
width: "16",
|
|
1819
|
+
height: "16",
|
|
1820
|
+
viewBox: "0 0 16 16",
|
|
1821
|
+
fill: "none",
|
|
1822
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1823
|
+
children: /* @__PURE__ */ jsx(
|
|
1824
|
+
"path",
|
|
1825
|
+
{
|
|
1826
|
+
d: "M12 4L4 12M4 4L12 12",
|
|
1827
|
+
stroke: "currentColor",
|
|
1828
|
+
strokeWidth: "2",
|
|
1829
|
+
strokeLinecap: "round",
|
|
1830
|
+
strokeLinejoin: "round"
|
|
1831
|
+
}
|
|
1832
|
+
)
|
|
1833
|
+
}
|
|
1834
|
+
)
|
|
1835
|
+
}
|
|
1836
|
+
)
|
|
1837
|
+
] }),
|
|
1838
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-auto p-4", children: /* @__PURE__ */ jsx("div", { className: "font-mondwest text-base text-content-primary space-y-4", children }) })
|
|
1839
|
+
]
|
|
1840
|
+
}
|
|
1841
|
+
)
|
|
1842
|
+
}
|
|
1843
|
+
);
|
|
1844
|
+
}
|
|
1845
|
+
var PopoverContext = createContext(null);
|
|
1846
|
+
function usePopoverContext() {
|
|
1847
|
+
const context = useContext(PopoverContext);
|
|
1848
|
+
if (!context) {
|
|
1849
|
+
throw new Error("Popover components must be used within a Popover");
|
|
1850
|
+
}
|
|
1851
|
+
return context;
|
|
1852
|
+
}
|
|
1853
|
+
function Popover({
|
|
1854
|
+
open: controlledOpen,
|
|
1855
|
+
defaultOpen = false,
|
|
1856
|
+
onOpenChange,
|
|
1857
|
+
position = "bottom",
|
|
1858
|
+
children
|
|
1859
|
+
}) {
|
|
1860
|
+
const [internalOpen, setInternalOpen] = useState(defaultOpen);
|
|
1861
|
+
const isControlled = controlledOpen !== void 0;
|
|
1862
|
+
const open = isControlled ? controlledOpen : internalOpen;
|
|
1863
|
+
const triggerRef = useRef(null);
|
|
1864
|
+
const setOpen = useCallback((newOpen) => {
|
|
1865
|
+
if (!isControlled) {
|
|
1866
|
+
setInternalOpen(newOpen);
|
|
1867
|
+
}
|
|
1868
|
+
onOpenChange?.(newOpen);
|
|
1869
|
+
}, [isControlled, onOpenChange]);
|
|
1870
|
+
return /* @__PURE__ */ jsx(PopoverContext.Provider, { value: { open, setOpen, triggerRef, position }, children });
|
|
1871
|
+
}
|
|
1872
|
+
function PopoverTrigger({ children, asChild }) {
|
|
1873
|
+
const { open, setOpen, triggerRef } = usePopoverContext();
|
|
1874
|
+
const handleClick = () => {
|
|
1875
|
+
setOpen(!open);
|
|
1876
|
+
};
|
|
1877
|
+
if (asChild && React14.isValidElement(children)) {
|
|
1878
|
+
return React14.cloneElement(children, {
|
|
1879
|
+
onClick: handleClick,
|
|
1880
|
+
ref: triggerRef
|
|
1881
|
+
});
|
|
1882
|
+
}
|
|
1883
|
+
return /* @__PURE__ */ jsx(
|
|
1884
|
+
"button",
|
|
1885
|
+
{
|
|
1886
|
+
type: "button",
|
|
1887
|
+
ref: triggerRef,
|
|
1888
|
+
onClick: handleClick,
|
|
1889
|
+
children
|
|
1890
|
+
}
|
|
1891
|
+
);
|
|
1892
|
+
}
|
|
1893
|
+
function PopoverContent({ className = "", children, align = "center" }) {
|
|
1894
|
+
const { open, setOpen, triggerRef, position } = usePopoverContext();
|
|
1895
|
+
const contentRef = useRef(null);
|
|
1896
|
+
const [mounted, setMounted] = useState(false);
|
|
1897
|
+
const [coords, setCoords] = useState({ top: 0, left: 0 });
|
|
1898
|
+
useEffect(() => {
|
|
1899
|
+
setMounted(true);
|
|
1900
|
+
}, []);
|
|
1901
|
+
useEffect(() => {
|
|
1902
|
+
if (!open || !triggerRef.current || !contentRef.current) return;
|
|
1903
|
+
const trigger = triggerRef.current.getBoundingClientRect();
|
|
1904
|
+
const content = contentRef.current.getBoundingClientRect();
|
|
1905
|
+
const gap = 8;
|
|
1906
|
+
let top = 0;
|
|
1907
|
+
let left = 0;
|
|
1908
|
+
switch (position) {
|
|
1909
|
+
case "top":
|
|
1910
|
+
top = trigger.top - content.height - gap;
|
|
1911
|
+
left = trigger.left + (trigger.width - content.width) / 2;
|
|
1912
|
+
break;
|
|
1913
|
+
case "bottom":
|
|
1914
|
+
top = trigger.bottom + gap;
|
|
1915
|
+
left = trigger.left + (trigger.width - content.width) / 2;
|
|
1916
|
+
break;
|
|
1917
|
+
case "left":
|
|
1918
|
+
top = trigger.top + (trigger.height - content.height) / 2;
|
|
1919
|
+
left = trigger.left - content.width - gap;
|
|
1920
|
+
break;
|
|
1921
|
+
case "right":
|
|
1922
|
+
top = trigger.top + (trigger.height - content.height) / 2;
|
|
1923
|
+
left = trigger.right + gap;
|
|
1924
|
+
break;
|
|
1925
|
+
}
|
|
1926
|
+
if (position === "top" || position === "bottom") {
|
|
1927
|
+
if (align === "start") {
|
|
1928
|
+
left = trigger.left;
|
|
1929
|
+
} else if (align === "end") {
|
|
1930
|
+
left = trigger.right - content.width;
|
|
1931
|
+
}
|
|
1932
|
+
}
|
|
1933
|
+
top = Math.max(8, Math.min(top, window.innerHeight - content.height - 8));
|
|
1934
|
+
left = Math.max(8, Math.min(left, window.innerWidth - content.width - 8));
|
|
1935
|
+
setCoords({ top, left });
|
|
1936
|
+
}, [open, position, align, triggerRef]);
|
|
1937
|
+
useClickOutside(open, [contentRef, triggerRef], () => setOpen(false));
|
|
1938
|
+
useEscapeKey(open, () => setOpen(false));
|
|
1939
|
+
if (!mounted || !open) return null;
|
|
1940
|
+
return createPortal(
|
|
1941
|
+
/* @__PURE__ */ jsx(
|
|
1942
|
+
"div",
|
|
1943
|
+
{
|
|
1944
|
+
ref: contentRef,
|
|
1945
|
+
className: `
|
|
1946
|
+
fixed z-50
|
|
1947
|
+
bg-surface-primary
|
|
1948
|
+
border-2 border-edge-primary
|
|
1949
|
+
rounded-sm
|
|
1950
|
+
shadow-[2px_2px_0_0_var(--color-edge-primary)]
|
|
1951
|
+
p-4
|
|
1952
|
+
animate-fadeIn
|
|
1953
|
+
${className}
|
|
1954
|
+
`.trim(),
|
|
1955
|
+
style: { top: coords.top, left: coords.left },
|
|
1956
|
+
children
|
|
1957
|
+
}
|
|
1958
|
+
),
|
|
1959
|
+
document.body
|
|
1960
|
+
);
|
|
1961
|
+
}
|
|
1962
|
+
var SheetContext = createContext(null);
|
|
1963
|
+
function useSheetContext() {
|
|
1964
|
+
const context = useContext(SheetContext);
|
|
1965
|
+
if (!context) {
|
|
1966
|
+
throw new Error("Sheet components must be used within a Sheet");
|
|
1967
|
+
}
|
|
1968
|
+
return context;
|
|
1969
|
+
}
|
|
1970
|
+
function Sheet({
|
|
1971
|
+
open: controlledOpen,
|
|
1972
|
+
defaultOpen = false,
|
|
1973
|
+
onOpenChange,
|
|
1974
|
+
side = "right",
|
|
1975
|
+
children
|
|
1976
|
+
}) {
|
|
1977
|
+
const [internalOpen, setInternalOpen] = useState(defaultOpen);
|
|
1978
|
+
const isControlled = controlledOpen !== void 0;
|
|
1979
|
+
const open = isControlled ? controlledOpen : internalOpen;
|
|
1980
|
+
const setOpen = useCallback((newOpen) => {
|
|
1981
|
+
if (!isControlled) {
|
|
1982
|
+
setInternalOpen(newOpen);
|
|
1983
|
+
}
|
|
1984
|
+
onOpenChange?.(newOpen);
|
|
1985
|
+
}, [isControlled, onOpenChange]);
|
|
1986
|
+
return /* @__PURE__ */ jsx(SheetContext.Provider, { value: { open, setOpen, side }, children });
|
|
1987
|
+
}
|
|
1988
|
+
function SheetTrigger({ children, asChild }) {
|
|
1989
|
+
const { setOpen } = useSheetContext();
|
|
1990
|
+
if (asChild && React14.isValidElement(children)) {
|
|
1991
|
+
return React14.cloneElement(children, {
|
|
1992
|
+
onClick: () => setOpen(true)
|
|
1993
|
+
});
|
|
1994
|
+
}
|
|
1995
|
+
return /* @__PURE__ */ jsx("button", { type: "button", onClick: () => setOpen(true), children });
|
|
1996
|
+
}
|
|
1997
|
+
var sideStyles = {
|
|
1998
|
+
left: {
|
|
1999
|
+
container: "inset-y-0 left-0 h-full w-80 max-w-[90vw]",
|
|
2000
|
+
open: "translate-x-0",
|
|
2001
|
+
closed: "-translate-x-full"
|
|
2002
|
+
},
|
|
2003
|
+
right: {
|
|
2004
|
+
container: "inset-y-0 right-0 h-full w-80 max-w-[90vw]",
|
|
2005
|
+
open: "translate-x-0",
|
|
2006
|
+
closed: "translate-x-full"
|
|
2007
|
+
},
|
|
2008
|
+
top: {
|
|
2009
|
+
container: "inset-x-0 top-0 w-full h-80 max-h-[90vh]",
|
|
2010
|
+
open: "translate-y-0",
|
|
2011
|
+
closed: "-translate-y-full"
|
|
2012
|
+
},
|
|
2013
|
+
bottom: {
|
|
2014
|
+
container: "inset-x-0 bottom-0 w-full h-80 max-h-[90vh]",
|
|
2015
|
+
open: "translate-y-0",
|
|
2016
|
+
closed: "translate-y-full"
|
|
2017
|
+
}
|
|
2018
|
+
};
|
|
2019
|
+
function SheetContent({ className = "", children }) {
|
|
2020
|
+
const { open, setOpen, side } = useSheetContext();
|
|
2021
|
+
const [mounted, setMounted] = useState(false);
|
|
2022
|
+
const [isVisible, setIsVisible] = useState(false);
|
|
2023
|
+
const styles = sideStyles[side];
|
|
2024
|
+
useEffect(() => {
|
|
2025
|
+
setMounted(true);
|
|
2026
|
+
}, []);
|
|
2027
|
+
useEffect(() => {
|
|
2028
|
+
if (open) {
|
|
2029
|
+
setIsVisible(true);
|
|
2030
|
+
} else {
|
|
2031
|
+
const timer = setTimeout(() => {
|
|
2032
|
+
setIsVisible(false);
|
|
2033
|
+
}, 200);
|
|
2034
|
+
return () => clearTimeout(timer);
|
|
2035
|
+
}
|
|
2036
|
+
}, [open]);
|
|
2037
|
+
useEscapeKey(open, () => setOpen(false));
|
|
2038
|
+
useLockBodyScroll(open);
|
|
2039
|
+
if (!mounted || !isVisible) return null;
|
|
2040
|
+
return createPortal(
|
|
2041
|
+
/* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-50", children: [
|
|
2042
|
+
/* @__PURE__ */ jsx(
|
|
2043
|
+
"div",
|
|
2044
|
+
{
|
|
2045
|
+
className: `
|
|
2046
|
+
absolute inset-0 bg-surface-secondary/50
|
|
2047
|
+
transition-opacity duration-200
|
|
2048
|
+
${open ? "opacity-100" : "opacity-0"}
|
|
2049
|
+
`.trim(),
|
|
2050
|
+
onClick: () => setOpen(false),
|
|
2051
|
+
"aria-hidden": "true"
|
|
2052
|
+
}
|
|
2053
|
+
),
|
|
2054
|
+
/* @__PURE__ */ jsx(
|
|
2055
|
+
"div",
|
|
2056
|
+
{
|
|
2057
|
+
role: "dialog",
|
|
2058
|
+
"aria-modal": "true",
|
|
2059
|
+
className: `
|
|
2060
|
+
fixed
|
|
2061
|
+
${styles.container}
|
|
2062
|
+
bg-surface-primary
|
|
2063
|
+
border-edge-primary
|
|
2064
|
+
${side === "left" ? "border-r-2" : ""}
|
|
2065
|
+
${side === "right" ? "border-l-2" : ""}
|
|
2066
|
+
${side === "top" ? "border-b-2" : ""}
|
|
2067
|
+
${side === "bottom" ? "border-t-2" : ""}
|
|
2068
|
+
shadow-[4px_4px_0_0_var(--color-edge-primary)]
|
|
2069
|
+
transform transition-transform duration-200 ease-out
|
|
2070
|
+
${open ? styles.open : styles.closed}
|
|
2071
|
+
${className}
|
|
2072
|
+
`.trim(),
|
|
2073
|
+
children
|
|
2074
|
+
}
|
|
2075
|
+
)
|
|
2076
|
+
] }),
|
|
2077
|
+
document.body
|
|
2078
|
+
);
|
|
2079
|
+
}
|
|
2080
|
+
function SheetHeader({ className = "", children }) {
|
|
2081
|
+
return /* @__PURE__ */ jsx("div", { className: `px-6 pt-6 pb-4 border-b border-edge-primary/20 ${className}`.trim(), children });
|
|
2082
|
+
}
|
|
2083
|
+
function SheetTitle({ className = "", children }) {
|
|
2084
|
+
return /* @__PURE__ */ jsx("h2", { className: `font-joystix text-base uppercase text-content-primary ${className}`.trim(), children });
|
|
2085
|
+
}
|
|
2086
|
+
function SheetDescription({ className = "", children }) {
|
|
2087
|
+
return /* @__PURE__ */ jsx("p", { className: `font-mondwest text-base text-content-primary/70 mt-2 ${className}`.trim(), children });
|
|
2088
|
+
}
|
|
2089
|
+
function SheetBody({ className = "", children }) {
|
|
2090
|
+
return /* @__PURE__ */ jsx("div", { className: `px-6 py-4 flex-1 overflow-auto ${className}`.trim(), children });
|
|
2091
|
+
}
|
|
2092
|
+
function SheetFooter({ className = "", children }) {
|
|
2093
|
+
return /* @__PURE__ */ jsx("div", { className: `px-6 pb-6 pt-4 border-t border-edge-primary/20 flex justify-end gap-2 ${className}`.trim(), children });
|
|
2094
|
+
}
|
|
2095
|
+
function SheetClose({ children, asChild }) {
|
|
2096
|
+
const { setOpen } = useSheetContext();
|
|
2097
|
+
if (asChild && React14.isValidElement(children)) {
|
|
2098
|
+
return React14.cloneElement(children, {
|
|
2099
|
+
onClick: () => setOpen(false)
|
|
2100
|
+
});
|
|
2101
|
+
}
|
|
2102
|
+
return /* @__PURE__ */ jsx("button", { type: "button", onClick: () => setOpen(false), children });
|
|
2103
|
+
}
|
|
2104
|
+
var popoverStyles = `
|
|
2105
|
+
absolute top-12 right-2 z-50 w-72
|
|
2106
|
+
bg-surface-primary border-2 border-edge-primary rounded-sm shadow-lg
|
|
2107
|
+
`;
|
|
2108
|
+
var headerStyles = `
|
|
2109
|
+
flex items-center justify-between px-3 py-2 border-b border-edge-primary/20
|
|
2110
|
+
`;
|
|
2111
|
+
var contentStyles = `
|
|
2112
|
+
p-2 space-y-3 max-h-80 overflow-y-auto
|
|
2113
|
+
`;
|
|
2114
|
+
var categoryLabelStyles = `
|
|
2115
|
+
font-heading text-xs uppercase text-content-secondary px-2 mb-1
|
|
2116
|
+
`;
|
|
2117
|
+
var footerStyles = `
|
|
2118
|
+
px-3 py-2 border-t border-edge-primary/20 bg-content-primary/5
|
|
2119
|
+
`;
|
|
2120
|
+
function MockStatesPopover({
|
|
2121
|
+
isOpen,
|
|
2122
|
+
onClose,
|
|
2123
|
+
mockStates,
|
|
2124
|
+
activeMockState,
|
|
2125
|
+
onSelectState,
|
|
2126
|
+
categories,
|
|
2127
|
+
title = "Mock States",
|
|
2128
|
+
footerText = "Dev mode only",
|
|
2129
|
+
className = ""
|
|
2130
|
+
}) {
|
|
2131
|
+
if (!isOpen) return null;
|
|
2132
|
+
const derivedCategories = categories ?? [...new Set(mockStates.map((s) => s.category))].map((cat) => ({
|
|
2133
|
+
id: cat,
|
|
2134
|
+
label: cat.charAt(0).toUpperCase() + cat.slice(1)
|
|
2135
|
+
}));
|
|
2136
|
+
const statesByCategory = derivedCategories.map((cat) => ({
|
|
2137
|
+
category: cat,
|
|
2138
|
+
states: mockStates.filter((s) => s.category === cat.id)
|
|
2139
|
+
})).filter((group) => group.states.length > 0);
|
|
2140
|
+
const renderStateButton = (def) => {
|
|
2141
|
+
const isActive = activeMockState === def.id;
|
|
2142
|
+
return /* @__PURE__ */ jsxs(
|
|
2143
|
+
"button",
|
|
2144
|
+
{
|
|
2145
|
+
onClick: () => onSelectState(def.id),
|
|
2146
|
+
className: `
|
|
2147
|
+
w-full text-left px-3 py-2 rounded-sm
|
|
2148
|
+
flex items-center gap-2
|
|
2149
|
+
transition-colors duration-150
|
|
2150
|
+
${isActive ? "bg-action-primary text-content-primary" : "hover:bg-content-primary/5 text-content-primary"}
|
|
2151
|
+
`,
|
|
2152
|
+
children: [
|
|
2153
|
+
def.icon && /* @__PURE__ */ jsx("span", { className: "text-sm", children: def.icon }),
|
|
2154
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
2155
|
+
/* @__PURE__ */ jsx("div", { className: "font-heading text-xs uppercase truncate", children: def.name }),
|
|
2156
|
+
/* @__PURE__ */ jsx("div", { className: "font-body text-xs text-content-secondary truncate", children: def.description })
|
|
2157
|
+
] }),
|
|
2158
|
+
isActive && /* @__PURE__ */ jsx("span", { className: "text-xs", children: "\u2713" })
|
|
2159
|
+
]
|
|
2160
|
+
},
|
|
2161
|
+
def.id
|
|
2162
|
+
);
|
|
2163
|
+
};
|
|
2164
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2165
|
+
/* @__PURE__ */ jsx(
|
|
2166
|
+
"div",
|
|
2167
|
+
{
|
|
2168
|
+
className: "fixed inset-0 z-40",
|
|
2169
|
+
onClick: onClose
|
|
2170
|
+
}
|
|
2171
|
+
),
|
|
2172
|
+
/* @__PURE__ */ jsxs("div", { className: `${popoverStyles} ${className}`.trim(), children: [
|
|
2173
|
+
/* @__PURE__ */ jsxs("div", { className: headerStyles, children: [
|
|
2174
|
+
/* @__PURE__ */ jsx("span", { className: "font-heading text-xs uppercase", children: title }),
|
|
2175
|
+
/* @__PURE__ */ jsx(
|
|
2176
|
+
Button,
|
|
2177
|
+
{
|
|
2178
|
+
variant: "ghost",
|
|
2179
|
+
size: "sm",
|
|
2180
|
+
iconOnly: true,
|
|
2181
|
+
onClick: onClose,
|
|
2182
|
+
"aria-label": "Close",
|
|
2183
|
+
children: "\u2715"
|
|
2184
|
+
}
|
|
2185
|
+
)
|
|
2186
|
+
] }),
|
|
2187
|
+
/* @__PURE__ */ jsx("div", { className: contentStyles, children: statesByCategory.map(({ category, states }) => /* @__PURE__ */ jsxs("div", { children: [
|
|
2188
|
+
/* @__PURE__ */ jsx("div", { className: categoryLabelStyles, children: category.label }),
|
|
2189
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-1", children: states.map(renderStateButton) })
|
|
2190
|
+
] }, category.id)) }),
|
|
2191
|
+
footerText && /* @__PURE__ */ jsx("div", { className: footerStyles, children: /* @__PURE__ */ jsx("div", { className: "font-body text-xs text-content-secondary text-center", children: footerText }) })
|
|
2192
|
+
] })
|
|
2193
|
+
] });
|
|
2194
|
+
}
|
|
2195
|
+
var baseStyles5 = `
|
|
2196
|
+
text-center
|
|
2197
|
+
`;
|
|
2198
|
+
var variantStyles7 = {
|
|
2199
|
+
default: {
|
|
2200
|
+
container: "p-4 bg-surface-primary border border-edge-primary rounded-md",
|
|
2201
|
+
label: "font-mono text-xs text-content-primary/60 mb-2",
|
|
2202
|
+
timer: "flex items-center justify-center gap-1",
|
|
2203
|
+
segment: "flex flex-col items-center min-w-[3rem]",
|
|
2204
|
+
value: "font-joystix text-2xl text-content-primary tabular-nums",
|
|
2205
|
+
unit: "font-mono text-2xs text-content-primary/50 uppercase mt-0.5",
|
|
2206
|
+
separator: "font-joystix text-xl text-content-primary/40 self-start mt-1"
|
|
2207
|
+
},
|
|
2208
|
+
compact: {
|
|
2209
|
+
container: "px-3 py-2 bg-surface-primary border border-edge-primary rounded-sm",
|
|
2210
|
+
label: "font-mono text-2xs text-content-primary/60 mb-1",
|
|
2211
|
+
timer: "flex items-center justify-center gap-0.5",
|
|
2212
|
+
segment: "flex flex-col items-center min-w-[2rem]",
|
|
2213
|
+
value: "font-joystix text-sm text-content-primary tabular-nums",
|
|
2214
|
+
unit: "font-mono text-2xs text-content-primary/50 uppercase",
|
|
2215
|
+
separator: "font-joystix text-sm text-content-primary/40 self-start"
|
|
2216
|
+
},
|
|
2217
|
+
large: {
|
|
2218
|
+
container: "p-6 bg-surface-primary border border-edge-primary rounded-md shadow-card",
|
|
2219
|
+
label: "font-mono text-sm text-content-primary/60 mb-3",
|
|
2220
|
+
timer: "flex items-center justify-center gap-2",
|
|
2221
|
+
segment: "flex flex-col items-center min-w-[4rem] bg-surface-muted border border-edge-primary rounded-sm px-3 py-2",
|
|
2222
|
+
value: "font-joystix text-3xl text-content-primary tabular-nums",
|
|
2223
|
+
unit: "font-mono text-xs text-content-primary/50 uppercase mt-1",
|
|
2224
|
+
separator: "font-joystix text-2xl text-content-primary/40 self-center"
|
|
2225
|
+
}
|
|
2226
|
+
};
|
|
2227
|
+
function getTimeRemaining(endTime) {
|
|
2228
|
+
const end = typeof endTime === "number" ? endTime : endTime.getTime();
|
|
2229
|
+
const total = Math.max(0, end - Date.now());
|
|
2230
|
+
const seconds = Math.floor(total / 1e3 % 60);
|
|
2231
|
+
const minutes = Math.floor(total / 1e3 / 60 % 60);
|
|
2232
|
+
const hours = Math.floor(total / (1e3 * 60 * 60) % 24);
|
|
2233
|
+
const days = Math.floor(total / (1e3 * 60 * 60 * 24));
|
|
2234
|
+
return { days, hours, minutes, seconds, total };
|
|
2235
|
+
}
|
|
2236
|
+
function getStatus(endTime, startTime) {
|
|
2237
|
+
const now = Date.now();
|
|
2238
|
+
const end = typeof endTime === "number" ? endTime : endTime.getTime();
|
|
2239
|
+
const start = startTime ? typeof startTime === "number" ? startTime : startTime.getTime() : now;
|
|
2240
|
+
if (now < start) return "upcoming";
|
|
2241
|
+
if (now >= end) return "ended";
|
|
2242
|
+
return "active";
|
|
2243
|
+
}
|
|
2244
|
+
function padZero(num) {
|
|
2245
|
+
return num.toString().padStart(2, "0");
|
|
2246
|
+
}
|
|
2247
|
+
function CountdownTimer({
|
|
2248
|
+
endTime,
|
|
2249
|
+
startTime,
|
|
2250
|
+
variant = "default",
|
|
2251
|
+
label,
|
|
2252
|
+
onComplete,
|
|
2253
|
+
endedMessage = "Ended",
|
|
2254
|
+
upcomingMessage = "Starting soon",
|
|
2255
|
+
showDays = true,
|
|
2256
|
+
className = ""
|
|
2257
|
+
}) {
|
|
2258
|
+
const [timeRemaining, setTimeRemaining] = useState(
|
|
2259
|
+
() => getTimeRemaining(endTime)
|
|
2260
|
+
);
|
|
2261
|
+
const [status, setStatus] = useState(
|
|
2262
|
+
() => getStatus(endTime, startTime)
|
|
2263
|
+
);
|
|
2264
|
+
const updateTime = useCallback(() => {
|
|
2265
|
+
const newTime = getTimeRemaining(endTime);
|
|
2266
|
+
const newStatus = getStatus(endTime, startTime);
|
|
2267
|
+
setTimeRemaining(newTime);
|
|
2268
|
+
setStatus(newStatus);
|
|
2269
|
+
if (newStatus === "ended" && onComplete) {
|
|
2270
|
+
onComplete();
|
|
2271
|
+
}
|
|
2272
|
+
}, [endTime, startTime, onComplete]);
|
|
2273
|
+
useEffect(() => {
|
|
2274
|
+
updateTime();
|
|
2275
|
+
if (status === "ended") return;
|
|
2276
|
+
const interval = setInterval(updateTime, 1e3);
|
|
2277
|
+
return () => clearInterval(interval);
|
|
2278
|
+
}, [updateTime, status]);
|
|
2279
|
+
const styles = variantStyles7[variant];
|
|
2280
|
+
if (status === "ended") {
|
|
2281
|
+
return /* @__PURE__ */ jsxs("div", { className: `${baseStyles5} ${styles.container} ${className}`, children: [
|
|
2282
|
+
label && /* @__PURE__ */ jsx("p", { className: styles.label, children: label }),
|
|
2283
|
+
/* @__PURE__ */ jsx("p", { className: `font-joystix ${variant === "large" ? "text-xl" : variant === "compact" ? "text-sm" : "text-lg"} text-content-primary/60`, children: endedMessage })
|
|
2284
|
+
] });
|
|
2285
|
+
}
|
|
2286
|
+
if (status === "upcoming" && startTime) {
|
|
2287
|
+
const startRemaining = getTimeRemaining(startTime);
|
|
2288
|
+
return /* @__PURE__ */ jsxs("div", { className: `${baseStyles5} ${styles.container} ${className}`, children: [
|
|
2289
|
+
/* @__PURE__ */ jsx("p", { className: styles.label, children: "Starts in" }),
|
|
2290
|
+
/* @__PURE__ */ jsxs("div", { className: styles.timer, children: [
|
|
2291
|
+
showDays && startRemaining.days > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2292
|
+
/* @__PURE__ */ jsxs("div", { className: styles.segment, children: [
|
|
2293
|
+
/* @__PURE__ */ jsx("span", { className: styles.value, children: startRemaining.days }),
|
|
2294
|
+
/* @__PURE__ */ jsx("span", { className: styles.unit, children: "days" })
|
|
2295
|
+
] }),
|
|
2296
|
+
/* @__PURE__ */ jsx("span", { className: styles.separator, children: ":" })
|
|
2297
|
+
] }),
|
|
2298
|
+
/* @__PURE__ */ jsxs("div", { className: styles.segment, children: [
|
|
2299
|
+
/* @__PURE__ */ jsx("span", { className: styles.value, children: padZero(startRemaining.hours) }),
|
|
2300
|
+
/* @__PURE__ */ jsx("span", { className: styles.unit, children: "hrs" })
|
|
2301
|
+
] }),
|
|
2302
|
+
/* @__PURE__ */ jsx("span", { className: styles.separator, children: ":" }),
|
|
2303
|
+
/* @__PURE__ */ jsxs("div", { className: styles.segment, children: [
|
|
2304
|
+
/* @__PURE__ */ jsx("span", { className: styles.value, children: padZero(startRemaining.minutes) }),
|
|
2305
|
+
/* @__PURE__ */ jsx("span", { className: styles.unit, children: "min" })
|
|
2306
|
+
] }),
|
|
2307
|
+
/* @__PURE__ */ jsx("span", { className: styles.separator, children: ":" }),
|
|
2308
|
+
/* @__PURE__ */ jsxs("div", { className: styles.segment, children: [
|
|
2309
|
+
/* @__PURE__ */ jsx("span", { className: styles.value, children: padZero(startRemaining.seconds) }),
|
|
2310
|
+
/* @__PURE__ */ jsx("span", { className: styles.unit, children: "sec" })
|
|
2311
|
+
] })
|
|
2312
|
+
] })
|
|
2313
|
+
] });
|
|
2314
|
+
}
|
|
2315
|
+
return /* @__PURE__ */ jsxs("div", { className: `${baseStyles5} ${styles.container} ${className}`, children: [
|
|
2316
|
+
label && /* @__PURE__ */ jsx("p", { className: styles.label, children: label }),
|
|
2317
|
+
/* @__PURE__ */ jsxs("div", { className: styles.timer, children: [
|
|
2318
|
+
showDays && timeRemaining.days > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2319
|
+
/* @__PURE__ */ jsxs("div", { className: styles.segment, children: [
|
|
2320
|
+
/* @__PURE__ */ jsx("span", { className: styles.value, children: timeRemaining.days }),
|
|
2321
|
+
/* @__PURE__ */ jsx("span", { className: styles.unit, children: "days" })
|
|
2322
|
+
] }),
|
|
2323
|
+
/* @__PURE__ */ jsx("span", { className: styles.separator, children: ":" })
|
|
2324
|
+
] }),
|
|
2325
|
+
/* @__PURE__ */ jsxs("div", { className: styles.segment, children: [
|
|
2326
|
+
/* @__PURE__ */ jsx("span", { className: styles.value, children: padZero(timeRemaining.hours) }),
|
|
2327
|
+
/* @__PURE__ */ jsx("span", { className: styles.unit, children: "hrs" })
|
|
2328
|
+
] }),
|
|
2329
|
+
/* @__PURE__ */ jsx("span", { className: styles.separator, children: ":" }),
|
|
2330
|
+
/* @__PURE__ */ jsxs("div", { className: styles.segment, children: [
|
|
2331
|
+
/* @__PURE__ */ jsx("span", { className: styles.value, children: padZero(timeRemaining.minutes) }),
|
|
2332
|
+
/* @__PURE__ */ jsx("span", { className: styles.unit, children: "min" })
|
|
2333
|
+
] }),
|
|
2334
|
+
/* @__PURE__ */ jsx("span", { className: styles.separator, children: ":" }),
|
|
2335
|
+
/* @__PURE__ */ jsxs("div", { className: styles.segment, children: [
|
|
2336
|
+
/* @__PURE__ */ jsx("span", { className: styles.value, children: padZero(timeRemaining.seconds) }),
|
|
2337
|
+
/* @__PURE__ */ jsx("span", { className: styles.unit, children: "sec" })
|
|
2338
|
+
] })
|
|
2339
|
+
] })
|
|
2340
|
+
] });
|
|
2341
|
+
}
|
|
2342
|
+
function formatAddress(address) {
|
|
2343
|
+
if (!address) return "";
|
|
2344
|
+
if (address.length <= 10) return address;
|
|
2345
|
+
return `${address.slice(0, 4)}...${address.slice(-4)}`;
|
|
2346
|
+
}
|
|
2347
|
+
function Web3ActionBar({
|
|
2348
|
+
isConnected,
|
|
2349
|
+
walletAddress,
|
|
2350
|
+
onConnect,
|
|
2351
|
+
onDisconnect,
|
|
2352
|
+
disconnectIcon,
|
|
2353
|
+
children,
|
|
2354
|
+
className = ""
|
|
2355
|
+
}) {
|
|
2356
|
+
return /* @__PURE__ */ jsxs("div", { className: `flex items-center justify-between gap-4 px-2 py-2 bg-surface-primary border-t border-edge-primary shrink-0 ${className}`.trim(), children: [
|
|
2357
|
+
/* @__PURE__ */ jsx("div", { className: "flex gap-2 items-center", children: !isConnected ? /* @__PURE__ */ jsx(Button, { onClick: onConnect, children: "Connect" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2358
|
+
walletAddress && /* @__PURE__ */ jsx("span", { className: "font-mono text-xs text-content-primary", children: formatAddress(walletAddress) }),
|
|
2359
|
+
onDisconnect && /* @__PURE__ */ jsx(
|
|
2360
|
+
Button,
|
|
2361
|
+
{
|
|
2362
|
+
variant: "ghost",
|
|
2363
|
+
iconOnly: true,
|
|
2364
|
+
icon: disconnectIcon,
|
|
2365
|
+
onClick: onDisconnect,
|
|
2366
|
+
title: "Disconnect wallet"
|
|
2367
|
+
}
|
|
2368
|
+
)
|
|
2369
|
+
] }) }),
|
|
2370
|
+
isConnected && children && /* @__PURE__ */ jsx("div", { className: "flex gap-2 items-center", children })
|
|
2371
|
+
] });
|
|
2372
|
+
}
|
|
2373
|
+
var DialogContext = createContext(null);
|
|
2374
|
+
function useDialogContext() {
|
|
2375
|
+
const context = useContext(DialogContext);
|
|
2376
|
+
if (!context) {
|
|
2377
|
+
throw new Error("Dialog components must be used within a Dialog");
|
|
2378
|
+
}
|
|
2379
|
+
return context;
|
|
2380
|
+
}
|
|
2381
|
+
function Dialog({
|
|
2382
|
+
open: controlledOpen,
|
|
2383
|
+
defaultOpen = false,
|
|
2384
|
+
onOpenChange,
|
|
2385
|
+
children
|
|
2386
|
+
}) {
|
|
2387
|
+
const [internalOpen, setInternalOpen] = useState(defaultOpen);
|
|
2388
|
+
const isControlled = controlledOpen !== void 0;
|
|
2389
|
+
const open = isControlled ? controlledOpen : internalOpen;
|
|
2390
|
+
const setOpen = useCallback((newOpen) => {
|
|
2391
|
+
if (!isControlled) {
|
|
2392
|
+
setInternalOpen(newOpen);
|
|
2393
|
+
}
|
|
2394
|
+
onOpenChange?.(newOpen);
|
|
2395
|
+
}, [isControlled, onOpenChange]);
|
|
2396
|
+
return /* @__PURE__ */ jsx(DialogContext.Provider, { value: { open, setOpen }, children });
|
|
2397
|
+
}
|
|
2398
|
+
function DialogTrigger({ children, asChild }) {
|
|
2399
|
+
const { setOpen } = useDialogContext();
|
|
2400
|
+
if (asChild && React14.isValidElement(children)) {
|
|
2401
|
+
return React14.cloneElement(children, {
|
|
2402
|
+
onClick: () => setOpen(true)
|
|
2403
|
+
});
|
|
2404
|
+
}
|
|
2405
|
+
return /* @__PURE__ */ jsx("button", { type: "button", onClick: () => setOpen(true), children });
|
|
2406
|
+
}
|
|
2407
|
+
function DialogContent({ className = "", children }) {
|
|
2408
|
+
const { open, setOpen } = useDialogContext();
|
|
2409
|
+
const [mounted, setMounted] = useState(false);
|
|
2410
|
+
useEffect(() => {
|
|
2411
|
+
setMounted(true);
|
|
2412
|
+
}, []);
|
|
2413
|
+
useEscapeKey(open, () => setOpen(false));
|
|
2414
|
+
useLockBodyScroll(open);
|
|
2415
|
+
if (!mounted || !open) return null;
|
|
2416
|
+
return createPortal(
|
|
2417
|
+
/* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-50 flex items-center justify-center", children: [
|
|
2418
|
+
/* @__PURE__ */ jsx(
|
|
2419
|
+
"div",
|
|
2420
|
+
{
|
|
2421
|
+
className: "absolute inset-0 bg-surface-secondary/50 animate-fadeIn",
|
|
2422
|
+
onClick: () => setOpen(false),
|
|
2423
|
+
"aria-hidden": "true"
|
|
2424
|
+
}
|
|
2425
|
+
),
|
|
2426
|
+
/* @__PURE__ */ jsx(
|
|
2427
|
+
"div",
|
|
2428
|
+
{
|
|
2429
|
+
role: "dialog",
|
|
2430
|
+
"aria-modal": "true",
|
|
2431
|
+
className: `
|
|
2432
|
+
relative z-10
|
|
2433
|
+
w-full max-w-lg mx-4
|
|
2434
|
+
bg-surface-primary
|
|
2435
|
+
border-2 border-edge-primary
|
|
2436
|
+
rounded-sm
|
|
2437
|
+
shadow-[4px_4px_0_0_var(--color-edge-primary)]
|
|
2438
|
+
animate-scaleIn
|
|
2439
|
+
${className}
|
|
2440
|
+
`.trim(),
|
|
2441
|
+
children
|
|
2442
|
+
}
|
|
2443
|
+
)
|
|
2444
|
+
] }),
|
|
2445
|
+
document.body
|
|
2446
|
+
);
|
|
2447
|
+
}
|
|
2448
|
+
function DialogHeader({ className = "", children }) {
|
|
2449
|
+
return /* @__PURE__ */ jsx("div", { className: `px-6 pt-6 pb-4 border-b border-edge-primary/20 ${className}`.trim(), children });
|
|
2450
|
+
}
|
|
2451
|
+
function DialogTitle({ className = "", children }) {
|
|
2452
|
+
return /* @__PURE__ */ jsx("h2", { className: `font-joystix text-base uppercase text-content-primary ${className}`.trim(), children });
|
|
2453
|
+
}
|
|
2454
|
+
function DialogDescription({ className = "", children }) {
|
|
2455
|
+
return /* @__PURE__ */ jsx("p", { className: `font-mondwest text-base text-content-primary/70 mt-2 ${className}`.trim(), children });
|
|
2456
|
+
}
|
|
2457
|
+
function DialogBody({ className = "", children }) {
|
|
2458
|
+
return /* @__PURE__ */ jsx("div", { className: `px-6 py-4 ${className}`.trim(), children });
|
|
2459
|
+
}
|
|
2460
|
+
function DialogFooter({ className = "", children }) {
|
|
2461
|
+
return /* @__PURE__ */ jsx("div", { className: `px-6 pb-6 pt-4 border-t border-edge-primary/20 flex justify-end gap-2 ${className}`.trim(), children });
|
|
2462
|
+
}
|
|
2463
|
+
function DialogClose({ children, asChild }) {
|
|
2464
|
+
const { setOpen } = useDialogContext();
|
|
2465
|
+
if (asChild && React14.isValidElement(children)) {
|
|
2466
|
+
return React14.cloneElement(children, {
|
|
2467
|
+
onClick: () => setOpen(false)
|
|
2468
|
+
});
|
|
2469
|
+
}
|
|
2470
|
+
return /* @__PURE__ */ jsx("button", { type: "button", onClick: () => setOpen(false), children });
|
|
2471
|
+
}
|
|
2472
|
+
|
|
2473
|
+
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, Badge, Breadcrumbs, Button, Card, CardBody, CardFooter, CardHeader, Checkbox, ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuSeparator, CountdownTimer, Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, Divider, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, HelpPanel, Input, Label, MockStatesPopover, Popover, PopoverContent, PopoverTrigger, Progress, Radio, Select, Sheet, SheetBody, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Slider, Spinner, Switch, TabContent, TabList, TabTrigger, Tabs, TextArea, ToastProvider, Tooltip, Web3ActionBar, useToast };
|
|
2474
|
+
//# sourceMappingURL=index.mjs.map
|
|
2475
|
+
//# sourceMappingURL=index.mjs.map
|