@geomak/ui 6.2.1 → 6.2.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
@@ -1648,6 +1648,16 @@ interface MegaMenuProps {
1648
1648
  align?: 'start' | 'center' | 'end';
1649
1649
  /** Delay (ms) before a hovered item opens. Default `200`. */
1650
1650
  delayDuration?: number;
1651
+ /**
1652
+ * Below the `md` breakpoint, collapse the hover bar into a tap-friendly
1653
+ * hamburger disclosure (a vertical accordion of the same items). Hover
1654
+ * mega-panels don't work on touch, so this is the graceful fallback.
1655
+ * Set `false` to render the desktop bar at every width (e.g. when you
1656
+ * provide your own mobile navigation). Default `true`.
1657
+ */
1658
+ responsive?: boolean;
1659
+ /** Label for the mobile disclosure toggle. Default `'Menu'`. */
1660
+ mobileLabel?: React__default.ReactNode;
1651
1661
  /** Extra classes merged onto the menu bar root. */
1652
1662
  className?: string;
1653
1663
  style?: React__default.CSSProperties;
@@ -1680,7 +1690,7 @@ interface MegaMenuProps {
1680
1690
  * </MegaMenu>
1681
1691
  * ```
1682
1692
  */
1683
- declare function MegaMenu({ children, align, delayDuration, className, style, 'aria-label': ariaLabel }: MegaMenuProps): react_jsx_runtime.JSX.Element;
1693
+ declare function MegaMenu({ children, align, delayDuration, responsive, mobileLabel, className, style, 'aria-label': ariaLabel, }: MegaMenuProps): react_jsx_runtime.JSX.Element;
1684
1694
  declare namespace MegaMenu {
1685
1695
  var Item: typeof MegaMenuItem;
1686
1696
  var Panel: typeof MegaMenuPanel;
package/dist/index.d.ts CHANGED
@@ -1648,6 +1648,16 @@ interface MegaMenuProps {
1648
1648
  align?: 'start' | 'center' | 'end';
1649
1649
  /** Delay (ms) before a hovered item opens. Default `200`. */
1650
1650
  delayDuration?: number;
1651
+ /**
1652
+ * Below the `md` breakpoint, collapse the hover bar into a tap-friendly
1653
+ * hamburger disclosure (a vertical accordion of the same items). Hover
1654
+ * mega-panels don't work on touch, so this is the graceful fallback.
1655
+ * Set `false` to render the desktop bar at every width (e.g. when you
1656
+ * provide your own mobile navigation). Default `true`.
1657
+ */
1658
+ responsive?: boolean;
1659
+ /** Label for the mobile disclosure toggle. Default `'Menu'`. */
1660
+ mobileLabel?: React__default.ReactNode;
1651
1661
  /** Extra classes merged onto the menu bar root. */
1652
1662
  className?: string;
1653
1663
  style?: React__default.CSSProperties;
@@ -1680,7 +1690,7 @@ interface MegaMenuProps {
1680
1690
  * </MegaMenu>
1681
1691
  * ```
1682
1692
  */
1683
- declare function MegaMenu({ children, align, delayDuration, className, style, 'aria-label': ariaLabel }: MegaMenuProps): react_jsx_runtime.JSX.Element;
1693
+ declare function MegaMenu({ children, align, delayDuration, responsive, mobileLabel, className, style, 'aria-label': ariaLabel, }: MegaMenuProps): react_jsx_runtime.JSX.Element;
1684
1694
  declare namespace MegaMenu {
1685
1695
  var Item: typeof MegaMenuItem;
1686
1696
  var Panel: typeof MegaMenuPanel;
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
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 React8, { createContext, useState, useEffect, useMemo, useId, useCallback, useRef, useContext, useLayoutEffect, useSyncExternalStore } from 'react';
4
+ import React12, { createContext, useState, useEffect, useMemo, useId, useCallback, useRef, useContext, useLayoutEffect, useSyncExternalStore } from 'react';
5
5
  import { createPortal } from 'react-dom';
6
6
  import * as AvatarPrimitive from '@radix-ui/react-avatar';
7
7
  import * as Dialog from '@radix-ui/react-dialog';
@@ -2471,7 +2471,7 @@ function Field({
2471
2471
  );
2472
2472
  }
2473
2473
  var SearchIcon = /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", className: "w-4 h-4", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { fillRule: "evenodd", d: "M10.5 3.75a6.75 6.75 0 100 13.5 6.75 6.75 0 000-13.5zM2.25 10.5a8.25 8.25 0 1114.59 5.28l4.69 4.69a.75.75 0 11-1.06 1.06l-4.69-4.69A8.25 8.25 0 012.25 10.5z", clipRule: "evenodd" }) });
2474
- var SearchInput = React8.forwardRef(function SearchInput2({ value, onChange, disabled, label, htmlFor, placeholder, name, inputStyle, style, layout = "vertical", size = "md", icon, helperText, className }, ref) {
2474
+ var SearchInput = React12.forwardRef(function SearchInput2({ value, onChange, disabled, label, htmlFor, placeholder, name, inputStyle, style, layout = "vertical", size = "md", icon, helperText, className }, ref) {
2475
2475
  return /* @__PURE__ */ jsx(Field, { className, label, htmlFor, layout, helperText, children: /* @__PURE__ */ jsxs(
2476
2476
  "div",
2477
2477
  {
@@ -2958,6 +2958,7 @@ function TableBody({
2958
2958
  getRowKey
2959
2959
  }) {
2960
2960
  const [expanded, setExpanded] = useState(() => /* @__PURE__ */ new Set());
2961
+ const reduced = useReducedMotion();
2961
2962
  const toggleRow = (rowKey) => {
2962
2963
  setExpanded((prev) => {
2963
2964
  const next = new Set(prev);
@@ -2971,7 +2972,7 @@ function TableBody({
2971
2972
  return /* @__PURE__ */ jsx("tbody", { children: rows.map((row, i) => {
2972
2973
  const rowKey = getRowKey(row, i);
2973
2974
  const isExpanded = expanded.has(rowKey);
2974
- return /* @__PURE__ */ jsxs(React8.Fragment, { children: [
2975
+ return /* @__PURE__ */ jsxs(React12.Fragment, { children: [
2975
2976
  /* @__PURE__ */ jsxs(
2976
2977
  "tr",
2977
2978
  {
@@ -2999,7 +3000,19 @@ function TableBody({
2999
3000
  ]
3000
3001
  }
3001
3002
  ),
3002
- hasExpand && isExpanded && /* @__PURE__ */ jsx("tr", { className: "bg-surface", children: /* @__PURE__ */ jsx("td", { colSpan: expandColCount, className: "p-0 border-b border-border", children: /* @__PURE__ */ jsx("div", { className: "p-3", children: expandRow.expandComponent?.(row) }) }) })
3003
+ hasExpand && /* @__PURE__ */ jsx("tr", { className: "bg-surface", children: /* @__PURE__ */ jsx("td", { colSpan: expandColCount, className: "p-0", children: /* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: isExpanded && /* @__PURE__ */ jsx(
3004
+ motion.div,
3005
+ {
3006
+ initial: { height: 0, opacity: 0 },
3007
+ animate: { height: "auto", opacity: 1 },
3008
+ exit: { height: 0, opacity: 0 },
3009
+ transition: reduced ? { duration: 0 } : { height: { duration: 0.28, ease: [0.16, 1, 0.3, 1] }, opacity: { duration: 0.2 } },
3010
+ style: { overflow: "hidden" },
3011
+ className: "border-b border-border",
3012
+ children: /* @__PURE__ */ jsx("div", { className: "p-3", children: expandRow.expandComponent?.(row) })
3013
+ },
3014
+ "expand"
3015
+ ) }) }) })
3003
3016
  ] }, rowKey);
3004
3017
  }) });
3005
3018
  }
@@ -3388,17 +3401,33 @@ function Sidebar({
3388
3401
  ) });
3389
3402
  }
3390
3403
  var MegaMenuContext = createContext({ align: "start" });
3391
- function MegaMenu({ children, align = "start", delayDuration = 200, className = "", style, "aria-label": ariaLabel }) {
3392
- return /* @__PURE__ */ jsx(MegaMenuContext.Provider, { value: { align }, children: /* @__PURE__ */ jsx(
3393
- NavigationMenu.Root,
3394
- {
3395
- delayDuration,
3396
- "aria-label": ariaLabel,
3397
- className: ["relative z-10 flex w-full", className].filter(Boolean).join(" "),
3398
- style,
3399
- children: /* @__PURE__ */ jsx(NavigationMenu.List, { className: "flex items-center gap-1", children })
3400
- }
3401
- ) });
3404
+ function MegaMenu({
3405
+ children,
3406
+ align = "start",
3407
+ delayDuration = 200,
3408
+ responsive = true,
3409
+ mobileLabel = "Menu",
3410
+ className = "",
3411
+ style,
3412
+ "aria-label": ariaLabel
3413
+ }) {
3414
+ return /* @__PURE__ */ jsxs(MegaMenuContext.Provider, { value: { align }, children: [
3415
+ /* @__PURE__ */ jsx(
3416
+ NavigationMenu.Root,
3417
+ {
3418
+ delayDuration,
3419
+ "aria-label": ariaLabel,
3420
+ className: [
3421
+ "relative z-10 w-full",
3422
+ responsive ? "hidden md:flex" : "flex",
3423
+ className
3424
+ ].filter(Boolean).join(" "),
3425
+ style,
3426
+ children: /* @__PURE__ */ jsx(NavigationMenu.List, { className: "flex items-center gap-1", children })
3427
+ }
3428
+ ),
3429
+ responsive && /* @__PURE__ */ jsx(MegaMenuMobile, { label: mobileLabel, children })
3430
+ ] });
3402
3431
  }
3403
3432
  var TOP_ITEM = "group/top inline-flex items-center gap-1.5 h-10 px-3 rounded-md text-sm font-medium select-none text-foreground-secondary hover:text-foreground hover:bg-surface-raised data-[state=open]:text-accent data-[active]:text-accent transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-accent";
3404
3433
  function MegaMenuItem({ label, icon, href, children, className = "" }) {
@@ -3439,18 +3468,24 @@ function MegaMenuItem({ label, icon, href, children, className = "" }) {
3439
3468
  ] });
3440
3469
  }
3441
3470
  function MegaMenuPanel({ children, columns, className = "", style }) {
3442
- const maxWidth = columns ? `${columns * 248}px` : "min(92vw, 880px)";
3471
+ const layout = columns ? {
3472
+ gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))`,
3473
+ width: `min(92vw, ${columns * 272}px)`
3474
+ } : {
3475
+ gridTemplateColumns: "repeat(auto-fit, minmax(220px, 1fr))",
3476
+ width: "min(92vw, 760px)"
3477
+ };
3443
3478
  return /* @__PURE__ */ jsx(
3444
3479
  "div",
3445
3480
  {
3446
- className: ["flex flex-wrap gap-6 p-6", className].filter(Boolean).join(" "),
3447
- style: { maxWidth, ...style },
3481
+ className: ["grid gap-6 p-6", className].filter(Boolean).join(" "),
3482
+ style: { ...layout, maxWidth: "min(92vw, 960px)", ...style },
3448
3483
  children
3449
3484
  }
3450
3485
  );
3451
3486
  }
3452
3487
  function MegaMenuSection({ title, children, className = "" }) {
3453
- return /* @__PURE__ */ jsxs("div", { className: ["min-w-[200px] flex flex-col", className].filter(Boolean).join(" "), children: [
3488
+ return /* @__PURE__ */ jsxs("div", { className: ["min-w-0 flex flex-col", className].filter(Boolean).join(" "), children: [
3454
3489
  title && /* @__PURE__ */ jsx("p", { className: "px-3 pb-1.5 text-[11px] font-semibold uppercase tracking-widest text-foreground-muted select-none", children: title }),
3455
3490
  /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-0.5", children })
3456
3491
  ] });
@@ -3479,7 +3514,124 @@ function MegaMenuLink({ href, icon, description, active, onClick, children, clas
3479
3514
  );
3480
3515
  }
3481
3516
  function MegaMenuFeatured({ children, className = "" }) {
3482
- return /* @__PURE__ */ jsx("div", { className: ["min-w-[220px] rounded-lg bg-surface-raised border border-border p-4 flex flex-col", className].filter(Boolean).join(" "), children });
3517
+ return /* @__PURE__ */ jsx("div", { className: ["min-w-0 rounded-lg bg-surface-raised border border-border p-4 flex flex-col", className].filter(Boolean).join(" "), children });
3518
+ }
3519
+ var elementsOfType = (children, type) => React12.Children.toArray(children).filter(
3520
+ (c) => React12.isValidElement(c) && c.type === type
3521
+ );
3522
+ var MOBILE_CHEVRON = /* @__PURE__ */ jsx(
3523
+ "svg",
3524
+ {
3525
+ viewBox: "0 0 24 24",
3526
+ fill: "none",
3527
+ stroke: "currentColor",
3528
+ strokeWidth: 2,
3529
+ "aria-hidden": "true",
3530
+ className: "h-4 w-4 flex-shrink-0 text-foreground-muted transition-transform duration-200",
3531
+ children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" })
3532
+ }
3533
+ );
3534
+ function MobileLinkRow({ link, onNavigate }) {
3535
+ const { href, icon, description, active, onClick, children } = link.props;
3536
+ return /* @__PURE__ */ jsxs(
3537
+ "a",
3538
+ {
3539
+ href,
3540
+ onClick: (e) => {
3541
+ onClick?.(e);
3542
+ onNavigate();
3543
+ },
3544
+ "data-active": active ? "" : void 0,
3545
+ className: "flex items-start gap-3 rounded-md p-2.5 transition-colors select-none\n hover:bg-surface-raised focus:outline-none focus-visible:ring-2 focus-visible:ring-accent\n data-[active]:bg-surface-raised",
3546
+ children: [
3547
+ icon && /* @__PURE__ */ jsx("span", { className: "flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-md bg-surface-raised text-accent", children: /* @__PURE__ */ jsx("span", { className: "h-[17px] w-[17px] inline-flex items-center justify-center", children: icon }) }),
3548
+ /* @__PURE__ */ jsxs("span", { className: "flex flex-col min-w-0", children: [
3549
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-foreground data-[active]:text-accent", children }),
3550
+ description && /* @__PURE__ */ jsx("span", { className: "text-xs text-foreground-muted leading-snug mt-0.5", children: description })
3551
+ ] })
3552
+ ]
3553
+ }
3554
+ );
3555
+ }
3556
+ function MobilePanel({ panel, onNavigate }) {
3557
+ const nodes = React12.Children.toArray(panel.props.children);
3558
+ return /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-4 px-2 pb-3 pt-1", children: nodes.map((node, i) => {
3559
+ if (!React12.isValidElement(node)) return null;
3560
+ const el = node;
3561
+ if (el.type === MegaMenuSection) {
3562
+ const { title, children } = el.props;
3563
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
3564
+ title && /* @__PURE__ */ jsx("p", { className: "px-2.5 pb-1 text-[11px] font-semibold uppercase tracking-widest text-foreground-muted select-none", children: title }),
3565
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-0.5", children: elementsOfType(children, MegaMenuLink).map((lnk, j) => /* @__PURE__ */ jsx(MobileLinkRow, { link: lnk, onNavigate }, j)) })
3566
+ ] }, i);
3567
+ }
3568
+ if (el.type === MegaMenuFeatured) {
3569
+ return /* @__PURE__ */ jsx("div", { className: "rounded-lg bg-surface-raised border border-border p-3 flex flex-col", children: el.props.children }, i);
3570
+ }
3571
+ return /* @__PURE__ */ jsx("div", { children: node }, i);
3572
+ }) });
3573
+ }
3574
+ function MegaMenuMobile({
3575
+ children,
3576
+ label
3577
+ }) {
3578
+ const [open, setOpen] = useState(false);
3579
+ const [expanded, setExpanded] = useState(null);
3580
+ const items = elementsOfType(children, MegaMenuItem);
3581
+ return /* @__PURE__ */ jsxs("div", { className: "md:hidden w-full", children: [
3582
+ /* @__PURE__ */ jsxs(
3583
+ "button",
3584
+ {
3585
+ type: "button",
3586
+ onClick: () => setOpen((o) => !o),
3587
+ "aria-expanded": open,
3588
+ className: "inline-flex items-center gap-2 h-10 px-3 rounded-md text-sm font-medium\n text-foreground-secondary hover:text-foreground hover:bg-surface-raised\n focus:outline-none focus-visible:ring-2 focus-visible:ring-accent transition-colors",
3589
+ children: [
3590
+ /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, "aria-hidden": "true", className: "h-5 w-5", children: open ? /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 6l12 12M18 6L6 18" }) : /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M4 7h16M4 12h16M4 17h16" }) }),
3591
+ label
3592
+ ]
3593
+ }
3594
+ ),
3595
+ open && /* @__PURE__ */ jsx("div", { className: "mt-2 overflow-hidden rounded-lg border border-border bg-surface shadow-lg", children: items.map((item, i) => {
3596
+ const { label: itemLabel, icon, href, children: panel } = item.props;
3597
+ const hasPanel = panel != null;
3598
+ const isOpen = expanded === i;
3599
+ const rowBase = "flex w-full items-center gap-2 px-3 h-11 text-sm font-medium text-foreground-secondary hover:bg-surface-raised hover:text-foreground transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-accent";
3600
+ const divider = i > 0 ? "border-t border-border" : "";
3601
+ if (!hasPanel) {
3602
+ return /* @__PURE__ */ jsxs(
3603
+ "a",
3604
+ {
3605
+ href,
3606
+ onClick: () => setOpen(false),
3607
+ className: [rowBase, divider].filter(Boolean).join(" "),
3608
+ children: [
3609
+ icon && /* @__PURE__ */ jsx("span", { className: "flex h-4 w-4 flex-shrink-0 items-center justify-center", children: icon }),
3610
+ itemLabel
3611
+ ]
3612
+ },
3613
+ i
3614
+ );
3615
+ }
3616
+ return /* @__PURE__ */ jsxs("div", { className: divider || void 0, children: [
3617
+ /* @__PURE__ */ jsxs(
3618
+ "button",
3619
+ {
3620
+ type: "button",
3621
+ onClick: () => setExpanded(isOpen ? null : i),
3622
+ "aria-expanded": isOpen,
3623
+ className: [rowBase, isOpen ? "text-accent" : ""].filter(Boolean).join(" "),
3624
+ children: [
3625
+ icon && /* @__PURE__ */ jsx("span", { className: "flex h-4 w-4 flex-shrink-0 items-center justify-center", children: icon }),
3626
+ /* @__PURE__ */ jsx("span", { className: "flex-1 text-left", children: itemLabel }),
3627
+ /* @__PURE__ */ jsx("span", { className: isOpen ? "rotate-180" : "", children: MOBILE_CHEVRON })
3628
+ ]
3629
+ }
3630
+ ),
3631
+ isOpen && /* @__PURE__ */ jsx(MobilePanel, { panel, onNavigate: () => setOpen(false) })
3632
+ ] }, i);
3633
+ }) })
3634
+ ] });
3483
3635
  }
3484
3636
  MegaMenu.Item = MegaMenuItem;
3485
3637
  MegaMenu.Panel = MegaMenuPanel;
@@ -3697,7 +3849,7 @@ function ThemeProvider({
3697
3849
  className = "",
3698
3850
  style
3699
3851
  }) {
3700
- const id = React8.useId().replace(/:/g, "");
3852
+ const id = React12.useId().replace(/:/g, "");
3701
3853
  const scopeClass = `geo-th-${id}`;
3702
3854
  const divRef = useRef(null);
3703
3855
  useEffect(() => {
@@ -5701,7 +5853,7 @@ function OtpInput({
5701
5853
  emit(valid.join(""));
5702
5854
  focusBox(valid.length);
5703
5855
  };
5704
- return /* @__PURE__ */ jsx(Field, { className, label, htmlFor, errorId, errorMessage, required, layout, helperText, children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", role: "group", "aria-label": typeof label === "string" ? label : "One-time code", children: chars.map((char, idx) => /* @__PURE__ */ jsxs(React8.Fragment, { children: [
5856
+ return /* @__PURE__ */ jsx(Field, { className, label, htmlFor, errorId, errorMessage, required, layout, helperText, children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", role: "group", "aria-label": typeof label === "string" ? label : "One-time code", children: chars.map((char, idx) => /* @__PURE__ */ jsxs(React12.Fragment, { children: [
5705
5857
  /* @__PURE__ */ jsx(
5706
5858
  "input",
5707
5859
  {