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.
Files changed (50) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +231 -0
  3. package/lib/module/components/TourOverlay.js +134 -0
  4. package/lib/module/components/TourOverlay.js.map +1 -0
  5. package/lib/module/components/TourProvider.js +233 -0
  6. package/lib/module/components/TourProvider.js.map +1 -0
  7. package/lib/module/components/TourTooltip.js +233 -0
  8. package/lib/module/components/TourTooltip.js.map +1 -0
  9. package/lib/module/components/TourZone.js +246 -0
  10. package/lib/module/components/TourZone.js.map +1 -0
  11. package/lib/module/constants/animations.js +72 -0
  12. package/lib/module/constants/animations.js.map +1 -0
  13. package/lib/module/constants/defaults.js +14 -0
  14. package/lib/module/constants/defaults.js.map +1 -0
  15. package/lib/module/hooks/useTour.js +12 -0
  16. package/lib/module/hooks/useTour.js.map +1 -0
  17. package/lib/module/index.js +11 -0
  18. package/lib/module/index.js.map +1 -0
  19. package/lib/module/package.json +1 -0
  20. package/lib/module/types/index.js +4 -0
  21. package/lib/module/types/index.js.map +1 -0
  22. package/lib/typescript/package.json +1 -0
  23. package/lib/typescript/src/components/TourOverlay.d.ts +2 -0
  24. package/lib/typescript/src/components/TourOverlay.d.ts.map +1 -0
  25. package/lib/typescript/src/components/TourProvider.d.ts +21 -0
  26. package/lib/typescript/src/components/TourProvider.d.ts.map +1 -0
  27. package/lib/typescript/src/components/TourTooltip.d.ts +2 -0
  28. package/lib/typescript/src/components/TourTooltip.d.ts.map +1 -0
  29. package/lib/typescript/src/components/TourZone.d.ts +16 -0
  30. package/lib/typescript/src/components/TourZone.d.ts.map +1 -0
  31. package/lib/typescript/src/constants/animations.d.ts +34 -0
  32. package/lib/typescript/src/constants/animations.d.ts.map +1 -0
  33. package/lib/typescript/src/constants/defaults.d.ts +10 -0
  34. package/lib/typescript/src/constants/defaults.d.ts.map +1 -0
  35. package/lib/typescript/src/hooks/useTour.d.ts +2 -0
  36. package/lib/typescript/src/hooks/useTour.d.ts.map +1 -0
  37. package/lib/typescript/src/index.d.ts +9 -0
  38. package/lib/typescript/src/index.d.ts.map +1 -0
  39. package/lib/typescript/src/types/index.d.ts +135 -0
  40. package/lib/typescript/src/types/index.d.ts.map +1 -0
  41. package/package.json +171 -0
  42. package/src/components/TourOverlay.tsx +153 -0
  43. package/src/components/TourProvider.tsx +361 -0
  44. package/src/components/TourTooltip.tsx +252 -0
  45. package/src/components/TourZone.tsx +372 -0
  46. package/src/constants/animations.ts +71 -0
  47. package/src/constants/defaults.ts +15 -0
  48. package/src/hooks/useTour.ts +10 -0
  49. package/src/index.tsx +8 -0
  50. 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,2 @@
1
+ export declare const TourTooltip: import("react").MemoExoticComponent<() => import("react/jsx-runtime").JSX.Element | null>;
2
+ //# sourceMappingURL=TourTooltip.d.ts.map
@@ -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,2 @@
1
+ export declare const useTour: () => import("..").InternalTourContextType;
2
+ //# sourceMappingURL=useTour.d.ts.map
@@ -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
+ });