@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.js CHANGED
@@ -1,7 +1,8 @@
1
1
  import { colors_default } from './chunk-GKXP6OJJ.js';
2
2
  export { colors_default as COLORS, PALETTE as palette, semanticTokens, vars } from './chunk-GKXP6OJJ.js';
3
3
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
- import React9, { createContext, useMemo, useState, useEffect, useContext, useRef, useCallback, useId } from 'react';
4
+ import React10, { createContext, useState, useEffect, useMemo, useContext, useRef, useCallback, useId } from 'react';
5
+ import { createPortal } from 'react-dom';
5
6
  import * as Dialog from '@radix-ui/react-dialog';
6
7
  import { useReducedMotion, AnimatePresence, motion } from 'framer-motion';
7
8
  import * as TooltipPrimitive from '@radix-ui/react-tooltip';
@@ -172,6 +173,18 @@ Icon.Save = Save;
172
173
  Icon.Copy = Copy;
173
174
  Icon.CircleStack = CircleStack;
174
175
  var icons_default = Icon;
176
+ function Portal({ children, target }) {
177
+ const [resolved, setResolved] = useState(null);
178
+ useEffect(() => {
179
+ if (target === null) {
180
+ setResolved(null);
181
+ return;
182
+ }
183
+ const node = typeof target === "function" ? target() : target ?? document.body;
184
+ setResolved(node ?? null);
185
+ }, [target]);
186
+ return resolved ? createPortal(children, resolved) : null;
187
+ }
175
188
  function IconButton({
176
189
  icon,
177
190
  onClick,
@@ -287,7 +300,8 @@ function Button({
287
300
  );
288
301
  }
289
302
  function Modal({
290
- size = [600, 400],
303
+ width,
304
+ size,
291
305
  isOpen = false,
292
306
  onClose,
293
307
  onOk,
@@ -299,6 +313,7 @@ function Modal({
299
313
  children
300
314
  }) {
301
315
  const reduced = useReducedMotion();
316
+ const maxWidth = width ?? size?.[0] ?? 600;
302
317
  return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, onOpenChange: (open) => {
303
318
  if (!open) onClose?.();
304
319
  }, children: /* @__PURE__ */ jsxs(Dialog.Portal, { forceMount: true, children: [
@@ -317,7 +332,7 @@ function Modal({
317
332
  {
318
333
  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",
319
334
  style: {
320
- maxWidth: size[0],
335
+ maxWidth,
321
336
  x: "-50%",
322
337
  y: "-50%"
323
338
  },
@@ -342,7 +357,7 @@ function Modal({
342
357
  }
343
358
  ) })
344
359
  ] }),
345
- /* @__PURE__ */ jsx("div", { className: `flex-1 overflow-y-auto p-5 ${hasFooter ? "" : "pb-5"}`, children: isOpen && children }),
360
+ /* @__PURE__ */ jsx("div", { className: `flex-1 overflow-y-auto p-5 ${hasFooter ? "" : "pb-5"}`, children }),
346
361
  hasFooter && /* @__PURE__ */ jsxs("div", { className: "flex flex-shrink-0 items-center justify-end gap-3 border-t border-border px-5 py-3", children: [
347
362
  /* @__PURE__ */ jsx(
348
363
  Button,
@@ -424,7 +439,7 @@ function Drawer({
424
439
  }
425
440
  ) })
426
441
  ] }),
427
- /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto p-5", children: isOpen && children }),
442
+ /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto p-5", children }),
428
443
  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: [
429
444
  /* @__PURE__ */ jsx(Button, { style: { width: 90 }, content: cancelText, onClick: onCancel }),
430
445
  /* @__PURE__ */ jsx(Button, { style: { width: 90 }, content: okText, onClick: onOk })
@@ -543,29 +558,46 @@ function Tabs({
543
558
  {
544
559
  "aria-label": "Tabs",
545
560
  className: "flex-1 flex items-center gap-1 overflow-x-auto overflow-y-hidden rounded-lg scroll-smooth snap-x snap-mandatory hidden-scrollbar",
546
- children: tabs.map((tab) => /* @__PURE__ */ jsxs(
547
- TabsPrimitive.Trigger,
548
- {
549
- value: tab.key,
550
- 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",
551
- children: [
552
- /* @__PURE__ */ jsx("span", { className: "truncate text-sm", children: tab.title }),
553
- tabsClosable && /* @__PURE__ */ jsx(
554
- "span",
555
- {
556
- role: "button",
557
- "aria-label": `Close ${tab.title}`,
558
- onClick: (e) => {
559
- e.stopPropagation();
560
- onTabClose?.(tab.key);
561
- },
562
- className: "flex-shrink-0 rounded hover:bg-black/10 p-0.5 transition-colors",
563
- children: /* @__PURE__ */ jsx("svg", { width: "14", height: "14", viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M15 5L5 15M5 5l10 10", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
564
- }
565
- )
566
- ]
567
- },
568
- tab.key
561
+ children: tabs.map((tab) => (
562
+ // Trigger + close button are SIBLINGS, not nested.
563
+ // Nesting a clickable element inside <button> is invalid
564
+ // HTML and breaks keyboard activation of the inner one.
565
+ // The wrapper carries `group` so the close button can
566
+ // react to the trigger's `data-state=active` for styling.
567
+ /* @__PURE__ */ jsxs(
568
+ "div",
569
+ {
570
+ className: "snap-start snap-always relative flex items-center flex-1 min-w-[120px] max-w-[220px] flex-shrink-0 group",
571
+ children: [
572
+ /* @__PURE__ */ jsx(
573
+ TabsPrimitive.Trigger,
574
+ {
575
+ value: tab.key,
576
+ 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
577
+ text-foreground-secondary bg-surface-raised
578
+ hover:bg-surface hover:text-foreground
579
+ data-[state=active]:bg-accent data-[state=active]:text-accent-foreground
580
+ focus:outline-none focus-visible:ring-2 focus-visible:ring-accent`,
581
+ children: /* @__PURE__ */ jsx("span", { className: "truncate text-sm block", children: tab.title })
582
+ }
583
+ ),
584
+ tabsClosable && /* @__PURE__ */ jsx(
585
+ "button",
586
+ {
587
+ type: "button",
588
+ "aria-label": `Close ${tab.title}`,
589
+ onClick: (e) => {
590
+ e.stopPropagation();
591
+ onTabClose?.(tab.key);
592
+ },
593
+ 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",
594
+ children: /* @__PURE__ */ jsx("svg", { width: "14", height: "14", viewBox: "0 0 20 20", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M15 5L5 15M5 5l10 10", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
595
+ }
596
+ )
597
+ ]
598
+ },
599
+ tab.key
600
+ )
569
601
  ))
570
602
  }
571
603
  ),
@@ -628,40 +660,41 @@ function TreeNodeItem({
628
660
  defaultValue: initialOpen,
629
661
  style: { paddingLeft: depth * 12 },
630
662
  children: /* @__PURE__ */ jsxs(Accordion.Item, { value: item.key, className: "border-none", children: [
631
- /* @__PURE__ */ jsxs(Accordion.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: [
632
- /* @__PURE__ */ jsx(
633
- "svg",
634
- {
635
- viewBox: "0 0 24 24",
636
- fill: "none",
637
- stroke: "currentColor",
638
- strokeWidth: 2.5,
639
- 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",
640
- children: /* @__PURE__ */ jsx(
641
- "path",
663
+ /* @__PURE__ */ jsxs(
664
+ Accordion.Trigger,
665
+ {
666
+ onClick: () => onNodeClick({
667
+ isParent: true,
668
+ key: item.key,
669
+ label: item.label,
670
+ data: item.nodeData,
671
+ parentLabel: item.parentLabel
672
+ }),
673
+ 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",
674
+ children: [
675
+ /* @__PURE__ */ jsx(
676
+ "svg",
642
677
  {
643
- strokeLinecap: "round",
644
- strokeLinejoin: "round",
645
- d: "M19 9l-7 7-7-7"
678
+ viewBox: "0 0 24 24",
679
+ fill: "none",
680
+ stroke: "currentColor",
681
+ strokeWidth: 2.5,
682
+ 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",
683
+ "aria-hidden": "true",
684
+ children: /* @__PURE__ */ jsx(
685
+ "path",
686
+ {
687
+ strokeLinecap: "round",
688
+ strokeLinejoin: "round",
689
+ d: "M19 9l-7 7-7-7"
690
+ }
691
+ )
646
692
  }
647
- )
648
- }
649
- ),
650
- /* @__PURE__ */ jsx(
651
- "span",
652
- {
653
- className: "text-sm font-semibold text-foreground select-none",
654
- onClick: () => onNodeClick({
655
- isParent: true,
656
- key: item.key,
657
- label: item.label,
658
- data: item.nodeData,
659
- parentLabel: item.parentLabel
660
- }),
661
- children: item.label
662
- }
663
- )
664
- ] }),
693
+ ),
694
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-foreground select-none", children: item.label })
695
+ ]
696
+ }
697
+ ),
665
698
  /* @__PURE__ */ jsx(Accordion.Content, { className: "overflow-hidden data-[state=open]:animate-accordion-down data-[state=closed]:animate-accordion-up", children: /* @__PURE__ */ jsx("div", { className: "ml-3.5 border-l border-border py-0.5", children: item.children.map((child) => /* @__PURE__ */ jsx(
666
699
  TreeNodeItem,
667
700
  {
@@ -735,9 +768,9 @@ var TYPE_BG = {
735
768
  danger: "bg-status-error"
736
769
  };
737
770
  var VIEWPORT_CLASSES = {
738
- "top-right": "fixed top-14 right-4 flex flex-col items-end",
739
- "top-left": "fixed top-14 left-4 flex flex-col items-start",
740
- "top-center": "fixed top-14 left-1/2 flex flex-col items-center -translate-x-1/2",
771
+ "top-right": "fixed top-4 right-4 flex flex-col items-end",
772
+ "top-left": "fixed top-4 left-4 flex flex-col items-start",
773
+ "top-center": "fixed top-4 left-1/2 flex flex-col items-center -translate-x-1/2",
741
774
  "bottom-right": "fixed bottom-4 right-4 flex flex-col-reverse items-end",
742
775
  "bottom-left": "fixed bottom-4 left-4 flex flex-col-reverse items-start",
743
776
  "bottom-center": "fixed bottom-4 left-1/2 flex flex-col-reverse items-center -translate-x-1/2"
@@ -790,6 +823,7 @@ function NotificationItem({
790
823
  return /* @__PURE__ */ jsx(
791
824
  motion.div,
792
825
  {
826
+ className: "pointer-events-auto",
793
827
  initial,
794
828
  animate: { opacity: 1, y: 0, scale: 1 },
795
829
  exit: {
@@ -875,13 +909,13 @@ function NotificationProvider({
875
909
  };
876
910
  return /* @__PURE__ */ jsx(NotificationContext.Provider, { value: { open, close }, children: /* @__PURE__ */ jsxs(Toast.Provider, { swipeDirection: position.endsWith("right") ? "right" : position.endsWith("left") ? "left" : "up", children: [
877
911
  children,
878
- /* @__PURE__ */ jsx(
912
+ /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(
879
913
  Toast.Viewport,
880
914
  {
881
915
  asChild: true,
882
916
  className: [
883
917
  VIEWPORT_CLASSES[position],
884
- "z-[500000] gap-2 w-[340px] p-4 outline-none overflow-hidden"
918
+ "z-[500000] gap-2 w-[332px] outline-none pointer-events-none"
885
919
  ].join(" "),
886
920
  children: /* @__PURE__ */ jsx("ul", { children: /* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: notifications.map((n) => /* @__PURE__ */ jsx(
887
921
  NotificationItem,
@@ -894,7 +928,7 @@ function NotificationProvider({
894
928
  n.id
895
929
  )) }) })
896
930
  }
897
- )
931
+ ) })
898
932
  ] }) });
899
933
  }
900
934
  function useNotification() {
@@ -921,20 +955,24 @@ function LoadingSpinner({ prompt }) {
921
955
  }
922
956
  return () => timeouts.forEach(clearTimeout);
923
957
  }, [letterRefs, letters.length]);
924
- return /* @__PURE__ */ 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: [
925
- /* @__PURE__ */ 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" }),
926
- /* @__PURE__ */ jsx("div", { className: "text-prussian-blue dark:text-white text-3xl font-bold", children: letters.map((letter, index) => /* @__PURE__ */ jsx(
927
- "span",
928
- {
929
- className: "select-none",
930
- ref: (ref) => {
931
- letterRefs[index] = ref;
958
+ return (
959
+ // Portaled so the full-screen overlay always covers the real viewport,
960
+ // not whatever container the consumer renders LoadingSpinner inside.
961
+ /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ 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: [
962
+ /* @__PURE__ */ 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" }),
963
+ /* @__PURE__ */ jsx("div", { className: "text-prussian-blue dark:text-white text-3xl font-bold", children: letters.map((letter, index) => /* @__PURE__ */ jsx(
964
+ "span",
965
+ {
966
+ className: "select-none",
967
+ ref: (ref) => {
968
+ letterRefs[index] = ref;
969
+ },
970
+ children: letter
932
971
  },
933
- children: letter
934
- },
935
- index
936
- )) })
937
- ] });
972
+ index
973
+ )) })
974
+ ] }) })
975
+ );
938
976
  }
939
977
  function FadingBase({
940
978
  className = "",
@@ -1196,7 +1234,12 @@ function MenuBarItem({ icon, isActive, title, onClick }) {
1196
1234
  className: `transition duration-300 hover:bg-prussian-blue ${isActive ? "bg-prussian-blue" : ""} rounded-lg p-2 cursor-pointer`,
1197
1235
  onClick,
1198
1236
  tabIndex: 0,
1199
- onKeyDown: (e) => e.key === "Enter" && onClick?.(),
1237
+ onKeyDown: (e) => {
1238
+ if (e.key === "Enter" || e.key === " ") {
1239
+ e.preventDefault();
1240
+ onClick?.();
1241
+ }
1242
+ },
1200
1243
  children: icon
1201
1244
  }
1202
1245
  ) });
@@ -1404,7 +1447,7 @@ function Wizard({ children, steps, storageKey = "po_wizard" }) {
1404
1447
  children
1405
1448
  ] });
1406
1449
  }
1407
- var SearchInput = React9.forwardRef(function SearchInput2({
1450
+ var SearchInput = React10.forwardRef(function SearchInput2({
1408
1451
  value,
1409
1452
  onChange,
1410
1453
  disabled,
@@ -1431,7 +1474,8 @@ var SearchInput = React9.forwardRef(function SearchInput2({
1431
1474
  disabled,
1432
1475
  value,
1433
1476
  onChange,
1434
- type: "text",
1477
+ type: "search",
1478
+ enterKeyHint: "search",
1435
1479
  name,
1436
1480
  id: htmlFor,
1437
1481
  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",
@@ -1668,7 +1712,7 @@ function TableBody({
1668
1712
  setVisibleRows(initial);
1669
1713
  }
1670
1714
  }, [rows]);
1671
- return /* @__PURE__ */ jsx("tbody", { className: "w-full", children: rows.map((row, i) => /* @__PURE__ */ jsxs(React9.Fragment, { children: [
1715
+ return /* @__PURE__ */ jsx("tbody", { className: "w-full", children: rows.map((row, i) => /* @__PURE__ */ jsxs(React10.Fragment, { children: [
1672
1716
  /* @__PURE__ */ jsxs(
1673
1717
  "tr",
1674
1718
  {
@@ -2118,7 +2162,7 @@ function AppShell({
2118
2162
  footer: sidebarFooter
2119
2163
  }
2120
2164
  ),
2121
- hasSidebar && isMobile && /* @__PURE__ */ jsxs(Fragment, { children: [
2165
+ hasSidebar && isMobile && /* @__PURE__ */ jsxs(Portal, { children: [
2122
2166
  /* @__PURE__ */ jsx(AnimatePresence, { children: mobileOpen && /* @__PURE__ */ jsx(
2123
2167
  motion.div,
2124
2168
  {
@@ -2249,7 +2293,7 @@ function ThemeProvider({
2249
2293
  className = "",
2250
2294
  style
2251
2295
  }) {
2252
- const id = React9.useId().replace(/:/g, "");
2296
+ const id = React10.useId().replace(/:/g, "");
2253
2297
  const scopeClass = `geo-th-${id}`;
2254
2298
  const divRef = useRef(null);
2255
2299
  useEffect(() => {
@@ -2402,6 +2446,9 @@ function TextInput({
2402
2446
  className: `flex ${layout === "vertical" ? "flex-col" : "flex-row items-center gap-2"}`,
2403
2447
  style: style ?? {},
2404
2448
  children: [
2449
+ label && // Render <label> only when a label is provided. An empty
2450
+ // <label htmlFor=…> announces as an unlabeled control in
2451
+ // some screen readers.
2405
2452
  /* @__PURE__ */ jsx(
2406
2453
  "label",
2407
2454
  {
@@ -2548,6 +2595,9 @@ function Password({
2548
2595
  const color = iconColor ?? colors_default.PALETTE["prussian-blue"];
2549
2596
  return /* @__PURE__ */ jsxs("div", { className: "relative flex flex-col items-center justify-center", style: style ?? {}, children: [
2550
2597
  /* @__PURE__ */ jsxs("div", { className: `flex ${layout === "vertical" ? "flex-col" : "flex-row items-center gap-2"}`, children: [
2598
+ label && // Render <label> only when a label is provided. An empty
2599
+ // <label htmlFor=…> announces as an unlabeled control in
2600
+ // some screen readers.
2551
2601
  /* @__PURE__ */ jsx(
2552
2602
  "label",
2553
2603
  {
@@ -2908,7 +2958,7 @@ function FileInput({
2908
2958
  const fileInput = useRef(null);
2909
2959
  const [files, setFiles] = useState([]);
2910
2960
  const openPicker = () => {
2911
- fileInput.current?.dispatchEvent(new MouseEvent("click", { bubbles: false }));
2961
+ fileInput.current?.click();
2912
2962
  };
2913
2963
  const handleFiles = (list) => {
2914
2964
  setFiles(list);
@@ -2940,56 +2990,70 @@ function FileInput({
2940
2990
  onChange?.({ target: { files: [], name, id: name, value: "" } });
2941
2991
  if (fileInput.current) fileInput.current.value = "";
2942
2992
  };
2943
- return /* @__PURE__ */ jsxs(
2944
- "div",
2945
- {
2946
- onClick: openPicker,
2947
- 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",
2948
- onDragOver: (e) => e.preventDefault(),
2949
- onDrop,
2950
- children: [
2951
- /* @__PURE__ */ jsx(
2952
- "input",
2953
- {
2954
- id: name,
2955
- name,
2956
- onChange: localOnChange,
2957
- ref: fileInput,
2958
- hidden: true,
2959
- type: "file",
2960
- accept,
2961
- multiple: allowMultiple
2993
+ return (
2994
+ // Dropzone is keyboard-activatable: role="button", focusable via
2995
+ // tabIndex, and Space/Enter trigger the file picker. Without these
2996
+ // a keyboard-only user could not upload a file.
2997
+ /* @__PURE__ */ jsxs(
2998
+ "div",
2999
+ {
3000
+ role: "button",
3001
+ tabIndex: 0,
3002
+ "aria-label": "Upload file \u2014 click or drop",
3003
+ onClick: openPicker,
3004
+ onKeyDown: (e) => {
3005
+ if (e.key === "Enter" || e.key === " ") {
3006
+ e.preventDefault();
3007
+ openPicker();
2962
3008
  }
2963
- ),
2964
- files.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full items-center justify-center gap-2", children: [
2965
- /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: colors_default.PALETTE["prussian-blue"], className: "w-16 h-16 dark:fill-white", children: /* @__PURE__ */ 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" }) }),
2966
- /* @__PURE__ */ jsx("div", { className: "text-prussian-blue dark:text-white text-sm", children: "Click or Drop a file" })
2967
- ] }) : /* @__PURE__ */ jsx("div", { className: "flex gap-3 items-center justify-center w-full h-full", children: files.map((file, id) => /* @__PURE__ */ jsxs(
2968
- "div",
2969
- {
2970
- 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",
2971
- children: [
2972
- /* @__PURE__ */ jsx(
2973
- "button",
2974
- {
2975
- type: "button",
2976
- onClick: removeFile,
2977
- className: "bg-error rounded-full w-4 h-4 absolute right-[-5px] top-[-5px] cursor-pointer flex items-center justify-center",
2978
- "aria-label": "Remove file",
2979
- children: /* @__PURE__ */ jsx("svg", { width: "10", height: "10", viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M15 5L5 15M5 5l10 10", stroke: "#fff", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })
2980
- }
2981
- ),
2982
- /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: colors_default.PALETTE["prussian-blue"], className: "w-10 h-10 dark:fill-white", children: [
2983
- /* @__PURE__ */ 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" }),
2984
- /* @__PURE__ */ 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" })
2985
- ] }),
2986
- /* @__PURE__ */ jsx("span", { className: "text-ellipsis whitespace-nowrap overflow-hidden w-full text-prussian-blue dark:text-white", children: file.name })
2987
- ]
2988
- },
2989
- `${id}${file.name}`
2990
- )) })
2991
- ]
2992
- }
3009
+ },
3010
+ 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",
3011
+ onDragOver: (e) => e.preventDefault(),
3012
+ onDrop,
3013
+ children: [
3014
+ /* @__PURE__ */ jsx(
3015
+ "input",
3016
+ {
3017
+ id: name,
3018
+ name,
3019
+ onChange: localOnChange,
3020
+ ref: fileInput,
3021
+ hidden: true,
3022
+ type: "file",
3023
+ accept,
3024
+ multiple: allowMultiple
3025
+ }
3026
+ ),
3027
+ files.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full items-center justify-center gap-2", children: [
3028
+ /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: colors_default.PALETTE["prussian-blue"], className: "w-16 h-16 dark:fill-white", children: /* @__PURE__ */ 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" }) }),
3029
+ /* @__PURE__ */ jsx("div", { className: "text-prussian-blue dark:text-white text-sm", children: "Click or Drop a file" })
3030
+ ] }) : /* @__PURE__ */ jsx("div", { className: "flex gap-3 items-center justify-center w-full h-full", children: files.map((file, id) => /* @__PURE__ */ jsxs(
3031
+ "div",
3032
+ {
3033
+ 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",
3034
+ children: [
3035
+ /* @__PURE__ */ jsx(
3036
+ "button",
3037
+ {
3038
+ type: "button",
3039
+ onClick: removeFile,
3040
+ className: "bg-error rounded-full w-4 h-4 absolute right-[-5px] top-[-5px] cursor-pointer flex items-center justify-center",
3041
+ "aria-label": "Remove file",
3042
+ children: /* @__PURE__ */ jsx("svg", { width: "10", height: "10", viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M15 5L5 15M5 5l10 10", stroke: "#fff", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })
3043
+ }
3044
+ ),
3045
+ /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: colors_default.PALETTE["prussian-blue"], className: "w-10 h-10 dark:fill-white", children: [
3046
+ /* @__PURE__ */ 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" }),
3047
+ /* @__PURE__ */ 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" })
3048
+ ] }),
3049
+ /* @__PURE__ */ jsx("span", { className: "text-ellipsis whitespace-nowrap overflow-hidden w-full text-prussian-blue dark:text-white", children: file.name })
3050
+ ]
3051
+ },
3052
+ `${id}${file.name}`
3053
+ )) })
3054
+ ]
3055
+ }
3056
+ )
2993
3057
  );
2994
3058
  }
2995
3059
  var MONTHS = {
@@ -3281,6 +3345,6 @@ Temporal.DatePicker = DatePickerBase;
3281
3345
  Temporal.TemporalPicker = TemporalPickerBase;
3282
3346
  var DatePicker_default = Temporal;
3283
3347
 
3284
- export { AppShell, AutoComplete, Button, Catalog, CatalogCarousel, CatalogGrid, Checkbox, ContextMenu, Drawer, Dropdown, DropdownPill, FadingBase, FileInput, GridCard, icons_default as Icon, IconButton, List2 as List, LoadingSpinner, MenuBar, MenuBarItem, Modal, NotificationProvider, NumberInput, OpaqueGridCard, Password, ScalableContainer, SearchInput_default as SearchInput, Sidebar, SkeletonBox, SkeletonCard, SkeletonCircle, SkeletonText, Switch, Table, Tabs, DatePicker_default as Temporal, TextInput, ThemeProvider, ThemeSwitch, ToggleButton, Tooltip, TooltipProvider, TopBar, Tree, TreeSelect, Wizard, useNotification };
3348
+ export { AppShell, AutoComplete, Button, Catalog, CatalogCarousel, CatalogGrid, Checkbox, ContextMenu, Drawer, Dropdown, DropdownPill, FadingBase, FileInput, GridCard, icons_default as Icon, IconButton, List2 as List, LoadingSpinner, MenuBar, MenuBarItem, Modal, NotificationProvider, NumberInput, OpaqueGridCard, Password, Portal, ScalableContainer, SearchInput_default as SearchInput, Sidebar, SkeletonBox, SkeletonCard, SkeletonCircle, SkeletonText, Switch, Table, Tabs, DatePicker_default as Temporal, TextInput, ThemeProvider, ThemeSwitch, ToggleButton, Tooltip, TooltipProvider, TopBar, Tree, TreeSelect, Wizard, useNotification };
3285
3349
  //# sourceMappingURL=index.js.map
3286
3350
  //# sourceMappingURL=index.js.map