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 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 using **circle or rounded-rectangle spotlight**
32
-
13
+ * 🎯 Highlight any UI element with **Circle / RoundRect** spotlight
33
14
  * 📐 Auto-calculated spotlight position using `measureInWindow`
34
-
35
- * 🔁 Show once / persistent keys using AsyncStorage
36
-
37
- * 🎞 Lottie animation support above target
38
-
39
- * 🕳 Multiple shapes per screen (multi-step tutorial)
40
-
41
- * Gesture hints (swipe left/right, scroll)
42
-
43
- * 🎨 Customizable:
44
-
45
- * Overlay background color
46
- * Button text, color, style
47
- * Title & description
48
- * Lottie size & position
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 Example
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 HomeScreen() {
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
- 'يمكنك سحب هذا القسم لأعلى أو لأسفل لتغيير ترتيبه في الصفحة.\n' +
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: 100, backgroundColor: '#eee', padding: 20 }}>
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
- # 🧩 API Documentation
90
+ # 🎞 Lottie Placement (New)
118
91
 
119
- ## `<TutoShowcase />` Props
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
- # 🎛 Ref API (Controller)
135
-
136
- Returned via:
96
+ ## 🔹 Available placements
137
97
 
138
- ```ts
139
- const tutoRef = useRef<TutoShowcaseHandle>(null);
140
98
  ```
141
-
142
- Then:
143
-
144
- ```ts
145
- tutoRef.current?.on(targetRef)
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
- ### Methods
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
- Lottie will automatically be positioned above the target highlight.
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
- # 🎨 Customizing Button Style
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
- paddingVertical: 10,
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
- # Spotlight Shape Options
196
+ # 📐 Spotlight Options
207
197
 
208
- ### Circle Spotlight
198
+ ### Circle
209
199
 
210
- ```ts
200
+ ```tsx
211
201
  .on(ref)
212
- .addCircle(1.2) // ratio
202
+ .addCircle(1.3)
213
203
  .show()
214
204
  ```
215
205
 
216
- ### Rounded Rectangle Spotlight
206
+ ### Rounded Rectangle
217
207
 
218
- ```ts
208
+ ```tsx
219
209
  .on(ref)
220
- .addRoundRect(1.1, 20, { pad: 30, dx: 0, dy: 0 })
210
+ .addRoundRect(1.1, 20, { pad: 30 })
221
211
  .show()
222
212
  ```
223
213
 
224
214
  ---
225
215
 
226
- # 🗂 Show Once Logic
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
- Bundled `.d.ts` typings included automatically:
218
+ ### 📱 iOS
242
219
 
243
- ```ts
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
- * Must wrap elements you spotlight with a `ref`
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 default function LottieAboveTarget({ shapes, lottie, }: {
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
- }): import("react/jsx-runtime").JSX.Element | null;
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
- export default function LottieAboveTarget({ shapes, lottie, }) {
5
- if (!lottie || shapes.length === 0)
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
- const cx = focus.cx;
12
- const topOfHole = focus.type === 'circle' ? focus.cy - focus.r : focus.y;
13
- const top = topOfHole - lh + 50;
14
- const left = cx - lw / 2;
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
- declare const TutoShowcase: React.ForwardRefExoticComponent<Omit<any, "ref"> & React.RefAttributes<TutoShowcaseHandle>>;
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, }, ref) {
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",
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
  }