@geomak/ui 7.9.0 → 7.11.0

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
@@ -2,7 +2,7 @@
2
2
 
3
3
  var chunk4V4U2W7K_cjs = require('./chunk-4V4U2W7K.cjs');
4
4
  var chunkCNUDNGJM_cjs = require('./chunk-CNUDNGJM.cjs');
5
- var React34 = require('react');
5
+ var React36 = require('react');
6
6
  var reactDom = require('react-dom');
7
7
  var jsxRuntime = require('react/jsx-runtime');
8
8
  var AvatarPrimitive = require('@radix-ui/react-avatar');
@@ -41,7 +41,7 @@ function _interopNamespace(e) {
41
41
  return Object.freeze(n);
42
42
  }
43
43
 
44
- var React34__default = /*#__PURE__*/_interopDefault(React34);
44
+ var React36__default = /*#__PURE__*/_interopDefault(React36);
45
45
  var AvatarPrimitive__namespace = /*#__PURE__*/_interopNamespace(AvatarPrimitive);
46
46
  var DropdownMenu2__namespace = /*#__PURE__*/_interopNamespace(DropdownMenu2);
47
47
  var Dialog__namespace = /*#__PURE__*/_interopNamespace(Dialog);
@@ -67,8 +67,8 @@ function cx(...values) {
67
67
  return out;
68
68
  }
