ontheway-sdk 0.1.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 +110 -0
- package/dist/checklist.cjs +319 -0
- package/dist/checklist.cjs.map +1 -0
- package/dist/checklist.d.cts +58 -0
- package/dist/checklist.d.ts +58 -0
- package/dist/checklist.js +314 -0
- package/dist/checklist.js.map +1 -0
- package/dist/chunk-254YHUN3.cjs +26 -0
- package/dist/chunk-254YHUN3.cjs.map +1 -0
- package/dist/chunk-DDAAVRWG.js +23 -0
- package/dist/chunk-DDAAVRWG.js.map +1 -0
- package/dist/chunk-NRUQU5AR.cjs +94 -0
- package/dist/chunk-NRUQU5AR.cjs.map +1 -0
- package/dist/chunk-OKJ5GEH3.js +358 -0
- package/dist/chunk-OKJ5GEH3.js.map +1 -0
- package/dist/chunk-RNQLNLNI.js +91 -0
- package/dist/chunk-RNQLNLNI.js.map +1 -0
- package/dist/chunk-UE3T6TSM.cjs +361 -0
- package/dist/chunk-UE3T6TSM.cjs.map +1 -0
- package/dist/components.cjs +211 -0
- package/dist/components.cjs.map +1 -0
- package/dist/components.d.cts +51 -0
- package/dist/components.d.ts +51 -0
- package/dist/components.js +205 -0
- package/dist/components.js.map +1 -0
- package/dist/devtools.cjs +733 -0
- package/dist/devtools.cjs.map +1 -0
- package/dist/devtools.d.cts +18 -0
- package/dist/devtools.d.ts +18 -0
- package/dist/devtools.js +727 -0
- package/dist/devtools.js.map +1 -0
- package/dist/index.cjs +19 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +163 -0
- package/dist/index.d.ts +163 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/react.cjs +18 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +68 -0
- package/dist/react.d.ts +68 -0
- package/dist/react.js +5 -0
- package/dist/react.js.map +1 -0
- package/package.json +93 -0
package/README.md
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# @ontheway/sdk
|
|
2
|
+
|
|
3
|
+
Lightweight onboarding SDK based on [Driver.js](https://driverjs.com/). Create interactive product tours and onboarding flows.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @ontheway/sdk driver.js
|
|
9
|
+
# or
|
|
10
|
+
pnpm add @ontheway/sdk driver.js
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
> **Note:** `driver.js` is a peer dependency. The SDK automatically injects Driver.js CSS from CDN at runtime. To disable this behavior, pass `driverCssUrl: false` and import the CSS yourself.
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
### Vanilla JavaScript / TypeScript
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { OnTheWay } from '@ontheway/sdk'
|
|
21
|
+
|
|
22
|
+
const otw = new OnTheWay({
|
|
23
|
+
projectId: 'YOUR_PROJECT_ID',
|
|
24
|
+
apiUrl: 'https://your-api.com/api',
|
|
25
|
+
onComplete: (taskId) => console.log('Completed:', taskId),
|
|
26
|
+
onSkip: (taskId, stepIndex) => console.log('Skipped:', taskId, 'at step', stepIndex),
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
// Start a specific tour
|
|
30
|
+
otw.start('welcome-tour')
|
|
31
|
+
|
|
32
|
+
// Reset a task
|
|
33
|
+
otw.reset('welcome-tour')
|
|
34
|
+
|
|
35
|
+
// Reset all tasks
|
|
36
|
+
otw.resetAll()
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### React
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
import { OnTheWayProvider, useOnTheWay } from '@ontheway/sdk/react'
|
|
43
|
+
|
|
44
|
+
function App() {
|
|
45
|
+
return (
|
|
46
|
+
<OnTheWayProvider projectId="YOUR_PROJECT_ID">
|
|
47
|
+
<YourApp />
|
|
48
|
+
</OnTheWayProvider>
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function HelpButton() {
|
|
53
|
+
const { start, ready } = useOnTheWay()
|
|
54
|
+
return (
|
|
55
|
+
<button onClick={() => start('welcome-tour')} disabled={!ready}>
|
|
56
|
+
Show Tour
|
|
57
|
+
</button>
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Components
|
|
63
|
+
|
|
64
|
+
```tsx
|
|
65
|
+
import { HelpMenu, HelpTrigger } from '@ontheway/sdk/components'
|
|
66
|
+
|
|
67
|
+
// Floating help menu with all available tours
|
|
68
|
+
<HelpMenu position="bottom-right" />
|
|
69
|
+
|
|
70
|
+
// Inline trigger for a specific tour
|
|
71
|
+
<HelpTrigger taskSlug="welcome-tour">
|
|
72
|
+
<button>Need help?</button>
|
|
73
|
+
</HelpTrigger>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### DevTools (Development Only)
|
|
77
|
+
|
|
78
|
+
```tsx
|
|
79
|
+
import { OnTheWayDevToolsPanel } from '@ontheway/sdk/devtools'
|
|
80
|
+
|
|
81
|
+
// Add to your app root in development
|
|
82
|
+
{process.env.NODE_ENV === 'development' && (
|
|
83
|
+
<OnTheWayDevToolsPanel
|
|
84
|
+
projectId="YOUR_PROJECT_ID"
|
|
85
|
+
apiKey="otw_YOUR_API_KEY"
|
|
86
|
+
/>
|
|
87
|
+
)}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Configuration
|
|
91
|
+
|
|
92
|
+
| Option | Type | Default | Description |
|
|
93
|
+
|--------|------|---------|-------------|
|
|
94
|
+
| `projectId` | `string` | — | **Required.** Your project ID |
|
|
95
|
+
| `apiUrl` | `string` | `'/api'` | API base URL |
|
|
96
|
+
| `driverCssUrl` | `string \| false` | CDN URL | Custom CSS URL, or `false` to disable auto-injection |
|
|
97
|
+
| `onComplete` | `(taskId: string) => void` | — | Callback when a task is completed |
|
|
98
|
+
| `onSkip` | `(taskId: string, stepIndex: number) => void` | — | Callback when a task is skipped |
|
|
99
|
+
|
|
100
|
+
## Driver.js CSS
|
|
101
|
+
|
|
102
|
+
By default, the SDK injects the Driver.js CSS from CDN at runtime. You can:
|
|
103
|
+
|
|
104
|
+
1. **Let it auto-inject** (default behavior, no action needed)
|
|
105
|
+
2. **Provide a custom URL**: `new OnTheWay({ projectId: '...', driverCssUrl: 'https://...' })`
|
|
106
|
+
3. **Disable and import manually**: `new OnTheWay({ projectId: '...', driverCssUrl: false })` then add `import 'driver.js/dist/driver.css'` yourself
|
|
107
|
+
|
|
108
|
+
## License
|
|
109
|
+
|
|
110
|
+
MIT
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var chunkNRUQU5AR_cjs = require('./chunk-NRUQU5AR.cjs');
|
|
6
|
+
require('./chunk-UE3T6TSM.cjs');
|
|
7
|
+
var chunk254YHUN3_cjs = require('./chunk-254YHUN3.cjs');
|
|
8
|
+
var react = require('react');
|
|
9
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
10
|
+
|
|
11
|
+
var STORAGE_KEY_PREFIX = "otw_checklist_";
|
|
12
|
+
function getCompletedSlugs(projectId) {
|
|
13
|
+
if (typeof localStorage === "undefined") return /* @__PURE__ */ new Set();
|
|
14
|
+
try {
|
|
15
|
+
const raw = localStorage.getItem(STORAGE_KEY_PREFIX + projectId);
|
|
16
|
+
if (raw) return new Set(JSON.parse(raw));
|
|
17
|
+
} catch (e) {
|
|
18
|
+
}
|
|
19
|
+
return /* @__PURE__ */ new Set();
|
|
20
|
+
}
|
|
21
|
+
function saveCompletedSlugs(projectId, slugs) {
|
|
22
|
+
if (typeof localStorage === "undefined") return;
|
|
23
|
+
localStorage.setItem(STORAGE_KEY_PREFIX + projectId, JSON.stringify([...slugs]));
|
|
24
|
+
}
|
|
25
|
+
function OnTheWayChecklist({
|
|
26
|
+
tasks,
|
|
27
|
+
title = "Getting Started",
|
|
28
|
+
position = "bottom-right",
|
|
29
|
+
onAllComplete,
|
|
30
|
+
autoHide = true,
|
|
31
|
+
autoHideDelay = 4e3
|
|
32
|
+
}) {
|
|
33
|
+
var _a;
|
|
34
|
+
const { otw, ready, start, isTaskCompleted } = chunkNRUQU5AR_cjs.useOnTheWay();
|
|
35
|
+
const [expanded, setExpanded] = react.useState(true);
|
|
36
|
+
const [completedSlugs, setCompletedSlugs] = react.useState(/* @__PURE__ */ new Set());
|
|
37
|
+
const [hidden, setHidden] = react.useState(false);
|
|
38
|
+
const [celebrating, setCelebrating] = react.useState(false);
|
|
39
|
+
const allCompleteFired = react.useRef(false);
|
|
40
|
+
const projectId = (_a = otw == null ? void 0 : otw.getProjectId()) != null ? _a : "default";
|
|
41
|
+
react.useEffect(() => {
|
|
42
|
+
const stored = getCompletedSlugs(projectId);
|
|
43
|
+
if (stored.size > 0) setCompletedSlugs(stored);
|
|
44
|
+
}, [projectId]);
|
|
45
|
+
react.useEffect(() => {
|
|
46
|
+
if (!ready || !otw) return;
|
|
47
|
+
const interval = setInterval(() => {
|
|
48
|
+
let changed = false;
|
|
49
|
+
const next = new Set(completedSlugs);
|
|
50
|
+
for (const task of tasks) {
|
|
51
|
+
if (!next.has(task.slug) && isTaskCompleted(task.slug)) {
|
|
52
|
+
next.add(task.slug);
|
|
53
|
+
changed = true;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (changed) {
|
|
57
|
+
setCompletedSlugs(next);
|
|
58
|
+
saveCompletedSlugs(projectId, next);
|
|
59
|
+
}
|
|
60
|
+
}, 500);
|
|
61
|
+
return () => clearInterval(interval);
|
|
62
|
+
}, [ready, otw, tasks, completedSlugs, isTaskCompleted, projectId]);
|
|
63
|
+
const requiredTasks = tasks.filter((t) => t.required !== false);
|
|
64
|
+
const allDone = requiredTasks.length > 0 && requiredTasks.every((t) => completedSlugs.has(t.slug));
|
|
65
|
+
const completedCount = tasks.filter((t) => completedSlugs.has(t.slug)).length;
|
|
66
|
+
const progress = tasks.length > 0 ? Math.round(completedCount / tasks.length * 100) : 0;
|
|
67
|
+
react.useEffect(() => {
|
|
68
|
+
if (allDone && !allCompleteFired.current) {
|
|
69
|
+
allCompleteFired.current = true;
|
|
70
|
+
setCelebrating(true);
|
|
71
|
+
onAllComplete == null ? void 0 : onAllComplete();
|
|
72
|
+
if (autoHide) {
|
|
73
|
+
const timer = setTimeout(() => setHidden(true), autoHideDelay);
|
|
74
|
+
return () => clearTimeout(timer);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}, [allDone, onAllComplete, autoHide, autoHideDelay]);
|
|
78
|
+
const handleTaskClick = react.useCallback(
|
|
79
|
+
(slug) => {
|
|
80
|
+
if (completedSlugs.has(slug)) return;
|
|
81
|
+
start(slug);
|
|
82
|
+
},
|
|
83
|
+
[completedSlugs, start]
|
|
84
|
+
);
|
|
85
|
+
if (hidden) return null;
|
|
86
|
+
const isRight = position === "bottom-right";
|
|
87
|
+
const containerStyle = chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({
|
|
88
|
+
position: "fixed",
|
|
89
|
+
bottom: 24
|
|
90
|
+
}, isRight ? { right: 24 } : { left: 24 }), {
|
|
91
|
+
zIndex: 2147483640,
|
|
92
|
+
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
93
|
+
fontSize: 13,
|
|
94
|
+
width: expanded ? 320 : "auto"
|
|
95
|
+
});
|
|
96
|
+
const cardStyle = {
|
|
97
|
+
background: "#fff",
|
|
98
|
+
borderRadius: 12,
|
|
99
|
+
boxShadow: "0 8px 32px rgba(0,0,0,0.15)",
|
|
100
|
+
border: "1px solid #e5e7eb",
|
|
101
|
+
overflow: "hidden"
|
|
102
|
+
};
|
|
103
|
+
const headerStyle = {
|
|
104
|
+
display: "flex",
|
|
105
|
+
alignItems: "center",
|
|
106
|
+
justifyContent: "space-between",
|
|
107
|
+
padding: "12px 16px",
|
|
108
|
+
cursor: "pointer",
|
|
109
|
+
userSelect: "none",
|
|
110
|
+
background: celebrating ? "#f0fdf4" : "#fff",
|
|
111
|
+
borderBottom: expanded ? "1px solid #f3f4f6" : "none"
|
|
112
|
+
};
|
|
113
|
+
const progressBarBg = {
|
|
114
|
+
height: 4,
|
|
115
|
+
background: "#f3f4f6",
|
|
116
|
+
borderRadius: 2,
|
|
117
|
+
overflow: "hidden",
|
|
118
|
+
marginTop: 8
|
|
119
|
+
};
|
|
120
|
+
const progressBarFill = {
|
|
121
|
+
height: "100%",
|
|
122
|
+
width: `${progress}%`,
|
|
123
|
+
background: allDone ? "#22c55e" : "#3b82f6",
|
|
124
|
+
borderRadius: 2,
|
|
125
|
+
transition: "width 0.4s ease"
|
|
126
|
+
};
|
|
127
|
+
const taskItemStyle = (done) => ({
|
|
128
|
+
display: "flex",
|
|
129
|
+
alignItems: "flex-start",
|
|
130
|
+
gap: 10,
|
|
131
|
+
padding: "10px 16px",
|
|
132
|
+
cursor: done ? "default" : "pointer",
|
|
133
|
+
borderBottom: "1px solid #f9fafb",
|
|
134
|
+
opacity: done ? 0.6 : 1,
|
|
135
|
+
transition: "background 0.15s"
|
|
136
|
+
});
|
|
137
|
+
const checkboxStyle = (done) => ({
|
|
138
|
+
width: 18,
|
|
139
|
+
height: 18,
|
|
140
|
+
borderRadius: 4,
|
|
141
|
+
border: done ? "2px solid #22c55e" : "2px solid #d1d5db",
|
|
142
|
+
background: done ? "#22c55e" : "#fff",
|
|
143
|
+
display: "flex",
|
|
144
|
+
alignItems: "center",
|
|
145
|
+
justifyContent: "center",
|
|
146
|
+
flexShrink: 0,
|
|
147
|
+
marginTop: 1,
|
|
148
|
+
transition: "all 0.2s",
|
|
149
|
+
color: "#fff",
|
|
150
|
+
fontSize: 11,
|
|
151
|
+
fontWeight: 700
|
|
152
|
+
});
|
|
153
|
+
if (!expanded) {
|
|
154
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { style: containerStyle, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
155
|
+
"button",
|
|
156
|
+
{
|
|
157
|
+
onClick: () => setExpanded(true),
|
|
158
|
+
style: {
|
|
159
|
+
display: "flex",
|
|
160
|
+
alignItems: "center",
|
|
161
|
+
gap: 8,
|
|
162
|
+
padding: "10px 16px",
|
|
163
|
+
background: celebrating ? "#22c55e" : "#111",
|
|
164
|
+
color: "#fff",
|
|
165
|
+
border: "none",
|
|
166
|
+
borderRadius: 24,
|
|
167
|
+
cursor: "pointer",
|
|
168
|
+
fontSize: 13,
|
|
169
|
+
fontWeight: 600,
|
|
170
|
+
boxShadow: "0 4px 14px rgba(0,0,0,0.2)"
|
|
171
|
+
},
|
|
172
|
+
children: [
|
|
173
|
+
celebrating ? "\u{1F389}" : "\u{1F4CB}",
|
|
174
|
+
" ",
|
|
175
|
+
title,
|
|
176
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
177
|
+
"span",
|
|
178
|
+
{
|
|
179
|
+
style: {
|
|
180
|
+
background: "rgba(255,255,255,0.2)",
|
|
181
|
+
padding: "2px 8px",
|
|
182
|
+
borderRadius: 12,
|
|
183
|
+
fontSize: 11
|
|
184
|
+
},
|
|
185
|
+
children: [
|
|
186
|
+
completedCount,
|
|
187
|
+
"/",
|
|
188
|
+
tasks.length
|
|
189
|
+
]
|
|
190
|
+
}
|
|
191
|
+
)
|
|
192
|
+
]
|
|
193
|
+
}
|
|
194
|
+
) });
|
|
195
|
+
}
|
|
196
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { style: containerStyle, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: cardStyle, children: [
|
|
197
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: headerStyle, onClick: () => setExpanded(false), children: [
|
|
198
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flex: 1 }, children: [
|
|
199
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
200
|
+
"div",
|
|
201
|
+
{
|
|
202
|
+
style: {
|
|
203
|
+
fontWeight: 600,
|
|
204
|
+
fontSize: 14,
|
|
205
|
+
color: "#111",
|
|
206
|
+
display: "flex",
|
|
207
|
+
alignItems: "center",
|
|
208
|
+
gap: 6
|
|
209
|
+
},
|
|
210
|
+
children: [
|
|
211
|
+
celebrating ? "\u{1F389}" : "\u{1F4CB}",
|
|
212
|
+
" ",
|
|
213
|
+
title
|
|
214
|
+
]
|
|
215
|
+
}
|
|
216
|
+
),
|
|
217
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: progressBarBg, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: progressBarFill }) }),
|
|
218
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: 11, color: "#9ca3af", marginTop: 4 }, children: [
|
|
219
|
+
completedCount,
|
|
220
|
+
" of ",
|
|
221
|
+
tasks.length,
|
|
222
|
+
" complete"
|
|
223
|
+
] })
|
|
224
|
+
] }),
|
|
225
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
226
|
+
"span",
|
|
227
|
+
{
|
|
228
|
+
style: {
|
|
229
|
+
color: "#9ca3af",
|
|
230
|
+
fontSize: 18,
|
|
231
|
+
marginLeft: 8,
|
|
232
|
+
transition: "transform 0.2s",
|
|
233
|
+
transform: "rotate(0deg)"
|
|
234
|
+
},
|
|
235
|
+
children: "\u25BE"
|
|
236
|
+
}
|
|
237
|
+
)
|
|
238
|
+
] }),
|
|
239
|
+
celebrating && /* @__PURE__ */ jsxRuntime.jsx(
|
|
240
|
+
"div",
|
|
241
|
+
{
|
|
242
|
+
style: {
|
|
243
|
+
padding: "12px 16px",
|
|
244
|
+
background: "#f0fdf4",
|
|
245
|
+
borderBottom: "1px solid #dcfce7",
|
|
246
|
+
textAlign: "center",
|
|
247
|
+
fontSize: 13,
|
|
248
|
+
color: "#15803d",
|
|
249
|
+
fontWeight: 500
|
|
250
|
+
},
|
|
251
|
+
children: "\u{1F389} All done! You're all set."
|
|
252
|
+
}
|
|
253
|
+
),
|
|
254
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { maxHeight: 320, overflowY: "auto" }, children: tasks.map((task) => {
|
|
255
|
+
const done = completedSlugs.has(task.slug);
|
|
256
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
257
|
+
"div",
|
|
258
|
+
{
|
|
259
|
+
style: taskItemStyle(done),
|
|
260
|
+
onClick: () => handleTaskClick(task.slug),
|
|
261
|
+
onMouseEnter: (e) => {
|
|
262
|
+
if (!done) e.currentTarget.style.background = "#f9fafb";
|
|
263
|
+
},
|
|
264
|
+
onMouseLeave: (e) => {
|
|
265
|
+
e.currentTarget.style.background = "";
|
|
266
|
+
},
|
|
267
|
+
role: "button",
|
|
268
|
+
tabIndex: 0,
|
|
269
|
+
onKeyDown: (e) => {
|
|
270
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
271
|
+
e.preventDefault();
|
|
272
|
+
handleTaskClick(task.slug);
|
|
273
|
+
}
|
|
274
|
+
},
|
|
275
|
+
children: [
|
|
276
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: checkboxStyle(done), children: done ? "\u2713" : "" }),
|
|
277
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
278
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
279
|
+
"div",
|
|
280
|
+
{
|
|
281
|
+
style: {
|
|
282
|
+
fontWeight: 500,
|
|
283
|
+
fontSize: 13,
|
|
284
|
+
color: done ? "#9ca3af" : "#374151",
|
|
285
|
+
textDecoration: done ? "line-through" : "none"
|
|
286
|
+
},
|
|
287
|
+
children: [
|
|
288
|
+
task.title,
|
|
289
|
+
task.required === false && /* @__PURE__ */ jsxRuntime.jsx(
|
|
290
|
+
"span",
|
|
291
|
+
{
|
|
292
|
+
style: {
|
|
293
|
+
fontSize: 10,
|
|
294
|
+
color: "#9ca3af",
|
|
295
|
+
marginLeft: 6,
|
|
296
|
+
fontWeight: 400
|
|
297
|
+
},
|
|
298
|
+
children: "optional"
|
|
299
|
+
}
|
|
300
|
+
)
|
|
301
|
+
]
|
|
302
|
+
}
|
|
303
|
+
),
|
|
304
|
+
task.description && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 11, color: "#9ca3af", marginTop: 2 }, children: task.description })
|
|
305
|
+
] }),
|
|
306
|
+
!done && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "#d1d5db", fontSize: 16, marginTop: 1 }, children: "\u203A" })
|
|
307
|
+
]
|
|
308
|
+
},
|
|
309
|
+
task.slug
|
|
310
|
+
);
|
|
311
|
+
}) })
|
|
312
|
+
] }) });
|
|
313
|
+
}
|
|
314
|
+
var checklist_default = OnTheWayChecklist;
|
|
315
|
+
|
|
316
|
+
exports.OnTheWayChecklist = OnTheWayChecklist;
|
|
317
|
+
exports.default = checklist_default;
|
|
318
|
+
//# sourceMappingURL=checklist.cjs.map
|
|
319
|
+
//# sourceMappingURL=checklist.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/checklist.tsx"],"names":["useOnTheWay","useState","useRef","useEffect","useCallback","__spreadProps","__spreadValues","jsx","jsxs"],"mappings":"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","file":"checklist.cjs","sourcesContent":["'use client'\n\nimport { useState, useEffect, useCallback, useRef } from 'react'\nimport { useOnTheWay } from './react'\n\n// ---- Types ----\n\n/**\n * A single task entry in the checklist.\n */\nexport interface ChecklistTask {\n /** Slug of the OnTheWay task — must match a server-side task slug */\n slug: string\n /** Human-readable title displayed in the list */\n title: string\n /** Optional description shown below the title */\n description?: string\n /** Whether this task must be completed before the checklist hides (default `true`) */\n required?: boolean\n}\n\n/**\n * Props for the `<OnTheWayChecklist>` component.\n */\nexport interface OnTheWayChecklistProps {\n /** Ordered list of tasks to display */\n tasks: ChecklistTask[]\n /** Panel title (default \"Getting Started\") */\n title?: string\n /** Panel position (default \"bottom-right\") */\n position?: 'bottom-right' | 'bottom-left'\n /** Fired when all required tasks are completed */\n onAllComplete?: () => void\n /**\n * Auto-hide the panel a few seconds after all required tasks are completed.\n * Default `true`. Set to `false` to keep it visible.\n */\n autoHide?: boolean\n /**\n * Delay in ms before auto-hiding after completion (default 4000).\n */\n autoHideDelay?: number\n}\n\n// ---- Storage helpers ----\n\nconst STORAGE_KEY_PREFIX = 'otw_checklist_'\n\nfunction getCompletedSlugs(projectId: string): Set<string> {\n if (typeof localStorage === 'undefined') return new Set()\n try {\n const raw = localStorage.getItem(STORAGE_KEY_PREFIX + projectId)\n if (raw) return new Set(JSON.parse(raw))\n } catch {\n // ignore\n }\n return new Set()\n}\n\nfunction saveCompletedSlugs(projectId: string, slugs: Set<string>) {\n if (typeof localStorage === 'undefined') return\n localStorage.setItem(STORAGE_KEY_PREFIX + projectId, JSON.stringify([...slugs]))\n}\n\n// ---- Component ----\n\n/**\n * Floating checklist panel that shows onboarding progress.\n *\n * Each task maps to an OnTheWay tour by slug. Clicking a task starts the\n * corresponding tour; completion is tracked and persisted to `localStorage`.\n *\n * @example\n * ```tsx\n * <OnTheWayChecklist\n * tasks={[\n * { slug: 'add-company', title: '接入公司' },\n * { slug: 'add-courier', title: '添加快递员' },\n * { slug: 'first-sync', title: '首次同步', required: false },\n * ]}\n * onAllComplete={() => console.log('🎉 All done!')}\n * />\n * ```\n */\nexport function OnTheWayChecklist({\n tasks,\n title = 'Getting Started',\n position = 'bottom-right',\n onAllComplete,\n autoHide = true,\n autoHideDelay = 4000,\n}: OnTheWayChecklistProps) {\n const { otw, ready, start, isTaskCompleted } = useOnTheWay()\n const [expanded, setExpanded] = useState(true)\n const [completedSlugs, setCompletedSlugs] = useState<Set<string>>(new Set())\n const [hidden, setHidden] = useState(false)\n const [celebrating, setCelebrating] = useState(false)\n const allCompleteFired = useRef(false)\n\n // Access projectId from the SDK instance\n const projectId = otw?.getProjectId() ?? 'default'\n\n // Load persisted state\n useEffect(() => {\n const stored = getCompletedSlugs(projectId)\n if (stored.size > 0) setCompletedSlugs(stored)\n }, [projectId])\n\n // Poll for newly completed tasks (the SDK marks them on tour finish)\n useEffect(() => {\n if (!ready || !otw) return\n const interval = setInterval(() => {\n let changed = false\n const next = new Set(completedSlugs)\n for (const task of tasks) {\n if (!next.has(task.slug) && isTaskCompleted(task.slug)) {\n next.add(task.slug)\n changed = true\n }\n }\n if (changed) {\n setCompletedSlugs(next)\n saveCompletedSlugs(projectId, next)\n }\n }, 500)\n return () => clearInterval(interval)\n }, [ready, otw, tasks, completedSlugs, isTaskCompleted, projectId])\n\n // Check all-complete\n const requiredTasks = tasks.filter(t => t.required !== false)\n const allDone = requiredTasks.length > 0 && requiredTasks.every(t => completedSlugs.has(t.slug))\n const completedCount = tasks.filter(t => completedSlugs.has(t.slug)).length\n const progress = tasks.length > 0 ? Math.round((completedCount / tasks.length) * 100) : 0\n\n useEffect(() => {\n if (allDone && !allCompleteFired.current) {\n allCompleteFired.current = true\n setCelebrating(true)\n onAllComplete?.()\n if (autoHide) {\n const timer = setTimeout(() => setHidden(true), autoHideDelay)\n return () => clearTimeout(timer)\n }\n }\n }, [allDone, onAllComplete, autoHide, autoHideDelay])\n\n const handleTaskClick = useCallback(\n (slug: string) => {\n if (completedSlugs.has(slug)) return\n start(slug)\n },\n [completedSlugs, start],\n )\n\n if (hidden) return null\n\n // ---- Styles ----\n const isRight = position === 'bottom-right'\n\n const containerStyle: React.CSSProperties = {\n position: 'fixed',\n bottom: 24,\n ...(isRight ? { right: 24 } : { left: 24 }),\n zIndex: 2147483640,\n fontFamily: 'system-ui, -apple-system, sans-serif',\n fontSize: 13,\n width: expanded ? 320 : 'auto',\n }\n\n const cardStyle: React.CSSProperties = {\n background: '#fff',\n borderRadius: 12,\n boxShadow: '0 8px 32px rgba(0,0,0,0.15)',\n border: '1px solid #e5e7eb',\n overflow: 'hidden',\n }\n\n const headerStyle: React.CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n padding: '12px 16px',\n cursor: 'pointer',\n userSelect: 'none',\n background: celebrating ? '#f0fdf4' : '#fff',\n borderBottom: expanded ? '1px solid #f3f4f6' : 'none',\n }\n\n const progressBarBg: React.CSSProperties = {\n height: 4,\n background: '#f3f4f6',\n borderRadius: 2,\n overflow: 'hidden',\n marginTop: 8,\n }\n\n const progressBarFill: React.CSSProperties = {\n height: '100%',\n width: `${progress}%`,\n background: allDone ? '#22c55e' : '#3b82f6',\n borderRadius: 2,\n transition: 'width 0.4s ease',\n }\n\n const taskItemStyle = (done: boolean): React.CSSProperties => ({\n display: 'flex',\n alignItems: 'flex-start',\n gap: 10,\n padding: '10px 16px',\n cursor: done ? 'default' : 'pointer',\n borderBottom: '1px solid #f9fafb',\n opacity: done ? 0.6 : 1,\n transition: 'background 0.15s',\n })\n\n const checkboxStyle = (done: boolean): React.CSSProperties => ({\n width: 18,\n height: 18,\n borderRadius: 4,\n border: done ? '2px solid #22c55e' : '2px solid #d1d5db',\n background: done ? '#22c55e' : '#fff',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n marginTop: 1,\n transition: 'all 0.2s',\n color: '#fff',\n fontSize: 11,\n fontWeight: 700,\n })\n\n // Collapsed badge\n if (!expanded) {\n return (\n <div style={containerStyle}>\n <button\n onClick={() => setExpanded(true)}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n padding: '10px 16px',\n background: celebrating ? '#22c55e' : '#111',\n color: '#fff',\n border: 'none',\n borderRadius: 24,\n cursor: 'pointer',\n fontSize: 13,\n fontWeight: 600,\n boxShadow: '0 4px 14px rgba(0,0,0,0.2)',\n }}\n >\n {celebrating ? '🎉' : '📋'} {title}\n <span\n style={{\n background: 'rgba(255,255,255,0.2)',\n padding: '2px 8px',\n borderRadius: 12,\n fontSize: 11,\n }}\n >\n {completedCount}/{tasks.length}\n </span>\n </button>\n </div>\n )\n }\n\n return (\n <div style={containerStyle}>\n <div style={cardStyle}>\n {/* Header */}\n <div style={headerStyle} onClick={() => setExpanded(false)}>\n <div style={{ flex: 1 }}>\n <div\n style={{\n fontWeight: 600,\n fontSize: 14,\n color: '#111',\n display: 'flex',\n alignItems: 'center',\n gap: 6,\n }}\n >\n {celebrating ? '🎉' : '📋'} {title}\n </div>\n <div style={progressBarBg}>\n <div style={progressBarFill} />\n </div>\n <div style={{ fontSize: 11, color: '#9ca3af', marginTop: 4 }}>\n {completedCount} of {tasks.length} complete\n </div>\n </div>\n <span\n style={{\n color: '#9ca3af',\n fontSize: 18,\n marginLeft: 8,\n transition: 'transform 0.2s',\n transform: 'rotate(0deg)',\n }}\n >\n ▾\n </span>\n </div>\n\n {/* Celebration banner */}\n {celebrating && (\n <div\n style={{\n padding: '12px 16px',\n background: '#f0fdf4',\n borderBottom: '1px solid #dcfce7',\n textAlign: 'center',\n fontSize: 13,\n color: '#15803d',\n fontWeight: 500,\n }}\n >\n 🎉 All done! You're all set.\n </div>\n )}\n\n {/* Task list */}\n <div style={{ maxHeight: 320, overflowY: 'auto' }}>\n {tasks.map(task => {\n const done = completedSlugs.has(task.slug)\n return (\n <div\n key={task.slug}\n style={taskItemStyle(done)}\n onClick={() => handleTaskClick(task.slug)}\n onMouseEnter={e => {\n if (!done) (e.currentTarget as HTMLElement).style.background = '#f9fafb'\n }}\n onMouseLeave={e => {\n (e.currentTarget as HTMLElement).style.background = ''\n }}\n role=\"button\"\n tabIndex={0}\n onKeyDown={e => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n handleTaskClick(task.slug)\n }\n }}\n >\n <div style={checkboxStyle(done)}>\n {done ? '✓' : ''}\n </div>\n <div style={{ flex: 1, minWidth: 0 }}>\n <div\n style={{\n fontWeight: 500,\n fontSize: 13,\n color: done ? '#9ca3af' : '#374151',\n textDecoration: done ? 'line-through' : 'none',\n }}\n >\n {task.title}\n {task.required === false && (\n <span\n style={{\n fontSize: 10,\n color: '#9ca3af',\n marginLeft: 6,\n fontWeight: 400,\n }}\n >\n optional\n </span>\n )}\n </div>\n {task.description && (\n <div style={{ fontSize: 11, color: '#9ca3af', marginTop: 2 }}>\n {task.description}\n </div>\n )}\n </div>\n {!done && (\n <span style={{ color: '#d1d5db', fontSize: 16, marginTop: 1 }}>›</span>\n )}\n </div>\n )\n })}\n </div>\n </div>\n </div>\n )\n}\n\nexport default OnTheWayChecklist\n"]}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A single task entry in the checklist.
|
|
5
|
+
*/
|
|
6
|
+
interface ChecklistTask {
|
|
7
|
+
/** Slug of the OnTheWay task — must match a server-side task slug */
|
|
8
|
+
slug: string;
|
|
9
|
+
/** Human-readable title displayed in the list */
|
|
10
|
+
title: string;
|
|
11
|
+
/** Optional description shown below the title */
|
|
12
|
+
description?: string;
|
|
13
|
+
/** Whether this task must be completed before the checklist hides (default `true`) */
|
|
14
|
+
required?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Props for the `<OnTheWayChecklist>` component.
|
|
18
|
+
*/
|
|
19
|
+
interface OnTheWayChecklistProps {
|
|
20
|
+
/** Ordered list of tasks to display */
|
|
21
|
+
tasks: ChecklistTask[];
|
|
22
|
+
/** Panel title (default "Getting Started") */
|
|
23
|
+
title?: string;
|
|
24
|
+
/** Panel position (default "bottom-right") */
|
|
25
|
+
position?: 'bottom-right' | 'bottom-left';
|
|
26
|
+
/** Fired when all required tasks are completed */
|
|
27
|
+
onAllComplete?: () => void;
|
|
28
|
+
/**
|
|
29
|
+
* Auto-hide the panel a few seconds after all required tasks are completed.
|
|
30
|
+
* Default `true`. Set to `false` to keep it visible.
|
|
31
|
+
*/
|
|
32
|
+
autoHide?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Delay in ms before auto-hiding after completion (default 4000).
|
|
35
|
+
*/
|
|
36
|
+
autoHideDelay?: number;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Floating checklist panel that shows onboarding progress.
|
|
40
|
+
*
|
|
41
|
+
* Each task maps to an OnTheWay tour by slug. Clicking a task starts the
|
|
42
|
+
* corresponding tour; completion is tracked and persisted to `localStorage`.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```tsx
|
|
46
|
+
* <OnTheWayChecklist
|
|
47
|
+
* tasks={[
|
|
48
|
+
* { slug: 'add-company', title: '接入公司' },
|
|
49
|
+
* { slug: 'add-courier', title: '添加快递员' },
|
|
50
|
+
* { slug: 'first-sync', title: '首次同步', required: false },
|
|
51
|
+
* ]}
|
|
52
|
+
* onAllComplete={() => console.log('🎉 All done!')}
|
|
53
|
+
* />
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
declare function OnTheWayChecklist({ tasks, title, position, onAllComplete, autoHide, autoHideDelay, }: OnTheWayChecklistProps): react_jsx_runtime.JSX.Element | null;
|
|
57
|
+
|
|
58
|
+
export { type ChecklistTask, OnTheWayChecklist, type OnTheWayChecklistProps, OnTheWayChecklist as default };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A single task entry in the checklist.
|
|
5
|
+
*/
|
|
6
|
+
interface ChecklistTask {
|
|
7
|
+
/** Slug of the OnTheWay task — must match a server-side task slug */
|
|
8
|
+
slug: string;
|
|
9
|
+
/** Human-readable title displayed in the list */
|
|
10
|
+
title: string;
|
|
11
|
+
/** Optional description shown below the title */
|
|
12
|
+
description?: string;
|
|
13
|
+
/** Whether this task must be completed before the checklist hides (default `true`) */
|
|
14
|
+
required?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Props for the `<OnTheWayChecklist>` component.
|
|
18
|
+
*/
|
|
19
|
+
interface OnTheWayChecklistProps {
|
|
20
|
+
/** Ordered list of tasks to display */
|
|
21
|
+
tasks: ChecklistTask[];
|
|
22
|
+
/** Panel title (default "Getting Started") */
|
|
23
|
+
title?: string;
|
|
24
|
+
/** Panel position (default "bottom-right") */
|
|
25
|
+
position?: 'bottom-right' | 'bottom-left';
|
|
26
|
+
/** Fired when all required tasks are completed */
|
|
27
|
+
onAllComplete?: () => void;
|
|
28
|
+
/**
|
|
29
|
+
* Auto-hide the panel a few seconds after all required tasks are completed.
|
|
30
|
+
* Default `true`. Set to `false` to keep it visible.
|
|
31
|
+
*/
|
|
32
|
+
autoHide?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Delay in ms before auto-hiding after completion (default 4000).
|
|
35
|
+
*/
|
|
36
|
+
autoHideDelay?: number;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Floating checklist panel that shows onboarding progress.
|
|
40
|
+
*
|
|
41
|
+
* Each task maps to an OnTheWay tour by slug. Clicking a task starts the
|
|
42
|
+
* corresponding tour; completion is tracked and persisted to `localStorage`.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```tsx
|
|
46
|
+
* <OnTheWayChecklist
|
|
47
|
+
* tasks={[
|
|
48
|
+
* { slug: 'add-company', title: '接入公司' },
|
|
49
|
+
* { slug: 'add-courier', title: '添加快递员' },
|
|
50
|
+
* { slug: 'first-sync', title: '首次同步', required: false },
|
|
51
|
+
* ]}
|
|
52
|
+
* onAllComplete={() => console.log('🎉 All done!')}
|
|
53
|
+
* />
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
declare function OnTheWayChecklist({ tasks, title, position, onAllComplete, autoHide, autoHideDelay, }: OnTheWayChecklistProps): react_jsx_runtime.JSX.Element | null;
|
|
57
|
+
|
|
58
|
+
export { type ChecklistTask, OnTheWayChecklist, type OnTheWayChecklistProps, OnTheWayChecklist as default };
|