@geomak/ui 7.9.0 → 7.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ import { X, Error as Error$1, Warning, CheckCircle, Info } from './chunk-KAFJJO5
2
2
  export { icons_default as Icon, createIcon } from './chunk-KAFJJO5O.js';
3
3
  import { colors_default } from './chunk-DXOWXLKK.js';
4
4
  export { colors_default as COLORS, PALETTE as palette, semanticTokens, vars } from './chunk-DXOWXLKK.js';
5
- import React34, { useMemo, createContext, useState, useEffect, useId, useCallback, useRef, useContext, useSyncExternalStore, useLayoutEffect } from 'react';
5
+ import React36, { useMemo, createContext, useState, useEffect, useId, useCallback, useRef, useContext, useSyncExternalStore, useLayoutEffect } from 'react';
6
6
  import { createPortal } from 'react-dom';
7
7
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
8
8
  import * as AvatarPrimitive from '@radix-ui/react-avatar';
@@ -453,7 +453,7 @@ function Typography({
453
453
  }
454
454
  );
455
455
  }
456
- var IconButton = React34.forwardRef(function IconButton2({
456
+ var IconButton = React36.forwardRef(function IconButton2({
457
457
  icon,
458
458
  onClick,
459
459
  type = "primary",
@@ -562,7 +562,7 @@ var SIZE_CLASSES = {
562
562
  md: "h-9 px-4 text-sm gap-1.5 rounded-lg",
563
563
  lg: "h-11 px-5 text-sm gap-2 rounded-xl"
564
564
  };
565
- var Button = React34.forwardRef(function Button2({
565
+ var Button = React36.forwardRef(function Button2({
566
566
  content,
567
567
  variant = "primary",
568
568
  size = "md",
@@ -670,7 +670,7 @@ function MenuButton({
670
670
  "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
671
671
  "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95"
672
672
  ].join(" "),
673
- children: items.map((item) => /* @__PURE__ */ jsxs(React34.Fragment, { children: [
673
+ children: items.map((item) => /* @__PURE__ */ jsxs(React36.Fragment, { children: [
674
674
  item.separatorBefore && /* @__PURE__ */ jsx(DropdownMenu2.Separator, { className: "my-1 h-px bg-border" }),
675
675
  /* @__PURE__ */ jsxs(
676
676
  DropdownMenu2.Item,
@@ -693,6 +693,10 @@ function MenuButton({
693
693
  ) })
694
694
  ] });
695
695
  }
696
+ var DialogContainerContext = createContext(null);
697
+ function useDialogContainer() {
698
+ return useContext(DialogContainerContext);
699
+ }
696
700
  var SIZE_MAP = {
697
701
  sm: 400,
698
702
  md: 600,
@@ -717,6 +721,7 @@ function Modal({
717
721
  className = ""
718
722
  }) {
719
723
  const reduced = useReducedMotion();
724
+ const [panelEl, setPanelEl] = useState(null);
720
725
  const maxWidth = width ?? SIZE_MAP[size];
721
726
  return /* @__PURE__ */ jsx(Dialog.Root, { open, onOpenChange: (next) => {
722
727
  if (!next) onClose?.();
@@ -734,6 +739,7 @@ function Modal({
734
739
  /* @__PURE__ */ jsx(AnimatePresence, { children: open && /* @__PURE__ */ jsx(Dialog.Content, { asChild: true, children: /* @__PURE__ */ jsxs(
735
740
  motion.div,
736
741
  {
742
+ ref: setPanelEl,
737
743
  className: `fixed left-1/2 top-1/2 z-modal flex flex-col w-[calc(100%-2rem)] max-h-[90dvh] bg-surface rounded-2xl shadow-xl overflow-hidden focus:outline-none ${className}`.trim(),
738
744
  style: {
739
745
  maxWidth,
@@ -761,7 +767,7 @@ function Modal({
761
767
  }
762
768
  ) })
763
769
  ] }),
764
- /* @__PURE__ */ jsx("div", { className: `flex-1 overflow-y-auto p-5 ${hasFooter ? "" : "pb-5"}`, children }),
770
+ /* @__PURE__ */ jsx("div", { className: `flex-1 overflow-y-auto p-5 ${hasFooter ? "" : "pb-5"}`, children: /* @__PURE__ */ jsx(DialogContainerContext.Provider, { value: panelEl, children }) }),
765
771
  hasFooter && /* @__PURE__ */ jsxs("div", { className: "flex flex-shrink-0 items-center justify-end gap-3 border-t border-border px-5 py-3", children: [
766
772
  /* @__PURE__ */ jsx(
767
773
  Button_default,
@@ -812,6 +818,7 @@ function Drawer({
812
818
  className = ""
813
819
  }) {
814
820
  const reduced = useReducedMotion();
821
+ const [panelEl, setPanelEl] = useState(null);
815
822
  const isRight = placement === "right";
816
823
  const hiddenX = isRight ? "100%" : "-100%";
817
824
  const resolvedWidth = width ?? SIZE_MAP2[size];
@@ -832,6 +839,7 @@ function Drawer({
832
839
  /* @__PURE__ */ jsx(AnimatePresence, { children: open && /* @__PURE__ */ jsx(Dialog.Content, { asChild: true, children: /* @__PURE__ */ jsxs(
833
840
  motion.div,
834
841
  {
842
+ ref: setPanelEl,
835
843
  className: `fixed top-0 bottom-0 ${isRight ? "right-0" : "left-0"} z-modal flex flex-col bg-surface shadow-xl focus:outline-none ${className}`.trim(),
836
844
  style: { width: `min(calc(100vw - 1rem), ${widthCss})` },
837
845
  initial: { x: reduced ? 0 : hiddenX, opacity: reduced ? 0 : 1 },
@@ -858,7 +866,7 @@ function Drawer({
858
866
  }
859
867
  ) })
860
868
  ] }),
861
- /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto p-5", children }),
869
+ /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto p-5", children: /* @__PURE__ */ jsx(DialogContainerContext.Provider, { value: panelEl, children }) }),
862
870
  hasFooter && /* @__PURE__ */ jsxs("div", { className: `flex flex-shrink-0 items-center gap-3 border-t border-border px-5 py-3 ${isRight ? "justify-start" : "justify-end"}`, children: [
863
871
  /* @__PURE__ */ jsx(Button_default, { style: { width: 90 }, variant: cancelVariant, content: cancelText, onClick: onCancel }),
864
872
  /* @__PURE__ */ jsx(Button_default, { style: { width: 90 }, variant: okVariant, content: okText, onClick: onOk })
@@ -1817,7 +1825,7 @@ function Kbd({
1817
1825
  style
1818
1826
  }) {
1819
1827
  if (keys && keys.length > 0) {
1820
- return /* @__PURE__ */ jsx("span", { className: cx("inline-flex items-center gap-1", className), style, children: keys.map((k, i) => /* @__PURE__ */ jsxs(React34.Fragment, { children: [
1828
+ return /* @__PURE__ */ jsx("span", { className: cx("inline-flex items-center gap-1", className), style, children: keys.map((k, i) => /* @__PURE__ */ jsxs(React36.Fragment, { children: [
1821
1829
  i > 0 && /* @__PURE__ */ jsx("span", { className: "text-foreground-muted text-xs select-none", children: separator }),
1822
1830
  /* @__PURE__ */ jsx("kbd", { className: [cap, SIZE3[size]].join(" "), children: k })
1823
1831
  ] }, `${k}-${i}`)) });
@@ -1909,7 +1917,7 @@ function FlatCarousel({
1909
1917
  style
1910
1918
  }) {
1911
1919
  const scrollerRef = useRef(null);
1912
- const slides = React34.Children.toArray(children);
1920
+ const slides = React36.Children.toArray(children);
1913
1921
  const [active, setActive] = useState(0);
1914
1922
  const [atStart, setAtStart] = useState(true);
1915
1923
  const [atEnd, setAtEnd] = useState(false);
@@ -1964,7 +1972,7 @@ function RotatingCarousel({
1964
1972
  className = "",
1965
1973
  style
1966
1974
  }) {
1967
- const slides = React34.Children.toArray(children);
1975
+ const slides = React36.Children.toArray(children);
1968
1976
  const count = slides.length;
1969
1977
  const [active, setActive] = useState(0);
1970
1978
  const reduced = useReducedMotion();
@@ -5245,7 +5253,7 @@ function Wizard({
5245
5253
  ] });
5246
5254
  }
5247
5255
  var SearchIcon = /* @__PURE__ */ 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__ */ 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" }) });
5248
- var SearchInput = React34.forwardRef(function SearchInput2({ value, onChange, disabled, label, htmlFor, placeholder, name, inputStyle, style, layout = "vertical", size = "md", icon, helperText, className }, ref) {
5256
+ var SearchInput = React36.forwardRef(function SearchInput2({ value, onChange, disabled, label, htmlFor, placeholder, name, inputStyle, style, layout = "vertical", size = "md", icon, helperText, className }, ref) {
5249
5257
  return /* @__PURE__ */ jsx(Field, { className, label, htmlFor, layout, helperText, children: /* @__PURE__ */ jsxs(
5250
5258
  "div",
5251
5259
  {
@@ -5562,7 +5570,7 @@ function TableBody({
5562
5570
  return /* @__PURE__ */ jsx("tbody", { children: rows.map((row, i) => {
5563
5571
  const rowKey = getRowKey(row, i);
5564
5572
  const isExpanded = expanded.has(rowKey);
5565
- return /* @__PURE__ */ jsxs(React34.Fragment, { children: [
5573
+ return /* @__PURE__ */ jsxs(React36.Fragment, { children: [
5566
5574
  /* @__PURE__ */ jsxs(
5567
5575
  "tr",
5568
5576
  {
@@ -6007,6 +6015,8 @@ function PdfViewer({
6007
6015
  onLoad,
6008
6016
  onError,
6009
6017
  onPageChange,
6018
+ height = 600,
6019
+ width,
6010
6020
  className = "",
6011
6021
  style
6012
6022
  }) {
@@ -6241,7 +6251,7 @@ function PdfViewer({
6241
6251
  ] });
6242
6252
  }
6243
6253
  const ready = status === "ready";
6244
- return /* @__PURE__ */ jsxs("div", { className: cx("flex flex-col overflow-hidden rounded-lg border border-border bg-surface-raised", className), style: { height: 600, ...style }, children: [
6254
+ return /* @__PURE__ */ jsxs("div", { className: cx("flex flex-col overflow-hidden rounded-lg border border-border bg-surface-raised", className), style: { height, width, ...style }, children: [
6245
6255
  toolbar !== false && /* @__PURE__ */ jsxs("div", { className: "flex flex-shrink-0 flex-col border-b border-border bg-surface", children: [
6246
6256
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 px-2 py-1.5", children: [
6247
6257
  tb.pager && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
@@ -6422,6 +6432,15 @@ var FitPageIcon = () => /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill
6422
6432
  ] });
6423
6433
  var DEFAULT_COL_WIDTH = 140;
6424
6434
  var GUTTER = 52;
6435
+ var END_PAD = 12;
6436
+ function compareValues2(a, b) {
6437
+ if (a == null && b == null) return 0;
6438
+ if (a == null) return 1;
6439
+ if (b == null) return -1;
6440
+ if (typeof a === "number" && typeof b === "number") return a - b;
6441
+ if (typeof a === "boolean" && typeof b === "boolean") return a === b ? 0 : a ? 1 : -1;
6442
+ return String(a).localeCompare(String(b), void 0, { numeric: true, sensitivity: "base" });
6443
+ }
6425
6444
  function resolveWidth(w) {
6426
6445
  if (typeof w === "number" && Number.isFinite(w)) return w;
6427
6446
  if (typeof w === "string") {
@@ -6440,7 +6459,11 @@ function DataGrid({
6440
6459
  rowHeight = 34,
6441
6460
  headerHeight = 38,
6442
6461
  height = 480,
6462
+ width,
6443
6463
  editable = false,
6464
+ sortable = false,
6465
+ sort: sortProp,
6466
+ onSortChange,
6444
6467
  virtualize = true,
6445
6468
  overscan = 4,
6446
6469
  rowNumbers = true,
@@ -6454,7 +6477,10 @@ function DataGrid({
6454
6477
  const [viewport, setViewport] = useState({ w: 0, h: 0 });
6455
6478
  const [editing, setEditing] = useState(null);
6456
6479
  const [draft, setDraft] = useState("");
6480
+ const [internalSort, setInternalSort] = useState(null);
6481
+ const sort = sortProp !== void 0 ? sortProp : internalSort;
6457
6482
  const gutter = rowNumbers ? GUTTER : 0;
6483
+ const colSortable = (c) => c.sortable ?? sortable;
6458
6484
  const { widths, offsets, totalWidth } = useMemo(() => {
6459
6485
  const widths2 = columns.map((c) => resolveWidth(c.width));
6460
6486
  const offsets2 = [];
@@ -6465,6 +6491,18 @@ function DataGrid({
6465
6491
  }
6466
6492
  return { widths: widths2, offsets: offsets2, totalWidth: acc };
6467
6493
  }, [columns]);
6494
+ const order = useMemo(() => {
6495
+ const idx = rows.map((_, i) => i);
6496
+ if (!sort) return idx;
6497
+ const dir = sort.dir === "asc" ? 1 : -1;
6498
+ return idx.sort((ia, ib) => dir * compareValues2(rows[ia]?.[sort.key] ?? null, rows[ib]?.[sort.key] ?? null));
6499
+ }, [rows, sort]);
6500
+ const toggleSort = (key) => {
6501
+ const nextDir = sort?.key !== key ? "asc" : sort.dir === "asc" ? "desc" : null;
6502
+ const next = nextDir ? { key, dir: nextDir } : null;
6503
+ if (sortProp === void 0) setInternalSort(next);
6504
+ onSortChange?.(next);
6505
+ };
6468
6506
  const totalHeight = rows.length * rowHeight;
6469
6507
  useEffect(() => {
6470
6508
  const el = scrollRef.current;
@@ -6495,14 +6533,14 @@ function DataGrid({
6495
6533
  const commit = useCallback(() => {
6496
6534
  if (!editing) return;
6497
6535
  const col = columns[editing.col];
6498
- onCellEdit?.({ row: editing.row, column: col.key, value: draft });
6536
+ onCellEdit?.({ row: order[editing.disp], column: col.key, value: draft });
6499
6537
  setEditing(null);
6500
- }, [editing, columns, draft, onCellEdit]);
6501
- const startEdit = (row, col) => {
6538
+ }, [editing, columns, draft, onCellEdit, order]);
6539
+ const startEdit = (disp, col) => {
6502
6540
  const c = columns[col];
6503
6541
  if (!(c.editable ?? editable)) return;
6504
- setDraft(displayValue(rows[row]?.[c.key] ?? ""));
6505
- setEditing({ row, col });
6542
+ setDraft(displayValue(rows[order[disp]]?.[c.key] ?? ""));
6543
+ setEditing({ disp, col });
6506
6544
  };
6507
6545
  return /* @__PURE__ */ jsxs(
6508
6546
  "div",
@@ -6510,12 +6548,12 @@ function DataGrid({
6510
6548
  ref: scrollRef,
6511
6549
  onScroll: (e) => setScroll({ top: e.currentTarget.scrollTop, left: e.currentTarget.scrollLeft }),
6512
6550
  className: cx("relative overflow-auto rounded-lg border border-border bg-surface-raised text-sm", className),
6513
- style: { height, ...style },
6551
+ style: { height, width, ...style },
6514
6552
  role: "grid",
6515
6553
  "aria-rowcount": rows.length,
6516
6554
  "aria-colcount": columns.length,
6517
6555
  children: [
6518
- /* @__PURE__ */ jsxs("div", { style: { position: "relative", width: gutter + totalWidth, height: headerHeight + totalHeight }, children: [
6556
+ /* @__PURE__ */ jsxs("div", { style: { position: "relative", width: gutter + totalWidth + END_PAD, height: headerHeight + totalHeight + END_PAD }, children: [
6519
6557
  rowNumbers && /* @__PURE__ */ jsx(
6520
6558
  "div",
6521
6559
  {
@@ -6525,11 +6563,18 @@ function DataGrid({
6525
6563
  ),
6526
6564
  visibleCols.map((ci) => {
6527
6565
  const c = columns[ci];
6528
- return /* @__PURE__ */ jsx(
6566
+ const sortDir = sort?.key === c.key ? sort.dir : null;
6567
+ const canSort = colSortable(c);
6568
+ return /* @__PURE__ */ jsxs(
6529
6569
  "div",
6530
6570
  {
6531
6571
  role: "columnheader",
6532
- className: "flex items-center border-b border-r border-border bg-surface px-3 font-medium text-foreground-secondary",
6572
+ "aria-sort": sortDir ? sortDir === "asc" ? "ascending" : "descending" : void 0,
6573
+ onClick: canSort ? () => toggleSort(c.key) : void 0,
6574
+ className: cx(
6575
+ "flex items-center gap-1 border-b border-r border-border bg-surface px-3 font-medium text-foreground-secondary",
6576
+ canSort && "cursor-pointer select-none hover:text-foreground"
6577
+ ),
6533
6578
  style: {
6534
6579
  position: "absolute",
6535
6580
  top: scroll.top,
@@ -6539,38 +6584,42 @@ function DataGrid({
6539
6584
  zIndex: 2,
6540
6585
  justifyContent: c.align === "right" ? "flex-end" : c.align === "center" ? "center" : "flex-start"
6541
6586
  },
6542
- children: /* @__PURE__ */ jsx("span", { className: "truncate", children: c.label ?? c.key })
6587
+ children: [
6588
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: c.label ?? c.key }),
6589
+ canSort && /* @__PURE__ */ jsx(SortCaret, { dir: sortDir })
6590
+ ]
6543
6591
  },
6544
6592
  `h-${c.key}`
6545
6593
  );
6546
6594
  }),
6547
- rowNumbers && visibleRows.map((ri) => /* @__PURE__ */ jsx(
6595
+ rowNumbers && visibleRows.map((disp) => /* @__PURE__ */ jsx(
6548
6596
  "div",
6549
6597
  {
6550
6598
  className: "flex items-center justify-center border-b border-r border-border bg-surface text-xs tabular-nums text-foreground-muted",
6551
- style: { position: "absolute", left: scroll.left, top: headerHeight + ri * rowHeight, width: gutter, height: rowHeight, zIndex: 1 },
6552
- children: ri + 1
6599
+ style: { position: "absolute", left: scroll.left, top: headerHeight + disp * rowHeight, width: gutter, height: rowHeight, zIndex: 1 },
6600
+ children: disp + 1
6553
6601
  },
6554
- `g-${ri}`
6602
+ `g-${disp}`
6555
6603
  )),
6556
- visibleRows.map(
6557
- (ri) => visibleCols.map((ci) => {
6604
+ visibleRows.map((disp) => {
6605
+ const ri = order[disp];
6606
+ return visibleCols.map((ci) => {
6558
6607
  const c = columns[ci];
6559
- const isEditing = editing?.row === ri && editing?.col === ci;
6608
+ const isEditing = editing?.disp === disp && editing?.col === ci;
6560
6609
  const canEdit = c.editable ?? editable;
6561
6610
  return /* @__PURE__ */ jsx(
6562
6611
  "div",
6563
6612
  {
6564
6613
  role: "gridcell",
6565
- onDoubleClick: () => startEdit(ri, ci),
6614
+ onDoubleClick: () => startEdit(disp, ci),
6566
6615
  className: cx(
6567
6616
  "flex items-center border-b border-r border-border px-3",
6568
- ri % 2 ? "bg-surface-raised" : "bg-surface",
6617
+ disp % 2 ? "bg-surface-raised" : "bg-surface",
6569
6618
  canEdit && "cursor-text"
6570
6619
  ),
6571
6620
  style: {
6572
6621
  position: "absolute",
6573
- top: headerHeight + ri * rowHeight,
6622
+ top: headerHeight + disp * rowHeight,
6574
6623
  left: gutter + offsets[ci],
6575
6624
  width: widths[ci],
6576
6625
  height: rowHeight,
@@ -6591,16 +6640,22 @@ function DataGrid({
6591
6640
  }
6592
6641
  ) : /* @__PURE__ */ jsx("span", { className: "truncate text-foreground", children: displayValue(rows[ri]?.[c.key] ?? "") })
6593
6642
  },
6594
- `${ri}-${c.key}`
6643
+ `${disp}-${c.key}`
6595
6644
  );
6596
- })
6597
- )
6645
+ });
6646
+ })
6598
6647
  ] }),
6599
6648
  rows.length === 0 && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex items-center justify-center text-foreground-muted", style: { top: headerHeight }, children: emptyState })
6600
6649
  ]
6601
6650
  }
6602
6651
  );
6603
6652
  }
6653
+ function SortCaret({ dir }) {
6654
+ return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 16 16", className: "h-3 w-3 flex-shrink-0", fill: "none", stroke: "currentColor", strokeWidth: 1.75, "aria-hidden": "true", children: [
6655
+ /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 6.5 8 3.5l3 3", className: dir === "asc" ? "text-accent" : "text-foreground-muted opacity-50" }),
6656
+ /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 9.5 8 12.5l3-3", className: dir === "desc" ? "text-accent" : "text-foreground-muted opacity-50" })
6657
+ ] });
6658
+ }
6604
6659
  function toColumns(cols) {
6605
6660
  return cols.map((c) => typeof c === "string" ? { key: c, label: c } : { ...c, label: c.label ?? c.key });
6606
6661
  }
@@ -6639,6 +6694,9 @@ function Spreadsheet({
6639
6694
  export: exportFormats = ["xlsx", "csv", "pdf"],
6640
6695
  fileName,
6641
6696
  virtualize = true,
6697
+ sortable = true,
6698
+ height = 480,
6699
+ width,
6642
6700
  className = "",
6643
6701
  style
6644
6702
  }) {
@@ -6786,16 +6844,16 @@ function Spreadsheet({
6786
6844
  else void exportPdf();
6787
6845
  };
6788
6846
  if (status === "error") {
6789
- return /* @__PURE__ */ jsxs("div", { className: cx("flex flex-col items-center justify-center gap-3 rounded-lg border border-border bg-surface p-8 text-center", className), style, children: [
6847
+ return /* @__PURE__ */ jsxs("div", { className: cx("flex flex-col items-center justify-center gap-3 rounded-lg border border-border bg-surface p-8 text-center", className), style: { height, width, ...style }, children: [
6790
6848
  /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-status-error", children: "Couldn\u2019t load the spreadsheet" }),
6791
6849
  error?.message && /* @__PURE__ */ jsx("p", { className: "max-w-md text-xs text-foreground-muted", children: error.message }),
6792
6850
  /* @__PURE__ */ jsx(Button_default, { content: "Retry", size: "sm", variant: "outline", onClick: () => setReloadKey((k) => k + 1) })
6793
6851
  ] });
6794
6852
  }
6795
6853
  if (status === "loading" || !sheets) {
6796
- return /* @__PURE__ */ jsxs("div", { className: cx("rounded-lg border border-border bg-surface-raised p-4", className), style, children: [
6854
+ return /* @__PURE__ */ jsxs("div", { className: cx("overflow-hidden rounded-lg border border-border bg-surface-raised p-4", className), style: { height, width, ...style }, children: [
6797
6855
  /* @__PURE__ */ jsx(SkeletonBox, { height: 32, className: "mb-3 rounded" }),
6798
- /* @__PURE__ */ jsx(SkeletonBox, { height: 360, className: "rounded" })
6856
+ /* @__PURE__ */ jsx(SkeletonBox, { height: "calc(100% - 44px)", className: "rounded" })
6799
6857
  ] });
6800
6858
  }
6801
6859
  const formats = exportFormats || [];
@@ -6804,25 +6862,10 @@ function Spreadsheet({
6804
6862
  csv: "CSV \u2014 this sheet (.csv)",
6805
6863
  pdf: "PDF table (.pdf)"
6806
6864
  };
6807
- return /* @__PURE__ */ jsxs("div", { className: cx("flex flex-col overflow-hidden rounded-lg border border-border bg-surface-raised", className), style, children: [
6808
- /* @__PURE__ */ jsxs("div", { className: "flex flex-shrink-0 items-center gap-2 border-b border-border bg-surface px-2 py-1.5", children: [
6809
- sheets.length > 1 ? /* @__PURE__ */ jsx("div", { role: "tablist", "aria-label": "Sheets", className: "flex min-w-0 flex-1 items-center gap-0.5 overflow-x-auto", children: sheets.map((s, i) => /* @__PURE__ */ jsx(
6810
- "button",
6811
- {
6812
- role: "tab",
6813
- type: "button",
6814
- "aria-selected": i === active,
6815
- onClick: () => setActive(i),
6816
- className: cx(
6817
- "flex-shrink-0 rounded-md px-3 py-1 text-sm font-medium transition-colors",
6818
- "focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
6819
- i === active ? "bg-accent text-accent-fg shadow-sm" : "text-foreground-secondary hover:bg-surface-raised hover:text-foreground"
6820
- ),
6821
- children: s.name || `Sheet ${i + 1}`
6822
- },
6823
- `${s.name}-${i}`
6824
- )) }) : /* @__PURE__ */ jsx("span", { className: "flex-1 truncate px-1 text-sm font-medium text-foreground", children: sheet?.name || "Sheet 1" }),
6825
- /* @__PURE__ */ jsxs("span", { className: "hidden flex-shrink-0 px-1 text-xs tabular-nums text-foreground-muted sm:inline", children: [
6865
+ return /* @__PURE__ */ jsxs("div", { className: cx("flex flex-col overflow-hidden rounded-lg border border-border bg-surface-raised", className), style: { height, width, ...style }, children: [
6866
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-shrink-0 items-center gap-2 border-b border-border bg-surface px-3 py-1.5", children: [
6867
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-sm font-semibold text-foreground", children: sheet?.name || "Sheet 1" }),
6868
+ /* @__PURE__ */ jsxs("span", { className: "hidden flex-shrink-0 text-xs tabular-nums text-foreground-muted sm:inline", children: [
6826
6869
  plainRows.length.toLocaleString(),
6827
6870
  " ",
6828
6871
  plainRows.length === 1 ? "row" : "rows",
@@ -6849,17 +6892,36 @@ function Spreadsheet({
6849
6892
  )
6850
6893
  ] })
6851
6894
  ] }),
6852
- /* @__PURE__ */ jsx(
6895
+ /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsx(
6853
6896
  DataGrid,
6854
6897
  {
6855
6898
  columns,
6856
6899
  rows: plainRows,
6857
6900
  editable,
6901
+ sortable,
6858
6902
  virtualize,
6859
6903
  onCellEdit: handleCellEdit,
6904
+ height: "100%",
6860
6905
  className: "!rounded-none !border-0"
6861
- }
6862
- )
6906
+ },
6907
+ active
6908
+ ) }),
6909
+ sheets.length > 1 && /* @__PURE__ */ jsx("div", { role: "tablist", "aria-label": "Sheets", className: "flex flex-shrink-0 items-center gap-1 overflow-x-auto border-t border-border bg-surface px-2 py-1", children: sheets.map((s, i) => /* @__PURE__ */ jsx(
6910
+ "button",
6911
+ {
6912
+ role: "tab",
6913
+ type: "button",
6914
+ "aria-selected": i === active,
6915
+ onClick: () => setActive(i),
6916
+ className: cx(
6917
+ "flex-shrink-0 rounded-md px-3 py-1 text-xs font-medium transition-colors",
6918
+ "focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
6919
+ i === active ? "bg-surface-raised text-foreground shadow-sm" : "text-foreground-secondary hover:bg-surface-raised hover:text-foreground"
6920
+ ),
6921
+ children: s.name || `Sheet ${i + 1}`
6922
+ },
6923
+ `${s.name}-${i}`
6924
+ )) })
6863
6925
  ] });
6864
6926
  }
6865
6927
  var DownloadIcon2 = () => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 3v12m0 0 4-4m-4 4-4-4M4 21h16" }) });
@@ -6963,7 +7025,7 @@ function FlyoutItems({ items }) {
6963
7025
  }
6964
7026
  function CollapsedFlyout({ item, trigger }) {
6965
7027
  const [open, setOpen] = useState(false);
6966
- const closeTimer = React34.useRef(void 0);
7028
+ const closeTimer = React36.useRef(void 0);
6967
7029
  const openNow = () => {
6968
7030
  window.clearTimeout(closeTimer.current);
6969
7031
  setOpen(true);
@@ -6972,7 +7034,7 @@ function CollapsedFlyout({ item, trigger }) {
6972
7034
  window.clearTimeout(closeTimer.current);
6973
7035
  closeTimer.current = window.setTimeout(() => setOpen(false), 150);
6974
7036
  };
6975
- React34.useEffect(() => () => window.clearTimeout(closeTimer.current), []);
7037
+ React36.useEffect(() => () => window.clearTimeout(closeTimer.current), []);
6976
7038
  return /* @__PURE__ */ jsxs(DropdownMenu2.Root, { open, onOpenChange: setOpen, modal: false, children: [
6977
7039
  /* @__PURE__ */ jsx(
6978
7040
  DropdownMenu2.Trigger,
@@ -7264,8 +7326,8 @@ function MegaMenuLink({ href, icon, description, active, onClick, children, clas
7264
7326
  function MegaMenuFeatured({ children, className = "" }) {
7265
7327
  return /* @__PURE__ */ jsx("div", { className: cx("min-w-0 rounded-lg bg-surface-raised border border-border p-4 flex flex-col", className), children });
7266
7328
  }
7267
- var elementsOfType = (children, type) => React34.Children.toArray(children).filter(
7268
- (c) => React34.isValidElement(c) && c.type === type
7329
+ var elementsOfType = (children, type) => React36.Children.toArray(children).filter(
7330
+ (c) => React36.isValidElement(c) && c.type === type
7269
7331
  );
7270
7332
  var MOBILE_CHEVRON = /* @__PURE__ */ jsx(
7271
7333
  "svg",
@@ -7302,9 +7364,9 @@ function MobileLinkRow({ link, onNavigate }) {
7302
7364
  );
7303
7365
  }
7304
7366
  function MobilePanel({ panel, onNavigate }) {
7305
- const nodes = React34.Children.toArray(panel.props.children);
7367
+ const nodes = React36.Children.toArray(panel.props.children);
7306
7368
  return /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-4 px-2 pb-3 pt-1", children: nodes.map((node, i) => {
7307
- if (!React34.isValidElement(node)) return null;
7369
+ if (!React36.isValidElement(node)) return null;
7308
7370
  const el = node;
7309
7371
  if (el.type === MegaMenuSection) {
7310
7372
  const { title, children } = el.props;
@@ -7713,7 +7775,7 @@ function ThemeProvider({
7713
7775
  className = "",
7714
7776
  style
7715
7777
  }) {
7716
- const id = React34.useId().replace(/:/g, "");
7778
+ const id = React36.useId().replace(/:/g, "");
7717
7779
  const scopeClass = `geo-th-${id}`;
7718
7780
  const divRef = useRef(null);
7719
7781
  useEffect(() => {
@@ -8526,8 +8588,11 @@ function Dropdown({
8526
8588
  labelStyle = {},
8527
8589
  placeholder,
8528
8590
  size = "md",
8529
- className = ""
8591
+ className = "",
8592
+ container
8530
8593
  }) {
8594
+ const dialogContainer = useDialogContainer();
8595
+ const portalContainer = container ?? dialogContainer ?? void 0;
8531
8596
  const [open, setOpen] = useState(false);
8532
8597
  const [selectedItems, setSelectedItems] = useState([]);
8533
8598
  const [searchTerm, setSearchTerm] = useState("");
@@ -8633,7 +8698,7 @@ function Dropdown({
8633
8698
  ]
8634
8699
  }
8635
8700
  ) }),
8636
- /* @__PURE__ */ jsx(Popover.Portal, { children: /* @__PURE__ */ jsxs(
8701
+ /* @__PURE__ */ jsx(Popover.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxs(
8637
8702
  Popover.Content,
8638
8703
  {
8639
8704
  align: "start",
@@ -10021,7 +10086,7 @@ function OtpInput({
10021
10086
  emit(valid.join(""));
10022
10087
  focusBox(valid.length);
10023
10088
  };
10024
- return /* @__PURE__ */ jsx(Field, { className, label, htmlFor, errorId, errorMessage, required, layout, helperText, children: /* @__PURE__ */ 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__ */ jsxs(React34.Fragment, { children: [
10089
+ return /* @__PURE__ */ jsx(Field, { className, label, htmlFor, errorId, errorMessage, required, layout, helperText, children: /* @__PURE__ */ 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__ */ jsxs(React36.Fragment, { children: [
10025
10090
  /* @__PURE__ */ jsx(
10026
10091
  "input",
10027
10092
  {
@@ -11080,7 +11145,7 @@ function Blog({
11080
11145
  post.tag != null && !post.image && /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Badge, { tone: "accent", variant: "soft", size: "sm", children: post.tag }) }),
11081
11146
  /* @__PURE__ */ jsx("h3", { className: "text-base font-semibold leading-snug text-foreground transition-colors group-hover:text-accent", children: post.title }),
11082
11147
  post.excerpt != null && /* @__PURE__ */ jsx("p", { className: "line-clamp-3 text-sm leading-relaxed text-foreground-secondary", children: post.excerpt }),
11083
- meta.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-auto flex flex-wrap items-center gap-x-2 gap-y-1 pt-3 text-xs text-foreground-muted", children: meta.map((m, j) => /* @__PURE__ */ jsxs(React34.Fragment, { children: [
11148
+ meta.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-auto flex flex-wrap items-center gap-x-2 gap-y-1 pt-3 text-xs text-foreground-muted", children: meta.map((m, j) => /* @__PURE__ */ jsxs(React36.Fragment, { children: [
11084
11149
  j > 0 && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\xB7" }),
11085
11150
  /* @__PURE__ */ jsx("span", { children: m })
11086
11151
  ] }, j)) })