@geomak/ui 4.0.0 → 5.0.1

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.js CHANGED
@@ -2804,7 +2804,7 @@ function NumberInput({
2804
2804
  "div",
2805
2805
  {
2806
2806
  style,
2807
- className: `flex items-center rounded-lg border ${hasError ? "border-status-error" : "border-border"} ${disabled ? "bg-surface-raised text-foreground-muted cursor-not-allowed" : "bg-surface text-foreground"} focus-within:ring-2 focus-within:ring-accent transition-colors`,
2807
+ className: `flex items-center rounded-lg border overflow-hidden ${hasError ? "border-status-error" : "border-border"} ${disabled ? "bg-surface-raised text-foreground-muted cursor-not-allowed" : "bg-surface text-foreground"} focus-within:ring-2 focus-within:ring-accent transition-colors`,
2808
2808
  children: [
2809
2809
  /* @__PURE__ */ jsx(
2810
2810
  "input",
@@ -3024,25 +3024,22 @@ function Switch({
3024
3024
  uncheckedIcon
3025
3025
  }) {
3026
3026
  const id = useId();
3027
- return /* @__PURE__ */ jsxs("div", { children: [
3028
- "// mr-12 was a hardcoded right margin that broke layouts; spacing // is the parent's responsibility now.",
3029
- /* @__PURE__ */ jsx("label", { htmlFor: id, className: "flex items-center cursor-pointer select-none", children: /* @__PURE__ */ jsx(
3030
- SwitchPrimitive.Root,
3031
- {
3032
- id,
3033
- checked,
3034
- onCheckedChange: (c) => onChange?.({ target: { checked: c } }),
3035
- className: "relative inline-flex h-6 w-14 items-center rounded-full bg-foreground-secondary data-[state=checked]:bg-accent transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2",
3036
- children: /* @__PURE__ */ jsx(
3037
- SwitchPrimitive.Thumb,
3038
- {
3039
- className: "pointer-events-none inline-flex h-8 w-8 items-center justify-center rounded-full bg-background text-foreground shadow transition-transform duration-200 data-[state=checked]:translate-x-[22px] data-[state=unchecked]:translate-x-[-4px]",
3040
- children: checkedIcon && uncheckedIcon ? checked ? checkedIcon : uncheckedIcon : null
3041
- }
3042
- )
3043
- }
3044
- ) })
3045
- ] });
3027
+ return /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("label", { htmlFor: id, className: "flex items-center cursor-pointer select-none", children: /* @__PURE__ */ jsx(
3028
+ SwitchPrimitive.Root,
3029
+ {
3030
+ id,
3031
+ checked,
3032
+ onCheckedChange: (c) => onChange?.({ target: { checked: c } }),
3033
+ className: "relative inline-flex h-6 w-14 items-center rounded-full bg-foreground-secondary data-[state=checked]:bg-accent transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2",
3034
+ children: /* @__PURE__ */ jsx(
3035
+ SwitchPrimitive.Thumb,
3036
+ {
3037
+ className: "pointer-events-none inline-flex h-8 w-8 items-center justify-center rounded-full bg-background text-foreground shadow transition-transform duration-200 data-[state=checked]:translate-x-[22px] data-[state=unchecked]:translate-x-[-4px]",
3038
+ children: checkedIcon && uncheckedIcon ? checked ? checkedIcon : uncheckedIcon : null
3039
+ }
3040
+ )
3041
+ }
3042
+ ) }) });
3046
3043
  }
3047
3044
  function AutoComplete({
3048
3045
  disabled,
@@ -3185,11 +3182,17 @@ function TreeSelect({
3185
3182
  const [activeIndex, setActiveIndex] = useState(0);
3186
3183
  const listRef = useRef(null);
3187
3184
  const visible = useMemo(() => flattenVisible(items, expanded), [items, expanded]);
3185
+ const didSyncOnOpenRef = useRef(false);
3188
3186
  useEffect(() => {
3189
- if (!open) return;
3187
+ if (!open) {
3188
+ didSyncOnOpenRef.current = false;
3189
+ return;
3190
+ }
3191
+ if (didSyncOnOpenRef.current) return;
3190
3192
  const selectedIdx = visible.findIndex((v) => v.node.key === value);
3191
3193
  setActiveIndex(selectedIdx >= 0 ? selectedIdx : 0);
3192
- }, [open, visible, value]);
3194
+ didSyncOnOpenRef.current = true;
3195
+ }, [open, value]);
3193
3196
  const selectedNode = useMemo(
3194
3197
  () => value != null ? findNodeByKey(items, value) : null,
3195
3198
  [items, value]
@@ -3503,295 +3506,285 @@ function FileInput({
3503
3506
  )
3504
3507
  );
3505
3508
  }
3506
- var MONTHS = {
3507
- 1: "January",
3508
- 2: "February",
3509
- 3: "March",
3510
- 4: "April",
3511
- 5: "May",
3512
- 6: "June",
3513
- 7: "July",
3514
- 8: "August",
3515
- 9: "September",
3516
- 10: "October",
3517
- 11: "November",
3518
- 12: "December"
3519
- };
3520
- var DAYS = { 0: "Sun", 1: "Mon", 2: "Tue", 3: "Wed", 4: "Thu", 5: "Fri", 6: "Sat" };
3521
- function formatDate(date) {
3522
- const fmt = new Intl.DateTimeFormat("en-GB", { year: "numeric", month: "numeric", day: "numeric" });
3523
- const parts = fmt.formatToParts(date);
3524
- const d = parts.find((x) => x.type === "day").value;
3525
- const m = parts.find((x) => x.type === "month").value;
3526
- const y = parts.find((x) => x.type === "year").value;
3527
- return `${y}-${m}-${d}`;
3528
- }
3529
- function getMonthDays(year, month) {
3530
- const days = [];
3531
- for (let i = 1; i <= 31; i++) {
3532
- const d = new Date(year, month - 1, i);
3533
- if (d.getMonth() + 1 > month) break;
3534
- days.push(d);
3509
+ var MONTH_NAMES = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
3510
+ var WEEKDAY_SHORT = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
3511
+ function isSameDay(a, b) {
3512
+ return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
3513
+ }
3514
+ function startOfMonth(d) {
3515
+ return new Date(d.getFullYear(), d.getMonth(), 1);
3516
+ }
3517
+ function addDays(d, n) {
3518
+ const c = new Date(d);
3519
+ c.setDate(c.getDate() + n);
3520
+ return c;
3521
+ }
3522
+ function addMonths(d, n) {
3523
+ const c = new Date(d);
3524
+ c.setMonth(c.getMonth() + n);
3525
+ return c;
3526
+ }
3527
+ function defaultFormat(d) {
3528
+ const y = d.getFullYear().toString().padStart(4, "0");
3529
+ const m = (d.getMonth() + 1).toString().padStart(2, "0");
3530
+ const day = d.getDate().toString().padStart(2, "0");
3531
+ return `${y}-${m}-${day}`;
3532
+ }
3533
+ function buildGrid(viewMonth, weekStartsOn) {
3534
+ const first = startOfMonth(viewMonth);
3535
+ const startOffset = (first.getDay() - weekStartsOn + 7) % 7;
3536
+ const gridStart = addDays(first, -startOffset);
3537
+ const cells = [];
3538
+ for (let i = 0; i < 42; i++) {
3539
+ const d = addDays(gridStart, i);
3540
+ cells.push({ date: d, outside: d.getMonth() !== viewMonth.getMonth() });
3535
3541
  }
3536
- return days;
3542
+ const rows = [];
3543
+ for (let r = 0; r < 6; r++) rows.push(cells.slice(r * 7, r * 7 + 7));
3544
+ return rows;
3537
3545
  }
3538
- var ChevronRight3 = ({ color = colors_default.PALETTE["prussian-blue"] }) => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: 2, className: "w-4 h-4", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 5l7 7-7 7" }) });
3539
- var DoubleChevronRight2 = ({ color = colors_default.PALETTE["prussian-blue"] }) => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: 2, className: "w-4 h-4", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M13 5l7 7-7 7M5 5l7 7-7 7" }) });
3540
- var ChevronDown2 = ({ color = colors_default.PALETTE["prussian-blue"] }) => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: 2, className: "w-4 h-4", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) });
3541
- function DatePickerBase({
3546
+ function DatePicker({
3542
3547
  value,
3543
3548
  onChange,
3544
- layout,
3545
3549
  label,
3550
+ placeholder = "Select a date\u2026",
3546
3551
  htmlFor,
3547
- name,
3548
- style = {},
3552
+ name: _name,
3553
+ layout = "horizontal",
3554
+ disabled,
3549
3555
  errorMessage,
3550
- disableBefore,
3551
- disableAfter,
3552
- disabled
3556
+ min,
3557
+ max,
3558
+ style,
3559
+ format = defaultFormat,
3560
+ weekStartsOn = 0,
3561
+ clearable = true
3553
3562
  }) {
3554
- const pickerRef = useRef(null);
3555
- const calendarRef = useRef(null);
3556
- const [isExpanded, setExpanded] = useState(false);
3557
- const [isCloseToBottom, setCloseToBottom] = useState(false);
3558
- const [currentYear, setCurrentYear] = useState(value.getFullYear());
3559
- const [currentMonth, setCurrentMonth] = useState(value.getMonth() + 1);
3560
- const toggle = () => {
3561
- if (!disabled) setExpanded((p) => !p);
3562
- };
3563
- const toNextMonth = () => {
3564
- if (currentMonth + 1 > 12) {
3565
- setCurrentMonth(1);
3566
- setCurrentYear((y) => y + 1);
3567
- } else setCurrentMonth((m) => m + 1);
3568
- };
3569
- const toPrevMonth = () => {
3570
- if (currentMonth - 1 === 0) {
3571
- setCurrentMonth(12);
3572
- setCurrentYear((y) => y - 1);
3573
- } else setCurrentMonth((m) => m - 1);
3574
- };
3575
- const isToday = (d) => {
3576
- const t = /* @__PURE__ */ new Date();
3577
- return t.getDate() === d.getDate() && t.getMonth() === d.getMonth() && t.getFullYear() === d.getFullYear();
3578
- };
3579
- const isSelected = (d) => value.getDate() === d.getDate() && value.getMonth() === d.getMonth() && value.getFullYear() === d.getFullYear();
3580
- const isDateDisabled = (d) => {
3581
- if (disableBefore && d.getTime() < new Date(disableBefore).getTime()) return true;
3582
- if (disableAfter && d.getTime() > new Date(disableAfter).getTime()) return true;
3563
+ const errorId = useId();
3564
+ const hasError = errorMessage != null;
3565
+ const [open, setOpen] = useState(false);
3566
+ const [viewMonth, setViewMonth] = useState(() => startOfMonth(value ?? /* @__PURE__ */ new Date()));
3567
+ const [focusDate, setFocusDate] = useState(() => value ?? /* @__PURE__ */ new Date());
3568
+ const gridRef = useRef(null);
3569
+ useEffect(() => {
3570
+ if (!open) return;
3571
+ const target = value ?? /* @__PURE__ */ new Date();
3572
+ setViewMonth(startOfMonth(target));
3573
+ setFocusDate(target);
3574
+ }, [open, value]);
3575
+ useEffect(() => {
3576
+ if (!open) return;
3577
+ const cell = gridRef.current?.querySelector(`[data-day="${defaultFormat(focusDate)}"]`);
3578
+ cell?.focus();
3579
+ }, [open, focusDate]);
3580
+ const weekdays = useMemo(() => {
3581
+ const ordered = WEEKDAY_SHORT.slice(weekStartsOn).concat(WEEKDAY_SHORT.slice(0, weekStartsOn));
3582
+ return ordered;
3583
+ }, [weekStartsOn]);
3584
+ const grid = useMemo(() => buildGrid(viewMonth, weekStartsOn), [viewMonth, weekStartsOn]);
3585
+ const isDisabled = (d) => {
3586
+ if (min && d < min) return true;
3587
+ if (max && d > max) return true;
3583
3588
  return false;
3584
3589
  };
3585
- const onDateClick = (d) => {
3586
- const next = new Date(formatDate(d));
3587
- onChange({ target: { value: next, id: htmlFor, name } });
3588
- setExpanded(false);
3589
- setCurrentYear(d.getFullYear());
3590
- setCurrentMonth(d.getMonth() + 1);
3590
+ const selectDate = (d) => {
3591
+ if (isDisabled(d)) return;
3592
+ onChange?.(d);
3593
+ setOpen(false);
3591
3594
  };
3592
- const renderCalendar = () => {
3593
- const days = getMonthDays(currentYear, currentMonth);
3594
- const firstDay = days[0].getDay();
3595
- const cols = [[], [], [], [], [], [], []];
3596
- days.forEach((d) => cols[d.getDay()].push(d));
3597
- let ordered = [...cols];
3598
- if (firstDay > 0) {
3599
- ordered = [...ordered.splice(firstDay), ...ordered];
3595
+ const onKey = (e) => {
3596
+ const next = (delta) => {
3597
+ const nd = addDays(focusDate, delta);
3598
+ setFocusDate(nd);
3599
+ if (nd.getMonth() !== viewMonth.getMonth()) setViewMonth(startOfMonth(nd));
3600
+ };
3601
+ if (e.key === "ArrowLeft") {
3602
+ e.preventDefault();
3603
+ next(-1);
3604
+ } else if (e.key === "ArrowRight") {
3605
+ e.preventDefault();
3606
+ next(1);
3607
+ } else if (e.key === "ArrowUp") {
3608
+ e.preventDefault();
3609
+ next(-7);
3610
+ } else if (e.key === "ArrowDown") {
3611
+ e.preventDefault();
3612
+ next(7);
3613
+ } else if (e.key === "PageUp") {
3614
+ e.preventDefault();
3615
+ const nm = addMonths(viewMonth, -1);
3616
+ setViewMonth(nm);
3617
+ setFocusDate((d) => addMonths(d, -1));
3618
+ } else if (e.key === "PageDown") {
3619
+ e.preventDefault();
3620
+ const nm = addMonths(viewMonth, 1);
3621
+ setViewMonth(nm);
3622
+ setFocusDate((d) => addMonths(d, 1));
3623
+ } else if (e.key === "Home") {
3624
+ e.preventDefault();
3625
+ const dow = (focusDate.getDay() - weekStartsOn + 7) % 7;
3626
+ setFocusDate(addDays(focusDate, -dow));
3627
+ } else if (e.key === "End") {
3628
+ e.preventDefault();
3629
+ const dow = (focusDate.getDay() - weekStartsOn + 7) % 7;
3630
+ setFocusDate(addDays(focusDate, 6 - dow));
3631
+ } else if (e.key === "Enter" || e.key === " ") {
3632
+ e.preventDefault();
3633
+ selectDate(focusDate);
3634
+ } else if (e.key === "Escape") {
3635
+ e.preventDefault();
3636
+ setOpen(false);
3600
3637
  }
3601
- return ordered;
3602
3638
  };
3603
- useEffect(() => {
3604
- const clickAway = (e) => {
3605
- if (pickerRef.current && !pickerRef.current.contains(e.target) && calendarRef.current && !calendarRef.current.contains(e.target)) setExpanded(false);
3606
- };
3607
- document.addEventListener("mousedown", clickAway);
3608
- return () => document.removeEventListener("mousedown", clickAway);
3609
- }, []);
3610
- useEffect(() => {
3611
- const bbox = pickerRef.current?.getBoundingClientRect();
3612
- if (bbox && (bbox.y > window.innerHeight - 220 || bbox.bottom > window.innerHeight - 400)) {
3613
- setCloseToBottom(true);
3614
- } else setCloseToBottom(false);
3615
- }, []);
3616
- return /* @__PURE__ */ jsxs("div", { className: "w-full", children: [
3617
- /* @__PURE__ */ jsxs("div", { className: `flex relative ${layout === "vertical" ? "flex-col" : "flex-row items-center gap-2"}`, children: [
3618
- label && /* @__PURE__ */ jsx("label", { className: "text-md font-bold ml-1 max-content text-prussian-blue dark:text-white", children: label }),
3619
- /* @__PURE__ */ jsxs(
3620
- "div",
3639
+ const displayValue = value ? format(value) : "";
3640
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
3641
+ /* @__PURE__ */ jsxs("div", { className: `flex ${layout === "vertical" ? "flex-col gap-1" : "flex-row items-center gap-2"}`, children: [
3642
+ label && /* @__PURE__ */ jsx(
3643
+ "label",
3621
3644
  {
3622
- style,
3623
- ref: pickerRef,
3624
- className: `flex items-center justify-between relative h-9 ${disabled ? "bg-disabled cursor-not-allowed" : "bg-white cursor-pointer"} rounded-lg p-2`,
3625
- children: [
3626
- /* @__PURE__ */ jsx(
3627
- "div",
3628
- {
3629
- onClick: toggle,
3630
- className: `h-7 focus:outline-none text-prussian-blue ${disabled ? "cursor-not-allowed" : "cursor-pointer"} ${!style.width ? "min-w-[240px]" : ""} flex items-center gap-1`,
3631
- children: formatDate(value)
3632
- }
3633
- ),
3634
- /* @__PURE__ */ jsx(
3635
- "div",
3636
- {
3637
- onClick: toggle,
3638
- className: `transition-all duration-300 ml-2 ${isExpanded ? "rotate-180" : "rotate-0 w-4 h-4"}`,
3639
- children: /* @__PURE__ */ jsx(ChevronDown2, {})
3640
- }
3641
- )
3642
- ]
3645
+ className: "text-sm font-medium ml-1 max-content select-none text-foreground",
3646
+ htmlFor,
3647
+ children: label
3643
3648
  }
3644
3649
  ),
3645
- /* @__PURE__ */ jsx(
3646
- "div",
3647
- {
3648
- ref: calendarRef,
3649
- className: `w-[280px] bg-ice absolute ${isCloseToBottom ? "bottom-[40px]" : "top-[60px]"} z-10 rounded-lg shadow-md transition-all duration-150 ${isExpanded ? "h-max scale-100" : "scale-0 pointer-events-none"}`,
3650
- children: isExpanded && /* @__PURE__ */ jsxs("div", { className: "pt-3", children: [
3651
- /* @__PURE__ */ jsxs("div", { className: "flex items-center mx-auto w-max", children: [
3652
- /* @__PURE__ */ jsx("span", { onClick: () => setCurrentYear((y) => y - 1), className: "cursor-pointer rotate-180 p-1 rounded-lg hover:bg-ice-dark transition-all duration-300", children: /* @__PURE__ */ jsx(DoubleChevronRight2, {}) }),
3653
- /* @__PURE__ */ jsx("span", { onClick: toPrevMonth, className: "cursor-pointer rotate-180 p-1 rounded-lg hover:bg-ice-dark transition-all duration-300", children: /* @__PURE__ */ jsx(ChevronRight3, {}) }),
3654
- /* @__PURE__ */ jsxs("span", { className: "font-bold text-prussian-blue select-none w-[130px] text-center", children: [
3655
- currentYear,
3656
- " ",
3657
- MONTHS[currentMonth]
3650
+ /* @__PURE__ */ jsxs(Popover.Root, { open: open && !disabled, onOpenChange: (o) => !disabled && setOpen(o), children: [
3651
+ /* @__PURE__ */ jsx(Popover.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs(
3652
+ "button",
3653
+ {
3654
+ id: htmlFor,
3655
+ type: "button",
3656
+ disabled,
3657
+ style,
3658
+ "aria-invalid": hasError || void 0,
3659
+ "aria-describedby": hasError ? errorId : void 0,
3660
+ "aria-haspopup": "dialog",
3661
+ "aria-expanded": open,
3662
+ className: `flex items-center justify-between h-9 rounded-lg border px-3 cursor-pointer select-none focus:outline-none focus-visible:ring-2 focus-visible:ring-accent ${hasError ? "border-status-error" : "border-border"} ${disabled ? "cursor-not-allowed bg-surface-raised text-foreground-muted" : "bg-surface text-foreground"} ${!style?.width ? "min-w-[200px]" : ""}`,
3663
+ children: [
3664
+ /* @__PURE__ */ jsx("span", { className: `text-sm truncate ${displayValue ? "" : "text-foreground-muted"}`, children: displayValue || placeholder }),
3665
+ /* @__PURE__ */ jsx(CalendarIcon, {})
3666
+ ]
3667
+ }
3668
+ ) }),
3669
+ /* @__PURE__ */ jsx(Popover.Portal, { children: /* @__PURE__ */ jsxs(
3670
+ Popover.Content,
3671
+ {
3672
+ align: "start",
3673
+ sideOffset: 4,
3674
+ className: "bg-surface text-foreground border border-border rounded-lg shadow-md z-50 p-3 animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
3675
+ onOpenAutoFocus: (e) => {
3676
+ e.preventDefault();
3677
+ },
3678
+ children: [
3679
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-2", children: [
3680
+ /* @__PURE__ */ jsx(
3681
+ "button",
3682
+ {
3683
+ type: "button",
3684
+ onClick: () => setViewMonth(addMonths(viewMonth, -1)),
3685
+ "aria-label": "Previous month",
3686
+ className: "w-7 h-7 inline-flex items-center justify-center rounded-md hover:bg-surface-raised focus:outline-none focus-visible:ring-2 focus-visible:ring-accent transition-colors",
3687
+ children: /* @__PURE__ */ jsx(ChevronLeft, {})
3688
+ }
3689
+ ),
3690
+ /* @__PURE__ */ jsxs("div", { className: "text-sm font-semibold select-none", children: [
3691
+ MONTH_NAMES[viewMonth.getMonth()],
3692
+ " ",
3693
+ viewMonth.getFullYear()
3694
+ ] }),
3695
+ /* @__PURE__ */ jsx(
3696
+ "button",
3697
+ {
3698
+ type: "button",
3699
+ onClick: () => setViewMonth(addMonths(viewMonth, 1)),
3700
+ "aria-label": "Next month",
3701
+ className: "w-7 h-7 inline-flex items-center justify-center rounded-md hover:bg-surface-raised focus:outline-none focus-visible:ring-2 focus-visible:ring-accent transition-colors",
3702
+ children: /* @__PURE__ */ jsx(ChevronRight3, {})
3703
+ }
3704
+ )
3658
3705
  ] }),
3659
- /* @__PURE__ */ jsx("span", { onClick: toNextMonth, className: "cursor-pointer p-1 rounded-lg hover:bg-ice-dark transition-all duration-300", children: /* @__PURE__ */ jsx(ChevronRight3, {}) }),
3660
- /* @__PURE__ */ jsx("span", { onClick: () => setCurrentYear((y) => y + 1), className: "cursor-pointer p-1 rounded-lg hover:bg-ice-dark transition-all duration-300", children: /* @__PURE__ */ jsx(DoubleChevronRight2, {}) })
3661
- ] }),
3662
- /* @__PURE__ */ jsx("div", { className: "flex gap-3 p-2", children: renderCalendar().map((weekDay, index) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-2", children: [
3663
- /* @__PURE__ */ jsx("div", { className: "text-center font-bold text-sm text-prussian-blue", children: weekDay[0] ? DAYS[weekDay[0].getDay()] : "" }),
3664
- weekDay.map((day) => /* @__PURE__ */ jsx(
3665
- "div",
3706
+ /* @__PURE__ */ jsxs(
3707
+ "table",
3666
3708
  {
3667
- onClick: () => !isDateDisabled(day) && onDateClick(day),
3668
- className: `cursor-pointer flex items-center justify-center text-prussian-blue rounded-md w-6 h-6 transition-all duration-300
3669
- ${isToday(day) ? "border border-prussian-blue" : ""}
3670
- ${isSelected(day) ? "bg-prussian-blue text-white" : ""}
3671
- ${!isSelected(day) ? "hover:bg-ice-dark" : ""}
3672
- ${isDateDisabled(day) ? "bg-ice-dark text-roman-silver cursor-not-allowed pointer-events-none" : ""}`,
3673
- children: day.getDate()
3674
- },
3675
- day.getDate()
3676
- ))
3677
- ] }, index)) }),
3678
- /* @__PURE__ */ jsx("div", { className: "pb-2 pr-2 flex items-center justify-end", children: /* @__PURE__ */ jsx(
3679
- Button,
3680
- {
3681
- onClick: () => onDateClick(/* @__PURE__ */ new Date()),
3682
- content: "Today",
3683
- style: { width: "max-content", padding: "0px 5px", margin: "0" }
3684
- }
3685
- ) })
3686
- ] })
3687
- }
3688
- )
3709
+ ref: gridRef,
3710
+ role: "grid",
3711
+ "aria-label": `${MONTH_NAMES[viewMonth.getMonth()]} ${viewMonth.getFullYear()}`,
3712
+ onKeyDown: onKey,
3713
+ className: "border-separate border-spacing-0",
3714
+ children: [
3715
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { children: weekdays.map((w) => /* @__PURE__ */ jsx("th", { scope: "col", className: "text-[11px] font-medium text-foreground-muted uppercase tracking-wide w-8 h-8", children: w }, w)) }) }),
3716
+ /* @__PURE__ */ jsx("tbody", { children: grid.map((row, ri) => /* @__PURE__ */ jsx("tr", { children: row.map(({ date, outside }) => {
3717
+ const dis = isDisabled(date);
3718
+ const sel = value ? isSameDay(date, value) : false;
3719
+ const focused = isSameDay(date, focusDate);
3720
+ const today = isSameDay(date, /* @__PURE__ */ new Date());
3721
+ return /* @__PURE__ */ jsx("td", { role: "gridcell", className: "p-0", children: /* @__PURE__ */ jsx(
3722
+ "button",
3723
+ {
3724
+ type: "button",
3725
+ disabled: dis,
3726
+ tabIndex: focused ? 0 : -1,
3727
+ "data-day": defaultFormat(date),
3728
+ "aria-label": defaultFormat(date),
3729
+ "aria-selected": sel || void 0,
3730
+ onClick: () => selectDate(date),
3731
+ className: [
3732
+ "w-8 h-8 rounded-md text-xs font-medium transition-colors duration-100",
3733
+ "focus:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1 focus-visible:ring-offset-surface",
3734
+ "disabled:opacity-30 disabled:cursor-not-allowed",
3735
+ sel ? "bg-accent text-accent-fg" : today ? "bg-surface-raised text-foreground ring-1 ring-inset ring-accent" : outside ? "text-foreground-muted hover:bg-surface-raised" : "text-foreground hover:bg-surface-raised"
3736
+ ].join(" "),
3737
+ children: date.getDate()
3738
+ }
3739
+ ) }, defaultFormat(date));
3740
+ }) }, ri)) })
3741
+ ]
3742
+ }
3743
+ ),
3744
+ /* @__PURE__ */ jsxs("div", { className: "mt-2 flex items-center justify-between gap-2 border-t border-border pt-2", children: [
3745
+ /* @__PURE__ */ jsx(
3746
+ "button",
3747
+ {
3748
+ type: "button",
3749
+ onClick: () => selectDate(/* @__PURE__ */ new Date()),
3750
+ className: "text-xs text-accent hover:underline focus:outline-none focus-visible:ring-2 focus-visible:ring-accent rounded-sm px-1",
3751
+ children: "Today"
3752
+ }
3753
+ ),
3754
+ clearable && value && /* @__PURE__ */ jsx(
3755
+ "button",
3756
+ {
3757
+ type: "button",
3758
+ onClick: () => {
3759
+ onChange?.(null);
3760
+ setOpen(false);
3761
+ },
3762
+ className: "text-xs text-foreground-secondary hover:text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-accent rounded-sm px-1",
3763
+ children: "Clear"
3764
+ }
3765
+ )
3766
+ ] })
3767
+ ]
3768
+ }
3769
+ ) })
3770
+ ] })
3689
3771
  ] }),
3690
- /* @__PURE__ */ jsx("div", { className: "text-center text-error dark:text-prussian-blue min-h-0", children: errorMessage })
3772
+ hasError && /* @__PURE__ */ jsx("div", { id: errorId, className: "text-xs text-status-error ml-1", children: errorMessage })
3691
3773
  ] });
3692
3774
  }
3693
- function TemporalPickerBase({
3694
- value,
3695
- onChange,
3696
- lowerLimit = 2e3,
3697
- upperLimit = (/* @__PURE__ */ new Date()).getFullYear(),
3698
- errorMessage,
3699
- label,
3700
- layout,
3701
- style = {}
3702
- }) {
3703
- const pickerRef = useRef(null);
3704
- const calendarRef = useRef(null);
3705
- const valueRefs = useRef([]);
3706
- const [isExpanded, setExpanded] = useState(false);
3707
- const [isCloseToBottom, setCloseToBottom] = useState(false);
3708
- const innerValues = useMemo(() => {
3709
- const vals = [];
3710
- for (let i = lowerLimit; i <= upperLimit; i++) vals.push(i);
3711
- return vals;
3712
- }, [lowerLimit, upperLimit]);
3713
- useEffect(() => {
3714
- const clickAway = (e) => {
3715
- if (pickerRef.current && !pickerRef.current.contains(e.target) && calendarRef.current && !calendarRef.current.contains(e.target)) setExpanded(false);
3716
- };
3717
- document.addEventListener("mousedown", clickAway);
3718
- return () => document.removeEventListener("mousedown", clickAway);
3719
- }, []);
3720
- useEffect(() => {
3721
- const bbox = pickerRef.current?.getBoundingClientRect();
3722
- if (bbox && bbox.y > window.innerHeight - 220) setCloseToBottom(true);
3723
- else setCloseToBottom(false);
3724
- }, []);
3725
- useEffect(() => {
3726
- if (!isExpanded) return;
3727
- const t = setTimeout(() => {
3728
- const node = valueRefs.current.find((n) => n.value === value);
3729
- node?.ref.scrollIntoView({ block: "end", inline: "nearest", behavior: "smooth" });
3730
- }, 150);
3731
- return () => clearTimeout(t);
3732
- }, [isExpanded, value]);
3733
- const navigate = (delta) => {
3734
- const next = value + delta;
3735
- if (next < lowerLimit || next > upperLimit) return;
3736
- onChange({ target: { value: next } });
3737
- const node = valueRefs.current.find((n) => n.value === next);
3738
- node?.ref.scrollIntoView({ block: "end", inline: "nearest", behavior: "smooth" });
3739
- };
3740
- return /* @__PURE__ */ jsxs("div", { className: "mt-2", children: [
3741
- /* @__PURE__ */ jsxs("div", { className: `flex relative ${layout === "vertical" ? "flex-col" : "flex-row items-center gap-2"}`, children: [
3742
- label && /* @__PURE__ */ jsx("label", { className: "text-md font-bold ml-1 max-content text-prussian-blue dark:text-white", children: label }),
3743
- /* @__PURE__ */ jsxs(
3744
- "div",
3745
- {
3746
- style,
3747
- ref: pickerRef,
3748
- className: "flex items-center justify-between relative h-9 bg-white rounded-lg p-2 cursor-pointer",
3749
- children: [
3750
- /* @__PURE__ */ jsx(
3751
- "div",
3752
- {
3753
- onClick: () => setExpanded((p) => !p),
3754
- className: `h-7 ${!style.width ? "min-w-[240px]" : ""} focus:outline-none text-prussian-blue cursor-pointer flex items-center gap-1`,
3755
- children: innerValues.includes(value) ? value : "N/A"
3756
- }
3757
- ),
3758
- /* @__PURE__ */ jsx("div", { onClick: () => setExpanded((p) => !p), className: `transition-all duration-300 ml-2 ${isExpanded ? "rotate-180" : "rotate-0 w-4 h-4"}`, children: /* @__PURE__ */ jsx(ChevronDown2, {}) })
3759
- ]
3760
- }
3761
- ),
3762
- /* @__PURE__ */ jsxs(
3763
- "div",
3764
- {
3765
- style: { width: style.width },
3766
- ref: calendarRef,
3767
- className: `${!style.width ? "w-[280px]" : ""} bg-ice absolute z-10 ${isCloseToBottom ? "bottom-[40px]" : "top-10"} rounded-lg shadow-md transition-all duration-150 right-0 overflow-hidden ${isExpanded ? "h-max scale-100" : "scale-0 pointer-events-none"}`,
3768
- children: [
3769
- /* @__PURE__ */ jsx("div", { onClick: () => navigate(-1), className: "flex items-center justify-center rotate-180 transition-all duration-300 hover:bg-ice-dark cursor-pointer rounded-br-lg rounded-bl-lg", children: /* @__PURE__ */ jsx(ChevronDown2, {}) }),
3770
- /* @__PURE__ */ jsx("div", { className: "h-8 overflow-hidden", children: innerValues.map((val) => /* @__PURE__ */ jsx(
3771
- "div",
3772
- {
3773
- ref: (ref) => {
3774
- if (!valueRefs.current.find((n) => n.value === val) && ref)
3775
- valueRefs.current.push({ value: val, ref });
3776
- },
3777
- className: "font-bold text-center text-lg",
3778
- children: val
3779
- },
3780
- val
3781
- )) }),
3782
- /* @__PURE__ */ jsx("div", { onClick: () => navigate(1), className: "flex items-center justify-center transition-all hover:bg-ice-dark cursor-pointer rounded-br-lg rounded-bl-lg", children: /* @__PURE__ */ jsx(ChevronDown2, {}) })
3783
- ]
3784
- }
3785
- )
3786
- ] }),
3787
- /* @__PURE__ */ jsx("div", { className: "text-center text-error dark:text-prussian-blue min-h-0", children: errorMessage })
3775
+ function CalendarIcon() {
3776
+ return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.75, className: "w-4 h-4 flex-shrink-0", "aria-hidden": "true", children: [
3777
+ /* @__PURE__ */ jsx("rect", { x: "3", y: "5", width: "18", height: "16", rx: "2" }),
3778
+ /* @__PURE__ */ jsx("path", { d: "M3 9h18M8 3v4M16 3v4", strokeLinecap: "round" })
3788
3779
  ] });
3789
3780
  }
3790
- var Temporal = {};
3791
- Temporal.DatePicker = DatePickerBase;
3792
- Temporal.TemporalPicker = TemporalPickerBase;
3793
- var DatePicker_default = Temporal;
3781
+ function ChevronLeft() {
3782
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "w-4 h-4", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15 19l-7-7 7-7" }) });
3783
+ }
3784
+ function ChevronRight3() {
3785
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "w-4 h-4", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 5l7 7-7 7" }) });
3786
+ }
3794
3787
 
3795
- export { AppShell, AutoComplete, Button, Catalog, CatalogCarousel, CatalogGrid, Checkbox, ContextMenu, Drawer, Dropdown, DropdownPill, FadingBase, FileInput, GridCard, icons_default as Icon, IconButton, List2 as List, LoadingSpinner, MenuBar, MenuBarItem, Modal, NotificationProvider, NumberInput, OpaqueGridCard, Password, Portal, ScalableContainer, SearchInput_default as SearchInput, Sidebar, SkeletonBox, SkeletonCard, SkeletonCircle, SkeletonText, Switch, Table, Tabs, DatePicker_default as Temporal, TextInput, ThemeProvider, ThemeSwitch, ToggleButton, Tooltip, TooltipProvider, TopBar, Tree, TreeSelect, Wizard, useNotification };
3788
+ export { AppShell, AutoComplete, Button, Catalog, CatalogCarousel, CatalogGrid, Checkbox, ContextMenu, Drawer, Dropdown, DropdownPill, FadingBase, FileInput, GridCard, icons_default as Icon, IconButton, List2 as List, LoadingSpinner, MenuBar, MenuBarItem, Modal, NotificationProvider, NumberInput, OpaqueGridCard, Password, Portal, ScalableContainer, SearchInput_default as SearchInput, Sidebar, SkeletonBox, SkeletonCard, SkeletonCircle, SkeletonText, Switch, Table, Tabs, DatePicker as Temporal, TextInput, ThemeProvider, ThemeSwitch, ToggleButton, Tooltip, TooltipProvider, TopBar, Tree, TreeSelect, Wizard, useNotification };
3796
3789
  //# sourceMappingURL=index.js.map
3797
3790
  //# sourceMappingURL=index.js.map