rn-smart-tour 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 +90 -158
- package/dist/DapOverlay.js +3 -3
- package/dist/DapProvider.js +20 -5
- package/dist/DapTarget.d.ts +6 -0
- package/dist/DapTarget.js +36 -2
- package/package.json +1 -9
package/README.md
CHANGED
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
# rn-smart-tour
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<p align="center">
|
|
4
|
+
<b>Enterprise-grade Digital Adoption Platform (DAP) for React Native</b><br>
|
|
5
|
+
Easily add product tours, guided walkthroughs, and onboarding overlays without intrusive code changes.
|
|
6
|
+
</p>
|
|
4
7
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
- **
|
|
10
|
-
- **
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## ✨ Features
|
|
11
|
+
|
|
12
|
+
- 🎯 **Multi-Pass Measurement**: Native `measureInWindow` API with self-correcting strategy for animation resilience.
|
|
13
|
+
- 📱 **Rotation & Resize Aware**: Targets re-measure automatically on orientation change or split-screen.
|
|
14
|
+
- ⚡ **Auto-Start Engine**: Trigger tours instantly on mount with a smart debounce for layout stability.
|
|
15
|
+
- 💾 **Seen State Caching**: Persistent "only-once" logic with pluggable storage (AsyncStorage, MMKV, etc.).
|
|
16
|
+
- 🎨 **Smart Overlays**: Dynamic cutouts with Back/Next/Skip navigation and step indicators.
|
|
11
17
|
|
|
12
|
-
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 📦 Installation
|
|
13
21
|
|
|
14
22
|
```sh
|
|
15
23
|
npm install rn-smart-tour
|
|
@@ -17,202 +25,126 @@ npm install rn-smart-tour
|
|
|
17
25
|
|
|
18
26
|
---
|
|
19
27
|
|
|
20
|
-
## 🚀 Quick Start
|
|
21
|
-
|
|
22
|
-
Adding a product tour to your app only takes 3 simple steps:
|
|
28
|
+
## 🚀 Quick Start
|
|
23
29
|
|
|
24
|
-
###
|
|
25
|
-
|
|
30
|
+
### 1. Wrap your App
|
|
31
|
+
Wrap your root component in the `DapProvider` and define your tours.
|
|
26
32
|
|
|
27
33
|
```tsx
|
|
28
|
-
import React from 'react';
|
|
29
34
|
import { DapProvider } from 'rn-smart-tour';
|
|
30
35
|
|
|
31
|
-
|
|
32
|
-
const MY_TOURS = {
|
|
36
|
+
const TOURS = {
|
|
33
37
|
'welcome-tour': {
|
|
34
38
|
id: 'welcome-tour',
|
|
35
|
-
steps: [
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
]
|
|
39
|
+
steps: [{
|
|
40
|
+
targetId: 'save-btn',
|
|
41
|
+
title: 'Welcome!',
|
|
42
|
+
description: 'Tap here to save your progress.',
|
|
43
|
+
}]
|
|
42
44
|
}
|
|
43
45
|
};
|
|
44
46
|
|
|
45
47
|
export default function App() {
|
|
46
48
|
return (
|
|
47
|
-
<DapProvider tours={
|
|
48
|
-
<
|
|
49
|
+
<DapProvider tours={TOURS}>
|
|
50
|
+
<MainApp />
|
|
49
51
|
</DapProvider>
|
|
50
52
|
);
|
|
51
53
|
}
|
|
52
54
|
```
|
|
53
55
|
|
|
54
|
-
###
|
|
55
|
-
|
|
56
|
+
### 2. Mark your Target
|
|
57
|
+
Wrap any view or button you want to highlight with `DapTarget`.
|
|
56
58
|
|
|
57
59
|
```tsx
|
|
58
|
-
import { View, Button } from 'react-native';
|
|
59
60
|
import { DapTarget } from 'rn-smart-tour';
|
|
60
61
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
<
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
<Button title="Save Button" onPress={() => {}} />
|
|
67
|
-
</DapTarget>
|
|
68
|
-
</View>
|
|
69
|
-
);
|
|
70
|
-
};
|
|
62
|
+
const MyButton = () => (
|
|
63
|
+
<DapTarget name="save-btn">
|
|
64
|
+
<Button title="Save" onPress={...} />
|
|
65
|
+
</DapTarget>
|
|
66
|
+
);
|
|
71
67
|
```
|
|
72
68
|
|
|
73
|
-
###
|
|
74
|
-
|
|
69
|
+
### 3. Start the Tour
|
|
70
|
+
Use the `useDap` hook to trigger the onboarding.
|
|
75
71
|
|
|
76
72
|
```tsx
|
|
77
|
-
import { Button } from 'react-native';
|
|
78
73
|
import { useDap } from 'rn-smart-tour';
|
|
79
74
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
return (
|
|
84
|
-
<Button
|
|
85
|
-
title="Start Walkthrough"
|
|
86
|
-
onPress={() => startTour('welcome-tour')}
|
|
87
|
-
/>
|
|
88
|
-
);
|
|
89
|
-
}
|
|
75
|
+
const { startTour } = useDap();
|
|
76
|
+
// ...
|
|
77
|
+
<Button title="Help" onPress={() => startTour('welcome-tour')} />
|
|
90
78
|
```
|
|
91
79
|
|
|
92
80
|
---
|
|
93
81
|
|
|
94
|
-
## 🧠
|
|
95
|
-
|
|
96
|
-
### 1. Auto-Start & Show "Only Once"
|
|
97
|
-
For true enterprise onboarding, you want the tour to start *automatically* when a user visits a new screen, and never show it to them again after they finish it.
|
|
98
|
-
|
|
99
|
-
By passing a `storageAdapter` (like `AsyncStorage`) into the Provider, the package will permanently remember who has seen the tour!
|
|
100
|
-
|
|
101
|
-
```tsx
|
|
102
|
-
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
103
|
-
|
|
104
|
-
const MY_TOURS = {
|
|
105
|
-
'welcome-tour': {
|
|
106
|
-
id: 'welcome-tour',
|
|
107
|
-
autoStart: true, // Automatically starts when "my-first-button" mounts!
|
|
108
|
-
steps: [ ... ]
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
// Map the Storage commands
|
|
113
|
-
const myStorage = {
|
|
114
|
-
getItem: async (key) => await AsyncStorage.getItem(key),
|
|
115
|
-
setItem: async (key, value) => { await AsyncStorage.setItem(key, value); }
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
// Pass it to the Provider
|
|
119
|
-
<DapProvider tours={MY_TOURS} storageAdapter={myStorage}>
|
|
120
|
-
```
|
|
82
|
+
## 🧠 Technical Architecture
|
|
121
83
|
|
|
122
|
-
|
|
84
|
+
<details>
|
|
85
|
+
<summary><b>View How Measurements Work (Click to expand)</b></summary>
|
|
123
86
|
|
|
124
|
-
|
|
87
|
+
To guarantee accuracy during navigation animations, `rn-smart-tour` uses a **multi-pass strategy**:
|
|
125
88
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
| 2nd | 500ms | Self-corrects after most navigation transitions finish |
|
|
130
|
-
| 3rd | 1000ms | Final safety net for slow animations or async layout shifts |
|
|
89
|
+
- **Pass 1 (100ms)**: Fast first estimate.
|
|
90
|
+
- **Pass 2 (500ms)**: Corrects after most screen transitions finish.
|
|
91
|
+
- **Pass 3 (1000ms)**: Final safety net for slow async layout shifts.
|
|
131
92
|
|
|
132
|
-
|
|
133
|
-
- A measurement is only sent to the Provider if the position has **actually changed** (>1pt threshold), avoiding unnecessary re-renders.
|
|
134
|
-
- On **rotation/resize**, all targets automatically re-measure themselves.
|
|
135
|
-
- On unmount, all timers are cleaned up and the target is unregistered.
|
|
93
|
+
Measurements only trigger a re-render if the position changes by more than **1pt (threshold)**.
|
|
136
94
|
|
|
137
|
-
|
|
95
|
+
</details>
|
|
138
96
|
|
|
139
|
-
|
|
97
|
+
<details>
|
|
98
|
+
<summary><b>Auto-Start & Debounce Settings</b></summary>
|
|
140
99
|
|
|
141
|
-
|
|
100
|
+
When `autoStart: true` is enabled, the overlay waits **300ms** after registration. This allows the multi-pass system to settle on the final coordinates before the hole is cut into the backdrop.
|
|
142
101
|
|
|
143
|
-
|
|
102
|
+
</details>
|
|
144
103
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
| Constant | File | Default | Description |
|
|
148
|
-
|----------|------|---------|-------------|
|
|
149
|
-
| `MEASUREMENT_DELAYS` | `DapTarget.tsx` | `[100, 500, 1000]` | Multi-pass measurement intervals (ms) |
|
|
150
|
-
| `POSITION_THRESHOLD` | `DapTarget.tsx` | `1` | Minimum position change (points) to trigger re-registration |
|
|
151
|
-
| `AUTO_START_DEBOUNCE_MS` | `DapProvider.tsx` | `300` | Debounce delay (ms) before auto-starting a tour |
|
|
152
|
-
|
|
153
|
-
### 3. Programmatic Control
|
|
154
|
-
|
|
155
|
-
The `useDap()` hook exposes full control over tours:
|
|
156
|
-
|
|
157
|
-
```tsx
|
|
158
|
-
const { startTour, stopTour, nextStep, prevStep, activeTour, currentStepIndex } = useDap();
|
|
159
|
-
|
|
160
|
-
// Start a specific tour
|
|
161
|
-
startTour('welcome-tour');
|
|
162
|
-
|
|
163
|
-
// Stop and mark as seen (default)
|
|
164
|
-
stopTour();
|
|
165
|
-
|
|
166
|
-
// Stop WITHOUT marking as seen (user can see it again)
|
|
167
|
-
stopTour(false);
|
|
168
|
-
|
|
169
|
-
// Navigate between steps
|
|
170
|
-
nextStep();
|
|
171
|
-
prevStep();
|
|
172
|
-
```
|
|
104
|
+
---
|
|
173
105
|
|
|
174
|
-
## API Reference
|
|
106
|
+
## 🛠 API Reference
|
|
175
107
|
|
|
176
|
-
### Tour
|
|
108
|
+
### Tour Configuration
|
|
177
109
|
| Property | Type | Description |
|
|
178
|
-
|
|
179
|
-
| `id` | `string` | Unique identifier
|
|
180
|
-
| `autoStart` | `boolean` |
|
|
181
|
-
| `steps` | `TourStep[]` |
|
|
110
|
+
|:---|:---|:---|
|
|
111
|
+
| `id` | `string` | Unique identifier for caching. |
|
|
112
|
+
| `autoStart` | `boolean` | Trigger as soon as the first target mounts. |
|
|
113
|
+
| `steps` | `TourStep[]` | Sequence of highlight steps. |
|
|
182
114
|
|
|
183
|
-
###
|
|
184
|
-
| Property | Type | Default | Description |
|
|
185
|
-
|-----------|------|---------|-------------|
|
|
186
|
-
| `targetId` | `string` | — | Must directly match the `name=""` prop passed to `<DapTarget>`. |
|
|
187
|
-
| `title` | `string` | — | Large text inside the tooltip. |
|
|
188
|
-
| `description` | `string` | — | Context explanation inside the tooltip. |
|
|
189
|
-
| `position` | `'top' \| 'bottom' \| 'left' \| 'right'` | `'bottom'` | Where the tooltip appears relative to the highlighted target. |
|
|
190
|
-
|
|
191
|
-
### DapTarget Props
|
|
115
|
+
### DapTarget
|
|
192
116
|
| Property | Type | Description |
|
|
193
|
-
|
|
117
|
+
|:---|:---|:---|
|
|
194
118
|
| `name` | `string` | Unique identifier that matches a `targetId` in a tour step. |
|
|
195
119
|
| `children` | `ReactElement` | The UI element to wrap and highlight. |
|
|
120
|
+
| `asChild` | `boolean` | **New!** If true, clones the child to avoid an extra View wrapper. (Crucial for flex/percentage layouts). |
|
|
196
121
|
| `...props` | `ViewProps` | All standard React Native `View` props are forwarded. |
|
|
197
122
|
|
|
198
|
-
###
|
|
199
|
-
| Property | Type | Description |
|
|
200
|
-
|
|
201
|
-
| `
|
|
202
|
-
| `
|
|
203
|
-
| `
|
|
204
|
-
| `
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
|
212
|
-
|
|
213
|
-
| `
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
123
|
+
### TourStep
|
|
124
|
+
| Property | Type | Default | Description |
|
|
125
|
+
|:---|:---|:---|:---|
|
|
126
|
+
| `targetId` | `string` | — | Matches the `name` prop in `<DapTarget>`. |
|
|
127
|
+
| `title` | `string` | — | Tooltip header. |
|
|
128
|
+
| `description` | `string` | — | Tooltip body. |
|
|
129
|
+
| `position` | `string` | `'bottom'` | `top`, `bottom`, `left`, `right`. |
|
|
130
|
+
|
|
131
|
+
### `useDap()` Hook
|
|
132
|
+
| Method | Description |
|
|
133
|
+
|:---|:---|
|
|
134
|
+
| `startTour(id)` | Start a tour by ID. |
|
|
135
|
+
| `stopTour(markAsSeen?)`| End tour. Pass `false` to keep it unread. |
|
|
136
|
+
| `nextStep()` / `prevStep()` | Manual step navigation. |
|
|
137
|
+
| `activeTour` | Current active tour object. |
|
|
138
|
+
| `currentStepIndex` | Current step number (0-indexed). |
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## 🤝 Contributing
|
|
143
|
+
|
|
144
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
<p align="center">
|
|
149
|
+
<b>rn-smart-tour</b> • Built with ❤️ for the React Native community.
|
|
150
|
+
</p>
|
package/dist/DapOverlay.js
CHANGED
|
@@ -126,9 +126,9 @@ const DapOverlay = () => {
|
|
|
126
126
|
</react_native_1.Text>)}
|
|
127
127
|
|
|
128
128
|
<react_native_1.View style={styles.actions}>
|
|
129
|
-
<react_native_1.TouchableOpacity onPress={() => stopTour()} style={styles.actionBtn}>
|
|
130
|
-
|
|
131
|
-
|
|
129
|
+
{!isLastStep && (<react_native_1.TouchableOpacity onPress={() => stopTour()} style={styles.actionBtn}>
|
|
130
|
+
<react_native_1.Text style={styles.actionText}>Skip</react_native_1.Text>
|
|
131
|
+
</react_native_1.TouchableOpacity>)}
|
|
132
132
|
|
|
133
133
|
{!isFirstStep && (<react_native_1.TouchableOpacity onPress={prevStep} style={styles.actionBtn}>
|
|
134
134
|
<react_native_1.Text style={styles.actionText}>Back</react_native_1.Text>
|
package/dist/DapProvider.js
CHANGED
|
@@ -50,9 +50,15 @@ const DapProvider = ({ children, tours, storageAdapter }) => {
|
|
|
50
50
|
const [currentStepIndex, setCurrentStepIndex] = (0, react_1.useState)(0);
|
|
51
51
|
const [seenTours, setSeenTours] = (0, react_1.useState)({});
|
|
52
52
|
const [isStorageLoaded, setIsStorageLoaded] = (0, react_1.useState)(!storageAdapter);
|
|
53
|
-
// Ref to
|
|
53
|
+
// Ref to always hold the latest activeTourId, avoiding stale closures.
|
|
54
54
|
const activeTourIdRef = (0, react_1.useRef)(activeTourId);
|
|
55
55
|
activeTourIdRef.current = activeTourId;
|
|
56
|
+
/**
|
|
57
|
+
* Ref to track the ID of a tour that was just manually stopped/skipped.
|
|
58
|
+
* This prevents the auto-start engine from immediately restarting the same tour
|
|
59
|
+
* before the 'seenTours' state update has been processed.
|
|
60
|
+
*/
|
|
61
|
+
const tourIdJustStoppedRef = (0, react_1.useRef)(null);
|
|
56
62
|
// Load seen tours on mount if a storage adapter is provided
|
|
57
63
|
(0, react_1.useEffect)(() => {
|
|
58
64
|
const loadStorage = async () => {
|
|
@@ -102,11 +108,14 @@ const DapProvider = ({ children, tours, storageAdapter }) => {
|
|
|
102
108
|
console.warn(`[rn-dap] Tour with id ${tourId} not found.`);
|
|
103
109
|
}
|
|
104
110
|
}, [tours, seenTours]);
|
|
105
|
-
// Uses activeTourIdRef to avoid stale closures and prevent cascading re-renders.
|
|
106
111
|
const stopTour = (0, react_1.useCallback)((markAsSeen = true) => {
|
|
107
112
|
const currentTourId = activeTourIdRef.current;
|
|
108
|
-
if (currentTourId
|
|
109
|
-
|
|
113
|
+
if (currentTourId) {
|
|
114
|
+
if (markAsSeen) {
|
|
115
|
+
saveSeenTour(currentTourId);
|
|
116
|
+
}
|
|
117
|
+
// Block this specific tour from auto-restarting until coordinates or seenTours settle.
|
|
118
|
+
tourIdJustStoppedRef.current = currentTourId;
|
|
110
119
|
}
|
|
111
120
|
setActiveTourId(null);
|
|
112
121
|
setCurrentStepIndex(0);
|
|
@@ -142,7 +151,9 @@ const DapProvider = ({ children, tours, storageAdapter }) => {
|
|
|
142
151
|
autoStartTimerRef.current = setTimeout(() => {
|
|
143
152
|
for (const tourId of Object.keys(tours)) {
|
|
144
153
|
const tour = tours[tourId];
|
|
145
|
-
if
|
|
154
|
+
// Skip if this tour was just manually stopped and haven't confirmed 'seen' yet.
|
|
155
|
+
const wasJustStopped = tourIdJustStoppedRef.current === tourId;
|
|
156
|
+
if (tour.autoStart && !seenTours[tourId] && !wasJustStopped && tour.steps.length > 0) {
|
|
146
157
|
const firstTargetId = tour.steps[0].targetId;
|
|
147
158
|
// If the first target of an unread, auto-starting tour is mounted
|
|
148
159
|
if (targets[firstTargetId]) {
|
|
@@ -151,6 +162,10 @@ const DapProvider = ({ children, tours, storageAdapter }) => {
|
|
|
151
162
|
}
|
|
152
163
|
}
|
|
153
164
|
}
|
|
165
|
+
// Cleanup the "just stopped" ref once the seenTours state finally reflects the closure.
|
|
166
|
+
if (tourIdJustStoppedRef.current && seenTours[tourIdJustStoppedRef.current]) {
|
|
167
|
+
tourIdJustStoppedRef.current = null;
|
|
168
|
+
}
|
|
154
169
|
}, AUTO_START_DEBOUNCE_MS);
|
|
155
170
|
return () => {
|
|
156
171
|
if (autoStartTimerRef.current) {
|
package/dist/DapTarget.d.ts
CHANGED
|
@@ -3,6 +3,12 @@ import { ViewProps } from 'react-native';
|
|
|
3
3
|
interface DapTargetProps extends ViewProps {
|
|
4
4
|
name: string;
|
|
5
5
|
children: ReactElement;
|
|
6
|
+
/**
|
|
7
|
+
* If true, DapTarget will not wrap your child in a View. Instead, it will
|
|
8
|
+
* clone the child and inject the ref/onLayout logic directly.
|
|
9
|
+
* Useful for maintaining flex layouts or percentage widths (e.g. 33%).
|
|
10
|
+
*/
|
|
11
|
+
asChild?: boolean;
|
|
6
12
|
}
|
|
7
13
|
export declare const DapTarget: React.FC<DapTargetProps>;
|
|
8
14
|
export {};
|
package/dist/DapTarget.js
CHANGED
|
@@ -45,7 +45,22 @@ const DapContext_1 = require("./DapContext");
|
|
|
45
45
|
const MEASUREMENT_DELAYS = [100, 500, 1000];
|
|
46
46
|
/** Threshold in points — ignore sub-pixel drift to avoid unnecessary re-registers. */
|
|
47
47
|
const POSITION_THRESHOLD = 1;
|
|
48
|
-
|
|
48
|
+
/**
|
|
49
|
+
* Utility to merge multiple refs into a single callback ref.
|
|
50
|
+
*/
|
|
51
|
+
function setRefs(...refs) {
|
|
52
|
+
return (value) => {
|
|
53
|
+
refs.forEach((ref) => {
|
|
54
|
+
if (typeof ref === 'function') {
|
|
55
|
+
ref(value);
|
|
56
|
+
}
|
|
57
|
+
else if (ref && typeof ref === 'object') {
|
|
58
|
+
ref.current = value;
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
const DapTarget = ({ name, children, asChild, ...props }) => {
|
|
49
64
|
const viewRef = (0, react_1.useRef)(null);
|
|
50
65
|
const context = (0, react_1.useContext)(DapContext_1.DapContext);
|
|
51
66
|
/** Holds all scheduled timer IDs so we can cancel them on re-layout or unmount. */
|
|
@@ -116,7 +131,26 @@ const DapTarget = ({ name, children, ...props }) => {
|
|
|
116
131
|
unregisterTarget?.(name);
|
|
117
132
|
};
|
|
118
133
|
}, [name, unregisterTarget, clearAllTimers]);
|
|
119
|
-
//
|
|
134
|
+
// If asChild is enabled, clone the child and inject measurement logic.
|
|
135
|
+
if (asChild && (0, react_1.isValidElement)(children)) {
|
|
136
|
+
try {
|
|
137
|
+
const child = react_1.Children.only(children);
|
|
138
|
+
return (0, react_1.cloneElement)(child, {
|
|
139
|
+
...props,
|
|
140
|
+
ref: setRefs(viewRef, child.ref),
|
|
141
|
+
onLayout: (e) => {
|
|
142
|
+
handleLayout(e);
|
|
143
|
+
child.props.onLayout?.(e);
|
|
144
|
+
},
|
|
145
|
+
// collapsable={false} is vital for Android measurement
|
|
146
|
+
collapsable: false,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
catch (e) {
|
|
150
|
+
console.warn('[rn-dap] asChild requires a single React element as a child.');
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
// Fallback to standard View wrapper
|
|
120
154
|
return (<react_native_1.View ref={viewRef} onLayout={handleLayout} collapsable={false} {...props}>
|
|
121
155
|
{children}
|
|
122
156
|
</react_native_1.View>);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rn-smart-tour",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "Enterprise-grade Digital Adoption Platform (DAP) package for React Native. Provides guided walkthroughs, tooltips, and app tours.",
|
|
5
5
|
"author": "Vishwas Gaur",
|
|
6
6
|
"license": "MIT",
|
|
@@ -9,14 +9,6 @@
|
|
|
9
9
|
"files": [
|
|
10
10
|
"dist"
|
|
11
11
|
],
|
|
12
|
-
"repository": {
|
|
13
|
-
"type": "git",
|
|
14
|
-
"url": "https://github.com/Vishwasgaur0819/rn-smart-tour"
|
|
15
|
-
},
|
|
16
|
-
"homepage": "https://github.com/Vishwasgaur0819/rn-smart-tour#readme",
|
|
17
|
-
"bugs": {
|
|
18
|
-
"url": "https://github.com/Vishwasgaur0819/rn-smart-tour/issues"
|
|
19
|
-
},
|
|
20
12
|
"keywords": [
|
|
21
13
|
"react-native",
|
|
22
14
|
"tour",
|