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