@flowsterix/react 0.5.0 → 0.6.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.mjs CHANGED
@@ -1,3 +1,5 @@
1
+ import "./chunk-WCLT3A6G.mjs";
2
+ import "./chunk-2ZX2Y3JL.mjs";
1
3
  import {
2
4
  createPathString,
3
5
  expandRect,
@@ -44,7 +46,17 @@ var defaultLabels = {
44
46
  ariaStepProgress: ({ current, total }) => `Step ${current} of ${total}`,
45
47
  ariaTimeRemaining: ({ ms }) => `${Math.ceil(ms / 1e3)} seconds remaining`,
46
48
  ariaDelayProgress: "Auto-advance progress",
47
- formatTimeRemaining: ({ ms }) => `${Math.ceil(ms / 1e3)}s remaining`
49
+ formatTimeRemaining: ({ ms }) => `${Math.ceil(ms / 1e3)}s remaining`,
50
+ targetIssue: {
51
+ missingTitle: "Target not visible",
52
+ missingBody: "The target element is not currently visible. Make sure the UI piece is mounted and displayed.",
53
+ missingHint: "Showing the last known position until the element returns.",
54
+ hiddenTitle: "Target not visible",
55
+ hiddenBody: "The target element is not currently visible. Make sure the UI piece is mounted and displayed.",
56
+ hiddenHint: "Showing the last known position until the element returns.",
57
+ detachedTitle: "Target left the page",
58
+ detachedBody: "Navigate back to the screen that contains this element or reopen it before continuing the tour."
59
+ }
48
60
  };
49
61
  var LabelsContext = createContext(defaultLabels);
50
62
  var LabelsProvider = LabelsContext.Provider;
@@ -1404,7 +1416,7 @@ var useTourTarget = () => {
1404
1416
  };
1405
1417
 
1406
1418
  // src/hooks/useHudState.ts
1407
- import { useCallback as useCallback2, useEffect as useEffect7, useMemo as useMemo4, useState as useState6 } from "react";
1419
+ import { useCallback as useCallback2, useEffect as useEffect8, useMemo as useMemo4, useRef as useRef5, useState as useState7 } from "react";
1408
1420
 
1409
1421
  // src/hooks/useAdvanceRules.ts
1410
1422
  import { useEffect as useEffect4 } from "react";
@@ -1666,7 +1678,8 @@ var useHiddenTargetFallback = ({
1666
1678
  clearGraceTimeout();
1667
1679
  const isHiddenOrDetached = (target.visibility === "hidden" || target.visibility === "detached") && target.status === "ready";
1668
1680
  const isMissingWithNoRect = target.visibility === "missing" && target.status === "resolving" && target.rect === null && target.lastResolvedRect === null;
1669
- const shouldHandleHiddenTarget = !target.isScreen && (isHiddenOrDetached || isMissingWithNoRect);
1681
+ const isMissingAfterNavigation = target.visibility === "missing" && target.status === "resolving" && target.rect === null;
1682
+ const shouldHandleHiddenTarget = !target.isScreen && (isHiddenOrDetached || isMissingWithNoRect || isMissingAfterNavigation);
1670
1683
  if (!shouldHandleHiddenTarget) {
1671
1684
  setUsingScreenFallback(false);
1672
1685
  setIsInGracePeriod(false);
@@ -1725,14 +1738,32 @@ var useHiddenTargetFallback = ({
1725
1738
  };
1726
1739
  };
1727
1740
 
1741
+ // src/hooks/useRouteMismatch.ts
1742
+ import { useEffect as useEffect6, useState as useState5 } from "react";
1743
+ var useRouteMismatch = (step) => {
1744
+ const [currentPath, setCurrentPath] = useState5(() => getCurrentRoutePath());
1745
+ useEffect6(() => {
1746
+ return subscribeToRouteChanges((path) => {
1747
+ setCurrentPath(path);
1748
+ });
1749
+ }, []);
1750
+ const expectedRoute = step?.route;
1751
+ const isRouteMismatch = step !== null && expectedRoute !== void 0 && !matchRoute({ pattern: expectedRoute, path: currentPath });
1752
+ return {
1753
+ isRouteMismatch,
1754
+ currentPath,
1755
+ expectedRoute
1756
+ };
1757
+ };
1758
+
1728
1759
  // src/hooks/useViewportRect.ts
1729
- import { useEffect as useEffect6, useRef as useRef4, useState as useState5 } from "react";
1760
+ import { useEffect as useEffect7, useRef as useRef4, useState as useState6 } from "react";
1730
1761
  var useViewportRect = () => {
1731
- const [viewport, setViewport] = useState5(
1762
+ const [viewport, setViewport] = useState6(
1732
1763
  () => getViewportRect()
1733
1764
  );
1734
1765
  const rafRef = useRef4(null);
1735
- useEffect6(() => {
1766
+ useEffect7(() => {
1736
1767
  if (!isBrowser) return;
1737
1768
  const updateViewport = () => {
1738
1769
  rafRef.current = null;
@@ -1775,7 +1806,7 @@ var normalizeFlowFilter = (value) => {
1775
1806
  var useHudState = (options = {}) => {
1776
1807
  const { flowId } = options;
1777
1808
  const flowFilter = useMemo4(() => normalizeFlowFilter(flowId), [flowId]);
1778
- const { state, activeStep, activeFlowId, flows, next, complete } = useTour();
1809
+ const { state, activeStep, activeFlowId, flows, next, complete, pause, resume } = useTour();
1779
1810
  const target = useTourTarget();
1780
1811
  const viewportRect = useViewportRect();
1781
1812
  useAdvanceRules(target);
@@ -1787,15 +1818,15 @@ var useHudState = (options = {}) => {
1787
1818
  const isRunning = state?.status === "running";
1788
1819
  const runningState = isRunning && matchesFlowFilter ? state : null;
1789
1820
  const runningStep = runningState && activeStep ? activeStep : null;
1790
- const [shouldRender, setShouldRender] = useState6(
1821
+ const [shouldRender, setShouldRender] = useState7(
1791
1822
  Boolean(runningStep)
1792
1823
  );
1793
- useEffect7(() => {
1824
+ useEffect8(() => {
1794
1825
  if (runningStep) {
1795
1826
  setShouldRender(true);
1796
1827
  }
1797
1828
  }, [runningStep?.id]);
1798
- useEffect7(() => {
1829
+ useEffect8(() => {
1799
1830
  if (!shouldRender) return;
1800
1831
  if (runningStep) return;
1801
1832
  if (target.status !== "idle") return;
@@ -1806,6 +1837,19 @@ var useHudState = (options = {}) => {
1806
1837
  window.clearTimeout(timeoutId);
1807
1838
  };
1808
1839
  }, [runningStep, shouldRender, target.status]);
1840
+ const { isRouteMismatch, currentPath } = useRouteMismatch(activeStep);
1841
+ const pausedForMissingTargetRef = useRef5(null);
1842
+ useEffect8(() => {
1843
+ if (!isRouteMismatch) return;
1844
+ if (!runningState || runningState.status !== "running") return;
1845
+ pause();
1846
+ }, [isRouteMismatch, runningState, pause]);
1847
+ useEffect8(() => {
1848
+ if (isRouteMismatch) return;
1849
+ if (pausedForMissingTargetRef.current !== null) return;
1850
+ if (!state || state.status !== "paused") return;
1851
+ resume();
1852
+ }, [isRouteMismatch, state, resume]);
1809
1853
  const skipHiddenStep = useCallback2(() => {
1810
1854
  if (!runningState || runningState.status !== "running") return;
1811
1855
  if (!activeFlowId) return;
@@ -1824,6 +1868,35 @@ var useHudState = (options = {}) => {
1824
1868
  viewportRect,
1825
1869
  onSkip: skipHiddenStep
1826
1870
  });
1871
+ useEffect8(() => {
1872
+ if (isRouteMismatch) return;
1873
+ if (activeStep?.route !== void 0) return;
1874
+ if (isInGracePeriod) return;
1875
+ if (target.visibility !== "missing") return;
1876
+ if (target.isScreen) return;
1877
+ if (!runningState || runningState.status !== "running") return;
1878
+ pausedForMissingTargetRef.current = currentPath;
1879
+ pause();
1880
+ }, [
1881
+ isRouteMismatch,
1882
+ activeStep?.route,
1883
+ isInGracePeriod,
1884
+ target.visibility,
1885
+ target.isScreen,
1886
+ runningState,
1887
+ currentPath,
1888
+ pause
1889
+ ]);
1890
+ useEffect8(() => {
1891
+ if (pausedForMissingTargetRef.current === null) return;
1892
+ if (!state || state.status !== "paused") return;
1893
+ if (currentPath === pausedForMissingTargetRef.current) return;
1894
+ pausedForMissingTargetRef.current = null;
1895
+ resume();
1896
+ }, [currentPath, state, resume]);
1897
+ useEffect8(() => {
1898
+ pausedForMissingTargetRef.current = null;
1899
+ }, [activeStep?.id]);
1827
1900
  const canRenderStep = Boolean(runningStep && runningState);
1828
1901
  const focusTrapActive = canRenderStep;
1829
1902
  const flowHudOptions = matchesFlowFilter && activeFlowId ? flows.get(activeFlowId)?.hud ?? null : null;
@@ -1875,7 +1948,7 @@ var useHudDescription = (options) => {
1875
1948
  };
1876
1949
 
1877
1950
  // src/hooks/useHudShortcuts.ts
1878
- import { useEffect as useEffect8 } from "react";
1951
+ import { useEffect as useEffect9 } from "react";
1879
1952
 
1880
1953
  // src/hooks/useTourControls.ts
1881
1954
  import { useCallback as useCallback3, useMemo as useMemo6 } from "react";
@@ -2000,7 +2073,7 @@ var useHudShortcuts = (target, options) => {
2000
2073
  const escapeEnabled = options?.escape ?? true;
2001
2074
  const { state } = useTour();
2002
2075
  const { cancel, canGoBack, goBack, canGoNext, goNext, isActive } = useTourControls();
2003
- useEffect8(() => {
2076
+ useEffect9(() => {
2004
2077
  if (!isBrowser) return void 0;
2005
2078
  if (!enabled) return void 0;
2006
2079
  if (!target) return void 0;
@@ -2064,10 +2137,10 @@ var useHudShortcuts = (target, options) => {
2064
2137
  };
2065
2138
 
2066
2139
  // src/hooks/useTourHud.ts
2067
- import { useMemo as useMemo8, useState as useState8 } from "react";
2140
+ import { useMemo as useMemo8, useState as useState9 } from "react";
2068
2141
 
2069
2142
  // src/hooks/useBodyScrollLock.ts
2070
- import { useEffect as useEffect9 } from "react";
2143
+ import { useEffect as useEffect10 } from "react";
2071
2144
  var lockCount = 0;
2072
2145
  var previousOverflow = null;
2073
2146
  var acquireLock = () => {
@@ -2088,7 +2161,7 @@ var releaseLock = () => {
2088
2161
  }
2089
2162
  };
2090
2163
  var useBodyScrollLock = (enabled) => {
2091
- useEffect9(() => {
2164
+ useEffect10(() => {
2092
2165
  if (!enabled) return;
2093
2166
  acquireLock();
2094
2167
  return () => {
@@ -2098,37 +2171,45 @@ var useBodyScrollLock = (enabled) => {
2098
2171
  };
2099
2172
 
2100
2173
  // src/hooks/useHudTargetIssue.ts
2101
- import { useEffect as useEffect10, useMemo as useMemo7, useState as useState7 } from "react";
2102
- var deriveTargetIssue = (target) => {
2174
+ import { useEffect as useEffect11, useMemo as useMemo7, useState as useState8 } from "react";
2175
+ var deriveTargetIssue = (params) => {
2176
+ const { target, labels } = params;
2103
2177
  if (target.isScreen) return null;
2104
2178
  if (target.status === "idle") return null;
2105
2179
  switch (target.visibility) {
2106
2180
  case "missing":
2181
+ return {
2182
+ type: "missing",
2183
+ title: labels.targetIssue.missingTitle,
2184
+ body: labels.targetIssue.missingBody,
2185
+ hint: target.rectSource === "stored" ? labels.targetIssue.missingHint : void 0
2186
+ };
2107
2187
  case "hidden":
2108
2188
  return {
2109
- type: target.visibility,
2110
- title: "Target not visible",
2111
- body: "The target element is not currently visible. Make sure the UI piece is mounted and displayed.",
2112
- hint: target.rectSource === "stored" ? "Showing the last known position until the element returns." : void 0
2189
+ type: "hidden",
2190
+ title: labels.targetIssue.hiddenTitle,
2191
+ body: labels.targetIssue.hiddenBody,
2192
+ hint: target.rectSource === "stored" ? labels.targetIssue.hiddenHint : void 0
2113
2193
  };
2114
2194
  case "detached":
2115
2195
  return {
2116
2196
  type: "detached",
2117
- title: "Target left the page",
2118
- body: "Navigate back to the screen that contains this element or reopen it before continuing the tour."
2197
+ title: labels.targetIssue.detachedTitle,
2198
+ body: labels.targetIssue.detachedBody
2119
2199
  };
2120
2200
  default:
2121
2201
  return null;
2122
2202
  }
2123
2203
  };
2124
2204
  var useHudTargetIssue = (target, options) => {
2205
+ const labels = useTourLabels();
2125
2206
  const delayMs = Math.max(0, options?.delayMs ?? 500);
2126
- const [armed, setArmed] = useState7(false);
2207
+ const [armed, setArmed] = useState8(false);
2127
2208
  const rawIssue = useMemo7(
2128
- () => deriveTargetIssue(target),
2129
- [target.isScreen, target.rectSource, target.status, target.visibility]
2209
+ () => deriveTargetIssue({ target, labels }),
2210
+ [target.isScreen, target.rectSource, target.status, target.visibility, labels]
2130
2211
  );
2131
- useEffect10(() => {
2212
+ useEffect11(() => {
2132
2213
  if (!rawIssue) {
2133
2214
  setArmed(false);
2134
2215
  return;
@@ -2162,7 +2243,7 @@ var useTourHud = (options = {}) => {
2162
2243
  const { backdropInteraction, lockBodyScroll } = useTour();
2163
2244
  const hudState = useHudState();
2164
2245
  const disableDefaultHud = hudState.hudRenderMode === "none";
2165
- const [popoverNode, setPopoverNode] = useState8(null);
2246
+ const [popoverNode, setPopoverNode] = useState9(null);
2166
2247
  const popoverOptions = hudState.flowHudOptions?.popover;
2167
2248
  const description = useHudDescription({
2168
2249
  step: hudState.runningStep,
@@ -2234,7 +2315,7 @@ var useTourHud = (options = {}) => {
2234
2315
  };
2235
2316
 
2236
2317
  // src/hooks/useTourOverlay.ts
2237
- import { useEffect as useEffect11, useMemo as useMemo9, useRef as useRef5 } from "react";
2318
+ import { useEffect as useEffect12, useMemo as useMemo9, useRef as useRef6 } from "react";
2238
2319
  var DEFAULT_PADDING = 12;
2239
2320
  var DEFAULT_RADIUS = 12;
2240
2321
  var DEFAULT_EDGE_BUFFER = 0;
@@ -2247,9 +2328,9 @@ var useTourOverlay = (options) => {
2247
2328
  interactionMode = "passthrough",
2248
2329
  isInGracePeriod = false
2249
2330
  } = options;
2250
- const hasShownRef = useRef5(false);
2251
- const lastReadyTargetRef = useRef5(null);
2252
- useEffect11(() => {
2331
+ const hasShownRef = useRef6(false);
2332
+ const lastReadyTargetRef = useRef6(null);
2333
+ useEffect12(() => {
2253
2334
  if (!isBrowser) return;
2254
2335
  if (target.status === "ready") {
2255
2336
  hasShownRef.current = true;
@@ -2485,12 +2566,12 @@ var useRadixDialogAdapter = (options = {}) => {
2485
2566
  };
2486
2567
 
2487
2568
  // src/hooks/useDelayAdvance.ts
2488
- import { useEffect as useEffect12, useMemo as useMemo10, useState as useState9 } from "react";
2569
+ import { useEffect as useEffect13, useMemo as useMemo10, useState as useState10 } from "react";
2489
2570
  var getTimestamp = () => typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
2490
2571
  var useDelayAdvance = () => {
2491
2572
  const { delayInfo, activeStep, state } = useTour();
2492
- const [now, setNow] = useState9(() => getTimestamp());
2493
- useEffect12(() => {
2573
+ const [now, setNow] = useState10(() => getTimestamp());
2574
+ useEffect13(() => {
2494
2575
  if (!delayInfo) return;
2495
2576
  if (!activeStep || activeStep.id !== delayInfo.stepId) return;
2496
2577
  if (!state || state.status !== "running") return;
@@ -2507,7 +2588,7 @@ var useDelayAdvance = () => {
2507
2588
  }
2508
2589
  };
2509
2590
  }, [delayInfo, activeStep, state]);
2510
- useEffect12(() => {
2591
+ useEffect13(() => {
2511
2592
  if (!delayInfo) {
2512
2593
  setNow(getTimestamp());
2513
2594
  }
@@ -2565,7 +2646,7 @@ var useDelayAdvance = () => {
2565
2646
  };
2566
2647
 
2567
2648
  // src/components/OverlayBackdrop.tsx
2568
- import { useEffect as useEffect13, useRef as useRef6 } from "react";
2649
+ import { useEffect as useEffect14, useRef as useRef7 } from "react";
2569
2650
  import { createPortal } from "react-dom";
2570
2651
  import { AnimatePresence } from "motion/react";
2571
2652
  import { jsx as jsx3, jsxs } from "react/jsx-runtime";
@@ -2654,9 +2735,9 @@ var OverlayBackdrop = ({
2654
2735
  viewport
2655
2736
  } = overlay;
2656
2737
  const hasHighlightBounds = Boolean(highlight.rect);
2657
- const prevScreenTargetRef = useRef6(null);
2738
+ const prevScreenTargetRef = useRef7(null);
2658
2739
  const shouldSnapHighlight = prevScreenTargetRef.current === true && !highlight.isScreen && hasHighlightBounds;
2659
- useEffect13(() => {
2740
+ useEffect14(() => {
2660
2741
  prevScreenTargetRef.current = highlight.isScreen;
2661
2742
  }, [highlight.isScreen]);
2662
2743
  const resolvedBlur = typeof blurAmount === "number" ? `${blurAmount}px` : "0px";
@@ -2893,7 +2974,7 @@ var OverlayBackdrop = ({
2893
2974
  };
2894
2975
 
2895
2976
  // src/components/TourPopoverPortal.tsx
2896
- import { useEffect as useEffect14, useLayoutEffect as useLayoutEffect2, useMemo as useMemo11, useRef as useRef7, useState as useState10 } from "react";
2977
+ import { useEffect as useEffect15, useLayoutEffect as useLayoutEffect2, useMemo as useMemo11, useRef as useRef8, useState as useState11 } from "react";
2897
2978
  import { createPortal as createPortal2 } from "react-dom";
2898
2979
  import {
2899
2980
  autoPlacement,
@@ -2947,8 +3028,7 @@ var TourPopoverPortal = ({
2947
3028
  layoutId,
2948
3029
  containerComponent,
2949
3030
  contentComponent,
2950
- transitionsOverride,
2951
- isInGracePeriod = false
3031
+ transitionsOverride
2952
3032
  }) => {
2953
3033
  if (!isBrowser) return null;
2954
3034
  const host = portalHost();
@@ -2961,12 +3041,12 @@ var TourPopoverPortal = ({
2961
3041
  const popoverContentTransition = transitionsOverride?.popoverContent ?? adapter.transitions.popoverContent ?? DEFAULT_POPOVER_CONTENT_TRANSITION;
2962
3042
  const viewport = useViewportRect();
2963
3043
  const prefersMobileLayout = viewport.width <= MOBILE_BREAKPOINT || viewport.height <= MOBILE_HEIGHT_BREAKPOINT;
2964
- const prefersMobileRef = useRef7(prefersMobileLayout);
2965
- useEffect14(() => {
3044
+ const prefersMobileRef = useRef8(prefersMobileLayout);
3045
+ useEffect15(() => {
2966
3046
  prefersMobileRef.current = prefersMobileLayout;
2967
3047
  }, [prefersMobileLayout]);
2968
- const lastReadyTargetRef = useRef7(null);
2969
- useEffect14(() => {
3048
+ const lastReadyTargetRef = useRef8(null);
3049
+ useEffect15(() => {
2970
3050
  if (target.status === "ready" && target.rect) {
2971
3051
  lastReadyTargetRef.current = {
2972
3052
  rect: { ...target.rect },
@@ -2979,10 +3059,10 @@ var TourPopoverPortal = ({
2979
3059
  const cachedTarget = lastReadyTargetRef.current;
2980
3060
  const resolvedRect = target.rect ?? target.lastResolvedRect ?? cachedTarget?.rect ?? null;
2981
3061
  const resolvedIsScreen = target.status === "ready" ? target.isScreen : cachedTarget?.isScreen ?? target.isScreen;
2982
- const shouldHideForGracePeriod = isInGracePeriod && !resolvedRect;
3062
+ const shouldHidePopover = !resolvedRect && !target.isScreen;
2983
3063
  const fallbackRect = resolvedRect ?? viewport;
2984
3064
  const fallbackIsScreen = resolvedIsScreen;
2985
- const [floatingSize, setFloatingSize] = useState10(null);
3065
+ const [floatingSize, setFloatingSize] = useState11(null);
2986
3066
  const clampVertical = (value) => Math.min(viewport.height - 24, Math.max(24, value));
2987
3067
  const clampHorizontal = (value) => Math.min(viewport.width - 24, Math.max(24, value));
2988
3068
  const screenCenteredTop = viewport.height / 2 - (floatingSize?.height ?? 0) / 2;
@@ -3009,22 +3089,22 @@ var TourPopoverPortal = ({
3009
3089
  }),
3010
3090
  [viewport.height, viewport.width]
3011
3091
  );
3012
- const floatingRef = useRef7(null);
3013
- const cachedFloatingPositionRef = useRef7(null);
3014
- const appliedFloatingCacheRef = useRef7(null);
3015
- const deferredScreenSnapRef = useRef7(null);
3016
- const [layoutMode, setLayoutMode] = useState10(
3092
+ const floatingRef = useRef8(null);
3093
+ const cachedFloatingPositionRef = useRef8(null);
3094
+ const appliedFloatingCacheRef = useRef8(null);
3095
+ const deferredScreenSnapRef = useRef8(null);
3096
+ const [layoutMode, setLayoutMode] = useState11(
3017
3097
  () => prefersMobileLayout ? "mobile" : "floating"
3018
3098
  );
3019
- const [floatingPosition, setFloatingPosition] = useState10(fallbackPosition);
3020
- const [dragPosition, setDragPosition] = useState10(null);
3021
- const [isDragging, setIsDragging] = useState10(false);
3022
- const dragStateRef = useRef7(null);
3023
- const overflowRetryRef = useRef7({
3099
+ const [floatingPosition, setFloatingPosition] = useState11(fallbackPosition);
3100
+ const [dragPosition, setDragPosition] = useState11(null);
3101
+ const [isDragging, setIsDragging] = useState11(false);
3102
+ const dragStateRef = useRef8(null);
3103
+ const overflowRetryRef = useRef8({
3024
3104
  stepId: null,
3025
3105
  attempts: 0
3026
3106
  });
3027
- const overflowRetryTimeoutRef = useRef7(null);
3107
+ const overflowRetryTimeoutRef = useRef8(null);
3028
3108
  useLayoutEffect2(() => {
3029
3109
  if (!isBrowser) return;
3030
3110
  const node = floatingRef.current;
@@ -3044,18 +3124,18 @@ var TourPopoverPortal = ({
3044
3124
  const autoAlignment = resolvedPlacement.endsWith(
3045
3125
  "-start"
3046
3126
  ) ? "start" : resolvedPlacement.endsWith("-end") ? "end" : void 0;
3047
- useEffect14(() => {
3127
+ useEffect15(() => {
3048
3128
  setDragPosition(null);
3049
3129
  setLayoutMode(prefersMobileRef.current ? "mobile" : "floating");
3050
3130
  cachedFloatingPositionRef.current = null;
3051
3131
  appliedFloatingCacheRef.current = null;
3052
3132
  }, [target.stepId]);
3053
- useEffect14(() => {
3133
+ useEffect15(() => {
3054
3134
  if (layoutMode !== "manual") {
3055
3135
  setDragPosition(null);
3056
3136
  }
3057
3137
  }, [layoutMode]);
3058
- useEffect14(() => {
3138
+ useEffect15(() => {
3059
3139
  cachedFloatingPositionRef.current = floatingPosition;
3060
3140
  const cacheKey = getFloatingCacheKey(target);
3061
3141
  if (cacheKey) {
@@ -3078,17 +3158,17 @@ var TourPopoverPortal = ({
3078
3158
  }),
3079
3159
  [viewport.height, viewport.width]
3080
3160
  );
3081
- useEffect14(() => {
3161
+ useEffect15(() => {
3082
3162
  if (layoutMode === "docked") {
3083
3163
  setFloatingPosition(dockedPosition);
3084
3164
  }
3085
3165
  }, [dockedPosition, layoutMode]);
3086
- useEffect14(() => {
3166
+ useEffect15(() => {
3087
3167
  if (layoutMode === "mobile") {
3088
3168
  setFloatingPosition(mobilePosition);
3089
3169
  }
3090
3170
  }, [layoutMode, mobilePosition]);
3091
- useEffect14(() => {
3171
+ useEffect15(() => {
3092
3172
  if (prefersMobileLayout) {
3093
3173
  if (layoutMode !== "mobile") {
3094
3174
  setLayoutMode("mobile");
@@ -3101,7 +3181,7 @@ var TourPopoverPortal = ({
3101
3181
  setFloatingPosition(fallbackPosition);
3102
3182
  }
3103
3183
  }, [fallbackPosition, layoutMode, prefersMobileLayout]);
3104
- useEffect14(() => {
3184
+ useEffect15(() => {
3105
3185
  if (layoutMode !== "floating") return;
3106
3186
  const stepId = target.stepId;
3107
3187
  if (!stepId) return;
@@ -3125,7 +3205,7 @@ var TourPopoverPortal = ({
3125
3205
  target.stepId
3126
3206
  ]);
3127
3207
  const shouldDeferScreenSnap = layoutMode === "floating" && target.isScreen && Boolean(layoutId);
3128
- useEffect14(() => {
3208
+ useEffect15(() => {
3129
3209
  return () => {
3130
3210
  if (deferredScreenSnapRef.current !== null) {
3131
3211
  cancelAnimationFrame(deferredScreenSnapRef.current);
@@ -3145,7 +3225,7 @@ var TourPopoverPortal = ({
3145
3225
  target.isScreen,
3146
3226
  target.status
3147
3227
  ]);
3148
- useEffect14(() => {
3228
+ useEffect15(() => {
3149
3229
  if (!shouldDeferScreenSnap) return;
3150
3230
  if (deferredScreenSnapRef.current !== null) {
3151
3231
  cancelAnimationFrame(deferredScreenSnapRef.current);
@@ -3172,7 +3252,7 @@ var TourPopoverPortal = ({
3172
3252
  }
3173
3253
  };
3174
3254
  }, [fallbackPosition, shouldDeferScreenSnap]);
3175
- useEffect14(() => {
3255
+ useEffect15(() => {
3176
3256
  return () => {
3177
3257
  if (overflowRetryTimeoutRef.current !== null) {
3178
3258
  window.clearTimeout(overflowRetryTimeoutRef.current);
@@ -3398,7 +3478,7 @@ var TourPopoverPortal = ({
3398
3478
  }
3399
3479
  event.preventDefault();
3400
3480
  };
3401
- useEffect14(() => endDrag, []);
3481
+ useEffect15(() => endDrag, []);
3402
3482
  const shouldUseFallbackInitial = layoutMode !== "mobile" && (Boolean(target.lastResolvedRect) || Boolean(cachedTarget));
3403
3483
  const floatingCacheKey = layoutMode === "mobile" ? null : getFloatingCacheKey(target);
3404
3484
  const persistedFloatingInitial = floatingCacheKey && floatingPositionCache.has(floatingCacheKey) ? floatingPositionCache.get(floatingCacheKey) ?? null : null;
@@ -3485,12 +3565,12 @@ var TourPopoverPortal = ({
3485
3565
  dragHandleProps,
3486
3566
  descriptionProps
3487
3567
  };
3488
- if (shouldHideForGracePeriod) return null;
3568
+ if (shouldHidePopover) return null;
3489
3569
  return createPortal2(children(context), host);
3490
3570
  };
3491
3571
 
3492
3572
  // src/components/TourFocusManager.tsx
3493
- import { useEffect as useEffect15, useLayoutEffect as useLayoutEffect3, useRef as useRef8, useState as useState11 } from "react";
3573
+ import { useEffect as useEffect16, useLayoutEffect as useLayoutEffect3, useRef as useRef9, useState as useState12 } from "react";
3494
3574
  import { createPortal as createPortal3 } from "react-dom";
3495
3575
 
3496
3576
  // src/utils/focus.ts
@@ -3567,18 +3647,18 @@ var TourFocusManager = ({
3567
3647
  highlightRect,
3568
3648
  guardElementFocusRing
3569
3649
  }) => {
3570
- const previousFocusRef = useRef8(null);
3571
- const guardNodesRef = useRef8({
3650
+ const previousFocusRef = useRef9(null);
3651
+ const guardNodesRef = useRef9({
3572
3652
  "target-start": null,
3573
3653
  "target-end": null,
3574
3654
  "popover-start": null,
3575
3655
  "popover-end": null
3576
3656
  });
3577
- const lastTabDirectionRef = useRef8("forward");
3578
- const suppressGuardHopRef = useRef8(null);
3579
- const [targetRingActive, setTargetRingActive] = useState11(false);
3580
- const [popoverRingActive, setPopoverRingActive] = useState11(false);
3581
- const [popoverRect, setPopoverRect] = useState11(null);
3657
+ const lastTabDirectionRef = useRef9("forward");
3658
+ const suppressGuardHopRef = useRef9(null);
3659
+ const [targetRingActive, setTargetRingActive] = useState12(false);
3660
+ const [popoverRingActive, setPopoverRingActive] = useState12(false);
3661
+ const [popoverRect, setPopoverRect] = useState12(null);
3582
3662
  const restoreFocus = () => {
3583
3663
  const previous = previousFocusRef.current;
3584
3664
  previousFocusRef.current = null;
@@ -3604,7 +3684,7 @@ var TourFocusManager = ({
3604
3684
  restoreFocus();
3605
3685
  };
3606
3686
  }, [active, popoverNode, target.element]);
3607
- useEffect15(() => {
3687
+ useEffect16(() => {
3608
3688
  if (!isBrowser) return;
3609
3689
  if (!active) return;
3610
3690
  const doc = popoverNode?.ownerDocument ?? target.element?.ownerDocument ?? document;
package/dist/labels.d.ts CHANGED
@@ -15,6 +15,16 @@ export interface TourLabels {
15
15
  formatTimeRemaining: (params: {
16
16
  ms: number;
17
17
  }) => string;
18
+ targetIssue: {
19
+ missingTitle: string;
20
+ missingBody: string;
21
+ missingHint: string;
22
+ hiddenTitle: string;
23
+ hiddenBody: string;
24
+ hiddenHint: string;
25
+ detachedTitle: string;
26
+ detachedBody: string;
27
+ };
18
28
  }
19
29
  export declare const defaultLabels: TourLabels;
20
30
  export declare const LabelsProvider: import("react").Provider<TourLabels>;
@@ -1 +1 @@
1
- {"version":3,"file":"labels.d.ts","sourceRoot":"","sources":["../src/labels.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IAEzB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,aAAa,EAAE,MAAM,CAAA;IAGrB,gBAAgB,EAAE,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,CAAA;IACxE,iBAAiB,EAAE,CAAC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,CAAA;IACrD,iBAAiB,EAAE,MAAM,CAAA;IAGzB,mBAAmB,EAAE,CAAC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,CAAA;CACxD;AAED,eAAO,MAAM,aAAa,EAAE,UAa3B,CAAA;AAID,eAAO,MAAM,cAAc,sCAAyB,CAAA;AAEpD,wBAAgB,aAAa,IAAI,UAAU,CAE1C"}
1
+ {"version":3,"file":"labels.d.ts","sourceRoot":"","sources":["../src/labels.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IAEzB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,aAAa,EAAE,MAAM,CAAA;IAGrB,gBAAgB,EAAE,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,CAAA;IACxE,iBAAiB,EAAE,CAAC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,CAAA;IACrD,iBAAiB,EAAE,MAAM,CAAA;IAGzB,mBAAmB,EAAE,CAAC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,CAAA;IAGvD,WAAW,EAAE;QACX,YAAY,EAAE,MAAM,CAAA;QACpB,WAAW,EAAE,MAAM,CAAA;QACnB,WAAW,EAAE,MAAM,CAAA;QACnB,WAAW,EAAE,MAAM,CAAA;QACnB,UAAU,EAAE,MAAM,CAAA;QAClB,UAAU,EAAE,MAAM,CAAA;QAClB,aAAa,EAAE,MAAM,CAAA;QACrB,YAAY,EAAE,MAAM,CAAA;KACrB,CAAA;CACF;AAED,eAAO,MAAM,aAAa,EAAE,UA2B3B,CAAA;AAID,eAAO,MAAM,cAAc,sCAAyB,CAAA;AAEpD,wBAAgB,aAAa,IAAI,UAAU,CAE1C"}
@@ -1,3 +1,4 @@
1
+ import "../chunk-WCLT3A6G.mjs";
1
2
  import {
2
3
  TanStackRouterSync,
3
4
  getTanStackRouter,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowsterix/react",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "React bindings for Flowsterix - guided tours and onboarding flows",
5
5
  "license": "MIT",
6
6
  "repository": {