69
69
  function Portal({ children, target }) {
70
- const [resolved, setResolved] = React34.useState(null);
71
- React34.useEffect(() => {
70
+ const [resolved, setResolved] = React36.useState(null);
71
+ React36.useEffect(() => {
72
72
  if (target === null) {
73
73
  setResolved(null);
74
74
  return;
@@ -489,7 +489,7 @@ function Typography({
489
489
  }
490
490
  );
491
491
  }
492
- var IconButton = React34__default.default.forwardRef(function IconButton2({
492
+ var IconButton = React36__default.default.forwardRef(function IconButton2({
493
493
  icon,
494
494
  onClick,
495
495
  type = "primary",
@@ -502,7 +502,7 @@ var IconButton = React34__default.default.forwardRef(function IconButton2({
502
502
  className = "",
503
503
  style
504
504
  }, ref) {
505
- const colorScheme = React34.useMemo(() => {
505
+ const colorScheme = React36.useMemo(() => {
506
506
  if (type === "primary") {
507
507
  return "bg-accent text-accent-fg hover:bg-accent-hover";
508
508
  }
@@ -598,7 +598,7 @@ var SIZE_CLASSES = {
598
598
  md: "h-9 px-4 text-sm gap-1.5 rounded-lg",
599
599
  lg: "h-11 px-5 text-sm gap-2 rounded-xl"
600
600
  };
601
- var Button = React34__default.default.forwardRef(function Button2({
601
+ var Button = React36__default.default.forwardRef(function Button2({
602
602
  content,
603
603
  variant = "primary",
604
604
  size = "md",
@@ -706,7 +706,7 @@ function MenuButton({
706
706
  "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
707
707
  "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95"
708
708
  ].join(" "),
709
- children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(React34__default.default.Fragment, { children: [
709
+ children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(React36__default.default.Fragment, { children: [
710
710
  item.separatorBefore && /* @__PURE__ */ jsxRuntime.jsx(DropdownMenu2__namespace.Separator, { className: "my-1 h-px bg-border" }),
711
711
  /* @__PURE__ */ jsxRuntime.jsxs(
712
712
  DropdownMenu2__namespace.Item,
@@ -729,6 +729,10 @@ function MenuButton({
729
729
  ) })
730
730
  ] });
731
731
  }
732
+ var DialogContainerContext = React36.createContext(null);
733
+ function useDialogContainer() {
734
+ return React36.useContext(DialogContainerContext);
735
+ }
732
736
  var SIZE_MAP = {
733
737
  sm: 400,
734
738
  md: 600,
@@ -753,6 +757,7 @@ function Modal({
753
757
  className = ""
754
758
  }) {
755
759
  const reduced = framerMotion.useReducedMotion();
760
+ const [panelEl, setPanelEl] = React36.useState(null);
756
761
  const maxWidth = width ?? SIZE_MAP[size];
757
762
  return /* @__PURE__ */ jsxRuntime.jsx(Dialog__namespace.Root, { open, onOpenChange: (next) => {
758
763
  if (!next) onClose?.();
@@ -770,6 +775,7 @@ function Modal({
770
775
  /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: open && /* @__PURE__ */ jsxRuntime.jsx(Dialog__namespace.Content, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
771
776
  framerMotion.motion.div,
772
777
  {
778
+ ref: setPanelEl,
773
779
  className: `fixed left-1/2 top-1/2 z-modal flex flex-col w-[calc(100%-2rem)] max-h-[90dvh] bg-surface rounded-2xl shadow-xl overflow-hidden focus:outline-none ${className}`.trim(),
774
780
  style: {
775
781
  maxWidth,
@@ -797,7 +803,7 @@ function Modal({
797
803
  }
798
804
  ) })
799
805
  ] }),
800
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex-1 overflow-y-auto p-5 ${hasFooter ? "" : "pb-5"}`, children }),
806
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex-1 overflow-y-auto p-5 ${hasFooter ? "" : "pb-5"}`, children: /* @__PURE__ */ jsxRuntime.jsx(DialogContainerContext.Provider, { value: panelEl, children }) }),
801
807
  hasFooter && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-shrink-0 items-center justify-end gap-3 border-t border-border px-5 py-3", children: [
802
808
  /* @__PURE__ */ jsxRuntime.jsx(
803
809
  Button_default,
@@ -848,6 +854,7 @@ function Drawer({
848
854
  className = ""
849
855
  }) {
850
856
  const reduced = framerMotion.useReducedMotion();
857
+ const [panelEl, setPanelEl] = React36.useState(null);
851
858
  const isRight = placement === "right";
852
859
  const hiddenX = isRight ? "100%" : "-100%";
853
860
  const resolvedWidth = width ?? SIZE_MAP2[size];
@@ -868,6 +875,7 @@ function Drawer({
868
875
  /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: open && /* @__PURE__ */ jsxRuntime.jsx(Dialog__namespace.Content, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
869
876
  framerMotion.motion.div,
870
877
  {
878
+ ref: setPanelEl,
871
879
  className: `fixed top-0 bottom-0 ${isRight ? "right-0" : "left-0"} z-modal flex flex-col bg-surface shadow-xl focus:outline-none ${className}`.trim(),
872
880
  style: { width: `min(calc(100vw - 1rem), ${widthCss})` },
873
881
  initial: { x: reduced ? 0 : hiddenX, opacity: reduced ? 0 : 1 },
@@ -894,7 +902,7 @@ function Drawer({
894
902
  }
895
903
  ) })
896
904
  ] }),
897
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-y-auto p-5", children }),
905
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-y-auto p-5", children: /* @__PURE__ */ jsxRuntime.jsx(DialogContainerContext.Provider, { value: panelEl, children }) }),
898
906
  hasFooter && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex flex-shrink-0 items-center gap-3 border-t border-border px-5 py-3 ${isRight ? "justify-start" : "justify-end"}`, children: [
899
907
  /* @__PURE__ */ jsxRuntime.jsx(Button_default, { style: { width: 90 }, variant: cancelVariant, content: cancelText, onClick: onCancel }),
900
908
  /* @__PURE__ */ jsxRuntime.jsx(Button_default, { style: { width: 90 }, variant: okVariant, content: okText, onClick: onOk })
@@ -955,9 +963,9 @@ function Tooltip({
955
963
  ] }) });
956
964
  }
957
965
  var TooltipProvider = TooltipPrimitive__namespace.Provider;
958
- var TabsContext = React34.createContext(null);
966
+ var TabsContext = React36.createContext(null);
959
967
  function useTabsContext() {
960
- const ctx = React34.useContext(TabsContext);
968
+ const ctx = React36.useContext(TabsContext);
961
969
  if (!ctx) throw new Error("Tabs.List / Tabs.Trigger / Tabs.Panel must be rendered inside <Tabs>.");
962
970
  return ctx;
963
971
  }
@@ -979,26 +987,26 @@ function Tabs({
979
987
  children
980
988
  }) {
981
989
  const isControlled = value !== void 0;
982
- const [internal, setInternal] = React34.useState(defaultValue);
990
+ const [internal, setInternal] = React36.useState(defaultValue);
983
991
  const current = isControlled ? value : internal;
984
992
  const reduced = !!framerMotion.useReducedMotion();
985
- const indicatorId = React34.useId();
986
- const select = React34.useCallback((next) => {
993
+ const indicatorId = React36.useId();
994
+ const select = React36.useCallback((next) => {
987
995
  if (!isControlled) setInternal(next);
988
996
  onChange?.(next);
989
997
  }, [isControlled, onChange]);
990
- const registry = React34.useRef(/* @__PURE__ */ new Map());
991
- const orderRef = React34.useRef(0);
992
- const [, bump] = React34.useState(0);
993
- const registerTab = React34.useCallback((val, meta) => {
998
+ const registry = React36.useRef(/* @__PURE__ */ new Map());
999
+ const orderRef = React36.useRef(0);
1000
+ const [, bump] = React36.useState(0);
1001
+ const registerTab = React36.useCallback((val, meta) => {
994
1002
  const existing = registry.current.get(val);
995
1003
  registry.current.set(val, { ...meta, order: existing?.order ?? orderRef.current++ });
996
1004
  if (!existing) bump((v) => v + 1);
997
1005
  }, []);
998
- const unregisterTab = React34.useCallback((val) => {
1006
+ const unregisterTab = React36.useCallback((val) => {
999
1007
  if (registry.current.delete(val)) bump((v) => v + 1);
1000
1008
  }, []);
1001
- const getTabs = React34.useCallback(() => [...registry.current.entries()].sort((a, b) => a[1].order - b[1].order).map(([val, m]) => ({ value: val, label: m.label, icon: m.icon, disabled: m.disabled })), []);
1009
+ const getTabs = React36.useCallback(() => [...registry.current.entries()].sort((a, b) => a[1].order - b[1].order).map(([val, m]) => ({ value: val, label: m.label, icon: m.icon, disabled: m.disabled })), []);
1002
1010
  return /* @__PURE__ */ jsxRuntime.jsx(TabsContext.Provider, { value: { value: current, variant, size, orientation, indicatorId, reduced, select, registerTab, unregisterTab, getTabs }, children: /* @__PURE__ */ jsxRuntime.jsx(
1003
1011
  TabsPrimitive__namespace.Root,
1004
1012
  {
@@ -1018,10 +1026,10 @@ function Tabs({
1018
1026
  function TabsList({ children, "aria-label": ariaLabel, className = "" }) {
1019
1027
  const { variant, orientation, reduced, value } = useTabsContext();
1020
1028
  const horizontal = orientation === "horizontal";
1021
- const scrollRef = React34.useRef(null);
1022
- const [edges, setEdges] = React34.useState({ start: false, end: false });
1029
+ const scrollRef = React36.useRef(null);
1030
+ const [edges, setEdges] = React36.useState({ start: false, end: false });
1023
1031
  const scrollable = variant !== "segmented";
1024
- React34.useLayoutEffect(() => {
1032
+ React36.useLayoutEffect(() => {
1025
1033
  const el = scrollRef.current;
1026
1034
  if (!el || !scrollable) return;
1027
1035
  const update = () => {
@@ -1046,13 +1054,13 @@ function TabsList({ children, "aria-label": ariaLabel, className = "" }) {
1046
1054
  ro.disconnect();
1047
1055
  };
1048
1056
  }, [horizontal, scrollable, children]);
1049
- const nudge = React34.useCallback((dir) => {
1057
+ const nudge = React36.useCallback((dir) => {
1050
1058
  const el = scrollRef.current;
1051
1059
  if (!el) return;
1052
1060
  const amount = (horizontal ? el.clientWidth : el.clientHeight) * 0.7 * dir;
1053
1061
  el.scrollBy({ [horizontal ? "left" : "top"]: amount, behavior: reduced ? "auto" : "smooth" });
1054
1062
  }, [horizontal, reduced]);
1055
- React34.useLayoutEffect(() => {
1063
+ React36.useLayoutEffect(() => {
1056
1064
  const el = scrollRef.current;
1057
1065
  if (!el || !scrollable) return;
1058
1066
  const active = el.querySelector("[role=tab][data-state=active]");
@@ -1110,9 +1118,9 @@ function Chevron2({ side, orientation, onClick }) {
1110
1118
  function OverflowMenu() {
1111
1119
  const { getTabs, value, select, orientation } = useTabsContext();
1112
1120
  const horizontal = orientation === "horizontal";
1113
- const [open, setOpen] = React34.useState(false);
1114
- const wrapRef = React34.useRef(null);
1115
- const timer = React34.useRef(null);
1121
+ const [open, setOpen] = React36.useState(false);
1122
+ const wrapRef = React36.useRef(null);
1123
+ const timer = React36.useRef(null);
1116
1124
  const openNow = () => {
1117
1125
  if (timer.current) clearTimeout(timer.current);
1118
1126
  setOpen(true);
@@ -1120,7 +1128,7 @@ function OverflowMenu() {
1120
1128
  const closeSoon = () => {
1121
1129
  timer.current = setTimeout(() => setOpen(false), 160);
1122
1130
  };
1123
- React34.useLayoutEffect(() => {
1131
+ React36.useLayoutEffect(() => {
1124
1132
  if (!open) return;
1125
1133
  const onDoc = (e) => {
1126
1134
  if (wrapRef.current && !wrapRef.current.contains(e.target)) setOpen(false);
@@ -1201,7 +1209,7 @@ function TabsTrigger({ value, icon, badge, closeable, onClose, disabled, classNa
1201
1209
  const isActive = active === value;
1202
1210
  const horizontal = orientation === "horizontal";
1203
1211
  const sz = SIZE[size];
1204
- React34.useLayoutEffect(() => {
1212
+ React36.useLayoutEffect(() => {
1205
1213
  registerTab(value, { label: children, icon, disabled });
1206
1214
  return () => unregisterTab(value);
1207
1215
  }, [value, children, icon, disabled, registerTab, unregisterTab]);
@@ -1400,7 +1408,7 @@ function Tree({
1400
1408
  item.key
1401
1409
  )) });
1402
1410
  }
1403
- var AccordionCtx = React34.createContext({ variant: "separated" });
1411
+ var AccordionCtx = React36.createContext({ variant: "separated" });
1404
1412
  function Accordion2({
1405
1413
  children,
1406
1414
  type = "single",
@@ -1459,7 +1467,7 @@ var Chevron3 = /* @__PURE__ */ jsxRuntime.jsx(
1459
1467
  }
1460
1468
  );
1461
1469
  function AccordionItem({ value, title, icon, children, disabled, className = "" }) {
1462
- const { variant } = React34.useContext(AccordionCtx);
1470
+ const { variant } = React36.useContext(AccordionCtx);
1463
1471
  return /* @__PURE__ */ jsxRuntime.jsxs(
1464
1472
  AccordionPrimitive__namespace.Item,
1465
1473
  {
@@ -1518,7 +1526,7 @@ function Breadcrumbs({
1518
1526
  className = "",
1519
1527
  style
1520
1528
  }) {
1521
- const [expanded, setExpanded] = React34.useState(false);
1529
+ const [expanded, setExpanded] = React36.useState(false);
1522
1530
  const shouldCollapse = maxItems > 0 && items.length > maxItems && !expanded;
1523
1531
  const visible = [];
1524
1532
  if (shouldCollapse) {
@@ -1743,8 +1751,8 @@ function Stepper({
1743
1751
  className = ""
1744
1752
  }) {
1745
1753
  const reduced = framerMotion.useReducedMotion();
1746
- const [forcedVertical, setForcedVertical] = React34.useState(false);
1747
- React34.useEffect(() => {
1754
+ const [forcedVertical, setForcedVertical] = React36.useState(false);
1755
+ React36.useEffect(() => {
1748
1756
  if (!responsive || orientation === "vertical") return;
1749
1757
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
1750
1758
  const mq = window.matchMedia("(max-width: 767px)");
@@ -1853,7 +1861,7 @@ function Kbd({
1853
1861
  style
1854
1862
  }) {
1855
1863
  if (keys && keys.length > 0) {
1856
- return /* @__PURE__ */ jsxRuntime.jsx("span", { className: cx("inline-flex items-center gap-1", className), style, children: keys.map((k, i) => /* @__PURE__ */ jsxRuntime.jsxs(React34__default.default.Fragment, { children: [
1864
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: cx("inline-flex items-center gap-1", className), style, children: keys.map((k, i) => /* @__PURE__ */ jsxRuntime.jsxs(React36__default.default.Fragment, { children: [
1857
1865
  i > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground-muted text-xs select-none", children: separator }),
1858
1866
  /* @__PURE__ */ jsxRuntime.jsx("kbd", { className: [cap, SIZE3[size]].join(" "), children: k })
1859
1867
  ] }, `${k}-${i}`)) });
@@ -1944,13 +1952,13 @@ function FlatCarousel({
1944
1952
  className = "",
1945
1953
  style
1946
1954
  }) {
1947
- const scrollerRef = React34.useRef(null);
1948
- const slides = React34__default.default.Children.toArray(children);
1949
- const [active, setActive] = React34.useState(0);
1950
- const [atStart, setAtStart] = React34.useState(true);
1951
- const [atEnd, setAtEnd] = React34.useState(false);
1955
+ const scrollerRef = React36.useRef(null);
1956
+ const slides = React36__default.default.Children.toArray(children);
1957
+ const [active, setActive] = React36.useState(0);
1958
+ const [atStart, setAtStart] = React36.useState(true);
1959
+ const [atEnd, setAtEnd] = React36.useState(false);
1952
1960
  const width = typeof itemWidth === "number" ? `${itemWidth}px` : itemWidth;
1953
- const update = React34.useCallback(() => {
1961
+ const update = React36.useCallback(() => {
1954
1962
  const el = scrollerRef.current;
1955
1963
  if (!el) return;
1956
1964
  setAtStart(el.scrollLeft <= 1);
@@ -1959,7 +1967,7 @@ function FlatCarousel({
1959
1967
  const slideW = first ? first.getBoundingClientRect().width + gap : el.clientWidth;
1960
1968
  setActive(Math.round(el.scrollLeft / slideW));
1961
1969
  }, [gap]);
1962
- React34.useEffect(() => {
1970
+ React36.useEffect(() => {
1963
1971
  update();
1964
1972
  const el = scrollerRef.current;
1965
1973
  if (!el) return;
@@ -2000,9 +2008,9 @@ function RotatingCarousel({
2000
2008
  className = "",
2001
2009
  style
2002
2010
  }) {
2003
- const slides = React34__default.default.Children.toArray(children);
2011
+ const slides = React36__default.default.Children.toArray(children);
2004
2012
  const count = slides.length;
2005
- const [active, setActive] = React34.useState(0);
2013
+ const [active, setActive] = React36.useState(0);
2006
2014
  const reduced = framerMotion.useReducedMotion();
2007
2015
  const wrap = (n) => count > 0 ? (n % count + count) % count : 0;
2008
2016
  const idx = wrap(active);
@@ -2240,13 +2248,13 @@ function Chat({
2240
2248
  className = "",
2241
2249
  style
2242
2250
  }) {
2243
- const listRef = React34.useRef(null);
2244
- const atBottomRef = React34.useRef(true);
2245
- const [showJump, setShowJump] = React34.useState(false);
2246
- const [draft, setDraft] = React34.useState("");
2251
+ const listRef = React36.useRef(null);
2252
+ const atBottomRef = React36.useRef(true);
2253
+ const [showJump, setShowJump] = React36.useState(false);
2254
+ const [draft, setDraft] = React36.useState("");
2247
2255
  const hasHeader = title != null || subtitle != null || avatar != null || headerActions != null;
2248
2256
  const isTyping = typingNames.length > 0;
2249
- const scrollToBottom = React34.useCallback((smooth = true) => {
2257
+ const scrollToBottom = React36.useCallback((smooth = true) => {
2250
2258
  const el = listRef.current;
2251
2259
  if (!el) return;
2252
2260
  if (typeof el.scrollTo === "function") el.scrollTo({ top: el.scrollHeight, behavior: smooth ? "smooth" : "auto" });
@@ -2259,10 +2267,10 @@ function Chat({
2259
2267
  atBottomRef.current = near;
2260
2268
  setShowJump(!near);
2261
2269
  };
2262
- React34.useEffect(() => {
2270
+ React36.useEffect(() => {
2263
2271
  if (atBottomRef.current) scrollToBottom(messages.length > 0);
2264
2272
  }, [messages.length, isTyping]);
2265
- React34.useEffect(() => {
2273
+ React36.useEffect(() => {
2266
2274
  scrollToBottom(false);
2267
2275
  }, [scrollToBottom]);
2268
2276
  const send = () => {
@@ -2452,7 +2460,7 @@ function FAB({
2452
2460
  className = "",
2453
2461
  style
2454
2462
  }) {
2455
- const [open, setOpen] = React34.useState(false);
2463
+ const [open, setOpen] = React36.useState(false);
2456
2464
  const reduced = framerMotion.useReducedMotion();
2457
2465
  const hasDial = !!actions && actions.length > 0;
2458
2466
  const bottom = position.startsWith("bottom");
@@ -2554,8 +2562,8 @@ function PopConfirm({
2554
2562
  onOpenChange,
2555
2563
  className = ""
2556
2564
  }) {
2557
- const [uncontrolledOpen, setUncontrolledOpen] = React34.useState(false);
2558
- const [loading, setLoading] = React34.useState(false);
2565
+ const [uncontrolledOpen, setUncontrolledOpen] = React36.useState(false);
2566
+ const [loading, setLoading] = React36.useState(false);
2559
2567
  const isOpen = open ?? uncontrolledOpen;
2560
2568
  const setOpen = (next) => {
2561
2569
  onOpenChange?.(next);
@@ -2658,16 +2666,16 @@ function LogoutTimer({
2658
2666
  logoutLabel = "Sign out now"
2659
2667
  }) {
2660
2668
  const reduced = framerMotion.useReducedMotion();
2661
- const [warning, setWarning] = React34.useState(false);
2662
- const [remaining, setRemaining] = React34.useState(countdown);
2663
- const idleTimer = React34.useRef(null);
2664
- const tick = React34.useRef(null);
2665
- const deadline = React34.useRef(0);
2666
- const warningRef = React34.useRef(false);
2667
- const lastReset = React34.useRef(0);
2668
- const cbs = React34.useRef({ onLogout, onContinue, onWarning });
2669
+ const [warning, setWarning] = React36.useState(false);
2670
+ const [remaining, setRemaining] = React36.useState(countdown);
2671
+ const idleTimer = React36.useRef(null);
2672
+ const tick = React36.useRef(null);
2673
+ const deadline = React36.useRef(0);
2674
+ const warningRef = React36.useRef(false);
2675
+ const lastReset = React36.useRef(0);
2676
+ const cbs = React36.useRef({ onLogout, onContinue, onWarning });
2669
2677
  cbs.current = { onLogout, onContinue, onWarning };
2670
- const clearTimers = React34.useCallback(() => {
2678
+ const clearTimers = React36.useCallback(() => {
2671
2679
  if (idleTimer.current) {
2672
2680
  clearTimeout(idleTimer.current);
2673
2681
  idleTimer.current = null;
@@ -2677,13 +2685,13 @@ function LogoutTimer({
2677
2685
  tick.current = null;
2678
2686
  }
2679
2687
  }, []);
2680
- const logout = React34.useCallback(() => {
2688
+ const logout = React36.useCallback(() => {
2681
2689
  clearTimers();
2682
2690
  warningRef.current = false;
2683
2691
  setWarning(false);
2684
2692
  cbs.current.onLogout();
2685
2693
  }, [clearTimers]);
2686
- const startIdle = React34.useCallback(() => {
2694
+ const startIdle = React36.useCallback(() => {
2687
2695
  if (idleTimer.current) clearTimeout(idleTimer.current);
2688
2696
  idleTimer.current = setTimeout(() => {
2689
2697
  warningRef.current = true;
@@ -2698,7 +2706,7 @@ function LogoutTimer({
2698
2706
  }, 250);
2699
2707
  }, timeout);
2700
2708
  }, [timeout, countdown, logout]);
2701
- const stay = React34.useCallback(() => {
2709
+ const stay = React36.useCallback(() => {
2702
2710
  if (tick.current) {
2703
2711
  clearInterval(tick.current);
2704
2712
  tick.current = null;
@@ -2708,7 +2716,7 @@ function LogoutTimer({
2708
2716
  cbs.current.onContinue?.();
2709
2717
  startIdle();
2710
2718
  }, [startIdle]);
2711
- React34.useEffect(() => {
2719
+ React36.useEffect(() => {
2712
2720
  if (!enabled) {
2713
2721
  clearTimers();
2714
2722
  warningRef.current = false;
@@ -2773,11 +2781,11 @@ function SegmentedControl({
2773
2781
  "aria-label": ariaLabel
2774
2782
  }) {
2775
2783
  const sz = SIZE5[size];
2776
- const groupId = React34.useId();
2777
- const errorId = React34.useId();
2784
+ const groupId = React36.useId();
2785
+ const errorId = React36.useId();
2778
2786
  const hasError = errorMessage != null;
2779
2787
  const isControlled = value !== void 0;
2780
- const [internal, setInternal] = React34.useState(defaultValue);
2788
+ const [internal, setInternal] = React36.useState(defaultValue);
2781
2789
  const current = isControlled ? value : internal;
2782
2790
  const handle = (v) => {
2783
2791
  if (!v) return;
@@ -2938,22 +2946,22 @@ function Scheduler({
2938
2946
  style
2939
2947
  }) {
2940
2948
  const reduced = framerMotion.useReducedMotion();
2941
- const [view, setView] = React34.useState(defaultView);
2942
- const [cursor, setCursor] = React34.useState(() => defaultDate ?? /* @__PURE__ */ new Date());
2943
- const [loaded, setLoaded] = React34.useState([]);
2944
- const [loading, setLoading] = React34.useState(false);
2945
- const [error, setError] = React34.useState(null);
2946
- const [reloadKey, setReloadKey] = React34.useState(0);
2947
- const [dir, setDir] = React34.useState(0);
2948
- const cbRef = React34.useRef({ loadEvents, onError });
2949
+ const [view, setView] = React36.useState(defaultView);
2950
+ const [cursor, setCursor] = React36.useState(() => defaultDate ?? /* @__PURE__ */ new Date());
2951
+ const [loaded, setLoaded] = React36.useState([]);
2952
+ const [loading, setLoading] = React36.useState(false);
2953
+ const [error, setError] = React36.useState(null);
2954
+ const [reloadKey, setReloadKey] = React36.useState(0);
2955
+ const [dir, setDir] = React36.useState(0);
2956
+ const cbRef = React36.useRef({ loadEvents, onError });
2949
2957
  cbRef.current = { loadEvents, onError };
2950
- const range = React34.useMemo(
2958
+ const range = React36.useMemo(
2951
2959
  () => view === "month" ? monthRange(cursor) : weekRange(cursor, weekStartsOn),
2952
2960
  [view, cursor, weekStartsOn]
2953
2961
  );
2954
2962
  const fromKey = range.from.getTime();
2955
2963
  const toKey = range.to.getTime();
2956
- React34.useEffect(() => {
2964
+ React36.useEffect(() => {
2957
2965
  const { loadEvents: loader, onError: onErr } = cbRef.current;
2958
2966
  if (!loader) return;
2959
2967
  let cancelled = false;
@@ -2973,16 +2981,16 @@ function Scheduler({
2973
2981
  cancelled = true;
2974
2982
  };
2975
2983
  }, [fromKey, toKey, view, reloadKey]);
2976
- const retry = React34.useCallback(() => setReloadKey((k) => k + 1), []);
2977
- const events = React34.useMemo(
2984
+ const retry = React36.useCallback(() => setReloadKey((k) => k + 1), []);
2985
+ const events = React36.useMemo(
2978
2986
  () => (controlledEvents ?? loaded).map(normalize),
2979
2987
  [controlledEvents, loaded]
2980
2988
  );
2981
- const go = React34.useCallback((delta) => {
2989
+ const go = React36.useCallback((delta) => {
2982
2990
  setDir(delta);
2983
2991
  setCursor((c) => view === "month" ? addMonths(c, delta) : addDays(c, delta * 7));
2984
2992
  }, [view]);
2985
- const goToday = React34.useCallback(() => {
2993
+ const goToday = React36.useCallback(() => {
2986
2994
  setDir(0);
2987
2995
  setCursor(/* @__PURE__ */ new Date());
2988
2996
  }, []);
@@ -3092,9 +3100,9 @@ function SchedulerError({ onRetry }) {
3092
3100
  ] });
3093
3101
  }
3094
3102
  function MonthYearPicker({ label, cursor, onPick }) {
3095
- const [open, setOpen] = React34.useState(false);
3096
- const [viewYear, setViewYear] = React34.useState(cursor.getFullYear());
3097
- React34.useEffect(() => {
3103
+ const [open, setOpen] = React36.useState(false);
3104
+ const [viewYear, setViewYear] = React36.useState(cursor.getFullYear());
3105
+ React36.useEffect(() => {
3098
3106
  if (open) setViewYear(cursor.getFullYear());
3099
3107
  }, [open, cursor]);
3100
3108
  return /* @__PURE__ */ jsxRuntime.jsxs(Popover__namespace.Root, { open, onOpenChange: setOpen, children: [
@@ -3168,8 +3176,8 @@ function MonthView({
3168
3176
  onSelectSlot,
3169
3177
  onSelectEvent
3170
3178
  }) {
3171
- const grid = React34.useMemo(() => buildMonthGrid(cursor, weekStartsOn), [cursor, weekStartsOn]);
3172
- const eventsByDay = React34.useMemo(() => bucketByDay(events), [events]);
3179
+ const grid = React36.useMemo(() => buildMonthGrid(cursor, weekStartsOn), [cursor, weekStartsOn]);
3180
+ const eventsByDay = React36.useMemo(() => bucketByDay(events), [events]);
3173
3181
  const labels = weekdayLabels(weekStartsOn);
3174
3182
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full flex-col", children: [
3175
3183
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-7 border-b border-border", children: labels.map((l) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2 py-1.5 text-center text-[11px] font-medium uppercase tracking-wide text-foreground-muted", children: l }, l)) }),
@@ -3243,12 +3251,12 @@ function WeekView({
3243
3251
  onSelectSlot,
3244
3252
  onSelectEvent
3245
3253
  }) {
3246
- const days = React34.useMemo(() => getWeekDays(cursor, weekStartsOn), [cursor, weekStartsOn]);
3247
- const eventsByDay = React34.useMemo(() => bucketByDay(events), [events]);
3248
- const labels = React34.useMemo(() => weekdayLabels(weekStartsOn), [weekStartsOn]);
3254
+ const days = React36.useMemo(() => getWeekDays(cursor, weekStartsOn), [cursor, weekStartsOn]);
3255
+ const eventsByDay = React36.useMemo(() => bucketByDay(events), [events]);
3256
+ const labels = React36.useMemo(() => weekdayLabels(weekStartsOn), [weekStartsOn]);
3249
3257
  const dow = (d) => labels[(d.getDay() - weekStartsOn + 7) % 7];
3250
3258
  const [startHour, endHour] = dayHours;
3251
- const hours = React34.useMemo(
3259
+ const hours = React36.useMemo(
3252
3260
  () => Array.from({ length: endHour - startHour }, (_, i) => startHour + i),
3253
3261
  [startHour, endHour]
3254
3262
  );
@@ -3439,17 +3447,17 @@ function Cart({
3439
3447
  ] })
3440
3448
  ] });
3441
3449
  }
3442
- var CartContext = React34.createContext(null);
3450
+ var CartContext = React36.createContext(null);
3443
3451
  var clampQty = (qty, max) => {
3444
3452
  const lower = Math.max(1, Math.round(qty));
3445
3453
  return max != null ? Math.min(lower, max) : lower;
3446
3454
  };
3447
3455
  function CartProvider({ children, initialItems = [], onChange }) {
3448
- const [items, setItems] = React34.useState(initialItems);
3449
- React34.useEffect(() => {
3456
+ const [items, setItems] = React36.useState(initialItems);
3457
+ React36.useEffect(() => {
3450
3458
  onChange?.(items);
3451
3459
  }, [items]);
3452
- const addToCart = React34.useCallback((item, quantity) => {
3460
+ const addToCart = React36.useCallback((item, quantity) => {
3453
3461
  const addQty = quantity ?? item.quantity ?? 1;
3454
3462
  setItems((prev) => {
3455
3463
  const existing = prev.find((it) => it.id === item.id);
@@ -3462,29 +3470,29 @@ function CartProvider({ children, initialItems = [], onChange }) {
3462
3470
  return [...prev, { ...rest, quantity: clampQty(addQty, item.max) }];
3463
3471
  });
3464
3472
  }, []);
3465
- const removeFromCart = React34.useCallback((id) => {
3473
+ const removeFromCart = React36.useCallback((id) => {
3466
3474
  setItems((prev) => prev.filter((it) => it.id !== id));
3467
3475
  }, []);
3468
- const updateQuantity = React34.useCallback((id, quantity) => {
3476
+ const updateQuantity = React36.useCallback((id, quantity) => {
3469
3477
  setItems(
3470
3478
  (prev) => prev.map((it) => it.id === id ? { ...it, quantity: clampQty(quantity, it.max) } : it)
3471
3479
  );
3472
3480
  }, []);
3473
- const clearCart = React34.useCallback(() => setItems([]), []);
3474
- const isInCart = React34.useCallback((id) => items.some((it) => it.id === id), [items]);
3475
- const getItemCount = React34.useCallback(() => items.reduce((sum, it) => sum + it.quantity, 0), [items]);
3476
- const getCartTotal = React34.useCallback(
3481
+ const clearCart = React36.useCallback(() => setItems([]), []);
3482
+ const isInCart = React36.useCallback((id) => items.some((it) => it.id === id), [items]);
3483
+ const getItemCount = React36.useCallback(() => items.reduce((sum, it) => sum + it.quantity, 0), [items]);
3484
+ const getCartTotal = React36.useCallback(
3477
3485
  () => items.reduce((sum, it) => sum + it.price * it.quantity, 0),
3478
3486
  [items]
3479
3487
  );
3480
- const value = React34.useMemo(
3488
+ const value = React36.useMemo(
3481
3489
  () => ({ items, addToCart, removeFromCart, updateQuantity, clearCart, isInCart, getItemCount, getCartTotal }),
3482
3490
  [items, addToCart, removeFromCart, updateQuantity, clearCart, isInCart, getItemCount, getCartTotal]
3483
3491
  );
3484
3492
  return /* @__PURE__ */ jsxRuntime.jsx(CartContext.Provider, { value, children });
3485
3493
  }
3486
3494
  function useCart() {
3487
- const ctx = React34.useContext(CartContext);
3495
+ const ctx = React36.useContext(CartContext);
3488
3496
  if (!ctx) {
3489
3497
  throw new Error("useCart must be used within a <CartProvider>.");
3490
3498
  }
@@ -3826,11 +3834,11 @@ function buildBindings(store, name, kind, snap) {
3826
3834
 
3827
3835
  // src/form/useForm.ts
3828
3836
  function useForm(options = {}) {
3829
- const ref = React34.useRef(null);
3837
+ const ref = React36.useRef(null);
3830
3838
  if (ref.current === null) ref.current = new FormStore(options);
3831
3839
  const store = ref.current;
3832
- React34.useSyncExternalStore(store.subscribe, store.getRootSnapshot, store.getRootSnapshot);
3833
- const make = React34.useCallback(
3840
+ React36.useSyncExternalStore(store.subscribe, store.getRootSnapshot, store.getRootSnapshot);
3841
+ const make = React36.useCallback(
3834
3842
  (kind) => (name, rules) => {
3835
3843
  if (rules !== void 0) store.setRule(name, rules);
3836
3844
  return buildBindings(store, name, kind, store.getFieldSnapshot(name));
@@ -3860,9 +3868,9 @@ function useForm(options = {}) {
3860
3868
  fieldTarget: make("target")
3861
3869
  };
3862
3870
  }
3863
- var FormContext = React34.createContext(null);
3871
+ var FormContext = React36.createContext(null);
3864
3872
  function useFormStore() {
3865
- const store = React34.useContext(FormContext);
3873
+ const store = React36.useContext(FormContext);
3866
3874
  if (!store) {
3867
3875
  throw new Error("useFormStore must be used within a <Form>. Did you forget to wrap your fields?");
3868
3876
  }
@@ -3876,8 +3884,8 @@ function Form({
3876
3884
  children,
3877
3885
  ...rest
3878
3886
  }) {
3879
- const ref = React34.useRef(null);
3880
- const bypass = React34.useRef(false);
3887
+ const ref = React36.useRef(null);
3888
+ const bypass = React36.useRef(false);
3881
3889
  const handleSubmit = async (e) => {
3882
3890
  if (bypass.current) {
3883
3891
  bypass.current = false;
@@ -3934,12 +3942,12 @@ function useFormField(name, options = {}) {
3934
3942
  const store = useFormStore();
3935
3943
  const { kind = "value", rules } = options;
3936
3944
  if (rules !== void 0 && store.getRule(name) !== rules) store.setRule(name, rules);
3937
- React34.useEffect(() => {
3945
+ React36.useEffect(() => {
3938
3946
  return () => {
3939
3947
  if (rules !== void 0) store.removeRule(name);
3940
3948
  };
3941
3949
  }, [store, name]);
3942
- const snap = React34.useSyncExternalStore(
3950
+ const snap = React36.useSyncExternalStore(
3943
3951
  store.subscribe,
3944
3952
  () => store.getFieldSnapshot(name)
3945
3953
  );
@@ -3951,7 +3959,7 @@ function FormField({ name, kind, rules, children }) {
3951
3959
  }
3952
3960
  function useFieldArray(name) {
3953
3961
  const store = useFormStore();
3954
- React34.useSyncExternalStore(store.subscribe, store.getRootSnapshot, store.getRootSnapshot);
3962
+ React36.useSyncExternalStore(store.subscribe, store.getRootSnapshot, store.getRootSnapshot);
3955
3963
  const arr = store.getValue(name) ?? [];
3956
3964
  const keys = store.getKeys(name);
3957
3965
  return {
@@ -3984,7 +3992,7 @@ function TextInput({
3984
3992
  suffix,
3985
3993
  id
3986
3994
  }) {
3987
- const errorId = React34.useId();
3995
+ const errorId = React36.useId();
3988
3996
  const hasError = errorMessage != null;
3989
3997
  const hasAdornment = prefix != null || suffix != null;
3990
3998
  const inputId = htmlFor ?? id;
@@ -4145,7 +4153,7 @@ function CreditCardForm({
4145
4153
  className = "",
4146
4154
  style
4147
4155
  }) {
4148
- const initial = React34.useRef({
4156
+ const initial = React36.useRef({
4149
4157
  number: formatCardNumber(defaultValue?.number ?? ""),
4150
4158
  name: defaultValue?.name ?? "",
4151
4159
  expiry: formatExpiry(defaultValue?.expiry ?? ""),
@@ -4154,7 +4162,7 @@ function CreditCardForm({
4154
4162
  const form = useForm({ initialValues: initial });
4155
4163
  const numberStr = String(form.values.number ?? "");
4156
4164
  const brand = detectBrand(numberStr);
4157
- React34.useEffect(() => {
4165
+ React36.useEffect(() => {
4158
4166
  onChange?.(toCard(form.values));
4159
4167
  }, [form.values.number, form.values.name, form.values.expiry, form.values.cvv]);
4160
4168
  const numberBind = form.fieldNative("number", {
@@ -4277,7 +4285,7 @@ function Checkout({
4277
4285
  ] })
4278
4286
  ] });
4279
4287
  }
4280
- var NotificationContext = React34.createContext({
4288
+ var NotificationContext = React36.createContext({
4281
4289
  open: () => void 0,
4282
4290
  close: () => void 0
4283
4291
  });
@@ -4335,26 +4343,26 @@ function NotificationItem({
4335
4343
  onClose,
4336
4344
  reduced
4337
4345
  }) {
4338
- const [paused, setPaused] = React34.useState(false);
4346
+ const [paused, setPaused] = React36.useState(false);
4339
4347
  const duration = n.duration ?? 4e3;
4340
4348
  const isAutoDismissing = isFinite(duration) && duration > 0;
4341
4349
  const showProgress = !reduced && isAutoDismissing;
4342
- const timerRef = React34.useRef(null);
4343
- const startTimeRef = React34.useRef(0);
4344
- const remainingRef = React34.useRef(duration);
4345
- const clearTimer = React34.useCallback(() => {
4350
+ const timerRef = React36.useRef(null);
4351
+ const startTimeRef = React36.useRef(0);
4352
+ const remainingRef = React36.useRef(duration);
4353
+ const clearTimer = React36.useCallback(() => {
4346
4354
  if (timerRef.current !== null) {
4347
4355
  clearTimeout(timerRef.current);
4348
4356
  timerRef.current = null;
4349
4357
  }
4350
4358
  }, []);
4351
- const scheduleDismiss = React34.useCallback((ms) => {
4359
+ const scheduleDismiss = React36.useCallback((ms) => {
4352
4360
  clearTimer();
4353
4361
  if (!isAutoDismissing) return;
4354
4362
  startTimeRef.current = Date.now();
4355
4363
  timerRef.current = setTimeout(() => onClose(n.id), ms);
4356
4364
  }, [clearTimer, isAutoDismissing, n.id, onClose]);
4357
- React34.useEffect(() => {
4365
+ React36.useEffect(() => {
4358
4366
  if (paused || !isAutoDismissing) return;
4359
4367
  scheduleDismiss(remainingRef.current);
4360
4368
  return clearTimer;
@@ -4437,15 +4445,15 @@ function NotificationProvider({
4437
4445
  children,
4438
4446
  position = "top-right"
4439
4447
  }) {
4440
- const [notifications, setNotifications] = React34.useState([]);
4448
+ const [notifications, setNotifications] = React36.useState([]);
4441
4449
  const reduced = framerMotion.useReducedMotion();
4442
- const open = React34.useCallback((payload) => {
4450
+ const open = React36.useCallback((payload) => {
4443
4451
  setNotifications((prev) => [
4444
4452
  ...prev,
4445
4453
  { duration: 4e3, ...payload, id: Date.now() + Math.random() }
4446
4454
  ]);
4447
4455
  }, []);
4448
- const close = React34.useCallback((id) => {
4456
+ const close = React36.useCallback((id) => {
4449
4457
  setNotifications((prev) => prev.filter((n) => n.id !== id));
4450
4458
  }, []);
4451
4459
  return /* @__PURE__ */ jsxRuntime.jsxs(NotificationContext.Provider, { value: { open, close }, children: [
@@ -4474,7 +4482,7 @@ function NotificationProvider({
4474
4482
  ] });
4475
4483
  }
4476
4484
  function useNotification() {
4477
- const { open } = React34.useContext(NotificationContext);
4485
+ const { open } = React36.useContext(NotificationContext);
4478
4486
  return {
4479
4487
  info: (props) => open({ type: "info", ...props }),
4480
4488
  success: (props) => open({ type: "success", ...props }),
@@ -4591,10 +4599,10 @@ function FadingBase({
4591
4599
  isMounted = false,
4592
4600
  children
4593
4601
  }) {
4594
- const [shouldRender, setShouldRender] = React34.useState(isMounted);
4595
- const [visible, setVisible] = React34.useState(false);
4596
- const timerRef = React34.useRef(null);
4597
- React34.useEffect(() => {
4602
+ const [shouldRender, setShouldRender] = React36.useState(isMounted);
4603
+ const [visible, setVisible] = React36.useState(false);
4604
+ const timerRef = React36.useRef(null);
4605
+ React36.useEffect(() => {
4598
4606
  if (isMounted) {
4599
4607
  setShouldRender(true);
4600
4608
  const rafId = requestAnimationFrame(() => setVisible(true));
@@ -4706,14 +4714,14 @@ function ScalableContainer({
4706
4714
  togglePosition = "top-right",
4707
4715
  className = ""
4708
4716
  }) {
4709
- const containerRef = React34.useRef(null);
4710
- const [internalScaled, setInternalScaled] = React34.useState(false);
4717
+ const containerRef = React36.useRef(null);
4718
+ const [internalScaled, setInternalScaled] = React36.useState(false);
4711
4719
  const isScaled = expanded ?? internalScaled;
4712
4720
  const reduced = framerMotion.useReducedMotion();
4713
- const prevScaled = React34.useRef(isScaled);
4721
+ const prevScaled = React36.useRef(isScaled);
4714
4722
  const expandW = targetWidth ?? expandedWidth;
4715
4723
  const expandH = targetHeight ?? expandedHeight;
4716
- React34.useEffect(() => {
4724
+ React36.useEffect(() => {
4717
4725
  if (isScaled === prevScaled.current) return;
4718
4726
  prevScaled.current = isScaled;
4719
4727
  if (typeof window === "undefined") return;
@@ -4860,17 +4868,17 @@ function CatalogGrid({ items, buttonText, onOpen, className = "" }) {
4860
4868
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex flex-wrap gap-2 ${className}`.trim(), children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(GridCard, { item, buttonText, onOpen }, item.key)) });
4861
4869
  }
4862
4870
  function CatalogCarousel({ items, buttonText, onOpen, className = "" }) {
4863
- const [activeIndex, setActiveIndex] = React34.useState(0);
4864
- const [indexPool, setIndexPool] = React34.useState([]);
4865
- const cardRefs = React34.useRef([]);
4866
- const getIndexes = React34.useMemo(() => {
4871
+ const [activeIndex, setActiveIndex] = React36.useState(0);
4872
+ const [indexPool, setIndexPool] = React36.useState([]);
4873
+ const cardRefs = React36.useRef([]);
4874
+ const getIndexes = React36.useMemo(() => {
4867
4875
  let nextIndex = activeIndex + 1;
4868
4876
  let previousIndex = activeIndex - 1;
4869
4877
  if (activeIndex === 0) previousIndex = items.length - 1;
4870
4878
  if (activeIndex === items.length - 1) nextIndex = 0;
4871
4879
  return { previousIndex, nextIndex };
4872
4880
  }, [activeIndex, items.length]);
4873
- React34.useEffect(() => {
4881
+ React36.useEffect(() => {
4874
4882
  const { nextIndex, previousIndex } = getIndexes;
4875
4883
  let indexes = [previousIndex, activeIndex, nextIndex];
4876
4884
  if (activeIndex !== 0 && activeIndex !== items.length - 1) {
@@ -5043,8 +5051,8 @@ function writeDismissed(key) {
5043
5051
  }
5044
5052
  }
5045
5053
  function useTargetBbox(ref) {
5046
- const [bbox, setBbox] = React34.useState(null);
5047
- React34.useLayoutEffect(() => {
5054
+ const [bbox, setBbox] = React36.useState(null);
5055
+ React36.useLayoutEffect(() => {
5048
5056
  const el = ref?.current;
5049
5057
  if (!el) {
5050
5058
  setBbox(null);
@@ -5074,7 +5082,7 @@ function tooltipStyleFor(bbox, placement) {
5074
5082
  return { left: bbox.left + bbox.width / 2, top: bbox.top - TOOLTIP_GAP, transform: "translate(-50%, -100%)", width: TOOLTIP_WIDTH };
5075
5083
  }
5076
5084
  function useFocusTrap(containerRef, active) {
5077
- React34.useEffect(() => {
5085
+ React36.useEffect(() => {
5078
5086
  if (!active) return;
5079
5087
  const el = containerRef.current;
5080
5088
  if (!el) return;
@@ -5113,16 +5121,16 @@ function Wizard({
5113
5121
  onComplete,
5114
5122
  onSkip
5115
5123
  }) {
5116
- const tooltipRef = React34.useRef(null);
5117
- const tooltipTitleId = React34.useId();
5118
- const tooltipBodyId = React34.useId();
5124
+ const tooltipRef = React36.useRef(null);
5125
+ const tooltipTitleId = React36.useId();
5126
+ const tooltipBodyId = React36.useId();
5119
5127
  const reduced = framerMotion.useReducedMotion();
5120
- const [open, setOpen] = React34.useState(() => steps.length > 0 && !readDismissed(storageKey));
5121
- const [activeIndex, setActiveIndex] = React34.useState(0);
5128
+ const [open, setOpen] = React36.useState(() => steps.length > 0 && !readDismissed(storageKey));
5129
+ const [activeIndex, setActiveIndex] = React36.useState(0);
5122
5130
  const step = steps[activeIndex];
5123
5131
  const bbox = useTargetBbox(step?.stepRef);
5124
5132
  useFocusTrap(tooltipRef, open);
5125
- React34.useEffect(() => {
5133
+ React36.useEffect(() => {
5126
5134
  if (!open || !dismissible) return;
5127
5135
  const onKey = (e) => {
5128
5136
  if (e.key === "Escape") {
@@ -5133,12 +5141,12 @@ function Wizard({
5133
5141
  document.addEventListener("keydown", onKey);
5134
5142
  return () => document.removeEventListener("keydown", onKey);
5135
5143
  }, [open, dismissible]);
5136
- const handleSkip = React34.useCallback(() => {
5144
+ const handleSkip = React36.useCallback(() => {
5137
5145
  writeDismissed(storageKey);
5138
5146
  setOpen(false);
5139
5147
  onSkip?.();
5140
5148
  }, [storageKey, onSkip]);
5141
- const handleComplete = React34.useCallback(() => {
5149
+ const handleComplete = React36.useCallback(() => {
5142
5150
  writeDismissed(storageKey);
5143
5151
  setOpen(false);
5144
5152
  onComplete?.();
@@ -5281,7 +5289,7 @@ function Wizard({
5281
5289
  ] });
5282
5290
  }
5283
5291
  var SearchIcon = /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", className: "w-4 h-4", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { fillRule: "evenodd", d: "M10.5 3.75a6.75 6.75 0 100 13.5 6.75 6.75 0 000-13.5zM2.25 10.5a8.25 8.25 0 1114.59 5.28l4.69 4.69a.75.75 0 11-1.06 1.06l-4.69-4.69A8.25 8.25 0 012.25 10.5z", clipRule: "evenodd" }) });
5284
- var SearchInput = React34__default.default.forwardRef(function SearchInput2({ value, onChange, disabled, label, htmlFor, placeholder, name, inputStyle, style, layout = "vertical", size = "md", icon, helperText, className }, ref) {
5292
+ var SearchInput = React36__default.default.forwardRef(function SearchInput2({ value, onChange, disabled, label, htmlFor, placeholder, name, inputStyle, style, layout = "vertical", size = "md", icon, helperText, className }, ref) {
5285
5293
  return /* @__PURE__ */ jsxRuntime.jsx(Field, { className, label, htmlFor, layout, helperText, children: /* @__PURE__ */ jsxRuntime.jsxs(
5286
5294
  "div",
5287
5295
  {
@@ -5516,15 +5524,15 @@ function EditableCell({
5516
5524
  rowIndex,
5517
5525
  onCellEdit
5518
5526
  }) {
5519
- const [editing, setEditing] = React34.useState(false);
5520
- const editRef = React34.useRef(null);
5527
+ const [editing, setEditing] = React36.useState(false);
5528
+ const editRef = React36.useRef(null);
5521
5529
  const value = row[col.keyBind];
5522
5530
  const commit = (next) => {
5523
5531
  setEditing(false);
5524
5532
  onCellEdit?.({ row, key: col.keyBind, value: next, rowIndex });
5525
5533
  };
5526
5534
  const cancel = () => setEditing(false);
5527
- React34.useEffect(() => {
5535
+ React36.useEffect(() => {
5528
5536
  if (!editing || !col.editor) return;
5529
5537
  const onMouseDown = (e) => {
5530
5538
  const target = e.target;
@@ -5583,7 +5591,7 @@ function TableBody({
5583
5591
  getRowKey,
5584
5592
  onCellEdit
5585
5593
  }) {
5586
- const [expanded, setExpanded] = React34.useState(() => /* @__PURE__ */ new Set());
5594
+ const [expanded, setExpanded] = React36.useState(() => /* @__PURE__ */ new Set());
5587
5595
  const reduced = framerMotion.useReducedMotion();
5588
5596
  const toggleRow = (rowKey) => {
5589
5597
  setExpanded((prev) => {
@@ -5598,7 +5606,7 @@ function TableBody({
5598
5606
  return /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: rows.map((row, i) => {
5599
5607
  const rowKey = getRowKey(row, i);
5600
5608
  const isExpanded = expanded.has(rowKey);
5601
- return /* @__PURE__ */ jsxRuntime.jsxs(React34__default.default.Fragment, { children: [
5609
+ return /* @__PURE__ */ jsxRuntime.jsxs(React36__default.default.Fragment, { children: [
5602
5610
  /* @__PURE__ */ jsxRuntime.jsxs(
5603
5611
  "tr",
5604
5612
  {
@@ -5710,13 +5718,13 @@ function Table({
5710
5718
  className = "",
5711
5719
  style
5712
5720
  }) {
5713
- const searchRef = React34.useRef(null);
5714
- const [searchTerm, setSearchTerm] = React34.useState("");
5715
- const [perPage, setPerPage] = React34.useState(
5721
+ const searchRef = React36.useRef(null);
5722
+ const [searchTerm, setSearchTerm] = React36.useState("");
5723
+ const [perPage, setPerPage] = React36.useState(
5716
5724
  typeof pagination.perPage === "number" ? pagination.perPage : 15
5717
5725
  );
5718
- const [activePage, setActivePage] = React34.useState(0);
5719
- const [sortState, setSortState] = React34.useState(defaultSort);
5726
+ const [activePage, setActivePage] = React36.useState(0);
5727
+ const [sortState, setSortState] = React36.useState(defaultSort);
5720
5728
  const isServerSide = !!(pagination.enabled && pagination.serverSide);
5721
5729
  const handleSort = (col) => {
5722
5730
  const key = col.keyBind;
@@ -5728,8 +5736,8 @@ function Table({
5728
5736
  onSortChange?.(next);
5729
5737
  };
5730
5738
  const debounceMs = search?.debounceMs ?? 0;
5731
- const [debouncedTerm, setDebouncedTerm] = React34.useState("");
5732
- React34.useEffect(() => {
5739
+ const [debouncedTerm, setDebouncedTerm] = React36.useState("");
5740
+ React36.useEffect(() => {
5733
5741
  if (debounceMs <= 0) {
5734
5742
  setDebouncedTerm(searchTerm);
5735
5743
  return;
@@ -5738,7 +5746,7 @@ function Table({
5738
5746
  return () => clearTimeout(t);
5739
5747
  }, [searchTerm, debounceMs]);
5740
5748
  const term = debounceMs > 0 ? debouncedTerm : searchTerm;
5741
- const filteredRows = React34.useMemo(() => {
5749
+ const filteredRows = React36.useMemo(() => {
5742
5750
  if (isServerSide || !term) return rows;
5743
5751
  if (search?.predicate) return rows.filter((row) => search.predicate(row, term));
5744
5752
  const cs = !!search?.caseSensitive;
@@ -5752,7 +5760,7 @@ function Table({
5752
5760
  };
5753
5761
  return rows.filter((row) => keys ? keys.some((k) => test(row[k])) : Object.values(row).some(test));
5754
5762
  }, [rows, term, isServerSide, search?.predicate, search?.caseSensitive, search?.matchMode, search?.keys]);
5755
- const sortedRows = React34.useMemo(() => {
5763
+ const sortedRows = React36.useMemo(() => {
5756
5764
  if (isServerSide || !sortState) return filteredRows;
5757
5765
  const col = columns.find((c) => c.keyBind === sortState.key);
5758
5766
  const accessor = col?.sortAccessor ?? ((r) => r[sortState.key]);
@@ -5760,29 +5768,29 @@ function Table({
5760
5768
  if (sortState.direction === "desc") out.reverse();
5761
5769
  return out;
5762
5770
  }, [filteredRows, sortState, isServerSide, columns]);
5763
- const datasets = React34.useMemo(() => {
5771
+ const datasets = React36.useMemo(() => {
5764
5772
  if (isServerSide) return [rows];
5765
5773
  return createDatasets(sortedRows, pagination.enabled ? perPage : null);
5766
5774
  }, [sortedRows, perPage, pagination.enabled, isServerSide, rows]);
5767
- const MAX_PAGE = React34.useMemo(() => {
5775
+ const MAX_PAGE = React36.useMemo(() => {
5768
5776
  if (isServerSide && typeof pagination.maxPage === "number") return Math.max(0, pagination.maxPage);
5769
5777
  if (isServerSide && typeof pagination.totalCount === "number")
5770
5778
  return Math.max(0, Math.ceil(pagination.totalCount / perPage) - 1);
5771
5779
  return datasets.length ? datasets.length - 1 : 0;
5772
5780
  }, [isServerSide, pagination.maxPage, pagination.totalCount, perPage, datasets.length]);
5773
- const currentPageRows = React34.useMemo(() => {
5781
+ const currentPageRows = React36.useMemo(() => {
5774
5782
  if (isServerSide) return rows;
5775
5783
  return datasets[activePage] ?? [];
5776
5784
  }, [isServerSide, rows, datasets, activePage]);
5777
- React34.useEffect(() => {
5785
+ React36.useEffect(() => {
5778
5786
  if (pagination.enabled && !isServerSide && typeof pagination.perPage === "number") {
5779
5787
  setPerPage(pagination.perPage);
5780
5788
  }
5781
5789
  }, [pagination.enabled, pagination.perPage, isServerSide]);
5782
- React34.useEffect(() => {
5790
+ React36.useEffect(() => {
5783
5791
  if (isServerSide && typeof pagination.perPage === "number") setPerPage(pagination.perPage);
5784
5792
  }, [isServerSide, pagination.perPage]);
5785
- React34.useEffect(() => {
5793
+ React36.useEffect(() => {
5786
5794
  if (isServerSide && typeof pagination.page === "number" && pagination.page >= 1)
5787
5795
  setActivePage(pagination.page - 1);
5788
5796
  }, [isServerSide, pagination.page]);
@@ -5871,7 +5879,7 @@ function TableSkeletonBody({
5871
5879
  i
5872
5880
  )) });
5873
5881
  }
5874
- var useIsoLayoutEffect = typeof window !== "undefined" ? React34.useLayoutEffect : React34.useEffect;
5882
+ var useIsoLayoutEffect = typeof window !== "undefined" ? React36.useLayoutEffect : React36.useEffect;
5875
5883
  function VirtualList({
5876
5884
  items,
5877
5885
  rowHeight,
@@ -5888,10 +5896,10 @@ function VirtualList({
5888
5896
  className = "",
5889
5897
  style
5890
5898
  }) {
5891
- const scrollRef = React34.useRef(null);
5892
- const [scrollTop, setScrollTop] = React34.useState(0);
5893
- const [viewport, setViewport] = React34.useState(typeof height === "number" ? height : 400);
5894
- const [term, setTerm] = React34.useState("");
5899
+ const scrollRef = React36.useRef(null);
5900
+ const [scrollTop, setScrollTop] = React36.useState(0);
5901
+ const [viewport, setViewport] = React36.useState(typeof height === "number" ? height : 400);
5902
+ const [term, setTerm] = React36.useState("");
5895
5903
  useIsoLayoutEffect(() => {
5896
5904
  const el = scrollRef.current;
5897
5905
  if (!el) return;
@@ -5902,7 +5910,7 @@ function VirtualList({
5902
5910
  ro.observe(el);
5903
5911
  return () => ro.disconnect();
5904
5912
  }, []);
5905
- const filtered = React34.useMemo(() => {
5913
+ const filtered = React36.useMemo(() => {
5906
5914
  if (!searchable || !term) return items;
5907
5915
  if (filter) return items.filter((it) => filter(it, term));
5908
5916
  const needle = term.toLowerCase();
@@ -6043,35 +6051,37 @@ function PdfViewer({
6043
6051
  onLoad,
6044
6052
  onError,
6045
6053
  onPageChange,
6054
+ height = 600,
6055
+ width,
6046
6056
  className = "",
6047
6057
  style
6048
6058
  }) {
6049
- const [pdfjs, setPdfjs] = React34.useState(null);
6050
- const [doc, setDoc] = React34.useState(null);
6051
- const [numPages, setNumPages] = React34.useState(0);
6052
- const [baseSize, setBaseSize] = React34.useState(null);
6053
- const [sizes, setSizes] = React34.useState([]);
6054
- const [status, setStatus] = React34.useState("loading");
6055
- const [error, setError] = React34.useState(null);
6056
- const [reloadKey, setReloadKey] = React34.useState(0);
6057
- const scrollRef = React34.useRef(null);
6058
- const [scrollTop, setScrollTop] = React34.useState(0);
6059
- const [viewport, setViewport] = React34.useState({ w: 0, h: 0 });
6060
- const [zoomMode, setZoomMode] = React34.useState(zoom);
6061
- const [page, setPage] = React34.useState(initialPage);
6062
- const [showSearch, setShowSearch] = React34.useState(false);
6063
- const [query, setQuery] = React34.useState("");
6064
- const [matchPages, setMatchPages] = React34.useState(null);
6065
- const [matchIdx, setMatchIdx] = React34.useState(0);
6066
- const [searching, setSearching] = React34.useState(false);
6067
- const [pageDraft, setPageDraft] = React34.useState("");
6068
- const pageEditing = React34.useRef(false);
6069
- const pageText = React34.useRef(/* @__PURE__ */ new Map());
6070
- const searchSeq = React34.useRef(0);
6071
- const searchTimer = React34.useRef(null);
6072
- const measured = React34.useRef(/* @__PURE__ */ new Set());
6059
+ const [pdfjs, setPdfjs] = React36.useState(null);
6060
+ const [doc, setDoc] = React36.useState(null);
6061
+ const [numPages, setNumPages] = React36.useState(0);
6062
+ const [baseSize, setBaseSize] = React36.useState(null);
6063
+ const [sizes, setSizes] = React36.useState([]);
6064
+ const [status, setStatus] = React36.useState("loading");
6065
+ const [error, setError] = React36.useState(null);
6066
+ const [reloadKey, setReloadKey] = React36.useState(0);
6067
+ const scrollRef = React36.useRef(null);
6068
+ const [scrollTop, setScrollTop] = React36.useState(0);
6069
+ const [viewport, setViewport] = React36.useState({ w: 0, h: 0 });
6070
+ const [zoomMode, setZoomMode] = React36.useState(zoom);
6071
+ const [page, setPage] = React36.useState(initialPage);
6072
+ const [showSearch, setShowSearch] = React36.useState(false);
6073
+ const [query, setQuery] = React36.useState("");
6074
+ const [matchPages, setMatchPages] = React36.useState(null);
6075
+ const [matchIdx, setMatchIdx] = React36.useState(0);
6076
+ const [searching, setSearching] = React36.useState(false);
6077
+ const [pageDraft, setPageDraft] = React36.useState("");
6078
+ const pageEditing = React36.useRef(false);
6079
+ const pageText = React36.useRef(/* @__PURE__ */ new Map());
6080
+ const searchSeq = React36.useRef(0);
6081
+ const searchTimer = React36.useRef(null);
6082
+ const measured = React36.useRef(/* @__PURE__ */ new Set());
6073
6083
  const tb = toolbar === true ? { zoom: true, pager: true, download: true, print: true, search: true } : toolbar || {};
6074
- React34.useEffect(() => {
6084
+ React36.useEffect(() => {
6075
6085
  let cancelled = false;
6076
6086
  let task;
6077
6087
  setStatus("loading");
@@ -6115,10 +6125,10 @@ function PdfViewer({
6115
6125
  task?.destroy?.();
6116
6126
  };
6117
6127
  }, [source, remote, reloadKey, workerSrc]);
6118
- React34.useEffect(() => () => {
6128
+ React36.useEffect(() => () => {
6119
6129
  doc?.destroy?.();
6120
6130
  }, [doc]);
6121
- React34.useEffect(() => {
6131
+ React36.useEffect(() => {
6122
6132
  const el = scrollRef.current;
6123
6133
  if (!el || typeof ResizeObserver === "undefined") return;
6124
6134
  const measure = () => setViewport({ w: el.clientWidth, h: el.clientHeight });
@@ -6127,7 +6137,7 @@ function PdfViewer({
6127
6137
  ro.observe(el);
6128
6138
  return () => ro.disconnect();
6129
6139
  }, [status]);
6130
- const handleMeasure = React34.useCallback((p, size) => {
6140
+ const handleMeasure = React36.useCallback((p, size) => {
6131
6141
  setSizes((prev) => {
6132
6142
  const cur = prev[p - 1];
6133
6143
  if (cur && Math.abs(cur.width - size.width) < 0.5 && Math.abs(cur.height - size.height) < 0.5) return prev;
@@ -6136,7 +6146,7 @@ function PdfViewer({
6136
6146
  return next;
6137
6147
  });
6138
6148
  }, []);
6139
- const scale = React34.useMemo(() => {
6149
+ const scale = React36.useMemo(() => {
6140
6150
  if (!baseSize) return 1;
6141
6151
  if (typeof zoomMode === "number") return zoomMode;
6142
6152
  const avail = Math.max(1, (viewport.w || baseSize.width) - 32);
@@ -6147,7 +6157,7 @@ function PdfViewer({
6147
6157
  }
6148
6158
  return 1;
6149
6159
  }, [zoomMode, baseSize, viewport]);
6150
- const { offsets, total } = React34.useMemo(() => {
6160
+ const { offsets, total } = React36.useMemo(() => {
6151
6161
  const offs = new Array(sizes.length);
6152
6162
  let acc = 0;
6153
6163
  for (let i = 0; i < sizes.length; i++) {
@@ -6161,13 +6171,13 @@ function PdfViewer({
6161
6171
  const startIdx = hasLayout ? Math.max(0, pageIndexAt(offsets, scrollTop) - overscan) : 0;
6162
6172
  const endIdx = hasLayout ? Math.min(numPages, pageIndexAt(offsets, scrollTop + viewport.h) + 1 + overscan) : 0;
6163
6173
  const visiblePages = Array.from({ length: Math.max(0, endIdx - startIdx) }, (_, i) => startIdx + i + 1);
6164
- const scrollToPage = React34.useCallback((p) => {
6174
+ const scrollToPage = React36.useCallback((p) => {
6165
6175
  const el = scrollRef.current;
6166
6176
  if (!el || !offsets.length) return;
6167
6177
  const clamped = Math.min(offsets.length, Math.max(1, p));
6168
6178
  el.scrollTo({ top: offsets[clamped - 1] ?? 0, behavior: "smooth" });
6169
6179
  }, [offsets]);
6170
- React34.useEffect(() => {
6180
+ React36.useEffect(() => {
6171
6181
  if (!hasLayout) return;
6172
6182
  const cur = pageIndexAt(offsets, scrollTop + viewport.h / 2) + 1;
6173
6183
  if (cur !== page) {
@@ -6175,10 +6185,10 @@ function PdfViewer({
6175
6185
  onPageChange?.(cur);
6176
6186
  }
6177
6187
  }, [scrollTop, offsets, viewport.h, numPages]);
6178
- React34.useEffect(() => {
6188
+ React36.useEffect(() => {
6179
6189
  if (status === "ready" && initialPage > 1) scrollToPage(initialPage);
6180
6190
  }, [status, initialPage]);
6181
- const runSearch = React34.useCallback(async (q) => {
6191
+ const runSearch = React36.useCallback(async (q) => {
6182
6192
  const needle = q.trim().toLowerCase();
6183
6193
  if (!doc || !needle) {
6184
6194
  setMatchPages(null);
@@ -6207,7 +6217,7 @@ function PdfViewer({
6207
6217
  setSearching(false);
6208
6218
  if (hits.length) scrollToPage(hits[0]);
6209
6219
  }, [doc, numPages, scrollToPage]);
6210
- const onQueryChange = React34.useCallback((v) => {
6220
+ const onQueryChange = React36.useCallback((v) => {
6211
6221
  setQuery(v);
6212
6222
  if (searchTimer.current) clearTimeout(searchTimer.current);
6213
6223
  if (!v.trim()) {
@@ -6219,7 +6229,7 @@ function PdfViewer({
6219
6229
  }
6220
6230
  searchTimer.current = setTimeout(() => runSearch(v), SEARCH_DEBOUNCE);
6221
6231
  }, [runSearch]);
6222
- React34.useEffect(() => () => {
6232
+ React36.useEffect(() => () => {
6223
6233
  if (searchTimer.current) clearTimeout(searchTimer.current);
6224
6234
  }, []);
6225
6235
  const gotoMatch = (dir) => {
@@ -6228,18 +6238,18 @@ function PdfViewer({
6228
6238
  setMatchIdx(next);
6229
6239
  scrollToPage(matchPages[next]);
6230
6240
  };
6231
- const getBytes = React34.useCallback(async () => {
6241
+ const getBytes = React36.useCallback(async () => {
6232
6242
  if (doc?.getData) return doc.getData();
6233
6243
  if (source instanceof Uint8Array) return source;
6234
6244
  if (source instanceof ArrayBuffer) return new Uint8Array(source);
6235
6245
  if (typeof Blob !== "undefined" && source instanceof Blob) return new Uint8Array(await source.arrayBuffer());
6236
6246
  throw new Error("No bytes available");
6237
6247
  }, [doc, source]);
6238
- const download = React34.useCallback(async () => {
6248
+ const download = React36.useCallback(async () => {
6239
6249
  const bytes = await getBytes();
6240
6250
  downloadBlob(new Blob([bytes], { type: "application/pdf" }), sourceName(source) || "document.pdf");
6241
6251
  }, [getBytes, source]);
6242
- const print = React34.useCallback(async () => {
6252
+ const print = React36.useCallback(async () => {
6243
6253
  const bytes = await getBytes();
6244
6254
  const blob = new Blob([bytes], { type: "application/pdf" });
6245
6255
  const url = URL.createObjectURL(blob);
@@ -6277,7 +6287,7 @@ function PdfViewer({
6277
6287
  ] });
6278
6288
  }
6279
6289
  const ready = status === "ready";
6280
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx("flex flex-col overflow-hidden rounded-lg border border-border bg-surface-raised", className), style: { height: 600, ...style }, children: [
6290
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx("flex flex-col overflow-hidden rounded-lg border border-border bg-surface-raised", className), style: { height, width, ...style }, children: [
6281
6291
  toolbar !== false && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-shrink-0 flex-col border-b border-border bg-surface", children: [
6282
6292
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 px-2 py-1.5", children: [
6283
6293
  tb.pager && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
@@ -6397,9 +6407,9 @@ function PdfPage({
6397
6407
  textLayer,
6398
6408
  onMeasure
6399
6409
  }) {
6400
- const canvasRef = React34.useRef(null);
6401
- const textRef = React34.useRef(null);
6402
- React34.useEffect(() => {
6410
+ const canvasRef = React36.useRef(null);
6411
+ const textRef = React36.useRef(null);
6412
+ React36.useEffect(() => {
6403
6413
  let cancelled = false;
6404
6414
  let renderTask;
6405
6415
  (async () => {
@@ -6458,6 +6468,15 @@ var FitPageIcon = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 2
6458
6468
  ] });
6459
6469
  var DEFAULT_COL_WIDTH = 140;
6460
6470
  var GUTTER = 52;
6471
+ var END_PAD = 12;
6472
+ function compareValues2(a, b) {
6473
+ if (a == null && b == null) return 0;
6474
+ if (a == null) return 1;
6475
+ if (b == null) return -1;
6476
+ if (typeof a === "number" && typeof b === "number") return a - b;
6477
+ if (typeof a === "boolean" && typeof b === "boolean") return a === b ? 0 : a ? 1 : -1;
6478
+ return String(a).localeCompare(String(b), void 0, { numeric: true, sensitivity: "base" });
6479
+ }
6461
6480
  function resolveWidth(w) {
6462
6481
  if (typeof w === "number" && Number.isFinite(w)) return w;
6463
6482
  if (typeof w === "string") {
@@ -6476,22 +6495,30 @@ function DataGrid({
6476
6495
  rowHeight = 34,
6477
6496
  headerHeight = 38,
6478
6497
  height = 480,
6498
+ width,
6479
6499
  editable = false,
6500
+ sortable = false,
6501
+ sort: sortProp,
6502
+ onSortChange,
6480
6503
  virtualize = true,
6481
6504
  overscan = 4,
6482
6505
  rowNumbers = true,
6506
+ trailingRows = 0,
6483
6507
  onCellEdit,
6484
6508
  className = "",
6485
6509
  style,
6486
6510
  emptyState = "No data"
6487
6511
  }) {
6488
- const scrollRef = React34.useRef(null);
6489
- const [scroll, setScroll] = React34.useState({ top: 0, left: 0 });
6490
- const [viewport, setViewport] = React34.useState({ w: 0, h: 0 });
6491
- const [editing, setEditing] = React34.useState(null);
6492
- const [draft, setDraft] = React34.useState("");
6512
+ const scrollRef = React36.useRef(null);
6513
+ const [scroll, setScroll] = React36.useState({ top: 0, left: 0 });
6514
+ const [viewport, setViewport] = React36.useState({ w: 0, h: 0 });
6515
+ const [editing, setEditing] = React36.useState(null);
6516
+ const [draft, setDraft] = React36.useState("");
6517
+ const [internalSort, setInternalSort] = React36.useState(null);
6518
+ const sort = sortProp !== void 0 ? sortProp : internalSort;
6493
6519
  const gutter = rowNumbers ? GUTTER : 0;
6494
- const { widths, offsets, totalWidth } = React34.useMemo(() => {
6520
+ const colSortable = (c) => c.sortable ?? sortable;
6521
+ const { widths, offsets, totalWidth } = React36.useMemo(() => {
6495
6522
  const widths2 = columns.map((c) => resolveWidth(c.width));
6496
6523
  const offsets2 = [];
6497
6524
  let acc = 0;
@@ -6501,8 +6528,22 @@ function DataGrid({
6501
6528
  }
6502
6529
  return { widths: widths2, offsets: offsets2, totalWidth: acc };
6503
6530
  }, [columns]);
6504
- const totalHeight = rows.length * rowHeight;
6505
- React34.useEffect(() => {
6531
+ const order = React36.useMemo(() => {
6532
+ const idx = rows.map((_, i) => i);
6533
+ if (!sort) return idx;
6534
+ const dir = sort.dir === "asc" ? 1 : -1;
6535
+ return idx.sort((ia, ib) => dir * compareValues2(rows[ia]?.[sort.key] ?? null, rows[ib]?.[sort.key] ?? null));
6536
+ }, [rows, sort]);
6537
+ const toggleSort = (key) => {
6538
+ const nextDir = sort?.key !== key ? "asc" : sort.dir === "asc" ? "desc" : null;
6539
+ const next = nextDir ? { key, dir: nextDir } : null;
6540
+ if (sortProp === void 0) setInternalSort(next);
6541
+ onSortChange?.(next);
6542
+ };
6543
+ const displayRowCount = rows.length + Math.max(0, trailingRows);
6544
+ const totalHeight = displayRowCount * rowHeight;
6545
+ const rowIndexForDisp = (disp) => disp < rows.length ? order[disp] : disp;
6546
+ React36.useEffect(() => {
6506
6547
  const el = scrollRef.current;
6507
6548
  if (!el || typeof ResizeObserver === "undefined") return;
6508
6549
  const measure = () => setViewport({ w: el.clientWidth, h: el.clientHeight });
@@ -6513,7 +6554,7 @@ function DataGrid({
6513
6554
  }, []);
6514
6555
  const bodyH = (viewport.h || (typeof height === "number" ? height : 480)) - headerHeight;
6515
6556
  const rowStart = virtualize ? Math.max(0, Math.floor(scroll.top / rowHeight) - overscan) : 0;
6516
- const rowEnd = virtualize ? Math.min(rows.length, Math.ceil((scroll.top + bodyH) / rowHeight) + overscan) : rows.length;
6557
+ const rowEnd = virtualize ? Math.min(displayRowCount, Math.ceil((scroll.top + bodyH) / rowHeight) + overscan) : displayRowCount;
6517
6558
  let colStart = 0;
6518
6559
  let colEnd = columns.length;
6519
6560
  if (virtualize && viewport.w) {
@@ -6528,17 +6569,18 @@ function DataGrid({
6528
6569
  }
6529
6570
  const visibleRows = Array.from({ length: Math.max(0, rowEnd - rowStart) }, (_, i) => rowStart + i);
6530
6571
  const visibleCols = Array.from({ length: Math.max(0, colEnd - colStart) }, (_, i) => colStart + i);
6531
- const commit = React34.useCallback(() => {
6572
+ const commit = React36.useCallback(() => {
6532
6573
  if (!editing) return;
6533
6574
  const col = columns[editing.col];
6534
- onCellEdit?.({ row: editing.row, column: col.key, value: draft });
6575
+ const ri = editing.disp < rows.length ? order[editing.disp] : editing.disp;
6576
+ onCellEdit?.({ row: ri, column: col.key, value: draft });
6535
6577
  setEditing(null);
6536
- }, [editing, columns, draft, onCellEdit]);
6537
- const startEdit = (row, col) => {
6578
+ }, [editing, columns, draft, onCellEdit, order, rows.length]);
6579
+ const startEdit = (disp, col) => {
6538
6580
  const c = columns[col];
6539
6581
  if (!(c.editable ?? editable)) return;
6540
- setDraft(displayValue(rows[row]?.[c.key] ?? ""));
6541
- setEditing({ row, col });
6582
+ setDraft(displayValue(rows[rowIndexForDisp(disp)]?.[c.key] ?? ""));
6583
+ setEditing({ disp, col });
6542
6584
  };
6543
6585
  return /* @__PURE__ */ jsxRuntime.jsxs(
6544
6586
  "div",
@@ -6546,12 +6588,12 @@ function DataGrid({
6546
6588
  ref: scrollRef,
6547
6589
  onScroll: (e) => setScroll({ top: e.currentTarget.scrollTop, left: e.currentTarget.scrollLeft }),
6548
6590
  className: cx("relative overflow-auto rounded-lg border border-border bg-surface-raised text-sm", className),
6549
- style: { height, ...style },
6591
+ style: { height, width, ...style },
6550
6592
  role: "grid",
6551
6593
  "aria-rowcount": rows.length,
6552
6594
  "aria-colcount": columns.length,
6553
6595
  children: [
6554
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative", width: gutter + totalWidth, height: headerHeight + totalHeight }, children: [
6596
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative", width: gutter + totalWidth + END_PAD, height: headerHeight + totalHeight + END_PAD }, children: [
6555
6597
  rowNumbers && /* @__PURE__ */ jsxRuntime.jsx(
6556
6598
  "div",
6557
6599
  {
@@ -6561,11 +6603,18 @@ function DataGrid({
6561
6603
  ),
6562
6604
  visibleCols.map((ci) => {
6563
6605
  const c = columns[ci];
6564
- return /* @__PURE__ */ jsxRuntime.jsx(
6606
+ const sortDir = sort?.key === c.key ? sort.dir : null;
6607
+ const canSort = colSortable(c);
6608
+ return /* @__PURE__ */ jsxRuntime.jsxs(
6565
6609
  "div",
6566
6610
  {
6567
6611
  role: "columnheader",
6568
- className: "flex items-center border-b border-r border-border bg-surface px-3 font-medium text-foreground-secondary",
6612
+ "aria-sort": sortDir ? sortDir === "asc" ? "ascending" : "descending" : void 0,
6613
+ onClick: canSort ? () => toggleSort(c.key) : void 0,
6614
+ className: cx(
6615
+ "flex items-center gap-1 border-b border-r border-border bg-surface px-3 font-medium text-foreground-secondary",
6616
+ canSort && "cursor-pointer select-none hover:text-foreground"
6617
+ ),
6569
6618
  style: {
6570
6619
  position: "absolute",
6571
6620
  top: scroll.top,
@@ -6575,38 +6624,42 @@ function DataGrid({
6575
6624
  zIndex: 2,
6576
6625
  justifyContent: c.align === "right" ? "flex-end" : c.align === "center" ? "center" : "flex-start"
6577
6626
  },
6578
- children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: c.label ?? c.key })
6627
+ children: [
6628
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: c.label ?? c.key }),
6629
+ canSort && /* @__PURE__ */ jsxRuntime.jsx(SortCaret, { dir: sortDir })
6630
+ ]
6579
6631
  },
6580
6632
  `h-${c.key}`
6581
6633
  );
6582
6634
  }),
6583
- rowNumbers && visibleRows.map((ri) => /* @__PURE__ */ jsxRuntime.jsx(
6635
+ rowNumbers && visibleRows.map((disp) => /* @__PURE__ */ jsxRuntime.jsx(
6584
6636
  "div",
6585
6637
  {
6586
6638
  className: "flex items-center justify-center border-b border-r border-border bg-surface text-xs tabular-nums text-foreground-muted",
6587
- style: { position: "absolute", left: scroll.left, top: headerHeight + ri * rowHeight, width: gutter, height: rowHeight, zIndex: 1 },
6588
- children: ri + 1
6639
+ style: { position: "absolute", left: scroll.left, top: headerHeight + disp * rowHeight, width: gutter, height: rowHeight, zIndex: 1 },
6640
+ children: disp + 1
6589
6641
  },
6590
- `g-${ri}`
6642
+ `g-${disp}`
6591
6643
  )),
6592
- visibleRows.map(
6593
- (ri) => visibleCols.map((ci) => {
6644
+ visibleRows.map((disp) => {
6645
+ const ri = rowIndexForDisp(disp);
6646
+ return visibleCols.map((ci) => {
6594
6647
  const c = columns[ci];
6595
- const isEditing = editing?.row === ri && editing?.col === ci;
6648
+ const isEditing = editing?.disp === disp && editing?.col === ci;
6596
6649
  const canEdit = c.editable ?? editable;
6597
6650
  return /* @__PURE__ */ jsxRuntime.jsx(
6598
6651
  "div",
6599
6652
  {
6600
6653
  role: "gridcell",
6601
- onDoubleClick: () => startEdit(ri, ci),
6654
+ onDoubleClick: () => startEdit(disp, ci),
6602
6655
  className: cx(
6603
6656
  "flex items-center border-b border-r border-border px-3",
6604
- ri % 2 ? "bg-surface-raised" : "bg-surface",
6657
+ disp % 2 ? "bg-surface-raised" : "bg-surface",
6605
6658
  canEdit && "cursor-text"
6606
6659
  ),
6607
6660
  style: {
6608
6661
  position: "absolute",
6609
- top: headerHeight + ri * rowHeight,
6662
+ top: headerHeight + disp * rowHeight,
6610
6663
  left: gutter + offsets[ci],
6611
6664
  width: widths[ci],
6612
6665
  height: rowHeight,
@@ -6627,16 +6680,22 @@ function DataGrid({
6627
6680
  }
6628
6681
  ) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-foreground", children: displayValue(rows[ri]?.[c.key] ?? "") })
6629
6682
  },
6630
- `${ri}-${c.key}`
6683
+ `${disp}-${c.key}`
6631
6684
  );
6632
- })
6633
- )
6685
+ });
6686
+ })
6634
6687
  ] }),
6635
- rows.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex items-center justify-center text-foreground-muted", style: { top: headerHeight }, children: emptyState })
6688
+ displayRowCount === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex items-center justify-center text-foreground-muted", style: { top: headerHeight }, children: emptyState })
6636
6689
  ]
6637
6690
  }
6638
6691
  );
6639
6692
  }
6693
+ function SortCaret({ dir }) {
6694
+ return /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 16 16", className: "h-3 w-3 flex-shrink-0", fill: "none", stroke: "currentColor", strokeWidth: 1.75, "aria-hidden": "true", children: [
6695
+ /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 6.5 8 3.5l3 3", className: dir === "asc" ? "text-accent" : "text-foreground-muted opacity-50" }),
6696
+ /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 9.5 8 12.5l3-3", className: dir === "desc" ? "text-accent" : "text-foreground-muted opacity-50" })
6697
+ ] });
6698
+ }
6640
6699
  function toColumns(cols) {
6641
6700
  return cols.map((c) => typeof c === "string" ? { key: c, label: c } : { ...c, label: c.label ?? c.key });
6642
6701
  }
@@ -6644,6 +6703,18 @@ function cellValue(v) {
6644
6703
  if (v != null && typeof v === "object" && "value" in v) return v.value;
6645
6704
  return v;
6646
6705
  }
6706
+ function columnLetter(i) {
6707
+ let s = "";
6708
+ let n = i;
6709
+ do {
6710
+ s = String.fromCharCode(65 + n % 26) + s;
6711
+ n = Math.floor(n / 26) - 1;
6712
+ } while (n >= 0);
6713
+ return s;
6714
+ }
6715
+ function blankSheet(name, cols = 8) {
6716
+ return { name, columns: Array.from({ length: cols }, (_, i) => ({ key: columnLetter(i), label: columnLetter(i) })), rows: [] };
6717
+ }
6647
6718
  function toPlainRows(sheet, columns) {
6648
6719
  return sheet.rows.map((row) => {
6649
6720
  const out = {};
@@ -6675,15 +6746,21 @@ function Spreadsheet({
6675
6746
  export: exportFormats = ["xlsx", "csv", "pdf"],
6676
6747
  fileName,
6677
6748
  virtualize = true,
6749
+ sortable = true,
6750
+ emptyRows = 50,
6751
+ allowAddSheet,
6752
+ height = 480,
6753
+ width,
6678
6754
  className = "",
6679
6755
  style
6680
6756
  }) {
6681
- const [sheets, setSheets] = React34.useState(Array.isArray(source) ? source : null);
6682
- const [active, setActive] = React34.useState(0);
6683
- const [status, setStatus] = React34.useState(Array.isArray(source) ? "ready" : "loading");
6684
- const [error, setError] = React34.useState(null);
6685
- const [reloadKey, setReloadKey] = React34.useState(0);
6686
- React34.useEffect(() => {
6757
+ const canAddSheet = allowAddSheet ?? editable;
6758
+ const [sheets, setSheets] = React36.useState(Array.isArray(source) ? source : null);
6759
+ const [active, setActive] = React36.useState(0);
6760
+ const [status, setStatus] = React36.useState(Array.isArray(source) ? "ready" : "loading");
6761
+ const [error, setError] = React36.useState(null);
6762
+ const [reloadKey, setReloadKey] = React36.useState(0);
6763
+ React36.useEffect(() => {
6687
6764
  if (Array.isArray(source)) {
6688
6765
  setSheets(source);
6689
6766
  setStatus("ready");
@@ -6729,14 +6806,15 @@ function Spreadsheet({
6729
6806
  };
6730
6807
  }, [source, remote, reloadKey]);
6731
6808
  const sheet = sheets?.[active];
6732
- const columns = React34.useMemo(() => sheet ? toColumns(sheet.columns) : [], [sheet]);
6733
- const plainRows = React34.useMemo(() => sheet ? toPlainRows(sheet, columns) : [], [sheet, columns]);
6734
- const handleCellEdit = React34.useCallback(({ row, column, value }) => {
6809
+ const columns = React36.useMemo(() => sheet ? toColumns(sheet.columns) : [], [sheet]);
6810
+ const plainRows = React36.useMemo(() => sheet ? toPlainRows(sheet, columns) : [], [sheet, columns]);
6811
+ const handleCellEdit = React36.useCallback(({ row, column, value }) => {
6735
6812
  let coerced = value;
6736
6813
  setSheets((prev) => {
6737
6814
  if (!prev) return prev;
6738
6815
  const next = prev.map((s, i) => i === active ? { ...s, rows: s.rows.map((r) => ({ ...r })) } : s);
6739
6816
  const target = next[active];
6817
+ while (target.rows.length <= row) target.rows.push({});
6740
6818
  const existing = target.rows[row]?.[column];
6741
6819
  const prevValue = cellValue(existing);
6742
6820
  coerced = coerceToCellType(prevValue, value);
@@ -6750,17 +6828,29 @@ function Spreadsheet({
6750
6828
  });
6751
6829
  onCellEdit?.({ sheet: sheets?.[active]?.name ?? "", row, column, value: coerced });
6752
6830
  }, [active, onCellEdit, onChange, sheets]);
6753
- const baseName = React34.useMemo(
6831
+ const addSheet = React36.useCallback(() => {
6832
+ setSheets((prev) => {
6833
+ const list = prev ?? [];
6834
+ const used = new Set(list.map((s) => s.name));
6835
+ let n = list.length + 1;
6836
+ while (used.has(`Sheet ${n}`)) n++;
6837
+ const next = [...list, blankSheet(`Sheet ${n}`)];
6838
+ setActive(next.length - 1);
6839
+ onChange?.(next);
6840
+ return next;
6841
+ });
6842
+ }, [onChange]);
6843
+ const baseName = React36.useMemo(
6754
6844
  () => (fileName || (typeof source === "object" && "name" in source ? sourceName(source) : null) || "spreadsheet").replace(/\.[^.]+$/, ""),
6755
6845
  [fileName, source]
6756
6846
  );
6757
- const sheetAoa = React34.useCallback((s) => {
6847
+ const sheetAoa = React36.useCallback((s) => {
6758
6848
  const cols = toColumns(s.columns);
6759
6849
  const header = cols.map((c) => typeof c.label === "string" ? c.label : c.key);
6760
6850
  const body = s.rows.map((r) => cols.map((c) => cellValue(r[c.key])));
6761
6851
  return [header, ...body];
6762
6852
  }, []);
6763
- const exportXlsx = React34.useCallback(async () => {
6853
+ const exportXlsx = React36.useCallback(async () => {
6764
6854
  if (!sheets) return;
6765
6855
  const XLSX = await loadXlsx();
6766
6856
  const wb = XLSX.utils.book_new();
@@ -6771,7 +6861,7 @@ function Spreadsheet({
6771
6861
  const out = XLSX.write(wb, { bookType: "xlsx", type: "array" });
6772
6862
  downloadBlob(new Blob([out], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" }), `${baseName}.xlsx`);
6773
6863
  }, [sheets, sheetAoa, baseName]);
6774
- const exportCsv = React34.useCallback(() => {
6864
+ const exportCsv = React36.useCallback(() => {
6775
6865
  if (!sheet) return;
6776
6866
  const aoa = sheetAoa(sheet);
6777
6867
  const esc = (v) => {
@@ -6781,7 +6871,7 @@ function Spreadsheet({
6781
6871
  const csv = aoa.map((row) => row.map(esc).join(",")).join("\r\n");
6782
6872
  downloadBlob(new Blob([`\uFEFF${csv}`], { type: "text/csv;charset=utf-8" }), `${baseName}.csv`);
6783
6873
  }, [sheet, sheetAoa, baseName]);
6784
- const exportPdf = React34.useCallback(async () => {
6874
+ const exportPdf = React36.useCallback(async () => {
6785
6875
  if (!sheet) return;
6786
6876
  const { jsPDF } = await loadJspdf();
6787
6877
  const doc = new jsPDF({ orientation: "landscape", unit: "pt", format: "a4" });
@@ -6822,16 +6912,16 @@ function Spreadsheet({
6822
6912
  else void exportPdf();
6823
6913
  };
6824
6914
  if (status === "error") {
6825
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx("flex flex-col items-center justify-center gap-3 rounded-lg border border-border bg-surface p-8 text-center", className), style, children: [
6915
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx("flex flex-col items-center justify-center gap-3 rounded-lg border border-border bg-surface p-8 text-center", className), style: { height, width, ...style }, children: [
6826
6916
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-status-error", children: "Couldn\u2019t load the spreadsheet" }),
6827
6917
  error?.message && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "max-w-md text-xs text-foreground-muted", children: error.message }),
6828
6918
  /* @__PURE__ */ jsxRuntime.jsx(Button_default, { content: "Retry", size: "sm", variant: "outline", onClick: () => setReloadKey((k) => k + 1) })
6829
6919
  ] });
6830
6920
  }
6831
6921
  if (status === "loading" || !sheets) {
6832
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx("rounded-lg border border-border bg-surface-raised p-4", className), style, children: [
6922
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx("overflow-hidden rounded-lg border border-border bg-surface-raised p-4", className), style: { height, width, ...style }, children: [
6833
6923
  /* @__PURE__ */ jsxRuntime.jsx(SkeletonBox, { height: 32, className: "mb-3 rounded" }),
6834
- /* @__PURE__ */ jsxRuntime.jsx(SkeletonBox, { height: 360, className: "rounded" })
6924
+ /* @__PURE__ */ jsxRuntime.jsx(SkeletonBox, { height: "calc(100% - 44px)", className: "rounded" })
6835
6925
  ] });
6836
6926
  }
6837
6927
  const formats = exportFormats || [];
@@ -6840,25 +6930,10 @@ function Spreadsheet({
6840
6930
  csv: "CSV \u2014 this sheet (.csv)",
6841
6931
  pdf: "PDF table (.pdf)"
6842
6932
  };
6843
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx("flex flex-col overflow-hidden rounded-lg border border-border bg-surface-raised", className), style, children: [
6844
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-shrink-0 items-center gap-2 border-b border-border bg-surface px-2 py-1.5", children: [
6845
- sheets.length > 1 ? /* @__PURE__ */ jsxRuntime.jsx("div", { role: "tablist", "aria-label": "Sheets", className: "flex min-w-0 flex-1 items-center gap-0.5 overflow-x-auto", children: sheets.map((s, i) => /* @__PURE__ */ jsxRuntime.jsx(
6846
- "button",
6847
- {
6848
- role: "tab",
6849
- type: "button",
6850
- "aria-selected": i === active,
6851
- onClick: () => setActive(i),
6852
- className: cx(
6853
- "flex-shrink-0 rounded-md px-3 py-1 text-sm font-medium transition-colors",
6854
- "focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
6855
- i === active ? "bg-accent text-accent-fg shadow-sm" : "text-foreground-secondary hover:bg-surface-raised hover:text-foreground"
6856
- ),
6857
- children: s.name || `Sheet ${i + 1}`
6858
- },
6859
- `${s.name}-${i}`
6860
- )) }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 truncate px-1 text-sm font-medium text-foreground", children: sheet?.name || "Sheet 1" }),
6861
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "hidden flex-shrink-0 px-1 text-xs tabular-nums text-foreground-muted sm:inline", children: [
6933
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx("flex flex-col overflow-hidden rounded-lg border border-border bg-surface-raised", className), style: { height, width, ...style }, children: [
6934
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-shrink-0 items-center gap-2 border-b border-border bg-surface px-3 py-1.5", children: [
6935
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate text-sm font-semibold text-foreground", children: sheet?.name || "Sheet 1" }),
6936
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "hidden flex-shrink-0 text-xs tabular-nums text-foreground-muted sm:inline", children: [
6862
6937
  plainRows.length.toLocaleString(),
6863
6938
  " ",
6864
6939
  plainRows.length === 1 ? "row" : "rows",
@@ -6885,22 +6960,58 @@ function Spreadsheet({
6885
6960
  )
6886
6961
  ] })
6887
6962
  ] }),
6888
- /* @__PURE__ */ jsxRuntime.jsx(
6963
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(
6889
6964
  DataGrid,
6890
6965
  {
6891
6966
  columns,
6892
6967
  rows: plainRows,
6893
6968
  editable,
6969
+ sortable,
6894
6970
  virtualize,
6971
+ trailingRows: emptyRows,
6895
6972
  onCellEdit: handleCellEdit,
6973
+ height: "100%",
6896
6974
  className: "!rounded-none !border-0"
6897
- }
6898
- )
6975
+ },
6976
+ active
6977
+ ) }),
6978
+ (sheets.length > 1 || canAddSheet) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-shrink-0 items-center gap-1 border-t border-border bg-surface px-2 py-1", children: [
6979
+ /* @__PURE__ */ jsxRuntime.jsx("div", { role: "tablist", "aria-label": "Sheets", className: "flex min-w-0 flex-1 items-center gap-1 overflow-x-auto", children: sheets.map((s, i) => {
6980
+ const activeTab = i === active;
6981
+ return /* @__PURE__ */ jsxRuntime.jsx(
6982
+ "button",
6983
+ {
6984
+ role: "tab",
6985
+ type: "button",
6986
+ "aria-selected": activeTab,
6987
+ onClick: () => setActive(i),
6988
+ className: cx(
6989
+ "flex-shrink-0 rounded-t-md border-t-2 px-3 py-1 text-xs transition-colors",
6990
+ "focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
6991
+ activeTab ? "border-t-accent bg-surface-raised font-semibold text-foreground shadow-sm" : "border-t-transparent font-medium text-foreground-secondary hover:bg-surface-raised hover:text-foreground"
6992
+ ),
6993
+ children: s.name || `Sheet ${i + 1}`
6994
+ },
6995
+ `${s.name}-${i}`
6996
+ );
6997
+ }) }),
6998
+ canAddSheet && /* @__PURE__ */ jsxRuntime.jsx(
6999
+ "button",
7000
+ {
7001
+ type: "button",
7002
+ onClick: addSheet,
7003
+ title: "Add sheet",
7004
+ "aria-label": "Add sheet",
7005
+ className: "flex h-6 w-6 flex-shrink-0 items-center justify-center rounded-md text-foreground-muted transition-colors hover:bg-surface-raised hover:text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
7006
+ children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", d: "M12 5v14M5 12h14" }) })
7007
+ }
7008
+ )
7009
+ ] })
6899
7010
  ] });
6900
7011
  }
6901
7012
  var DownloadIcon2 = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 3v12m0 0 4-4m-4 4-4-4M4 21h16" }) });
6902
7013
  function ThemeSwitch({ checked, onChange, label = "Toggle dark mode", className = "" }) {
6903
- const id = React34.useId();
7014
+ const id = React36.useId();
6904
7015
  return /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, className: `flex items-center gap-2 cursor-pointer select-none ${className}`.trim(), children: /* @__PURE__ */ jsxRuntime.jsx(
6905
7016
  SwitchPrimitive__namespace.Root,
6906
7017
  {
@@ -6998,8 +7109,8 @@ function FlyoutItems({ items }) {
6998
7109
  }) });
6999
7110
  }
7000
7111
  function CollapsedFlyout({ item, trigger }) {
7001
- const [open, setOpen] = React34.useState(false);
7002
- const closeTimer = React34__default.default.useRef(void 0);
7112
+ const [open, setOpen] = React36.useState(false);
7113
+ const closeTimer = React36__default.default.useRef(void 0);
7003
7114
  const openNow = () => {
7004
7115
  window.clearTimeout(closeTimer.current);
7005
7116
  setOpen(true);
@@ -7008,7 +7119,7 @@ function CollapsedFlyout({ item, trigger }) {
7008
7119
  window.clearTimeout(closeTimer.current);
7009
7120
  closeTimer.current = window.setTimeout(() => setOpen(false), 150);
7010
7121
  };
7011
- React34__default.default.useEffect(() => () => window.clearTimeout(closeTimer.current), []);
7122
+ React36__default.default.useEffect(() => () => window.clearTimeout(closeTimer.current), []);
7012
7123
  return /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu2__namespace.Root, { open, onOpenChange: setOpen, modal: false, children: [
7013
7124
  /* @__PURE__ */ jsxRuntime.jsx(
7014
7125
  DropdownMenu2__namespace.Trigger,
@@ -7046,7 +7157,7 @@ function NavItem({
7046
7157
  depth = 0
7047
7158
  }) {
7048
7159
  const hasChildren = !!(item.items && item.items.length);
7049
- const [open, setOpen] = React34.useState(item.defaultOpen ?? (hasChildren && hasActiveDescendant(item)));
7160
+ const [open, setOpen] = React36.useState(item.defaultOpen ?? (hasChildren && hasActiveDescendant(item)));
7050
7161
  const handleClick = () => {
7051
7162
  if (hasChildren && isExpanded) setOpen((o) => !o);
7052
7163
  item.onClick?.();
@@ -7184,7 +7295,7 @@ function Sidebar({
7184
7295
  }
7185
7296
  ) });
7186
7297
  }
7187
- var MegaMenuContext = React34.createContext({ align: "start" });
7298
+ var MegaMenuContext = React36.createContext({ align: "start" });
7188
7299
  function MegaMenu({
7189
7300
  children,
7190
7301
  align = "start",
@@ -7215,7 +7326,7 @@ function MegaMenu({
7215
7326
  }
7216
7327
  var TOP_ITEM = "group/top inline-flex items-center gap-1.5 h-10 px-3 rounded-md text-sm font-medium select-none text-foreground-secondary hover:text-foreground hover:bg-surface-raised data-[state=open]:text-accent data-[active]:text-accent transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-accent";
7217
7328
  function MegaMenuItem({ label, icon, href, children, className = "" }) {
7218
- const { align } = React34.useContext(MegaMenuContext);
7329
+ const { align } = React36.useContext(MegaMenuContext);
7219
7330
  const pos = align === "center" ? "left-1/2 -translate-x-1/2" : align === "end" ? "right-0" : "left-0";
7220
7331
  if (!children) {
7221
7332
  return /* @__PURE__ */ jsxRuntime.jsx(NavigationMenu__namespace.Item, { children: /* @__PURE__ */ jsxRuntime.jsxs(NavigationMenu__namespace.Link, { href, className: cx(TOP_ITEM, className), children: [
@@ -7300,8 +7411,8 @@ function MegaMenuLink({ href, icon, description, active, onClick, children, clas
7300
7411
  function MegaMenuFeatured({ children, className = "" }) {
7301
7412
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cx("min-w-0 rounded-lg bg-surface-raised border border-border p-4 flex flex-col", className), children });
7302
7413
  }
7303
- var elementsOfType = (children, type) => React34__default.default.Children.toArray(children).filter(
7304
- (c) => React34__default.default.isValidElement(c) && c.type === type
7414
+ var elementsOfType = (children, type) => React36__default.default.Children.toArray(children).filter(
7415
+ (c) => React36__default.default.isValidElement(c) && c.type === type
7305
7416
  );
7306
7417
  var MOBILE_CHEVRON = /* @__PURE__ */ jsxRuntime.jsx(
7307
7418
  "svg",
@@ -7338,9 +7449,9 @@ function MobileLinkRow({ link, onNavigate }) {
7338
7449
  );
7339
7450
  }
7340
7451
  function MobilePanel({ panel, onNavigate }) {
7341
- const nodes = React34__default.default.Children.toArray(panel.props.children);
7452
+ const nodes = React36__default.default.Children.toArray(panel.props.children);
7342
7453
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-4 px-2 pb-3 pt-1", children: nodes.map((node, i) => {
7343
- if (!React34__default.default.isValidElement(node)) return null;
7454
+ if (!React36__default.default.isValidElement(node)) return null;
7344
7455
  const el = node;
7345
7456
  if (el.type === MegaMenuSection) {
7346
7457
  const { title, children } = el.props;
@@ -7359,8 +7470,8 @@ function MegaMenuMobile({
7359
7470
  children,
7360
7471
  label
7361
7472
  }) {
7362
- const [open, setOpen] = React34.useState(false);
7363
- const [expanded, setExpanded] = React34.useState(null);
7473
+ const [open, setOpen] = React36.useState(false);
7474
+ const [expanded, setExpanded] = React36.useState(null);
7364
7475
  const items = elementsOfType(children, MegaMenuItem);
7365
7476
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "md:hidden w-full", children: [
7366
7477
  /* @__PURE__ */ jsxRuntime.jsxs(
@@ -7433,17 +7544,17 @@ function AppShell({
7433
7544
  children,
7434
7545
  className = ""
7435
7546
  }) {
7436
- const [expanded, setExpanded] = React34.useState(sidebarDefaultExpanded);
7437
- const [isMobile, setIsMobile] = React34.useState(false);
7438
- const [mobileOpen, setMobileOpen] = React34.useState(false);
7439
- React34.useEffect(() => {
7547
+ const [expanded, setExpanded] = React36.useState(sidebarDefaultExpanded);
7548
+ const [isMobile, setIsMobile] = React36.useState(false);
7549
+ const [mobileOpen, setMobileOpen] = React36.useState(false);
7550
+ React36.useEffect(() => {
7440
7551
  const mq = window.matchMedia("(max-width: 767px)");
7441
7552
  const update = (e) => setIsMobile(e.matches);
7442
7553
  update(mq);
7443
7554
  mq.addEventListener("change", update);
7444
7555
  return () => mq.removeEventListener("change", update);
7445
7556
  }, []);
7446
- React34.useEffect(() => {
7557
+ React36.useEffect(() => {
7447
7558
  if (!isMobile) setMobileOpen(false);
7448
7559
  }, [isMobile]);
7449
7560
  const hasSidebar = sidebarSections.length > 0;
@@ -7570,7 +7681,7 @@ function SecureLayout({
7570
7681
  className = ""
7571
7682
  }) {
7572
7683
  const reduced = framerMotion.useReducedMotion();
7573
- const cbs = React34.useRef({ canAccess, onGranted, onDeny });
7684
+ const cbs = React36.useRef({ canAccess, onGranted, onDeny });
7574
7685
  cbs.current = { canAccess, onGranted, onDeny };
7575
7686
  const rolesKey = JSON.stringify(roles);
7576
7687
  const requiredRolesKey = JSON.stringify(requiredRoles);
@@ -7585,10 +7696,10 @@ function SecureLayout({
7585
7696
  if (requiredPermissions?.length && !has(permissions, requiredPermissions, requireAllPermissions)) return false;
7586
7697
  return true;
7587
7698
  };
7588
- const [state, setState] = React34.useState(
7699
+ const [state, setState] = React36.useState(
7589
7700
  () => !passesSync() ? "denied" : canAccess ? "checking" : "granted"
7590
7701
  );
7591
- React34.useEffect(() => {
7702
+ React36.useEffect(() => {
7592
7703
  let cancelled = false;
7593
7704
  const { canAccess: check, onGranted: granted, onDeny: deny } = cbs.current;
7594
7705
  const finish = (ok) => {
@@ -7749,10 +7860,10 @@ function ThemeProvider({
7749
7860
  className = "",
7750
7861
  style
7751
7862
  }) {
7752
- const id = React34__default.default.useId().replace(/:/g, "");
7863
+ const id = React36__default.default.useId().replace(/:/g, "");
7753
7864
  const scopeClass = `geo-th-${id}`;
7754
- const divRef = React34.useRef(null);
7755
- React34.useEffect(() => {
7865
+ const divRef = React36.useRef(null);
7866
+ React36.useEffect(() => {
7756
7867
  const el = divRef.current;
7757
7868
  if (!el) return;
7758
7869
  if (colorScheme === "auto") return;
@@ -7767,8 +7878,8 @@ function ThemeProvider({
7767
7878
  }
7768
7879
  el.classList.toggle("dark", colorScheme === "dark");
7769
7880
  }, [colorScheme]);
7770
- const lightVars = React34.useMemo(() => toCssVars(theme), [theme]);
7771
- const darkVarStr = React34.useMemo(() => {
7881
+ const lightVars = React36.useMemo(() => toCssVars(theme), [theme]);
7882
+ const darkVarStr = React36.useMemo(() => {
7772
7883
  if (!darkTheme) return "";
7773
7884
  const dvars = toCssVars(darkTheme);
7774
7885
  if (!Object.keys(dvars).length) return "";
@@ -7810,7 +7921,7 @@ function NumberInput({
7810
7921
  readOnly = false,
7811
7922
  precision
7812
7923
  }) {
7813
- const errorId = React34.useId();
7924
+ const errorId = React36.useId();
7814
7925
  const hasError = errorMessage != null;
7815
7926
  const inferredPrecision = precision ?? (Number.isInteger(step) ? 0 : String(step).split(".")[1]?.length ?? 0);
7816
7927
  const round = (n) => {
@@ -7941,8 +8052,8 @@ function Password({
7941
8052
  showIcon,
7942
8053
  hideIcon
7943
8054
  }) {
7944
- const [visible, setVisible] = React34.useState(false);
7945
- const errorId = React34.useId();
8055
+ const [visible, setVisible] = React36.useState(false);
8056
+ const errorId = React36.useId();
7946
8057
  const hasError = errorMessage != null;
7947
8058
  return /* @__PURE__ */ jsxRuntime.jsx(
7948
8059
  Field,
@@ -8042,7 +8153,7 @@ function PasswordStrength({
8042
8153
  className = "",
8043
8154
  style
8044
8155
  }) {
8045
- const { score, label } = React34.useMemo(() => scorer(value), [scorer, value]);
8156
+ const { score, label } = React36.useMemo(() => scorer(value), [scorer, value]);
8046
8157
  const showMatch = confirmValue != null && (value.length > 0 || confirmValue.length > 0);
8047
8158
  const matches = value.length > 0 && value === confirmValue;
8048
8159
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx("flex flex-col gap-2", className), style, "aria-live": "polite", children: [
@@ -8101,8 +8212,8 @@ function RadioTile({
8101
8212
  errorMessage,
8102
8213
  className
8103
8214
  }) {
8104
- const groupId = React34.useId();
8105
- const errorId = React34.useId();
8215
+ const groupId = React36.useId();
8216
+ const errorId = React36.useId();
8106
8217
  const hasError = errorMessage != null;
8107
8218
  return /* @__PURE__ */ jsxRuntime.jsx(
8108
8219
  Field,
@@ -8177,7 +8288,7 @@ function Checkbox({
8177
8288
  }) {
8178
8289
  const isChecked = checked ?? value ?? false;
8179
8290
  const labelFirst = labelPosition === "left";
8180
- const errorId = React34.useId();
8291
+ const errorId = React36.useId();
8181
8292
  const hasError = errorMessage != null;
8182
8293
  const box = /* @__PURE__ */ jsxRuntime.jsx(
8183
8294
  CheckboxPrimitive__namespace.Root,
@@ -8285,8 +8396,8 @@ function RadioGroup({
8285
8396
  className,
8286
8397
  errorMessage
8287
8398
  }) {
8288
- const errorId = React34.useId();
8289
- const groupId = React34.useId();
8399
+ const errorId = React36.useId();
8400
+ const groupId = React36.useId();
8290
8401
  const hasError = errorMessage != null;
8291
8402
  const labelFirst = labelPosition === "left";
8292
8403
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -8386,11 +8497,11 @@ function Switch({
8386
8497
  disabled,
8387
8498
  errorMessage
8388
8499
  }) {
8389
- const id = React34.useId();
8390
- const errorId = React34.useId();
8500
+ const id = React36.useId();
8501
+ const errorId = React36.useId();
8391
8502
  const hasError = errorMessage != null;
8392
8503
  const isControlled = checked !== void 0;
8393
- const [internal, setInternal] = React34.useState(defaultChecked);
8504
+ const [internal, setInternal] = React36.useState(defaultChecked);
8394
8505
  const isOn = isControlled ? checked : internal;
8395
8506
  const handle = (c) => {
8396
8507
  if (!isControlled) setInternal(c);
@@ -8466,11 +8577,11 @@ function MultiTagRow({
8466
8577
  labelFor,
8467
8578
  onRemove
8468
8579
  }) {
8469
- const wrapRef = React34.useRef(null);
8470
- const measureRef = React34.useRef(null);
8471
- const [visibleCount, setVisibleCount] = React34.useState(values.length);
8580
+ const wrapRef = React36.useRef(null);
8581
+ const measureRef = React36.useRef(null);
8582
+ const [visibleCount, setVisibleCount] = React36.useState(values.length);
8472
8583
  const key = values.map(String).join("|");
8473
- React34.useLayoutEffect(() => {
8584
+ React36.useLayoutEffect(() => {
8474
8585
  const wrap = wrapRef.current;
8475
8586
  const measure = measureRef.current;
8476
8587
  if (!wrap || !measure) return;
@@ -8562,18 +8673,21 @@ function Dropdown({
8562
8673
  labelStyle = {},
8563
8674
  placeholder,
8564
8675
  size = "md",
8565
- className = ""
8676
+ className = "",
8677
+ container
8566
8678
  }) {
8567
- const [open, setOpen] = React34.useState(false);
8568
- const [selectedItems, setSelectedItems] = React34.useState([]);
8569
- const [searchTerm, setSearchTerm] = React34.useState("");
8570
- const [innerItems, setInnerItems] = React34.useState([]);
8571
- const errorId = React34.useId();
8679
+ const dialogContainer = useDialogContainer();
8680
+ const portalContainer = container ?? dialogContainer ?? void 0;
8681
+ const [open, setOpen] = React36.useState(false);
8682
+ const [selectedItems, setSelectedItems] = React36.useState([]);
8683
+ const [searchTerm, setSearchTerm] = React36.useState("");
8684
+ const [innerItems, setInnerItems] = React36.useState([]);
8685
+ const errorId = React36.useId();
8572
8686
  const hasError = errorMessage != null;
8573
- React34.useEffect(() => {
8687
+ React36.useEffect(() => {
8574
8688
  setInnerItems(items);
8575
8689
  }, [items]);
8576
- React34.useEffect(() => {
8690
+ React36.useEffect(() => {
8577
8691
  if (isMultiselect && Array.isArray(value)) {
8578
8692
  setSelectedItems(value);
8579
8693
  }
@@ -8669,7 +8783,7 @@ function Dropdown({
8669
8783
  ]
8670
8784
  }
8671
8785
  ) }),
8672
- /* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs(
8786
+ /* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsxs(
8673
8787
  Popover__namespace.Content,
8674
8788
  {
8675
8789
  align: "start",
@@ -8766,19 +8880,19 @@ function AutoComplete({
8766
8880
  required,
8767
8881
  htmlFor
8768
8882
  }) {
8769
- const errorId = React34.useId();
8883
+ const errorId = React36.useId();
8770
8884
  const hasError = errorMessage != null;
8771
- const [term, setTerm] = React34.useState("");
8772
- const [open, setOpen] = React34.useState(false);
8773
- const [asyncItems, setAsyncItems] = React34.useState([]);
8774
- const [loading, setLoading] = React34.useState(false);
8885
+ const [term, setTerm] = React36.useState("");
8886
+ const [open, setOpen] = React36.useState(false);
8887
+ const [asyncItems, setAsyncItems] = React36.useState([]);
8888
+ const [loading, setLoading] = React36.useState(false);
8775
8889
  const isAsync = typeof onSearch === "function";
8776
- const debounceRef = React34.useRef(null);
8777
- const requestIdRef = React34.useRef(0);
8890
+ const debounceRef = React36.useRef(null);
8891
+ const requestIdRef = React36.useRef(0);
8778
8892
  const staticFiltered = isAsync || !items ? [] : term.trim() ? items.filter(
8779
8893
  ({ key, label: label2 }) => label2.toLowerCase().includes(term.toLowerCase()) || key.toLowerCase().includes(term.toLowerCase())
8780
8894
  ) : [];
8781
- React34.useEffect(() => {
8895
+ React36.useEffect(() => {
8782
8896
  if (!isAsync) return;
8783
8897
  if (debounceRef.current) clearTimeout(debounceRef.current);
8784
8898
  if (!term.trim()) {
@@ -8935,15 +9049,15 @@ function TreeSelect({
8935
9049
  defaultExpandedKeys = [],
8936
9050
  size = "md"
8937
9051
  }) {
8938
- const errorId = React34.useId();
9052
+ const errorId = React36.useId();
8939
9053
  const hasError = errorMessage != null;
8940
- const [open, setOpen] = React34.useState(false);
8941
- const [expanded, setExpanded] = React34.useState(() => new Set(defaultExpandedKeys));
8942
- const [activeIndex, setActiveIndex] = React34.useState(0);
8943
- const listRef = React34.useRef(null);
8944
- const visible = React34.useMemo(() => flattenVisible(items, expanded), [items, expanded]);
8945
- const didSyncOnOpenRef = React34.useRef(false);
8946
- React34.useEffect(() => {
9054
+ const [open, setOpen] = React36.useState(false);
9055
+ const [expanded, setExpanded] = React36.useState(() => new Set(defaultExpandedKeys));
9056
+ const [activeIndex, setActiveIndex] = React36.useState(0);
9057
+ const listRef = React36.useRef(null);
9058
+ const visible = React36.useMemo(() => flattenVisible(items, expanded), [items, expanded]);
9059
+ const didSyncOnOpenRef = React36.useRef(false);
9060
+ React36.useEffect(() => {
8947
9061
  if (!open) {
8948
9062
  didSyncOnOpenRef.current = false;
8949
9063
  return;
@@ -8953,7 +9067,7 @@ function TreeSelect({
8953
9067
  setActiveIndex(selectedIdx >= 0 ? selectedIdx : 0);
8954
9068
  didSyncOnOpenRef.current = true;
8955
9069
  }, [open, value]);
8956
- const selectedNode = React34.useMemo(
9070
+ const selectedNode = React36.useMemo(
8957
9071
  () => value != null ? findNodeByKey(items, value) : null,
8958
9072
  [items, value]
8959
9073
  );
@@ -9185,11 +9299,11 @@ function FileInput({
9185
9299
  required,
9186
9300
  icon
9187
9301
  }) {
9188
- const inputRef = React34.useRef(null);
9189
- const errorId = React34.useId();
9190
- const [files, setFiles] = React34.useState([]);
9191
- const [dragging, setDragging] = React34.useState(false);
9192
- const [sizeError, setSizeError] = React34.useState(null);
9302
+ const inputRef = React36.useRef(null);
9303
+ const errorId = React36.useId();
9304
+ const [files, setFiles] = React36.useState([]);
9305
+ const [dragging, setDragging] = React36.useState(false);
9306
+ const [sizeError, setSizeError] = React36.useState(null);
9193
9307
  const effectiveError = errorMessage ?? sizeError ?? void 0;
9194
9308
  const openPicker = () => {
9195
9309
  if (!disabled) inputRef.current?.click();
@@ -9380,30 +9494,30 @@ function DatePicker({
9380
9494
  size = "md",
9381
9495
  className = ""
9382
9496
  }) {
9383
- const errorId = React34.useId();
9497
+ const errorId = React36.useId();
9384
9498
  const hasError = errorMessage != null;
9385
- const [open, setOpen] = React34.useState(false);
9386
- const [viewMonth, setViewMonth] = React34.useState(() => startOfMonth2(value ?? /* @__PURE__ */ new Date()));
9387
- const [focusDate, setFocusDate] = React34.useState(() => value ?? /* @__PURE__ */ new Date());
9388
- const [view, setView] = React34.useState("days");
9389
- const gridRef = React34.useRef(null);
9390
- React34.useEffect(() => {
9499
+ const [open, setOpen] = React36.useState(false);
9500
+ const [viewMonth, setViewMonth] = React36.useState(() => startOfMonth2(value ?? /* @__PURE__ */ new Date()));
9501
+ const [focusDate, setFocusDate] = React36.useState(() => value ?? /* @__PURE__ */ new Date());
9502
+ const [view, setView] = React36.useState("days");
9503
+ const gridRef = React36.useRef(null);
9504
+ React36.useEffect(() => {
9391
9505
  if (!open) return;
9392
9506
  const target = value ?? /* @__PURE__ */ new Date();
9393
9507
  setViewMonth(startOfMonth2(target));
9394
9508
  setFocusDate(target);
9395
9509
  setView("days");
9396
9510
  }, [open, value]);
9397
- React34.useEffect(() => {
9511
+ React36.useEffect(() => {
9398
9512
  if (!open) return;
9399
9513
  const cell = gridRef.current?.querySelector(`[data-day="${defaultFormat3(focusDate)}"]`);
9400
9514
  cell?.focus();
9401
9515
  }, [open, focusDate]);
9402
- const weekdays = React34.useMemo(() => {
9516
+ const weekdays = React36.useMemo(() => {
9403
9517
  const ordered = WEEKDAY_SHORT.slice(weekStartsOn).concat(WEEKDAY_SHORT.slice(0, weekStartsOn));
9404
9518
  return ordered;
9405
9519
  }, [weekStartsOn]);
9406
- const grid = React34.useMemo(() => buildGrid(viewMonth, weekStartsOn), [viewMonth, weekStartsOn]);
9520
+ const grid = React36.useMemo(() => buildGrid(viewMonth, weekStartsOn), [viewMonth, weekStartsOn]);
9407
9521
  const isDisabled = (d) => {
9408
9522
  if (min && d < min) return true;
9409
9523
  if (max && d > max) return true;
@@ -9694,10 +9808,10 @@ function TextArea({
9694
9808
  style,
9695
9809
  inputStyle
9696
9810
  }) {
9697
- const errorId = React34.useId();
9811
+ const errorId = React36.useId();
9698
9812
  const hasError = errorMessage != null;
9699
- const ref = React34.useRef(null);
9700
- React34.useLayoutEffect(() => {
9813
+ const ref = React36.useRef(null);
9814
+ React36.useLayoutEffect(() => {
9701
9815
  if (!autoGrow) return;
9702
9816
  const el = ref.current;
9703
9817
  if (!el) return;
@@ -9769,14 +9883,14 @@ function Slider({
9769
9883
  name,
9770
9884
  htmlFor
9771
9885
  }) {
9772
- const errorId = React34.useId();
9886
+ const errorId = React36.useId();
9773
9887
  const hasError = errorMessage != null;
9774
9888
  const isRange = Array.isArray(value ?? defaultValue);
9775
- const [internal, setInternal] = React34.useState(
9889
+ const [internal, setInternal] = React36.useState(
9776
9890
  () => toArray(value) ?? toArray(defaultValue) ?? [min]
9777
9891
  );
9778
9892
  const current = toArray(value) ?? internal;
9779
- const [dragging, setDragging] = React34.useState(false);
9893
+ const [dragging, setDragging] = React36.useState(false);
9780
9894
  const emit = (arr) => {
9781
9895
  setInternal(arr);
9782
9896
  const next = isRange ? [arr[0], arr[1]] : arr[0];
@@ -9871,11 +9985,11 @@ function TagsInput({
9871
9985
  validate,
9872
9986
  separators = ["Enter", ","]
9873
9987
  }) {
9874
- const errorId = React34.useId();
9875
- const inputRef = React34.useRef(null);
9876
- const [internal, setInternal] = React34.useState(defaultValue ?? []);
9877
- const [draft, setDraft] = React34.useState("");
9878
- const [localError, setLocalError] = React34.useState(null);
9988
+ const errorId = React36.useId();
9989
+ const inputRef = React36.useRef(null);
9990
+ const [internal, setInternal] = React36.useState(defaultValue ?? []);
9991
+ const [draft, setDraft] = React36.useState("");
9992
+ const [localError, setLocalError] = React36.useState(null);
9879
9993
  const tags = value ?? internal;
9880
9994
  const hasError = errorMessage != null || localError != null;
9881
9995
  const errorText = errorMessage ?? localError ?? void 0;
@@ -10006,9 +10120,9 @@ function OtpInput({
10006
10120
  className,
10007
10121
  groupAfter
10008
10122
  }) {
10009
- const errorId = React34.useId();
10123
+ const errorId = React36.useId();
10010
10124
  const hasError = errorMessage != null;
10011
- const refs = React34.useRef([]);
10125
+ const refs = React36.useRef([]);
10012
10126
  const chars = Array.from({ length }, (_, i) => value[i] ?? "");
10013
10127
  const pattern = mode === "numeric" ? /[0-9]/ : /[a-zA-Z0-9]/;
10014
10128
  const emit = (next) => {
@@ -10057,7 +10171,7 @@ function OtpInput({
10057
10171
  emit(valid.join(""));
10058
10172
  focusBox(valid.length);
10059
10173
  };
10060
- return /* @__PURE__ */ jsxRuntime.jsx(Field, { className, label, htmlFor, errorId, errorMessage, required, layout, helperText, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap items-center gap-2", role: "group", "aria-label": typeof label === "string" ? label : "One-time code", children: chars.map((char, idx) => /* @__PURE__ */ jsxRuntime.jsxs(React34__default.default.Fragment, { children: [
10174
+ return /* @__PURE__ */ jsxRuntime.jsx(Field, { className, label, htmlFor, errorId, errorMessage, required, layout, helperText, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap items-center gap-2", role: "group", "aria-label": typeof label === "string" ? label : "One-time code", children: chars.map((char, idx) => /* @__PURE__ */ jsxRuntime.jsxs(React36__default.default.Fragment, { children: [
10061
10175
  /* @__PURE__ */ jsxRuntime.jsx(
10062
10176
  "input",
10063
10177
  {
@@ -10115,9 +10229,9 @@ function Rating({
10115
10229
  className,
10116
10230
  required
10117
10231
  }) {
10118
- const errorId = React34.useId();
10119
- const [internal, setInternal] = React34.useState(defaultValue);
10120
- const [hover, setHover] = React34.useState(null);
10232
+ const errorId = React36.useId();
10233
+ const [internal, setInternal] = React36.useState(defaultValue);
10234
+ const [hover, setHover] = React36.useState(null);
10121
10235
  const current = value ?? internal;
10122
10236
  const display2 = hover ?? current;
10123
10237
  const interactive = !readOnly && !disabled;
@@ -10240,9 +10354,9 @@ function TimePicker({
10240
10354
  required,
10241
10355
  style
10242
10356
  }) {
10243
- const errorId = React34.useId();
10357
+ const errorId = React36.useId();
10244
10358
  const hasError = errorMessage != null;
10245
- const [open, setOpen] = React34.useState(false);
10359
+ const [open, setOpen] = React36.useState(false);
10246
10360
  const parsed = parse(value) ?? { h: 0, m: 0, s: 0 };
10247
10361
  const update = (next) => {
10248
10362
  const merged = { ...parsed, ...next };
@@ -10367,13 +10481,13 @@ function DateRangePicker({
10367
10481
  required,
10368
10482
  style
10369
10483
  }) {
10370
- const errorId = React34.useId();
10484
+ const errorId = React36.useId();
10371
10485
  const hasError = errorMessage != null;
10372
- const [open, setOpen] = React34.useState(false);
10373
- const [leftMonth, setLeftMonth] = React34.useState(() => startOfMonth3(value.start ?? /* @__PURE__ */ new Date()));
10374
- const [pendingStart, setPendingStart] = React34.useState(null);
10375
- const [hoverDate, setHoverDate] = React34.useState(null);
10376
- const weekdays = React34.useMemo(
10486
+ const [open, setOpen] = React36.useState(false);
10487
+ const [leftMonth, setLeftMonth] = React36.useState(() => startOfMonth3(value.start ?? /* @__PURE__ */ new Date()));
10488
+ const [pendingStart, setPendingStart] = React36.useState(null);
10489
+ const [hoverDate, setHoverDate] = React36.useState(null);
10490
+ const weekdays = React36.useMemo(
10377
10491
  () => WEEKDAY.slice(weekStartsOn).concat(WEEKDAY.slice(0, weekStartsOn)),
10378
10492
  [weekStartsOn]
10379
10493
  );
@@ -10550,10 +10664,10 @@ function ColorPicker({
10550
10664
  required,
10551
10665
  placeholder = "Pick a colour\u2026"
10552
10666
  }) {
10553
- const errorId = React34.useId();
10667
+ const errorId = React36.useId();
10554
10668
  const hasError = errorMessage != null;
10555
- const [open, setOpen] = React34.useState(false);
10556
- const [draft, setDraft] = React34.useState(value);
10669
+ const [open, setOpen] = React36.useState(false);
10670
+ const [draft, setDraft] = React36.useState(value);
10557
10671
  const valid = HEX_RE.test(value);
10558
10672
  const pick = (hex) => {
10559
10673
  onChange?.(hex);
@@ -10641,7 +10755,7 @@ function ColorPicker({
10641
10755
  }
10642
10756
  var CUSTOM_EVENT = "oxy-local-storage";
10643
10757
  function useLocalStorage(key, initialValue) {
10644
- const read = React34.useCallback(() => {
10758
+ const read = React36.useCallback(() => {
10645
10759
  if (typeof window === "undefined") return initialValue;
10646
10760
  try {
10647
10761
  const item = window.localStorage.getItem(key);
@@ -10650,8 +10764,8 @@ function useLocalStorage(key, initialValue) {
10650
10764
  return initialValue;
10651
10765
  }
10652
10766
  }, [key]);
10653
- const [stored, setStored] = React34.useState(read);
10654
- const setValue = React34.useCallback((value) => {
10767
+ const [stored, setStored] = React36.useState(read);
10768
+ const setValue = React36.useCallback((value) => {
10655
10769
  setStored((prev) => {
10656
10770
  const next = value instanceof Function ? value(prev) : value;
10657
10771
  try {
@@ -10664,7 +10778,7 @@ function useLocalStorage(key, initialValue) {
10664
10778
  return next;
10665
10779
  });
10666
10780
  }, [key]);
10667
- const remove = React34.useCallback(() => {
10781
+ const remove = React36.useCallback(() => {
10668
10782
  try {
10669
10783
  if (typeof window !== "undefined") {
10670
10784
  window.localStorage.removeItem(key);
@@ -10674,10 +10788,10 @@ function useLocalStorage(key, initialValue) {
10674
10788
  }
10675
10789
  setStored(initialValue);
10676
10790
  }, [key]);
10677
- React34.useEffect(() => {
10791
+ React36.useEffect(() => {
10678
10792
  setStored(read());
10679
10793
  }, [key, read]);
10680
- React34.useEffect(() => {
10794
+ React36.useEffect(() => {
10681
10795
  if (typeof window === "undefined") return;
10682
10796
  const onStorage = (e) => {
10683
10797
  if (e.key === null || e.key === key) setStored(read());
@@ -10696,8 +10810,8 @@ function useLocalStorage(key, initialValue) {
10696
10810
  }
10697
10811
  function useMediaQuery(query) {
10698
10812
  const get = () => typeof window !== "undefined" && typeof window.matchMedia === "function" ? window.matchMedia(query).matches : false;
10699
- const [matches, setMatches] = React34.useState(get);
10700
- React34.useEffect(() => {
10813
+ const [matches, setMatches] = React36.useState(get);
10814
+ React36.useEffect(() => {
10701
10815
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
10702
10816
  const mql = window.matchMedia(query);
10703
10817
  const onChange = () => setMatches(mql.matches);
@@ -10728,8 +10842,8 @@ function decodeSegment(seg) {
10728
10842
  }
10729
10843
  }
10730
10844
  function useJwt(token) {
10731
- const [, tick] = React34.useState(0);
10732
- const decoded = React34.useMemo(() => {
10845
+ const [, tick] = React36.useState(0);
10846
+ const decoded = React36.useMemo(() => {
10733
10847
  if (!token) return { payload: null, header: null, exp: null };
10734
10848
  const [h, p] = token.split(".");
10735
10849
  const header = decodeSegment(h);
@@ -10737,7 +10851,7 @@ function useJwt(token) {
10737
10851
  const exp = payload && typeof payload.exp === "number" ? payload.exp : null;
10738
10852
  return { payload, header, exp };
10739
10853
  }, [token]);
10740
- React34.useEffect(() => {
10854
+ React36.useEffect(() => {
10741
10855
  if (decoded.exp == null) return;
10742
10856
  const ms = decoded.exp * 1e3 - Date.now();
10743
10857
  if (ms <= 0) return;
@@ -10911,13 +11025,13 @@ function SlideShow({
10911
11025
  style
10912
11026
  }) {
10913
11027
  const reduced = framerMotion.useReducedMotion();
10914
- const [index, setIndex] = React34.useState(0);
10915
- const [paused, setPaused] = React34.useState(false);
11028
+ const [index, setIndex] = React36.useState(0);
11029
+ const [paused, setPaused] = React36.useState(false);
10916
11030
  const count = slides.length;
10917
11031
  const idx = count ? (index % count + count) % count : 0;
10918
- const go = React34.useCallback((d) => setIndex((i) => i + d), []);
10919
- const timer = React34.useRef(null);
10920
- React34.useEffect(() => {
11032
+ const go = React36.useCallback((d) => setIndex((i) => i + d), []);
11033
+ const timer = React36.useRef(null);
11034
+ React36.useEffect(() => {
10921
11035
  if (!autoPlay || paused || count <= 1) return;
10922
11036
  timer.current = setInterval(() => setIndex((i) => i + 1), interval);
10923
11037
  return () => {
@@ -10993,7 +11107,7 @@ function Video({
10993
11107
  className = "",
10994
11108
  style
10995
11109
  }) {
10996
- const [playing, setPlaying] = React34.useState(autoPlay);
11110
+ const [playing, setPlaying] = React36.useState(autoPlay);
10997
11111
  const frame = cx("relative w-full overflow-hidden bg-backdrop", framed ? "rounded-2xl border border-border shadow-sm" : "", className);
10998
11112
  const ratio = aspect.replace("/", " / ");
10999
11113
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: frame, style: { aspectRatio: ratio, ...style }, children: embedUrl ? /* @__PURE__ */ jsxRuntime.jsx(
@@ -11048,7 +11162,7 @@ function Parallax({
11048
11162
  style
11049
11163
  }) {
11050
11164
  const reduced = framerMotion.useReducedMotion();
11051
- const ref = React34.useRef(null);
11165
+ const ref = React36.useRef(null);
11052
11166
  const { scrollYProgress } = framerMotion.useScroll({ target: ref, offset: ["start end", "end start"] });
11053
11167
  const shift = Math.max(0, Math.min(1, speed)) * 100;
11054
11168
  const y = framerMotion.useTransform(scrollYProgress, [0, 1], reduced ? ["0%", "0%"] : [`-${shift / 2}%`, `${shift / 2}%`]);
@@ -11116,7 +11230,7 @@ function Blog({
11116
11230
  post.tag != null && !post.image && /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(Badge, { tone: "accent", variant: "soft", size: "sm", children: post.tag }) }),
11117
11231
  /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-base font-semibold leading-snug text-foreground transition-colors group-hover:text-accent", children: post.title }),
11118
11232
  post.excerpt != null && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "line-clamp-3 text-sm leading-relaxed text-foreground-secondary", children: post.excerpt }),
11119
- meta.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-auto flex flex-wrap items-center gap-x-2 gap-y-1 pt-3 text-xs text-foreground-muted", children: meta.map((m, j) => /* @__PURE__ */ jsxRuntime.jsxs(React34__default.default.Fragment, { children: [
11233
+ meta.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-auto flex flex-wrap items-center gap-x-2 gap-y-1 pt-3 text-xs text-foreground-muted", children: meta.map((m, j) => /* @__PURE__ */ jsxRuntime.jsxs(React36__default.default.Fragment, { children: [
11120
11234
  j > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: "\xB7" }),
11121
11235
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: m })
11122
11236
  ] }, j)) })
@@ -11245,8 +11359,8 @@ function LeadCapture({
11245
11359
  className = "",
11246
11360
  style
11247
11361
  }) {
11248
- const [email, setEmail] = React34.useState("");
11249
- const [done, setDone] = React34.useState(false);
11362
+ const [email, setEmail] = React36.useState("");
11363
+ const [done, setDone] = React36.useState(false);
11250
11364
  const submit = (e) => {
11251
11365
  e.preventDefault();
11252
11366
  const value = email.trim();