infinity-ui-elements 1.9.3 → 1.9.4

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.esm.js CHANGED
@@ -5,7 +5,7 @@ import { Slot } from '@radix-ui/react-slot';
5
5
  import { PulseLoader, ClipLoader } from 'react-spinners';
6
6
  import { clsx } from 'clsx';
7
7
  import { twMerge } from 'tailwind-merge';
8
- import { ExternalLink, Calendar, X, Loader2, Search, ChevronDown } from 'lucide-react';
8
+ import { ExternalLink, Calendar, X, ChevronLeft, ChevronRight, Loader2, Search, ChevronDown } from 'lucide-react';
9
9
  import { createPortal } from 'react-dom';
10
10
  import Calendar$1 from 'react-calendar';
11
11
  import 'react-calendar/dist/Calendar.css';
@@ -2070,7 +2070,7 @@ const datePickerVariants = cva("relative flex items-center gap-2 border rounded-
2070
2070
  },
2071
2071
  });
2072
2072
  // Helper functions
2073
- const parseDate = (date) => {
2073
+ const parseDate$1 = (date) => {
2074
2074
  if (!date)
2075
2075
  return null;
2076
2076
  if (date instanceof Date)
@@ -2081,7 +2081,7 @@ const parseDate = (date) => {
2081
2081
  }
2082
2082
  return null;
2083
2083
  };
2084
- const formatDateDefault = (date) => {
2084
+ const formatDateDefault$1 = (date) => {
2085
2085
  return date.toLocaleDateString("en-US", {
2086
2086
  year: "numeric",
2087
2087
  month: "short",
@@ -2152,8 +2152,8 @@ const formatDateByPattern = (date, format) => {
2152
2152
  formatted = formatted.replace(/D/g, day.toString());
2153
2153
  return formatted;
2154
2154
  };
2155
- const DatePicker = React.forwardRef(({ className, value: controlledValue, defaultValue, onChange, placeholder = "Select a date", label, helperText, errorText, successText, validationState = "none", isDisabled = false, isRequired = false, isOptional = false, size = "medium", showClearButton = true, onClear, containerClassName, labelClassName, triggerClassName, calendarClassName, minDate, maxDate, formatDate = formatDateDefault, format, infoHeading, infoDescription, LinkComponent, linkText, linkHref, onLinkClick, ...props }, ref) => {
2156
- const [uncontrolledValue, setUncontrolledValue] = React.useState(parseDate(defaultValue));
2155
+ const DatePicker = React.forwardRef(({ className, value: controlledValue, defaultValue, onChange, placeholder = "Select a date", label, helperText, errorText, successText, validationState = "none", isDisabled = false, isRequired = false, isOptional = false, size = "medium", showClearButton = true, onClear, containerClassName, labelClassName, triggerClassName, calendarClassName, minDate, maxDate, formatDate = formatDateDefault$1, format, infoHeading, infoDescription, LinkComponent, linkText, linkHref, onLinkClick, ...props }, ref) => {
2156
+ const [uncontrolledValue, setUncontrolledValue] = React.useState(parseDate$1(defaultValue));
2157
2157
  const [isOpen, setIsOpen] = React.useState(false);
2158
2158
  const datePickerRef = React.useRef(null);
2159
2159
  const calendarRef = React.useRef(null);
@@ -2167,7 +2167,7 @@ const DatePicker = React.forwardRef(({ className, value: controlledValue, defaul
2167
2167
  });
2168
2168
  const [calendarHeight, setCalendarHeight] = React.useState(300); // Default height estimate
2169
2169
  const value = controlledValue !== undefined
2170
- ? parseDate(controlledValue)
2170
+ ? parseDate$1(controlledValue)
2171
2171
  : uncontrolledValue;
2172
2172
  const hasValue = value !== null;
2173
2173
  // Create a formatter function that uses format prop if provided, otherwise formatDate
@@ -2388,8 +2388,8 @@ const DatePicker = React.forwardRef(({ className, value: controlledValue, defaul
2388
2388
  };
2389
2389
  }
2390
2390
  }, [isOpen]);
2391
- const minDateParsed = parseDate(minDate);
2392
- const maxDateParsed = parseDate(maxDate);
2391
+ const minDateParsed = parseDate$1(minDate);
2392
+ const maxDateParsed = parseDate$1(maxDate);
2393
2393
  const sizeConfig = {
2394
2394
  small: {
2395
2395
  gap: "gap-2",
@@ -2427,7 +2427,7 @@ const DatePicker = React.forwardRef(({ className, value: controlledValue, defaul
2427
2427
  top: `${calendarTop}px`,
2428
2428
  left: `${position.left}px`,
2429
2429
  zIndex: isInsideModal ? 10001 : 9999,
2430
- }, className: cn("bg-surface-fill-neutral-intense rounded-large shadow-lg p-4 w-fit", calendarClassName), onClick: (e) => e.stopPropagation(), children: jsx("div", { className: "react-calendar-wrapper w-fit", children: jsx(Calendar$1, { onChange: handleCalendarChange, value: value ?? null, minDate: minDateParsed ?? undefined, maxDate: maxDateParsed ?? undefined, locale: "en-US", formatShortWeekday: (locale, date) => {
2430
+ }, className: cn("bg-surface-fill-neutral-intense rounded-large shadow-lg p-4 w-fit", calendarClassName), onClick: (e) => e.stopPropagation(), children: jsx("div", { className: "react-calendar-wrapper w-fit", children: jsx(Calendar$1, { onChange: handleCalendarChange, value: value ?? null, minDate: minDateParsed ?? undefined, maxDate: maxDateParsed ?? undefined, locale: "en-US", showNeighboringMonth: true, showFixedNumberOfWeeks: true, formatShortWeekday: (locale, date) => {
2431
2431
  const weekdayNames = [
2432
2432
  "Su",
2433
2433
  "Mo",
@@ -2444,6 +2444,502 @@ const DatePicker = React.forwardRef(({ className, value: controlledValue, defaul
2444
2444
  });
2445
2445
  DatePicker.displayName = "DatePicker";
2446
2446
 
2447
+ const listItemVariants = cva("flex items-start gap-3 p-3 rounded-medium transition-colors cursor-pointer", {
2448
+ variants: {
2449
+ variant: {
2450
+ default: `hover:bg-action-fill-neutral-faded
2451
+ focus:bg-action-fill-neutral-faded
2452
+ focus:ring-2
2453
+ ring-action-outline-primary-faded-hover
2454
+ border border-transparent
2455
+ `,
2456
+ bordered: "border border-action-outline-primary-faded hover:bg-surface-fill-primary-subtle",
2457
+ primary: `hover:bg-action-fill-neutral-faded
2458
+ focus:bg-action-fill-neutral-faded
2459
+ focus:ring-2
2460
+ ring-action-outline-primary-faded-hover
2461
+ border border-transparent
2462
+ `,
2463
+ negative: `hover:bg-action-fill-negative-faded
2464
+ focus:bg-action-fill-negative-faded
2465
+ focus:ring-2 ring-action-outline-negative-faded-hover
2466
+ border border-transparent
2467
+ `,
2468
+ },
2469
+ isDisabled: {
2470
+ true: "cursor-not-allowed opacity-60",
2471
+ false: "",
2472
+ },
2473
+ isSelected: {
2474
+ true: "bg-action-fill-primary-faded border-action-outline-primary-faded",
2475
+ false: "",
2476
+ },
2477
+ },
2478
+ defaultVariants: {
2479
+ variant: "default",
2480
+ isDisabled: false,
2481
+ isSelected: false,
2482
+ },
2483
+ });
2484
+ const ChevronRightIcon = ({ className }) => (jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", className: className, children: jsx("path", { d: "M7.5 15L12.5 10L7.5 5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }));
2485
+ const ListItem = React.forwardRef(({ className, type = "single", leadingIcon, title, description, trailingIcon, showChevron = true, variant = "default", isDisabled = false, isSelected = false, onSelectionChange, checkboxSize = "small", containerClassName, contentClassName, onClick, ...props }, ref) => {
2486
+ const [internalSelected, setInternalSelected] = React.useState(isSelected);
2487
+ // Sync internal state with prop
2488
+ React.useEffect(() => {
2489
+ setInternalSelected(isSelected);
2490
+ }, [isSelected]);
2491
+ const handleClick = (e) => {
2492
+ if (isDisabled)
2493
+ return;
2494
+ if (type === "multiple") {
2495
+ const newSelected = !internalSelected;
2496
+ setInternalSelected(newSelected);
2497
+ onSelectionChange?.(newSelected);
2498
+ }
2499
+ onClick?.(e);
2500
+ };
2501
+ const handleCheckboxChange = (e) => {
2502
+ e.stopPropagation();
2503
+ if (isDisabled)
2504
+ return;
2505
+ const newSelected = e.target.checked;
2506
+ setInternalSelected(newSelected);
2507
+ onSelectionChange?.(newSelected);
2508
+ };
2509
+ return (jsxs("div", { ref: ref, className: cn(listItemVariants({
2510
+ variant,
2511
+ isDisabled,
2512
+ isSelected: type === "multiple" ? internalSelected : false,
2513
+ }), containerClassName), onClick: handleClick, role: type === "multiple" ? "checkbox" : "button", "aria-checked": type === "multiple" ? internalSelected : undefined, "aria-disabled": isDisabled, tabIndex: isDisabled ? -1 : 0, ...props, children: [type === "multiple" && (jsx(Checkbox, { checked: internalSelected, onChange: handleCheckboxChange, isDisabled: isDisabled, size: checkboxSize, className: "shrink-0 mt-0.5" })), leadingIcon && (jsx("div", { className: cn(`shrink-0 flex items-center justify-center mt-0.5`, variant === "primary"
2514
+ ? "text-action-ink-primary-normal"
2515
+ : variant === "negative"
2516
+ ? "text-action-ink-negative-normal"
2517
+ : "text-action-ink-neutral-subtle", isDisabled && "text-surface-ink-neutral-disabled"), children: leadingIcon })), jsxs("div", { className: cn("flex-1 min-w-0 flex flex-col justify-center", contentClassName), children: [jsx("div", { className: cn("text-body-medium-regular truncate", variant === "primary"
2518
+ ? "text-action-ink-primary-normal"
2519
+ : variant === "negative"
2520
+ ? "text-action-ink-negative-normal"
2521
+ : "text-action-ink-neutral-normal", isDisabled && "text-surface-ink-neutral-disabled"), children: title }), description && (jsx("div", { className: cn("text-body-small-regular text-surface-ink-neutral-muted mt-0.5 line-clamp-2", isDisabled && "text-surface-ink-neutral-disabled"), children: description }))] }), (trailingIcon || showChevron) && (jsx("div", { className: "shrink-0 self-center text-action-ink-neutral-subtle", children: trailingIcon || jsx(ChevronRightIcon, {}) }))] }));
2522
+ });
2523
+ ListItem.displayName = "ListItem";
2524
+
2525
+ const dateRangePickerVariants = cva("relative flex items-center gap-2 border rounded-large transition-all font-functional font-size-100 leading-100 bg-surface-fill-neutral-intense", {
2526
+ variants: {
2527
+ size: {
2528
+ small: "h-[28px] px-3 text-xs gap-2",
2529
+ medium: "h-[36px] px-4 text-sm gap-2",
2530
+ large: "h-[44px] px-5 text-base gap-3",
2531
+ },
2532
+ isDisabled: {
2533
+ true: `
2534
+ border-[var(--border-width-thinner)]
2535
+ hover:border-action-outline-neutral-disabled
2536
+ border-action-outline-neutral-disabled
2537
+ bg-surface-fill-neutral-intense cursor-not-allowed opacity-60`,
2538
+ false: `
2539
+ border-action-outline-neutral-faded
2540
+ hover:border-action-outline-primary-hover
2541
+ focus-within:border-action-outline-primary-hover
2542
+ focus-within:ring-2
2543
+ ring-action-outline-primary-faded-hover`,
2544
+ },
2545
+ },
2546
+ defaultVariants: {
2547
+ size: "medium",
2548
+ isDisabled: false,
2549
+ },
2550
+ });
2551
+ // Default preset options
2552
+ const defaultPresets = [
2553
+ {
2554
+ label: "Today",
2555
+ value: "today",
2556
+ getDateRange: () => {
2557
+ const today = new Date();
2558
+ today.setHours(0, 0, 0, 0);
2559
+ return { startDate: today, endDate: today };
2560
+ },
2561
+ },
2562
+ {
2563
+ label: "Yesterday",
2564
+ value: "yesterday",
2565
+ getDateRange: () => {
2566
+ const yesterday = new Date();
2567
+ yesterday.setDate(yesterday.getDate() - 1);
2568
+ yesterday.setHours(0, 0, 0, 0);
2569
+ return { startDate: yesterday, endDate: yesterday };
2570
+ },
2571
+ },
2572
+ {
2573
+ label: "Last 7 days",
2574
+ value: "last7days",
2575
+ getDateRange: () => {
2576
+ const endDate = new Date();
2577
+ endDate.setHours(0, 0, 0, 0);
2578
+ const startDate = new Date();
2579
+ startDate.setDate(startDate.getDate() - 6);
2580
+ startDate.setHours(0, 0, 0, 0);
2581
+ return { startDate, endDate };
2582
+ },
2583
+ },
2584
+ {
2585
+ label: "Last 30 days",
2586
+ value: "last30days",
2587
+ getDateRange: () => {
2588
+ const endDate = new Date();
2589
+ endDate.setHours(0, 0, 0, 0);
2590
+ const startDate = new Date();
2591
+ startDate.setDate(startDate.getDate() - 29);
2592
+ startDate.setHours(0, 0, 0, 0);
2593
+ return { startDate, endDate };
2594
+ },
2595
+ },
2596
+ {
2597
+ label: "Last 6 months",
2598
+ value: "last6months",
2599
+ getDateRange: () => {
2600
+ const endDate = new Date();
2601
+ endDate.setHours(0, 0, 0, 0);
2602
+ const startDate = new Date();
2603
+ startDate.setMonth(startDate.getMonth() - 6);
2604
+ startDate.setHours(0, 0, 0, 0);
2605
+ return { startDate, endDate };
2606
+ },
2607
+ },
2608
+ {
2609
+ label: "All time",
2610
+ value: "alltime",
2611
+ getDateRange: () => {
2612
+ return { startDate: null, endDate: null };
2613
+ },
2614
+ },
2615
+ ];
2616
+ // Helper functions
2617
+ const parseDate = (date) => {
2618
+ if (!date)
2619
+ return null;
2620
+ if (date instanceof Date)
2621
+ return date;
2622
+ if (typeof date === "string") {
2623
+ const parsed = new Date(date);
2624
+ return isNaN(parsed.getTime()) ? null : parsed;
2625
+ }
2626
+ return null;
2627
+ };
2628
+ const formatDateDefault = (date) => {
2629
+ return date.toLocaleDateString("en-US", {
2630
+ year: "numeric",
2631
+ month: "short",
2632
+ day: "numeric",
2633
+ });
2634
+ };
2635
+ const isSameDay = (date1, date2) => {
2636
+ if (!date1 || !date2)
2637
+ return false;
2638
+ return (date1.getFullYear() === date2.getFullYear() &&
2639
+ date1.getMonth() === date2.getMonth() &&
2640
+ date1.getDate() === date2.getDate());
2641
+ };
2642
+ const formatMonthYear = (date) => {
2643
+ return date.toLocaleDateString("en-US", {
2644
+ month: "long",
2645
+ year: "numeric",
2646
+ });
2647
+ };
2648
+ const DateRangePicker = React.forwardRef(({ className, value: controlledValue, defaultValue, onChange, placeholder = "Select date range", isDisabled = false, size = "medium", triggerClassName, calendarClassName, minDate, maxDate, formatDate = formatDateDefault, presets = defaultPresets, showPresets = true, selectedPresetLabel, ...props }, ref) => {
2649
+ const [uncontrolledValue, setUncontrolledValue] = React.useState(defaultValue || { startDate: null, endDate: null });
2650
+ const [tempValue, setTempValue] = React.useState(defaultValue || { startDate: null, endDate: null });
2651
+ const [isOpen, setIsOpen] = React.useState(false);
2652
+ const [selectedPreset, setSelectedPreset] = React.useState(null);
2653
+ const [startMonth, setStartMonth] = React.useState(new Date());
2654
+ const [endMonth, setEndMonth] = React.useState(() => {
2655
+ const nextMonth = new Date();
2656
+ nextMonth.setMonth(nextMonth.getMonth() + 1);
2657
+ return nextMonth;
2658
+ });
2659
+ const datePickerRef = React.useRef(null);
2660
+ const calendarRef = React.useRef(null);
2661
+ const [position, setPosition] = React.useState({
2662
+ top: 0,
2663
+ left: 0,
2664
+ width: 0,
2665
+ bottom: 0,
2666
+ });
2667
+ const [dropdownPlacement, setDropdownPlacement] = React.useState("bottom");
2668
+ const [isInsideModal, setIsInsideModal] = React.useState(false);
2669
+ const value = controlledValue !== undefined ? controlledValue : uncontrolledValue;
2670
+ const hasValue = value.startDate !== null || value.endDate !== null;
2671
+ const handleOpenChange = (newOpen) => {
2672
+ if (!isDisabled) {
2673
+ setIsOpen(newOpen);
2674
+ if (newOpen) {
2675
+ // Set temp value to current value when opening
2676
+ setTempValue(value);
2677
+ }
2678
+ }
2679
+ };
2680
+ const toggleOpen = () => {
2681
+ handleOpenChange(!isOpen);
2682
+ };
2683
+ const handlePresetClick = (preset) => {
2684
+ const dateRange = preset.getDateRange();
2685
+ setTempValue(dateRange);
2686
+ setSelectedPreset(preset.value);
2687
+ };
2688
+ const handleStartDateChange = (value, event) => {
2689
+ const selectedDate = Array.isArray(value) ? value[0] : value;
2690
+ if (!selectedDate)
2691
+ return;
2692
+ const newStartDate = new Date(selectedDate);
2693
+ newStartDate.setHours(0, 0, 0, 0);
2694
+ setTempValue((prev) => ({
2695
+ startDate: newStartDate,
2696
+ endDate: prev.endDate,
2697
+ }));
2698
+ setSelectedPreset(null);
2699
+ };
2700
+ const handleEndDateChange = (value, event) => {
2701
+ const selectedDate = Array.isArray(value) ? value[0] : value;
2702
+ if (!selectedDate)
2703
+ return;
2704
+ const newEndDate = new Date(selectedDate);
2705
+ newEndDate.setHours(0, 0, 0, 0);
2706
+ setTempValue((prev) => ({
2707
+ startDate: prev.startDate,
2708
+ endDate: newEndDate,
2709
+ }));
2710
+ setSelectedPreset(null);
2711
+ };
2712
+ const handleApply = () => {
2713
+ if (controlledValue === undefined) {
2714
+ setUncontrolledValue(tempValue);
2715
+ }
2716
+ onChange?.(tempValue);
2717
+ setIsOpen(false);
2718
+ };
2719
+ const handleCancel = () => {
2720
+ setTempValue(value);
2721
+ setIsOpen(false);
2722
+ };
2723
+ const handlePrevStartMonth = () => {
2724
+ const newMonth = new Date(startMonth);
2725
+ newMonth.setMonth(newMonth.getMonth() - 1);
2726
+ setStartMonth(newMonth);
2727
+ };
2728
+ const handleNextStartMonth = () => {
2729
+ const newMonth = new Date(startMonth);
2730
+ newMonth.setMonth(newMonth.getMonth() + 1);
2731
+ setStartMonth(newMonth);
2732
+ };
2733
+ const handlePrevEndMonth = () => {
2734
+ const newMonth = new Date(endMonth);
2735
+ newMonth.setMonth(newMonth.getMonth() - 1);
2736
+ setEndMonth(newMonth);
2737
+ };
2738
+ const handleNextEndMonth = () => {
2739
+ const newMonth = new Date(endMonth);
2740
+ newMonth.setMonth(newMonth.getMonth() + 1);
2741
+ setEndMonth(newMonth);
2742
+ };
2743
+ // Check if date picker is inside a modal
2744
+ React.useEffect(() => {
2745
+ if (isOpen && datePickerRef.current) {
2746
+ let element = datePickerRef.current;
2747
+ let foundModal = false;
2748
+ while (element && !foundModal) {
2749
+ const styles = window.getComputedStyle(element);
2750
+ const zIndex = parseInt(styles.zIndex, 10);
2751
+ if (zIndex === 10000 || element.getAttribute("role") === "dialog") {
2752
+ foundModal = true;
2753
+ setIsInsideModal(true);
2754
+ break;
2755
+ }
2756
+ element = element.parentElement;
2757
+ }
2758
+ if (!foundModal) {
2759
+ setIsInsideModal(false);
2760
+ }
2761
+ }
2762
+ }, [isOpen]);
2763
+ // Update position and placement when calendar opens or window resizes
2764
+ React.useEffect(() => {
2765
+ if (isOpen && datePickerRef.current) {
2766
+ const updatePosition = () => {
2767
+ const rect = datePickerRef.current?.getBoundingClientRect();
2768
+ const calendarHeight = calendarRef.current?.offsetHeight || 600; // Estimated height
2769
+ if (rect) {
2770
+ const viewportHeight = window.innerHeight;
2771
+ const viewportWidth = window.innerWidth;
2772
+ const gap = 4;
2773
+ // Calculate available space
2774
+ const spaceBelow = viewportHeight - rect.bottom - gap;
2775
+ const spaceAbove = rect.top - gap;
2776
+ // Determine vertical placement
2777
+ const placement = spaceBelow >= calendarHeight || spaceBelow >= spaceAbove
2778
+ ? "bottom"
2779
+ : "top";
2780
+ setDropdownPlacement(placement);
2781
+ // Calculate horizontal position
2782
+ let leftPosition = rect.left;
2783
+ const calendarWidth = calendarRef.current?.offsetWidth || 900; // Estimated width
2784
+ // Adjust if dropdown would overflow right edge
2785
+ if (leftPosition + calendarWidth > viewportWidth) {
2786
+ leftPosition = viewportWidth - calendarWidth - 10; // 10px margin from edge
2787
+ }
2788
+ // Ensure it doesn't overflow left edge
2789
+ if (leftPosition < 10) {
2790
+ leftPosition = 10;
2791
+ }
2792
+ setPosition({
2793
+ top: rect.top,
2794
+ left: leftPosition,
2795
+ width: rect.width,
2796
+ bottom: rect.bottom,
2797
+ });
2798
+ }
2799
+ };
2800
+ updatePosition();
2801
+ // Small delay to ensure calendar is rendered for accurate measurements
2802
+ const timeoutId = setTimeout(updatePosition, 10);
2803
+ window.addEventListener("resize", updatePosition);
2804
+ window.addEventListener("scroll", updatePosition, true);
2805
+ return () => {
2806
+ clearTimeout(timeoutId);
2807
+ window.removeEventListener("resize", updatePosition);
2808
+ window.removeEventListener("scroll", updatePosition, true);
2809
+ };
2810
+ }
2811
+ }, [isOpen]);
2812
+ // Close calendar when clicking outside
2813
+ React.useEffect(() => {
2814
+ const handleClickOutside = (event) => {
2815
+ if (datePickerRef.current &&
2816
+ !datePickerRef.current.contains(event.target) &&
2817
+ calendarRef.current &&
2818
+ !calendarRef.current.contains(event.target)) {
2819
+ handleCancel();
2820
+ }
2821
+ };
2822
+ if (isOpen) {
2823
+ document.addEventListener("mousedown", handleClickOutside);
2824
+ return () => {
2825
+ document.removeEventListener("mousedown", handleClickOutside);
2826
+ };
2827
+ }
2828
+ }, [isOpen, value]);
2829
+ // Close on escape key
2830
+ React.useEffect(() => {
2831
+ const handleEscape = (event) => {
2832
+ if (event.key === "Escape") {
2833
+ handleCancel();
2834
+ }
2835
+ };
2836
+ if (isOpen) {
2837
+ document.addEventListener("keydown", handleEscape);
2838
+ return () => {
2839
+ document.removeEventListener("keydown", handleEscape);
2840
+ };
2841
+ }
2842
+ }, [isOpen, value]);
2843
+ const minDateParsed = parseDate(minDate);
2844
+ const maxDateParsed = parseDate(maxDate);
2845
+ const getDisplayText = () => {
2846
+ if (selectedPresetLabel) {
2847
+ return selectedPresetLabel;
2848
+ }
2849
+ if (selectedPreset) {
2850
+ const preset = presets.find((p) => p.value === selectedPreset);
2851
+ if (preset)
2852
+ return preset.label;
2853
+ }
2854
+ if (!hasValue) {
2855
+ return placeholder;
2856
+ }
2857
+ if (value.startDate && value.endDate) {
2858
+ if (isSameDay(value.startDate, value.endDate)) {
2859
+ return formatDate(value.startDate);
2860
+ }
2861
+ return `${formatDate(value.startDate)} - ${formatDate(value.endDate)}`;
2862
+ }
2863
+ if (value.startDate) {
2864
+ return `From ${formatDate(value.startDate)}`;
2865
+ }
2866
+ if (value.endDate) {
2867
+ return `Until ${formatDate(value.endDate)}`;
2868
+ }
2869
+ return placeholder;
2870
+ };
2871
+ return (jsxs("div", { ref: datePickerRef, className: cn("relative w-fit", className), children: [jsxs("div", { className: cn(dateRangePickerVariants({
2872
+ size,
2873
+ isDisabled,
2874
+ }), "cursor-pointer", triggerClassName), onClick: !isDisabled ? toggleOpen : undefined, role: "button", "aria-haspopup": "dialog", "aria-expanded": isOpen, "aria-disabled": isDisabled, ...props, children: [jsx(Calendar, { className: cn("shrink-0 w-4 h-4", isDisabled
2875
+ ? "text-surface-ink-neutral-disabled"
2876
+ : "text-surface-ink-neutral-muted") }), jsx("span", { className: cn("flex-1 text-left truncate", !hasValue && "text-surface-ink-neutral-muted", isDisabled && "text-surface-ink-neutral-disabled"), children: getDisplayText() }), jsx(Icon, { name: "chevronDown", size: 16, className: cn("shrink-0 transition-transform", isDisabled
2877
+ ? "text-surface-ink-neutral-disabled"
2878
+ : "text-surface-ink-neutral-muted", isOpen && "rotate-180") })] }), typeof document !== "undefined" &&
2879
+ isOpen &&
2880
+ !isDisabled &&
2881
+ (() => {
2882
+ const gap = 4;
2883
+ const calendarHeight = calendarRef.current?.offsetHeight || 0;
2884
+ // Calculate top position based on placement
2885
+ const calendarTop = dropdownPlacement === "bottom"
2886
+ ? position.bottom + gap
2887
+ : position.top - calendarHeight - gap;
2888
+ const calendarPopup = (jsx("div", { ref: calendarRef, style: {
2889
+ position: "fixed",
2890
+ top: `${calendarTop}px`,
2891
+ left: `${position.left}px`,
2892
+ zIndex: isInsideModal ? 10001 : 9999,
2893
+ maxHeight: dropdownPlacement === "bottom"
2894
+ ? `${window.innerHeight - position.bottom - gap - 10}px`
2895
+ : `${position.top - gap - 10}px`,
2896
+ overflowY: "auto",
2897
+ }, className: cn("bg-surface-fill-neutral-intense rounded-large shadow-lg border border-surface-outline-neutral-subtle", calendarClassName), onClick: (e) => e.stopPropagation(), children: jsxs("div", { className: "flex", children: [showPresets && presets.length > 0 && (jsx("div", { className: "w-48 border-r border-surface-outline-neutral-subtle p-4 flex flex-col", children: presets.map((preset) => (jsx(ListItem, { title: preset.label, type: "single", showChevron: false, isSelected: selectedPreset === preset.value, onClick: () => handlePresetClick(preset), containerClassName: "mb-1 last:mb-0" }, preset.value))) })), jsxs("div", { className: "p-4", children: [jsxs("div", { className: "flex gap-6", children: [jsxs("div", { className: "flex flex-col gap-3", children: [jsx("div", { className: "flex flex-col px-3", children: jsx("p", { className: "text-body-small-medium", children: "Start Date" }) }), jsxs("div", { className: "flex flex-col p-5 rounded-[8px] bg-surface-fill-neutral-moderate", children: [jsxs("div", { className: "flex items-center justify-between mb-3 px-3", children: [jsx("h3", { className: "text-body-small-medium font-medium text-surface-ink-neutral-normal", children: formatMonthYear(startMonth) }), jsxs("div", { className: "flex items-center gap-2", children: [jsx("button", { onClick: handlePrevStartMonth, className: "p-1 hover:bg-surface-fill-neutral-faded rounded transition-colors", "aria-label": "Previous month", children: jsx(ChevronLeft, { className: "w-4 h-4 text-surface-ink-neutral-normal" }) }), jsx("button", { onClick: handleNextStartMonth, className: "p-1 hover:bg-surface-fill-neutral-faded rounded transition-colors", "aria-label": "Next month", children: jsx(ChevronRight, { className: "w-4 h-4 text-surface-ink-neutral-normal" }) })] })] }), jsx("div", { className: "date-range-calendar-wrapper", children: jsx(Calendar$1, { onChange: handleStartDateChange, value: tempValue.startDate, minDate: minDateParsed ?? undefined, maxDate: tempValue.endDate
2898
+ ? tempValue.endDate
2899
+ : maxDateParsed ?? undefined, activeStartDate: startMonth, onActiveStartDateChange: ({ activeStartDate, }) => {
2900
+ if (activeStartDate)
2901
+ setStartMonth(activeStartDate);
2902
+ }, locale: "en-US", showNavigation: false, showNeighboringMonth: true, showFixedNumberOfWeeks: true, formatShortWeekday: (locale, date) => {
2903
+ const weekdayNames = [
2904
+ "SUN",
2905
+ "MON",
2906
+ "TUE",
2907
+ "WED",
2908
+ "THU",
2909
+ "FRI",
2910
+ "SAT",
2911
+ ];
2912
+ return weekdayNames[date.getDay()];
2913
+ } }) })] })] }), jsxs("div", { className: "flex flex-col gap-3 ", children: [jsx("div", { className: "flex flex-col px-3", children: jsx("p", { className: "text-body-small-medium", children: "End Date" }) }), jsxs("div", { className: "flex flex-col p-5 rounded-[8px] bg-surface-fill-neutral-moderate", children: [jsxs("div", { className: "flex items-center justify-between mb-3 px-3", children: [jsx("h3", { className: "text-body-small-medium font-medium text-surface-ink-neutral-normal", children: formatMonthYear(endMonth) }), jsxs("div", { className: "flex items-center gap-2", children: [jsx("button", { onClick: handlePrevEndMonth, className: "p-1 hover:bg-surface-fill-neutral-faded rounded transition-colors", "aria-label": "Previous month", children: jsx(ChevronLeft, { className: "w-4 h-4 text-surface-ink-neutral-normal" }) }), jsx("button", { onClick: handleNextEndMonth, className: "p-1 hover:bg-surface-fill-neutral-faded rounded transition-colors", "aria-label": "Next month", children: jsx(ChevronRight, { className: "w-4 h-4 text-surface-ink-neutral-normal" }) })] })] }), jsx("div", { className: "date-range-calendar-wrapper", children: jsx(Calendar$1, { onChange: handleEndDateChange, value: tempValue.endDate, minDate: tempValue.startDate
2914
+ ? tempValue.startDate
2915
+ : minDateParsed ?? undefined, maxDate: maxDateParsed ?? undefined, activeStartDate: endMonth, onActiveStartDateChange: ({ activeStartDate, }) => {
2916
+ if (activeStartDate)
2917
+ setEndMonth(activeStartDate);
2918
+ }, locale: "en-US", showNavigation: false, showNeighboringMonth: true, showFixedNumberOfWeeks: true, formatShortWeekday: (locale, date) => {
2919
+ const weekdayNames = [
2920
+ "SUN",
2921
+ "MON",
2922
+ "TUE",
2923
+ "WED",
2924
+ "THU",
2925
+ "FRI",
2926
+ "SAT",
2927
+ ];
2928
+ return weekdayNames[date.getDay()];
2929
+ } }) })] })] })] }), jsxs("div", { className: "mt-4 pt-4 border-t border-surface-outline-neutral-subtle flex items-center justify-between", children: [jsxs("div", { className: "flex items-center gap-2", children: [jsx("div", { className: "w-2 h-2 rounded-full bg-action-fill-primary-default" }), jsx("span", { className: "text-sm text-surface-ink-neutral-normal", children: tempValue.startDate && tempValue.endDate
2930
+ ? isSameDay(tempValue.startDate, tempValue.endDate)
2931
+ ? "Today"
2932
+ : `${formatDate(tempValue.startDate)} - ${formatDate(tempValue.endDate)}`
2933
+ : tempValue.startDate
2934
+ ? `From ${formatDate(tempValue.startDate)}`
2935
+ : tempValue.endDate
2936
+ ? `Until ${formatDate(tempValue.endDate)}`
2937
+ : "No selection" })] }), jsxs("div", { className: "flex items-center gap-2", children: [jsx(Button, { variant: "secondary", color: "neutral", size: "small", onClick: handleCancel, children: "Cancel" }), jsx(Button, { variant: "primary", color: "primary", size: "small", onClick: handleApply, children: "Apply date range" })] })] })] })] }) }));
2938
+ return createPortal(calendarPopup, document.body);
2939
+ })()] }));
2940
+ });
2941
+ DateRangePicker.displayName = "DateRangePicker";
2942
+
2447
2943
  const dividerVariants = cva("", {
2448
2944
  variants: {
2449
2945
  orientation: {
@@ -2537,84 +3033,6 @@ const Divider = React.forwardRef(({ className, orientation = "horizontal", thick
2537
3033
  });
2538
3034
  Divider.displayName = "Divider";
2539
3035
 
2540
- const listItemVariants = cva("flex items-start gap-3 p-3 rounded-medium transition-colors cursor-pointer", {
2541
- variants: {
2542
- variant: {
2543
- default: `hover:bg-action-fill-neutral-faded
2544
- focus:bg-action-fill-neutral-faded
2545
- focus:ring-2
2546
- ring-action-outline-primary-faded-hover
2547
- border border-transparent
2548
- `,
2549
- bordered: "border border-action-outline-primary-faded hover:bg-surface-fill-primary-subtle",
2550
- primary: `hover:bg-action-fill-neutral-faded
2551
- focus:bg-action-fill-neutral-faded
2552
- focus:ring-2
2553
- ring-action-outline-primary-faded-hover
2554
- border border-transparent
2555
- `,
2556
- negative: `hover:bg-action-fill-negative-faded
2557
- focus:bg-action-fill-negative-faded
2558
- focus:ring-2 ring-action-outline-negative-faded-hover
2559
- border border-transparent
2560
- `,
2561
- },
2562
- isDisabled: {
2563
- true: "cursor-not-allowed opacity-60",
2564
- false: "",
2565
- },
2566
- isSelected: {
2567
- true: "bg-action-fill-primary-faded border-action-outline-primary-faded",
2568
- false: "",
2569
- },
2570
- },
2571
- defaultVariants: {
2572
- variant: "default",
2573
- isDisabled: false,
2574
- isSelected: false,
2575
- },
2576
- });
2577
- const ChevronRightIcon = ({ className }) => (jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", className: className, children: jsx("path", { d: "M7.5 15L12.5 10L7.5 5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }));
2578
- const ListItem = React.forwardRef(({ className, type = "single", leadingIcon, title, description, trailingIcon, showChevron = true, variant = "default", isDisabled = false, isSelected = false, onSelectionChange, checkboxSize = "small", containerClassName, contentClassName, onClick, ...props }, ref) => {
2579
- const [internalSelected, setInternalSelected] = React.useState(isSelected);
2580
- // Sync internal state with prop
2581
- React.useEffect(() => {
2582
- setInternalSelected(isSelected);
2583
- }, [isSelected]);
2584
- const handleClick = (e) => {
2585
- if (isDisabled)
2586
- return;
2587
- if (type === "multiple") {
2588
- const newSelected = !internalSelected;
2589
- setInternalSelected(newSelected);
2590
- onSelectionChange?.(newSelected);
2591
- }
2592
- onClick?.(e);
2593
- };
2594
- const handleCheckboxChange = (e) => {
2595
- e.stopPropagation();
2596
- if (isDisabled)
2597
- return;
2598
- const newSelected = e.target.checked;
2599
- setInternalSelected(newSelected);
2600
- onSelectionChange?.(newSelected);
2601
- };
2602
- return (jsxs("div", { ref: ref, className: cn(listItemVariants({
2603
- variant,
2604
- isDisabled,
2605
- isSelected: type === "multiple" ? internalSelected : false,
2606
- }), containerClassName), onClick: handleClick, role: type === "multiple" ? "checkbox" : "button", "aria-checked": type === "multiple" ? internalSelected : undefined, "aria-disabled": isDisabled, tabIndex: isDisabled ? -1 : 0, ...props, children: [type === "multiple" && (jsx(Checkbox, { checked: internalSelected, onChange: handleCheckboxChange, isDisabled: isDisabled, size: checkboxSize, className: "shrink-0 mt-0.5" })), leadingIcon && (jsx("div", { className: cn(`shrink-0 flex items-center justify-center mt-0.5`, variant === "primary"
2607
- ? "text-action-ink-primary-normal"
2608
- : variant === "negative"
2609
- ? "text-action-ink-negative-normal"
2610
- : "text-action-ink-neutral-subtle", isDisabled && "text-surface-ink-neutral-disabled"), children: leadingIcon })), jsxs("div", { className: cn("flex-1 min-w-0 flex flex-col justify-center", contentClassName), children: [jsx("div", { className: cn("text-body-medium-regular truncate", variant === "primary"
2611
- ? "text-action-ink-primary-normal"
2612
- : variant === "negative"
2613
- ? "text-action-ink-negative-normal"
2614
- : "text-action-ink-neutral-normal", isDisabled && "text-surface-ink-neutral-disabled"), children: title }), description && (jsx("div", { className: cn("text-body-small-regular text-surface-ink-neutral-muted mt-0.5 line-clamp-2", isDisabled && "text-surface-ink-neutral-disabled"), children: description }))] }), (trailingIcon || showChevron) && (jsx("div", { className: "shrink-0 self-center text-action-ink-neutral-subtle", children: trailingIcon || jsx(ChevronRightIcon, {}) }))] }));
2615
- });
2616
- ListItem.displayName = "ListItem";
2617
-
2618
3036
  const DropdownMenu = React.forwardRef(({ items = [], customContent, customContentClassName, sectionHeading, isLoading = false, isEmpty = false, emptyTitle = "No Search Results Found", emptyDescription = "Add description of what the user can search for here.", emptyLinkText = "Link to support site", onEmptyLinkClick, primaryButtonText = "Primary", secondaryButtonText = "Secondary", onPrimaryClick, onSecondaryClick, showChevron = false, emptyIcon, disableFooter = false, showFooter, footerLayout = "horizontal", onClose, focusedIndex = -1, className, width = "auto", maxHeight = "400px", }, ref) => {
2619
3037
  const renderContent = () => {
2620
3038
  if (isLoading) {
@@ -5530,5 +5948,5 @@ const UploadBox = React.forwardRef(({ label, helperText, errorText, successText,
5530
5948
  });
5531
5949
  UploadBox.displayName = "UploadBox";
5532
5950
 
5533
- export { Alert, Amount, Avatar, AvatarCell, Badge, Button, ButtonGroup, Checkbox, Counter, DatePicker, Divider, Dropdown, DropdownMenu, FormFooter, FormHeader, Icon, IconButton, IconCell, Link, ListItem, Modal, NumberCell, Pagination, Radio, RadioGroup, SearchableDropdown, Select, SelectTextField, SidePanel, Skeleton, SlotCell, SpacerCell, Switch, TabItem, Table, TableDetailPanel, Tabs, Text, TextArea, TextField, Toast, ToastProvider, Tooltip, UploadBox, alertVariants, avatarVariants, badgeVariants, buttonGroupVariants, buttonVariants, checkboxVariants, cn, counterVariants, datePickerVariants, dropdownVariants, getAvailableIcons, hasIcon, iconButtonVariants, iconRegistry, linkVariants, listItemVariants, paginationVariants, radioVariants, selectTriggerVariants, switchVariants, tableCellVariants, tableHeaderVariants, tableVariants, textAreaVariants, textFieldVariants, tooltipVariants, uploadBoxVariants, useToast };
5951
+ export { Alert, Amount, Avatar, AvatarCell, Badge, Button, ButtonGroup, Checkbox, Counter, DatePicker, DateRangePicker, Divider, Dropdown, DropdownMenu, FormFooter, FormHeader, Icon, IconButton, IconCell, Link, ListItem, Modal, NumberCell, Pagination, Radio, RadioGroup, SearchableDropdown, Select, SelectTextField, SidePanel, Skeleton, SlotCell, SpacerCell, Switch, TabItem, Table, TableDetailPanel, Tabs, Text, TextArea, TextField, Toast, ToastProvider, Tooltip, UploadBox, alertVariants, avatarVariants, badgeVariants, buttonGroupVariants, buttonVariants, checkboxVariants, cn, counterVariants, datePickerVariants, dateRangePickerVariants, dropdownVariants, getAvailableIcons, hasIcon, iconButtonVariants, iconRegistry, linkVariants, listItemVariants, paginationVariants, radioVariants, selectTriggerVariants, switchVariants, tableCellVariants, tableHeaderVariants, tableVariants, textAreaVariants, textFieldVariants, tooltipVariants, uploadBoxVariants, useToast };
5534
5952
  //# sourceMappingURL=index.esm.js.map