@tent-official/react-walkthrough 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/README.md ADDED
@@ -0,0 +1,174 @@
1
+ # @tent-official/react-walkthrough
2
+
3
+ Lightweight React walkthrough/tour component with auto-positioning, dependency chains, and smooth animations.
4
+
5
+ ## Features
6
+
7
+ - SVG-based spotlight overlay with smooth animated transitions
8
+ - Auto-positioning popover (top/bottom/left/right) with viewport detection
9
+ - Dependency chains — start a walkthrough only after another completes
10
+ - Customizable labels, colors, and layout
11
+ - Reset and replay walkthroughs without page refresh
12
+ - Portal-based rendering (works inside modals)
13
+ - Zero external dependencies (only React + styled-components as peer deps)
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ npm install @tent-official/react-walkthrough
19
+ # or
20
+ yarn add @tent-official/react-walkthrough
21
+ ```
22
+
23
+ ### Peer Dependencies
24
+
25
+ Make sure these are installed in your project:
26
+
27
+ ```bash
28
+ npm install react react-dom styled-components
29
+ ```
30
+
31
+ ## Quick Start
32
+
33
+ ```jsx
34
+ import { useWalkthrough, WalkthroughOverlay } from "@tent-official/react-walkthrough";
35
+
36
+ function App() {
37
+ useWalkthrough({
38
+ name: "intro-tour",
39
+ steps: [
40
+ {
41
+ el: "welcome-title",
42
+ title: "Welcome!",
43
+ description: [{ description: "This is the main title of your app." }],
44
+ },
45
+ {
46
+ el: "nav-menu",
47
+ title: "Navigation",
48
+ description: [{ description: "Use this menu to navigate around." }],
49
+ position: "right",
50
+ },
51
+ ],
52
+ });
53
+
54
+ return (
55
+ <div>
56
+ <h1 id="welcome-title">My App</h1>
57
+ <nav id="nav-menu">...</nav>
58
+ <WalkthroughOverlay />
59
+ </div>
60
+ );
61
+ }
62
+ ```
63
+
64
+ ## API
65
+
66
+ ### `useWalkthrough(options)`
67
+
68
+ Hook to register a walkthrough tour.
69
+
70
+ | Option | Type | Default | Description |
71
+ | --- | --- | --- | --- |
72
+ | `name` | `string` | **required** | Unique name for this walkthrough |
73
+ | `steps` | `WalkthroughStep[]` | **required** | Array of steps |
74
+ | `storageKey` | `string` | `""` | Storage key prefix for localStorage |
75
+ | `dependsOn` | `string[]` | `[]` | Walkthrough names that must complete first |
76
+ | `onWalkthroughComplete` | `(name: string) => void` | — | Callback when walkthrough completes |
77
+ | `isShowSkip` | `boolean` | `true` | Show skip button |
78
+ | `isShowPrev` | `boolean` | `true` | Show back button |
79
+ | `nextLabel` | `string` | `"Next →"` | Next button label |
80
+ | `prevLabel` | `string` | `"Back"` | Previous button label |
81
+ | `skipLabel` | `string` | `"Skip"` | Skip button label |
82
+ | `doneLabel` | `string` | `"Done ✓"` | Done button label (last step) |
83
+ | `nextColor` | `string` | — | Custom next button color |
84
+ | `prevColor` | `string` | — | Custom previous button color |
85
+ | `skipColor` | `string` | — | Custom skip button color |
86
+
87
+ **Returns:** `{ start: () => void }`
88
+
89
+ ### `WalkthroughStep`
90
+
91
+ | Property | Type | Default | Description |
92
+ | --- | --- | --- | --- |
93
+ | `el` | `string` | **required** | DOM element ID to highlight |
94
+ | `title` | `string` | — | Popover title |
95
+ | `description` | `StepDescription[]` | **required** | Description blocks |
96
+ | `position` | `"top" \| "bottom" \| "left" \| "right"` | auto | Preferred popover position |
97
+ | `padding` | `number` | `8` | Padding around highlighted element (px) |
98
+ | `borderRadius` | `number` | `10` | Border radius of highlight cutout (px) |
99
+ | `width` | `number \| string` | `"auto"` | Popover width |
100
+ | `height` | `number \| string` | — | Popover height |
101
+ | `isTriggerEl` | `boolean` | `false` | Click the target element when "Next" is pressed |
102
+
103
+ ### `StepDescription`
104
+
105
+ | Property | Type | Description |
106
+ | --- | --- | --- |
107
+ | `title` | `string` | Optional label for this block |
108
+ | `description` | `ReactNode` | Description content |
109
+ | `direction` | `"row" \| "column"` | Layout direction |
110
+
111
+ ### `<WalkthroughOverlay />`
112
+
113
+ Place this component once at the root of your app. It renders via React Portal into `document.body`.
114
+
115
+ | Prop | Type | Default | Description |
116
+ | --- | --- | --- | --- |
117
+ | `$popoverPadding` | `number` | `12` | Inner padding of popover (px) |
118
+ | `$popoverBorderRadius` | `number` | `8` | Border radius of popover (px) |
119
+ | `$popoverGap` | `number` | `12` | Gap between highlight and popover (px) |
120
+ | `$fontFamily` | `string` | system default | Font family for popover text |
121
+ | `$animationSpeed` | `number` | `350` | Highlight transition speed (ms) |
122
+
123
+ ### `resetWalkthrough(options?)`
124
+
125
+ Reset walkthroughs so they can be replayed without page refresh.
126
+
127
+ ```js
128
+ import { resetWalkthrough } from "@tent-official/react-walkthrough";
129
+
130
+ resetWalkthrough({
131
+ storageKey: "my-app",
132
+ walkthroughList: ["intro-tour", "feature-tour"],
133
+ });
134
+ ```
135
+
136
+ | Option | Type | Default | Description |
137
+ | --- | --- | --- | --- |
138
+ | `storageKey` | `string` | `""` | Storage key prefix |
139
+ | `walkthroughList` | `string[]` | `[]` | Names of walkthroughs to reset |
140
+
141
+ ## Dependency Chains
142
+
143
+ You can create sequential walkthroughs using `dependsOn`:
144
+
145
+ ```jsx
146
+ // This runs first
147
+ useWalkthrough({
148
+ name: "intro-tour",
149
+ storageKey: "my-app",
150
+ steps: [/* ... */],
151
+ });
152
+
153
+ // This starts automatically after intro-tour completes
154
+ useWalkthrough({
155
+ name: "advanced-tour",
156
+ storageKey: "my-app",
157
+ dependsOn: ["intro-tour"],
158
+ steps: [/* ... */],
159
+ });
160
+ ```
161
+
162
+ ## Auto-Positioning
163
+
164
+ The popover automatically positions itself to stay within the viewport:
165
+
166
+ 1. If `position` is specified, it tries that position first
167
+ 2. If it doesn't fit, it falls back to: bottom → top → right → left
168
+ 3. If nothing fits perfectly, it picks the direction with the most available space
169
+
170
+ The popover also waits for the target element to be scrolled into view before appearing.
171
+
172
+ ## License
173
+
174
+ MIT
@@ -0,0 +1,124 @@
1
+ import { ReactNode, ReactPortal } from 'react';
2
+
3
+ /**
4
+ * Position of the popover relative to the target element.
5
+ * If the preferred position doesn't fit in the viewport, it will auto-fallback.
6
+ */
7
+ type PopoverPosition = "top" | "bottom" | "left" | "right";
8
+ /**
9
+ * Direction for description block layout.
10
+ */
11
+ type DescriptionDirection = "row" | "column";
12
+ /**
13
+ * A single description block within a step.
14
+ */
15
+ interface StepDescription {
16
+ /** Optional title for this description block */
17
+ title?: string;
18
+ /** Description text or React node */
19
+ description: ReactNode;
20
+ /** Layout direction for this block */
21
+ direction?: DescriptionDirection;
22
+ }
23
+ /**
24
+ * A single step in a walkthrough tour.
25
+ */
26
+ interface WalkthroughStep {
27
+ /** The DOM element ID to highlight */
28
+ el: string;
29
+ /** Title displayed at the top of the popover */
30
+ title?: string;
31
+ /** Array of description blocks */
32
+ description: StepDescription[];
33
+ /** Preferred popover position. Auto-positioned if omitted or if preferred doesn't fit */
34
+ position?: PopoverPosition;
35
+ /** Padding around the highlighted element (px). Default: 8 */
36
+ padding?: number;
37
+ /** Border radius of the highlight cutout (px). Default: 10 */
38
+ borderRadius?: number;
39
+ /** Popover width (px or "auto"). Default: "auto" */
40
+ width?: number | string;
41
+ /** Popover height (px or "auto"). Default: auto */
42
+ height?: number | string;
43
+ /** If true, clicking "Next" will also trigger a click on the target element */
44
+ isTriggerEl?: boolean;
45
+ }
46
+ /**
47
+ * Options for the useWalkthrough hook.
48
+ */
49
+ interface UseWalkthroughOptions {
50
+ /** Unique name for this walkthrough */
51
+ name: string;
52
+ /** Storage key prefix for localStorage. Walkthroughs sharing the same key share completion state */
53
+ storageKey?: string;
54
+ /** List of walkthrough names that must complete before this one starts */
55
+ dependsOn?: string[];
56
+ /** Array of steps for this walkthrough */
57
+ steps: WalkthroughStep[];
58
+ /** Callback fired when the walkthrough completes (either finished or skipped) */
59
+ onWalkthroughComplete?: (name: string) => void;
60
+ /** Show the skip button. Default: true */
61
+ isShowSkip?: boolean;
62
+ /** Show the back/previous button. Default: true */
63
+ isShowPrev?: boolean;
64
+ /** Label for the next button. Default: "Next →" */
65
+ nextLabel?: string;
66
+ /** Label for the previous button. Default: "Back" */
67
+ prevLabel?: string;
68
+ /** Label for the skip button. Default: "Skip" */
69
+ skipLabel?: string;
70
+ /** Label for the done button (last step). Default: "Done ✓" */
71
+ doneLabel?: string;
72
+ /** Custom color for the next button */
73
+ nextColor?: string;
74
+ /** Custom color for the previous button */
75
+ prevColor?: string;
76
+ /** Custom color for the skip button */
77
+ skipColor?: string;
78
+ }
79
+ /**
80
+ * Return value of the useWalkthrough hook.
81
+ */
82
+ interface UseWalkthroughReturn {
83
+ /** Manually start the walkthrough (respects isDone and dependsOn checks) */
84
+ start: () => void;
85
+ }
86
+ /**
87
+ * Props for the WalkthroughOverlay component.
88
+ */
89
+ interface WalkthroughOverlayProps {
90
+ /** Inner padding of the popover (px). Default: 12 */
91
+ $popoverPadding?: number;
92
+ /** Border radius of the popover (px). Default: 8 */
93
+ $popoverBorderRadius?: number;
94
+ /** Gap between the highlight and the popover (px). Default: 12 */
95
+ $popoverGap?: number;
96
+ /** Font family for the popover text */
97
+ $fontFamily?: string;
98
+ /** Animation speed for highlight transitions (ms). Default: 350 */
99
+ $animationSpeed?: number;
100
+ }
101
+ /**
102
+ * Options for the resetWalkthrough function.
103
+ */
104
+ interface ResetWalkthroughOptions {
105
+ /** Storage key prefix matching the one used in useWalkthrough. Default: "" */
106
+ storageKey?: string;
107
+ /** List of walkthrough names to reset */
108
+ walkthroughList?: string[];
109
+ }
110
+ /**
111
+ * Reset specified walkthroughs so they can be replayed without page refresh.
112
+ */
113
+ declare function resetWalkthrough(options?: ResetWalkthroughOptions): void;
114
+ /**
115
+ * Hook to register and control a walkthrough tour.
116
+ */
117
+ declare function useWalkthrough(options: UseWalkthroughOptions): UseWalkthroughReturn;
118
+ /**
119
+ * Overlay component that renders the walkthrough spotlight, popover, and controls.
120
+ * Place this once at the root of your app.
121
+ */
122
+ declare function WalkthroughOverlay(props?: WalkthroughOverlayProps): ReactPortal | null;
123
+
124
+ export { type DescriptionDirection, type PopoverPosition, type ResetWalkthroughOptions, type StepDescription, type UseWalkthroughOptions, type UseWalkthroughReturn, WalkthroughOverlay, type WalkthroughOverlayProps, type WalkthroughStep, resetWalkthrough, useWalkthrough };
@@ -0,0 +1,124 @@
1
+ import { ReactNode, ReactPortal } from 'react';
2
+
3
+ /**
4
+ * Position of the popover relative to the target element.
5
+ * If the preferred position doesn't fit in the viewport, it will auto-fallback.
6
+ */
7
+ type PopoverPosition = "top" | "bottom" | "left" | "right";
8
+ /**
9
+ * Direction for description block layout.
10
+ */
11
+ type DescriptionDirection = "row" | "column";
12
+ /**
13
+ * A single description block within a step.
14
+ */
15
+ interface StepDescription {
16
+ /** Optional title for this description block */
17
+ title?: string;
18
+ /** Description text or React node */
19
+ description: ReactNode;
20
+ /** Layout direction for this block */
21
+ direction?: DescriptionDirection;
22
+ }
23
+ /**
24
+ * A single step in a walkthrough tour.
25
+ */
26
+ interface WalkthroughStep {
27
+ /** The DOM element ID to highlight */
28
+ el: string;
29
+ /** Title displayed at the top of the popover */
30
+ title?: string;
31
+ /** Array of description blocks */
32
+ description: StepDescription[];
33
+ /** Preferred popover position. Auto-positioned if omitted or if preferred doesn't fit */
34
+ position?: PopoverPosition;
35
+ /** Padding around the highlighted element (px). Default: 8 */
36
+ padding?: number;
37
+ /** Border radius of the highlight cutout (px). Default: 10 */
38
+ borderRadius?: number;
39
+ /** Popover width (px or "auto"). Default: "auto" */
40
+ width?: number | string;
41
+ /** Popover height (px or "auto"). Default: auto */
42
+ height?: number | string;
43
+ /** If true, clicking "Next" will also trigger a click on the target element */
44
+ isTriggerEl?: boolean;
45
+ }
46
+ /**
47
+ * Options for the useWalkthrough hook.
48
+ */
49
+ interface UseWalkthroughOptions {
50
+ /** Unique name for this walkthrough */
51
+ name: string;
52
+ /** Storage key prefix for localStorage. Walkthroughs sharing the same key share completion state */
53
+ storageKey?: string;
54
+ /** List of walkthrough names that must complete before this one starts */
55
+ dependsOn?: string[];
56
+ /** Array of steps for this walkthrough */
57
+ steps: WalkthroughStep[];
58
+ /** Callback fired when the walkthrough completes (either finished or skipped) */
59
+ onWalkthroughComplete?: (name: string) => void;
60
+ /** Show the skip button. Default: true */
61
+ isShowSkip?: boolean;
62
+ /** Show the back/previous button. Default: true */
63
+ isShowPrev?: boolean;
64
+ /** Label for the next button. Default: "Next →" */
65
+ nextLabel?: string;
66
+ /** Label for the previous button. Default: "Back" */
67
+ prevLabel?: string;
68
+ /** Label for the skip button. Default: "Skip" */
69
+ skipLabel?: string;
70
+ /** Label for the done button (last step). Default: "Done ✓" */
71
+ doneLabel?: string;
72
+ /** Custom color for the next button */
73
+ nextColor?: string;
74
+ /** Custom color for the previous button */
75
+ prevColor?: string;
76
+ /** Custom color for the skip button */
77
+ skipColor?: string;
78
+ }
79
+ /**
80
+ * Return value of the useWalkthrough hook.
81
+ */
82
+ interface UseWalkthroughReturn {
83
+ /** Manually start the walkthrough (respects isDone and dependsOn checks) */
84
+ start: () => void;
85
+ }
86
+ /**
87
+ * Props for the WalkthroughOverlay component.
88
+ */
89
+ interface WalkthroughOverlayProps {
90
+ /** Inner padding of the popover (px). Default: 12 */
91
+ $popoverPadding?: number;
92
+ /** Border radius of the popover (px). Default: 8 */
93
+ $popoverBorderRadius?: number;
94
+ /** Gap between the highlight and the popover (px). Default: 12 */
95
+ $popoverGap?: number;
96
+ /** Font family for the popover text */
97
+ $fontFamily?: string;
98
+ /** Animation speed for highlight transitions (ms). Default: 350 */
99
+ $animationSpeed?: number;
100
+ }
101
+ /**
102
+ * Options for the resetWalkthrough function.
103
+ */
104
+ interface ResetWalkthroughOptions {
105
+ /** Storage key prefix matching the one used in useWalkthrough. Default: "" */
106
+ storageKey?: string;
107
+ /** List of walkthrough names to reset */
108
+ walkthroughList?: string[];
109
+ }
110
+ /**
111
+ * Reset specified walkthroughs so they can be replayed without page refresh.
112
+ */
113
+ declare function resetWalkthrough(options?: ResetWalkthroughOptions): void;
114
+ /**
115
+ * Hook to register and control a walkthrough tour.
116
+ */
117
+ declare function useWalkthrough(options: UseWalkthroughOptions): UseWalkthroughReturn;
118
+ /**
119
+ * Overlay component that renders the walkthrough spotlight, popover, and controls.
120
+ * Place this once at the root of your app.
121
+ */
122
+ declare function WalkthroughOverlay(props?: WalkthroughOverlayProps): ReactPortal | null;
123
+
124
+ export { type DescriptionDirection, type PopoverPosition, type ResetWalkthroughOptions, type StepDescription, type UseWalkthroughOptions, type UseWalkthroughReturn, WalkthroughOverlay, type WalkthroughOverlayProps, type WalkthroughStep, resetWalkthrough, useWalkthrough };