@underverse-ui/underverse 0.2.55 → 0.2.56
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +968 -603
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1024 -659
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -3650,6 +3650,23 @@ var useShadCNAnimations = () => {
|
|
|
3650
3650
|
|
|
3651
3651
|
// ../../components/ui/Popover.tsx
|
|
3652
3652
|
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
3653
|
+
function assignRef(ref, value) {
|
|
3654
|
+
if (!ref) return;
|
|
3655
|
+
if (typeof ref === "function") {
|
|
3656
|
+
ref(value);
|
|
3657
|
+
return;
|
|
3658
|
+
}
|
|
3659
|
+
try {
|
|
3660
|
+
ref.current = value;
|
|
3661
|
+
} catch {
|
|
3662
|
+
}
|
|
3663
|
+
}
|
|
3664
|
+
function getTransformOrigin(side, align) {
|
|
3665
|
+
if (side === "top") return `${align === "end" ? "right" : "left"} bottom`;
|
|
3666
|
+
if (side === "bottom") return `${align === "end" ? "right" : "left"} top`;
|
|
3667
|
+
if (side === "left") return "right top";
|
|
3668
|
+
return "left top";
|
|
3669
|
+
}
|
|
3653
3670
|
function normalizePlacement(placement) {
|
|
3654
3671
|
switch (placement) {
|
|
3655
3672
|
case "top":
|
|
@@ -3738,10 +3755,10 @@ var Popover = ({
|
|
|
3738
3755
|
}) => {
|
|
3739
3756
|
const isControlled = open !== void 0;
|
|
3740
3757
|
const [internalOpen, setInternalOpen] = React14.useState(false);
|
|
3741
|
-
const [dropdownPosition, setDropdownPosition] = React14.useState(null);
|
|
3742
|
-
const [lastTriggerRect, setLastTriggerRect] = React14.useState(null);
|
|
3743
3758
|
const triggerRef = React14.useRef(null);
|
|
3744
|
-
const
|
|
3759
|
+
const positionerRef = React14.useRef(null);
|
|
3760
|
+
const panelRef = React14.useRef(null);
|
|
3761
|
+
const lastAppliedRef = React14.useRef(null);
|
|
3745
3762
|
useShadCNAnimations();
|
|
3746
3763
|
const isOpen = isControlled ? open : internalOpen;
|
|
3747
3764
|
const setIsOpen = React14.useCallback(
|
|
@@ -3753,27 +3770,44 @@ var Popover = ({
|
|
|
3753
3770
|
);
|
|
3754
3771
|
const offset = 4;
|
|
3755
3772
|
const padding = 8;
|
|
3756
|
-
const
|
|
3773
|
+
const initialPlacement = React14.useMemo(() => normalizePlacement(placement), [placement]);
|
|
3757
3774
|
const updatePosition = React14.useCallback(() => {
|
|
3758
3775
|
const triggerEl = triggerRef.current;
|
|
3759
|
-
const
|
|
3760
|
-
|
|
3776
|
+
const positionerEl = positionerRef.current;
|
|
3777
|
+
const panelEl = panelRef.current;
|
|
3778
|
+
if (!triggerEl || !positionerEl || !panelEl) return;
|
|
3761
3779
|
const triggerRect = triggerEl.getBoundingClientRect();
|
|
3762
|
-
const
|
|
3763
|
-
const
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3780
|
+
const widthWanted = matchTriggerWidth ? triggerRect.width : contentWidth;
|
|
3781
|
+
const widthPx = widthWanted == null ? void 0 : Math.max(0, Math.round(widthWanted));
|
|
3782
|
+
if (widthPx == null) {
|
|
3783
|
+
if (positionerEl.style.width) positionerEl.style.width = "";
|
|
3784
|
+
} else if (positionerEl.style.width !== `${widthPx}px`) {
|
|
3785
|
+
positionerEl.style.width = `${widthPx}px`;
|
|
3786
|
+
}
|
|
3787
|
+
const prevApplied = lastAppliedRef.current;
|
|
3788
|
+
const measuredWidth = positionerEl.offsetWidth;
|
|
3789
|
+
const measuredHeight = positionerEl.offsetHeight;
|
|
3790
|
+
const contentRect = positionerEl.getBoundingClientRect();
|
|
3791
|
+
const contentBoxWidth = measuredWidth || contentRect.width;
|
|
3792
|
+
const contentBoxHeight = measuredHeight || contentRect.height;
|
|
3767
3793
|
const next = computePopoverPosition({
|
|
3768
3794
|
triggerRect,
|
|
3769
|
-
contentSize: { width:
|
|
3795
|
+
contentSize: { width: contentBoxWidth, height: contentBoxHeight },
|
|
3770
3796
|
placement,
|
|
3771
3797
|
offset,
|
|
3772
3798
|
padding,
|
|
3773
3799
|
viewport: { width: window.innerWidth, height: window.innerHeight }
|
|
3774
3800
|
});
|
|
3775
|
-
|
|
3776
|
-
|
|
3801
|
+
const top = Math.round(next.top);
|
|
3802
|
+
const left = Math.round(next.left);
|
|
3803
|
+
const applied = prevApplied && Math.abs(prevApplied.top - top) < 0.5 && Math.abs(prevApplied.left - left) < 0.5 && prevApplied.side === next.side && prevApplied.align === next.align && prevApplied.width === widthPx;
|
|
3804
|
+
if (applied) return;
|
|
3805
|
+
lastAppliedRef.current = { top, left, side: next.side, align: next.align, width: widthPx };
|
|
3806
|
+
positionerEl.style.transform = `translate3d(${left}px, ${top}px, 0)`;
|
|
3807
|
+
panelEl.style.transformOrigin = getTransformOrigin(next.side, next.align);
|
|
3808
|
+
if (positionerEl.style.visibility !== "visible") positionerEl.style.visibility = "visible";
|
|
3809
|
+
if (positionerEl.style.pointerEvents !== "auto") positionerEl.style.pointerEvents = "auto";
|
|
3810
|
+
}, [placement, matchTriggerWidth, contentWidth]);
|
|
3777
3811
|
React14.useLayoutEffect(() => {
|
|
3778
3812
|
if (!isOpen) return;
|
|
3779
3813
|
updatePosition();
|
|
@@ -3787,7 +3821,17 @@ var Popover = ({
|
|
|
3787
3821
|
cancelAnimationFrame(raf1);
|
|
3788
3822
|
cancelAnimationFrame(raf2);
|
|
3789
3823
|
};
|
|
3790
|
-
}, [isOpen, updatePosition
|
|
3824
|
+
}, [isOpen, updatePosition]);
|
|
3825
|
+
React14.useEffect(() => {
|
|
3826
|
+
if (!isOpen) return;
|
|
3827
|
+
let raf = 0;
|
|
3828
|
+
const tick = () => {
|
|
3829
|
+
updatePosition();
|
|
3830
|
+
raf = window.requestAnimationFrame(tick);
|
|
3831
|
+
};
|
|
3832
|
+
raf = window.requestAnimationFrame(tick);
|
|
3833
|
+
return () => window.cancelAnimationFrame(raf);
|
|
3834
|
+
}, [isOpen, updatePosition]);
|
|
3791
3835
|
React14.useEffect(() => {
|
|
3792
3836
|
if (!isOpen) return;
|
|
3793
3837
|
let raf = 0;
|
|
@@ -3798,34 +3842,34 @@ var Popover = ({
|
|
|
3798
3842
|
handler();
|
|
3799
3843
|
window.addEventListener("resize", handler);
|
|
3800
3844
|
window.addEventListener("scroll", handler, true);
|
|
3845
|
+
document.addEventListener("scroll", handler, true);
|
|
3801
3846
|
return () => {
|
|
3802
3847
|
cancelAnimationFrame(raf);
|
|
3803
3848
|
window.removeEventListener("resize", handler);
|
|
3804
3849
|
window.removeEventListener("scroll", handler, true);
|
|
3850
|
+
document.removeEventListener("scroll", handler, true);
|
|
3805
3851
|
};
|
|
3806
3852
|
}, [isOpen, updatePosition]);
|
|
3807
3853
|
React14.useEffect(() => {
|
|
3808
3854
|
if (!isOpen) return;
|
|
3809
|
-
if (!popoverRef.current) return;
|
|
3810
3855
|
if (typeof ResizeObserver === "undefined") return;
|
|
3811
3856
|
const ro = new ResizeObserver(() => updatePosition());
|
|
3812
|
-
ro.observe(
|
|
3857
|
+
if (positionerRef.current) ro.observe(positionerRef.current);
|
|
3858
|
+
if (triggerRef.current) ro.observe(triggerRef.current);
|
|
3813
3859
|
return () => ro.disconnect();
|
|
3814
3860
|
}, [isOpen, updatePosition]);
|
|
3815
3861
|
React14.useLayoutEffect(() => {
|
|
3816
3862
|
if (!isOpen) {
|
|
3817
|
-
|
|
3863
|
+
lastAppliedRef.current = null;
|
|
3818
3864
|
return;
|
|
3819
3865
|
}
|
|
3820
|
-
const rect = triggerRef.current?.getBoundingClientRect();
|
|
3821
|
-
if (rect) setLastTriggerRect({ width: rect.width });
|
|
3822
3866
|
}, [isOpen]);
|
|
3823
3867
|
React14.useEffect(() => {
|
|
3824
3868
|
if (!isOpen) return;
|
|
3825
3869
|
const handleClickOutside = (event) => {
|
|
3826
3870
|
const target = event.target;
|
|
3827
3871
|
const triggerEl = triggerRef.current;
|
|
3828
|
-
const popoverEl =
|
|
3872
|
+
const popoverEl = positionerRef.current;
|
|
3829
3873
|
if (!triggerEl || !popoverEl) return;
|
|
3830
3874
|
if (triggerEl.contains(target)) return;
|
|
3831
3875
|
if (popoverEl.contains(target)) return;
|
|
@@ -3847,56 +3891,53 @@ var Popover = ({
|
|
|
3847
3891
|
}, [isOpen, setIsOpen]);
|
|
3848
3892
|
const handleTriggerClick = () => {
|
|
3849
3893
|
if (!disabled) {
|
|
3850
|
-
|
|
3851
|
-
if (next) {
|
|
3852
|
-
const rect = triggerRef.current?.getBoundingClientRect();
|
|
3853
|
-
if (rect) setLastTriggerRect({ width: rect.width });
|
|
3854
|
-
setDropdownPosition(null);
|
|
3855
|
-
}
|
|
3856
|
-
setIsOpen(next);
|
|
3894
|
+
setIsOpen(!isOpen);
|
|
3857
3895
|
}
|
|
3858
3896
|
};
|
|
3859
3897
|
const popoverContent = isOpen && typeof window !== "undefined" ? (0, import_react_dom3.createPortal)(
|
|
3860
3898
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
3861
3899
|
"div",
|
|
3862
3900
|
{
|
|
3863
|
-
ref:
|
|
3901
|
+
ref: positionerRef,
|
|
3864
3902
|
"data-popover": true,
|
|
3865
3903
|
style: {
|
|
3866
3904
|
position: "fixed",
|
|
3867
|
-
top:
|
|
3868
|
-
left:
|
|
3869
|
-
|
|
3905
|
+
top: 0,
|
|
3906
|
+
left: 0,
|
|
3907
|
+
transform: "translate3d(0, 0, 0)",
|
|
3870
3908
|
zIndex: 9999,
|
|
3871
|
-
visibility:
|
|
3872
|
-
pointerEvents:
|
|
3873
|
-
|
|
3874
|
-
const { side, align } = dropdownPosition ?? normalizePlacement(placement);
|
|
3875
|
-
if (side === "top") return `${align === "end" ? "right" : "left"} bottom`;
|
|
3876
|
-
if (side === "bottom") return `${align === "end" ? "right" : "left"} top`;
|
|
3877
|
-
if (side === "left") return "right top";
|
|
3878
|
-
return "left top";
|
|
3879
|
-
})()
|
|
3909
|
+
visibility: "hidden",
|
|
3910
|
+
pointerEvents: "none",
|
|
3911
|
+
willChange: "transform"
|
|
3880
3912
|
},
|
|
3881
|
-
|
|
3882
|
-
role: "dialog",
|
|
3883
|
-
"aria-modal": modal || void 0,
|
|
3884
|
-
className: cn(
|
|
3885
|
-
"z-9999",
|
|
3886
|
-
// shadcn-like enter animation
|
|
3887
|
-
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
3888
|
-
className
|
|
3889
|
-
),
|
|
3913
|
+
className: "z-9999",
|
|
3890
3914
|
children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
3891
3915
|
"div",
|
|
3892
3916
|
{
|
|
3917
|
+
ref: panelRef,
|
|
3918
|
+
"data-state": "open",
|
|
3919
|
+
role: "dialog",
|
|
3920
|
+
"aria-modal": modal || void 0,
|
|
3921
|
+
style: {
|
|
3922
|
+
transformOrigin: getTransformOrigin(initialPlacement.side, initialPlacement.align)
|
|
3923
|
+
},
|
|
3893
3924
|
className: cn(
|
|
3894
|
-
|
|
3895
|
-
"
|
|
3896
|
-
|
|
3925
|
+
// shadcn-like enter animation
|
|
3926
|
+
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
3927
|
+
className
|
|
3897
3928
|
),
|
|
3898
|
-
|
|
3899
|
-
|
|
3929
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
3930
|
+
"div",
|
|
3931
|
+
{
|
|
3932
|
+
className: cn(
|
|
3933
|
+
"rounded-md border bg-popover text-popover-foreground shadow-md",
|
|
3934
|
+
"backdrop-blur-sm bg-popover/95 border-border/60 p-4",
|
|
3935
|
+
contentClassName
|
|
3936
|
+
),
|
|
3937
|
+
tabIndex: -1,
|
|
3938
|
+
children
|
|
3939
|
+
}
|
|
3940
|
+
)
|
|
3900
3941
|
}
|
|
3901
3942
|
)
|
|
3902
3943
|
}
|
|
@@ -3907,7 +3948,10 @@ var Popover = ({
|
|
|
3907
3948
|
(() => {
|
|
3908
3949
|
const triggerEl = trigger;
|
|
3909
3950
|
return React14.cloneElement(triggerEl, {
|
|
3910
|
-
ref:
|
|
3951
|
+
ref: (node) => {
|
|
3952
|
+
triggerRef.current = node;
|
|
3953
|
+
assignRef(triggerEl.props?.ref, node);
|
|
3954
|
+
},
|
|
3911
3955
|
onClick: (e) => {
|
|
3912
3956
|
e.preventDefault();
|
|
3913
3957
|
e.stopPropagation();
|
|
@@ -5678,7 +5722,6 @@ ScrollArea.displayName = "ScrollArea";
|
|
|
5678
5722
|
// ../../components/ui/DatePicker.tsx
|
|
5679
5723
|
var React23 = __toESM(require("react"), 1);
|
|
5680
5724
|
var import_react15 = require("react");
|
|
5681
|
-
var import_react_dom7 = require("react-dom");
|
|
5682
5725
|
var import_lucide_react14 = require("lucide-react");
|
|
5683
5726
|
|
|
5684
5727
|
// ../../lib/utils/date.ts
|
|
@@ -5713,35 +5756,11 @@ var DatePicker = ({
|
|
|
5713
5756
|
const t = useTranslations("DatePicker");
|
|
5714
5757
|
const locale = useLocale();
|
|
5715
5758
|
const [isOpen, setIsOpen] = React23.useState(false);
|
|
5716
|
-
const [dropdownPosition, setDropdownPosition] = React23.useState(null);
|
|
5717
5759
|
const [viewDate, setViewDate] = React23.useState(value || /* @__PURE__ */ new Date());
|
|
5718
5760
|
const triggerRef = React23.useRef(null);
|
|
5719
|
-
const
|
|
5761
|
+
const wheelContainerRef = React23.useRef(null);
|
|
5762
|
+
const wheelDeltaRef = React23.useRef(0);
|
|
5720
5763
|
useShadCNAnimations();
|
|
5721
|
-
const calculatePosition = React23.useCallback(() => {
|
|
5722
|
-
if (!triggerRef.current) return null;
|
|
5723
|
-
const rect = triggerRef.current.getBoundingClientRect();
|
|
5724
|
-
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
|
5725
|
-
const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
|
|
5726
|
-
return {
|
|
5727
|
-
top: rect.bottom + scrollTop + 4,
|
|
5728
|
-
left: rect.left + scrollLeft,
|
|
5729
|
-
width: rect.width
|
|
5730
|
-
};
|
|
5731
|
-
}, []);
|
|
5732
|
-
React23.useEffect(() => {
|
|
5733
|
-
if (!isOpen) return;
|
|
5734
|
-
const handler = () => {
|
|
5735
|
-
const pos = calculatePosition();
|
|
5736
|
-
if (pos) setDropdownPosition(pos);
|
|
5737
|
-
};
|
|
5738
|
-
window.addEventListener("resize", handler);
|
|
5739
|
-
window.addEventListener("scroll", handler, true);
|
|
5740
|
-
return () => {
|
|
5741
|
-
window.removeEventListener("resize", handler);
|
|
5742
|
-
window.removeEventListener("scroll", handler, true);
|
|
5743
|
-
};
|
|
5744
|
-
}, [isOpen, calculatePosition]);
|
|
5745
5764
|
React23.useEffect(() => {
|
|
5746
5765
|
if (value) {
|
|
5747
5766
|
setViewDate(value);
|
|
@@ -5749,31 +5768,6 @@ var DatePicker = ({
|
|
|
5749
5768
|
setViewDate(/* @__PURE__ */ new Date());
|
|
5750
5769
|
}
|
|
5751
5770
|
}, [value]);
|
|
5752
|
-
React23.useEffect(() => {
|
|
5753
|
-
if (!isOpen) return;
|
|
5754
|
-
const handleClickOutside = (event) => {
|
|
5755
|
-
const target = event.target;
|
|
5756
|
-
const trigger = triggerRef.current;
|
|
5757
|
-
const dropdown = dropdownRef.current;
|
|
5758
|
-
if (!trigger || !dropdown) return;
|
|
5759
|
-
const clickedOutsideTrigger = !trigger.contains(target);
|
|
5760
|
-
const clickedOutsideDropdown = !dropdown.contains(target);
|
|
5761
|
-
if (clickedOutsideTrigger && clickedOutsideDropdown) {
|
|
5762
|
-
setIsOpen(false);
|
|
5763
|
-
}
|
|
5764
|
-
};
|
|
5765
|
-
const handleEscape = (event) => {
|
|
5766
|
-
if (event.key === "Escape") {
|
|
5767
|
-
setIsOpen(false);
|
|
5768
|
-
}
|
|
5769
|
-
};
|
|
5770
|
-
document.addEventListener("mousedown", handleClickOutside);
|
|
5771
|
-
document.addEventListener("keydown", handleEscape);
|
|
5772
|
-
return () => {
|
|
5773
|
-
document.removeEventListener("mousedown", handleClickOutside);
|
|
5774
|
-
document.removeEventListener("keydown", handleEscape);
|
|
5775
|
-
};
|
|
5776
|
-
}, [isOpen]);
|
|
5777
5771
|
const handleDateSelect = (date) => {
|
|
5778
5772
|
let selectedDate;
|
|
5779
5773
|
if (value && (value.getHours() !== 0 || value.getMinutes() !== 0 || value.getSeconds() !== 0)) {
|
|
@@ -5798,19 +5792,52 @@ var DatePicker = ({
|
|
|
5798
5792
|
const getFirstDayOfMonth = (date) => {
|
|
5799
5793
|
return new Date(date.getFullYear(), date.getMonth(), 1).getDay();
|
|
5800
5794
|
};
|
|
5801
|
-
const navigateMonth = (direction) => {
|
|
5795
|
+
const navigateMonth = React23.useCallback((direction) => {
|
|
5802
5796
|
setViewDate((prev) => {
|
|
5803
5797
|
const newDate = new Date(prev);
|
|
5804
5798
|
newDate.setMonth(prev.getMonth() + (direction === "next" ? 1 : -1));
|
|
5805
5799
|
return newDate;
|
|
5806
5800
|
});
|
|
5801
|
+
}, []);
|
|
5802
|
+
const isElementVerticallyScrollable = (el) => {
|
|
5803
|
+
const style = window.getComputedStyle(el);
|
|
5804
|
+
const overflowY = style.overflowY;
|
|
5805
|
+
if (overflowY !== "auto" && overflowY !== "scroll") return false;
|
|
5806
|
+
const node = el;
|
|
5807
|
+
return node.scrollHeight > node.clientHeight + 1;
|
|
5807
5808
|
};
|
|
5809
|
+
React23.useEffect(() => {
|
|
5810
|
+
if (!isOpen) return;
|
|
5811
|
+
const container = wheelContainerRef.current;
|
|
5812
|
+
if (!container) return;
|
|
5813
|
+
const onWheel = (event) => {
|
|
5814
|
+
if (!container.contains(event.target)) return;
|
|
5815
|
+
if (event.ctrlKey) return;
|
|
5816
|
+
let node = event.target;
|
|
5817
|
+
while (node && node !== container) {
|
|
5818
|
+
if (isElementVerticallyScrollable(node)) return;
|
|
5819
|
+
node = node.parentElement;
|
|
5820
|
+
}
|
|
5821
|
+
if (isElementVerticallyScrollable(container)) return;
|
|
5822
|
+
event.preventDefault();
|
|
5823
|
+
event.stopPropagation();
|
|
5824
|
+
wheelDeltaRef.current += event.deltaY;
|
|
5825
|
+
const threshold = 70;
|
|
5826
|
+
if (Math.abs(wheelDeltaRef.current) < threshold) return;
|
|
5827
|
+
const steps = Math.trunc(wheelDeltaRef.current / threshold);
|
|
5828
|
+
wheelDeltaRef.current -= steps * threshold;
|
|
5829
|
+
const direction = steps > 0 ? "next" : "prev";
|
|
5830
|
+
for (let i = 0; i < Math.abs(steps); i++) navigateMonth(direction);
|
|
5831
|
+
};
|
|
5832
|
+
container.addEventListener("wheel", onWheel, { passive: false });
|
|
5833
|
+
return () => container.removeEventListener("wheel", onWheel);
|
|
5834
|
+
}, [isOpen, navigateMonth]);
|
|
5808
5835
|
const renderCalendar = () => {
|
|
5809
5836
|
const daysInMonth = getDaysInMonth(viewDate);
|
|
5810
5837
|
const firstDayOfMonth = getFirstDayOfMonth(viewDate);
|
|
5811
5838
|
const days = [];
|
|
5812
5839
|
for (let i = 0; i < firstDayOfMonth; i++) {
|
|
5813
|
-
days.push(/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "w-8 h-8" }, `empty-${i}`));
|
|
5840
|
+
days.push(/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: size === "sm" ? "w-7 h-7" : "w-8 h-8" }, `empty-${i}`));
|
|
5814
5841
|
}
|
|
5815
5842
|
const today = /* @__PURE__ */ new Date();
|
|
5816
5843
|
today.setHours(0, 0, 0, 0);
|
|
@@ -5822,23 +5849,26 @@ var DatePicker = ({
|
|
|
5822
5849
|
const totalDaysFromStart = firstDayOfMonth + day - 1;
|
|
5823
5850
|
const rowIndex = Math.floor(totalDaysFromStart / 7);
|
|
5824
5851
|
days.push(
|
|
5825
|
-
/* @__PURE__ */ (0, import_jsx_runtime29.
|
|
5852
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
5826
5853
|
"button",
|
|
5827
5854
|
{
|
|
5828
5855
|
onClick: () => !isPastDate && handleDateSelect(date),
|
|
5829
5856
|
disabled: isPastDate,
|
|
5830
5857
|
style: {
|
|
5831
|
-
animationDelay: isOpen ? `${rowIndex *
|
|
5858
|
+
animationDelay: isOpen ? `${rowIndex * 40}ms` : "0ms"
|
|
5832
5859
|
},
|
|
5833
5860
|
className: cn(
|
|
5834
5861
|
size === "sm" ? "w-7 h-7 text-[12px]" : "w-8 h-8 text-sm",
|
|
5835
|
-
"datepicker-day rounded-
|
|
5836
|
-
"transition-
|
|
5837
|
-
isPastDate && "opacity-
|
|
5838
|
-
isSelected ? "bg-primary
|
|
5839
|
-
isToday2 && !isSelected && "bg-
|
|
5862
|
+
"datepicker-day rounded-lg focus:outline-none relative",
|
|
5863
|
+
"transition-all duration-200 font-medium",
|
|
5864
|
+
isPastDate && "opacity-30 cursor-not-allowed text-muted-foreground",
|
|
5865
|
+
isSelected ? "bg-gradient-to-br from-primary to-primary/80 text-primary-foreground font-bold shadow-lg shadow-primary/30 scale-110 z-10 hover:from-primary hover:to-primary/70" : !isPastDate && "hover:bg-accent/80 hover:text-accent-foreground hover:scale-105 focus:bg-accent focus:text-accent-foreground",
|
|
5866
|
+
isToday2 && !isSelected && "bg-primary/15 text-primary font-bold ring-2 ring-primary/30"
|
|
5840
5867
|
),
|
|
5841
|
-
children:
|
|
5868
|
+
children: [
|
|
5869
|
+
day,
|
|
5870
|
+
isToday2 && !isSelected && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "absolute -bottom-0.5 left-1/2 -translate-x-1/2 w-1 h-1 rounded-full bg-primary" })
|
|
5871
|
+
]
|
|
5842
5872
|
},
|
|
5843
5873
|
day
|
|
5844
5874
|
)
|
|
@@ -5846,62 +5876,102 @@ var DatePicker = ({
|
|
|
5846
5876
|
}
|
|
5847
5877
|
return days;
|
|
5848
5878
|
};
|
|
5849
|
-
const datePickerContent =
|
|
5850
|
-
"div",
|
|
5851
|
-
|
|
5852
|
-
|
|
5853
|
-
|
|
5854
|
-
|
|
5855
|
-
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
|
|
5859
|
-
|
|
5860
|
-
|
|
5861
|
-
|
|
5862
|
-
|
|
5863
|
-
|
|
5864
|
-
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
5865
|
-
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95"
|
|
5879
|
+
const datePickerContent = /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { ref: wheelContainerRef, "data-datepicker": true, className: "w-full", children: [
|
|
5880
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex items-center justify-between mb-4 px-1", children: [
|
|
5881
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
5882
|
+
"button",
|
|
5883
|
+
{
|
|
5884
|
+
type: "button",
|
|
5885
|
+
onClick: () => navigateMonth("prev"),
|
|
5886
|
+
className: cn(
|
|
5887
|
+
"p-2 rounded-xl transition-all duration-200",
|
|
5888
|
+
"bg-muted/50 hover:bg-muted text-muted-foreground hover:text-foreground",
|
|
5889
|
+
"hover:scale-110 active:scale-95 hover:shadow-md",
|
|
5890
|
+
"focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/50"
|
|
5891
|
+
),
|
|
5892
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react14.ChevronLeft, { className: "h-4 w-4" })
|
|
5893
|
+
}
|
|
5866
5894
|
),
|
|
5867
|
-
|
|
5895
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col items-center", children: [
|
|
5896
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "text-sm font-bold text-foreground", children: viewDate.toLocaleDateString(locale === "vi" ? "vi-VN" : "en-US", { month: "long" }) }),
|
|
5897
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "text-xs text-muted-foreground font-medium", children: viewDate.getFullYear() })
|
|
5898
|
+
] }),
|
|
5899
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
5900
|
+
"button",
|
|
5901
|
+
{
|
|
5902
|
+
type: "button",
|
|
5903
|
+
onClick: () => navigateMonth("next"),
|
|
5904
|
+
className: cn(
|
|
5905
|
+
"p-2 rounded-xl transition-all duration-200",
|
|
5906
|
+
"bg-muted/50 hover:bg-muted text-muted-foreground hover:text-foreground",
|
|
5907
|
+
"hover:scale-110 active:scale-95 hover:shadow-md",
|
|
5908
|
+
"focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/50"
|
|
5909
|
+
),
|
|
5910
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react14.ChevronRight, { className: "h-4 w-4" })
|
|
5911
|
+
}
|
|
5912
|
+
)
|
|
5913
|
+
] }),
|
|
5914
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: cn("grid grid-cols-7 gap-1 mb-2 px-0.5"), children: (weekdayLabels || (locale === "vi" ? ["CN", "T2", "T3", "T4", "T5", "T6", "T7"] : ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"])).map(
|
|
5915
|
+
(day, idx) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
5868
5916
|
"div",
|
|
5869
5917
|
{
|
|
5870
|
-
ref: dropdownRef,
|
|
5871
5918
|
className: cn(
|
|
5872
|
-
"
|
|
5873
|
-
"
|
|
5874
|
-
|
|
5919
|
+
"text-center font-bold uppercase tracking-wide",
|
|
5920
|
+
size === "sm" ? "text-[9px] py-1" : "text-[10px] py-1.5",
|
|
5921
|
+
idx === 0 || idx === 6 ? "text-primary/70" : "text-muted-foreground/60"
|
|
5922
|
+
),
|
|
5923
|
+
children: day
|
|
5924
|
+
},
|
|
5925
|
+
day
|
|
5926
|
+
)
|
|
5927
|
+
) }),
|
|
5928
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "grid grid-cols-7 gap-1 p-1 rounded-xl bg-muted/20", children: renderCalendar() }),
|
|
5929
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex items-center gap-2 mt-4 pt-3 border-t border-border/50", children: [
|
|
5930
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
5931
|
+
"button",
|
|
5932
|
+
{
|
|
5933
|
+
type: "button",
|
|
5934
|
+
onClick: () => {
|
|
5935
|
+
const today = /* @__PURE__ */ new Date();
|
|
5936
|
+
handleDateSelect(today);
|
|
5937
|
+
},
|
|
5938
|
+
className: cn(
|
|
5939
|
+
"flex-1 px-3 py-2 text-xs font-semibold rounded-xl",
|
|
5940
|
+
"bg-gradient-to-r from-primary/10 to-primary/5 border border-primary/30",
|
|
5941
|
+
"text-primary hover:from-primary/20 hover:to-primary/10 hover:border-primary/50",
|
|
5942
|
+
"transition-all duration-300 flex items-center justify-center gap-2",
|
|
5943
|
+
"hover:scale-[1.02] active:scale-[0.98] hover:shadow-md hover:shadow-primary/10"
|
|
5875
5944
|
),
|
|
5876
|
-
style: { pointerEvents: "auto" },
|
|
5877
5945
|
children: [
|
|
5878
|
-
/* @__PURE__ */ (0, import_jsx_runtime29.
|
|
5879
|
-
|
|
5880
|
-
|
|
5881
|
-
|
|
5882
|
-
|
|
5883
|
-
|
|
5884
|
-
|
|
5885
|
-
|
|
5886
|
-
|
|
5887
|
-
|
|
5888
|
-
|
|
5889
|
-
|
|
5890
|
-
|
|
5891
|
-
|
|
5892
|
-
|
|
5893
|
-
|
|
5894
|
-
|
|
5895
|
-
|
|
5896
|
-
|
|
5897
|
-
|
|
5898
|
-
|
|
5899
|
-
|
|
5946
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react14.Sparkles, { className: "w-3.5 h-3.5" }),
|
|
5947
|
+
todayLabel || t("today")
|
|
5948
|
+
]
|
|
5949
|
+
}
|
|
5950
|
+
),
|
|
5951
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
5952
|
+
"button",
|
|
5953
|
+
{
|
|
5954
|
+
type: "button",
|
|
5955
|
+
onClick: () => {
|
|
5956
|
+
onChange(void 0);
|
|
5957
|
+
setIsOpen(false);
|
|
5958
|
+
setViewDate(/* @__PURE__ */ new Date());
|
|
5959
|
+
},
|
|
5960
|
+
className: cn(
|
|
5961
|
+
"flex-1 px-3 py-2 text-xs font-semibold rounded-xl",
|
|
5962
|
+
"bg-gradient-to-r from-destructive/10 to-destructive/5 border border-destructive/30",
|
|
5963
|
+
"text-destructive hover:from-destructive/20 hover:to-destructive/10 hover:border-destructive/50",
|
|
5964
|
+
"transition-all duration-300 flex items-center justify-center gap-2",
|
|
5965
|
+
"hover:scale-[1.02] active:scale-[0.98] hover:shadow-md hover:shadow-destructive/10"
|
|
5966
|
+
),
|
|
5967
|
+
children: [
|
|
5968
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react14.X, { className: "w-3.5 h-3.5" }),
|
|
5969
|
+
clearLabel || t("clear")
|
|
5900
5970
|
]
|
|
5901
5971
|
}
|
|
5902
5972
|
)
|
|
5903
|
-
}
|
|
5904
|
-
)
|
|
5973
|
+
] })
|
|
5974
|
+
] });
|
|
5905
5975
|
const autoId = (0, import_react15.useId)();
|
|
5906
5976
|
const resolvedId = id ? String(id) : `datepicker-${autoId}`;
|
|
5907
5977
|
const labelId = label ? `${resolvedId}-label` : void 0;
|
|
@@ -5909,7 +5979,7 @@ var DatePicker = ({
|
|
|
5909
5979
|
const radiusClass = size === "sm" ? "rounded-md" : "rounded-lg";
|
|
5910
5980
|
const verticalGap = size === "sm" ? "space-y-1.5" : "space-y-2";
|
|
5911
5981
|
return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: cn("w-full group", verticalGap), children: [
|
|
5912
|
-
label && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
5982
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "flex items-center justify-between mb-2", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
5913
5983
|
"label",
|
|
5914
5984
|
{
|
|
5915
5985
|
id: labelId,
|
|
@@ -5917,82 +5987,122 @@ var DatePicker = ({
|
|
|
5917
5987
|
onClick: () => triggerRef.current?.focus(),
|
|
5918
5988
|
className: cn(
|
|
5919
5989
|
labelSize,
|
|
5920
|
-
"font-
|
|
5921
|
-
disabled ? "text-muted-foreground" : "text-foreground group-focus-within:text-primary"
|
|
5990
|
+
"font-semibold transition-colors duration-300 cursor-pointer",
|
|
5991
|
+
disabled ? "text-muted-foreground" : "text-foreground group-focus-within:text-primary hover:text-primary"
|
|
5922
5992
|
),
|
|
5923
5993
|
children: [
|
|
5924
5994
|
label,
|
|
5925
|
-
required && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "text-destructive ml-1", children: "*" })
|
|
5995
|
+
required && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "text-destructive ml-1 animate-pulse", children: "*" })
|
|
5926
5996
|
]
|
|
5927
5997
|
}
|
|
5928
5998
|
) }),
|
|
5929
|
-
/* @__PURE__ */ (0, import_jsx_runtime29.
|
|
5930
|
-
|
|
5999
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
6000
|
+
Popover,
|
|
5931
6001
|
{
|
|
5932
|
-
|
|
5933
|
-
|
|
6002
|
+
open: isOpen,
|
|
6003
|
+
onOpenChange: setIsOpen,
|
|
6004
|
+
placement: "bottom-start",
|
|
5934
6005
|
disabled,
|
|
5935
|
-
|
|
5936
|
-
|
|
5937
|
-
|
|
5938
|
-
|
|
5939
|
-
|
|
5940
|
-
|
|
5941
|
-
|
|
6006
|
+
contentWidth: size === "sm" ? 240 : 280,
|
|
6007
|
+
contentClassName: cn(
|
|
6008
|
+
"p-0",
|
|
6009
|
+
"backdrop-blur-xl bg-popover/95 border-border/40 shadow-2xl",
|
|
6010
|
+
"rounded-2xl",
|
|
6011
|
+
// Keep usable on small viewports (wheel scroll should stay within the popover if it overflows)
|
|
6012
|
+
"max-w-[calc(100vw-1rem)] max-h-[calc(100vh-6rem)] overflow-auto overscroll-contain",
|
|
6013
|
+
size === "sm" ? "p-4" : "p-5",
|
|
6014
|
+
"animate-in fade-in-0 zoom-in-95 slide-in-from-top-2 duration-300"
|
|
6015
|
+
),
|
|
6016
|
+
trigger: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
6017
|
+
"button",
|
|
6018
|
+
{
|
|
6019
|
+
ref: triggerRef,
|
|
6020
|
+
type: "button",
|
|
6021
|
+
disabled,
|
|
6022
|
+
id: resolvedId,
|
|
6023
|
+
"aria-labelledby": labelId,
|
|
6024
|
+
className: cn(
|
|
6025
|
+
"group flex w-full items-center justify-between border bg-background/80 backdrop-blur-sm",
|
|
6026
|
+
size === "sm" ? "rounded-lg" : "rounded-xl",
|
|
6027
|
+
size === "sm" ? "px-2.5 py-1.5 text-sm h-8 md:h-7 md:text-xs md:py-1" : "px-3 py-2.5 text-sm h-11",
|
|
6028
|
+
"border-border/60 hover:border-primary/40",
|
|
6029
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background",
|
|
6030
|
+
"disabled:opacity-50 disabled:cursor-not-allowed",
|
|
6031
|
+
"hover:bg-accent/10 hover:shadow-lg hover:shadow-primary/5 hover:-translate-y-0.5",
|
|
6032
|
+
"transition-all duration-300 ease-out",
|
|
6033
|
+
isOpen && "ring-2 ring-primary/30 border-primary/50 shadow-lg shadow-primary/10",
|
|
6034
|
+
className
|
|
6035
|
+
),
|
|
6036
|
+
children: [
|
|
6037
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex items-center gap-2.5", children: [
|
|
6038
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
6039
|
+
"div",
|
|
6040
|
+
{
|
|
6041
|
+
className: cn(
|
|
6042
|
+
"flex items-center justify-center rounded-lg p-1.5 transition-all duration-300",
|
|
6043
|
+
isOpen ? "bg-primary/15 text-primary" : "bg-muted/50 text-muted-foreground group-hover:bg-primary/10 group-hover:text-primary"
|
|
6044
|
+
),
|
|
6045
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react14.Calendar, { className: cn(size === "sm" ? "h-3.5 w-3.5" : "h-4 w-4", "transition-transform duration-300", isOpen && "scale-110") })
|
|
6046
|
+
}
|
|
6047
|
+
),
|
|
6048
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
6049
|
+
"span",
|
|
6050
|
+
{
|
|
6051
|
+
className: cn("truncate font-medium transition-colors duration-200", !value && "text-muted-foreground", value && "text-foreground"),
|
|
6052
|
+
children: value ? formatDateDisplay(value) : placeholder || t("placeholder")
|
|
6053
|
+
}
|
|
6054
|
+
)
|
|
6055
|
+
] }),
|
|
6056
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
6057
|
+
value && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
6058
|
+
"span",
|
|
6059
|
+
{
|
|
6060
|
+
role: "button",
|
|
6061
|
+
"aria-label": clearLabel || t("clear"),
|
|
6062
|
+
tabIndex: 0,
|
|
6063
|
+
onClick: (e) => {
|
|
6064
|
+
e.preventDefault();
|
|
6065
|
+
e.stopPropagation();
|
|
6066
|
+
onChange(void 0);
|
|
6067
|
+
setViewDate(/* @__PURE__ */ new Date());
|
|
6068
|
+
},
|
|
6069
|
+
onKeyDown: (e) => {
|
|
6070
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
6071
|
+
e.preventDefault();
|
|
6072
|
+
e.stopPropagation();
|
|
6073
|
+
onChange(void 0);
|
|
6074
|
+
setViewDate(/* @__PURE__ */ new Date());
|
|
6075
|
+
}
|
|
6076
|
+
},
|
|
6077
|
+
className: cn(
|
|
6078
|
+
"inline-flex items-center justify-center rounded-lg p-1",
|
|
6079
|
+
"text-muted-foreground hover:text-destructive hover:bg-destructive/10",
|
|
6080
|
+
"transition-all duration-200 cursor-pointer hover:scale-110"
|
|
6081
|
+
),
|
|
6082
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react14.X, { className: "h-3.5 w-3.5" })
|
|
6083
|
+
}
|
|
6084
|
+
),
|
|
6085
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
6086
|
+
"span",
|
|
6087
|
+
{
|
|
6088
|
+
className: cn("transition-all duration-300 text-muted-foreground group-hover:text-foreground", isOpen && "rotate-180 text-primary"),
|
|
6089
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("svg", { className: size === "sm" ? "h-3.5 w-3.5" : "h-4 w-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2.5, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) })
|
|
6090
|
+
}
|
|
6091
|
+
)
|
|
6092
|
+
] })
|
|
6093
|
+
]
|
|
5942
6094
|
}
|
|
5943
|
-
setIsOpen(next);
|
|
5944
|
-
},
|
|
5945
|
-
className: cn(
|
|
5946
|
-
cn(
|
|
5947
|
-
"flex w-full items-center justify-between border border-input bg-background",
|
|
5948
|
-
radiusClass,
|
|
5949
|
-
size === "sm" ? "px-2.5 py-1.5 text-sm h-8 md:h-7 md:text-xs md:py-1" : "px-3 py-2 text-sm h-10"
|
|
5950
|
-
),
|
|
5951
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
|
|
5952
|
-
"disabled:opacity-50 disabled:cursor-not-allowed",
|
|
5953
|
-
"hover:bg-accent/5 transition-colors",
|
|
5954
|
-
className
|
|
5955
6095
|
),
|
|
5956
|
-
children:
|
|
5957
|
-
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: cn("truncate", !value && "text-muted-foreground"), children: value ? formatDateDisplay(value) : placeholder || t("placeholder") }),
|
|
5958
|
-
value && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
5959
|
-
"span",
|
|
5960
|
-
{
|
|
5961
|
-
role: "button",
|
|
5962
|
-
"aria-label": clearLabel || t("clear"),
|
|
5963
|
-
tabIndex: 0,
|
|
5964
|
-
onClick: (e) => {
|
|
5965
|
-
e.preventDefault();
|
|
5966
|
-
e.stopPropagation();
|
|
5967
|
-
onChange(void 0);
|
|
5968
|
-
setViewDate(/* @__PURE__ */ new Date());
|
|
5969
|
-
},
|
|
5970
|
-
onKeyDown: (e) => {
|
|
5971
|
-
if (e.key === "Enter" || e.key === " ") {
|
|
5972
|
-
e.preventDefault();
|
|
5973
|
-
e.stopPropagation();
|
|
5974
|
-
onChange(void 0);
|
|
5975
|
-
setViewDate(/* @__PURE__ */ new Date());
|
|
5976
|
-
}
|
|
5977
|
-
},
|
|
5978
|
-
className: "absolute right-8 inline-flex items-center justify-center rounded-sm text-muted-foreground hover:text-foreground hover:bg-accent/50 transition-colors cursor-pointer",
|
|
5979
|
-
style: { width: 20, height: 20 },
|
|
5980
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react14.X, { className: "h-3.5 w-3.5" })
|
|
5981
|
-
}
|
|
5982
|
-
),
|
|
5983
|
-
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react14.Calendar, { className: "h-4 w-4 text-muted-foreground ml-2" })
|
|
5984
|
-
]
|
|
6096
|
+
children: datePickerContent
|
|
5985
6097
|
}
|
|
5986
|
-
)
|
|
5987
|
-
isOpen && dropdownPosition && typeof window !== "undefined" && (0, import_react_dom7.createPortal)(datePickerContent, document.body)
|
|
6098
|
+
)
|
|
5988
6099
|
] });
|
|
5989
6100
|
};
|
|
5990
6101
|
var DateRangePicker = ({ startDate, endDate, onChange, placeholder = "Select date range...", className, disablePastDates = false }) => {
|
|
5991
6102
|
const locale = useLocale();
|
|
5992
6103
|
const [isOpen, setIsOpen] = React23.useState(false);
|
|
5993
|
-
const
|
|
5994
|
-
const
|
|
5995
|
-
const panelRef = React23.useRef(null);
|
|
6104
|
+
const wheelContainerRef = React23.useRef(null);
|
|
6105
|
+
const wheelDeltaRef = React23.useRef(0);
|
|
5996
6106
|
const [viewDate, setViewDate] = React23.useState(startDate || /* @__PURE__ */ new Date());
|
|
5997
6107
|
const [tempStart, setTempStart] = React23.useState(startDate || null);
|
|
5998
6108
|
const [tempEnd, setTempEnd] = React23.useState(endDate || null);
|
|
@@ -6003,43 +6113,6 @@ var DateRangePicker = ({ startDate, endDate, onChange, placeholder = "Select dat
|
|
|
6003
6113
|
React23.useEffect(() => {
|
|
6004
6114
|
setTempEnd(endDate || null);
|
|
6005
6115
|
}, [endDate]);
|
|
6006
|
-
const calculatePosition = React23.useCallback(() => {
|
|
6007
|
-
if (!triggerRef.current) return null;
|
|
6008
|
-
const rect = triggerRef.current.getBoundingClientRect();
|
|
6009
|
-
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
|
6010
|
-
const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
|
|
6011
|
-
return { top: rect.bottom + scrollTop + 4, left: rect.left + scrollLeft, width: rect.width };
|
|
6012
|
-
}, []);
|
|
6013
|
-
React23.useEffect(() => {
|
|
6014
|
-
if (!isOpen) return;
|
|
6015
|
-
const handler = () => {
|
|
6016
|
-
const pos = calculatePosition();
|
|
6017
|
-
if (pos) setDropdownPosition(pos);
|
|
6018
|
-
};
|
|
6019
|
-
window.addEventListener("resize", handler);
|
|
6020
|
-
window.addEventListener("scroll", handler, true);
|
|
6021
|
-
return () => {
|
|
6022
|
-
window.removeEventListener("resize", handler);
|
|
6023
|
-
window.removeEventListener("scroll", handler, true);
|
|
6024
|
-
};
|
|
6025
|
-
}, [isOpen, calculatePosition]);
|
|
6026
|
-
React23.useEffect(() => {
|
|
6027
|
-
if (!isOpen) return;
|
|
6028
|
-
const handleClickOutside = (event) => {
|
|
6029
|
-
if (triggerRef.current && !triggerRef.current.contains(event.target) && panelRef.current && !panelRef.current.contains(event.target)) {
|
|
6030
|
-
setIsOpen(false);
|
|
6031
|
-
}
|
|
6032
|
-
};
|
|
6033
|
-
const handleEscape = (event) => {
|
|
6034
|
-
if (event.key === "Escape") setIsOpen(false);
|
|
6035
|
-
};
|
|
6036
|
-
document.addEventListener("mousedown", handleClickOutside);
|
|
6037
|
-
document.addEventListener("keydown", handleEscape);
|
|
6038
|
-
return () => {
|
|
6039
|
-
document.removeEventListener("mousedown", handleClickOutside);
|
|
6040
|
-
document.removeEventListener("keydown", handleEscape);
|
|
6041
|
-
};
|
|
6042
|
-
}, [isOpen]);
|
|
6043
6116
|
const isSameDay2 = (a, b) => {
|
|
6044
6117
|
if (!a || !b) return false;
|
|
6045
6118
|
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
@@ -6047,6 +6120,42 @@ var DateRangePicker = ({ startDate, endDate, onChange, placeholder = "Select dat
|
|
|
6047
6120
|
const inRange = (d, s, e) => d > s && d < e;
|
|
6048
6121
|
const getDaysInMonth = (d) => new Date(d.getFullYear(), d.getMonth() + 1, 0).getDate();
|
|
6049
6122
|
const getFirstDayOfMonth = (d) => new Date(d.getFullYear(), d.getMonth(), 1).getDay();
|
|
6123
|
+
const navigateMonth = React23.useCallback((direction) => {
|
|
6124
|
+
setViewDate((prev) => new Date(prev.getFullYear(), prev.getMonth() + (direction === "next" ? 1 : -1), 1));
|
|
6125
|
+
}, []);
|
|
6126
|
+
const isElementVerticallyScrollable = (el) => {
|
|
6127
|
+
const style = window.getComputedStyle(el);
|
|
6128
|
+
const overflowY = style.overflowY;
|
|
6129
|
+
if (overflowY !== "auto" && overflowY !== "scroll") return false;
|
|
6130
|
+
const node = el;
|
|
6131
|
+
return node.scrollHeight > node.clientHeight + 1;
|
|
6132
|
+
};
|
|
6133
|
+
React23.useEffect(() => {
|
|
6134
|
+
if (!isOpen) return;
|
|
6135
|
+
const container = wheelContainerRef.current;
|
|
6136
|
+
if (!container) return;
|
|
6137
|
+
const onWheel = (event) => {
|
|
6138
|
+
if (!container.contains(event.target)) return;
|
|
6139
|
+
if (event.ctrlKey) return;
|
|
6140
|
+
let node = event.target;
|
|
6141
|
+
while (node && node !== container) {
|
|
6142
|
+
if (isElementVerticallyScrollable(node)) return;
|
|
6143
|
+
node = node.parentElement;
|
|
6144
|
+
}
|
|
6145
|
+
if (isElementVerticallyScrollable(container)) return;
|
|
6146
|
+
event.preventDefault();
|
|
6147
|
+
event.stopPropagation();
|
|
6148
|
+
wheelDeltaRef.current += event.deltaY;
|
|
6149
|
+
const threshold = 70;
|
|
6150
|
+
if (Math.abs(wheelDeltaRef.current) < threshold) return;
|
|
6151
|
+
const steps = Math.trunc(wheelDeltaRef.current / threshold);
|
|
6152
|
+
wheelDeltaRef.current -= steps * threshold;
|
|
6153
|
+
const direction = steps > 0 ? "next" : "prev";
|
|
6154
|
+
for (let i = 0; i < Math.abs(steps); i++) navigateMonth(direction);
|
|
6155
|
+
};
|
|
6156
|
+
container.addEventListener("wheel", onWheel, { passive: false });
|
|
6157
|
+
return () => container.removeEventListener("wheel", onWheel);
|
|
6158
|
+
}, [isOpen, navigateMonth]);
|
|
6050
6159
|
const handleSelect = (date) => {
|
|
6051
6160
|
const localDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
|
6052
6161
|
if (!tempStart || tempStart && tempEnd) {
|
|
@@ -6105,16 +6214,16 @@ var DateRangePicker = ({ startDate, endDate, onChange, placeholder = "Select dat
|
|
|
6105
6214
|
className: cn(
|
|
6106
6215
|
"w-8 h-8 text-sm transition-all duration-200 focus:outline-none relative font-medium",
|
|
6107
6216
|
// Disabled/past date state
|
|
6108
|
-
isPastDate && "opacity-
|
|
6217
|
+
isPastDate && "opacity-30 cursor-not-allowed text-muted-foreground",
|
|
6109
6218
|
// Default state
|
|
6110
|
-
!isPastDate && !isInRange && !isRangeStart && !isRangeEnd && "hover:bg-accent hover:text-accent-foreground rounded-
|
|
6111
|
-
// Range selection styling - smooth continuous background
|
|
6112
|
-
isInRange && "bg-primary/15 text-foreground
|
|
6113
|
-
(isRangeStart || isRangeEnd) && "bg-primary text-primary-foreground hover:
|
|
6219
|
+
!isPastDate && !isInRange && !isRangeStart && !isRangeEnd && "hover:bg-accent/80 hover:text-accent-foreground hover:scale-105 rounded-lg",
|
|
6220
|
+
// Range selection styling - smooth continuous background with gradient
|
|
6221
|
+
isInRange && "bg-primary/15 text-foreground",
|
|
6222
|
+
(isRangeStart || isRangeEnd) && "bg-gradient-to-br from-primary to-primary/80 text-primary-foreground hover:from-primary hover:to-primary/70 shadow-lg shadow-primary/25",
|
|
6114
6223
|
// Only round the actual start and end of the range
|
|
6115
|
-
isRangeStart && !isRangeEnd && "rounded-l-
|
|
6116
|
-
isRangeEnd && !isRangeStart && "rounded-r-
|
|
6117
|
-
isRangeStart && isRangeEnd && "rounded-
|
|
6224
|
+
isRangeStart && !isRangeEnd && "rounded-l-lg rounded-r-none",
|
|
6225
|
+
isRangeEnd && !isRangeStart && "rounded-r-lg rounded-l-none",
|
|
6226
|
+
isRangeStart && isRangeEnd && "rounded-lg",
|
|
6118
6227
|
// Single day selection
|
|
6119
6228
|
// Hover effects for range
|
|
6120
6229
|
isInRange && !isPastDate && "hover:bg-primary/25",
|
|
@@ -6128,81 +6237,115 @@ var DateRangePicker = ({ startDate, endDate, onChange, placeholder = "Select dat
|
|
|
6128
6237
|
}
|
|
6129
6238
|
return nodes;
|
|
6130
6239
|
};
|
|
6131
|
-
const panel =
|
|
6132
|
-
"div",
|
|
6240
|
+
const panel = /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { ref: wheelContainerRef, className: "w-full", children: [
|
|
6241
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex items-center justify-between mb-4 px-1", children: [
|
|
6242
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
6243
|
+
"button",
|
|
6244
|
+
{
|
|
6245
|
+
type: "button",
|
|
6246
|
+
onClick: () => navigateMonth("prev"),
|
|
6247
|
+
className: cn(
|
|
6248
|
+
"p-2 rounded-xl transition-all duration-200",
|
|
6249
|
+
"bg-muted/50 hover:bg-muted text-muted-foreground hover:text-foreground",
|
|
6250
|
+
"hover:scale-110 active:scale-95 hover:shadow-md",
|
|
6251
|
+
"focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/50"
|
|
6252
|
+
),
|
|
6253
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react14.ChevronLeft, { className: "h-4 w-4" })
|
|
6254
|
+
}
|
|
6255
|
+
),
|
|
6256
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col items-center", children: [
|
|
6257
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "text-sm font-bold text-foreground", children: viewDate.toLocaleDateString(locale === "vi" ? "vi-VN" : "en-US", { month: "long" }) }),
|
|
6258
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "text-xs text-muted-foreground font-medium", children: viewDate.getFullYear() })
|
|
6259
|
+
] }),
|
|
6260
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
6261
|
+
"button",
|
|
6262
|
+
{
|
|
6263
|
+
type: "button",
|
|
6264
|
+
onClick: () => navigateMonth("next"),
|
|
6265
|
+
className: cn(
|
|
6266
|
+
"p-2 rounded-xl transition-all duration-200",
|
|
6267
|
+
"bg-muted/50 hover:bg-muted text-muted-foreground hover:text-foreground",
|
|
6268
|
+
"hover:scale-110 active:scale-95 hover:shadow-md",
|
|
6269
|
+
"focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/50"
|
|
6270
|
+
),
|
|
6271
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react14.ChevronRight, { className: "h-4 w-4" })
|
|
6272
|
+
}
|
|
6273
|
+
)
|
|
6274
|
+
] }),
|
|
6275
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "grid grid-cols-7 gap-1 mb-2 px-0.5", children: (locale === "vi" ? ["CN", "T2", "T3", "T4", "T5", "T6", "T7"] : ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"]).map((d, idx) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
6276
|
+
"div",
|
|
6277
|
+
{
|
|
6278
|
+
className: cn(
|
|
6279
|
+
"text-[10px] text-center py-1.5 font-bold uppercase tracking-wide",
|
|
6280
|
+
idx === 0 || idx === 6 ? "text-primary/70" : "text-muted-foreground/60"
|
|
6281
|
+
),
|
|
6282
|
+
children: d
|
|
6283
|
+
},
|
|
6284
|
+
d
|
|
6285
|
+
)) }),
|
|
6286
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "grid grid-cols-7 gap-0.5 p-1 rounded-xl bg-muted/20", children: renderGrid() })
|
|
6287
|
+
] });
|
|
6288
|
+
const displayFormat = (date) => formatDateShort(date);
|
|
6289
|
+
const label = tempStart && tempEnd ? `${displayFormat(tempStart)} - ${displayFormat(tempEnd)}` : tempStart ? `${displayFormat(tempStart)} - ...` : placeholder;
|
|
6290
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
6291
|
+
Popover,
|
|
6133
6292
|
{
|
|
6134
|
-
|
|
6135
|
-
|
|
6136
|
-
|
|
6137
|
-
|
|
6138
|
-
|
|
6139
|
-
"
|
|
6293
|
+
open: isOpen,
|
|
6294
|
+
onOpenChange: setIsOpen,
|
|
6295
|
+
placement: "bottom-start",
|
|
6296
|
+
contentWidth: 280,
|
|
6297
|
+
contentClassName: cn(
|
|
6298
|
+
"p-0",
|
|
6299
|
+
"backdrop-blur-xl bg-popover/95 border-border/40 shadow-2xl",
|
|
6300
|
+
"rounded-2xl",
|
|
6301
|
+
"max-w-[calc(100vw-1rem)] max-h-[calc(100vh-6rem)] overflow-auto overscroll-contain",
|
|
6302
|
+
"p-5",
|
|
6303
|
+
"animate-in fade-in-0 zoom-in-95 slide-in-from-top-2 duration-300"
|
|
6140
6304
|
),
|
|
6141
|
-
|
|
6142
|
-
"
|
|
6305
|
+
trigger: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
6306
|
+
"button",
|
|
6143
6307
|
{
|
|
6144
|
-
|
|
6145
|
-
className: cn(
|
|
6308
|
+
type: "button",
|
|
6309
|
+
className: cn(
|
|
6310
|
+
"group flex w-full items-center justify-between rounded-xl border bg-background/80 backdrop-blur-sm px-3 py-2.5 text-sm",
|
|
6311
|
+
"border-border/60 hover:border-primary/40",
|
|
6312
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background",
|
|
6313
|
+
"hover:bg-accent/10 hover:shadow-lg hover:shadow-primary/5 hover:-translate-y-0.5",
|
|
6314
|
+
"transition-all duration-300 ease-out",
|
|
6315
|
+
isOpen && "ring-2 ring-primary/30 border-primary/50 shadow-lg shadow-primary/10",
|
|
6316
|
+
className
|
|
6317
|
+
),
|
|
6146
6318
|
children: [
|
|
6147
|
-
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex items-center
|
|
6319
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex items-center gap-2.5", children: [
|
|
6148
6320
|
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
6149
|
-
|
|
6321
|
+
"div",
|
|
6150
6322
|
{
|
|
6151
|
-
|
|
6152
|
-
|
|
6153
|
-
|
|
6154
|
-
|
|
6155
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react14.
|
|
6323
|
+
className: cn(
|
|
6324
|
+
"flex items-center justify-center rounded-lg p-1.5 transition-all duration-300",
|
|
6325
|
+
isOpen ? "bg-primary/15 text-primary" : "bg-muted/50 text-muted-foreground group-hover:bg-primary/10 group-hover:text-primary"
|
|
6326
|
+
),
|
|
6327
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react14.Calendar, { className: cn("h-4 w-4 transition-transform duration-300", isOpen && "scale-110") })
|
|
6156
6328
|
}
|
|
6157
6329
|
),
|
|
6158
|
-
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "text-sm font-semibold", children: viewDate.toLocaleDateString(locale === "vi" ? "vi-VN" : "en-US", { month: "long", year: "numeric" }) }),
|
|
6159
6330
|
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
6160
|
-
|
|
6331
|
+
"span",
|
|
6161
6332
|
{
|
|
6162
|
-
|
|
6163
|
-
|
|
6164
|
-
|
|
6165
|
-
|
|
6166
|
-
|
|
6333
|
+
className: cn(
|
|
6334
|
+
"truncate font-medium transition-colors duration-200",
|
|
6335
|
+
!tempStart && !tempEnd && "text-muted-foreground",
|
|
6336
|
+
(tempStart || tempEnd) && "text-foreground"
|
|
6337
|
+
),
|
|
6338
|
+
children: label
|
|
6167
6339
|
}
|
|
6168
6340
|
)
|
|
6169
6341
|
] }),
|
|
6170
|
-
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("
|
|
6171
|
-
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "grid grid-cols-7", children: renderGrid() })
|
|
6342
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: cn("transition-all duration-300 text-muted-foreground group-hover:text-foreground", isOpen && "rotate-180 text-primary"), children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("svg", { className: "h-4 w-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2.5, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) }) })
|
|
6172
6343
|
]
|
|
6173
6344
|
}
|
|
6174
|
-
)
|
|
6345
|
+
),
|
|
6346
|
+
children: panel
|
|
6175
6347
|
}
|
|
6176
|
-
)
|
|
6177
|
-
const displayFormat = (date) => formatDateShort(date);
|
|
6178
|
-
const label = tempStart && tempEnd ? `${displayFormat(tempStart)} - ${displayFormat(tempEnd)}` : tempStart ? `${displayFormat(tempStart)} - ...` : placeholder;
|
|
6179
|
-
return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_jsx_runtime29.Fragment, { children: [
|
|
6180
|
-
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
6181
|
-
"button",
|
|
6182
|
-
{
|
|
6183
|
-
ref: triggerRef,
|
|
6184
|
-
type: "button",
|
|
6185
|
-
onClick: () => {
|
|
6186
|
-
const next = !isOpen;
|
|
6187
|
-
if (next) {
|
|
6188
|
-
const pos = calculatePosition();
|
|
6189
|
-
if (pos) setDropdownPosition(pos);
|
|
6190
|
-
}
|
|
6191
|
-
setIsOpen(next);
|
|
6192
|
-
},
|
|
6193
|
-
className: cn(
|
|
6194
|
-
"flex w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm",
|
|
6195
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
|
|
6196
|
-
className
|
|
6197
|
-
),
|
|
6198
|
-
children: [
|
|
6199
|
-
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: cn("truncate", !tempStart && !tempEnd && "text-muted-foreground"), children: label }),
|
|
6200
|
-
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react14.Calendar, { className: "h-4 w-4 text-muted-foreground ml-2" })
|
|
6201
|
-
]
|
|
6202
|
-
}
|
|
6203
|
-
),
|
|
6204
|
-
isOpen && dropdownPosition && typeof window !== "undefined" && (0, import_react_dom7.createPortal)(panel, document.body)
|
|
6205
|
-
] });
|
|
6348
|
+
);
|
|
6206
6349
|
};
|
|
6207
6350
|
|
|
6208
6351
|
// ../../components/ui/DateTimePicker.tsx
|
|
@@ -6496,6 +6639,175 @@ var React25 = __toESM(require("react"), 1);
|
|
|
6496
6639
|
var import_lucide_react16 = require("lucide-react");
|
|
6497
6640
|
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
6498
6641
|
var pad = (n) => n.toString().padStart(2, "0");
|
|
6642
|
+
var WHEEL_ITEM_HEIGHT = {
|
|
6643
|
+
sm: 30,
|
|
6644
|
+
md: 34,
|
|
6645
|
+
lg: 40
|
|
6646
|
+
};
|
|
6647
|
+
var WHEEL_VISIBLE_ITEMS = 5;
|
|
6648
|
+
function WheelColumn({
|
|
6649
|
+
labelText,
|
|
6650
|
+
column,
|
|
6651
|
+
items,
|
|
6652
|
+
valueIndex,
|
|
6653
|
+
onSelect,
|
|
6654
|
+
scrollRef,
|
|
6655
|
+
itemHeight,
|
|
6656
|
+
animate,
|
|
6657
|
+
focused,
|
|
6658
|
+
setFocusedColumn,
|
|
6659
|
+
onKeyDown
|
|
6660
|
+
}) {
|
|
6661
|
+
const height = itemHeight * WHEEL_VISIBLE_ITEMS;
|
|
6662
|
+
const paddingY = (height - itemHeight) / 2;
|
|
6663
|
+
const rafRef = React25.useRef(0);
|
|
6664
|
+
const lastIndexRef = React25.useRef(null);
|
|
6665
|
+
const wheelDeltaRef = React25.useRef(0);
|
|
6666
|
+
const scrollEndTimeoutRef = React25.useRef(null);
|
|
6667
|
+
const suppressScrollSelectUntilRef = React25.useRef(0);
|
|
6668
|
+
React25.useEffect(() => {
|
|
6669
|
+
const el = scrollRef.current;
|
|
6670
|
+
if (!el) return;
|
|
6671
|
+
const nextTop = Math.max(0, valueIndex) * itemHeight;
|
|
6672
|
+
if (Math.abs(el.scrollTop - nextTop) > 1) {
|
|
6673
|
+
el.scrollTo({ top: nextTop, behavior: animate ? "smooth" : "auto" });
|
|
6674
|
+
}
|
|
6675
|
+
lastIndexRef.current = valueIndex;
|
|
6676
|
+
return () => {
|
|
6677
|
+
if (scrollEndTimeoutRef.current != null) {
|
|
6678
|
+
window.clearTimeout(scrollEndTimeoutRef.current);
|
|
6679
|
+
scrollEndTimeoutRef.current = null;
|
|
6680
|
+
}
|
|
6681
|
+
cancelAnimationFrame(rafRef.current);
|
|
6682
|
+
};
|
|
6683
|
+
}, [animate, itemHeight, scrollRef, valueIndex]);
|
|
6684
|
+
React25.useEffect(() => {
|
|
6685
|
+
const el = scrollRef.current;
|
|
6686
|
+
if (!el) return;
|
|
6687
|
+
const lastWheelSignRef = { current: 0 };
|
|
6688
|
+
const lastStepAtRef = { current: 0 };
|
|
6689
|
+
const lastStepSignRef = { current: 0 };
|
|
6690
|
+
const onWheel = (event) => {
|
|
6691
|
+
if (!el.contains(event.target)) return;
|
|
6692
|
+
if (event.ctrlKey) return;
|
|
6693
|
+
event.preventDefault();
|
|
6694
|
+
event.stopPropagation();
|
|
6695
|
+
setFocusedColumn(column);
|
|
6696
|
+
if (document.activeElement !== el) el.focus({ preventScroll: true });
|
|
6697
|
+
const sign = Math.sign(event.deltaY);
|
|
6698
|
+
if (sign === 0) return;
|
|
6699
|
+
if (lastWheelSignRef.current !== 0 && sign !== lastWheelSignRef.current) {
|
|
6700
|
+
if (Date.now() - lastStepAtRef.current < 180 && lastStepSignRef.current !== 0) return;
|
|
6701
|
+
wheelDeltaRef.current = 0;
|
|
6702
|
+
}
|
|
6703
|
+
lastWheelSignRef.current = sign;
|
|
6704
|
+
let step = 0;
|
|
6705
|
+
if (event.deltaMode !== 0 || Math.abs(event.deltaY) >= 40) {
|
|
6706
|
+
step = sign;
|
|
6707
|
+
wheelDeltaRef.current = 0;
|
|
6708
|
+
} else {
|
|
6709
|
+
wheelDeltaRef.current += event.deltaY;
|
|
6710
|
+
const threshold = Math.min(12, Math.max(4, Math.round(itemHeight * 0.12)));
|
|
6711
|
+
if (Math.abs(wheelDeltaRef.current) < threshold) return;
|
|
6712
|
+
step = Math.sign(wheelDeltaRef.current);
|
|
6713
|
+
wheelDeltaRef.current = 0;
|
|
6714
|
+
}
|
|
6715
|
+
const fromIndex = lastIndexRef.current ?? valueIndex;
|
|
6716
|
+
const nextIndex = Math.max(0, Math.min(items.length - 1, fromIndex + step));
|
|
6717
|
+
if (nextIndex === fromIndex) return;
|
|
6718
|
+
lastStepAtRef.current = Date.now();
|
|
6719
|
+
lastStepSignRef.current = step;
|
|
6720
|
+
lastIndexRef.current = nextIndex;
|
|
6721
|
+
suppressScrollSelectUntilRef.current = Date.now() + 350;
|
|
6722
|
+
el.scrollTo({ top: nextIndex * itemHeight, behavior: animate ? "smooth" : "auto" });
|
|
6723
|
+
onSelect(items[nextIndex]);
|
|
6724
|
+
};
|
|
6725
|
+
el.addEventListener("wheel", onWheel, { passive: false });
|
|
6726
|
+
return () => el.removeEventListener("wheel", onWheel);
|
|
6727
|
+
}, [animate, column, itemHeight, items, onSelect, scrollRef, setFocusedColumn, valueIndex]);
|
|
6728
|
+
const handleScroll = () => {
|
|
6729
|
+
const el = scrollRef.current;
|
|
6730
|
+
if (!el) return;
|
|
6731
|
+
if (Date.now() < suppressScrollSelectUntilRef.current) return;
|
|
6732
|
+
cancelAnimationFrame(rafRef.current);
|
|
6733
|
+
rafRef.current = window.requestAnimationFrame(() => {
|
|
6734
|
+
if (scrollEndTimeoutRef.current != null) {
|
|
6735
|
+
window.clearTimeout(scrollEndTimeoutRef.current);
|
|
6736
|
+
}
|
|
6737
|
+
scrollEndTimeoutRef.current = window.setTimeout(() => {
|
|
6738
|
+
const idx = Math.max(0, Math.min(items.length - 1, Math.round(el.scrollTop / itemHeight)));
|
|
6739
|
+
if (lastIndexRef.current === idx) return;
|
|
6740
|
+
lastIndexRef.current = idx;
|
|
6741
|
+
suppressScrollSelectUntilRef.current = Date.now() + 350;
|
|
6742
|
+
el.scrollTo({ top: idx * itemHeight, behavior: animate ? "smooth" : "auto" });
|
|
6743
|
+
onSelect(items[idx]);
|
|
6744
|
+
}, 120);
|
|
6745
|
+
});
|
|
6746
|
+
};
|
|
6747
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex-1 min-w-[70px] max-w-[90px]", children: [
|
|
6748
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "text-[10px] font-bold uppercase tracking-wider text-muted-foreground/70 mb-3 text-center", children: labelText }),
|
|
6749
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "relative rounded-xl bg-muted/30 overflow-hidden", style: { height }, children: [
|
|
6750
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
6751
|
+
"div",
|
|
6752
|
+
{
|
|
6753
|
+
className: "pointer-events-none absolute inset-x-2 top-1/2 -translate-y-1/2 rounded-lg bg-gradient-to-r from-primary/20 via-primary/15 to-primary/20 border border-primary/30 shadow-sm shadow-primary/10",
|
|
6754
|
+
style: { height: itemHeight }
|
|
6755
|
+
}
|
|
6756
|
+
),
|
|
6757
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "pointer-events-none absolute inset-x-0 top-0 h-12 bg-gradient-to-b from-background/95 via-background/60 to-transparent z-10" }),
|
|
6758
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "pointer-events-none absolute inset-x-0 bottom-0 h-12 bg-gradient-to-t from-background/95 via-background/60 to-transparent z-10" }),
|
|
6759
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
6760
|
+
"div",
|
|
6761
|
+
{
|
|
6762
|
+
ref: scrollRef,
|
|
6763
|
+
className: cn(
|
|
6764
|
+
"h-full overflow-y-auto overscroll-contain snap-y snap-mandatory scroll-smooth",
|
|
6765
|
+
"scrollbar-none",
|
|
6766
|
+
"focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background rounded-xl"
|
|
6767
|
+
),
|
|
6768
|
+
style: { paddingTop: paddingY, paddingBottom: paddingY },
|
|
6769
|
+
role: "listbox",
|
|
6770
|
+
"aria-label": `Select ${labelText.toLowerCase()}`,
|
|
6771
|
+
tabIndex: focused ? 0 : -1,
|
|
6772
|
+
onKeyDown: (e) => onKeyDown(e, column),
|
|
6773
|
+
onFocus: () => setFocusedColumn(column),
|
|
6774
|
+
onScroll: handleScroll,
|
|
6775
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { children: items.map((n, index) => {
|
|
6776
|
+
const dist = Math.abs(index - valueIndex);
|
|
6777
|
+
const scale = 1 - Math.min(dist * 0.12, 0.36);
|
|
6778
|
+
const opacity = 1 - Math.min(dist * 0.22, 0.75);
|
|
6779
|
+
const isSelected = index === valueIndex;
|
|
6780
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
6781
|
+
"button",
|
|
6782
|
+
{
|
|
6783
|
+
type: "button",
|
|
6784
|
+
role: "option",
|
|
6785
|
+
"aria-selected": isSelected,
|
|
6786
|
+
className: cn(
|
|
6787
|
+
"w-full snap-center flex items-center justify-center rounded-lg transition-all duration-200 font-bold tabular-nums",
|
|
6788
|
+
isSelected ? "text-primary text-lg" : "text-muted-foreground hover:text-foreground/70"
|
|
6789
|
+
),
|
|
6790
|
+
style: {
|
|
6791
|
+
height: itemHeight,
|
|
6792
|
+
transform: `scale(${scale})`,
|
|
6793
|
+
opacity
|
|
6794
|
+
},
|
|
6795
|
+
onClick: () => {
|
|
6796
|
+
const el = scrollRef.current;
|
|
6797
|
+
suppressScrollSelectUntilRef.current = Date.now() + 350;
|
|
6798
|
+
el?.scrollTo({ top: index * itemHeight, behavior: animate ? "smooth" : "auto" });
|
|
6799
|
+
onSelect(n);
|
|
6800
|
+
},
|
|
6801
|
+
children: pad(n)
|
|
6802
|
+
},
|
|
6803
|
+
n
|
|
6804
|
+
);
|
|
6805
|
+
}) })
|
|
6806
|
+
}
|
|
6807
|
+
)
|
|
6808
|
+
] })
|
|
6809
|
+
] });
|
|
6810
|
+
}
|
|
6499
6811
|
function parseTime(input, fmt = "24", includeSeconds) {
|
|
6500
6812
|
if (!input) return null;
|
|
6501
6813
|
try {
|
|
@@ -6528,10 +6840,10 @@ function formatTime({ h, m, s, p }, fmt, includeSeconds) {
|
|
|
6528
6840
|
return includeSeconds ? `${base}:${pad(s)}` : base;
|
|
6529
6841
|
}
|
|
6530
6842
|
var PRESETS = {
|
|
6531
|
-
morning: { h: 9, m: 0, s: 0 },
|
|
6532
|
-
afternoon: { h: 14, m: 0, s: 0 },
|
|
6533
|
-
evening: { h: 18, m: 0, s: 0 },
|
|
6534
|
-
night: { h: 21, m: 0, s: 0 }
|
|
6843
|
+
morning: { h: 9, m: 0, s: 0, icon: import_lucide_react16.Coffee, label: "Morning", color: "from-amber-400 to-orange-400" },
|
|
6844
|
+
afternoon: { h: 14, m: 0, s: 0, icon: import_lucide_react16.Sun, label: "Afternoon", color: "from-yellow-400 to-amber-400" },
|
|
6845
|
+
evening: { h: 18, m: 0, s: 0, icon: import_lucide_react16.Sunset, label: "Evening", color: "from-orange-400 to-rose-400" },
|
|
6846
|
+
night: { h: 21, m: 0, s: 0, icon: import_lucide_react16.Moon, label: "Night", color: "from-indigo-400 to-purple-400" }
|
|
6535
6847
|
};
|
|
6536
6848
|
function TimePicker({
|
|
6537
6849
|
value,
|
|
@@ -6580,23 +6892,6 @@ function TimePicker({
|
|
|
6580
6892
|
if (parsed) setParts(parsed);
|
|
6581
6893
|
}
|
|
6582
6894
|
}, [value, isControlled, format, includeSeconds]);
|
|
6583
|
-
React25.useEffect(() => {
|
|
6584
|
-
if (!open) return;
|
|
6585
|
-
const scrollToSelected = (ref, targetValue, step) => {
|
|
6586
|
-
if (!ref.current) return;
|
|
6587
|
-
const buttons = ref.current.querySelectorAll("button");
|
|
6588
|
-
const targetIndex = Math.floor(targetValue / step);
|
|
6589
|
-
const targetButton = buttons[targetIndex];
|
|
6590
|
-
if (targetButton) {
|
|
6591
|
-
targetButton.scrollIntoView({ behavior: animate ? "smooth" : "auto", block: "center" });
|
|
6592
|
-
}
|
|
6593
|
-
};
|
|
6594
|
-
setTimeout(() => {
|
|
6595
|
-
scrollToSelected(hourScrollRef, parts.h, 1);
|
|
6596
|
-
scrollToSelected(minuteScrollRef, parts.m, minuteStep);
|
|
6597
|
-
if (includeSeconds) scrollToSelected(secondScrollRef, parts.s, secondStep);
|
|
6598
|
-
}, 50);
|
|
6599
|
-
}, [open, parts.h, parts.m, parts.s, minuteStep, secondStep, includeSeconds, animate]);
|
|
6600
6895
|
const isTimeDisabled = React25.useCallback(
|
|
6601
6896
|
(timeStr) => {
|
|
6602
6897
|
if (!disabledTimes) return false;
|
|
@@ -6752,68 +7047,117 @@ function TimePicker({
|
|
|
6752
7047
|
"aria-haspopup": "dialog",
|
|
6753
7048
|
"aria-expanded": open,
|
|
6754
7049
|
className: cn(
|
|
6755
|
-
"flex w-full items-center justify-between border bg-background",
|
|
7050
|
+
"group flex w-full items-center justify-between border bg-background/80 backdrop-blur-sm",
|
|
6756
7051
|
sz.height,
|
|
6757
7052
|
sz.padding,
|
|
6758
7053
|
sz.text,
|
|
6759
7054
|
radiusClass,
|
|
6760
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-
|
|
7055
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background",
|
|
6761
7056
|
"disabled:opacity-50 disabled:cursor-not-allowed",
|
|
6762
|
-
"transition-all duration-
|
|
6763
|
-
error && "border-destructive focus-visible:ring-destructive",
|
|
6764
|
-
success && "border-green-500 focus-visible:ring-green-500",
|
|
6765
|
-
!error && !success && "border-
|
|
6766
|
-
animate && !disabled && "hover:shadow-
|
|
7057
|
+
"transition-all duration-300 ease-out",
|
|
7058
|
+
error && "border-destructive/60 focus-visible:ring-destructive/50 bg-destructive/5",
|
|
7059
|
+
success && "border-green-500/60 focus-visible:ring-green-500/50 bg-green-500/5",
|
|
7060
|
+
!error && !success && "border-border/60 hover:border-primary/40 hover:bg-accent/10",
|
|
7061
|
+
animate && !disabled && "hover:shadow-lg hover:shadow-primary/5 hover:-translate-y-0.5",
|
|
7062
|
+
open && "ring-2 ring-primary/30 border-primary/50 shadow-lg shadow-primary/10",
|
|
6767
7063
|
className
|
|
6768
7064
|
),
|
|
6769
7065
|
children: [
|
|
6770
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
6771
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
6772
|
-
|
|
7066
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex items-center gap-2.5", children: [
|
|
7067
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
7068
|
+
"div",
|
|
7069
|
+
{
|
|
7070
|
+
className: cn(
|
|
7071
|
+
"flex items-center justify-center rounded-md p-1.5 transition-all duration-300",
|
|
7072
|
+
error ? "bg-destructive/10 text-destructive" : success ? "bg-green-500/10 text-green-500" : open ? "bg-primary/15 text-primary" : "bg-muted/50 text-muted-foreground group-hover:bg-primary/10 group-hover:text-primary"
|
|
7073
|
+
),
|
|
7074
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react16.Clock, { className: cn(sz.icon, "transition-transform duration-300", open && "rotate-12") })
|
|
7075
|
+
}
|
|
7076
|
+
),
|
|
7077
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
7078
|
+
"span",
|
|
7079
|
+
{
|
|
7080
|
+
className: cn(
|
|
7081
|
+
"truncate font-medium transition-colors duration-200",
|
|
7082
|
+
!value && !defaultValue && "text-muted-foreground",
|
|
7083
|
+
value || defaultValue ? "text-foreground" : ""
|
|
7084
|
+
),
|
|
7085
|
+
children: value || defaultValue ? display : placeholder
|
|
7086
|
+
}
|
|
7087
|
+
)
|
|
6773
7088
|
] }),
|
|
6774
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: cn("ml-2 transition-
|
|
7089
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: cn("ml-2 transition-all duration-300 text-muted-foreground group-hover:text-foreground", open && "rotate-180 text-primary"), children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("svg", { className: sz.icon, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2.5, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) }) })
|
|
6775
7090
|
]
|
|
6776
7091
|
}
|
|
6777
7092
|
);
|
|
6778
7093
|
const contentWidth = variant === "compact" ? 240 : variant === "inline" ? 320 : includeSeconds ? 340 : 300;
|
|
6779
|
-
const
|
|
6780
|
-
|
|
6781
|
-
|
|
6782
|
-
|
|
6783
|
-
|
|
6784
|
-
|
|
6785
|
-
|
|
6786
|
-
|
|
6787
|
-
|
|
6788
|
-
|
|
6789
|
-
|
|
6790
|
-
|
|
6791
|
-
|
|
6792
|
-
|
|
6793
|
-
|
|
6794
|
-
|
|
6795
|
-
|
|
6796
|
-
|
|
6797
|
-
|
|
6798
|
-
|
|
6799
|
-
|
|
6800
|
-
|
|
6801
|
-
|
|
6802
|
-
|
|
6803
|
-
|
|
6804
|
-
|
|
6805
|
-
|
|
6806
|
-
|
|
6807
|
-
}
|
|
6808
|
-
|
|
6809
|
-
|
|
7094
|
+
const itemHeight = WHEEL_ITEM_HEIGHT[size];
|
|
7095
|
+
const setHourFromDisplay = (hourDisplay) => {
|
|
7096
|
+
const period = parts.p ?? (parts.h >= 12 ? "PM" : "AM");
|
|
7097
|
+
const nextH = format === "24" ? hourDisplay : (() => {
|
|
7098
|
+
const base = hourDisplay % 12;
|
|
7099
|
+
return period === "PM" ? base + 12 : base;
|
|
7100
|
+
})();
|
|
7101
|
+
const next = { ...parts, h: nextH, p: format === "12" ? period : parts.p };
|
|
7102
|
+
setParts(next);
|
|
7103
|
+
emit(next);
|
|
7104
|
+
};
|
|
7105
|
+
const timePickerContent = /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "space-y-4", children: [
|
|
7106
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "flex items-center justify-center py-2 px-3 rounded-xl bg-gradient-to-r from-primary/10 via-primary/5 to-primary/10 border border-primary/20", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "text-2xl font-bold tabular-nums tracking-wide text-foreground", children: display }) }),
|
|
7107
|
+
allowManualInput && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "relative", children: [
|
|
7108
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
7109
|
+
Input_default,
|
|
7110
|
+
{
|
|
7111
|
+
placeholder: format === "12" ? "02:30 PM" : "14:30",
|
|
7112
|
+
value: manualInput || display,
|
|
7113
|
+
onChange: (e) => handleManualInput(e.target.value),
|
|
7114
|
+
size: "sm",
|
|
7115
|
+
variant: "outlined",
|
|
7116
|
+
className: "pl-9"
|
|
7117
|
+
}
|
|
7118
|
+
),
|
|
7119
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react16.Clock, { className: "absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground" })
|
|
7120
|
+
] }),
|
|
7121
|
+
showPresets && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "grid grid-cols-2 gap-2", children: Object.keys(PRESETS).map((preset) => {
|
|
7122
|
+
const { icon: Icon, label: label2, color } = PRESETS[preset];
|
|
7123
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
7124
|
+
"button",
|
|
7125
|
+
{
|
|
7126
|
+
type: "button",
|
|
7127
|
+
className: cn(
|
|
7128
|
+
"group relative px-3 py-2.5 text-xs font-medium rounded-xl border border-border/50 overflow-hidden",
|
|
7129
|
+
"bg-gradient-to-br from-background to-muted/30",
|
|
7130
|
+
"hover:border-primary/40 hover:shadow-md transition-all duration-300",
|
|
7131
|
+
animate && "hover:scale-[1.02] active:scale-[0.98]"
|
|
7132
|
+
),
|
|
7133
|
+
onClick: () => setPreset(preset),
|
|
7134
|
+
"aria-label": `Set time to ${label2}`,
|
|
7135
|
+
children: [
|
|
7136
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
7137
|
+
"div",
|
|
7138
|
+
{
|
|
7139
|
+
className: cn("absolute inset-0 opacity-0 group-hover:opacity-100 transition-opacity duration-300", "bg-gradient-to-r", color),
|
|
7140
|
+
style: { opacity: 0.08 }
|
|
7141
|
+
}
|
|
7142
|
+
),
|
|
7143
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "relative flex items-center gap-2", children: [
|
|
7144
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Icon, { className: "w-3.5 h-3.5 text-muted-foreground group-hover:text-primary transition-colors" }),
|
|
7145
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "text-foreground/80 group-hover:text-foreground transition-colors", children: label2 })
|
|
7146
|
+
] })
|
|
7147
|
+
]
|
|
7148
|
+
},
|
|
7149
|
+
preset
|
|
7150
|
+
);
|
|
7151
|
+
}) }),
|
|
6810
7152
|
customPresets && customPresets.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "grid grid-cols-2 gap-2", children: customPresets.map((preset, idx) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
6811
7153
|
"button",
|
|
6812
7154
|
{
|
|
6813
7155
|
type: "button",
|
|
6814
7156
|
className: cn(
|
|
6815
|
-
"px-
|
|
6816
|
-
|
|
7157
|
+
"px-3 py-2.5 text-xs font-medium rounded-xl border border-border/50",
|
|
7158
|
+
"bg-gradient-to-br from-background to-muted/30",
|
|
7159
|
+
"hover:border-primary/40 hover:bg-primary/5 hover:shadow-md transition-all duration-300",
|
|
7160
|
+
animate && "hover:scale-[1.02] active:scale-[0.98]"
|
|
6817
7161
|
),
|
|
6818
7162
|
onClick: () => handleCustomPreset(preset.time),
|
|
6819
7163
|
"aria-label": `Set time to ${preset.label}`,
|
|
@@ -6821,145 +7165,89 @@ function TimePicker({
|
|
|
6821
7165
|
},
|
|
6822
7166
|
idx
|
|
6823
7167
|
)) }),
|
|
6824
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex gap-
|
|
6825
|
-
|
|
6826
|
-
|
|
6827
|
-
|
|
6828
|
-
|
|
7168
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex gap-2 justify-center items-stretch", children: [
|
|
7169
|
+
(() => {
|
|
7170
|
+
const hourDisplay = format === "24" ? parts.h : parts.h % 12 || 12;
|
|
7171
|
+
const hourIndex = Math.max(0, hours.indexOf(hourDisplay));
|
|
7172
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
7173
|
+
WheelColumn,
|
|
6829
7174
|
{
|
|
6830
|
-
|
|
6831
|
-
|
|
6832
|
-
|
|
6833
|
-
|
|
6834
|
-
|
|
6835
|
-
|
|
6836
|
-
|
|
6837
|
-
|
|
6838
|
-
|
|
6839
|
-
|
|
6840
|
-
|
|
6841
|
-
{
|
|
6842
|
-
type: "button",
|
|
6843
|
-
role: "option",
|
|
6844
|
-
"aria-selected": isSelected,
|
|
6845
|
-
className: cn(
|
|
6846
|
-
"w-full text-center rounded-md transition-all font-medium",
|
|
6847
|
-
itemSz.padding,
|
|
6848
|
-
itemSz.text,
|
|
6849
|
-
"hover:bg-accent hover:scale-105 active:scale-95 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1",
|
|
6850
|
-
isSelected && "bg-primary text-primary-foreground shadow-md",
|
|
6851
|
-
!isSelected && "text-foreground/80",
|
|
6852
|
-
animate && "transition-transform duration-150"
|
|
6853
|
-
),
|
|
6854
|
-
onClick: () => {
|
|
6855
|
-
const nextH = format === "24" ? h : (parts.p === "PM" ? h % 12 + 12 : h % 12) % 24;
|
|
6856
|
-
const next = { ...parts, h: format === "24" ? h : nextH === 0 && parts.p === "AM" ? 0 : nextH || (parts.p === "PM" ? 12 : 0) };
|
|
6857
|
-
setParts(next);
|
|
6858
|
-
emit(next);
|
|
6859
|
-
},
|
|
6860
|
-
children: pad(h)
|
|
6861
|
-
},
|
|
6862
|
-
h
|
|
6863
|
-
);
|
|
6864
|
-
})
|
|
7175
|
+
labelText: "Hour",
|
|
7176
|
+
column: "hour",
|
|
7177
|
+
items: hours,
|
|
7178
|
+
valueIndex: hourIndex,
|
|
7179
|
+
onSelect: setHourFromDisplay,
|
|
7180
|
+
scrollRef: hourScrollRef,
|
|
7181
|
+
itemHeight,
|
|
7182
|
+
animate,
|
|
7183
|
+
focused: focusedColumn === "hour",
|
|
7184
|
+
setFocusedColumn: (col) => setFocusedColumn(col),
|
|
7185
|
+
onKeyDown: (e, col) => handleKeyDown(e, col)
|
|
6865
7186
|
}
|
|
6866
|
-
)
|
|
6867
|
-
|
|
6868
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "
|
|
6869
|
-
|
|
6870
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "
|
|
6871
|
-
|
|
6872
|
-
|
|
7187
|
+
);
|
|
7188
|
+
})(),
|
|
7189
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "flex flex-col items-center justify-center pt-8", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
7190
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "w-1.5 h-1.5 rounded-full bg-primary/60" }),
|
|
7191
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "w-1.5 h-1.5 rounded-full bg-primary/60" })
|
|
7192
|
+
] }) }),
|
|
7193
|
+
(() => {
|
|
7194
|
+
const minuteIndex = Math.max(0, Math.min(minutes.length - 1, Math.round(parts.m / minuteStep)));
|
|
7195
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
7196
|
+
WheelColumn,
|
|
6873
7197
|
{
|
|
6874
|
-
|
|
6875
|
-
|
|
6876
|
-
|
|
6877
|
-
|
|
6878
|
-
|
|
6879
|
-
|
|
6880
|
-
|
|
6881
|
-
|
|
6882
|
-
|
|
6883
|
-
|
|
6884
|
-
|
|
6885
|
-
|
|
6886
|
-
|
|
6887
|
-
|
|
6888
|
-
|
|
6889
|
-
className: cn(
|
|
6890
|
-
"w-full text-center rounded-md transition-all font-medium",
|
|
6891
|
-
itemSz.padding,
|
|
6892
|
-
itemSz.text,
|
|
6893
|
-
"hover:bg-accent hover:scale-105 active:scale-95 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1",
|
|
6894
|
-
isSelected && "bg-primary text-primary-foreground shadow-md",
|
|
6895
|
-
!isSelected && "text-foreground/80",
|
|
6896
|
-
animate && "transition-transform duration-150"
|
|
6897
|
-
),
|
|
6898
|
-
onClick: () => {
|
|
6899
|
-
const next = { ...parts, m };
|
|
6900
|
-
setParts(next);
|
|
6901
|
-
emit(next);
|
|
6902
|
-
},
|
|
6903
|
-
children: pad(m)
|
|
6904
|
-
},
|
|
6905
|
-
m
|
|
6906
|
-
);
|
|
6907
|
-
})
|
|
7198
|
+
labelText: "Min",
|
|
7199
|
+
column: "minute",
|
|
7200
|
+
items: minutes,
|
|
7201
|
+
valueIndex: minuteIndex,
|
|
7202
|
+
onSelect: (m) => {
|
|
7203
|
+
const next = { ...parts, m };
|
|
7204
|
+
setParts(next);
|
|
7205
|
+
emit(next);
|
|
7206
|
+
},
|
|
7207
|
+
scrollRef: minuteScrollRef,
|
|
7208
|
+
itemHeight,
|
|
7209
|
+
animate,
|
|
7210
|
+
focused: focusedColumn === "minute",
|
|
7211
|
+
setFocusedColumn: (col) => setFocusedColumn(col),
|
|
7212
|
+
onKeyDown: (e, col) => handleKeyDown(e, col)
|
|
6908
7213
|
}
|
|
6909
|
-
)
|
|
6910
|
-
|
|
6911
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "w-px bg-border/50 self-stretch my-8" }),
|
|
7214
|
+
);
|
|
7215
|
+
})(),
|
|
6912
7216
|
includeSeconds && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_jsx_runtime31.Fragment, { children: [
|
|
6913
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "
|
|
6914
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "
|
|
6915
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
6916
|
-
|
|
7217
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "flex flex-col items-center justify-center pt-8", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
7218
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "w-1.5 h-1.5 rounded-full bg-primary/60" }),
|
|
7219
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "w-1.5 h-1.5 rounded-full bg-primary/60" })
|
|
7220
|
+
] }) }),
|
|
7221
|
+
(() => {
|
|
7222
|
+
const secondIndex = Math.max(0, Math.min(seconds.length - 1, Math.round(parts.s / secondStep)));
|
|
7223
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
7224
|
+
WheelColumn,
|
|
6917
7225
|
{
|
|
6918
|
-
|
|
6919
|
-
|
|
6920
|
-
|
|
6921
|
-
|
|
6922
|
-
|
|
6923
|
-
|
|
6924
|
-
|
|
6925
|
-
|
|
6926
|
-
|
|
6927
|
-
|
|
6928
|
-
|
|
6929
|
-
|
|
6930
|
-
|
|
6931
|
-
|
|
6932
|
-
|
|
6933
|
-
className: cn(
|
|
6934
|
-
"w-full text-center rounded-md transition-all font-medium",
|
|
6935
|
-
itemSz.padding,
|
|
6936
|
-
itemSz.text,
|
|
6937
|
-
"hover:bg-accent hover:scale-105 active:scale-95 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1",
|
|
6938
|
-
isSelected && "bg-primary text-primary-foreground shadow-md",
|
|
6939
|
-
!isSelected && "text-foreground/80",
|
|
6940
|
-
animate && "transition-transform duration-150"
|
|
6941
|
-
),
|
|
6942
|
-
onClick: () => {
|
|
6943
|
-
const next = { ...parts, s };
|
|
6944
|
-
setParts(next);
|
|
6945
|
-
emit(next);
|
|
6946
|
-
},
|
|
6947
|
-
children: pad(s)
|
|
6948
|
-
},
|
|
6949
|
-
s
|
|
6950
|
-
);
|
|
6951
|
-
})
|
|
7226
|
+
labelText: "Sec",
|
|
7227
|
+
column: "second",
|
|
7228
|
+
items: seconds,
|
|
7229
|
+
valueIndex: secondIndex,
|
|
7230
|
+
onSelect: (s) => {
|
|
7231
|
+
const next = { ...parts, s };
|
|
7232
|
+
setParts(next);
|
|
7233
|
+
emit(next);
|
|
7234
|
+
},
|
|
7235
|
+
scrollRef: secondScrollRef,
|
|
7236
|
+
itemHeight,
|
|
7237
|
+
animate,
|
|
7238
|
+
focused: focusedColumn === "second",
|
|
7239
|
+
setFocusedColumn: (col) => setFocusedColumn(col),
|
|
7240
|
+
onKeyDown: (e, col) => handleKeyDown(e, col)
|
|
6952
7241
|
}
|
|
6953
|
-
)
|
|
6954
|
-
|
|
6955
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "w-px bg-border/50 self-stretch my-8" })
|
|
7242
|
+
);
|
|
7243
|
+
})()
|
|
6956
7244
|
] }),
|
|
6957
|
-
format === "12" && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "w-
|
|
6958
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "text-
|
|
7245
|
+
format === "12" && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex-1 min-w-[70px] max-w-[90px]", children: [
|
|
7246
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "text-[10px] font-bold uppercase tracking-wider text-muted-foreground/70 mb-3 text-center", children: "Period" }),
|
|
6959
7247
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
6960
7248
|
"div",
|
|
6961
7249
|
{
|
|
6962
|
-
className: "flex flex-col gap-2",
|
|
7250
|
+
className: "flex flex-col gap-2 p-1 rounded-xl bg-muted/30",
|
|
6963
7251
|
role: "radiogroup",
|
|
6964
7252
|
"aria-label": "Select AM or PM",
|
|
6965
7253
|
tabIndex: focusedColumn === "period" ? 0 : -1,
|
|
@@ -6967,18 +7255,18 @@ function TimePicker({
|
|
|
6967
7255
|
onFocus: () => setFocusedColumn("period"),
|
|
6968
7256
|
children: ["AM", "PM"].map((p) => {
|
|
6969
7257
|
const isSelected = parts.p === p;
|
|
6970
|
-
return /* @__PURE__ */ (0, import_jsx_runtime31.
|
|
7258
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
6971
7259
|
"button",
|
|
6972
7260
|
{
|
|
6973
7261
|
type: "button",
|
|
6974
7262
|
role: "radio",
|
|
6975
7263
|
"aria-checked": isSelected,
|
|
6976
7264
|
className: cn(
|
|
6977
|
-
"px-4 py-3 rounded-
|
|
6978
|
-
"
|
|
6979
|
-
isSelected && "bg-primary text-primary-foreground shadow-
|
|
6980
|
-
!isSelected && "text-foreground
|
|
6981
|
-
animate && "
|
|
7265
|
+
"relative px-4 py-3 rounded-lg transition-all duration-300 text-sm font-bold overflow-hidden",
|
|
7266
|
+
"focus-visible:ring-2 focus-visible:ring-primary/50 focus-visible:ring-offset-1",
|
|
7267
|
+
isSelected && "bg-gradient-to-r from-primary to-primary/80 text-primary-foreground shadow-lg shadow-primary/25",
|
|
7268
|
+
!isSelected && "text-muted-foreground hover:text-foreground hover:bg-muted/50",
|
|
7269
|
+
animate && "hover:scale-[1.02] active:scale-[0.98]"
|
|
6982
7270
|
),
|
|
6983
7271
|
onClick: () => {
|
|
6984
7272
|
const pVal = p;
|
|
@@ -6989,7 +7277,10 @@ function TimePicker({
|
|
|
6989
7277
|
setParts(next);
|
|
6990
7278
|
emit(next);
|
|
6991
7279
|
},
|
|
6992
|
-
children:
|
|
7280
|
+
children: [
|
|
7281
|
+
isSelected && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "absolute inset-0 bg-gradient-to-tr from-white/20 to-transparent" }),
|
|
7282
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "relative", children: p })
|
|
7283
|
+
]
|
|
6993
7284
|
},
|
|
6994
7285
|
p
|
|
6995
7286
|
);
|
|
@@ -6998,14 +7289,17 @@ function TimePicker({
|
|
|
6998
7289
|
)
|
|
6999
7290
|
] })
|
|
7000
7291
|
] }),
|
|
7001
|
-
(showNow || clearable) && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex items-center
|
|
7292
|
+
(showNow || clearable) && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex items-center gap-2 pt-3 border-t border-border/50", children: [
|
|
7002
7293
|
showNow && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
7003
7294
|
"button",
|
|
7004
7295
|
{
|
|
7005
7296
|
type: "button",
|
|
7006
7297
|
className: cn(
|
|
7007
|
-
"px-
|
|
7008
|
-
|
|
7298
|
+
"flex-1 px-4 py-2.5 text-xs font-semibold rounded-xl",
|
|
7299
|
+
"bg-gradient-to-r from-primary/10 to-primary/5 border border-primary/30",
|
|
7300
|
+
"text-primary hover:from-primary/20 hover:to-primary/10 hover:border-primary/50",
|
|
7301
|
+
"transition-all duration-300 flex items-center justify-center gap-2",
|
|
7302
|
+
animate && "hover:scale-[1.02] active:scale-[0.98] hover:shadow-md hover:shadow-primary/10"
|
|
7009
7303
|
),
|
|
7010
7304
|
onClick: () => {
|
|
7011
7305
|
setNow();
|
|
@@ -7018,14 +7312,16 @@ function TimePicker({
|
|
|
7018
7312
|
]
|
|
7019
7313
|
}
|
|
7020
7314
|
),
|
|
7021
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "flex-1" }),
|
|
7022
7315
|
clearable && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
7023
7316
|
"button",
|
|
7024
7317
|
{
|
|
7025
7318
|
type: "button",
|
|
7026
7319
|
className: cn(
|
|
7027
|
-
"px-
|
|
7028
|
-
|
|
7320
|
+
"flex-1 px-4 py-2.5 text-xs font-semibold rounded-xl",
|
|
7321
|
+
"bg-gradient-to-r from-destructive/10 to-destructive/5 border border-destructive/30",
|
|
7322
|
+
"text-destructive hover:from-destructive/20 hover:to-destructive/10 hover:border-destructive/50",
|
|
7323
|
+
"transition-all duration-300 flex items-center justify-center gap-2",
|
|
7324
|
+
animate && "hover:scale-[1.02] active:scale-[0.98] hover:shadow-md hover:shadow-destructive/10"
|
|
7029
7325
|
),
|
|
7030
7326
|
onClick: () => {
|
|
7031
7327
|
setParts(initial);
|
|
@@ -7043,18 +7339,23 @@ function TimePicker({
|
|
|
7043
7339
|
] });
|
|
7044
7340
|
if (variant === "inline") {
|
|
7045
7341
|
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "w-fit max-w-full", ...rest, children: [
|
|
7046
|
-
label && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "flex items-center justify-between mb-
|
|
7342
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "flex items-center justify-between mb-3", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("label", { className: cn(sz.label, "font-semibold", disabled ? "text-muted-foreground" : "text-foreground"), children: [
|
|
7047
7343
|
label,
|
|
7048
7344
|
required && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "text-destructive ml-1", children: "*" })
|
|
7049
7345
|
] }) }),
|
|
7050
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: cn("p-
|
|
7346
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: cn("p-5 rounded-2xl border border-border/60 bg-card/95 backdrop-blur-sm shadow-xl", className), children: timePickerContent })
|
|
7051
7347
|
] });
|
|
7052
7348
|
}
|
|
7053
7349
|
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "w-full", ...rest, children: [
|
|
7054
|
-
label && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "flex items-center justify-between mb-
|
|
7350
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "flex items-center justify-between mb-2", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
7055
7351
|
"label",
|
|
7056
7352
|
{
|
|
7057
|
-
className: cn(
|
|
7353
|
+
className: cn(
|
|
7354
|
+
sz.label,
|
|
7355
|
+
"font-semibold",
|
|
7356
|
+
disabled ? "text-muted-foreground" : "text-foreground",
|
|
7357
|
+
"cursor-pointer transition-colors hover:text-primary"
|
|
7358
|
+
),
|
|
7058
7359
|
onClick: () => !disabled && handleOpenChange(true),
|
|
7059
7360
|
children: [
|
|
7060
7361
|
label,
|
|
@@ -7069,28 +7370,27 @@ function TimePicker({
|
|
|
7069
7370
|
open,
|
|
7070
7371
|
onOpenChange: handleOpenChange,
|
|
7071
7372
|
placement: "bottom-start",
|
|
7072
|
-
matchTriggerWidth: variant === "compact",
|
|
7073
7373
|
contentWidth,
|
|
7074
7374
|
contentClassName: cn(
|
|
7075
|
-
"p-
|
|
7076
|
-
error && "border-destructive",
|
|
7077
|
-
success && "border-green-500",
|
|
7078
|
-
!error && !success && "border-border",
|
|
7079
|
-
animate && "animate-in fade-in-0 zoom-in-95 duration-
|
|
7375
|
+
"p-5 rounded-2xl border bg-popover/95 backdrop-blur-xl shadow-2xl",
|
|
7376
|
+
error && "border-destructive/40",
|
|
7377
|
+
success && "border-green-500/40",
|
|
7378
|
+
!error && !success && "border-border/60",
|
|
7379
|
+
animate && "animate-in fade-in-0 zoom-in-95 slide-in-from-top-2 duration-300"
|
|
7080
7380
|
),
|
|
7081
7381
|
children: timePickerContent
|
|
7082
7382
|
}
|
|
7083
7383
|
),
|
|
7084
|
-
(error || success || helperText) && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: cn("mt-
|
|
7085
|
-
error && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex items-center gap-1.5
|
|
7384
|
+
(error || success || helperText) && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: cn("mt-2 flex items-start gap-2", sz.label), children: [
|
|
7385
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex items-center gap-2 text-destructive bg-destructive/10 px-3 py-1.5 rounded-lg", children: [
|
|
7086
7386
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react16.X, { className: "w-3.5 h-3.5 shrink-0" }),
|
|
7087
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { children: error })
|
|
7387
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "font-medium", children: error })
|
|
7088
7388
|
] }),
|
|
7089
|
-
success && !error && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex items-center gap-
|
|
7389
|
+
success && !error && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex items-center gap-2 text-green-600 bg-green-500/10 px-3 py-1.5 rounded-lg", children: [
|
|
7090
7390
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react16.Check, { className: "w-3.5 h-3.5 shrink-0" }),
|
|
7091
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { children: "Valid time selected" })
|
|
7391
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "font-medium", children: "Valid time selected" })
|
|
7092
7392
|
] }),
|
|
7093
|
-
helperText && !error && !success && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "text-muted-foreground", children: helperText })
|
|
7393
|
+
helperText && !error && !success && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "text-muted-foreground/80 italic", children: helperText })
|
|
7094
7394
|
] })
|
|
7095
7395
|
] });
|
|
7096
7396
|
}
|
|
@@ -7309,7 +7609,7 @@ var DateTimePicker = ({
|
|
|
7309
7609
|
// ../../components/ui/MultiCombobox.tsx
|
|
7310
7610
|
var React27 = __toESM(require("react"), 1);
|
|
7311
7611
|
var import_react16 = require("react");
|
|
7312
|
-
var
|
|
7612
|
+
var import_react_dom7 = require("react-dom");
|
|
7313
7613
|
var import_lucide_react18 = require("lucide-react");
|
|
7314
7614
|
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
7315
7615
|
var MultiCombobox = ({
|
|
@@ -7551,7 +7851,7 @@ var MultiCombobox = ({
|
|
|
7551
7851
|
]
|
|
7552
7852
|
}
|
|
7553
7853
|
),
|
|
7554
|
-
open && dropdownPosition && typeof window !== "undefined" ? (0,
|
|
7854
|
+
open && dropdownPosition && typeof window !== "undefined" ? (0, import_react_dom7.createPortal)(
|
|
7555
7855
|
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
7556
7856
|
"div",
|
|
7557
7857
|
{
|
|
@@ -8613,19 +8913,26 @@ function CategoryTreeSelect(props) {
|
|
|
8613
8913
|
const hasChildren = children.length > 0;
|
|
8614
8914
|
const isExpanded = expandedNodes.has(category.id);
|
|
8615
8915
|
const isSelected = valueArray.includes(category.id);
|
|
8616
|
-
return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { children: [
|
|
8916
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "animate-in fade-in-50 duration-200", style: { animationDelay: `${level * 30}ms` }, children: [
|
|
8617
8917
|
/* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
|
|
8618
8918
|
"div",
|
|
8619
8919
|
{
|
|
8620
8920
|
className: cn(
|
|
8621
|
-
"relative flex items-center gap-2 px-3 py-2 rounded-
|
|
8622
|
-
!viewOnly && "cursor-pointer
|
|
8623
|
-
|
|
8624
|
-
|
|
8921
|
+
"relative flex items-center gap-2.5 px-3 py-2.5 rounded-xl transition-all duration-200",
|
|
8922
|
+
!viewOnly && "cursor-pointer",
|
|
8923
|
+
!viewOnly && !isSelected && "hover:bg-accent/60 hover:shadow-sm",
|
|
8924
|
+
// Selected state
|
|
8925
|
+
!viewOnly && isSelected && "bg-gradient-to-r from-primary/15 via-primary/10 to-primary/5 shadow-sm"
|
|
8625
8926
|
),
|
|
8626
|
-
style: { paddingLeft: `${level * 1.
|
|
8927
|
+
style: { paddingLeft: `${level * 1.25 + 0.75}rem` },
|
|
8627
8928
|
children: [
|
|
8628
|
-
!viewOnly && isSelected && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
8929
|
+
!viewOnly && isSelected && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
8930
|
+
"span",
|
|
8931
|
+
{
|
|
8932
|
+
"aria-hidden": true,
|
|
8933
|
+
className: "absolute left-0 top-2 bottom-2 w-1 rounded-full bg-gradient-to-b from-primary to-primary/70 shadow-sm shadow-primary/30"
|
|
8934
|
+
}
|
|
8935
|
+
),
|
|
8629
8936
|
hasChildren ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
8630
8937
|
"button",
|
|
8631
8938
|
{
|
|
@@ -8634,56 +8941,97 @@ function CategoryTreeSelect(props) {
|
|
|
8634
8941
|
e.stopPropagation();
|
|
8635
8942
|
toggleExpand(category.id);
|
|
8636
8943
|
},
|
|
8637
|
-
className:
|
|
8638
|
-
|
|
8944
|
+
className: cn(
|
|
8945
|
+
"p-1.5 rounded-lg transition-all duration-200",
|
|
8946
|
+
"hover:bg-accent hover:scale-110 active:scale-95",
|
|
8947
|
+
"focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/50",
|
|
8948
|
+
isExpanded && "bg-accent/50 text-primary"
|
|
8949
|
+
),
|
|
8950
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: cn("transition-transform duration-200", isExpanded && "rotate-90"), children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_lucide_react20.ChevronRight, { className: "w-4 h-4" }) })
|
|
8639
8951
|
}
|
|
8640
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "w-
|
|
8952
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "w-7" }),
|
|
8641
8953
|
viewOnly ? (
|
|
8642
|
-
// View-only mode: just display the name
|
|
8643
|
-
/* @__PURE__ */ (0, import_jsx_runtime37.
|
|
8954
|
+
// View-only mode: just display the name with folder icon
|
|
8955
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "flex items-center gap-2.5", children: [
|
|
8956
|
+
hasChildren ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_lucide_react20.FolderTree, { className: "w-4 h-4 text-muted-foreground/60" }) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "w-1.5 h-1.5 rounded-full bg-muted-foreground/40" }),
|
|
8957
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "text-sm font-medium", children: category.name })
|
|
8958
|
+
] })
|
|
8644
8959
|
) : singleSelect ? (
|
|
8645
8960
|
// Single select mode: radio-style indicator
|
|
8646
|
-
/* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { onClick: () => handleSelect(category.id, category), className: "flex items-center gap-2 flex-1", children: [
|
|
8961
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { onClick: () => handleSelect(category.id, category), className: "flex items-center gap-2.5 flex-1", children: [
|
|
8647
8962
|
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
8648
8963
|
"div",
|
|
8649
8964
|
{
|
|
8650
8965
|
className: cn(
|
|
8651
|
-
"w-
|
|
8652
|
-
isSelected ? "border-primary" : "border-muted-foreground/30"
|
|
8966
|
+
"w-5 h-5 border-2 rounded-full flex items-center justify-center transition-all duration-200",
|
|
8967
|
+
isSelected ? "border-primary bg-primary/10 shadow-sm shadow-primary/20" : "border-muted-foreground/30 hover:border-primary/50"
|
|
8968
|
+
),
|
|
8969
|
+
children: isSelected && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "w-2.5 h-2.5 rounded-full bg-gradient-to-br from-primary to-primary/80 shadow-sm" })
|
|
8970
|
+
}
|
|
8971
|
+
),
|
|
8972
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
8973
|
+
"span",
|
|
8974
|
+
{
|
|
8975
|
+
className: cn(
|
|
8976
|
+
"text-sm transition-all duration-200",
|
|
8977
|
+
isSelected ? "font-semibold text-primary" : "text-foreground/80 hover:text-foreground"
|
|
8653
8978
|
),
|
|
8654
|
-
children:
|
|
8979
|
+
children: category.name
|
|
8655
8980
|
}
|
|
8656
8981
|
),
|
|
8657
|
-
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className:
|
|
8982
|
+
hasChildren && !isSelected && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "ml-auto text-[10px] font-medium text-muted-foreground/50 bg-muted/50 px-1.5 py-0.5 rounded-md", children: children.length })
|
|
8658
8983
|
] })
|
|
8659
8984
|
) : (
|
|
8660
8985
|
// Multi select mode: checkbox-style indicator
|
|
8661
|
-
/* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { onClick: () => handleSelect(category.id, category), className: "flex items-center gap-2 flex-1", children: [
|
|
8986
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { onClick: () => handleSelect(category.id, category), className: "flex items-center gap-2.5 flex-1", children: [
|
|
8662
8987
|
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
8663
8988
|
"div",
|
|
8664
8989
|
{
|
|
8665
8990
|
className: cn(
|
|
8666
|
-
"w-
|
|
8667
|
-
isSelected ? "bg-primary border-primary" : "border-muted-foreground/30"
|
|
8991
|
+
"w-5 h-5 border-2 rounded-lg flex items-center justify-center transition-all duration-200",
|
|
8992
|
+
isSelected ? "bg-gradient-to-br from-primary to-primary/80 border-primary shadow-sm shadow-primary/25" : "border-muted-foreground/30 hover:border-primary/50 hover:bg-primary/5"
|
|
8993
|
+
),
|
|
8994
|
+
children: isSelected && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_lucide_react20.Check, { className: "w-3 h-3 text-primary-foreground", strokeWidth: 3 })
|
|
8995
|
+
}
|
|
8996
|
+
),
|
|
8997
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
8998
|
+
"span",
|
|
8999
|
+
{
|
|
9000
|
+
className: cn(
|
|
9001
|
+
"text-sm transition-all duration-200",
|
|
9002
|
+
isSelected ? "font-semibold text-primary" : "text-foreground/80 hover:text-foreground"
|
|
8668
9003
|
),
|
|
8669
|
-
children:
|
|
9004
|
+
children: category.name
|
|
8670
9005
|
}
|
|
8671
9006
|
),
|
|
8672
|
-
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className:
|
|
9007
|
+
hasChildren && !isSelected && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "ml-auto text-[10px] font-medium text-muted-foreground/50 bg-muted/50 px-1.5 py-0.5 rounded-md", children: children.length })
|
|
8673
9008
|
] })
|
|
8674
9009
|
)
|
|
8675
9010
|
]
|
|
8676
9011
|
}
|
|
8677
9012
|
),
|
|
8678
|
-
hasChildren && isExpanded && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { children: children.map((child) => renderCategory(child, level + 1)) })
|
|
9013
|
+
hasChildren && isExpanded && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: cn("ml-2 pl-2 border-l-2 border-dashed border-border/50", "animate-in slide-in-from-top-2 fade-in-50 duration-200"), children: children.map((child) => renderCategory(child, level + 1)) })
|
|
8679
9014
|
] }, category.id);
|
|
8680
9015
|
};
|
|
8681
|
-
const renderTreeContent = () => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
9016
|
+
const renderTreeContent = () => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "space-y-0.5", children: parentCategories.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "flex flex-col items-center justify-center py-8 text-center", children: [
|
|
9017
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "w-12 h-12 rounded-2xl bg-muted/50 flex items-center justify-center mb-3", children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_lucide_react20.Layers, { className: "w-6 h-6 text-muted-foreground/50" }) }),
|
|
9018
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "text-sm text-muted-foreground", children: mergedLabels.emptyText })
|
|
9019
|
+
] }) : parentCategories.map((cat) => renderCategory(cat)) });
|
|
8682
9020
|
if (viewOnly) {
|
|
8683
|
-
return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: cn("rounded-
|
|
9021
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: cn("rounded-2xl border border-border/60 bg-card/50 backdrop-blur-sm p-3 shadow-sm", disabled && "opacity-50", className), children: renderTreeContent() });
|
|
8684
9022
|
}
|
|
8685
9023
|
if (inline) {
|
|
8686
|
-
return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
9024
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
9025
|
+
"div",
|
|
9026
|
+
{
|
|
9027
|
+
className: cn(
|
|
9028
|
+
"rounded-2xl border border-border/60 bg-card/50 backdrop-blur-sm p-3 shadow-sm",
|
|
9029
|
+
disabled && "opacity-50 pointer-events-none",
|
|
9030
|
+
className
|
|
9031
|
+
),
|
|
9032
|
+
children: renderTreeContent()
|
|
9033
|
+
}
|
|
9034
|
+
);
|
|
8687
9035
|
}
|
|
8688
9036
|
const selectedCount = valueArray.length;
|
|
8689
9037
|
const displayText = singleSelect ? selectedCount > 0 ? categories.find((c) => c.id === valueArray[0])?.name || placeholder : placeholder : selectedCount > 0 ? mergedLabels.selectedText(selectedCount) : placeholder;
|
|
@@ -8695,17 +9043,32 @@ function CategoryTreeSelect(props) {
|
|
|
8695
9043
|
onClick: () => !disabled && setIsOpen(!isOpen),
|
|
8696
9044
|
disabled,
|
|
8697
9045
|
className: cn(
|
|
8698
|
-
//
|
|
8699
|
-
"flex w-full items-center justify-between px-3
|
|
8700
|
-
"
|
|
8701
|
-
"
|
|
8702
|
-
"
|
|
8703
|
-
|
|
8704
|
-
|
|
9046
|
+
// Modern trigger button styling
|
|
9047
|
+
"group flex w-full items-center justify-between px-3 py-2.5",
|
|
9048
|
+
"bg-background/80 backdrop-blur-sm border border-border/60",
|
|
9049
|
+
"rounded-xl h-11 text-sm",
|
|
9050
|
+
"hover:bg-accent/10 hover:border-primary/40 hover:shadow-lg hover:shadow-primary/5 hover:-translate-y-0.5",
|
|
9051
|
+
"transition-all duration-300 ease-out",
|
|
9052
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background",
|
|
9053
|
+
disabled && "opacity-50 cursor-not-allowed hover:transform-none hover:shadow-none",
|
|
9054
|
+
isOpen && "ring-2 ring-primary/30 border-primary/50 shadow-lg shadow-primary/10"
|
|
8705
9055
|
),
|
|
8706
9056
|
children: [
|
|
8707
|
-
/* @__PURE__ */ (0, import_jsx_runtime37.
|
|
8708
|
-
|
|
9057
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "flex items-center gap-2.5", children: [
|
|
9058
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
9059
|
+
"div",
|
|
9060
|
+
{
|
|
9061
|
+
className: cn(
|
|
9062
|
+
"flex items-center justify-center rounded-lg p-1.5 transition-all duration-300",
|
|
9063
|
+
isOpen ? "bg-primary/15 text-primary" : "bg-muted/50 text-muted-foreground group-hover:bg-primary/10 group-hover:text-primary"
|
|
9064
|
+
),
|
|
9065
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_lucide_react20.FolderTree, { className: cn("w-4 h-4 transition-transform duration-300", isOpen && "scale-110") })
|
|
9066
|
+
}
|
|
9067
|
+
),
|
|
9068
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: cn("font-medium transition-colors duration-200", selectedCount === 0 ? "text-muted-foreground" : "text-foreground"), children: displayText }),
|
|
9069
|
+
selectedCount > 0 && !singleSelect && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "ml-1 px-2 py-0.5 text-xs font-bold rounded-full bg-primary/15 text-primary", children: selectedCount })
|
|
9070
|
+
] }),
|
|
9071
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: cn("transition-all duration-300 text-muted-foreground group-hover:text-foreground", isOpen && "rotate-180 text-primary"), children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_lucide_react20.ChevronDown, { className: "w-4 h-4" }) })
|
|
8709
9072
|
]
|
|
8710
9073
|
}
|
|
8711
9074
|
),
|
|
@@ -8715,11 +9078,13 @@ function CategoryTreeSelect(props) {
|
|
|
8715
9078
|
"div",
|
|
8716
9079
|
{
|
|
8717
9080
|
className: cn(
|
|
8718
|
-
"absolute z-20 mt-
|
|
8719
|
-
"rounded-
|
|
8720
|
-
"backdrop-blur-
|
|
9081
|
+
"absolute z-20 mt-2 w-full max-h-80 overflow-auto",
|
|
9082
|
+
"rounded-2xl border border-border/40 bg-popover/95 text-popover-foreground",
|
|
9083
|
+
"shadow-2xl backdrop-blur-xl",
|
|
9084
|
+
"p-2",
|
|
9085
|
+
"animate-in fade-in-0 zoom-in-95 slide-in-from-top-2 duration-300"
|
|
8721
9086
|
),
|
|
8722
|
-
children:
|
|
9087
|
+
children: renderTreeContent()
|
|
8723
9088
|
}
|
|
8724
9089
|
)
|
|
8725
9090
|
] })
|
|
@@ -9736,7 +10101,7 @@ var List_default = List;
|
|
|
9736
10101
|
|
|
9737
10102
|
// ../../components/ui/Watermark.tsx
|
|
9738
10103
|
var React35 = __toESM(require("react"), 1);
|
|
9739
|
-
var
|
|
10104
|
+
var import_react_dom8 = require("react-dom");
|
|
9740
10105
|
var import_jsx_runtime42 = require("react/jsx-runtime");
|
|
9741
10106
|
var PRESETS2 = {
|
|
9742
10107
|
confidential: { text: "CONFIDENTIAL", color: "rgba(220, 38, 38, 0.15)", rotate: -22, fontSize: 16, fontWeight: "bold" },
|
|
@@ -10018,7 +10383,7 @@ var Watermark = ({
|
|
|
10018
10383
|
if (fullPage) {
|
|
10019
10384
|
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_jsx_runtime42.Fragment, { children: [
|
|
10020
10385
|
children,
|
|
10021
|
-
typeof window !== "undefined" ? (0,
|
|
10386
|
+
typeof window !== "undefined" ? (0, import_react_dom8.createPortal)(overlay, document.body) : null
|
|
10022
10387
|
] });
|
|
10023
10388
|
}
|
|
10024
10389
|
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: cn("relative", className), style, ...rest, children: [
|
|
@@ -10922,7 +11287,7 @@ var import_react23 = require("react");
|
|
|
10922
11287
|
|
|
10923
11288
|
// ../../components/ui/ChartTooltip.tsx
|
|
10924
11289
|
var import_react22 = require("react");
|
|
10925
|
-
var
|
|
11290
|
+
var import_react_dom9 = require("react-dom");
|
|
10926
11291
|
var import_jsx_runtime46 = require("react/jsx-runtime");
|
|
10927
11292
|
function ChartTooltip({ x, y, visible, label, value, color, secondaryLabel, secondaryValue, items, containerRef }) {
|
|
10928
11293
|
const [isMounted, setIsMounted] = (0, import_react22.useState)(false);
|
|
@@ -10993,7 +11358,7 @@ function ChartTooltip({ x, y, visible, label, value, color, secondaryLabel, seco
|
|
|
10993
11358
|
]
|
|
10994
11359
|
}
|
|
10995
11360
|
);
|
|
10996
|
-
return (0,
|
|
11361
|
+
return (0, import_react_dom9.createPortal)(tooltipContent, document.body);
|
|
10997
11362
|
}
|
|
10998
11363
|
|
|
10999
11364
|
// ../../components/ui/LineChart.tsx
|
|
@@ -13255,7 +13620,7 @@ function AccessDenied({
|
|
|
13255
13620
|
// ../../components/ui/ThemeToggleHeadless.tsx
|
|
13256
13621
|
var import_lucide_react31 = require("lucide-react");
|
|
13257
13622
|
var import_react33 = require("react");
|
|
13258
|
-
var
|
|
13623
|
+
var import_react_dom10 = require("react-dom");
|
|
13259
13624
|
var import_jsx_runtime62 = require("react/jsx-runtime");
|
|
13260
13625
|
function ThemeToggleHeadless({
|
|
13261
13626
|
theme,
|
|
@@ -13308,8 +13673,8 @@ function ThemeToggleHeadless({
|
|
|
13308
13673
|
}
|
|
13309
13674
|
),
|
|
13310
13675
|
isOpen && /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(import_jsx_runtime62.Fragment, { children: [
|
|
13311
|
-
typeof window !== "undefined" && (0,
|
|
13312
|
-
typeof window !== "undefined" && dropdownPosition && (0,
|
|
13676
|
+
typeof window !== "undefined" && (0, import_react_dom10.createPortal)(/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "fixed inset-0 z-9998", onClick: () => setIsOpen(false) }), document.body),
|
|
13677
|
+
typeof window !== "undefined" && dropdownPosition && (0, import_react_dom10.createPortal)(
|
|
13313
13678
|
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
13314
13679
|
"div",
|
|
13315
13680
|
{
|
|
@@ -13357,7 +13722,7 @@ function ThemeToggleHeadless({
|
|
|
13357
13722
|
|
|
13358
13723
|
// ../../components/ui/LanguageSwitcherHeadless.tsx
|
|
13359
13724
|
var import_react34 = require("react");
|
|
13360
|
-
var
|
|
13725
|
+
var import_react_dom11 = require("react-dom");
|
|
13361
13726
|
var import_lucide_react32 = require("lucide-react");
|
|
13362
13727
|
var import_jsx_runtime63 = require("react/jsx-runtime");
|
|
13363
13728
|
function LanguageSwitcherHeadless({
|
|
@@ -13405,8 +13770,8 @@ function LanguageSwitcherHeadless({
|
|
|
13405
13770
|
}
|
|
13406
13771
|
),
|
|
13407
13772
|
isOpen && /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(import_jsx_runtime63.Fragment, { children: [
|
|
13408
|
-
typeof window !== "undefined" && (0,
|
|
13409
|
-
typeof window !== "undefined" && dropdownPosition && (0,
|
|
13773
|
+
typeof window !== "undefined" && (0, import_react_dom11.createPortal)(/* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: "fixed inset-0 z-9998", onClick: () => setIsOpen(false) }), document.body),
|
|
13774
|
+
typeof window !== "undefined" && dropdownPosition && (0, import_react_dom11.createPortal)(
|
|
13410
13775
|
/* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
|
|
13411
13776
|
"div",
|
|
13412
13777
|
{
|