@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 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 popoverRef = React14.useRef(null);
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 renderedWidth = matchTriggerWidth ? lastTriggerRect?.width : contentWidth;
3773
+ const initialPlacement = React14.useMemo(() => normalizePlacement(placement), [placement]);
3757
3774
  const updatePosition = React14.useCallback(() => {
3758
3775
  const triggerEl = triggerRef.current;
3759
- const popoverEl = popoverRef.current;
3760
- if (!triggerEl || !popoverEl) return;
3776
+ const positionerEl = positionerRef.current;
3777
+ const panelEl = panelRef.current;
3778
+ if (!triggerEl || !positionerEl || !panelEl) return;
3761
3779
  const triggerRect = triggerEl.getBoundingClientRect();
3762
- const measuredWidth = popoverEl.offsetWidth;
3763
- const measuredHeight = popoverEl.offsetHeight;
3764
- const contentRect = popoverEl.getBoundingClientRect();
3765
- const contentWidth2 = measuredWidth || contentRect.width;
3766
- const contentHeight = measuredHeight || contentRect.height;
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: contentWidth2, height: contentHeight },
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
- setDropdownPosition(next);
3776
- }, [placement]);
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, renderedWidth]);
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(popoverRef.current);
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
- setDropdownPosition(null);
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 = popoverRef.current;
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
- const next = !isOpen;
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: popoverRef,
3901
+ ref: positionerRef,
3864
3902
  "data-popover": true,
