react-native-lumen 1.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/LICENSE +20 -0
- package/README.md +231 -0
- package/lib/module/components/TourOverlay.js +134 -0
- package/lib/module/components/TourOverlay.js.map +1 -0
- package/lib/module/components/TourProvider.js +233 -0
- package/lib/module/components/TourProvider.js.map +1 -0
- package/lib/module/components/TourTooltip.js +233 -0
- package/lib/module/components/TourTooltip.js.map +1 -0
- package/lib/module/components/TourZone.js +246 -0
- package/lib/module/components/TourZone.js.map +1 -0
- package/lib/module/constants/animations.js +72 -0
- package/lib/module/constants/animations.js.map +1 -0
- package/lib/module/constants/defaults.js +14 -0
- package/lib/module/constants/defaults.js.map +1 -0
- package/lib/module/hooks/useTour.js +12 -0
- package/lib/module/hooks/useTour.js.map +1 -0
- package/lib/module/index.js +11 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/types/index.js +4 -0
- package/lib/module/types/index.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/components/TourOverlay.d.ts +2 -0
- package/lib/typescript/src/components/TourOverlay.d.ts.map +1 -0
- package/lib/typescript/src/components/TourProvider.d.ts +21 -0
- package/lib/typescript/src/components/TourProvider.d.ts.map +1 -0
- package/lib/typescript/src/components/TourTooltip.d.ts +2 -0
- package/lib/typescript/src/components/TourTooltip.d.ts.map +1 -0
- package/lib/typescript/src/components/TourZone.d.ts +16 -0
- package/lib/typescript/src/components/TourZone.d.ts.map +1 -0
- package/lib/typescript/src/constants/animations.d.ts +34 -0
- package/lib/typescript/src/constants/animations.d.ts.map +1 -0
- package/lib/typescript/src/constants/defaults.d.ts +10 -0
- package/lib/typescript/src/constants/defaults.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useTour.d.ts +2 -0
- package/lib/typescript/src/hooks/useTour.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +9 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/types/index.d.ts +135 -0
- package/lib/typescript/src/types/index.d.ts.map +1 -0
- package/package.json +171 -0
- package/src/components/TourOverlay.tsx +153 -0
- package/src/components/TourProvider.tsx +361 -0
- package/src/components/TourTooltip.tsx +252 -0
- package/src/components/TourZone.tsx +372 -0
- package/src/constants/animations.ts +71 -0
- package/src/constants/defaults.ts +15 -0
- package/src/hooks/useTour.ts +10 -0
- package/src/index.tsx +8 -0
- package/src/types/index.ts +142 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 thedev204
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
in the Software without restriction, including without limitation the rights
|
|
7
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
furnished to do so, subject to the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
# React Native Lumen 💡
|
|
2
|
+
|
|
3
|
+
> A high-performance, fully customizable app tour library for React Native, powered by Reanimated 3.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
## Demo
|
|
8
|
+
|
|
9
|
+
<p>
|
|
10
|
+
<img src="./assets/showcase.gif" width="220" alt="App Tour Demo" />
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- âš¡ **High Performance**: Built with `react-native-reanimated` worklets for 60fps animations.
|
|
16
|
+
- 🎨 **Fully Customizable**: Custom Renderers for tooltips, customizable shapes, and backdrops.
|
|
17
|
+
- 📱 **Expo Compatible**: Works seamlessly with Expo and bare React Native projects.
|
|
18
|
+
- 🤸 **Smooth Transitions**: Fluid morphing animations between steps.
|
|
19
|
+
- ✨ **Animation Presets**: Ships with beautiful bouncy, gentle, and snappy spring presets.
|
|
20
|
+
- 📜 **Auto Scrolling**: Automatically scrolls to next steps.
|
|
21
|
+
- 👆 **Interaction Control**: Choose to block or allow interactions with the underlying app.
|
|
22
|
+
|
|
23
|
+
## Requirements
|
|
24
|
+
|
|
25
|
+
This library relies on strict peer dependencies to ensure performance:
|
|
26
|
+
|
|
27
|
+
- `react-native` >= 0.70.0
|
|
28
|
+
- `react-native-reanimated` >= 3.0.0
|
|
29
|
+
- `react-native-svg` >= 12.0.0
|
|
30
|
+
- `react-native-gesture-handler` >= 2.0.0
|
|
31
|
+
|
|
32
|
+
## Installation
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
npm install react-native-lumen react-native-reanimated react-native-svg react-native-gesture-handler react-native-worklets
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Usage
|
|
39
|
+
|
|
40
|
+
1. **Wrap your App with `TourProvider`**:
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
import { TourProvider } from 'react-native-lumen';
|
|
44
|
+
|
|
45
|
+
export default function App() {
|
|
46
|
+
return (
|
|
47
|
+
<TourProvider>
|
|
48
|
+
<YourAppContent />
|
|
49
|
+
</TourProvider>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
2. **Highlight Elements with `TourZone`**:
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
import { TourZone } from 'react-native-lumen';
|
|
58
|
+
|
|
59
|
+
<TourZone
|
|
60
|
+
stepKey="step-1"
|
|
61
|
+
name="My Feature"
|
|
62
|
+
description="This is an awesome feature you should know about."
|
|
63
|
+
order={1}
|
|
64
|
+
borderRadius={10}
|
|
65
|
+
>
|
|
66
|
+
<MyButton />
|
|
67
|
+
</TourZone>;
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
3. **Control the Tour**:
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
import { useTour } from 'react-native-lumen';
|
|
74
|
+
|
|
75
|
+
const MyComponent = () => {
|
|
76
|
+
const { start } = useTour();
|
|
77
|
+
return <Button title="Start Tour" onPress={() => start()} />;
|
|
78
|
+
};
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## API Documentation
|
|
82
|
+
|
|
83
|
+
### `TourProvider`
|
|
84
|
+
|
|
85
|
+
The main context provider. Place this at the root of your application.
|
|
86
|
+
|
|
87
|
+
| Prop | Type | Default | Description |
|
|
88
|
+
| :---------------- | :---------------- | :---------- | :------------------------------------------------------- |
|
|
89
|
+
| `children` | `React.ReactNode` | Required | Application content. |
|
|
90
|
+
| `stepsOrder` | `string[]` | `undefined` | Optional array of step keys to define a forced sequence. |
|
|
91
|
+
| `backdropOpacity` | `number` | `0.5` | Opacity of the dark background overlay (0-1). |
|
|
92
|
+
| `config` | `TourConfig` | `undefined` | Global configuration options. |
|
|
93
|
+
|
|
94
|
+
### `TourZone`
|
|
95
|
+
|
|
96
|
+
Wrapper component to register an element as a tour step.
|
|
97
|
+
|
|
98
|
+
| Prop | Type | Default | Description |
|
|
99
|
+
| :------------- | :------------------- | :---------- | :---------------------------------------------- |
|
|
100
|
+
| `stepKey` | `string` | Required | Unique identifier for the step. |
|
|
101
|
+
| `name` | `string` | `undefined` | Title of the step. |
|
|
102
|
+
| `description` | `string` | Required | Description text shown in the tooltip. |
|
|
103
|
+
| `order` | `number` | `undefined` | Order of appearance (if `stepsOrder` not used). |
|
|
104
|
+
| `shape` | `'rect' \| 'circle'` | `'rect'` | Shape of the spotlight. |
|
|
105
|
+
| `borderRadius` | `number` | `10` | Border radius of the spotlight. |
|
|
106
|
+
| `clickable` | `boolean` | `false` | If `true`, the step remains interactive. |
|
|
107
|
+
| `style` | `ViewStyle` | `undefined` | Style for the wrapping container. |
|
|
108
|
+
|
|
109
|
+
### `TourConfig`
|
|
110
|
+
|
|
111
|
+
Configuration object needed for `TourProvider`.
|
|
112
|
+
|
|
113
|
+
```tsx
|
|
114
|
+
interface TourConfig {
|
|
115
|
+
/**
|
|
116
|
+
* Animation configuration for the spotlight movement.
|
|
117
|
+
* You can use presets like WigglySpringConfig, GentleSpringConfig etc.
|
|
118
|
+
*/
|
|
119
|
+
springConfig?: WithSpringConfig;
|
|
120
|
+
/**
|
|
121
|
+
* If true, prevents interaction with the underlying app while tour is active.
|
|
122
|
+
*/
|
|
123
|
+
preventInteraction?: boolean;
|
|
124
|
+
/**
|
|
125
|
+
* Custom labels for buttons.
|
|
126
|
+
*/
|
|
127
|
+
labels?: {
|
|
128
|
+
next?: string;
|
|
129
|
+
previous?: string;
|
|
130
|
+
finish?: string;
|
|
131
|
+
skip?: string;
|
|
132
|
+
};
|
|
133
|
+
/**
|
|
134
|
+
* Custom renderer for the card/tooltip.
|
|
135
|
+
*/
|
|
136
|
+
renderCard?: (props: CardProps) => React.ReactNode;
|
|
137
|
+
/**
|
|
138
|
+
* Initial overlay opacity. Default 0.5
|
|
139
|
+
*/
|
|
140
|
+
backdropOpacity?: number;
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Customization Guide
|
|
145
|
+
|
|
146
|
+
### Animation Presets
|
|
147
|
+
|
|
148
|
+
React Native Lumen comes with built-in Reanimated spring configs for easy usage.
|
|
149
|
+
|
|
150
|
+
```tsx
|
|
151
|
+
import { TourProvider, WigglySpringConfig } from 'react-native-lumen';
|
|
152
|
+
|
|
153
|
+
<TourProvider config={{ springConfig: WigglySpringConfig }}>...</TourProvider>;
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Auto Scroll Support
|
|
157
|
+
|
|
158
|
+
React Native Lumen supports auto-scrolling to steps that are off-screen. To enable this, simply attach the `scrollViewRef` provided by the hook to your scroll container.
|
|
159
|
+
|
|
160
|
+
```tsx
|
|
161
|
+
import { useTour } from 'react-native-lumen';
|
|
162
|
+
import Animated from 'react-native-reanimated';
|
|
163
|
+
|
|
164
|
+
const MyScrollableScreen = () => {
|
|
165
|
+
const { scrollViewRef } = useTour();
|
|
166
|
+
|
|
167
|
+
return (
|
|
168
|
+
<Animated.ScrollView ref={scrollViewRef}>
|
|
169
|
+
{/* ... content with TourZones ... */}
|
|
170
|
+
</Animated.ScrollView>
|
|
171
|
+
);
|
|
172
|
+
};
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
> **Note:** The scroll view must be compatible with Reanimated refs (e.g. `Animated.ScrollView`).
|
|
176
|
+
|
|
177
|
+
Available presets:
|
|
178
|
+
|
|
179
|
+
- `Reanimated3DefaultSpringConfig`
|
|
180
|
+
- `WigglySpringConfig` (Bouncy)
|
|
181
|
+
- `GentleSpringConfig` (Smooth)
|
|
182
|
+
- `SnappySpringConfig` (Fast & Responsive)
|
|
183
|
+
- `and more!`
|
|
184
|
+
|
|
185
|
+
### Custom Tooltip Card
|
|
186
|
+
|
|
187
|
+
You can fully replace the default tooltip with your own beautiful UI using the `renderCard` prop in `config`.
|
|
188
|
+
|
|
189
|
+
```tsx
|
|
190
|
+
import { TourProvider, CardProps } from 'react-native-lumen';
|
|
191
|
+
|
|
192
|
+
const CustomCard = ({
|
|
193
|
+
step,
|
|
194
|
+
next,
|
|
195
|
+
prev,
|
|
196
|
+
stop,
|
|
197
|
+
isLast,
|
|
198
|
+
currentStepIndex,
|
|
199
|
+
totalSteps,
|
|
200
|
+
}: CardProps) => (
|
|
201
|
+
<View style={{ padding: 20, backgroundColor: 'white', borderRadius: 20 }}>
|
|
202
|
+
<Text style={{ fontWeight: 'bold', fontSize: 20 }}>{step.name}</Text>
|
|
203
|
+
<Text>{step.description}</Text>
|
|
204
|
+
<Text style={{ color: 'gray' }}>
|
|
205
|
+
Step {currentStepIndex + 1} of {totalSteps}
|
|
206
|
+
</Text>
|
|
207
|
+
|
|
208
|
+
<View style={{ flexDirection: 'row', marginTop: 10 }}>
|
|
209
|
+
<Button onPress={stop} title="Close" />
|
|
210
|
+
<View style={{ flex: 1 }} />
|
|
211
|
+
{!isLast ? (
|
|
212
|
+
<Button onPress={next} title="Next" />
|
|
213
|
+
) : (
|
|
214
|
+
<Button onPress={stop} title="Finish" />
|
|
215
|
+
)}
|
|
216
|
+
</View>
|
|
217
|
+
</View>
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
export default function App() {
|
|
221
|
+
return (
|
|
222
|
+
<TourProvider config={{ renderCard: (props) => <CustomCard {...props} /> }}>
|
|
223
|
+
<AppContent />
|
|
224
|
+
</TourProvider>
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
## License
|
|
230
|
+
|
|
231
|
+
MIT
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { memo } from 'react';
|
|
4
|
+
import { StyleSheet, Dimensions } from 'react-native';
|
|
5
|
+
import Svg, { Path } from 'react-native-svg';
|
|
6
|
+
import Animated, { useAnimatedProps, useAnimatedStyle } from 'react-native-reanimated';
|
|
7
|
+
import { useTour } from "../hooks/useTour.js";
|
|
8
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
9
|
+
const {
|
|
10
|
+
width: SCREEN_WIDTH,
|
|
11
|
+
height: SCREEN_HEIGHT
|
|
12
|
+
} = Dimensions.get('window');
|
|
13
|
+
const AnimatedPath = Animated.createAnimatedComponent(Path);
|
|
14
|
+
const AnimatedView = Animated.View;
|
|
15
|
+
|
|
16
|
+
// Helper to create rounded rect path
|
|
17
|
+
// x,y are top-left coordinates
|
|
18
|
+
const createRoundedRectPath = (x, y, w, h, r) => {
|
|
19
|
+
'worklet';
|
|
20
|
+
|
|
21
|
+
// Ensure radius doesn't exceed dimensions
|
|
22
|
+
const radius = Math.min(r, w / 2, h / 2);
|
|
23
|
+
|
|
24
|
+
// Standard SVG Path command for rounded rect
|
|
25
|
+
return `
|
|
26
|
+
M ${x + radius}, ${y}
|
|
27
|
+
H ${x + w - radius}
|
|
28
|
+
A ${radius} ${radius} 0 0 1 ${x + w}, ${y + radius}
|
|
29
|
+
V ${y + h - radius}
|
|
30
|
+
A ${radius} ${radius} 0 0 1 ${x + w - radius}, ${y + h}
|
|
31
|
+
H ${x + radius}
|
|
32
|
+
A ${radius} ${radius} 0 0 1 ${x}, ${y + h - radius}
|
|
33
|
+
V ${y + radius}
|
|
34
|
+
A ${radius} ${radius} 0 0 1 ${x + radius}, ${y}
|
|
35
|
+
Z
|
|
36
|
+
`;
|
|
37
|
+
};
|
|
38
|
+
export const TourOverlay = /*#__PURE__*/memo(() => {
|
|
39
|
+
const {
|
|
40
|
+
targetX,
|
|
41
|
+
targetY,
|
|
42
|
+
targetWidth,
|
|
43
|
+
targetHeight,
|
|
44
|
+
targetRadius,
|
|
45
|
+
opacity,
|
|
46
|
+
config,
|
|
47
|
+
currentStep,
|
|
48
|
+
steps
|
|
49
|
+
} = useTour();
|
|
50
|
+
|
|
51
|
+
// Create the d string for the mask
|
|
52
|
+
// Outer rectangle covers the whole screen
|
|
53
|
+
// Inner shape is the "hole"
|
|
54
|
+
// fillRule="evenodd" makes the intersection transparent
|
|
55
|
+
const animatedProps = useAnimatedProps(() => {
|
|
56
|
+
const holePath = createRoundedRectPath(targetX.value, targetY.value, targetWidth.value, targetHeight.value, targetRadius.value);
|
|
57
|
+
const path = `
|
|
58
|
+
M 0,0
|
|
59
|
+
H ${SCREEN_WIDTH}
|
|
60
|
+
V ${SCREEN_HEIGHT}
|
|
61
|
+
H 0
|
|
62
|
+
Z
|
|
63
|
+
${holePath}
|
|
64
|
+
`;
|
|
65
|
+
return {
|
|
66
|
+
d: path,
|
|
67
|
+
fillOpacity: opacity.value
|
|
68
|
+
};
|
|
69
|
+
});
|
|
70
|
+
const step = currentStep ? steps[currentStep] : null;
|
|
71
|
+
const isClickable = step?.clickable ?? false;
|
|
72
|
+
|
|
73
|
+
// Interaction Logic:
|
|
74
|
+
// 1. preventInteraction = true:
|
|
75
|
+
// - Wrapper pointerEvents = 'box-none' (pass through) BUT SVG is auto?
|
|
76
|
+
// - Actually, if we want to block OUTSIDE but allow INSIDE:
|
|
77
|
+
// - SVG path normally blocks where it draws (the dark part).
|
|
78
|
+
// - The 'hole' is empty, so touches pass through the hole to the app?
|
|
79
|
+
// - YES, with fillRule="evenodd", the hole effectively has no fill.
|
|
80
|
+
// - So if SVG is 'auto', touching the dark mask is blocked (if we consume touch).
|
|
81
|
+
// - Touching the hole goes through to the app (GOOD for clickable).
|
|
82
|
+
// - IF we want to BLOCK the hole (clickable=false):
|
|
83
|
+
// - We need a transparent view covering the hole that consumes touches.
|
|
84
|
+
//
|
|
85
|
+
// 2. preventInteraction = false (default):
|
|
86
|
+
// - Overlay shouldn't block anything?
|
|
87
|
+
// - pointerEvents='none' on the whole container.
|
|
88
|
+
|
|
89
|
+
const shouldBlockOutside = config?.preventInteraction ?? false;
|
|
90
|
+
|
|
91
|
+
// If we don't want to block outside, we just let everything pass.
|
|
92
|
+
// But wait, if we let everything pass, we can't implement 'clickable=false' strictness?
|
|
93
|
+
// Usually preventInteraction=false means "just show the highlighter, let user do whatever".
|
|
94
|
+
|
|
95
|
+
const containerPointerEvents = shouldBlockOutside && currentStep ? 'box-none' : 'none';
|
|
96
|
+
|
|
97
|
+
// If blocking outside, the SVG (which is absolute fill) needs to catch touches on the dark part.
|
|
98
|
+
|
|
99
|
+
// Blocker style for the hole (only if NOT clickable)
|
|
100
|
+
const blockerStyle = useAnimatedStyle(() => {
|
|
101
|
+
return {
|
|
102
|
+
position: 'absolute',
|
|
103
|
+
left: targetX.value,
|
|
104
|
+
top: targetY.value,
|
|
105
|
+
width: targetWidth.value,
|
|
106
|
+
height: targetHeight.value,
|
|
107
|
+
// We can match radius too if needed, but rect is fine for touch area usually
|
|
108
|
+
borderRadius: targetRadius.value
|
|
109
|
+
};
|
|
110
|
+
});
|
|
111
|
+
return /*#__PURE__*/_jsxs(AnimatedView, {
|
|
112
|
+
pointerEvents: containerPointerEvents,
|
|
113
|
+
style: StyleSheet.absoluteFill,
|
|
114
|
+
children: [/*#__PURE__*/_jsx(Svg, {
|
|
115
|
+
height: "100%",
|
|
116
|
+
width: "100%",
|
|
117
|
+
style: StyleSheet.absoluteFill,
|
|
118
|
+
children: /*#__PURE__*/_jsx(AnimatedPath, {
|
|
119
|
+
animatedProps: animatedProps,
|
|
120
|
+
fill: "black" // The backdrop color
|
|
121
|
+
,
|
|
122
|
+
fillRule: "evenodd",
|
|
123
|
+
onPress: () => {
|
|
124
|
+
// Consume touch on the backdrop?
|
|
125
|
+
}
|
|
126
|
+
})
|
|
127
|
+
}), shouldBlockOutside && !isClickable && currentStep && /*#__PURE__*/_jsx(AnimatedView, {
|
|
128
|
+
style: blockerStyle,
|
|
129
|
+
pointerEvents: "auto" // Catch touches
|
|
130
|
+
// backgroundColor="transparent" // Default
|
|
131
|
+
})]
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
//# sourceMappingURL=TourOverlay.js.map
|
|
@@ -0,0 +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":[]}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import React, { createContext, useState, useCallback, useMemo, useRef } from 'react';
|
|
4
|
+
import { useSharedValue, withSpring, withTiming, useAnimatedRef, default as Animated } from 'react-native-reanimated';
|
|
5
|
+
import { StyleSheet } from 'react-native';
|
|
6
|
+
import { TourOverlay } from "./TourOverlay.js";
|
|
7
|
+
import { TourTooltip } from "./TourTooltip.js";
|
|
8
|
+
import { DEFAULT_BACKDROP_OPACITY, DEFAULT_SPRING_CONFIG } from "../constants/defaults.js";
|
|
9
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
10
|
+
export const TourContext = /*#__PURE__*/createContext(null);
|
|
11
|
+
const AnimatedView = Animated.View;
|
|
12
|
+
export const TourProvider = ({
|
|
13
|
+
children,
|
|
14
|
+
stepsOrder: initialStepsOrder,
|
|
15
|
+
backdropOpacity = DEFAULT_BACKDROP_OPACITY,
|
|
16
|
+
config
|
|
17
|
+
}) => {
|
|
18
|
+
const [steps, setSteps] = useState({});
|
|
19
|
+
const [currentStep, setCurrentStep] = useState(null);
|
|
20
|
+
|
|
21
|
+
// ref to access latest measurements without causing re-renders
|
|
22
|
+
const measurements = useRef({});
|
|
23
|
+
const containerRef = useAnimatedRef();
|
|
24
|
+
|
|
25
|
+
// --- Shared Values for Animations (Zero Bridge Crossing) ---
|
|
26
|
+
// Initialize off-screen or 0
|
|
27
|
+
const targetX = useSharedValue(0);
|
|
28
|
+
const targetY = useSharedValue(0);
|
|
29
|
+
const targetWidth = useSharedValue(0);
|
|
30
|
+
const targetHeight = useSharedValue(0);
|
|
31
|
+
const targetRadius = useSharedValue(10); // Default border radius
|
|
32
|
+
const opacity = useSharedValue(0); // 0 = hidden, 1 = visible
|
|
33
|
+
|
|
34
|
+
// Helper to animate to a specific step's layout
|
|
35
|
+
const animateToStep = useCallback(stepKey => {
|
|
36
|
+
const measure = measurements.current[stepKey];
|
|
37
|
+
if (measure) {
|
|
38
|
+
// Validate measurements before animating
|
|
39
|
+
if (!measure.width || !measure.height || measure.width <= 0 || measure.height <= 0 || isNaN(measure.x) || isNaN(measure.y) || isNaN(measure.width) || isNaN(measure.height)) {
|
|
40
|
+
console.warn('[TourProvider] Invalid measurements for step:', stepKey, measure);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
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
|
+
const step = steps[stepKey];
|
|
53
|
+
const radius = step?.meta?.borderRadius ?? 10;
|
|
54
|
+
targetRadius.value = withSpring(radius, springConfig);
|
|
55
|
+
|
|
56
|
+
// Ensure overlay is visible
|
|
57
|
+
opacity.value = withTiming(backdropOpacity, {
|
|
58
|
+
duration: 300
|
|
59
|
+
});
|
|
60
|
+
} else {
|
|
61
|
+
console.warn('[TourProvider] No measurements found for step:', stepKey);
|
|
62
|
+
}
|
|
63
|
+
}, [backdropOpacity, targetX, targetY, targetWidth, targetHeight, targetRadius, opacity, config?.springConfig, steps]);
|
|
64
|
+
const registerStep = useCallback(step => {
|
|
65
|
+
setSteps(prev => ({
|
|
66
|
+
...prev,
|
|
67
|
+
[step.key]: step
|
|
68
|
+
}));
|
|
69
|
+
}, []);
|
|
70
|
+
const unregisterStep = useCallback(key => {
|
|
71
|
+
setSteps(prev => {
|
|
72
|
+
const newSteps = {
|
|
73
|
+
...prev
|
|
74
|
+
};
|
|
75
|
+
delete newSteps[key];
|
|
76
|
+
return newSteps;
|
|
77
|
+
});
|
|
78
|
+
}, []);
|
|
79
|
+
const updateStepLayout = useCallback((key, measure) => {
|
|
80
|
+
// Validate measurements before storing
|
|
81
|
+
if (!measure.width || !measure.height || measure.width <= 0 || measure.height <= 0 || isNaN(measure.x) || isNaN(measure.y) || isNaN(measure.width) || isNaN(measure.height) || !isFinite(measure.x) || !isFinite(measure.y) || !isFinite(measure.width) || !isFinite(measure.height)) {
|
|
82
|
+
console.warn('[TourProvider] Invalid measurement update for step:', key, measure);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
measurements.current[key] = measure;
|
|
86
|
+
// If this step is currently active (e.g. scroll happened or resize), update shared values on the fly
|
|
87
|
+
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
|
+
const step = steps[key];
|
|
96
|
+
const radius = step?.meta?.borderRadius ?? 10;
|
|
97
|
+
targetRadius.value = withSpring(radius, springConfig);
|
|
98
|
+
|
|
99
|
+
// Ensure overlay is visible (fixes race condition where start() was called before measure)
|
|
100
|
+
opacity.value = withTiming(backdropOpacity, {
|
|
101
|
+
duration: 300
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}, [currentStep, targetX, targetY, targetWidth, targetHeight, targetRadius, opacity, backdropOpacity, config?.springConfig, steps]);
|
|
105
|
+
const getOrderedSteps = useCallback(() => {
|
|
106
|
+
if (initialStepsOrder) return initialStepsOrder;
|
|
107
|
+
// If order property exists on steps, sort by it.
|
|
108
|
+
const stepKeys = Object.keys(steps);
|
|
109
|
+
if (stepKeys.length > 0) {
|
|
110
|
+
// Check if any step has order
|
|
111
|
+
const hasOrder = stepKeys.some(key => typeof steps[key]?.order === 'number');
|
|
112
|
+
if (hasOrder) {
|
|
113
|
+
return stepKeys.sort((a, b) => (steps[a]?.order ?? 0) - (steps[b]?.order ?? 0));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return stepKeys;
|
|
117
|
+
}, [initialStepsOrder, steps]);
|
|
118
|
+
const start = useCallback(stepKey => {
|
|
119
|
+
const ordered = getOrderedSteps();
|
|
120
|
+
const firstStep = stepKey || ordered[0];
|
|
121
|
+
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);
|
|
130
|
+
}
|
|
131
|
+
}, [getOrderedSteps, animateToStep]);
|
|
132
|
+
const stop = useCallback(() => {
|
|
133
|
+
setCurrentStep(null);
|
|
134
|
+
opacity.value = withTiming(0, {
|
|
135
|
+
duration: 300
|
|
136
|
+
});
|
|
137
|
+
}, [opacity]);
|
|
138
|
+
const next = useCallback(() => {
|
|
139
|
+
if (!currentStep) return;
|
|
140
|
+
const ordered = getOrderedSteps();
|
|
141
|
+
const currentIndex = ordered.indexOf(currentStep);
|
|
142
|
+
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
|
+
});
|
|
153
|
+
} else {
|
|
154
|
+
stop();
|
|
155
|
+
}
|
|
156
|
+
} else {
|
|
157
|
+
stop(); // End of tour
|
|
158
|
+
}
|
|
159
|
+
}, [currentStep, getOrderedSteps, stop, opacity, backdropOpacity]);
|
|
160
|
+
const prev = useCallback(() => {
|
|
161
|
+
if (!currentStep) return;
|
|
162
|
+
const ordered = getOrderedSteps();
|
|
163
|
+
const currentIndex = ordered.indexOf(currentStep);
|
|
164
|
+
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
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}, [currentStep, getOrderedSteps, opacity, backdropOpacity]);
|
|
175
|
+
const scrollViewRef = useAnimatedRef();
|
|
176
|
+
const setScrollViewRef = useCallback(_ref => {
|
|
177
|
+
// If user passes a ref, we might want to sync it?
|
|
178
|
+
// Or we just provide this function for them to give us the ref.
|
|
179
|
+
// With useAnimatedRef, we can assign it if it's a function or object?
|
|
180
|
+
// Actually, safest is to let them assign our ref to their component.
|
|
181
|
+
// But they might have their own ref.
|
|
182
|
+
// Let's assume they call this with their ref.
|
|
183
|
+
// BUT useAnimatedRef cannot easily accept an external ref object to "become".
|
|
184
|
+
// Pattern: They should use the ref we give them, OR we wrap their component?
|
|
185
|
+
// Simpler: We just expose 'scrollViewRef' from context, and they attach it.
|
|
186
|
+
// So 'setScrollViewRef' might be redundant if we just say "here is the ref, use it".
|
|
187
|
+
// But if they have their own, they can't usage two refs easily without merging.
|
|
188
|
+
// Let's stick to exposing `scrollViewRef` from context that they MUST use.
|
|
189
|
+
// But wait, the interface says `setScrollViewRef`.
|
|
190
|
+
// Let's keep `setScrollViewRef` as a no-op or a way to manually set it if needed (not RecAnimated friendly).
|
|
191
|
+
// Actually, let's just expose `scrollViewRef` and `registerScrollView` which essentially does nothing if we expect them to use the ref object.
|
|
192
|
+
// Let's make `setScrollViewRef` actually do something if possible, or just document "Use exposed scrollViewRef".
|
|
193
|
+
// For now, let's just return the `scrollViewRef` we created.
|
|
194
|
+
}, []);
|
|
195
|
+
const value = useMemo(() => ({
|
|
196
|
+
start,
|
|
197
|
+
stop,
|
|
198
|
+
next,
|
|
199
|
+
prev,
|
|
200
|
+
registerStep,
|
|
201
|
+
unregisterStep,
|
|
202
|
+
updateStepLayout,
|
|
203
|
+
currentStep,
|
|
204
|
+
targetX,
|
|
205
|
+
targetY,
|
|
206
|
+
targetWidth,
|
|
207
|
+
targetHeight,
|
|
208
|
+
targetRadius,
|
|
209
|
+
opacity,
|
|
210
|
+
steps,
|
|
211
|
+
config,
|
|
212
|
+
containerRef,
|
|
213
|
+
scrollViewRef,
|
|
214
|
+
setScrollViewRef
|
|
215
|
+
}), [start, stop, next, prev, registerStep, unregisterStep, updateStepLayout, currentStep, targetX, targetY, targetWidth, targetHeight, targetRadius, opacity, steps, config,
|
|
216
|
+
// containerRef is stable
|
|
217
|
+
scrollViewRef, setScrollViewRef]);
|
|
218
|
+
return /*#__PURE__*/_jsx(TourContext.Provider, {
|
|
219
|
+
value: value,
|
|
220
|
+
children: /*#__PURE__*/_jsxs(AnimatedView, {
|
|
221
|
+
ref: containerRef,
|
|
222
|
+
style: styles.container,
|
|
223
|
+
collapsable: false,
|
|
224
|
+
children: [children, /*#__PURE__*/_jsx(TourOverlay, {}), /*#__PURE__*/_jsx(TourTooltip, {})]
|
|
225
|
+
})
|
|
226
|
+
});
|
|
227
|
+
};
|
|
228
|
+
const styles = StyleSheet.create({
|
|
229
|
+
container: {
|
|
230
|
+
flex: 1
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
//# sourceMappingURL=TourProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["React","createContext","useState","useCallback","useMemo","useRef","useSharedValue","withSpring","withTiming","useAnimatedRef","default","Animated","StyleSheet","TourOverlay","TourTooltip","DEFAULT_BACKDROP_OPACITY","DEFAULT_SPRING_CONFIG","jsx","_jsx","jsxs","_jsxs","TourContext","AnimatedView","View","TourProvider","children","stepsOrder","initialStepsOrder","backdropOpacity","config","steps","setSteps","currentStep","setCurrentStep","measurements","containerRef","targetX","targetY","targetWidth","targetHeight","targetRadius","opacity","animateToStep","stepKey","measure","current","width","height","isNaN","x","y","console","warn","springConfig","value","step","radius","meta","borderRadius","duration","registerStep","prev","key","unregisterStep","newSteps","updateStepLayout","isFinite","getOrderedSteps","stepKeys","Object","keys","length","hasOrder","some","order","sort","a","b","start","ordered","firstStep","setTimeout","stop","next","currentIndex","indexOf","nextStep","prevStep","scrollViewRef","setScrollViewRef","_ref","Provider","ref","style","styles","container","collapsable","create","flex"],"sourceRoot":"..\\..\\..\\src","sources":["components/TourProvider.tsx"],"mappings":"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","ignoreList":[]}
|