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
@@ -0,0 +1,51 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ interface HelpMenuProps {
4
+ /** 按钮文字,默认 "?" */
5
+ label?: string | React.ReactNode;
6
+ /** 菜单标题 */
7
+ title?: string;
8
+ /** 自定义位置 */
9
+ position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
10
+ /** 自定义样式类 */
11
+ className?: string;
12
+ /** 自定义按钮样式类 */
13
+ buttonClassName?: string;
14
+ }
15
+ /**
16
+ * 帮助菜单组件 - 显示所有可用的 onboarding 任务
17
+ *
18
+ * @example
19
+ * ```tsx
20
+ * // 基础用法
21
+ * <HelpMenu />
22
+ *
23
+ * // 自定义
24
+ * <HelpMenu label="Need help?" title="Guides" position="bottom-left" />
25
+ * ```
26
+ */
27
+ declare function HelpMenu({ label, title, position, className, buttonClassName, }: HelpMenuProps): react_jsx_runtime.JSX.Element;
28
+ interface HelpTriggerProps {
29
+ /** 要触发的任务 slug */
30
+ taskSlug: string;
31
+ children: React.ReactNode;
32
+ className?: string;
33
+ style?: React.CSSProperties;
34
+ }
35
+ /**
36
+ * 内联触发按钮 - 包裹任何元素,点击启动指定任务
37
+ *
38
+ * @example
39
+ * ```tsx
40
+ * <HelpTrigger taskSlug="welcome">
41
+ * <button>Show Tour</button>
42
+ * </HelpTrigger>
43
+ *
44
+ * <HelpTrigger taskSlug="settings-guide">
45
+ * <span className="text-blue-500 cursor-pointer">Learn more</span>
46
+ * </HelpTrigger>
47
+ * ```
48
+ */
49
+ declare function HelpTrigger({ taskSlug, children, className, style, }: HelpTriggerProps): react_jsx_runtime.JSX.Element;
50
+
51
+ export { HelpMenu, HelpTrigger, HelpMenu as default };
@@ -0,0 +1,51 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ interface HelpMenuProps {
4
+ /** 按钮文字,默认 "?" */
5
+ label?: string | React.ReactNode;
6
+ /** 菜单标题 */
7
+ title?: string;
8
+ /** 自定义位置 */
9
+ position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
10
+ /** 自定义样式类 */
11
+ className?: string;
12
+ /** 自定义按钮样式类 */
13
+ buttonClassName?: string;
14
+ }
15
+ /**
16
+ * 帮助菜单组件 - 显示所有可用的 onboarding 任务
17
+ *
18
+ * @example
19
+ * ```tsx
20
+ * // 基础用法
21
+ * <HelpMenu />
22
+ *
23
+ * // 自定义
24
+ * <HelpMenu label="Need help?" title="Guides" position="bottom-left" />
25
+ * ```
26
+ */
27
+ declare function HelpMenu({ label, title, position, className, buttonClassName, }: HelpMenuProps): react_jsx_runtime.JSX.Element;
28
+ interface HelpTriggerProps {
29
+ /** 要触发的任务 slug */
30
+ taskSlug: string;
31
+ children: React.ReactNode;
32
+ className?: string;
33
+ style?: React.CSSProperties;
34
+ }
35
+ /**
36
+ * 内联触发按钮 - 包裹任何元素,点击启动指定任务
37
+ *
38
+ * @example
39
+ * ```tsx
40
+ * <HelpTrigger taskSlug="welcome">
41
+ * <button>Show Tour</button>
42
+ * </HelpTrigger>
43
+ *
44
+ * <HelpTrigger taskSlug="settings-guide">
45
+ * <span className="text-blue-500 cursor-pointer">Learn more</span>
46
+ * </HelpTrigger>
47
+ * ```
48
+ */
49
+ declare function HelpTrigger({ taskSlug, children, className, style, }: HelpTriggerProps): react_jsx_runtime.JSX.Element;
50
+
51
+ export { HelpMenu, HelpTrigger, HelpMenu as default };
@@ -0,0 +1,205 @@
1
+ import { useOnTheWay } from './chunk-RNQLNLNI.js';
2
+ import './chunk-OKJ5GEH3.js';
3
+ import { __spreadProps, __spreadValues } from './chunk-DDAAVRWG.js';
4
+ import { useState, useRef, useEffect } from 'react';
5
+ import { jsxs, jsx } from 'react/jsx-runtime';
6
+
7
+ function HelpMenu({
8
+ label = "?",
9
+ title = "Help & Guides",
10
+ position = "bottom-right",
11
+ className = "",
12
+ buttonClassName = ""
13
+ }) {
14
+ var _a;
15
+ const { otw, ready, start } = useOnTheWay();
16
+ const [open, setOpen] = useState(false);
17
+ const menuRef = useRef(null);
18
+ const tasks = ready ? (_a = otw == null ? void 0 : otw.getTasks()) != null ? _a : [] : [];
19
+ useEffect(() => {
20
+ const handleClick = (e) => {
21
+ if (menuRef.current && !menuRef.current.contains(e.target)) {
22
+ setOpen(false);
23
+ }
24
+ };
25
+ if (open) document.addEventListener("mousedown", handleClick);
26
+ return () => document.removeEventListener("mousedown", handleClick);
27
+ }, [open]);
28
+ const positionStyles = {
29
+ "bottom-right": { position: "fixed", bottom: 24, right: 24 },
30
+ "bottom-left": { position: "fixed", bottom: 24, left: 24 },
31
+ "top-right": { position: "fixed", top: 24, right: 24 },
32
+ "top-left": { position: "fixed", top: 24, left: 24 }
33
+ };
34
+ const menuPosition = {
35
+ "bottom-right": { bottom: "100%", right: 0, marginBottom: 8 },
36
+ "bottom-left": { bottom: "100%", left: 0, marginBottom: 8 },
37
+ "top-right": { top: "100%", right: 0, marginTop: 8 },
38
+ "top-left": { top: "100%", left: 0, marginTop: 8 }
39
+ };
40
+ const triggerLabels = {
41
+ auto: "\u{1F504}",
42
+ manual: "\u{1F446}",
43
+ "first-visit": "\u{1F44B}"
44
+ };
45
+ return /* @__PURE__ */ jsxs(
46
+ "div",
47
+ {
48
+ ref: menuRef,
49
+ style: __spreadProps(__spreadValues({}, positionStyles[position]), { zIndex: 2147483640 }),
50
+ className,
51
+ children: [
52
+ open && /* @__PURE__ */ jsxs(
53
+ "div",
54
+ {
55
+ style: __spreadProps(__spreadValues({
56
+ position: "absolute"
57
+ }, menuPosition[position]), {
58
+ width: 280,
59
+ background: "#fff",
60
+ borderRadius: 12,
61
+ boxShadow: "0 8px 32px rgba(0,0,0,0.15)",
62
+ border: "1px solid #e5e7eb",
63
+ overflow: "hidden",
64
+ fontFamily: "system-ui, -apple-system, sans-serif"
65
+ }),
66
+ children: [
67
+ /* @__PURE__ */ jsx(
68
+ "div",
69
+ {
70
+ style: {
71
+ padding: "14px 16px",
72
+ borderBottom: "1px solid #f3f4f6",
73
+ fontWeight: 600,
74
+ fontSize: 14,
75
+ color: "#111"
76
+ },
77
+ children: title
78
+ }
79
+ ),
80
+ /* @__PURE__ */ jsx("div", { style: { maxHeight: 320, overflowY: "auto" }, children: tasks.length === 0 ? /* @__PURE__ */ jsx(
81
+ "div",
82
+ {
83
+ style: {
84
+ padding: "24px 16px",
85
+ textAlign: "center",
86
+ color: "#9ca3af",
87
+ fontSize: 13
88
+ },
89
+ children: ready ? "No guides available" : "Loading..."
90
+ }
91
+ ) : tasks.map((task) => {
92
+ var _a2;
93
+ return /* @__PURE__ */ jsxs(
94
+ "button",
95
+ {
96
+ onClick: () => {
97
+ start(task.slug);
98
+ setOpen(false);
99
+ },
100
+ style: {
101
+ display: "flex",
102
+ alignItems: "center",
103
+ gap: 10,
104
+ width: "100%",
105
+ padding: "12px 16px",
106
+ border: "none",
107
+ background: "none",
108
+ cursor: "pointer",
109
+ textAlign: "left",
110
+ fontSize: 14,
111
+ color: "#374151",
112
+ borderBottom: "1px solid #f9fafb",
113
+ transition: "background 0.15s"
114
+ },
115
+ onMouseEnter: (e) => e.currentTarget.style.background = "#f9fafb",
116
+ onMouseLeave: (e) => e.currentTarget.style.background = "none",
117
+ children: [
118
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 16 }, children: (_a2 = triggerLabels[task.trigger]) != null ? _a2 : "\u{1F4D6}" }),
119
+ /* @__PURE__ */ jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [
120
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 500 }, children: task.slug.replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()) }),
121
+ /* @__PURE__ */ jsxs("div", { style: { fontSize: 12, color: "#9ca3af" }, children: [
122
+ task.steps.length,
123
+ " steps"
124
+ ] })
125
+ ] }),
126
+ /* @__PURE__ */ jsx("span", { style: { color: "#d1d5db", fontSize: 18 }, children: "\u203A" })
127
+ ]
128
+ },
129
+ task.id
130
+ );
131
+ }) })
132
+ ]
133
+ }
134
+ ),
135
+ /* @__PURE__ */ jsx(
136
+ "button",
137
+ {
138
+ onClick: () => setOpen(!open),
139
+ className: buttonClassName,
140
+ style: buttonClassName ? void 0 : {
141
+ width: 48,
142
+ height: 48,
143
+ borderRadius: "50%",
144
+ border: "none",
145
+ background: "#111",
146
+ color: "#fff",
147
+ fontSize: 20,
148
+ fontWeight: 700,
149
+ cursor: "pointer",
150
+ boxShadow: "0 4px 14px rgba(0,0,0,0.2)",
151
+ display: "flex",
152
+ alignItems: "center",
153
+ justifyContent: "center",
154
+ transition: "transform 0.2s, box-shadow 0.2s"
155
+ },
156
+ onMouseEnter: (e) => {
157
+ if (!buttonClassName) {
158
+ e.currentTarget.style.transform = "scale(1.1)";
159
+ e.currentTarget.style.boxShadow = "0 6px 20px rgba(0,0,0,0.25)";
160
+ }
161
+ },
162
+ onMouseLeave: (e) => {
163
+ if (!buttonClassName) {
164
+ e.currentTarget.style.transform = "scale(1)";
165
+ e.currentTarget.style.boxShadow = "0 4px 14px rgba(0,0,0,0.2)";
166
+ }
167
+ },
168
+ "aria-label": "Help menu",
169
+ children: label
170
+ }
171
+ )
172
+ ]
173
+ }
174
+ );
175
+ }
176
+ function HelpTrigger({
177
+ taskSlug,
178
+ children,
179
+ className,
180
+ style
181
+ }) {
182
+ const { start, ready } = useOnTheWay();
183
+ return /* @__PURE__ */ jsx(
184
+ "span",
185
+ {
186
+ onClick: () => ready && start(taskSlug),
187
+ className,
188
+ style: __spreadValues({ cursor: ready ? "pointer" : "default" }, style),
189
+ role: "button",
190
+ tabIndex: 0,
191
+ onKeyDown: (e) => {
192
+ if (e.key === "Enter" || e.key === " ") {
193
+ e.preventDefault();
194
+ ready && start(taskSlug);
195
+ }
196
+ },
197
+ children
198
+ }
199
+ );
200
+ }
201
+ var components_default = HelpMenu;
202
+
203
+ export { HelpMenu, HelpTrigger, components_default as default };
204
+ //# sourceMappingURL=components.js.map
205
+ //# sourceMappingURL=components.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components.tsx"],"names":["_a"],"mappings":"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","file":"components.js","sourcesContent":["'use client'\n\nimport { useState, useRef, useEffect } from 'react'\nimport { useOnTheWay } from './react'\n\n// ---- Types ----\n\ninterface HelpMenuProps {\n /** 按钮文字,默认 \"?\" */\n label?: string | React.ReactNode\n /** 菜单标题 */\n title?: string\n /** 自定义位置 */\n position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left'\n /** 自定义样式类 */\n className?: string\n /** 自定义按钮样式类 */\n buttonClassName?: string\n}\n\n/**\n * 帮助菜单组件 - 显示所有可用的 onboarding 任务\n *\n * @example\n * ```tsx\n * // 基础用法\n * <HelpMenu />\n *\n * // 自定义\n * <HelpMenu label=\"Need help?\" title=\"Guides\" position=\"bottom-left\" />\n * ```\n */\nexport function HelpMenu({\n label = '?',\n title = 'Help & Guides',\n position = 'bottom-right',\n className = '',\n buttonClassName = '',\n}: HelpMenuProps) {\n const { otw, ready, start } = useOnTheWay()\n const [open, setOpen] = useState(false)\n const menuRef = useRef<HTMLDivElement>(null)\n\n const tasks = ready ? otw?.getTasks() ?? [] : []\n\n // 点击外部关闭\n useEffect(() => {\n const handleClick = (e: MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(e.target as Node)) {\n setOpen(false)\n }\n }\n if (open) document.addEventListener('mousedown', handleClick)\n return () => document.removeEventListener('mousedown', handleClick)\n }, [open])\n\n const positionStyles: Record<string, React.CSSProperties> = {\n 'bottom-right': { position: 'fixed', bottom: 24, right: 24 },\n 'bottom-left': { position: 'fixed', bottom: 24, left: 24 },\n 'top-right': { position: 'fixed', top: 24, right: 24 },\n 'top-left': { position: 'fixed', top: 24, left: 24 },\n }\n\n const menuPosition: Record<string, React.CSSProperties> = {\n 'bottom-right': { bottom: '100%', right: 0, marginBottom: 8 },\n 'bottom-left': { bottom: '100%', left: 0, marginBottom: 8 },\n 'top-right': { top: '100%', right: 0, marginTop: 8 },\n 'top-left': { top: '100%', left: 0, marginTop: 8 },\n }\n\n const triggerLabels: Record<string, string> = {\n auto: '🔄',\n manual: '👆',\n 'first-visit': '👋',\n }\n\n return (\n <div\n ref={menuRef}\n style={{ ...positionStyles[position], zIndex: 2147483640 }}\n className={className}\n >\n {/* 菜单面板 */}\n {open && (\n <div\n style={{\n position: 'absolute',\n ...menuPosition[position],\n width: 280,\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 fontFamily: 'system-ui, -apple-system, sans-serif',\n }}\n >\n {/* Header */}\n <div\n style={{\n padding: '14px 16px',\n borderBottom: '1px solid #f3f4f6',\n fontWeight: 600,\n fontSize: 14,\n color: '#111',\n }}\n >\n {title}\n </div>\n\n {/* Task list */}\n <div style={{ maxHeight: 320, overflowY: 'auto' }}>\n {tasks.length === 0 ? (\n <div\n style={{\n padding: '24px 16px',\n textAlign: 'center',\n color: '#9ca3af',\n fontSize: 13,\n }}\n >\n {ready ? 'No guides available' : 'Loading...'}\n </div>\n ) : (\n tasks.map((task) => (\n <button\n key={task.id}\n onClick={() => {\n start(task.slug)\n setOpen(false)\n }}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 10,\n width: '100%',\n padding: '12px 16px',\n border: 'none',\n background: 'none',\n cursor: 'pointer',\n textAlign: 'left',\n fontSize: 14,\n color: '#374151',\n borderBottom: '1px solid #f9fafb',\n transition: 'background 0.15s',\n }}\n onMouseEnter={(e) =>\n (e.currentTarget.style.background = '#f9fafb')\n }\n onMouseLeave={(e) =>\n (e.currentTarget.style.background = 'none')\n }\n >\n <span style={{ fontSize: 16 }}>\n {triggerLabels[task.trigger] ?? '📖'}\n </span>\n <div style={{ flex: 1, minWidth: 0 }}>\n <div style={{ fontWeight: 500 }}>\n {task.slug\n .replace(/[-_]/g, ' ')\n .replace(/\\b\\w/g, (c) => c.toUpperCase())}\n </div>\n <div style={{ fontSize: 12, color: '#9ca3af' }}>\n {task.steps.length} steps\n </div>\n </div>\n <span style={{ color: '#d1d5db', fontSize: 18 }}>›</span>\n </button>\n ))\n )}\n </div>\n </div>\n )}\n\n {/* 触发按钮 */}\n <button\n onClick={() => setOpen(!open)}\n className={buttonClassName}\n style={\n buttonClassName\n ? undefined\n : {\n width: 48,\n height: 48,\n borderRadius: '50%',\n border: 'none',\n background: '#111',\n color: '#fff',\n fontSize: 20,\n fontWeight: 700,\n cursor: 'pointer',\n boxShadow: '0 4px 14px rgba(0,0,0,0.2)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n transition: 'transform 0.2s, box-shadow 0.2s',\n }\n }\n onMouseEnter={(e) => {\n if (!buttonClassName) {\n e.currentTarget.style.transform = 'scale(1.1)'\n e.currentTarget.style.boxShadow = '0 6px 20px rgba(0,0,0,0.25)'\n }\n }}\n onMouseLeave={(e) => {\n if (!buttonClassName) {\n e.currentTarget.style.transform = 'scale(1)'\n e.currentTarget.style.boxShadow = '0 4px 14px rgba(0,0,0,0.2)'\n }\n }}\n aria-label=\"Help menu\"\n >\n {label}\n </button>\n </div>\n )\n}\n\n// ---- Inline trigger ----\n\ninterface HelpTriggerProps {\n /** 要触发的任务 slug */\n taskSlug: string\n children: React.ReactNode\n className?: string\n style?: React.CSSProperties\n}\n\n/**\n * 内联触发按钮 - 包裹任何元素,点击启动指定任务\n *\n * @example\n * ```tsx\n * <HelpTrigger taskSlug=\"welcome\">\n * <button>Show Tour</button>\n * </HelpTrigger>\n *\n * <HelpTrigger taskSlug=\"settings-guide\">\n * <span className=\"text-blue-500 cursor-pointer\">Learn more</span>\n * </HelpTrigger>\n * ```\n */\nexport function HelpTrigger({\n taskSlug,\n children,\n className,\n style,\n}: HelpTriggerProps) {\n const { start, ready } = useOnTheWay()\n\n return (\n <span\n onClick={() => ready && start(taskSlug)}\n className={className}\n style={{ cursor: ready ? 'pointer' : 'default', ...style }}\n role=\"button\"\n tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n ready && start(taskSlug)\n }\n }}\n >\n {children}\n </span>\n )\n}\n\nexport default HelpMenu\n"]}