3865
3903
  style: {
3866
3904
  position: "fixed",
3867
- top: dropdownPosition?.top ?? 0,
3868
- left: dropdownPosition?.left ?? 0,
3869
- width: renderedWidth ?? void 0,
3905
+ top: 0,
3906
+ left: 0,
3907
+ transform: "translate3d(0, 0, 0)",
3870
3908
  zIndex: 9999,
3871
- visibility: dropdownPosition ? "visible" : "hidden",
3872
- pointerEvents: dropdownPosition ? "auto" : "none",
3873
- transformOrigin: (() => {
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
- "data-state": "open",
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
- "rounded-md border bg-popover text-popover-foreground shadow-md",
3895
- "backdrop-blur-sm bg-popover/95 border-border/60 p-4",
3896
- contentClassName
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
- tabIndex: -1,
3899
- children
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: triggerRef,
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 dropdownRef = React23.useRef(null);
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.jsx)(
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 * 50}ms` : "0ms"
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-md focus:outline-none",
5836
- "transition-colors",
5837
- isPastDate && "opacity-40 cursor-not-allowed text-muted-foreground",
5838
- isSelected ? "bg-primary! text-primary-foreground font-bold ring-2 ring-primary-foreground/60 shadow-lg scale-105 z-10 hover:bg-primary! focus:bg-primary! focus:text-primary-foreground" : !isPastDate && "hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",
5839
- isToday2 && !isSelected && "bg-accent text-accent-foreground font-semibold"
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: day
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 = isOpen && dropdownPosition ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
5850
- "div",
5851
- {
5852
- "data-datepicker": true,
5853
- style: {
5854
- position: "absolute",
5855
- top: dropdownPosition?.top || 0,
5856
- left: dropdownPosition?.left || 0,
5857
- width: size === "sm" ? dropdownPosition?.width || 224 : dropdownPosition?.width || 256,
5858
- zIndex: 9999,
5859
- pointerEvents: "none"
5860
- },
5861
- "data-state": isOpen ? "open" : "closed",
5862
- className: cn(
5863
- "z-9999",
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
- children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
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
- "rounded-md border bg-popover text-popover-foreground shadow-md",
5873
- "backdrop-blur-sm bg-popover/95 border-border/60",
5874
- size === "sm" ? "p-3 w-56" : "p-4 w-64"
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.jsxs)("div", { className: "flex items-center justify-between mb-4", children: [
5879
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(Button_default, { variant: "ghost", size: "sm", onClick: () => navigateMonth("prev"), className: "p-1 h-auto", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react14.ChevronLeft, { className: "h-4 w-4" }) }),
5880
- /* @__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" }) }),
5881
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(Button_default, { variant: "ghost", size: "sm", onClick: () => navigateMonth("next"), className: "p-1 h-auto", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react14.ChevronRight, { className: "h-4 w-4" }) })
5882
- ] }),
5883
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: cn("grid grid-cols-7 gap-1", size === "sm" ? "mb-1" : "mb-2"), children: (weekdayLabels || (locale === "vi" ? ["CN", "T2", "T3", "T4", "T5", "T6", "T7"] : ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"])).map(
5884
- (day) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: cn("text-muted-foreground text-center font-medium", size === "sm" ? "text-[10px] py-0.5" : "text-xs py-1"), children: day }, day)
5885
- ) }),
5886
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "grid grid-cols-7 gap-1", children: renderCalendar() }),
5887
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "flex items-center justify-end mt-2", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
5888
- Button_default,
5889
- {
5890
- variant: "outline",
5891
- size: "sm",
5892
- onClick: () => {
5893
- onChange(void 0);
5894
- setIsOpen(false);
5895
- setViewDate(/* @__PURE__ */ new Date());
5896
- },
5897
- children: clearLabel || t("clear")
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
- ) : null;
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-medium transition-colors duration-200",
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.jsxs)(
5930
- "button",
5999
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6000
+ Popover,
5931
6001
  {
5932
- ref: triggerRef,
5933
- type: "button",
6002
+ open: isOpen,
6003
+ onOpenChange: setIsOpen,
6004
+ placement: "bottom-start",
5934
6005
  disabled,
5935
- id: resolvedId,
5936
- "aria-labelledby": labelId,
5937
- onClick: () => {
5938
- const next = !isOpen;
5939
- if (next) {
5940
- const pos = calculatePosition();
5941
- if (pos) setDropdownPosition(pos);
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 [dropdownPosition, setDropdownPosition] = React23.useState(null);
5994
- const triggerRef = React23.useRef(null);
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-40 cursor-not-allowed text-muted-foreground",
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-md",
6111
- // Range selection styling - smooth continuous background
6112
- isInRange && "bg-primary/15 text-foreground shadow-sm",
6113
- (isRangeStart || isRangeEnd) && "bg-primary text-primary-foreground hover:bg-primary/90 shadow-sm",
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-md rounded-r-none",
6116
- isRangeEnd && !isRangeStart && "rounded-r-md rounded-l-none",
6117
- isRangeStart && isRangeEnd && "rounded-md",
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 = isOpen && dropdownPosition ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
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
- style: { position: "absolute", top: dropdownPosition.top, left: dropdownPosition.left, width: dropdownPosition.width || 256, zIndex: 9999 },
6135
- "data-state": isOpen ? "open" : "closed",
6136
- className: cn(
6137
- "z-9999",
6138
- "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
6139
- "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95"
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
- children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
6142
- "div",
6305
+ trigger: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
6306
+ "button",
6143
6307
  {
6144
- ref: panelRef,
6145
- className: cn("rounded-md border bg-popover text-popover-foreground shadow-md", "backdrop-blur-sm bg-popover/95 border-border/60 p-4 w-64"),
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 justify-between mb-3", children: [
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
- Button_default,
6321
+ "div",
6150
6322
  {
6151
- variant: "ghost",
6152
- size: "sm",
6153
- onClick: () => setViewDate(new Date(viewDate.getFullYear(), viewDate.getMonth() - 1, 1)),
6154
- className: "p-1 h-auto",
6155
- children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react14.ChevronLeft, { className: "h-4 w-4" })
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
- Button_default,
6331
+ "span",
6161
6332
  {
6162
- variant: "ghost",
6163
- size: "sm",
6164
- onClick: () => setViewDate(new Date(viewDate.getFullYear(), viewDate.getMonth() + 1, 1)),
6165
- className: "p-1 h-auto",
6166
- children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react14.ChevronRight, { className: "h-4 w-4" })
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)("div", { className: "grid grid-cols-7 gap-1 mb-2", children: (locale === "vi" ? ["CN", "T2", "T3", "T4", "T5", "T6", "T7"] : ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"]).map((d) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "text-xs text-muted-foreground text-center py-1 font-medium", children: d }, d)) }),
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
- ) : null;
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-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
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-200",
6763
- error && "border-destructive focus-visible:ring-destructive",
6764
- success && "border-green-500 focus-visible:ring-green-500",
6765
- !error && !success && "border-input hover:bg-accent/5",
6766
- animate && !disabled && "hover:shadow-md",
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)(import_lucide_react16.Clock, { className: cn(sz.icon, error ? "text-destructive" : success ? "text-green-500" : "text-muted-foreground") }),
6772
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: cn("truncate", !value && !defaultValue && "text-muted-foreground"), children: value || defaultValue ? display : placeholder })
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-transform duration-200", open && "rotate-180"), children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("svg", { className: sz.icon, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) }) })
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 itemSizeClasses = {
6780
- sm: { padding: "px-2 py-1", text: "text-xs" },
6781
- md: { padding: "px-3 py-2", text: "text-sm" },
6782
- lg: { padding: "px-4 py-3", text: "text-base" }
6783
- };
6784
- const itemSz = itemSizeClasses[size];
6785
- const timePickerContent = /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "space-y-3", children: [
6786
- allowManualInput && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
6787
- Input_default,
6788
- {
6789
- placeholder: format === "12" ? "02:30 PM" : "14:30",
6790
- value: manualInput || display,
6791
- onChange: (e) => handleManualInput(e.target.value),
6792
- size: "sm",
6793
- variant: "outlined"
6794
- }
6795
- ) }),
6796
- showPresets && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "grid grid-cols-2 gap-2", children: Object.keys(PRESETS).map((preset) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
6797
- "button",
6798
- {
6799
- type: "button",
6800
- className: cn(
6801
- "px-2 py-1.5 text-xs rounded-md border border-border hover:bg-accent/10 capitalize transition-all",
6802
- animate && "hover:scale-105 active:scale-95"
6803
- ),
6804
- onClick: () => setPreset(preset),
6805
- "aria-label": `Set time to ${preset}`,
6806
- children: preset
6807
- },
6808
- preset
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-2 py-1.5 text-xs rounded-md border border-border hover:bg-accent/10 transition-all",
6816
- animate && "hover:scale-105 active:scale-95"
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-3 w-fit max-w-full", children: [
6825
- /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "w-20", children: [
6826
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "text-xs font-semibold text-muted-foreground mb-2 text-center", children: "Hour" }),
6827
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
6828
- "div",
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
- ref: hourScrollRef,
6831
- className: "max-h-48 overflow-y-auto pr-1 space-y-1 scrollbar-thin scroll-smooth",
6832
- role: "listbox",
6833
- "aria-label": "Select hour",
6834
- tabIndex: focusedColumn === "hour" ? 0 : -1,
6835
- onKeyDown: (e) => handleKeyDown(e, "hour"),
6836
- onFocus: () => setFocusedColumn("hour"),
6837
- children: hours.map((h) => {
6838
- const isSelected = format === "24" && parts.h === h || format === "12" && (parts.h % 12 || 12) === (h % 12 || 12);
6839
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
6840
- "button",
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: "w-px bg-border/50 self-stretch my-8" }),
6869
- /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "w-20", children: [
6870
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "text-xs font-semibold text-muted-foreground mb-2 text-center", children: "Min" }),
6871
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
6872
- "div",
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
- ref: minuteScrollRef,
6875
- className: "max-h-48 overflow-y-auto pr-1 space-y-1 scrollbar-thin scroll-smooth",
6876
- role: "listbox",
6877
- "aria-label": "Select minute",
6878
- tabIndex: focusedColumn === "minute" ? 0 : -1,
6879
- onKeyDown: (e) => handleKeyDown(e, "minute"),
6880
- onFocus: () => setFocusedColumn("minute"),
6881
- children: minutes.map((m) => {
6882
- const isSelected = parts.m === m;
6883
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
6884
- "button",
6885
- {
6886
- type: "button",
6887
- role: "option",
6888
- "aria-selected": isSelected,
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: "w-20", children: [
6914
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "text-xs font-semibold text-muted-foreground mb-2 text-center", children: "Sec" }),
6915
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
6916
- "div",
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
- ref: secondScrollRef,
6919
- className: "max-h-48 overflow-y-auto pr-1 space-y-1 scrollbar-thin scroll-smooth",
6920
- role: "listbox",
6921
- "aria-label": "Select second",
6922
- tabIndex: focusedColumn === "second" ? 0 : -1,
6923
- onKeyDown: (e) => handleKeyDown(e, "second"),
6924
- onFocus: () => setFocusedColumn("second"),
6925
- children: seconds.map((s) => {
6926
- const isSelected = parts.s === s;
6927
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
6928
- "button",
6929
- {
6930
- type: "button",
6931
- role: "option",
6932
- "aria-selected": isSelected,
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-20", children: [
6958
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "text-xs font-semibold text-muted-foreground mb-2 text-center", children: "Period" }),
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.jsx)(
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-md transition-all text-sm font-semibold",
6978
- "hover:bg-accent hover:scale-105 active:scale-95 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1",
6979
- isSelected && "bg-primary text-primary-foreground shadow-md",
6980
- !isSelected && "text-foreground/80 border border-border",
6981
- animate && "transition-transform duration-150"
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: p
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 justify-between gap-2 pt-3 border-t border-border", children: [
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-3 py-2 text-xs rounded-md border border-border hover:bg-accent/10 transition-all flex items-center gap-2 font-medium",
7008
- animate && "hover:scale-105 active:scale-95"
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-3 py-2 text-xs rounded-md border border-border hover:bg-destructive/10 hover:text-destructive transition-all flex items-center gap-2 font-medium",
7028
- animate && "hover:scale-105 active:scale-95"
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-2", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("label", { className: cn(sz.label, "font-medium", disabled ? "text-muted-foreground" : "text-foreground"), children: [
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-3 rounded-lg border border-border bg-card shadow-sm", className), children: timePickerContent })
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-1.5", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
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(sz.label, "font-medium", disabled ? "text-muted-foreground" : "text-foreground", "cursor-pointer"),
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-4 rounded-lg border bg-popover shadow-xl backdrop-blur-md",
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-200"
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-1.5 flex items-start gap-1.5", sz.label), children: [
7085
- error && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex items-center gap-1.5 text-destructive", children: [
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-1.5 text-green-600", children: [
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 import_react_dom8 = require("react-dom");
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, import_react_dom8.createPortal)(
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-md transition-colors",
8622
- !viewOnly && "cursor-pointer hover:bg-accent",
8623
- // Selected state: subtle bg + square left indicator (only in select mode)
8624
- !viewOnly && isSelected && "bg-primary/10 rounded-r-md"
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.5 + 0.75}rem` },
8927
+ style: { paddingLeft: `${level * 1.25 + 0.75}rem` },
8627
8928
  children: [
8628
- !viewOnly && isSelected && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { "aria-hidden": true, className: "absolute left-0 top-0 bottom-0 w-1 bg-primary" }),
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: "p-0.5 hover:bg-accent rounded",
8638
- children: isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_lucide_react20.ChevronDown, { className: "w-4 h-4" }) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_lucide_react20.ChevronRight, { className: "w-4 h-4" })
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-5" }),
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.jsx)("span", { className: "text-sm", children: category.name })
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-4 h-4 border-2 rounded-full flex items-center justify-center transition-colors",
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: isSelected && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "w-2 h-2 rounded-full bg-primary" })
8979
+ children: category.name
8655
8980
  }
