@geomak/ui 1.6.2 → 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -2,7 +2,8 @@
2
2
 
3
3
  var chunk255PCZIW_cjs = require('./chunk-255PCZIW.cjs');
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
- var React9 = require('react');
5
+ var React10 = require('react');
6
+ var reactDom = require('react-dom');
6
7
  var Dialog = require('@radix-ui/react-dialog');
7
8
  var framerMotion = require('framer-motion');
8
9
  var TooltipPrimitive = require('@radix-ui/react-tooltip');
@@ -34,7 +35,7 @@ function _interopNamespace(e) {
34
35
  return Object.freeze(n);
35
36
  }
36
37
 
37
- var React9__default = /*#__PURE__*/_interopDefault(React9);
38
+ var React10__default = /*#__PURE__*/_interopDefault(React10);
38
39
  var Dialog__namespace = /*#__PURE__*/_interopNamespace(Dialog);
39
40
  var TooltipPrimitive__namespace = /*#__PURE__*/_interopNamespace(TooltipPrimitive);
40
41
  var TabsPrimitive__namespace = /*#__PURE__*/_interopNamespace(TabsPrimitive);
@@ -204,6 +205,18 @@ Icon.Save = Save;
204
205
  Icon.Copy = Copy;
205
206
  Icon.CircleStack = CircleStack;
206
207
  var icons_default = Icon;
