@page-speed/forms 0.4.2 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core.cjs +1 -1
- package/dist/core.cjs.map +1 -1
- package/dist/core.js +1 -1
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/inputs.cjs +338 -229
- package/dist/inputs.cjs.map +1 -1
- package/dist/inputs.d.cts +1 -8
- package/dist/inputs.d.ts +1 -8
- package/dist/inputs.js +338 -229
- package/dist/inputs.js.map +1 -1
- package/package.json +1 -1
package/dist/inputs.js
CHANGED
|
@@ -23,7 +23,7 @@ function TextInput({
|
|
|
23
23
|
const handleBlur = () => {
|
|
24
24
|
onBlur?.();
|
|
25
25
|
};
|
|
26
|
-
const baseClassName = "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors
|
|
26
|
+
const baseClassName = "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm";
|
|
27
27
|
const errorClassName = error ? "border-red-500 ring-1 ring-red-500" : "";
|
|
28
28
|
const combinedClassName = `${baseClassName} ${errorClassName} ${className}`.trim();
|
|
29
29
|
return /* @__PURE__ */ React7.createElement(
|
|
@@ -70,7 +70,7 @@ function TextArea({
|
|
|
70
70
|
const handleBlur = () => {
|
|
71
71
|
onBlur?.();
|
|
72
72
|
};
|
|
73
|
-
const baseClassName = "flex min-h-20 w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm transition-colors
|
|
73
|
+
const baseClassName = "flex min-h-20 w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm";
|
|
74
74
|
const errorClassName = error ? "border-red-500 ring-1 ring-red-500" : "";
|
|
75
75
|
const combinedClassName = `${baseClassName} ${errorClassName} ${className}`.trim();
|
|
76
76
|
return /* @__PURE__ */ React7.createElement(
|
|
@@ -304,8 +304,8 @@ function CheckboxGroup({
|
|
|
304
304
|
gridTemplateColumns: `repeat(${gridColumns}, 1fr)`
|
|
305
305
|
} : void 0
|
|
306
306
|
},
|
|
307
|
-
label
|
|
308
|
-
description
|
|
307
|
+
label ? /* @__PURE__ */ React7.createElement("div", { className: "text-sm font-medium" }, label) : null,
|
|
308
|
+
description ? /* @__PURE__ */ React7.createElement("div", { className: "text-xs opacity-70" }, description) : null,
|
|
309
309
|
showSelectAll && enabledOptions.length > 0 && /* @__PURE__ */ React7.createElement(
|
|
310
310
|
Checkbox,
|
|
311
311
|
{
|
|
@@ -367,7 +367,6 @@ function Radio({
|
|
|
367
367
|
error = false,
|
|
368
368
|
className = "",
|
|
369
369
|
layout = "stacked",
|
|
370
|
-
radioVariant = "inline",
|
|
371
370
|
label,
|
|
372
371
|
options,
|
|
373
372
|
...props
|
|
@@ -403,12 +402,16 @@ function Radio({
|
|
|
403
402
|
const handleBlur = () => {
|
|
404
403
|
onBlur?.();
|
|
405
404
|
};
|
|
406
|
-
const
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
405
|
+
const useChoiceCard = React7.useMemo(() => {
|
|
406
|
+
return options.some((option) => option.description);
|
|
407
|
+
}, [options]);
|
|
408
|
+
const containerClass = React7.useMemo(() => {
|
|
409
|
+
return cn(
|
|
410
|
+
"w-full gap-3 grid grid-cols-1",
|
|
411
|
+
layout === "inline" && "md:grid-cols-2",
|
|
412
|
+
className
|
|
413
|
+
);
|
|
414
|
+
}, [layout, className]);
|
|
412
415
|
return /* @__PURE__ */ React7.createElement(
|
|
413
416
|
"div",
|
|
414
417
|
{
|
|
@@ -455,29 +458,22 @@ function Radio({
|
|
|
455
458
|
},
|
|
456
459
|
isChecked && /* @__PURE__ */ React7.createElement("div", { className: "size-3 rounded-full bg-primary" })
|
|
457
460
|
));
|
|
458
|
-
const labelContent = /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col gap-0.5" }, /* @__PURE__ */ React7.createElement("div", { className: "text-sm font-medium" }, option.label), hasDescription && /* @__PURE__ */ React7.createElement(
|
|
459
|
-
"p",
|
|
460
|
-
{
|
|
461
|
-
className: "text-xs opacity-75",
|
|
462
|
-
id: `${radioId}-description`
|
|
463
|
-
},
|
|
464
|
-
option.description
|
|
465
|
-
));
|
|
461
|
+
const labelContent = /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col gap-0.5" }, /* @__PURE__ */ React7.createElement("div", { className: "text-sm font-medium" }, option.label), hasDescription && /* @__PURE__ */ React7.createElement("p", { className: "text-xs opacity-75", id: `${radioId}-description` }, option.description));
|
|
466
462
|
return /* @__PURE__ */ React7.createElement(
|
|
467
463
|
"label",
|
|
468
464
|
{
|
|
469
465
|
key: option.value,
|
|
470
466
|
className: cn(
|
|
471
467
|
"w-full h-full flex gap-3 p-3 duration-200",
|
|
472
|
-
|
|
473
|
-
|
|
468
|
+
useChoiceCard && "border rounded-lg hover:ring-2",
|
|
469
|
+
useChoiceCard && isChecked && "ring-2",
|
|
474
470
|
isDisabled ? "opacity-50 cursor-not-allowed hover:ring-0" : "cursor-pointer"
|
|
475
471
|
),
|
|
476
472
|
htmlFor: radioId,
|
|
477
473
|
onKeyDown: (e) => handleKeyDown(e, index),
|
|
478
474
|
tabIndex: isDisabled ? -1 : 0
|
|
479
475
|
},
|
|
480
|
-
/* @__PURE__ */ React7.createElement("div", { className: "flex w-full flex-row items-center gap-2" },
|
|
476
|
+
/* @__PURE__ */ React7.createElement("div", { className: "flex w-full flex-row items-center gap-2" }, !useChoiceCard && radioIndicator, /* @__PURE__ */ React7.createElement("div", { className: "flex flex-1 flex-col gap-0.5" }, labelContent), useChoiceCard && radioIndicator)
|
|
481
477
|
);
|
|
482
478
|
})
|
|
483
479
|
);
|
|
@@ -567,9 +563,7 @@ function Select({
|
|
|
567
563
|
if (enabledOptions.length > 0) {
|
|
568
564
|
const currentIndexInFiltered = focusedIndex;
|
|
569
565
|
const nextIndex = (currentIndexInFiltered + 1) % enabledOptions.length;
|
|
570
|
-
setFocusedIndex(
|
|
571
|
-
filteredOptions.indexOf(enabledOptions[nextIndex])
|
|
572
|
-
);
|
|
566
|
+
setFocusedIndex(filteredOptions.indexOf(enabledOptions[nextIndex]));
|
|
573
567
|
}
|
|
574
568
|
}
|
|
575
569
|
break;
|
|
@@ -580,9 +574,7 @@ function Select({
|
|
|
580
574
|
if (enabledOptions.length > 0) {
|
|
581
575
|
const currentIndexInFiltered = focusedIndex;
|
|
582
576
|
const prevIndex = (currentIndexInFiltered - 1 + enabledOptions.length) % enabledOptions.length;
|
|
583
|
-
setFocusedIndex(
|
|
584
|
-
filteredOptions.indexOf(enabledOptions[prevIndex])
|
|
585
|
-
);
|
|
577
|
+
setFocusedIndex(filteredOptions.indexOf(enabledOptions[prevIndex]));
|
|
586
578
|
}
|
|
587
579
|
}
|
|
588
580
|
break;
|
|
@@ -672,7 +664,7 @@ function Select({
|
|
|
672
664
|
/* @__PURE__ */ React7.createElement(
|
|
673
665
|
"div",
|
|
674
666
|
{
|
|
675
|
-
className: `flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm cursor-pointer transition-colors hover:bg-
|
|
667
|
+
className: `flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm cursor-pointer transition-colors hover:bg-muted focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring ${disabled ? "cursor-not-allowed opacity-50 pointer-events-none" : ""} ${error ? "border-red-500 ring-1 ring-red-500" : ""}`,
|
|
676
668
|
onClick: handleToggle,
|
|
677
669
|
role: "combobox",
|
|
678
670
|
"aria-expanded": isOpen,
|
|
@@ -683,48 +675,76 @@ function Select({
|
|
|
683
675
|
"aria-disabled": disabled,
|
|
684
676
|
tabIndex: disabled ? -1 : 0
|
|
685
677
|
},
|
|
686
|
-
/* @__PURE__ */ React7.createElement("span", { className: "flex items-center flex-1 overflow-hidden text-ellipsis" }, selectedOption ? renderOption ? renderOption(selectedOption) : selectedOption.label : /* @__PURE__ */ React7.createElement("span", { className: "
|
|
678
|
+
/* @__PURE__ */ React7.createElement("span", { className: "flex items-center flex-1 overflow-hidden text-ellipsis" }, selectedOption ? renderOption ? renderOption(selectedOption) : selectedOption.label : /* @__PURE__ */ React7.createElement("span", { className: "relative" }, placeholder)),
|
|
687
679
|
/* @__PURE__ */ React7.createElement("div", { className: "flex items-center gap-1 ml-2" }, loading && /* @__PURE__ */ React7.createElement("span", { className: "text-xs" }, "\u23F3"), clearable && value && !disabled && !loading && /* @__PURE__ */ React7.createElement(
|
|
688
680
|
"button",
|
|
689
681
|
{
|
|
690
682
|
type: "button",
|
|
691
|
-
className: "flex items-center justify-center h-4 w-4 rounded-sm border-none bg-transparent
|
|
683
|
+
className: "flex items-center justify-center h-4 w-4 rounded-sm border-none bg-transparent cursor-pointer text-xs p-0 transition-opacity hover:opacity-70",
|
|
692
684
|
onClick: handleClear,
|
|
693
685
|
"aria-label": "Clear selection",
|
|
694
686
|
tabIndex: -1
|
|
695
687
|
},
|
|
696
688
|
"\u2715"
|
|
697
|
-
), /* @__PURE__ */ React7.createElement("span", { className: "text-
|
|
689
|
+
), /* @__PURE__ */ React7.createElement("span", { className: "text-xs leading-none", "aria-hidden": "true" }, isOpen ? "\u25B2" : "\u25BC"))
|
|
698
690
|
),
|
|
699
|
-
isOpen && /* @__PURE__ */ React7.createElement(
|
|
700
|
-
"
|
|
691
|
+
isOpen && /* @__PURE__ */ React7.createElement(
|
|
692
|
+
"div",
|
|
701
693
|
{
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
(
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
694
|
+
id: dropdownId,
|
|
695
|
+
className: "absolute z-50 top-full mt-1 min-w-full overflow-hidden rounded-md border border-border bg-popover text-popover-foreground shadow-md",
|
|
696
|
+
role: "listbox"
|
|
697
|
+
},
|
|
698
|
+
searchable && /* @__PURE__ */ React7.createElement("div", { className: "p-2 border-b border-border" }, /* @__PURE__ */ React7.createElement(
|
|
699
|
+
"input",
|
|
700
|
+
{
|
|
701
|
+
ref: searchInputRef,
|
|
702
|
+
type: "text",
|
|
703
|
+
className: "w-full border border-input rounded px-2 py-1 text-sm bg-transparent outline-none focus:ring-1 focus:ring-ring",
|
|
704
|
+
placeholder: "Search...",
|
|
705
|
+
value: searchQuery,
|
|
706
|
+
onChange: handleSearchChange,
|
|
707
|
+
onClick: (e) => e.stopPropagation(),
|
|
708
|
+
"aria-label": "Search options"
|
|
709
|
+
}
|
|
710
|
+
)),
|
|
711
|
+
/* @__PURE__ */ React7.createElement("div", { className: "max-h-64 overflow-y-auto p-1" }, filteredOptions.length === 0 ? /* @__PURE__ */ React7.createElement("div", { className: "py-2 px-3 text-center text-sm " }, "No options found") : optionGroups.length > 0 ? (
|
|
712
|
+
// Render grouped options
|
|
713
|
+
optionGroups.map((group, groupIndex) => {
|
|
714
|
+
const groupOptions = group.options.filter(
|
|
715
|
+
(opt) => filteredOptions.includes(opt)
|
|
716
|
+
);
|
|
717
|
+
if (groupOptions.length === 0) return null;
|
|
718
|
+
return /* @__PURE__ */ React7.createElement("div", { key: groupIndex, className: "py-1" }, /* @__PURE__ */ React7.createElement("div", { className: "py-1.5 px-2 text-xs font-semibold " }, group.label), groupOptions.map((option) => {
|
|
719
|
+
const globalIndex = filteredOptions.indexOf(option);
|
|
720
|
+
const isSelected = value === option.value;
|
|
721
|
+
const isFocused = globalIndex === focusedIndex;
|
|
722
|
+
const isDisabled = option.disabled;
|
|
723
|
+
return /* @__PURE__ */ React7.createElement(
|
|
724
|
+
"div",
|
|
725
|
+
{
|
|
726
|
+
key: option.value,
|
|
727
|
+
className: `relative flex w-full cursor-pointer items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors hover:bg-muted ${isFocused ? "bg-muted" : ""} ${isSelected ? "font-medium bg-muted" : ""} ${isDisabled ? "pointer-events-none opacity-50" : ""}`,
|
|
728
|
+
onClick: () => !isDisabled && handleSelect(option.value),
|
|
729
|
+
role: "option",
|
|
730
|
+
"aria-selected": isSelected,
|
|
731
|
+
"aria-disabled": isDisabled
|
|
732
|
+
},
|
|
733
|
+
renderOption ? renderOption(option) : option.label
|
|
734
|
+
);
|
|
735
|
+
}));
|
|
736
|
+
})
|
|
737
|
+
) : (
|
|
738
|
+
// Render flat options
|
|
739
|
+
filteredOptions.map((option, index) => {
|
|
720
740
|
const isSelected = value === option.value;
|
|
721
|
-
const isFocused =
|
|
741
|
+
const isFocused = index === focusedIndex;
|
|
722
742
|
const isDisabled = option.disabled;
|
|
723
743
|
return /* @__PURE__ */ React7.createElement(
|
|
724
744
|
"div",
|
|
725
745
|
{
|
|
726
746
|
key: option.value,
|
|
727
|
-
className: `relative flex w-full cursor-pointer items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors hover:bg-
|
|
747
|
+
className: `relative flex w-full cursor-pointer items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors hover:bg-muted ${isFocused ? "bg-muted" : ""} ${isSelected ? "font-medium bg-muted" : ""} ${isDisabled ? "pointer-events-none opacity-50" : ""}`,
|
|
728
748
|
onClick: () => !isDisabled && handleSelect(option.value),
|
|
729
749
|
role: "option",
|
|
730
750
|
"aria-selected": isSelected,
|
|
@@ -732,28 +752,9 @@ function Select({
|
|
|
732
752
|
},
|
|
733
753
|
renderOption ? renderOption(option) : option.label
|
|
734
754
|
);
|
|
735
|
-
})
|
|
736
|
-
|
|
737
|
-
)
|
|
738
|
-
// Render flat options
|
|
739
|
-
filteredOptions.map((option, index) => {
|
|
740
|
-
const isSelected = value === option.value;
|
|
741
|
-
const isFocused = index === focusedIndex;
|
|
742
|
-
const isDisabled = option.disabled;
|
|
743
|
-
return /* @__PURE__ */ React7.createElement(
|
|
744
|
-
"div",
|
|
745
|
-
{
|
|
746
|
-
key: option.value,
|
|
747
|
-
className: `relative flex w-full cursor-pointer items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground ${isFocused ? "bg-accent text-accent-foreground" : ""} ${isSelected ? "font-medium bg-accent" : ""} ${isDisabled ? "pointer-events-none opacity-50" : ""}`,
|
|
748
|
-
onClick: () => !isDisabled && handleSelect(option.value),
|
|
749
|
-
role: "option",
|
|
750
|
-
"aria-selected": isSelected,
|
|
751
|
-
"aria-disabled": isDisabled
|
|
752
|
-
},
|
|
753
|
-
renderOption ? renderOption(option) : option.label
|
|
754
|
-
);
|
|
755
|
-
})
|
|
756
|
-
)))
|
|
755
|
+
})
|
|
756
|
+
))
|
|
757
|
+
)
|
|
757
758
|
);
|
|
758
759
|
}
|
|
759
760
|
Select.displayName = "Select";
|
|
@@ -762,7 +763,7 @@ function FileInput({
|
|
|
762
763
|
value = [],
|
|
763
764
|
onChange,
|
|
764
765
|
onBlur,
|
|
765
|
-
placeholder = "Choose file
|
|
766
|
+
placeholder = "Choose file...",
|
|
766
767
|
disabled = false,
|
|
767
768
|
required = false,
|
|
768
769
|
error = false,
|
|
@@ -865,7 +866,15 @@ function FileInput({
|
|
|
865
866
|
inputRef.current.value = "";
|
|
866
867
|
}
|
|
867
868
|
},
|
|
868
|
-
[
|
|
869
|
+
[
|
|
870
|
+
value,
|
|
871
|
+
onChange,
|
|
872
|
+
validateFile,
|
|
873
|
+
maxFiles,
|
|
874
|
+
multiple,
|
|
875
|
+
enableCropping,
|
|
876
|
+
onValidationError
|
|
877
|
+
]
|
|
869
878
|
);
|
|
870
879
|
const createCroppedImage = React7.useCallback(
|
|
871
880
|
async (imageUrl, cropArea) => {
|
|
@@ -891,13 +900,17 @@ function FileInput({
|
|
|
891
900
|
cropArea.width,
|
|
892
901
|
cropArea.height
|
|
893
902
|
);
|
|
894
|
-
canvas.toBlob(
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
903
|
+
canvas.toBlob(
|
|
904
|
+
(blob) => {
|
|
905
|
+
if (blob) {
|
|
906
|
+
resolve(blob);
|
|
907
|
+
} else {
|
|
908
|
+
reject(new Error("Failed to create blob from canvas"));
|
|
909
|
+
}
|
|
910
|
+
},
|
|
911
|
+
"image/jpeg",
|
|
912
|
+
0.95
|
|
913
|
+
);
|
|
901
914
|
};
|
|
902
915
|
image.onerror = () => {
|
|
903
916
|
reject(new Error("Failed to load image"));
|
|
@@ -917,11 +930,9 @@ function FileInput({
|
|
|
917
930
|
if (onCropComplete) {
|
|
918
931
|
onCropComplete(croppedBlob, imageToCrop.file);
|
|
919
932
|
}
|
|
920
|
-
const croppedFile = new File(
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
{ type: "image/jpeg" }
|
|
924
|
-
);
|
|
933
|
+
const croppedFile = new File([croppedBlob], imageToCrop.file.name, {
|
|
934
|
+
type: "image/jpeg"
|
|
935
|
+
});
|
|
925
936
|
const updatedFiles = multiple ? [...value, croppedFile] : [croppedFile];
|
|
926
937
|
onChange(updatedFiles);
|
|
927
938
|
setCropperOpen(false);
|
|
@@ -933,7 +944,15 @@ function FileInput({
|
|
|
933
944
|
} catch (error2) {
|
|
934
945
|
console.error("Failed to crop image:", error2);
|
|
935
946
|
}
|
|
936
|
-
}, [
|
|
947
|
+
}, [
|
|
948
|
+
imageToCrop,
|
|
949
|
+
croppedAreaPixels,
|
|
950
|
+
createCroppedImage,
|
|
951
|
+
onCropComplete,
|
|
952
|
+
value,
|
|
953
|
+
onChange,
|
|
954
|
+
multiple
|
|
955
|
+
]);
|
|
937
956
|
const handleCropCancel = React7.useCallback(() => {
|
|
938
957
|
if (imageToCrop) {
|
|
939
958
|
URL.revokeObjectURL(imageToCrop.url);
|
|
@@ -1045,7 +1064,7 @@ function FileInput({
|
|
|
1045
1064
|
), /* @__PURE__ */ React7.createElement(
|
|
1046
1065
|
"div",
|
|
1047
1066
|
{
|
|
1048
|
-
className: `flex min-h-32 w-full cursor-pointer items-center justify-center rounded-md border-2 border-dashed border-input bg-transparent p-6 transition-colors hover:bg-
|
|
1067
|
+
className: `flex min-h-32 w-full cursor-pointer items-center justify-center rounded-md border-2 border-dashed border-input bg-transparent p-6 transition-colors hover:bg-primary/50 hover:border-ring ${dragActive ? "bg-primary text-primary-foreground border-ring" : ""} ${disabled ? "cursor-not-allowed opacity-50" : ""} ${error ? "border-red-500" : ""}`,
|
|
1049
1068
|
onDragEnter: handleDrag,
|
|
1050
1069
|
onDragLeave: handleDrag,
|
|
1051
1070
|
onDragOver: handleDrag,
|
|
@@ -1060,7 +1079,6 @@ function FileInput({
|
|
|
1060
1079
|
/* @__PURE__ */ React7.createElement("div", { className: "flex flex-col items-center gap-2 text-center" }, /* @__PURE__ */ React7.createElement(
|
|
1061
1080
|
"svg",
|
|
1062
1081
|
{
|
|
1063
|
-
className: "text-muted-foreground",
|
|
1064
1082
|
width: "48",
|
|
1065
1083
|
height: "48",
|
|
1066
1084
|
viewBox: "0 0 24 24",
|
|
@@ -1074,92 +1092,102 @@ function FileInput({
|
|
|
1074
1092
|
/* @__PURE__ */ React7.createElement("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
|
|
1075
1093
|
/* @__PURE__ */ React7.createElement("polyline", { points: "17 8 12 3 7 8" }),
|
|
1076
1094
|
/* @__PURE__ */ React7.createElement("line", { x1: "12", y1: "3", x2: "12", y2: "15" })
|
|
1077
|
-
), /* @__PURE__ */ React7.createElement("p", { className: "text-sm font-medium" }, value.length > 0 ? `${value.length} file(s) selected` : placeholder), accept && /* @__PURE__ */ React7.createElement("p", { className: "text-xs
|
|
1095
|
+
), /* @__PURE__ */ React7.createElement("p", { className: "text-sm font-medium" }, value.length > 0 ? `${value.length} file(s) selected` : placeholder), accept && /* @__PURE__ */ React7.createElement("p", { className: "text-xs" }, "Accepted: ", accept), maxSize && /* @__PURE__ */ React7.createElement("p", { className: "text-xs " }, "Max size: ", formatFileSize(maxSize)))
|
|
1078
1096
|
), value.length > 0 && /* @__PURE__ */ React7.createElement("ul", { className: "flex flex-col gap-2 mt-4", role: "list" }, value.map((file, index) => {
|
|
1079
1097
|
const previewUrl = showPreview ? getPreviewUrl(file) : null;
|
|
1080
|
-
return /* @__PURE__ */ React7.createElement(
|
|
1081
|
-
"
|
|
1082
|
-
{
|
|
1083
|
-
src: previewUrl,
|
|
1084
|
-
alt: file.name,
|
|
1085
|
-
className: "w-12 h-12 rounded object-cover",
|
|
1086
|
-
width: "48",
|
|
1087
|
-
height: "48"
|
|
1088
|
-
}
|
|
1089
|
-
), /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col flex-1 min-w-0" }, /* @__PURE__ */ React7.createElement("span", { className: "text-sm font-medium truncate" }, file.name), /* @__PURE__ */ React7.createElement("span", { className: "text-xs text-muted-foreground" }, formatFileSize(file.size)), showProgress && uploadProgress[file.name] !== void 0 && /* @__PURE__ */ React7.createElement("div", { className: "flex items-center gap-2 mt-1" }, /* @__PURE__ */ React7.createElement(
|
|
1090
|
-
"div",
|
|
1098
|
+
return /* @__PURE__ */ React7.createElement(
|
|
1099
|
+
"li",
|
|
1091
1100
|
{
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
"aria-valuenow": uploadProgress[file.name],
|
|
1095
|
-
"aria-valuemin": 0,
|
|
1096
|
-
"aria-valuemax": 100,
|
|
1097
|
-
"aria-label": `Upload progress: ${uploadProgress[file.name]}%`
|
|
1101
|
+
key: `${file.name}-${index}`,
|
|
1102
|
+
className: "flex items-center gap-3 p-3 rounded-md border border-border bg-card text-card-foreground hover:bg-primary/50 transition-colors"
|
|
1098
1103
|
},
|
|
1099
|
-
/* @__PURE__ */ React7.createElement(
|
|
1100
|
-
"
|
|
1104
|
+
previewUrl && /* @__PURE__ */ React7.createElement(
|
|
1105
|
+
"img",
|
|
1101
1106
|
{
|
|
1102
|
-
|
|
1103
|
-
|
|
1107
|
+
src: previewUrl,
|
|
1108
|
+
alt: file.name,
|
|
1109
|
+
className: "w-12 h-12 rounded object-cover",
|
|
1110
|
+
width: "48",
|
|
1111
|
+
height: "48"
|
|
1104
1112
|
}
|
|
1105
|
-
)
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
{
|
|
1109
|
-
type: "button",
|
|
1110
|
-
onClick: (e) => {
|
|
1111
|
-
e.stopPropagation();
|
|
1112
|
-
handleCrop(file);
|
|
1113
|
-
},
|
|
1114
|
-
disabled,
|
|
1115
|
-
className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-accent text-muted-foreground hover:text-foreground transition-colors",
|
|
1116
|
-
"aria-label": `Crop ${file.name}`
|
|
1117
|
-
},
|
|
1118
|
-
/* @__PURE__ */ React7.createElement(
|
|
1119
|
-
"svg",
|
|
1113
|
+
),
|
|
1114
|
+
/* @__PURE__ */ React7.createElement("div", { className: "flex flex-col flex-1 min-w-0" }, /* @__PURE__ */ React7.createElement("span", { className: "text-sm font-medium truncate" }, file.name), /* @__PURE__ */ React7.createElement("span", { className: "text-xs" }, formatFileSize(file.size)), showProgress && uploadProgress[file.name] !== void 0 && /* @__PURE__ */ React7.createElement("div", { className: "flex items-center gap-2 mt-1" }, /* @__PURE__ */ React7.createElement(
|
|
1115
|
+
"div",
|
|
1120
1116
|
{
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
strokeLinecap: "round",
|
|
1128
|
-
strokeLinejoin: "round",
|
|
1129
|
-
"aria-hidden": "true"
|
|
1117
|
+
className: "h-1.5 bg-muted rounded-full overflow-hidden flex-1",
|
|
1118
|
+
role: "progressbar",
|
|
1119
|
+
"aria-valuenow": uploadProgress[file.name],
|
|
1120
|
+
"aria-valuemin": 0,
|
|
1121
|
+
"aria-valuemax": 100,
|
|
1122
|
+
"aria-label": `Upload progress: ${uploadProgress[file.name]}%`
|
|
1130
1123
|
},
|
|
1131
|
-
/* @__PURE__ */ React7.createElement(
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1124
|
+
/* @__PURE__ */ React7.createElement(
|
|
1125
|
+
"div",
|
|
1126
|
+
{
|
|
1127
|
+
className: "h-full bg-primary transition-all",
|
|
1128
|
+
style: { width: `${uploadProgress[file.name]}%` }
|
|
1129
|
+
}
|
|
1130
|
+
)
|
|
1131
|
+
), /* @__PURE__ */ React7.createElement("span", { className: "text-xs " }, uploadProgress[file.name], "%"))),
|
|
1132
|
+
enableCropping && file.type.startsWith("image/") && /* @__PURE__ */ React7.createElement(
|
|
1133
|
+
"button",
|
|
1134
|
+
{
|
|
1135
|
+
type: "button",
|
|
1136
|
+
onClick: (e) => {
|
|
1137
|
+
e.stopPropagation();
|
|
1138
|
+
handleCrop(file);
|
|
1139
|
+
},
|
|
1140
|
+
disabled,
|
|
1141
|
+
className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-primary hover:text-primary-foreground transition-colors",
|
|
1142
|
+
"aria-label": `Crop ${file.name}`
|
|
1141
1143
|
},
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1144
|
+
/* @__PURE__ */ React7.createElement(
|
|
1145
|
+
"svg",
|
|
1146
|
+
{
|
|
1147
|
+
width: "20",
|
|
1148
|
+
height: "20",
|
|
1149
|
+
viewBox: "0 0 24 24",
|
|
1150
|
+
fill: "none",
|
|
1151
|
+
stroke: "currentColor",
|
|
1152
|
+
strokeWidth: "2",
|
|
1153
|
+
strokeLinecap: "round",
|
|
1154
|
+
strokeLinejoin: "round",
|
|
1155
|
+
"aria-hidden": "true"
|
|
1156
|
+
},
|
|
1157
|
+
/* @__PURE__ */ React7.createElement("path", { d: "M6.13 1L6 16a2 2 0 0 0 2 2h15" }),
|
|
1158
|
+
/* @__PURE__ */ React7.createElement("path", { d: "M1 6.13L16 6a2 2 0 0 1 2 2v15" })
|
|
1159
|
+
)
|
|
1160
|
+
),
|
|
1146
1161
|
/* @__PURE__ */ React7.createElement(
|
|
1147
|
-
"
|
|
1162
|
+
"button",
|
|
1148
1163
|
{
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
"aria-hidden": "true"
|
|
1164
|
+
type: "button",
|
|
1165
|
+
onClick: (e) => {
|
|
1166
|
+
e.stopPropagation();
|
|
1167
|
+
handleRemove(index);
|
|
1168
|
+
},
|
|
1169
|
+
disabled,
|
|
1170
|
+
className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-primary hover:text-primary-foreground transition-colors",
|
|
1171
|
+
"aria-label": `Remove ${file.name}`
|
|
1158
1172
|
},
|
|
1159
|
-
/* @__PURE__ */ React7.createElement(
|
|
1160
|
-
|
|
1173
|
+
/* @__PURE__ */ React7.createElement(
|
|
1174
|
+
"svg",
|
|
1175
|
+
{
|
|
1176
|
+
width: "20",
|
|
1177
|
+
height: "20",
|
|
1178
|
+
viewBox: "0 0 24 24",
|
|
1179
|
+
fill: "none",
|
|
1180
|
+
stroke: "currentColor",
|
|
1181
|
+
strokeWidth: "2",
|
|
1182
|
+
strokeLinecap: "round",
|
|
1183
|
+
strokeLinejoin: "round",
|
|
1184
|
+
"aria-hidden": "true"
|
|
1185
|
+
},
|
|
1186
|
+
/* @__PURE__ */ React7.createElement("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
1187
|
+
/* @__PURE__ */ React7.createElement("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
1188
|
+
)
|
|
1161
1189
|
)
|
|
1162
|
-
)
|
|
1190
|
+
);
|
|
1163
1191
|
})), cropperOpen && imageToCrop && /* @__PURE__ */ React7.createElement("div", { className: "fixed inset-0 z-50 flex items-center justify-center" }, /* @__PURE__ */ React7.createElement(
|
|
1164
1192
|
"div",
|
|
1165
1193
|
{
|
|
@@ -1171,7 +1199,7 @@ function FileInput({
|
|
|
1171
1199
|
"button",
|
|
1172
1200
|
{
|
|
1173
1201
|
type: "button",
|
|
1174
|
-
className: "flex items-center justify-center h-8 w-8 rounded hover:bg-
|
|
1202
|
+
className: "flex items-center justify-center h-8 w-8 rounded hover:bg-primary hover:text-primary-foreground transition-colors",
|
|
1175
1203
|
onClick: handleCropCancel,
|
|
1176
1204
|
"aria-label": "Close"
|
|
1177
1205
|
},
|
|
@@ -1212,7 +1240,10 @@ function FileInput({
|
|
|
1212
1240
|
const img = e.currentTarget;
|
|
1213
1241
|
const containerWidth = 600;
|
|
1214
1242
|
const containerHeight = 400;
|
|
1215
|
-
const cropWidth = cropAspectRatio ? Math.min(
|
|
1243
|
+
const cropWidth = cropAspectRatio ? Math.min(
|
|
1244
|
+
containerWidth * 0.8,
|
|
1245
|
+
containerHeight * 0.8 * cropAspectRatio
|
|
1246
|
+
) : containerWidth * 0.8;
|
|
1216
1247
|
const cropHeight = cropAspectRatio ? cropWidth / cropAspectRatio : containerHeight * 0.8;
|
|
1217
1248
|
const scale = zoom;
|
|
1218
1249
|
const imgWidth = img.naturalWidth;
|
|
@@ -1241,7 +1272,16 @@ function FileInput({
|
|
|
1241
1272
|
},
|
|
1242
1273
|
/* @__PURE__ */ React7.createElement("div", { className: "absolute inset-0 grid grid-cols-3 grid-rows-3" }, /* @__PURE__ */ React7.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React7.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React7.createElement("div", { className: "border-b border-primary/30" }), /* @__PURE__ */ React7.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React7.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React7.createElement("div", { className: "border-b border-primary/30" }), /* @__PURE__ */ React7.createElement("div", { className: "border-r border-primary/30" }), /* @__PURE__ */ React7.createElement("div", { className: "border-r border-primary/30" }), /* @__PURE__ */ React7.createElement("div", null))
|
|
1243
1274
|
)
|
|
1244
|
-
), /* @__PURE__ */ React7.createElement("div", { className: "flex items-center gap-3 mt-4" }, /* @__PURE__ */ React7.createElement(
|
|
1275
|
+
), /* @__PURE__ */ React7.createElement("div", { className: "flex items-center gap-3 mt-4" }, /* @__PURE__ */ React7.createElement(
|
|
1276
|
+
"label",
|
|
1277
|
+
{
|
|
1278
|
+
htmlFor: "zoom-slider",
|
|
1279
|
+
className: "text-sm font-medium whitespace-nowrap"
|
|
1280
|
+
},
|
|
1281
|
+
"Zoom: ",
|
|
1282
|
+
zoom.toFixed(1),
|
|
1283
|
+
"x"
|
|
1284
|
+
), /* @__PURE__ */ React7.createElement(
|
|
1245
1285
|
"input",
|
|
1246
1286
|
{
|
|
1247
1287
|
id: "zoom-slider",
|
|
@@ -1258,7 +1298,7 @@ function FileInput({
|
|
|
1258
1298
|
"button",
|
|
1259
1299
|
{
|
|
1260
1300
|
type: "button",
|
|
1261
|
-
className: "inline-flex items-center justify-center h-9 rounded-md px-4 text-sm font-medium border border-input bg-transparent hover:bg-
|
|
1301
|
+
className: "inline-flex items-center justify-center h-9 rounded-md px-4 text-sm font-medium border border-input bg-transparent hover:bg-primary hover:text-primary-foreground transition-colors",
|
|
1262
1302
|
onClick: handleCropCancel
|
|
1263
1303
|
},
|
|
1264
1304
|
"Cancel"
|
|
@@ -1652,36 +1692,43 @@ function TimePicker({
|
|
|
1652
1692
|
}
|
|
1653
1693
|
return mins;
|
|
1654
1694
|
}, [minuteStep]);
|
|
1655
|
-
const combinedClassName =
|
|
1695
|
+
const combinedClassName = cn("relative", className);
|
|
1656
1696
|
const displayValue = formatTimeValue(timeValue, use24Hour);
|
|
1657
|
-
return /* @__PURE__ */ React7.createElement("div", { ref: containerRef, className: combinedClassName }, /* @__PURE__ */ React7.createElement(
|
|
1658
|
-
"
|
|
1659
|
-
{
|
|
1660
|
-
type: "hidden",
|
|
1661
|
-
name,
|
|
1662
|
-
value
|
|
1663
|
-
}
|
|
1664
|
-
), /* @__PURE__ */ React7.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React7.createElement("span", { className: "absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground pointer-events-none", "aria-hidden": "true" }, /* @__PURE__ */ React7.createElement(
|
|
1665
|
-
"svg",
|
|
1697
|
+
return /* @__PURE__ */ React7.createElement("div", { ref: containerRef, className: combinedClassName }, /* @__PURE__ */ React7.createElement("input", { type: "hidden", name, value }), /* @__PURE__ */ React7.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React7.createElement(
|
|
1698
|
+
"span",
|
|
1666
1699
|
{
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
height: "18",
|
|
1670
|
-
viewBox: "0 0 24 24",
|
|
1671
|
-
fill: "none",
|
|
1672
|
-
stroke: "currentColor",
|
|
1673
|
-
strokeLinecap: "round",
|
|
1674
|
-
strokeLinejoin: "round",
|
|
1675
|
-
strokeWidth: "2"
|
|
1700
|
+
className: "absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none",
|
|
1701
|
+
"aria-hidden": "true"
|
|
1676
1702
|
},
|
|
1677
|
-
/* @__PURE__ */ React7.createElement(
|
|
1678
|
-
|
|
1679
|
-
|
|
1703
|
+
/* @__PURE__ */ React7.createElement(
|
|
1704
|
+
"svg",
|
|
1705
|
+
{
|
|
1706
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1707
|
+
width: "18",
|
|
1708
|
+
height: "18",
|
|
1709
|
+
viewBox: "0 0 24 24",
|
|
1710
|
+
fill: "none",
|
|
1711
|
+
stroke: "currentColor",
|
|
1712
|
+
strokeLinecap: "round",
|
|
1713
|
+
strokeLinejoin: "round",
|
|
1714
|
+
strokeWidth: "2"
|
|
1715
|
+
},
|
|
1716
|
+
/* @__PURE__ */ React7.createElement("circle", { cx: "12", cy: "12", r: "10" }),
|
|
1717
|
+
/* @__PURE__ */ React7.createElement("path", { d: "M12 6v6l4 2" })
|
|
1718
|
+
)
|
|
1719
|
+
), /* @__PURE__ */ React7.createElement(
|
|
1680
1720
|
"input",
|
|
1681
1721
|
{
|
|
1682
1722
|
ref: inputRef,
|
|
1683
1723
|
type: "text",
|
|
1684
|
-
className:
|
|
1724
|
+
className: cn(
|
|
1725
|
+
"flex h-9 w-full rounded-md border border-input bg-transparent py-1 text-base shadow-sm transition-colors",
|
|
1726
|
+
"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
1727
|
+
"disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
|
1728
|
+
showIcon ? "pl-10" : "pl-3",
|
|
1729
|
+
clearable && value ? "pr-10" : "pr-3",
|
|
1730
|
+
error && "border-red-500 ring-1 ring-red-500"
|
|
1731
|
+
),
|
|
1685
1732
|
value: displayValue,
|
|
1686
1733
|
onClick: handleToggle,
|
|
1687
1734
|
onBlur,
|
|
@@ -1697,13 +1744,13 @@ function TimePicker({
|
|
|
1697
1744
|
"button",
|
|
1698
1745
|
{
|
|
1699
1746
|
type: "button",
|
|
1700
|
-
className: "absolute right-3 top-1/2 -translate-y-1/2
|
|
1747
|
+
className: "absolute right-3 top-1/2 -translate-y-1/2 transition-colors",
|
|
1701
1748
|
onClick: handleClear,
|
|
1702
1749
|
"aria-label": "Clear time",
|
|
1703
1750
|
tabIndex: -1
|
|
1704
1751
|
},
|
|
1705
1752
|
"\u2715"
|
|
1706
|
-
)), isOpen && !disabled && /* @__PURE__ */ React7.createElement("div", { className: "absolute z-50 top-full mt-1 min-w-full rounded-md border border-border bg-popover text-popover-foreground shadow-md p-3" }, /* @__PURE__ */ React7.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col flex-1" }, /* @__PURE__ */ React7.createElement("div", { className: "text-xs font-medium
|
|
1753
|
+
)), isOpen && !disabled && /* @__PURE__ */ React7.createElement("div", { className: "absolute z-50 top-full mt-1 min-w-full rounded-md border border-border bg-popover text-popover-foreground shadow-md p-3" }, /* @__PURE__ */ React7.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col flex-1" }, /* @__PURE__ */ React7.createElement("div", { className: "text-xs font-medium mb-2 text-center" }, use24Hour ? "Hour" : "Hour"), /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col gap-1 max-h-48 overflow-y-auto" }, hours.map((hour) => {
|
|
1707
1754
|
const displayHour = use24Hour ? hour : hour;
|
|
1708
1755
|
const isSelected = use24Hour ? timeValue?.hour === (hour === 0 ? 12 : hour > 12 ? hour - 12 : hour) && timeValue?.period === (hour >= 12 ? "PM" : "AM") : timeValue?.hour === hour;
|
|
1709
1756
|
return /* @__PURE__ */ React7.createElement(
|
|
@@ -1711,7 +1758,12 @@ function TimePicker({
|
|
|
1711
1758
|
{
|
|
1712
1759
|
key: hour,
|
|
1713
1760
|
type: "button",
|
|
1714
|
-
className:
|
|
1761
|
+
className: cn(
|
|
1762
|
+
"flex items-center justify-center h-8 w-full rounded",
|
|
1763
|
+
"border-none bg-transparent cursor-pointer text-sm transition-colors",
|
|
1764
|
+
"hover:bg-primary hover:text-primary-foreground",
|
|
1765
|
+
isSelected ? "bg-primary text-primary-foreground font-semibold" : ""
|
|
1766
|
+
),
|
|
1715
1767
|
onClick: () => {
|
|
1716
1768
|
if (use24Hour) {
|
|
1717
1769
|
const hour12 = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour;
|
|
@@ -1731,24 +1783,34 @@ function TimePicker({
|
|
|
1731
1783
|
},
|
|
1732
1784
|
String(displayHour).padStart(2, "0")
|
|
1733
1785
|
);
|
|
1734
|
-
}))), /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col flex-1" }, /* @__PURE__ */ React7.createElement("div", { className: "text-xs font-medium
|
|
1786
|
+
}))), /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col flex-1" }, /* @__PURE__ */ React7.createElement("div", { className: "text-xs font-medium mb-2 text-center" }, "Minute"), /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col gap-1 max-h-48 overflow-y-auto" }, minutes.map((minute) => {
|
|
1735
1787
|
const isSelected = timeValue?.minute === minute;
|
|
1736
1788
|
return /* @__PURE__ */ React7.createElement(
|
|
1737
1789
|
"button",
|
|
1738
1790
|
{
|
|
1739
1791
|
key: minute,
|
|
1740
1792
|
type: "button",
|
|
1741
|
-
className:
|
|
1793
|
+
className: cn(
|
|
1794
|
+
"flex items-center justify-center h-8 w-full",
|
|
1795
|
+
"rounded border-none bg-transparent cursor-pointer text-sm transition-colors",
|
|
1796
|
+
"hover:bg-primary hover:text-primary-foreground",
|
|
1797
|
+
isSelected ? "bg-primary text-primary-foreground font-semibold" : ""
|
|
1798
|
+
),
|
|
1742
1799
|
onClick: () => handleMinuteChange(minute),
|
|
1743
1800
|
"aria-label": `${String(minute).padStart(2, "0")} minutes`
|
|
1744
1801
|
},
|
|
1745
1802
|
String(minute).padStart(2, "0")
|
|
1746
1803
|
);
|
|
1747
|
-
}))), !use24Hour && /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col w-20" }, /* @__PURE__ */ React7.createElement("div", { className: "text-xs font-medium
|
|
1804
|
+
}))), !use24Hour && /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col w-20" }, /* @__PURE__ */ React7.createElement("div", { className: "text-xs font-medium mb-2 text-center" }, "Period"), /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col gap-1" }, /* @__PURE__ */ React7.createElement(
|
|
1748
1805
|
"button",
|
|
1749
1806
|
{
|
|
1750
1807
|
type: "button",
|
|
1751
|
-
className:
|
|
1808
|
+
className: cn(
|
|
1809
|
+
"flex items-center justify-center h-8 w-full",
|
|
1810
|
+
"rounded border-none bg-transparent cursor-pointer text-sm",
|
|
1811
|
+
"transition-colors hover:bg-primary hover:text-primary-foreground",
|
|
1812
|
+
timeValue?.period === "AM" ? "bg-muted font-semibold" : ""
|
|
1813
|
+
),
|
|
1752
1814
|
onClick: () => handlePeriodChange("AM")
|
|
1753
1815
|
},
|
|
1754
1816
|
"AM"
|
|
@@ -1756,7 +1818,12 @@ function TimePicker({
|
|
|
1756
1818
|
"button",
|
|
1757
1819
|
{
|
|
1758
1820
|
type: "button",
|
|
1759
|
-
className:
|
|
1821
|
+
className: cn(
|
|
1822
|
+
"flex items-center justify-center h-8 w-full",
|
|
1823
|
+
"rounded border-none bg-transparent cursor-pointer text-sm",
|
|
1824
|
+
"transition-colors hover:bg-primary hover:text-primary-foreground",
|
|
1825
|
+
timeValue?.period === "PM" ? "bg-muted font-semibold" : ""
|
|
1826
|
+
),
|
|
1760
1827
|
onClick: () => handlePeriodChange("PM")
|
|
1761
1828
|
},
|
|
1762
1829
|
"PM"
|
|
@@ -1801,7 +1868,9 @@ function DateRangePicker({
|
|
|
1801
1868
|
...props
|
|
1802
1869
|
}) {
|
|
1803
1870
|
const [isOpen, setIsOpen] = React7.useState(false);
|
|
1804
|
-
const [selectedMonth, setSelectedMonth] = React7.useState(
|
|
1871
|
+
const [selectedMonth, setSelectedMonth] = React7.useState(
|
|
1872
|
+
value.start || /* @__PURE__ */ new Date()
|
|
1873
|
+
);
|
|
1805
1874
|
const [rangeStart, setRangeStart] = React7.useState(value.start);
|
|
1806
1875
|
const [rangeEnd, setRangeEnd] = React7.useState(value.end);
|
|
1807
1876
|
const [hoverDate, setHoverDate] = React7.useState(null);
|
|
@@ -1899,7 +1968,7 @@ function DateRangePicker({
|
|
|
1899
1968
|
"button",
|
|
1900
1969
|
{
|
|
1901
1970
|
type: "button",
|
|
1902
|
-
className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-
|
|
1971
|
+
className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-primary hover:text-primary-foreground cursor-pointer",
|
|
1903
1972
|
onClick: handlePrevMonth,
|
|
1904
1973
|
"aria-label": "Previous month"
|
|
1905
1974
|
},
|
|
@@ -1908,19 +1977,30 @@ function DateRangePicker({
|
|
|
1908
1977
|
"button",
|
|
1909
1978
|
{
|
|
1910
1979
|
type: "button",
|
|
1911
|
-
className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-
|
|
1980
|
+
className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-primary hover:text-primary-foreground cursor-pointer",
|
|
1912
1981
|
onClick: handleNextMonth,
|
|
1913
1982
|
"aria-label": "Next month"
|
|
1914
1983
|
},
|
|
1915
1984
|
"\u2192"
|
|
1916
|
-
)), /* @__PURE__ */ React7.createElement("div", { className: "grid grid-cols-7 gap-1 mt-2" }, ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((day) => /* @__PURE__ */ React7.createElement(
|
|
1985
|
+
)), /* @__PURE__ */ React7.createElement("div", { className: "grid grid-cols-7 gap-1 mt-2" }, ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((day) => /* @__PURE__ */ React7.createElement(
|
|
1986
|
+
"div",
|
|
1987
|
+
{
|
|
1988
|
+
key: day,
|
|
1989
|
+
className: "flex items-center justify-center h-8 w-full text-xs font-medium"
|
|
1990
|
+
},
|
|
1991
|
+
day
|
|
1992
|
+
))), /* @__PURE__ */ React7.createElement("div", { className: "grid grid-cols-7 gap-1" }, days.map((date, index) => {
|
|
1917
1993
|
if (!date) {
|
|
1918
1994
|
return /* @__PURE__ */ React7.createElement("div", { key: `empty-${index}` });
|
|
1919
1995
|
}
|
|
1920
1996
|
const isStart = rangeStart && date.toDateString() === rangeStart.toDateString();
|
|
1921
1997
|
const isEnd = rangeEnd && date.toDateString() === rangeEnd.toDateString();
|
|
1998
|
+
const isRangeEndpoint = Boolean(isStart || isEnd);
|
|
1922
1999
|
const isInRange = rangeStart && rangeEnd && isDateInRange(date, rangeStart, rangeEnd);
|
|
1923
2000
|
const isInHoverRange = rangeStart && !rangeEnd && hoverDate && (date >= rangeStart && date <= hoverDate || date <= rangeStart && date >= hoverDate);
|
|
2001
|
+
const isRangeHighlight = Boolean(
|
|
2002
|
+
(isInRange || isInHoverRange) && !isRangeEndpoint
|
|
2003
|
+
);
|
|
1924
2004
|
const isToday = date.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
|
|
1925
2005
|
const disabled2 = isDisabled(date);
|
|
1926
2006
|
return /* @__PURE__ */ React7.createElement(
|
|
@@ -1928,7 +2008,14 @@ function DateRangePicker({
|
|
|
1928
2008
|
{
|
|
1929
2009
|
key: date.toISOString(),
|
|
1930
2010
|
type: "button",
|
|
1931
|
-
className:
|
|
2011
|
+
className: cn(
|
|
2012
|
+
"flex items-center justify-center h-8 w-full rounded border-none bg-transparent",
|
|
2013
|
+
"cursor-pointer text-sm transition-colors hover:bg-muted",
|
|
2014
|
+
isRangeEndpoint && "bg-muted font-semibold",
|
|
2015
|
+
isRangeHighlight && "bg-muted/70",
|
|
2016
|
+
isToday && "border border-primary",
|
|
2017
|
+
disabled2 && "cursor-not-allowed opacity-50 pointer-events-none"
|
|
2018
|
+
),
|
|
1932
2019
|
onClick: () => !disabled2 && handleDateSelect(date),
|
|
1933
2020
|
onMouseEnter: () => setHoverDate(date),
|
|
1934
2021
|
onMouseLeave: () => setHoverDate(null),
|
|
@@ -1939,7 +2026,7 @@ function DateRangePicker({
|
|
|
1939
2026
|
);
|
|
1940
2027
|
})));
|
|
1941
2028
|
};
|
|
1942
|
-
const combinedClassName =
|
|
2029
|
+
const combinedClassName = cn("relative", className);
|
|
1943
2030
|
const displayValue = rangeStart && rangeEnd ? `${formatDate2(rangeStart, format)}${separator}${formatDate2(rangeEnd, format)}` : rangeStart ? formatDate2(rangeStart, format) : "";
|
|
1944
2031
|
return /* @__PURE__ */ React7.createElement("div", { ref: containerRef, className: combinedClassName }, /* @__PURE__ */ React7.createElement(
|
|
1945
2032
|
"input",
|
|
@@ -1955,25 +2042,39 @@ function DateRangePicker({
|
|
|
1955
2042
|
name: `${name}[end]`,
|
|
1956
2043
|
value: rangeEnd ? rangeEnd.toISOString() : ""
|
|
1957
2044
|
}
|
|
1958
|
-
), /* @__PURE__ */ React7.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React7.createElement(
|
|
1959
|
-
"
|
|
2045
|
+
), /* @__PURE__ */ React7.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React7.createElement(
|
|
2046
|
+
"span",
|
|
1960
2047
|
{
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
height: "18",
|
|
1964
|
-
viewBox: "0 0 24 24",
|
|
1965
|
-
fill: "none",
|
|
1966
|
-
stroke: "currentColor",
|
|
1967
|
-
strokeLinecap: "round",
|
|
1968
|
-
strokeLinejoin: "round",
|
|
1969
|
-
strokeWidth: "2"
|
|
2048
|
+
className: "absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none",
|
|
2049
|
+
"aria-hidden": "true"
|
|
1970
2050
|
},
|
|
1971
|
-
/* @__PURE__ */ React7.createElement(
|
|
1972
|
-
|
|
2051
|
+
/* @__PURE__ */ React7.createElement(
|
|
2052
|
+
"svg",
|
|
2053
|
+
{
|
|
2054
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2055
|
+
width: "18",
|
|
2056
|
+
height: "18",
|
|
2057
|
+
viewBox: "0 0 24 24",
|
|
2058
|
+
fill: "none",
|
|
2059
|
+
stroke: "currentColor",
|
|
2060
|
+
strokeLinecap: "round",
|
|
2061
|
+
strokeLinejoin: "round",
|
|
2062
|
+
strokeWidth: "2"
|
|
2063
|
+
},
|
|
2064
|
+
/* @__PURE__ */ React7.createElement("path", { d: "M8 2v4m8-4v4m5 8V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h8M3 10h18m-5 10l2 2l4-4" })
|
|
2065
|
+
)
|
|
2066
|
+
), /* @__PURE__ */ React7.createElement(
|
|
1973
2067
|
"input",
|
|
1974
2068
|
{
|
|
1975
2069
|
type: "text",
|
|
1976
|
-
className:
|
|
2070
|
+
className: cn(
|
|
2071
|
+
"flex h-9 w-full rounded-md border border-input bg-transparent py-1 text-base shadow-sm transition-colors",
|
|
2072
|
+
"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
2073
|
+
"disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
|
2074
|
+
showIcon ? "pl-10" : "pl-3",
|
|
2075
|
+
clearable && (rangeStart || rangeEnd) ? "pr-10" : "pr-3",
|
|
2076
|
+
error && "border-red-500 ring-1 ring-red-500"
|
|
2077
|
+
),
|
|
1977
2078
|
value: displayValue,
|
|
1978
2079
|
onClick: handleToggle,
|
|
1979
2080
|
onBlur,
|
|
@@ -1989,13 +2090,13 @@ function DateRangePicker({
|
|
|
1989
2090
|
"button",
|
|
1990
2091
|
{
|
|
1991
2092
|
type: "button",
|
|
1992
|
-
className: "absolute right-3 top-1/2 -translate-y-1/2
|
|
2093
|
+
className: "absolute right-3 top-1/2 -translate-y-1/2 transition-colors",
|
|
1993
2094
|
onClick: handleClear,
|
|
1994
2095
|
"aria-label": "Clear date range",
|
|
1995
2096
|
tabIndex: -1
|
|
1996
2097
|
},
|
|
1997
2098
|
"\u2715"
|
|
1998
|
-
)), isOpen && !disabled && /* @__PURE__ */ React7.createElement("div", { className: "absolute z-50 top-full mt-1 min-w-full rounded-md border border-border bg-popover text-popover-foreground shadow-md p-3" }, renderCalendar(), rangeStart && !rangeEnd && /* @__PURE__ */ React7.createElement("div", { className: "text-xs text-
|
|
2099
|
+
)), isOpen && !disabled && /* @__PURE__ */ React7.createElement("div", { className: "absolute z-50 top-full mt-1 min-w-full rounded-md border border-border bg-popover text-popover-foreground shadow-md p-3" }, renderCalendar(), rangeStart && !rangeEnd && /* @__PURE__ */ React7.createElement("div", { className: "text-xs text-center pt-2 border-t border-border mt-2" }, "Select end date")));
|
|
1999
2100
|
}
|
|
2000
2101
|
DateRangePicker.displayName = "DateRangePicker";
|
|
2001
2102
|
function htmlToMarkdown(html) {
|
|
@@ -2051,11 +2152,19 @@ function RichTextEditor({
|
|
|
2051
2152
|
className = "",
|
|
2052
2153
|
mode = "wysiwyg",
|
|
2053
2154
|
allowModeSwitch = false,
|
|
2054
|
-
placeholder = "
|
|
2155
|
+
placeholder = "Your message...",
|
|
2055
2156
|
minHeight = "200px",
|
|
2056
2157
|
maxHeight,
|
|
2057
2158
|
showToolbar = true,
|
|
2058
|
-
toolbarButtons = [
|
|
2159
|
+
toolbarButtons = [
|
|
2160
|
+
"bold",
|
|
2161
|
+
"italic",
|
|
2162
|
+
"underline",
|
|
2163
|
+
"heading",
|
|
2164
|
+
"bulletList",
|
|
2165
|
+
"orderedList",
|
|
2166
|
+
"link"
|
|
2167
|
+
],
|
|
2059
2168
|
...props
|
|
2060
2169
|
}) {
|
|
2061
2170
|
const [currentMode, setCurrentMode] = React7.useState(mode);
|
|
@@ -2164,7 +2273,7 @@ function RichTextEditor({
|
|
|
2164
2273
|
{
|
|
2165
2274
|
key: buttonName,
|
|
2166
2275
|
type: "button",
|
|
2167
|
-
className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-
|
|
2276
|
+
className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-muted cursor-pointer transition-colors disabled:cursor-not-allowed disabled:opacity-50",
|
|
2168
2277
|
onClick: () => editorRef.current && button.action(editorRef.current),
|
|
2169
2278
|
title: button.title,
|
|
2170
2279
|
disabled: disabled || currentMode === "markdown",
|
|
@@ -2176,7 +2285,7 @@ function RichTextEditor({
|
|
|
2176
2285
|
"button",
|
|
2177
2286
|
{
|
|
2178
2287
|
type: "button",
|
|
2179
|
-
className: "flex items-center justify-center h-8 px-3 rounded border-none bg-transparent hover:bg-
|
|
2288
|
+
className: "flex items-center justify-center h-8 px-3 rounded border-none bg-transparent hover:bg-muted text-xs font-medium cursor-pointer transition-colors disabled:cursor-not-allowed disabled:opacity-50",
|
|
2180
2289
|
onClick: handleModeToggle,
|
|
2181
2290
|
disabled,
|
|
2182
2291
|
title: `Switch to ${currentMode === "wysiwyg" ? "Markdown" : "WYSIWYG"}`,
|
|
@@ -2187,7 +2296,7 @@ function RichTextEditor({
|
|
|
2187
2296
|
"div",
|
|
2188
2297
|
{
|
|
2189
2298
|
ref: editorRef,
|
|
2190
|
-
className: "w-full p-3 text-base md:text-sm outline-none bg-transparent focus-visible:outline-none [&:empty:before]:content-[attr(data-placeholder)]
|
|
2299
|
+
className: "w-full p-3 text-base md:text-sm outline-none bg-transparent focus-visible:outline-none [&:empty:before]:content-[attr(data-placeholder)]",
|
|
2191
2300
|
role: "textbox",
|
|
2192
2301
|
contentEditable: !disabled,
|
|
2193
2302
|
onInput: handleWysiwygChange,
|
|
@@ -2202,7 +2311,7 @@ function RichTextEditor({
|
|
|
2202
2311
|
"textarea",
|
|
2203
2312
|
{
|
|
2204
2313
|
ref: textareaRef,
|
|
2205
|
-
className: "w-full p-3 text-base md:text-sm outline-none bg-transparent resize-none focus-visible:outline-none
|
|
2314
|
+
className: "w-full p-3 text-base md:text-sm outline-none bg-transparent resize-none focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50",
|
|
2206
2315
|
value: content,
|
|
2207
2316
|
onChange: handleMarkdownChange,
|
|
2208
2317
|
onBlur,
|