@geomak/ui 6.27.0 → 6.27.2

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
  }
@@ -689,6 +689,17 @@ var VARIANT_CLASSES = {
689
689
  "disabled:border-foreground-muted disabled:text-foreground-muted disabled:cursor-not-allowed",
690
690
  "focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2"
691
691
  ].join(" "),
692
+ // Neutral, flat, hairline-bordered button — the quiet sibling of `secondary`
693
+ // (which carries the accent border). Mirrors the input border behaviour:
694
+ // hairline at rest, strong-hairline on hover. No shadow (flat at rest).
695
+ outline: [
696
+ "bg-surface text-foreground",
697
+ "border border-border hover:border-border-strong",
698
+ "hover:bg-surface-raised",
699
+ "active:bg-surface",
700
+ "disabled:text-foreground-muted disabled:cursor-not-allowed",
701
+ "focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2"
702
+ ].join(" "),
692
703
  ghost: [
693
704
  "bg-transparent text-foreground-secondary",
694
705
  "hover:bg-surface-raised hover:text-foreground",
@@ -730,7 +741,7 @@ var SIZE_CLASSES = {
730
741
  md: "h-9 px-4 text-sm gap-1.5 rounded-lg",
731
742
  lg: "h-11 px-5 text-sm gap-2 rounded-xl"
732
743
  };
733
- var Button = React29__default.default.forwardRef(function Button2({
744
+ var Button = React28__default.default.forwardRef(function Button2({
734
745
  content,
735
746
  variant = "primary",
736
747
  size = "md",
@@ -838,7 +849,7 @@ function MenuButton({
838
849
  "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
839
850
  "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95"
840
851
  ].join(" "),
841
- children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(React29__default.default.Fragment, { children: [
852
+ children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(React28__default.default.Fragment, { children: [
842
853
  item.separatorBefore && /* @__PURE__ */ jsxRuntime.jsx(DropdownMenu__namespace.Separator, { className: "my-1 h-px bg-border" }),
843
854
  /* @__PURE__ */ jsxRuntime.jsxs(
844
855
  DropdownMenu__namespace.Item,
@@ -1081,9 +1092,9 @@ function Tooltip({
1081
1092
  ] }) });
1082
1093
  }
1083
1094
  var TooltipProvider = TooltipPrimitive__namespace.Provider;
1084
- var TabsContext = React29.createContext(null);
1095
+ var TabsContext = React28.createContext(null);
1085
1096
  function useTabsContext() {
1086
- const ctx = React29.useContext(TabsContext);
1097
+ const ctx = React28.useContext(TabsContext);
1087
1098
  if (!ctx) throw new Error("Tabs.List / Tabs.Trigger / Tabs.Panel must be rendered inside <Tabs>.");
1088
1099
  return ctx;
1089
1100
  }
@@ -1105,26 +1116,26 @@ function Tabs({
1105
1116
  children
1106
1117
  }) {
1107
1118
  const isControlled = value !== void 0;
1108
- const [internal, setInternal] = React29.useState(defaultValue);
1119
+ const [internal, setInternal] = React28.useState(defaultValue);
1109
1120
  const current = isControlled ? value : internal;
1110
1121
  const reduced = !!framerMotion.useReducedMotion();
1111
- const indicatorId = React29.useId();
1112
- const select = React29.useCallback((next) => {
1122
+ const indicatorId = React28.useId();
1123
+ const select = React28.useCallback((next) => {
1113
1124
  if (!isControlled) setInternal(next);
1114
1125
  onValueChange?.(next);
1115
1126
  }, [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) => {
1127
+ const registry = React28.useRef(/* @__PURE__ */ new Map());
1128
+ const orderRef = React28.useRef(0);
1129
+ const [, bump] = React28.useState(0);
1130
+ const registerTab = React28.useCallback((val, meta) => {
1120
1131
  const existing = registry.current.get(val);
1121
1132
  registry.current.set(val, { ...meta, order: existing?.order ?? orderRef.current++ });
1122
1133
  if (!existing) bump((v) => v + 1);
1123
1134
  }, []);
1124
- const unregisterTab = React29.useCallback((val) => {
1135
+ const unregisterTab = React28.useCallback((val) => {
1125
1136
  if (registry.current.delete(val)) bump((v) => v + 1);
1126
1137
  }, []);
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 })), []);
1138
+ 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
1139
  return /* @__PURE__ */ jsxRuntime.jsx(TabsContext.Provider, { value: { value: current, variant, size, orientation, indicatorId, reduced, select, registerTab, unregisterTab, getTabs }, children: /* @__PURE__ */ jsxRuntime.jsx(
1129
1140
  TabsPrimitive__namespace.Root,
1130
1141
  {
@@ -1144,10 +1155,10 @@ function Tabs({
1144
1155
  function TabsList({ children, "aria-label": ariaLabel, className = "" }) {
1145
1156
  const { variant, orientation, reduced, value } = useTabsContext();
1146
1157
  const horizontal = orientation === "horizontal";
1147
- const scrollRef = React29.useRef(null);
1148
- const [edges, setEdges] = React29.useState({ start: false, end: false });
1158
+ const scrollRef = React28.useRef(null);
1159
+ const [edges, setEdges] = React28.useState({ start: false, end: false });
1149
1160
  const scrollable = variant !== "segmented";
1150
- React29.useLayoutEffect(() => {
1161
+ React28.useLayoutEffect(() => {
1151
1162
  const el = scrollRef.current;
1152
1163
  if (!el || !scrollable) return;
1153
1164
  const update = () => {
@@ -1172,13 +1183,13 @@ function TabsList({ children, "aria-label": ariaLabel, className = "" }) {
1172
1183
  ro.disconnect();
1173
1184
  };
1174
1185
  }, [horizontal, scrollable, children]);
1175
- const nudge = React29.useCallback((dir) => {
1186
+ const nudge = React28.useCallback((dir) => {
1176
1187
  const el = scrollRef.current;
1177
1188
  if (!el) return;
1178
1189
  const amount = (horizontal ? el.clientWidth : el.clientHeight) * 0.7 * dir;
1179
1190
  el.scrollBy({ [horizontal ? "left" : "top"]: amount, behavior: reduced ? "auto" : "smooth" });
1180
1191
  }, [horizontal, reduced]);
1181
- React29.useLayoutEffect(() => {
1192
+ React28.useLayoutEffect(() => {
1182
1193
  const el = scrollRef.current;
1183
1194
  if (!el || !scrollable) return;
1184
1195
  const active = el.querySelector("[role=tab][data-state=active]");
@@ -1236,9 +1247,9 @@ function Chevron2({ side, orientation, onClick }) {
1236
1247
  function OverflowMenu() {
1237
1248
  const { getTabs, value, select, orientation } = useTabsContext();
1238
1249
  const horizontal = orientation === "horizontal";
1239
- const [open, setOpen] = React29.useState(false);
1240
- const wrapRef = React29.useRef(null);
1241
- const timer = React29.useRef(null);
1250
+ const [open, setOpen] = React28.useState(false);
1251
+ const wrapRef = React28.useRef(null);
1252
+ const timer = React28.useRef(null);
1242
1253
  const openNow = () => {
1243
1254
  if (timer.current) clearTimeout(timer.current);
1244
1255
  setOpen(true);
@@ -1246,7 +1257,7 @@ function OverflowMenu() {
1246
1257
  const closeSoon = () => {
1247
1258
  timer.current = setTimeout(() => setOpen(false), 160);
1248
1259
  };
1249
- React29.useLayoutEffect(() => {
1260
+ React28.useLayoutEffect(() => {
1250
1261
  if (!open) return;
1251
1262
  const onDoc = (e) => {
1252
1263
  if (wrapRef.current && !wrapRef.current.contains(e.target)) setOpen(false);
@@ -1327,7 +1338,7 @@ function TabsTrigger({ value, icon, badge, closeable, onClose, disabled, classNa
1327
1338
  const isActive = active === value;
1328
1339
  const horizontal = orientation === "horizontal";
1329
1340
  const sz = SIZE[size];
1330
- React29.useLayoutEffect(() => {
1341
+ React28.useLayoutEffect(() => {
1331
1342
  registerTab(value, { label: children, icon, disabled });
1332
1343
  return () => unregisterTab(value);
1333
1344
  }, [value, children, icon, disabled, registerTab, unregisterTab]);
@@ -1525,7 +1536,7 @@ function Tree({
1525
1536
  item.key
1526
1537
  )) });
1527
1538
  }
1528
- var AccordionCtx = React29.createContext({ variant: "separated" });
1539
+ var AccordionCtx = React28.createContext({ variant: "separated" });
1529
1540
  function Accordion2({
1530
1541
  children,
1531
1542
  type = "single",
@@ -1584,7 +1595,7 @@ var Chevron3 = /* @__PURE__ */ jsxRuntime.jsx(
1584
1595
  }
1585
1596
  );
1586
1597
  function AccordionItem({ value, title, icon, children, disabled, className = "" }) {
1587
- const { variant } = React29.useContext(AccordionCtx);
1598
+ const { variant } = React28.useContext(AccordionCtx);
1588
1599
  return /* @__PURE__ */ jsxRuntime.jsxs(
1589
1600
  AccordionPrimitive__namespace.Item,
1590
1601
  {
@@ -1643,7 +1654,7 @@ function Breadcrumbs({
1643
1654
  className = "",
1644
1655
  style
1645
1656
  }) {
1646
- const [expanded, setExpanded] = React29.useState(false);
1657
+ const [expanded, setExpanded] = React28.useState(false);
1647
1658
  const shouldCollapse = maxItems > 0 && items.length > maxItems && !expanded;
1648
1659
  const visible = [];
1649
1660
  if (shouldCollapse) {
@@ -1827,8 +1838,8 @@ function Stepper({
1827
1838
  className = ""
1828
1839
  }) {
1829
1840
  const reduced = framerMotion.useReducedMotion();
1830
- const [forcedVertical, setForcedVertical] = React29.useState(false);
1831
- React29.useEffect(() => {
1841
+ const [forcedVertical, setForcedVertical] = React28.useState(false);
1842
+ React28.useEffect(() => {
1832
1843
  if (!responsive || orientation === "vertical") return;
1833
1844
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
1834
1845
  const mq = window.matchMedia("(max-width: 767px)");
@@ -1937,7 +1948,7 @@ function Kbd({
1937
1948
  style
1938
1949
  }) {
1939
1950
  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: [
1951
+ 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
1952
  i > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground-muted text-xs select-none", children: separator }),
1942
1953
  /* @__PURE__ */ jsxRuntime.jsx("kbd", { className: [cap, SIZE3[size]].join(" "), children: k })
1943
1954
  ] }, `${k}-${i}`)) });
@@ -2028,13 +2039,13 @@ function FlatCarousel({
2028
2039
  className = "",
2029
2040
  style
2030
2041
  }) {
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);
2042
+ const scrollerRef = React28.useRef(null);
2043
+ const slides = React28__default.default.Children.toArray(children);
2044
+ const [active, setActive] = React28.useState(0);
2045
+ const [atStart, setAtStart] = React28.useState(true);
2046
+ const [atEnd, setAtEnd] = React28.useState(false);
2036
2047
  const width = typeof itemWidth === "number" ? `${itemWidth}px` : itemWidth;
2037
- const update = React29.useCallback(() => {
2048
+ const update = React28.useCallback(() => {
2038
2049
  const el = scrollerRef.current;
2039
2050
  if (!el) return;
2040
2051
  setAtStart(el.scrollLeft <= 1);
@@ -2043,7 +2054,7 @@ function FlatCarousel({
2043
2054
  const slideW = first ? first.getBoundingClientRect().width + gap : el.clientWidth;
2044
2055
  setActive(Math.round(el.scrollLeft / slideW));
2045
2056
  }, [gap]);
2046
- React29.useEffect(() => {
2057
+ React28.useEffect(() => {
2047
2058
  update();
2048
2059
  const el = scrollerRef.current;
2049
2060
  if (!el) return;
@@ -2084,9 +2095,9 @@ function RotatingCarousel({
2084
2095
  className = "",
2085
2096
  style
2086
2097
  }) {
2087
- const slides = React29__default.default.Children.toArray(children);
2098
+ const slides = React28__default.default.Children.toArray(children);
2088
2099
  const count = slides.length;
2089
- const [active, setActive] = React29.useState(0);
2100
+ const [active, setActive] = React28.useState(0);
2090
2101
  const reduced = framerMotion.useReducedMotion();
2091
2102
  const wrap = (n) => count > 0 ? (n % count + count) % count : 0;
2092
2103
  const idx = wrap(active);
@@ -2236,7 +2247,7 @@ function FAB({
2236
2247
  className = "",
2237
2248
  style
2238
2249
  }) {
2239
- const [open, setOpen] = React29.useState(false);
2250
+ const [open, setOpen] = React28.useState(false);
2240
2251
  const reduced = framerMotion.useReducedMotion();
2241
2252
  const hasDial = !!actions && actions.length > 0;
2242
2253
  const bottom = position.startsWith("bottom");
@@ -2338,8 +2349,8 @@ function PopConfirm({
2338
2349
  onOpenChange,
2339
2350
  className = ""
2340
2351
  }) {
2341
- const [uncontrolledOpen, setUncontrolledOpen] = React29.useState(false);
2342
- const [loading, setLoading] = React29.useState(false);
2352
+ const [uncontrolledOpen, setUncontrolledOpen] = React28.useState(false);
2353
+ const [loading, setLoading] = React28.useState(false);
2343
2354
  const isOpen = open ?? uncontrolledOpen;
2344
2355
  const setOpen = (next) => {
2345
2356
  onOpenChange?.(next);
@@ -2426,16 +2437,16 @@ function LogoutTimer({
2426
2437
  logoutLabel = "Sign out now"
2427
2438
  }) {
2428
2439
  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 });
2440
+ const [warning, setWarning] = React28.useState(false);
2441
+ const [remaining, setRemaining] = React28.useState(countdown);
2442
+ const idleTimer = React28.useRef(null);
2443
+ const tick = React28.useRef(null);
2444
+ const deadline = React28.useRef(0);
2445
+ const warningRef = React28.useRef(false);
2446
+ const lastReset = React28.useRef(0);
2447
+ const cbs = React28.useRef({ onLogout, onContinue, onWarning });
2437
2448
  cbs.current = { onLogout, onContinue, onWarning };
2438
- const clearTimers = React29.useCallback(() => {
2449
+ const clearTimers = React28.useCallback(() => {
2439
2450
  if (idleTimer.current) {
2440
2451
  clearTimeout(idleTimer.current);
2441
2452
  idleTimer.current = null;
@@ -2445,13 +2456,13 @@ function LogoutTimer({
2445
2456
  tick.current = null;
2446
2457
  }
2447
2458
  }, []);
2448
- const logout = React29.useCallback(() => {
2459
+ const logout = React28.useCallback(() => {
2449
2460
  clearTimers();
2450
2461
  warningRef.current = false;
2451
2462
  setWarning(false);
2452
2463
  cbs.current.onLogout();
2453
2464
  }, [clearTimers]);
2454
- const startIdle = React29.useCallback(() => {
2465
+ const startIdle = React28.useCallback(() => {
2455
2466
  if (idleTimer.current) clearTimeout(idleTimer.current);
2456
2467
  idleTimer.current = setTimeout(() => {
2457
2468
  warningRef.current = true;
@@ -2466,7 +2477,7 @@ function LogoutTimer({
2466
2477
  }, 250);
2467
2478
  }, timeout);
2468
2479
  }, [timeout, countdown, logout]);
2469
- const stay = React29.useCallback(() => {
2480
+ const stay = React28.useCallback(() => {
2470
2481
  if (tick.current) {
2471
2482
  clearInterval(tick.current);
2472
2483
  tick.current = null;
@@ -2476,7 +2487,7 @@ function LogoutTimer({
2476
2487
  cbs.current.onContinue?.();
2477
2488
  startIdle();
2478
2489
  }, [startIdle]);
2479
- React29.useEffect(() => {
2490
+ React28.useEffect(() => {
2480
2491
  if (!enabled) {
2481
2492
  clearTimers();
2482
2493
  warningRef.current = false;
@@ -2548,16 +2559,16 @@ function Calendar2({
2548
2559
  className = "",
2549
2560
  style
2550
2561
  }) {
2551
- const today = React29.useMemo(() => startOfDay(/* @__PURE__ */ new Date()), []);
2552
- const [internalMonth, setInternalMonth] = React29.useState(() => month ?? defaultMonth ?? value ?? today);
2562
+ const today = React28.useMemo(() => startOfDay(/* @__PURE__ */ new Date()), []);
2563
+ const [internalMonth, setInternalMonth] = React28.useState(() => month ?? defaultMonth ?? value ?? today);
2553
2564
  const visible = month ?? internalMonth;
2554
2565
  const setMonth = (next) => {
2555
2566
  onMonthChange?.(next);
2556
2567
  if (month === void 0) setInternalMonth(next);
2557
2568
  };
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(() => {
2569
+ const grid = React28.useMemo(() => buildGrid(visible, weekStartsOn), [visible, weekStartsOn]);
2570
+ const weekdays = React28.useMemo(() => Array.from({ length: 7 }, (_, i) => WEEKDAYS[(i + weekStartsOn) % 7]), [weekStartsOn]);
2571
+ const eventsByDay = React28.useMemo(() => {
2561
2572
  const map = /* @__PURE__ */ new Map();
2562
2573
  for (const ev of events ?? []) {
2563
2574
  const key = startOfDay(ev.date).toDateString();
@@ -2788,11 +2799,11 @@ function SegmentedControl({
2788
2799
  "aria-label": ariaLabel
2789
2800
  }) {
2790
2801
  const sz = SIZE5[size];
2791
- const groupId = React29.useId();
2792
- const errorId = React29.useId();
2802
+ const groupId = React28.useId();
2803
+ const errorId = React28.useId();
2793
2804
  const hasError = errorMessage != null;
2794
2805
  const isControlled = value !== void 0;
2795
- const [internal, setInternal] = React29.useState(defaultValue);
2806
+ const [internal, setInternal] = React28.useState(defaultValue);
2796
2807
  const current = isControlled ? value : internal;
2797
2808
  const handle = (v) => {
2798
2809
  if (!v) return;
@@ -2952,22 +2963,22 @@ function Scheduler({
2952
2963
  style
2953
2964
  }) {
2954
2965
  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 });
2966
+ const [view, setView] = React28.useState(defaultView);
2967
+ const [cursor, setCursor] = React28.useState(() => defaultDate ?? /* @__PURE__ */ new Date());
2968
+ const [loaded, setLoaded] = React28.useState([]);
2969
+ const [loading, setLoading] = React28.useState(false);
2970
+ const [error, setError] = React28.useState(null);
2971
+ const [reloadKey, setReloadKey] = React28.useState(0);
2972
+ const [dir, setDir] = React28.useState(0);
2973
+ const cbRef = React28.useRef({ loadEvents, onError });
2963
2974
  cbRef.current = { loadEvents, onError };
2964
- const range = React29.useMemo(
2975
+ const range = React28.useMemo(
2965
2976
  () => view === "month" ? monthRange(cursor) : weekRange(cursor, weekStartsOn),
2966
2977
  [view, cursor, weekStartsOn]
2967
2978
  );
2968
2979
  const fromKey = range.from.getTime();
2969
2980
  const toKey = range.to.getTime();
2970
- React29.useEffect(() => {
2981
+ React28.useEffect(() => {
2971
2982
  const { loadEvents: loader, onError: onErr } = cbRef.current;
2972
2983
  if (!loader) return;
2973
2984
  let cancelled = false;
@@ -2987,16 +2998,16 @@ function Scheduler({
2987
2998
  cancelled = true;
2988
2999
  };
2989
3000
  }, [fromKey, toKey, view, reloadKey]);
2990
- const retry = React29.useCallback(() => setReloadKey((k) => k + 1), []);
2991
- const events = React29.useMemo(
3001
+ const retry = React28.useCallback(() => setReloadKey((k) => k + 1), []);
3002
+ const events = React28.useMemo(
2992
3003
  () => (controlledEvents ?? loaded).map(normalize),
2993
3004
  [controlledEvents, loaded]
2994
3005
  );
2995
- const go = React29.useCallback((delta) => {
3006
+ const go = React28.useCallback((delta) => {
2996
3007
  setDir(delta);
2997
3008
  setCursor((c) => view === "month" ? addMonths2(c, delta) : addDays(c, delta * 7));
2998
3009
  }, [view]);
2999
- const goToday = React29.useCallback(() => {
3010
+ const goToday = React28.useCallback(() => {
3000
3011
  setDir(0);
3001
3012
  setCursor(/* @__PURE__ */ new Date());
3002
3013
  }, []);
@@ -3106,9 +3117,9 @@ function SchedulerError({ onRetry }) {
3106
3117
  ] });
3107
3118
  }
3108
3119
  function MonthYearPicker({ label, cursor, onPick }) {
3109
- const [open, setOpen] = React29.useState(false);
3110
- const [viewYear, setViewYear] = React29.useState(cursor.getFullYear());
3111
- React29.useEffect(() => {
3120
+ const [open, setOpen] = React28.useState(false);
3121
+ const [viewYear, setViewYear] = React28.useState(cursor.getFullYear());
3122
+ React28.useEffect(() => {
3112
3123
  if (open) setViewYear(cursor.getFullYear());
3113
3124
  }, [open, cursor]);
3114
3125
  return /* @__PURE__ */ jsxRuntime.jsxs(Popover__namespace.Root, { open, onOpenChange: setOpen, children: [
@@ -3171,7 +3182,7 @@ function MonthView({
3171
3182
  onSelectSlot,
3172
3183
  onSelectEvent
3173
3184
  }) {
3174
- const grid = React29.useMemo(() => buildMonthGrid(cursor, weekStartsOn), [cursor, weekStartsOn]);
3185
+ const grid = React28.useMemo(() => buildMonthGrid(cursor, weekStartsOn), [cursor, weekStartsOn]);
3175
3186
  const labels = weekdayLabels(weekStartsOn);
3176
3187
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full flex-col", children: [
3177
3188
  /* @__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 +3256,11 @@ function WeekView({
3245
3256
  onSelectSlot,
3246
3257
  onSelectEvent
3247
3258
  }) {
3248
- const days = React29.useMemo(() => getWeekDays(cursor, weekStartsOn), [cursor, weekStartsOn]);
3249
- const labels = React29.useMemo(() => weekdayLabels(weekStartsOn), [weekStartsOn]);
3259
+ const days = React28.useMemo(() => getWeekDays(cursor, weekStartsOn), [cursor, weekStartsOn]);
3260
+ const labels = React28.useMemo(() => weekdayLabels(weekStartsOn), [weekStartsOn]);
3250
3261
  const dow = (d) => labels[(d.getDay() - weekStartsOn + 7) % 7];
3251
3262
  const [startHour, endHour] = dayHours;
3252
- const hours = React29.useMemo(
3263
+ const hours = React28.useMemo(
3253
3264
  () => Array.from({ length: endHour - startHour }, (_, i) => startHour + i),
3254
3265
  [startHour, endHour]
3255
3266
  );
@@ -3440,17 +3451,17 @@ function Cart({
3440
3451
  ] })
3441
3452
  ] });
3442
3453
  }
3443
- var CartContext = React29.createContext(null);
3454
+ var CartContext = React28.createContext(null);
3444
3455
  var clampQty = (qty, max) => {
3445
3456
  const lower = Math.max(1, Math.round(qty));
3446
3457
  return max != null ? Math.min(lower, max) : lower;
3447
3458
  };
3448
3459
  function CartProvider({ children, initialItems = [], onChange }) {
3449
- const [items, setItems] = React29.useState(initialItems);
3450
- React29.useEffect(() => {
3460
+ const [items, setItems] = React28.useState(initialItems);
3461
+ React28.useEffect(() => {
3451
3462
  onChange?.(items);
3452
3463
  }, [items]);
3453
- const addToCart = React29.useCallback((item, quantity) => {
3464
+ const addToCart = React28.useCallback((item, quantity) => {
3454
3465
  const addQty = quantity ?? item.quantity ?? 1;
3455
3466
  setItems((prev) => {
3456
3467
  const existing = prev.find((it) => it.id === item.id);
@@ -3463,29 +3474,29 @@ function CartProvider({ children, initialItems = [], onChange }) {
3463
3474
  return [...prev, { ...rest, quantity: clampQty(addQty, item.max) }];
3464
3475
  });
3465
3476
  }, []);
3466
- const removeFromCart = React29.useCallback((id) => {
3477
+ const removeFromCart = React28.useCallback((id) => {
3467
3478
  setItems((prev) => prev.filter((it) => it.id !== id));
3468
3479
  }, []);
3469
- const updateQuantity = React29.useCallback((id, quantity) => {
3480
+ const updateQuantity = React28.useCallback((id, quantity) => {
3470
3481
  setItems(
3471
3482
  (prev) => prev.map((it) => it.id === id ? { ...it, quantity: clampQty(quantity, it.max) } : it)
3472
3483
  );
3473
3484
  }, []);
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(
3485
+ const clearCart = React28.useCallback(() => setItems([]), []);
3486
+ const isInCart = React28.useCallback((id) => items.some((it) => it.id === id), [items]);
3487
+ const getItemCount = React28.useCallback(() => items.reduce((sum, it) => sum + it.quantity, 0), [items]);
3488
+ const getCartTotal = React28.useCallback(
3478
3489
  () => items.reduce((sum, it) => sum + it.price * it.quantity, 0),
3479
3490
  [items]
3480
3491
  );
3481
- const value = React29.useMemo(
3492
+ const value = React28.useMemo(
3482
3493
  () => ({ items, addToCart, removeFromCart, updateQuantity, clearCart, isInCart, getItemCount, getCartTotal }),
3483
3494
  [items, addToCart, removeFromCart, updateQuantity, clearCart, isInCart, getItemCount, getCartTotal]
3484
3495
  );
3485
3496
  return /* @__PURE__ */ jsxRuntime.jsx(CartContext.Provider, { value, children });
3486
3497
  }
3487
3498
  function useCart() {
3488
- const ctx = React29.useContext(CartContext);
3499
+ const ctx = React28.useContext(CartContext);
3489
3500
  if (!ctx) {
3490
3501
  throw new Error("useCart must be used within a <CartProvider>.");
3491
3502
  }
@@ -3819,11 +3830,11 @@ function buildBindings(store, name, kind, snap) {
3819
3830
 
3820
3831
  // src/form/useForm.ts
3821
3832
  function useForm(options = {}) {
3822
- const ref = React29.useRef(null);
3833
+ const ref = React28.useRef(null);
3823
3834
  if (ref.current === null) ref.current = new FormStore(options);
3824
3835
  const store = ref.current;
3825
- React29.useSyncExternalStore(store.subscribe, store.getRootSnapshot, store.getRootSnapshot);
3826
- const make = React29.useCallback(
3836
+ React28.useSyncExternalStore(store.subscribe, store.getRootSnapshot, store.getRootSnapshot);
3837
+ const make = React28.useCallback(
3827
3838
  (kind) => (name, rules) => {
3828
3839
  if (rules !== void 0) store.setRule(name, rules);
3829
3840
  return buildBindings(store, name, kind, store.getFieldSnapshot(name));
@@ -3852,9 +3863,9 @@ function useForm(options = {}) {
3852
3863
  fieldTarget: make("target")
3853
3864
  };
3854
3865
  }
3855
- var FormContext = React29.createContext(null);
3866
+ var FormContext = React28.createContext(null);
3856
3867
  function useFormStore() {
3857
- const store = React29.useContext(FormContext);
3868
+ const store = React28.useContext(FormContext);
3858
3869
  if (!store) {
3859
3870
  throw new Error("useFormStore must be used within a <Form>. Did you forget to wrap your fields?");
3860
3871
  }
@@ -3868,8 +3879,8 @@ function Form({
3868
3879
  children,
3869
3880
  ...rest
3870
3881
  }) {
3871
- const ref = React29.useRef(null);
3872
- const bypass = React29.useRef(false);
3882
+ const ref = React28.useRef(null);
3883
+ const bypass = React28.useRef(false);
3873
3884
  const handleSubmit = async (e) => {
3874
3885
  if (bypass.current) {
3875
3886
  bypass.current = false;
@@ -3921,12 +3932,12 @@ function useFormField(name, options = {}) {
3921
3932
  const store = useFormStore();
3922
3933
  const { kind = "value", rules } = options;
3923
3934
  if (rules !== void 0 && store.getRule(name) !== rules) store.setRule(name, rules);
3924
- React29.useEffect(() => {
3935
+ React28.useEffect(() => {
3925
3936
  return () => {
3926
3937
  if (rules !== void 0) store.removeRule(name);
3927
3938
  };
3928
3939
  }, [store, name]);
3929
- const snap = React29.useSyncExternalStore(
3940
+ const snap = React28.useSyncExternalStore(
3930
3941
  store.subscribe,
3931
3942
  () => store.getFieldSnapshot(name)
3932
3943
  );
@@ -3938,7 +3949,7 @@ function FormField({ name, kind, rules, children }) {
3938
3949
  }
3939
3950
  function useFieldArray(name) {
3940
3951
  const store = useFormStore();
3941
- React29.useSyncExternalStore(store.subscribe, store.getRootSnapshot, store.getRootSnapshot);
3952
+ React28.useSyncExternalStore(store.subscribe, store.getRootSnapshot, store.getRootSnapshot);
3942
3953
  const arr = store.getValue(name) ?? [];
3943
3954
  const keys = store.getKeys(name);
3944
3955
  return {
@@ -3971,7 +3982,7 @@ function TextInput({
3971
3982
  suffix,
3972
3983
  id
3973
3984
  }) {
3974
- const errorId = React29.useId();
3985
+ const errorId = React28.useId();
3975
3986
  const hasError = errorMessage != null;
3976
3987
  const hasAdornment = prefix != null || suffix != null;
3977
3988
  const inputId = htmlFor ?? id;
@@ -4132,7 +4143,7 @@ function CreditCardForm({
4132
4143
  className = "",
4133
4144
  style
4134
4145
  }) {
4135
- const initial = React29.useRef({
4146
+ const initial = React28.useRef({
4136
4147
  number: formatCardNumber(defaultValue?.number ?? ""),
4137
4148
  name: defaultValue?.name ?? "",
4138
4149
  expiry: formatExpiry(defaultValue?.expiry ?? ""),
@@ -4141,7 +4152,7 @@ function CreditCardForm({
4141
4152
  const form = useForm({ initialValues: initial });
4142
4153
  const numberStr = String(form.values.number ?? "");
4143
4154
  const brand = detectBrand(numberStr);
4144
- React29.useEffect(() => {
4155
+ React28.useEffect(() => {
4145
4156
  onChange?.(toCard(form.values));
4146
4157
  }, [form.values.number, form.values.name, form.values.expiry, form.values.cvv]);
4147
4158
  const numberBind = form.fieldNative("number", {
@@ -4264,7 +4275,7 @@ function Checkout({
4264
4275
  ] })
4265
4276
  ] });
4266
4277
  }
4267
- var NotificationContext = React29.createContext({
4278
+ var NotificationContext = React28.createContext({
4268
4279
  open: () => void 0,
4269
4280
  close: () => void 0
4270
4281
  });
@@ -4322,26 +4333,26 @@ function NotificationItem({
4322
4333
  onClose,
4323
4334
  reduced
4324
4335
  }) {
4325
- const [paused, setPaused] = React29.useState(false);
4336
+ const [paused, setPaused] = React28.useState(false);
4326
4337
  const duration = n.duration ?? 4e3;
4327
4338
  const isAutoDismissing = isFinite(duration) && duration > 0;
4328
4339
  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(() => {
4340
+ const timerRef = React28.useRef(null);
4341
+ const startTimeRef = React28.useRef(0);
4342
+ const remainingRef = React28.useRef(duration);
4343
+ const clearTimer = React28.useCallback(() => {
4333
4344
  if (timerRef.current !== null) {
4334
4345
  clearTimeout(timerRef.current);
4335
4346
  timerRef.current = null;
4336
4347
  }
4337
4348
  }, []);
4338
- const scheduleDismiss = React29.useCallback((ms) => {
4349
+ const scheduleDismiss = React28.useCallback((ms) => {
4339
4350
  clearTimer();
4340
4351
  if (!isAutoDismissing) return;
4341
4352
  startTimeRef.current = Date.now();
4342
4353
  timerRef.current = setTimeout(() => onClose(n.id), ms);
4343
4354
  }, [clearTimer, isAutoDismissing, n.id, onClose]);
4344
- React29.useEffect(() => {
4355
+ React28.useEffect(() => {
4345
4356
  if (paused || !isAutoDismissing) return;
4346
4357
  scheduleDismiss(remainingRef.current);
4347
4358
  return clearTimer;
@@ -4424,15 +4435,15 @@ function NotificationProvider({
4424
4435
  children,
4425
4436
  position = "top-right"
4426
4437
  }) {
4427
- const [notifications, setNotifications] = React29.useState([]);
4438
+ const [notifications, setNotifications] = React28.useState([]);
4428
4439
  const reduced = framerMotion.useReducedMotion();
4429
- const open = React29.useCallback((payload) => {
4440
+ const open = React28.useCallback((payload) => {
4430
4441
  setNotifications((prev) => [
4431
4442
  ...prev,
4432
4443
  { duration: 4e3, ...payload, id: Date.now() + Math.random() }
4433
4444
  ]);
4434
4445
  }, []);
4435
- const close = React29.useCallback((id) => {
4446
+ const close = React28.useCallback((id) => {
4436
4447
  setNotifications((prev) => prev.filter((n) => n.id !== id));
4437
4448
  }, []);
4438
4449
  return /* @__PURE__ */ jsxRuntime.jsxs(NotificationContext.Provider, { value: { open, close }, children: [
@@ -4461,7 +4472,7 @@ function NotificationProvider({
4461
4472
  ] });
4462
4473
  }
4463
4474
  function useNotification() {
4464
- const { open } = React29.useContext(NotificationContext);
4475
+ const { open } = React28.useContext(NotificationContext);
4465
4476
  return {
4466
4477
  info: (props) => open({ type: "info", ...props }),
4467
4478
  success: (props) => open({ type: "success", ...props }),
@@ -4578,10 +4589,10 @@ function FadingBase({
4578
4589
  isMounted = false,
4579
4590
  children
4580
4591
  }) {
4581
- const [shouldRender, setShouldRender] = React29.useState(isMounted);
4582
- const [visible, setVisible] = React29.useState(false);
4583
- const timerRef = React29.useRef(null);
4584
- React29.useEffect(() => {
4592
+ const [shouldRender, setShouldRender] = React28.useState(isMounted);
4593
+ const [visible, setVisible] = React28.useState(false);
4594
+ const timerRef = React28.useRef(null);
4595
+ React28.useEffect(() => {
4585
4596
  if (isMounted) {
4586
4597
  setShouldRender(true);
4587
4598
  const rafId = requestAnimationFrame(() => setVisible(true));
@@ -4679,8 +4690,8 @@ function ScalableContainer({
4679
4690
  togglePosition = "top-right",
4680
4691
  className = ""
4681
4692
  }) {
4682
- const containerRef = React29.useRef(null);
4683
- const [internalScaled, setInternalScaled] = React29.useState(false);
4693
+ const containerRef = React28.useRef(null);
4694
+ const [internalScaled, setInternalScaled] = React28.useState(false);
4684
4695
  const isScaled = expanded ?? internalScaled;
4685
4696
  const reduced = framerMotion.useReducedMotion();
4686
4697
  const onToggle = () => {
@@ -4818,17 +4829,17 @@ function CatalogGrid({ items, buttonText, onOpen, className = "" }) {
4818
4829
  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
4830
  }
4820
4831
  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(() => {
4832
+ const [activeIndex, setActiveIndex] = React28.useState(0);
4833
+ const [indexPool, setIndexPool] = React28.useState([]);
4834
+ const cardRefs = React28.useRef([]);
4835
+ const getIndexes = React28.useMemo(() => {
4825
4836
  let nextIndex = activeIndex + 1;
4826
4837
  let previousIndex = activeIndex - 1;
4827
4838
  if (activeIndex === 0) previousIndex = items.length - 1;
4828
4839
  if (activeIndex === items.length - 1) nextIndex = 0;
4829
4840
  return { previousIndex, nextIndex };
4830
4841
  }, [activeIndex, items.length]);
4831
- React29.useEffect(() => {
4842
+ React28.useEffect(() => {
4832
4843
  const { nextIndex, previousIndex } = getIndexes;
4833
4844
  let indexes = [previousIndex, activeIndex, nextIndex];
4834
4845
  if (activeIndex !== 0 && activeIndex !== items.length - 1) {
@@ -5001,8 +5012,8 @@ function writeDismissed(key) {
5001
5012
  }
5002
5013
  }
5003
5014
  function useTargetBbox(ref) {
5004
- const [bbox, setBbox] = React29.useState(null);
5005
- React29.useLayoutEffect(() => {
5015
+ const [bbox, setBbox] = React28.useState(null);
5016
+ React28.useLayoutEffect(() => {
5006
5017
  const el = ref?.current;
5007
5018
  if (!el) {
5008
5019
  setBbox(null);
@@ -5032,7 +5043,7 @@ function tooltipStyleFor(bbox, placement) {
5032
5043
  return { left: bbox.left + bbox.width / 2, top: bbox.top - TOOLTIP_GAP, transform: "translate(-50%, -100%)", width: TOOLTIP_WIDTH };
5033
5044
  }
5034
5045
  function useFocusTrap(containerRef, active) {
5035
- React29.useEffect(() => {
5046
+ React28.useEffect(() => {
5036
5047
  if (!active) return;
5037
5048
  const el = containerRef.current;
5038
5049
  if (!el) return;
@@ -5071,16 +5082,16 @@ function Wizard({
5071
5082
  onComplete,
5072
5083
  onSkip
5073
5084
  }) {
5074
- const tooltipRef = React29.useRef(null);
5075
- const tooltipTitleId = React29.useId();
5076
- const tooltipBodyId = React29.useId();
5085
+ const tooltipRef = React28.useRef(null);
5086
+ const tooltipTitleId = React28.useId();
5087
+ const tooltipBodyId = React28.useId();
5077
5088
  const reduced = framerMotion.useReducedMotion();
5078
- const [open, setOpen] = React29.useState(() => steps.length > 0 && !readDismissed(storageKey));
5079
- const [activeIndex, setActiveIndex] = React29.useState(0);
5089
+ const [open, setOpen] = React28.useState(() => steps.length > 0 && !readDismissed(storageKey));
5090
+ const [activeIndex, setActiveIndex] = React28.useState(0);
5080
5091
  const step = steps[activeIndex];
5081
5092
  const bbox = useTargetBbox(step?.stepRef);
5082
5093
  useFocusTrap(tooltipRef, open);
5083
- React29.useEffect(() => {
5094
+ React28.useEffect(() => {
5084
5095
  if (!open || !dismissible) return;
5085
5096
  const onKey = (e) => {
5086
5097
  if (e.key === "Escape") {
@@ -5091,12 +5102,12 @@ function Wizard({
5091
5102
  document.addEventListener("keydown", onKey);
5092
5103
  return () => document.removeEventListener("keydown", onKey);
5093
5104
  }, [open, dismissible]);
5094
- const handleSkip = React29.useCallback(() => {
5105
+ const handleSkip = React28.useCallback(() => {
5095
5106
  writeDismissed(storageKey);
5096
5107
  setOpen(false);
5097
5108
  onSkip?.();
5098
5109
  }, [storageKey, onSkip]);
5099
- const handleComplete = React29.useCallback(() => {
5110
+ const handleComplete = React28.useCallback(() => {
5100
5111
  writeDismissed(storageKey);
5101
5112
  setOpen(false);
5102
5113
  onComplete?.();
@@ -5239,7 +5250,7 @@ function Wizard({
5239
5250
  ] });
5240
5251
  }
5241
5252
  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) {
5253
+ 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
5254
  return /* @__PURE__ */ jsxRuntime.jsx(Field, { className, label, htmlFor, layout, helperText, children: /* @__PURE__ */ jsxRuntime.jsxs(
5244
5255
  "div",
5245
5256
  {
@@ -5268,438 +5279,136 @@ var SearchInput = React29__default.default.forwardRef(function SearchInput2({ va
5268
5279
  ) });
5269
5280
  });
5270
5281
  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" }) })
5282
+ var SHIMMER = "oxy-skeleton rounded-sm bg-surface-raised";
5283
+ function SkeletonBox({ width, height = 16, radius, className = "", style }) {
5284
+ return /* @__PURE__ */ jsxRuntime.jsx(
5285
+ "span",
5286
+ {
5287
+ role: "presentation",
5288
+ "aria-hidden": "true",
5289
+ className: `block ${SHIMMER} ${className}`,
5290
+ style: {
5291
+ width: width ?? "100%",
5292
+ height,
5293
+ borderRadius: radius ?? "var(--radius-md)",
5294
+ ...style
5286
5295
  }
5287
- )
5288
- ] });
5296
+ }
5297
+ );
5289
5298
  }
5290
- function MultiTagRow({
5291
- values,
5292
- disabled,
5293
- labelFor,
5294
- onRemove
5299
+ function SkeletonText({
5300
+ lines = 3,
5301
+ lastLineWidth = 60,
5302
+ lineHeight = 14,
5303
+ gap = 8,
5304
+ className = "",
5305
+ style
5295
5306
  }) {
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
- ]
5307
+ return /* @__PURE__ */ jsxRuntime.jsx(
5308
+ "div",
5309
+ {
5310
+ role: "presentation",
5311
+ "aria-hidden": "true",
5312
+ className: `flex flex-col ${className}`,
5313
+ style: { gap, ...style },
5314
+ children: Array.from({ length: lines }).map((_, i) => {
5315
+ const isLast = i === lines - 1;
5316
+ const width = isLast && lines > 1 ? `${lastLineWidth}%` : "100%";
5317
+ return /* @__PURE__ */ jsxRuntime.jsx(
5318
+ "span",
5319
+ {
5320
+ className: `block ${SHIMMER}`,
5321
+ style: { height: lineHeight, width, borderRadius: "var(--radius-sm)" }
5322
+ },
5323
+ i
5324
+ );
5325
+ })
5326
+ }
5327
+ );
5328
+ }
5329
+ function SkeletonCircle({ size = 40, className = "", style }) {
5330
+ return /* @__PURE__ */ jsxRuntime.jsx(
5331
+ "span",
5332
+ {
5333
+ role: "presentation",
5334
+ "aria-hidden": "true",
5335
+ className: `block flex-shrink-0 ${SHIMMER} ${className}`,
5336
+ style: {
5337
+ width: size,
5338
+ height: size,
5339
+ borderRadius: "50%",
5340
+ ...style
5359
5341
  }
5360
- ),
5361
- values.slice(0, visibleCount).map((val) => /* @__PURE__ */ jsxRuntime.jsx(
5362
- Tag,
5342
+ }
5343
+ );
5344
+ }
5345
+ function SkeletonCard({ hasAvatar = true, lines = 3, className = "", style }) {
5346
+ return /* @__PURE__ */ jsxRuntime.jsxs(
5347
+ "div",
5348
+ {
5349
+ role: "presentation",
5350
+ "aria-hidden": "true",
5351
+ className: `rounded-lg border border-border bg-surface p-4 ${className}`,
5352
+ style,
5353
+ children: [
5354
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 mb-4", children: [
5355
+ hasAvatar && /* @__PURE__ */ jsxRuntime.jsx(SkeletonCircle, { size: 36 }),
5356
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 flex flex-col gap-2", children: [
5357
+ /* @__PURE__ */ jsxRuntime.jsx(SkeletonBox, { height: 12, width: "55%" }),
5358
+ /* @__PURE__ */ jsxRuntime.jsx(SkeletonBox, { height: 10, width: "35%" })
5359
+ ] })
5360
+ ] }),
5361
+ /* @__PURE__ */ jsxRuntime.jsx(SkeletonText, { lines, lastLineWidth: 55 }),
5362
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 flex gap-2", children: [
5363
+ /* @__PURE__ */ jsxRuntime.jsx(SkeletonBox, { height: 28, width: 72 }),
5364
+ /* @__PURE__ */ jsxRuntime.jsx(SkeletonBox, { height: 28, width: 56 })
5365
+ ] })
5366
+ ]
5367
+ }
5368
+ );
5369
+ }
5370
+ var DEFAULT_PICKER = [
5371
+ { key: 1, value: 5, label: 5 },
5372
+ { key: 2, value: 10, label: 10 },
5373
+ { key: 3, value: 15, label: 15 },
5374
+ { key: 4, value: 20, label: 20 }
5375
+ ];
5376
+ var DEFAULT_PAGINATION = {
5377
+ enabled: true,
5378
+ perPage: 15,
5379
+ withPicker: true,
5380
+ pickerOptions: DEFAULT_PICKER
5381
+ };
5382
+ var DEFAULT_EXPAND = {
5383
+ enabled: false
5384
+ };
5385
+ function createDatasets(rows, perPage) {
5386
+ if (!perPage) return [rows.slice()];
5387
+ const all = [];
5388
+ for (let i = 0; i < rows.length; i += perPage) {
5389
+ all.push(rows.slice(i, i + perPage));
5390
+ }
5391
+ return all;
5392
+ }
5393
+ var defaultGetRowKey = (_row, index) => index;
5394
+ var cellAlign = (align) => align === "left" ? "text-left" : align === "right" ? "text-right" : "text-center";
5395
+ function TableHeader({
5396
+ columns,
5397
+ hasExpand
5398
+ }) {
5399
+ return /* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-surface-raised border-b border-border", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
5400
+ hasExpand && /* @__PURE__ */ jsxRuntime.jsx("th", { "aria-hidden": "true", className: "w-9" }),
5401
+ columns.map((col) => /* @__PURE__ */ jsxRuntime.jsx(
5402
+ "th",
5363
5403
  {
5364
- disabled,
5365
- removeLabel: `Remove ${labelFor(val)}`,
5366
- onRemove: () => onRemove(val),
5367
- children: labelFor(val)
5404
+ scope: "col",
5405
+ className: `${cellAlign(col.align)} text-sm font-semibold text-foreground py-3 px-3`,
5406
+ style: col.width != null ? { width: col.width } : void 0,
5407
+ children: col.label
5368
5408
  },
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
- var SHIMMER = "oxy-skeleton rounded-sm bg-surface-raised";
5574
- function SkeletonBox({ width, height = 16, radius, className = "", style }) {
5575
- return /* @__PURE__ */ jsxRuntime.jsx(
5576
- "span",
5577
- {
5578
- role: "presentation",
5579
- "aria-hidden": "true",
5580
- className: `block ${SHIMMER} ${className}`,
5581
- style: {
5582
- width: width ?? "100%",
5583
- height,
5584
- borderRadius: radius ?? "var(--radius-md)",
5585
- ...style
5586
- }
5587
- }
5588
- );
5589
- }
5590
- function SkeletonText({
5591
- lines = 3,
5592
- lastLineWidth = 60,
5593
- lineHeight = 14,
5594
- gap = 8,
5595
- className = "",
5596
- style
5597
- }) {
5598
- return /* @__PURE__ */ jsxRuntime.jsx(
5599
- "div",
5600
- {
5601
- role: "presentation",
5602
- "aria-hidden": "true",
5603
- className: `flex flex-col ${className}`,
5604
- style: { gap, ...style },
5605
- children: Array.from({ length: lines }).map((_, i) => {
5606
- const isLast = i === lines - 1;
5607
- const width = isLast && lines > 1 ? `${lastLineWidth}%` : "100%";
5608
- return /* @__PURE__ */ jsxRuntime.jsx(
5609
- "span",
5610
- {
5611
- className: `block ${SHIMMER}`,
5612
- style: { height: lineHeight, width, borderRadius: "var(--radius-sm)" }
5613
- },
5614
- i
5615
- );
5616
- })
5617
- }
5618
- );
5619
- }
5620
- function SkeletonCircle({ size = 40, className = "", style }) {
5621
- return /* @__PURE__ */ jsxRuntime.jsx(
5622
- "span",
5623
- {
5624
- role: "presentation",
5625
- "aria-hidden": "true",
5626
- className: `block flex-shrink-0 ${SHIMMER} ${className}`,
5627
- style: {
5628
- width: size,
5629
- height: size,
5630
- borderRadius: "50%",
5631
- ...style
5632
- }
5633
- }
5634
- );
5635
- }
5636
- function SkeletonCard({ hasAvatar = true, lines = 3, className = "", style }) {
5637
- return /* @__PURE__ */ jsxRuntime.jsxs(
5638
- "div",
5639
- {
5640
- role: "presentation",
5641
- "aria-hidden": "true",
5642
- className: `rounded-lg border border-border bg-surface p-4 ${className}`,
5643
- style,
5644
- children: [
5645
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 mb-4", children: [
5646
- hasAvatar && /* @__PURE__ */ jsxRuntime.jsx(SkeletonCircle, { size: 36 }),
5647
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 flex flex-col gap-2", children: [
5648
- /* @__PURE__ */ jsxRuntime.jsx(SkeletonBox, { height: 12, width: "55%" }),
5649
- /* @__PURE__ */ jsxRuntime.jsx(SkeletonBox, { height: 10, width: "35%" })
5650
- ] })
5651
- ] }),
5652
- /* @__PURE__ */ jsxRuntime.jsx(SkeletonText, { lines, lastLineWidth: 55 }),
5653
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 flex gap-2", children: [
5654
- /* @__PURE__ */ jsxRuntime.jsx(SkeletonBox, { height: 28, width: 72 }),
5655
- /* @__PURE__ */ jsxRuntime.jsx(SkeletonBox, { height: 28, width: 56 })
5656
- ] })
5657
- ]
5658
- }
5659
- );
5660
- }
5661
- var DEFAULT_PICKER = [
5662
- { key: 1, value: 5, label: 5 },
5663
- { key: 2, value: 10, label: 10 },
5664
- { key: 3, value: 15, label: 15 },
5665
- { key: 4, value: 20, label: 20 }
5666
- ];
5667
- var DEFAULT_PAGINATION = {
5668
- enabled: true,
5669
- perPage: 15,
5670
- withPicker: true,
5671
- pickerOptions: DEFAULT_PICKER
5672
- };
5673
- var DEFAULT_EXPAND = {
5674
- enabled: false
5675
- };
5676
- function createDatasets(rows, perPage) {
5677
- if (!perPage) return [rows.slice()];
5678
- const all = [];
5679
- for (let i = 0; i < rows.length; i += perPage) {
5680
- all.push(rows.slice(i, i + perPage));
5681
- }
5682
- return all;
5683
- }
5684
- var defaultGetRowKey = (_row, index) => index;
5685
- var cellAlign = (align) => align === "left" ? "text-left" : align === "right" ? "text-right" : "text-center";
5686
- function TableHeader({
5687
- columns,
5688
- hasExpand
5689
- }) {
5690
- return /* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-surface-raised border-b border-border", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
5691
- hasExpand && /* @__PURE__ */ jsxRuntime.jsx("th", { "aria-hidden": "true", className: "w-9" }),
5692
- columns.map((col) => /* @__PURE__ */ jsxRuntime.jsx(
5693
- "th",
5694
- {
5695
- scope: "col",
5696
- className: `${cellAlign(col.align)} text-sm font-semibold text-foreground py-3 px-3`,
5697
- style: col.width != null ? { width: col.width } : void 0,
5698
- children: col.label
5699
- },
5700
- col.key
5701
- ))
5702
- ] }) });
5409
+ col.key
5410
+ ))
5411
+ ] }) });
5703
5412
  }
5704
5413
  var DefaultExpandIcon = /* @__PURE__ */ jsxRuntime.jsx(
5705
5414
  "svg",
@@ -5725,7 +5434,7 @@ function TableBody({
5725
5434
  expandRow,
5726
5435
  getRowKey
5727
5436
  }) {
5728
- const [expanded, setExpanded] = React29.useState(() => /* @__PURE__ */ new Set());
5437
+ const [expanded, setExpanded] = React28.useState(() => /* @__PURE__ */ new Set());
5729
5438
  const reduced = framerMotion.useReducedMotion();
5730
5439
  const toggleRow = (rowKey) => {
5731
5440
  setExpanded((prev) => {
@@ -5740,7 +5449,7 @@ function TableBody({
5740
5449
  return /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: rows.map((row, i) => {
5741
5450
  const rowKey = getRowKey(row, i);
5742
5451
  const isExpanded = expanded.has(rowKey);
5743
- return /* @__PURE__ */ jsxRuntime.jsxs(React29__default.default.Fragment, { children: [
5452
+ return /* @__PURE__ */ jsxRuntime.jsxs(React28__default.default.Fragment, { children: [
5744
5453
  /* @__PURE__ */ jsxRuntime.jsxs(
5745
5454
  "tr",
5746
5455
  {
@@ -5796,36 +5505,37 @@ function Pagination({
5796
5505
  const matchedOption = picker.find(
5797
5506
  (o) => o.label === options.perPage || o.value === options.perPage
5798
5507
  );
5799
- const [perPageKey, setPerPageKey] = React29.useState(() => matchedOption?.key ?? picker[0]?.key);
5508
+ const [perPageKey, setPerPageKey] = React28.useState(() => matchedOption?.key ?? picker[0]?.key);
5800
5509
  const displayPerPageKey = serverSide ? matchedOption?.key ?? perPageKey : perPageKey;
5801
- React29.useEffect(() => {
5510
+ React28.useEffect(() => {
5802
5511
  if (serverSide && options.perPage != null) {
5803
5512
  const next = picker.find((o) => o.label === options.perPage || o.value === options.perPage);
5804
5513
  if (next) setPerPageKey(next.key);
5805
5514
  }
5806
5515
  }, [serverSide, options.perPage, picker]);
5807
- const navBtn = (icon, disabled, onClick, title) => /* @__PURE__ */ jsxRuntime.jsx(IconButton, { type: "bordered", size: "sm", disabled, onClick, icon, title });
5516
+ const currentOpt = picker.find((o) => o.key === displayPerPageKey);
5517
+ const currentPerPageLabel = currentOpt?.label ?? currentOpt?.value ?? options.perPage ?? "";
5518
+ const navBtn = (icon, disabled, onClick, title) => /* @__PURE__ */ jsxRuntime.jsx(Button_default, { variant: "outline", size: "sm", disabled, onClick, icon, className: "w-7 !px-0", "aria-label": title, title });
5808
5519
  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
5520
  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" }) });
5810
5521
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-end gap-x-4 gap-y-3 pt-3", children: [
5811
5522
  options.withPicker && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mr-auto flex items-center gap-2", children: [
5812
5523
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "whitespace-nowrap text-xs text-foreground-muted", children: "Rows per page" }),
5813
5524
  /* @__PURE__ */ jsxRuntime.jsx(
5814
- Dropdown,
5525
+ MenuButton,
5815
5526
  {
5527
+ variant: "outline",
5816
5528
  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
- }
5529
+ side: "top",
5530
+ label: String(currentPerPageLabel),
5531
+ items: picker.map((o) => ({
5532
+ key: o.key,
5533
+ label: String(o.label ?? o.value ?? o.key),
5534
+ onSelect: () => {
5535
+ if (!serverSide) setPerPageKey(o.key);
5536
+ onPerPageChange(o.label ?? o.value ?? o.key);
5537
+ }
5538
+ }))
5829
5539
  }
5830
5540
  )
5831
5541
  ] }),
@@ -5859,14 +5569,14 @@ function Table({
5859
5569
  className = "",
5860
5570
  style
5861
5571
  }) {
5862
- const searchRef = React29.useRef(null);
5863
- const [searchTerm, setSearchTerm] = React29.useState("");
5864
- const [perPage, setPerPage] = React29.useState(
5572
+ const searchRef = React28.useRef(null);
5573
+ const [searchTerm, setSearchTerm] = React28.useState("");
5574
+ const [perPage, setPerPage] = React28.useState(
5865
5575
  typeof pagination.perPage === "number" ? pagination.perPage : 15
5866
5576
  );
5867
- const [activePage, setActivePage] = React29.useState(0);
5577
+ const [activePage, setActivePage] = React28.useState(0);
5868
5578
  const isServerSide = !!(pagination.enabled && pagination.serverSide);
5869
- const filteredRows = React29.useMemo(() => {
5579
+ const filteredRows = React28.useMemo(() => {
5870
5580
  if (isServerSide || !searchTerm) return rows;
5871
5581
  const term = searchTerm.toLowerCase();
5872
5582
  return rows.filter(
@@ -5875,29 +5585,29 @@ function Table({
5875
5585
  )
5876
5586
  );
5877
5587
  }, [rows, searchTerm, isServerSide]);
5878
- const datasets = React29.useMemo(() => {
5588
+ const datasets = React28.useMemo(() => {
5879
5589
  if (isServerSide) return [rows];
5880
5590
  return createDatasets(filteredRows, pagination.enabled ? perPage : null);
5881
5591
  }, [filteredRows, perPage, pagination.enabled, isServerSide, rows]);
5882
- const MAX_PAGE = React29.useMemo(() => {
5592
+ const MAX_PAGE = React28.useMemo(() => {
5883
5593
  if (isServerSide && typeof pagination.maxPage === "number") return Math.max(0, pagination.maxPage);
5884
5594
  if (isServerSide && typeof pagination.totalCount === "number")
5885
5595
  return Math.max(0, Math.ceil(pagination.totalCount / perPage) - 1);
5886
5596
  return datasets.length ? datasets.length - 1 : 0;
5887
5597
  }, [isServerSide, pagination.maxPage, pagination.totalCount, perPage, datasets.length]);
5888
- const currentPageRows = React29.useMemo(() => {
5598
+ const currentPageRows = React28.useMemo(() => {
5889
5599
  if (isServerSide) return rows;
5890
5600
  return datasets[activePage] ?? [];
5891
5601
  }, [isServerSide, rows, datasets, activePage]);
5892
- React29.useEffect(() => {
5602
+ React28.useEffect(() => {
5893
5603
  if (pagination.enabled && !isServerSide && typeof pagination.perPage === "number") {
5894
5604
  setPerPage(pagination.perPage);
5895
5605
  }
5896
5606
  }, [pagination.enabled, pagination.perPage, isServerSide]);
5897
- React29.useEffect(() => {
5607
+ React28.useEffect(() => {
5898
5608
  if (isServerSide && typeof pagination.perPage === "number") setPerPage(pagination.perPage);
5899
5609
  }, [isServerSide, pagination.perPage]);
5900
- React29.useEffect(() => {
5610
+ React28.useEffect(() => {
5901
5611
  if (isServerSide && typeof pagination.page === "number" && pagination.page >= 1)
5902
5612
  setActivePage(pagination.page - 1);
5903
5613
  }, [isServerSide, pagination.page]);
@@ -5981,7 +5691,7 @@ function TableSkeletonBody({
5981
5691
  )) });
5982
5692
  }
5983
5693
  function ThemeSwitch({ checked, onChange, label = "Toggle dark mode", className = "" }) {
5984
- const id = React29.useId();
5694
+ const id = React28.useId();
5985
5695
  return /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, className: `flex items-center gap-2 cursor-pointer select-none ${className}`.trim(), children: /* @__PURE__ */ jsxRuntime.jsx(
5986
5696
  SwitchPrimitive__namespace.Root,
5987
5697
  {
@@ -6165,7 +5875,7 @@ function Sidebar({
6165
5875
  }
6166
5876
  ) });
6167
5877
  }
6168
- var MegaMenuContext = React29.createContext({ align: "start" });
5878
+ var MegaMenuContext = React28.createContext({ align: "start" });
6169
5879
  function MegaMenu({
6170
5880
  children,
6171
5881
  align = "start",
@@ -6196,7 +5906,7 @@ function MegaMenu({
6196
5906
  }
6197
5907
  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
5908
  function MegaMenuItem({ label, icon, href, children, className = "" }) {
6199
- const { align } = React29.useContext(MegaMenuContext);
5909
+ const { align } = React28.useContext(MegaMenuContext);
6200
5910
  const pos = align === "center" ? "left-1/2 -translate-x-1/2" : align === "end" ? "right-0" : "left-0";
6201
5911
  if (!children) {
6202
5912
  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 +5991,8 @@ function MegaMenuLink({ href, icon, description, active, onClick, children, clas
6281
5991
  function MegaMenuFeatured({ children, className = "" }) {
6282
5992
  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
5993
  }
6284
- var elementsOfType = (children, type) => React29__default.default.Children.toArray(children).filter(
6285
- (c) => React29__default.default.isValidElement(c) && c.type === type
5994
+ var elementsOfType = (children, type) => React28__default.default.Children.toArray(children).filter(
5995
+ (c) => React28__default.default.isValidElement(c) && c.type === type
6286
5996
  );
6287
5997
  var MOBILE_CHEVRON = /* @__PURE__ */ jsxRuntime.jsx(
6288
5998
  "svg",
@@ -6319,9 +6029,9 @@ function MobileLinkRow({ link, onNavigate }) {
6319
6029
  );
6320
6030
  }
6321
6031
  function MobilePanel({ panel, onNavigate }) {
6322
- const nodes = React29__default.default.Children.toArray(panel.props.children);
6032
+ const nodes = React28__default.default.Children.toArray(panel.props.children);
6323
6033
  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;
6034
+ if (!React28__default.default.isValidElement(node)) return null;
6325
6035
  const el = node;
6326
6036
  if (el.type === MegaMenuSection) {
6327
6037
  const { title, children } = el.props;
@@ -6340,8 +6050,8 @@ function MegaMenuMobile({
6340
6050
  children,
6341
6051
  label
6342
6052
  }) {
6343
- const [open, setOpen] = React29.useState(false);
6344
- const [expanded, setExpanded] = React29.useState(null);
6053
+ const [open, setOpen] = React28.useState(false);
6054
+ const [expanded, setExpanded] = React28.useState(null);
6345
6055
  const items = elementsOfType(children, MegaMenuItem);
6346
6056
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "md:hidden w-full", children: [
6347
6057
  /* @__PURE__ */ jsxRuntime.jsxs(
@@ -6414,17 +6124,17 @@ function AppShell({
6414
6124
  children,
6415
6125
  className = ""
6416
6126
  }) {
6417
- const [expanded, setExpanded] = React29.useState(sidebarDefaultExpanded);
6418
- const [isMobile, setIsMobile] = React29.useState(false);
6419
- const [mobileOpen, setMobileOpen] = React29.useState(false);
6420
- React29.useEffect(() => {
6127
+ const [expanded, setExpanded] = React28.useState(sidebarDefaultExpanded);
6128
+ const [isMobile, setIsMobile] = React28.useState(false);
6129
+ const [mobileOpen, setMobileOpen] = React28.useState(false);
6130
+ React28.useEffect(() => {
6421
6131
  const mq = window.matchMedia("(max-width: 767px)");
6422
6132
  const update = (e) => setIsMobile(e.matches);
6423
6133
  update(mq);
6424
6134
  mq.addEventListener("change", update);
6425
6135
  return () => mq.removeEventListener("change", update);
6426
6136
  }, []);
6427
- React29.useEffect(() => {
6137
+ React28.useEffect(() => {
6428
6138
  if (!isMobile) setMobileOpen(false);
6429
6139
  }, [isMobile]);
6430
6140
  const hasSidebar = sidebarSections.length > 0;
@@ -6551,7 +6261,7 @@ function SecureLayout({
6551
6261
  className = ""
6552
6262
  }) {
6553
6263
  const reduced = framerMotion.useReducedMotion();
6554
- const cbs = React29.useRef({ canAccess, onGranted, onDeny });
6264
+ const cbs = React28.useRef({ canAccess, onGranted, onDeny });
6555
6265
  cbs.current = { canAccess, onGranted, onDeny };
6556
6266
  const rolesKey = JSON.stringify(roles);
6557
6267
  const requiredRolesKey = JSON.stringify(requiredRoles);
@@ -6566,10 +6276,10 @@ function SecureLayout({
6566
6276
  if (requiredPermissions?.length && !has(permissions, requiredPermissions, requireAllPermissions)) return false;
6567
6277
  return true;
6568
6278
  };
6569
- const [state, setState] = React29.useState(
6279
+ const [state, setState] = React28.useState(
6570
6280
  () => !passesSync() ? "denied" : canAccess ? "checking" : "granted"
6571
6281
  );
6572
- React29.useEffect(() => {
6282
+ React28.useEffect(() => {
6573
6283
  let cancelled = false;
6574
6284
  const { canAccess: check, onGranted: granted, onDeny: deny } = cbs.current;
6575
6285
  const finish = (ok) => {
@@ -6730,10 +6440,10 @@ function ThemeProvider({
6730
6440
  className = "",
6731
6441
  style
6732
6442
  }) {
6733
- const id = React29__default.default.useId().replace(/:/g, "");
6443
+ const id = React28__default.default.useId().replace(/:/g, "");
6734
6444
  const scopeClass = `geo-th-${id}`;
6735
- const divRef = React29.useRef(null);
6736
- React29.useEffect(() => {
6445
+ const divRef = React28.useRef(null);
6446
+ React28.useEffect(() => {
6737
6447
  const el = divRef.current;
6738
6448
  if (!el) return;
6739
6449
  if (colorScheme === "auto") return;
@@ -6748,8 +6458,8 @@ function ThemeProvider({
6748
6458
  }
6749
6459
  el.classList.toggle("dark", colorScheme === "dark");
6750
6460
  }, [colorScheme]);
6751
- const lightVars = React29.useMemo(() => toCssVars(theme), [theme]);
6752
- const darkVarStr = React29.useMemo(() => {
6461
+ const lightVars = React28.useMemo(() => toCssVars(theme), [theme]);
6462
+ const darkVarStr = React28.useMemo(() => {
6753
6463
  if (!darkTheme) return "";
6754
6464
  const dvars = toCssVars(darkTheme);
6755
6465
  if (!Object.keys(dvars).length) return "";
@@ -6791,7 +6501,7 @@ function NumberInput({
6791
6501
  readOnly = false,
6792
6502
  precision
6793
6503
  }) {
6794
- const errorId = React29.useId();
6504
+ const errorId = React28.useId();
6795
6505
  const hasError = errorMessage != null;
6796
6506
  const inferredPrecision = precision ?? (Number.isInteger(step) ? 0 : String(step).split(".")[1]?.length ?? 0);
6797
6507
  const round = (n) => {
@@ -6922,8 +6632,8 @@ function Password({
6922
6632
  showIcon,
6923
6633
  hideIcon
6924
6634
  }) {
6925
- const [visible, setVisible] = React29.useState(false);
6926
- const errorId = React29.useId();
6635
+ const [visible, setVisible] = React28.useState(false);
6636
+ const errorId = React28.useId();
6927
6637
  const hasError = errorMessage != null;
6928
6638
  return /* @__PURE__ */ jsxRuntime.jsx(
6929
6639
  Field,
@@ -6996,7 +6706,7 @@ function Checkbox({
6996
6706
  }) {
6997
6707
  const isChecked = checked ?? value ?? false;
6998
6708
  const labelFirst = labelPosition === "left";
6999
- const errorId = React29.useId();
6709
+ const errorId = React28.useId();
7000
6710
  const hasError = errorMessage != null;
7001
6711
  const box = /* @__PURE__ */ jsxRuntime.jsx(
7002
6712
  CheckboxPrimitive__namespace.Root,
@@ -7104,8 +6814,8 @@ function RadioGroup({
7104
6814
  className,
7105
6815
  errorMessage
7106
6816
  }) {
7107
- const errorId = React29.useId();
7108
- const groupId = React29.useId();
6817
+ const errorId = React28.useId();
6818
+ const groupId = React28.useId();
7109
6819
  const hasError = errorMessage != null;
7110
6820
  const labelFirst = labelPosition === "left";
7111
6821
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -7188,77 +6898,379 @@ function RadioGroup({
7188
6898
  }
7189
6899
  );
7190
6900
  }
7191
- function Switch({
7192
- checked,
7193
- defaultChecked = false,
7194
- onChange,
7195
- checkedIcon,
7196
- uncheckedIcon,
6901
+ function Switch({
6902
+ checked,
6903
+ defaultChecked = false,
6904
+ onChange,
6905
+ checkedIcon,
6906
+ uncheckedIcon,
6907
+ label,
6908
+ layout = "horizontal",
6909
+ helperText,
6910
+ className,
6911
+ offLabel,
6912
+ onLabel,
6913
+ name,
6914
+ required,
6915
+ disabled,
6916
+ errorMessage
6917
+ }) {
6918
+ const id = React28.useId();
6919
+ const errorId = React28.useId();
6920
+ const hasError = errorMessage != null;
6921
+ const isControlled = checked !== void 0;
6922
+ const [internal, setInternal] = React28.useState(defaultChecked);
6923
+ const isOn = isControlled ? checked : internal;
6924
+ const handle = (c) => {
6925
+ if (!isControlled) setInternal(c);
6926
+ onChange?.({ target: { checked: c, name } });
6927
+ };
6928
+ const stateLabel = (active) => [
6929
+ "text-sm select-none transition-colors",
6930
+ active ? "text-foreground font-medium" : "text-foreground-muted",
6931
+ disabled ? "opacity-50" : "cursor-pointer"
6932
+ ].filter(Boolean).join(" ");
6933
+ return /* @__PURE__ */ jsxRuntime.jsx(
6934
+ Field,
6935
+ {
6936
+ className,
6937
+ label,
6938
+ htmlFor: id,
6939
+ errorId,
6940
+ errorMessage,
6941
+ layout,
6942
+ required,
6943
+ helperText,
6944
+ labelAlign: "center",
6945
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2.5", children: [
6946
+ offLabel != null && /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, className: stateLabel(!isOn), children: offLabel }),
6947
+ /* @__PURE__ */ jsxRuntime.jsx(
6948
+ SwitchPrimitive__namespace.Root,
6949
+ {
6950
+ id,
6951
+ name,
6952
+ checked: isOn,
6953
+ onCheckedChange: handle,
6954
+ disabled,
6955
+ required,
6956
+ "aria-invalid": hasError || void 0,
6957
+ "aria-describedby": hasError ? errorId : void 0,
6958
+ 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",
6959
+ children: /* @__PURE__ */ jsxRuntime.jsx(
6960
+ SwitchPrimitive__namespace.Thumb,
6961
+ {
6962
+ 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]",
6963
+ children: checkedIcon && uncheckedIcon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex items-center justify-center w-3 h-3", children: isOn ? checkedIcon : uncheckedIcon }) : null
6964
+ }
6965
+ )
6966
+ }
6967
+ ),
6968
+ onLabel != null && /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, className: stateLabel(isOn), children: onLabel })
6969
+ ] })
6970
+ }
6971
+ );
6972
+ }
6973
+ function Tag({ children, onRemove, removeLabel, disabled }) {
6974
+ 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: [
6975
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children }),
6976
+ onRemove && /* @__PURE__ */ jsxRuntime.jsx(
6977
+ "button",
6978
+ {
6979
+ type: "button",
6980
+ disabled,
6981
+ onClick: (e) => {
6982
+ e.stopPropagation();
6983
+ onRemove();
6984
+ },
6985
+ "aria-label": removeLabel ?? "Remove",
6986
+ 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",
6987
+ 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" }) })
6988
+ }
6989
+ )
6990
+ ] });
6991
+ }
6992
+ function MultiTagRow({
6993
+ values,
6994
+ disabled,
6995
+ labelFor,
6996
+ onRemove
6997
+ }) {
6998
+ const wrapRef = React28.useRef(null);
6999
+ const measureRef = React28.useRef(null);
7000
+ const [visibleCount, setVisibleCount] = React28.useState(values.length);
7001
+ const key = values.map(String).join("|");
7002
+ React28.useLayoutEffect(() => {
7003
+ const wrap = wrapRef.current;
7004
+ const measure = measureRef.current;
7005
+ if (!wrap || !measure) return;
7006
+ const GAP = 6;
7007
+ const recompute = () => {
7008
+ const avail = wrap.clientWidth;
7009
+ const tagEls = Array.from(measure.querySelectorAll("[data-mt]"));
7010
+ const moreEl = measure.querySelector("[data-mm]");
7011
+ const widths = tagEls.map((e) => e.offsetWidth);
7012
+ const moreW = moreEl ? moreEl.offsetWidth : 0;
7013
+ if (widths.length === 0) {
7014
+ setVisibleCount(0);
7015
+ return;
7016
+ }
7017
+ let used = 0;
7018
+ let count = 0;
7019
+ for (let i = 0; i < widths.length; i++) {
7020
+ const w = widths[i] + (i > 0 ? GAP : 0);
7021
+ if (used + w <= avail) {
7022
+ used += w;
7023
+ count++;
7024
+ } else break;
7025
+ }
7026
+ if (count < widths.length) {
7027
+ while (count > 0) {
7028
+ let t = 0;
7029
+ for (let i = 0; i < count; i++) t += widths[i] + (i > 0 ? GAP : 0);
7030
+ t += GAP + moreW;
7031
+ if (t <= avail) break;
7032
+ count--;
7033
+ }
7034
+ }
7035
+ setVisibleCount(count);
7036
+ };
7037
+ recompute();
7038
+ const ro = new ResizeObserver(recompute);
7039
+ ro.observe(wrap);
7040
+ return () => ro.disconnect();
7041
+ }, [key]);
7042
+ const hidden = values.length - visibleCount;
7043
+ 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: [
7044
+ "+",
7045
+ n,
7046
+ " more"
7047
+ ] });
7048
+ 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: [
7049
+ /* @__PURE__ */ jsxRuntime.jsxs(
7050
+ "div",
7051
+ {
7052
+ ref: measureRef,
7053
+ "aria-hidden": "true",
7054
+ className: "absolute invisible pointer-events-none flex flex-nowrap items-center gap-1.5",
7055
+ style: { left: -9999, top: -9999 },
7056
+ children: [
7057
+ values.map((val) => /* @__PURE__ */ jsxRuntime.jsx("span", { "data-mt": true, children: /* @__PURE__ */ jsxRuntime.jsx(Tag, { removeLabel: "x", onRemove: () => {
7058
+ }, children: labelFor(val) }) }, `m-${val}`)),
7059
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "data-mm": true, children: moreChip(values.length) })
7060
+ ]
7061
+ }
7062
+ ),
7063
+ values.slice(0, visibleCount).map((val) => /* @__PURE__ */ jsxRuntime.jsx(
7064
+ Tag,
7065
+ {
7066
+ disabled,
7067
+ removeLabel: `Remove ${labelFor(val)}`,
7068
+ onRemove: () => onRemove(val),
7069
+ children: labelFor(val)
7070
+ },
7071
+ String(val)
7072
+ )),
7073
+ hidden > 0 && moreChip(hidden)
7074
+ ] });
7075
+ }
7076
+ function Dropdown({
7077
+ isMultiselect = false,
7078
+ hasSearch = true,
7197
7079
  label,
7080
+ name,
7081
+ value,
7082
+ onChange,
7083
+ disabled,
7198
7084
  layout = "horizontal",
7199
7085
  helperText,
7200
- className,
7201
- offLabel,
7202
- onLabel,
7203
- name,
7204
7086
  required,
7205
- disabled,
7206
- errorMessage
7087
+ errorMessage,
7088
+ style = {},
7089
+ htmlFor,
7090
+ items = [],
7091
+ labelStyle = {},
7092
+ placeholder,
7093
+ size = "md",
7094
+ className = ""
7207
7095
  }) {
7208
- const id = React29.useId();
7209
- const errorId = React29.useId();
7096
+ const [open, setOpen] = React28.useState(false);
7097
+ const [selectedItems, setSelectedItems] = React28.useState([]);
7098
+ const [searchTerm, setSearchTerm] = React28.useState("");
7099
+ const [innerItems, setInnerItems] = React28.useState([]);
7100
+ const errorId = React28.useId();
7210
7101
  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 } });
7102
+ React28.useEffect(() => {
7103
+ setInnerItems(items);
7104
+ }, [items]);
7105
+ React28.useEffect(() => {
7106
+ if (isMultiselect && Array.isArray(value)) {
7107
+ setSelectedItems(value);
7108
+ }
7109
+ }, [isMultiselect, value]);
7110
+ const selectItem = (key) => {
7111
+ if (isMultiselect) {
7112
+ const next = selectedItems.includes(key) ? selectedItems.filter((it) => it !== key) : [...selectedItems, key];
7113
+ setSelectedItems(next);
7114
+ onChange?.({ target: { value: next, id: htmlFor, name } });
7115
+ } else {
7116
+ setSelectedItems([key]);
7117
+ onChange?.({ target: { value: key, id: htmlFor, name } });
7118
+ setOpen(false);
7119
+ }
7217
7120
  };
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,
7121
+ const removeSelected = (key) => {
7122
+ if (isMultiselect) {
7123
+ const next = selectedItems.filter((it) => it !== key);
7124
+ setSelectedItems(next);
7125
+ onChange?.({ target: { value: next, id: htmlFor, name } });
7126
+ } else {
7127
+ setSelectedItems([]);
7128
+ onChange?.({ target: { value: "", id: htmlFor, name } });
7129
+ }
7130
+ };
7131
+ const labelFor = (key) => innerItems.find((it) => it.key === key)?.label ?? String(key);
7132
+ const onSearchChange = (e) => {
7133
+ const term = e.target.value;
7134
+ setSearchTerm(term);
7135
+ setInnerItems(
7136
+ term.trim() === "" ? items : items.filter(
7137
+ (it) => String(it.label).toLowerCase().includes(term.toLowerCase())
7138
+ )
7139
+ );
7140
+ };
7141
+ const isSelected = (key) => Array.isArray(value) ? value.includes(key) : value === key;
7142
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: className || void 0, children: [
7143
+ /* @__PURE__ */ jsxRuntime.jsxs(
7144
+ "div",
7145
+ {
7146
+ className: `flex ${layout === "vertical" ? "flex-col gap-1.5" : "flex-row items-start gap-3"}`,
7147
+ children: [
7148
+ /* @__PURE__ */ jsxRuntime.jsx(
7149
+ FieldLabel,
7150
+ {
7151
+ label,
7152
+ htmlFor,
7153
+ required,
7154
+ helperText,
7155
+ horizontal: layout === "horizontal",
7156
+ style: labelStyle
7157
+ }
7158
+ ),
7159
+ /* @__PURE__ */ jsxRuntime.jsxs(Popover__namespace.Root, { open: open && !disabled, onOpenChange: (o) => !disabled && setOpen(o), children: [
7160
+ /* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
7161
+ "div",
7251
7162
  {
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
7163
+ id: htmlFor,
7164
+ role: "combobox",
7165
+ "aria-expanded": open,
7166
+ "aria-haspopup": "listbox",
7167
+ "aria-invalid": hasError || void 0,
7168
+ "aria-describedby": hasError ? errorId : void 0,
7169
+ style: { width: 240, ...style },
7170
+ 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 })}`,
7171
+ tabIndex: disabled ? -1 : 0,
7172
+ onKeyDown: (e) => {
7173
+ if (disabled) return;
7174
+ if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown" || e.key === "ArrowUp") {
7175
+ e.preventDefault();
7176
+ setOpen(true);
7177
+ }
7178
+ },
7179
+ children: [
7180
+ !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(
7181
+ MultiTagRow,
7182
+ {
7183
+ values: value,
7184
+ disabled,
7185
+ labelFor,
7186
+ onRemove: removeSelected
7187
+ }
7188
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-w-0 flex items-center overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
7189
+ Tag,
7190
+ {
7191
+ disabled,
7192
+ removeLabel: `Remove ${labelFor(value)}`,
7193
+ onRemove: () => removeSelected(value),
7194
+ children: labelFor(value)
7195
+ }
7196
+ ) }),
7197
+ /* @__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" }) }) })
7198
+ ]
7254
7199
  }
7255
- )
7256
- }
7257
- ),
7258
- onLabel != null && /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, className: stateLabel(isOn), children: onLabel })
7259
- ] })
7260
- }
7261
- );
7200
+ ) }),
7201
+ /* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs(
7202
+ Popover__namespace.Content,
7203
+ {
7204
+ align: "start",
7205
+ sideOffset: 4,
7206
+ style: { width: style?.width || 240 },
7207
+ 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",
7208
+ onInteractOutside: () => setOpen(false),
7209
+ children: [
7210
+ hasSearch && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-2", children: /* @__PURE__ */ jsxRuntime.jsx(
7211
+ SearchInput_default,
7212
+ {
7213
+ style: { width: "100%" },
7214
+ inputStyle: { width: "100%" },
7215
+ value: searchTerm,
7216
+ onChange: onSearchChange,
7217
+ placeholder: "Search..."
7218
+ }
7219
+ ) }),
7220
+ /* @__PURE__ */ jsxRuntime.jsx("div", { role: "listbox", "aria-multiselectable": isMultiselect, className: "max-h-40 overflow-y-auto", children: innerItems.map((item) => (
7221
+ // aria-rowindex was previously set here but
7222
+ // it's invalid ARIA on role="option" (it
7223
+ // belongs on rows of a grid/treegrid). Dropped.
7224
+ // tabIndex={0} + Enter/Space handler makes the
7225
+ // option keyboard-activatable; the full
7226
+ // combobox roving-tabindex pattern is deferred
7227
+ // until the planned Phase-5 rewrite.
7228
+ /* @__PURE__ */ jsxRuntime.jsxs(
7229
+ "div",
7230
+ {
7231
+ role: "option",
7232
+ "aria-selected": isSelected(item.key),
7233
+ tabIndex: 0,
7234
+ 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"}`,
7235
+ onClick: () => selectItem(item.key),
7236
+ onKeyDown: (e) => {
7237
+ if (e.key === "Enter" || e.key === " ") {
7238
+ e.preventDefault();
7239
+ selectItem(item.key);
7240
+ }
7241
+ },
7242
+ children: [
7243
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-xs", children: [
7244
+ item.icon && /* @__PURE__ */ jsxRuntime.jsx("div", { children: item.icon }),
7245
+ item.label
7246
+ ] }),
7247
+ isSelected(item.key) && // currentColor — checkmark follows
7248
+ // the item's text colour, which
7249
+ // flips automatically on hover.
7250
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 20 20", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(
7251
+ "path",
7252
+ {
7253
+ d: "M4 10l4.5 4.5L16 6",
7254
+ stroke: "currentColor",
7255
+ strokeWidth: "2",
7256
+ strokeLinecap: "round",
7257
+ strokeLinejoin: "round"
7258
+ }
7259
+ ) })
7260
+ ]
7261
+ },
7262
+ item.key
7263
+ )
7264
+ )) })
7265
+ ]
7266
+ }
7267
+ ) })
7268
+ ] })
7269
+ ]
7270
+ }
7271
+ ),
7272
+ hasError && /* @__PURE__ */ jsxRuntime.jsx("div", { id: errorId, className: "text-status-error text-xs mt-1", children: errorMessage })
7273
+ ] });
7262
7274
  }
7263
7275
  function AutoComplete({
7264
7276
  disabled,
@@ -7282,19 +7294,19 @@ function AutoComplete({
7282
7294
  required,
7283
7295
  htmlFor
7284
7296
  }) {
7285
- const errorId = React29.useId();
7297
+ const errorId = React28.useId();
7286
7298
  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);
7299
+ const [term, setTerm] = React28.useState("");
7300
+ const [open, setOpen] = React28.useState(false);
7301
+ const [asyncItems, setAsyncItems] = React28.useState([]);
7302
+ const [loading, setLoading] = React28.useState(false);
7291
7303
  const isAsync = typeof onSearch === "function";
7292
- const debounceRef = React29.useRef(null);
7293
- const requestIdRef = React29.useRef(0);
7304
+ const debounceRef = React28.useRef(null);
7305
+ const requestIdRef = React28.useRef(0);
7294
7306
  const staticFiltered = isAsync || !items ? [] : term.trim() ? items.filter(
7295
7307
  ({ key, label: label2 }) => label2.toLowerCase().includes(term.toLowerCase()) || key.toLowerCase().includes(term.toLowerCase())
7296
7308
  ) : [];
7297
- React29.useEffect(() => {
7309
+ React28.useEffect(() => {
7298
7310
  if (!isAsync) return;
7299
7311
  if (debounceRef.current) clearTimeout(debounceRef.current);
7300
7312
  if (!term.trim()) {
@@ -7450,15 +7462,15 @@ function TreeSelect({
7450
7462
  defaultExpandedKeys = [],
7451
7463
  size = "md"
7452
7464
  }) {
7453
- const errorId = React29.useId();
7465
+ const errorId = React28.useId();
7454
7466
  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(() => {
7467
+ const [open, setOpen] = React28.useState(false);
7468
+ const [expanded, setExpanded] = React28.useState(() => new Set(defaultExpandedKeys));
7469
+ const [activeIndex, setActiveIndex] = React28.useState(0);
7470
+ const listRef = React28.useRef(null);
7471
+ const visible = React28.useMemo(() => flattenVisible(items, expanded), [items, expanded]);
7472
+ const didSyncOnOpenRef = React28.useRef(false);
7473
+ React28.useEffect(() => {
7462
7474
  if (!open) {
7463
7475
  didSyncOnOpenRef.current = false;
7464
7476
  return;
@@ -7468,7 +7480,7 @@ function TreeSelect({
7468
7480
  setActiveIndex(selectedIdx >= 0 ? selectedIdx : 0);
7469
7481
  didSyncOnOpenRef.current = true;
7470
7482
  }, [open, value]);
7471
- const selectedNode = React29.useMemo(
7483
+ const selectedNode = React28.useMemo(
7472
7484
  () => value != null ? findNodeByKey(items, value) : null,
7473
7485
  [items, value]
7474
7486
  );
@@ -7699,11 +7711,11 @@ function FileInput({
7699
7711
  required,
7700
7712
  icon
7701
7713
  }) {
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);
7714
+ const inputRef = React28.useRef(null);
7715
+ const errorId = React28.useId();
7716
+ const [files, setFiles] = React28.useState([]);
7717
+ const [dragging, setDragging] = React28.useState(false);
7718
+ const [sizeError, setSizeError] = React28.useState(null);
7707
7719
  const effectiveError = errorMessage ?? sizeError ?? void 0;
7708
7720
  const openPicker = () => {
7709
7721
  if (!disabled) inputRef.current?.click();
@@ -7894,30 +7906,30 @@ function DatePicker({
7894
7906
  size = "md",
7895
7907
  className = ""
7896
7908
  }) {
7897
- const errorId = React29.useId();
7909
+ const errorId = React28.useId();
7898
7910
  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(() => {
7911
+ const [open, setOpen] = React28.useState(false);
7912
+ const [viewMonth, setViewMonth] = React28.useState(() => startOfMonth2(value ?? /* @__PURE__ */ new Date()));
7913
+ const [focusDate, setFocusDate] = React28.useState(() => value ?? /* @__PURE__ */ new Date());
7914
+ const [view, setView] = React28.useState("days");
7915
+ const gridRef = React28.useRef(null);
7916
+ React28.useEffect(() => {
7905
7917
  if (!open) return;
7906
7918
  const target = value ?? /* @__PURE__ */ new Date();
7907
7919
  setViewMonth(startOfMonth2(target));
7908
7920
  setFocusDate(target);
7909
7921
  setView("days");
7910
7922
  }, [open, value]);
7911
- React29.useEffect(() => {
7923
+ React28.useEffect(() => {
7912
7924
  if (!open) return;
7913
7925
  const cell = gridRef.current?.querySelector(`[data-day="${defaultFormat3(focusDate)}"]`);
7914
7926
  cell?.focus();
7915
7927
  }, [open, focusDate]);
7916
- const weekdays = React29.useMemo(() => {
7928
+ const weekdays = React28.useMemo(() => {
7917
7929
  const ordered = WEEKDAY_SHORT.slice(weekStartsOn).concat(WEEKDAY_SHORT.slice(0, weekStartsOn));
7918
7930
  return ordered;
7919
7931
  }, [weekStartsOn]);
7920
- const grid = React29.useMemo(() => buildGrid2(viewMonth, weekStartsOn), [viewMonth, weekStartsOn]);
7932
+ const grid = React28.useMemo(() => buildGrid2(viewMonth, weekStartsOn), [viewMonth, weekStartsOn]);
7921
7933
  const isDisabled = (d) => {
7922
7934
  if (min && d < min) return true;
7923
7935
  if (max && d > max) return true;
@@ -8207,10 +8219,10 @@ function TextArea({
8207
8219
  style,
8208
8220
  inputStyle
8209
8221
  }) {
8210
- const errorId = React29.useId();
8222
+ const errorId = React28.useId();
8211
8223
  const hasError = errorMessage != null;
8212
- const ref = React29.useRef(null);
8213
- React29.useLayoutEffect(() => {
8224
+ const ref = React28.useRef(null);
8225
+ React28.useLayoutEffect(() => {
8214
8226
  if (!autoGrow) return;
8215
8227
  const el = ref.current;
8216
8228
  if (!el) return;
@@ -8282,14 +8294,14 @@ function Slider({
8282
8294
  name,
8283
8295
  htmlFor
8284
8296
  }) {
8285
- const errorId = React29.useId();
8297
+ const errorId = React28.useId();
8286
8298
  const hasError = errorMessage != null;
8287
8299
  const isRange = Array.isArray(value ?? defaultValue);
8288
- const [internal, setInternal] = React29.useState(
8300
+ const [internal, setInternal] = React28.useState(
8289
8301
  () => toArray(value) ?? toArray(defaultValue) ?? [min]
8290
8302
  );
8291
8303
  const current = toArray(value) ?? internal;
8292
- const [dragging, setDragging] = React29.useState(false);
8304
+ const [dragging, setDragging] = React28.useState(false);
8293
8305
  const emit = (arr) => {
8294
8306
  setInternal(arr);
8295
8307
  const next = isRange ? [arr[0], arr[1]] : arr[0];
@@ -8384,11 +8396,11 @@ function TagsInput({
8384
8396
  validate,
8385
8397
  separators = ["Enter", ","]
8386
8398
  }) {
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);
8399
+ const errorId = React28.useId();
8400
+ const inputRef = React28.useRef(null);
8401
+ const [internal, setInternal] = React28.useState(defaultValue ?? []);
8402
+ const [draft, setDraft] = React28.useState("");
8403
+ const [localError, setLocalError] = React28.useState(null);
8392
8404
  const tags = value ?? internal;
8393
8405
  const hasError = errorMessage != null || localError != null;
8394
8406
  const errorText = errorMessage ?? localError ?? void 0;
@@ -8519,9 +8531,9 @@ function OtpInput({
8519
8531
  className,
8520
8532
  groupAfter
8521
8533
  }) {
8522
- const errorId = React29.useId();
8534
+ const errorId = React28.useId();
8523
8535
  const hasError = errorMessage != null;
8524
- const refs = React29.useRef([]);
8536
+ const refs = React28.useRef([]);
8525
8537
  const chars = Array.from({ length }, (_, i) => value[i] ?? "");
8526
8538
  const pattern = mode === "numeric" ? /[0-9]/ : /[a-zA-Z0-9]/;
8527
8539
  const emit = (next) => {
@@ -8570,7 +8582,7 @@ function OtpInput({
8570
8582
  emit(valid.join(""));
8571
8583
  focusBox(valid.length);
8572
8584
  };
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: [
8585
+ 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
8586
  /* @__PURE__ */ jsxRuntime.jsx(
8575
8587
  "input",
8576
8588
  {
@@ -8628,9 +8640,9 @@ function Rating({
8628
8640
  className,
8629
8641
  required
8630
8642
  }) {
8631
- const errorId = React29.useId();
8632
- const [internal, setInternal] = React29.useState(defaultValue);
8633
- const [hover, setHover] = React29.useState(null);
8643
+ const errorId = React28.useId();
8644
+ const [internal, setInternal] = React28.useState(defaultValue);
8645
+ const [hover, setHover] = React28.useState(null);
8634
8646
  const current = value ?? internal;
8635
8647
  const display2 = hover ?? current;
8636
8648
  const interactive = !readOnly && !disabled;
@@ -8753,9 +8765,9 @@ function TimePicker({
8753
8765
  required,
8754
8766
  style
8755
8767
  }) {
8756
- const errorId = React29.useId();
8768
+ const errorId = React28.useId();
8757
8769
  const hasError = errorMessage != null;
8758
- const [open, setOpen] = React29.useState(false);
8770
+ const [open, setOpen] = React28.useState(false);
8759
8771
  const parsed = parse(value) ?? { h: 0, m: 0, s: 0 };
8760
8772
  const update = (next) => {
8761
8773
  const merged = { ...parsed, ...next };
@@ -8879,13 +8891,13 @@ function DateRangePicker({
8879
8891
  required,
8880
8892
  style
8881
8893
  }) {
8882
- const errorId = React29.useId();
8894
+ const errorId = React28.useId();
8883
8895
  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(
8896
+ const [open, setOpen] = React28.useState(false);
8897
+ const [leftMonth, setLeftMonth] = React28.useState(() => startOfMonth3(value.start ?? /* @__PURE__ */ new Date()));
8898
+ const [pendingStart, setPendingStart] = React28.useState(null);
8899
+ const [hoverDate, setHoverDate] = React28.useState(null);
8900
+ const weekdays = React28.useMemo(
8889
8901
  () => WEEKDAY.slice(weekStartsOn).concat(WEEKDAY.slice(0, weekStartsOn)),
8890
8902
  [weekStartsOn]
8891
8903
  );
@@ -9061,10 +9073,10 @@ function ColorPicker({
9061
9073
  required,
9062
9074
  placeholder = "Pick a colour\u2026"
9063
9075
  }) {
9064
- const errorId = React29.useId();
9076
+ const errorId = React28.useId();
9065
9077
  const hasError = errorMessage != null;
9066
- const [open, setOpen] = React29.useState(false);
9067
- const [draft, setDraft] = React29.useState(value);
9078
+ const [open, setOpen] = React28.useState(false);
9079
+ const [draft, setDraft] = React28.useState(value);
9068
9080
  const valid = HEX_RE.test(value);
9069
9081
  const pick = (hex) => {
9070
9082
  onChange?.(hex);