@geomak/ui 6.27.0 → 6.27.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  var chunkOAV4TA4B_cjs = require('./chunk-OAV4TA4B.cjs');
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
- var React29 = require('react');
5
+ var React28 = require('react');
6
6
  var reactDom = require('react-dom');
7
7
  var AvatarPrimitive = require('@radix-ui/react-avatar');
8
8
  var DropdownMenu = require('@radix-ui/react-dropdown-menu');
@@ -40,7 +40,7 @@ function _interopNamespace(e) {
40
40
  return Object.freeze(n);
41
41
  }
42
42
 
43
- var React29__default = /*#__PURE__*/_interopDefault(React29);
43
+ var React28__default = /*#__PURE__*/_interopDefault(React28);
44
44
  var AvatarPrimitive__namespace = /*#__PURE__*/_interopNamespace(AvatarPrimitive);
45
45
  var DropdownMenu__namespace = /*#__PURE__*/_interopNamespace(DropdownMenu);
46
46
  var Dialog__namespace = /*#__PURE__*/_interopNamespace(Dialog);
@@ -216,8 +216,8 @@ Icon.Copy = Copy;
216
216
  Icon.CircleStack = CircleStack;
217
217
  var icons_default = Icon;
218
218
  function Portal({ children, target }) {
219
- const [resolved, setResolved] = React29.useState(null);
220
- React29.useEffect(() => {
219
+ const [resolved, setResolved] = React28.useState(null);
220
+ React28.useEffect(() => {
221
221
  if (target === null) {
222
222
  setResolved(null);
223
223
  return;
@@ -651,7 +651,7 @@ function IconButton({
651
651
  className = "",
652
652
  style
653
653
  }) {
654
- const colorScheme = React29.useMemo(() => {
654
+ const colorScheme = React28.useMemo(() => {
655
655
  if (type === "primary") {
656
656
  return "bg-accent text-accent-fg hover:bg-accent-hover";
657
657
  }
@@ -730,7 +730,7 @@ var SIZE_CLASSES = {
730
730
  md: "h-9 px-4 text-sm gap-1.5 rounded-lg",
731
731
  lg: "h-11 px-5 text-sm gap-2 rounded-xl"
732
732
  };
733
- var Button = React29__default.default.forwardRef(function Button2({
733
+ var Button = React28__default.default.forwardRef(function Button2({
734
734
  content,
735
735
  variant = "primary",
736
736
  size = "md",
@@ -838,7 +838,7 @@ function MenuButton({
838
838
  "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
839
839
  "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95"
840
840
  ].join(" "),
841
- children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(React29__default.default.Fragment, { children: [
841
+ children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(React28__default.default.Fragment, { children: [
842
842
  item.separatorBefore && /* @__PURE__ */ jsxRuntime.jsx(DropdownMenu__namespace.Separator, { className: "my-1 h-px bg-border" }),
843
843
  /* @__PURE__ */ jsxRuntime.jsxs(
844
844
  DropdownMenu__namespace.Item,
@@ -1081,9 +1081,9 @@ function Tooltip({
1081
1081
  ] }) });
1082
1082
  }
1083
1083
  var TooltipProvider = TooltipPrimitive__namespace.Provider;
1084
- var TabsContext = React29.createContext(null);
1084
+ var TabsContext = React28.createContext(null);
1085
1085
  function useTabsContext() {
1086
- const ctx = React29.useContext(TabsContext);
1086
+ const ctx = React28.useContext(TabsContext);
1087
1087
  if (!ctx) throw new Error("Tabs.List / Tabs.Trigger / Tabs.Panel must be rendered inside <Tabs>.");
1088
1088
  return ctx;
1089
1089
  }
@@ -1105,26 +1105,26 @@ function Tabs({
1105
1105
  children
1106
1106
  }) {
1107
1107
  const isControlled = value !== void 0;
1108
- const [internal, setInternal] = React29.useState(defaultValue);
1108
+ const [internal, setInternal] = React28.useState(defaultValue);
1109
1109
  const current = isControlled ? value : internal;
1110
1110
  const reduced = !!framerMotion.useReducedMotion();
1111
- const indicatorId = React29.useId();
1112
- const select = React29.useCallback((next) => {
1111
+ const indicatorId = React28.useId();
1112
+ const select = React28.useCallback((next) => {
1113
1113
  if (!isControlled) setInternal(next);
1114
1114
  onValueChange?.(next);
1115
1115
  }, [isControlled, onValueChange]);
1116
- const registry = React29.useRef(/* @__PURE__ */ new Map());
1117
- const orderRef = React29.useRef(0);
1118
- const [, bump] = React29.useState(0);
1119
- const registerTab = React29.useCallback((val, meta) => {
1116
+ const registry = React28.useRef(/* @__PURE__ */ new Map());
1117
+ const orderRef = React28.useRef(0);
1118
+ const [, bump] = React28.useState(0);
1119
+ const registerTab = React28.useCallback((val, meta) => {
1120
1120
  const existing = registry.current.get(val);
1121
1121
  registry.current.set(val, { ...meta, order: existing?.order ?? orderRef.current++ });
1122
1122
  if (!existing) bump((v) => v + 1);
1123
1123
  }, []);
1124
- const unregisterTab = React29.useCallback((val) => {
1124
+ const unregisterTab = React28.useCallback((val) => {
1125
1125
  if (registry.current.delete(val)) bump((v) => v + 1);
1126
1126
  }, []);
1127
- const getTabs = React29.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 })), []);
1127
+ const getTabs = React28.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 })), []);
1128
1128
  return /* @__PURE__ */ jsxRuntime.jsx(TabsContext.Provider, { value: { value: current, variant, size, orientation, indicatorId, reduced, select, registerTab, unregisterTab, getTabs }, children: /* @__PURE__ */ jsxRuntime.jsx(
1129
1129
  TabsPrimitive__namespace.Root,
1130
1130
  {
@@ -1144,10 +1144,10 @@ function Tabs({
1144
1144
  function TabsList({ children, "aria-label": ariaLabel, className = "" }) {
1145
1145
  const { variant, orientation, reduced, value } = useTabsContext();
1146
1146
  const horizontal = orientation === "horizontal";
1147
- const scrollRef = React29.useRef(null);
1148
- const [edges, setEdges] = React29.useState({ start: false, end: false });
1147
+ const scrollRef = React28.useRef(null);
1148
+ const [edges, setEdges] = React28.useState({ start: false, end: false });
1149
1149
  const scrollable = variant !== "segmented";
1150
- React29.useLayoutEffect(() => {
1150
+ React28.useLayoutEffect(() => {
1151
1151
  const el = scrollRef.current;
1152
1152
  if (!el || !scrollable) return;
1153
1153
  const update = () => {
@@ -1172,13 +1172,13 @@ function TabsList({ children, "aria-label": ariaLabel, className = "" }) {
1172
1172
  ro.disconnect();
1173
1173
  };
1174
1174
  }, [horizontal, scrollable, children]);
1175
- const nudge = React29.useCallback((dir) => {
1175
+ const nudge = React28.useCallback((dir) => {
1176
1176
  const el = scrollRef.current;
1177
1177
  if (!el) return;
1178
1178
  const amount = (horizontal ? el.clientWidth : el.clientHeight) * 0.7 * dir;
1179
1179
  el.scrollBy({ [horizontal ? "left" : "top"]: amount, behavior: reduced ? "auto" : "smooth" });
1180
1180
  }, [horizontal, reduced]);
1181
- React29.useLayoutEffect(() => {
1181
+ React28.useLayoutEffect(() => {
1182
1182
  const el = scrollRef.current;
1183
1183
  if (!el || !scrollable) return;
1184
1184
  const active = el.querySelector("[role=tab][data-state=active]");
@@ -1236,9 +1236,9 @@ function Chevron2({ side, orientation, onClick }) {
1236
1236
  function OverflowMenu() {
1237
1237
  const { getTabs, value, select, orientation } = useTabsContext();
1238
1238
  const horizontal = orientation === "horizontal";
1239
- const [open, setOpen] = React29.useState(false);
1240
- const wrapRef = React29.useRef(null);
1241
- const timer = React29.useRef(null);
1239
+ const [open, setOpen] = React28.useState(false);
1240
+ const wrapRef = React28.useRef(null);
1241
+ const timer = React28.useRef(null);
1242
1242
  const openNow = () => {
1243
1243
  if (timer.current) clearTimeout(timer.current);
1244
1244
  setOpen(true);
@@ -1246,7 +1246,7 @@ function OverflowMenu() {
1246
1246
  const closeSoon = () => {
1247
1247
  timer.current = setTimeout(() => setOpen(false), 160);
1248
1248
  };
1249
- React29.useLayoutEffect(() => {
1249
+ React28.useLayoutEffect(() => {
1250
1250
  if (!open) return;
1251
1251
  const onDoc = (e) => {
1252
1252
  if (wrapRef.current && !wrapRef.current.contains(e.target)) setOpen(false);
@@ -1327,7 +1327,7 @@ function TabsTrigger({ value, icon, badge, closeable, onClose, disabled, classNa
1327
1327
  const isActive = active === value;
1328
1328
  const horizontal = orientation === "horizontal";
1329
1329
  const sz = SIZE[size];
1330
- React29.useLayoutEffect(() => {
1330
+ React28.useLayoutEffect(() => {
1331
1331
  registerTab(value, { label: children, icon, disabled });
1332
1332
  return () => unregisterTab(value);
1333
1333
  }, [value, children, icon, disabled, registerTab, unregisterTab]);
@@ -1525,7 +1525,7 @@ function Tree({
1525
1525
  item.key
1526
1526
  )) });
1527
1527
  }
1528
- var AccordionCtx = React29.createContext({ variant: "separated" });
1528
+ var AccordionCtx = React28.createContext({ variant: "separated" });
1529
1529
  function Accordion2({
1530
1530
  children,
1531
1531
  type = "single",
@@ -1584,7 +1584,7 @@ var Chevron3 = /* @__PURE__ */ jsxRuntime.jsx(
1584
1584
  }
1585
1585
  );
1586
1586
  function AccordionItem({ value, title, icon, children, disabled, className = "" }) {
1587
- const { variant } = React29.useContext(AccordionCtx);
1587
+ const { variant } = React28.useContext(AccordionCtx);
1588
1588
  return /* @__PURE__ */ jsxRuntime.jsxs(
1589
1589
  AccordionPrimitive__namespace.Item,
1590
1590
  {
@@ -1643,7 +1643,7 @@ function Breadcrumbs({
1643
1643
  className = "",
1644
1644
  style
1645
1645
  }) {
1646
- const [expanded, setExpanded] = React29.useState(false);
1646
+ const [expanded, setExpanded] = React28.useState(false);
1647
1647
  const shouldCollapse = maxItems > 0 && items.length > maxItems && !expanded;
1648
1648
  const visible = [];
1649
1649
  if (shouldCollapse) {
@@ -1827,8 +1827,8 @@ function Stepper({
1827
1827
  className = ""
1828
1828
  }) {
1829
1829
  const reduced = framerMotion.useReducedMotion();
1830
- const [forcedVertical, setForcedVertical] = React29.useState(false);
1831
- React29.useEffect(() => {
1830
+ const [forcedVertical, setForcedVertical] = React28.useState(false);
1831
+ React28.useEffect(() => {
1832
1832
  if (!responsive || orientation === "vertical") return;
1833
1833
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
1834
1834
  const mq = window.matchMedia("(max-width: 767px)");
@@ -1937,7 +1937,7 @@ function Kbd({
1937
1937
  style
1938
1938
  }) {
1939
1939
  if (keys && keys.length > 0) {
1940
- return /* @__PURE__ */ jsxRuntime.jsx("span", { className: ["inline-flex items-center gap-1", className].filter(Boolean).join(" "), style, children: keys.map((k, i) => /* @__PURE__ */ jsxRuntime.jsxs(React29__default.default.Fragment, { children: [
1940
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: ["inline-flex items-center gap-1", className].filter(Boolean).join(" "), style, children: keys.map((k, i) => /* @__PURE__ */ jsxRuntime.jsxs(React28__default.default.Fragment, { children: [
1941
1941
  i > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground-muted text-xs select-none", children: separator }),
1942
1942
  /* @__PURE__ */ jsxRuntime.jsx("kbd", { className: [cap, SIZE3[size]].join(" "), children: k })
1943
1943
  ] }, `${k}-${i}`)) });
@@ -2028,13 +2028,13 @@ function FlatCarousel({
2028
2028
  className = "",
2029
2029
  style
2030
2030
  }) {
2031
- const scrollerRef = React29.useRef(null);
2032
- const slides = React29__default.default.Children.toArray(children);
2033
- const [active, setActive] = React29.useState(0);
2034
- const [atStart, setAtStart] = React29.useState(true);
2035
- const [atEnd, setAtEnd] = React29.useState(false);
2031
+ const scrollerRef = React28.useRef(null);
2032
+ const slides = React28__default.default.Children.toArray(children);
2033
+ const [active, setActive] = React28.useState(0);
2034
+ const [atStart, setAtStart] = React28.useState(true);
2035
+ const [atEnd, setAtEnd] = React28.useState(false);
2036
2036
  const width = typeof itemWidth === "number" ? `${itemWidth}px` : itemWidth;
2037
- const update = React29.useCallback(() => {
2037
+ const update = React28.useCallback(() => {
2038
2038
  const el = scrollerRef.current;
2039
2039
  if (!el) return;
2040
2040
  setAtStart(el.scrollLeft <= 1);
@@ -2043,7 +2043,7 @@ function FlatCarousel({
2043
2043
  const slideW = first ? first.getBoundingClientRect().width + gap : el.clientWidth;
2044
2044
  setActive(Math.round(el.scrollLeft / slideW));
2045
2045
  }, [gap]);
2046
- React29.useEffect(() => {
2046
+ React28.useEffect(() => {
2047
2047
  update();
2048
2048
  const el = scrollerRef.current;
2049
2049
  if (!el) return;
@@ -2084,9 +2084,9 @@ function RotatingCarousel({
2084
2084
  className = "",
2085
2085
  style
2086
2086
  }) {
2087
- const slides = React29__default.default.Children.toArray(children);
2087
+ const slides = React28__default.default.Children.toArray(children);
2088
2088
  const count = slides.length;
2089
- const [active, setActive] = React29.useState(0);
2089
+ const [active, setActive] = React28.useState(0);
2090
2090
  const reduced = framerMotion.useReducedMotion();
2091
2091
  const wrap = (n) => count > 0 ? (n % count + count) % count : 0;
2092
2092
  const idx = wrap(active);
@@ -2236,7 +2236,7 @@ function FAB({
2236
2236
  className = "",
2237
2237
  style
2238
2238
  }) {
2239
- const [open, setOpen] = React29.useState(false);
2239
+ const [open, setOpen] = React28.useState(false);
2240
2240
  const reduced = framerMotion.useReducedMotion();
2241
2241
  const hasDial = !!actions && actions.length > 0;
2242
2242
  const bottom = position.startsWith("bottom");
@@ -2338,8 +2338,8 @@ function PopConfirm({
2338
2338
  onOpenChange,
2339
2339
  className = ""
2340
2340
  }) {
2341
- const [uncontrolledOpen, setUncontrolledOpen] = React29.useState(false);
2342
- const [loading, setLoading] = React29.useState(false);
2341
+ const [uncontrolledOpen, setUncontrolledOpen] = React28.useState(false);
2342
+ const [loading, setLoading] = React28.useState(false);
2343
2343
  const isOpen = open ?? uncontrolledOpen;
2344
2344
  const setOpen = (next) => {
2345
2345
  onOpenChange?.(next);
@@ -2426,16 +2426,16 @@ function LogoutTimer({
2426
2426
  logoutLabel = "Sign out now"
2427
2427
  }) {
2428
2428
  const reduced = framerMotion.useReducedMotion();
2429
- const [warning, setWarning] = React29.useState(false);
2430
- const [remaining, setRemaining] = React29.useState(countdown);
2431
- const idleTimer = React29.useRef(null);
2432
- const tick = React29.useRef(null);
2433
- const deadline = React29.useRef(0);
2434
- const warningRef = React29.useRef(false);
2435
- const lastReset = React29.useRef(0);
2436
- const cbs = React29.useRef({ onLogout, onContinue, onWarning });
2429
+ const [warning, setWarning] = React28.useState(false);
2430
+ const [remaining, setRemaining] = React28.useState(countdown);
2431
+ const idleTimer = React28.useRef(null);
2432
+ const tick = React28.useRef(null);
2433
+ const deadline = React28.useRef(0);
2434
+ const warningRef = React28.useRef(false);
2435
+ const lastReset = React28.useRef(0);
2436
+ const cbs = React28.useRef({ onLogout, onContinue, onWarning });
2437
2437
  cbs.current = { onLogout, onContinue, onWarning };
2438
- const clearTimers = React29.useCallback(() => {
2438
+ const clearTimers = React28.useCallback(() => {
2439
2439
  if (idleTimer.current) {
2440
2440
  clearTimeout(idleTimer.current);
2441
2441
  idleTimer.current = null;
@@ -2445,13 +2445,13 @@ function LogoutTimer({
2445
2445
  tick.current = null;
2446
2446
  }
2447
2447
  }, []);
2448
- const logout = React29.useCallback(() => {
2448
+ const logout = React28.useCallback(() => {
2449
2449
  clearTimers();
2450
2450
  warningRef.current = false;
2451
2451
  setWarning(false);
2452
2452
  cbs.current.onLogout();
2453
2453
  }, [clearTimers]);
2454
- const startIdle = React29.useCallback(() => {
2454
+ const startIdle = React28.useCallback(() => {
2455
2455
  if (idleTimer.current) clearTimeout(idleTimer.current);
2456
2456
  idleTimer.current = setTimeout(() => {
2457
2457
  warningRef.current = true;
@@ -2466,7 +2466,7 @@ function LogoutTimer({
2466
2466
  }, 250);
2467
2467
  }, timeout);
2468
2468
  }, [timeout, countdown, logout]);
2469
- const stay = React29.useCallback(() => {
2469
+ const stay = React28.useCallback(() => {
2470
2470
  if (tick.current) {
2471
2471
  clearInterval(tick.current);
2472
2472
  tick.current = null;
@@ -2476,7 +2476,7 @@ function LogoutTimer({
2476
2476
  cbs.current.onContinue?.();
2477
2477
  startIdle();
2478
2478
  }, [startIdle]);
2479
- React29.useEffect(() => {
2479
+ React28.useEffect(() => {
2480
2480
  if (!enabled) {
2481
2481
  clearTimers();
2482
2482
  warningRef.current = false;
@@ -2548,16 +2548,16 @@ function Calendar2({
2548
2548
  className = "",
2549
2549
  style
2550
2550
  }) {
2551
- const today = React29.useMemo(() => startOfDay(/* @__PURE__ */ new Date()), []);
2552
- const [internalMonth, setInternalMonth] = React29.useState(() => month ?? defaultMonth ?? value ?? today);
2551
+ const today = React28.useMemo(() => startOfDay(/* @__PURE__ */ new Date()), []);
2552
+ const [internalMonth, setInternalMonth] = React28.useState(() => month ?? defaultMonth ?? value ?? today);
2553
2553
  const visible = month ?? internalMonth;
2554
2554
  const setMonth = (next) => {
2555
2555
  onMonthChange?.(next);
2556
2556
  if (month === void 0) setInternalMonth(next);
2557
2557
  };
2558
- const grid = React29.useMemo(() => buildGrid(visible, weekStartsOn), [visible, weekStartsOn]);
2559
- const weekdays = React29.useMemo(() => Array.from({ length: 7 }, (_, i) => WEEKDAYS[(i + weekStartsOn) % 7]), [weekStartsOn]);
2560
- const eventsByDay = React29.useMemo(() => {
2558
+ const grid = React28.useMemo(() => buildGrid(visible, weekStartsOn), [visible, weekStartsOn]);
2559
+ const weekdays = React28.useMemo(() => Array.from({ length: 7 }, (_, i) => WEEKDAYS[(i + weekStartsOn) % 7]), [weekStartsOn]);
2560
+ const eventsByDay = React28.useMemo(() => {
2561
2561
  const map = /* @__PURE__ */ new Map();
2562
2562
  for (const ev of events ?? []) {
2563
2563
  const key = startOfDay(ev.date).toDateString();
@@ -2788,11 +2788,11 @@ function SegmentedControl({
2788
2788
  "aria-label": ariaLabel
2789
2789
  }) {
2790
2790
  const sz = SIZE5[size];
2791
- const groupId = React29.useId();
2792
- const errorId = React29.useId();
2791
+ const groupId = React28.useId();
2792
+ const errorId = React28.useId();
2793
2793
  const hasError = errorMessage != null;
2794
2794
  const isControlled = value !== void 0;
2795
- const [internal, setInternal] = React29.useState(defaultValue);
2795
+ const [internal, setInternal] = React28.useState(defaultValue);
2796
2796
  const current = isControlled ? value : internal;
2797
2797
  const handle = (v) => {
2798
2798
  if (!v) return;
@@ -2952,22 +2952,22 @@ function Scheduler({
2952
2952
  style
2953
2953
  }) {
2954
2954
  const reduced = framerMotion.useReducedMotion();
2955
- const [view, setView] = React29.useState(defaultView);
2956
- const [cursor, setCursor] = React29.useState(() => defaultDate ?? /* @__PURE__ */ new Date());
2957
- const [loaded, setLoaded] = React29.useState([]);
2958
- const [loading, setLoading] = React29.useState(false);
2959
- const [error, setError] = React29.useState(null);
2960
- const [reloadKey, setReloadKey] = React29.useState(0);
2961
- const [dir, setDir] = React29.useState(0);
2962
- const cbRef = React29.useRef({ loadEvents, onError });
2955
+ const [view, setView] = React28.useState(defaultView);
2956
+ const [cursor, setCursor] = React28.useState(() => defaultDate ?? /* @__PURE__ */ new Date());
2957
+ const [loaded, setLoaded] = React28.useState([]);
2958
+ const [loading, setLoading] = React28.useState(false);
2959
+ const [error, setError] = React28.useState(null);
2960
+ const [reloadKey, setReloadKey] = React28.useState(0);
2961
+ const [dir, setDir] = React28.useState(0);
2962
+ const cbRef = React28.useRef({ loadEvents, onError });
2963
2963
  cbRef.current = { loadEvents, onError };
2964
- const range = React29.useMemo(
2964
+ const range = React28.useMemo(
2965
2965
  () => view === "month" ? monthRange(cursor) : weekRange(cursor, weekStartsOn),
2966
2966
  [view, cursor, weekStartsOn]
2967
2967
  );
2968
2968
  const fromKey = range.from.getTime();
2969
2969
  const toKey = range.to.getTime();
2970
- React29.useEffect(() => {
2970
+ React28.useEffect(() => {
2971
2971
  const { loadEvents: loader, onError: onErr } = cbRef.current;
2972
2972
  if (!loader) return;
2973
2973
  let cancelled = false;
@@ -2987,16 +2987,16 @@ function Scheduler({
2987
2987
  cancelled = true;
2988
2988
  };
2989
2989
  }, [fromKey, toKey, view, reloadKey]);
2990
- const retry = React29.useCallback(() => setReloadKey((k) => k + 1), []);
2991
- const events = React29.useMemo(
2990
+ const retry = React28.useCallback(() => setReloadKey((k) => k + 1), []);
2991
+ const events = React28.useMemo(
2992
2992
  () => (controlledEvents ?? loaded).map(normalize),
2993
2993
  [controlledEvents, loaded]
2994
2994
  );
2995
- const go = React29.useCallback((delta) => {
2995
+ const go = React28.useCallback((delta) => {
2996
2996
  setDir(delta);
2997
2997
  setCursor((c) => view === "month" ? addMonths2(c, delta) : addDays(c, delta * 7));
2998
2998
  }, [view]);
2999
- const goToday = React29.useCallback(() => {
2999
+ const goToday = React28.useCallback(() => {
3000
3000
  setDir(0);
3001
3001
  setCursor(/* @__PURE__ */ new Date());
3002
3002
  }, []);
@@ -3106,9 +3106,9 @@ function SchedulerError({ onRetry }) {
3106
3106
  ] });
3107
3107
  }
3108
3108
  function MonthYearPicker({ label, cursor, onPick }) {
3109
- const [open, setOpen] = React29.useState(false);
3110
- const [viewYear, setViewYear] = React29.useState(cursor.getFullYear());
3111
- React29.useEffect(() => {
3109
+ const [open, setOpen] = React28.useState(false);
3110
+ const [viewYear, setViewYear] = React28.useState(cursor.getFullYear());
3111
+ React28.useEffect(() => {
3112
3112
  if (open) setViewYear(cursor.getFullYear());
3113
3113
  }, [open, cursor]);
3114
3114
  return /* @__PURE__ */ jsxRuntime.jsxs(Popover__namespace.Root, { open, onOpenChange: setOpen, children: [
@@ -3171,7 +3171,7 @@ function MonthView({
3171
3171
  onSelectSlot,
3172
3172
  onSelectEvent
3173
3173
  }) {
3174
- const grid = React29.useMemo(() => buildMonthGrid(cursor, weekStartsOn), [cursor, weekStartsOn]);
3174
+ const grid = React28.useMemo(() => buildMonthGrid(cursor, weekStartsOn), [cursor, weekStartsOn]);
3175
3175
  const labels = weekdayLabels(weekStartsOn);
3176
3176
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full flex-col", children: [
3177
3177
  /* @__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)) }),
@@ -3245,11 +3245,11 @@ function WeekView({
3245
3245
  onSelectSlot,
3246
3246
  onSelectEvent
3247
3247
  }) {
3248
- const days = React29.useMemo(() => getWeekDays(cursor, weekStartsOn), [cursor, weekStartsOn]);
3249
- const labels = React29.useMemo(() => weekdayLabels(weekStartsOn), [weekStartsOn]);
3248
+ const days = React28.useMemo(() => getWeekDays(cursor, weekStartsOn), [cursor, weekStartsOn]);
3249
+ const labels = React28.useMemo(() => weekdayLabels(weekStartsOn), [weekStartsOn]);
3250
3250
  const dow = (d) => labels[(d.getDay() - weekStartsOn + 7) % 7];
3251
3251
  const [startHour, endHour] = dayHours;
3252
- const hours = React29.useMemo(
3252
+ const hours = React28.useMemo(
3253
3253
  () => Array.from({ length: endHour - startHour }, (_, i) => startHour + i),
3254
3254
  [startHour, endHour]
3255
3255
  );
@@ -3440,17 +3440,17 @@ function Cart({
3440
3440
  ] })
3441
3441
  ] });
3442
3442
  }
3443
- var CartContext = React29.createContext(null);
3443
+ var CartContext = React28.createContext(null);
3444
3444
  var clampQty = (qty, max) => {
3445
3445
  const lower = Math.max(1, Math.round(qty));
3446
3446
  return max != null ? Math.min(lower, max) : lower;
3447
3447
  };
3448
3448
  function CartProvider({ children, initialItems = [], onChange }) {
3449
- const [items, setItems] = React29.useState(initialItems);
3450
- React29.useEffect(() => {
3449
+ const [items, setItems] = React28.useState(initialItems);
3450
+ React28.useEffect(() => {
3451
3451
  onChange?.(items);
3452
3452
  }, [items]);
3453
- const addToCart = React29.useCallback((item, quantity) => {
3453
+ const addToCart = React28.useCallback((item, quantity) => {
3454
3454
  const addQty = quantity ?? item.quantity ?? 1;
3455
3455
  setItems((prev) => {
3456
3456
  const existing = prev.find((it) => it.id === item.id);
@@ -3463,29 +3463,29 @@ function CartProvider({ children, initialItems = [], onChange }) {
3463
3463
  return [...prev, { ...rest, quantity: clampQty(addQty, item.max) }];
3464
3464
  });
3465
3465
  }, []);
3466
- const removeFromCart = React29.useCallback((id) => {
3466
+ const removeFromCart = React28.useCallback((id) => {
3467
3467
  setItems((prev) => prev.filter((it) => it.id !== id));
3468
3468
  }, []);
3469
- const updateQuantity = React29.useCallback((id, quantity) => {
3469
+ const updateQuantity = React28.useCallback((id, quantity) => {
3470
3470
  setItems(
3471
3471
  (prev) => prev.map((it) => it.id === id ? { ...it, quantity: clampQty(quantity, it.max) } : it)
3472
3472
  );
3473
3473
  }, []);
3474
- const clearCart = React29.useCallback(() => setItems([]), []);
3475
- const isInCart = React29.useCallback((id) => items.some((it) => it.id === id), [items]);
3476
- const getItemCount = React29.useCallback(() => items.reduce((sum, it) => sum + it.quantity, 0), [items]);
3477
- const getCartTotal = React29.useCallback(
3474
+ const clearCart = React28.useCallback(() => setItems([]), []);
3475
+ const isInCart = React28.useCallback((id) => items.some((it) => it.id === id), [items]);
3476
+ const getItemCount = React28.useCallback(() => items.reduce((sum, it) => sum + it.quantity, 0), [items]);
3477
+ const getCartTotal = React28.useCallback(
3478
3478
  () => items.reduce((sum, it) => sum + it.price * it.quantity, 0),
3479
3479
  [items]
3480
3480
  );
3481
- const value = React29.useMemo(
3481
+ const value = React28.useMemo(
3482
3482
  () => ({ items, addToCart, removeFromCart, updateQuantity, clearCart, isInCart, getItemCount, getCartTotal }),
3483
3483
  [items, addToCart, removeFromCart, updateQuantity, clearCart, isInCart, getItemCount, getCartTotal]
3484
3484
  );
3485
3485
  return /* @__PURE__ */ jsxRuntime.jsx(CartContext.Provider, { value, children });
3486
3486
  }
3487
3487
  function useCart() {
3488
- const ctx = React29.useContext(CartContext);
3488
+ const ctx = React28.useContext(CartContext);
3489
3489
  if (!ctx) {
3490
3490
  throw new Error("useCart must be used within a <CartProvider>.");
3491
3491
  }
@@ -3819,11 +3819,11 @@ function buildBindings(store, name, kind, snap) {
3819
3819
 
3820
3820
  // src/form/useForm.ts
3821
3821
  function useForm(options = {}) {
3822
- const ref = React29.useRef(null);
3822
+ const ref = React28.useRef(null);
3823
3823
  if (ref.current === null) ref.current = new FormStore(options);
3824
3824
  const store = ref.current;
3825
- React29.useSyncExternalStore(store.subscribe, store.getRootSnapshot, store.getRootSnapshot);
3826
- const make = React29.useCallback(
3825
+ React28.useSyncExternalStore(store.subscribe, store.getRootSnapshot, store.getRootSnapshot);
3826
+ const make = React28.useCallback(
3827
3827
  (kind) => (name, rules) => {
3828
3828
  if (rules !== void 0) store.setRule(name, rules);
3829
3829
  return buildBindings(store, name, kind, store.getFieldSnapshot(name));
@@ -3852,9 +3852,9 @@ function useForm(options = {}) {
3852
3852
  fieldTarget: make("target")
3853
3853
  };
3854
3854
  }
3855
- var FormContext = React29.createContext(null);
3855
+ var FormContext = React28.createContext(null);
3856
3856
  function useFormStore() {
3857
- const store = React29.useContext(FormContext);
3857
+ const store = React28.useContext(FormContext);
3858
3858
  if (!store) {
3859
3859
  throw new Error("useFormStore must be used within a <Form>. Did you forget to wrap your fields?");
3860
3860
  }
@@ -3868,8 +3868,8 @@ function Form({
3868
3868
  children,
3869
3869
  ...rest
3870
3870
  }) {
3871
- const ref = React29.useRef(null);
3872
- const bypass = React29.useRef(false);
3871
+ const ref = React28.useRef(null);
3872
+ const bypass = React28.useRef(false);
3873
3873
  const handleSubmit = async (e) => {
3874
3874
  if (bypass.current) {
3875
3875
  bypass.current = false;
@@ -3921,12 +3921,12 @@ function useFormField(name, options = {}) {
3921
3921
  const store = useFormStore();
3922
3922
  const { kind = "value", rules } = options;
3923
3923
  if (rules !== void 0 && store.getRule(name) !== rules) store.setRule(name, rules);
3924
- React29.useEffect(() => {
3924
+ React28.useEffect(() => {
3925
3925
  return () => {
3926
3926
  if (rules !== void 0) store.removeRule(name);
3927
3927
  };
3928
3928
  }, [store, name]);
3929
- const snap = React29.useSyncExternalStore(
3929
+ const snap = React28.useSyncExternalStore(
3930
3930
  store.subscribe,
3931
3931
  () => store.getFieldSnapshot(name)
3932
3932
  );
@@ -3938,7 +3938,7 @@ function FormField({ name, kind, rules, children }) {
3938
3938
  }
3939
3939
  function useFieldArray(name) {
3940
3940
  const store = useFormStore();
3941
- React29.useSyncExternalStore(store.subscribe, store.getRootSnapshot, store.getRootSnapshot);
3941
+ React28.useSyncExternalStore(store.subscribe, store.getRootSnapshot, store.getRootSnapshot);
3942
3942
  const arr = store.getValue(name) ?? [];
3943
3943
  const keys = store.getKeys(name);
3944
3944
  return {
@@ -3971,7 +3971,7 @@ function TextInput({
3971
3971
  suffix,
3972
3972
  id
3973
3973
  }) {
3974
- const errorId = React29.useId();
3974
+ const errorId = React28.useId();
3975
3975
  const hasError = errorMessage != null;
3976
3976
  const hasAdornment = prefix != null || suffix != null;
3977
3977
  const inputId = htmlFor ?? id;
@@ -4132,7 +4132,7 @@ function CreditCardForm({
4132
4132
  className = "",
4133
4133
  style
4134
4134
  }) {
4135
- const initial = React29.useRef({
4135
+ const initial = React28.useRef({
4136
4136
  number: formatCardNumber(defaultValue?.number ?? ""),
4137
4137
  name: defaultValue?.name ?? "",
4138
4138
  expiry: formatExpiry(defaultValue?.expiry ?? ""),
@@ -4141,7 +4141,7 @@ function CreditCardForm({
4141
4141
  const form = useForm({ initialValues: initial });
4142
4142
  const numberStr = String(form.values.number ?? "");
4143
4143
  const brand = detectBrand(numberStr);
4144
- React29.useEffect(() => {
4144
+ React28.useEffect(() => {
4145
4145
  onChange?.(toCard(form.values));
4146
4146
  }, [form.values.number, form.values.name, form.values.expiry, form.values.cvv]);
4147
4147
  const numberBind = form.fieldNative("number", {
@@ -4264,7 +4264,7 @@ function Checkout({
4264
4264
  ] })
4265
4265
  ] });
4266
4266
  }
4267
- var NotificationContext = React29.createContext({
4267
+ var NotificationContext = React28.createContext({
4268
4268
  open: () => void 0,
4269
4269
  close: () => void 0
4270
4270
  });
@@ -4322,26 +4322,26 @@ function NotificationItem({
4322
4322
  onClose,
4323
4323
  reduced
4324
4324
  }) {
4325
- const [paused, setPaused] = React29.useState(false);
4325
+ const [paused, setPaused] = React28.useState(false);
4326
4326
  const duration = n.duration ?? 4e3;
4327
4327
  const isAutoDismissing = isFinite(duration) && duration > 0;
4328
4328
  const showProgress = !reduced && isAutoDismissing;
4329
- const timerRef = React29.useRef(null);
4330
- const startTimeRef = React29.useRef(0);
4331
- const remainingRef = React29.useRef(duration);
4332
- const clearTimer = React29.useCallback(() => {
4329
+ const timerRef = React28.useRef(null);
4330
+ const startTimeRef = React28.useRef(0);
4331
+ const remainingRef = React28.useRef(duration);
4332
+ const clearTimer = React28.useCallback(() => {
4333
4333
  if (timerRef.current !== null) {
4334
4334
  clearTimeout(timerRef.current);
4335
4335
  timerRef.current = null;
4336
4336
  }
4337
4337
  }, []);
4338
- const scheduleDismiss = React29.useCallback((ms) => {
4338
+ const scheduleDismiss = React28.useCallback((ms) => {
4339
4339
  clearTimer();
4340
4340
  if (!isAutoDismissing) return;
4341
4341
  startTimeRef.current = Date.now();
4342
4342
  timerRef.current = setTimeout(() => onClose(n.id), ms);
4343
4343
  }, [clearTimer, isAutoDismissing, n.id, onClose]);
4344
- React29.useEffect(() => {
4344
+ React28.useEffect(() => {
4345
4345
  if (paused || !isAutoDismissing) return;
4346
4346
  scheduleDismiss(remainingRef.current);
4347
4347
  return clearTimer;
@@ -4424,15 +4424,15 @@ function NotificationProvider({
4424
4424
  children,
4425
4425
  position = "top-right"
4426
4426
  }) {
4427
- const [notifications, setNotifications] = React29.useState([]);
4427
+ const [notifications, setNotifications] = React28.useState([]);
4428
4428
  const reduced = framerMotion.useReducedMotion();
4429
- const open = React29.useCallback((payload) => {
4429
+ const open = React28.useCallback((payload) => {
4430
4430
  setNotifications((prev) => [
4431
4431
  ...prev,
4432
4432
  { duration: 4e3, ...payload, id: Date.now() + Math.random() }
4433
4433
  ]);
4434
4434
  }, []);
4435
- const close = React29.useCallback((id) => {
4435
+ const close = React28.useCallback((id) => {
4436
4436
  setNotifications((prev) => prev.filter((n) => n.id !== id));
4437
4437
  }, []);
4438
4438
  return /* @__PURE__ */ jsxRuntime.jsxs(NotificationContext.Provider, { value: { open, close }, children: [
@@ -4461,7 +4461,7 @@ function NotificationProvider({
4461
4461
  ] });
4462
4462
  }
4463
4463
  function useNotification() {
4464
- const { open } = React29.useContext(NotificationContext);
4464
+ const { open } = React28.useContext(NotificationContext);
4465
4465
  return {
4466
4466
  info: (props) => open({ type: "info", ...props }),
4467
4467
  success: (props) => open({ type: "success", ...props }),
@@ -4578,10 +4578,10 @@ function FadingBase({
4578
4578
  isMounted = false,
4579
4579
  children
4580
4580
  }) {
4581
- const [shouldRender, setShouldRender] = React29.useState(isMounted);
4582
- const [visible, setVisible] = React29.useState(false);
4583
- const timerRef = React29.useRef(null);
4584
- React29.useEffect(() => {
4581
+ const [shouldRender, setShouldRender] = React28.useState(isMounted);
4582
+ const [visible, setVisible] = React28.useState(false);
4583
+ const timerRef = React28.useRef(null);
4584
+ React28.useEffect(() => {
4585
4585
  if (isMounted) {
4586
4586
  setShouldRender(true);
4587
4587
  const rafId = requestAnimationFrame(() => setVisible(true));
@@ -4679,8 +4679,8 @@ function ScalableContainer({
4679
4679
  togglePosition = "top-right",
4680
4680
  className = ""
4681
4681
  }) {
4682
- const containerRef = React29.useRef(null);
4683
- const [internalScaled, setInternalScaled] = React29.useState(false);
4682
+ const containerRef = React28.useRef(null);
4683
+ const [internalScaled, setInternalScaled] = React28.useState(false);
4684
4684
  const isScaled = expanded ?? internalScaled;
4685
4685
  const reduced = framerMotion.useReducedMotion();
4686
4686
  const onToggle = () => {
@@ -4818,17 +4818,17 @@ function CatalogGrid({ items, buttonText, onOpen, className = "" }) {
4818
4818
  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)) });
4819
4819
  }
4820
4820
  function CatalogCarousel({ items, buttonText, onOpen, className = "" }) {
4821
- const [activeIndex, setActiveIndex] = React29.useState(0);
4822
- const [indexPool, setIndexPool] = React29.useState([]);
4823
- const cardRefs = React29.useRef([]);
4824
- const getIndexes = React29.useMemo(() => {
4821
+ const [activeIndex, setActiveIndex] = React28.useState(0);
4822
+ const [indexPool, setIndexPool] = React28.useState([]);
4823
+ const cardRefs = React28.useRef([]);
4824
+ const getIndexes = React28.useMemo(() => {
4825
4825
  let nextIndex = activeIndex + 1;
4826
4826
  let previousIndex = activeIndex - 1;
4827
4827
  if (activeIndex === 0) previousIndex = items.length - 1;
4828
4828
  if (activeIndex === items.length - 1) nextIndex = 0;
4829
4829
  return { previousIndex, nextIndex };
4830
4830
  }, [activeIndex, items.length]);
4831
- React29.useEffect(() => {
4831
+ React28.useEffect(() => {
4832
4832
  const { nextIndex, previousIndex } = getIndexes;
4833
4833
  let indexes = [previousIndex, activeIndex, nextIndex];
4834
4834
  if (activeIndex !== 0 && activeIndex !== items.length - 1) {
@@ -5001,8 +5001,8 @@ function writeDismissed(key) {
5001
5001
  }
5002
5002
  }
5003
5003
  function useTargetBbox(ref) {
5004
- const [bbox, setBbox] = React29.useState(null);
5005
- React29.useLayoutEffect(() => {
5004
+ const [bbox, setBbox] = React28.useState(null);
5005
+ React28.useLayoutEffect(() => {
5006
5006
  const el = ref?.current;
5007
5007
  if (!el) {
5008
5008
  setBbox(null);
@@ -5032,7 +5032,7 @@ function tooltipStyleFor(bbox, placement) {
5032
5032
  return { left: bbox.left + bbox.width / 2, top: bbox.top - TOOLTIP_GAP, transform: "translate(-50%, -100%)", width: TOOLTIP_WIDTH };
5033
5033
  }
5034
5034
  function useFocusTrap(containerRef, active) {
5035
- React29.useEffect(() => {
5035
+ React28.useEffect(() => {
5036
5036
  if (!active) return;
5037
5037
  const el = containerRef.current;
5038
5038
  if (!el) return;
@@ -5071,16 +5071,16 @@ function Wizard({
5071
5071
  onComplete,
5072
5072
  onSkip
5073
5073
  }) {
5074
- const tooltipRef = React29.useRef(null);
5075
- const tooltipTitleId = React29.useId();
5076
- const tooltipBodyId = React29.useId();
5074
+ const tooltipRef = React28.useRef(null);
5075
+ const tooltipTitleId = React28.useId();
5076
+ const tooltipBodyId = React28.useId();
5077
5077
  const reduced = framerMotion.useReducedMotion();
5078
- const [open, setOpen] = React29.useState(() => steps.length > 0 && !readDismissed(storageKey));
5079
- const [activeIndex, setActiveIndex] = React29.useState(0);
5078
+ const [open, setOpen] = React28.useState(() => steps.length > 0 && !readDismissed(storageKey));
5079
+ const [activeIndex, setActiveIndex] = React28.useState(0);
5080
5080
  const step = steps[activeIndex];
5081
5081
  const bbox = useTargetBbox(step?.stepRef);
5082
5082
  useFocusTrap(tooltipRef, open);
5083
- React29.useEffect(() => {
5083
+ React28.useEffect(() => {
5084
5084
  if (!open || !dismissible) return;
5085
5085
  const onKey = (e) => {
5086
5086
  if (e.key === "Escape") {
@@ -5091,12 +5091,12 @@ function Wizard({
5091
5091
  document.addEventListener("keydown", onKey);
5092
5092
  return () => document.removeEventListener("keydown", onKey);
5093
5093
  }, [open, dismissible]);
5094
- const handleSkip = React29.useCallback(() => {
5094
+ const handleSkip = React28.useCallback(() => {
5095
5095
  writeDismissed(storageKey);
5096
5096
  setOpen(false);
5097
5097
  onSkip?.();
5098
5098
  }, [storageKey, onSkip]);
5099
- const handleComplete = React29.useCallback(() => {
5099
+ const handleComplete = React28.useCallback(() => {
5100
5100
  writeDismissed(storageKey);
5101
5101
  setOpen(false);
5102
5102
  onComplete?.();
@@ -5239,7 +5239,7 @@ function Wizard({
5239
5239
  ] });
5240
5240
  }
5241
5241
  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" }) });
5242
- var SearchInput = React29__default.default.forwardRef(function SearchInput2({ value, onChange, disabled, label, htmlFor, placeholder, name, inputStyle, style, layout = "vertical", size = "md", icon, helperText, className }, ref) {
5242
+ var SearchInput = React28__default.default.forwardRef(function SearchInput2({ value, onChange, disabled, label, htmlFor, placeholder, name, inputStyle, style, layout = "vertical", size = "md", icon, helperText, className }, ref) {
5243
5243
  return /* @__PURE__ */ jsxRuntime.jsx(Field, { className, label, htmlFor, layout, helperText, children: /* @__PURE__ */ jsxRuntime.jsxs(
5244
5244
  "div",
5245
5245
  {
@@ -5268,308 +5268,6 @@ var SearchInput = React29__default.default.forwardRef(function SearchInput2({ va
5268
5268
  ) });
5269
5269
  });
5270
5270
  var SearchInput_default = SearchInput;
5271
- function Tag({ children, onRemove, removeLabel, disabled }) {
5272
- return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1 rounded-md border border-border bg-surface-raised text-foreground text-xs pl-2 pr-1 py-0.5 max-w-full", children: [
5273
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children }),
5274
- onRemove && /* @__PURE__ */ jsxRuntime.jsx(
5275
- "button",
5276
- {
5277
- type: "button",
5278
- disabled,
5279
- onClick: (e) => {
5280
- e.stopPropagation();
5281
- onRemove();
5282
- },
5283
- "aria-label": removeLabel ?? "Remove",
5284
- className: "inline-flex items-center justify-center w-4 h-4 flex-shrink-0 rounded text-foreground-muted hover:text-status-error hover:bg-surface transition-colors focus:outline-none focus-visible:ring-1 focus-visible:ring-accent disabled:cursor-not-allowed",
5285
- children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "10", height: "10", viewBox: "0 0 20 20", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15 5L5 15M5 5l10 10", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) })
5286
- }
5287
- )
5288
- ] });
5289
- }
5290
- function MultiTagRow({
5291
- values,
5292
- disabled,
5293
- labelFor,
5294
- onRemove
5295
- }) {
5296
- const wrapRef = React29.useRef(null);
5297
- const measureRef = React29.useRef(null);
5298
- const [visibleCount, setVisibleCount] = React29.useState(values.length);
5299
- const key = values.map(String).join("|");
5300
- React29.useLayoutEffect(() => {
5301
- const wrap = wrapRef.current;
5302
- const measure = measureRef.current;
5303
- if (!wrap || !measure) return;
5304
- const GAP = 6;
5305
- const recompute = () => {
5306
- const avail = wrap.clientWidth;
5307
- const tagEls = Array.from(measure.querySelectorAll("[data-mt]"));
5308
- const moreEl = measure.querySelector("[data-mm]");
5309
- const widths = tagEls.map((e) => e.offsetWidth);
5310
- const moreW = moreEl ? moreEl.offsetWidth : 0;
5311
- if (widths.length === 0) {
5312
- setVisibleCount(0);
5313
- return;
5314
- }
5315
- let used = 0;
5316
- let count = 0;
5317
- for (let i = 0; i < widths.length; i++) {
5318
- const w = widths[i] + (i > 0 ? GAP : 0);
5319
- if (used + w <= avail) {
5320
- used += w;
5321
- count++;
5322
- } else break;
5323
- }
5324
- if (count < widths.length) {
5325
- while (count > 0) {
5326
- let t = 0;
5327
- for (let i = 0; i < count; i++) t += widths[i] + (i > 0 ? GAP : 0);
5328
- t += GAP + moreW;
5329
- if (t <= avail) break;
5330
- count--;
5331
- }
5332
- }
5333
- setVisibleCount(count);
5334
- };
5335
- recompute();
5336
- const ro = new ResizeObserver(recompute);
5337
- ro.observe(wrap);
5338
- return () => ro.disconnect();
5339
- }, [key]);
5340
- const hidden = values.length - visibleCount;
5341
- const moreChip = (n) => /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center flex-shrink-0 rounded-md border border-border bg-surface-raised text-foreground-secondary text-xs px-2 py-0.5", children: [
5342
- "+",
5343
- n,
5344
- " more"
5345
- ] });
5346
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: wrapRef, className: "relative flex-1 min-w-0 flex flex-nowrap items-center gap-1.5 overflow-hidden", children: [
5347
- /* @__PURE__ */ jsxRuntime.jsxs(
5348
- "div",
5349
- {
5350
- ref: measureRef,
5351
- "aria-hidden": "true",
5352
- className: "absolute invisible pointer-events-none flex flex-nowrap items-center gap-1.5",
5353
- style: { left: -9999, top: -9999 },
5354
- children: [
5355
- values.map((val) => /* @__PURE__ */ jsxRuntime.jsx("span", { "data-mt": true, children: /* @__PURE__ */ jsxRuntime.jsx(Tag, { removeLabel: "x", onRemove: () => {
5356
- }, children: labelFor(val) }) }, `m-${val}`)),
5357
- /* @__PURE__ */ jsxRuntime.jsx("span", { "data-mm": true, children: moreChip(values.length) })
5358
- ]
5359
- }
5360
- ),
5361
- values.slice(0, visibleCount).map((val) => /* @__PURE__ */ jsxRuntime.jsx(
5362
- Tag,
5363
- {
5364
- disabled,
5365
- removeLabel: `Remove ${labelFor(val)}`,
5366
- onRemove: () => onRemove(val),
5367
- children: labelFor(val)
5368
- },
5369
- String(val)
5370
- )),
5371
- hidden > 0 && moreChip(hidden)
5372
- ] });
5373
- }
5374
- function Dropdown({
5375
- isMultiselect = false,
5376
- hasSearch = true,
5377
- label,
5378
- name,
5379
- value,
5380
- onChange,
5381
- disabled,
5382
- layout = "horizontal",
5383
- helperText,
5384
- required,
5385
- errorMessage,
5386
- style = {},
5387
- htmlFor,
5388
- items = [],
5389
- labelStyle = {},
5390
- placeholder,
5391
- size = "md",
5392
- className = ""
5393
- }) {
5394
- const [open, setOpen] = React29.useState(false);
5395
- const [selectedItems, setSelectedItems] = React29.useState([]);
5396
- const [searchTerm, setSearchTerm] = React29.useState("");
5397
- const [innerItems, setInnerItems] = React29.useState([]);
5398
- const errorId = React29.useId();
5399
- const hasError = errorMessage != null;
5400
- React29.useEffect(() => {
5401
- setInnerItems(items);
5402
- }, [items]);
5403
- React29.useEffect(() => {
5404
- if (isMultiselect && Array.isArray(value)) {
5405
- setSelectedItems(value);
5406
- }
5407
- }, [isMultiselect, value]);
5408
- const selectItem = (key) => {
5409
- if (isMultiselect) {
5410
- const next = selectedItems.includes(key) ? selectedItems.filter((it) => it !== key) : [...selectedItems, key];
5411
- setSelectedItems(next);
5412
- onChange?.({ target: { value: next, id: htmlFor, name } });
5413
- } else {
5414
- setSelectedItems([key]);
5415
- onChange?.({ target: { value: key, id: htmlFor, name } });
5416
- setOpen(false);
5417
- }
5418
- };
5419
- const removeSelected = (key) => {
5420
- if (isMultiselect) {
5421
- const next = selectedItems.filter((it) => it !== key);
5422
- setSelectedItems(next);
5423
- onChange?.({ target: { value: next, id: htmlFor, name } });
5424
- } else {
5425
- setSelectedItems([]);
5426
- onChange?.({ target: { value: "", id: htmlFor, name } });
5427
- }
5428
- };
5429
- const labelFor = (key) => innerItems.find((it) => it.key === key)?.label ?? String(key);
5430
- const onSearchChange = (e) => {
5431
- const term = e.target.value;
5432
- setSearchTerm(term);
5433
- setInnerItems(
5434
- term.trim() === "" ? items : items.filter(
5435
- (it) => String(it.label).toLowerCase().includes(term.toLowerCase())
5436
- )
5437
- );
5438
- };
5439
- const isSelected = (key) => Array.isArray(value) ? value.includes(key) : value === key;
5440
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: className || void 0, children: [
5441
- /* @__PURE__ */ jsxRuntime.jsxs(
5442
- "div",
5443
- {
5444
- className: `flex ${layout === "vertical" ? "flex-col gap-1.5" : "flex-row items-start gap-3"}`,
5445
- children: [
5446
- /* @__PURE__ */ jsxRuntime.jsx(
5447
- FieldLabel,
5448
- {
5449
- label,
5450
- htmlFor,
5451
- required,
5452
- helperText,
5453
- horizontal: layout === "horizontal",
5454
- style: labelStyle
5455
- }
5456
- ),
5457
- /* @__PURE__ */ jsxRuntime.jsxs(Popover__namespace.Root, { open: open && !disabled, onOpenChange: (o) => !disabled && setOpen(o), children: [
5458
- /* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
5459
- "div",
5460
- {
5461
- id: htmlFor,
5462
- role: "combobox",
5463
- "aria-expanded": open,
5464
- "aria-haspopup": "listbox",
5465
- "aria-invalid": hasError || void 0,
5466
- "aria-describedby": hasError ? errorId : void 0,
5467
- style: { width: 240, ...style },
5468
- className: `flex items-center justify-between gap-2 cursor-pointer select-none min-h-[36px] px-3 py-1.5 ${fieldShell({ size, hasError, disabled, sized: false })}`,
5469
- tabIndex: disabled ? -1 : 0,
5470
- onKeyDown: (e) => {
5471
- if (disabled) return;
5472
- if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown" || e.key === "ArrowUp") {
5473
- e.preventDefault();
5474
- setOpen(true);
5475
- }
5476
- },
5477
- children: [
5478
- !value || Array.isArray(value) && value.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 min-w-0 truncate text-foreground-muted text-sm", children: placeholder }) : Array.isArray(value) ? /* @__PURE__ */ jsxRuntime.jsx(
5479
- MultiTagRow,
5480
- {
5481
- values: value,
5482
- disabled,
5483
- labelFor,
5484
- onRemove: removeSelected
5485
- }
5486
- ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-w-0 flex items-center overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
5487
- Tag,
5488
- {
5489
- disabled,
5490
- removeLabel: `Remove ${labelFor(value)}`,
5491
- onRemove: () => removeSelected(value),
5492
- children: labelFor(value)
5493
- }
5494
- ) }),
5495
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex-shrink-0 text-foreground-muted transition-transform duration-200 ${open ? "rotate-180" : "rotate-0"}`, "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) }) })
5496
- ]
5497
- }
5498
- ) }),
5499
- /* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs(
5500
- Popover__namespace.Content,
5501
- {
5502
- align: "start",
5503
- sideOffset: 4,
5504
- style: { width: style?.width || 240 },
5505
- className: "bg-surface text-foreground border border-border rounded-lg shadow-md z-50 p-2 animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
5506
- onInteractOutside: () => setOpen(false),
5507
- children: [
5508
- hasSearch && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-2", children: /* @__PURE__ */ jsxRuntime.jsx(
5509
- SearchInput_default,
5510
- {
5511
- style: { width: "100%" },
5512
- inputStyle: { width: "100%" },
5513
- value: searchTerm,
5514
- onChange: onSearchChange,
5515
- placeholder: "Search..."
5516
- }
5517
- ) }),
5518
- /* @__PURE__ */ jsxRuntime.jsx("div", { role: "listbox", "aria-multiselectable": isMultiselect, className: "max-h-40 overflow-y-auto", children: innerItems.map((item) => (
5519
- // aria-rowindex was previously set here but
5520
- // it's invalid ARIA on role="option" (it
5521
- // belongs on rows of a grid/treegrid). Dropped.
5522
- // tabIndex={0} + Enter/Space handler makes the
5523
- // option keyboard-activatable; the full
5524
- // combobox roving-tabindex pattern is deferred
5525
- // until the planned Phase-5 rewrite.
5526
- /* @__PURE__ */ jsxRuntime.jsxs(
5527
- "div",
5528
- {
5529
- role: "option",
5530
- "aria-selected": isSelected(item.key),
5531
- tabIndex: 0,
5532
- className: `flex items-center justify-between p-2 hover:bg-accent hover:text-accent-fg transition-colors duration-150 text-sm rounded-lg cursor-pointer focus:outline-none focus-visible:ring-2 focus-visible:ring-accent ${selectedItems.includes(item.key) ? "bg-surface-raised text-foreground" : "text-foreground"}`,
5533
- onClick: () => selectItem(item.key),
5534
- onKeyDown: (e) => {
5535
- if (e.key === "Enter" || e.key === " ") {
5536
- e.preventDefault();
5537
- selectItem(item.key);
5538
- }
5539
- },
5540
- children: [
5541
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-xs", children: [
5542
- item.icon && /* @__PURE__ */ jsxRuntime.jsx("div", { children: item.icon }),
5543
- item.label
5544
- ] }),
5545
- isSelected(item.key) && // currentColor — checkmark follows
5546
- // the item's text colour, which
5547
- // flips automatically on hover.
5548
- /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 20 20", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(
5549
- "path",
5550
- {
5551
- d: "M4 10l4.5 4.5L16 6",
5552
- stroke: "currentColor",
5553
- strokeWidth: "2",
5554
- strokeLinecap: "round",
5555
- strokeLinejoin: "round"
5556
- }
5557
- ) })
5558
- ]
5559
- },
5560
- item.key
5561
- )
5562
- )) })
5563
- ]
5564
- }
5565
- ) })
5566
- ] })
5567
- ]
5568
- }
5569
- ),
5570
- hasError && /* @__PURE__ */ jsxRuntime.jsx("div", { id: errorId, className: "text-status-error text-xs mt-1", children: errorMessage })
5571
- ] });
5572
- }
5573
5271
  var SHIMMER = "oxy-skeleton rounded-sm bg-surface-raised";
5574
5272
  function SkeletonBox({ width, height = 16, radius, className = "", style }) {
5575
5273
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -5725,7 +5423,7 @@ function TableBody({
5725
5423
  expandRow,
5726
5424
  getRowKey
5727
5425
  }) {
5728
- const [expanded, setExpanded] = React29.useState(() => /* @__PURE__ */ new Set());
5426
+ const [expanded, setExpanded] = React28.useState(() => /* @__PURE__ */ new Set());
5729
5427
  const reduced = framerMotion.useReducedMotion();
5730
5428
  const toggleRow = (rowKey) => {
5731
5429
  setExpanded((prev) => {
@@ -5740,7 +5438,7 @@ function TableBody({
5740
5438
  return /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: rows.map((row, i) => {
5741
5439
  const rowKey = getRowKey(row, i);
5742
5440
  const isExpanded = expanded.has(rowKey);
5743
- return /* @__PURE__ */ jsxRuntime.jsxs(React29__default.default.Fragment, { children: [
5441
+ return /* @__PURE__ */ jsxRuntime.jsxs(React28__default.default.Fragment, { children: [
5744
5442
  /* @__PURE__ */ jsxRuntime.jsxs(
5745
5443
  "tr",
5746
5444
  {
@@ -5796,14 +5494,16 @@ function Pagination({
5796
5494
  const matchedOption = picker.find(
5797
5495
  (o) => o.label === options.perPage || o.value === options.perPage
5798
5496
  );
5799
- const [perPageKey, setPerPageKey] = React29.useState(() => matchedOption?.key ?? picker[0]?.key);
5497
+ const [perPageKey, setPerPageKey] = React28.useState(() => matchedOption?.key ?? picker[0]?.key);
5800
5498
  const displayPerPageKey = serverSide ? matchedOption?.key ?? perPageKey : perPageKey;
5801
- React29.useEffect(() => {
5499
+ React28.useEffect(() => {
5802
5500
  if (serverSide && options.perPage != null) {
5803
5501
  const next = picker.find((o) => o.label === options.perPage || o.value === options.perPage);
5804
5502
  if (next) setPerPageKey(next.key);
5805
5503
  }
5806
5504
  }, [serverSide, options.perPage, picker]);
5505
+ const currentOpt = picker.find((o) => o.key === displayPerPageKey);
5506
+ const currentPerPageLabel = currentOpt?.label ?? currentOpt?.value ?? options.perPage ?? "";
5807
5507
  const navBtn = (icon, disabled, onClick, title) => /* @__PURE__ */ jsxRuntime.jsx(IconButton, { type: "bordered", size: "sm", disabled, onClick, icon, title });
5808
5508
  const chevronRight = /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 5l7 7-7 7" }) });
5809
5509
  const doubleChevronRight = /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M13 5l7 7-7 7M5 5l7 7-7 7" }) });
@@ -5811,21 +5511,20 @@ function Pagination({
5811
5511
  options.withPicker && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mr-auto flex items-center gap-2", children: [
5812
5512
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "whitespace-nowrap text-xs text-foreground-muted", children: "Rows per page" }),
5813
5513
  /* @__PURE__ */ jsxRuntime.jsx(
5814
- Dropdown,
5514
+ MenuButton,
5815
5515
  {
5516
+ variant: "secondary",
5816
5517
  size: "sm",
5817
- style: { width: 76 },
5818
- hasSearch: false,
5819
- items: picker,
5820
- isMultiselect: false,
5821
- value: displayPerPageKey,
5822
- onChange: ({ target: { value } }) => {
5823
- if (Array.isArray(value)) return;
5824
- const numKey = typeof value === "number" ? value : Number(value);
5825
- if (!serverSide) setPerPageKey(numKey);
5826
- const opt = picker.find((o) => o.key === numKey);
5827
- onPerPageChange(opt?.label ?? opt?.value ?? numKey);
5828
- }
5518
+ side: "top",
5519
+ label: String(currentPerPageLabel),
5520
+ items: picker.map((o) => ({
5521
+ key: o.key,
5522
+ label: String(o.label ?? o.value ?? o.key),
5523
+ onSelect: () => {
5524
+ if (!serverSide) setPerPageKey(o.key);
5525
+ onPerPageChange(o.label ?? o.value ?? o.key);
5526
+ }
5527
+ }))
5829
5528
  }
5830
5529
  )
5831
5530
  ] }),
@@ -5859,14 +5558,14 @@ function Table({
5859
5558
  className = "",
5860
5559
  style
5861
5560
  }) {
5862
- const searchRef = React29.useRef(null);
5863
- const [searchTerm, setSearchTerm] = React29.useState("");
5864
- const [perPage, setPerPage] = React29.useState(
5561
+ const searchRef = React28.useRef(null);
5562
+ const [searchTerm, setSearchTerm] = React28.useState("");
5563
+ const [perPage, setPerPage] = React28.useState(
5865
5564
  typeof pagination.perPage === "number" ? pagination.perPage : 15
5866
5565
  );
5867
- const [activePage, setActivePage] = React29.useState(0);
5566
+ const [activePage, setActivePage] = React28.useState(0);
5868
5567
  const isServerSide = !!(pagination.enabled && pagination.serverSide);
5869
- const filteredRows = React29.useMemo(() => {
5568
+ const filteredRows = React28.useMemo(() => {
5870
5569
  if (isServerSide || !searchTerm) return rows;
5871
5570
  const term = searchTerm.toLowerCase();
5872
5571
  return rows.filter(
@@ -5875,29 +5574,29 @@ function Table({
5875
5574
  )
5876
5575
  );
5877
5576
  }, [rows, searchTerm, isServerSide]);
5878
- const datasets = React29.useMemo(() => {
5577
+ const datasets = React28.useMemo(() => {
5879
5578
  if (isServerSide) return [rows];
5880
5579
  return createDatasets(filteredRows, pagination.enabled ? perPage : null);
5881
5580
  }, [filteredRows, perPage, pagination.enabled, isServerSide, rows]);
5882
- const MAX_PAGE = React29.useMemo(() => {
5581
+ const MAX_PAGE = React28.useMemo(() => {
5883
5582
  if (isServerSide && typeof pagination.maxPage === "number") return Math.max(0, pagination.maxPage);
5884
5583
  if (isServerSide && typeof pagination.totalCount === "number")
5885
5584
  return Math.max(0, Math.ceil(pagination.totalCount / perPage) - 1);
5886
5585
  return datasets.length ? datasets.length - 1 : 0;
5887
5586
  }, [isServerSide, pagination.maxPage, pagination.totalCount, perPage, datasets.length]);
5888
- const currentPageRows = React29.useMemo(() => {
5587
+ const currentPageRows = React28.useMemo(() => {
5889
5588
  if (isServerSide) return rows;
5890
5589
  return datasets[activePage] ?? [];
5891
5590
  }, [isServerSide, rows, datasets, activePage]);
5892
- React29.useEffect(() => {
5591
+ React28.useEffect(() => {
5893
5592
  if (pagination.enabled && !isServerSide && typeof pagination.perPage === "number") {
5894
5593
  setPerPage(pagination.perPage);
5895
5594
  }
5896
5595
  }, [pagination.enabled, pagination.perPage, isServerSide]);
5897
- React29.useEffect(() => {
5596
+ React28.useEffect(() => {
5898
5597
  if (isServerSide && typeof pagination.perPage === "number") setPerPage(pagination.perPage);
5899
5598
  }, [isServerSide, pagination.perPage]);
5900
- React29.useEffect(() => {
5599
+ React28.useEffect(() => {
5901
5600
  if (isServerSide && typeof pagination.page === "number" && pagination.page >= 1)
5902
5601
  setActivePage(pagination.page - 1);
5903
5602
  }, [isServerSide, pagination.page]);
@@ -5981,7 +5680,7 @@ function TableSkeletonBody({
5981
5680
  )) });
5982
5681
  }
5983
5682
  function ThemeSwitch({ checked, onChange, label = "Toggle dark mode", className = "" }) {
5984
- const id = React29.useId();
5683
+ const id = React28.useId();
5985
5684
  return /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, className: `flex items-center gap-2 cursor-pointer select-none ${className}`.trim(), children: /* @__PURE__ */ jsxRuntime.jsx(
5986
5685
  SwitchPrimitive__namespace.Root,
5987
5686
  {
@@ -6165,7 +5864,7 @@ function Sidebar({
6165
5864
  }
6166
5865
  ) });
6167
5866
  }
6168
- var MegaMenuContext = React29.createContext({ align: "start" });
5867
+ var MegaMenuContext = React28.createContext({ align: "start" });
6169
5868
  function MegaMenu({
6170
5869
  children,
6171
5870
  align = "start",
@@ -6196,7 +5895,7 @@ function MegaMenu({
6196
5895
  }
6197
5896
  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";
6198
5897
  function MegaMenuItem({ label, icon, href, children, className = "" }) {
6199
- const { align } = React29.useContext(MegaMenuContext);
5898
+ const { align } = React28.useContext(MegaMenuContext);
6200
5899
  const pos = align === "center" ? "left-1/2 -translate-x-1/2" : align === "end" ? "right-0" : "left-0";
6201
5900
  if (!children) {
6202
5901
  return /* @__PURE__ */ jsxRuntime.jsx(NavigationMenu__namespace.Item, { children: /* @__PURE__ */ jsxRuntime.jsxs(NavigationMenu__namespace.Link, { href, className: [TOP_ITEM, className].filter(Boolean).join(" "), children: [
@@ -6281,8 +5980,8 @@ function MegaMenuLink({ href, icon, description, active, onClick, children, clas
6281
5980
  function MegaMenuFeatured({ children, className = "" }) {
6282
5981
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: ["min-w-0 rounded-lg bg-surface-raised border border-border p-4 flex flex-col", className].filter(Boolean).join(" "), children });
6283
5982
  }
6284
- var elementsOfType = (children, type) => React29__default.default.Children.toArray(children).filter(
6285
- (c) => React29__default.default.isValidElement(c) && c.type === type
5983
+ var elementsOfType = (children, type) => React28__default.default.Children.toArray(children).filter(
5984
+ (c) => React28__default.default.isValidElement(c) && c.type === type
6286
5985
  );
6287
5986
  var MOBILE_CHEVRON = /* @__PURE__ */ jsxRuntime.jsx(
6288
5987
  "svg",
@@ -6319,9 +6018,9 @@ function MobileLinkRow({ link, onNavigate }) {
6319
6018
  );
6320
6019
  }
6321
6020
  function MobilePanel({ panel, onNavigate }) {
6322
- const nodes = React29__default.default.Children.toArray(panel.props.children);
6021
+ const nodes = React28__default.default.Children.toArray(panel.props.children);
6323
6022
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-4 px-2 pb-3 pt-1", children: nodes.map((node, i) => {
6324
- if (!React29__default.default.isValidElement(node)) return null;
6023
+ if (!React28__default.default.isValidElement(node)) return null;
6325
6024
  const el = node;
6326
6025
  if (el.type === MegaMenuSection) {
6327
6026
  const { title, children } = el.props;
@@ -6340,8 +6039,8 @@ function MegaMenuMobile({
6340
6039
  children,
6341
6040
  label
6342
6041
  }) {
6343
- const [open, setOpen] = React29.useState(false);
6344
- const [expanded, setExpanded] = React29.useState(null);
6042
+ const [open, setOpen] = React28.useState(false);
6043
+ const [expanded, setExpanded] = React28.useState(null);
6345
6044
  const items = elementsOfType(children, MegaMenuItem);
6346
6045
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "md:hidden w-full", children: [
6347
6046
  /* @__PURE__ */ jsxRuntime.jsxs(
@@ -6414,17 +6113,17 @@ function AppShell({
6414
6113
  children,
6415
6114
  className = ""
6416
6115
  }) {
6417
- const [expanded, setExpanded] = React29.useState(sidebarDefaultExpanded);
6418
- const [isMobile, setIsMobile] = React29.useState(false);
6419
- const [mobileOpen, setMobileOpen] = React29.useState(false);
6420
- React29.useEffect(() => {
6116
+ const [expanded, setExpanded] = React28.useState(sidebarDefaultExpanded);
6117
+ const [isMobile, setIsMobile] = React28.useState(false);
6118
+ const [mobileOpen, setMobileOpen] = React28.useState(false);
6119
+ React28.useEffect(() => {
6421
6120
  const mq = window.matchMedia("(max-width: 767px)");
6422
6121
  const update = (e) => setIsMobile(e.matches);
6423
6122
  update(mq);
6424
6123
  mq.addEventListener("change", update);
6425
6124
  return () => mq.removeEventListener("change", update);
6426
6125
  }, []);
6427
- React29.useEffect(() => {
6126
+ React28.useEffect(() => {
6428
6127
  if (!isMobile) setMobileOpen(false);
6429
6128
  }, [isMobile]);
6430
6129
  const hasSidebar = sidebarSections.length > 0;
@@ -6551,7 +6250,7 @@ function SecureLayout({
6551
6250
  className = ""
6552
6251
  }) {
6553
6252
  const reduced = framerMotion.useReducedMotion();
6554
- const cbs = React29.useRef({ canAccess, onGranted, onDeny });
6253
+ const cbs = React28.useRef({ canAccess, onGranted, onDeny });
6555
6254
  cbs.current = { canAccess, onGranted, onDeny };
6556
6255
  const rolesKey = JSON.stringify(roles);
6557
6256
  const requiredRolesKey = JSON.stringify(requiredRoles);
@@ -6566,10 +6265,10 @@ function SecureLayout({
6566
6265
  if (requiredPermissions?.length && !has(permissions, requiredPermissions, requireAllPermissions)) return false;
6567
6266
  return true;
6568
6267
  };
6569
- const [state, setState] = React29.useState(
6268
+ const [state, setState] = React28.useState(
6570
6269
  () => !passesSync() ? "denied" : canAccess ? "checking" : "granted"
6571
6270
  );
6572
- React29.useEffect(() => {
6271
+ React28.useEffect(() => {
6573
6272
  let cancelled = false;
6574
6273
  const { canAccess: check, onGranted: granted, onDeny: deny } = cbs.current;
6575
6274
  const finish = (ok) => {
@@ -6730,10 +6429,10 @@ function ThemeProvider({
6730
6429
  className = "",
6731
6430
  style
6732
6431
  }) {
6733
- const id = React29__default.default.useId().replace(/:/g, "");
6432
+ const id = React28__default.default.useId().replace(/:/g, "");
6734
6433
  const scopeClass = `geo-th-${id}`;
6735
- const divRef = React29.useRef(null);
6736
- React29.useEffect(() => {
6434
+ const divRef = React28.useRef(null);
6435
+ React28.useEffect(() => {
6737
6436
  const el = divRef.current;
6738
6437
  if (!el) return;
6739
6438
  if (colorScheme === "auto") return;
@@ -6748,8 +6447,8 @@ function ThemeProvider({
6748
6447
  }
6749
6448
  el.classList.toggle("dark", colorScheme === "dark");
6750
6449
  }, [colorScheme]);
6751
- const lightVars = React29.useMemo(() => toCssVars(theme), [theme]);
6752
- const darkVarStr = React29.useMemo(() => {
6450
+ const lightVars = React28.useMemo(() => toCssVars(theme), [theme]);
6451
+ const darkVarStr = React28.useMemo(() => {
6753
6452
  if (!darkTheme) return "";
6754
6453
  const dvars = toCssVars(darkTheme);
6755
6454
  if (!Object.keys(dvars).length) return "";
@@ -6791,7 +6490,7 @@ function NumberInput({
6791
6490
  readOnly = false,
6792
6491
  precision
6793
6492
  }) {
6794
- const errorId = React29.useId();
6493
+ const errorId = React28.useId();
6795
6494
  const hasError = errorMessage != null;
6796
6495
  const inferredPrecision = precision ?? (Number.isInteger(step) ? 0 : String(step).split(".")[1]?.length ?? 0);
6797
6496
  const round = (n) => {
@@ -6922,8 +6621,8 @@ function Password({
6922
6621
  showIcon,
6923
6622
  hideIcon
6924
6623
  }) {
6925
- const [visible, setVisible] = React29.useState(false);
6926
- const errorId = React29.useId();
6624
+ const [visible, setVisible] = React28.useState(false);
6625
+ const errorId = React28.useId();
6927
6626
  const hasError = errorMessage != null;
6928
6627
  return /* @__PURE__ */ jsxRuntime.jsx(
6929
6628
  Field,
@@ -6996,7 +6695,7 @@ function Checkbox({
6996
6695
  }) {
6997
6696
  const isChecked = checked ?? value ?? false;
6998
6697
  const labelFirst = labelPosition === "left";
6999
- const errorId = React29.useId();
6698
+ const errorId = React28.useId();
7000
6699
  const hasError = errorMessage != null;
7001
6700
  const box = /* @__PURE__ */ jsxRuntime.jsx(
7002
6701
  CheckboxPrimitive__namespace.Root,
@@ -7104,8 +6803,8 @@ function RadioGroup({
7104
6803
  className,
7105
6804
  errorMessage
7106
6805
  }) {
7107
- const errorId = React29.useId();
7108
- const groupId = React29.useId();
6806
+ const errorId = React28.useId();
6807
+ const groupId = React28.useId();
7109
6808
  const hasError = errorMessage != null;
7110
6809
  const labelFirst = labelPosition === "left";
7111
6810
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -7188,77 +6887,379 @@ function RadioGroup({
7188
6887
  }
7189
6888
  );
7190
6889
  }
7191
- function Switch({
7192
- checked,
7193
- defaultChecked = false,
7194
- onChange,
7195
- checkedIcon,
7196
- uncheckedIcon,
6890
+ function Switch({
6891
+ checked,
6892
+ defaultChecked = false,
6893
+ onChange,
6894
+ checkedIcon,
6895
+ uncheckedIcon,
6896
+ label,
6897
+ layout = "horizontal",
6898
+ helperText,
6899
+ className,
6900
+ offLabel,
6901
+ onLabel,
6902
+ name,
6903
+ required,
6904
+ disabled,
6905
+ errorMessage
6906
+ }) {
6907
+ const id = React28.useId();
6908
+ const errorId = React28.useId();
6909
+ const hasError = errorMessage != null;
6910
+ const isControlled = checked !== void 0;
6911
+ const [internal, setInternal] = React28.useState(defaultChecked);
6912
+ const isOn = isControlled ? checked : internal;
6913
+ const handle = (c) => {
6914
+ if (!isControlled) setInternal(c);
6915
+ onChange?.({ target: { checked: c, name } });
6916
+ };
6917
+ const stateLabel = (active) => [
6918
+ "text-sm select-none transition-colors",
6919
+ active ? "text-foreground font-medium" : "text-foreground-muted",
6920
+ disabled ? "opacity-50" : "cursor-pointer"
6921
+ ].filter(Boolean).join(" ");
6922
+ return /* @__PURE__ */ jsxRuntime.jsx(
6923
+ Field,
6924
+ {
6925
+ className,
6926
+ label,
6927
+ htmlFor: id,
6928
+ errorId,
6929
+ errorMessage,
6930
+ layout,
6931
+ required,
6932
+ helperText,
6933
+ labelAlign: "center",
6934
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2.5", children: [
6935
+ offLabel != null && /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, className: stateLabel(!isOn), children: offLabel }),
6936
+ /* @__PURE__ */ jsxRuntime.jsx(
6937
+ SwitchPrimitive__namespace.Root,
6938
+ {
6939
+ id,
6940
+ name,
6941
+ checked: isOn,
6942
+ onCheckedChange: handle,
6943
+ disabled,
6944
+ required,
6945
+ "aria-invalid": hasError || void 0,
6946
+ "aria-describedby": hasError ? errorId : void 0,
6947
+ className: "relative inline-flex h-6 w-11 flex-shrink-0 items-center rounded-full bg-foreground-secondary data-[state=checked]:bg-accent transition-colors focus:outline-none focus-visible:ring-[3px] focus-visible:ring-focus-ring disabled:opacity-50 disabled:cursor-not-allowed",
6948
+ children: /* @__PURE__ */ jsxRuntime.jsx(
6949
+ SwitchPrimitive__namespace.Thumb,
6950
+ {
6951
+ className: "pointer-events-none flex h-5 w-5 items-center justify-center rounded-full bg-background text-foreground shadow transition-transform duration-200 data-[state=checked]:translate-x-[22px] data-[state=unchecked]:translate-x-[2px]",
6952
+ children: checkedIcon && uncheckedIcon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex items-center justify-center w-3 h-3", children: isOn ? checkedIcon : uncheckedIcon }) : null
6953
+ }
6954
+ )
6955
+ }
6956
+ ),
6957
+ onLabel != null && /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, className: stateLabel(isOn), children: onLabel })
6958
+ ] })
6959
+ }
6960
+ );
6961
+ }
6962
+ function Tag({ children, onRemove, removeLabel, disabled }) {
6963
+ return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1 rounded-md border border-border bg-surface-raised text-foreground text-xs pl-2 pr-1 py-0.5 max-w-full", children: [
6964
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children }),
6965
+ onRemove && /* @__PURE__ */ jsxRuntime.jsx(
6966
+ "button",
6967
+ {
6968
+ type: "button",
6969
+ disabled,
6970
+ onClick: (e) => {
6971
+ e.stopPropagation();
6972
+ onRemove();
6973
+ },
6974
+ "aria-label": removeLabel ?? "Remove",
6975
+ className: "inline-flex items-center justify-center w-4 h-4 flex-shrink-0 rounded text-foreground-muted hover:text-status-error hover:bg-surface transition-colors focus:outline-none focus-visible:ring-1 focus-visible:ring-accent disabled:cursor-not-allowed",
6976
+ children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "10", height: "10", viewBox: "0 0 20 20", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15 5L5 15M5 5l10 10", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) })
6977
+ }
6978
+ )
6979
+ ] });
6980
+ }
6981
+ function MultiTagRow({
6982
+ values,
6983
+ disabled,
6984
+ labelFor,
6985
+ onRemove
6986
+ }) {
6987
+ const wrapRef = React28.useRef(null);
6988
+ const measureRef = React28.useRef(null);
6989
+ const [visibleCount, setVisibleCount] = React28.useState(values.length);
6990
+ const key = values.map(String).join("|");
6991
+ React28.useLayoutEffect(() => {
6992
+ const wrap = wrapRef.current;
6993
+ const measure = measureRef.current;
6994
+ if (!wrap || !measure) return;
6995
+ const GAP = 6;
6996
+ const recompute = () => {
6997
+ const avail = wrap.clientWidth;
6998
+ const tagEls = Array.from(measure.querySelectorAll("[data-mt]"));
6999
+ const moreEl = measure.querySelector("[data-mm]");
7000
+ const widths = tagEls.map((e) => e.offsetWidth);
7001
+ const moreW = moreEl ? moreEl.offsetWidth : 0;
7002
+ if (widths.length === 0) {
7003
+ setVisibleCount(0);
7004
+ return;
7005
+ }
7006
+ let used = 0;
7007
+ let count = 0;
7008
+ for (let i = 0; i < widths.length; i++) {
7009
+ const w = widths[i] + (i > 0 ? GAP : 0);
7010
+ if (used + w <= avail) {
7011
+ used += w;
7012
+ count++;
7013
+ } else break;
7014
+ }
7015
+ if (count < widths.length) {
7016
+ while (count > 0) {
7017
+ let t = 0;
7018
+ for (let i = 0; i < count; i++) t += widths[i] + (i > 0 ? GAP : 0);
7019
+ t += GAP + moreW;
7020
+ if (t <= avail) break;
7021
+ count--;
7022
+ }
7023
+ }
7024
+ setVisibleCount(count);
7025
+ };
7026
+ recompute();
7027
+ const ro = new ResizeObserver(recompute);
7028
+ ro.observe(wrap);
7029
+ return () => ro.disconnect();
7030
+ }, [key]);
7031
+ const hidden = values.length - visibleCount;
7032
+ const moreChip = (n) => /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center flex-shrink-0 rounded-md border border-border bg-surface-raised text-foreground-secondary text-xs px-2 py-0.5", children: [
7033
+ "+",
7034
+ n,
7035
+ " more"
7036
+ ] });
7037
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: wrapRef, className: "relative flex-1 min-w-0 flex flex-nowrap items-center gap-1.5 overflow-hidden", children: [
7038
+ /* @__PURE__ */ jsxRuntime.jsxs(
7039
+ "div",
7040
+ {
7041
+ ref: measureRef,
7042
+ "aria-hidden": "true",
7043
+ className: "absolute invisible pointer-events-none flex flex-nowrap items-center gap-1.5",
7044
+ style: { left: -9999, top: -9999 },
7045
+ children: [
7046
+ values.map((val) => /* @__PURE__ */ jsxRuntime.jsx("span", { "data-mt": true, children: /* @__PURE__ */ jsxRuntime.jsx(Tag, { removeLabel: "x", onRemove: () => {
7047
+ }, children: labelFor(val) }) }, `m-${val}`)),
7048
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "data-mm": true, children: moreChip(values.length) })
7049
+ ]
7050
+ }
7051
+ ),
7052
+ values.slice(0, visibleCount).map((val) => /* @__PURE__ */ jsxRuntime.jsx(
7053
+ Tag,
7054
+ {
7055
+ disabled,
7056
+ removeLabel: `Remove ${labelFor(val)}`,
7057
+ onRemove: () => onRemove(val),
7058
+ children: labelFor(val)
7059
+ },
7060
+ String(val)
7061
+ )),
7062
+ hidden > 0 && moreChip(hidden)
7063
+ ] });
7064
+ }
7065
+ function Dropdown({
7066
+ isMultiselect = false,
7067
+ hasSearch = true,
7197
7068
  label,
7069
+ name,
7070
+ value,
7071
+ onChange,
7072
+ disabled,
7198
7073
  layout = "horizontal",
7199
7074
  helperText,
7200
- className,
7201
- offLabel,
7202
- onLabel,
7203
- name,
7204
7075
  required,
7205
- disabled,
7206
- errorMessage
7076
+ errorMessage,
7077
+ style = {},
7078
+ htmlFor,
7079
+ items = [],
7080
+ labelStyle = {},
7081
+ placeholder,
7082
+ size = "md",
7083
+ className = ""
7207
7084
  }) {
7208
- const id = React29.useId();
7209
- const errorId = React29.useId();
7085
+ const [open, setOpen] = React28.useState(false);
7086
+ const [selectedItems, setSelectedItems] = React28.useState([]);
7087
+ const [searchTerm, setSearchTerm] = React28.useState("");
7088
+ const [innerItems, setInnerItems] = React28.useState([]);
7089
+ const errorId = React28.useId();
7210
7090
  const hasError = errorMessage != null;
7211
- const isControlled = checked !== void 0;
7212
- const [internal, setInternal] = React29.useState(defaultChecked);
7213
- const isOn = isControlled ? checked : internal;
7214
- const handle = (c) => {
7215
- if (!isControlled) setInternal(c);
7216
- onChange?.({ target: { checked: c, name } });
7091
+ React28.useEffect(() => {
7092
+ setInnerItems(items);
7093
+ }, [items]);
7094
+ React28.useEffect(() => {
7095
+ if (isMultiselect && Array.isArray(value)) {
7096
+ setSelectedItems(value);
7097
+ }
7098
+ }, [isMultiselect, value]);
7099
+ const selectItem = (key) => {
7100
+ if (isMultiselect) {
7101
+ const next = selectedItems.includes(key) ? selectedItems.filter((it) => it !== key) : [...selectedItems, key];
7102
+ setSelectedItems(next);
7103
+ onChange?.({ target: { value: next, id: htmlFor, name } });
7104
+ } else {
7105
+ setSelectedItems([key]);
7106
+ onChange?.({ target: { value: key, id: htmlFor, name } });
7107
+ setOpen(false);
7108
+ }
7217
7109
  };
7218
- const stateLabel = (active) => [
7219
- "text-sm select-none transition-colors",
7220
- active ? "text-foreground font-medium" : "text-foreground-muted",
7221
- disabled ? "opacity-50" : "cursor-pointer"
7222
- ].filter(Boolean).join(" ");
7223
- return /* @__PURE__ */ jsxRuntime.jsx(
7224
- Field,
7225
- {
7226
- className,
7227
- label,
7228
- htmlFor: id,
7229
- errorId,
7230
- errorMessage,
7231
- layout,
7232
- required,
7233
- helperText,
7234
- labelAlign: "center",
7235
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2.5", children: [
7236
- offLabel != null && /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, className: stateLabel(!isOn), children: offLabel }),
7237
- /* @__PURE__ */ jsxRuntime.jsx(
7238
- SwitchPrimitive__namespace.Root,
7239
- {
7240
- id,
7241
- name,
7242
- checked: isOn,
7243
- onCheckedChange: handle,
7244
- disabled,
7245
- required,
7246
- "aria-invalid": hasError || void 0,
7247
- "aria-describedby": hasError ? errorId : void 0,
7248
- className: "relative inline-flex h-6 w-11 flex-shrink-0 items-center rounded-full bg-foreground-secondary data-[state=checked]:bg-accent transition-colors focus:outline-none focus-visible:ring-[3px] focus-visible:ring-focus-ring disabled:opacity-50 disabled:cursor-not-allowed",
7249
- children: /* @__PURE__ */ jsxRuntime.jsx(
7250
- SwitchPrimitive__namespace.Thumb,
7110
+ const removeSelected = (key) => {
7111
+ if (isMultiselect) {
7112
+ const next = selectedItems.filter((it) => it !== key);
7113
+ setSelectedItems(next);
7114
+ onChange?.({ target: { value: next, id: htmlFor, name } });
7115
+ } else {
7116
+ setSelectedItems([]);
7117
+ onChange?.({ target: { value: "", id: htmlFor, name } });
7118
+ }
7119
+ };
7120
+ const labelFor = (key) => innerItems.find((it) => it.key === key)?.label ?? String(key);
7121
+ const onSearchChange = (e) => {
7122
+ const term = e.target.value;
7123
+ setSearchTerm(term);
7124
+ setInnerItems(
7125
+ term.trim() === "" ? items : items.filter(
7126
+ (it) => String(it.label).toLowerCase().includes(term.toLowerCase())
7127
+ )
7128
+ );
7129
+ };
7130
+ const isSelected = (key) => Array.isArray(value) ? value.includes(key) : value === key;
7131
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: className || void 0, children: [
7132
+ /* @__PURE__ */ jsxRuntime.jsxs(
7133
+ "div",
7134
+ {
7135
+ className: `flex ${layout === "vertical" ? "flex-col gap-1.5" : "flex-row items-start gap-3"}`,
7136
+ children: [
7137
+ /* @__PURE__ */ jsxRuntime.jsx(
7138
+ FieldLabel,
7139
+ {
7140
+ label,
7141
+ htmlFor,
7142
+ required,
7143
+ helperText,
7144
+ horizontal: layout === "horizontal",
7145
+ style: labelStyle
7146
+ }
7147
+ ),
7148
+ /* @__PURE__ */ jsxRuntime.jsxs(Popover__namespace.Root, { open: open && !disabled, onOpenChange: (o) => !disabled && setOpen(o), children: [
7149
+ /* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
7150
+ "div",
7251
7151
  {
7252
- className: "pointer-events-none flex h-5 w-5 items-center justify-center rounded-full bg-background text-foreground shadow transition-transform duration-200 data-[state=checked]:translate-x-[22px] data-[state=unchecked]:translate-x-[2px]",
7253
- children: checkedIcon && uncheckedIcon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex items-center justify-center w-3 h-3", children: isOn ? checkedIcon : uncheckedIcon }) : null
7152
+ id: htmlFor,
7153
+ role: "combobox",
7154
+ "aria-expanded": open,
7155
+ "aria-haspopup": "listbox",
7156
+ "aria-invalid": hasError || void 0,
7157
+ "aria-describedby": hasError ? errorId : void 0,
7158
+ style: { width: 240, ...style },
7159
+ className: `flex items-center justify-between gap-2 cursor-pointer select-none min-h-[36px] px-3 py-1.5 ${fieldShell({ size, hasError, disabled, sized: false })}`,
7160
+ tabIndex: disabled ? -1 : 0,
7161
+ onKeyDown: (e) => {
7162
+ if (disabled) return;
7163
+ if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown" || e.key === "ArrowUp") {
7164
+ e.preventDefault();
7165
+ setOpen(true);
7166
+ }
7167
+ },
7168
+ children: [
7169
+ !value || Array.isArray(value) && value.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 min-w-0 truncate text-foreground-muted text-sm", children: placeholder }) : Array.isArray(value) ? /* @__PURE__ */ jsxRuntime.jsx(
7170
+ MultiTagRow,
7171
+ {
7172
+ values: value,
7173
+ disabled,
7174
+ labelFor,
7175
+ onRemove: removeSelected
7176
+ }
7177
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-w-0 flex items-center overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
7178
+ Tag,
7179
+ {
7180
+ disabled,
7181
+ removeLabel: `Remove ${labelFor(value)}`,
7182
+ onRemove: () => removeSelected(value),
7183
+ children: labelFor(value)
7184
+ }
7185
+ ) }),
7186
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex-shrink-0 text-foreground-muted transition-transform duration-200 ${open ? "rotate-180" : "rotate-0"}`, "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) }) })
7187
+ ]
7254
7188
  }
7255
- )
7256
- }
7257
- ),
7258
- onLabel != null && /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, className: stateLabel(isOn), children: onLabel })
7259
- ] })
7260
- }
7261
- );
7189
+ ) }),
7190
+ /* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs(
7191
+ Popover__namespace.Content,
7192
+ {
7193
+ align: "start",
7194
+ sideOffset: 4,
7195
+ style: { width: style?.width || 240 },
7196
+ className: "bg-surface text-foreground border border-border rounded-lg shadow-md z-50 p-2 animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
7197
+ onInteractOutside: () => setOpen(false),
7198
+ children: [
7199
+ hasSearch && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-2", children: /* @__PURE__ */ jsxRuntime.jsx(
7200
+ SearchInput_default,
7201
+ {
7202
+ style: { width: "100%" },
7203
+ inputStyle: { width: "100%" },
7204
+ value: searchTerm,
7205
+ onChange: onSearchChange,
7206
+ placeholder: "Search..."
7207
+ }
7208
+ ) }),
7209
+ /* @__PURE__ */ jsxRuntime.jsx("div", { role: "listbox", "aria-multiselectable": isMultiselect, className: "max-h-40 overflow-y-auto", children: innerItems.map((item) => (
7210
+ // aria-rowindex was previously set here but
7211
+ // it's invalid ARIA on role="option" (it
7212
+ // belongs on rows of a grid/treegrid). Dropped.
7213
+ // tabIndex={0} + Enter/Space handler makes the
7214
+ // option keyboard-activatable; the full
7215
+ // combobox roving-tabindex pattern is deferred
7216
+ // until the planned Phase-5 rewrite.
7217
+ /* @__PURE__ */ jsxRuntime.jsxs(
7218
+ "div",
7219
+ {
7220
+ role: "option",
7221
+ "aria-selected": isSelected(item.key),
7222
+ tabIndex: 0,
7223
+ className: `flex items-center justify-between p-2 hover:bg-accent hover:text-accent-fg transition-colors duration-150 text-sm rounded-lg cursor-pointer focus:outline-none focus-visible:ring-2 focus-visible:ring-accent ${selectedItems.includes(item.key) ? "bg-surface-raised text-foreground" : "text-foreground"}`,
7224
+ onClick: () => selectItem(item.key),
7225
+ onKeyDown: (e) => {
7226
+ if (e.key === "Enter" || e.key === " ") {
7227
+ e.preventDefault();
7228
+ selectItem(item.key);
7229
+ }
7230
+ },
7231
+ children: [
7232
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-xs", children: [
7233
+ item.icon && /* @__PURE__ */ jsxRuntime.jsx("div", { children: item.icon }),
7234
+ item.label
7235
+ ] }),
7236
+ isSelected(item.key) && // currentColor — checkmark follows
7237
+ // the item's text colour, which
7238
+ // flips automatically on hover.
7239
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 20 20", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(
7240
+ "path",
7241
+ {
7242
+ d: "M4 10l4.5 4.5L16 6",
7243
+ stroke: "currentColor",
7244
+ strokeWidth: "2",
7245
+ strokeLinecap: "round",
7246
+ strokeLinejoin: "round"
7247
+ }
7248
+ ) })
7249
+ ]
7250
+ },
7251
+ item.key
7252
+ )
7253
+ )) })
7254
+ ]
7255
+ }
7256
+ ) })
7257
+ ] })
7258
+ ]
7259
+ }
7260
+ ),
7261
+ hasError && /* @__PURE__ */ jsxRuntime.jsx("div", { id: errorId, className: "text-status-error text-xs mt-1", children: errorMessage })
7262
+ ] });
7262
7263
  }
7263
7264
  function AutoComplete({
7264
7265
  disabled,
@@ -7282,19 +7283,19 @@ function AutoComplete({
7282
7283
  required,
7283
7284
  htmlFor
7284
7285
  }) {
7285
- const errorId = React29.useId();
7286
+ const errorId = React28.useId();
7286
7287
  const hasError = errorMessage != null;
7287
- const [term, setTerm] = React29.useState("");
7288
- const [open, setOpen] = React29.useState(false);
7289
- const [asyncItems, setAsyncItems] = React29.useState([]);
7290
- const [loading, setLoading] = React29.useState(false);
7288
+ const [term, setTerm] = React28.useState("");
7289
+ const [open, setOpen] = React28.useState(false);
7290
+ const [asyncItems, setAsyncItems] = React28.useState([]);
7291
+ const [loading, setLoading] = React28.useState(false);
7291
7292
  const isAsync = typeof onSearch === "function";
7292
- const debounceRef = React29.useRef(null);
7293
- const requestIdRef = React29.useRef(0);
7293
+ const debounceRef = React28.useRef(null);
7294
+ const requestIdRef = React28.useRef(0);
7294
7295
  const staticFiltered = isAsync || !items ? [] : term.trim() ? items.filter(
7295
7296
  ({ key, label: label2 }) => label2.toLowerCase().includes(term.toLowerCase()) || key.toLowerCase().includes(term.toLowerCase())
7296
7297
  ) : [];
7297
- React29.useEffect(() => {
7298
+ React28.useEffect(() => {
7298
7299
  if (!isAsync) return;
7299
7300
  if (debounceRef.current) clearTimeout(debounceRef.current);
7300
7301
  if (!term.trim()) {
@@ -7450,15 +7451,15 @@ function TreeSelect({
7450
7451
  defaultExpandedKeys = [],
7451
7452
  size = "md"
7452
7453
  }) {
7453
- const errorId = React29.useId();
7454
+ const errorId = React28.useId();
7454
7455
  const hasError = errorMessage != null;
7455
- const [open, setOpen] = React29.useState(false);
7456
- const [expanded, setExpanded] = React29.useState(() => new Set(defaultExpandedKeys));
7457
- const [activeIndex, setActiveIndex] = React29.useState(0);
7458
- const listRef = React29.useRef(null);
7459
- const visible = React29.useMemo(() => flattenVisible(items, expanded), [items, expanded]);
7460
- const didSyncOnOpenRef = React29.useRef(false);
7461
- React29.useEffect(() => {
7456
+ const [open, setOpen] = React28.useState(false);
7457
+ const [expanded, setExpanded] = React28.useState(() => new Set(defaultExpandedKeys));
7458
+ const [activeIndex, setActiveIndex] = React28.useState(0);
7459
+ const listRef = React28.useRef(null);
7460
+ const visible = React28.useMemo(() => flattenVisible(items, expanded), [items, expanded]);
7461
+ const didSyncOnOpenRef = React28.useRef(false);
7462
+ React28.useEffect(() => {
7462
7463
  if (!open) {
7463
7464
  didSyncOnOpenRef.current = false;
7464
7465
  return;
@@ -7468,7 +7469,7 @@ function TreeSelect({
7468
7469
  setActiveIndex(selectedIdx >= 0 ? selectedIdx : 0);
7469
7470
  didSyncOnOpenRef.current = true;
7470
7471
  }, [open, value]);
7471
- const selectedNode = React29.useMemo(
7472
+ const selectedNode = React28.useMemo(
7472
7473
  () => value != null ? findNodeByKey(items, value) : null,
7473
7474
  [items, value]
7474
7475
  );
@@ -7699,11 +7700,11 @@ function FileInput({
7699
7700
  required,
7700
7701
  icon
7701
7702
  }) {
7702
- const inputRef = React29.useRef(null);
7703
- const errorId = React29.useId();
7704
- const [files, setFiles] = React29.useState([]);
7705
- const [dragging, setDragging] = React29.useState(false);
7706
- const [sizeError, setSizeError] = React29.useState(null);
7703
+ const inputRef = React28.useRef(null);
7704
+ const errorId = React28.useId();
7705
+ const [files, setFiles] = React28.useState([]);
7706
+ const [dragging, setDragging] = React28.useState(false);
7707
+ const [sizeError, setSizeError] = React28.useState(null);
7707
7708
  const effectiveError = errorMessage ?? sizeError ?? void 0;
7708
7709
  const openPicker = () => {
7709
7710
  if (!disabled) inputRef.current?.click();
@@ -7894,30 +7895,30 @@ function DatePicker({
7894
7895
  size = "md",
7895
7896
  className = ""
7896
7897
  }) {
7897
- const errorId = React29.useId();
7898
+ const errorId = React28.useId();
7898
7899
  const hasError = errorMessage != null;
7899
- const [open, setOpen] = React29.useState(false);
7900
- const [viewMonth, setViewMonth] = React29.useState(() => startOfMonth2(value ?? /* @__PURE__ */ new Date()));
7901
- const [focusDate, setFocusDate] = React29.useState(() => value ?? /* @__PURE__ */ new Date());
7902
- const [view, setView] = React29.useState("days");
7903
- const gridRef = React29.useRef(null);
7904
- React29.useEffect(() => {
7900
+ const [open, setOpen] = React28.useState(false);
7901
+ const [viewMonth, setViewMonth] = React28.useState(() => startOfMonth2(value ?? /* @__PURE__ */ new Date()));
7902
+ const [focusDate, setFocusDate] = React28.useState(() => value ?? /* @__PURE__ */ new Date());
7903
+ const [view, setView] = React28.useState("days");
7904
+ const gridRef = React28.useRef(null);
7905
+ React28.useEffect(() => {
7905
7906
  if (!open) return;
7906
7907
  const target = value ?? /* @__PURE__ */ new Date();
7907
7908
  setViewMonth(startOfMonth2(target));
7908
7909
  setFocusDate(target);
7909
7910
  setView("days");
7910
7911
  }, [open, value]);
7911
- React29.useEffect(() => {
7912
+ React28.useEffect(() => {
7912
7913
  if (!open) return;
7913
7914
  const cell = gridRef.current?.querySelector(`[data-day="${defaultFormat3(focusDate)}"]`);
7914
7915
  cell?.focus();
7915
7916
  }, [open, focusDate]);
7916
- const weekdays = React29.useMemo(() => {
7917
+ const weekdays = React28.useMemo(() => {
7917
7918
  const ordered = WEEKDAY_SHORT.slice(weekStartsOn).concat(WEEKDAY_SHORT.slice(0, weekStartsOn));
7918
7919
  return ordered;
7919
7920
  }, [weekStartsOn]);
7920
- const grid = React29.useMemo(() => buildGrid2(viewMonth, weekStartsOn), [viewMonth, weekStartsOn]);
7921
+ const grid = React28.useMemo(() => buildGrid2(viewMonth, weekStartsOn), [viewMonth, weekStartsOn]);
7921
7922
  const isDisabled = (d) => {
7922
7923
  if (min && d < min) return true;
7923
7924
  if (max && d > max) return true;
@@ -8207,10 +8208,10 @@ function TextArea({
8207
8208
  style,
8208
8209
  inputStyle
8209
8210
  }) {
8210
- const errorId = React29.useId();
8211
+ const errorId = React28.useId();
8211
8212
  const hasError = errorMessage != null;
8212
- const ref = React29.useRef(null);
8213
- React29.useLayoutEffect(() => {
8213
+ const ref = React28.useRef(null);
8214
+ React28.useLayoutEffect(() => {
8214
8215
  if (!autoGrow) return;
8215
8216
  const el = ref.current;
8216
8217
  if (!el) return;
@@ -8282,14 +8283,14 @@ function Slider({
8282
8283
  name,
8283
8284
  htmlFor
8284
8285
  }) {
8285
- const errorId = React29.useId();
8286
+ const errorId = React28.useId();
8286
8287
  const hasError = errorMessage != null;
8287
8288
  const isRange = Array.isArray(value ?? defaultValue);
8288
- const [internal, setInternal] = React29.useState(
8289
+ const [internal, setInternal] = React28.useState(
8289
8290
  () => toArray(value) ?? toArray(defaultValue) ?? [min]
8290
8291
  );
8291
8292
  const current = toArray(value) ?? internal;
8292
- const [dragging, setDragging] = React29.useState(false);
8293
+ const [dragging, setDragging] = React28.useState(false);
8293
8294
  const emit = (arr) => {
8294
8295
  setInternal(arr);
8295
8296
  const next = isRange ? [arr[0], arr[1]] : arr[0];
@@ -8384,11 +8385,11 @@ function TagsInput({
8384
8385
  validate,
8385
8386
  separators = ["Enter", ","]
8386
8387
  }) {
8387
- const errorId = React29.useId();
8388
- const inputRef = React29.useRef(null);
8389
- const [internal, setInternal] = React29.useState(defaultValue ?? []);
8390
- const [draft, setDraft] = React29.useState("");
8391
- const [localError, setLocalError] = React29.useState(null);
8388
+ const errorId = React28.useId();
8389
+ const inputRef = React28.useRef(null);
8390
+ const [internal, setInternal] = React28.useState(defaultValue ?? []);
8391
+ const [draft, setDraft] = React28.useState("");
8392
+ const [localError, setLocalError] = React28.useState(null);
8392
8393
  const tags = value ?? internal;
8393
8394
  const hasError = errorMessage != null || localError != null;
8394
8395
  const errorText = errorMessage ?? localError ?? void 0;
@@ -8519,9 +8520,9 @@ function OtpInput({
8519
8520
  className,
8520
8521
  groupAfter
8521
8522
  }) {
8522
- const errorId = React29.useId();
8523
+ const errorId = React28.useId();
8523
8524
  const hasError = errorMessage != null;
8524
- const refs = React29.useRef([]);
8525
+ const refs = React28.useRef([]);
8525
8526
  const chars = Array.from({ length }, (_, i) => value[i] ?? "");
8526
8527
  const pattern = mode === "numeric" ? /[0-9]/ : /[a-zA-Z0-9]/;
8527
8528
  const emit = (next) => {
@@ -8570,7 +8571,7 @@ function OtpInput({
8570
8571
  emit(valid.join(""));
8571
8572
  focusBox(valid.length);
8572
8573
  };
8573
- 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(React29__default.default.Fragment, { children: [
8574
+ 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(React28__default.default.Fragment, { children: [
8574
8575
  /* @__PURE__ */ jsxRuntime.jsx(
8575
8576
  "input",
8576
8577
  {
@@ -8628,9 +8629,9 @@ function Rating({
8628
8629
  className,
8629
8630
  required
8630
8631
  }) {
8631
- const errorId = React29.useId();
8632
- const [internal, setInternal] = React29.useState(defaultValue);
8633
- const [hover, setHover] = React29.useState(null);
8632
+ const errorId = React28.useId();
8633
+ const [internal, setInternal] = React28.useState(defaultValue);
8634
+ const [hover, setHover] = React28.useState(null);
8634
8635
  const current = value ?? internal;
8635
8636
  const display2 = hover ?? current;
8636
8637
  const interactive = !readOnly && !disabled;
@@ -8753,9 +8754,9 @@ function TimePicker({
8753
8754
  required,
8754
8755
  style
8755
8756
  }) {
8756
- const errorId = React29.useId();
8757
+ const errorId = React28.useId();
8757
8758
  const hasError = errorMessage != null;
8758
- const [open, setOpen] = React29.useState(false);
8759
+ const [open, setOpen] = React28.useState(false);
8759
8760
  const parsed = parse(value) ?? { h: 0, m: 0, s: 0 };
8760
8761
  const update = (next) => {
8761
8762
  const merged = { ...parsed, ...next };
@@ -8879,13 +8880,13 @@ function DateRangePicker({
8879
8880
  required,
8880
8881
  style
8881
8882
  }) {
8882
- const errorId = React29.useId();
8883
+ const errorId = React28.useId();
8883
8884
  const hasError = errorMessage != null;
8884
- const [open, setOpen] = React29.useState(false);
8885
- const [leftMonth, setLeftMonth] = React29.useState(() => startOfMonth3(value.start ?? /* @__PURE__ */ new Date()));
8886
- const [pendingStart, setPendingStart] = React29.useState(null);
8887
- const [hoverDate, setHoverDate] = React29.useState(null);
8888
- const weekdays = React29.useMemo(
8885
+ const [open, setOpen] = React28.useState(false);
8886
+ const [leftMonth, setLeftMonth] = React28.useState(() => startOfMonth3(value.start ?? /* @__PURE__ */ new Date()));
8887
+ const [pendingStart, setPendingStart] = React28.useState(null);
8888
+ const [hoverDate, setHoverDate] = React28.useState(null);
8889
+ const weekdays = React28.useMemo(
8889
8890
  () => WEEKDAY.slice(weekStartsOn).concat(WEEKDAY.slice(0, weekStartsOn)),
8890
8891
  [weekStartsOn]
8891
8892
  );
@@ -9061,10 +9062,10 @@ function ColorPicker({
9061
9062
  required,
9062
9063
  placeholder = "Pick a colour\u2026"
9063
9064
  }) {
9064
- const errorId = React29.useId();
9065
+ const errorId = React28.useId();
9065
9066
  const hasError = errorMessage != null;
9066
- const [open, setOpen] = React29.useState(false);
9067
- const [draft, setDraft] = React29.useState(value);
9067
+ const [open, setOpen] = React28.useState(false);
9068
+ const [draft, setDraft] = React28.useState(value);
9068
9069
  const valid = HEX_RE.test(value);
9069
9070
  const pick = (hex) => {
9070
9071
  onChange?.(hex);