8656
8981
  ),
8657
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: cn("text-sm", isSelected && "font-medium text-primary"), children: category.name })
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-4 h-4 border-2 rounded flex items-center justify-center transition-colors",
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: isSelected && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_lucide_react20.Check, { className: "w-3 h-3 text-primary-foreground" })
9004
+ children: category.name
8670
9005
  }
8671
9006
  ),
8672
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: cn("text-sm", isSelected && "font-medium text-primary"), children: category.name })
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)(import_jsx_runtime37.Fragment, { children: parentCategories.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "px-3 py-2 text-sm text-muted-foreground", children: mergedLabels.emptyText }) : parentCategories.map((cat) => renderCategory(cat)) });
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-md border bg-background p-2", disabled && "opacity-50", className), children: renderTreeContent() });
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)("div", { className: cn("rounded-md border bg-background p-2", disabled && "opacity-50 pointer-events-none", className), children: renderTreeContent() });
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
- // Match Combobox trigger outline + focus styles
8699
- "flex w-full items-center justify-between px-3 bg-background border border-input",
8700
- "rounded-md h-10 py-2 text-sm",
8701
- "hover:bg-accent/5 transition-colors hover:border-primary/40 focus:border-primary",
8702
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
8703
- disabled && "opacity-50 cursor-not-allowed",
8704
- isOpen && "border-primary"
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.jsx)("span", { className: cn("text-sm", selectedCount === 0 && "text-muted-foreground"), children: displayText }),
8708
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_lucide_react20.ChevronDown, { className: cn("w-4 h-4 transition-transform", isOpen && "transform rotate-180") })
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-1 w-full max-h-80 overflow-auto",
8719
- "rounded-md border bg-popover text-popover-foreground shadow-md",
8720
- "backdrop-blur-sm bg-popover/95 border-border/60"
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: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "p-1", children: renderTreeContent() })
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 import_react_dom9 = require("react-dom");
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, import_react_dom9.createPortal)(overlay, document.body) : null
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 import_react_dom10 = require("react-dom");
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, import_react_dom10.createPortal)(tooltipContent, document.body);
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 import_react_dom11 = require("react-dom");
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, import_react_dom11.createPortal)(/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "fixed inset-0 z-9998", onClick: () => setIsOpen(false) }), document.body),
13312
- typeof window !== "undefined" && dropdownPosition && (0, import_react_dom11.createPortal)(
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 import_react_dom12 = require("react-dom");
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, import_react_dom12.createPortal)(/* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: "fixed inset-0 z-9998", onClick: () => setIsOpen(false) }), document.body),
13409
- typeof window !== "undefined" && dropdownPosition && (0, import_react_dom12.createPortal)(
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
  {