208
+ function Portal({ children, target }) {
209
+ const [resolved, setResolved] = React10.useState(null);
210
+ React10.useEffect(() => {
211
+ if (target === null) {
212
+ setResolved(null);
213
+ return;
214
+ }
215
+ const node = typeof target === "function" ? target() : target ?? document.body;
216
+ setResolved(node ?? null);
217
+ }, [target]);
218
+ return resolved ? reactDom.createPortal(children, resolved) : null;
219
+ }
207
220
  function IconButton({
208
221
  icon,
209
222
  onClick,
@@ -214,7 +227,7 @@ function IconButton({
214
227
  loading = false,
215
228
  loadingIcon
216
229
  }) {
217
- const colorScheme = React9.useMemo(() => {
230
+ const colorScheme = React10.useMemo(() => {
218
231
  if (type === "primary") {
219
232
  return "hover:bg-true-blue bg-usafa-blue dark:bg-independence dark:hover:bg-black-coral";
220
233
  }
@@ -319,7 +332,8 @@ function Button({
319
332
  );
320
333
  }
321
334
  function Modal({
322
- size = [600, 400],
335
+ width,
336
+ size,
323
337
  isOpen = false,
324
338
  onClose,
325
339
  onOk,
@@ -331,6 +345,7 @@ function Modal({
331
345
  children
332
346
  }) {
333
347
  const reduced = framerMotion.useReducedMotion();
348
+ const maxWidth = width ?? size?.[0] ?? 600;
334
349
  return /* @__PURE__ */ jsxRuntime.jsx(Dialog__namespace.Root, { open: isOpen, onOpenChange: (open) => {
335
350
  if (!open) onClose?.();
336
351
  }, children: /* @__PURE__ */ jsxRuntime.jsxs(Dialog__namespace.Portal, { forceMount: true, children: [
@@ -349,7 +364,7 @@ function Modal({
349
364
  {
350
365
  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",
351
366
  style: {
352
- maxWidth: size[0],
367
+ maxWidth,
353
368
  x: "-50%",
354
369
  y: "-50%"
355
370
  },
@@ -374,7 +389,7 @@ function Modal({
374
389
  }
375
390
  ) })
376
391
  ] }),
377
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex-1 overflow-y-auto p-5 ${hasFooter ? "" : "pb-5"}`, children: isOpen && children }),
392
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex-1 overflow-y-auto p-5 ${hasFooter ? "" : "pb-5"}`, children }),
378
393
  hasFooter && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-shrink-0 items-center justify-end gap-3 border-t border-border px-5 py-3", children: [
379
394
  /* @__PURE__ */ jsxRuntime.jsx(
380
395
  Button,
@@ -456,7 +471,7 @@ function Drawer({
456
471
  }
457
472
  ) })
458
473
  ] }),
459
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-y-auto p-5", children: isOpen && children }),
474
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-y-auto p-5", children }),
460
475
  hasFooter && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex flex-shrink-0 items-center gap-3 border-t border-border px-5 py-3 ${isRight ? "justify-start" : "justify-end"}`, children: [
461
476
  /* @__PURE__ */ jsxRuntime.jsx(Button, { style: { width: 90 }, content: cancelText, onClick: onCancel }),
462
477
  /* @__PURE__ */ jsxRuntime.jsx(Button, { style: { width: 90 }, content: okText, onClick: onOk })
@@ -523,11 +538,11 @@ function Tabs({
523
538
  tabsClosable = true,
524
539
  defaultActiveTab
525
540
  }) {
526
- const [value, setValue] = React9.useState(() => defaultActiveTab ?? tabs[0]?.key ?? "");
527
- React9.useEffect(() => {
541
+ const [value, setValue] = React10.useState(() => defaultActiveTab ?? tabs[0]?.key ?? "");
542
+ React10.useEffect(() => {
528
543
  if (defaultActiveTab) setValue(defaultActiveTab);
529
544
  }, [defaultActiveTab]);
530
- React9.useEffect(() => {
545
+ React10.useEffect(() => {
531
546
  if (tabs.length === 0) {
532
547
  setValue("");
533
548
  return;
@@ -575,29 +590,46 @@ function Tabs({
575
590
  {
576
591
  "aria-label": "Tabs",
577
592
  className: "flex-1 flex items-center gap-1 overflow-x-auto overflow-y-hidden rounded-lg scroll-smooth snap-x snap-mandatory hidden-scrollbar",
578
- children: tabs.map((tab) => /* @__PURE__ */ jsxRuntime.jsxs(
579
- TabsPrimitive__namespace.Trigger,
580
- {
581
- value: tab.key,
582
- className: "snap-start snap-always flex items-center justify-between gap-2 px-3 py-2 rounded-3xl cursor-pointer transition-all duration-200 select-none h-10 flex-1 min-w-[120px] max-w-[220px] flex-shrink-0\n text-foreground-secondary bg-surface-raised\n hover:bg-surface hover:text-foreground\n data-[state=active]:bg-accent data-[state=active]:text-accent-foreground\n focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
583
- children: [
584
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-sm", children: tab.title }),
585
- tabsClosable && /* @__PURE__ */ jsxRuntime.jsx(
586
- "span",
587
- {
588
- role: "button",
589
- "aria-label": `Close ${tab.title}`,
590
- onClick: (e) => {
591
- e.stopPropagation();
592
- onTabClose?.(tab.key);
593
- },
594
- className: "flex-shrink-0 rounded hover:bg-black/10 p-0.5 transition-colors",
595
- children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "14", height: "14", viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15 5L5 15M5 5l10 10", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
596
- }
597
- )
598
- ]
599
- },
600
- tab.key
593
+ children: tabs.map((tab) => (
594
+ // Trigger + close button are SIBLINGS, not nested.
595
+ // Nesting a clickable element inside <button> is invalid
596
+ // HTML and breaks keyboard activation of the inner one.
597
+ // The wrapper carries `group` so the close button can
598
+ // react to the trigger's `data-state=active` for styling.
599
+ /* @__PURE__ */ jsxRuntime.jsxs(
600
+ "div",
601
+ {
602
+ className: "snap-start snap-always relative flex items-center flex-1 min-w-[120px] max-w-[220px] flex-shrink-0 group",
603
+ children: [
604
+ /* @__PURE__ */ jsxRuntime.jsx(
605
+ TabsPrimitive__namespace.Trigger,
606
+ {
607
+ value: tab.key,
608
+ className: `w-full ${tabsClosable ? "pr-8" : "pr-3"} pl-3 py-2 rounded-3xl cursor-pointer transition-all duration-200 select-none h-10 text-left
609
+ text-foreground-secondary bg-surface-raised
610
+ hover:bg-surface hover:text-foreground
611
+ data-[state=active]:bg-accent data-[state=active]:text-accent-foreground
612
+ focus:outline-none focus-visible:ring-2 focus-visible:ring-accent`,
613
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-sm block", children: tab.title })
614
+ }
615
+ ),
616
+ tabsClosable && /* @__PURE__ */ jsxRuntime.jsx(
617
+ "button",
618
+ {
619
+ type: "button",
620
+ "aria-label": `Close ${tab.title}`,
621
+ onClick: (e) => {
622
+ e.stopPropagation();
623
+ onTabClose?.(tab.key);
624
+ },
625
+ className: "absolute right-1.5 top-1/2 -translate-y-1/2 rounded p-0.5 text-foreground-secondary group-data-[state=active]:text-accent-foreground hover:bg-black/10 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
626
+ children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "14", height: "14", viewBox: "0 0 20 20", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15 5L5 15M5 5l10 10", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
627
+ }
628
+ )
629
+ ]
630
+ },
631
+ tab.key
632
+ )
601
633
  ))
602
634
  }
603
635
  ),
@@ -660,40 +692,41 @@ function TreeNodeItem({
660
692
  defaultValue: initialOpen,
661
693
  style: { paddingLeft: depth * 12 },
662
694
  children: /* @__PURE__ */ jsxRuntime.jsxs(Accordion__namespace.Item, { value: item.key, className: "border-none", children: [
663
- /* @__PURE__ */ jsxRuntime.jsxs(Accordion__namespace.Trigger, { className: "flex items-center gap-2 cursor-pointer py-1.5 px-2 group focus:outline-none focus-visible:ring-2 focus-visible:ring-accent w-full text-left rounded-md hover:bg-surface-raised transition-colors duration-150", children: [
664
- /* @__PURE__ */ jsxRuntime.jsx(
665
- "svg",
666
- {
667
- viewBox: "0 0 24 24",
668
- fill: "none",
669
- stroke: "currentColor",
670
- strokeWidth: 2.5,
671
- className: "h-3.5 w-3.5 flex-shrink-0 text-foreground-muted transition-transform duration-200 group-data-[state=open]:rotate-0 group-data-[state=closed]:-rotate-90",
672
- children: /* @__PURE__ */ jsxRuntime.jsx(
673
- "path",
695
+ /* @__PURE__ */ jsxRuntime.jsxs(
696
+ Accordion__namespace.Trigger,
697
+ {
698
+ onClick: () => onNodeClick({
699
+ isParent: true,
700
+ key: item.key,
701
+ label: item.label,
702
+ data: item.nodeData,
703
+ parentLabel: item.parentLabel
704
+ }),
705
+ className: "flex items-center gap-2 cursor-pointer py-1.5 px-2 group focus:outline-none focus-visible:ring-2 focus-visible:ring-accent w-full text-left rounded-md hover:bg-surface-raised transition-colors duration-150",
706
+ children: [
707
+ /* @__PURE__ */ jsxRuntime.jsx(
708
+ "svg",
674
709
  {
675
- strokeLinecap: "round",
676
- strokeLinejoin: "round",
677
- d: "M19 9l-7 7-7-7"
710
+ viewBox: "0 0 24 24",
711
+ fill: "none",
712
+ stroke: "currentColor",
713
+ strokeWidth: 2.5,
714
+ className: "h-3.5 w-3.5 flex-shrink-0 text-foreground-muted transition-transform duration-200 group-data-[state=open]:rotate-0 group-data-[state=closed]:-rotate-90",
715
+ "aria-hidden": "true",
716
+ children: /* @__PURE__ */ jsxRuntime.jsx(
717
+ "path",
718
+ {
719
+ strokeLinecap: "round",
720
+ strokeLinejoin: "round",
721
+ d: "M19 9l-7 7-7-7"
722
+ }
723
+ )
678
724
  }
679
- )
680
- }
681
- ),
682
- /* @__PURE__ */ jsxRuntime.jsx(
683
- "span",
684
- {
685
- className: "text-sm font-semibold text-foreground select-none",
686
- onClick: () => onNodeClick({
687
- isParent: true,
688
- key: item.key,
689
- label: item.label,
690
- data: item.nodeData,
691
- parentLabel: item.parentLabel
692
- }),
693
- children: item.label
694
- }
695
- )
696
- ] }),
725
+ ),
726
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold text-foreground select-none", children: item.label })
727
+ ]
728
+ }
729
+ ),
697
730
  /* @__PURE__ */ jsxRuntime.jsx(Accordion__namespace.Content, { className: "overflow-hidden data-[state=open]:animate-accordion-down data-[state=closed]:animate-accordion-up", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ml-3.5 border-l border-border py-0.5", children: item.children.map((child) => /* @__PURE__ */ jsxRuntime.jsx(
698
731
  TreeNodeItem,
699
732
  {
@@ -756,7 +789,7 @@ function ToggleButton({ items, onChange, activeKey }) {
756
789
  }
757
790
  );
758
791
  }
759
- var NotificationContext = React9.createContext({
792
+ var NotificationContext = React10.createContext({
760
793
  open: () => void 0,
761
794
  close: () => void 0
762
795
  });
@@ -767,9 +800,9 @@ var TYPE_BG = {
767
800
  danger: "bg-status-error"
768
801
  };
769
802
  var VIEWPORT_CLASSES = {
770
- "top-right": "fixed top-14 right-4 flex flex-col items-end",
771
- "top-left": "fixed top-14 left-4 flex flex-col items-start",
772
- "top-center": "fixed top-14 left-1/2 flex flex-col items-center -translate-x-1/2",
803
+ "top-right": "fixed top-4 right-4 flex flex-col items-end",
804
+ "top-left": "fixed top-4 left-4 flex flex-col items-start",
805
+ "top-center": "fixed top-4 left-1/2 flex flex-col items-center -translate-x-1/2",
773
806
  "bottom-right": "fixed bottom-4 right-4 flex flex-col-reverse items-end",
774
807
  "bottom-left": "fixed bottom-4 left-4 flex flex-col-reverse items-start",
775
808
  "bottom-center": "fixed bottom-4 left-1/2 flex flex-col-reverse items-center -translate-x-1/2"
@@ -814,7 +847,7 @@ function NotificationItem({
814
847
  onClose,
815
848
  reduced
816
849
  }) {
817
- const [hovered, setHovered] = React9.useState(false);
850
+ const [hovered, setHovered] = React10.useState(false);
818
851
  const initial = getInitialMotion(pos, reduced);
819
852
  const center = pos.endsWith("center");
820
853
  const duration = n.duration ?? 4e3;
@@ -822,6 +855,7 @@ function NotificationItem({
822
855
  return /* @__PURE__ */ jsxRuntime.jsx(
823
856
  framerMotion.motion.div,
824
857
  {
858
+ className: "pointer-events-auto",
825
859
  initial,
826
860
  animate: { opacity: 1, y: 0, scale: 1 },
827
861
  exit: {
@@ -894,7 +928,7 @@ function NotificationProvider({
894
928
  children,
895
929
  position = "top-right"
896
930
  }) {
897
- const [notifications, setNotifications] = React9.useState([]);
931
+ const [notifications, setNotifications] = React10.useState([]);
898
932
  const reduced = framerMotion.useReducedMotion();
899
933
  const open = (payload) => {
900
934
  setNotifications((prev) => [
@@ -907,13 +941,13 @@ function NotificationProvider({
907
941
  };
908
942
  return /* @__PURE__ */ jsxRuntime.jsx(NotificationContext.Provider, { value: { open, close }, children: /* @__PURE__ */ jsxRuntime.jsxs(Toast__namespace.Provider, { swipeDirection: position.endsWith("right") ? "right" : position.endsWith("left") ? "left" : "up", children: [
909
943
  children,
910
- /* @__PURE__ */ jsxRuntime.jsx(
944
+ /* @__PURE__ */ jsxRuntime.jsx(Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
911
945
  Toast__namespace.Viewport,
912
946
  {
913
947
  asChild: true,
914
948
  className: [
915
949
  VIEWPORT_CLASSES[position],
916
- "z-[500000] gap-2 w-[340px] p-4 outline-none overflow-hidden"
950
+ "z-[500000] gap-2 w-[332px] outline-none pointer-events-none"
917
951
  ].join(" "),
918
952
  children: /* @__PURE__ */ jsxRuntime.jsx("ul", { children: /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { initial: false, children: notifications.map((n) => /* @__PURE__ */ jsxRuntime.jsx(
919
953
  NotificationItem,
@@ -926,11 +960,11 @@ function NotificationProvider({
926
960
  n.id
927
961
  )) }) })
928
962
  }
929
- )
963
+ ) })
930
964
  ] }) });
931
965
  }
932
966
  function useNotification() {
933
- const { open } = React9.useContext(NotificationContext);
967
+ const { open } = React10.useContext(NotificationContext);
934
968
  return {
935
969
  info: (props) => open({ type: "info", ...props }),
936
970
  success: (props) => open({ type: "success", ...props }),
@@ -939,9 +973,9 @@ function useNotification() {
939
973
  };
940
974
  }
941
975
  function LoadingSpinner({ prompt }) {
942
- const letterRefs = React9.useMemo(() => [], []);
976
+ const letterRefs = React10.useMemo(() => [], []);
943
977
  const letters = prompt.split("");
944
- React9.useEffect(() => {
978
+ React10.useEffect(() => {
945
979
  const timeouts = [];
946
980
  if (letterRefs.length === letters.length) {
947
981
  letterRefs.forEach((ref, index) => {
@@ -953,30 +987,34 @@ function LoadingSpinner({ prompt }) {
953
987
  }
954
988
  return () => timeouts.forEach(clearTimeout);
955
989
  }, [letterRefs, letters.length]);
956
- return /* @__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: [
957
- /* @__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" }),
958
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-prussian-blue dark:text-white text-3xl font-bold", children: letters.map((letter, index) => /* @__PURE__ */ jsxRuntime.jsx(
959
- "span",
960
- {
961
- className: "select-none",
962
- ref: (ref) => {
963
- letterRefs[index] = ref;
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
964
1003
  },
965
- children: letter
966
- },
967
- index
968
- )) })
969
- ] });
1004
+ index
1005
+ )) })
1006
+ ] }) })
1007
+ );
970
1008
  }
971
1009
  function FadingBase({
972
1010
  className = "",
973
1011
  isMounted = false,
974
1012
  children
975
1013
  }) {
976
- const [shouldRender, setShouldRender] = React9.useState(isMounted);
977
- const [visible, setVisible] = React9.useState(false);
978
- const timerRef = React9.useRef(null);
979
- React9.useEffect(() => {
1014
+ const [shouldRender, setShouldRender] = React10.useState(isMounted);
1015
+ const [visible, setVisible] = React10.useState(false);
1016
+ const timerRef = React10.useRef(null);
1017
+ React10.useEffect(() => {
980
1018
  if (isMounted) {
981
1019
  setShouldRender(true);
982
1020
  const rafId = requestAnimationFrame(() => setVisible(true));
@@ -1017,9 +1055,9 @@ function ScalableContainer({
1017
1055
  children,
1018
1056
  assignClassOnClick
1019
1057
  }) {
1020
- const containerRef = React9.useRef(null);
1021
- const [isScaled, setScaled] = React9.useState(false);
1022
- const [wrapperClass, setWrapperClass] = React9.useState("");
1058
+ const containerRef = React10.useRef(null);
1059
+ const [isScaled, setScaled] = React10.useState(false);
1060
+ const [wrapperClass, setWrapperClass] = React10.useState("");
1023
1061
  const onClick = () => {
1024
1062
  const next = !isScaled;
1025
1063
  setScaled(next);
@@ -1129,17 +1167,17 @@ function CatalogGrid({ items, buttonText, onOpen }) {
1129
1167
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(GridCard, { item, buttonText, onOpen }, item.key)) });
1130
1168
  }
1131
1169
  function CatalogCarousel({ items, buttonText, onOpen }) {
1132
- const [activeIndex, setActiveIndex] = React9.useState(0);
1133
- const [indexPool, setIndexPool] = React9.useState([]);
1134
- const cardRefs = React9.useRef([]);
1135
- const getIndexes = React9.useMemo(() => {
1170
+ const [activeIndex, setActiveIndex] = React10.useState(0);
1171
+ const [indexPool, setIndexPool] = React10.useState([]);
1172
+ const cardRefs = React10.useRef([]);
1173
+ const getIndexes = React10.useMemo(() => {
1136
1174
  let nextIndex = activeIndex + 1;
1137
1175
  let previousIndex = activeIndex - 1;
1138
1176
  if (activeIndex === 0) previousIndex = items.length - 1;
1139
1177
  if (activeIndex === items.length - 1) nextIndex = 0;
1140
1178
  return { previousIndex, nextIndex };
1141
1179
  }, [activeIndex, items.length]);
1142
- React9.useEffect(() => {
1180
+ React10.useEffect(() => {
1143
1181
  const { nextIndex, previousIndex } = getIndexes;
1144
1182
  let indexes = [previousIndex, activeIndex, nextIndex];
1145
1183
  if (activeIndex !== 0 && activeIndex !== items.length - 1) {
@@ -1228,7 +1266,12 @@ function MenuBarItem({ icon, isActive, title, onClick }) {
1228
1266
  className: `transition duration-300 hover:bg-prussian-blue ${isActive ? "bg-prussian-blue" : ""} rounded-lg p-2 cursor-pointer`,
1229
1267
  onClick,
1230
1268
  tabIndex: 0,
1231
- onKeyDown: (e) => e.key === "Enter" && onClick?.(),
1269
+ onKeyDown: (e) => {
1270
+ if (e.key === "Enter" || e.key === " ") {
1271
+ e.preventDefault();
1272
+ onClick?.();
1273
+ }
1274
+ },
1232
1275
  children: icon
1233
1276
  }
1234
1277
  ) });
@@ -1253,14 +1296,14 @@ function MenuBar({ items }) {
1253
1296
  );
1254
1297
  }
1255
1298
  function ContextMenu({ items, position, visible, onClose }) {
1256
- const contextRef = React9.useRef(null);
1257
- const childMenuRef = React9.useRef(null);
1258
- const [hasArrowUp, setHasArrowUp] = React9.useState(true);
1259
- const [childArrowUp, setChildArrowUp] = React9.useState(false);
1260
- const [hoveredItem, setHoveredItem] = React9.useState(-1);
1261
- const [hoveredChild, setHoveredChild] = React9.useState(-1);
1262
- const [activeChildren, setActiveChildren] = React9.useState([]);
1263
- React9.useEffect(() => {
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(() => {
1264
1307
  const clickAway = ({ target }) => {
1265
1308
  if (contextRef.current && !contextRef.current.contains(target)) {
1266
1309
  if (childMenuRef.current) {
@@ -1275,7 +1318,7 @@ function ContextMenu({ items, position, visible, onClose }) {
1275
1318
  window.addEventListener("click", clickAway);
1276
1319
  return () => window.removeEventListener("click", clickAway);
1277
1320
  }, [onClose]);
1278
- React9.useEffect(() => {
1321
+ React10.useEffect(() => {
1279
1322
  const current = contextRef.current;
1280
1323
  const child = childMenuRef.current;
1281
1324
  if (!current || !child) return;
@@ -1371,18 +1414,18 @@ function ContextMenu({ items, position, visible, onClose }) {
1371
1414
  );
1372
1415
  }
1373
1416
  function Wizard({ children, steps, storageKey = "po_wizard" }) {
1374
- const wizardRef = React9.useRef(null);
1375
- const [activeStep, setActiveStep] = React9.useState(0);
1376
- const [targetBbox, setTargetBbox] = React9.useState(null);
1377
- const HIGHLIGHTED = React9.useMemo(
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(
1378
1421
  () => ["border", "border-4", "border-prussian-blue", "pointer-events-none"],
1379
1422
  []
1380
1423
  );
1381
- const closeWizard = React9.useCallback(() => {
1424
+ const closeWizard = React10.useCallback(() => {
1382
1425
  steps[activeStep]?.stepRef.current?.classList.remove(...HIGHLIGHTED);
1383
1426
  if (wizardRef.current) wizardRef.current.style.display = "none";
1384
1427
  }, [HIGHLIGHTED, steps, activeStep]);
1385
- React9.useEffect(() => {
1428
+ React10.useEffect(() => {
1386
1429
  const visited = JSON.parse(localStorage.getItem(storageKey) ?? "false");
1387
1430
  if (visited) {
1388
1431
  closeWizard();
@@ -1436,7 +1479,7 @@ function Wizard({ children, steps, storageKey = "po_wizard" }) {
1436
1479
  children
1437
1480
  ] });
1438
1481
  }
1439
- var SearchInput = React9__default.default.forwardRef(function SearchInput2({
1482
+ var SearchInput = React10__default.default.forwardRef(function SearchInput2({
1440
1483
  value,
1441
1484
  onChange,
1442
1485
  disabled,
@@ -1463,7 +1506,8 @@ var SearchInput = React9__default.default.forwardRef(function SearchInput2({
1463
1506
  disabled,
1464
1507
  value,
1465
1508
  onChange,
1466
- type: "text",
1509
+ type: "search",
1510
+ enterKeyHint: "search",
1467
1511
  name,
1468
1512
  id: htmlFor,
1469
1513
  className: "focus:outline-none pl-2 h-9 w-56 outline-offset-2 text-prussian-blue mt-1 rounded-lg disabled:bg-disabled disabled:cursor-not-allowed",
@@ -1503,15 +1547,15 @@ function Dropdown({
1503
1547
  labelStyle = {},
1504
1548
  placeholder
1505
1549
  }) {
1506
- const [open, setOpen] = React9.useState(false);
1507
- const [selectedItems, setSelectedItems] = React9.useState([]);
1508
- const [hoveredItem, setHoveredItem] = React9.useState(null);
1509
- const [searchTerm, setSearchTerm] = React9.useState("");
1510
- const [innerItems, setInnerItems] = React9.useState([]);
1511
- React9.useEffect(() => {
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(() => {
1512
1556
  setInnerItems(items);
1513
1557
  }, [items]);
1514
- React9.useEffect(() => {
1558
+ React10.useEffect(() => {
1515
1559
  if (isMultiselect && Array.isArray(value)) {
1516
1560
  setSelectedItems(value);
1517
1561
  }
@@ -1684,14 +1728,14 @@ function TableBody({
1684
1728
  rows,
1685
1729
  expandRow
1686
1730
  }) {
1687
- const [visibleRows, setVisibleRows] = React9.useState({});
1731
+ const [visibleRows, setVisibleRows] = React10.useState({});
1688
1732
  const toggleRow = (rowKey) => {
1689
1733
  setVisibleRows((prev) => ({
1690
1734
  ...prev,
1691
1735
  [rowKey]: { visible: !prev[rowKey]?.visible }
1692
1736
  }));
1693
1737
  };
1694
- React9.useEffect(() => {
1738
+ React10.useEffect(() => {
1695
1739
  if (rows.length && Object.keys(visibleRows).length === 0) {
1696
1740
  const initial = {};
1697
1741
  rows.forEach((row) => {
@@ -1700,7 +1744,7 @@ function TableBody({
1700
1744
  setVisibleRows(initial);
1701
1745
  }
1702
1746
  }, [rows]);
1703
- return /* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "w-full", children: rows.map((row, i) => /* @__PURE__ */ jsxRuntime.jsxs(React9__default.default.Fragment, { children: [
1747
+ return /* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "w-full", children: rows.map((row, i) => /* @__PURE__ */ jsxRuntime.jsxs(React10__default.default.Fragment, { children: [
1704
1748
  /* @__PURE__ */ jsxRuntime.jsxs(
1705
1749
  "tr",
1706
1750
  {
@@ -1754,9 +1798,9 @@ function Pagination({
1754
1798
  const matchedOption = picker.find(
1755
1799
  (o) => o.label === options.perPage || o.value === options.perPage
1756
1800
  );
1757
- const [perPageKey, setPerPageKey] = React9.useState(() => matchedOption?.key ?? picker[0]?.key);
1801
+ const [perPageKey, setPerPageKey] = React10.useState(() => matchedOption?.key ?? picker[0]?.key);
1758
1802
  const displayPerPageKey = serverSide ? matchedOption?.key ?? perPageKey : perPageKey;
1759
- React9.useEffect(() => {
1803
+ React10.useEffect(() => {
1760
1804
  if (serverSide && options.perPage != null) {
1761
1805
  const next = picker.find((o) => o.label === options.perPage || o.value === options.perPage);
1762
1806
  if (next) setPerPageKey(next.key);
@@ -1816,35 +1860,35 @@ function Table({
1816
1860
  footer = null,
1817
1861
  header = null
1818
1862
  }) {
1819
- const searchRef = React9.useRef(null);
1820
- const [searchTerm, setSearchTerm] = React9.useState("");
1821
- const [perPage, setPerPage] = React9.useState(
1863
+ const searchRef = React10.useRef(null);
1864
+ const [searchTerm, setSearchTerm] = React10.useState("");
1865
+ const [perPage, setPerPage] = React10.useState(
1822
1866
  typeof pagination.perPage === "number" ? pagination.perPage : 15
1823
1867
  );
1824
- const [activePage, setActivePage] = React9.useState(0);
1825
- const [datasets, setDatasets] = React9.useState([]);
1868
+ const [activePage, setActivePage] = React10.useState(0);
1869
+ const [datasets, setDatasets] = React10.useState([]);
1826
1870
  const isServerSide = !!(pagination.enabled && pagination.serverSide);
1827
- const MAX_PAGE = React9.useMemo(() => {
1871
+ const MAX_PAGE = React10.useMemo(() => {
1828
1872
  if (isServerSide && typeof pagination.maxPage === "number") return Math.max(0, pagination.maxPage);
1829
1873
  if (isServerSide && typeof pagination.totalCount === "number")
1830
1874
  return Math.max(0, Math.ceil(pagination.totalCount / perPage) - 1);
1831
1875
  return datasets.length ? datasets.length - 1 : 0;
1832
1876
  }, [isServerSide, pagination.maxPage, pagination.totalCount, perPage, datasets.length]);
1833
- const currentPageRows = React9.useMemo(() => {
1877
+ const currentPageRows = React10.useMemo(() => {
1834
1878
  if (isServerSide) return rows;
1835
1879
  return datasets.length ? datasets[activePage] ?? [] : [];
1836
1880
  }, [isServerSide, rows, datasets, activePage]);
1837
- React9.useEffect(() => {
1881
+ React10.useEffect(() => {
1838
1882
  if (pagination.enabled && !isServerSide) setPerPage(pagination.perPage ?? 15);
1839
1883
  }, [pagination, isServerSide]);
1840
- React9.useEffect(() => {
1884
+ React10.useEffect(() => {
1841
1885
  if (isServerSide && typeof pagination.perPage === "number") setPerPage(pagination.perPage);
1842
1886
  }, [isServerSide, pagination.perPage]);
1843
- React9.useEffect(() => {
1887
+ React10.useEffect(() => {
1844
1888
  if (isServerSide) return;
1845
1889
  setDatasets(createDatasets(rows, pagination.enabled ? perPage : null));
1846
1890
  }, [rows, perPage, pagination, isServerSide]);
1847
- React9.useEffect(() => {
1891
+ React10.useEffect(() => {
1848
1892
  if (isServerSide && typeof pagination.page === "number" && pagination.page >= 1)
1849
1893
  setActivePage(pagination.page - 1);
1850
1894
  }, [isServerSide, pagination.page]);
@@ -1904,7 +1948,7 @@ function Table({
1904
1948
  ] });
1905
1949
  }
1906
1950
  function ThemeSwitch({ checked, onChange, label = "Toggle dark mode" }) {
1907
- const id = React9.useId();
1951
+ const id = React10.useId();
1908
1952
  return /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, className: "flex items-center gap-2 cursor-pointer select-none", children: /* @__PURE__ */ jsxRuntime.jsx(
1909
1953
  SwitchPrimitive__namespace.Root,
1910
1954
  {
@@ -2097,17 +2141,17 @@ function AppShell({
2097
2141
  children,
2098
2142
  className = ""
2099
2143
  }) {
2100
- const [expanded, setExpanded] = React9.useState(sidebarDefaultExpanded);
2101
- const [isMobile, setIsMobile] = React9.useState(false);
2102
- const [mobileOpen, setMobileOpen] = React9.useState(false);
2103
- React9.useEffect(() => {
2144
+ const [expanded, setExpanded] = React10.useState(sidebarDefaultExpanded);
2145
+ const [isMobile, setIsMobile] = React10.useState(false);
2146
+ const [mobileOpen, setMobileOpen] = React10.useState(false);
2147
+ React10.useEffect(() => {
2104
2148
  const mq = window.matchMedia("(max-width: 767px)");
2105
2149
  const update = (e) => setIsMobile(e.matches);
2106
2150
  update(mq);
2107
2151
  mq.addEventListener("change", update);
2108
2152
  return () => mq.removeEventListener("change", update);
2109
2153
  }, []);
2110
- React9.useEffect(() => {
2154
+ React10.useEffect(() => {
2111
2155
  if (!isMobile) setMobileOpen(false);
2112
2156
  }, [isMobile]);
2113
2157
  const hasSidebar = sidebarSections.length > 0;
@@ -2150,7 +2194,7 @@ function AppShell({
2150
2194
  footer: sidebarFooter
2151
2195
  }
2152
2196
  ),
2153
- hasSidebar && isMobile && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2197
+ hasSidebar && isMobile && /* @__PURE__ */ jsxRuntime.jsxs(Portal, { children: [
2154
2198
  /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: mobileOpen && /* @__PURE__ */ jsxRuntime.jsx(
2155
2199
  framerMotion.motion.div,
2156
2200
  {
@@ -2281,10 +2325,10 @@ function ThemeProvider({
2281
2325
  className = "",
2282
2326
  style
2283
2327
  }) {
2284
- const id = React9__default.default.useId().replace(/:/g, "");
2328
+ const id = React10__default.default.useId().replace(/:/g, "");
2285
2329
  const scopeClass = `geo-th-${id}`;
2286
- const divRef = React9.useRef(null);
2287
- React9.useEffect(() => {
2330
+ const divRef = React10.useRef(null);
2331
+ React10.useEffect(() => {
2288
2332
  const el = divRef.current;
2289
2333
  if (!el) return;
2290
2334
  if (colorScheme === "auto") return;
@@ -2299,8 +2343,8 @@ function ThemeProvider({
2299
2343
  }
2300
2344
  el.classList.toggle("dark", colorScheme === "dark");
2301
2345
  }, [colorScheme]);
2302
- const lightVars = React9.useMemo(() => toCssVars(theme), [theme]);
2303
- const darkVarStr = React9.useMemo(() => {
2346
+ const lightVars = React10.useMemo(() => toCssVars(theme), [theme]);
2347
+ const darkVarStr = React10.useMemo(() => {
2304
2348
  if (!darkTheme) return "";
2305
2349
  const dvars = toCssVars(darkTheme);
2306
2350
  if (!Object.keys(dvars).length) return "";
@@ -2434,6 +2478,9 @@ function TextInput({
2434
2478
  className: `flex ${layout === "vertical" ? "flex-col" : "flex-row items-center gap-2"}`,
2435
2479
  style: style ?? {},
2436
2480
  children: [
2481
+ label && // Render <label> only when a label is provided. An empty
2482
+ // <label htmlFor=…> announces as an unlabeled control in
2483
+ // some screen readers.
2437
2484
  /* @__PURE__ */ jsxRuntime.jsx(
2438
2485
  "label",
2439
2486
  {
@@ -2576,10 +2623,13 @@ function Password({
2576
2623
  labelColor,
2577
2624
  iconColor
2578
2625
  }) {
2579
- const [passwordVisible, setPasswordVisible] = React9.useState(false);
2626
+ const [passwordVisible, setPasswordVisible] = React10.useState(false);
2580
2627
  const color = iconColor ?? chunk255PCZIW_cjs.colors_default.PALETTE["prussian-blue"];
2581
2628
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex flex-col items-center justify-center", style: style ?? {}, children: [
2582
2629
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex ${layout === "vertical" ? "flex-col" : "flex-row items-center gap-2"}`, children: [
2630
+ label && // Render <label> only when a label is provided. An empty
2631
+ // <label htmlFor=…> announces as an unlabeled control in
2632
+ // some screen readers.
2583
2633
  /* @__PURE__ */ jsxRuntime.jsx(
2584
2634
  "label",
2585
2635
  {
@@ -2719,7 +2769,7 @@ function Switch({
2719
2769
  checkedIcon,
2720
2770
  uncheckedIcon
2721
2771
  }) {
2722
- const id = React9.useId();
2772
+ const id = React10.useId();
2723
2773
  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(
2724
2774
  SwitchPrimitive__namespace.Root,
2725
2775
  {
@@ -2749,8 +2799,8 @@ function AutoComplete({
2749
2799
  onItemClick,
2750
2800
  emptyText = "No results found"
2751
2801
  }) {
2752
- const [term, setTerm] = React9.useState("");
2753
- const [open, setOpen] = React9.useState(false);
2802
+ const [term, setTerm] = React10.useState("");
2803
+ const [open, setOpen] = React10.useState(false);
2754
2804
  const foundItems = term.trim() ? items.filter(
2755
2805
  ({ key, label: label2 }) => label2.toLowerCase().includes(term.toLowerCase()) || key.toLowerCase().includes(term.toLowerCase())
2756
2806
  ) : [];
@@ -2835,10 +2885,10 @@ function TreeSelect({
2835
2885
  htmlFor,
2836
2886
  items = []
2837
2887
  }) {
2838
- const [open, setOpen] = React9.useState(false);
2839
- const [hoveredItem, setHoveredItem] = React9.useState(null);
2840
- const [innerItems, setInnerItems] = React9.useState([]);
2841
- React9.useEffect(() => {
2888
+ const [open, setOpen] = React10.useState(false);
2889
+ const [hoveredItem, setHoveredItem] = React10.useState(null);
2890
+ const [innerItems, setInnerItems] = React10.useState([]);
2891
+ React10.useEffect(() => {
2842
2892
  setInnerItems(items);
2843
2893
  }, [items]);
2844
2894
  const selectItem = (key) => {
@@ -2937,10 +2987,10 @@ function FileInput({
2937
2987
  name,
2938
2988
  accept = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,.xlsx"
2939
2989
  }) {
2940
- const fileInput = React9.useRef(null);
2941
- const [files, setFiles] = React9.useState([]);
2990
+ const fileInput = React10.useRef(null);
2991
+ const [files, setFiles] = React10.useState([]);
2942
2992
  const openPicker = () => {
2943
- fileInput.current?.dispatchEvent(new MouseEvent("click", { bubbles: false }));
2993
+ fileInput.current?.click();
2944
2994
  };
2945
2995
  const handleFiles = (list) => {
2946
2996
  setFiles(list);
@@ -2972,56 +3022,70 @@ function FileInput({
2972
3022
  onChange?.({ target: { files: [], name, id: name, value: "" } });
2973
3023
  if (fileInput.current) fileInput.current.value = "";
2974
3024
  };
2975
- return /* @__PURE__ */ jsxRuntime.jsxs(
2976
- "div",
2977
- {
2978
- onClick: openPicker,
2979
- className: "border-2 hover:border-prussian-blue border-ice-dark w-full h-full rounded-md transition-all duration-300 border-dashed dark:border-independence hover:dark:border-ice-dark cursor-pointer",
2980
- onDragOver: (e) => e.preventDefault(),
2981
- onDrop,
2982
- children: [
2983
- /* @__PURE__ */ jsxRuntime.jsx(
2984
- "input",
2985
- {
2986
- id: name,
2987
- name,
2988
- onChange: localOnChange,
2989
- ref: fileInput,
2990
- hidden: true,
2991
- type: "file",
2992
- accept,
2993
- multiple: allowMultiple
3025
+ return (
3026
+ // Dropzone is keyboard-activatable: role="button", focusable via
3027
+ // tabIndex, and Space/Enter trigger the file picker. Without these
3028
+ // a keyboard-only user could not upload a file.
3029
+ /* @__PURE__ */ jsxRuntime.jsxs(
3030
+ "div",
3031
+ {
3032
+ role: "button",
3033
+ tabIndex: 0,
3034
+ "aria-label": "Upload file \u2014 click or drop",
3035
+ onClick: openPicker,
3036
+ onKeyDown: (e) => {
3037
+ if (e.key === "Enter" || e.key === " ") {
3038
+ e.preventDefault();
3039
+ openPicker();
2994
3040
  }
2995
- ),
2996
- files.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col h-full items-center justify-center gap-2", children: [
2997
- /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: chunk255PCZIW_cjs.colors_default.PALETTE["prussian-blue"], className: "w-16 h-16 dark:fill-white", children: /* @__PURE__ */ jsxRuntime.jsx("path", { fillRule: "evenodd", d: "M11.47 2.47a.75.75 0 011.06 0l4.5 4.5a.75.75 0 01-1.06 1.06l-3.22-3.22V16.5a.75.75 0 01-1.5 0V4.81L8.03 8.03a.75.75 0 01-1.06-1.06l4.5-4.5zM3 15.75a.75.75 0 01.75.75v2.25a1.5 1.5 0 001.5 1.5h13.5a1.5 1.5 0 001.5-1.5V16.5a.75.75 0 011.5 0v2.25a3 3 0 01-3 3H5.25a3 3 0 01-3-3V16.5a.75.75 0 01.75-.75z", clipRule: "evenodd" }) }),
2998
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-prussian-blue dark:text-white text-sm", children: "Click or Drop a file" })
2999
- ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-3 items-center justify-center w-full h-full", children: files.map((file, id) => /* @__PURE__ */ jsxRuntime.jsxs(
3000
- "div",
3001
- {
3002
- className: "text-xs flex flex-col items-center w-20 h-24 text-center bg-ice-dark p-4 dark:bg-independence rounded-md relative",
3003
- children: [
3004
- /* @__PURE__ */ jsxRuntime.jsx(
3005
- "button",
3006
- {
3007
- type: "button",
3008
- onClick: removeFile,
3009
- className: "bg-error rounded-full w-4 h-4 absolute right-[-5px] top-[-5px] cursor-pointer flex items-center justify-center",
3010
- "aria-label": "Remove file",
3011
- children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "10", height: "10", viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15 5L5 15M5 5l10 10", stroke: "#fff", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })
3012
- }
3013
- ),
3014
- /* @__PURE__ */ jsxRuntime.jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: chunk255PCZIW_cjs.colors_default.PALETTE["prussian-blue"], className: "w-10 h-10 dark:fill-white", children: [
3015
- /* @__PURE__ */ jsxRuntime.jsx("path", { fillRule: "evenodd", d: "M5.625 1.5c-1.036 0-1.875.84-1.875 1.875v17.25c0 1.035.84 1.875 1.875 1.875h12.75c1.035 0 1.875-.84 1.875-1.875V12.75A3.75 3.75 0 0016.5 9h-1.875a1.875 1.875 0 01-1.875-1.875V5.25A3.75 3.75 0 009 1.5H5.625z", clipRule: "evenodd" }),
3016
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12.971 1.816A5.23 5.23 0 0114.25 5.25v1.875c0 .207.168.375.375.375H16.5a5.23 5.23 0 013.434 1.279 9.768 9.768 0 00-6.963-6.963z" })
3017
- ] }),
3018
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ellipsis whitespace-nowrap overflow-hidden w-full text-prussian-blue dark:text-white", children: file.name })
3019
- ]
3020
- },
3021
- `${id}${file.name}`
3022
- )) })
3023
- ]
3024
- }
3041
+ },
3042
+ className: "border-2 hover:border-prussian-blue border-ice-dark w-full h-full rounded-md transition-all duration-300 border-dashed dark:border-independence hover:dark:border-ice-dark cursor-pointer focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
3043
+ onDragOver: (e) => e.preventDefault(),
3044
+ onDrop,
3045
+ children: [
3046
+ /* @__PURE__ */ jsxRuntime.jsx(
3047
+ "input",
3048
+ {
3049
+ id: name,
3050
+ name,
3051
+ onChange: localOnChange,
3052
+ ref: fileInput,
3053
+ hidden: true,
3054
+ type: "file",
3055
+ accept,
3056
+ multiple: allowMultiple
3057
+ }
3058
+ ),
3059
+ files.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col h-full items-center justify-center gap-2", children: [
3060
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: chunk255PCZIW_cjs.colors_default.PALETTE["prussian-blue"], className: "w-16 h-16 dark:fill-white", children: /* @__PURE__ */ jsxRuntime.jsx("path", { fillRule: "evenodd", d: "M11.47 2.47a.75.75 0 011.06 0l4.5 4.5a.75.75 0 01-1.06 1.06l-3.22-3.22V16.5a.75.75 0 01-1.5 0V4.81L8.03 8.03a.75.75 0 01-1.06-1.06l4.5-4.5zM3 15.75a.75.75 0 01.75.75v2.25a1.5 1.5 0 001.5 1.5h13.5a1.5 1.5 0 001.5-1.5V16.5a.75.75 0 011.5 0v2.25a3 3 0 01-3 3H5.25a3 3 0 01-3-3V16.5a.75.75 0 01.75-.75z", clipRule: "evenodd" }) }),
3061
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-prussian-blue dark:text-white text-sm", children: "Click or Drop a file" })
3062
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-3 items-center justify-center w-full h-full", children: files.map((file, id) => /* @__PURE__ */ jsxRuntime.jsxs(
3063
+ "div",
3064
+ {
3065
+ className: "text-xs flex flex-col items-center w-20 h-24 text-center bg-ice-dark p-4 dark:bg-independence rounded-md relative",
3066
+ children: [
3067
+ /* @__PURE__ */ jsxRuntime.jsx(
3068
+ "button",
3069
+ {
3070
+ type: "button",
3071
+ onClick: removeFile,
3072
+ className: "bg-error rounded-full w-4 h-4 absolute right-[-5px] top-[-5px] cursor-pointer flex items-center justify-center",
3073
+ "aria-label": "Remove file",
3074
+ children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "10", height: "10", viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15 5L5 15M5 5l10 10", stroke: "#fff", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })
3075
+ }
3076
+ ),
3077
+ /* @__PURE__ */ jsxRuntime.jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: chunk255PCZIW_cjs.colors_default.PALETTE["prussian-blue"], className: "w-10 h-10 dark:fill-white", children: [
3078
+ /* @__PURE__ */ jsxRuntime.jsx("path", { fillRule: "evenodd", d: "M5.625 1.5c-1.036 0-1.875.84-1.875 1.875v17.25c0 1.035.84 1.875 1.875 1.875h12.75c1.035 0 1.875-.84 1.875-1.875V12.75A3.75 3.75 0 0016.5 9h-1.875a1.875 1.875 0 01-1.875-1.875V5.25A3.75 3.75 0 009 1.5H5.625z", clipRule: "evenodd" }),
3079
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12.971 1.816A5.23 5.23 0 0114.25 5.25v1.875c0 .207.168.375.375.375H16.5a5.23 5.23 0 013.434 1.279 9.768 9.768 0 00-6.963-6.963z" })
3080
+ ] }),
3081
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ellipsis whitespace-nowrap overflow-hidden w-full text-prussian-blue dark:text-white", children: file.name })
3082
+ ]
3083
+ },
3084
+ `${id}${file.name}`
3085
+ )) })
3086
+ ]
3087
+ }
3088
+ )
3025
3089
  );
3026
3090
  }
3027
3091
  var MONTHS = {
@@ -3072,12 +3136,12 @@ function DatePickerBase({
3072
3136
  disableAfter,
3073
3137
  disabled
3074
3138
  }) {
3075
- const pickerRef = React9.useRef(null);
3076
- const calendarRef = React9.useRef(null);
3077
- const [isExpanded, setExpanded] = React9.useState(false);
3078
- const [isCloseToBottom, setCloseToBottom] = React9.useState(false);
3079
- const [currentYear, setCurrentYear] = React9.useState(value.getFullYear());
3080
- const [currentMonth, setCurrentMonth] = React9.useState(value.getMonth() + 1);
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);
3081
3145
  const toggle = () => {
3082
3146
  if (!disabled) setExpanded((p) => !p);
3083
3147
  };
@@ -3121,14 +3185,14 @@ function DatePickerBase({
3121
3185
  }
3122
3186
  return ordered;
3123
3187
  };
3124
- React9.useEffect(() => {
3188
+ React10.useEffect(() => {
3125
3189
  const clickAway = (e) => {
3126
3190
  if (pickerRef.current && !pickerRef.current.contains(e.target) && calendarRef.current && !calendarRef.current.contains(e.target)) setExpanded(false);
3127
3191
  };
3128
3192
  document.addEventListener("mousedown", clickAway);
3129
3193
  return () => document.removeEventListener("mousedown", clickAway);
3130
3194
  }, []);
3131
- React9.useEffect(() => {
3195
+ React10.useEffect(() => {
3132
3196
  const bbox = pickerRef.current?.getBoundingClientRect();
3133
3197
  if (bbox && (bbox.y > window.innerHeight - 220 || bbox.bottom > window.innerHeight - 400)) {
3134
3198
  setCloseToBottom(true);
@@ -3221,29 +3285,29 @@ function TemporalPickerBase({
3221
3285
  layout,
3222
3286
  style = {}
3223
3287
  }) {
3224
- const pickerRef = React9.useRef(null);
3225
- const calendarRef = React9.useRef(null);
3226
- const valueRefs = React9.useRef([]);
3227
- const [isExpanded, setExpanded] = React9.useState(false);
3228
- const [isCloseToBottom, setCloseToBottom] = React9.useState(false);
3229
- const innerValues = React9.useMemo(() => {
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(() => {
3230
3294
  const vals = [];
3231
3295
  for (let i = lowerLimit; i <= upperLimit; i++) vals.push(i);
3232
3296
  return vals;
3233
3297
  }, [lowerLimit, upperLimit]);
3234
- React9.useEffect(() => {
3298
+ React10.useEffect(() => {
3235
3299
  const clickAway = (e) => {
3236
3300
  if (pickerRef.current && !pickerRef.current.contains(e.target) && calendarRef.current && !calendarRef.current.contains(e.target)) setExpanded(false);
3237
3301
  };
3238
3302
  document.addEventListener("mousedown", clickAway);
3239
3303
  return () => document.removeEventListener("mousedown", clickAway);
3240
3304
  }, []);
3241
- React9.useEffect(() => {
3305
+ React10.useEffect(() => {
3242
3306
  const bbox = pickerRef.current?.getBoundingClientRect();
3243
3307
  if (bbox && bbox.y > window.innerHeight - 220) setCloseToBottom(true);
3244
3308
  else setCloseToBottom(false);
3245
3309
  }, []);
3246
- React9.useEffect(() => {
3310
+ React10.useEffect(() => {
3247
3311
  if (!isExpanded) return;
3248
3312
  const t = setTimeout(() => {
3249
3313
  const node = valueRefs.current.find((n) => n.value === value);
@@ -3354,6 +3418,7 @@ exports.NotificationProvider = NotificationProvider;
3354
3418
  exports.NumberInput = NumberInput;
3355
3419
  exports.OpaqueGridCard = OpaqueGridCard;
3356
3420
  exports.Password = Password;
3421
+ exports.Portal = Portal;
3357
3422
  exports.ScalableContainer = ScalableContainer;
3358
3423
  exports.SearchInput = SearchInput_default;
3359
3424
  exports.Sidebar = Sidebar;