@geomak/ui 7.3.0 → 7.3.2

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
@@ -5,7 +5,7 @@ import React30, { createContext, useState, useEffect, useMemo, useId, useCallbac
5
5
  import { createPortal } from 'react-dom';
6
6
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
7
7
  import * as AvatarPrimitive from '@radix-ui/react-avatar';
8
- import * as DropdownMenu from '@radix-ui/react-dropdown-menu';
8
+ import * as DropdownMenu2 from '@radix-ui/react-dropdown-menu';
9
9
  import * as Dialog from '@radix-ui/react-dialog';
10
10
  import { useReducedMotion, AnimatePresence, motion, useScroll, useTransform } from 'framer-motion';
11
11
  import * as TooltipPrimitive from '@radix-ui/react-tooltip';
@@ -636,8 +636,8 @@ function MenuButton({
636
636
  side = "bottom",
637
637
  className = ""
638
638
  }) {
639
- return /* @__PURE__ */ jsxs(DropdownMenu.Root, { children: [
640
- /* @__PURE__ */ jsx(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(
639
+ return /* @__PURE__ */ jsxs(DropdownMenu2.Root, { children: [
640
+ /* @__PURE__ */ jsx(DropdownMenu2.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(
641
641
  Button_default,
642
642
  {
643
643
  variant,
@@ -651,8 +651,8 @@ function MenuButton({
651
651
  ] })
652
652
  }
653
653
  ) }),
654
- /* @__PURE__ */ jsx(DropdownMenu.Portal, { children: /* @__PURE__ */ jsx(
655
- DropdownMenu.Content,
654
+ /* @__PURE__ */ jsx(DropdownMenu2.Portal, { children: /* @__PURE__ */ jsx(
655
+ DropdownMenu2.Content,
656
656
  {
657
657
  align,
658
658
  side,
@@ -664,9 +664,9 @@ function MenuButton({
664
664
  "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95"
665
665
  ].join(" "),
666
666
  children: items.map((item) => /* @__PURE__ */ jsxs(React30.Fragment, { children: [
667
- item.separatorBefore && /* @__PURE__ */ jsx(DropdownMenu.Separator, { className: "my-1 h-px bg-border" }),
667
+ item.separatorBefore && /* @__PURE__ */ jsx(DropdownMenu2.Separator, { className: "my-1 h-px bg-border" }),
668
668
  /* @__PURE__ */ jsxs(
669
- DropdownMenu.Item,
669
+ DropdownMenu2.Item,
670
670
  {
671
671
  disabled: item.disabled,
672
672
  onSelect: () => item.onSelect?.(),
@@ -1666,7 +1666,7 @@ function Stepper({
1666
1666
  const vertical = orientation === "vertical" || forcedVertical;
1667
1667
  const s = SIZES[size];
1668
1668
  const stateOf = (i) => i < current ? "completed" : i === current ? status : "pending";
1669
- const Label = ({ step, state, align }) => /* @__PURE__ */ jsxs("div", { className: align === "center" ? "mt-2 text-center" : "pt-0.5", children: [
1669
+ const Label2 = ({ step, state, align }) => /* @__PURE__ */ jsxs("div", { className: align === "center" ? "mt-2 text-center" : "pt-0.5", children: [
1670
1670
  /* @__PURE__ */ jsx("div", { className: `font-medium leading-tight ${s.title} ${state === "pending" ? "text-foreground-muted" : "text-foreground"}`, children: step.title }),
1671
1671
  step.description && /* @__PURE__ */ jsx("div", { className: `mt-0.5 leading-snug text-foreground-muted ${s.desc}`, children: step.description })
1672
1672
  ] });
@@ -1681,7 +1681,7 @@ function Stepper({
1681
1681
  stepButton(i, /* @__PURE__ */ jsx(Indicator, { state, index: i, step, sizeKey: size })),
1682
1682
  !last && /* @__PURE__ */ jsx(VConnector, { filled: i < current, reduced })
1683
1683
  ] }),
1684
- /* @__PURE__ */ jsx("div", { className: last ? "" : "pb-6", children: stepButton(i, /* @__PURE__ */ jsx(Label, { step, state, align: "left" })) })
1684
+ /* @__PURE__ */ jsx("div", { className: last ? "" : "pb-6", children: stepButton(i, /* @__PURE__ */ jsx(Label2, { step, state, align: "left" })) })
1685
1685
  ] }, step.key);
1686
1686
  }) });
1687
1687
  }
@@ -1700,7 +1700,7 @@ function Stepper({
1700
1700
  ) }),
1701
1701
  stepButton(i, /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center", children: [
1702
1702
  /* @__PURE__ */ jsx(Indicator, { state, index: i, step, sizeKey: size }),
1703
- /* @__PURE__ */ jsx(Label, { step, state, align: "center" })
1703
+ /* @__PURE__ */ jsx(Label2, { step, state, align: "center" })
1704
1704
  ] }))
1705
1705
  ] }, step.key);
1706
1706
  }) });
@@ -5852,13 +5852,82 @@ function TopBar({
5852
5852
  }
5853
5853
  );
5854
5854
  }
5855
+ function hasActiveDescendant(item) {
5856
+ return !!item.items?.some((c) => c.isActive || hasActiveDescendant(c));
5857
+ }
5858
+ var FLYOUT_PANEL = "z-[400] min-w-[11rem] rounded-lg border border-border bg-surface p-1 shadow-lg data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95";
5859
+ function FlyoutItems({ items }) {
5860
+ return /* @__PURE__ */ jsx(Fragment, { children: items.map((child) => {
5861
+ const cls = [
5862
+ "flex items-center gap-2.5 rounded-md px-2.5 py-1.5 text-sm outline-none cursor-pointer select-none transition-colors",
5863
+ child.isActive ? "text-accent data-[highlighted]:bg-accent/10" : "text-foreground data-[highlighted]:bg-surface-raised"
5864
+ ].join(" ");
5865
+ const label = /* @__PURE__ */ jsxs(Fragment, { children: [
5866
+ /* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: child.label }),
5867
+ child.badge !== void 0 && child.badge > 0 && /* @__PURE__ */ jsx("span", { className: "flex h-4 min-w-4 items-center justify-center rounded-full bg-status-error px-1 text-[9px] font-bold leading-none text-white", children: child.badge > 99 ? "99+" : child.badge })
5868
+ ] });
5869
+ if (child.items?.length) {
5870
+ return /* @__PURE__ */ jsxs(DropdownMenu2.Sub, { children: [
5871
+ /* @__PURE__ */ jsxs(DropdownMenu2.SubTrigger, { className: cls, children: [
5872
+ label,
5873
+ /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, "aria-hidden": "true", className: "h-3.5 w-3.5 flex-shrink-0", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "m9 6 6 6-6 6" }) })
5874
+ ] }),
5875
+ /* @__PURE__ */ jsx(DropdownMenu2.Portal, { children: /* @__PURE__ */ jsx(DropdownMenu2.SubContent, { sideOffset: 6, collisionPadding: 8, className: FLYOUT_PANEL, children: /* @__PURE__ */ jsx(FlyoutItems, { items: child.items }) }) })
5876
+ ] }, child.key);
5877
+ }
5878
+ return /* @__PURE__ */ jsx(DropdownMenu2.Item, { onSelect: () => child.onClick?.(), className: cls, children: label }, child.key);
5879
+ }) });
5880
+ }
5881
+ function CollapsedFlyout({ item, trigger }) {
5882
+ const [open, setOpen] = useState(false);
5883
+ const closeTimer = React30.useRef(void 0);
5884
+ const openNow = () => {
5885
+ window.clearTimeout(closeTimer.current);
5886
+ setOpen(true);
5887
+ };
5888
+ const closeSoon = () => {
5889
+ window.clearTimeout(closeTimer.current);
5890
+ closeTimer.current = window.setTimeout(() => setOpen(false), 150);
5891
+ };
5892
+ React30.useEffect(() => () => window.clearTimeout(closeTimer.current), []);
5893
+ return /* @__PURE__ */ jsxs(DropdownMenu2.Root, { open, onOpenChange: setOpen, modal: false, children: [
5894
+ /* @__PURE__ */ jsx(
5895
+ DropdownMenu2.Trigger,
5896
+ {
5897
+ asChild: true,
5898
+ onPointerEnter: openNow,
5899
+ onPointerLeave: closeSoon,
5900
+ onPointerDown: (e) => {
5901
+ if (e.pointerType === "mouse") e.preventDefault();
5902
+ },
5903
+ children: trigger
5904
+ }
5905
+ ),
5906
+ /* @__PURE__ */ jsx(DropdownMenu2.Portal, { children: /* @__PURE__ */ jsxs(
5907
+ DropdownMenu2.Content,
5908
+ {
5909
+ side: "right",
5910
+ align: "start",
5911
+ sideOffset: 8,
5912
+ collisionPadding: 8,
5913
+ className: FLYOUT_PANEL,
5914
+ onPointerEnter: openNow,
5915
+ onPointerLeave: closeSoon,
5916
+ children: [
5917
+ /* @__PURE__ */ jsx(DropdownMenu2.Label, { className: "px-2.5 pb-1 pt-1.5 text-xs font-semibold text-foreground-muted", children: item.label }),
5918
+ /* @__PURE__ */ jsx(FlyoutItems, { items: item.items })
5919
+ ]
5920
+ }
5921
+ ) })
5922
+ ] });
5923
+ }
5855
5924
  function NavItem({
5856
5925
  item,
5857
5926
  isExpanded,
5858
5927
  depth = 0
5859
5928
  }) {
5860
5929
  const hasChildren = !!(item.items && item.items.length);
5861
- const [open, setOpen] = useState(item.defaultOpen ?? (hasChildren && !!item.items?.some((c) => c.isActive)));
5930
+ const [open, setOpen] = useState(item.defaultOpen ?? (hasChildren && hasActiveDescendant(item)));
5862
5931
  const handleClick = () => {
5863
5932
  if (hasChildren && isExpanded) setOpen((o) => !o);
5864
5933
  item.onClick?.();
@@ -5868,13 +5937,14 @@ function NavItem({
5868
5937
  {
5869
5938
  type: "button",
5870
5939
  onClick: handleClick,
5940
+ "aria-label": !isExpanded && typeof item.label === "string" ? item.label : void 0,
5871
5941
  "aria-expanded": hasChildren && isExpanded ? open : void 0,
5872
5942
  style: isExpanded && depth > 0 ? { paddingLeft: 10 + depth * 18 } : void 0,
5873
5943
  className: [
5874
5944
  "group relative flex w-full items-center gap-2.5 rounded-md",
5875
5945
  "px-2.5 py-2 transition-colors duration-100",
5876
5946
  "focus:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-inset",
5877
- item.isActive ? "bg-accent/10 text-accent" : "text-foreground-secondary hover:bg-surface-raised hover:text-foreground"
5947
+ item.isActive || !isExpanded && hasActiveDescendant(item) ? "bg-accent/10 text-accent" : "text-foreground-secondary hover:bg-surface-raised hover:text-foreground"
5878
5948
  ].join(" "),
5879
5949
  children: [
5880
5950
  /* @__PURE__ */ jsxs("span", { className: "relative flex h-5 w-5 flex-shrink-0 items-center justify-center", children: [
@@ -5899,6 +5969,7 @@ function NavItem({
5899
5969
  }
5900
5970
  );
5901
5971
  if (!isExpanded) {
5972
+ if (hasChildren) return /* @__PURE__ */ jsx(CollapsedFlyout, { item, trigger: btn });
5902
5973
  return /* @__PURE__ */ jsx(Tooltip, { title: item.label, placement: "right", delayDuration: 200, children: btn });
5903
5974
  }
5904
5975
  if (!hasChildren) return btn;