@geomak/ui 2.0.0 → 3.0.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
@@ -928,34 +928,87 @@ interface ContextMenuPosition {
928
928
  }
929
929
 
930
930
  interface WizardStep {
931
- /** Ref to the DOM element to highlight */
932
- stepRef: React$1.RefObject<HTMLElement>;
931
+ /** Ref to the DOM element to highlight for this step. */
932
+ stepRef: React$1.RefObject<HTMLElement | null>;
933
+ /** Tooltip body content. */
933
934
  description: React$1.ReactNode;
934
- /** 'natural' | 'center' — controls tooltip position relative to target */
935
- positioning?: 'natural' | 'center';
935
+ /**
936
+ * Tooltip placement relative to the highlighted element.
937
+ * - `'right'` (default) — to the right of the highlight
938
+ * - `'left'` — to the left of the highlight
939
+ * - `'top'` — above the highlight
940
+ * - `'bottom'` — below the highlight
941
+ */
942
+ placement?: 'right' | 'left' | 'top' | 'bottom';
943
+ /** Optional heading for the step's tooltip. */
944
+ title?: React$1.ReactNode;
936
945
  }
937
946
  interface WizardProps {
947
+ /** The wrapped subtree — refs in `steps` point into this tree. */
938
948
  children: React$1.ReactNode;
949
+ /** Ordered list of steps to walk the user through. */
939
950
  steps: WizardStep[];
940
- /** localStorage key used to remember dismissal (default: 'oxygen_wizard') */
941
- storageKey?: string;
951
+ /**
952
+ * `localStorage` key used to remember dismissal. When the user clicks
953
+ * "Done" (or "Skip" when dismissible), this key is set so the wizard
954
+ * won't reopen on subsequent mounts.
955
+ *
956
+ * Pass `null` to disable persistence entirely (useful for tests or
957
+ * tours that should always run).
958
+ *
959
+ * Default: `'oxygen.wizard.completed'`.
960
+ */
961
+ storageKey?: string | null;
962
+ /** Show a "Skip tour" button + Esc-to-dismiss. Default `true`. */
963
+ dismissible?: boolean;
964
+ /** Called when the user reaches the final step's "Done" button. */
965
+ onComplete?: () => void;
966
+ /** Called when the user skips (or presses Esc) before completing. */
967
+ onSkip?: () => void;
942
968
  }
943
969
  /**
944
- * Guided-tour overlay wizard.
970
+ * Guided-tour overlay that walks the user through a sequence of UI elements.
971
+ *
972
+ * Highlights each step's target element with an outlined "spotlight", shows a
973
+ * tooltip with the description, and provides Prev / Next / Done navigation.
974
+ * The wrapped tree is rendered unchanged; the overlay sits on top of it via a
975
+ * portal so it always covers the real viewport regardless of where Wizard
976
+ * lives in the React tree.
945
977
  *
946
- * Highlights a DOM element via a border, then shows a floating tooltip
947
- * adjacent to it. Remembers dismissal via localStorage.
978
+ * **What's improved over the previous version**
979
+ * - `localStorage` access is SSR-safe and try/catch-guarded (Safari private
980
+ * mode, quota exceeded, no-storage browsers all degrade silently).
981
+ * - No more `classList.add(...)` on consumer-owned DOM. The spotlight is a
982
+ * portaled outline rectangle that tracks the target's bbox via
983
+ * `ResizeObserver` + scroll/resize listeners. The consumer's DOM is never
984
+ * mutated, so unmounting Wizard mid-tour leaves no orphan classes.
985
+ * - Focus trap inside the tooltip — Tab and Shift+Tab cycle through the
986
+ * tooltip's buttons. Esc dismisses (when `dismissible`).
987
+ * - Backdrop blocks click-through on the rest of the page so the user can't
988
+ * stumble into unrelated UI mid-tour. The highlighted target itself stays
989
+ * click-blocked too (use the "Next" button to advance).
990
+ * - Position recalculates on scroll / resize / target size changes via
991
+ * `ResizeObserver`.
992
+ * - All `dark-cornflower-blue` / `prussian-blue` / `bg-white` swapped for
993
+ * semantic tokens — both light and dark modes work out of the box.
948
994
  *
949
995
  * @example
950
- * const step1Ref = useRef<HTMLDivElement>(null)
951
- * const steps = [
952
- * { stepRef: step1Ref, description: 'Click here to start.', positioning: 'natural' },
953
- * ]
954
- * <Wizard steps={steps}>
955
- * <div ref={step1Ref}>...</div>
996
+ * ```tsx
997
+ * const dashRef = useRef<HTMLDivElement>(null)
998
+ * const sidebarRef = useRef<HTMLElement>(null)
999
+ *
1000
+ * <Wizard
1001
+ * steps={[
1002
+ * { stepRef: dashRef, title: 'Dashboard', description: 'Your fleet at a glance.' },
1003
+ * { stepRef: sidebarRef, title: 'Navigation', description: 'Jump between sections here.', placement: 'right' },
1004
+ * ]}
1005
+ * onComplete={() => track('onboarding_complete')}
1006
+ * >
1007
+ * <Layout dashRef={dashRef} sidebarRef={sidebarRef} />
956
1008
  * </Wizard>
1009
+ * ```
957
1010
  */
