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
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { TourConfig, InternalTourContextType } from '../types';
|
|
3
|
+
export declare const TourContext: React.Context<InternalTourContextType | null>;
|
|
4
|
+
interface TourProviderProps {
|
|
5
|
+
children: React.ReactNode;
|
|
6
|
+
/**
|
|
7
|
+
* Optional custom steps order. If provided, the tour will follow this array of keys.
|
|
8
|
+
*/
|
|
9
|
+
stepsOrder?: string[];
|
|
10
|
+
/**
|
|
11
|
+
* Initial overlay opacity. Default 0.5
|
|
12
|
+
*/
|
|
13
|
+
backdropOpacity?: number;
|
|
14
|
+
/**
|
|
15
|
+
* Global configuration for the tour.
|
|
16
|
+
*/
|
|
17
|
+
config?: TourConfig;
|
|
18
|
+
}
|
|
19
|
+
export declare const TourProvider: React.FC<TourProviderProps>;
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=TourProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TourProvider.d.ts","sourceRoot":"","sources":["../../../../src/components/TourProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAON,MAAM,OAAO,CAAC;AASf,OAAO,KAAK,EAGV,UAAU,EACV,uBAAuB,EACxB,MAAM,UAAU,CAAC;AAQlB,eAAO,MAAM,WAAW,+CAAsD,CAAC;AAE/E,UAAU,iBAAiB;IACzB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;OAEG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAID,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAiTpD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TourTooltip.d.ts","sourceRoot":"","sources":["../../../../src/components/TourTooltip.tsx"],"names":[],"mappings":"AAoBA,eAAO,MAAM,WAAW,2FAyKtB,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ViewStyle, StyleProp } from 'react-native';
|
|
3
|
+
interface TourZoneProps {
|
|
4
|
+
stepKey: string;
|
|
5
|
+
name?: string;
|
|
6
|
+
description: string;
|
|
7
|
+
order?: number;
|
|
8
|
+
shape?: 'rect' | 'circle';
|
|
9
|
+
borderRadius?: number;
|
|
10
|
+
children: React.ReactNode;
|
|
11
|
+
style?: StyleProp<ViewStyle>;
|
|
12
|
+
clickable?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare const TourZone: React.FC<TourZoneProps>;
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=TourZone.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TourZone.d.ts","sourceRoot":"","sources":["../../../../src/components/TourZone.tsx"],"names":[],"mappings":"AAAA,OAAO,KAKN,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAkBzD,UAAU,aAAa;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CA+U5C,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { WithSpringConfig } from 'react-native-reanimated';
|
|
2
|
+
/**
|
|
3
|
+
* Default spring configuration matching Reanimated 3 defaults.
|
|
4
|
+
*/
|
|
5
|
+
export declare const Reanimated3DefaultSpringConfig: WithSpringConfig;
|
|
6
|
+
/**
|
|
7
|
+
* Spring configuration with duration.
|
|
8
|
+
*/
|
|
9
|
+
export declare const Reanimated3DefaultSpringConfigWithDuration: WithSpringConfig;
|
|
10
|
+
/**
|
|
11
|
+
* A bouncy and energetic spring configuration.
|
|
12
|
+
*/
|
|
13
|
+
export declare const WigglySpringConfig: WithSpringConfig;
|
|
14
|
+
/**
|
|
15
|
+
* A bouncy spring configuration with fixed duration.
|
|
16
|
+
*/
|
|
17
|
+
export declare const WigglySpringConfigWithDuration: WithSpringConfig;
|
|
18
|
+
/**
|
|
19
|
+
* A gentle and smooth spring configuration.
|
|
20
|
+
*/
|
|
21
|
+
export declare const GentleSpringConfig: WithSpringConfig;
|
|
22
|
+
/**
|
|
23
|
+
* A gentle spring configuration with fixed duration.
|
|
24
|
+
*/
|
|
25
|
+
export declare const GentleSpringConfigWithDuration: WithSpringConfig;
|
|
26
|
+
/**
|
|
27
|
+
* A snappy and responsive spring configuration.
|
|
28
|
+
*/
|
|
29
|
+
export declare const SnappySpringConfig: WithSpringConfig;
|
|
30
|
+
/**
|
|
31
|
+
* A snappy spring configuration with fixed duration.
|
|
32
|
+
*/
|
|
33
|
+
export declare const SnappySpringConfigWithDuration: WithSpringConfig;
|
|
34
|
+
//# sourceMappingURL=animations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"animations.d.ts","sourceRoot":"","sources":["../../../../src/constants/animations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE;;GAEG;AACH,eAAO,MAAM,8BAA8B,EAAE,gBAI5C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,0CAA0C,EAAE,gBAGxD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB,EAAE,gBAIhC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,8BAA8B,EAAE,gBAG5C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB,EAAE,gBAIhC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,8BAA8B,EAAE,gBAG5C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB,EAAE,gBAKhC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,8BAA8B,EAAE,gBAI5C,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { WithSpringConfig } from 'react-native-reanimated';
|
|
2
|
+
export declare const DEFAULT_SPRING_CONFIG: WithSpringConfig;
|
|
3
|
+
export declare const DEFAULT_BACKDROP_OPACITY = 0.5;
|
|
4
|
+
export declare const DEFAULT_LABELS: {
|
|
5
|
+
next: string;
|
|
6
|
+
previous: string;
|
|
7
|
+
finish: string;
|
|
8
|
+
skip: string;
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=defaults.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../../../src/constants/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,eAAO,MAAM,qBAAqB,EAAE,gBAGnC,CAAC;AAEF,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAE5C,eAAO,MAAM,cAAc;;;;;CAK1B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useTour.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useTour.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,OAAO,4CAMnB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from './types';
|
|
2
|
+
export * from './components/TourProvider';
|
|
3
|
+
export * from './components/TourZone';
|
|
4
|
+
export * from './hooks/useTour';
|
|
5
|
+
export { TourOverlay } from './components/TourOverlay';
|
|
6
|
+
export { TourTooltip } from './components/TourTooltip';
|
|
7
|
+
export * from './constants/defaults';
|
|
8
|
+
export * from './constants/animations';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,iBAAiB,CAAC;AAChC,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import type { WithSpringConfig, SharedValue } from 'react-native-reanimated';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
export interface TourStep {
|
|
4
|
+
/**
|
|
5
|
+
* Unique key for this step.
|
|
6
|
+
*/
|
|
7
|
+
key: string;
|
|
8
|
+
/**
|
|
9
|
+
* Optional display name/label for this step.
|
|
10
|
+
*/
|
|
11
|
+
name?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Description text to show in the tooltip.
|
|
14
|
+
*/
|
|
15
|
+
description: string;
|
|
16
|
+
/**
|
|
17
|
+
* Optional order index. If not provided, registration order is used (or explicit ordering in context).
|
|
18
|
+
*/
|
|
19
|
+
order?: number;
|
|
20
|
+
/**
|
|
21
|
+
* Optional data for custom tooltip rendering
|
|
22
|
+
*/
|
|
23
|
+
meta?: any;
|
|
24
|
+
/**
|
|
25
|
+
* If true, allows user interaction with the target element.
|
|
26
|
+
* If false, interactions are blocked (default behavior depends on global config).
|
|
27
|
+
*/
|
|
28
|
+
clickable?: boolean;
|
|
29
|
+
}
|
|
30
|
+
export interface MeasureResult {
|
|
31
|
+
x: number;
|
|
32
|
+
y: number;
|
|
33
|
+
width: number;
|
|
34
|
+
height: number;
|
|
35
|
+
}
|
|
36
|
+
export type StepMap = Record<string, TourStep>;
|
|
37
|
+
export interface TourLabels {
|
|
38
|
+
next?: string;
|
|
39
|
+
previous?: string;
|
|
40
|
+
finish?: string;
|
|
41
|
+
skip?: string;
|
|
42
|
+
}
|
|
43
|
+
export interface CardProps {
|
|
44
|
+
step: TourStep;
|
|
45
|
+
currentStepIndex: number;
|
|
46
|
+
totalSteps: number;
|
|
47
|
+
next: () => void;
|
|
48
|
+
prev: () => void;
|
|
49
|
+
stop: () => void;
|
|
50
|
+
isFirst: boolean;
|
|
51
|
+
isLast: boolean;
|
|
52
|
+
labels?: TourLabels;
|
|
53
|
+
}
|
|
54
|
+
export interface TourConfig {
|
|
55
|
+
/**
|
|
56
|
+
* Animation configuration for the spotlight movement.
|
|
57
|
+
*/
|
|
58
|
+
springConfig?: WithSpringConfig;
|
|
59
|
+
/**
|
|
60
|
+
* If true, prevents interaction with the underlying app while tour is active.
|
|
61
|
+
* Default: false (interactions allowed outside the tooltip, but overlay might block them depending on implementation).
|
|
62
|
+
*/
|
|
63
|
+
preventInteraction?: boolean;
|
|
64
|
+
/**
|
|
65
|
+
* Custom labels for buttons.
|
|
66
|
+
*/
|
|
67
|
+
labels?: TourLabels;
|
|
68
|
+
/**
|
|
69
|
+
* Custom renderer for the card/tooltip.
|
|
70
|
+
*/
|
|
71
|
+
renderCard?: (props: CardProps) => React.ReactNode;
|
|
72
|
+
/**
|
|
73
|
+
* Backdrop opacity. Default 0.5
|
|
74
|
+
*/
|
|
75
|
+
backdropOpacity?: number;
|
|
76
|
+
}
|
|
77
|
+
export interface TourContextType {
|
|
78
|
+
/**
|
|
79
|
+
* Starts the tour at the first step or a specific step (by key).
|
|
80
|
+
*/
|
|
81
|
+
start: (stepKey?: string) => void;
|
|
82
|
+
/**
|
|
83
|
+
* Stops the tour and hides the overlay.
|
|
84
|
+
*/
|
|
85
|
+
stop: () => void;
|
|
86
|
+
/**
|
|
87
|
+
* Advances to the next step.
|
|
88
|
+
*/
|
|
89
|
+
next: () => void;
|
|
90
|
+
/**
|
|
91
|
+
* Goes back to the previous step.
|
|
92
|
+
*/
|
|
93
|
+
prev: () => void;
|
|
94
|
+
/**
|
|
95
|
+
* Registers a zone/step.
|
|
96
|
+
*/
|
|
97
|
+
registerStep: (step: TourStep) => void;
|
|
98
|
+
/**
|
|
99
|
+
* Unregisters a zone/step.
|
|
100
|
+
*/
|
|
101
|
+
unregisterStep: (key: string) => void;
|
|
102
|
+
/**
|
|
103
|
+
* Updates the layout of a specific step.
|
|
104
|
+
* This is called by TourZone on layout/mount.
|
|
105
|
+
*/
|
|
106
|
+
updateStepLayout: (key: string, measure: MeasureResult) => void;
|
|
107
|
+
/**
|
|
108
|
+
* The current active step key, or null if tour is inactive.
|
|
109
|
+
*/
|
|
110
|
+
currentStep: string | null;
|
|
111
|
+
/**
|
|
112
|
+
* Map of registered steps.
|
|
113
|
+
*/
|
|
114
|
+
steps: StepMap;
|
|
115
|
+
/**
|
|
116
|
+
* Global tour configuration
|
|
117
|
+
*/
|
|
118
|
+
config?: TourConfig;
|
|
119
|
+
/**
|
|
120
|
+
* Registers the main ScrollView ref for auto-scrolling
|
|
121
|
+
*/
|
|
122
|
+
setScrollViewRef: (ref: any) => void;
|
|
123
|
+
}
|
|
124
|
+
export interface InternalTourContextType extends TourContextType {
|
|
125
|
+
targetX: SharedValue<number>;
|
|
126
|
+
targetY: SharedValue<number>;
|
|
127
|
+
targetWidth: SharedValue<number>;
|
|
128
|
+
targetHeight: SharedValue<number>;
|
|
129
|
+
targetRadius: SharedValue<number>;
|
|
130
|
+
opacity: SharedValue<number>;
|
|
131
|
+
containerRef: React.RefObject<any>;
|
|
132
|
+
scrollViewRef: React.RefObject<any>;
|
|
133
|
+
setScrollViewRef: (ref: any) => void;
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/types/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "react-native-lumen",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A customizable app tour library for React Native",
|
|
5
|
+
"main": "./lib/module/index.js",
|
|
6
|
+
"types": "./lib/typescript/src/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"source": "./src/index.tsx",
|
|
10
|
+
"types": "./lib/typescript/src/index.d.ts",
|
|
11
|
+
"default": "./lib/module/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./package.json": "./package.json"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"src",
|
|
17
|
+
"lib",
|
|
18
|
+
"android",
|
|
19
|
+
"ios",
|
|
20
|
+
"cpp",
|
|
21
|
+
"*.podspec",
|
|
22
|
+
"react-native.config.js",
|
|
23
|
+
"!ios/build",
|
|
24
|
+
"!android/build",
|
|
25
|
+
"!android/gradle",
|
|
26
|
+
"!android/gradlew",
|
|
27
|
+
"!android/gradlew.bat",
|
|
28
|
+
"!android/local.properties",
|
|
29
|
+
"!**/__tests__",
|
|
30
|
+
"!**/__fixtures__",
|
|
31
|
+
"!**/__mocks__",
|
|
32
|
+
"!**/.*"
|
|
33
|
+
],
|
|
34
|
+
"scripts": {
|
|
35
|
+
"example": "yarn workspace react-native-lumen-example",
|
|
36
|
+
"clean": "del-cli lib",
|
|
37
|
+
"prepare": "bob build",
|
|
38
|
+
"typecheck": "tsc",
|
|
39
|
+
"lint": "eslint \"**/*.{js,ts,tsx}\"",
|
|
40
|
+
"test": "jest",
|
|
41
|
+
"release": "release-it --only-version"
|
|
42
|
+
},
|
|
43
|
+
"keywords": [
|
|
44
|
+
"react-native",
|
|
45
|
+
"ios",
|
|
46
|
+
"android"
|
|
47
|
+
],
|
|
48
|
+
"repository": {
|
|
49
|
+
"type": "git",
|
|
50
|
+
"url": "git+https://github.com/thedev204/react-native-lumen.git"
|
|
51
|
+
},
|
|
52
|
+
"author": "thedev204 <116882323+thedev204@users.noreply.github.com> (https://github.com/thedev204)",
|
|
53
|
+
"license": "MIT",
|
|
54
|
+
"bugs": {
|
|
55
|
+
"url": "https://github.com/thedev204/react-native-lumen/issues"
|
|
56
|
+
},
|
|
57
|
+
"homepage": "https://github.com/thedev204/react-native-lumen#readme",
|
|
58
|
+
"publishConfig": {
|
|
59
|
+
"registry": "https://registry.npmjs.org/"
|
|
60
|
+
},
|
|
61
|
+
"devDependencies": {
|
|
62
|
+
"@commitlint/config-conventional": "^19.8.1",
|
|
63
|
+
"@eslint/compat": "^1.3.2",
|
|
64
|
+
"@eslint/eslintrc": "^3.3.1",
|
|
65
|
+
"@eslint/js": "^9.35.0",
|
|
66
|
+
"@react-native/babel-preset": "0.83.0",
|
|
67
|
+
"@react-native/eslint-config": "0.83.0",
|
|
68
|
+
"@release-it/conventional-changelog": "^10.0.1",
|
|
69
|
+
"@types/jest": "^29.5.14",
|
|
70
|
+
"@types/react": "^19.1.12",
|
|
71
|
+
"commitlint": "^19.8.1",
|
|
72
|
+
"del-cli": "^6.0.0",
|
|
73
|
+
"eslint": "^9.39.2",
|
|
74
|
+
"eslint-config-prettier": "^9.0.0",
|
|
75
|
+
"eslint-plugin-prettier": "^5.0.0",
|
|
76
|
+
"jest": "^29.7.0",
|
|
77
|
+
"lefthook": "^2.0.3",
|
|
78
|
+
"prettier": "^3.0.0",
|
|
79
|
+
"react": "19.1.0",
|
|
80
|
+
"react-native": "0.81.5",
|
|
81
|
+
"react-native-builder-bob": "^0.40.13",
|
|
82
|
+
"react-native-gesture-handler": "^2.16.0",
|
|
83
|
+
"react-native-reanimated": "^3.0.0",
|
|
84
|
+
"react-native-svg": "^12.0.0",
|
|
85
|
+
"release-it": "^19.0.4",
|
|
86
|
+
"typescript": "~5.7.0"
|
|
87
|
+
},
|
|
88
|
+
"peerDependencies": {
|
|
89
|
+
"react": "*",
|
|
90
|
+
"react-native": "*",
|
|
91
|
+
"react-native-gesture-handler": ">=2.0.0",
|
|
92
|
+
"react-native-reanimated": ">=3.0.0",
|
|
93
|
+
"react-native-svg": ">=12.0.0",
|
|
94
|
+
"react-native-worklets": ">=0.3.0"
|
|
95
|
+
},
|
|
96
|
+
"workspaces": [
|
|
97
|
+
"example"
|
|
98
|
+
],
|
|
99
|
+
"packageManager": "yarn@4.11.0",
|
|
100
|
+
"react-native-builder-bob": {
|
|
101
|
+
"source": "src",
|
|
102
|
+
"output": "lib",
|
|
103
|
+
"targets": [
|
|
104
|
+
[
|
|
105
|
+
"module",
|
|
106
|
+
{
|
|
107
|
+
"esm": true
|
|
108
|
+
}
|
|
109
|
+
],
|
|
110
|
+
[
|
|
111
|
+
"typescript",
|
|
112
|
+
{
|
|
113
|
+
"project": "tsconfig.build.json"
|
|
114
|
+
}
|
|
115
|
+
]
|
|
116
|
+
]
|
|
117
|
+
},
|
|
118
|
+
"prettier": {
|
|
119
|
+
"quoteProps": "consistent",
|
|
120
|
+
"singleQuote": true,
|
|
121
|
+
"tabWidth": 2,
|
|
122
|
+
"trailingComma": "es5",
|
|
123
|
+
"useTabs": false
|
|
124
|
+
},
|
|
125
|
+
"jest": {
|
|
126
|
+
"preset": "react-native",
|
|
127
|
+
"modulePathIgnorePatterns": [
|
|
128
|
+
"<rootDir>/example/node_modules",
|
|
129
|
+
"<rootDir>/lib/"
|
|
130
|
+
]
|
|
131
|
+
},
|
|
132
|
+
"commitlint": {
|
|
133
|
+
"extends": [
|
|
134
|
+
"@commitlint/config-conventional"
|
|
135
|
+
]
|
|
136
|
+
},
|
|
137
|
+
"release-it": {
|
|
138
|
+
"git": {
|
|
139
|
+
"commitMessage": "chore: release ${version}",
|
|
140
|
+
"tagName": "v${version}"
|
|
141
|
+
},
|
|
142
|
+
"npm": {
|
|
143
|
+
"publish": true
|
|
144
|
+
},
|
|
145
|
+
"github": {
|
|
146
|
+
"release": true
|
|
147
|
+
},
|
|
148
|
+
"plugins": {
|
|
149
|
+
"@release-it/conventional-changelog": {
|
|
150
|
+
"preset": {
|
|
151
|
+
"name": "angular"
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
"create-react-native-library": {
|
|
157
|
+
"type": "library",
|
|
158
|
+
"languages": "js",
|
|
159
|
+
"tools": [
|
|
160
|
+
"eslint",
|
|
161
|
+
"jest",
|
|
162
|
+
"lefthook",
|
|
163
|
+
"release-it"
|
|
164
|
+
],
|
|
165
|
+
"version": "0.57.0"
|
|
166
|
+
},
|
|
167
|
+
"resolutions": {
|
|
168
|
+
"@types/react": "^19.1.12",
|
|
169
|
+
"typescript": "5.7.3"
|
|
170
|
+
}
|
|
171
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { memo, type ComponentType } from 'react';
|
|
2
|
+
import { StyleSheet, Dimensions } from 'react-native';
|
|
3
|
+
import Svg, { Path } from 'react-native-svg';
|
|
4
|
+
import Animated, {
|
|
5
|
+
useAnimatedProps,
|
|
6
|
+
useAnimatedStyle,
|
|
7
|
+
} from 'react-native-reanimated';
|
|
8
|
+
import { useTour } from '../hooks/useTour';
|
|
9
|
+
import type { InternalTourContextType } from '../types';
|
|
10
|
+
|
|
11
|
+
const { width: SCREEN_WIDTH, height: SCREEN_HEIGHT } = Dimensions.get('window');
|
|
12
|
+
|
|
13
|
+
const AnimatedPath = Animated.createAnimatedComponent(Path);
|
|
14
|
+
const AnimatedView = Animated.View as unknown as ComponentType<any>;
|
|
15
|
+
|
|
16
|
+
// Helper to create rounded rect path
|
|
17
|
+
// x,y are top-left coordinates
|
|
18
|
+
const createRoundedRectPath = (
|
|
19
|
+
x: number,
|
|
20
|
+
y: number,
|
|
21
|
+
w: number,
|
|
22
|
+
h: number,
|
|
23
|
+
r: number
|
|
24
|
+
) => {
|
|
25
|
+
'worklet';
|
|
26
|
+
// Ensure radius doesn't exceed dimensions
|
|
27
|
+
const radius = Math.min(r, w / 2, h / 2);
|
|
28
|
+
|
|
29
|
+
// Standard SVG Path command for rounded rect
|
|
30
|
+
return `
|
|
31
|
+
M ${x + radius}, ${y}
|
|
32
|
+
H ${x + w - radius}
|
|
33
|
+
A ${radius} ${radius} 0 0 1 ${x + w}, ${y + radius}
|
|
34
|
+
V ${y + h - radius}
|
|
35
|
+
A ${radius} ${radius} 0 0 1 ${x + w - radius}, ${y + h}
|
|
36
|
+
H ${x + radius}
|
|
37
|
+
A ${radius} ${radius} 0 0 1 ${x}, ${y + h - radius}
|
|
38
|
+
V ${y + radius}
|
|
39
|
+
A ${radius} ${radius} 0 0 1 ${x + radius}, ${y}
|
|
40
|
+
Z
|
|
41
|
+
`;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const TourOverlay = memo(() => {
|
|
45
|
+
const {
|
|
46
|
+
targetX,
|
|
47
|
+
targetY,
|
|
48
|
+
targetWidth,
|
|
49
|
+
targetHeight,
|
|
50
|
+
targetRadius,
|
|
51
|
+
opacity,
|
|
52
|
+
config,
|
|
53
|
+
currentStep,
|
|
54
|
+
steps,
|
|
55
|
+
} = useTour() as InternalTourContextType;
|
|
56
|
+
|
|
57
|
+
// Create the d string for the mask
|
|
58
|
+
// Outer rectangle covers the whole screen
|
|
59
|
+
// Inner shape is the "hole"
|
|
60
|
+
// fillRule="evenodd" makes the intersection transparent
|
|
61
|
+
const animatedProps = useAnimatedProps(() => {
|
|
62
|
+
const holePath = createRoundedRectPath(
|
|
63
|
+
targetX.value,
|
|
64
|
+
targetY.value,
|
|
65
|
+
targetWidth.value,
|
|
66
|
+
targetHeight.value,
|
|
67
|
+
targetRadius.value
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
const path = `
|
|
71
|
+
M 0,0
|
|
72
|
+
H ${SCREEN_WIDTH}
|
|
73
|
+
V ${SCREEN_HEIGHT}
|
|
74
|
+
H 0
|
|
75
|
+
Z
|
|
76
|
+
${holePath}
|
|
77
|
+
`;
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
d: path,
|
|
81
|
+
fillOpacity: opacity.value,
|
|
82
|
+
};
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const step = currentStep ? steps[currentStep] : null;
|
|
86
|
+
const isClickable = step?.clickable ?? false;
|
|
87
|
+
|
|
88
|
+
// Interaction Logic:
|
|
89
|
+
// 1. preventInteraction = true:
|
|
90
|
+
// - Wrapper pointerEvents = 'box-none' (pass through) BUT SVG is auto?
|
|
91
|
+
// - Actually, if we want to block OUTSIDE but allow INSIDE:
|
|
92
|
+
// - SVG path normally blocks where it draws (the dark part).
|
|
93
|
+
// - The 'hole' is empty, so touches pass through the hole to the app?
|
|
94
|
+
// - YES, with fillRule="evenodd", the hole effectively has no fill.
|
|
95
|
+
// - So if SVG is 'auto', touching the dark mask is blocked (if we consume touch).
|
|
96
|
+
// - Touching the hole goes through to the app (GOOD for clickable).
|
|
97
|
+
// - IF we want to BLOCK the hole (clickable=false):
|
|
98
|
+
// - We need a transparent view covering the hole that consumes touches.
|
|
99
|
+
//
|
|
100
|
+
// 2. preventInteraction = false (default):
|
|
101
|
+
// - Overlay shouldn't block anything?
|
|
102
|
+
// - pointerEvents='none' on the whole container.
|
|
103
|
+
|
|
104
|
+
const shouldBlockOutside = config?.preventInteraction ?? false;
|
|
105
|
+
|
|
106
|
+
// If we don't want to block outside, we just let everything pass.
|
|
107
|
+
// But wait, if we let everything pass, we can't implement 'clickable=false' strictness?
|
|
108
|
+
// Usually preventInteraction=false means "just show the highlighter, let user do whatever".
|
|
109
|
+
|
|
110
|
+
const containerPointerEvents =
|
|
111
|
+
shouldBlockOutside && currentStep ? 'box-none' : 'none';
|
|
112
|
+
|
|
113
|
+
// If blocking outside, the SVG (which is absolute fill) needs to catch touches on the dark part.
|
|
114
|
+
|
|
115
|
+
// Blocker style for the hole (only if NOT clickable)
|
|
116
|
+
const blockerStyle = useAnimatedStyle(() => {
|
|
117
|
+
return {
|
|
118
|
+
position: 'absolute',
|
|
119
|
+
left: targetX.value,
|
|
120
|
+
top: targetY.value,
|
|
121
|
+
width: targetWidth.value,
|
|
122
|
+
height: targetHeight.value,
|
|
123
|
+
// We can match radius too if needed, but rect is fine for touch area usually
|
|
124
|
+
borderRadius: targetRadius.value,
|
|
125
|
+
};
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
return (
|
|
129
|
+
<AnimatedView
|
|
130
|
+
pointerEvents={containerPointerEvents}
|
|
131
|
+
style={StyleSheet.absoluteFill}
|
|
132
|
+
>
|
|
133
|
+
<Svg height="100%" width="100%" style={StyleSheet.absoluteFill}>
|
|
134
|
+
<AnimatedPath
|
|
135
|
+
animatedProps={animatedProps as any}
|
|
136
|
+
fill="black" // The backdrop color
|
|
137
|
+
fillRule="evenodd"
|
|
138
|
+
onPress={() => {
|
|
139
|
+
// Consume touch on the backdrop?
|
|
140
|
+
}}
|
|
141
|
+
/>
|
|
142
|
+
</Svg>
|
|
143
|
+
{/* If strictly blocking interaction AND current step is NOT clickable, we cover the hole */}
|
|
144
|
+
{shouldBlockOutside && !isClickable && currentStep && (
|
|
145
|
+
<AnimatedView
|
|
146
|
+
style={blockerStyle}
|
|
147
|
+
pointerEvents="auto" // Catch touches
|
|
148
|
+
// backgroundColor="transparent" // Default
|
|
149
|
+
/>
|
|
150
|
+
)}
|
|
151
|
+
</AnimatedView>
|
|
152
|
+
);
|
|
153
|
+
});
|