react-native-lumen 1.0.1 → 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.
Files changed (51) hide show
  1. package/README.md +763 -231
  2. package/lib/module/components/TourOverlay.js +43 -3
  3. package/lib/module/components/TourOverlay.js.map +1 -1
  4. package/lib/module/components/TourProvider.js +318 -61
  5. package/lib/module/components/TourProvider.js.map +1 -1
  6. package/lib/module/components/TourTooltip.js +113 -73
  7. package/lib/module/components/TourTooltip.js.map +1 -1
  8. package/lib/module/components/TourZone.js +186 -119
  9. package/lib/module/components/TourZone.js.map +1 -1
  10. package/lib/module/constants/defaults.js +43 -0
  11. package/lib/module/constants/defaults.js.map +1 -1
  12. package/lib/module/context/TourContext.js +5 -0
  13. package/lib/module/context/TourContext.js.map +1 -0
  14. package/lib/module/hooks/useTour.js +1 -1
  15. package/lib/module/hooks/useTour.js.map +1 -1
  16. package/lib/module/hooks/useTourScrollView.js +71 -0
  17. package/lib/module/hooks/useTourScrollView.js.map +1 -0
  18. package/lib/module/index.js +6 -0
  19. package/lib/module/index.js.map +1 -1
  20. package/lib/module/utils/storage.js +188 -0
  21. package/lib/module/utils/storage.js.map +1 -0
  22. package/lib/typescript/src/components/TourOverlay.d.ts.map +1 -1
  23. package/lib/typescript/src/components/TourProvider.d.ts +21 -4
  24. package/lib/typescript/src/components/TourProvider.d.ts.map +1 -1
  25. package/lib/typescript/src/components/TourTooltip.d.ts.map +1 -1
  26. package/lib/typescript/src/components/TourZone.d.ts +19 -1
  27. package/lib/typescript/src/components/TourZone.d.ts.map +1 -1
  28. package/lib/typescript/src/constants/defaults.d.ts +10 -0
  29. package/lib/typescript/src/constants/defaults.d.ts.map +1 -1
  30. package/lib/typescript/src/context/TourContext.d.ts +3 -0
  31. package/lib/typescript/src/context/TourContext.d.ts.map +1 -0
  32. package/lib/typescript/src/hooks/useTourScrollView.d.ts +65 -0
  33. package/lib/typescript/src/hooks/useTourScrollView.d.ts.map +1 -0
  34. package/lib/typescript/src/index.d.ts +4 -0
  35. package/lib/typescript/src/index.d.ts.map +1 -1
  36. package/lib/typescript/src/types/index.d.ts +296 -1
  37. package/lib/typescript/src/types/index.d.ts.map +1 -1
  38. package/lib/typescript/src/utils/storage.d.ts +51 -0
  39. package/lib/typescript/src/utils/storage.d.ts.map +1 -0
  40. package/package.json +173 -171
  41. package/src/components/TourOverlay.tsx +45 -2
  42. package/src/components/TourProvider.tsx +408 -56
  43. package/src/components/TourTooltip.tsx +144 -71
  44. package/src/components/TourZone.tsx +238 -140
  45. package/src/constants/defaults.ts +51 -0
  46. package/src/context/TourContext.ts +4 -0
  47. package/src/hooks/useTour.ts +1 -1
  48. package/src/hooks/useTourScrollView.ts +111 -0
  49. package/src/index.tsx +27 -0
  50. package/src/types/index.ts +306 -1
  51. package/src/utils/storage.ts +226 -0
@@ -1,10 +1,11 @@
1
1
  "use strict";
2
2
 
3
- import { memo } from 'react';
3
+ import { memo, useMemo } from 'react';
4
4
  import { StyleSheet, Dimensions } from 'react-native';
5
5
  import Svg, { Path } from 'react-native-svg';
6
6
  import Animated, { useAnimatedProps, useAnimatedStyle } from 'react-native-reanimated';
7
7
  import { useTour } from "../hooks/useTour.js";
