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.
Files changed (44) hide show
  1. package/README.md +110 -0
  2. package/dist/checklist.cjs +319 -0
  3. package/dist/checklist.cjs.map +1 -0
  4. package/dist/checklist.d.cts +58 -0
  5. package/dist/checklist.d.ts +58 -0
  6. package/dist/checklist.js +314 -0
  7. package/dist/checklist.js.map +1 -0
  8. package/dist/chunk-254YHUN3.cjs +26 -0
  9. package/dist/chunk-254YHUN3.cjs.map +1 -0
  10. package/dist/chunk-DDAAVRWG.js +23 -0
  11. package/dist/chunk-DDAAVRWG.js.map +1 -0
  12. package/dist/chunk-NRUQU5AR.cjs +94 -0
  13. package/dist/chunk-NRUQU5AR.cjs.map +1 -0
  14. package/dist/chunk-OKJ5GEH3.js +358 -0
  15. package/dist/chunk-OKJ5GEH3.js.map +1 -0
  16. package/dist/chunk-RNQLNLNI.js +91 -0
  17. package/dist/chunk-RNQLNLNI.js.map +1 -0
  18. package/dist/chunk-UE3T6TSM.cjs +361 -0
  19. package/dist/chunk-UE3T6TSM.cjs.map +1 -0
  20. package/dist/components.cjs +211 -0
  21. package/dist/components.cjs.map +1 -0
  22. package/dist/components.d.cts +51 -0
  23. package/dist/components.d.ts +51 -0
  24. package/dist/components.js +205 -0
  25. package/dist/components.js.map +1 -0
  26. package/dist/devtools.cjs +733 -0
  27. package/dist/devtools.cjs.map +1 -0
  28. package/dist/devtools.d.cts +18 -0
  29. package/dist/devtools.d.ts +18 -0
  30. package/dist/devtools.js +727 -0
  31. package/dist/devtools.js.map +1 -0
  32. package/dist/index.cjs +19 -0
  33. package/dist/index.cjs.map +1 -0
  34. package/dist/index.d.cts +163 -0
  35. package/dist/index.d.ts +163 -0
  36. package/dist/index.js +4 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/react.cjs +18 -0
  39. package/dist/react.cjs.map +1 -0
  40. package/dist/react.d.cts +68 -0
  41. package/dist/react.d.ts +68 -0
  42. package/dist/react.js +5 -0
  43. package/dist/react.js.map +1 -0
  44. 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&apos;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 };