958
- declare function Wizard({ children, steps, storageKey }: WizardProps): react_jsx_runtime.JSX.Element;
1011
+ declare function Wizard({ children, steps, storageKey, dismissible, onComplete, onSkip, }: WizardProps): react_jsx_runtime.JSX.Element;
959
1012
 
960
1013
  /** ─────────────────── types ─────────────────── */
961
1014
  /**
package/dist/index.d.ts CHANGED
@@ -928,34 +928,87 @@ interface ContextMenuPosition {
928
928
  }
929
929
 
930
930
  interface WizardStep {
931
- /** Ref to the DOM element to highlight */
932
- stepRef: React$1.RefObject<HTMLElement>;
931
+ /** Ref to the DOM element to highlight for this step. */
932
+ stepRef: React$1.RefObject<HTMLElement | null>;
933
+ /** Tooltip body content. */
933
934
  description: React$1.ReactNode;
934
- /** 'natural' | 'center' — controls tooltip position relative to target */
935
- positioning?: 'natural' | 'center';
935
+ /**
936
+ * Tooltip placement relative to the highlighted element.
937
+ * - `'right'` (default) — to the right of the highlight
938
+ * - `'left'` — to the left of the highlight
939
+ * - `'top'` — above the highlight
940
+ * - `'bottom'` — below the highlight
941
+ */
942
+ placement?: 'right' | 'left' | 'top' | 'bottom';
943
+ /** Optional heading for the step's tooltip. */
944
+ title?: React$1.ReactNode;
936
945
  }
937
946
  interface WizardProps {
947
+ /** The wrapped subtree — refs in `steps` point into this tree. */
938
948
  children: React$1.ReactNode;
949
+ /** Ordered list of steps to walk the user through. */
939
950
  steps: WizardStep[];
940
- /** localStorage key used to remember dismissal (default: 'oxygen_wizard') */
941
- storageKey?: string;
951
+ /**
952
+ * `localStorage` key used to remember dismissal. When the user clicks
953
+ * "Done" (or "Skip" when dismissible), this key is set so the wizard
954
+ * won't reopen on subsequent mounts.
955
+ *
956
+ * Pass `null` to disable persistence entirely (useful for tests or
957
+ * tours that should always run).
958
+ *
959
+ * Default: `'oxygen.wizard.completed'`.
960
+ */
961
+ storageKey?: string | null;
962
+ /** Show a "Skip tour" button + Esc-to-dismiss. Default `true`. */
963
+ dismissible?: boolean;
964
+ /** Called when the user reaches the final step's "Done" button. */
965
+ onComplete?: () => void;
966
+ /** Called when the user skips (or presses Esc) before completing. */
967
+ onSkip?: () => void;
942
968
  }
