react-native-tuto-showcase 1.0.3 → 1.0.5
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/README.md +107 -138
- package/dist/components/LottieAboveTarget.d.ts +14 -2
- package/dist/components/LottieAboveTarget.js +46 -7
- package/dist/index.d.ts +17 -1
- package/dist/index.js +3 -2
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -4,51 +4,30 @@
|
|
|
4
4
|
|
|
5
5
|
Perfect for onboarding flows, feature tours, highlighting UI elements, and guiding users interactively.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
# 📽 Demo
|
|
10
|
-
|
|
11
|
-
### **iOS Showcase**
|
|
12
|
-
|
|
13
|
-
<img
|
|
14
|
-
src="https://raw.githubusercontent.com/ahmedhegazydev/react-native-tuto-showcase/master/src/assets/SimulatorScreenRecording-iPhone16Pro-2025-11-24at14.14.46online-video-cutter.com-ezgif.com-video-to-gif-converter.gif"
|
|
15
|
-
width="350"
|
|
16
|
-
/>
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
### **Android Showcase**
|
|
21
|
-
|
|
22
|
-
<img
|
|
23
|
-
src="https://raw.githubusercontent.com/ahmedhegazydev/react-native-tuto-showcase/master/src/assets/ScreenRecording2025-12-02at7.52.23PMonline-video-cutter.com-ezgif.com-video-to-gif-converter.gif"
|
|
24
|
-
width="350"
|
|
25
|
-
/>
|
|
7
|
+
Now with **full-screen Lottie placement** + **custom offsets**.
|
|
26
8
|
|
|
27
9
|
---
|
|
28
10
|
|
|
29
11
|
# ✨ Features
|
|
30
12
|
|
|
31
|
-
* 🎯 Highlight any UI element
|
|
32
|
-
|
|
13
|
+
* 🎯 Highlight any UI element with **Circle / RoundRect** spotlight
|
|
33
14
|
* 📐 Auto-calculated spotlight position using `measureInWindow`
|
|
34
|
-
|
|
35
|
-
*
|
|
36
|
-
|
|
37
|
-
*
|
|
38
|
-
|
|
39
|
-
*
|
|
40
|
-
|
|
41
|
-
*
|
|
42
|
-
|
|
43
|
-
* 🎨
|
|
44
|
-
|
|
45
|
-
*
|
|
46
|
-
* Button
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
|
|
50
|
-
* 📱 Works on both **iOS & Android**
|
|
51
|
-
|
|
15
|
+
* 🔁 Show-once logic (AsyncStorage)
|
|
16
|
+
* 🎞 **Lottie Animations with full-screen positioning**
|
|
17
|
+
|
|
18
|
+
* `top-left`, `top-right`, `top-center`
|
|
19
|
+
* `bottom-left`, `bottom-right`, `bottom-center`
|
|
20
|
+
* `center`
|
|
21
|
+
* * `lottieOffset={{dx, dy}}`
|
|
22
|
+
* 📦 Multiple spots on one screen
|
|
23
|
+
* ✋ Gesture hints (swipe / scroll)
|
|
24
|
+
* 🎨 Fully customizable:
|
|
25
|
+
|
|
26
|
+
* Colors
|
|
27
|
+
* Button style
|
|
28
|
+
* Fonts
|
|
29
|
+
* Overlay background
|
|
30
|
+
* 📱 Works on **iOS & Android**
|
|
52
31
|
* ⚡ Supports React Native 0.72+
|
|
53
32
|
|
|
54
33
|
---
|
|
@@ -61,20 +40,16 @@ npm install react-native-tuto-showcase
|
|
|
61
40
|
yarn add react-native-tuto-showcase
|
|
62
41
|
```
|
|
63
42
|
|
|
64
|
-
> Make sure you have `react-native-svg` installed (auto-installed as dependency).
|
|
65
|
-
|
|
66
43
|
---
|
|
67
44
|
|
|
68
|
-
# 🚀 Usage
|
|
69
|
-
|
|
70
|
-
### **Highlight a component inside your screen**
|
|
45
|
+
# 🚀 Basic Usage
|
|
71
46
|
|
|
72
47
|
```tsx
|
|
73
48
|
import React, { useRef } from 'react';
|
|
74
49
|
import { View, Text, Pressable } from 'react-native';
|
|
75
50
|
import TutoShowcase, { TutoShowcaseHandle } from 'react-native-tuto-showcase';
|
|
76
51
|
|
|
77
|
-
export default function
|
|
52
|
+
export default function Home() {
|
|
78
53
|
const tutoRef = useRef<TutoShowcaseHandle>(null);
|
|
79
54
|
const boxRef = useRef<View>(null);
|
|
80
55
|
|
|
@@ -84,27 +59,25 @@ export default function HomeScreen() {
|
|
|
84
59
|
ref={tutoRef}
|
|
85
60
|
title={<Text style={{ color: '#fff', fontSize: 22 }}>ترتيب الأقسام</Text>}
|
|
86
61
|
description={
|
|
87
|
-
'يمكنك سحب هذا القسم لأعلى أو لأسفل لتغيير
|
|
88
|
-
'سيتم حفظ الترتيب
|
|
62
|
+
'يمكنك سحب هذا القسم لأعلى أو لأسفل لتغيير ترتيبه.\n' +
|
|
63
|
+
'سيتم حفظ الترتيب تلقائيًا.'
|
|
89
64
|
}
|
|
90
65
|
buttonText="تمام"
|
|
91
|
-
overlayBackgroundColor="rgba(0,0,0,0.85)"
|
|
92
|
-
buttonContainerStyle={{ backgroundColor: '#ff9800' }}
|
|
93
|
-
buttonTextStyle={{ color: '#000', fontWeight: 'bold' }}
|
|
94
66
|
/>
|
|
95
67
|
|
|
96
|
-
<View ref={boxRef} style={{ marginTop:
|
|
68
|
+
<View ref={boxRef} style={{ marginTop: 120, padding: 20, backgroundColor: '#eee' }}>
|
|
97
69
|
<Text>Drag Me</Text>
|
|
98
70
|
</View>
|
|
99
71
|
|
|
100
72
|
<Pressable
|
|
101
|
-
onPress={() =>
|
|
73
|
+
onPress={() =>
|
|
102
74
|
tutoRef.current
|
|
103
75
|
?.on(boxRef)
|
|
104
76
|
.addRoundRect()
|
|
105
77
|
.withBorder()
|
|
106
|
-
.showOnce('highlight-box')
|
|
107
|
-
}
|
|
78
|
+
.showOnce('highlight-box')
|
|
79
|
+
}
|
|
80
|
+
>
|
|
108
81
|
<Text>Start Tutorial</Text>
|
|
109
82
|
</Pressable>
|
|
110
83
|
</>
|
|
@@ -114,58 +87,25 @@ export default function HomeScreen() {
|
|
|
114
87
|
|
|
115
88
|
---
|
|
116
89
|
|
|
117
|
-
#
|
|
90
|
+
# 🎞 Lottie Placement (New)
|
|
118
91
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
| Prop | Type | Default | Description |
|
|
122
|
-
| ------------------------ | --------------------- | ------------------ | ---------------------------------- |
|
|
123
|
-
| `title` | `ReactNode` | — | Title element (supports JSX & RTL) |
|
|
124
|
-
| `description` | `string \| ReactNode` | — | Description text |
|
|
125
|
-
| `buttonText` | `string` | `"GOT IT"` | CTA button label |
|
|
126
|
-
| `buttonTextStyle` | `TextStyle` | — | Custom style for CTA text |
|
|
127
|
-
| `buttonContainerStyle` | `ViewStyle` | — | Custom style for CTA container |
|
|
128
|
-
| `overlayBackgroundColor` | `string` | `rgba(0,0,0,0.78)` | Background dim color |
|
|
129
|
-
| `onGotIt` | `() => void` | — | Called when user presses CTA |
|
|
130
|
-
| `lottie` | `ReactElement` | — | Lottie animation above target |
|
|
92
|
+
The Lottie animation is now positioned **relative to the full screen**, not the spotlight.
|
|
131
93
|
|
|
132
94
|
---
|
|
133
95
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
Returned via:
|
|
96
|
+
## 🔹 Available placements
|
|
137
97
|
|
|
138
|
-
```ts
|
|
139
|
-
const tutoRef = useRef<TutoShowcaseHandle>(null);
|
|
140
98
|
```
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
99
|
+
top-left
|
|
100
|
+
top-center
|
|
101
|
+
top-right
|
|
102
|
+
bottom-left
|
|
103
|
+
bottom-center
|
|
104
|
+
bottom-right
|
|
105
|
+
center
|
|
146
106
|
```
|
|
147
107
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
| Method | Description |
|
|
151
|
-
| -------------------------------------- | -------------------------------------------- |
|
|
152
|
-
| `on(ref)` | Select target element |
|
|
153
|
-
| `show()` | Show the spotlight |
|
|
154
|
-
| `dismiss()` | Hide the overlay |
|
|
155
|
-
| `addCircle(ratio?)` | Add circle spotlight |
|
|
156
|
-
| `addRoundRect(ratio?, radius?, opts?)` | Add rounded-rect spotlight |
|
|
157
|
-
| `displaySwipableLeft()` | Show left gesture hint |
|
|
158
|
-
| `displaySwipableRight()` | Show right gesture hint |
|
|
159
|
-
| `displayScrollable()` | Show scroll gesture hint |
|
|
160
|
-
| `withBorder()` | Add border around spotlight |
|
|
161
|
-
| `onClick(cb)` | Make spotlight clickable |
|
|
162
|
-
| `showOnce(key)` | Show once only (persistent via AsyncStorage) |
|
|
163
|
-
| `resetShowOnce(key)` | Clear “show once” key |
|
|
164
|
-
| `isShowOnce(key)` | Check stored key |
|
|
165
|
-
|
|
166
|
-
---
|
|
167
|
-
|
|
168
|
-
# 🎬 Lottie Support
|
|
108
|
+
## 🔹 Example
|
|
169
109
|
|
|
170
110
|
```tsx
|
|
171
111
|
<TutoShowcase
|
|
@@ -174,25 +114,75 @@ tutoRef.current?.on(targetRef)
|
|
|
174
114
|
<LottieView
|
|
175
115
|
source={require('./hand.json')}
|
|
176
116
|
style={{ width: 120, height: 120 }}
|
|
177
|
-
autoPlay
|
|
178
|
-
loop
|
|
179
117
|
/>
|
|
180
118
|
}
|
|
119
|
+
lottiePlacement="top-right"
|
|
120
|
+
lottieOffset={{ dx: -20, dy: 10 }}
|
|
181
121
|
/>
|
|
182
122
|
```
|
|
183
123
|
|
|
184
|
-
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
# 🧩 Props
|
|
127
|
+
|
|
128
|
+
## `<TutoShowcase />`
|
|
129
|
+
|
|
130
|
+
| Prop | Type | Default | Description |
|
|
131
|
+
| ------------------------ | ------------------------------ | ------------------ | ----------------------- |
|
|
132
|
+
| `title` | `ReactNode` | — | Title JSX |
|
|
133
|
+
| `description` | `string \| ReactNode` | — | Description text |
|
|
134
|
+
| `buttonText` | `string` | `"GOT IT"` | CTA label |
|
|
135
|
+
| `buttonTextStyle` | `TextStyle` | — | Style for CTA text |
|
|
136
|
+
| `buttonContainerStyle` | `ViewStyle` | — | Style for CTA button |
|
|
137
|
+
| `overlayBackgroundColor` | `string` | `rgba(0,0,0,0.78)` | Dim overlay color |
|
|
138
|
+
| `onGotIt` | `() => void` | — | Called when CTA pressed |
|
|
139
|
+
| `lottie` | `ReactElement` | — | Lottie animation |
|
|
140
|
+
| **`lottiePlacement`** | `"top-left" \| ...` | `"top-center"` | ⭐ Full-screen placement |
|
|
141
|
+
| **`lottieOffset`** | `{ dx?: number; dy?: number }` | `{}` | Extra offset |
|
|
185
142
|
|
|
186
143
|
---
|
|
187
144
|
|
|
188
|
-
#
|
|
145
|
+
# 🎛 Ref API
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
const tutoRef = useRef<TutoShowcaseHandle>(null);
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
| Method | Description |
|
|
152
|
+
| -------------------------------------- | ----------------------------- |
|
|
153
|
+
| `on(ref)` | Select target element |
|
|
154
|
+
| `addCircle(ratio?)` | Add circle spotlight |
|
|
155
|
+
| `addRoundRect(ratio?, radius?, opts?)` | Add rounded spotlight |
|
|
156
|
+
| `withBorder()` | Add border |
|
|
157
|
+
| `displaySwipableLeft()` | Gesture hint |
|
|
158
|
+
| `displaySwipableRight()` | Gesture hint |
|
|
159
|
+
| `displayScrollable()` | Gesture hint |
|
|
160
|
+
| `onClick(cb)` | Capture taps inside spotlight |
|
|
161
|
+
| `show()` | Show spotlight immediately |
|
|
162
|
+
| `showOnce(key)` | Show once (AsyncStorage) |
|
|
163
|
+
| `resetShowOnce(key)` | Clear stored key |
|
|
164
|
+
| `isShowOnce(key)` | Check if key shown |
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
# 🗂 Show Once Logic
|
|
169
|
+
|
|
170
|
+
```tsx
|
|
171
|
+
tutoRef.current
|
|
172
|
+
?.on(boxRef)
|
|
173
|
+
.addCircle()
|
|
174
|
+
.showOnce('first-time');
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
# 🎨 Button Customization
|
|
189
180
|
|
|
190
181
|
```tsx
|
|
191
182
|
<TutoShowcase
|
|
192
183
|
buttonContainerStyle={{
|
|
193
184
|
backgroundColor: '#FFD700',
|
|
194
|
-
|
|
195
|
-
borderRadius: 8,
|
|
185
|
+
borderRadius: 10,
|
|
196
186
|
}}
|
|
197
187
|
buttonTextStyle={{
|
|
198
188
|
color: '#000',
|
|
@@ -203,55 +193,35 @@ Lottie will automatically be positioned above the target highlight.
|
|
|
203
193
|
|
|
204
194
|
---
|
|
205
195
|
|
|
206
|
-
#
|
|
196
|
+
# 📐 Spotlight Options
|
|
207
197
|
|
|
208
|
-
### Circle
|
|
198
|
+
### Circle
|
|
209
199
|
|
|
210
|
-
```
|
|
200
|
+
```tsx
|
|
211
201
|
.on(ref)
|
|
212
|
-
.addCircle(1.
|
|
202
|
+
.addCircle(1.3)
|
|
213
203
|
.show()
|
|
214
204
|
```
|
|
215
205
|
|
|
216
|
-
### Rounded Rectangle
|
|
206
|
+
### Rounded Rectangle
|
|
217
207
|
|
|
218
|
-
```
|
|
208
|
+
```tsx
|
|
219
209
|
.on(ref)
|
|
220
|
-
.addRoundRect(1.1, 20, { pad: 30
|
|
210
|
+
.addRoundRect(1.1, 20, { pad: 30 })
|
|
221
211
|
.show()
|
|
222
212
|
```
|
|
223
213
|
|
|
224
214
|
---
|
|
225
215
|
|
|
226
|
-
#
|
|
227
|
-
|
|
228
|
-
```ts
|
|
229
|
-
tutoRef.current
|
|
230
|
-
?.on(someRef)
|
|
231
|
-
.addCircle()
|
|
232
|
-
.showOnce('home-feature');
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
Key stored automatically in AsyncStorage → won’t show again.
|
|
236
|
-
|
|
237
|
-
---
|
|
238
|
-
|
|
239
|
-
# 📦 TypeScript Support
|
|
216
|
+
# 🎥 Demo Videos
|
|
240
217
|
|
|
241
|
-
|
|
218
|
+
### 📱 iOS
|
|
242
219
|
|
|
243
|
-
|
|
244
|
-
import type { TutoShowcaseHandle } from 'react-native-tuto-showcase';
|
|
245
|
-
```
|
|
220
|
+
[https://github.com/ahmedhegazydev/react-native-tuto-showcase/blob/master/src/assets/SimulatorScreenRecording-iPhone16Pro-2025-11-24at14.14.46online-video-cutter.com-ezgif.com-video-to-gif-converter.gif](https://github.com/ahmedhegazydev/react-native-tuto-showcase/blob/master/src/assets/SimulatorScreenRecording-iPhone16Pro-2025-11-24at14.14.46online-video-cutter.com-ezgif.com-video-to-gif-converter.gif)
|
|
246
221
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
# 📐 Important Notes
|
|
222
|
+
### 🤖 Android
|
|
250
223
|
|
|
251
|
-
|
|
252
|
-
* Uses `measureInWindow` → works inside ScrollView, Tabs, Modals, etc.
|
|
253
|
-
* Overlay is drawn using **react-native-svg**
|
|
254
|
-
* Fully RTL-compatible
|
|
224
|
+
[https://github.com/ahmedhegazydev/react-native-tuto-showcase/blob/master/src/assets/ScreenRecording2025-12-02at7.52.23PMonline-video-cutter.com-ezgif.com-video-to-gif-converter.gif](https://github.com/ahmedhegazydev/react-native-tuto-showcase/blob/master/src/assets/ScreenRecording2025-12-02at7.52.23PMonline-video-cutter.com-ezgif.com-video-to-gif-converter.gif)
|
|
255
225
|
|
|
256
226
|
---
|
|
257
227
|
|
|
@@ -259,5 +229,4 @@ import type { TutoShowcaseHandle } from 'react-native-tuto-showcase';
|
|
|
259
229
|
|
|
260
230
|
MIT © **Ahmed Mohamed Ali Ali Hegazy**
|
|
261
231
|
|
|
262
|
-
---
|
|
263
|
-
|
|
232
|
+
---
|
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { AnyShape } from '../types/shapes';
|
|
3
|
-
export
|
|
3
|
+
export type LottiePlacement = 'top-left' | 'top-right' | 'top-center' | 'bottom-left' | 'bottom-right' | 'bottom-center' | 'center';
|
|
4
|
+
type Offset = {
|
|
5
|
+
dx?: number;
|
|
6
|
+
dy?: number;
|
|
7
|
+
};
|
|
8
|
+
type Props = {
|
|
4
9
|
shapes: AnyShape[];
|
|
5
10
|
lottie: React.ReactElement<any>;
|
|
6
|
-
|
|
11
|
+
overlayWidth: number;
|
|
12
|
+
overlayHeight: number;
|
|
13
|
+
placement?: LottiePlacement;
|
|
14
|
+
offset?: Offset;
|
|
15
|
+
};
|
|
16
|
+
export default function LottieAboveTarget({ shapes, lottie, overlayWidth, overlayHeight, placement, // 👈 الديفولت: فوق في النص بالنسبة للشاشة كلها
|
|
17
|
+
offset, }: Props): import("react/jsx-runtime").JSX.Element | null;
|
|
18
|
+
export {};
|
|
@@ -1,17 +1,56 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { View, StyleSheet } from 'react-native';
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
const PADDING_H = 24;
|
|
5
|
+
const PADDING_V = 32;
|
|
6
|
+
export default function LottieAboveTarget({ shapes, lottie, overlayWidth, overlayHeight, placement = 'top-center', // 👈 الديفولت: فوق في النص بالنسبة للشاشة كلها
|
|
7
|
+
offset, }) {
|
|
8
|
+
if (!lottie)
|
|
6
9
|
return null;
|
|
7
|
-
const focus = shapes[shapes.length - 1];
|
|
8
10
|
const layout = StyleSheet.flatten(lottie.props?.style) || {};
|
|
9
11
|
const lw = layout.width ?? 100;
|
|
10
12
|
const lh = layout.height ?? 100;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
let top = 0;
|
|
14
|
+
let left = 0;
|
|
15
|
+
switch (placement) {
|
|
16
|
+
case 'top-left':
|
|
17
|
+
top = PADDING_V;
|
|
18
|
+
left = PADDING_H;
|
|
19
|
+
break;
|
|
20
|
+
case 'top-right':
|
|
21
|
+
top = PADDING_V;
|
|
22
|
+
left = overlayWidth - lw - PADDING_H;
|
|
23
|
+
break;
|
|
24
|
+
case 'top-center':
|
|
25
|
+
top = PADDING_V;
|
|
26
|
+
left = (overlayWidth - lw) / 2;
|
|
27
|
+
break;
|
|
28
|
+
case 'bottom-left':
|
|
29
|
+
top = overlayHeight - lh - PADDING_V;
|
|
30
|
+
left = PADDING_H;
|
|
31
|
+
break;
|
|
32
|
+
case 'bottom-right':
|
|
33
|
+
top = overlayHeight - lh - PADDING_V;
|
|
34
|
+
left = overlayWidth - lw - PADDING_H;
|
|
35
|
+
break;
|
|
36
|
+
case 'bottom-center':
|
|
37
|
+
top = overlayHeight - lh - PADDING_V;
|
|
38
|
+
left = (overlayWidth - lw) / 2;
|
|
39
|
+
break;
|
|
40
|
+
case 'center':
|
|
41
|
+
top = (overlayHeight - lh) / 2;
|
|
42
|
+
left = (overlayWidth - lw) / 2;
|
|
43
|
+
break;
|
|
44
|
+
default:
|
|
45
|
+
top = PADDING_V;
|
|
46
|
+
left = (overlayWidth - lw) / 2;
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
// ✅ اختياري: إزاحة إضافية
|
|
50
|
+
if (offset?.dx)
|
|
51
|
+
left += offset.dx;
|
|
52
|
+
if (offset?.dy)
|
|
53
|
+
top += offset.dy;
|
|
15
54
|
return (_jsx(View, { pointerEvents: "none", style: [
|
|
16
55
|
styles.container,
|
|
17
56
|
{ top, left, width: lw, height: lh },
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { LottiePlacement } from './components/LottieAboveTarget';
|
|
2
3
|
export type TutoShowcaseHandle = {
|
|
3
4
|
on: (r: any) => any;
|
|
4
5
|
show: () => void;
|
|
@@ -7,5 +8,20 @@ export type TutoShowcaseHandle = {
|
|
|
7
8
|
isShowOnce: (key: string) => boolean;
|
|
8
9
|
resetShowOnce: (key: string) => void;
|
|
9
10
|
};
|
|
10
|
-
|
|
11
|
+
type TutoShowcaseProps = {
|
|
12
|
+
title?: React.ReactNode;
|
|
13
|
+
description?: React.ReactNode;
|
|
14
|
+
buttonText?: string;
|
|
15
|
+
buttonTextStyle?: any;
|
|
16
|
+
buttonContainerStyle?: any;
|
|
17
|
+
overlayBackgroundColor?: string;
|
|
18
|
+
onGotIt?: () => void;
|
|
19
|
+
lottie?: React.ReactElement<any> | null;
|
|
20
|
+
lottiePlacement?: LottiePlacement;
|
|
21
|
+
lottieOffset?: {
|
|
22
|
+
dx?: number;
|
|
23
|
+
dy?: number;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
declare const TutoShowcase: React.ForwardRefExoticComponent<TutoShowcaseProps & React.RefAttributes<TutoShowcaseHandle>>;
|
|
11
27
|
export default TutoShowcase;
|
package/dist/index.js
CHANGED
|
@@ -11,7 +11,8 @@ import { usePulseAnimation } from './hooks/usePulseAnimation';
|
|
|
11
11
|
import { buildActionsFactory } from './helpers/buildActions';
|
|
12
12
|
import { useContentPosition } from './hooks/useContentPosition';
|
|
13
13
|
const DEFAULT_BG = 'rgba(0,0,0,0.78)';
|
|
14
|
-
const TutoShowcase = forwardRef(function Tuto({ title, description, buttonText = 'GOT IT', buttonTextStyle, buttonContainerStyle, overlayBackgroundColor, onGotIt, lottie,
|
|
14
|
+
const TutoShowcase = forwardRef(function Tuto({ title, description, buttonText = 'GOT IT', buttonTextStyle, buttonContainerStyle, overlayBackgroundColor, onGotIt, lottie, lottiePlacement, // 👈 خدناه من props
|
|
15
|
+
lottieOffset, }, ref) {
|
|
15
16
|
// -------- Hooks يجب أن تكون في الأعلى وبنفس الترتيب دائماً --------
|
|
16
17
|
const [visible, setVisible] = useState(false);
|
|
17
18
|
const [bgColor, setBgColor] = useState(overlayBackgroundColor || DEFAULT_BG);
|
|
@@ -84,7 +85,7 @@ const TutoShowcase = forwardRef(function Tuto({ title, description, buttonText =
|
|
|
84
85
|
// ✅ الشرط هنا بعد كل الـ hooks
|
|
85
86
|
if (!visible)
|
|
86
87
|
return null;
|
|
87
|
-
return (_jsx(Modal, { visible: true, transparent: true, animationType: "fade", children: _jsx(TouchableWithoutFeedback, { onPress: onOverlayPress, children: _jsxs(View, { ref: rootRef, onLayout: onLayout, style: [StyleSheet.absoluteFill, { direction: 'ltr' }], children: [_jsx(Overlay, { width: width, height: height, shapes: shapes, bgColor: bgColor, spotScale: spotScale, spotOpacity: spotOpacity }), lottie && _jsx(LottieAboveTarget, { shapes: shapes, lottie: lottie }), (title || description) && (_jsx(ContentSection, { title: title, description: description, buttonText: buttonText, buttonTextStyle: buttonTextStyle, buttonContainerStyle: buttonContainerStyle, coords: coords, onPress: () => {
|
|
88
|
+
return (_jsx(Modal, { visible: true, transparent: true, animationType: "fade", children: _jsx(TouchableWithoutFeedback, { onPress: onOverlayPress, children: _jsxs(View, { ref: rootRef, onLayout: onLayout, style: [StyleSheet.absoluteFill, { direction: 'ltr' }], children: [_jsx(Overlay, { width: width, height: height, shapes: shapes, bgColor: bgColor, spotScale: spotScale, spotOpacity: spotOpacity }), lottie && (_jsx(LottieAboveTarget, { shapes: shapes, lottie: lottie, overlayWidth: width, overlayHeight: height, placement: lottiePlacement, offset: lottieOffset })), (title || description) && (_jsx(ContentSection, { title: title, description: description, buttonText: buttonText, buttonTextStyle: buttonTextStyle, buttonContainerStyle: buttonContainerStyle, coords: coords, onPress: () => {
|
|
88
89
|
onGotIt?.();
|
|
89
90
|
dismiss();
|
|
90
91
|
} })), _jsx(GestureHints, { hints: hints })] }) }) }));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-tuto-showcase",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "Customizable tutorial / spotlight overlay for React Native (onboarding, feature tours, coachmarks).",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -26,18 +26,18 @@
|
|
|
26
26
|
],
|
|
27
27
|
"author": "Ahmed Mohamed Ali Ali Hegazy",
|
|
28
28
|
"license": "MIT",
|
|
29
|
+
"packageManager": "yarn@3.6.4+sha512.e70835d4d6d62c07be76b3c1529cb640c7443f0fe434ef4b6478a5a399218cbaf1511b396b3c56eb03bc86424cff2320f6167ad2fde273aa0df6e60b7754029f",
|
|
29
30
|
"peerDependencies": {
|
|
31
|
+
"@react-native-async-storage/async-storage": ">=1.17.0",
|
|
30
32
|
"react": ">=18.0.0",
|
|
31
|
-
"react-native": ">=0.72.0"
|
|
32
|
-
|
|
33
|
-
"dependencies": {
|
|
34
|
-
"@react-native-async-storage/async-storage": "^1.23.0",
|
|
35
|
-
"react-native-svg": "^13.14.0"
|
|
33
|
+
"react-native": ">=0.72.0",
|
|
34
|
+
"react-native-svg": ">=13.0.0"
|
|
36
35
|
},
|
|
37
|
-
"packageManager": "yarn@3.6.4+sha512.e70835d4d6d62c07be76b3c1529cb640c7443f0fe434ef4b6478a5a399218cbaf1511b396b3c56eb03bc86424cff2320f6167ad2fde273aa0df6e60b7754029f",
|
|
38
36
|
"devDependencies": {
|
|
37
|
+
"@react-native-async-storage/async-storage": "^1.23.0",
|
|
39
38
|
"@types/react": "^19.2.7",
|
|
40
39
|
"@types/react-native": "^0.72.8",
|
|
40
|
+
"react-native-svg": "^13.14.0",
|
|
41
41
|
"typescript": "^5.9.3"
|
|
42
42
|
}
|
|
43
43
|
}
|