8
+ import { DEFAULT_ZONE_STYLE } from "../constants/defaults.js";
8
9
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
9
10
  const {
10
11
  width: SCREEN_WIDTH,
@@ -43,11 +44,22 @@ export const TourOverlay = /*#__PURE__*/memo(() => {
43
44
  targetHeight,
44
45
  targetRadius,
45
46
  opacity,
47
+ zoneBorderWidth,
46
48
  config,
47
49
  currentStep,
48
- steps
50
+ steps,
51
+ currentZoneStyle
49
52
  } = useTour();
50
53
 
54
+ // Get resolved zone style for styling the glow/border
55
+ const zoneStyle = useMemo(() => {
56
+ return {
57
+ ...DEFAULT_ZONE_STYLE,
58
+ ...config?.zoneStyle,
59
+ ...currentZoneStyle
60
+ };
61
+ }, [config?.zoneStyle, currentZoneStyle]);
62
+
51
63
  // Create the d string for the mask
52
64
  // Outer rectangle covers the whole screen
53
65
  // Inner shape is the "hole"
@@ -86,7 +98,8 @@ export const TourOverlay = /*#__PURE__*/memo(() => {
86
98
  // - Overlay shouldn't block anything?
87
99
  // - pointerEvents='none' on the whole container.
88
100
 
89
- const shouldBlockOutside = config?.preventInteraction ?? false;
101
+ // Check per-step preventInteraction first, then fall back to global config
102
+ const shouldBlockOutside = step?.preventInteraction ?? config?.preventInteraction ?? false;
90
103
 
91
104
  // If we don't want to block outside, we just let everything pass.
92
105
  // But wait, if we let everything pass, we can't implement 'clickable=false' strictness?
@@ -108,6 +121,30 @@ export const TourOverlay = /*#__PURE__*/memo(() => {
108
121
  borderRadius: targetRadius.value
109
122
  };
110
123
  });
124
+
125
+ // Animated style for the zone border/glow ring
126
+ const zoneBorderStyle = useAnimatedStyle(() => {
127
+ const isGlowEnabled = config?.enableGlow === true;
128
+ const borderW = zoneBorderWidth?.value ?? zoneStyle.borderWidth;
129
+ return {
130
+ position: 'absolute',
131
+ left: targetX.value,
132
+ top: targetY.value,
133
+ width: targetWidth.value,
134
+ height: targetHeight.value,
135
+ borderRadius: targetRadius.value,
136
+ borderWidth: borderW,
137
+ borderColor: zoneStyle.borderColor,
138
+ backgroundColor: 'transparent',
139
+ ...(isGlowEnabled && {
140
+ // Glow effect using React Native 0.76+ boxShadow API
141
+ boxShadow: `${zoneStyle.glowOffsetX}px ${zoneStyle.glowOffsetY}px ${zoneStyle.glowRadius}px ${zoneStyle.glowSpread}px ${zoneStyle.glowColor}`
142
+ })
143
+ };
144
+ });
145
+
146
+ // Determine if we should show the border/glow
147
+ const showBorder = config?.enableGlow === true || zoneStyle.borderWidth > 0;
111
148
  return /*#__PURE__*/_jsxs(AnimatedView, {
112
149
  pointerEvents: containerPointerEvents,
113
150
  style: StyleSheet.absoluteFill,
@@ -128,6 +165,9 @@ export const TourOverlay = /*#__PURE__*/memo(() => {
128
165
  style: blockerStyle,
129
166
  pointerEvents: "auto" // Catch touches
130
167
  // backgroundColor="transparent" // Default
168
+ }), showBorder && currentStep && /*#__PURE__*/_jsx(AnimatedView, {
169
+ style: zoneBorderStyle,
170
+ pointerEvents: "none"
131
171
  })]
132
172
  });
133
173
  });