943
969
  /**
944
- * Guided-tour overlay wizard.
970
+ * Guided-tour overlay that walks the user through a sequence of UI elements.
971
+ *
972
+ * Highlights each step's target element with an outlined "spotlight", shows a
973
+ * tooltip with the description, and provides Prev / Next / Done navigation.
974
+ * The wrapped tree is rendered unchanged; the overlay sits on top of it via a
975
+ * portal so it always covers the real viewport regardless of where Wizard
976
+ * lives in the React tree.
945
977
  *
946
- * Highlights a DOM element via a border, then shows a floating tooltip
947
- * adjacent to it. Remembers dismissal via localStorage.
978
+ * **What's improved over the previous version**
979
+ * - `localStorage` access is SSR-safe and try/catch-guarded (Safari private
980
+ * mode, quota exceeded, no-storage browsers all degrade silently).
981
+ * - No more `classList.add(...)` on consumer-owned DOM. The spotlight is a
982
+ * portaled outline rectangle that tracks the target's bbox via
983
+ * `ResizeObserver` + scroll/resize listeners. The consumer's DOM is never
984
+ * mutated, so unmounting Wizard mid-tour leaves no orphan classes.
985
+ * - Focus trap inside the tooltip — Tab and Shift+Tab cycle through the
986
+ * tooltip's buttons. Esc dismisses (when `dismissible`).
987
+ * - Backdrop blocks click-through on the rest of the page so the user can't
988
+ * stumble into unrelated UI mid-tour. The highlighted target itself stays
989
+ * click-blocked too (use the "Next" button to advance).
990
+ * - Position recalculates on scroll / resize / target size changes via
991
+ * `ResizeObserver`.
992
+ * - All `dark-cornflower-blue` / `prussian-blue` / `bg-white` swapped for
993
+ * semantic tokens — both light and dark modes work out of the box.
948
994
  *
949
995
  * @example
950
- * const step1Ref = useRef<HTMLDivElement>(null)
951
- * const steps = [
952
- * { stepRef: step1Ref, description: 'Click here to start.', positioning: 'natural' },
953
- * ]
954
- * <Wizard steps={steps}>
955
- * <div ref={step1Ref}>...</div>
996
+ * ```tsx
997
+ * const dashRef = useRef<HTMLDivElement>(null)
998
+ * const sidebarRef = useRef<HTMLElement>(null)
999
+ *
1000
+ * <Wizard
1001
+ * steps={[
1002
+ * { stepRef: dashRef, title: 'Dashboard', description: 'Your fleet at a glance.' },
1003
+ * { stepRef: sidebarRef, title: 'Navigation', description: 'Jump between sections here.', placement: 'right' },
1004
+ * ]}
1005
+ * onComplete={() => track('onboarding_complete')}
1006
+ * >
1007
+ * <Layout dashRef={dashRef} sidebarRef={sidebarRef} />
956
1008
  * </Wizard>
1009
+ * ```
957
1010
  */
958
- declare function Wizard({ children, steps, storageKey }: WizardProps): react_jsx_runtime.JSX.Element;
1011
+ declare function Wizard({ children, steps, storageKey, dismissible, onComplete, onSkip, }: WizardProps): react_jsx_runtime.JSX.Element;
959
1012
 
960
1013
  /** ─────────────────── types ─────────────────── */
