@gamecp/ui 0.1.0 → 0.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +198 -70
- package/dist/index.d.ts +198 -70
- package/dist/index.js +1349 -567
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1343 -558
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,15 +1,69 @@
|
|
|
1
|
-
import React4, { forwardRef, useState, useRef, useEffect } from 'react';
|
|
2
1
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
3
|
-
import
|
|
4
|
-
import
|
|
2
|
+
import React4, { forwardRef, useState, useRef, useEffect, useCallback } from 'react';
|
|
3
|
+
import { RiCloseLine, RiCheckLine, RiLoader4Line, RiFileCopyLine, RiEyeOffLine, RiEyeLine, RiRefreshLine, RiArrowDownSLine } from 'react-icons/ri';
|
|
5
4
|
import { createPortal } from 'react-dom';
|
|
6
5
|
import { AnimatePresence, motion } from 'framer-motion';
|
|
6
|
+
import NextLink from 'next/link';
|
|
7
7
|
|
|
8
|
-
// src/
|
|
8
|
+
// src/Badge.tsx
|
|
9
|
+
var badgeVariants = {
|
|
10
|
+
default: "bg-gray-100 text-foreground border-border",
|
|
11
|
+
primary: "bg-primary-100 text-primary-800 border-primary-200",
|
|
12
|
+
secondary: "bg-gray-100 text-foreground border-border",
|
|
13
|
+
success: "bg-success text-success-dark border-success-light",
|
|
14
|
+
warning: "bg-yellow-100 text-yellow-800 border-yellow-200",
|
|
15
|
+
error: "bg-red-100 text-red-800 border-red-200",
|
|
16
|
+
info: "bg-muted text-muted-foreground border-ring",
|
|
17
|
+
gray: "bg-gray-100 text-foreground border-border",
|
|
18
|
+
purple: "bg-purple-100 text-purple-800 border-purple-200",
|
|
19
|
+
pink: "bg-pink-100 text-pink-800 border-pink-200",
|
|
20
|
+
indigo: "bg-indigo-100 text-indigo-800 border-indigo-200",
|
|
21
|
+
yellow: "bg-yellow-100 text-yellow-800 border-yellow-200",
|
|
22
|
+
orange: "bg-orange-100 text-orange-800 border-orange-200",
|
|
23
|
+
teal: "bg-teal-100 text-teal-800 border-teal-200",
|
|
24
|
+
cyan: "bg-cyan-100 text-cyan-800 border-cyan-200",
|
|
25
|
+
lime: "bg-lime-100 text-lime-800 border-lime-200",
|
|
26
|
+
emerald: "bg-emerald-100 text-emerald-800 border-emerald-200",
|
|
27
|
+
rose: "bg-rose-100 text-rose-800 border-rose-200",
|
|
28
|
+
sky: "bg-sky-100 text-sky-800 border-sky-200",
|
|
29
|
+
violet: "bg-violet-100 text-violet-800 border-violet-200",
|
|
30
|
+
fuchsia: "bg-fuchsia-100 text-fuchsia-800 border-fuchsia-200",
|
|
31
|
+
amber: "bg-amber-100 text-amber-800 border-amber-200"
|
|
32
|
+
};
|
|
33
|
+
var badgeSizes = {
|
|
34
|
+
sm: "px-2 py-0.5 text-xs",
|
|
35
|
+
md: "px-2.5 py-0.5 text-xs",
|
|
36
|
+
lg: "px-3 py-1 text-sm"
|
|
37
|
+
};
|
|
38
|
+
function Badge({
|
|
39
|
+
children,
|
|
40
|
+
variant = "default",
|
|
41
|
+
size = "md",
|
|
42
|
+
className = "",
|
|
43
|
+
customColors
|
|
44
|
+
}) {
|
|
45
|
+
const baseClasses = "inline-flex items-center font-medium rounded-full border";
|
|
46
|
+
const variantClasses5 = variant === "custom" ? "" : badgeVariants[variant];
|
|
47
|
+
const sizeClasses5 = badgeSizes[size];
|
|
48
|
+
const customStyles = variant === "custom" && customColors ? {
|
|
49
|
+
backgroundColor: customColors.background,
|
|
50
|
+
color: customColors.text,
|
|
51
|
+
borderColor: customColors.border || customColors.background
|
|
52
|
+
} : {};
|
|
53
|
+
return /* @__PURE__ */ jsx(
|
|
54
|
+
"span",
|
|
55
|
+
{
|
|
56
|
+
className: `${baseClasses} ${variantClasses5} ${sizeClasses5} ${className}`,
|
|
57
|
+
style: customStyles,
|
|
58
|
+
children
|
|
59
|
+
}
|
|
60
|
+
);
|
|
61
|
+
}
|
|
9
62
|
var variantClasses = {
|
|
10
63
|
primary: "bg-primary text-primary-foreground hover:bg-primary/90 border-transparent",
|
|
11
64
|
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80 border-transparent",
|
|
12
65
|
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90 border-transparent",
|
|
66
|
+
danger: "bg-red-600 text-white hover:bg-red-700 border-transparent",
|
|
13
67
|
ghost: "bg-transparent hover:bg-muted hover:text-foreground border-transparent",
|
|
14
68
|
link: "bg-transparent text-primary underline-offset-4 hover:underline border-transparent p-0",
|
|
15
69
|
outline: "bg-transparent border-border hover:bg-muted hover:text-foreground"
|
|
@@ -88,73 +142,6 @@ var Button = forwardRef(
|
|
|
88
142
|
);
|
|
89
143
|
Button.displayName = "Button";
|
|
90
144
|
var Button_default = Button;
|
|
91
|
-
var badgeVariants = {
|
|
92
|
-
default: "bg-gray-100 text-foreground border-border",
|
|
93
|
-
primary: "bg-primary-100 text-primary-800 border-primary-200",
|
|
94
|
-
secondary: "bg-gray-100 text-foreground border-border",
|
|
95
|
-
success: "bg-success text-success-dark border-success-light",
|
|
96
|
-
warning: "bg-yellow-100 text-yellow-800 border-yellow-200",
|
|
97
|
-
error: "bg-red-100 text-red-800 border-red-200",
|
|
98
|
-
info: "bg-muted text-muted-foreground border-ring",
|
|
99
|
-
gray: "bg-gray-100 text-foreground border-border",
|
|
100
|
-
purple: "bg-purple-100 text-purple-800 border-purple-200",
|
|
101
|
-
pink: "bg-pink-100 text-pink-800 border-pink-200",
|
|
102
|
-
indigo: "bg-indigo-100 text-indigo-800 border-indigo-200",
|
|
103
|
-
yellow: "bg-yellow-100 text-yellow-800 border-yellow-200",
|
|
104
|
-
orange: "bg-orange-100 text-orange-800 border-orange-200",
|
|
105
|
-
teal: "bg-teal-100 text-teal-800 border-teal-200",
|
|
106
|
-
cyan: "bg-cyan-100 text-cyan-800 border-cyan-200",
|
|
107
|
-
lime: "bg-lime-100 text-lime-800 border-lime-200",
|
|
108
|
-
emerald: "bg-emerald-100 text-emerald-800 border-emerald-200",
|
|
109
|
-
rose: "bg-rose-100 text-rose-800 border-rose-200",
|
|
110
|
-
sky: "bg-sky-100 text-sky-800 border-sky-200",
|
|
111
|
-
violet: "bg-violet-100 text-violet-800 border-violet-200",
|
|
112
|
-
fuchsia: "bg-fuchsia-100 text-fuchsia-800 border-fuchsia-200",
|
|
113
|
-
amber: "bg-amber-100 text-amber-800 border-amber-200"
|
|
114
|
-
};
|
|
115
|
-
var badgeSizes = {
|
|
116
|
-
sm: "px-2 py-0.5 text-xs",
|
|
117
|
-
md: "px-2.5 py-0.5 text-xs",
|
|
118
|
-
lg: "px-3 py-1 text-sm"
|
|
119
|
-
};
|
|
120
|
-
function Badge({
|
|
121
|
-
children,
|
|
122
|
-
variant = "default",
|
|
123
|
-
size = "md",
|
|
124
|
-
className = "",
|
|
125
|
-
customColors
|
|
126
|
-
}) {
|
|
127
|
-
const baseClasses = "inline-flex items-center font-medium rounded-full border";
|
|
128
|
-
const variantClasses4 = variant === "custom" ? "" : badgeVariants[variant];
|
|
129
|
-
const sizeClasses4 = badgeSizes[size];
|
|
130
|
-
const customStyles = variant === "custom" && customColors ? {
|
|
131
|
-
backgroundColor: customColors.background,
|
|
132
|
-
color: customColors.text,
|
|
133
|
-
borderColor: customColors.border || customColors.background
|
|
134
|
-
} : {};
|
|
135
|
-
return /* @__PURE__ */ jsx(
|
|
136
|
-
"span",
|
|
137
|
-
{
|
|
138
|
-
className: `${baseClasses} ${variantClasses4} ${sizeClasses4} ${className}`,
|
|
139
|
-
style: customStyles,
|
|
140
|
-
children
|
|
141
|
-
}
|
|
142
|
-
);
|
|
143
|
-
}
|
|
144
|
-
var SuccessBadge = (props) => /* @__PURE__ */ jsx(Badge, { ...props, variant: "success" });
|
|
145
|
-
var WarningBadge = (props) => /* @__PURE__ */ jsx(Badge, { ...props, variant: "warning" });
|
|
146
|
-
var ErrorBadge = (props) => /* @__PURE__ */ jsx(Badge, { ...props, variant: "error" });
|
|
147
|
-
var InfoBadge = (props) => /* @__PURE__ */ jsx(Badge, { ...props, variant: "info" });
|
|
148
|
-
var PrimaryBadge = (props) => /* @__PURE__ */ jsx(Badge, { ...props, variant: "primary" });
|
|
149
|
-
var GrayBadge = (props) => /* @__PURE__ */ jsx(Badge, { ...props, variant: "gray" });
|
|
150
|
-
function StatusBadge({
|
|
151
|
-
isActive,
|
|
152
|
-
activeText = "Active",
|
|
153
|
-
inactiveText = "Inactive",
|
|
154
|
-
...props
|
|
155
|
-
}) {
|
|
156
|
-
return /* @__PURE__ */ jsx(Badge, { ...props, variant: isActive ? "success" : "error", children: isActive ? activeText : inactiveText });
|
|
157
|
-
}
|
|
158
145
|
var sizeClasses2 = {
|
|
159
146
|
xs: "w-3 h-3",
|
|
160
147
|
sm: "w-4 h-4",
|
|
@@ -260,7 +247,8 @@ function Card({
|
|
|
260
247
|
contentClassName = "",
|
|
261
248
|
status,
|
|
262
249
|
statusIcon,
|
|
263
|
-
statusText
|
|
250
|
+
statusText,
|
|
251
|
+
id
|
|
264
252
|
}) {
|
|
265
253
|
const [isExpanded, setIsExpanded] = useState(defaultExpanded);
|
|
266
254
|
const baseClasses = [
|
|
@@ -290,6 +278,7 @@ function Card({
|
|
|
290
278
|
return /* @__PURE__ */ jsxs(
|
|
291
279
|
"div",
|
|
292
280
|
{
|
|
281
|
+
id,
|
|
293
282
|
className: `${baseClasses} ${className}`,
|
|
294
283
|
style,
|
|
295
284
|
onClick: clickable || onClick ? handleClick : void 0,
|
|
@@ -343,133 +332,1033 @@ function Card({
|
|
|
343
332
|
}
|
|
344
333
|
);
|
|
345
334
|
}
|
|
346
|
-
|
|
335
|
+
var sizeClasses3 = {
|
|
336
|
+
sm: "max-w-md",
|
|
337
|
+
md: "max-w-2xl",
|
|
338
|
+
lg: "max-w-4xl",
|
|
339
|
+
xl: "max-w-6xl",
|
|
340
|
+
full: "max-w-full mx-4"
|
|
341
|
+
};
|
|
342
|
+
function Modal({
|
|
343
|
+
isOpen,
|
|
344
|
+
onClose,
|
|
347
345
|
children,
|
|
348
|
-
className = "",
|
|
349
|
-
...props
|
|
350
|
-
}) {
|
|
351
|
-
return /* @__PURE__ */ jsx(Card, { className, ...props, children });
|
|
352
|
-
}
|
|
353
|
-
function HeaderCard({
|
|
354
346
|
title,
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
iconColor,
|
|
359
|
-
iconSize,
|
|
360
|
-
actionButton,
|
|
361
|
-
children,
|
|
347
|
+
header,
|
|
348
|
+
blocking = false,
|
|
349
|
+
size = "md",
|
|
362
350
|
className = "",
|
|
363
|
-
|
|
351
|
+
footer,
|
|
352
|
+
fullScreen = false,
|
|
353
|
+
noPadding = false,
|
|
354
|
+
footerBg = "gray",
|
|
355
|
+
variant = "default",
|
|
356
|
+
scrollable = true,
|
|
357
|
+
"aria-describedby": ariaDescribedBy,
|
|
358
|
+
customStyles = {}
|
|
364
359
|
}) {
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
360
|
+
const modalContentRef = useRef(null);
|
|
361
|
+
const previousActiveElementRef = useRef(null);
|
|
362
|
+
const hasPerformedInitialFocusRef = useRef(false);
|
|
363
|
+
const getFocusableElements = () => {
|
|
364
|
+
if (!modalContentRef.current) return [];
|
|
365
|
+
const focusableSelectors = [
|
|
366
|
+
"button:not([disabled])",
|
|
367
|
+
"a[href]",
|
|
368
|
+
"input:not([disabled])",
|
|
369
|
+
"select:not([disabled])",
|
|
370
|
+
"textarea:not([disabled])",
|
|
371
|
+
'[tabindex]:not([tabindex="-1"])'
|
|
372
|
+
].join(", ");
|
|
373
|
+
return Array.from(
|
|
374
|
+
modalContentRef.current.querySelectorAll(focusableSelectors)
|
|
375
|
+
);
|
|
376
|
+
};
|
|
377
|
+
useEffect(() => {
|
|
378
|
+
if (!isOpen) {
|
|
379
|
+
hasPerformedInitialFocusRef.current = false;
|
|
380
|
+
return;
|
|
378
381
|
}
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
function StatusCard({
|
|
382
|
-
status,
|
|
383
|
-
statusIcon,
|
|
384
|
-
statusText,
|
|
385
|
-
children,
|
|
386
|
-
className = "",
|
|
387
|
-
...props
|
|
388
|
-
}) {
|
|
389
|
-
return /* @__PURE__ */ jsx(
|
|
390
|
-
Card,
|
|
391
|
-
{
|
|
392
|
-
status,
|
|
393
|
-
statusIcon,
|
|
394
|
-
statusText,
|
|
395
|
-
className,
|
|
396
|
-
...props,
|
|
397
|
-
children
|
|
382
|
+
if (!hasPerformedInitialFocusRef.current) {
|
|
383
|
+
previousActiveElementRef.current = document.activeElement;
|
|
398
384
|
}
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
default: "text-foreground hover:text-primary",
|
|
419
|
-
primary: "text-primary hover:text-primary/80",
|
|
420
|
-
muted: "text-muted-foreground hover:text-foreground"
|
|
421
|
-
};
|
|
422
|
-
var Link = forwardRef(
|
|
423
|
-
({
|
|
424
|
-
href,
|
|
425
|
-
variant = "default",
|
|
426
|
-
underline = false,
|
|
427
|
-
external = false,
|
|
428
|
-
className = "",
|
|
429
|
-
children,
|
|
430
|
-
...props
|
|
431
|
-
}, ref) => {
|
|
432
|
-
const classes = [
|
|
433
|
-
"transition-colors",
|
|
434
|
-
variantClasses3[variant],
|
|
435
|
-
underline ? "underline underline-offset-4" : "hover:underline hover:underline-offset-4",
|
|
436
|
-
className
|
|
437
|
-
].filter(Boolean).join(" ");
|
|
438
|
-
if (external || href.startsWith("http")) {
|
|
439
|
-
return /* @__PURE__ */ jsx(
|
|
440
|
-
"a",
|
|
441
|
-
{
|
|
442
|
-
ref,
|
|
443
|
-
href,
|
|
444
|
-
className: classes,
|
|
445
|
-
target: "_blank",
|
|
446
|
-
rel: "noopener noreferrer",
|
|
447
|
-
...props,
|
|
448
|
-
children
|
|
385
|
+
let timeoutId = null;
|
|
386
|
+
if (!hasPerformedInitialFocusRef.current) {
|
|
387
|
+
const focusableElements = getFocusableElements();
|
|
388
|
+
const firstFocusable = focusableElements[0];
|
|
389
|
+
timeoutId = setTimeout(() => {
|
|
390
|
+
const activeElement = document.activeElement;
|
|
391
|
+
const isHTMLElement = activeElement instanceof HTMLElement;
|
|
392
|
+
const isUserTyping = activeElement && (activeElement.tagName === "INPUT" || activeElement.tagName === "TEXTAREA" || isHTMLElement && activeElement.isContentEditable);
|
|
393
|
+
const isFocusInModal = modalContentRef.current?.contains(activeElement);
|
|
394
|
+
if (!isUserTyping && !isFocusInModal) {
|
|
395
|
+
if (firstFocusable) {
|
|
396
|
+
firstFocusable.focus();
|
|
397
|
+
hasPerformedInitialFocusRef.current = true;
|
|
398
|
+
} else if (modalContentRef.current) {
|
|
399
|
+
modalContentRef.current.focus();
|
|
400
|
+
hasPerformedInitialFocusRef.current = true;
|
|
401
|
+
}
|
|
402
|
+
} else if (isFocusInModal) {
|
|
403
|
+
hasPerformedInitialFocusRef.current = true;
|
|
449
404
|
}
|
|
450
|
-
);
|
|
405
|
+
}, 100);
|
|
451
406
|
}
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
);
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
407
|
+
const handleTab = (event) => {
|
|
408
|
+
if (event.key !== "Tab") return;
|
|
409
|
+
const focusableElements = getFocusableElements();
|
|
410
|
+
if (focusableElements.length === 0) return;
|
|
411
|
+
const firstElement = focusableElements[0];
|
|
412
|
+
const lastElement = focusableElements[focusableElements.length - 1];
|
|
413
|
+
if (event.shiftKey) {
|
|
414
|
+
if (document.activeElement === firstElement) {
|
|
415
|
+
event.preventDefault();
|
|
416
|
+
lastElement.focus();
|
|
417
|
+
}
|
|
418
|
+
} else {
|
|
419
|
+
if (document.activeElement === lastElement) {
|
|
420
|
+
event.preventDefault();
|
|
421
|
+
firstElement.focus();
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
};
|
|
425
|
+
const handleEsc = (event) => {
|
|
426
|
+
if (event.key === "Escape" && !blocking) {
|
|
427
|
+
onClose();
|
|
428
|
+
}
|
|
429
|
+
};
|
|
430
|
+
document.addEventListener("keydown", handleTab);
|
|
431
|
+
document.addEventListener("keydown", handleEsc);
|
|
432
|
+
document.body.style.overflow = "hidden";
|
|
433
|
+
return () => {
|
|
434
|
+
if (timeoutId) {
|
|
435
|
+
clearTimeout(timeoutId);
|
|
436
|
+
}
|
|
437
|
+
document.removeEventListener("keydown", handleTab);
|
|
438
|
+
document.removeEventListener("keydown", handleEsc);
|
|
439
|
+
document.body.style.overflow = "unset";
|
|
440
|
+
if (!isOpen && previousActiveElementRef.current) {
|
|
441
|
+
previousActiveElementRef.current.focus();
|
|
442
|
+
}
|
|
443
|
+
};
|
|
444
|
+
}, [isOpen, onClose, blocking]);
|
|
445
|
+
const modalRoot = (() => {
|
|
446
|
+
if (typeof document === "undefined") return null;
|
|
447
|
+
let root = document.getElementById("modal-root");
|
|
448
|
+
if (!root) {
|
|
449
|
+
root = document.createElement("div");
|
|
450
|
+
root.id = "modal-root";
|
|
451
|
+
document.body.appendChild(root);
|
|
452
|
+
}
|
|
453
|
+
return root;
|
|
454
|
+
})();
|
|
455
|
+
if (!modalRoot) {
|
|
456
|
+
return null;
|
|
457
|
+
}
|
|
458
|
+
const backdropVariants = {
|
|
459
|
+
hidden: { opacity: 0 },
|
|
460
|
+
visible: { opacity: 1 }
|
|
461
|
+
};
|
|
462
|
+
const modalVariants = {
|
|
463
|
+
hidden: {
|
|
464
|
+
opacity: 0,
|
|
465
|
+
scale: 0.95,
|
|
466
|
+
y: 20
|
|
467
|
+
},
|
|
468
|
+
visible: {
|
|
469
|
+
opacity: 1,
|
|
470
|
+
scale: 1,
|
|
471
|
+
y: 0,
|
|
472
|
+
transition: {
|
|
473
|
+
duration: 0.2,
|
|
474
|
+
ease: "easeOut"
|
|
475
|
+
}
|
|
476
|
+
},
|
|
477
|
+
exit: {
|
|
478
|
+
opacity: 0,
|
|
479
|
+
scale: 0.9,
|
|
480
|
+
y: 100,
|
|
481
|
+
// Slide down much further for reverse effect
|
|
482
|
+
transition: {
|
|
483
|
+
duration: 0.3,
|
|
484
|
+
ease: "easeIn"
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
};
|
|
488
|
+
if (!isOpen) return null;
|
|
489
|
+
if (variant === "plain") {
|
|
490
|
+
return createPortal(
|
|
491
|
+
/* @__PURE__ */ jsx(AnimatePresence, { children: /* @__PURE__ */ jsx(
|
|
492
|
+
motion.div,
|
|
493
|
+
{
|
|
494
|
+
className: `modal-backdrop fixed inset-0 w-screen h-screen flex items-center ${customStyles.backdrop?.includes("justify-") ? customStyles.backdrop : customStyles.backdrop ? `${customStyles.backdrop} justify-center` : "justify-center bg-black/10"} z-[999999] m-0 ${fullScreen ? "p-0" : "p-4"}`,
|
|
495
|
+
variants: backdropVariants,
|
|
496
|
+
initial: "hidden",
|
|
497
|
+
animate: isOpen ? "visible" : "hidden",
|
|
498
|
+
exit: "hidden",
|
|
499
|
+
onClick: blocking ? void 0 : onClose,
|
|
500
|
+
children: /* @__PURE__ */ jsx(
|
|
501
|
+
motion.div,
|
|
502
|
+
{
|
|
503
|
+
ref: modalContentRef,
|
|
504
|
+
role: "dialog",
|
|
505
|
+
"aria-modal": "true",
|
|
506
|
+
"aria-labelledby": title ? "modal-title-plain" : void 0,
|
|
507
|
+
"aria-describedby": ariaDescribedBy || "modal-content-plain",
|
|
508
|
+
tabIndex: -1,
|
|
509
|
+
className: `w-full flex flex-col overflow-hidden relative z-[1000000] ${customStyles.container || "bg-card shadow-xl"} ${fullScreen ? "h-full rounded-none" : `rounded-lg ${className} ${sizeClasses3[size]} max-h-[90vh]`}`,
|
|
510
|
+
variants: modalVariants,
|
|
511
|
+
initial: "hidden",
|
|
512
|
+
animate: isOpen ? "visible" : "exit",
|
|
513
|
+
exit: "exit",
|
|
514
|
+
onClick: (e) => e.stopPropagation(),
|
|
515
|
+
children: /* @__PURE__ */ jsx(
|
|
516
|
+
"div",
|
|
517
|
+
{
|
|
518
|
+
id: "modal-content-plain",
|
|
519
|
+
className: `flex-1 ${customStyles.content || ""}`,
|
|
520
|
+
children
|
|
521
|
+
}
|
|
522
|
+
)
|
|
523
|
+
},
|
|
524
|
+
"modal-content"
|
|
525
|
+
)
|
|
526
|
+
},
|
|
527
|
+
"modal-backdrop"
|
|
528
|
+
) }),
|
|
529
|
+
modalRoot
|
|
530
|
+
);
|
|
531
|
+
}
|
|
532
|
+
return createPortal(
|
|
533
|
+
/* @__PURE__ */ jsx(AnimatePresence, { children: /* @__PURE__ */ jsx(
|
|
534
|
+
motion.div,
|
|
535
|
+
{
|
|
536
|
+
className: `modal-backdrop fixed inset-0 w-screen h-screen bg-black/10 flex items-center ${customStyles.backdrop || "justify-center"} z-[999999] m-0 ${fullScreen ? "p-0" : "p-4"}`,
|
|
537
|
+
variants: backdropVariants,
|
|
538
|
+
initial: "hidden",
|
|
539
|
+
animate: isOpen ? "visible" : "hidden",
|
|
540
|
+
exit: "hidden",
|
|
541
|
+
onClick: blocking ? void 0 : onClose,
|
|
542
|
+
children: /* @__PURE__ */ jsxs(
|
|
543
|
+
motion.div,
|
|
544
|
+
{
|
|
545
|
+
ref: modalContentRef,
|
|
546
|
+
role: "dialog",
|
|
547
|
+
"aria-modal": "true",
|
|
548
|
+
"aria-labelledby": title ? "modal-title" : void 0,
|
|
549
|
+
"aria-describedby": ariaDescribedBy || "modal-content",
|
|
550
|
+
tabIndex: -1,
|
|
551
|
+
className: `bg-card border border-border shadow-xl w-full flex flex-col overflow-hidden relative z-[1000000] ${fullScreen ? "h-full rounded-none" : `rounded-lg ${customStyles.container || className || sizeClasses3[size]} max-h-[90vh]`}`,
|
|
552
|
+
variants: modalVariants,
|
|
553
|
+
initial: "hidden",
|
|
554
|
+
animate: isOpen ? "visible" : "exit",
|
|
555
|
+
exit: "exit",
|
|
556
|
+
onClick: (e) => e.stopPropagation(),
|
|
557
|
+
children: [
|
|
558
|
+
header ? /* @__PURE__ */ jsx("div", { className: "flex-shrink-0", children: header }) : title ? /* @__PURE__ */ jsxs(
|
|
559
|
+
"div",
|
|
560
|
+
{
|
|
561
|
+
className: `px-6 py-4 border-b border-border flex justify-between items-center flex-shrink-0 ${customStyles.header || ""}`,
|
|
562
|
+
children: [
|
|
563
|
+
/* @__PURE__ */ jsx(
|
|
564
|
+
"h2",
|
|
565
|
+
{
|
|
566
|
+
id: "modal-title",
|
|
567
|
+
className: "text-xl font-semibold text-foreground",
|
|
568
|
+
children: title
|
|
569
|
+
}
|
|
570
|
+
),
|
|
571
|
+
/* @__PURE__ */ jsx(
|
|
572
|
+
"button",
|
|
573
|
+
{
|
|
574
|
+
onClick: onClose,
|
|
575
|
+
className: "p-2 text-muted-foreground hover:text-foreground hover:bg-muted rounded-full transition-colors",
|
|
576
|
+
title: "Close",
|
|
577
|
+
"aria-label": "Close modal",
|
|
578
|
+
disabled: blocking,
|
|
579
|
+
children: /* @__PURE__ */ jsx(RiCloseLine, { className: "w-5 h-5", "aria-hidden": "true" })
|
|
580
|
+
}
|
|
581
|
+
)
|
|
582
|
+
]
|
|
583
|
+
}
|
|
584
|
+
) : null,
|
|
585
|
+
/* @__PURE__ */ jsx(
|
|
586
|
+
"div",
|
|
587
|
+
{
|
|
588
|
+
id: "modal-content",
|
|
589
|
+
className: `bg-background text-foreground flex-1 ${scrollable ? "overflow-y-auto" : ""} ${fullScreen || noPadding ? "p-0" : "px-6 py-4"}`,
|
|
590
|
+
children
|
|
591
|
+
}
|
|
592
|
+
),
|
|
593
|
+
footer && /* @__PURE__ */ jsx(
|
|
594
|
+
"div",
|
|
595
|
+
{
|
|
596
|
+
className: `flex-shrink-0 px-6 py-4 border-t border-border ${footerBg === "white" ? "bg-card" : "bg-muted"} ${customStyles.footer || ""}`,
|
|
597
|
+
children: footer
|
|
598
|
+
}
|
|
599
|
+
)
|
|
600
|
+
]
|
|
601
|
+
},
|
|
602
|
+
"modal-content"
|
|
603
|
+
)
|
|
604
|
+
},
|
|
605
|
+
"modal-backdrop"
|
|
606
|
+
) }),
|
|
607
|
+
modalRoot
|
|
608
|
+
);
|
|
609
|
+
}
|
|
610
|
+
function ConfirmDialog({ isOpen, options, onConfirm, onCancel }) {
|
|
611
|
+
const { title, message, confirmText, cancelText = "Cancel", confirmButtonColor = "blue" } = options;
|
|
612
|
+
const getConfirmVariant = () => {
|
|
613
|
+
switch (confirmButtonColor) {
|
|
614
|
+
case "red":
|
|
615
|
+
return "danger";
|
|
616
|
+
case "green":
|
|
617
|
+
return "primary";
|
|
618
|
+
case "blue":
|
|
619
|
+
default:
|
|
620
|
+
return "primary";
|
|
621
|
+
}
|
|
622
|
+
};
|
|
623
|
+
return /* @__PURE__ */ jsx(Modal, { isOpen, onClose: onCancel, title, children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
624
|
+
/* @__PURE__ */ jsx("p", { className: "text-foreground", children: message }),
|
|
625
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-3 justify-end", children: [
|
|
626
|
+
/* @__PURE__ */ jsx(Button_default, { variant: "secondary", onClick: onCancel, children: cancelText }),
|
|
627
|
+
/* @__PURE__ */ jsx(Button_default, { variant: getConfirmVariant(), onClick: onConfirm, children: confirmText })
|
|
628
|
+
] })
|
|
629
|
+
] }) });
|
|
630
|
+
}
|
|
631
|
+
function useConfirmDialog() {
|
|
632
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
633
|
+
const [options, setOptions] = useState({
|
|
634
|
+
title: "",
|
|
635
|
+
message: "",
|
|
636
|
+
confirmText: "Confirm"
|
|
637
|
+
});
|
|
638
|
+
const [resolver, setResolver] = useState(null);
|
|
639
|
+
const confirm = (opts) => {
|
|
640
|
+
setOptions(opts);
|
|
641
|
+
setIsOpen(true);
|
|
642
|
+
return new Promise((resolve) => {
|
|
643
|
+
setResolver(() => resolve);
|
|
644
|
+
});
|
|
645
|
+
};
|
|
646
|
+
const handleConfirm = () => {
|
|
647
|
+
setIsOpen(false);
|
|
648
|
+
if (resolver) {
|
|
649
|
+
resolver(true);
|
|
650
|
+
setResolver(null);
|
|
651
|
+
}
|
|
652
|
+
};
|
|
653
|
+
const handleCancel = () => {
|
|
654
|
+
setIsOpen(false);
|
|
655
|
+
if (resolver) {
|
|
656
|
+
resolver(false);
|
|
657
|
+
setResolver(null);
|
|
658
|
+
}
|
|
659
|
+
};
|
|
660
|
+
const dialog = /* @__PURE__ */ jsx(
|
|
661
|
+
ConfirmDialog,
|
|
662
|
+
{
|
|
663
|
+
isOpen,
|
|
664
|
+
options,
|
|
665
|
+
onConfirm: handleConfirm,
|
|
666
|
+
onCancel: handleCancel
|
|
667
|
+
}
|
|
668
|
+
);
|
|
669
|
+
return { confirm, dialog };
|
|
670
|
+
}
|
|
671
|
+
var ConfirmDialog_default = ConfirmDialog;
|
|
672
|
+
var paddingClasses2 = {
|
|
673
|
+
none: "",
|
|
674
|
+
sm: "p-4",
|
|
675
|
+
md: "p-6",
|
|
676
|
+
lg: "p-8"
|
|
677
|
+
};
|
|
678
|
+
function Container({
|
|
679
|
+
children,
|
|
680
|
+
className = "",
|
|
681
|
+
padding = "md",
|
|
682
|
+
id
|
|
683
|
+
}) {
|
|
684
|
+
return /* @__PURE__ */ jsx("div", { id, className: `${paddingClasses2[padding]} ${className}`, children });
|
|
685
|
+
}
|
|
686
|
+
var EmptyState = ({
|
|
687
|
+
icon: Icon,
|
|
688
|
+
title,
|
|
689
|
+
subtitle,
|
|
690
|
+
action,
|
|
691
|
+
className = ""
|
|
692
|
+
}) => {
|
|
693
|
+
return /* @__PURE__ */ jsxs(
|
|
694
|
+
"div",
|
|
695
|
+
{
|
|
696
|
+
className: `text-center py-12 text-secondary-foreground p-6 lg:p-12 ${className}`,
|
|
697
|
+
role: "status",
|
|
698
|
+
"aria-live": "polite",
|
|
699
|
+
children: [
|
|
700
|
+
/* @__PURE__ */ jsx(
|
|
701
|
+
Icon,
|
|
702
|
+
{
|
|
703
|
+
className: "w-12 h-12 mx-auto mb-3 text-muted-foreground",
|
|
704
|
+
"aria-hidden": "true"
|
|
705
|
+
}
|
|
706
|
+
),
|
|
707
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium mb-1", children: title }),
|
|
708
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mb-4", children: subtitle }),
|
|
709
|
+
action && /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: action })
|
|
710
|
+
]
|
|
711
|
+
}
|
|
712
|
+
);
|
|
713
|
+
};
|
|
714
|
+
var EmptyState_default = EmptyState;
|
|
715
|
+
function useKeyboardNavigation({
|
|
716
|
+
isOpen,
|
|
717
|
+
optionsLength,
|
|
718
|
+
onSelect,
|
|
719
|
+
onClose,
|
|
720
|
+
onOpen
|
|
721
|
+
}) {
|
|
722
|
+
const [focusedIndex, setFocusedIndex] = useState(-1);
|
|
723
|
+
const resetFocus = useCallback(() => {
|
|
724
|
+
setFocusedIndex(-1);
|
|
725
|
+
}, []);
|
|
726
|
+
const handleKeyDown = useCallback(
|
|
727
|
+
(e) => {
|
|
728
|
+
if (!isOpen) {
|
|
729
|
+
if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") {
|
|
730
|
+
e.preventDefault();
|
|
731
|
+
onOpen?.();
|
|
732
|
+
}
|
|
733
|
+
return;
|
|
734
|
+
}
|
|
735
|
+
switch (e.key) {
|
|
736
|
+
case "ArrowDown":
|
|
737
|
+
e.preventDefault();
|
|
738
|
+
setFocusedIndex((prev) => prev < optionsLength - 1 ? prev + 1 : 0);
|
|
739
|
+
break;
|
|
740
|
+
case "ArrowUp":
|
|
741
|
+
e.preventDefault();
|
|
742
|
+
setFocusedIndex((prev) => prev > 0 ? prev - 1 : optionsLength - 1);
|
|
743
|
+
break;
|
|
744
|
+
case "Enter":
|
|
745
|
+
e.preventDefault();
|
|
746
|
+
if (focusedIndex >= 0 && focusedIndex < optionsLength) {
|
|
747
|
+
onSelect(focusedIndex);
|
|
748
|
+
}
|
|
749
|
+
break;
|
|
750
|
+
case "Escape":
|
|
751
|
+
e.preventDefault();
|
|
752
|
+
onClose();
|
|
753
|
+
resetFocus();
|
|
754
|
+
break;
|
|
755
|
+
case "Tab":
|
|
756
|
+
onClose();
|
|
757
|
+
resetFocus();
|
|
758
|
+
break;
|
|
759
|
+
}
|
|
760
|
+
},
|
|
761
|
+
[isOpen, optionsLength, focusedIndex, onSelect, onClose, onOpen, resetFocus]
|
|
762
|
+
);
|
|
763
|
+
return {
|
|
764
|
+
focusedIndex,
|
|
765
|
+
handleKeyDown,
|
|
766
|
+
resetFocus,
|
|
767
|
+
setFocusedIndex
|
|
768
|
+
};
|
|
769
|
+
}
|
|
770
|
+
function SmartDropdown({
|
|
771
|
+
isOpen,
|
|
772
|
+
onClose,
|
|
773
|
+
trigger,
|
|
774
|
+
children,
|
|
775
|
+
className = "",
|
|
776
|
+
width = 384,
|
|
777
|
+
maxHeight = 450,
|
|
778
|
+
offset = 8,
|
|
779
|
+
margin = 16,
|
|
780
|
+
id = "dropdown-listbox",
|
|
781
|
+
position = "auto"
|
|
782
|
+
}) {
|
|
783
|
+
const [dropdownPosition, setDropdownPosition] = useState({
|
|
784
|
+
top: 0,
|
|
785
|
+
left: 0,
|
|
786
|
+
right: void 0,
|
|
787
|
+
width: 0,
|
|
788
|
+
maxHeight: 0,
|
|
789
|
+
isAbove: false
|
|
790
|
+
});
|
|
791
|
+
const dropdownRef = useRef(null);
|
|
792
|
+
const triggerRef = useRef(null);
|
|
793
|
+
const calculateDropdownPosition = useCallback(() => {
|
|
794
|
+
if (!triggerRef.current) return;
|
|
795
|
+
const triggerRect = triggerRef.current.getBoundingClientRect();
|
|
796
|
+
const viewportWidth = window.innerWidth;
|
|
797
|
+
const viewportHeight = window.innerHeight;
|
|
798
|
+
const spaceAbove = triggerRect.top - margin;
|
|
799
|
+
const spaceBelow = viewportHeight - triggerRect.bottom - margin;
|
|
800
|
+
let calculatedWidth;
|
|
801
|
+
if (width === "fit-content") {
|
|
802
|
+
calculatedWidth = triggerRect.width;
|
|
803
|
+
} else if (width === "auto") {
|
|
804
|
+
calculatedWidth = triggerRect.width;
|
|
805
|
+
} else if (typeof width === "number") {
|
|
806
|
+
calculatedWidth = Math.min(width, viewportWidth - margin * 2);
|
|
807
|
+
} else {
|
|
808
|
+
calculatedWidth = triggerRect.width;
|
|
809
|
+
}
|
|
810
|
+
const calculatedMaxHeight = Math.min(
|
|
811
|
+
maxHeight,
|
|
812
|
+
Math.max(spaceAbove, spaceBelow)
|
|
813
|
+
);
|
|
814
|
+
let left = triggerRect.left;
|
|
815
|
+
let right = void 0;
|
|
816
|
+
if (position === "top-right" || position === "bottom-right") {
|
|
817
|
+
left = triggerRect.right - calculatedWidth;
|
|
818
|
+
} else if (position === "top-left" || position === "bottom-left") {
|
|
819
|
+
left = triggerRect.left;
|
|
820
|
+
} else if (position === "top-left-aligned" || position === "bottom-left-aligned") {
|
|
821
|
+
const availableLeftSpace = triggerRect.left - margin;
|
|
822
|
+
const dynamicOffset = Math.max(20, availableLeftSpace * 0.2);
|
|
823
|
+
right = viewportWidth - triggerRect.left + dynamicOffset;
|
|
824
|
+
left = 0;
|
|
825
|
+
calculatedWidth = Math.min(
|
|
826
|
+
calculatedWidth,
|
|
827
|
+
triggerRect.left - dynamicOffset - margin
|
|
828
|
+
);
|
|
829
|
+
} else {
|
|
830
|
+
if (left + calculatedWidth > viewportWidth - margin) {
|
|
831
|
+
left = triggerRect.right - calculatedWidth;
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
if (left !== void 0 && left < margin) {
|
|
835
|
+
left = margin;
|
|
836
|
+
}
|
|
837
|
+
let top = triggerRect.bottom + offset;
|
|
838
|
+
let finalMaxHeight = calculatedMaxHeight;
|
|
839
|
+
let isAbove = false;
|
|
840
|
+
if (spaceAbove > spaceBelow && top + calculatedMaxHeight > viewportHeight - margin) {
|
|
841
|
+
isAbove = true;
|
|
842
|
+
top = triggerRect.top - calculatedMaxHeight - offset;
|
|
843
|
+
finalMaxHeight = Math.min(calculatedMaxHeight, spaceAbove);
|
|
844
|
+
if (top < margin) {
|
|
845
|
+
top = margin;
|
|
846
|
+
finalMaxHeight = triggerRect.top - margin - offset;
|
|
847
|
+
}
|
|
848
|
+
} else {
|
|
849
|
+
finalMaxHeight = Math.min(calculatedMaxHeight, spaceBelow);
|
|
850
|
+
if (top + finalMaxHeight > viewportHeight - margin) {
|
|
851
|
+
top = viewportHeight - margin - finalMaxHeight;
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
if (position === "top-right") {
|
|
855
|
+
left = triggerRect.right - calculatedWidth;
|
|
856
|
+
top = triggerRect.top - offset;
|
|
857
|
+
isAbove = true;
|
|
858
|
+
finalMaxHeight = Math.min(maxHeight, spaceAbove);
|
|
859
|
+
} else if (position === "top-left") {
|
|
860
|
+
left = triggerRect.left;
|
|
861
|
+
top = triggerRect.top - offset;
|
|
862
|
+
isAbove = true;
|
|
863
|
+
finalMaxHeight = Math.min(maxHeight, spaceAbove);
|
|
864
|
+
} else if (position === "bottom-right") {
|
|
865
|
+
left = triggerRect.right - calculatedWidth;
|
|
866
|
+
top = triggerRect.bottom + offset;
|
|
867
|
+
isAbove = false;
|
|
868
|
+
finalMaxHeight = Math.min(maxHeight, spaceBelow);
|
|
869
|
+
} else if (position === "bottom-left") {
|
|
870
|
+
left = triggerRect.left;
|
|
871
|
+
top = triggerRect.bottom + offset;
|
|
872
|
+
isAbove = false;
|
|
873
|
+
finalMaxHeight = Math.min(maxHeight, spaceBelow);
|
|
874
|
+
} else if (position === "top-left-aligned") {
|
|
875
|
+
right = viewportWidth - triggerRect.right;
|
|
876
|
+
left = 0;
|
|
877
|
+
top = triggerRect.top - offset;
|
|
878
|
+
isAbove = true;
|
|
879
|
+
finalMaxHeight = Math.min(maxHeight, spaceAbove);
|
|
880
|
+
} else if (position === "bottom-left-aligned") {
|
|
881
|
+
right = viewportWidth - triggerRect.right;
|
|
882
|
+
left = 0;
|
|
883
|
+
top = triggerRect.bottom + offset;
|
|
884
|
+
isAbove = false;
|
|
885
|
+
finalMaxHeight = Math.min(maxHeight, spaceBelow);
|
|
886
|
+
}
|
|
887
|
+
setDropdownPosition({
|
|
888
|
+
top,
|
|
889
|
+
left,
|
|
890
|
+
right,
|
|
891
|
+
width: calculatedWidth,
|
|
892
|
+
maxHeight: finalMaxHeight,
|
|
893
|
+
isAbove
|
|
894
|
+
});
|
|
895
|
+
}, [width, maxHeight, margin, offset, position]);
|
|
896
|
+
useEffect(() => {
|
|
897
|
+
const handleClickOutside = (event) => {
|
|
898
|
+
const target = event.target;
|
|
899
|
+
const isInsideDropdown = dropdownRef.current?.contains(target);
|
|
900
|
+
const isInsideTrigger = triggerRef.current?.contains(target);
|
|
901
|
+
if (!isInsideDropdown && !isInsideTrigger) {
|
|
902
|
+
onClose();
|
|
903
|
+
}
|
|
904
|
+
};
|
|
905
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
906
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
907
|
+
}, [onClose]);
|
|
908
|
+
useEffect(() => {
|
|
909
|
+
if (isOpen) {
|
|
910
|
+
calculateDropdownPosition();
|
|
911
|
+
}
|
|
912
|
+
}, [isOpen, calculateDropdownPosition]);
|
|
913
|
+
useEffect(() => {
|
|
914
|
+
if (!isOpen) return;
|
|
915
|
+
const handleResize = () => {
|
|
916
|
+
calculateDropdownPosition();
|
|
917
|
+
};
|
|
918
|
+
const handleScroll = () => {
|
|
919
|
+
calculateDropdownPosition();
|
|
920
|
+
};
|
|
921
|
+
window.addEventListener("resize", handleResize);
|
|
922
|
+
window.addEventListener("scroll", handleScroll, true);
|
|
923
|
+
return () => {
|
|
924
|
+
window.removeEventListener("resize", handleResize);
|
|
925
|
+
window.removeEventListener("scroll", handleScroll, true);
|
|
926
|
+
};
|
|
927
|
+
}, [isOpen, calculateDropdownPosition]);
|
|
928
|
+
useEffect(() => {
|
|
929
|
+
if (!isOpen || !dropdownRef.current || !triggerRef.current) return;
|
|
930
|
+
if (dropdownPosition.isAbove) {
|
|
931
|
+
const adjustPosition = () => {
|
|
932
|
+
const dropdownRect = dropdownRef.current?.getBoundingClientRect();
|
|
933
|
+
const triggerRect = triggerRef.current?.getBoundingClientRect();
|
|
934
|
+
if (!dropdownRect || !triggerRect) return;
|
|
935
|
+
const actualHeight = dropdownRect.height;
|
|
936
|
+
const newTop = triggerRect.top - actualHeight - offset;
|
|
937
|
+
if (newTop !== dropdownPosition.top && newTop >= margin) {
|
|
938
|
+
setDropdownPosition((prev) => ({
|
|
939
|
+
...prev,
|
|
940
|
+
top: newTop
|
|
941
|
+
}));
|
|
942
|
+
}
|
|
943
|
+
};
|
|
944
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
945
|
+
setTimeout(adjustPosition, 0);
|
|
946
|
+
});
|
|
947
|
+
resizeObserver.observe(dropdownRef.current);
|
|
948
|
+
adjustPosition();
|
|
949
|
+
return () => {
|
|
950
|
+
resizeObserver.disconnect();
|
|
951
|
+
};
|
|
952
|
+
}
|
|
953
|
+
}, [isOpen, dropdownPosition.isAbove, dropdownPosition.top, offset, margin]);
|
|
954
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
955
|
+
/* @__PURE__ */ jsx(
|
|
956
|
+
"div",
|
|
957
|
+
{
|
|
958
|
+
ref: triggerRef,
|
|
959
|
+
className: "w-full",
|
|
960
|
+
role: "combobox",
|
|
961
|
+
"aria-expanded": isOpen,
|
|
962
|
+
"aria-haspopup": "listbox",
|
|
963
|
+
"aria-controls": "dropdown-listbox",
|
|
964
|
+
children: trigger
|
|
965
|
+
}
|
|
966
|
+
),
|
|
967
|
+
isOpen && typeof window !== "undefined" && createPortal(
|
|
968
|
+
/* @__PURE__ */ jsx(
|
|
969
|
+
"div",
|
|
970
|
+
{
|
|
971
|
+
ref: dropdownRef,
|
|
972
|
+
id,
|
|
973
|
+
"data-smart-dropdown": true,
|
|
974
|
+
role: "listbox",
|
|
975
|
+
"aria-label": "Dropdown options",
|
|
976
|
+
className: `fixed z-[1000001] card overflow-hidden`,
|
|
977
|
+
style: {
|
|
978
|
+
top: dropdownPosition.top,
|
|
979
|
+
...dropdownPosition.left !== void 0 ? { left: dropdownPosition.left } : {},
|
|
980
|
+
...dropdownPosition.right !== void 0 ? { right: dropdownPosition.right } : {},
|
|
981
|
+
width: width === "fit-content" ? "auto" : dropdownPosition.width,
|
|
982
|
+
maxHeight: dropdownPosition.maxHeight
|
|
983
|
+
},
|
|
984
|
+
onClick: (e) => {
|
|
985
|
+
e.stopPropagation();
|
|
986
|
+
},
|
|
987
|
+
children: /* @__PURE__ */ jsx(
|
|
988
|
+
"div",
|
|
989
|
+
{
|
|
990
|
+
className: className ? className : "overflow-y-auto",
|
|
991
|
+
style: { maxHeight: dropdownPosition.maxHeight },
|
|
992
|
+
children: typeof children === "function" ? children({ isAbove: dropdownPosition.isAbove }) : children
|
|
993
|
+
}
|
|
994
|
+
)
|
|
995
|
+
}
|
|
996
|
+
),
|
|
997
|
+
document.body
|
|
998
|
+
)
|
|
999
|
+
] });
|
|
1000
|
+
}
|
|
1001
|
+
function SmartSelect({
|
|
1002
|
+
options,
|
|
1003
|
+
value,
|
|
1004
|
+
onChange,
|
|
1005
|
+
placeholder = "Select option...",
|
|
1006
|
+
className = "",
|
|
1007
|
+
description,
|
|
1008
|
+
disabled = false,
|
|
1009
|
+
multiple = false,
|
|
1010
|
+
width,
|
|
1011
|
+
searchable = false,
|
|
1012
|
+
keepOpen = false,
|
|
1013
|
+
clearable = true,
|
|
1014
|
+
// API integration props
|
|
1015
|
+
onOpen,
|
|
1016
|
+
onClose,
|
|
1017
|
+
onSearch,
|
|
1018
|
+
isLoading = false
|
|
1019
|
+
}) {
|
|
1020
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
1021
|
+
const [triggerWidth, setTriggerWidth] = useState(
|
|
1022
|
+
void 0
|
|
1023
|
+
);
|
|
1024
|
+
const [searchTerm, setSearchTerm] = useState("");
|
|
1025
|
+
const [displayValue, setDisplayValue] = useState("");
|
|
1026
|
+
const inputRef = useRef(null);
|
|
1027
|
+
const buttonRef = useRef(null);
|
|
1028
|
+
const selectedValues = multiple ? value || [] : [value];
|
|
1029
|
+
const selectedOptions = options.filter(
|
|
1030
|
+
(opt) => selectedValues.includes(opt.value)
|
|
1031
|
+
);
|
|
1032
|
+
const hasSelection = multiple ? selectedValues.length > 0 : value && value !== "";
|
|
1033
|
+
const filteredOptions = searchable && searchTerm.trim() ? options.filter(
|
|
1034
|
+
(option) => option.label.toLowerCase().includes(searchTerm.toLowerCase()) || option.value.toLowerCase().includes(searchTerm.toLowerCase()) || option.description?.toLowerCase().includes(searchTerm.toLowerCase())
|
|
1035
|
+
) : options;
|
|
1036
|
+
const { focusedIndex, handleKeyDown, resetFocus } = useKeyboardNavigation({
|
|
1037
|
+
isOpen,
|
|
1038
|
+
optionsLength: filteredOptions.length,
|
|
1039
|
+
onSelect: (index) => handleSelect(filteredOptions[index].value),
|
|
1040
|
+
onClose: () => setIsOpen(false),
|
|
1041
|
+
onOpen: () => setIsOpen(true)
|
|
1042
|
+
});
|
|
1043
|
+
useEffect(() => {
|
|
1044
|
+
if (selectedOptions.length > 0) {
|
|
1045
|
+
if (multiple) {
|
|
1046
|
+
setDisplayValue(selectedOptions.map((opt) => opt.label).join(", "));
|
|
1047
|
+
} else {
|
|
1048
|
+
setDisplayValue(selectedOptions[0].label);
|
|
1049
|
+
}
|
|
1050
|
+
} else {
|
|
1051
|
+
setDisplayValue("");
|
|
1052
|
+
}
|
|
1053
|
+
}, [selectedOptions, multiple]);
|
|
1054
|
+
const handleSelect = (optionValue) => {
|
|
1055
|
+
if (multiple) {
|
|
1056
|
+
const currentValues = value || [];
|
|
1057
|
+
const newValues = currentValues.includes(optionValue) ? currentValues.filter((v) => v !== optionValue) : [...currentValues, optionValue];
|
|
1058
|
+
onChange(newValues);
|
|
1059
|
+
} else {
|
|
1060
|
+
onChange(optionValue);
|
|
1061
|
+
setSearchTerm("");
|
|
1062
|
+
setIsOpen(false);
|
|
1063
|
+
}
|
|
1064
|
+
};
|
|
1065
|
+
const currentTriggerRef = searchable ? inputRef : buttonRef;
|
|
1066
|
+
useEffect(() => {
|
|
1067
|
+
if (currentTriggerRef.current) {
|
|
1068
|
+
const rect = currentTriggerRef.current.getBoundingClientRect();
|
|
1069
|
+
setTriggerWidth(rect.width);
|
|
1070
|
+
}
|
|
1071
|
+
}, [isOpen, currentTriggerRef]);
|
|
1072
|
+
useEffect(() => {
|
|
1073
|
+
if (!currentTriggerRef.current) return;
|
|
1074
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
1075
|
+
if (currentTriggerRef.current) {
|
|
1076
|
+
const rect = currentTriggerRef.current.getBoundingClientRect();
|
|
1077
|
+
setTriggerWidth(rect.width);
|
|
1078
|
+
}
|
|
1079
|
+
});
|
|
1080
|
+
resizeObserver.observe(currentTriggerRef.current);
|
|
1081
|
+
return () => {
|
|
1082
|
+
resizeObserver.disconnect();
|
|
1083
|
+
};
|
|
1084
|
+
}, [currentTriggerRef]);
|
|
1085
|
+
useEffect(() => {
|
|
1086
|
+
if (isOpen && searchable && inputRef.current) {
|
|
1087
|
+
setTimeout(() => {
|
|
1088
|
+
inputRef.current?.focus();
|
|
1089
|
+
}, 0);
|
|
1090
|
+
} else if (!isOpen) {
|
|
1091
|
+
setSearchTerm("");
|
|
1092
|
+
resetFocus();
|
|
1093
|
+
}
|
|
1094
|
+
}, [isOpen, searchable, resetFocus]);
|
|
1095
|
+
const handleOpen = () => {
|
|
1096
|
+
setIsOpen(true);
|
|
1097
|
+
onOpen?.();
|
|
1098
|
+
};
|
|
1099
|
+
const handleClose = () => {
|
|
1100
|
+
setIsOpen(false);
|
|
1101
|
+
onClose?.();
|
|
1102
|
+
};
|
|
1103
|
+
const handleSearchChange = (search) => {
|
|
1104
|
+
setSearchTerm(search);
|
|
1105
|
+
onSearch?.(search);
|
|
1106
|
+
};
|
|
1107
|
+
return /* @__PURE__ */ jsxs("div", { className: "w-full", "data-smart-select": true, children: [
|
|
1108
|
+
description && /* @__PURE__ */ jsx("p", { className: "form-description", children: description }),
|
|
1109
|
+
/* @__PURE__ */ jsx(
|
|
1110
|
+
SmartDropdown,
|
|
1111
|
+
{
|
|
1112
|
+
isOpen,
|
|
1113
|
+
onClose: handleClose,
|
|
1114
|
+
width: width !== void 0 ? width : triggerWidth,
|
|
1115
|
+
maxHeight: 200,
|
|
1116
|
+
trigger: searchable ? /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
1117
|
+
/* @__PURE__ */ jsx(
|
|
1118
|
+
"input",
|
|
1119
|
+
{
|
|
1120
|
+
ref: inputRef,
|
|
1121
|
+
type: "text",
|
|
1122
|
+
value: isOpen ? searchTerm : displayValue,
|
|
1123
|
+
onChange: (e) => {
|
|
1124
|
+
if (isOpen) {
|
|
1125
|
+
handleSearchChange(e.target.value);
|
|
1126
|
+
resetFocus();
|
|
1127
|
+
}
|
|
1128
|
+
},
|
|
1129
|
+
onFocus: () => !disabled && handleOpen(),
|
|
1130
|
+
onClick: (e) => {
|
|
1131
|
+
e.stopPropagation();
|
|
1132
|
+
!disabled && handleOpen();
|
|
1133
|
+
},
|
|
1134
|
+
onKeyDown: handleKeyDown,
|
|
1135
|
+
placeholder,
|
|
1136
|
+
disabled,
|
|
1137
|
+
role: "combobox",
|
|
1138
|
+
"aria-expanded": isOpen,
|
|
1139
|
+
"aria-haspopup": "listbox",
|
|
1140
|
+
"aria-controls": "dropdown-listbox",
|
|
1141
|
+
"aria-autocomplete": "list",
|
|
1142
|
+
"aria-activedescendant": focusedIndex >= 0 ? `option-${focusedIndex}` : void 0,
|
|
1143
|
+
className: `form-input truncate ${hasSelection ? "pr-12" : "pr-8"} ${disabled ? "opacity-50 cursor-not-allowed" : ""} ${className}`
|
|
1144
|
+
}
|
|
1145
|
+
),
|
|
1146
|
+
hasSelection && clearable && /* @__PURE__ */ jsx(
|
|
1147
|
+
"button",
|
|
1148
|
+
{
|
|
1149
|
+
type: "button",
|
|
1150
|
+
onClick: (e) => {
|
|
1151
|
+
e.stopPropagation();
|
|
1152
|
+
onChange(multiple ? [] : "");
|
|
1153
|
+
},
|
|
1154
|
+
className: "absolute right-6 top-1/2 transform -translate-y-1/2 w-4 h-4 text-muted-foreground hover:text-muted-foreground transition-colors",
|
|
1155
|
+
"aria-label": "Clear selection",
|
|
1156
|
+
title: "Clear selection",
|
|
1157
|
+
children: /* @__PURE__ */ jsx(RiCloseLine, { className: "w-4 h-4", "aria-hidden": true })
|
|
1158
|
+
}
|
|
1159
|
+
),
|
|
1160
|
+
/* @__PURE__ */ jsx(
|
|
1161
|
+
"button",
|
|
1162
|
+
{
|
|
1163
|
+
type: "button",
|
|
1164
|
+
onClick: (e) => {
|
|
1165
|
+
e.stopPropagation();
|
|
1166
|
+
!disabled && setIsOpen(!isOpen);
|
|
1167
|
+
},
|
|
1168
|
+
className: `absolute right-2 top-1/2 transform -translate-y-1/2 w-4 h-4 text-muted-foreground hover:text-muted-foreground transition-colors ${disabled ? "opacity-50 cursor-not-allowed" : ""}`,
|
|
1169
|
+
disabled,
|
|
1170
|
+
"aria-label": isOpen ? "Close dropdown" : "Open dropdown",
|
|
1171
|
+
"aria-expanded": isOpen,
|
|
1172
|
+
children: /* @__PURE__ */ jsx(
|
|
1173
|
+
DropDownArrow,
|
|
1174
|
+
{
|
|
1175
|
+
isOpen,
|
|
1176
|
+
disabled,
|
|
1177
|
+
size: "sm",
|
|
1178
|
+
color: "gray",
|
|
1179
|
+
"aria-hidden": true
|
|
1180
|
+
}
|
|
1181
|
+
)
|
|
1182
|
+
}
|
|
1183
|
+
)
|
|
1184
|
+
] }) : /* @__PURE__ */ jsxs("div", { className: "relative group", children: [
|
|
1185
|
+
/* @__PURE__ */ jsx(
|
|
1186
|
+
"button",
|
|
1187
|
+
{
|
|
1188
|
+
ref: buttonRef,
|
|
1189
|
+
type: "button",
|
|
1190
|
+
onClick: (e) => {
|
|
1191
|
+
e.stopPropagation();
|
|
1192
|
+
!disabled && (isOpen ? handleClose() : handleOpen());
|
|
1193
|
+
},
|
|
1194
|
+
onKeyDown: handleKeyDown,
|
|
1195
|
+
disabled,
|
|
1196
|
+
role: "combobox",
|
|
1197
|
+
"aria-expanded": isOpen,
|
|
1198
|
+
"aria-haspopup": "listbox",
|
|
1199
|
+
"aria-controls": "dropdown-listbox",
|
|
1200
|
+
"aria-label": placeholder,
|
|
1201
|
+
"aria-activedescendant": focusedIndex >= 0 ? `option-${focusedIndex}` : void 0,
|
|
1202
|
+
className: `form-input flex items-center justify-between text-left ${hasSelection ? "pr-12" : "pr-8"} ${disabled ? "opacity-60 cursor-not-allowed" : ""} ${className}`,
|
|
1203
|
+
children: /* @__PURE__ */ jsx(
|
|
1204
|
+
"span",
|
|
1205
|
+
{
|
|
1206
|
+
className: `flex items-center gap-2 min-w-0 flex-1 ${selectedOptions.length > 0 ? "" : "text-muted-foreground opacity-60"}`,
|
|
1207
|
+
children: multiple ? selectedOptions.length > 0 ? (() => {
|
|
1208
|
+
const displayText = selectedOptions.map((opt) => opt.label).join(", ");
|
|
1209
|
+
return /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1 min-w-0 flex-1", children: [
|
|
1210
|
+
selectedOptions[0].icon && /* @__PURE__ */ jsx("span", { className: "flex-shrink-0", children: selectedOptions[0].icon }),
|
|
1211
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: displayText })
|
|
1212
|
+
] });
|
|
1213
|
+
})() : /* @__PURE__ */ jsx("span", { className: "truncate", children: placeholder }) : selectedOptions[0] ? /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1 min-w-0 flex-1", children: [
|
|
1214
|
+
selectedOptions[0].icon && /* @__PURE__ */ jsx("span", { className: "flex-shrink-0", children: selectedOptions[0].icon }),
|
|
1215
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: selectedOptions[0].label })
|
|
1216
|
+
] }) : /* @__PURE__ */ jsx("span", { className: "truncate", children: placeholder })
|
|
1217
|
+
}
|
|
1218
|
+
)
|
|
1219
|
+
}
|
|
1220
|
+
),
|
|
1221
|
+
hasSelection && clearable && /* @__PURE__ */ jsx(
|
|
1222
|
+
"button",
|
|
1223
|
+
{
|
|
1224
|
+
type: "button",
|
|
1225
|
+
onClick: (e) => {
|
|
1226
|
+
e.stopPropagation();
|
|
1227
|
+
onChange(multiple ? [] : "");
|
|
1228
|
+
},
|
|
1229
|
+
className: "absolute right-6 top-1/2 transform -translate-y-1/2 w-4 h-4 text-muted-foreground hover:text-muted-foreground transition-all duration-200 opacity-0 group-hover:opacity-100",
|
|
1230
|
+
"aria-label": "Clear selection",
|
|
1231
|
+
title: "Clear selection",
|
|
1232
|
+
children: /* @__PURE__ */ jsx(RiCloseLine, { className: "w-4 h-4", "aria-hidden": true })
|
|
1233
|
+
}
|
|
1234
|
+
),
|
|
1235
|
+
/* @__PURE__ */ jsx(
|
|
1236
|
+
"button",
|
|
1237
|
+
{
|
|
1238
|
+
type: "button",
|
|
1239
|
+
onClick: (e) => {
|
|
1240
|
+
e.stopPropagation();
|
|
1241
|
+
!disabled && setIsOpen(!isOpen);
|
|
1242
|
+
},
|
|
1243
|
+
className: `absolute right-2 top-1/2 transform -translate-y-1/2 w-4 h-4 text-muted-foreground hover:text-muted-foreground transition-colors ${disabled ? "opacity-50 cursor-not-allowed" : ""}`,
|
|
1244
|
+
disabled,
|
|
1245
|
+
"aria-label": isOpen ? "Close dropdown" : "Open dropdown",
|
|
1246
|
+
"aria-expanded": isOpen,
|
|
1247
|
+
children: /* @__PURE__ */ jsx(
|
|
1248
|
+
DropDownArrow,
|
|
1249
|
+
{
|
|
1250
|
+
isOpen,
|
|
1251
|
+
disabled,
|
|
1252
|
+
size: "sm",
|
|
1253
|
+
color: "gray",
|
|
1254
|
+
"aria-hidden": true
|
|
1255
|
+
}
|
|
1256
|
+
)
|
|
1257
|
+
}
|
|
1258
|
+
)
|
|
1259
|
+
] }),
|
|
1260
|
+
children: /* @__PURE__ */ jsx("div", { className: "py-2", children: filteredOptions.length > 0 ? filteredOptions.map((option, index) => /* @__PURE__ */ jsxs(
|
|
1261
|
+
"button",
|
|
1262
|
+
{
|
|
1263
|
+
id: `option-${index}`,
|
|
1264
|
+
type: "button",
|
|
1265
|
+
role: "option",
|
|
1266
|
+
"aria-selected": selectedValues.includes(option.value),
|
|
1267
|
+
onMouseDown: (e) => {
|
|
1268
|
+
e.preventDefault();
|
|
1269
|
+
e.stopPropagation();
|
|
1270
|
+
handleSelect(option.value);
|
|
1271
|
+
},
|
|
1272
|
+
className: `w-full px-3 py-2 text-left text-sm hover:bg-accent flex items-center justify-between min-h-[40px] transition-colors ${selectedValues.includes(option.value) ? "bg-accent border-l-2 border-l-ring" : index === focusedIndex ? "bg-muted ring-2 ring-ring" : ""}`,
|
|
1273
|
+
children: [
|
|
1274
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 min-w-0 flex-1", children: [
|
|
1275
|
+
option.icon && /* @__PURE__ */ jsx("span", { className: "flex-shrink-0", children: option.icon }),
|
|
1276
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
1277
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1278
|
+
/* @__PURE__ */ jsx("div", { className: "font-medium text-foreground truncate", children: option.label }),
|
|
1279
|
+
option.metadata?.isDefault && /* @__PURE__ */ jsx("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded text-xs font-medium success-badge flex-shrink-0", children: "Default" })
|
|
1280
|
+
] }),
|
|
1281
|
+
option.description && /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground truncate", children: option.description }),
|
|
1282
|
+
option.metadata?.args && option.metadata.args.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mt-1", children: [
|
|
1283
|
+
/* @__PURE__ */ jsx("div", { className: "text-xs text-secondary-foreground mb-1", children: "Arguments:" }),
|
|
1284
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-1", children: [
|
|
1285
|
+
option.metadata.args.slice(0, 3).map((arg, argIndex) => /* @__PURE__ */ jsx(
|
|
1286
|
+
"span",
|
|
1287
|
+
{
|
|
1288
|
+
className: "inline-flex items-center px-1.5 py-0.5 rounded text-xs font-mono bg-muted text-muted-foreground",
|
|
1289
|
+
children: arg
|
|
1290
|
+
},
|
|
1291
|
+
argIndex
|
|
1292
|
+
)),
|
|
1293
|
+
option.metadata.args.length > 3 && /* @__PURE__ */ jsxs("span", { className: "text-xs text-secondary-foreground", children: [
|
|
1294
|
+
"+",
|
|
1295
|
+
option.metadata.args.length - 3,
|
|
1296
|
+
" more"
|
|
1297
|
+
] })
|
|
1298
|
+
] })
|
|
1299
|
+
] })
|
|
1300
|
+
] })
|
|
1301
|
+
] }),
|
|
1302
|
+
multiple ? /* @__PURE__ */ jsx(
|
|
1303
|
+
"input",
|
|
1304
|
+
{
|
|
1305
|
+
type: "checkbox",
|
|
1306
|
+
checked: selectedValues.includes(option.value),
|
|
1307
|
+
onChange: () => {
|
|
1308
|
+
},
|
|
1309
|
+
className: "w-4 h-4 text-primary bg-muted border-border rounded focus:ring-primary focus:ring-2"
|
|
1310
|
+
}
|
|
1311
|
+
) : selectedValues.includes(option.value) && /* @__PURE__ */ jsx(RiCheckLine, { className: "w-4 h-4 text-primary flex-shrink-0" })
|
|
1312
|
+
]
|
|
1313
|
+
},
|
|
1314
|
+
option.value
|
|
1315
|
+
)) : /* @__PURE__ */ jsx("div", { className: "px-3 py-2 text-sm text-secondary-foreground flex items-center gap-2", children: isLoading ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1316
|
+
/* @__PURE__ */ jsx(RiLoader4Line, { className: "w-4 h-4 animate-spin" }),
|
|
1317
|
+
/* @__PURE__ */ jsx("span", { children: "Loading..." })
|
|
1318
|
+
] }) : searchTerm.trim() ? /* @__PURE__ */ jsx("span", { children: "No results found" }) : /* @__PURE__ */ jsx("span", { children: "No options available" }) }) })
|
|
1319
|
+
}
|
|
1320
|
+
)
|
|
1321
|
+
] });
|
|
1322
|
+
}
|
|
1323
|
+
function Skeleton({ className = "", children }) {
|
|
1324
|
+
return /* @__PURE__ */ jsx("div", { className: `animate-pulse ${className}`, children });
|
|
1325
|
+
}
|
|
1326
|
+
function SkeletonItem({
|
|
1327
|
+
className = "",
|
|
1328
|
+
width = "w-full",
|
|
1329
|
+
height = "h-4",
|
|
1330
|
+
rounded = true,
|
|
1331
|
+
animate = true
|
|
1332
|
+
}) {
|
|
1333
|
+
const isArbitraryHeight = height.includes("[") && height.includes("]");
|
|
1334
|
+
const baseClasses = isArbitraryHeight ? `bg-muted ${width}` : `${height} bg-muted ${width}`;
|
|
1335
|
+
const roundedClasses = rounded ? "rounded" : "";
|
|
1336
|
+
const animateClasses = animate ? "animate-pulse" : "";
|
|
1337
|
+
const style = isArbitraryHeight ? { height: height.replace("h-[", "").replace("]", "") } : {};
|
|
1338
|
+
return /* @__PURE__ */ jsx(
|
|
1339
|
+
"div",
|
|
1340
|
+
{
|
|
1341
|
+
className: `${baseClasses} ${roundedClasses} ${animateClasses} ${className}`,
|
|
1342
|
+
style
|
|
1343
|
+
}
|
|
1344
|
+
);
|
|
1345
|
+
}
|
|
1346
|
+
function FormInput({
|
|
1347
|
+
label,
|
|
1348
|
+
name,
|
|
1349
|
+
type = "text",
|
|
1350
|
+
value,
|
|
1351
|
+
onChange,
|
|
1352
|
+
placeholder,
|
|
1353
|
+
required = false,
|
|
1354
|
+
disabled = false,
|
|
1355
|
+
error,
|
|
1356
|
+
className = "",
|
|
1357
|
+
inputClassName = "",
|
|
1358
|
+
min,
|
|
1359
|
+
max,
|
|
1360
|
+
step,
|
|
1361
|
+
maxLength,
|
|
473
1362
|
autoComplete,
|
|
474
1363
|
description,
|
|
475
1364
|
footerDescription,
|
|
@@ -477,12 +1366,17 @@ function FormInput({
|
|
|
477
1366
|
onKeyDown,
|
|
478
1367
|
onBlur,
|
|
479
1368
|
icon,
|
|
1369
|
+
options = [],
|
|
1370
|
+
multiSelect = false,
|
|
1371
|
+
selectWidth,
|
|
1372
|
+
searchable = false,
|
|
1373
|
+
clearable = true,
|
|
480
1374
|
rows = 3,
|
|
481
1375
|
showHidePassword = false,
|
|
482
1376
|
onGeneratePassword,
|
|
1377
|
+
isLoading = false,
|
|
483
1378
|
copyable = false,
|
|
484
|
-
readOnly = false
|
|
485
|
-
clearable = true
|
|
1379
|
+
readOnly = false
|
|
486
1380
|
}) {
|
|
487
1381
|
const [showPassword, setShowPassword] = useState(false);
|
|
488
1382
|
const [copied, setCopied] = useState(false);
|
|
@@ -524,14 +1418,82 @@ function FormInput({
|
|
|
524
1418
|
};
|
|
525
1419
|
const getInputPaddingClasses = (inputType, iconConfig) => {
|
|
526
1420
|
if (!shouldShowIcons(inputType)) return "";
|
|
527
|
-
const
|
|
528
|
-
if (iconConfig.left)
|
|
1421
|
+
const paddingClasses3 = [];
|
|
1422
|
+
if (iconConfig.left) paddingClasses3.push("pl-10");
|
|
529
1423
|
if (iconConfig.right) {
|
|
530
|
-
|
|
1424
|
+
paddingClasses3.push(inputType === "number" ? "pr-12" : "pr-10");
|
|
1425
|
+
}
|
|
1426
|
+
return paddingClasses3.join(" ");
|
|
1427
|
+
};
|
|
1428
|
+
const SkeletonInput = () => {
|
|
1429
|
+
const iconConfig = getIconConfig(icon);
|
|
1430
|
+
const hasLeftIcon = iconConfig.left;
|
|
1431
|
+
const hasRightIcon = iconConfig.right;
|
|
1432
|
+
if (type === "checkbox") {
|
|
1433
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center p-2 space-x-3 h-full", children: [
|
|
1434
|
+
/* @__PURE__ */ jsx("div", { className: "relative inline-flex h-6 w-11 items-center rounded-full bg-muted", children: /* @__PURE__ */ jsx("span", { className: "inline-block h-4 w-4 transform rounded-full bg-white border border-border translate-x-1" }) }),
|
|
1435
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
|
|
1436
|
+
/* @__PURE__ */ jsxs("label", { className: "form-label", children: [
|
|
1437
|
+
label,
|
|
1438
|
+
required && /* @__PURE__ */ jsx("span", { className: "text-destructive ml-1", children: "*" })
|
|
1439
|
+
] }),
|
|
1440
|
+
description && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: description })
|
|
1441
|
+
] })
|
|
1442
|
+
] });
|
|
1443
|
+
}
|
|
1444
|
+
if (type === "textarea") {
|
|
1445
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
1446
|
+
/* @__PURE__ */ jsxs("label", { className: "form-label", children: [
|
|
1447
|
+
label,
|
|
1448
|
+
required && /* @__PURE__ */ jsx("span", { className: "text-red-500 ml-1", children: "*" })
|
|
1449
|
+
] }),
|
|
1450
|
+
description && /* @__PURE__ */ jsx("p", { className: "text-sm text-secondary-foreground", children: description }),
|
|
1451
|
+
/* @__PURE__ */ jsx("div", { className: "relative", children: /* @__PURE__ */ jsx(
|
|
1452
|
+
SkeletonItem,
|
|
1453
|
+
{
|
|
1454
|
+
width: "w-full",
|
|
1455
|
+
height: "h-24",
|
|
1456
|
+
className: `rounded-md`
|
|
1457
|
+
}
|
|
1458
|
+
) }),
|
|
1459
|
+
footerDescription && /* @__PURE__ */ jsx("p", { className: "text-sm text-secondary-foreground", children: footerDescription })
|
|
1460
|
+
] });
|
|
531
1461
|
}
|
|
532
|
-
|
|
1462
|
+
if (type === "color") {
|
|
1463
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
1464
|
+
/* @__PURE__ */ jsxs("label", { className: "form-label", children: [
|
|
1465
|
+
label,
|
|
1466
|
+
required && /* @__PURE__ */ jsx("span", { className: "text-red-500 ml-1", children: "*" })
|
|
1467
|
+
] }),
|
|
1468
|
+
description && /* @__PURE__ */ jsx("p", { className: "text-sm text-secondary-foreground", children: description }),
|
|
1469
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-3", children: [
|
|
1470
|
+
/* @__PURE__ */ jsx(SkeletonItem, { width: "w-10", height: "h-10", className: "rounded-md" }),
|
|
1471
|
+
/* @__PURE__ */ jsx("div", { className: "relative", children: /* @__PURE__ */ jsx(SkeletonItem, { width: "w-24", height: "h-10", className: "rounded-md" }) })
|
|
1472
|
+
] })
|
|
1473
|
+
] });
|
|
1474
|
+
}
|
|
1475
|
+
return /* @__PURE__ */ jsxs("div", { children: [
|
|
1476
|
+
/* @__PURE__ */ jsxs("label", { className: "form-label", children: [
|
|
1477
|
+
label,
|
|
1478
|
+
required && /* @__PURE__ */ jsx("span", { className: "text-red-500 ml-1", children: "*" })
|
|
1479
|
+
] }),
|
|
1480
|
+
description && /* @__PURE__ */ jsx("p", { className: "text-sm text-secondary-foreground", children: description }),
|
|
1481
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
1482
|
+
/* @__PURE__ */ jsx(
|
|
1483
|
+
SkeletonItem,
|
|
1484
|
+
{
|
|
1485
|
+
width: "w-full",
|
|
1486
|
+
height: "h-10",
|
|
1487
|
+
className: `rounded-md ${hasLeftIcon ? "pl-10" : ""} ${hasRightIcon ? "pr-10" : ""}`
|
|
1488
|
+
}
|
|
1489
|
+
),
|
|
1490
|
+
hasLeftIcon && /* @__PURE__ */ jsx("div", { className: "absolute inset-y-0 left-0 pl-3 flex items-center", children: /* @__PURE__ */ jsx(SkeletonItem, { width: "w-5", height: "h-5", className: "rounded-full" }) }),
|
|
1491
|
+
hasRightIcon && /* @__PURE__ */ jsx("div", { className: "absolute inset-y-0 right-0 pr-3 flex items-center", children: /* @__PURE__ */ jsx(SkeletonItem, { width: "w-5", height: "h-5", className: "rounded-full" }) })
|
|
1492
|
+
] }),
|
|
1493
|
+
footerDescription && /* @__PURE__ */ jsx("p", { className: "text-sm text-secondary-foreground", children: footerDescription })
|
|
1494
|
+
] });
|
|
533
1495
|
};
|
|
534
|
-
return /* @__PURE__ */ jsx("div", { className: `form-group ${className}`, children: type === "checkbox" ? /* @__PURE__ */ jsxs("div", { className: "flex items-center p-2 space-x-3 h-full", children: [
|
|
1496
|
+
return /* @__PURE__ */ jsx("div", { className: `form-group ${className}`, children: isLoading ? /* @__PURE__ */ jsx(SkeletonInput, {}) : type === "checkbox" ? /* @__PURE__ */ jsxs("div", { className: "flex items-center p-2 space-x-3 h-full", children: [
|
|
535
1497
|
/* @__PURE__ */ jsx(
|
|
536
1498
|
"input",
|
|
537
1499
|
{
|
|
@@ -636,7 +1598,45 @@ function FormInput({
|
|
|
636
1598
|
required && /* @__PURE__ */ jsx("span", { className: "form-label-required", children: "*" })
|
|
637
1599
|
] }),
|
|
638
1600
|
description && /* @__PURE__ */ jsx("p", { id: `${name}-description`, className: "form-description", children: description }),
|
|
639
|
-
type === "
|
|
1601
|
+
type === "select" ? /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
1602
|
+
/* @__PURE__ */ jsx(
|
|
1603
|
+
SmartSelect,
|
|
1604
|
+
{
|
|
1605
|
+
value: multiSelect ? Array.isArray(value) ? value : value ? String(value).split(",") : [] : String(value),
|
|
1606
|
+
onChange: multiSelect ? (selectedValue) => {
|
|
1607
|
+
const syntheticEvent = {
|
|
1608
|
+
target: {
|
|
1609
|
+
name,
|
|
1610
|
+
value: Array.isArray(selectedValue) ? selectedValue.join(",") : selectedValue
|
|
1611
|
+
}
|
|
1612
|
+
};
|
|
1613
|
+
onChange(syntheticEvent);
|
|
1614
|
+
} : (selectedValue) => {
|
|
1615
|
+
const syntheticEvent = {
|
|
1616
|
+
target: {
|
|
1617
|
+
name,
|
|
1618
|
+
value: selectedValue
|
|
1619
|
+
}
|
|
1620
|
+
};
|
|
1621
|
+
onChange(syntheticEvent);
|
|
1622
|
+
},
|
|
1623
|
+
options,
|
|
1624
|
+
placeholder: placeholder || "Select an option...",
|
|
1625
|
+
className: `form-input ${error ? "form-input-error" : ""} ${disabled ? "opacity-50 cursor-not-allowed" : ""} ${getInputPaddingClasses(type, getIconConfig(icon))} ${inputClassName}`,
|
|
1626
|
+
multiple: multiSelect,
|
|
1627
|
+
width: selectWidth,
|
|
1628
|
+
searchable,
|
|
1629
|
+
clearable
|
|
1630
|
+
}
|
|
1631
|
+
),
|
|
1632
|
+
shouldShowIcons(type) && (() => {
|
|
1633
|
+
const iconConfig = getIconConfig(icon);
|
|
1634
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1635
|
+
renderIcon(iconConfig.left, "left"),
|
|
1636
|
+
renderIcon(iconConfig.right, "right")
|
|
1637
|
+
] });
|
|
1638
|
+
})()
|
|
1639
|
+
] }) : type === "textarea" ? /* @__PURE__ */ jsx(
|
|
640
1640
|
"textarea",
|
|
641
1641
|
{
|
|
642
1642
|
id: name,
|
|
@@ -835,337 +1835,85 @@ function FormInput({
|
|
|
835
1835
|
error && /* @__PURE__ */ jsx("div", { id: `${name}-error`, className: "form-error", role: "alert", children: typeof error === "string" ? /* @__PURE__ */ jsx("p", { children: error }) : error })
|
|
836
1836
|
] }) });
|
|
837
1837
|
}
|
|
838
|
-
function
|
|
839
|
-
|
|
840
|
-
onChange,
|
|
841
|
-
disabled = false,
|
|
842
|
-
label,
|
|
1838
|
+
function FormSection({
|
|
1839
|
+
title,
|
|
843
1840
|
description,
|
|
844
|
-
|
|
845
|
-
|
|
1841
|
+
children,
|
|
1842
|
+
className = ""
|
|
846
1843
|
}) {
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
sm: { track: "w-8 h-4", thumb: "w-3 h-3", translate: "translate-x-4" },
|
|
854
|
-
md: { track: "w-11 h-6", thumb: "w-5 h-5", translate: "translate-x-5" },
|
|
855
|
-
lg: { track: "w-14 h-8", thumb: "w-7 h-7", translate: "translate-x-6" }
|
|
856
|
-
};
|
|
857
|
-
const currentSize = sizes[size];
|
|
858
|
-
return /* @__PURE__ */ jsxs("div", { className: `flex items-start ${className}`, children: [
|
|
859
|
-
/* @__PURE__ */ jsx(
|
|
860
|
-
"button",
|
|
861
|
-
{
|
|
862
|
-
type: "button",
|
|
863
|
-
role: "switch",
|
|
864
|
-
"aria-checked": checked,
|
|
865
|
-
disabled,
|
|
866
|
-
onClick: toggle,
|
|
867
|
-
className: `
|
|
868
|
-
relative inline-flex flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent
|
|
869
|
-
transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2
|
|
870
|
-
${checked ? "bg-primary" : "bg-muted"}
|
|
871
|
-
${disabled ? "opacity-50 cursor-not-allowed" : ""}
|
|
872
|
-
${currentSize.track}
|
|
873
|
-
`,
|
|
874
|
-
children: /* @__PURE__ */ jsx(
|
|
875
|
-
"span",
|
|
876
|
-
{
|
|
877
|
-
"aria-hidden": "true",
|
|
878
|
-
className: `
|
|
879
|
-
pointer-events-none inline-block transform rounded-full bg-white shadow ring-0
|
|
880
|
-
transition duration-200 ease-in-out
|
|
881
|
-
${checked ? currentSize.translate : "translate-x-0"}
|
|
882
|
-
${currentSize.thumb}
|
|
883
|
-
`
|
|
884
|
-
}
|
|
885
|
-
)
|
|
886
|
-
}
|
|
887
|
-
),
|
|
888
|
-
(label || description) && /* @__PURE__ */ jsxs("div", { className: "ml-3 text-sm leading-6", children: [
|
|
889
|
-
label && /* @__PURE__ */ jsx("label", { className: "font-medium text-foreground cursor-pointer", onClick: toggle, children: label }),
|
|
890
|
-
description && /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: description })
|
|
891
|
-
] })
|
|
1844
|
+
return /* @__PURE__ */ jsxs("div", { className: `space-y-4 ${className}`, children: [
|
|
1845
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
1846
|
+
/* @__PURE__ */ jsx("h3", { className: "text-lg font-medium ", children: title }),
|
|
1847
|
+
description && /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: description })
|
|
1848
|
+
] }),
|
|
1849
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-4", children })
|
|
892
1850
|
] });
|
|
893
1851
|
}
|
|
894
|
-
|
|
895
|
-
sm: "max-w-md",
|
|
896
|
-
md: "max-w-2xl",
|
|
897
|
-
lg: "max-w-4xl",
|
|
898
|
-
xl: "max-w-6xl",
|
|
899
|
-
full: "max-w-full mx-4"
|
|
900
|
-
};
|
|
901
|
-
function Modal({
|
|
902
|
-
isOpen,
|
|
903
|
-
onClose,
|
|
1852
|
+
function Grid({
|
|
904
1853
|
children,
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
size = "md",
|
|
909
|
-
className = "",
|
|
910
|
-
footer,
|
|
911
|
-
fullScreen = false,
|
|
912
|
-
noPadding = false,
|
|
913
|
-
footerBg = "gray",
|
|
914
|
-
variant = "default",
|
|
915
|
-
scrollable = true,
|
|
916
|
-
"aria-describedby": ariaDescribedBy,
|
|
917
|
-
customStyles = {}
|
|
1854
|
+
cols = 1,
|
|
1855
|
+
gap = 4,
|
|
1856
|
+
className = ""
|
|
918
1857
|
}) {
|
|
919
|
-
const
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
"input:not([disabled])",
|
|
928
|
-
"select:not([disabled])",
|
|
929
|
-
"textarea:not([disabled])",
|
|
930
|
-
'[tabindex]:not([tabindex="-1"])'
|
|
931
|
-
].join(", ");
|
|
932
|
-
return Array.from(
|
|
933
|
-
modalContentRef.current.querySelectorAll(focusableSelectors)
|
|
934
|
-
);
|
|
935
|
-
};
|
|
936
|
-
useEffect(() => {
|
|
937
|
-
if (!isOpen) {
|
|
938
|
-
hasPerformedInitialFocusRef.current = false;
|
|
939
|
-
return;
|
|
940
|
-
}
|
|
941
|
-
if (!hasPerformedInitialFocusRef.current) {
|
|
942
|
-
previousActiveElementRef.current = document.activeElement;
|
|
943
|
-
}
|
|
944
|
-
let timeoutId = null;
|
|
945
|
-
if (!hasPerformedInitialFocusRef.current) {
|
|
946
|
-
const focusableElements = getFocusableElements();
|
|
947
|
-
const firstFocusable = focusableElements[0];
|
|
948
|
-
timeoutId = setTimeout(() => {
|
|
949
|
-
const activeElement = document.activeElement;
|
|
950
|
-
const isHTMLElement = activeElement instanceof HTMLElement;
|
|
951
|
-
const isUserTyping = activeElement && (activeElement.tagName === "INPUT" || activeElement.tagName === "TEXTAREA" || isHTMLElement && activeElement.isContentEditable);
|
|
952
|
-
const isFocusInModal = modalContentRef.current?.contains(activeElement);
|
|
953
|
-
if (!isUserTyping && !isFocusInModal) {
|
|
954
|
-
if (firstFocusable) {
|
|
955
|
-
firstFocusable.focus();
|
|
956
|
-
hasPerformedInitialFocusRef.current = true;
|
|
957
|
-
} else if (modalContentRef.current) {
|
|
958
|
-
modalContentRef.current.focus();
|
|
959
|
-
hasPerformedInitialFocusRef.current = true;
|
|
960
|
-
}
|
|
961
|
-
} else if (isFocusInModal) {
|
|
962
|
-
hasPerformedInitialFocusRef.current = true;
|
|
963
|
-
}
|
|
964
|
-
}, 100);
|
|
965
|
-
}
|
|
966
|
-
const handleTab = (event) => {
|
|
967
|
-
if (event.key !== "Tab") return;
|
|
968
|
-
const focusableElements = getFocusableElements();
|
|
969
|
-
if (focusableElements.length === 0) return;
|
|
970
|
-
const firstElement = focusableElements[0];
|
|
971
|
-
const lastElement = focusableElements[focusableElements.length - 1];
|
|
972
|
-
if (event.shiftKey) {
|
|
973
|
-
if (document.activeElement === firstElement) {
|
|
974
|
-
event.preventDefault();
|
|
975
|
-
lastElement.focus();
|
|
976
|
-
}
|
|
977
|
-
} else {
|
|
978
|
-
if (document.activeElement === lastElement) {
|
|
979
|
-
event.preventDefault();
|
|
980
|
-
firstElement.focus();
|
|
981
|
-
}
|
|
982
|
-
}
|
|
983
|
-
};
|
|
984
|
-
const handleEsc = (event) => {
|
|
985
|
-
if (event.key === "Escape" && !blocking) {
|
|
986
|
-
onClose();
|
|
987
|
-
}
|
|
988
|
-
};
|
|
989
|
-
document.addEventListener("keydown", handleTab);
|
|
990
|
-
document.addEventListener("keydown", handleEsc);
|
|
991
|
-
document.body.style.overflow = "hidden";
|
|
992
|
-
return () => {
|
|
993
|
-
if (timeoutId) {
|
|
994
|
-
clearTimeout(timeoutId);
|
|
995
|
-
}
|
|
996
|
-
document.removeEventListener("keydown", handleTab);
|
|
997
|
-
document.removeEventListener("keydown", handleEsc);
|
|
998
|
-
document.body.style.overflow = "unset";
|
|
999
|
-
if (!isOpen && previousActiveElementRef.current) {
|
|
1000
|
-
previousActiveElementRef.current.focus();
|
|
1001
|
-
}
|
|
1002
|
-
};
|
|
1003
|
-
}, [isOpen, onClose, blocking]);
|
|
1004
|
-
const modalRoot = (() => {
|
|
1005
|
-
if (typeof document === "undefined") return null;
|
|
1006
|
-
let root = document.getElementById("modal-root");
|
|
1007
|
-
if (!root) {
|
|
1008
|
-
root = document.createElement("div");
|
|
1009
|
-
root.id = "modal-root";
|
|
1010
|
-
document.body.appendChild(root);
|
|
1011
|
-
}
|
|
1012
|
-
return root;
|
|
1013
|
-
})();
|
|
1014
|
-
if (!modalRoot) {
|
|
1015
|
-
return null;
|
|
1016
|
-
}
|
|
1017
|
-
const backdropVariants = {
|
|
1018
|
-
hidden: { opacity: 0 },
|
|
1019
|
-
visible: { opacity: 1 }
|
|
1858
|
+
const colClasses = {
|
|
1859
|
+
1: "grid-cols-1",
|
|
1860
|
+
2: "grid-cols-1 md:grid-cols-2",
|
|
1861
|
+
3: "grid-cols-1 md:grid-cols-2 lg:grid-cols-3",
|
|
1862
|
+
4: "grid-cols-1 md:grid-cols-2 lg:grid-cols-4",
|
|
1863
|
+
5: "grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5",
|
|
1864
|
+
6: "grid-cols-2 md:grid-cols-3 lg:grid-cols-6",
|
|
1865
|
+
12: "grid-cols-12"
|
|
1020
1866
|
};
|
|
1021
|
-
const
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
opacity: 1,
|
|
1029
|
-
scale: 1,
|
|
1030
|
-
y: 0,
|
|
1031
|
-
transition: {
|
|
1032
|
-
duration: 0.2,
|
|
1033
|
-
ease: "easeOut"
|
|
1034
|
-
}
|
|
1035
|
-
},
|
|
1036
|
-
exit: {
|
|
1037
|
-
opacity: 0,
|
|
1038
|
-
scale: 0.9,
|
|
1039
|
-
y: 100,
|
|
1040
|
-
// Slide down much further for reverse effect
|
|
1041
|
-
transition: {
|
|
1042
|
-
duration: 0.3,
|
|
1043
|
-
ease: "easeIn"
|
|
1044
|
-
}
|
|
1045
|
-
}
|
|
1867
|
+
const gapClasses = {
|
|
1868
|
+
1: "gap-1",
|
|
1869
|
+
2: "gap-2",
|
|
1870
|
+
3: "gap-3",
|
|
1871
|
+
4: "gap-4",
|
|
1872
|
+
6: "gap-6",
|
|
1873
|
+
8: "gap-8"
|
|
1046
1874
|
};
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1875
|
+
return /* @__PURE__ */ jsx("div", { className: `grid ${colClasses[cols]} ${gapClasses[gap]} ${className}`, children });
|
|
1876
|
+
}
|
|
1877
|
+
var variantClasses3 = {
|
|
1878
|
+
default: "text-foreground hover:text-primary",
|
|
1879
|
+
primary: "text-primary hover:text-primary/80",
|
|
1880
|
+
muted: "text-muted-foreground hover:text-foreground"
|
|
1881
|
+
};
|
|
1882
|
+
var Link = forwardRef(
|
|
1883
|
+
({
|
|
1884
|
+
href,
|
|
1885
|
+
variant = "default",
|
|
1886
|
+
underline = false,
|
|
1887
|
+
external = false,
|
|
1888
|
+
className = "",
|
|
1889
|
+
children,
|
|
1890
|
+
...props
|
|
1891
|
+
}, ref) => {
|
|
1892
|
+
const classes = [
|
|
1893
|
+
"transition-colors",
|
|
1894
|
+
variantClasses3[variant],
|
|
1895
|
+
underline ? "underline underline-offset-4" : "hover:underline hover:underline-offset-4",
|
|
1896
|
+
className
|
|
1897
|
+
].filter(Boolean).join(" ");
|
|
1898
|
+
if (external || href.startsWith("http")) {
|
|
1899
|
+
return /* @__PURE__ */ jsx(
|
|
1900
|
+
"a",
|
|
1052
1901
|
{
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
children
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
"aria-modal": "true",
|
|
1065
|
-
"aria-labelledby": title ? "modal-title-plain" : void 0,
|
|
1066
|
-
"aria-describedby": ariaDescribedBy || "modal-content-plain",
|
|
1067
|
-
tabIndex: -1,
|
|
1068
|
-
className: `w-full flex flex-col overflow-hidden relative z-[1000000] ${customStyles.container || "bg-card shadow-xl"} ${fullScreen ? "h-full rounded-none" : `rounded-lg ${className} ${sizeClasses3[size]} max-h-[90vh]`}`,
|
|
1069
|
-
variants: modalVariants,
|
|
1070
|
-
initial: "hidden",
|
|
1071
|
-
animate: isOpen ? "visible" : "exit",
|
|
1072
|
-
exit: "exit",
|
|
1073
|
-
onClick: (e) => e.stopPropagation(),
|
|
1074
|
-
children: /* @__PURE__ */ jsx(
|
|
1075
|
-
"div",
|
|
1076
|
-
{
|
|
1077
|
-
id: "modal-content-plain",
|
|
1078
|
-
className: `flex-1 ${customStyles.content || ""}`,
|
|
1079
|
-
children
|
|
1080
|
-
}
|
|
1081
|
-
)
|
|
1082
|
-
},
|
|
1083
|
-
"modal-content"
|
|
1084
|
-
)
|
|
1085
|
-
},
|
|
1086
|
-
"modal-backdrop"
|
|
1087
|
-
) }),
|
|
1088
|
-
modalRoot
|
|
1089
|
-
);
|
|
1902
|
+
ref,
|
|
1903
|
+
href,
|
|
1904
|
+
className: classes,
|
|
1905
|
+
target: "_blank",
|
|
1906
|
+
rel: "noopener noreferrer",
|
|
1907
|
+
...props,
|
|
1908
|
+
children
|
|
1909
|
+
}
|
|
1910
|
+
);
|
|
1911
|
+
}
|
|
1912
|
+
return /* @__PURE__ */ jsx(NextLink, { ref, href, className: classes, ...props, children });
|
|
1090
1913
|
}
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
{
|
|
1095
|
-
className: `modal-backdrop fixed inset-0 w-screen h-screen bg-black/10 flex items-center ${customStyles.backdrop || "justify-center"} z-[999999] m-0 ${fullScreen ? "p-0" : "p-4"}`,
|
|
1096
|
-
variants: backdropVariants,
|
|
1097
|
-
initial: "hidden",
|
|
1098
|
-
animate: isOpen ? "visible" : "hidden",
|
|
1099
|
-
exit: "hidden",
|
|
1100
|
-
onClick: blocking ? void 0 : onClose,
|
|
1101
|
-
children: /* @__PURE__ */ jsxs(
|
|
1102
|
-
motion.div,
|
|
1103
|
-
{
|
|
1104
|
-
ref: modalContentRef,
|
|
1105
|
-
role: "dialog",
|
|
1106
|
-
"aria-modal": "true",
|
|
1107
|
-
"aria-labelledby": title ? "modal-title" : void 0,
|
|
1108
|
-
"aria-describedby": ariaDescribedBy || "modal-content",
|
|
1109
|
-
tabIndex: -1,
|
|
1110
|
-
className: `bg-card border border-border shadow-xl w-full flex flex-col overflow-hidden relative z-[1000000] ${fullScreen ? "h-full rounded-none" : `rounded-lg ${customStyles.container || className || sizeClasses3[size]} max-h-[90vh]`}`,
|
|
1111
|
-
variants: modalVariants,
|
|
1112
|
-
initial: "hidden",
|
|
1113
|
-
animate: isOpen ? "visible" : "exit",
|
|
1114
|
-
exit: "exit",
|
|
1115
|
-
onClick: (e) => e.stopPropagation(),
|
|
1116
|
-
children: [
|
|
1117
|
-
header ? /* @__PURE__ */ jsx("div", { className: "flex-shrink-0", children: header }) : title ? /* @__PURE__ */ jsxs(
|
|
1118
|
-
"div",
|
|
1119
|
-
{
|
|
1120
|
-
className: `px-6 py-4 border-b border-border flex justify-between items-center flex-shrink-0 ${customStyles.header || ""}`,
|
|
1121
|
-
children: [
|
|
1122
|
-
/* @__PURE__ */ jsx(
|
|
1123
|
-
"h2",
|
|
1124
|
-
{
|
|
1125
|
-
id: "modal-title",
|
|
1126
|
-
className: "text-xl font-semibold text-foreground",
|
|
1127
|
-
children: title
|
|
1128
|
-
}
|
|
1129
|
-
),
|
|
1130
|
-
/* @__PURE__ */ jsx(
|
|
1131
|
-
"button",
|
|
1132
|
-
{
|
|
1133
|
-
onClick: onClose,
|
|
1134
|
-
className: "p-2 text-muted-foreground hover:text-foreground hover:bg-muted rounded-full transition-colors",
|
|
1135
|
-
title: "Close",
|
|
1136
|
-
"aria-label": "Close modal",
|
|
1137
|
-
disabled: blocking,
|
|
1138
|
-
children: /* @__PURE__ */ jsx(RiCloseLine, { className: "w-5 h-5", "aria-hidden": "true" })
|
|
1139
|
-
}
|
|
1140
|
-
)
|
|
1141
|
-
]
|
|
1142
|
-
}
|
|
1143
|
-
) : null,
|
|
1144
|
-
/* @__PURE__ */ jsx(
|
|
1145
|
-
"div",
|
|
1146
|
-
{
|
|
1147
|
-
id: "modal-content",
|
|
1148
|
-
className: `bg-background text-foreground flex-1 ${scrollable ? "overflow-y-auto" : ""} ${fullScreen || noPadding ? "p-0" : "px-6 py-4"}`,
|
|
1149
|
-
children
|
|
1150
|
-
}
|
|
1151
|
-
),
|
|
1152
|
-
footer && /* @__PURE__ */ jsx(
|
|
1153
|
-
"div",
|
|
1154
|
-
{
|
|
1155
|
-
className: `flex-shrink-0 px-6 py-4 border-t border-border ${footerBg === "white" ? "bg-card" : "bg-muted"} ${customStyles.footer || ""}`,
|
|
1156
|
-
children: footer
|
|
1157
|
-
}
|
|
1158
|
-
)
|
|
1159
|
-
]
|
|
1160
|
-
},
|
|
1161
|
-
"modal-content"
|
|
1162
|
-
)
|
|
1163
|
-
},
|
|
1164
|
-
"modal-backdrop"
|
|
1165
|
-
) }),
|
|
1166
|
-
modalRoot
|
|
1167
|
-
);
|
|
1168
|
-
}
|
|
1914
|
+
);
|
|
1915
|
+
Link.displayName = "Link";
|
|
1916
|
+
var Link_default = Link;
|
|
1169
1917
|
var LoadingSpinner = ({
|
|
1170
1918
|
message = "Initializing...",
|
|
1171
1919
|
className,
|
|
@@ -1224,53 +1972,90 @@ function PageHeader({
|
|
|
1224
1972
|
rightContent && /* @__PURE__ */ jsx("div", { className: "flex items-center space-x-2 lg:space-x-3 flex-shrink-0", children: rightContent })
|
|
1225
1973
|
] }) });
|
|
1226
1974
|
}
|
|
1227
|
-
function
|
|
1228
|
-
|
|
1975
|
+
function Switch({
|
|
1976
|
+
checked,
|
|
1977
|
+
onChange,
|
|
1978
|
+
disabled = false,
|
|
1979
|
+
label,
|
|
1229
1980
|
description,
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
}) {
|
|
1233
|
-
return /* @__PURE__ */ jsxs("div", { className: `space-y-4 ${className}`, children: [
|
|
1234
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
1235
|
-
/* @__PURE__ */ jsx("h3", { className: "text-lg font-medium ", children: title }),
|
|
1236
|
-
description && /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: description })
|
|
1237
|
-
] }),
|
|
1238
|
-
/* @__PURE__ */ jsx("div", { className: "space-y-4", children })
|
|
1239
|
-
] });
|
|
1240
|
-
}
|
|
1241
|
-
function Grid({
|
|
1242
|
-
children,
|
|
1243
|
-
cols = 1,
|
|
1244
|
-
gap = 4,
|
|
1245
|
-
className = ""
|
|
1981
|
+
className = "",
|
|
1982
|
+
size = "md"
|
|
1246
1983
|
}) {
|
|
1247
|
-
const
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
4: "grid-cols-1 md:grid-cols-2 lg:grid-cols-4",
|
|
1252
|
-
5: "grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5",
|
|
1253
|
-
6: "grid-cols-2 md:grid-cols-3 lg:grid-cols-6",
|
|
1254
|
-
12: "grid-cols-12"
|
|
1984
|
+
const toggle = () => {
|
|
1985
|
+
if (!disabled) {
|
|
1986
|
+
onChange(!checked);
|
|
1987
|
+
}
|
|
1255
1988
|
};
|
|
1256
|
-
const
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
4: "gap-4",
|
|
1261
|
-
6: "gap-6",
|
|
1262
|
-
8: "gap-8"
|
|
1989
|
+
const sizes = {
|
|
1990
|
+
sm: { track: "w-8 h-4", thumb: "w-3 h-3", translate: "translate-x-4" },
|
|
1991
|
+
md: { track: "w-11 h-6", thumb: "w-5 h-5", translate: "translate-x-5" },
|
|
1992
|
+
lg: { track: "w-14 h-8", thumb: "w-7 h-7", translate: "translate-x-6" }
|
|
1263
1993
|
};
|
|
1264
|
-
|
|
1994
|
+
const currentSize = sizes[size];
|
|
1995
|
+
return /* @__PURE__ */ jsxs("div", { className: `flex items-start ${className}`, children: [
|
|
1996
|
+
/* @__PURE__ */ jsx(
|
|
1997
|
+
"button",
|
|
1998
|
+
{
|
|
1999
|
+
type: "button",
|
|
2000
|
+
role: "switch",
|
|
2001
|
+
"aria-checked": checked,
|
|
2002
|
+
disabled,
|
|
2003
|
+
onClick: toggle,
|
|
2004
|
+
className: `
|
|
2005
|
+
relative inline-flex flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent
|
|
2006
|
+
transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2
|
|
2007
|
+
${checked ? "bg-primary" : "bg-muted"}
|
|
2008
|
+
${disabled ? "opacity-50 cursor-not-allowed" : ""}
|
|
2009
|
+
${currentSize.track}
|
|
2010
|
+
`,
|
|
2011
|
+
children: /* @__PURE__ */ jsx(
|
|
2012
|
+
"span",
|
|
2013
|
+
{
|
|
2014
|
+
"aria-hidden": "true",
|
|
2015
|
+
className: `
|
|
2016
|
+
pointer-events-none inline-block transform rounded-full bg-white shadow ring-0
|
|
2017
|
+
transition duration-200 ease-in-out
|
|
2018
|
+
${checked ? currentSize.translate : "translate-x-0"}
|
|
2019
|
+
${currentSize.thumb}
|
|
2020
|
+
`
|
|
2021
|
+
}
|
|
2022
|
+
)
|
|
2023
|
+
}
|
|
2024
|
+
),
|
|
2025
|
+
(label || description) && /* @__PURE__ */ jsxs("div", { className: "ml-3 text-sm leading-6", children: [
|
|
2026
|
+
label && /* @__PURE__ */ jsx("label", { className: "font-medium text-foreground cursor-pointer", onClick: toggle, children: label }),
|
|
2027
|
+
description && /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: description })
|
|
2028
|
+
] })
|
|
2029
|
+
] });
|
|
1265
2030
|
}
|
|
1266
|
-
|
|
2031
|
+
var variantClasses4 = {
|
|
2032
|
+
default: "text-foreground",
|
|
2033
|
+
muted: "text-muted-foreground",
|
|
2034
|
+
bold: "font-semibold"
|
|
2035
|
+
};
|
|
2036
|
+
var sizeClasses4 = {
|
|
2037
|
+
xs: "text-xs",
|
|
2038
|
+
sm: "text-sm",
|
|
2039
|
+
base: "text-base",
|
|
2040
|
+
lg: "text-lg",
|
|
2041
|
+
xl: "text-xl",
|
|
2042
|
+
"2xl": "text-2xl",
|
|
2043
|
+
"3xl": "text-3xl"
|
|
2044
|
+
};
|
|
2045
|
+
function Typography({
|
|
2046
|
+
as: Element = "p",
|
|
2047
|
+
variant = "default",
|
|
2048
|
+
size = "base",
|
|
1267
2049
|
children,
|
|
1268
|
-
span = 1,
|
|
1269
2050
|
className = ""
|
|
1270
2051
|
}) {
|
|
1271
|
-
|
|
2052
|
+
const classes = `${variantClasses4[variant]} ${sizeClasses4[size]} ${className}`;
|
|
2053
|
+
return /* @__PURE__ */ jsx(Element, { className: classes, children });
|
|
1272
2054
|
}
|
|
1273
2055
|
|
|
1274
|
-
|
|
2056
|
+
// src/index.ts
|
|
2057
|
+
var VERSION = "0.1.3";
|
|
2058
|
+
|
|
2059
|
+
export { Badge, Button_default as Button, Card, ConfirmDialog_default as ConfirmDialog, Container, EmptyState_default as EmptyState, FormInput, FormSection, Grid, Link_default as Link, LoadingSpinner_default as LoadingSpinner, Modal, PageHeader, Skeleton, SkeletonItem, SmartDropdown, SmartSelect, Switch, Typography, VERSION, useConfirmDialog };
|
|
1275
2060
|
//# sourceMappingURL=index.mjs.map
|
|
1276
2061
|
//# sourceMappingURL=index.mjs.map
|