@@ -1 +1 @@
1
- {"version":3,"names":["memo","StyleSheet","Dimensions","Svg","Path","Animated","useAnimatedProps","useAnimatedStyle","useTour","jsx","_jsx","jsxs","_jsxs","width","SCREEN_WIDTH","height","SCREEN_HEIGHT","get","AnimatedPath","createAnimatedComponent","AnimatedView","View","createRoundedRectPath","x","y","w","h","r","radius","Math","min","TourOverlay","targetX","targetY","targetWidth","targetHeight","targetRadius","opacity","config","currentStep","steps","animatedProps","holePath","value","path","d","fillOpacity","step","isClickable","clickable","shouldBlockOutside","preventInteraction","containerPointerEvents","blockerStyle","position","left","top","borderRadius","pointerEvents","style","absoluteFill","children","fill","fillRule","onPress"],"sourceRoot":"..\\..\\..\\src","sources":["components/TourOverlay.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["memo","useMemo","StyleSheet","Dimensions","Svg","Path","Animated","useAnimatedProps","useAnimatedStyle","useTour","DEFAULT_ZONE_STYLE","jsx","_jsx","jsxs","_jsxs","width","SCREEN_WIDTH","height","SCREEN_HEIGHT","get","AnimatedPath","createAnimatedComponent","AnimatedView","View","createRoundedRectPath","x","y","w","h","r","radius","Math","min","TourOverlay","targetX","targetY","targetWidth","targetHeight","targetRadius","opacity","zoneBorderWidth","config","currentStep","steps","currentZoneStyle","zoneStyle","animatedProps","holePath","value","path","d","fillOpacity","step","isClickable","clickable","shouldBlockOutside","preventInteraction","containerPointerEvents","blockerStyle","position","left","top","borderRadius","zoneBorderStyle","isGlowEnabled","enableGlow","borderW","borderWidth","borderColor","backgroundColor","boxShadow","glowOffsetX","glowOffsetY","glowRadius","glowSpread","glowColor","showBorder","pointerEvents","style","absoluteFill","children","fill","fillRule","onPress"],"sourceRoot":"..\\..\\..\\src","sources":["components/TourOverlay.tsx"],"mappings":"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","ignoreList":[]}
@@ -1,13 +1,88 @@
1
1
  "use strict";
2
2
 
3
- import React, { createContext, useState, useCallback, useMemo, useRef } from 'react';
3
+ import React, { useState, useCallback, useMemo, useRef, useEffect } from 'react';
4
4
  import { useSharedValue, withSpring, withTiming, useAnimatedRef, default as Animated } from 'react-native-reanimated';
5
- import { StyleSheet } from 'react-native';
5
+ import { StyleSheet, Dimensions } from 'react-native';
6
+ import { TourContext } from "../context/TourContext.js";
6
7
  import { TourOverlay } from "./TourOverlay.js";
7
8
  import { TourTooltip } from "./TourTooltip.js";
8
- import { DEFAULT_BACKDROP_OPACITY, DEFAULT_SPRING_CONFIG } from "../constants/defaults.js";
9
+ import { DEFAULT_BACKDROP_OPACITY, DEFAULT_SPRING_CONFIG, DEFAULT_ZONE_STYLE, resolveZoneStyle } from "../constants/defaults.js";
10
+ import { detectStorage, saveTourProgress, loadTourProgress, clearTourProgress } from "../utils/storage.js";
9
11
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
10
- export const TourContext = /*#__PURE__*/createContext(null);
12
+ const {
13
+ width: SCREEN_WIDTH,
14
+ height: SCREEN_HEIGHT
15
+ } = Dimensions.get('window');
16
+
17
+ /**
18
+ * Computes the zone geometry based on element bounds and zone style.
19
+ * Handles different shapes: rounded-rect, circle, pill.
20
+ */
21
+ function computeZoneGeometry(element, style) {
22
+ const {
23
+ paddingTop,
24
+ paddingRight,
25
+ paddingBottom,
26
+ paddingLeft,
27
+ shape,
28
+ borderRadius
29
+ } = style;
30
+ let sx, sy, sw, sh, sr;
31
+ switch (shape) {
32
+ case 'circle':
33
+ {
34
+ // Create a circular zone that encompasses the element
35
+ const cx = element.x + element.width / 2;
36
+ const cy = element.y + element.height / 2;
37
+ // Use the larger dimension to create a circle, plus padding
38
+ const radius = Math.max(element.width, element.height) / 2 + style.padding;
39
+ sx = cx - radius;
40
+ sy = cy - radius;
41
+ sw = radius * 2;
42
+ sh = radius * 2;
43
+ sr = radius;
44
+ break;
45
+ }
46
+ case 'pill':
47
+ {
48
+ // Pill shape with fully rounded ends
49
+ sx = element.x - paddingLeft;
50
+ sy = element.y - paddingTop;
51
+ sw = element.width + paddingLeft + paddingRight;
52
+ sh = element.height + paddingTop + paddingBottom;
53
+ sr = sh / 2; // Fully rounded based on height
54
+ break;
55
+ }
56
+ case 'rounded-rect':
57
+ default:
58
+ {
59
+ sx = element.x - paddingLeft;
60
+ sy = element.y - paddingTop;
61
+ sw = element.width + paddingLeft + paddingRight;
62
+ sh = element.height + paddingTop + paddingBottom;
63
+ sr = borderRadius;
64
+ break;
65
+ }
66
+ }
67
+
68
+ // Clamp to screen bounds
69
+ sx = Math.max(0, Math.min(sx, SCREEN_WIDTH - sw));
70
+ sy = Math.max(0, Math.min(sy, SCREEN_HEIGHT - sh));
71
+ sw = Math.min(sw, SCREEN_WIDTH - sx);
72
+ sh = Math.min(sh, SCREEN_HEIGHT - sy);
73
+
74
+ // Ensure minimum size
75
+ const minSize = 40;
76
+ sw = Math.max(sw, minSize);
77
+ sh = Math.max(sh, minSize);
78
+ return {
79
+ x: sx,
80
+ y: sy,
81
+ width: sw,
82
+ height: sh,
83
+ borderRadius: sr
84
+ };
85
+ }
11
86
  const AnimatedView = Animated.View;
12
87
  export const TourProvider = ({
13
88
  children,
@@ -17,11 +92,55 @@ export const TourProvider = ({
17
92
  }) => {
18
93
  const [steps, setSteps] = useState({});
19
94
  const [currentStep, setCurrentStep] = useState(null);
95
+ const [hasSavedProgress, setHasSavedProgress] = useState(false);
20
96
 
21
97
  // ref to access latest measurements without causing re-renders
22
98
  const measurements = useRef({});
23
99
  const containerRef = useAnimatedRef();
24
100
 
101
+ // ─── Persistence Setup ─────────────────────────────────────────────────────
102
+ const persistenceConfig = config?.persistence;
103
+ const isPersistenceEnabled = persistenceConfig?.enabled ?? false;
104
+ const tourId = persistenceConfig?.tourId ?? 'default';
105
+ const autoResume = persistenceConfig?.autoResume ?? true;
106
+ const clearOnComplete = persistenceConfig?.clearOnComplete ?? true;
107
+ const maxAge = persistenceConfig?.maxAge;
108
+
109
+ // Get storage adapter (custom or auto-detected)
110
+ const storageAdapter = useMemo(() => {
111
+ if (!isPersistenceEnabled) return null;
112
+ if (persistenceConfig?.storage) return persistenceConfig.storage;
113
+ const detected = detectStorage();
114
+ return detected.adapter;
115
+ }, [isPersistenceEnabled, persistenceConfig?.storage]);
116
+
117
+ // Check for saved progress on mount
118
+ useEffect(() => {
119
+ if (!isPersistenceEnabled || !storageAdapter) {
120
+ setHasSavedProgress(false);
121
+ return;
122
+ }
123
+ const checkSavedProgress = async () => {
124
+ try {
125
+ const savedProgress = await loadTourProgress(storageAdapter, tourId);
126
+ if (savedProgress) {
127
+ // Check if progress is expired
128
+ if (maxAge && Date.now() - savedProgress.timestamp > maxAge) {
129
+ await clearTourProgress(storageAdapter, tourId);
130
+ setHasSavedProgress(false);
131
+ } else {
132
+ setHasSavedProgress(true);
133
+ }
134
+ } else {
135
+ setHasSavedProgress(false);
136
+ }
137
+ } catch {
138
+ setHasSavedProgress(false);
139
+ }
140
+ };
141
+ checkSavedProgress();
142
+ }, [isPersistenceEnabled, storageAdapter, tourId, maxAge]);
143
+
25
144
  // --- Shared Values for Animations (Zero Bridge Crossing) ---
26
145
  // Initialize off-screen or 0
27
146
  const targetX = useSharedValue(0);
@@ -30,6 +149,35 @@ export const TourProvider = ({
30
149
  const targetHeight = useSharedValue(0);
31
150
  const targetRadius = useSharedValue(10); // Default border radius
32
151
  const opacity = useSharedValue(0); // 0 = hidden, 1 = visible
152
+ const zoneBorderWidth = useSharedValue(DEFAULT_ZONE_STYLE.borderWidth);
153
+
154
+ // Track current step's resolved zone style
155
+ const currentZoneStyle = useMemo(() => {
156
+ if (!currentStep) return null;
157
+ const step = steps[currentStep];
158
+ if (!step) return null;
159
+ return resolveZoneStyle(config?.zoneStyle, step.zoneStyle);
160
+ }, [currentStep, steps, config?.zoneStyle]);
161
+
162
+ // Helper to get spring config for a step (supports per-step overrides)
163
+ const getSpringConfigForStep = useCallback(stepKey => {
164
+ const step = steps[stepKey];
165
+ const stepStyle = step?.zoneStyle;
166
+ const baseConfig = config?.springConfig ?? DEFAULT_SPRING_CONFIG;
167
+
168
+ // Allow per-step spring overrides
169
+ if (stepStyle?.springDamping !== undefined || stepStyle?.springStiffness !== undefined) {
170
+ return {
171
+ damping: stepStyle.springDamping ?? baseConfig.damping,
172
+ stiffness: stepStyle.springStiffness ?? baseConfig.stiffness,
173
+ mass: baseConfig.mass,
174
+ overshootClamping: baseConfig.overshootClamping,
175
+ restDisplacementThreshold: baseConfig.restDisplacementThreshold,
176
+ restSpeedThreshold: baseConfig.restSpeedThreshold
177
+ };
178
+ }
179
+ return baseConfig;
180
+ }, [steps, config?.springConfig]);
33
181
 
34
182
  // Helper to animate to a specific step's layout
35
183
  const animateToStep = useCallback(stepKey => {
@@ -40,18 +188,18 @@ export const TourProvider = ({
40
188
  console.warn('[TourProvider] Invalid measurements for step:', stepKey, measure);
41
189
  return;
42
190
  }
43
- const springConfig = config?.springConfig ?? DEFAULT_SPRING_CONFIG;
44
- targetX.value = withSpring(measure.x, springConfig);
45
- targetY.value = withSpring(measure.y, springConfig);
46
- targetWidth.value = withSpring(measure.width, springConfig);
47
- targetHeight.value = withSpring(measure.height, springConfig);
48
-
49
- // If measure result has radius or step meta has radius, use it.
50
- // For now defaulting to 10 or meta reading if we passed it back in measure?
51
- // Let's assume meta is in steps state.
52
191
  const step = steps[stepKey];
53
- const radius = step?.meta?.borderRadius ?? 10;
54
- targetRadius.value = withSpring(radius, springConfig);
192
+ const resolvedStyle = resolveZoneStyle(config?.zoneStyle, step?.zoneStyle);
193
+ const springConfig = getSpringConfigForStep(stepKey);
194
+
195
+ // Compute zone geometry based on style (handles shapes and padding)
196
+ const geo = computeZoneGeometry(measure, resolvedStyle);
197
+ targetX.value = withSpring(geo.x, springConfig);
198
+ targetY.value = withSpring(geo.y, springConfig);
199
+ targetWidth.value = withSpring(geo.width, springConfig);
200
+ targetHeight.value = withSpring(geo.height, springConfig);
201
+ targetRadius.value = withSpring(geo.borderRadius, springConfig);
202
+ zoneBorderWidth.value = withSpring(resolvedStyle.borderWidth, springConfig);
55
203
 
56
204
  // Ensure overlay is visible
57
205
  opacity.value = withTiming(backdropOpacity, {
@@ -60,12 +208,18 @@ export const TourProvider = ({
60
208
  } else {
61
209
  console.warn('[TourProvider] No measurements found for step:', stepKey);
62
210
  }
63
- }, [backdropOpacity, targetX, targetY, targetWidth, targetHeight, targetRadius, opacity, config?.springConfig, steps]);
211
+ }, [backdropOpacity, targetX, targetY, targetWidth, targetHeight, targetRadius, zoneBorderWidth, opacity, getSpringConfigForStep, steps, config?.zoneStyle]);
64
212
  const registerStep = useCallback(step => {
65
213
  setSteps(prev => ({
66
214
  ...prev,
67
215
  [step.key]: step
68
216
  }));
217
+ // If this step was pending (waiting for cross-screen mount), activate it
218
+ if (pendingStepRef.current === step.key) {
219
+ pendingStepRef.current = null;
220
+ setCurrentStep(step.key);
221
+ // Overlay opacity will be set by updateStepLayout when measurement arrives
222
+ }
69
223
  }, []);
70
224
  const unregisterStep = useCallback(key => {
71
225
  setSteps(prev => {
@@ -85,25 +239,35 @@ export const TourProvider = ({
85
239
  measurements.current[key] = measure;
86
240
  // If this step is currently active (e.g. scroll happened or resize), update shared values on the fly
87
241
  if (currentStep === key) {
88
- const springConfig = config?.springConfig ?? DEFAULT_SPRING_CONFIG;
89
- targetX.value = withSpring(measure.x, springConfig);
90
- targetY.value = withSpring(measure.y, springConfig);
91
- targetWidth.value = withSpring(measure.width, springConfig);
92
- targetHeight.value = withSpring(measure.height, springConfig);
93
-
94
- // Update radius if available
95
242
  const step = steps[key];
96
- const radius = step?.meta?.borderRadius ?? 10;
97
- targetRadius.value = withSpring(radius, springConfig);
243
+ const resolvedStyle = resolveZoneStyle(config?.zoneStyle, step?.zoneStyle);
244
+ const springConfig = getSpringConfigForStep(key);
245
+
246
+ // Compute zone geometry based on style
247
+ const geo = computeZoneGeometry(measure, resolvedStyle);
248
+ targetX.value = withSpring(geo.x, springConfig);
249
+ targetY.value = withSpring(geo.y, springConfig);
250
+ targetWidth.value = withSpring(geo.width, springConfig);
251
+ targetHeight.value = withSpring(geo.height, springConfig);
252
+ targetRadius.value = withSpring(geo.borderRadius, springConfig);
253
+ zoneBorderWidth.value = withSpring(resolvedStyle.borderWidth, springConfig);
98
254
 
99
255
  // Ensure overlay is visible (fixes race condition where start() was called before measure)
100
256
  opacity.value = withTiming(backdropOpacity, {
101
257
  duration: 300
102
258
  });
103
259
  }
104
- }, [currentStep, targetX, targetY, targetWidth, targetHeight, targetRadius, opacity, backdropOpacity, config?.springConfig, steps]);
260
+ }, [currentStep, targetX, targetY, targetWidth, targetHeight, targetRadius, zoneBorderWidth, opacity, backdropOpacity, getSpringConfigForStep, config?.zoneStyle, steps]);
261
+
262
+ // Flatten stepsOrder (supports both string[] and Record<string, string[]>)
263
+ const flatStepsOrder = useMemo(() => {
264
+ if (!initialStepsOrder) return undefined;
265
+ if (Array.isArray(initialStepsOrder)) return initialStepsOrder;
266
+ // Object format: flatten values in key order
267
+ return Object.values(initialStepsOrder).flat();
268
+ }, [initialStepsOrder]);
105
269
  const getOrderedSteps = useCallback(() => {
106
- if (initialStepsOrder) return initialStepsOrder;
270
+ if (flatStepsOrder) return flatStepsOrder;
107
271
  // If order property exists on steps, sort by it.
108
272
  const stepKeys = Object.keys(steps);
109
273
  if (stepKeys.length > 0) {
@@ -114,64 +278,149 @@ export const TourProvider = ({
114
278
  }
115
279
  }
116
280
  return stepKeys;
117
- }, [initialStepsOrder, steps]);
118
- const start = useCallback(stepKey => {
281
+ }, [flatStepsOrder, steps]);
282
+
283
+ // Pending step for cross-screen navigation
284
+ // When next/prev targets a step that isn't mounted yet, we store it here
285
+ // and resume when that step's TourZone registers.
286
+ const pendingStepRef = useRef(null);
287
+
288
+ // Save progress when step changes
289
+ useEffect(() => {
290
+ if (!isPersistenceEnabled || !storageAdapter || !currentStep) return;
119
291
  const ordered = getOrderedSteps();
120
- const firstStep = stepKey || ordered[0];
292
+ const stepIndex = ordered.indexOf(currentStep);
293
+ if (stepIndex >= 0) {
294
+ saveTourProgress(storageAdapter, tourId, currentStep, stepIndex).catch(() => {
295
+ // Silently ignore save errors
296
+ });
297
+ }
298
+ }, [currentStep, isPersistenceEnabled, storageAdapter, tourId, getOrderedSteps]);
299
+ const start = useCallback(async stepKey => {
300
+ const ordered = getOrderedSteps();
301
+ let targetStep = stepKey;
302
+
303
+ // If no specific step and autoResume is enabled, try to restore from storage
304
+ if (!targetStep && isPersistenceEnabled && storageAdapter && autoResume) {
305
+ try {
306
+ const savedProgress = await loadTourProgress(storageAdapter, tourId);
307
+ if (savedProgress) {
308
+ // Check if progress is expired
309
+ if (maxAge && Date.now() - savedProgress.timestamp > maxAge) {
310
+ await clearTourProgress(storageAdapter, tourId);
311
+ setHasSavedProgress(false);
312
+ } else if (ordered.includes(savedProgress.currentStepKey)) {
313
+ // Verify the saved step still exists in order
314
+ targetStep = savedProgress.currentStepKey;
315
+ }
316
+ }
317
+ } catch {
318
+ // Ignore load errors, start from beginning
319
+ }
320
+ }
321
+ const firstStep = targetStep || ordered[0];
121
322
  if (firstStep) {
122
- setCurrentStep(firstStep);
123
- // We need to wait for layout if it's not ready?
124
- // Assuming layout is ready since components are mounted.
125
- // But if we start immediately on mount, might be tricky.
126
- // For now assume standard flow.
127
- // requestAnimationFrame to ensure state update propagates if needed,
128
- // but simple call is usually fine.
129
- setTimeout(() => animateToStep(firstStep), 0);
323
+ // Check if the target step is registered (mounted)
324
+ if (steps[firstStep]) {
325
+ setCurrentStep(firstStep);
326
+ setTimeout(() => animateToStep(firstStep), 0);
327
+ } else {
328
+ // Step not mounted yet (on a different screen) - set as pending
329
+ pendingStepRef.current = firstStep;
330
+ // Don't set currentStep or opacity - wait for TourZone to mount
331
+ }
130
332
  }
131
- }, [getOrderedSteps, animateToStep]);
333
+ }, [getOrderedSteps, animateToStep, steps, isPersistenceEnabled, storageAdapter, autoResume, tourId, maxAge]);
132
334
  const stop = useCallback(() => {
133
335
  setCurrentStep(null);
134
336
  opacity.value = withTiming(0, {
135
337
  duration: 300
136
338
  });
339
+ // Note: We do NOT clear progress on stop - only on complete or explicit clearProgress
137
340
  }, [opacity]);
341
+
342
+ // Clear progress helper
343
+ const clearProgress = useCallback(async () => {
344
+ if (!isPersistenceEnabled || !storageAdapter) return;
345
+ try {
346
+ await clearTourProgress(storageAdapter, tourId);
347
+ setHasSavedProgress(false);
348
+ } catch {
349
+ // Silently ignore clear errors
350
+ }
351
+ }, [isPersistenceEnabled, storageAdapter, tourId]);
138
352
  const next = useCallback(() => {
139
353
  if (!currentStep) return;
354
+
355
+ // Block navigation if current step has completed === false
356
+ const currentStepData = steps[currentStep];
357
+ if (currentStepData?.completed === false) {
358
+ return;
359
+ }
140
360
  const ordered = getOrderedSteps();
141
361
  const currentIndex = ordered.indexOf(currentStep);
142
362
  if (currentIndex < ordered.length - 1) {
143
- const nextStep = ordered[currentIndex + 1];
144
- if (nextStep) {
145
- setCurrentStep(nextStep);
146
- // Don't call animateToStep here - it uses cached measurements that may be stale
147
- // after scroll. The useFrameCallback in TourZone will handle position tracking
148
- // using measure() with correct screen coordinates (pageX/pageY).
149
- // Just ensure the overlay is visible.
150
- opacity.value = withTiming(backdropOpacity, {
151
- duration: 300
152
- });
363
+ const nextStepKey = ordered[currentIndex + 1];
364
+ if (nextStepKey) {
365
+ // Check if the next step is registered (mounted)
366
+ if (steps[nextStepKey]) {
367
+ setCurrentStep(nextStepKey);
368
+ // Don't call animateToStep here - it uses cached measurements that may be stale
369
+ // after scroll. The useFrameCallback in TourZone will handle position tracking
370
+ // using measure() with correct screen coordinates (pageX/pageY).
371
+ // Just ensure the overlay is visible.
372
+ opacity.value = withTiming(backdropOpacity, {
373
+ duration: 300
374
+ });
375
+ } else {
376
+ // Step not mounted yet (on a different screen) - set as pending
377
+ pendingStepRef.current = nextStepKey;
378
+ setCurrentStep(null);
379
+ opacity.value = withTiming(0, {
380
+ duration: 300
381
+ });
382
+ // Persist pending step so it can be resumed
383
+ if (isPersistenceEnabled && storageAdapter) {
384
+ const stepIndex = ordered.indexOf(nextStepKey);
385
+ saveTourProgress(storageAdapter, tourId, nextStepKey, stepIndex).catch(() => {});
386
+ }
387
+ }
153
388
  } else {
154
389
  stop();
155
390
  }
156
391
  } else {
157
- stop(); // End of tour
392
+ // End of tour - clear progress if configured
393
+ if (isPersistenceEnabled && clearOnComplete && storageAdapter) {
394
+ clearTourProgress(storageAdapter, tourId).then(() => setHasSavedProgress(false)).catch(() => {});
395
+ }
396
+ stop();
158
397
  }
159
- }, [currentStep, getOrderedSteps, stop, opacity, backdropOpacity]);
398
+ }, [currentStep, steps, getOrderedSteps, stop, opacity, backdropOpacity, isPersistenceEnabled, clearOnComplete, storageAdapter, tourId]);
160
399
  const prev = useCallback(() => {
161
400
  if (!currentStep) return;
162
401
  const ordered = getOrderedSteps();
163
402
  const currentIndex = ordered.indexOf(currentStep);
164
403
  if (currentIndex > 0) {
165
- const prevStep = ordered[currentIndex - 1];
166
- if (prevStep) {
167
- setCurrentStep(prevStep);
168
- // Don't call animateToStep - let useFrameCallback handle position tracking
169
- opacity.value = withTiming(backdropOpacity, {
170
- duration: 300
171
- });
404
+ const prevStepKey = ordered[currentIndex - 1];
405
+ if (prevStepKey) {
406
+ // Check if the previous step is registered (mounted)
407
+ if (steps[prevStepKey]) {
408
+ setCurrentStep(prevStepKey);
409
+ // Don't call animateToStep - let useFrameCallback handle position tracking
410
+ opacity.value = withTiming(backdropOpacity, {
411
+ duration: 300
412
+ });
413
+ } else {
414
+ // Step not mounted (on a different screen) - set as pending
415
+ pendingStepRef.current = prevStepKey;
416
+ setCurrentStep(null);
417
+ opacity.value = withTiming(0, {
418
+ duration: 300
419
+ });
420
+ }
172
421
  }
173
422
  }
174
- }, [currentStep, getOrderedSteps, opacity, backdropOpacity]);
423
+ }, [currentStep, steps, getOrderedSteps, opacity, backdropOpacity]);
175
424
  const scrollViewRef = useAnimatedRef();
176
425
  const setScrollViewRef = useCallback(_ref => {
177
426
  // If user passes a ref, we might want to sync it?
@@ -192,6 +441,9 @@ export const TourProvider = ({
192
441
  // Let's make `setScrollViewRef` actually do something if possible, or just document "Use exposed scrollViewRef".
193
442
  // For now, let's just return the `scrollViewRef` we created.
194
443
  }, []);
444
+
445
+ // Expose ordered step keys for tooltip and external use
446
+ const orderedStepKeys = useMemo(() => getOrderedSteps(), [getOrderedSteps]);
195
447
  const value = useMemo(() => ({
196
448
  start,
197
449
  stop,
@@ -207,12 +459,17 @@ export const TourProvider = ({
207
459
  targetHeight,
208
460
  targetRadius,
209
461
  opacity,
462
+ zoneBorderWidth,
210
463
  steps,
211
464
  config,
212
465
  containerRef,
213
466
  scrollViewRef,
214
- setScrollViewRef
215
- }), [start, stop, next, prev, registerStep, unregisterStep, updateStepLayout, currentStep, targetX, targetY, targetWidth, targetHeight, targetRadius, opacity, steps, config, containerRef, scrollViewRef, setScrollViewRef]);
467
+ setScrollViewRef,
468
+ currentZoneStyle,
469
+ clearProgress,
470
+ hasSavedProgress,
471
+ orderedStepKeys
472
+ }), [start, stop, next, prev, registerStep, unregisterStep, updateStepLayout, currentStep, targetX, targetY, targetWidth, targetHeight, targetRadius, opacity, zoneBorderWidth, steps, config, containerRef, scrollViewRef, setScrollViewRef, currentZoneStyle, clearProgress, hasSavedProgress, orderedStepKeys]);
216
473
  return /*#__PURE__*/_jsx(TourContext.Provider, {
217
474
  value: value,
218
475
  children: /*#__PURE__*/_jsxs(AnimatedView, {