961
1014
  /**
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, useContext, useRef, useCallback, useId } from 'react';
4
+ import React8, { createContext, useState, useEffect, useMemo, useContext, useRef, useId, useCallback, useLayoutEffect } from 'react';
5
5
  import { createPortal } from 'react-dom';
6
6
  import * as Dialog from '@radix-ui/react-dialog';
7
7
  import { useReducedMotion, AnimatePresence, motion } from 'framer-motion';
@@ -1432,70 +1432,208 @@ function ContextMenuLabel({ icon, value }) {
1432
1432
  function ChevronRight2() {
1433
1433
  return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4 flex-shrink-0", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 5l7 7-7 7" }) });
1434
1434
  }
1435
- function Wizard({ children, steps, storageKey = "po_wizard" }) {
1436
- const wizardRef = useRef(null);
1437
- const [activeStep, setActiveStep] = useState(0);
1438
- const [targetBbox, setTargetBbox] = useState(null);
1439
- const HIGHLIGHTED = useMemo(
1440
- () => ["border", "border-4", "border-prussian-blue", "pointer-events-none"],
1441
- []
1442
- );
1443
- const closeWizard = useCallback(() => {
1444
- steps[activeStep]?.stepRef.current?.classList.remove(...HIGHLIGHTED);
1445
- if (wizardRef.current) wizardRef.current.style.display = "none";
1446
- }, [HIGHLIGHTED, steps, activeStep]);
1447
- useEffect(() => {
1448
- const visited = JSON.parse(localStorage.getItem(storageKey) ?? "false");
1449
- if (visited) {
1450
- closeWizard();
1435
+ function readDismissed(key) {
1436
+ if (key === null) return false;
1437
+ if (typeof window === "undefined") return false;
1438
+ try {
1439
+ return window.localStorage.getItem(key) === "true";
1440
+ } catch {
1441
+ return false;
1442
+ }
1443
+ }
1444
+ function writeDismissed(key) {
1445
+ if (key === null) return;
1446
+ if (typeof window === "undefined") return;
1447
+ try {
1448
+ window.localStorage.setItem(key, "true");
1449
+ } catch {
1450
+ }
1451
+ }
1452
+ function useTargetBbox(ref) {
1453
+ const [bbox, setBbox] = useState(null);
1454
+ useLayoutEffect(() => {
1455
+ const el = ref?.current;
1456
+ if (!el) {
1457
+ setBbox(null);
1451
1458
  return;
1452
1459
  }
1453
- const el = steps[activeStep]?.stepRef.current;
1454
- if (el) {
1455
- setTargetBbox(el.getBoundingClientRect());
1456
- el.classList.add(...HIGHLIGHTED);
1457
- }
1458
- }, [closeWizard, steps, activeStep, HIGHLIGHTED, storageKey]);
1459
- const onStepChange = () => {
1460
- if (steps[activeStep + 1]) {
1461
- steps[activeStep].stepRef.current?.classList.remove(...HIGHLIGHTED);
1462
- const nextEl = steps[activeStep + 1].stepRef.current;
1463
- if (nextEl) setTargetBbox(nextEl.getBoundingClientRect());
1464
- setActiveStep(activeStep + 1);
1465
- } else {
1466
- localStorage.setItem(storageKey, "true");
1467
- closeWizard();
1468
- }
1469
- };
1470
- const step = steps[activeStep];
1471
- const left = step && targetBbox ? step.positioning === "natural" ? isNaN(targetBbox.width + 20) ? 0 : targetBbox.width + 20 : isNaN(targetBbox.width / 2) ? 0 : targetBbox.width / 2 : "auto";
1472
- const top = step && targetBbox ? step.positioning === "natural" ? isNaN(targetBbox.y + 10) ? 0 : targetBbox.y + 10 : isNaN(targetBbox.height / 2) ? 0 : targetBbox.height / 2 : "auto";
1473
- return /* @__PURE__ */ jsxs("div", { className: "h-full p-1 rounded-lg w-full", children: [
1474
- /* @__PURE__ */ jsx("div", { className: "absolute", ref: wizardRef, children: /* @__PURE__ */ jsxs(
1475
- "div",
1476
- {
1477
- style: { left, top },
1478
- className: "absolute bg-white rounded-lg p-2 w-[220px] z-50 text-prussian-blue drop-shadow-md transition-all duration-300",
1479
- children: [
1480
- step?.description,
1481
- /* @__PURE__ */ jsxs("div", { className: "flex justify-end", children: [
1482
- /* @__PURE__ */ jsxs("span", { className: "flex h-3 w-3 relative left-14 top-4", children: [
1483
- /* @__PURE__ */ jsx("span", { className: "animate-ping absolute inline-flex h-3 w-3 rounded-full bg-dark-cornflower-blue opacity-75" }),
1484
- /* @__PURE__ */ jsx("span", { className: "relative inline-flex rounded-full h-3 w-3 bg-dark-cornflower-blue" })
1485
- ] }),
1486
- /* @__PURE__ */ jsx(
1487
- Button,
1488
- {
1489
- onClick: onStepChange,
1490
- content: activeStep === steps.length - 1 ? "Close" : "Next",
1491
- style: { width: 55, padding: "5px 10px", margin: "0" }
1492
- }
1493
- )
1494
- ] })
1495
- ]
1460
+ const update = () => setBbox(el.getBoundingClientRect());
1461
+ update();
1462
+ window.addEventListener("scroll", update, true);
1463
+ window.addEventListener("resize", update);
1464
+ const ro = typeof ResizeObserver !== "undefined" ? new ResizeObserver(update) : null;
1465
+ ro?.observe(el);
1466
+ return () => {
1467
+ window.removeEventListener("scroll", update, true);
1468
+ window.removeEventListener("resize", update);
1469
+ ro?.disconnect();
1470
+ };
1471
+ }, [ref]);
1472
+ return bbox;
1473
+ }
1474
+ var TOOLTIP_WIDTH = 280;
1475
+ var TOOLTIP_GAP = 12;
1476
+ function tooltipStyleFor(bbox, placement) {
1477
+ const pl = placement ?? "right";
1478
+ if (pl === "right") return { left: bbox.right + TOOLTIP_GAP, top: bbox.top + bbox.height / 2, transform: "translateY(-50%)", width: TOOLTIP_WIDTH };
1479
+ if (pl === "left") return { left: bbox.left - TOOLTIP_WIDTH - TOOLTIP_GAP, top: bbox.top + bbox.height / 2, transform: "translateY(-50%)", width: TOOLTIP_WIDTH };
1480
+ if (pl === "bottom") return { left: bbox.left + bbox.width / 2, top: bbox.bottom + TOOLTIP_GAP, transform: "translateX(-50%)", width: TOOLTIP_WIDTH };
1481
+ return { left: bbox.left + bbox.width / 2, top: bbox.top - TOOLTIP_GAP, transform: "translate(-50%, -100%)", width: TOOLTIP_WIDTH };
1482
+ }
1483
+ function useFocusTrap(containerRef, active) {
1484
+ useEffect(() => {
1485
+ if (!active) return;
1486
+ const el = containerRef.current;
1487
+ if (!el) return;
1488
+ const t = setTimeout(() => {
1489
+ const first = el.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
1490
+ first?.focus();
1491
+ }, 0);
1492
+ const onKey = (e) => {
1493
+ if (e.key !== "Tab") return;
1494
+ const focusables = el.querySelectorAll(
1495
+ 'button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])'
1496
+ );
1497
+ if (focusables.length === 0) return;
1498
+ const first = focusables[0];
1499
+ const last = focusables[focusables.length - 1];
1500
+ if (e.shiftKey && document.activeElement === first) {
1501
+ e.preventDefault();
1502
+ last.focus();
1503
+ } else if (!e.shiftKey && document.activeElement === last) {
1504
+ e.preventDefault();
1505
+ first.focus();
1506
+ }
1507
+ };
1508
+ document.addEventListener("keydown", onKey);
1509
+ return () => {
1510
+ clearTimeout(t);
1511
+ document.removeEventListener("keydown", onKey);
1512
+ };
1513
+ }, [containerRef, active]);
1514
+ }
1515
+ function Wizard({
1516
+ children,
1517
+ steps,
1518
+ storageKey = "oxygen.wizard.completed",
1519
+ dismissible = true,
1520
+ onComplete,
1521
+ onSkip
1522
+ }) {
1523
+ const tooltipRef = useRef(null);
1524
+ const tooltipTitleId = useId();
1525
+ const tooltipBodyId = useId();
1526
+ const [open, setOpen] = useState(() => steps.length > 0 && !readDismissed(storageKey));
1527
+ const [activeIndex, setActiveIndex] = useState(0);
1528
+ const step = steps[activeIndex];
1529
+ const bbox = useTargetBbox(step?.stepRef);
1530
+ useFocusTrap(tooltipRef, open);
1531
+ useEffect(() => {
1532
+ if (!open || !dismissible) return;
1533
+ const onKey = (e) => {
1534
+ if (e.key === "Escape") {
1535
+ e.preventDefault();
1536
+ handleSkip();
1496
1537
  }
1497
- ) }),
1498
- children
1538
+ };
1539
+ document.addEventListener("keydown", onKey);
1540
+ return () => document.removeEventListener("keydown", onKey);
1541
+ }, [open, dismissible]);
1542
+ const handleSkip = useCallback(() => {
1543
+ writeDismissed(storageKey);
1544
+ setOpen(false);
1545
+ onSkip?.();
1546
+ }, [storageKey, onSkip]);
1547
+ const handleComplete = useCallback(() => {
1548
+ writeDismissed(storageKey);
1549
+ setOpen(false);
1550
+ onComplete?.();
1551
+ }, [storageKey, onComplete]);
1552
+ const handleNext = () => {
1553
+ if (activeIndex < steps.length - 1) setActiveIndex((i) => i + 1);
1554
+ else handleComplete();
1555
+ };
1556
+ const handlePrev = () => {
1557
+ if (activeIndex > 0) setActiveIndex((i) => i - 1);
1558
+ };
1559
+ const highlightStyle = bbox ? {
1560
+ left: bbox.left - 4,
1561
+ top: bbox.top - 4,
1562
+ width: bbox.width + 8,
1563
+ height: bbox.height + 8
1564
+ } : { display: "none" };
1565
+ const tooltipStyle = bbox ? tooltipStyleFor(bbox, step?.placement) : { display: "none" };
1566
+ const isLast = activeIndex === steps.length - 1;
1567
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1568
+ children,
1569
+ open && step && /* @__PURE__ */ jsxs(Portal, { children: [
1570
+ /* @__PURE__ */ jsx(
1571
+ "div",
1572
+ {
1573
+ className: "fixed inset-0 z-[7000000] bg-foreground/40 backdrop-blur-[1px] pointer-events-auto",
1574
+ "aria-hidden": "true"
1575
+ }
1576
+ ),
1577
+ /* @__PURE__ */ jsx(
1578
+ "div",
1579
+ {
1580
+ className: "fixed z-[7000001] pointer-events-none rounded-md ring-2 ring-accent ring-offset-2 ring-offset-background transition-all duration-200",
1581
+ style: highlightStyle,
1582
+ "aria-hidden": "true"
1583
+ }
1584
+ ),
1585
+ /* @__PURE__ */ jsxs(
1586
+ "div",
1587
+ {
1588
+ ref: tooltipRef,
1589
+ role: "dialog",
1590
+ "aria-modal": "true",
1591
+ "aria-labelledby": step.title ? tooltipTitleId : void 0,
1592
+ "aria-describedby": tooltipBodyId,
1593
+ className: "fixed z-[7000002] rounded-lg bg-surface text-foreground border border-border shadow-xl p-4 pointer-events-auto",
1594
+ style: tooltipStyle,
1595
+ children: [
1596
+ step.title && /* @__PURE__ */ jsx("h3", { id: tooltipTitleId, className: "text-sm font-semibold text-foreground mb-1", children: step.title }),
1597
+ /* @__PURE__ */ jsx("div", { id: tooltipBodyId, className: "text-sm text-foreground-secondary leading-relaxed", children: step.description }),
1598
+ /* @__PURE__ */ jsxs("div", { className: "mt-4 flex items-center justify-between", children: [
1599
+ /* @__PURE__ */ jsxs("span", { className: "text-xs text-foreground-muted tabular-nums", children: [
1600
+ activeIndex + 1,
1601
+ " / ",
1602
+ steps.length
1603
+ ] }),
1604
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1605
+ dismissible && !isLast && /* @__PURE__ */ jsx(
1606
+ Button,
1607
+ {
1608
+ variant: "ghost",
1609
+ size: "sm",
1610
+ content: "Skip",
1611
+ onClick: handleSkip
1612
+ }
1613
+ ),
1614
+ activeIndex > 0 && /* @__PURE__ */ jsx(
1615
+ Button,
1616
+ {
1617
+ variant: "secondary",
1618
+ size: "sm",
1619
+ content: "Back",
1620
+ onClick: handlePrev
1621
+ }
1622
+ ),
1623
+ /* @__PURE__ */ jsx(
1624
+ Button,
1625
+ {
1626
+ size: "sm",
1627
+ content: isLast ? "Done" : "Next",
1628
+ onClick: handleNext
1629
+ }
1630
+ )
1631
+ ] })
1632
+ ] })
1633
+ ]
1634
+ }
1635
+ )
1636
+ ] })
1499
1637
  ] });
1500
1638
  }
1501
1639
  var SearchInput = React8.forwardRef(function SearchInput2({