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,733 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var chunk254YHUN3_cjs = require('./chunk-254YHUN3.cjs');
6
+ var react = require('react');
7
+ var jsxRuntime = require('react/jsx-runtime');
8
+
9
+ function genSelector(el) {
10
+ const ds = el.dataset;
11
+ if (ds == null ? void 0 : ds.onthewayId) return `[data-ontheway-id="${ds.onthewayId}"]`;
12
+ if (el.id && !/^[\d:]/.test(el.id)) {
13
+ try {
14
+ if (document.querySelectorAll("#" + CSS.escape(el.id)).length === 1) return "#" + CSS.escape(el.id);
15
+ } catch (e) {
16
+ }
17
+ }
18
+ const parts = [];
19
+ let cur = el;
20
+ while (cur && cur !== document.body && cur !== document.documentElement && parts.length < 4) {
21
+ let p = cur.tagName.toLowerCase();
22
+ if (cur.id && !/^[\d:]/.test(cur.id)) {
23
+ parts.unshift("#" + CSS.escape(cur.id));
24
+ break;
25
+ }
26
+ const cls = Array.from(cur.classList || []).filter((c) => !/^(w-|h-|p-|m-|text-|bg-|flex|grid|border|rounded|hover:|focus:|sm:|md:|lg:|xl:)/.test(c)).slice(0, 2);
27
+ if (cls.length) p += "." + cls.map((c) => CSS.escape(c)).join(".");
28
+ const parent = cur.parentElement;
29
+ if (parent) {
30
+ const sibs = Array.from(parent.children).filter((s) => s.tagName === cur.tagName);
31
+ if (sibs.length > 1) p += `:nth-child(${sibs.indexOf(cur) + 1})`;
32
+ }
33
+ parts.unshift(p);
34
+ cur = cur.parentElement;
35
+ }
36
+ const sel = parts.join(" > ");
37
+ try {
38
+ if (document.querySelector(sel) === el) return sel;
39
+ } catch (e) {
40
+ }
41
+ parts.length = 0;
42
+ cur = el;
43
+ while (cur && cur !== document.body) {
44
+ const parentEl = cur.parentElement;
45
+ if (!parentEl) break;
46
+ parts.unshift(cur.tagName.toLowerCase() + ":nth-child(" + (Array.from(parentEl.children).indexOf(cur) + 1) + ")");
47
+ cur = parentEl;
48
+ }
49
+ return "body > " + parts.join(" > ");
50
+ }
51
+ function OnTheWayDevToolsPanel({ projectId, apiKey, serverUrl }) {
52
+ const [minimized, setMinimized] = react.useState(true);
53
+ const [tab, setTab] = react.useState("record");
54
+ const [recording, setRecording] = react.useState(false);
55
+ const [steps, setSteps] = react.useState([]);
56
+ const [editingStep, setEditingStep] = react.useState(null);
57
+ const [taskName, setTaskName] = react.useState("");
58
+ const [taskSlug, setTaskSlug] = react.useState("");
59
+ const [trigger, setTrigger] = react.useState("manual");
60
+ const [saving, setSaving] = react.useState(false);
61
+ const [saveMsg, setSaveMsg] = react.useState("");
62
+ const [aiIntent, setAiIntent] = react.useState("");
63
+ const [aiGenerating, setAiGenerating] = react.useState(false);
64
+ const [tasks, setTasks] = react.useState([]);
65
+ const [loadingTasks, setLoadingTasks] = react.useState(false);
66
+ const highlightRef = react.useRef(null);
67
+ const hoveredRef = react.useRef(null);
68
+ const panelRef = react.useRef(null);
69
+ const baseUrl = serverUrl || (typeof window !== "undefined" ? window.location.origin : "");
70
+ const fetchTasks = react.useCallback(async () => {
71
+ setLoadingTasks(true);
72
+ try {
73
+ const res = await fetch(`${baseUrl}/api/sdk/${projectId}/config`);
74
+ const data = await res.json();
75
+ setTasks((data.tasks || []).map((t) => ({
76
+ id: t.id,
77
+ name: t.slug.replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()),
78
+ slug: t.slug,
79
+ steps: t.steps,
80
+ enabled: true
81
+ })));
82
+ } catch (e) {
83
+ setTasks([]);
84
+ }
85
+ setLoadingTasks(false);
86
+ }, [baseUrl, projectId]);
87
+ react.useEffect(() => {
88
+ if (tab === "tasks" && !minimized) fetchTasks();
89
+ }, [tab, minimized, fetchTasks]);
90
+ const isOurElement = react.useCallback((el) => {
91
+ var _a, _b;
92
+ return ((_a = panelRef.current) == null ? void 0 : _a.contains(el)) || ((_b = highlightRef.current) == null ? void 0 : _b.contains(el)) || el.id === "otw-devtools-highlight";
93
+ }, []);
94
+ const onMouseMove = react.useCallback((e) => {
95
+ const el = document.elementFromPoint(e.clientX, e.clientY);
96
+ if (!el || el === hoveredRef.current || isOurElement(el)) return;
97
+ hoveredRef.current = el;
98
+ if (!highlightRef.current) {
99
+ const div = document.createElement("div");
100
+ div.id = "otw-devtools-highlight";
101
+ div.style.cssText = "position:fixed;pointer-events:none;z-index:2147483645;border:2px solid #3b82f6;background:rgba(59,130,246,0.15);border-radius:3px;transition:all .08s ease";
102
+ document.documentElement.appendChild(div);
103
+ highlightRef.current = div;
104
+ }
105
+ const r = el.getBoundingClientRect();
106
+ const h = highlightRef.current;
107
+ h.style.display = "block";
108
+ h.style.top = r.top + "px";
109
+ h.style.left = r.left + "px";
110
+ h.style.width = r.width + "px";
111
+ h.style.height = r.height + "px";
112
+ }, [isOurElement]);
113
+ const onMouseLeave = react.useCallback(() => {
114
+ if (highlightRef.current) highlightRef.current.style.display = "none";
115
+ hoveredRef.current = null;
116
+ }, []);
117
+ const onClick = react.useCallback((e) => {
118
+ var _a;
119
+ const el = e.target;
120
+ if (isOurElement(el)) return;
121
+ e.preventDefault();
122
+ e.stopPropagation();
123
+ el.getBoundingClientRect();
124
+ const text = ((_a = el.innerText) == null ? void 0 : _a.trim().substring(0, 60)) || "";
125
+ const step = {
126
+ id: "step_" + Date.now(),
127
+ selector: genSelector(el),
128
+ tagName: el.tagName.toLowerCase(),
129
+ innerText: text,
130
+ title: `Step ${steps.length + 1}`,
131
+ description: "Click here to continue",
132
+ position: "auto",
133
+ spotlight: true,
134
+ url: location.href
135
+ };
136
+ setSteps((prev) => [...prev, step]);
137
+ setEditingStep(step.id);
138
+ const orig = el.style.outline;
139
+ el.style.outline = "3px solid #22c55e";
140
+ setTimeout(() => {
141
+ el.style.outline = orig;
142
+ }, 400);
143
+ }, [isOurElement, steps.length]);
144
+ const startRecording = react.useCallback(() => {
145
+ setRecording(true);
146
+ document.addEventListener("mousemove", onMouseMove, true);
147
+ document.addEventListener("mouseleave", onMouseLeave, true);
148
+ document.addEventListener("click", onClick, true);
149
+ }, [onMouseMove, onMouseLeave, onClick]);
150
+ const stopRecording = react.useCallback(() => {
151
+ setRecording(false);
152
+ document.removeEventListener("mousemove", onMouseMove, true);
153
+ document.removeEventListener("mouseleave", onMouseLeave, true);
154
+ document.removeEventListener("click", onClick, true);
155
+ if (highlightRef.current) {
156
+ highlightRef.current.remove();
157
+ highlightRef.current = null;
158
+ }
159
+ hoveredRef.current = null;
160
+ }, [onMouseMove, onMouseLeave, onClick]);
161
+ react.useEffect(() => {
162
+ return () => {
163
+ var _a;
164
+ document.removeEventListener("mousemove", onMouseMove, true);
165
+ document.removeEventListener("mouseleave", onMouseLeave, true);
166
+ document.removeEventListener("click", onClick, true);
167
+ (_a = highlightRef.current) == null ? void 0 : _a.remove();
168
+ };
169
+ }, [onMouseMove, onMouseLeave, onClick]);
170
+ react.useEffect(() => {
171
+ if (taskName) {
172
+ setTaskSlug(taskName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, ""));
173
+ }
174
+ }, [taskName]);
175
+ const updateStep = (id, updates) => {
176
+ setSteps((prev) => prev.map((s) => s.id === id ? chunk254YHUN3_cjs.__spreadValues(chunk254YHUN3_cjs.__spreadValues({}, s), updates) : s));
177
+ };
178
+ const deleteStep = (id) => {
179
+ setSteps((prev) => prev.filter((s) => s.id !== id));
180
+ if (editingStep === id) setEditingStep(null);
181
+ };
182
+ const moveStep = (id, dir) => {
183
+ setSteps((prev) => {
184
+ const i = prev.findIndex((s) => s.id === id);
185
+ if (i === -1) return prev;
186
+ if (dir === "up" && i === 0) return prev;
187
+ if (dir === "down" && i === prev.length - 1) return prev;
188
+ const next = [...prev];
189
+ const j = dir === "up" ? i - 1 : i + 1;
190
+ [next[i], next[j]] = [next[j], next[i]];
191
+ return next;
192
+ });
193
+ };
194
+ const extractDOM = react.useCallback(() => {
195
+ const walk = (el, depth) => {
196
+ var _a;
197
+ if (depth > 6) return "";
198
+ const tag = el.tagName.toLowerCase();
199
+ if (["script", "style", "noscript", "svg", "path"].includes(tag)) return "";
200
+ if ((_a = el.id) == null ? void 0 : _a.startsWith("otw-")) return "";
201
+ if (el.offsetParent === null && tag !== "body" && tag !== "html") return "";
202
+ const attrs = [];
203
+ if (el.id) attrs.push(`id="${el.id}"`);
204
+ if (el.className && typeof el.className === "string") {
205
+ const cls = el.className.split(/\s+/).filter(
206
+ (c) => !/^(w-|h-|p-|m-|text-|bg-|flex|grid|border|rounded|shadow|transition|transform|hover:|focus:|sm:|md:|lg:|xl:|2xl:)/.test(c)
207
+ ).slice(0, 3).join(" ");
208
+ if (cls) attrs.push(`class="${cls}"`);
209
+ }
210
+ if (el.type) attrs.push(`type="${el.type}"`);
211
+ if (el.name) attrs.push(`name="${el.name}"`);
212
+ if (el.placeholder) attrs.push(`placeholder="${el.placeholder}"`);
213
+ if (el.href && tag === "a") attrs.push(`href="..."`);
214
+ const ds = el.dataset;
215
+ if (ds == null ? void 0 : ds.onthewayId) attrs.push(`data-ontheway-id="${ds.onthewayId}"`);
216
+ const indent = " ".repeat(depth);
217
+ const attrStr = attrs.length ? " " + attrs.join(" ") : "";
218
+ const text = Array.from(el.childNodes).filter((n) => n.nodeType === 3).map((n) => {
219
+ var _a2;
220
+ return (_a2 = n.textContent) == null ? void 0 : _a2.trim();
221
+ }).filter(Boolean).join(" ").substring(0, 60);
222
+ const children = Array.from(el.children).map((c) => walk(c, depth + 1)).filter(Boolean).join("\n");
223
+ if (!children && !text && !["input", "button", "img", "video", "iframe"].includes(tag)) {
224
+ return "";
225
+ }
226
+ if (!children) {
227
+ return `${indent}<${tag}${attrStr}>${text ? " " + text + " " : ""}</${tag}>`;
228
+ }
229
+ return `${indent}<${tag}${attrStr}>${text ? " " + text : ""}
230
+ ${children}
231
+ ${indent}</${tag}>`;
232
+ };
233
+ return walk(document.body, 0);
234
+ }, []);
235
+ const aiGenerate = react.useCallback(async () => {
236
+ if (!aiIntent.trim()) {
237
+ setSaveMsg("\u274C Describe what the tour should do");
238
+ return;
239
+ }
240
+ setAiGenerating(true);
241
+ setSaveMsg("");
242
+ try {
243
+ const dom = extractDOM();
244
+ const res = await fetch(`${baseUrl}/api/ai/generate`, {
245
+ method: "POST",
246
+ headers: { "Content-Type": "application/json" },
247
+ body: JSON.stringify({
248
+ intent: aiIntent,
249
+ dom,
250
+ url: location.href,
251
+ taskName: taskName || void 0
252
+ })
253
+ });
254
+ const data = await res.json();
255
+ if (data.steps && data.steps.length > 0) {
256
+ const newSteps = data.steps.map((s, i) => ({
257
+ id: "ai_" + Date.now() + "_" + i,
258
+ selector: s.selector || "",
259
+ tagName: "",
260
+ innerText: "",
261
+ title: s.title || `Step ${i + 1}`,
262
+ description: s.content || s.description || "",
263
+ position: s.position || "auto",
264
+ spotlight: s.spotlight !== false,
265
+ url: location.href
266
+ }));
267
+ setSteps((prev) => [...prev, ...newSteps]);
268
+ if (!taskName && data.taskName) {
269
+ setTaskName(data.taskName);
270
+ }
271
+ setEditingStep(newSteps[0].id);
272
+ setSaveMsg(`\u2728 ${newSteps.length} steps generated (${data.source})`);
273
+ } else {
274
+ setSaveMsg("\u274C No steps generated");
275
+ }
276
+ } catch (e) {
277
+ setSaveMsg("\u274C AI generation failed");
278
+ }
279
+ setAiGenerating(false);
280
+ }, [aiIntent, baseUrl, extractDOM, taskName]);
281
+ const saveTask = async () => {
282
+ if (!taskName || !taskSlug || steps.length === 0) {
283
+ setSaveMsg("\u274C Fill name + at least 1 step");
284
+ return;
285
+ }
286
+ setSaving(true);
287
+ setSaveMsg("");
288
+ try {
289
+ const res = await fetch(`${baseUrl}/api/projects/${projectId}/tasks`, {
290
+ method: "POST",
291
+ headers: { "Content-Type": "application/json" },
292
+ body: JSON.stringify({
293
+ name: taskName,
294
+ slug: taskSlug,
295
+ trigger,
296
+ steps: steps.map((s) => ({
297
+ selector: s.selector,
298
+ title: s.title,
299
+ content: s.description,
300
+ position: s.position,
301
+ spotlight: s.spotlight
302
+ }))
303
+ })
304
+ });
305
+ if (res.ok) {
306
+ setSaveMsg("\u2705 Saved!");
307
+ setSteps([]);
308
+ setTaskName("");
309
+ setTaskSlug("");
310
+ setEditingStep(null);
311
+ stopRecording();
312
+ } else {
313
+ const err = await res.json();
314
+ setSaveMsg("\u274C " + (err.error || "Failed"));
315
+ }
316
+ } catch (e) {
317
+ setSaveMsg("\u274C Network error");
318
+ }
319
+ setSaving(false);
320
+ };
321
+ steps.find((s) => s.id === editingStep);
322
+ const S = {
323
+ panel: {
324
+ position: "fixed",
325
+ bottom: 16,
326
+ right: 16,
327
+ zIndex: 2147483646,
328
+ fontFamily: "system-ui, -apple-system, sans-serif",
329
+ fontSize: 13,
330
+ color: "#1f2937"
331
+ },
332
+ card: {
333
+ width: 360,
334
+ maxHeight: "80vh",
335
+ background: "#fff",
336
+ borderRadius: 12,
337
+ boxShadow: "0 8px 40px rgba(0,0,0,0.18)",
338
+ border: "1px solid #e5e7eb",
339
+ overflow: "hidden",
340
+ display: "flex",
341
+ flexDirection: "column"
342
+ },
343
+ header: {
344
+ display: "flex",
345
+ alignItems: "center",
346
+ justifyContent: "space-between",
347
+ padding: "10px 14px",
348
+ background: "#111",
349
+ color: "#fff",
350
+ fontSize: 13,
351
+ fontWeight: 600
352
+ },
353
+ tabs: {
354
+ display: "flex",
355
+ borderBottom: "1px solid #e5e7eb"
356
+ },
357
+ tab: (active) => ({
358
+ flex: 1,
359
+ padding: "8px 0",
360
+ border: "none",
361
+ background: active ? "#fff" : "#f9fafb",
362
+ borderBottom: active ? "2px solid #111" : "2px solid transparent",
363
+ cursor: "pointer",
364
+ fontSize: 12,
365
+ fontWeight: active ? 600 : 400,
366
+ color: active ? "#111" : "#6b7280"
367
+ }),
368
+ body: {
369
+ flex: 1,
370
+ overflow: "auto",
371
+ maxHeight: "calc(80vh - 100px)"
372
+ },
373
+ section: {
374
+ padding: "10px 14px",
375
+ borderBottom: "1px solid #f3f4f6"
376
+ },
377
+ input: {
378
+ width: "100%",
379
+ padding: "6px 8px",
380
+ border: "1px solid #d1d5db",
381
+ borderRadius: 6,
382
+ fontSize: 12,
383
+ marginTop: 4,
384
+ boxSizing: "border-box"
385
+ },
386
+ select: {
387
+ padding: "6px 8px",
388
+ border: "1px solid #d1d5db",
389
+ borderRadius: 6,
390
+ fontSize: 12,
391
+ marginTop: 4
392
+ },
393
+ btn: (color, disabled = false) => ({
394
+ padding: "6px 14px",
395
+ border: "none",
396
+ borderRadius: 6,
397
+ background: disabled ? "#d1d5db" : color,
398
+ color: "#fff",
399
+ fontSize: 12,
400
+ fontWeight: 600,
401
+ cursor: disabled ? "not-allowed" : "pointer"
402
+ }),
403
+ btnOutline: {
404
+ padding: "6px 14px",
405
+ border: "1px solid #d1d5db",
406
+ borderRadius: 6,
407
+ background: "#fff",
408
+ fontSize: 12,
409
+ cursor: "pointer"
410
+ },
411
+ stepItem: (active) => ({
412
+ padding: "8px 10px",
413
+ margin: "4px 0",
414
+ borderRadius: 6,
415
+ border: active ? "1px solid #3b82f6" : "1px solid #e5e7eb",
416
+ background: active ? "#eff6ff" : "#fff",
417
+ cursor: "pointer"
418
+ }),
419
+ fab: {
420
+ width: 48,
421
+ height: 48,
422
+ borderRadius: "50%",
423
+ border: "none",
424
+ background: "#111",
425
+ color: "#fff",
426
+ fontSize: 22,
427
+ cursor: "pointer",
428
+ boxShadow: "0 4px 16px rgba(0,0,0,0.2)",
429
+ display: "flex",
430
+ alignItems: "center",
431
+ justifyContent: "center"
432
+ },
433
+ label: {
434
+ fontSize: 11,
435
+ fontWeight: 600,
436
+ color: "#6b7280",
437
+ marginBottom: 2,
438
+ display: "block"
439
+ },
440
+ recDot: {
441
+ width: 8,
442
+ height: 8,
443
+ borderRadius: "50%",
444
+ background: "#ef4444",
445
+ animation: "otw-blink 1s ease-in-out infinite",
446
+ display: "inline-block",
447
+ marginRight: 6
448
+ }
449
+ };
450
+ react.useEffect(() => {
451
+ if (document.getElementById("otw-devtools-style")) return;
452
+ const style = document.createElement("style");
453
+ style.id = "otw-devtools-style";
454
+ style.textContent = "@keyframes otw-blink{0%,100%{opacity:1}50%{opacity:0.3}}";
455
+ document.head.appendChild(style);
456
+ return () => {
457
+ style.remove();
458
+ };
459
+ }, []);
460
+ const logoSvg = `data:image/svg+xml,${encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40" fill="none"><rect width="40" height="40" rx="10" fill="#111"/><path d="M12 32 C12 24,16 22,20 20 C24 18,28 16,28 8" stroke="#22c55e" stroke-width="3.5" stroke-linecap="round" fill="none"/><path d="M12 32 C12 24,16 22,20 20 C24 18,28 16,28 8" stroke="#fff" stroke-width="1.2" stroke-linecap="round" stroke-dasharray="2.5 3.5" fill="none" opacity="0.6"/><circle cx="28" cy="8" r="3.5" fill="#22c55e"/><circle cx="28" cy="8" r="1.5" fill="#111"/><circle cx="12" cy="32" r="2.5" fill="#fff" opacity="0.9"/></svg>')}`;
461
+ if (minimized) {
462
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: panelRef, style: S.panel, children: /* @__PURE__ */ jsxRuntime.jsx(
463
+ "button",
464
+ {
465
+ onClick: () => setMinimized(false),
466
+ style: chunk254YHUN3_cjs.__spreadValues(chunk254YHUN3_cjs.__spreadValues({}, S.fab), recording ? { background: "#22c55e", boxShadow: "0 0 20px rgba(34,197,94,0.5)" } : {}),
467
+ title: "OnTheWay DevTools",
468
+ children: recording ? /* @__PURE__ */ jsxRuntime.jsx("span", { style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ jsxRuntime.jsx("span", { style: S.recDot }) }) : /* @__PURE__ */ jsxRuntime.jsx("img", { src: logoSvg, alt: "OTW", style: { width: 24, height: 24 } })
469
+ }
470
+ ) });
471
+ }
472
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: panelRef, style: S.panel, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: S.card, children: [
473
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: S.header, children: [
474
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
475
+ /* @__PURE__ */ jsxRuntime.jsx("img", { src: logoSvg, alt: "OTW", style: { width: 18, height: 18 } }),
476
+ "OnTheWay DevTools"
477
+ ] }),
478
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", gap: 8, alignItems: "center" }, children: [
479
+ recording && /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "flex", alignItems: "center", fontSize: 11 }, children: [
480
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: S.recDot }),
481
+ " REC"
482
+ ] }),
483
+ /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => setMinimized(true), style: { background: "none", border: "none", color: "#fff", cursor: "pointer", fontSize: 16 }, children: "\u2212" })
484
+ ] })
485
+ ] }),
486
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: S.tabs, children: [
487
+ /* @__PURE__ */ jsxRuntime.jsx("button", { style: S.tab(tab === "record"), onClick: () => setTab("record"), children: "\u23FA Record" }),
488
+ /* @__PURE__ */ jsxRuntime.jsxs("button", { style: S.tab(tab === "tasks"), onClick: () => setTab("tasks"), children: [
489
+ "\u{1F4CB} Tasks (",
490
+ tasks.length,
491
+ ")"
492
+ ] })
493
+ ] }),
494
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: S.body, children: tab === "record" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
495
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: S.section, children: [
496
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8 }, children: [
497
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
498
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: S.label, children: "Task Name" }),
499
+ /* @__PURE__ */ jsxRuntime.jsx("input", { style: S.input, value: taskName, onChange: (e) => setTaskName(e.target.value), placeholder: "Welcome Tour" })
500
+ ] }),
501
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
502
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: S.label, children: "Trigger" }),
503
+ /* @__PURE__ */ jsxRuntime.jsxs("select", { style: chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({}, S.select), { width: "100%" }), value: trigger, onChange: (e) => setTrigger(e.target.value), children: [
504
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "manual", children: "Manual" }),
505
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "auto", children: "Auto" }),
506
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "first-visit", children: "First Visit" })
507
+ ] })
508
+ ] })
509
+ ] }),
510
+ taskSlug && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: 11, color: "#9ca3af", marginTop: 4 }, children: [
511
+ "slug: ",
512
+ taskSlug
513
+ ] })
514
+ ] }),
515
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({}, S.section), { display: "flex", gap: 8, flexWrap: "wrap" }), children: [
516
+ !recording ? /* @__PURE__ */ jsxRuntime.jsx("button", { style: S.btn("#22c55e"), onClick: startRecording, children: "\u23FA Record" }) : /* @__PURE__ */ jsxRuntime.jsx("button", { style: S.btn("#ef4444"), onClick: stopRecording, children: "\u23F9 Stop" }),
517
+ /* @__PURE__ */ jsxRuntime.jsx("button", { style: S.btn("#111", saving || steps.length === 0 || !taskName), onClick: saveTask, disabled: saving || steps.length === 0 || !taskName, children: saving ? "..." : "\u{1F4BE} Save" })
518
+ ] }),
519
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: S.section, children: [
520
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: S.label, children: "\u2728 AI Generate" }),
521
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", gap: 6, marginTop: 4 }, children: [
522
+ /* @__PURE__ */ jsxRuntime.jsx(
523
+ "input",
524
+ {
525
+ style: chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({}, S.input), { flex: 1, marginTop: 0 }),
526
+ value: aiIntent,
527
+ onChange: (e) => setAiIntent(e.target.value),
528
+ placeholder: "e.g. Guide new users to create their first project",
529
+ onKeyDown: (e) => {
530
+ if (e.key === "Enter" && !aiGenerating) aiGenerate();
531
+ }
532
+ }
533
+ ),
534
+ /* @__PURE__ */ jsxRuntime.jsx(
535
+ "button",
536
+ {
537
+ style: S.btn("#7c3aed", aiGenerating || !aiIntent.trim()),
538
+ onClick: aiGenerate,
539
+ disabled: aiGenerating || !aiIntent.trim(),
540
+ children: aiGenerating ? "..." : "\u2728"
541
+ }
542
+ )
543
+ ] }),
544
+ saveMsg && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 11, marginTop: 4, color: saveMsg.startsWith("\u2705") || saveMsg.startsWith("\u2728") ? "#16a34a" : saveMsg.startsWith("\u274C") ? "#dc2626" : "#6b7280" }, children: saveMsg })
545
+ ] }),
546
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: S.section, children: [
547
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { style: chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({}, S.label), { marginBottom: 6 }), children: [
548
+ "Steps (",
549
+ steps.length,
550
+ ")"
551
+ ] }),
552
+ steps.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { textAlign: "center", padding: "16px 0", color: "#9ca3af", fontSize: 12 }, children: recording ? "Click elements on the page to capture steps" : "Click Record to start" }) : steps.map((step, i) => /* @__PURE__ */ jsxRuntime.jsxs(
553
+ "div",
554
+ {
555
+ style: S.stepItem(editingStep === step.id),
556
+ onClick: () => setEditingStep(editingStep === step.id ? null : step.id),
557
+ children: [
558
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [
559
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontWeight: 500, fontSize: 12 }, children: [
560
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "#9ca3af", marginRight: 6 }, children: i + 1 }),
561
+ step.title
562
+ ] }),
563
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", gap: 4 }, children: [
564
+ /* @__PURE__ */ jsxRuntime.jsx(
565
+ "button",
566
+ {
567
+ onClick: (e) => {
568
+ e.stopPropagation();
569
+ moveStep(step.id, "up");
570
+ },
571
+ disabled: i === 0,
572
+ style: chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({}, S.btnOutline), { padding: "2px 6px", fontSize: 10 }),
573
+ children: "\u2191"
574
+ }
575
+ ),
576
+ /* @__PURE__ */ jsxRuntime.jsx(
577
+ "button",
578
+ {
579
+ onClick: (e) => {
580
+ e.stopPropagation();
581
+ moveStep(step.id, "down");
582
+ },
583
+ disabled: i === steps.length - 1,
584
+ style: chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({}, S.btnOutline), { padding: "2px 6px", fontSize: 10 }),
585
+ children: "\u2193"
586
+ }
587
+ ),
588
+ /* @__PURE__ */ jsxRuntime.jsx(
589
+ "button",
590
+ {
591
+ onClick: (e) => {
592
+ e.stopPropagation();
593
+ deleteStep(step.id);
594
+ },
595
+ style: chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({}, S.btnOutline), { padding: "2px 6px", fontSize: 10, color: "#ef4444" }),
596
+ children: "\u2715"
597
+ }
598
+ )
599
+ ] })
600
+ ] }),
601
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 10, color: "#9ca3af", fontFamily: "monospace", marginTop: 2, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: step.selector }),
602
+ editingStep === step.id && /* @__PURE__ */ jsxRuntime.jsxs(
603
+ "div",
604
+ {
605
+ style: { marginTop: 8, display: "flex", flexDirection: "column", gap: 6 },
606
+ onClick: (e) => e.stopPropagation(),
607
+ children: [
608
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
609
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: S.label, children: "Selector" }),
610
+ /* @__PURE__ */ jsxRuntime.jsx(
611
+ "input",
612
+ {
613
+ style: chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({}, S.input), { fontFamily: "monospace" }),
614
+ value: step.selector,
615
+ onChange: (e) => updateStep(step.id, { selector: e.target.value })
616
+ }
617
+ )
618
+ ] }),
619
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
620
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: S.label, children: "Title" }),
621
+ /* @__PURE__ */ jsxRuntime.jsx(
622
+ "input",
623
+ {
624
+ style: S.input,
625
+ value: step.title,
626
+ onChange: (e) => updateStep(step.id, { title: e.target.value })
627
+ }
628
+ )
629
+ ] }),
630
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
631
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: S.label, children: "Description" }),
632
+ /* @__PURE__ */ jsxRuntime.jsx(
633
+ "input",
634
+ {
635
+ style: S.input,
636
+ value: step.description,
637
+ onChange: (e) => updateStep(step.id, { description: e.target.value })
638
+ }
639
+ )
640
+ ] }),
641
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", gap: 8 }, children: [
642
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flex: 1 }, children: [
643
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: S.label, children: "Position" }),
644
+ /* @__PURE__ */ jsxRuntime.jsxs(
645
+ "select",
646
+ {
647
+ style: chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({}, S.select), { width: "100%" }),
648
+ value: step.position,
649
+ onChange: (e) => updateStep(step.id, { position: e.target.value }),
650
+ children: [
651
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "auto", children: "Auto" }),
652
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "top", children: "Top" }),
653
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "bottom", children: "Bottom" }),
654
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "left", children: "Left" }),
655
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "right", children: "Right" })
656
+ ]
657
+ }
658
+ )
659
+ ] }),
660
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", alignItems: "end", paddingBottom: 2 }, children: /* @__PURE__ */ jsxRuntime.jsxs("label", { style: { fontSize: 11, display: "flex", alignItems: "center", gap: 4 }, children: [
661
+ /* @__PURE__ */ jsxRuntime.jsx(
662
+ "input",
663
+ {
664
+ type: "checkbox",
665
+ checked: step.spotlight,
666
+ onChange: (e) => updateStep(step.id, { spotlight: e.target.checked })
667
+ }
668
+ ),
669
+ "Spotlight"
670
+ ] }) })
671
+ ] })
672
+ ]
673
+ }
674
+ )
675
+ ]
676
+ },
677
+ step.id
678
+ ))
679
+ ] })
680
+ ] }) : (
681
+ /* Tasks tab */
682
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: S.section, children: [
683
+ loadingTasks ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { textAlign: "center", padding: 16, color: "#9ca3af" }, children: "Loading..." }) : tasks.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { textAlign: "center", padding: 16, color: "#9ca3af" }, children: "No tasks yet" }) : tasks.map((task) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({}, S.stepItem(false)), { display: "flex", justifyContent: "space-between", alignItems: "center" }), children: [
684
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
685
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontWeight: 500, fontSize: 12 }, children: task.name }),
686
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: 10, color: "#9ca3af" }, children: [
687
+ task.slug,
688
+ " \xB7 ",
689
+ task.steps.length,
690
+ " steps"
691
+ ] })
692
+ ] }),
693
+ /* @__PURE__ */ jsxRuntime.jsx(
694
+ "button",
695
+ {
696
+ style: S.btn("#111"),
697
+ onClick: () => {
698
+ if (window.ontheway) {
699
+ window.ontheway.start(task.slug);
700
+ }
701
+ },
702
+ children: "\u25B6"
703
+ }
704
+ )
705
+ ] }, task.id)),
706
+ /* @__PURE__ */ jsxRuntime.jsx("button", { style: chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({}, S.btnOutline), { width: "100%", marginTop: 8 }), onClick: fetchTasks, children: "\u21BB Refresh" })
707
+ ] })
708
+ ) })
709
+ ] }) });
710
+ }
711
+ var OnTheWayDevTools = {
712
+ init(config) {
713
+ if (typeof window === "undefined") return;
714
+ if (typeof document === "undefined") return;
715
+ console.log(
716
+ "%c\u{1F6E4}\uFE0F OnTheWay DevTools %c Use <OnTheWayDevToolsPanel /> in React, or import the standalone recorder-snippet.js",
717
+ "background:#22c55e;color:#fff;padding:4px 8px;border-radius:4px;font-weight:bold",
718
+ "color:#666"
719
+ );
720
+ const script = document.createElement("script");
721
+ script.src = (config.serverUrl || "") + "/recorder-snippet.js";
722
+ script.dataset.session = "devtools_" + Date.now().toString(36);
723
+ script.dataset.server = config.serverUrl || window.location.origin;
724
+ document.head.appendChild(script);
725
+ }
726
+ };
727
+ var devtools_default = OnTheWayDevToolsPanel;
728
+
729
+ exports.OnTheWayDevTools = OnTheWayDevTools;
730
+ exports.OnTheWayDevToolsPanel = OnTheWayDevToolsPanel;
731
+ exports.default = devtools_default;
732
+ //# sourceMappingURL=devtools.cjs.map
733
+ //# sourceMappingURL=devtools.cjs.map