@geomak/ui 1.5.1 → 1.5.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.d.cts CHANGED
@@ -273,8 +273,13 @@ interface IconButtonProps {
273
273
  declare function IconButton({ icon, onClick, type, buttonType, disabled, size, loading, loadingIcon, }: IconButtonProps): react_jsx_runtime.JSX.Element;
274
274
 
275
275
  interface ModalProps {
276
- /** Pixel dimensions [width, height] */
277
- size?: [number, number];
276
+ /**
277
+ * Max width of the modal panel in pixels (default 600).
278
+ * On narrow viewports the panel fills the screen minus 1 rem on each side.
279
+ * Height is always content-driven — `size[1]` is accepted for backwards
280
+ * compatibility but is no longer used; remove it when convenient.
281
+ */
282
+ size?: [number, number] | [number];
278
283
  isOpen?: boolean;
279
284
  onClose?: () => void;
280
285
  onOk?: () => void;
@@ -375,7 +380,7 @@ interface TabsProps {
375
380
  * Scrollable pill-style tabs powered by Radix Tabs.
376
381
  *
377
382
  * Radix handles roving-tabindex keyboard navigation and ARIA roles.
378
- * The VesOPS pill visual style (rounded-3xl, ice/black-coral palette) is preserved.
383
+ * Rounded pill style, fully themed via semantic design tokens.
379
384
  * Supports dynamic tab add/remove with automatic activation.
380
385
  *
381
386
  * @example
@@ -932,6 +937,9 @@ interface AppShellProps {
932
937
  /**
933
938
  * Top navigation bar.
934
939
  * Typically `<TopBar brand={...} actions={...} />`.
940
+ * On mobile, a hamburger button is injected to the left of this slot when
941
+ * `sidebarSections` is non-empty. The TopBar should leave some leading space
942
+ * (or use its `center` / `actions` props) to avoid overlap.
935
943
  */
936
944
  topBar?: React$1.ReactNode;
937
945
  /** Sidebar navigation sections */
@@ -953,7 +961,12 @@ interface AppShellProps {
953
961
  * Full-page application layout skeleton.
954
962
  *
955
963
  * Composes a sticky TopBar + collapsible Sidebar + scrollable content area.
956
- * The main area shifts with the sidebar width via a Framer Motion margin animation.
964
+ *
965
+ * **Responsive behaviour:**
966
+ * - **≥ md (768 px):** Sidebar renders inline, collapsible via its own toggle.
967
+ * - **< md (mobile):** Sidebar becomes a fixed overlay drawer. A hamburger
968
+ * button appears to the left of the TopBar slot to open it. Tapping the
969
+ * backdrop or the sidebar's own toggle closes it.
957
970
  *
958
971
  * @example
959
972
  * <AppShell
package/dist/index.d.ts CHANGED
@@ -273,8 +273,13 @@ interface IconButtonProps {
273
273
  declare function IconButton({ icon, onClick, type, buttonType, disabled, size, loading, loadingIcon, }: IconButtonProps): react_jsx_runtime.JSX.Element;
274
274
 
275
275
  interface ModalProps {
276
- /** Pixel dimensions [width, height] */
277
- size?: [number, number];
276
+ /**
277
+ * Max width of the modal panel in pixels (default 600).
278
+ * On narrow viewports the panel fills the screen minus 1 rem on each side.
279
+ * Height is always content-driven — `size[1]` is accepted for backwards
280
+ * compatibility but is no longer used; remove it when convenient.
281
+ */
282
+ size?: [number, number] | [number];
278
283
  isOpen?: boolean;
279
284
  onClose?: () => void;
280
285
  onOk?: () => void;
@@ -375,7 +380,7 @@ interface TabsProps {
375
380
  * Scrollable pill-style tabs powered by Radix Tabs.
376
381
  *
377
382
  * Radix handles roving-tabindex keyboard navigation and ARIA roles.
378
- * The VesOPS pill visual style (rounded-3xl, ice/black-coral palette) is preserved.
383
+ * Rounded pill style, fully themed via semantic design tokens.
379
384
  * Supports dynamic tab add/remove with automatic activation.
380
385
  *
381
386
  * @example
@@ -932,6 +937,9 @@ interface AppShellProps {
932
937
  /**
933
938
  * Top navigation bar.
934
939
  * Typically `<TopBar brand={...} actions={...} />`.
940
+ * On mobile, a hamburger button is injected to the left of this slot when
941
+ * `sidebarSections` is non-empty. The TopBar should leave some leading space
942
+ * (or use its `center` / `actions` props) to avoid overlap.
935
943
  */
936
944
  topBar?: React$1.ReactNode;
937
945
  /** Sidebar navigation sections */
@@ -953,7 +961,12 @@ interface AppShellProps {
953
961
  * Full-page application layout skeleton.
954
962
  *
955
963
  * Composes a sticky TopBar + collapsible Sidebar + scrollable content area.
956
- * The main area shifts with the sidebar width via a Framer Motion margin animation.
964
+ *
965
+ * **Responsive behaviour:**
966
+ * - **≥ md (768 px):** Sidebar renders inline, collapsible via its own toggle.
967
+ * - **< md (mobile):** Sidebar becomes a fixed overlay drawer. A hamburger
968
+ * button appears to the left of the TopBar slot to open it. Tapping the
969
+ * backdrop or the sidebar's own toggle closes it.
957
970
  *
958
971
  * @example
959
972
  * <AppShell
package/dist/index.js CHANGED
@@ -305,7 +305,7 @@ function Modal({
305
305
  /* @__PURE__ */ jsx(AnimatePresence, { children: isOpen && /* @__PURE__ */ jsx(Dialog.Overlay, { asChild: true, children: /* @__PURE__ */ jsx(
306
306
  motion.div,
307
307
  {
308
- className: "fixed inset-0 bg-oxford-blue-700-opaque z-50",
308
+ className: "fixed inset-0 bg-black/40 z-overlay",
309
309
  initial: { opacity: 0 },
310
310
  animate: { opacity: 1 },
311
311
  exit: { opacity: 0 },
@@ -315,10 +315,9 @@ function Modal({
315
315
  /* @__PURE__ */ jsx(AnimatePresence, { children: isOpen && /* @__PURE__ */ jsx(Dialog.Content, { asChild: true, children: /* @__PURE__ */ jsxs(
316
316
  motion.div,
317
317
  {
318
- className: "fixed left-1/2 top-1/2 z-50 flex flex-col bg-white dark:bg-prussian-blue rounded-2xl shadow-2xl shadow-black/20 overflow-hidden focus:outline-none",
318
+ 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
319
  style: {
320
- width: size[0],
321
- height: size[1],
320
+ maxWidth: size[0],
322
321
  x: "-50%",
323
322
  y: "-50%"
324
323
  },
@@ -332,19 +331,19 @@ function Modal({
332
331
  duration: 0.25
333
332
  },
334
333
  children: [
335
- /* @__PURE__ */ jsxs("div", { className: "flex h-14 flex-shrink-0 items-center justify-between border-b border-ice dark:border-independence px-5", children: [
336
- /* @__PURE__ */ jsx(Dialog.Title, { className: "text-base font-semibold text-prussian-blue dark:text-white tracking-tight", children: title }),
334
+ /* @__PURE__ */ jsxs("div", { className: "flex h-14 flex-shrink-0 items-center justify-between border-b border-border px-5", children: [
335
+ /* @__PURE__ */ jsx(Dialog.Title, { className: "text-base font-semibold text-foreground tracking-tight", children: title }),
337
336
  /* @__PURE__ */ jsx(Dialog.Close, { asChild: true, children: /* @__PURE__ */ jsx(
338
337
  "button",
339
338
  {
340
339
  "aria-label": "Close",
341
- className: "flex h-7 w-7 items-center justify-center rounded-lg text-black-coral dark:text-manatee hover:bg-ice hover:text-prussian-blue dark:hover:bg-oxford-blue-700 dark:hover:text-white transition-colors duration-150 focus:outline-none focus-visible:ring-2 focus-visible:ring-true-blue",
340
+ className: "flex h-7 w-7 items-center justify-center rounded-lg text-foreground-muted hover:bg-surface-raised hover:text-foreground transition-colors duration-150 focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
342
341
  children: /* @__PURE__ */ jsx("svg", { width: "15", height: "15", viewBox: "0 0 15 15", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M11.7816 4.03157C12.0062 3.80702 12.0062 3.44295 11.7816 3.2184C11.5571 2.99385 11.193 2.99385 10.9685 3.2184L7.50005 6.68682L4.03164 3.2184C3.80708 2.99385 3.44301 2.99385 3.21846 3.2184C2.99391 3.44295 2.99391 3.80702 3.21846 4.03157L6.68688 7.49999L3.21846 10.9684C2.99391 11.193 2.99391 11.557 3.21846 11.7816C3.44301 12.0061 3.80708 12.0061 4.03164 11.7816L7.50005 8.31316L10.9685 11.7816C11.193 12.0061 11.5571 12.0061 11.7816 11.7816C12.0062 11.557 12.0062 11.193 11.7816 10.9684L8.31322 7.49999L11.7816 4.03157Z", fill: "currentColor", fillRule: "evenodd", clipRule: "evenodd" }) })
343
342
  }
344
343
  ) })
345
344
  ] }),
346
345
  /* @__PURE__ */ jsx("div", { className: `flex-1 overflow-y-auto p-5 ${hasFooter ? "" : "pb-5"}`, children: isOpen && children }),
347
- hasFooter && /* @__PURE__ */ jsxs("div", { className: "flex flex-shrink-0 items-center justify-end gap-3 border-t border-ice dark:border-independence px-5 py-3", children: [
346
+ hasFooter && /* @__PURE__ */ jsxs("div", { className: "flex flex-shrink-0 items-center justify-end gap-3 border-t border-border px-5 py-3", children: [
348
347
  /* @__PURE__ */ jsx(
349
348
  Button,
350
349
  {
@@ -389,7 +388,7 @@ function Drawer({
389
388
  /* @__PURE__ */ jsx(AnimatePresence, { children: isOpen && /* @__PURE__ */ jsx(Dialog.Overlay, { asChild: true, children: /* @__PURE__ */ jsx(
390
389
  motion.div,
391
390
  {
392
- className: "fixed inset-0 bg-oxford-blue-700-opaque z-[5000]",
391
+ className: "fixed inset-0 bg-black/40 z-overlay",
393
392
  initial: { opacity: 0 },
394
393
  animate: { opacity: 1 },
395
394
  exit: { opacity: 0 },
@@ -399,8 +398,8 @@ function Drawer({
399
398
  /* @__PURE__ */ jsx(AnimatePresence, { children: isOpen && /* @__PURE__ */ jsx(Dialog.Content, { asChild: true, children: /* @__PURE__ */ jsxs(
400
399
  motion.div,
401
400
  {
402
- className: `fixed top-0 bottom-0 ${isRight ? "right-0" : "left-0"} z-[5000] flex flex-col bg-white dark:bg-prussian-blue shadow-2xl shadow-black/25 focus:outline-none`,
403
- style: { width },
401
+ className: `fixed top-0 bottom-0 ${isRight ? "right-0" : "left-0"} z-modal flex flex-col bg-surface shadow-xl focus:outline-none`,
402
+ style: { width: `min(calc(100vw - 1rem), ${width}px)` },
404
403
  initial: { x: reduced ? 0 : hiddenX, opacity: reduced ? 0 : 1 },
405
404
  animate: { x: 0, opacity: 1 },
406
405
  exit: { x: reduced ? 0 : hiddenX, opacity: reduced ? 0 : 1 },
@@ -414,19 +413,19 @@ function Drawer({
414
413
  opacity: { duration: 0 }
415
414
  },
416
415
  children: [
417
- /* @__PURE__ */ jsxs("div", { className: `flex h-14 flex-shrink-0 items-center justify-between border-b border-ice dark:border-independence px-5 ${isRight ? "flex-row-reverse" : ""}`, children: [
418
- /* @__PURE__ */ jsx(Dialog.Title, { className: "text-base font-semibold text-prussian-blue dark:text-white tracking-tight", children: title }),
416
+ /* @__PURE__ */ jsxs("div", { className: `flex h-14 flex-shrink-0 items-center justify-between border-b border-border px-5 ${isRight ? "flex-row-reverse" : ""}`, children: [
417
+ /* @__PURE__ */ jsx(Dialog.Title, { className: "text-base font-semibold text-foreground tracking-tight", children: title }),
419
418
  /* @__PURE__ */ jsx(Dialog.Close, { asChild: true, children: /* @__PURE__ */ jsx(
420
419
  "button",
421
420
  {
422
421
  "aria-label": "Close drawer",
423
- className: "flex h-7 w-7 items-center justify-center rounded-lg text-black-coral dark:text-manatee hover:bg-ice hover:text-prussian-blue dark:hover:bg-oxford-blue-700 dark:hover:text-white transition-colors duration-150 focus:outline-none focus-visible:ring-2 focus-visible:ring-true-blue",
422
+ className: "flex h-7 w-7 items-center justify-center rounded-lg text-foreground-muted hover:bg-surface-raised hover:text-foreground transition-colors duration-150 focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
424
423
  children: /* @__PURE__ */ jsx("svg", { width: "15", height: "15", viewBox: "0 0 15 15", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M11.7816 4.03157C12.0062 3.80702 12.0062 3.44295 11.7816 3.2184C11.5571 2.99385 11.193 2.99385 10.9685 3.2184L7.50005 6.68682L4.03164 3.2184C3.80708 2.99385 3.44301 2.99385 3.21846 3.2184C2.99391 3.44295 2.99391 3.80702 3.21846 4.03157L6.68688 7.49999L3.21846 10.9684C2.99391 11.193 2.99391 11.557 3.21846 11.7816C3.44301 12.0061 3.80708 12.0061 4.03164 11.7816L7.50005 8.31316L10.9685 11.7816C11.193 12.0061 11.5571 12.0061 11.7816 11.7816C12.0062 11.557 12.0062 11.193 11.7816 10.9684L8.31322 7.49999L11.7816 4.03157Z", fill: "currentColor", fillRule: "evenodd", clipRule: "evenodd" }) })
425
424
  }
426
425
  ) })
427
426
  ] }),
428
427
  /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto p-5", children: isOpen && children }),
429
- hasFooter && /* @__PURE__ */ jsxs("div", { className: `flex flex-shrink-0 items-center gap-3 border-t border-ice dark:border-independence px-5 py-3 ${isRight ? "justify-start" : "justify-end"}`, children: [
428
+ 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: [
430
429
  /* @__PURE__ */ jsx(Button, { style: { width: 90 }, content: cancelText, onClick: onCancel }),
431
430
  /* @__PURE__ */ jsx(Button, { style: { width: 90 }, content: okText, onClick: onOk })
432
431
  ] })
@@ -458,11 +457,11 @@ function Tooltip({
458
457
  className: [
459
458
  // Layout + typography
460
459
  "pointer-events-none z-[500000] max-w-[220px] px-2.5 py-1.5",
461
- "text-xs font-medium leading-snug text-white",
462
- // Background + border — slightly translucent for depth
463
- "bg-foreground/95 rounded-md border border-white/5",
464
- // Shadow
465
- "shadow-md",
460
+ // Inverted surface: dark on light, light on dark — both readable
461
+ "bg-foreground text-background",
462
+ "text-xs font-medium leading-snug",
463
+ // Shape + shadow
464
+ "rounded-md shadow-md",
466
465
  // Out animation (always the same — just fade)
467
466
  "data-[state=closed]:animate-tooltip-out",
468
467
  // In animation — direction-aware
@@ -475,7 +474,7 @@ function Tooltip({
475
474
  {
476
475
  width: 10,
477
476
  height: 5,
478
- className: "fill-foreground/95"
477
+ className: "fill-foreground"
479
478
  }
480
479
  )
481
480
  ]
@@ -528,15 +527,15 @@ function Tabs({
528
527
  onValueChange: handleValueChange,
529
528
  className: "h-full max-w-full flex flex-col gap-2",
530
529
  children: [
531
- /* @__PURE__ */ jsxs("div", { className: "glassmorphism dark:bg-prussian-blue rounded-lg flex items-center justify-between h-[7%] w-full p-1 overflow-hidden", children: [
530
+ /* @__PURE__ */ jsxs("div", { className: "bg-surface border border-border rounded-lg flex items-center justify-between flex-shrink-0 w-full p-1 overflow-hidden", children: [
532
531
  /* @__PURE__ */ jsx(
533
532
  "button",
534
533
  {
535
534
  type: "button",
536
535
  onClick: toPreviousTab,
537
536
  "aria-label": "Previous tab",
538
- className: "cursor-pointer rounded-lg transition-all duration-300 hover:bg-ice-dark dark:hover:bg-independence rotate-180 flex-shrink-0",
539
- children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: colors_default.PALETTE["prussian-blue"], strokeWidth: 2, className: "h-6 w-6 dark:stroke-white", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 5l7 7-7 7" }) })
537
+ className: "cursor-pointer rounded-lg transition-colors duration-150 hover:bg-surface-raised text-foreground-secondary hover:text-foreground rotate-180 flex-shrink-0 focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
538
+ children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-6 w-6", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 5l7 7-7 7" }) })
540
539
  }
541
540
  ),
542
541
  /* @__PURE__ */ jsx(
@@ -548,7 +547,7 @@ function Tabs({
548
547
  TabsPrimitive.Trigger,
549
548
  {
550
549
  value: tab.key,
551
- className: "snap-start snap-always flex items-center justify-between gap-2 p-3 rounded-3xl cursor-pointer transition-all duration-300 select-none h-12 w-[220px] min-w-[220px] flex-shrink-0 text-prussian-blue dark:text-white\n bg-ice dark:bg-indigo-dye\n hover:bg-ice-dark dark:hover:bg-black-coral\n data-[state=active]:bg-ice-dark dark:data-[state=active]:bg-black-coral\n focus:outline-none focus-visible:ring-2 focus-visible:ring-usafa-blue",
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",
552
551
  children: [
553
552
  /* @__PURE__ */ jsx("span", { className: "truncate text-sm", children: tab.title }),
554
553
  tabsClosable && /* @__PURE__ */ jsx(
@@ -560,8 +559,8 @@ function Tabs({
560
559
  e.stopPropagation();
561
560
  onTabClose?.(tab.key);
562
561
  },
563
- className: "flex-shrink-0 rounded hover:bg-ice-dark dark:hover:bg-independence p-0.5 transition-colors",
564
- 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: colors_default.PALETTE["prussian-blue"], strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", className: "dark:stroke-white" }) })
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" }) })
565
564
  }
566
565
  )
567
566
  ]
@@ -576,12 +575,12 @@ function Tabs({
576
575
  type: "button",
577
576
  onClick: toNextTab,
578
577
  "aria-label": "Next tab",
579
- className: "cursor-pointer rounded-lg transition-all duration-300 hover:bg-ice-dark dark:hover:bg-independence flex-shrink-0",
580
- children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: colors_default.PALETTE["prussian-blue"], strokeWidth: 2, className: "h-6 w-6 dark:stroke-white", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 5l7 7-7 7" }) })
578
+ className: "cursor-pointer rounded-lg transition-colors duration-150 hover:bg-surface-raised text-foreground-secondary hover:text-foreground flex-shrink-0 focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
579
+ children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-6 w-6", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 5l7 7-7 7" }) })
581
580
  }
582
581
  )
583
582
  ] }),
584
- /* @__PURE__ */ jsx("div", { className: "p-2 rounded-lg w-full h-[92%] glassmorphism dark:bg-prussian-blue overflow-hidden", children: isLazy ? (
583
+ /* @__PURE__ */ jsx("div", { className: "p-2 rounded-lg w-full flex-1 min-h-0 bg-surface border border-border overflow-hidden", children: isLazy ? (
585
584
  // Mount only the active content
586
585
  tabs.filter((t) => t.key === value).map((t) => /* @__PURE__ */ jsx(TabsPrimitive.Content, { value: t.key, className: "w-full h-full focus:outline-none", children: t.content }, t.key))
587
586
  ) : (
@@ -605,7 +604,7 @@ function TreeNodeItem({
605
604
  "button",
606
605
  {
607
606
  type: "button",
608
- className: "flex w-full items-center gap-2.5 cursor-pointer select-none group text-left rounded-md px-2 py-1.5 hover:bg-ice dark:hover:bg-oxford-blue-700 transition-colors duration-150 focus:outline-none focus-visible:ring-2 focus-visible:ring-true-blue",
607
+ className: "flex w-full items-center gap-2.5 cursor-pointer select-none group text-left rounded-md px-2 py-1.5 hover:bg-surface-raised transition-colors duration-150 focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
609
608
  style: { paddingLeft: depth * 12 + 8 },
610
609
  onClick: () => onNodeClick({
611
610
  isParent: false,
@@ -615,8 +614,8 @@ function TreeNodeItem({
615
614
  parentLabel: item.parentLabel
616
615
  }),
617
616
  children: [
618
- /* @__PURE__ */ jsx("span", { className: "w-1.5 h-1.5 rounded-full flex-shrink-0 bg-roman-silver dark:bg-manatee group-hover:bg-true-blue dark:group-hover:bg-true-blue transition-colors duration-150" }),
619
- /* @__PURE__ */ jsx("span", { className: "text-sm text-independence dark:text-manatee group-hover:text-prussian-blue dark:group-hover:text-white transition-colors duration-150", children: item.label })
617
+ /* @__PURE__ */ jsx("span", { className: "w-1.5 h-1.5 rounded-full flex-shrink-0 bg-foreground-muted group-hover:bg-accent transition-colors duration-150" }),
618
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-foreground-secondary group-hover:text-foreground transition-colors duration-150", children: item.label })
620
619
  ]
621
620
  }
622
621
  );
@@ -629,7 +628,7 @@ function TreeNodeItem({
629
628
  defaultValue: initialOpen,
630
629
  style: { paddingLeft: depth * 12 },
631
630
  children: /* @__PURE__ */ jsxs(Accordion.Item, { value: item.key, className: "border-none", children: [
632
- /* @__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-true-blue w-full text-left rounded-md hover:bg-ice dark:hover:bg-oxford-blue-700 transition-colors duration-150", 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: [
633
632
  /* @__PURE__ */ jsx(
634
633
  "svg",
635
634
  {
@@ -637,7 +636,7 @@ function TreeNodeItem({
637
636
  fill: "none",
638
637
  stroke: "currentColor",
639
638
  strokeWidth: 2.5,
640
- className: "h-3.5 w-3.5 flex-shrink-0 text-black-coral dark:text-manatee transition-transform duration-200 group-data-[state=open]:rotate-0 group-data-[state=closed]:-rotate-90",
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",
641
640
  children: /* @__PURE__ */ jsx(
642
641
  "path",
643
642
  {
@@ -651,7 +650,7 @@ function TreeNodeItem({
651
650
  /* @__PURE__ */ jsx(
652
651
  "span",
653
652
  {
654
- className: "text-sm font-semibold text-prussian-blue dark:text-white select-none",
653
+ className: "text-sm font-semibold text-foreground select-none",
655
654
  onClick: () => onNodeClick({
656
655
  isParent: true,
657
656
  key: item.key,
@@ -663,7 +662,7 @@ function TreeNodeItem({
663
662
  }
664
663
  )
665
664
  ] }),
666
- /* @__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-ice-dark dark:border-independence py-0.5", children: item.children.map((child) => /* @__PURE__ */ jsx(
665
+ /* @__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(
667
666
  TreeNodeItem,
668
667
  {
669
668
  item: child,
@@ -1617,10 +1616,10 @@ function createDatasets(rows, perPage) {
1617
1616
  return all;
1618
1617
  }
1619
1618
  function TableHeader({ columns }) {
1620
- return /* @__PURE__ */ jsx("thead", { className: "dark:bg-prussian-blue bg-ice-dark min-h-[50px] border-b border-b-white border-t-white dark:border-b-independence flex items-center", children: /* @__PURE__ */ jsx("tr", { className: "flex w-full items-center justify-center", children: columns.map((col) => /* @__PURE__ */ jsx(
1619
+ return /* @__PURE__ */ jsx("thead", { className: "bg-surface-raised min-h-[50px] border-b border-b-border flex items-center", children: /* @__PURE__ */ jsx("tr", { className: "flex w-full items-center justify-center", children: columns.map((col) => /* @__PURE__ */ jsx(
1621
1620
  "th",
1622
1621
  {
1623
- className: "text-center w-full text-[13px] text-prussian-blue dark:text-white",
1622
+ className: "text-center w-full text-[13px] text-foreground",
1624
1623
  children: col.label
1625
1624
  },
1626
1625
  col.key
@@ -1651,7 +1650,7 @@ function TableBody({
1651
1650
  /* @__PURE__ */ jsxs(
1652
1651
  "tr",
1653
1652
  {
1654
- className: `border-b border-b-white dark:border-b-manatee flex min-w-max hover:bg-ice-dark dark:hover:bg-prussian-blue transition-all duration-150 ${i % 2 === 0 ? "bg-ice dark:bg-prussian-blue" : "bg-ice-dark dark:bg-black-coral"}`,
1653
+ 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"}`,
1655
1654
  children: [
1656
1655
  expandRow.enabled && /* @__PURE__ */ jsx("td", { className: "flex items-center", children: /* @__PURE__ */ jsx(
1657
1656
  "span",
@@ -1659,13 +1658,13 @@ function TableBody({
1659
1658
  onClick: () => toggleRow(row.key),
1660
1659
  className: `p-2 cursor-pointer origin-center transition-all duration-200 ${visibleRows[row.key]?.visible ? "rotate-180" : "rotate-0"}`,
1661
1660
  children: expandRow.expandIcon ?? /* PlusCircle */
1662
- /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: colors_default.PALETTE["prussian-blue"], className: "w-5 h-5 dark:fill-white", children: /* @__PURE__ */ 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" }) })
1661
+ /* @__PURE__ */ 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__ */ 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" }) })
1663
1662
  }
1664
1663
  ) }),
1665
1664
  columns.map((col, index) => /* @__PURE__ */ jsx(
1666
1665
  "td",
1667
1666
  {
1668
- className: `text-center min-h-[40px] w-full flex items-center justify-center p-1 border-white dark:border-manatee ${index !== columns.length - 1 ? "border-r-2" : ""}`,
1667
+ className: `text-center min-h-[40px] w-full flex items-center justify-center p-1 border-border ${index !== columns.length - 1 ? "border-r-2" : ""}`,
1669
1668
  children: "component" in col && col.component ? col.component(row[col.keyBind], row) : row[col.keyBind]
1670
1669
  },
1671
1670
  index
@@ -1712,8 +1711,8 @@ function Pagination({
1712
1711
  const navBtn = (icon, disabled, onClick) => /* @__PURE__ */ jsx(IconButton, { disabled, onClick, icon });
1713
1712
  const chevronRight = (color) => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: 2, className: "h-5 w-5", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 5l7 7-7 7" }) });
1714
1713
  const doubleChevronRight = (color) => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: 2, className: "h-5 w-5", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M13 5l7 7-7 7M5 5l7 7-7 7" }) });
1715
- const disabledColor = colors_default.PALETTE["prussian-blue"];
1716
- const enabledColor = colors_default.PALETTE.white;
1714
+ const disabledColor = "var(--color-foreground-muted)";
1715
+ const enabledColor = "var(--color-foreground)";
1717
1716
  return /* @__PURE__ */ jsxs("div", { className: "flex gap-2 items-center justify-end pt-2", children: [
1718
1717
  navBtn(
1719
1718
  /* @__PURE__ */ jsx("span", { className: "rotate-180 inline-flex", children: doubleChevronRight(activePage === 0 ? disabledColor : enabledColor) }),
@@ -1725,7 +1724,7 @@ function Pagination({
1725
1724
  activePage === 0,
1726
1725
  () => activePage > 0 && onPageChange(activePage - 1)
1727
1726
  ),
1728
- /* @__PURE__ */ jsx("span", { className: "bg-ice-dark dark:bg-independence rounded-lg ml-2 mr-2 shadow-md p-2 w-10 text-center select-none", children: activePage + 1 }),
1727
+ /* @__PURE__ */ 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 }),
1729
1728
  navBtn(
1730
1729
  chevronRight(activePage === maxPage ? disabledColor : enabledColor),
1731
1730
  activePage === maxPage,
@@ -1843,10 +1842,10 @@ function Table({
1843
1842
  )
1844
1843
  ] }),
1845
1844
  /* @__PURE__ */ jsx("div", { children: header }),
1846
- /* @__PURE__ */ jsxs("table", { className: "w-full h-full", children: [
1845
+ /* @__PURE__ */ jsx("div", { className: "overflow-x-auto rounded-lg", children: /* @__PURE__ */ jsxs("table", { className: "w-full", children: [
1847
1846
  /* @__PURE__ */ jsx(TableHeader, { columns }),
1848
1847
  /* @__PURE__ */ jsx(TableBody, { columns, rows: currentPageRows, expandRow })
1849
- ] }),
1848
+ ] }) }),
1850
1849
  /* @__PURE__ */ jsx("div", { children: footer })
1851
1850
  ] });
1852
1851
  }
@@ -2045,10 +2044,48 @@ function AppShell({
2045
2044
  className = ""
2046
2045
  }) {
2047
2046
  const [expanded, setExpanded] = useState(sidebarDefaultExpanded);
2047
+ const [isMobile, setIsMobile] = useState(false);
2048
+ const [mobileOpen, setMobileOpen] = useState(false);
2049
+ useEffect(() => {
2050
+ const mq = window.matchMedia("(max-width: 767px)");
2051
+ const update = (e) => setIsMobile(e.matches);
2052
+ update(mq);
2053
+ mq.addEventListener("change", update);
2054
+ return () => mq.removeEventListener("change", update);
2055
+ }, []);
2056
+ useEffect(() => {
2057
+ if (!isMobile) setMobileOpen(false);
2058
+ }, [isMobile]);
2059
+ const hasSidebar = sidebarSections.length > 0;
2048
2060
  return /* @__PURE__ */ jsxs("div", { className: `flex flex-col h-screen bg-background ${className}`, children: [
2049
- topBar && /* @__PURE__ */ jsx("div", { className: "flex-shrink-0 z-[200]", children: topBar }),
2061
+ topBar && /* @__PURE__ */ jsxs("div", { className: "flex-shrink-0 flex items-stretch z-topbar", children: [
2062
+ hasSidebar && /* @__PURE__ */ jsx(
2063
+ "button",
2064
+ {
2065
+ type: "button",
2066
+ className: [
2067
+ "md:hidden flex-shrink-0 self-stretch flex items-center justify-center w-14",
2068
+ "border-r border-border",
2069
+ "text-foreground-secondary hover:bg-surface-raised hover:text-foreground",
2070
+ "transition-colors duration-100",
2071
+ "focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-accent"
2072
+ ].join(" "),
2073
+ onClick: () => setMobileOpen((o) => !o),
2074
+ "aria-label": mobileOpen ? "Close navigation" : "Open navigation",
2075
+ "aria-expanded": mobileOpen,
2076
+ children: mobileOpen ? (
2077
+ /* X icon */
2078
+ /* @__PURE__ */ jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M18 6 6 18M6 6l12 12" }) })
2079
+ ) : (
2080
+ /* Hamburger icon */
2081
+ /* @__PURE__ */ jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M4 6h16M4 12h16M4 18h16" }) })
2082
+ )
2083
+ }
2084
+ ),
2085
+ /* @__PURE__ */ jsx("div", { className: "flex-1 min-w-0", children: topBar })
2086
+ ] }),
2050
2087
  /* @__PURE__ */ jsxs("div", { className: "flex flex-1 overflow-hidden", children: [
2051
- sidebarSections.length > 0 && /* @__PURE__ */ jsx(
2088
+ hasSidebar && !isMobile && /* @__PURE__ */ jsx(
2052
2089
  Sidebar,
2053
2090
  {
2054
2091
  sections: sidebarSections,
@@ -2059,15 +2096,47 @@ function AppShell({
2059
2096
  footer: sidebarFooter
2060
2097
  }
2061
2098
  ),
2062
- /* @__PURE__ */ jsx(
2063
- motion.main,
2064
- {
2065
- className: "flex-1 overflow-y-auto overflow-x-hidden",
2066
- animate: { marginLeft: 0 },
2067
- transition: { type: "tween", duration: 0.22, ease: [0.16, 1, 0.3, 1] },
2068
- children: /* @__PURE__ */ jsx("div", { className: "h-full p-6", children })
2069
- }
2070
- )
2099
+ hasSidebar && isMobile && /* @__PURE__ */ jsxs(Fragment, { children: [
2100
+ /* @__PURE__ */ jsx(AnimatePresence, { children: mobileOpen && /* @__PURE__ */ jsx(
2101
+ motion.div,
2102
+ {
2103
+ className: "fixed inset-0 bg-black/40 z-overlay md:hidden",
2104
+ initial: { opacity: 0 },
2105
+ animate: { opacity: 1 },
2106
+ exit: { opacity: 0 },
2107
+ transition: { duration: 0.2, ease: "easeOut" },
2108
+ onClick: () => setMobileOpen(false),
2109
+ "aria-hidden": "true"
2110
+ }
2111
+ ) }),
2112
+ /* @__PURE__ */ jsx(AnimatePresence, { children: mobileOpen && /* @__PURE__ */ jsx(
2113
+ motion.div,
2114
+ {
2115
+ className: "fixed inset-y-0 left-0 z-modal md:hidden",
2116
+ initial: { x: "-100%" },
2117
+ animate: { x: 0 },
2118
+ exit: { x: "-100%" },
2119
+ transition: {
2120
+ type: "tween",
2121
+ duration: 0.26,
2122
+ ease: [0.16, 1, 0.3, 1]
2123
+ // ease-out-expo
2124
+ },
2125
+ children: /* @__PURE__ */ jsx(
2126
+ Sidebar,
2127
+ {
2128
+ sections: sidebarSections,
2129
+ isExpanded: true,
2130
+ onToggle: () => setMobileOpen(false),
2131
+ expandedWidth: sidebarExpandedWidth,
2132
+ collapsedWidth: sidebarCollapsedWidth,
2133
+ footer: sidebarFooter
2134
+ }
2135
+ )
2136
+ }
2137
+ ) })
2138
+ ] }),
2139
+ /* @__PURE__ */ jsx("main", { className: "flex-1 overflow-y-auto overflow-x-hidden", children: /* @__PURE__ */ jsx("div", { className: "h-full p-6", children }) })
2071
2140
  ] })
2072
2141
  ] });
2073
2142
  }