@geomak/ui 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -322,14 +322,15 @@ interface ModalProps {
322
322
  children?: React$1.ReactNode;
323
323
  }
324
324
  /**
325
- * Centred modal dialog powered by Radix Dialog.
325
+ * Centred modal dialog powered by Radix Dialog + Framer Motion.
326
326
  *
327
- * The Radix primitive handles focus-trap, escape-to-close, and ARIA roles.
328
- * The VesOPS visual style (scale-in animation, prussian-blue header) is preserved.
327
+ * Radix handles focus-trap, escape-to-close, and ARIA roles.
328
+ * Framer Motion drives the scale + fade enter/exit animation.
329
+ * prefers-reduced-motion is respected via useReducedMotion().
329
330
  *
330
331
  * @example
331
332
  * <Modal isOpen={open} onClose={() => setOpen(false)} title="Confirm" onOk={handleOk}>
332
- * Are you sure?
333
+ * Are you sure you want to delete this item?
333
334
  * </Modal>
334
335
  */
335
336
  declare function Modal({ size, isOpen, onClose, onOk, onCancel, okText, cancelText, hasFooter, title, children, }: ModalProps): react_jsx_runtime.JSX.Element;
@@ -338,7 +339,7 @@ interface DrawerProps {
338
339
  isOpen?: boolean;
339
340
  onClose?: () => void;
340
341
  hasFooter?: boolean;
341
- /** 'left' | 'right' */
342
+ /** 'left' | 'right' — which edge the panel slides from */
342
343
  placement?: 'left' | 'right';
343
344
  width?: number;
344
345
  okText?: string;
@@ -349,10 +350,11 @@ interface DrawerProps {
349
350
  children?: React$1.ReactNode;
350
351
  }
351
352
  /**
352
- * Side-sliding drawer panel powered by Radix Dialog.
353
+ * Side-sliding drawer panel powered by Radix Dialog + Framer Motion.
353
354
  *
354
355
  * Radix handles focus-trap, escape-to-close, and ARIA roles.
355
- * The drawer slides in from the left or right depending on `placement`.
356
+ * Framer Motion drives the slide enter/exit animation.
357
+ * prefers-reduced-motion is respected via useReducedMotion().
356
358
  *
357
359
  * @example
358
360
  * <Drawer isOpen={open} placement="right" onClose={() => setOpen(false)} title="Filters">
@@ -421,7 +423,7 @@ declare function Tabs({ tabs, onTabChange, onTabClose, isLazy, tabsClosable, def
421
423
 
422
424
  interface TreeNode {
423
425
  key: string;
424
- value: string;
426
+ label: string;
425
427
  nodeData?: any;
426
428
  parentLabel?: string;
427
429
  children?: TreeNode[];
@@ -434,26 +436,27 @@ interface TreeItemClickPayload {
434
436
  parentLabel?: string;
435
437
  }
436
438
  interface TreeProps {
437
- structure: TreeNode[];
438
- onItemClick: (payload: TreeItemClickPayload) => void;
439
+ nodes: TreeNode[];
440
+ onNodeClick: (payload: TreeItemClickPayload) => void;
439
441
  defaultExpandAll?: boolean;
440
442
  defaultExpandedKeys?: string[];
441
443
  }
442
444
  /** ─────────────────── public component ─────────────────── */
443
445
  /**
444
- * Hierarchical tree view powered by Radix Accordion (nested).
446
+ * Hierarchical tree view powered by Radix Accordion.
445
447
  *
446
- * Each parent node is an independent Accordion.Root with `type="multiple"` so
447
- * sibling branches are independent. Leaf nodes are plain clickable rows.
448
+ * Each parent node is an independent Accordion.Root with type="multiple" so
449
+ * sibling branches expand independently. Leaf nodes are plain buttons.
450
+ * Expand/collapse is animated via CSS keyframes.
448
451
  *
449
452
  * @example
450
453
  * <Tree
451
- * structure={fleetTree}
452
- * onItemClick={({ key, isParent }) => selectNode(key)}
454
+ * nodes={fleetTree}
455
+ * onNodeClick={({ key, isParent }) => selectNode(key)}
453
456
  * defaultExpandAll
454
457
  * />
455
458
  */
456
- declare function Tree({ structure, onItemClick, defaultExpandAll, defaultExpandedKeys, }: TreeProps): react_jsx_runtime.JSX.Element;
459
+ declare function Tree({ nodes, onNodeClick, defaultExpandAll, defaultExpandedKeys, }: TreeProps): react_jsx_runtime.JSX.Element;
457
460
 
458
461
  interface ToggleItem {
459
462
  key: string;
package/dist/index.d.ts CHANGED
@@ -322,14 +322,15 @@ interface ModalProps {
322
322
  children?: React$1.ReactNode;
323
323
  }
324
324
  /**
325
- * Centred modal dialog powered by Radix Dialog.
325
+ * Centred modal dialog powered by Radix Dialog + Framer Motion.
326
326
  *
327
- * The Radix primitive handles focus-trap, escape-to-close, and ARIA roles.
328
- * The VesOPS visual style (scale-in animation, prussian-blue header) is preserved.
327
+ * Radix handles focus-trap, escape-to-close, and ARIA roles.
328
+ * Framer Motion drives the scale + fade enter/exit animation.
329
+ * prefers-reduced-motion is respected via useReducedMotion().
329
330
  *
330
331
  * @example
331
332
  * <Modal isOpen={open} onClose={() => setOpen(false)} title="Confirm" onOk={handleOk}>
332
- * Are you sure?
333
+ * Are you sure you want to delete this item?
333
334
  * </Modal>
334
335
  */
335
336
  declare function Modal({ size, isOpen, onClose, onOk, onCancel, okText, cancelText, hasFooter, title, children, }: ModalProps): react_jsx_runtime.JSX.Element;
@@ -338,7 +339,7 @@ interface DrawerProps {
338
339
  isOpen?: boolean;
339
340
  onClose?: () => void;
340
341
  hasFooter?: boolean;
341
- /** 'left' | 'right' */
342
+ /** 'left' | 'right' — which edge the panel slides from */
342
343
  placement?: 'left' | 'right';
343
344
  width?: number;
344
345
  okText?: string;
@@ -349,10 +350,11 @@ interface DrawerProps {
349
350
  children?: React$1.ReactNode;
350
351
  }
351
352
  /**
352
- * Side-sliding drawer panel powered by Radix Dialog.
353
+ * Side-sliding drawer panel powered by Radix Dialog + Framer Motion.
353
354
  *
354
355
  * Radix handles focus-trap, escape-to-close, and ARIA roles.
355
- * The drawer slides in from the left or right depending on `placement`.
356
+ * Framer Motion drives the slide enter/exit animation.
357
+ * prefers-reduced-motion is respected via useReducedMotion().
356
358
  *
357
359
  * @example
358
360
  * <Drawer isOpen={open} placement="right" onClose={() => setOpen(false)} title="Filters">
@@ -421,7 +423,7 @@ declare function Tabs({ tabs, onTabChange, onTabClose, isLazy, tabsClosable, def
421
423
 
422
424
  interface TreeNode {
423
425
  key: string;
424
- value: string;
426
+ label: string;
425
427
  nodeData?: any;
426
428
  parentLabel?: string;
427
429
  children?: TreeNode[];
@@ -434,26 +436,27 @@ interface TreeItemClickPayload {
434
436
  parentLabel?: string;
435
437
  }
436
438
  interface TreeProps {
437
- structure: TreeNode[];
438
- onItemClick: (payload: TreeItemClickPayload) => void;
439
+ nodes: TreeNode[];
440
+ onNodeClick: (payload: TreeItemClickPayload) => void;
439
441
  defaultExpandAll?: boolean;
440
442
  defaultExpandedKeys?: string[];
441
443
  }
442
444
  /** ─────────────────── public component ─────────────────── */
443
445
  /**
444
- * Hierarchical tree view powered by Radix Accordion (nested).
446
+ * Hierarchical tree view powered by Radix Accordion.
445
447
  *
446
- * Each parent node is an independent Accordion.Root with `type="multiple"` so
447
- * sibling branches are independent. Leaf nodes are plain clickable rows.
448
+ * Each parent node is an independent Accordion.Root with type="multiple" so
449
+ * sibling branches expand independently. Leaf nodes are plain buttons.
450
+ * Expand/collapse is animated via CSS keyframes.
448
451
  *
449
452
  * @example
450
453
  * <Tree
451
- * structure={fleetTree}
452
- * onItemClick={({ key, isParent }) => selectNode(key)}
454
+ * nodes={fleetTree}
455
+ * onNodeClick={({ key, isParent }) => selectNode(key)}
453
456
  * defaultExpandAll
454
457
  * />
455
458
  */
456
- declare function Tree({ structure, onItemClick, defaultExpandAll, defaultExpandedKeys, }: TreeProps): react_jsx_runtime.JSX.Element;
459
+ declare function Tree({ nodes, onNodeClick, defaultExpandAll, defaultExpandedKeys, }: TreeProps): react_jsx_runtime.JSX.Element;
457
460
 
458
461
  interface ToggleItem {
459
462
  key: string;
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import React9, { createContext, useMemo, useState, useEffect, useContext, useRef, useCallback, useId } from 'react';
3
3
  import * as Dialog from '@radix-ui/react-dialog';
4
+ import { useReducedMotion, AnimatePresence, motion } from 'framer-motion';
4
5
  import * as TooltipPrimitive from '@radix-ui/react-tooltip';
5
6
  import * as TabsPrimitive from '@radix-ui/react-tabs';
6
7
  import * as Accordion from '@radix-ui/react-accordion';
@@ -288,33 +289,57 @@ function Modal({
288
289
  title,
289
290
  children
290
291
  }) {
292
+ const reduced = useReducedMotion();
291
293
  return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, onOpenChange: (open) => {
292
294
  if (!open) onClose?.();
293
- }, children: /* @__PURE__ */ jsxs(Dialog.Portal, { children: [
294
- /* @__PURE__ */ jsx(Dialog.Overlay, { className: "fixed inset-0 bg-oxford-blue-700-opaque z-50 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 transition-all duration-300" }),
295
- /* @__PURE__ */ jsxs(
296
- Dialog.Content,
295
+ }, children: /* @__PURE__ */ jsxs(Dialog.Portal, { forceMount: true, children: [
296
+ /* @__PURE__ */ jsx(AnimatePresence, { children: isOpen && /* @__PURE__ */ jsx(Dialog.Overlay, { asChild: true, children: /* @__PURE__ */ jsx(
297
+ motion.div,
298
+ {
299
+ className: "fixed inset-0 bg-oxford-blue-700-opaque z-50",
300
+ initial: { opacity: 0 },
301
+ animate: { opacity: 1 },
302
+ exit: { opacity: 0 },
303
+ transition: { duration: reduced ? 0 : 0.18, ease: "easeOut" }
304
+ }
305
+ ) }) }),
306
+ /* @__PURE__ */ jsx(AnimatePresence, { children: isOpen && /* @__PURE__ */ jsx(Dialog.Content, { asChild: true, children: /* @__PURE__ */ jsxs(
307
+ motion.div,
297
308
  {
298
- style: { width: size[0], height: size[1] },
299
- className: "fixed left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 z-50 shadow-md rounded-lg bg-white dark:bg-prussian-blue p-1 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 duration-300 focus:outline-none",
309
+ 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",
310
+ style: {
311
+ width: size[0],
312
+ height: size[1],
313
+ x: "-50%",
314
+ y: "-50%"
315
+ },
316
+ initial: { opacity: 0, scale: reduced ? 1 : 0.96 },
317
+ animate: { opacity: 1, scale: 1 },
318
+ exit: { opacity: 0, scale: reduced ? 1 : 0.96 },
319
+ transition: reduced ? { duration: 0 } : {
320
+ type: "spring",
321
+ damping: 28,
322
+ stiffness: 380,
323
+ duration: 0.25
324
+ },
300
325
  children: [
301
- /* @__PURE__ */ jsxs("div", { className: "h-[12%] flex items-center justify-between border-b border-ice dark:border-independence p-2", children: [
302
- /* @__PURE__ */ jsx(Dialog.Title, { className: "text-prussian-blue dark:text-white font-bold text-lg", children: title }),
326
+ /* @__PURE__ */ jsxs("div", { className: "flex h-14 flex-shrink-0 items-center justify-between border-b border-ice dark:border-independence px-5", children: [
327
+ /* @__PURE__ */ jsx(Dialog.Title, { className: "text-base font-semibold text-prussian-blue dark:text-white tracking-tight", children: title }),
303
328
  /* @__PURE__ */ jsx(Dialog.Close, { asChild: true, children: /* @__PURE__ */ jsx(
304
329
  "button",
305
330
  {
306
331
  "aria-label": "Close",
307
- className: "cursor-pointer rounded p-1 hover:bg-ice dark:hover:bg-independence transition-colors",
308
- children: /* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", 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" }) })
332
+ 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",
333
+ 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" }) })
309
334
  }
310
335
  ) })
311
336
  ] }),
312
- /* @__PURE__ */ jsx("div", { className: `${hasFooter ? "max-h-[77%]" : "max-h-[90%]"} p-2 overflow-y-auto`, children: isOpen && children }),
313
- hasFooter && /* @__PURE__ */ jsxs("div", { className: "flex justify-end items-center gap-5 border-t border-ice dark:border-independence h-max p-2", children: [
337
+ /* @__PURE__ */ jsx("div", { className: `flex-1 overflow-y-auto p-5 ${hasFooter ? "" : "pb-5"}`, children: isOpen && children }),
338
+ 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: [
314
339
  /* @__PURE__ */ jsx(
315
340
  Button,
316
341
  {
317
- style: { width: 100, margin: "0" },
342
+ style: { width: 90 },
318
343
  content: cancelText,
319
344
  onClick: onCancel
320
345
  }
@@ -322,7 +347,7 @@ function Modal({
322
347
  /* @__PURE__ */ jsx(
323
348
  Button,
324
349
  {
325
- style: { width: 100, margin: "0" },
350
+ style: { width: 90 },
326
351
  content: okText,
327
352
  onClick: onOk
328
353
  }
@@ -330,7 +355,7 @@ function Modal({
330
355
  ] })
331
356
  ]
332
357
  }
333
- )
358
+ ) }) })
334
359
  ] }) });
335
360
  }
336
361
  function Drawer({
@@ -346,48 +371,59 @@ function Drawer({
346
371
  title,
347
372
  children
348
373
  }) {
374
+ const reduced = useReducedMotion();
349
375
  const isRight = placement === "right";
376
+ const hiddenX = isRight ? "100%" : "-100%";
350
377
  return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, onOpenChange: (open) => {
351
378
  if (!open) onClose?.();
352
- }, children: /* @__PURE__ */ jsxs(Dialog.Portal, { children: [
353
- /* @__PURE__ */ jsx(Dialog.Overlay, { className: "fixed inset-0 bg-oxford-blue-700-opaque z-[5000] data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 duration-300" }),
354
- /* @__PURE__ */ jsxs(
355
- Dialog.Content,
379
+ }, children: /* @__PURE__ */ jsxs(Dialog.Portal, { forceMount: true, children: [
380
+ /* @__PURE__ */ jsx(AnimatePresence, { children: isOpen && /* @__PURE__ */ jsx(Dialog.Overlay, { asChild: true, children: /* @__PURE__ */ jsx(
381
+ motion.div,
382
+ {
383
+ className: "fixed inset-0 bg-oxford-blue-700-opaque z-[5000]",
384
+ initial: { opacity: 0 },
385
+ animate: { opacity: 1 },
386
+ exit: { opacity: 0 },
387
+ transition: { duration: reduced ? 0 : 0.2, ease: "easeOut" }
388
+ }
389
+ ) }) }),
390
+ /* @__PURE__ */ jsx(AnimatePresence, { children: isOpen && /* @__PURE__ */ jsx(Dialog.Content, { asChild: true, children: /* @__PURE__ */ jsxs(
391
+ motion.div,
356
392
  {
393
+ 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`,
357
394
  style: { width },
358
- className: `fixed top-0 bottom-0 ${isRight ? "right-0 data-[state=open]:slide-in-from-right data-[state=closed]:slide-out-to-right" : "left-0 data-[state=open]:slide-in-from-left data-[state=closed]:slide-out-to-left"} z-[5000] h-full shadow-md bg-white dark:bg-prussian-blue p-1 data-[state=open]:animate-in data-[state=closed]:animate-out duration-300 focus:outline-none`,
395
+ initial: { x: reduced ? 0 : hiddenX, opacity: reduced ? 0 : 1 },
396
+ animate: { x: 0, opacity: 1 },
397
+ exit: { x: reduced ? 0 : hiddenX, opacity: reduced ? 0 : 1 },
398
+ transition: reduced ? { duration: 0 } : {
399
+ x: {
400
+ type: "tween",
401
+ duration: 0.26,
402
+ ease: [0.16, 1, 0.3, 1]
403
+ // ease-out-expo
404
+ },
405
+ opacity: { duration: 0 }
406
+ },
359
407
  children: [
360
- /* @__PURE__ */ jsxs(
361
- "div",
362
- {
363
- className: `h-[5%] border-b border-ice dark:border-independence p-2 flex items-center justify-between ${isRight && "flex-row-reverse"}`,
364
- children: [
365
- /* @__PURE__ */ jsx(Dialog.Title, { className: "text-prussian-blue dark:text-white font-bold text-lg", children: title }),
366
- /* @__PURE__ */ jsx(Dialog.Close, { asChild: true, children: /* @__PURE__ */ jsx(
367
- "button",
368
- {
369
- "aria-label": "Close drawer",
370
- className: "cursor-pointer rounded p-1 hover:bg-ice dark:hover:bg-independence transition-colors",
371
- children: /* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", 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" }) })
372
- }
373
- ) })
374
- ]
375
- }
376
- ),
377
- /* @__PURE__ */ jsx("div", { className: `${hasFooter ? "h-[88%]" : "h-[95%]"} overflow-y-auto`, children: isOpen && children }),
378
- hasFooter && /* @__PURE__ */ jsxs(
379
- "div",
380
- {
381
- className: `gap-5 h-[7%] pr-2 pl-2 border-t border-ice dark:border-independence flex items-center ${isRight ? "justify-start" : "justify-end"}`,
382
- children: [
383
- /* @__PURE__ */ jsx(Button, { style: { width: 100 }, content: cancelText, onClick: onCancel }),
384
- /* @__PURE__ */ jsx(Button, { style: { width: 100 }, content: okText, onClick: onOk })
385
- ]
386
- }
387
- )
408
+ /* @__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: [
409
+ /* @__PURE__ */ jsx(Dialog.Title, { className: "text-base font-semibold text-prussian-blue dark:text-white tracking-tight", children: title }),
410
+ /* @__PURE__ */ jsx(Dialog.Close, { asChild: true, children: /* @__PURE__ */ jsx(
411
+ "button",
412
+ {
413
+ "aria-label": "Close drawer",
414
+ 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",
415
+ 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" }) })
416
+ }
417
+ ) })
418
+ ] }),
419
+ /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto p-5", children: isOpen && children }),
420
+ 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: [
421
+ /* @__PURE__ */ jsx(Button, { style: { width: 90 }, content: cancelText, onClick: onCancel }),
422
+ /* @__PURE__ */ jsx(Button, { style: { width: 90 }, content: okText, onClick: onOk })
423
+ ] })
388
424
  ]
389
425
  }
390
- )
426
+ ) }) })
391
427
  ] }) });
392
428
  }
393
429
  function Tooltip({
@@ -524,27 +560,28 @@ function Tabs({
524
560
  var isParent = (item) => Boolean(item.children && item.children.length > 0);
525
561
  function TreeNodeItem({
526
562
  item,
527
- onItemClick,
563
+ onNodeClick,
528
564
  defaultExpandAll,
529
565
  defaultExpandedKeys,
530
566
  depth = 0
531
567
  }) {
532
568
  if (!isParent(item)) {
533
569
  return /* @__PURE__ */ jsxs(
534
- "div",
570
+ "button",
535
571
  {
536
- style: { marginLeft: depth * 10 + 16 },
537
- className: "flex items-center gap-2 cursor-pointer py-0.5",
538
- onClick: () => onItemClick({
572
+ type: "button",
573
+ 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",
574
+ style: { paddingLeft: depth * 12 + 8 },
575
+ onClick: () => onNodeClick({
539
576
  isParent: false,
540
577
  key: item.key,
541
- label: item.value,
578
+ label: item.label,
542
579
  data: item.nodeData,
543
580
  parentLabel: item.parentLabel
544
581
  }),
545
582
  children: [
546
- /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: colors_default.PALETTE["prussian-blue"], strokeWidth: 2, className: "h-4 w-4 flex-shrink-0 dark:stroke-white", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", d: "M5 12h14" }) }),
547
- /* @__PURE__ */ jsx("span", { className: "text-xs text-prussian-blue dark:text-white select-none transition-all duration-300 hover:bg-ice-dark dark:hover:bg-independence rounded-lg p-1", children: item.value })
583
+ /* @__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" }),
584
+ /* @__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 })
548
585
  ]
549
586
  }
550
587
  );
@@ -555,47 +592,47 @@ function TreeNodeItem({
555
592
  {
556
593
  type: "multiple",
557
594
  defaultValue: initialOpen,
558
- style: { marginLeft: depth * 10 },
595
+ style: { paddingLeft: depth * 12 },
559
596
  children: /* @__PURE__ */ jsxs(Accordion.Item, { value: item.key, className: "border-none", children: [
560
- /* @__PURE__ */ jsxs(
561
- Accordion.Trigger,
562
- {
563
- className: "flex items-center gap-2 cursor-pointer py-0.5 group focus:outline-none w-full text-left",
564
- onClick: (e) => e.stopPropagation(),
565
- children: [
566
- /* @__PURE__ */ jsx(
567
- "svg",
568
- {
569
- viewBox: "0 0 24 24",
570
- fill: "none",
571
- stroke: colors_default.PALETTE["prussian-blue"],
572
- strokeWidth: 2,
573
- className: "h-4 w-4 flex-shrink-0 transition-transform duration-300 group-data-[state=closed]:-rotate-90 dark:stroke-white",
574
- children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" })
575
- }
576
- ),
577
- /* @__PURE__ */ jsx(
578
- "span",
597
+ /* @__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: [
598
+ /* @__PURE__ */ jsx(
599
+ "svg",
600
+ {
601
+ viewBox: "0 0 24 24",
602
+ fill: "none",
603
+ stroke: "currentColor",
604
+ strokeWidth: 2.5,
605
+ 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",
606
+ children: /* @__PURE__ */ jsx(
607
+ "path",
579
608
  {
580
- className: "text-sm font-bold text-prussian-blue dark:text-white select-none transition-all duration-300 hover:bg-ice-dark dark:hover:bg-independence rounded-lg p-1",
581
- onClick: () => onItemClick({
582
- isParent: true,
583
- key: item.key,
584
- label: item.value,
585
- data: item.nodeData,
586
- parentLabel: item.parentLabel
587
- }),
588
- children: item.value
609
+ strokeLinecap: "round",
610
+ strokeLinejoin: "round",
611
+ d: "M19 9l-7 7-7-7"
589
612
  }
590
613
  )
591
- ]
592
- }
593
- ),
594
- /* @__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-[7px] border-l border-prussian-blue dark:border-ice-dark", children: item.children.map((child) => /* @__PURE__ */ jsx(
614
+ }
615
+ ),
616
+ /* @__PURE__ */ jsx(
617
+ "span",
618
+ {
619
+ className: "text-sm font-semibold text-prussian-blue dark:text-white select-none",
620
+ onClick: () => onNodeClick({
621
+ isParent: true,
622
+ key: item.key,
623
+ label: item.label,
624
+ data: item.nodeData,
625
+ parentLabel: item.parentLabel
626
+ }),
627
+ children: item.label
628
+ }
629
+ )
630
+ ] }),
631
+ /* @__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(
595
632
  TreeNodeItem,
596
633
  {
597
634
  item: child,
598
- onItemClick,
635
+ onNodeClick,
599
636
  defaultExpandAll,
600
637
  defaultExpandedKeys,
601
638
  depth: depth + 1
@@ -607,16 +644,16 @@ function TreeNodeItem({
607
644
  );
608
645
  }
609
646
  function Tree({
610
- structure,
611
- onItemClick,
647
+ nodes,
648
+ onNodeClick,
612
649
  defaultExpandAll = false,
613
650
  defaultExpandedKeys = []
614
651
  }) {
615
- return /* @__PURE__ */ jsx("div", { className: "p-2", children: structure.map((item) => /* @__PURE__ */ jsx(
652
+ return /* @__PURE__ */ jsx("div", { className: "p-1 w-full", children: nodes.map((item) => /* @__PURE__ */ jsx(
616
653
  TreeNodeItem,
617
654
  {
618
655
  item,
619
- onItemClick,
656
+ onNodeClick,
620
657
  defaultExpandAll,
621
658
  defaultExpandedKeys
622
659
  },