@geomak/ui 1.7.1 → 1.7.3

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 chunk255PCZIW_cjs = require('./chunk-255PCZIW.cjs');
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
- var React10 = require('react');
5
+ var React9 = require('react');
6
6
  var reactDom = require('react-dom');
7
7
  var Dialog = require('@radix-ui/react-dialog');
8
8
  var framerMotion = require('framer-motion');
@@ -35,7 +35,7 @@ function _interopNamespace(e) {
35
35
  return Object.freeze(n);
36
36
  }
37
37
 
38
- var React10__default = /*#__PURE__*/_interopDefault(React10);
38
+ var React9__default = /*#__PURE__*/_interopDefault(React9);
39
39
  var Dialog__namespace = /*#__PURE__*/_interopNamespace(Dialog);
40
40
  var TooltipPrimitive__namespace = /*#__PURE__*/_interopNamespace(TooltipPrimitive);
41
41
  var TabsPrimitive__namespace = /*#__PURE__*/_interopNamespace(TabsPrimitive);
@@ -206,8 +206,8 @@ Icon.Copy = Copy;
206
206
  Icon.CircleStack = CircleStack;
207
207
  var icons_default = Icon;
208
208
  function Portal({ children, target }) {
209
- const [resolved, setResolved] = React10.useState(null);
210
- React10.useEffect(() => {
209
+ const [resolved, setResolved] = React9.useState(null);
210
+ React9.useEffect(() => {
211
211
  if (target === null) {
212
212
  setResolved(null);
213
213
  return;
@@ -227,7 +227,7 @@ function IconButton({
227
227
  loading = false,
228
228
  loadingIcon
229
229
  }) {
230
- const colorScheme = React10.useMemo(() => {
230
+ const colorScheme = React9.useMemo(() => {
231
231
  if (type === "primary") {
232
232
  return "hover:bg-true-blue bg-usafa-blue dark:bg-independence dark:hover:bg-black-coral";
233
233
  }
@@ -538,11 +538,11 @@ function Tabs({
538
538
  tabsClosable = true,
539
539
  defaultActiveTab
540
540
  }) {
541
- const [value, setValue] = React10.useState(() => defaultActiveTab ?? tabs[0]?.key ?? "");
542
- React10.useEffect(() => {
541
+ const [value, setValue] = React9.useState(() => defaultActiveTab ?? tabs[0]?.key ?? "");
542
+ React9.useEffect(() => {
543
543
  if (defaultActiveTab) setValue(defaultActiveTab);
544
544
  }, [defaultActiveTab]);
545
- React10.useEffect(() => {
545
+ React9.useEffect(() => {
546
546
  if (tabs.length === 0) {
547
547
  setValue("");
548
548
  return;
@@ -789,7 +789,7 @@ function ToggleButton({ items, onChange, activeKey }) {
789
789
  }
790
790
  );
791
791
  }
792
- var NotificationContext = React10.createContext({
792
+ var NotificationContext = React9.createContext({
793
793
  open: () => void 0,
794
794
  close: () => void 0
795
795
  });
@@ -847,7 +847,7 @@ function NotificationItem({
847
847
  onClose,
848
848
  reduced
849
849
  }) {
850
- const [hovered, setHovered] = React10.useState(false);
850
+ const [hovered, setHovered] = React9.useState(false);
851
851
  const initial = getInitialMotion(pos, reduced);
852
852
  const center = pos.endsWith("center");
853
853
  const duration = n.duration ?? 4e3;
@@ -928,7 +928,7 @@ function NotificationProvider({
928
928
  children,
929
929
  position = "top-right"
930
930
  }) {
931
- const [notifications, setNotifications] = React10.useState([]);
931
+ const [notifications, setNotifications] = React9.useState([]);
932
932
  const reduced = framerMotion.useReducedMotion();
933
933
  const open = (payload) => {
934
934
  setNotifications((prev) => [
@@ -964,7 +964,7 @@ function NotificationProvider({
964
964
  ] }) });
965
965
  }
966
966
  function useNotification() {
967
- const { open } = React10.useContext(NotificationContext);
967
+ const { open } = React9.useContext(NotificationContext);
968
968
  return {
969
969
  info: (props) => open({ type: "info", ...props }),
970
970
  success: (props) => open({ type: "success", ...props }),
@@ -972,49 +972,71 @@ function useNotification() {
972
972
  danger: (props) => open({ type: "danger", ...props })
973
973
  };
974
974
  }
975
- function LoadingSpinner({ prompt }) {
976
- const letterRefs = React10.useMemo(() => [], []);
977
- const letters = prompt.split("");
978
- React10.useEffect(() => {
979
- const timeouts = [];
980
- if (letterRefs.length === letters.length) {
981
- letterRefs.forEach((ref, index) => {
982
- const t = setTimeout(() => {
983
- ref?.classList.add("slowly-appear");
984
- }, index * 100);
985
- timeouts.push(t);
986
- });
975
+ var containerVariants = {
976
+ hidden: {},
977
+ visible: { transition: { staggerChildren: 0.06 } }
978
+ };
979
+ var letterVariants = {
980
+ hidden: { opacity: 0, y: 6 },
981
+ visible: { opacity: 1, y: 0, transition: { duration: 0.25, ease: "easeOut" } }
982
+ };
983
+ function LoadingSpinner({
984
+ prompt,
985
+ spinnerColor,
986
+ textColor,
987
+ backdropOpacity = 0.92
988
+ }) {
989
+ const reduced = framerMotion.useReducedMotion();
990
+ const letters = Array.from(prompt);
991
+ return /* @__PURE__ */ jsxRuntime.jsx(Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs(
992
+ "div",
993
+ {
994
+ role: "status",
995
+ "aria-live": "polite",
996
+ "aria-label": prompt,
997
+ className: "fixed inset-0 z-[8000000] flex flex-col items-center justify-center gap-6 bg-background",
998
+ style: { opacity: backdropOpacity },
999
+ children: [
1000
+ /* @__PURE__ */ jsxRuntime.jsx(
1001
+ "div",
1002
+ {
1003
+ className: "w-20 h-20 rounded-2xl border-[6px] border-transparent border-t-current border-r-current animate-spin",
1004
+ style: { color: spinnerColor ?? "var(--color-accent)" },
1005
+ "aria-hidden": "true"
1006
+ }
1007
+ ),
1008
+ /* @__PURE__ */ jsxRuntime.jsx(
1009
+ framerMotion.motion.div,
1010
+ {
1011
+ className: "text-3xl font-bold tracking-tight select-none",
1012
+ style: { color: textColor ?? "var(--color-foreground)" },
1013
+ variants: containerVariants,
1014
+ initial: reduced ? "visible" : "hidden",
1015
+ animate: "visible",
1016
+ children: letters.map((letter, index) => /* @__PURE__ */ jsxRuntime.jsx(
1017
+ framerMotion.motion.span,
1018
+ {
1019
+ className: "inline-block whitespace-pre",
1020
+ variants: letterVariants,
1021
+ children: letter
1022
+ },
1023
+ index
1024
+ ))
1025
+ }
1026
+ )
1027
+ ]
987
1028
  }
988
- return () => timeouts.forEach(clearTimeout);
989
- }, [letterRefs, letters.length]);
990
- return (
991
- // Portaled so the full-screen overlay always covers the real viewport,
992
- // not whatever container the consumer renders LoadingSpinner inside.
993
- /* @__PURE__ */ jsxRuntime.jsx(Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fixed top-0 bottom-0 right-0 left-0 bg-oxford-blue-700-opaque z-[8000000] flex flex-col gap-5 items-center justify-start pt-80", children: [
994
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-r-prussian-blue border-l-prussian-blue border-t-white border-b-white border-[10px] w-[80px] h-[80px] rounded-xl shapeshift" }),
995
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-prussian-blue dark:text-white text-3xl font-bold", children: letters.map((letter, index) => /* @__PURE__ */ jsxRuntime.jsx(
996
- "span",
997
- {
998
- className: "select-none",
999
- ref: (ref) => {
1000
- letterRefs[index] = ref;
1001
- },
1002
- children: letter
1003
- },
1004
- index
1005
- )) })
1006
- ] }) })
1007
- );
1029
+ ) });
1008
1030
  }
1009
1031
  function FadingBase({
1010
1032
  className = "",
1011
1033
  isMounted = false,
1012
1034
  children
1013
1035
  }) {
1014
- const [shouldRender, setShouldRender] = React10.useState(isMounted);
1015
- const [visible, setVisible] = React10.useState(false);
1016
- const timerRef = React10.useRef(null);
1017
- React10.useEffect(() => {
1036
+ const [shouldRender, setShouldRender] = React9.useState(isMounted);
1037
+ const [visible, setVisible] = React9.useState(false);
1038
+ const timerRef = React9.useRef(null);
1039
+ React9.useEffect(() => {
1018
1040
  if (isMounted) {
1019
1041
  setShouldRender(true);
1020
1042
  const rafId = requestAnimationFrame(() => setVisible(true));
@@ -1055,9 +1077,9 @@ function ScalableContainer({
1055
1077
  children,
1056
1078
  assignClassOnClick
1057
1079
  }) {
1058
- const containerRef = React10.useRef(null);
1059
- const [isScaled, setScaled] = React10.useState(false);
1060
- const [wrapperClass, setWrapperClass] = React10.useState("");
1080
+ const containerRef = React9.useRef(null);
1081
+ const [isScaled, setScaled] = React9.useState(false);
1082
+ const [wrapperClass, setWrapperClass] = React9.useState("");
1061
1083
  const onClick = () => {
1062
1084
  const next = !isScaled;
1063
1085
  setScaled(next);
@@ -1167,17 +1189,17 @@ function CatalogGrid({ items, buttonText, onOpen }) {
1167
1189
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(GridCard, { item, buttonText, onOpen }, item.key)) });
1168
1190
  }
1169
1191
  function CatalogCarousel({ items, buttonText, onOpen }) {
1170
- const [activeIndex, setActiveIndex] = React10.useState(0);
1171
- const [indexPool, setIndexPool] = React10.useState([]);
1172
- const cardRefs = React10.useRef([]);
1173
- const getIndexes = React10.useMemo(() => {
1192
+ const [activeIndex, setActiveIndex] = React9.useState(0);
1193
+ const [indexPool, setIndexPool] = React9.useState([]);
1194
+ const cardRefs = React9.useRef([]);
1195
+ const getIndexes = React9.useMemo(() => {
1174
1196
  let nextIndex = activeIndex + 1;
1175
1197
  let previousIndex = activeIndex - 1;
1176
1198
  if (activeIndex === 0) previousIndex = items.length - 1;
1177
1199
  if (activeIndex === items.length - 1) nextIndex = 0;
1178
1200
  return { previousIndex, nextIndex };
1179
1201
  }, [activeIndex, items.length]);
1180
- React10.useEffect(() => {
1202
+ React9.useEffect(() => {
1181
1203
  const { nextIndex, previousIndex } = getIndexes;
1182
1204
  let indexes = [previousIndex, activeIndex, nextIndex];
1183
1205
  if (activeIndex !== 0 && activeIndex !== items.length - 1) {
@@ -1296,14 +1318,14 @@ function MenuBar({ items }) {
1296
1318
  );
1297
1319
  }
1298
1320
  function ContextMenu({ items, position, visible, onClose }) {
1299
- const contextRef = React10.useRef(null);
1300
- const childMenuRef = React10.useRef(null);
1301
- const [hasArrowUp, setHasArrowUp] = React10.useState(true);
1302
- const [childArrowUp, setChildArrowUp] = React10.useState(false);
1303
- const [hoveredItem, setHoveredItem] = React10.useState(-1);
1304
- const [hoveredChild, setHoveredChild] = React10.useState(-1);
1305
- const [activeChildren, setActiveChildren] = React10.useState([]);
1306
- React10.useEffect(() => {
1321
+ const contextRef = React9.useRef(null);
1322
+ const childMenuRef = React9.useRef(null);
1323
+ const [hasArrowUp, setHasArrowUp] = React9.useState(true);
1324
+ const [childArrowUp, setChildArrowUp] = React9.useState(false);
1325
+ const [hoveredItem, setHoveredItem] = React9.useState(-1);
1326
+ const [hoveredChild, setHoveredChild] = React9.useState(-1);
1327
+ const [activeChildren, setActiveChildren] = React9.useState([]);
1328
+ React9.useEffect(() => {
1307
1329
  const clickAway = ({ target }) => {
1308
1330
  if (contextRef.current && !contextRef.current.contains(target)) {
1309
1331
  if (childMenuRef.current) {
@@ -1318,7 +1340,7 @@ function ContextMenu({ items, position, visible, onClose }) {
1318
1340
  window.addEventListener("click", clickAway);
1319
1341
  return () => window.removeEventListener("click", clickAway);
1320
1342
  }, [onClose]);
1321
- React10.useEffect(() => {
1343
+ React9.useEffect(() => {
1322
1344
  const current = contextRef.current;
1323
1345
  const child = childMenuRef.current;
1324
1346
  if (!current || !child) return;
@@ -1414,18 +1436,18 @@ function ContextMenu({ items, position, visible, onClose }) {
1414
1436
  );
1415
1437
  }
1416
1438
  function Wizard({ children, steps, storageKey = "po_wizard" }) {
1417
- const wizardRef = React10.useRef(null);
1418
- const [activeStep, setActiveStep] = React10.useState(0);
1419
- const [targetBbox, setTargetBbox] = React10.useState(null);
1420
- const HIGHLIGHTED = React10.useMemo(
1439
+ const wizardRef = React9.useRef(null);
1440
+ const [activeStep, setActiveStep] = React9.useState(0);
1441
+ const [targetBbox, setTargetBbox] = React9.useState(null);
1442
+ const HIGHLIGHTED = React9.useMemo(
1421
1443
  () => ["border", "border-4", "border-prussian-blue", "pointer-events-none"],
1422
1444
  []
1423
1445
  );
1424
- const closeWizard = React10.useCallback(() => {
1446
+ const closeWizard = React9.useCallback(() => {
1425
1447
  steps[activeStep]?.stepRef.current?.classList.remove(...HIGHLIGHTED);
1426
1448
  if (wizardRef.current) wizardRef.current.style.display = "none";
1427
1449
  }, [HIGHLIGHTED, steps, activeStep]);
1428
- React10.useEffect(() => {
1450
+ React9.useEffect(() => {
1429
1451
  const visited = JSON.parse(localStorage.getItem(storageKey) ?? "false");
1430
1452
  if (visited) {
1431
1453
  closeWizard();
@@ -1479,7 +1501,7 @@ function Wizard({ children, steps, storageKey = "po_wizard" }) {
1479
1501
  children
1480
1502
  ] });
1481
1503
  }
1482
- var SearchInput = React10__default.default.forwardRef(function SearchInput2({
1504
+ var SearchInput = React9__default.default.forwardRef(function SearchInput2({
1483
1505
  value,
1484
1506
  onChange,
1485
1507
  disabled,
@@ -1547,15 +1569,15 @@ function Dropdown({
1547
1569
  labelStyle = {},
1548
1570
  placeholder
1549
1571
  }) {
1550
- const [open, setOpen] = React10.useState(false);
1551
- const [selectedItems, setSelectedItems] = React10.useState([]);
1552
- const [hoveredItem, setHoveredItem] = React10.useState(null);
1553
- const [searchTerm, setSearchTerm] = React10.useState("");
1554
- const [innerItems, setInnerItems] = React10.useState([]);
1555
- React10.useEffect(() => {
1572
+ const [open, setOpen] = React9.useState(false);
1573
+ const [selectedItems, setSelectedItems] = React9.useState([]);
1574
+ const [hoveredItem, setHoveredItem] = React9.useState(null);
1575
+ const [searchTerm, setSearchTerm] = React9.useState("");
1576
+ const [innerItems, setInnerItems] = React9.useState([]);
1577
+ React9.useEffect(() => {
1556
1578
  setInnerItems(items);
1557
1579
  }, [items]);
1558
- React10.useEffect(() => {
1580
+ React9.useEffect(() => {
1559
1581
  if (isMultiselect && Array.isArray(value)) {
1560
1582
  setSelectedItems(value);
1561
1583
  }
@@ -1701,9 +1723,7 @@ var DEFAULT_PAGINATION = {
1701
1723
  pickerOptions: DEFAULT_PICKER
1702
1724
  };
1703
1725
  var DEFAULT_EXPAND = {
1704
- enabled: false,
1705
- expandIcon: /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, {}),
1706
- expandComponent: () => /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, {})
1726
+ enabled: false
1707
1727
  };
1708
1728
  function createDatasets(rows, perPage) {
1709
1729
  if (!perPage) return [rows.slice()];
@@ -1713,78 +1733,95 @@ function createDatasets(rows, perPage) {
1713
1733
  }
1714
1734
  return all;
1715
1735
  }
1716
- function TableHeader({ columns }) {
1717
- return /* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-surface-raised min-h-[50px] border-b border-b-border flex items-center", children: /* @__PURE__ */ jsxRuntime.jsx("tr", { className: "flex w-full items-center justify-center", children: columns.map((col) => /* @__PURE__ */ jsxRuntime.jsx(
1718
- "th",
1719
- {
1720
- className: "text-center w-full text-[13px] text-foreground",
1721
- children: col.label
1722
- },
1723
- col.key
1724
- )) }) });
1736
+ var defaultGetRowKey = (_row, index) => index;
1737
+ var cellAlign = (align) => align === "left" ? "text-left" : align === "right" ? "text-right" : "text-center";
1738
+ function TableHeader({
1739
+ columns,
1740
+ hasExpand
1741
+ }) {
1742
+ return /* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-surface-raised border-b border-border", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
1743
+ hasExpand && /* @__PURE__ */ jsxRuntime.jsx("th", { "aria-hidden": "true", className: "w-9" }),
1744
+ columns.map((col) => /* @__PURE__ */ jsxRuntime.jsx(
1745
+ "th",
1746
+ {
1747
+ scope: "col",
1748
+ className: `${cellAlign(col.align)} text-sm font-semibold text-foreground py-3 px-3`,
1749
+ style: col.width != null ? { width: col.width } : void 0,
1750
+ children: col.label
1751
+ },
1752
+ col.key
1753
+ ))
1754
+ ] }) });
1725
1755
  }
1756
+ var DefaultExpandIcon = /* @__PURE__ */ jsxRuntime.jsx(
1757
+ "svg",
1758
+ {
1759
+ xmlns: "http://www.w3.org/2000/svg",
1760
+ viewBox: "0 0 24 24",
1761
+ fill: "currentColor",
1762
+ className: "w-5 h-5 text-foreground-muted",
1763
+ "aria-hidden": "true",
1764
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1765
+ "path",
1766
+ {
1767
+ fillRule: "evenodd",
1768
+ d: "M12 2.25c-5.385 0-9.75 4.365-9.75 9.75s4.365 9.75 9.75 9.75 9.75-4.365 9.75-9.75S17.385 2.25 12 2.25zM12.75 9a.75.75 0 00-1.5 0v2.25H9a.75.75 0 000 1.5h2.25V15a.75.75 0 001.5 0v-2.25H15a.75.75 0 000-1.5h-2.25V9z",
1769
+ clipRule: "evenodd"
1770
+ }
1771
+ )
1772
+ }
1773
+ );
1726
1774
  function TableBody({
1727
1775
  columns,
1728
1776
  rows,
1729
- expandRow
1777
+ expandRow,
1778
+ getRowKey
1730
1779
  }) {
1731
- const [visibleRows, setVisibleRows] = React10.useState({});
1780
+ const [expanded, setExpanded] = React9.useState(() => /* @__PURE__ */ new Set());
1732
1781
  const toggleRow = (rowKey) => {
1733
- setVisibleRows((prev) => ({
1734
- ...prev,
1735
- [rowKey]: { visible: !prev[rowKey]?.visible }
1736
- }));
1782
+ setExpanded((prev) => {
1783
+ const next = new Set(prev);
1784
+ if (next.has(rowKey)) next.delete(rowKey);
1785
+ else next.add(rowKey);
1786
+ return next;
1787
+ });
1737
1788
  };
1738
- React10.useEffect(() => {
1739
- if (rows.length && Object.keys(visibleRows).length === 0) {
1740
- const initial = {};
1741
- rows.forEach((row) => {
1742
- initial[row.key] = { visible: false };
1743
- });
1744
- setVisibleRows(initial);
1745
- }
1746
- }, [rows]);
1747
- return /* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "w-full", children: rows.map((row, i) => /* @__PURE__ */ jsxRuntime.jsxs(React10__default.default.Fragment, { children: [
1748
- /* @__PURE__ */ jsxRuntime.jsxs(
1749
- "tr",
1750
- {
1751
- className: `border-b border-b-border flex min-w-max hover:bg-surface-raised transition-all duration-150 ${i % 2 === 0 ? "bg-surface" : "bg-surface-raised"}`,
1752
- children: [
1753
- expandRow.enabled && /* @__PURE__ */ jsxRuntime.jsx("td", { className: "flex items-center", children: /* @__PURE__ */ jsxRuntime.jsx(
1754
- "span",
1755
- {
1756
- onClick: () => toggleRow(row.key),
1757
- className: `p-2 cursor-pointer origin-center transition-all duration-200 ${visibleRows[row.key]?.visible ? "rotate-180" : "rotate-0"}`,
1758
- children: expandRow.expandIcon ?? /* PlusCircle */
1759
- /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", className: "w-5 h-5 text-foreground-muted", children: /* @__PURE__ */ jsxRuntime.jsx("path", { fillRule: "evenodd", d: "M12 2.25c-5.385 0-9.75 4.365-9.75 9.75s4.365 9.75 9.75 9.75 9.75-4.365 9.75-9.75S17.385 2.25 12 2.25zM12.75 9a.75.75 0 00-1.5 0v2.25H9a.75.75 0 000 1.5h2.25V15a.75.75 0 001.5 0v-2.25H15a.75.75 0 000-1.5h-2.25V9z", clipRule: "evenodd" }) })
1760
- }
1761
- ) }),
1762
- columns.map((col, index) => /* @__PURE__ */ jsxRuntime.jsx(
1763
- "td",
1764
- {
1765
- className: `text-center min-h-[40px] w-full flex items-center justify-center p-1 border-border ${index !== columns.length - 1 ? "border-r-2" : ""}`,
1766
- children: "component" in col && col.component ? col.component(row[col.keyBind], row) : row[col.keyBind]
1767
- },
1768
- index
1769
- ))
1770
- ]
1771
- }
1772
- ),
1773
- expandRow.enabled && /* @__PURE__ */ jsxRuntime.jsx(
1774
- "tr",
1775
- {
1776
- className: `overflow-hidden w-full transition-all duration-300 ${visibleRows[row.key]?.visible ? "max-h-[2000px]" : "max-h-0"}`,
1777
- children: /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan: columns.length, className: "p-0 pb-1", children: /* @__PURE__ */ jsxRuntime.jsx(
1778
- "div",
1779
- {
1780
- className: `overflow-hidden w-full transition-[max-height] duration-300 ${visibleRows[row.key]?.visible ? "max-h-[2000px]" : "max-h-0"}`,
1781
- children: expandRow.expandComponent?.(row)
1782
- }
1783
- ) })
1784
- },
1785
- `extra-${i}`
1786
- )
1787
- ] }, row.key)) });
1789
+ const hasExpand = !!expandRow.enabled;
1790
+ const expandColCount = columns.length + (hasExpand ? 1 : 0);
1791
+ return /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: rows.map((row, i) => {
1792
+ const rowKey = getRowKey(row, i);
1793
+ const isExpanded = expanded.has(rowKey);
1794
+ return /* @__PURE__ */ jsxRuntime.jsxs(React9__default.default.Fragment, { children: [
1795
+ /* @__PURE__ */ jsxRuntime.jsxs(
1796
+ "tr",
1797
+ {
1798
+ className: `border-b border-border hover:bg-surface-raised transition-colors duration-150 ${i % 2 === 0 ? "bg-surface" : "bg-surface-raised"}`,
1799
+ children: [
1800
+ hasExpand && /* @__PURE__ */ jsxRuntime.jsx("td", { className: "p-0 align-middle w-9", children: /* @__PURE__ */ jsxRuntime.jsx(
1801
+ "button",
1802
+ {
1803
+ type: "button",
1804
+ onClick: () => toggleRow(rowKey),
1805
+ "aria-expanded": isExpanded,
1806
+ "aria-label": isExpanded ? "Collapse row" : "Expand row",
1807
+ className: `w-9 h-9 inline-flex items-center justify-center rounded-md hover:bg-surface/80 transition-transform duration-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-accent ${isExpanded ? "rotate-180" : ""}`,
1808
+ children: expandRow.expandIcon ?? DefaultExpandIcon
1809
+ }
1810
+ ) }),
1811
+ columns.map((col) => /* @__PURE__ */ jsxRuntime.jsx(
1812
+ "td",
1813
+ {
1814
+ className: `${cellAlign(col.align)} text-sm text-foreground py-2 px-3 align-middle`,
1815
+ children: col.component ? col.component(row[col.keyBind], row) : row[col.keyBind]
1816
+ },
1817
+ col.key
1818
+ ))
1819
+ ]
1820
+ }
1821
+ ),
1822
+ hasExpand && isExpanded && /* @__PURE__ */ jsxRuntime.jsx("tr", { className: "bg-surface", children: /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan: expandColCount, className: "p-0 border-b border-border", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-3", children: expandRow.expandComponent?.(row) }) }) })
1823
+ ] }, rowKey);
1824
+ }) });
1788
1825
  }
1789
1826
  function Pagination({
1790
1827
  activePage,
@@ -1798,38 +1835,36 @@ function Pagination({
1798
1835
  const matchedOption = picker.find(
1799
1836
  (o) => o.label === options.perPage || o.value === options.perPage
1800
1837
  );
1801
- const [perPageKey, setPerPageKey] = React10.useState(() => matchedOption?.key ?? picker[0]?.key);
1838
+ const [perPageKey, setPerPageKey] = React9.useState(() => matchedOption?.key ?? picker[0]?.key);
1802
1839
  const displayPerPageKey = serverSide ? matchedOption?.key ?? perPageKey : perPageKey;
1803
- React10.useEffect(() => {
1840
+ React9.useEffect(() => {
1804
1841
  if (serverSide && options.perPage != null) {
1805
1842
  const next = picker.find((o) => o.label === options.perPage || o.value === options.perPage);
1806
1843
  if (next) setPerPageKey(next.key);
1807
1844
  }
1808
1845
  }, [serverSide, options.perPage, picker]);
1809
1846
  const navBtn = (icon, disabled, onClick) => /* @__PURE__ */ jsxRuntime.jsx(IconButton, { disabled, onClick, icon });
1810
- const chevronRight = (color) => /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: 2, className: "h-5 w-5", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 5l7 7-7 7" }) });
1811
- const doubleChevronRight = (color) => /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: 2, className: "h-5 w-5", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M13 5l7 7-7 7M5 5l7 7-7 7" }) });
1812
- const disabledColor = "var(--color-foreground-muted)";
1813
- const enabledColor = "var(--color-foreground)";
1847
+ const chevronRight = /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-5 w-5", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 5l7 7-7 7" }) });
1848
+ const doubleChevronRight = /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-5 w-5", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M13 5l7 7-7 7M5 5l7 7-7 7" }) });
1814
1849
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2 items-center justify-end pt-2", children: [
1815
1850
  navBtn(
1816
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rotate-180 inline-flex", children: doubleChevronRight(activePage === 0 ? disabledColor : enabledColor) }),
1851
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rotate-180 inline-flex", children: doubleChevronRight }),
1817
1852
  activePage === 0,
1818
1853
  () => onPageChange(0)
1819
1854
  ),
1820
1855
  navBtn(
1821
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rotate-180 inline-flex", children: chevronRight(activePage === 0 ? disabledColor : enabledColor) }),
1856
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rotate-180 inline-flex", children: chevronRight }),
1822
1857
  activePage === 0,
1823
1858
  () => activePage > 0 && onPageChange(activePage - 1)
1824
1859
  ),
1825
1860
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bg-surface-raised rounded-lg ml-2 mr-2 shadow-sm p-2 w-10 text-center select-none text-foreground", children: activePage + 1 }),
1826
1861
  navBtn(
1827
- chevronRight(activePage === maxPage ? disabledColor : enabledColor),
1862
+ chevronRight,
1828
1863
  activePage === maxPage,
1829
1864
  () => activePage < maxPage && onPageChange(activePage + 1)
1830
1865
  ),
1831
1866
  navBtn(
1832
- doubleChevronRight(activePage === maxPage ? disabledColor : enabledColor),
1867
+ doubleChevronRight,
1833
1868
  activePage === maxPage,
1834
1869
  () => onPageChange(maxPage)
1835
1870
  ),
@@ -1854,54 +1889,57 @@ function Pagination({
1854
1889
  function Table({
1855
1890
  columns = [],
1856
1891
  rows = [],
1892
+ getRowKey = defaultGetRowKey,
1857
1893
  pagination = DEFAULT_PAGINATION,
1858
1894
  expandRow = DEFAULT_EXPAND,
1859
1895
  hasSearch = true,
1860
1896
  footer = null,
1861
1897
  header = null
1862
1898
  }) {
1863
- const searchRef = React10.useRef(null);
1864
- const [searchTerm, setSearchTerm] = React10.useState("");
1865
- const [perPage, setPerPage] = React10.useState(
1899
+ const searchRef = React9.useRef(null);
1900
+ const [searchTerm, setSearchTerm] = React9.useState("");
1901
+ const [perPage, setPerPage] = React9.useState(
1866
1902
  typeof pagination.perPage === "number" ? pagination.perPage : 15
1867
1903
  );
1868
- const [activePage, setActivePage] = React10.useState(0);
1869
- const [datasets, setDatasets] = React10.useState([]);
1904
+ const [activePage, setActivePage] = React9.useState(0);
1870
1905
  const isServerSide = !!(pagination.enabled && pagination.serverSide);
1871
- const MAX_PAGE = React10.useMemo(() => {
1906
+ const filteredRows = React9.useMemo(() => {
1907
+ if (isServerSide || !searchTerm) return rows;
1908
+ const term = searchTerm.toLowerCase();
1909
+ return rows.filter(
1910
+ (row) => Object.values(row).some(
1911
+ (v) => v != null && String(v).toLowerCase().includes(term)
1912
+ )
1913
+ );
1914
+ }, [rows, searchTerm, isServerSide]);
1915
+ const datasets = React9.useMemo(() => {
1916
+ if (isServerSide) return [rows];
1917
+ return createDatasets(filteredRows, pagination.enabled ? perPage : null);
1918
+ }, [filteredRows, perPage, pagination.enabled, isServerSide, rows]);
1919
+ const MAX_PAGE = React9.useMemo(() => {
1872
1920
  if (isServerSide && typeof pagination.maxPage === "number") return Math.max(0, pagination.maxPage);
1873
1921
  if (isServerSide && typeof pagination.totalCount === "number")
1874
1922
  return Math.max(0, Math.ceil(pagination.totalCount / perPage) - 1);
1875
1923
  return datasets.length ? datasets.length - 1 : 0;
1876
1924
  }, [isServerSide, pagination.maxPage, pagination.totalCount, perPage, datasets.length]);
1877
- const currentPageRows = React10.useMemo(() => {
1925
+ const currentPageRows = React9.useMemo(() => {
1878
1926
  if (isServerSide) return rows;
1879
- return datasets.length ? datasets[activePage] ?? [] : [];
1927
+ return datasets[activePage] ?? [];
1880
1928
  }, [isServerSide, rows, datasets, activePage]);
1881
- React10.useEffect(() => {
1882
- if (pagination.enabled && !isServerSide) setPerPage(pagination.perPage ?? 15);
1883
- }, [pagination, isServerSide]);
1884
- React10.useEffect(() => {
1929
+ React9.useEffect(() => {
1930
+ if (pagination.enabled && !isServerSide && typeof pagination.perPage === "number") {
1931
+ setPerPage(pagination.perPage);
1932
+ }
1933
+ }, [pagination.enabled, pagination.perPage, isServerSide]);
1934
+ React9.useEffect(() => {
1885
1935
  if (isServerSide && typeof pagination.perPage === "number") setPerPage(pagination.perPage);
1886
1936
  }, [isServerSide, pagination.perPage]);
1887
- React10.useEffect(() => {
1888
- if (isServerSide) return;
1889
- setDatasets(createDatasets(rows, pagination.enabled ? perPage : null));
1890
- }, [rows, perPage, pagination, isServerSide]);
1891
- React10.useEffect(() => {
1937
+ React9.useEffect(() => {
1892
1938
  if (isServerSide && typeof pagination.page === "number" && pagination.page >= 1)
1893
1939
  setActivePage(pagination.page - 1);
1894
1940
  }, [isServerSide, pagination.page]);
1895
1941
  const onSearchChange = (e) => {
1896
- const term = e.target.value;
1897
- setSearchTerm(term);
1898
- if (isServerSide) return;
1899
- const filtered = rows.filter(
1900
- (row) => Object.values(row).some(
1901
- (v) => !!v && String(v).toLowerCase().includes(term.toLowerCase())
1902
- )
1903
- );
1904
- setDatasets(createDatasets(filtered, pagination.enabled ? perPage : null));
1942
+ setSearchTerm(e.target.value);
1905
1943
  setActivePage(0);
1906
1944
  };
1907
1945
  const onPaginationChange = (perPageValue) => {
@@ -1940,15 +1978,23 @@ function Table({
1940
1978
  )
1941
1979
  ] }),
1942
1980
  /* @__PURE__ */ jsxRuntime.jsx("div", { children: header }),
1943
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto rounded-lg", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full", children: [
1944
- /* @__PURE__ */ jsxRuntime.jsx(TableHeader, { columns }),
1945
- /* @__PURE__ */ jsxRuntime.jsx(TableBody, { columns, rows: currentPageRows, expandRow })
1981
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto rounded-lg", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full border-collapse", children: [
1982
+ /* @__PURE__ */ jsxRuntime.jsx(TableHeader, { columns, hasExpand: !!expandRow.enabled }),
1983
+ /* @__PURE__ */ jsxRuntime.jsx(
1984
+ TableBody,
1985
+ {
1986
+ columns,
1987
+ rows: currentPageRows,
1988
+ expandRow,
1989
+ getRowKey
1990
+ }
1991
+ )
1946
1992
  ] }) }),
1947
1993
  /* @__PURE__ */ jsxRuntime.jsx("div", { children: footer })
1948
1994
  ] });
1949
1995
  }
1950
1996
  function ThemeSwitch({ checked, onChange, label = "Toggle dark mode" }) {
1951
- const id = React10.useId();
1997
+ const id = React9.useId();
1952
1998
  return /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, className: "flex items-center gap-2 cursor-pointer select-none", children: /* @__PURE__ */ jsxRuntime.jsx(
1953
1999
  SwitchPrimitive__namespace.Root,
1954
2000
  {
@@ -2141,17 +2187,17 @@ function AppShell({
2141
2187
  children,
2142
2188
  className = ""
2143
2189
  }) {
2144
- const [expanded, setExpanded] = React10.useState(sidebarDefaultExpanded);
2145
- const [isMobile, setIsMobile] = React10.useState(false);
2146
- const [mobileOpen, setMobileOpen] = React10.useState(false);
2147
- React10.useEffect(() => {
2190
+ const [expanded, setExpanded] = React9.useState(sidebarDefaultExpanded);
2191
+ const [isMobile, setIsMobile] = React9.useState(false);
2192
+ const [mobileOpen, setMobileOpen] = React9.useState(false);
2193
+ React9.useEffect(() => {
2148
2194
  const mq = window.matchMedia("(max-width: 767px)");
2149
2195
  const update = (e) => setIsMobile(e.matches);
2150
2196
  update(mq);
2151
2197
  mq.addEventListener("change", update);
2152
2198
  return () => mq.removeEventListener("change", update);
2153
2199
  }, []);
2154
- React10.useEffect(() => {
2200
+ React9.useEffect(() => {
2155
2201
  if (!isMobile) setMobileOpen(false);
2156
2202
  }, [isMobile]);
2157
2203
  const hasSidebar = sidebarSections.length > 0;
@@ -2325,10 +2371,10 @@ function ThemeProvider({
2325
2371
  className = "",
2326
2372
  style
2327
2373
  }) {
2328
- const id = React10__default.default.useId().replace(/:/g, "");
2374
+ const id = React9__default.default.useId().replace(/:/g, "");
2329
2375
  const scopeClass = `geo-th-${id}`;
2330
- const divRef = React10.useRef(null);
2331
- React10.useEffect(() => {
2376
+ const divRef = React9.useRef(null);
2377
+ React9.useEffect(() => {
2332
2378
  const el = divRef.current;
2333
2379
  if (!el) return;
2334
2380
  if (colorScheme === "auto") return;
@@ -2343,8 +2389,8 @@ function ThemeProvider({
2343
2389
  }
2344
2390
  el.classList.toggle("dark", colorScheme === "dark");
2345
2391
  }, [colorScheme]);
2346
- const lightVars = React10.useMemo(() => toCssVars(theme), [theme]);
2347
- const darkVarStr = React10.useMemo(() => {
2392
+ const lightVars = React9.useMemo(() => toCssVars(theme), [theme]);
2393
+ const darkVarStr = React9.useMemo(() => {
2348
2394
  if (!darkTheme) return "";
2349
2395
  const dvars = toCssVars(darkTheme);
2350
2396
  if (!Object.keys(dvars).length) return "";
@@ -2623,7 +2669,7 @@ function Password({
2623
2669
  labelColor,
2624
2670
  iconColor
2625
2671
  }) {
2626
- const [passwordVisible, setPasswordVisible] = React10.useState(false);
2672
+ const [passwordVisible, setPasswordVisible] = React9.useState(false);
2627
2673
  const color = iconColor ?? chunk255PCZIW_cjs.colors_default.PALETTE["prussian-blue"];
2628
2674
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex flex-col items-center justify-center", style: style ?? {}, children: [
2629
2675
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex ${layout === "vertical" ? "flex-col" : "flex-row items-center gap-2"}`, children: [
@@ -2769,7 +2815,7 @@ function Switch({
2769
2815
  checkedIcon,
2770
2816
  uncheckedIcon
2771
2817
  }) {
2772
- const id = React10.useId();
2818
+ const id = React9.useId();
2773
2819
  return /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, className: "flex items-center cursor-pointer mr-12 select-none", children: /* @__PURE__ */ jsxRuntime.jsx(
2774
2820
  SwitchPrimitive__namespace.Root,
2775
2821
  {
@@ -2799,8 +2845,8 @@ function AutoComplete({
2799
2845
  onItemClick,
2800
2846
  emptyText = "No results found"
2801
2847
  }) {
2802
- const [term, setTerm] = React10.useState("");
2803
- const [open, setOpen] = React10.useState(false);
2848
+ const [term, setTerm] = React9.useState("");
2849
+ const [open, setOpen] = React9.useState(false);
2804
2850
  const foundItems = term.trim() ? items.filter(
2805
2851
  ({ key, label: label2 }) => label2.toLowerCase().includes(term.toLowerCase()) || key.toLowerCase().includes(term.toLowerCase())
2806
2852
  ) : [];
@@ -2885,10 +2931,10 @@ function TreeSelect({
2885
2931
  htmlFor,
2886
2932
  items = []
2887
2933
  }) {
2888
- const [open, setOpen] = React10.useState(false);
2889
- const [hoveredItem, setHoveredItem] = React10.useState(null);
2890
- const [innerItems, setInnerItems] = React10.useState([]);
2891
- React10.useEffect(() => {
2934
+ const [open, setOpen] = React9.useState(false);
2935
+ const [hoveredItem, setHoveredItem] = React9.useState(null);
2936
+ const [innerItems, setInnerItems] = React9.useState([]);
2937
+ React9.useEffect(() => {
2892
2938
  setInnerItems(items);
2893
2939
  }, [items]);
2894
2940
  const selectItem = (key) => {
@@ -2987,8 +3033,8 @@ function FileInput({
2987
3033
  name,
2988
3034
  accept = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,.xlsx"
2989
3035
  }) {
2990
- const fileInput = React10.useRef(null);
2991
- const [files, setFiles] = React10.useState([]);
3036
+ const fileInput = React9.useRef(null);
3037
+ const [files, setFiles] = React9.useState([]);
2992
3038
  const openPicker = () => {
2993
3039
  fileInput.current?.click();
2994
3040
  };
@@ -3136,12 +3182,12 @@ function DatePickerBase({
3136
3182
  disableAfter,
3137
3183
  disabled
3138
3184
  }) {
3139
- const pickerRef = React10.useRef(null);
3140
- const calendarRef = React10.useRef(null);
3141
- const [isExpanded, setExpanded] = React10.useState(false);
3142
- const [isCloseToBottom, setCloseToBottom] = React10.useState(false);
3143
- const [currentYear, setCurrentYear] = React10.useState(value.getFullYear());
3144
- const [currentMonth, setCurrentMonth] = React10.useState(value.getMonth() + 1);
3185
+ const pickerRef = React9.useRef(null);
3186
+ const calendarRef = React9.useRef(null);
3187
+ const [isExpanded, setExpanded] = React9.useState(false);
3188
+ const [isCloseToBottom, setCloseToBottom] = React9.useState(false);
3189
+ const [currentYear, setCurrentYear] = React9.useState(value.getFullYear());
3190
+ const [currentMonth, setCurrentMonth] = React9.useState(value.getMonth() + 1);
3145
3191
  const toggle = () => {
3146
3192
  if (!disabled) setExpanded((p) => !p);
3147
3193
  };
@@ -3185,14 +3231,14 @@ function DatePickerBase({
3185
3231
  }
3186
3232
  return ordered;
3187
3233
  };
3188
- React10.useEffect(() => {
3234
+ React9.useEffect(() => {
3189
3235
  const clickAway = (e) => {
3190
3236
  if (pickerRef.current && !pickerRef.current.contains(e.target) && calendarRef.current && !calendarRef.current.contains(e.target)) setExpanded(false);
3191
3237
  };
3192
3238
  document.addEventListener("mousedown", clickAway);
3193
3239
  return () => document.removeEventListener("mousedown", clickAway);
3194
3240
  }, []);
3195
- React10.useEffect(() => {
3241
+ React9.useEffect(() => {
3196
3242
  const bbox = pickerRef.current?.getBoundingClientRect();
3197
3243
  if (bbox && (bbox.y > window.innerHeight - 220 || bbox.bottom > window.innerHeight - 400)) {
3198
3244
  setCloseToBottom(true);
@@ -3285,29 +3331,29 @@ function TemporalPickerBase({
3285
3331
  layout,
3286
3332
  style = {}
3287
3333
  }) {
3288
- const pickerRef = React10.useRef(null);
3289
- const calendarRef = React10.useRef(null);
3290
- const valueRefs = React10.useRef([]);
3291
- const [isExpanded, setExpanded] = React10.useState(false);
3292
- const [isCloseToBottom, setCloseToBottom] = React10.useState(false);
3293
- const innerValues = React10.useMemo(() => {
3334
+ const pickerRef = React9.useRef(null);
3335
+ const calendarRef = React9.useRef(null);
3336
+ const valueRefs = React9.useRef([]);
3337
+ const [isExpanded, setExpanded] = React9.useState(false);
3338
+ const [isCloseToBottom, setCloseToBottom] = React9.useState(false);
3339
+ const innerValues = React9.useMemo(() => {
3294
3340
  const vals = [];
3295
3341
  for (let i = lowerLimit; i <= upperLimit; i++) vals.push(i);
3296
3342
  return vals;
3297
3343
  }, [lowerLimit, upperLimit]);
3298
- React10.useEffect(() => {
3344
+ React9.useEffect(() => {
3299
3345
  const clickAway = (e) => {
3300
3346
  if (pickerRef.current && !pickerRef.current.contains(e.target) && calendarRef.current && !calendarRef.current.contains(e.target)) setExpanded(false);
3301
3347
  };
3302
3348
  document.addEventListener("mousedown", clickAway);
3303
3349
  return () => document.removeEventListener("mousedown", clickAway);
3304
3350
  }, []);
3305
- React10.useEffect(() => {
3351
+ React9.useEffect(() => {
3306
3352
  const bbox = pickerRef.current?.getBoundingClientRect();
3307
3353
  if (bbox && bbox.y > window.innerHeight - 220) setCloseToBottom(true);
3308
3354
  else setCloseToBottom(false);
3309
3355
  }, []);
3310
- React10.useEffect(() => {
3356
+ React9.useEffect(() => {
3311
3357
  if (!isExpanded) return;
3312
3358
  const t = setTimeout(() => {
3313
3359
  const node = valueRefs.current.find((n) => n.value === value);