mywhy-ui 0.1.0 → 0.2.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/README.md +136 -28
- package/dist/index.cjs +1453 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +288 -1
- package/dist/index.d.ts +288 -1
- package/dist/index.js +1415 -4
- package/dist/index.js.map +1 -1
- package/package.json +19 -4
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
-
var
|
|
4
|
+
var React9 = require('react');
|
|
5
|
+
|
|
6
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
7
|
+
|
|
8
|
+
var React9__default = /*#__PURE__*/_interopDefault(React9);
|
|
5
9
|
|
|
6
10
|
// src/components/Spinner/Spinner.tsx
|
|
7
11
|
var sizeClasses = {
|
|
@@ -196,6 +200,49 @@ function Select({
|
|
|
196
200
|
error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-danger-text", children: error })
|
|
197
201
|
] });
|
|
198
202
|
}
|
|
203
|
+
function Switch({
|
|
204
|
+
label,
|
|
205
|
+
description,
|
|
206
|
+
error,
|
|
207
|
+
id,
|
|
208
|
+
className = "",
|
|
209
|
+
checked,
|
|
210
|
+
...props
|
|
211
|
+
}) {
|
|
212
|
+
const switchId = id ?? (typeof label === "string" ? label.toLowerCase().replace(/\s+/g, "-") : void 0);
|
|
213
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex flex-col gap-0.5 ${className}`, children: [
|
|
214
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-3 cursor-pointer", htmlFor: switchId, children: [
|
|
215
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
216
|
+
"input",
|
|
217
|
+
{
|
|
218
|
+
id: switchId,
|
|
219
|
+
type: "checkbox",
|
|
220
|
+
role: "switch",
|
|
221
|
+
"aria-checked": checked,
|
|
222
|
+
className: [
|
|
223
|
+
"peer relative w-10 h-6 appearance-none rounded-full transition-colors",
|
|
224
|
+
"bg-surface-gray border border-outline",
|
|
225
|
+
"hover:bg-surface-overlay",
|
|
226
|
+
"focus:outline-none focus:ring-2 focus:ring-brand focus:ring-offset-2",
|
|
227
|
+
"disabled:opacity-50 disabled:cursor-not-allowed",
|
|
228
|
+
"checked:bg-brand checked:border-brand checked:hover:bg-brand-dark",
|
|
229
|
+
"after:content-[''] after:absolute after:top-1 after:left-1",
|
|
230
|
+
"after:w-4 after:h-4 after:bg-white after:rounded-full after:transition-transform",
|
|
231
|
+
"peer-checked:after:translate-x-4",
|
|
232
|
+
error ? "border-danger-border" : ""
|
|
233
|
+
].join(" "),
|
|
234
|
+
checked,
|
|
235
|
+
...props
|
|
236
|
+
}
|
|
237
|
+
),
|
|
238
|
+
(label || description) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
|
|
239
|
+
label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-base font-medium text-ink leading-tight", children: label }),
|
|
240
|
+
description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-ink-light", children: description })
|
|
241
|
+
] })
|
|
242
|
+
] }),
|
|
243
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-danger-text ml-4", children: error })
|
|
244
|
+
] });
|
|
245
|
+
}
|
|
199
246
|
var subtleClasses = {
|
|
200
247
|
brand: "bg-brand-50 text-brand border-brand-200",
|
|
201
248
|
success: "bg-success-bg text-success-text border-success-border",
|
|
@@ -392,6 +439,419 @@ function Textarea({
|
|
|
392
439
|
error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-danger-text", children: error })
|
|
393
440
|
] });
|
|
394
441
|
}
|
|
442
|
+
var themeClasses2 = {
|
|
443
|
+
info: "bg-brand-50 border-brand-200 text-brand-900",
|
|
444
|
+
success: "bg-green-50 border-green-200 text-green-900",
|
|
445
|
+
warning: "bg-amber-50 border-amber-200 text-amber-900",
|
|
446
|
+
danger: "bg-red-50 border-red-200 text-red-900"
|
|
447
|
+
};
|
|
448
|
+
var iconColors = {
|
|
449
|
+
info: "text-brand",
|
|
450
|
+
success: "text-success-icon",
|
|
451
|
+
warning: "text-warning-icon",
|
|
452
|
+
danger: "text-danger-icon"
|
|
453
|
+
};
|
|
454
|
+
var closeButtonColors = {
|
|
455
|
+
info: "hover:bg-brand-100 text-brand-600",
|
|
456
|
+
success: "hover:bg-green-100 text-green-600",
|
|
457
|
+
warning: "hover:bg-amber-100 text-amber-600",
|
|
458
|
+
danger: "hover:bg-red-100 text-red-600"
|
|
459
|
+
};
|
|
460
|
+
function Alert({
|
|
461
|
+
theme = "info",
|
|
462
|
+
title,
|
|
463
|
+
icon,
|
|
464
|
+
onClose,
|
|
465
|
+
isDismissible = false,
|
|
466
|
+
children,
|
|
467
|
+
className = "",
|
|
468
|
+
...props
|
|
469
|
+
}) {
|
|
470
|
+
const [isVisible, setIsVisible] = React9__default.default.useState(true);
|
|
471
|
+
const handleClose = () => {
|
|
472
|
+
setIsVisible(false);
|
|
473
|
+
onClose?.();
|
|
474
|
+
};
|
|
475
|
+
if (!isVisible) return null;
|
|
476
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
477
|
+
"div",
|
|
478
|
+
{
|
|
479
|
+
className: `flex gap-3 p-3 rounded-md border ${themeClasses2[theme]} ${className}`,
|
|
480
|
+
role: "alert",
|
|
481
|
+
...props,
|
|
482
|
+
children: [
|
|
483
|
+
icon && /* @__PURE__ */ jsxRuntime.jsx("div", { className: `shrink-0 mt-0.5 ${iconColors[theme]}`, children: icon }),
|
|
484
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1", children: [
|
|
485
|
+
title && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-medium", children: title }),
|
|
486
|
+
children && /* @__PURE__ */ jsxRuntime.jsx("p", { className: title ? "text-sm mt-0.5" : "text-sm", children })
|
|
487
|
+
] }),
|
|
488
|
+
isDismissible && /* @__PURE__ */ jsxRuntime.jsx(
|
|
489
|
+
"button",
|
|
490
|
+
{
|
|
491
|
+
onClick: handleClose,
|
|
492
|
+
className: `shrink-0 p-1 rounded transition-colors ${closeButtonColors[theme]}`,
|
|
493
|
+
"aria-label": "Dismiss alert",
|
|
494
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
|
|
495
|
+
}
|
|
496
|
+
)
|
|
497
|
+
]
|
|
498
|
+
}
|
|
499
|
+
);
|
|
500
|
+
}
|
|
501
|
+
function MultiSelect({
|
|
502
|
+
options,
|
|
503
|
+
value = [],
|
|
504
|
+
onChange,
|
|
505
|
+
placeholder = "Select items...",
|
|
506
|
+
label,
|
|
507
|
+
description,
|
|
508
|
+
error,
|
|
509
|
+
disabled = false,
|
|
510
|
+
searchable = true,
|
|
511
|
+
clearable = true,
|
|
512
|
+
size = "md",
|
|
513
|
+
className = "",
|
|
514
|
+
...props
|
|
515
|
+
}) {
|
|
516
|
+
const [isOpen, setIsOpen] = React9__default.default.useState(false);
|
|
517
|
+
const [searchTerm, setSearchTerm] = React9__default.default.useState("");
|
|
518
|
+
const containerRef = React9.useRef(null);
|
|
519
|
+
const inputRef = React9.useRef(null);
|
|
520
|
+
const filteredOptions = searchable ? options.filter(
|
|
521
|
+
(opt) => opt.label.toLowerCase().includes(searchTerm.toLowerCase())
|
|
522
|
+
) : options;
|
|
523
|
+
const handleSelect = (optionValue) => {
|
|
524
|
+
const newValues = value.includes(optionValue) ? value.filter((v) => v !== optionValue) : [...value, optionValue];
|
|
525
|
+
onChange?.(newValues);
|
|
526
|
+
};
|
|
527
|
+
const handleRemove = (optionValue) => {
|
|
528
|
+
const newValues = value.filter((v) => v !== optionValue);
|
|
529
|
+
onChange?.(newValues);
|
|
530
|
+
};
|
|
531
|
+
const handleClear = () => {
|
|
532
|
+
onChange?.([]);
|
|
533
|
+
setSearchTerm("");
|
|
534
|
+
};
|
|
535
|
+
React9.useEffect(() => {
|
|
536
|
+
const handleClickOutside = (event) => {
|
|
537
|
+
if (containerRef.current && !containerRef.current.contains(event.target)) {
|
|
538
|
+
setIsOpen(false);
|
|
539
|
+
}
|
|
540
|
+
};
|
|
541
|
+
if (isOpen) {
|
|
542
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
543
|
+
}
|
|
544
|
+
return () => {
|
|
545
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
546
|
+
};
|
|
547
|
+
}, [isOpen]);
|
|
548
|
+
const sizeClasses13 = {
|
|
549
|
+
sm: "h-7 px-2 text-sm",
|
|
550
|
+
md: "h-8 px-3 text-base",
|
|
551
|
+
lg: "h-9 px-4 text-base"
|
|
552
|
+
};
|
|
553
|
+
const selectedOptions = options.filter((opt) => value.includes(opt.value));
|
|
554
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, ...props, children: [
|
|
555
|
+
label && /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium text-ink mb-1", children: label }),
|
|
556
|
+
description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-ink-light mb-1.5", children: description }),
|
|
557
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", ref: containerRef, children: [
|
|
558
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
559
|
+
"div",
|
|
560
|
+
{
|
|
561
|
+
className: [
|
|
562
|
+
"flex flex-wrap gap-1 items-center border rounded-md transition-colors",
|
|
563
|
+
"focus-within:ring-2 focus-within:ring-brand focus-within:ring-offset-1",
|
|
564
|
+
disabled ? "bg-surface-gray opacity-50 cursor-not-allowed" : "bg-white",
|
|
565
|
+
error ? "border-danger-border" : "border-outline",
|
|
566
|
+
sizeClasses13[size]
|
|
567
|
+
].join(" "),
|
|
568
|
+
onClick: () => !disabled && setIsOpen(!isOpen),
|
|
569
|
+
children: [
|
|
570
|
+
selectedOptions.map((opt) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
571
|
+
"div",
|
|
572
|
+
{
|
|
573
|
+
className: "inline-flex items-center gap-1 bg-brand-50 text-brand px-2 py-0.5 rounded text-xs font-medium",
|
|
574
|
+
children: [
|
|
575
|
+
opt.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0", children: opt.icon }),
|
|
576
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: opt.label }),
|
|
577
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
578
|
+
"button",
|
|
579
|
+
{
|
|
580
|
+
onClick: (e) => {
|
|
581
|
+
e.stopPropagation();
|
|
582
|
+
handleRemove(opt.value);
|
|
583
|
+
},
|
|
584
|
+
className: "shrink-0 hover:text-brand-dark",
|
|
585
|
+
children: "\xD7"
|
|
586
|
+
}
|
|
587
|
+
)
|
|
588
|
+
]
|
|
589
|
+
},
|
|
590
|
+
opt.value
|
|
591
|
+
)),
|
|
592
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
593
|
+
"input",
|
|
594
|
+
{
|
|
595
|
+
ref: inputRef,
|
|
596
|
+
type: "text",
|
|
597
|
+
placeholder: value.length === 0 ? placeholder : "",
|
|
598
|
+
value: searchTerm,
|
|
599
|
+
onChange: (e) => setSearchTerm(e.target.value),
|
|
600
|
+
onFocus: () => !disabled && setIsOpen(true),
|
|
601
|
+
disabled,
|
|
602
|
+
className: "flex-1 min-w-[40px] bg-transparent border-0 outline-none text-sm"
|
|
603
|
+
}
|
|
604
|
+
),
|
|
605
|
+
clearable && value.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
606
|
+
"button",
|
|
607
|
+
{
|
|
608
|
+
onClick: (e) => {
|
|
609
|
+
e.stopPropagation();
|
|
610
|
+
handleClear();
|
|
611
|
+
},
|
|
612
|
+
className: "shrink-0 text-ink-light hover:text-ink",
|
|
613
|
+
children: "\u2715"
|
|
614
|
+
}
|
|
615
|
+
)
|
|
616
|
+
]
|
|
617
|
+
}
|
|
618
|
+
),
|
|
619
|
+
isOpen && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-full mt-1 left-0 right-0 z-50 bg-white border border-outline rounded-md shadow-lg py-1", children: filteredOptions.length > 0 ? filteredOptions.map((opt) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
620
|
+
"button",
|
|
621
|
+
{
|
|
622
|
+
onClick: () => {
|
|
623
|
+
handleSelect(opt.value);
|
|
624
|
+
if (!opt.disabled) {
|
|
625
|
+
inputRef.current?.focus();
|
|
626
|
+
}
|
|
627
|
+
},
|
|
628
|
+
disabled: opt.disabled,
|
|
629
|
+
className: [
|
|
630
|
+
"w-full px-3 py-2 text-left text-sm flex items-center gap-2 transition-colors",
|
|
631
|
+
opt.disabled ? "opacity-50 cursor-not-allowed" : "hover:bg-surface-gray",
|
|
632
|
+
value.includes(opt.value) ? "bg-brand-50" : ""
|
|
633
|
+
].join(" "),
|
|
634
|
+
children: [
|
|
635
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
636
|
+
"input",
|
|
637
|
+
{
|
|
638
|
+
type: "checkbox",
|
|
639
|
+
checked: value.includes(opt.value),
|
|
640
|
+
readOnly: true,
|
|
641
|
+
className: "w-4 h-4"
|
|
642
|
+
}
|
|
643
|
+
),
|
|
644
|
+
opt.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0", children: opt.icon }),
|
|
645
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: opt.label })
|
|
646
|
+
]
|
|
647
|
+
},
|
|
648
|
+
opt.value
|
|
649
|
+
)) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-2 text-sm text-ink-light", children: "No options found" }) })
|
|
650
|
+
] }),
|
|
651
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-danger-text mt-1", children: error })
|
|
652
|
+
] });
|
|
653
|
+
}
|
|
654
|
+
function FormControl({
|
|
655
|
+
label,
|
|
656
|
+
description,
|
|
657
|
+
error,
|
|
658
|
+
required = false,
|
|
659
|
+
helperText,
|
|
660
|
+
children,
|
|
661
|
+
className = "",
|
|
662
|
+
...props
|
|
663
|
+
}) {
|
|
664
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex flex-col gap-1.5 ${className}`, ...props, children: [
|
|
665
|
+
(label || description) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-0.5", children: [
|
|
666
|
+
label && /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "text-sm font-medium text-ink", children: [
|
|
667
|
+
label,
|
|
668
|
+
required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-danger-icon ml-1", children: "*" })
|
|
669
|
+
] }),
|
|
670
|
+
description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-ink-light", children: description })
|
|
671
|
+
] }),
|
|
672
|
+
children,
|
|
673
|
+
error && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-danger-text flex items-center gap-1", children: [
|
|
674
|
+
/* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-3.5 h-3.5 shrink-0", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsxRuntime.jsx("path", { fillRule: "evenodd", d: "M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z", clipRule: "evenodd" }) }),
|
|
675
|
+
error
|
|
676
|
+
] }),
|
|
677
|
+
helperText && !error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-ink-light", children: helperText })
|
|
678
|
+
] });
|
|
679
|
+
}
|
|
680
|
+
function Tabs({
|
|
681
|
+
tabs,
|
|
682
|
+
activeTab,
|
|
683
|
+
onTabChange,
|
|
684
|
+
variant = "underline",
|
|
685
|
+
className = "",
|
|
686
|
+
tabsClassName = "",
|
|
687
|
+
contentClassName = ""
|
|
688
|
+
}) {
|
|
689
|
+
const [internalActiveTab, setInternalActiveTab] = React9__default.default.useState(activeTab || tabs[0]?.value || "");
|
|
690
|
+
const active = activeTab !== void 0 ? activeTab : internalActiveTab;
|
|
691
|
+
const handleTabChange = (value) => {
|
|
692
|
+
setInternalActiveTab(value);
|
|
693
|
+
onTabChange?.(value);
|
|
694
|
+
};
|
|
695
|
+
const baseTabClasses = "px-3 py-2 font-medium text-sm rounded-t-md transition-colors whitespace-nowrap";
|
|
696
|
+
const variantClasses2 = {
|
|
697
|
+
underline: {
|
|
698
|
+
base: "border-b-2 border-transparent text-ink-light hover:text-ink hover:border-outline",
|
|
699
|
+
active: "border-brand text-brand",
|
|
700
|
+
disabled: "opacity-50 cursor-not-allowed"
|
|
701
|
+
},
|
|
702
|
+
soft: {
|
|
703
|
+
base: "text-ink-light hover:text-ink hover:bg-surface-gray",
|
|
704
|
+
active: "bg-brand text-white",
|
|
705
|
+
disabled: "opacity-50 cursor-not-allowed"
|
|
706
|
+
}
|
|
707
|
+
};
|
|
708
|
+
const variantStyle = variantClasses2[variant];
|
|
709
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, children: [
|
|
710
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
711
|
+
"div",
|
|
712
|
+
{
|
|
713
|
+
className: `flex gap-0 border-b border-outline ${tabsClassName}`,
|
|
714
|
+
role: "tablist",
|
|
715
|
+
children: tabs.map((tab) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
716
|
+
"button",
|
|
717
|
+
{
|
|
718
|
+
role: "tab",
|
|
719
|
+
"aria-selected": active === tab.value,
|
|
720
|
+
"aria-disabled": tab.disabled,
|
|
721
|
+
onClick: () => !tab.disabled && handleTabChange(tab.value),
|
|
722
|
+
disabled: tab.disabled,
|
|
723
|
+
className: [
|
|
724
|
+
baseTabClasses,
|
|
725
|
+
active === tab.value ? variantStyle.active : variantStyle.base,
|
|
726
|
+
tab.disabled ? variantStyle.disabled : ""
|
|
727
|
+
].join(" "),
|
|
728
|
+
children: [
|
|
729
|
+
tab.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-block mr-1", children: tab.icon }),
|
|
730
|
+
tab.label
|
|
731
|
+
]
|
|
732
|
+
},
|
|
733
|
+
tab.value
|
|
734
|
+
))
|
|
735
|
+
}
|
|
736
|
+
),
|
|
737
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: contentClassName, role: "tabpanel", children: tabs.find((tab) => tab.value === active)?.content })
|
|
738
|
+
] });
|
|
739
|
+
}
|
|
740
|
+
function Breadcrumbs({
|
|
741
|
+
items,
|
|
742
|
+
separator = "/",
|
|
743
|
+
className = "",
|
|
744
|
+
...props
|
|
745
|
+
}) {
|
|
746
|
+
return /* @__PURE__ */ jsxRuntime.jsx("nav", { className: `flex items-center gap-0 text-sm ${className}`, ...props, children: items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs(React9__default.default.Fragment, { children: [
|
|
747
|
+
index > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ink-light px-1.5", children: separator }),
|
|
748
|
+
item.href ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
749
|
+
"a",
|
|
750
|
+
{
|
|
751
|
+
href: item.href,
|
|
752
|
+
className: [
|
|
753
|
+
"flex items-center gap-1 rounded px-1.5 py-1 transition-colors",
|
|
754
|
+
item.isActive ? "text-ink font-medium" : "text-brand hover:bg-brand-50 cursor-pointer"
|
|
755
|
+
].join(" "),
|
|
756
|
+
children: [
|
|
757
|
+
item.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0", children: item.icon }),
|
|
758
|
+
item.label
|
|
759
|
+
]
|
|
760
|
+
}
|
|
761
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
762
|
+
"button",
|
|
763
|
+
{
|
|
764
|
+
onClick: item.onClick,
|
|
765
|
+
disabled: !item.onClick && !item.isActive,
|
|
766
|
+
className: [
|
|
767
|
+
"flex items-center gap-1 rounded px-1.5 py-1 transition-colors",
|
|
768
|
+
item.isActive ? "text-ink font-medium cursor-default" : item.onClick ? "text-brand hover:bg-brand-50 cursor-pointer" : "text-ink-light cursor-default"
|
|
769
|
+
].join(" "),
|
|
770
|
+
children: [
|
|
771
|
+
item.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0", children: item.icon }),
|
|
772
|
+
item.label
|
|
773
|
+
]
|
|
774
|
+
}
|
|
775
|
+
)
|
|
776
|
+
] }, index)) });
|
|
777
|
+
}
|
|
778
|
+
function Dropdown({
|
|
779
|
+
items,
|
|
780
|
+
trigger,
|
|
781
|
+
placement = "bottom",
|
|
782
|
+
isOpen: controlledIsOpen,
|
|
783
|
+
onOpenChange,
|
|
784
|
+
className = "",
|
|
785
|
+
triggerClassName = "",
|
|
786
|
+
menuClassName = ""
|
|
787
|
+
}) {
|
|
788
|
+
const [internalIsOpen, setInternalIsOpen] = React9__default.default.useState(false);
|
|
789
|
+
const containerRef = React9.useRef(null);
|
|
790
|
+
const menuRef = React9.useRef(null);
|
|
791
|
+
const isOpen = controlledIsOpen !== void 0 ? controlledIsOpen : internalIsOpen;
|
|
792
|
+
const toggleOpen = () => {
|
|
793
|
+
const newState = !isOpen;
|
|
794
|
+
setInternalIsOpen(newState);
|
|
795
|
+
onOpenChange?.(newState);
|
|
796
|
+
};
|
|
797
|
+
React9.useEffect(() => {
|
|
798
|
+
const handleClickOutside = (event) => {
|
|
799
|
+
if (containerRef.current && !containerRef.current.contains(event.target)) {
|
|
800
|
+
setInternalIsOpen(false);
|
|
801
|
+
onOpenChange?.(false);
|
|
802
|
+
}
|
|
803
|
+
};
|
|
804
|
+
if (isOpen) {
|
|
805
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
806
|
+
}
|
|
807
|
+
return () => {
|
|
808
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
809
|
+
};
|
|
810
|
+
}, [isOpen, onOpenChange]);
|
|
811
|
+
const placementClasses2 = {
|
|
812
|
+
bottom: "top-full mt-1 left-0",
|
|
813
|
+
top: "bottom-full mb-1 left-0",
|
|
814
|
+
left: "right-full mr-1 top-0",
|
|
815
|
+
right: "left-full ml-1 top-0"
|
|
816
|
+
};
|
|
817
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `relative inline-block ${className}`, ref: containerRef, children: [
|
|
818
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
819
|
+
"button",
|
|
820
|
+
{
|
|
821
|
+
onClick: toggleOpen,
|
|
822
|
+
className: `inline-flex items-center gap-1.5 ${triggerClassName}`,
|
|
823
|
+
children: trigger
|
|
824
|
+
}
|
|
825
|
+
),
|
|
826
|
+
isOpen && /* @__PURE__ */ jsxRuntime.jsx(
|
|
827
|
+
"div",
|
|
828
|
+
{
|
|
829
|
+
ref: menuRef,
|
|
830
|
+
className: `absolute ${placementClasses2[placement]} z-50 min-w-[160px] bg-surface-default border border-outline rounded-md shadow-lg py-1 ${menuClassName}`,
|
|
831
|
+
children: items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
832
|
+
"button",
|
|
833
|
+
{
|
|
834
|
+
onClick: () => {
|
|
835
|
+
item.onClick?.();
|
|
836
|
+
setInternalIsOpen(false);
|
|
837
|
+
onOpenChange?.(false);
|
|
838
|
+
},
|
|
839
|
+
disabled: item.disabled,
|
|
840
|
+
className: [
|
|
841
|
+
"w-full px-3 py-2 text-left text-sm flex items-center gap-2 transition-colors",
|
|
842
|
+
item.disabled ? "opacity-50 cursor-not-allowed" : item.isDanger ? "text-danger-text hover:bg-danger-bg" : "text-ink hover:bg-surface-gray"
|
|
843
|
+
].join(" "),
|
|
844
|
+
children: [
|
|
845
|
+
item.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0", children: item.icon }),
|
|
846
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: item.label })
|
|
847
|
+
]
|
|
848
|
+
},
|
|
849
|
+
index
|
|
850
|
+
))
|
|
851
|
+
}
|
|
852
|
+
)
|
|
853
|
+
] });
|
|
854
|
+
}
|
|
395
855
|
var sizeClasses7 = {
|
|
396
856
|
sm: "max-w-sm",
|
|
397
857
|
md: "max-w-md",
|
|
@@ -407,8 +867,8 @@ function Dialog({
|
|
|
407
867
|
footer,
|
|
408
868
|
className = ""
|
|
409
869
|
}) {
|
|
410
|
-
const overlayRef =
|
|
411
|
-
|
|
870
|
+
const overlayRef = React9.useRef(null);
|
|
871
|
+
React9.useEffect(() => {
|
|
412
872
|
if (!open) return;
|
|
413
873
|
const onKey = (e) => {
|
|
414
874
|
if (e.key === "Escape") onClose();
|
|
@@ -416,7 +876,7 @@ function Dialog({
|
|
|
416
876
|
document.addEventListener("keydown", onKey);
|
|
417
877
|
return () => document.removeEventListener("keydown", onKey);
|
|
418
878
|
}, [open, onClose]);
|
|
419
|
-
|
|
879
|
+
React9.useEffect(() => {
|
|
420
880
|
document.body.style.overflow = open ? "hidden" : "";
|
|
421
881
|
return () => {
|
|
422
882
|
document.body.style.overflow = "";
|
|
@@ -500,7 +960,7 @@ function Toast({
|
|
|
500
960
|
onClose,
|
|
501
961
|
className = ""
|
|
502
962
|
}) {
|
|
503
|
-
|
|
963
|
+
React9.useEffect(() => {
|
|
504
964
|
if (!duration || !onClose) return;
|
|
505
965
|
const timer = setTimeout(onClose, duration);
|
|
506
966
|
return () => clearTimeout(timer);
|
|
@@ -547,8 +1007,8 @@ function Tooltip({
|
|
|
547
1007
|
children,
|
|
548
1008
|
className = ""
|
|
549
1009
|
}) {
|
|
550
|
-
const [visible, setVisible] =
|
|
551
|
-
const timerRef =
|
|
1010
|
+
const [visible, setVisible] = React9.useState(false);
|
|
1011
|
+
const timerRef = React9.useRef(null);
|
|
552
1012
|
const show = () => {
|
|
553
1013
|
timerRef.current = setTimeout(() => setVisible(true), delay);
|
|
554
1014
|
};
|
|
@@ -556,7 +1016,7 @@ function Tooltip({
|
|
|
556
1016
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
557
1017
|
setVisible(false);
|
|
558
1018
|
};
|
|
559
|
-
|
|
1019
|
+
React9.useEffect(() => () => {
|
|
560
1020
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
561
1021
|
}, []);
|
|
562
1022
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -604,6 +1064,961 @@ function Link({
|
|
|
604
1064
|
}
|
|
605
1065
|
);
|
|
606
1066
|
}
|
|
1067
|
+
function FileUploader({
|
|
1068
|
+
label,
|
|
1069
|
+
description,
|
|
1070
|
+
error,
|
|
1071
|
+
hint,
|
|
1072
|
+
onFilesChange,
|
|
1073
|
+
maxSize,
|
|
1074
|
+
accept = "*",
|
|
1075
|
+
multiple = false,
|
|
1076
|
+
disabled = false,
|
|
1077
|
+
className = "",
|
|
1078
|
+
...props
|
|
1079
|
+
}) {
|
|
1080
|
+
const [dragActive, setDragActive] = React9__default.default.useState(false);
|
|
1081
|
+
const [files, setFiles] = React9__default.default.useState([]);
|
|
1082
|
+
const inputRef = React9__default.default.useRef(null);
|
|
1083
|
+
const handleFiles = (fileList) => {
|
|
1084
|
+
if (!fileList) return;
|
|
1085
|
+
let newFiles = Array.from(fileList);
|
|
1086
|
+
if (maxSize) {
|
|
1087
|
+
newFiles = newFiles.filter((file) => file.size <= maxSize);
|
|
1088
|
+
}
|
|
1089
|
+
if (!multiple && newFiles.length > 0) {
|
|
1090
|
+
newFiles = [newFiles[0]];
|
|
1091
|
+
}
|
|
1092
|
+
setFiles(newFiles);
|
|
1093
|
+
onFilesChange?.(newFiles);
|
|
1094
|
+
};
|
|
1095
|
+
const handleChange = (e) => {
|
|
1096
|
+
handleFiles(e.target.files);
|
|
1097
|
+
};
|
|
1098
|
+
const handleDrag = (e) => {
|
|
1099
|
+
e.preventDefault();
|
|
1100
|
+
e.stopPropagation();
|
|
1101
|
+
if (e.type === "dragenter" || e.type === "dragover") {
|
|
1102
|
+
setDragActive(true);
|
|
1103
|
+
} else if (e.type === "dragleave") {
|
|
1104
|
+
setDragActive(false);
|
|
1105
|
+
}
|
|
1106
|
+
};
|
|
1107
|
+
const handleDrop = (e) => {
|
|
1108
|
+
e.preventDefault();
|
|
1109
|
+
e.stopPropagation();
|
|
1110
|
+
setDragActive(false);
|
|
1111
|
+
handleFiles(e.dataTransfer.files);
|
|
1112
|
+
};
|
|
1113
|
+
const handleRemoveFile = (index) => {
|
|
1114
|
+
const newFiles = files.filter((_, i) => i !== index);
|
|
1115
|
+
setFiles(newFiles);
|
|
1116
|
+
onFilesChange?.(newFiles);
|
|
1117
|
+
};
|
|
1118
|
+
const handleClick = () => {
|
|
1119
|
+
inputRef.current?.click();
|
|
1120
|
+
};
|
|
1121
|
+
const formatFileSize = (bytes) => {
|
|
1122
|
+
if (bytes === 0) return "0 Bytes";
|
|
1123
|
+
const k = 1024;
|
|
1124
|
+
const sizes = ["Bytes", "KB", "MB", "GB"];
|
|
1125
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
1126
|
+
return Math.round(bytes / Math.pow(k, i) * 100) / 100 + " " + sizes[i];
|
|
1127
|
+
};
|
|
1128
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, children: [
|
|
1129
|
+
label && /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium text-ink mb-1", children: label }),
|
|
1130
|
+
description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-ink-light mb-2", children: description }),
|
|
1131
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1132
|
+
"div",
|
|
1133
|
+
{
|
|
1134
|
+
onDragEnter: handleDrag,
|
|
1135
|
+
onDragLeave: handleDrag,
|
|
1136
|
+
onDragOver: handleDrag,
|
|
1137
|
+
onDrop: handleDrop,
|
|
1138
|
+
onClick: handleClick,
|
|
1139
|
+
className: [
|
|
1140
|
+
"relative px-4 py-6 border-2 border-dashed rounded-md transition-colors cursor-pointer",
|
|
1141
|
+
disabled ? "opacity-50 cursor-not-allowed" : "",
|
|
1142
|
+
dragActive ? "border-brand bg-brand-50" : "border-outline hover:border-brand",
|
|
1143
|
+
error ? "border-danger-border" : ""
|
|
1144
|
+
].join(" "),
|
|
1145
|
+
children: [
|
|
1146
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1147
|
+
"input",
|
|
1148
|
+
{
|
|
1149
|
+
ref: inputRef,
|
|
1150
|
+
type: "file",
|
|
1151
|
+
accept,
|
|
1152
|
+
multiple,
|
|
1153
|
+
onChange: handleChange,
|
|
1154
|
+
disabled,
|
|
1155
|
+
className: "hidden",
|
|
1156
|
+
...props
|
|
1157
|
+
}
|
|
1158
|
+
),
|
|
1159
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center gap-2", children: [
|
|
1160
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1161
|
+
"svg",
|
|
1162
|
+
{
|
|
1163
|
+
className: "w-8 h-8 text-brand",
|
|
1164
|
+
fill: "none",
|
|
1165
|
+
stroke: "currentColor",
|
|
1166
|
+
viewBox: "0 0 24 24",
|
|
1167
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1168
|
+
"path",
|
|
1169
|
+
{
|
|
1170
|
+
strokeLinecap: "round",
|
|
1171
|
+
strokeLinejoin: "round",
|
|
1172
|
+
strokeWidth: 2,
|
|
1173
|
+
d: "M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M9 19l3 3m0 0l3-3m-3 3v-6"
|
|
1174
|
+
}
|
|
1175
|
+
)
|
|
1176
|
+
}
|
|
1177
|
+
),
|
|
1178
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
|
|
1179
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-ink", children: "Drag files here or click to upload" }),
|
|
1180
|
+
hint && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-ink-light mt-1", children: hint })
|
|
1181
|
+
] })
|
|
1182
|
+
] })
|
|
1183
|
+
]
|
|
1184
|
+
}
|
|
1185
|
+
),
|
|
1186
|
+
files.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 space-y-1.5", children: files.map((file, index) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1187
|
+
"div",
|
|
1188
|
+
{
|
|
1189
|
+
className: "flex items-center justify-between p-2 bg-surface-gray rounded border border-outline",
|
|
1190
|
+
children: [
|
|
1191
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [
|
|
1192
|
+
/* @__PURE__ */ jsxRuntime.jsxs("svg", { className: "w-4 h-4 text-brand shrink-0", fill: "currentColor", viewBox: "0 0 20 20", children: [
|
|
1193
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 16.5a1.5 1.5 0 11-3 0 1.5 1.5 0 013 0zM15 16.5a1.5 1.5 0 11-3 0 1.5 1.5 0 013 0z" }),
|
|
1194
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 4a1 1 0 00-1 1v10a1 1 0 001 1h1.05a2.5 2.5 0 014.9 0H10a1 1 0 001-1V5a1 1 0 00-1-1H3zM14 7a1 1 0 00-1 1v6.05A2.5 2.5 0 0015.95 16H17a1 1 0 001-1v-5a1 1 0 00-.293-.707l-2-2A1 1 0 0015 7h-1z" })
|
|
1195
|
+
] }),
|
|
1196
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
|
|
1197
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-ink truncate", children: file.name }),
|
|
1198
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-ink-light", children: formatFileSize(file.size) })
|
|
1199
|
+
] })
|
|
1200
|
+
] }),
|
|
1201
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1202
|
+
"button",
|
|
1203
|
+
{
|
|
1204
|
+
onClick: (e) => {
|
|
1205
|
+
e.stopPropagation();
|
|
1206
|
+
handleRemoveFile(index);
|
|
1207
|
+
},
|
|
1208
|
+
className: "p-1 hover:bg-surface-overlay rounded transition-colors",
|
|
1209
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-4 h-4 text-danger-text", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsxRuntime.jsx("path", { fillRule: "evenodd", d: "M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z", clipRule: "evenodd" }) })
|
|
1210
|
+
}
|
|
1211
|
+
)
|
|
1212
|
+
]
|
|
1213
|
+
},
|
|
1214
|
+
`${file.name}-${index}`
|
|
1215
|
+
)) }),
|
|
1216
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-danger-text mt-1", children: error })
|
|
1217
|
+
] });
|
|
1218
|
+
}
|
|
1219
|
+
function DatePicker({
|
|
1220
|
+
value = "",
|
|
1221
|
+
onChange,
|
|
1222
|
+
label,
|
|
1223
|
+
description,
|
|
1224
|
+
error,
|
|
1225
|
+
min,
|
|
1226
|
+
max,
|
|
1227
|
+
placeholder = "Select a date",
|
|
1228
|
+
disabled = false,
|
|
1229
|
+
className = "",
|
|
1230
|
+
...props
|
|
1231
|
+
}) {
|
|
1232
|
+
const [isOpen, setIsOpen] = React9__default.default.useState(false);
|
|
1233
|
+
const containerRef = React9.useRef(null);
|
|
1234
|
+
const handleDateChange = (e) => {
|
|
1235
|
+
onChange?.(e.target.value);
|
|
1236
|
+
};
|
|
1237
|
+
React9.useEffect(() => {
|
|
1238
|
+
const handleClickOutside = (event) => {
|
|
1239
|
+
if (containerRef.current && !containerRef.current.contains(event.target)) {
|
|
1240
|
+
setIsOpen(false);
|
|
1241
|
+
}
|
|
1242
|
+
};
|
|
1243
|
+
if (isOpen) {
|
|
1244
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
1245
|
+
}
|
|
1246
|
+
return () => {
|
|
1247
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
1248
|
+
};
|
|
1249
|
+
}, [isOpen]);
|
|
1250
|
+
const formatDateForDisplay = (dateString) => {
|
|
1251
|
+
if (!dateString) return "";
|
|
1252
|
+
const date = new Date(dateString);
|
|
1253
|
+
return date.toLocaleDateString("en-US", {
|
|
1254
|
+
year: "numeric",
|
|
1255
|
+
month: "long",
|
|
1256
|
+
day: "numeric"
|
|
1257
|
+
});
|
|
1258
|
+
};
|
|
1259
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, ref: containerRef, children: [
|
|
1260
|
+
label && /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium text-ink mb-1", children: label }),
|
|
1261
|
+
description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-ink-light mb-1.5", children: description }),
|
|
1262
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
1263
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
1264
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1265
|
+
"input",
|
|
1266
|
+
{
|
|
1267
|
+
type: "text",
|
|
1268
|
+
value: value ? formatDateForDisplay(value) : "",
|
|
1269
|
+
onChange: handleDateChange,
|
|
1270
|
+
placeholder,
|
|
1271
|
+
disabled,
|
|
1272
|
+
readOnly: true,
|
|
1273
|
+
onClick: () => !disabled && setIsOpen(!isOpen),
|
|
1274
|
+
className: [
|
|
1275
|
+
"w-full px-3 py-2 border rounded-md text-base transition-colors",
|
|
1276
|
+
"focus:outline-none focus:ring-2 focus:ring-brand focus:ring-offset-1",
|
|
1277
|
+
"cursor-pointer",
|
|
1278
|
+
disabled ? "bg-surface-gray opacity-50 cursor-not-allowed" : "bg-white",
|
|
1279
|
+
error ? "border-danger-border" : "border-outline"
|
|
1280
|
+
].join(" ")
|
|
1281
|
+
}
|
|
1282
|
+
),
|
|
1283
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1284
|
+
"button",
|
|
1285
|
+
{
|
|
1286
|
+
type: "button",
|
|
1287
|
+
onClick: () => !disabled && setIsOpen(!isOpen),
|
|
1288
|
+
className: "absolute right-3 top-1/2 -translate-y-1/2 text-ink-light hover:text-ink",
|
|
1289
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M8 7V3m8 4V3m-9 8h18M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" }) })
|
|
1290
|
+
}
|
|
1291
|
+
)
|
|
1292
|
+
] }),
|
|
1293
|
+
isOpen && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1294
|
+
"input",
|
|
1295
|
+
{
|
|
1296
|
+
type: "date",
|
|
1297
|
+
value,
|
|
1298
|
+
onChange: handleDateChange,
|
|
1299
|
+
min,
|
|
1300
|
+
max,
|
|
1301
|
+
disabled,
|
|
1302
|
+
autoFocus: true,
|
|
1303
|
+
className: "absolute inset-0 opacity-0 w-full h-full cursor-pointer",
|
|
1304
|
+
...props
|
|
1305
|
+
}
|
|
1306
|
+
)
|
|
1307
|
+
] }),
|
|
1308
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-danger-text mt-1", children: error })
|
|
1309
|
+
] });
|
|
1310
|
+
}
|
|
1311
|
+
function TimePicker({
|
|
1312
|
+
value = "",
|
|
1313
|
+
onChange,
|
|
1314
|
+
label,
|
|
1315
|
+
description,
|
|
1316
|
+
error,
|
|
1317
|
+
placeholder = "Select a time",
|
|
1318
|
+
format = "24h",
|
|
1319
|
+
disabled = false,
|
|
1320
|
+
className = "",
|
|
1321
|
+
...props
|
|
1322
|
+
}) {
|
|
1323
|
+
const [isOpen, setIsOpen] = React9__default.default.useState(false);
|
|
1324
|
+
const containerRef = React9.useRef(null);
|
|
1325
|
+
const handleTimeChange = (e) => {
|
|
1326
|
+
onChange?.(e.target.value);
|
|
1327
|
+
};
|
|
1328
|
+
React9.useEffect(() => {
|
|
1329
|
+
const handleClickOutside = (event) => {
|
|
1330
|
+
if (containerRef.current && !containerRef.current.contains(event.target)) {
|
|
1331
|
+
setIsOpen(false);
|
|
1332
|
+
}
|
|
1333
|
+
};
|
|
1334
|
+
if (isOpen) {
|
|
1335
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
1336
|
+
}
|
|
1337
|
+
return () => {
|
|
1338
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
1339
|
+
};
|
|
1340
|
+
}, [isOpen]);
|
|
1341
|
+
const formatTimeForDisplay = (timeString) => {
|
|
1342
|
+
if (!timeString) return "";
|
|
1343
|
+
const [hours, minutes] = timeString.split(":");
|
|
1344
|
+
if (format === "12h") {
|
|
1345
|
+
const h = parseInt(hours, 10);
|
|
1346
|
+
const period = h >= 12 ? "PM" : "AM";
|
|
1347
|
+
const displayHours = h > 12 ? h - 12 : h === 0 ? 12 : h;
|
|
1348
|
+
return `${displayHours.toString().padStart(2, "0")}:${minutes} ${period}`;
|
|
1349
|
+
}
|
|
1350
|
+
return `${hours}:${minutes}`;
|
|
1351
|
+
};
|
|
1352
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, ref: containerRef, children: [
|
|
1353
|
+
label && /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium text-ink mb-1", children: label }),
|
|
1354
|
+
description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-ink-light mb-1.5", children: description }),
|
|
1355
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
1356
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
1357
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1358
|
+
"input",
|
|
1359
|
+
{
|
|
1360
|
+
type: "text",
|
|
1361
|
+
value: value ? formatTimeForDisplay(value) : "",
|
|
1362
|
+
onChange: handleTimeChange,
|
|
1363
|
+
placeholder,
|
|
1364
|
+
disabled,
|
|
1365
|
+
readOnly: true,
|
|
1366
|
+
onClick: () => !disabled && setIsOpen(!isOpen),
|
|
1367
|
+
className: [
|
|
1368
|
+
"w-full px-3 py-2 border rounded-md text-base transition-colors",
|
|
1369
|
+
"focus:outline-none focus:ring-2 focus:ring-brand focus:ring-offset-1",
|
|
1370
|
+
"cursor-pointer",
|
|
1371
|
+
disabled ? "bg-surface-gray opacity-50 cursor-not-allowed" : "bg-white",
|
|
1372
|
+
error ? "border-danger-border" : "border-outline"
|
|
1373
|
+
].join(" ")
|
|
1374
|
+
}
|
|
1375
|
+
),
|
|
1376
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1377
|
+
"button",
|
|
1378
|
+
{
|
|
1379
|
+
type: "button",
|
|
1380
|
+
onClick: () => !disabled && setIsOpen(!isOpen),
|
|
1381
|
+
className: "absolute right-3 top-1/2 -translate-y-1/2 text-ink-light hover:text-ink",
|
|
1382
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" }) })
|
|
1383
|
+
}
|
|
1384
|
+
)
|
|
1385
|
+
] }),
|
|
1386
|
+
isOpen && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1387
|
+
"input",
|
|
1388
|
+
{
|
|
1389
|
+
type: "time",
|
|
1390
|
+
value,
|
|
1391
|
+
onChange: handleTimeChange,
|
|
1392
|
+
disabled,
|
|
1393
|
+
autoFocus: true,
|
|
1394
|
+
className: "absolute inset-0 opacity-0 w-full h-full cursor-pointer",
|
|
1395
|
+
...props
|
|
1396
|
+
}
|
|
1397
|
+
)
|
|
1398
|
+
] }),
|
|
1399
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-danger-text mt-1", children: error })
|
|
1400
|
+
] });
|
|
1401
|
+
}
|
|
1402
|
+
var sizeClasses8 = {
|
|
1403
|
+
sm: "h-1.5",
|
|
1404
|
+
md: "h-2.5",
|
|
1405
|
+
lg: "h-4"
|
|
1406
|
+
};
|
|
1407
|
+
var themeClasses3 = {
|
|
1408
|
+
brand: "bg-brand",
|
|
1409
|
+
success: "bg-success-icon",
|
|
1410
|
+
warning: "bg-warning-icon",
|
|
1411
|
+
danger: "bg-danger-icon"
|
|
1412
|
+
};
|
|
1413
|
+
function Progress({
|
|
1414
|
+
value,
|
|
1415
|
+
label,
|
|
1416
|
+
size = "md",
|
|
1417
|
+
theme = "brand",
|
|
1418
|
+
showLabel = false,
|
|
1419
|
+
striped = false,
|
|
1420
|
+
animated = false,
|
|
1421
|
+
className = "",
|
|
1422
|
+
...props
|
|
1423
|
+
}) {
|
|
1424
|
+
const clampedValue = Math.min(Math.max(value, 0), 100);
|
|
1425
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, ...props, children: [
|
|
1426
|
+
(label || showLabel) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-1.5", children: [
|
|
1427
|
+
label && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-ink", children: label }),
|
|
1428
|
+
showLabel && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm font-medium text-ink-light", children: [
|
|
1429
|
+
clampedValue,
|
|
1430
|
+
"%"
|
|
1431
|
+
] })
|
|
1432
|
+
] }),
|
|
1433
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-full bg-surface-gray rounded-full overflow-hidden ${sizeClasses8[size]}`, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1434
|
+
"div",
|
|
1435
|
+
{
|
|
1436
|
+
className: [
|
|
1437
|
+
`${themeClasses3[theme]} ${sizeClasses8[size]} rounded-full transition-all duration-300`,
|
|
1438
|
+
striped ? "bg-gradient-to-r from-transparent to-white opacity-30" : "",
|
|
1439
|
+
animated ? "animate-pulse" : ""
|
|
1440
|
+
].join(" "),
|
|
1441
|
+
style: { width: `${clampedValue}%` }
|
|
1442
|
+
}
|
|
1443
|
+
) })
|
|
1444
|
+
] });
|
|
1445
|
+
}
|
|
1446
|
+
var sizeClasses9 = {
|
|
1447
|
+
sm: "w-4 h-4",
|
|
1448
|
+
md: "w-5 h-5",
|
|
1449
|
+
lg: "w-6 h-6"
|
|
1450
|
+
};
|
|
1451
|
+
var colorClasses2 = {
|
|
1452
|
+
yellow: "text-yellow-400",
|
|
1453
|
+
brand: "text-brand",
|
|
1454
|
+
danger: "text-danger-icon"
|
|
1455
|
+
};
|
|
1456
|
+
function Rating({
|
|
1457
|
+
value = 0,
|
|
1458
|
+
onChange,
|
|
1459
|
+
count = 5,
|
|
1460
|
+
size = "md",
|
|
1461
|
+
readonly = false,
|
|
1462
|
+
label,
|
|
1463
|
+
color = "yellow",
|
|
1464
|
+
className = "",
|
|
1465
|
+
...props
|
|
1466
|
+
}) {
|
|
1467
|
+
const [hoverValue, setHoverValue] = React9__default.default.useState(0);
|
|
1468
|
+
const displayValue = hoverValue || value;
|
|
1469
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, ...props, children: [
|
|
1470
|
+
label && /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium text-ink mb-2", children: label }),
|
|
1471
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1", children: Array.from({ length: count }, (_, i) => i + 1).map((starValue) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1472
|
+
"button",
|
|
1473
|
+
{
|
|
1474
|
+
onClick: () => !readonly && onChange?.(starValue),
|
|
1475
|
+
onMouseEnter: () => !readonly && setHoverValue(starValue),
|
|
1476
|
+
onMouseLeave: () => setHoverValue(0),
|
|
1477
|
+
disabled: readonly,
|
|
1478
|
+
className: `transition-transform hover:scale-110 ${readonly ? "cursor-default" : "cursor-pointer"}`,
|
|
1479
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1480
|
+
"svg",
|
|
1481
|
+
{
|
|
1482
|
+
className: `${sizeClasses9[size]} ${starValue <= displayValue ? `fill-current ${colorClasses2[color]}` : "text-outline"}`,
|
|
1483
|
+
viewBox: "0 0 20 20",
|
|
1484
|
+
fill: "currentColor",
|
|
1485
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" })
|
|
1486
|
+
}
|
|
1487
|
+
)
|
|
1488
|
+
},
|
|
1489
|
+
starValue
|
|
1490
|
+
)) }),
|
|
1491
|
+
displayValue > 0 && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-ink-light mt-2", children: [
|
|
1492
|
+
displayValue,
|
|
1493
|
+
" / ",
|
|
1494
|
+
count
|
|
1495
|
+
] })
|
|
1496
|
+
] });
|
|
1497
|
+
}
|
|
1498
|
+
var themeClasses4 = {
|
|
1499
|
+
brand: "accent-brand",
|
|
1500
|
+
success: "accent-success-icon",
|
|
1501
|
+
danger: "accent-danger-icon"
|
|
1502
|
+
};
|
|
1503
|
+
function Slider({
|
|
1504
|
+
value = 0,
|
|
1505
|
+
onChange,
|
|
1506
|
+
min = 0,
|
|
1507
|
+
max = 100,
|
|
1508
|
+
step = 1,
|
|
1509
|
+
label,
|
|
1510
|
+
showValue = false,
|
|
1511
|
+
theme = "brand",
|
|
1512
|
+
className = "",
|
|
1513
|
+
disabled = false,
|
|
1514
|
+
...props
|
|
1515
|
+
}) {
|
|
1516
|
+
const handleChange = (e) => {
|
|
1517
|
+
onChange?.(parseFloat(e.target.value));
|
|
1518
|
+
};
|
|
1519
|
+
const percentage = (Number(value) - Number(min)) / (Number(max) - Number(min)) * 100;
|
|
1520
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, children: [
|
|
1521
|
+
(label || showValue) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-2", children: [
|
|
1522
|
+
label && /* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium text-ink", children: label }),
|
|
1523
|
+
showValue && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-ink-light", children: value })
|
|
1524
|
+
] }),
|
|
1525
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1526
|
+
"input",
|
|
1527
|
+
{
|
|
1528
|
+
type: "range",
|
|
1529
|
+
min,
|
|
1530
|
+
max,
|
|
1531
|
+
step,
|
|
1532
|
+
value,
|
|
1533
|
+
onChange: handleChange,
|
|
1534
|
+
disabled,
|
|
1535
|
+
className: [
|
|
1536
|
+
`w-full h-2 rounded-lg appearance-none cursor-pointer ${themeClasses4[theme]}`,
|
|
1537
|
+
"bg-gradient-to-r from-surface-gray to-surface-gray",
|
|
1538
|
+
"focus:outline-none focus:ring-2 focus:ring-brand focus:ring-offset-2",
|
|
1539
|
+
disabled ? "opacity-50 cursor-not-allowed" : ""
|
|
1540
|
+
].join(" "),
|
|
1541
|
+
style: {
|
|
1542
|
+
background: disabled ? void 0 : `linear-gradient(to right, var(--color-brand) 0%, var(--color-brand) ${percentage}%, var(--color-surface-gray) ${percentage}%, var(--color-surface-gray) 100%)`
|
|
1543
|
+
},
|
|
1544
|
+
...props
|
|
1545
|
+
}
|
|
1546
|
+
)
|
|
1547
|
+
] });
|
|
1548
|
+
}
|
|
1549
|
+
function Sidebar({
|
|
1550
|
+
sections,
|
|
1551
|
+
activeItem,
|
|
1552
|
+
onItemClick,
|
|
1553
|
+
collapsible = false,
|
|
1554
|
+
isCollapsed = false,
|
|
1555
|
+
onCollapsedChange,
|
|
1556
|
+
width = "w-64",
|
|
1557
|
+
className = "",
|
|
1558
|
+
...props
|
|
1559
|
+
}) {
|
|
1560
|
+
const handleItemClick = (value, onClick) => {
|
|
1561
|
+
onClick?.();
|
|
1562
|
+
onItemClick?.(value);
|
|
1563
|
+
};
|
|
1564
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1565
|
+
"aside",
|
|
1566
|
+
{
|
|
1567
|
+
className: [
|
|
1568
|
+
`${width} bg-surface-default border-r border-outline transition-all duration-200`,
|
|
1569
|
+
isCollapsed ? "w-16" : "",
|
|
1570
|
+
className
|
|
1571
|
+
].join(" "),
|
|
1572
|
+
...props,
|
|
1573
|
+
children: [
|
|
1574
|
+
collapsible && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between p-3 border-b border-outline", children: [
|
|
1575
|
+
!isCollapsed && /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-sm font-semibold text-ink", children: "Menu" }),
|
|
1576
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1577
|
+
"button",
|
|
1578
|
+
{
|
|
1579
|
+
onClick: () => onCollapsedChange?.(!isCollapsed),
|
|
1580
|
+
className: "p-1 hover:bg-surface-gray rounded transition-colors",
|
|
1581
|
+
title: isCollapsed ? "Expand sidebar" : "Collapse sidebar",
|
|
1582
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-4 h-4 text-ink", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: isCollapsed ? /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5l7 7-7 7" }) : /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 19l-7-7 7-7" }) })
|
|
1583
|
+
}
|
|
1584
|
+
)
|
|
1585
|
+
] }),
|
|
1586
|
+
/* @__PURE__ */ jsxRuntime.jsx("nav", { className: "py-2", children: sections.map((section, sectionIndex) => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1587
|
+
section.title && !isCollapsed && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-3 py-2 text-xs font-semibold text-ink-light uppercase tracking-wide", children: section.title }),
|
|
1588
|
+
section.items.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1589
|
+
"button",
|
|
1590
|
+
{
|
|
1591
|
+
onClick: () => handleItemClick(item.value, item.onClick),
|
|
1592
|
+
disabled: item.disabled,
|
|
1593
|
+
title: isCollapsed ? typeof item.label === "string" ? item.label : "" : void 0,
|
|
1594
|
+
className: [
|
|
1595
|
+
"w-full px-3 py-2 flex items-center gap-2 text-sm transition-colors",
|
|
1596
|
+
"hover:bg-surface-gray focus:outline-none focus:ring-2 focus:ring-brand focus:ring-offset-0",
|
|
1597
|
+
item.disabled ? "opacity-50 cursor-not-allowed hover:bg-transparent" : "",
|
|
1598
|
+
item.isActive || item.value === activeItem ? "bg-brand-50 text-brand font-medium" : "text-ink hover:text-brand",
|
|
1599
|
+
isCollapsed ? "justify-center" : ""
|
|
1600
|
+
].join(" "),
|
|
1601
|
+
children: [
|
|
1602
|
+
item.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0", children: item.icon }),
|
|
1603
|
+
!isCollapsed && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1604
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 text-left", children: item.label }),
|
|
1605
|
+
item.badge && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs px-1.5 py-0.5 bg-brand rounded-full text-white", children: item.badge })
|
|
1606
|
+
] })
|
|
1607
|
+
]
|
|
1608
|
+
},
|
|
1609
|
+
item.value
|
|
1610
|
+
))
|
|
1611
|
+
] }, sectionIndex)) })
|
|
1612
|
+
]
|
|
1613
|
+
}
|
|
1614
|
+
);
|
|
1615
|
+
}
|
|
1616
|
+
function Table({
|
|
1617
|
+
columns,
|
|
1618
|
+
data,
|
|
1619
|
+
striped = true,
|
|
1620
|
+
hoverable = true,
|
|
1621
|
+
compact = false,
|
|
1622
|
+
className = "",
|
|
1623
|
+
emptyMessage = "No data"
|
|
1624
|
+
}) {
|
|
1625
|
+
if (data.length === 0) {
|
|
1626
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-center py-8 text-ink-faint text-sm", children: emptyMessage });
|
|
1627
|
+
}
|
|
1628
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `overflow-x-auto border border-outline rounded-lg ${className}`, children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full", children: [
|
|
1629
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsx("tr", { className: "bg-surface-gray border-b border-outline", children: columns.map((col) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1630
|
+
"th",
|
|
1631
|
+
{
|
|
1632
|
+
style: { width: col.width },
|
|
1633
|
+
className: `
|
|
1634
|
+
${compact ? "px-3 py-2" : "px-4 py-3"}
|
|
1635
|
+
text-left text-xs font-semibold text-ink-faint uppercase tracking-wide
|
|
1636
|
+
${col.align === "center" ? "text-center" : col.align === "right" ? "text-right" : "text-left"}
|
|
1637
|
+
`,
|
|
1638
|
+
children: col.label
|
|
1639
|
+
},
|
|
1640
|
+
col.key
|
|
1641
|
+
)) }) }),
|
|
1642
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: data.map((row, rowIdx) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1643
|
+
"tr",
|
|
1644
|
+
{
|
|
1645
|
+
className: `
|
|
1646
|
+
border-b border-outline last:border-b-0
|
|
1647
|
+
${striped && rowIdx % 2 === 1 ? "bg-surface-gray/50" : ""}
|
|
1648
|
+
${hoverable ? "hover:bg-surface-overlay transition-colors" : ""}
|
|
1649
|
+
`,
|
|
1650
|
+
children: columns.map((col) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1651
|
+
"td",
|
|
1652
|
+
{
|
|
1653
|
+
style: { width: col.width },
|
|
1654
|
+
className: `
|
|
1655
|
+
${compact ? "px-3 py-2" : "px-4 py-3"}
|
|
1656
|
+
text-sm text-ink
|
|
1657
|
+
${col.align === "center" ? "text-center" : col.align === "right" ? "text-right" : "text-left"}
|
|
1658
|
+
`,
|
|
1659
|
+
children: col.render ? col.render(row[col.key], row) : row[col.key]
|
|
1660
|
+
},
|
|
1661
|
+
`${rowIdx}-${col.key}`
|
|
1662
|
+
))
|
|
1663
|
+
},
|
|
1664
|
+
rowIdx
|
|
1665
|
+
)) })
|
|
1666
|
+
] }) });
|
|
1667
|
+
}
|
|
1668
|
+
var ChevronLeftIcon = ({ size }) => /* @__PURE__ */ jsxRuntime.jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "15 18 9 12 15 6" }) });
|
|
1669
|
+
var ChevronRightIcon = ({ size }) => /* @__PURE__ */ jsxRuntime.jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "9 18 15 12 9 6" }) });
|
|
1670
|
+
function Pagination({
|
|
1671
|
+
current,
|
|
1672
|
+
total,
|
|
1673
|
+
onChange,
|
|
1674
|
+
size = "md",
|
|
1675
|
+
showInfo = true,
|
|
1676
|
+
maxVisible = 5,
|
|
1677
|
+
className = ""
|
|
1678
|
+
}) {
|
|
1679
|
+
const sizeClass = size === "sm" ? "text-xs px-2 py-1" : "text-sm px-3 py-2";
|
|
1680
|
+
const getPages = () => {
|
|
1681
|
+
const pages2 = [];
|
|
1682
|
+
const halfVisible = Math.floor(maxVisible / 2);
|
|
1683
|
+
let start = Math.max(1, current - halfVisible);
|
|
1684
|
+
let end = Math.min(total, current + halfVisible);
|
|
1685
|
+
if (start === 1) {
|
|
1686
|
+
end = Math.min(total, maxVisible);
|
|
1687
|
+
} else if (end === total) {
|
|
1688
|
+
start = Math.max(1, total - maxVisible + 1);
|
|
1689
|
+
}
|
|
1690
|
+
if (start > 1) pages2.push(1);
|
|
1691
|
+
if (start > 2) pages2.push("...");
|
|
1692
|
+
for (let i = start; i <= end; i++) {
|
|
1693
|
+
pages2.push(i);
|
|
1694
|
+
}
|
|
1695
|
+
if (end < total - 1) pages2.push("...");
|
|
1696
|
+
if (end < total) pages2.push(total);
|
|
1697
|
+
return pages2;
|
|
1698
|
+
};
|
|
1699
|
+
const pages = getPages();
|
|
1700
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex items-center gap-2 ${className}`, children: [
|
|
1701
|
+
showInfo && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-ink-faint", children: [
|
|
1702
|
+
"Page ",
|
|
1703
|
+
current,
|
|
1704
|
+
" of ",
|
|
1705
|
+
total
|
|
1706
|
+
] }),
|
|
1707
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1708
|
+
"button",
|
|
1709
|
+
{
|
|
1710
|
+
onClick: () => onChange(Math.max(1, current - 1)),
|
|
1711
|
+
disabled: current === 1,
|
|
1712
|
+
className: `
|
|
1713
|
+
flex items-center justify-center rounded border border-outline
|
|
1714
|
+
hover:bg-surface-overlay disabled:text-ink-faint disabled:cursor-not-allowed disabled:hover:bg-transparent
|
|
1715
|
+
transition-colors ${sizeClass}
|
|
1716
|
+
`,
|
|
1717
|
+
title: "Previous page",
|
|
1718
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ChevronLeftIcon, { size: size === "sm" ? 12 : 16 })
|
|
1719
|
+
}
|
|
1720
|
+
),
|
|
1721
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-1", children: pages.map(
|
|
1722
|
+
(page, i) => page === "..." ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-2 text-ink-faint", children: "..." }, `ellipsis-${i}`) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
1723
|
+
"button",
|
|
1724
|
+
{
|
|
1725
|
+
onClick: () => onChange(page),
|
|
1726
|
+
className: `
|
|
1727
|
+
flex items-center justify-center rounded border
|
|
1728
|
+
transition-colors ${sizeClass}
|
|
1729
|
+
${current === page ? "bg-brand text-white border-brand" : "border-outline hover:bg-surface-overlay"}
|
|
1730
|
+
`,
|
|
1731
|
+
children: page
|
|
1732
|
+
},
|
|
1733
|
+
page
|
|
1734
|
+
)
|
|
1735
|
+
) }),
|
|
1736
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1737
|
+
"button",
|
|
1738
|
+
{
|
|
1739
|
+
onClick: () => onChange(Math.min(total, current + 1)),
|
|
1740
|
+
disabled: current === total,
|
|
1741
|
+
className: `
|
|
1742
|
+
flex items-center justify-center rounded border border-outline
|
|
1743
|
+
hover:bg-surface-overlay disabled:text-ink-faint disabled:cursor-not-allowed disabled:hover:bg-transparent
|
|
1744
|
+
transition-colors ${sizeClass}
|
|
1745
|
+
`,
|
|
1746
|
+
title: "Next page",
|
|
1747
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ChevronRightIcon, { size: size === "sm" ? 12 : 16 })
|
|
1748
|
+
}
|
|
1749
|
+
)
|
|
1750
|
+
] });
|
|
1751
|
+
}
|
|
1752
|
+
function EmptyState({
|
|
1753
|
+
icon,
|
|
1754
|
+
title,
|
|
1755
|
+
description,
|
|
1756
|
+
action,
|
|
1757
|
+
className = ""
|
|
1758
|
+
}) {
|
|
1759
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex flex-col items-center justify-center py-12 px-4 ${className}`, children: [
|
|
1760
|
+
icon && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-4xl mb-4", children: icon }),
|
|
1761
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-ink mb-2", children: title }),
|
|
1762
|
+
description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-ink-faint mb-6 text-center max-w-sm", children: description }),
|
|
1763
|
+
action && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1764
|
+
"button",
|
|
1765
|
+
{
|
|
1766
|
+
onClick: action.onClick,
|
|
1767
|
+
className: "px-4 py-2 bg-brand text-white rounded-md hover:bg-brand-600 transition-colors text-sm font-medium",
|
|
1768
|
+
children: action.label
|
|
1769
|
+
}
|
|
1770
|
+
)
|
|
1771
|
+
] });
|
|
1772
|
+
}
|
|
1773
|
+
var ChevronUpIcon = ({ size }) => /* @__PURE__ */ jsxRuntime.jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "18 15 12 9 6 15" }) });
|
|
1774
|
+
var ChevronDownIcon = ({ size }) => /* @__PURE__ */ jsxRuntime.jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "6 9 12 15 18 9" }) });
|
|
1775
|
+
var sizeClasses10 = {
|
|
1776
|
+
sm: "text-xs px-2 py-1 h-8",
|
|
1777
|
+
md: "text-sm px-3 py-2 h-10",
|
|
1778
|
+
lg: "text-base px-4 py-2.5 h-12"
|
|
1779
|
+
};
|
|
1780
|
+
function NumberInput({
|
|
1781
|
+
value,
|
|
1782
|
+
onChange,
|
|
1783
|
+
step = 1,
|
|
1784
|
+
min,
|
|
1785
|
+
max,
|
|
1786
|
+
size = "md",
|
|
1787
|
+
disabled = false,
|
|
1788
|
+
placeholder,
|
|
1789
|
+
className = ""
|
|
1790
|
+
}) {
|
|
1791
|
+
const [isEditing, setIsEditing] = React9.useState(false);
|
|
1792
|
+
const handleIncrement = () => {
|
|
1793
|
+
const newValue = value + step;
|
|
1794
|
+
if (max === void 0 || newValue <= max) {
|
|
1795
|
+
onChange(newValue);
|
|
1796
|
+
}
|
|
1797
|
+
};
|
|
1798
|
+
const handleDecrement = () => {
|
|
1799
|
+
const newValue = value - step;
|
|
1800
|
+
if (min === void 0 || newValue >= min) {
|
|
1801
|
+
onChange(newValue);
|
|
1802
|
+
}
|
|
1803
|
+
};
|
|
1804
|
+
const handleInputChange = (e) => {
|
|
1805
|
+
const newValue = parseFloat(e.target.value);
|
|
1806
|
+
if (!isNaN(newValue)) {
|
|
1807
|
+
let val = newValue;
|
|
1808
|
+
if (min !== void 0 && val < min) val = min;
|
|
1809
|
+
if (max !== void 0 && val > max) val = max;
|
|
1810
|
+
onChange(val);
|
|
1811
|
+
}
|
|
1812
|
+
};
|
|
1813
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `relative inline-flex items-center border border-outline rounded-md bg-surface ${className}`, children: [
|
|
1814
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1815
|
+
"input",
|
|
1816
|
+
{
|
|
1817
|
+
type: "number",
|
|
1818
|
+
value,
|
|
1819
|
+
onChange: handleInputChange,
|
|
1820
|
+
onFocus: () => setIsEditing(true),
|
|
1821
|
+
onBlur: () => setIsEditing(false),
|
|
1822
|
+
disabled,
|
|
1823
|
+
placeholder,
|
|
1824
|
+
step,
|
|
1825
|
+
min,
|
|
1826
|
+
max,
|
|
1827
|
+
className: `
|
|
1828
|
+
flex-1 bg-transparent outline-none text-ink disabled:text-ink-faint disabled:cursor-not-allowed
|
|
1829
|
+
${sizeClasses10[size]}
|
|
1830
|
+
`
|
|
1831
|
+
}
|
|
1832
|
+
),
|
|
1833
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col border-l border-outline", children: [
|
|
1834
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1835
|
+
"button",
|
|
1836
|
+
{
|
|
1837
|
+
onClick: handleIncrement,
|
|
1838
|
+
disabled: disabled || max !== void 0 && value >= max,
|
|
1839
|
+
className: "flex-1 px-1 hover:bg-surface-overlay disabled:text-ink-faint disabled:cursor-not-allowed transition-colors",
|
|
1840
|
+
title: "Increment",
|
|
1841
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ChevronUpIcon, { size: size === "sm" ? 12 : size === "md" ? 14 : 16 })
|
|
1842
|
+
}
|
|
1843
|
+
),
|
|
1844
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1845
|
+
"button",
|
|
1846
|
+
{
|
|
1847
|
+
onClick: handleDecrement,
|
|
1848
|
+
disabled: disabled || min !== void 0 && value <= min,
|
|
1849
|
+
className: "flex-1 px-1 hover:bg-surface-overlay disabled:text-ink-faint disabled:cursor-not-allowed transition-colors border-t border-outline",
|
|
1850
|
+
title: "Decrement",
|
|
1851
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ChevronDownIcon, { size: size === "sm" ? 12 : size === "md" ? 14 : 16 })
|
|
1852
|
+
}
|
|
1853
|
+
)
|
|
1854
|
+
] })
|
|
1855
|
+
] });
|
|
1856
|
+
}
|
|
1857
|
+
var CopyIcon = ({ size }) => /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1858
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2" }),
|
|
1859
|
+
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: "8", y: "2", width: "8", height: "4", rx: "1", ry: "1" })
|
|
1860
|
+
] });
|
|
1861
|
+
var CheckIcon = ({ size, className }) => /* @__PURE__ */ jsxRuntime.jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "20 6 9 17 4 12" }) });
|
|
1862
|
+
function CodeBlock({
|
|
1863
|
+
code,
|
|
1864
|
+
language = "text",
|
|
1865
|
+
copyable = true,
|
|
1866
|
+
numbered = false,
|
|
1867
|
+
maxHeight = "max-h-96",
|
|
1868
|
+
className = ""
|
|
1869
|
+
}) {
|
|
1870
|
+
const [copied, setCopied] = React9.useState(false);
|
|
1871
|
+
const handleCopy = async () => {
|
|
1872
|
+
try {
|
|
1873
|
+
await navigator.clipboard.writeText(code);
|
|
1874
|
+
setCopied(true);
|
|
1875
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
1876
|
+
} catch (err) {
|
|
1877
|
+
console.error("Failed to copy:", err);
|
|
1878
|
+
}
|
|
1879
|
+
};
|
|
1880
|
+
const lines = code.split("\n");
|
|
1881
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `relative bg-ink rounded-lg overflow-hidden border border-outline ${className}`, children: [
|
|
1882
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between bg-surface-gray px-4 py-2 border-b border-outline", children: [
|
|
1883
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-ink-faint font-mono uppercase", children: language }),
|
|
1884
|
+
copyable && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1885
|
+
"button",
|
|
1886
|
+
{
|
|
1887
|
+
onClick: handleCopy,
|
|
1888
|
+
className: "p-1 rounded hover:bg-surface-overlay transition-colors text-ink-faint hover:text-ink",
|
|
1889
|
+
title: "Copy to clipboard",
|
|
1890
|
+
children: copied ? /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "currentColor" }, className: "text-status-online", children: /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, { size: 14 }) }) : /* @__PURE__ */ jsxRuntime.jsx(CopyIcon, { size: 14 })
|
|
1891
|
+
}
|
|
1892
|
+
)
|
|
1893
|
+
] }),
|
|
1894
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `overflow-auto ${maxHeight}`, children: /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "p-4 text-sm font-mono text-sky-100", children: numbered ? /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: lines.map((line, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-4", children: [
|
|
1895
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ink-faint select-none", children: String(i + 1).padStart(3, " ") }),
|
|
1896
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: line })
|
|
1897
|
+
] }, i)) }) : code }) })
|
|
1898
|
+
] });
|
|
1899
|
+
}
|
|
1900
|
+
var statusColors = {
|
|
1901
|
+
completed: {
|
|
1902
|
+
dot: "bg-status-online border-status-online",
|
|
1903
|
+
line: "bg-status-online",
|
|
1904
|
+
text: "text-status-online"
|
|
1905
|
+
},
|
|
1906
|
+
pending: {
|
|
1907
|
+
dot: "bg-ink-light border-ink-light",
|
|
1908
|
+
line: "bg-ink-faint",
|
|
1909
|
+
text: "text-ink-faint"
|
|
1910
|
+
},
|
|
1911
|
+
error: {
|
|
1912
|
+
dot: "bg-danger-icon border-danger-icon",
|
|
1913
|
+
line: "bg-danger-icon",
|
|
1914
|
+
text: "text-danger-text"
|
|
1915
|
+
},
|
|
1916
|
+
"in-progress": {
|
|
1917
|
+
dot: "bg-brand border-brand",
|
|
1918
|
+
line: "bg-brand",
|
|
1919
|
+
text: "text-brand"
|
|
1920
|
+
}
|
|
1921
|
+
};
|
|
1922
|
+
function Timeline({
|
|
1923
|
+
items,
|
|
1924
|
+
orientation = "vertical",
|
|
1925
|
+
className = ""
|
|
1926
|
+
}) {
|
|
1927
|
+
if (orientation === "vertical") {
|
|
1928
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `space-y-4 ${className}`, children: items.map((item, index) => {
|
|
1929
|
+
const colors = statusColors[item.status];
|
|
1930
|
+
const isLast = index === items.length - 1;
|
|
1931
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-4", children: [
|
|
1932
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center", children: [
|
|
1933
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1934
|
+
"div",
|
|
1935
|
+
{
|
|
1936
|
+
className: `
|
|
1937
|
+
w-4 h-4 rounded-full border-2 flex-shrink-0
|
|
1938
|
+
flex items-center justify-center bg-white
|
|
1939
|
+
${colors.dot}
|
|
1940
|
+
`,
|
|
1941
|
+
children: item.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-white text-2xs", children: item.icon })
|
|
1942
|
+
}
|
|
1943
|
+
),
|
|
1944
|
+
!isLast && /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-0.5 h-12 ${colors.line}` })
|
|
1945
|
+
] }),
|
|
1946
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 py-1", children: [
|
|
1947
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1948
|
+
/* @__PURE__ */ jsxRuntime.jsx("h4", { className: `font-semibold text-sm ${colors.text}`, children: item.label }),
|
|
1949
|
+
item.timestamp && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-ink-faint", children: typeof item.timestamp === "string" ? item.timestamp : new Date(item.timestamp).toLocaleTimeString("en-GB", {
|
|
1950
|
+
hour12: false,
|
|
1951
|
+
hour: "2-digit",
|
|
1952
|
+
minute: "2-digit",
|
|
1953
|
+
second: "2-digit"
|
|
1954
|
+
}) })
|
|
1955
|
+
] }),
|
|
1956
|
+
item.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-ink-faint mt-1", children: item.description })
|
|
1957
|
+
] })
|
|
1958
|
+
] }, item.id);
|
|
1959
|
+
}) });
|
|
1960
|
+
}
|
|
1961
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex gap-4 overflow-x-auto pb-2 ${className}`, children: items.map((item, index) => {
|
|
1962
|
+
const colors = statusColors[item.status];
|
|
1963
|
+
index === items.length - 1;
|
|
1964
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center flex-shrink-0 gap-2 min-w-fit", children: [
|
|
1965
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1966
|
+
index > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: `h-0.5 w-6 ${statusColors[items[index - 1].status].line}` }),
|
|
1967
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1968
|
+
"div",
|
|
1969
|
+
{
|
|
1970
|
+
className: `
|
|
1971
|
+
w-5 h-5 rounded-full border-2 flex items-center justify-center bg-white
|
|
1972
|
+
${colors.dot}
|
|
1973
|
+
`,
|
|
1974
|
+
children: item.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-white text-2xs", children: item.icon })
|
|
1975
|
+
}
|
|
1976
|
+
)
|
|
1977
|
+
] }),
|
|
1978
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
|
|
1979
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-xs font-semibold ${colors.text}`, children: item.label }),
|
|
1980
|
+
item.timestamp && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-2xs text-ink-faint", children: typeof item.timestamp === "string" ? item.timestamp : new Date(item.timestamp).toLocaleTimeString("en-GB", {
|
|
1981
|
+
hour12: false,
|
|
1982
|
+
hour: "2-digit",
|
|
1983
|
+
minute: "2-digit"
|
|
1984
|
+
}) })
|
|
1985
|
+
] })
|
|
1986
|
+
] }, item.id);
|
|
1987
|
+
}) });
|
|
1988
|
+
}
|
|
1989
|
+
var sizeClasses11 = {
|
|
1990
|
+
xs: "text-xs px-1.5 py-0.5 min-w-5 h-5",
|
|
1991
|
+
sm: "text-xs px-2 py-1 min-w-6 h-6",
|
|
1992
|
+
md: "text-sm px-2.5 py-1.5 min-w-8 h-8"
|
|
1993
|
+
};
|
|
1994
|
+
var themeClasses5 = {
|
|
1995
|
+
gray: "bg-surface-gray border-outline text-ink",
|
|
1996
|
+
dark: "bg-ink text-white border-ink-faint",
|
|
1997
|
+
brand: "bg-brand border-brand text-white"
|
|
1998
|
+
};
|
|
1999
|
+
function Kbd({
|
|
2000
|
+
keys,
|
|
2001
|
+
size = "sm",
|
|
2002
|
+
theme = "gray",
|
|
2003
|
+
className = ""
|
|
2004
|
+
}) {
|
|
2005
|
+
const keyArray = Array.isArray(keys) ? keys : [keys];
|
|
2006
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: `inline-flex items-center gap-1 ${className}`, children: keyArray.map((key, i) => /* @__PURE__ */ jsxRuntime.jsxs(React9__default.default.Fragment, { children: [
|
|
2007
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2008
|
+
"kbd",
|
|
2009
|
+
{
|
|
2010
|
+
className: `
|
|
2011
|
+
inline-flex items-center justify-center rounded font-mono font-medium
|
|
2012
|
+
border border-b-2 shadow-sm
|
|
2013
|
+
${sizeClasses11[size]}
|
|
2014
|
+
${themeClasses5[theme]}
|
|
2015
|
+
`,
|
|
2016
|
+
children: key
|
|
2017
|
+
}
|
|
2018
|
+
),
|
|
2019
|
+
i < keyArray.length - 1 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ink-faint text-xs", children: "+" })
|
|
2020
|
+
] }, key)) });
|
|
2021
|
+
}
|
|
607
2022
|
var statusConfig = {
|
|
608
2023
|
online: {
|
|
609
2024
|
label: "Online",
|
|
@@ -678,7 +2093,7 @@ function StatusBadge({
|
|
|
678
2093
|
}
|
|
679
2094
|
);
|
|
680
2095
|
}
|
|
681
|
-
var
|
|
2096
|
+
var sizeClasses12 = {
|
|
682
2097
|
sm: "text-xs gap-1.5",
|
|
683
2098
|
md: "text-sm gap-2",
|
|
684
2099
|
lg: "text-base gap-2"
|
|
@@ -697,7 +2112,7 @@ function ConnectionIndicator({
|
|
|
697
2112
|
className = ""
|
|
698
2113
|
}) {
|
|
699
2114
|
const status = connected ? "online" : "offline";
|
|
700
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `inline-flex items-center ${
|
|
2115
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `inline-flex items-center ${sizeClasses12[size]} ${className}`, children: [
|
|
701
2116
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
702
2117
|
StatusBadge,
|
|
703
2118
|
{
|
|
@@ -724,40 +2139,61 @@ function ConnectionIcon({ connected, size = "md", className = "" }) {
|
|
|
724
2139
|
);
|
|
725
2140
|
}
|
|
726
2141
|
function useDisclosure(initial = false) {
|
|
727
|
-
const [isOpen, setIsOpen] =
|
|
728
|
-
const open =
|
|
729
|
-
const close =
|
|
730
|
-
const toggle =
|
|
2142
|
+
const [isOpen, setIsOpen] = React9.useState(initial);
|
|
2143
|
+
const open = React9.useCallback(() => setIsOpen(true), []);
|
|
2144
|
+
const close = React9.useCallback(() => setIsOpen(false), []);
|
|
2145
|
+
const toggle = React9.useCallback(() => setIsOpen((v) => !v), []);
|
|
731
2146
|
return { isOpen, open, close, toggle };
|
|
732
2147
|
}
|
|
733
2148
|
var counter = 0;
|
|
734
2149
|
function useToast() {
|
|
735
|
-
const [toasts, setToasts] =
|
|
736
|
-
const addToast =
|
|
2150
|
+
const [toasts, setToasts] = React9.useState([]);
|
|
2151
|
+
const addToast = React9.useCallback((props) => {
|
|
737
2152
|
const id = `toast-${++counter}`;
|
|
738
2153
|
setToasts((prev) => [...prev, { ...props, id }]);
|
|
739
2154
|
return id;
|
|
740
2155
|
}, []);
|
|
741
|
-
const removeToast =
|
|
2156
|
+
const removeToast = React9.useCallback((id) => {
|
|
742
2157
|
setToasts((prev) => prev.filter((t) => t.id !== id));
|
|
743
2158
|
}, []);
|
|
744
2159
|
return { toasts, addToast, removeToast };
|
|
745
2160
|
}
|
|
746
2161
|
|
|
2162
|
+
exports.Alert = Alert;
|
|
747
2163
|
exports.Avatar = Avatar;
|
|
748
2164
|
exports.Badge = Badge;
|
|
2165
|
+
exports.Breadcrumbs = Breadcrumbs;
|
|
749
2166
|
exports.Button = Button;
|
|
750
2167
|
exports.Card = Card;
|
|
751
2168
|
exports.Checkbox = Checkbox;
|
|
2169
|
+
exports.CodeBlock = CodeBlock;
|
|
752
2170
|
exports.ConnectionIcon = ConnectionIcon;
|
|
753
2171
|
exports.ConnectionIndicator = ConnectionIndicator;
|
|
2172
|
+
exports.DatePicker = DatePicker;
|
|
754
2173
|
exports.Dialog = Dialog;
|
|
2174
|
+
exports.Dropdown = Dropdown;
|
|
2175
|
+
exports.EmptyState = EmptyState;
|
|
2176
|
+
exports.FileUploader = FileUploader;
|
|
2177
|
+
exports.FormControl = FormControl;
|
|
755
2178
|
exports.Input = Input;
|
|
2179
|
+
exports.Kbd = Kbd;
|
|
756
2180
|
exports.Link = Link;
|
|
2181
|
+
exports.MultiSelect = MultiSelect;
|
|
2182
|
+
exports.NumberInput = NumberInput;
|
|
2183
|
+
exports.Pagination = Pagination;
|
|
2184
|
+
exports.Progress = Progress;
|
|
2185
|
+
exports.Rating = Rating;
|
|
757
2186
|
exports.Select = Select;
|
|
2187
|
+
exports.Sidebar = Sidebar;
|
|
2188
|
+
exports.Slider = Slider;
|
|
758
2189
|
exports.Spinner = Spinner;
|
|
759
2190
|
exports.StatusBadge = StatusBadge;
|
|
2191
|
+
exports.Switch = Switch;
|
|
2192
|
+
exports.Table = Table;
|
|
2193
|
+
exports.Tabs = Tabs;
|
|
760
2194
|
exports.Textarea = Textarea;
|
|
2195
|
+
exports.TimePicker = TimePicker;
|
|
2196
|
+
exports.Timeline = Timeline;
|
|
761
2197
|
exports.Toast = Toast;
|
|
762
2198
|
exports.ToastContainer = ToastContainer;
|
|
763
2199
|
exports.Tooltip = Tooltip;
|