@burdenoff/microfe-tours 2026.608.1 → 2026.624.1
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/dist/tours/ToursUserRoutes.js +3 -3
- package/dist/tours/ToursUserRoutes.js.map +1 -1
- package/dist/tours/components/RouteHelpers.js +6 -6
- package/dist/tours/components/RouteHelpers.js.map +1 -1
- package/dist/tours/pages/AnalyticsDashboardPage.js +21 -21
- package/dist/tours/pages/AnalyticsDashboardPage.js.map +1 -1
- package/dist/tours/pages/MediaLibraryPage.js +18 -18
- package/dist/tours/pages/MediaLibraryPage.js.map +1 -1
- package/dist/tours/pages/MyToursPage.js +10 -10
- package/dist/tours/pages/MyToursPage.js.map +1 -1
- package/dist/tours/pages/MyToursProgressPage.js +11 -11
- package/dist/tours/pages/MyToursProgressPage.js.map +1 -1
- package/dist/tours/pages/SchedulerPage.js +15 -15
- package/dist/tours/pages/SchedulerPage.js.map +1 -1
- package/dist/tours/pages/StepEditorPage.js +47 -47
- package/dist/tours/pages/StepEditorPage.js.map +1 -1
- package/dist/tours/pages/SystemAnalyticsPage.js +17 -17
- package/dist/tours/pages/SystemAnalyticsPage.js.map +1 -1
- package/dist/tours/pages/TemplateLibraryPage.js +19 -19
- package/dist/tours/pages/TemplateLibraryPage.js.map +1 -1
- package/dist/tours/pages/TourBuilderPage.js +39 -39
- package/dist/tours/pages/TourBuilderPage.js.map +1 -1
- package/dist/tours/pages/TourPreviewPage.js +26 -26
- package/dist/tours/pages/TourPreviewPage.js.map +1 -1
- package/dist/tours/pages/ToursListPage.js +24 -24
- package/dist/tours/pages/ToursListPage.js.map +1 -1
- package/package.json +1 -1
|
@@ -66,9 +66,9 @@ function x() {
|
|
|
66
66
|
I(e), K && G(!1);
|
|
67
67
|
};
|
|
68
68
|
return /* @__PURE__ */ v("div", {
|
|
69
|
-
className: "flex flex-col h-full bg-
|
|
69
|
+
className: "flex flex-col h-full bg-bg-surface",
|
|
70
70
|
children: [/* @__PURE__ */ v("div", {
|
|
71
|
-
className: "border-b border-border p-3 sm:p-4 flex flex-col sm:flex-row sm:items-center gap-3 sm:gap-4 bg-
|
|
71
|
+
className: "border-b border-border-subtle p-3 sm:p-4 flex flex-col sm:flex-row sm:items-center gap-3 sm:gap-4 bg-bg-surface",
|
|
72
72
|
children: [/* @__PURE__ */ v("div", {
|
|
73
73
|
className: "flex items-center gap-3",
|
|
74
74
|
children: [/* @__PURE__ */ _("button", {
|
|
@@ -87,7 +87,7 @@ function x() {
|
|
|
87
87
|
x("stepEditor.stepsLabel")
|
|
88
88
|
]
|
|
89
89
|
}), /* @__PURE__ */ v("p", {
|
|
90
|
-
className: "text-xs sm:text-sm text-
|
|
90
|
+
className: "text-xs sm:text-sm text-text-secondary",
|
|
91
91
|
children: [
|
|
92
92
|
P.length,
|
|
93
93
|
" ",
|
|
@@ -101,7 +101,7 @@ function x() {
|
|
|
101
101
|
K && /* @__PURE__ */ v("button", {
|
|
102
102
|
type: "button",
|
|
103
103
|
onClick: () => G(!W),
|
|
104
|
-
className: "px-3 py-2 border border-border rounded-md hover:bg-accent flex items-center gap-2 sm:hidden",
|
|
104
|
+
className: "px-3 py-2 border border-border-subtle rounded-md hover:bg-accent flex items-center gap-2 sm:hidden",
|
|
105
105
|
children: [
|
|
106
106
|
/* @__PURE__ */ _(m, { size: 18 }),
|
|
107
107
|
/* @__PURE__ */ _("span", {
|
|
@@ -109,7 +109,7 @@ function x() {
|
|
|
109
109
|
children: x("stepEditor.steps")
|
|
110
110
|
}),
|
|
111
111
|
P.length > 0 && /* @__PURE__ */ _("span", {
|
|
112
|
-
className: "px-1.5 py-0.5 text-xs bg-primary/20 rounded-full",
|
|
112
|
+
className: "px-1.5 py-0.5 text-xs bg-action-primary-bg/20 rounded-full",
|
|
113
113
|
children: P.length
|
|
114
114
|
})
|
|
115
115
|
]
|
|
@@ -117,7 +117,7 @@ function x() {
|
|
|
117
117
|
D && /* @__PURE__ */ v("button", {
|
|
118
118
|
type: "button",
|
|
119
119
|
onClick: Q,
|
|
120
|
-
className: "px-3 sm:px-4 py-2 border border-border rounded-md hover:bg-accent flex items-center gap-2 text-sm sm:text-base",
|
|
120
|
+
className: "px-3 sm:px-4 py-2 border border-border-subtle rounded-md hover:bg-accent flex items-center gap-2 text-sm sm:text-base",
|
|
121
121
|
children: [/* @__PURE__ */ _(g, { size: 18 }), /* @__PURE__ */ _("span", {
|
|
122
122
|
className: "hidden xs:inline",
|
|
123
123
|
children: x("stepEditor.addStep")
|
|
@@ -129,7 +129,7 @@ function x() {
|
|
|
129
129
|
type: "button",
|
|
130
130
|
onClick: fe,
|
|
131
131
|
disabled: N || !O,
|
|
132
|
-
className: "px-3 sm:px-4 py-2 bg-primary text-primary-
|
|
132
|
+
className: "px-3 sm:px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg/90 disabled:opacity-50 flex items-center gap-2 text-sm sm:text-base",
|
|
133
133
|
children: [/* @__PURE__ */ _(ne, { size: 18 }), /* @__PURE__ */ _("span", {
|
|
134
134
|
className: "hidden xs:inline",
|
|
135
135
|
children: x(N ? "stepEditor.saving" : "stepEditor.save")
|
|
@@ -151,10 +151,10 @@ function x() {
|
|
|
151
151
|
className: `
|
|
152
152
|
${K ? "fixed inset-y-0 left-0 z-50 w-[min(18rem,calc(100vw-2rem))] transform transition-transform duration-300" : "w-64 lg:w-80 shrink-0"}
|
|
153
153
|
${K && !W ? "-translate-x-full" : "translate-x-0"}
|
|
154
|
-
border-r border-border overflow-y-auto bg-
|
|
154
|
+
border-r border-border-subtle overflow-y-auto bg-bg-surface
|
|
155
155
|
`,
|
|
156
156
|
children: [K && /* @__PURE__ */ v("div", {
|
|
157
|
-
className: "flex items-center justify-between p-4 border-b border-border sticky top-0 bg-
|
|
157
|
+
className: "flex items-center justify-between p-4 border-b border-border-subtle sticky top-0 bg-bg-surface z-10",
|
|
158
158
|
children: [/* @__PURE__ */ _("h2", {
|
|
159
159
|
className: "font-semibold",
|
|
160
160
|
children: x("stepEditor.tourSteps")
|
|
@@ -168,7 +168,7 @@ function x() {
|
|
|
168
168
|
}), /* @__PURE__ */ _("div", {
|
|
169
169
|
className: "p-3 sm:p-4 space-y-2",
|
|
170
170
|
children: P.length === 0 ? /* @__PURE__ */ v("div", {
|
|
171
|
-
className: "text-center py-8 text-
|
|
171
|
+
className: "text-center py-8 text-text-secondary",
|
|
172
172
|
children: [/* @__PURE__ */ _("p", {
|
|
173
173
|
className: "text-sm",
|
|
174
174
|
children: x("stepEditor.noStepsYet")
|
|
@@ -183,14 +183,14 @@ function x() {
|
|
|
183
183
|
onKeyDown: (t) => {
|
|
184
184
|
(t.key === "Enter" || t.key === " ") && (t.preventDefault(), $(e));
|
|
185
185
|
},
|
|
186
|
-
className: `p-3 border rounded-md cursor-pointer transition-colors ${F?.id === e.id ? "border-primary bg-primary/10" : "border-border hover:bg-accent"}`,
|
|
186
|
+
className: `p-3 border rounded-md cursor-pointer transition-colors ${F?.id === e.id ? "border-primary bg-action-primary-bg/10" : "border-border-subtle hover:bg-accent"}`,
|
|
187
187
|
children: /* @__PURE__ */ v("div", {
|
|
188
188
|
className: "flex items-start justify-between gap-2",
|
|
189
189
|
children: [/* @__PURE__ */ v("div", {
|
|
190
190
|
className: "flex-1 min-w-0",
|
|
191
191
|
children: [
|
|
192
192
|
/* @__PURE__ */ v("div", {
|
|
193
|
-
className: "text-xs text-
|
|
193
|
+
className: "text-xs text-text-secondary mb-1",
|
|
194
194
|
children: [
|
|
195
195
|
x("stepEditor.stepNumber"),
|
|
196
196
|
" ",
|
|
@@ -202,7 +202,7 @@ function x() {
|
|
|
202
202
|
children: e.title || x("stepEditor.untitled")
|
|
203
203
|
}),
|
|
204
204
|
e.targetSelector && /* @__PURE__ */ _("div", {
|
|
205
|
-
className: "text-xs text-
|
|
205
|
+
className: "text-xs text-text-secondary mt-1 truncate font-mono",
|
|
206
206
|
children: e.targetSelector
|
|
207
207
|
})
|
|
208
208
|
]
|
|
@@ -236,7 +236,7 @@ function x() {
|
|
|
236
236
|
onClick: (t) => {
|
|
237
237
|
t.stopPropagation(), R(e.id);
|
|
238
238
|
},
|
|
239
|
-
className: "p-1.5 sm:p-2 min-h-[32px] min-w-[32px] sm:min-h-[40px] sm:min-w-[40px] hover:bg-
|
|
239
|
+
className: "p-1.5 sm:p-2 min-h-[32px] min-w-[32px] sm:min-h-[40px] sm:min-w-[40px] hover:bg-status-error-bg/10 rounded text-status-error-text",
|
|
240
240
|
title: x("stepEditor.deleteStep"),
|
|
241
241
|
"aria-label": x("stepEditor.deleteStep"),
|
|
242
242
|
children: /* @__PURE__ */ _(re, { size: 14 })
|
|
@@ -253,7 +253,7 @@ function x() {
|
|
|
253
253
|
className: "max-w-2xl mx-auto space-y-4 sm:space-y-6",
|
|
254
254
|
children: [
|
|
255
255
|
K && P.length > 1 && /* @__PURE__ */ v("div", {
|
|
256
|
-
className: "flex items-center justify-between bg-
|
|
256
|
+
className: "flex items-center justify-between bg-bg-sunken/50 rounded-lg p-2 mb-4",
|
|
257
257
|
children: [
|
|
258
258
|
/* @__PURE__ */ _("button", {
|
|
259
259
|
type: "button",
|
|
@@ -267,7 +267,7 @@ function x() {
|
|
|
267
267
|
children: /* @__PURE__ */ _(d, { size: 20 })
|
|
268
268
|
}),
|
|
269
269
|
/* @__PURE__ */ v("span", {
|
|
270
|
-
className: "text-sm text-
|
|
270
|
+
className: "text-sm text-text-secondary",
|
|
271
271
|
children: [
|
|
272
272
|
x("stepEditor.stepNumber"),
|
|
273
273
|
" ",
|
|
@@ -304,7 +304,7 @@ function x() {
|
|
|
304
304
|
type: "text",
|
|
305
305
|
value: F.title,
|
|
306
306
|
onChange: (e) => z(F.id, "title", e.target.value),
|
|
307
|
-
className: "w-full px-3 py-2 border border-border rounded-md bg-
|
|
307
|
+
className: "w-full px-3 py-2 border border-border-subtle rounded-md bg-bg-surface text-sm sm:text-base",
|
|
308
308
|
placeholder: x("stepEditor.stepTitlePlaceholder"),
|
|
309
309
|
"aria-label": x("stepEditor.stepTitle")
|
|
310
310
|
})] }),
|
|
@@ -317,7 +317,7 @@ function x() {
|
|
|
317
317
|
value: F.content,
|
|
318
318
|
onChange: (e) => z(F.id, "content", e.target.value),
|
|
319
319
|
rows: 4,
|
|
320
|
-
className: "w-full px-3 py-2 border border-border rounded-md bg-
|
|
320
|
+
className: "w-full px-3 py-2 border border-border-subtle rounded-md bg-bg-surface text-sm sm:text-base resize-y min-h-[100px]",
|
|
321
321
|
placeholder: x("stepEditor.contentPlaceholder"),
|
|
322
322
|
"aria-label": x("stepEditor.content")
|
|
323
323
|
})] }),
|
|
@@ -329,7 +329,7 @@ function x() {
|
|
|
329
329
|
x("stepEditor.cssSelector"),
|
|
330
330
|
" *",
|
|
331
331
|
/* @__PURE__ */ v("span", {
|
|
332
|
-
className: "text-
|
|
332
|
+
className: "text-text-secondary font-normal ml-2",
|
|
333
333
|
children: [
|
|
334
334
|
"(",
|
|
335
335
|
x("stepEditor.targetElement"),
|
|
@@ -344,11 +344,11 @@ function x() {
|
|
|
344
344
|
value: F.targetSelector || "",
|
|
345
345
|
onChange: (e) => z(F.id, "targetSelector", e.target.value),
|
|
346
346
|
placeholder: x("stepEditor.cssSelectorPlaceholder"),
|
|
347
|
-
className: "w-full px-3 py-2 border border-border rounded-md bg-
|
|
347
|
+
className: "w-full px-3 py-2 border border-border-subtle rounded-md bg-bg-surface font-mono text-sm",
|
|
348
348
|
"aria-label": "{tr('stepEditor.cssSelector')} *\n \n ({tr('stepEditor.targetElement')})"
|
|
349
349
|
}),
|
|
350
350
|
/* @__PURE__ */ _("p", {
|
|
351
|
-
className: "text-xs text-
|
|
351
|
+
className: "text-xs text-text-secondary mt-1",
|
|
352
352
|
children: x("stepEditor.dataTourHint")
|
|
353
353
|
})
|
|
354
354
|
] }),
|
|
@@ -360,7 +360,7 @@ function x() {
|
|
|
360
360
|
id: "step-editor-placement",
|
|
361
361
|
value: F.placement,
|
|
362
362
|
onChange: (e) => z(F.id, "placement", e.target.value),
|
|
363
|
-
className: "w-full px-3 py-2 border border-border rounded-md bg-
|
|
363
|
+
className: "w-full px-3 py-2 border border-border-subtle rounded-md bg-bg-surface text-sm sm:text-base",
|
|
364
364
|
"aria-label": x("stepEditor.tooltipPlacement"),
|
|
365
365
|
children: [
|
|
366
366
|
/* @__PURE__ */ _("option", {
|
|
@@ -390,15 +390,15 @@ function x() {
|
|
|
390
390
|
]
|
|
391
391
|
})] }),
|
|
392
392
|
/* @__PURE__ */ v("details", {
|
|
393
|
-
className: "border border-border rounded-md",
|
|
393
|
+
className: "border border-border-subtle rounded-md",
|
|
394
394
|
children: [/* @__PURE__ */ _("summary", {
|
|
395
395
|
className: "px-4 py-3 cursor-pointer font-medium text-sm hover:bg-accent/50 rounded-t-md",
|
|
396
396
|
children: x("stepEditor.deviceSpecificSelectors")
|
|
397
397
|
}), /* @__PURE__ */ v("div", {
|
|
398
|
-
className: "p-4 pt-0 space-y-3 border-t border-border",
|
|
398
|
+
className: "p-4 pt-0 space-y-3 border-t border-border-subtle",
|
|
399
399
|
children: [
|
|
400
400
|
/* @__PURE__ */ _("p", {
|
|
401
|
-
className: "text-xs text-
|
|
401
|
+
className: "text-xs text-text-secondary mb-3",
|
|
402
402
|
children: x("stepEditor.deviceSelectorHint")
|
|
403
403
|
}),
|
|
404
404
|
/* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("label", {
|
|
@@ -411,7 +411,7 @@ function x() {
|
|
|
411
411
|
value: F.targetSelectorMobile || "",
|
|
412
412
|
onChange: (e) => z(F.id, "targetSelectorMobile", e.target.value),
|
|
413
413
|
placeholder: x("stepEditor.leaveEmptyDefault"),
|
|
414
|
-
className: "w-full px-3 py-2 border border-border rounded-md bg-
|
|
414
|
+
className: "w-full px-3 py-2 border border-border-subtle rounded-md bg-bg-surface text-sm font-mono",
|
|
415
415
|
"aria-label": x("stepEditor.mobileSelector")
|
|
416
416
|
})] }),
|
|
417
417
|
/* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("label", {
|
|
@@ -424,7 +424,7 @@ function x() {
|
|
|
424
424
|
value: F.targetSelectorTablet || "",
|
|
425
425
|
onChange: (e) => z(F.id, "targetSelectorTablet", e.target.value),
|
|
426
426
|
placeholder: x("stepEditor.leaveEmptyDefault"),
|
|
427
|
-
className: "w-full px-3 py-2 border border-border rounded-md bg-
|
|
427
|
+
className: "w-full px-3 py-2 border border-border-subtle rounded-md bg-bg-surface text-sm font-mono",
|
|
428
428
|
"aria-label": x("stepEditor.tabletSelector")
|
|
429
429
|
})] }),
|
|
430
430
|
/* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("label", {
|
|
@@ -437,7 +437,7 @@ function x() {
|
|
|
437
437
|
value: F.targetSelectorDesktop || "",
|
|
438
438
|
onChange: (e) => z(F.id, "targetSelectorDesktop", e.target.value),
|
|
439
439
|
placeholder: x("stepEditor.leaveEmptyDefault"),
|
|
440
|
-
className: "w-full px-3 py-2 border border-border rounded-md bg-
|
|
440
|
+
className: "w-full px-3 py-2 border border-border-subtle rounded-md bg-bg-surface text-sm font-mono",
|
|
441
441
|
"aria-label": x("stepEditor.desktopSelector")
|
|
442
442
|
})] })
|
|
443
443
|
]
|
|
@@ -446,7 +446,7 @@ function x() {
|
|
|
446
446
|
/* @__PURE__ */ v("div", {
|
|
447
447
|
className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
|
|
448
448
|
children: [/* @__PURE__ */ v("label", {
|
|
449
|
-
className: "flex items-center gap-3 cursor-pointer rounded-md border border-border p-3",
|
|
449
|
+
className: "flex items-center gap-3 cursor-pointer rounded-md border border-border-subtle p-3",
|
|
450
450
|
children: [/* @__PURE__ */ _("input", {
|
|
451
451
|
type: "checkbox",
|
|
452
452
|
checked: F.requireInteraction ?? !1,
|
|
@@ -457,7 +457,7 @@ function x() {
|
|
|
457
457
|
className: "text-sm font-medium",
|
|
458
458
|
children: "Require interaction"
|
|
459
459
|
}), /* @__PURE__ */ _("div", {
|
|
460
|
-
className: "text-xs text-
|
|
460
|
+
className: "text-xs text-text-secondary",
|
|
461
461
|
children: "User must interact with the highlighted element before advancing."
|
|
462
462
|
})] })]
|
|
463
463
|
}), /* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("label", {
|
|
@@ -470,7 +470,7 @@ function x() {
|
|
|
470
470
|
min: "0",
|
|
471
471
|
value: F.waitForTimeout ?? "",
|
|
472
472
|
onChange: (e) => z(F.id, "waitForTimeout", e.target.value ? Number(e.target.value) : void 0),
|
|
473
|
-
className: "w-full px-3 py-2 border border-border rounded-md bg-
|
|
473
|
+
className: "w-full px-3 py-2 border border-border-subtle rounded-md bg-bg-surface text-sm",
|
|
474
474
|
placeholder: "1500",
|
|
475
475
|
"aria-label": "Wait for timeout (ms)"
|
|
476
476
|
})] })]
|
|
@@ -489,7 +489,7 @@ function x() {
|
|
|
489
489
|
type: "text",
|
|
490
490
|
value: F.waitForSelector || "",
|
|
491
491
|
onChange: (e) => z(F.id, "waitForSelector", e.target.value || void 0),
|
|
492
|
-
className: "w-full px-3 py-2 border border-border rounded-md bg-
|
|
492
|
+
className: "w-full px-3 py-2 border border-border-subtle rounded-md bg-bg-surface text-sm font-mono",
|
|
493
493
|
placeholder: "[data-tour='agents-tabs']",
|
|
494
494
|
"aria-label": "Wait for selector"
|
|
495
495
|
})] }), /* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("label", {
|
|
@@ -501,7 +501,7 @@ function x() {
|
|
|
501
501
|
type: "text",
|
|
502
502
|
value: F.waitForEvent || "",
|
|
503
503
|
onChange: (e) => z(F.id, "waitForEvent", e.target.value || void 0),
|
|
504
|
-
className: "w-full px-3 py-2 border border-border rounded-md bg-
|
|
504
|
+
className: "w-full px-3 py-2 border border-border-subtle rounded-md bg-bg-surface text-sm",
|
|
505
505
|
placeholder: "tour:ready",
|
|
506
506
|
"aria-label": "Wait for event"
|
|
507
507
|
})] })]
|
|
@@ -527,14 +527,14 @@ function x() {
|
|
|
527
527
|
}
|
|
528
528
|
},
|
|
529
529
|
rows: 4,
|
|
530
|
-
className: "w-full px-3 py-2 border border-border rounded-md bg-
|
|
530
|
+
className: "w-full px-3 py-2 border border-border-subtle rounded-md bg-bg-surface text-sm font-mono",
|
|
531
531
|
placeholder: "{\"selectorMissing\":\"[data-tour=\\\"missing\\\"]\"}",
|
|
532
532
|
"aria-label": "Skip conditions (JSON)"
|
|
533
533
|
})]
|
|
534
534
|
})]
|
|
535
535
|
}),
|
|
536
536
|
/* @__PURE__ */ v("div", {
|
|
537
|
-
className: "border border-border rounded-md p-4 space-y-4",
|
|
537
|
+
className: "border border-border-subtle rounded-md p-4 space-y-4",
|
|
538
538
|
children: [
|
|
539
539
|
/* @__PURE__ */ v("div", {
|
|
540
540
|
className: "flex items-center gap-2",
|
|
@@ -546,20 +546,20 @@ function x() {
|
|
|
546
546
|
F.media && F.media.length > 0 ? /* @__PURE__ */ _("div", {
|
|
547
547
|
className: "space-y-2",
|
|
548
548
|
children: F.media.map((e) => /* @__PURE__ */ v("div", {
|
|
549
|
-
className: "flex items-center justify-between rounded-md border border-border p-2 text-sm",
|
|
549
|
+
className: "flex items-center justify-between rounded-md border border-border-subtle p-2 text-sm",
|
|
550
550
|
children: [/* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("div", {
|
|
551
551
|
className: "font-medium",
|
|
552
552
|
children: e.media.name
|
|
553
553
|
}), /* @__PURE__ */ _("div", {
|
|
554
|
-
className: "text-xs text-
|
|
554
|
+
className: "text-xs text-text-secondary",
|
|
555
555
|
children: e.position
|
|
556
556
|
})] }), /* @__PURE__ */ _("span", {
|
|
557
|
-
className: "text-xs text-
|
|
557
|
+
className: "text-xs text-text-secondary",
|
|
558
558
|
children: e.media.type
|
|
559
559
|
})]
|
|
560
560
|
}, e.id))
|
|
561
561
|
}) : /* @__PURE__ */ _("p", {
|
|
562
|
-
className: "text-sm text-
|
|
562
|
+
className: "text-sm text-text-secondary",
|
|
563
563
|
children: "No media attached to this step yet."
|
|
564
564
|
}),
|
|
565
565
|
/* @__PURE__ */ v("div", {
|
|
@@ -568,7 +568,7 @@ function x() {
|
|
|
568
568
|
/* @__PURE__ */ v("select", {
|
|
569
569
|
value: J,
|
|
570
570
|
onChange: (e) => Y(e.target.value),
|
|
571
|
-
className: "w-full px-3 py-2 border border-border rounded-md bg-
|
|
571
|
+
className: "w-full px-3 py-2 border border-border-subtle rounded-md bg-bg-surface text-sm",
|
|
572
572
|
"aria-label": "Select media to attach",
|
|
573
573
|
children: [/* @__PURE__ */ _("option", {
|
|
574
574
|
value: "",
|
|
@@ -586,7 +586,7 @@ function x() {
|
|
|
586
586
|
/* @__PURE__ */ v("select", {
|
|
587
587
|
value: X,
|
|
588
588
|
onChange: (e) => ue(e.target.value),
|
|
589
|
-
className: "w-full px-3 py-2 border border-border rounded-md bg-
|
|
589
|
+
className: "w-full px-3 py-2 border border-border-subtle rounded-md bg-bg-surface text-sm",
|
|
590
590
|
"aria-label": "Attachment position",
|
|
591
591
|
children: [
|
|
592
592
|
/* @__PURE__ */ _("option", {
|
|
@@ -607,7 +607,7 @@ function x() {
|
|
|
607
607
|
type: "button",
|
|
608
608
|
onClick: me,
|
|
609
609
|
disabled: de || !J,
|
|
610
|
-
className: "px-4 py-2 min-h-[44px] border border-border rounded-md hover:bg-accent disabled:opacity-50",
|
|
610
|
+
className: "px-4 py-2 min-h-[44px] border border-border-subtle rounded-md hover:bg-accent disabled:opacity-50",
|
|
611
611
|
children: "Attach"
|
|
612
612
|
})
|
|
613
613
|
]
|
|
@@ -619,24 +619,24 @@ function x() {
|
|
|
619
619
|
className: "flex flex-col items-center justify-center h-full text-center px-4",
|
|
620
620
|
children: [
|
|
621
621
|
/* @__PURE__ */ _("div", {
|
|
622
|
-
className: "size-16 bg-
|
|
622
|
+
className: "size-16 bg-bg-sunken rounded-full flex items-center justify-center mb-4",
|
|
623
623
|
children: /* @__PURE__ */ _(g, {
|
|
624
624
|
size: 24,
|
|
625
|
-
className: "text-
|
|
625
|
+
className: "text-text-secondary"
|
|
626
626
|
})
|
|
627
627
|
}),
|
|
628
628
|
/* @__PURE__ */ _("p", {
|
|
629
|
-
className: "text-
|
|
629
|
+
className: "text-text-secondary mb-2",
|
|
630
630
|
children: x("stepEditor.noStepSelected")
|
|
631
631
|
}),
|
|
632
632
|
/* @__PURE__ */ _("p", {
|
|
633
|
-
className: "text-sm text-
|
|
633
|
+
className: "text-sm text-text-secondary mb-4",
|
|
634
634
|
children: P.length > 0 ? x("stepEditor.selectStepToEdit") : x("stepEditor.createFirstStep")
|
|
635
635
|
}),
|
|
636
636
|
P.length === 0 && D && /* @__PURE__ */ v("button", {
|
|
637
637
|
type: "button",
|
|
638
638
|
onClick: Q,
|
|
639
|
-
className: "px-4 py-2 min-h-[44px] bg-primary text-primary-
|
|
639
|
+
className: "px-4 py-2 min-h-[44px] bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg/90 flex items-center gap-2",
|
|
640
640
|
children: [/* @__PURE__ */ _(g, { size: 18 }), x("stepEditor.addFirstStep")]
|
|
641
641
|
})
|
|
642
642
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StepEditorPage.js","names":[],"sources":["../../../src/tours/pages/StepEditorPage.tsx"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport { useParams, useNavigate } from 'react-router-dom';\nimport {\n ArrowLeft,\n Plus,\n Save,\n Trash2,\n ChevronLeft,\n ChevronRight,\n ChevronUp,\n ChevronDown,\n Menu,\n Paperclip,\n X,\n} from 'lucide-react';\nimport { PermissionGate } from '@burdenoff/fe-libs/shared/components';\nimport { useEventBus } from '@burdenoff/fe-libs/shared/events';\nimport { OptionalFields } from '@burdenoff/fe-libs/ui';\nimport { useStepSequencer } from '../hooks/useStepSequencer';\nimport { useTourBuilder } from '../hooks/useTourBuilder';\nimport { useMediaLibrary } from '../hooks/useMediaLibrary';\nimport { useToursPermissionAccess } from '../hooks/useToursPermissionAccess';\nimport { useToursContext } from '../providers/ToursProvider';\nimport { TOUR_PERMISSIONS } from '../../constants/permissions';\nimport { useToursI18n } from '../i18n';\nimport { emitToursApiFailed } from '../telemetry';\n\n/**\n * Step editor page\n * Manage tour steps with sequencer and editor\n * Responsive: sidebar drawer on mobile, side panel on desktop\n */\nexport function StepEditorPage() {\n const { tr } = useToursI18n();\n\n const { tourId, stepId } = useParams();\n const navigate = useNavigate();\n const toursContext = useToursContext();\n const { basePath = '/' } = toursContext;\n const eventBus = useEventBus();\n const { hasPermission } = useToursPermissionAccess();\n const canCreateStep = hasPermission(TOUR_PERMISSIONS.TOUR_STEP_CREATE);\n const canUpdateStep = hasPermission(TOUR_PERMISSIONS.TOUR_STEP_UPDATE);\n const canDeleteStep = hasPermission(TOUR_PERMISSIONS.TOUR_STEP_DELETE);\n\n const { tour, loadTour, syncSteps, saving } = useTourBuilder(tourId);\n const { steps, selectedStep, selectStep, createStep, deleteStep, updateStepField, moveStep } =\n useStepSequencer();\n const { media, fetchMedia, attachToStep, loading: mediaLoading } = useMediaLibrary();\n\n // Mobile sidebar state\n const [isSidebarOpen, setIsSidebarOpen] = useState(false);\n const [isMobile, setIsMobile] = useState(\n () => typeof window !== 'undefined' && window.innerWidth < 768\n );\n const [attachmentMediaId, setAttachmentMediaId] = useState('');\n const [attachmentPosition, setAttachmentPosition] = useState<'header' | 'body' | 'footer'>(\n 'body'\n );\n const [attachingMedia, setAttachingMedia] = useState(false);\n\n // Detect mobile viewport\n useEffect(() => {\n const checkMobile = () => {\n const mobile = window.innerWidth < 768;\n setIsMobile(mobile);\n // Auto-close sidebar on desktop\n if (!mobile) {\n setIsSidebarOpen(false);\n }\n };\n window.addEventListener('resize', checkMobile);\n return () => window.removeEventListener('resize', checkMobile);\n }, []);\n\n useEffect(() => {\n if (tourId) {\n loadTour(tourId);\n }\n }, [tourId, loadTour]);\n\n useEffect(() => {\n void fetchMedia();\n }, [fetchMedia]);\n\n useEffect(() => {\n const selectedStepId = stepId || selectedStep?.id;\n if (selectedStepId && steps.length > 0) {\n const step = steps.find((s) => s.id === selectedStepId);\n if (step) {\n selectStep(step);\n }\n }\n }, [stepId, steps, selectStep, selectedStep?.id]);\n\n const handleAddStep = () => {\n createStep();\n };\n\n const handleSaveSteps = async () => {\n if (tourId) {\n try {\n await syncSteps(tourId, steps);\n } catch {\n emitToursApiFailed(eventBus, 'step.save', toursContext);\n }\n }\n };\n\n const handleBack = () => {\n navigate(`${basePath}/${tourId}/edit`);\n };\n\n const handleAttachMedia = async () => {\n if (!selectedStep || !tourId || !attachmentMediaId) return;\n if (selectedStep.id.startsWith('temp_')) {\n window.alert('Save your steps before attaching media to them.');\n return;\n }\n\n try {\n setAttachingMedia(true);\n await attachToStep(\n selectedStep.id,\n attachmentMediaId,\n attachmentPosition,\n (selectedStep.media?.length ?? 0) + 1\n );\n await loadTour(tourId);\n setAttachmentMediaId('');\n } catch {\n emitToursApiFailed(eventBus, 'media.attach', toursContext);\n } finally {\n setAttachingMedia(false);\n }\n };\n\n const handleSelectStep = (step: (typeof steps)[0]) => {\n selectStep(step);\n // Close sidebar on mobile after selecting\n if (isMobile) {\n setIsSidebarOpen(false);\n }\n };\n\n return (\n <div className=\"flex flex-col h-full bg-background\">\n {/* Header */}\n <div className=\"border-b border-border p-3 sm:p-4 flex flex-col sm:flex-row sm:items-center gap-3 sm:gap-4 bg-card\">\n <div className=\"flex items-center gap-3\">\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"p-2 hover:bg-accent rounded-md shrink-0\"\n aria-label={tr('stepEditor.goBack')}\n >\n <ArrowLeft size={20} />\n </button>\n <div className=\"flex-1 min-w-0\">\n <h1 className=\"text-base sm:text-lg font-semibold truncate\">\n {tour?.name || tr('stepEditor.tourFallback')} - {tr('stepEditor.stepsLabel')}\n </h1>\n <p className=\"text-xs sm:text-sm text-muted-foreground\">\n {steps.length} {tr('stepEditor.stepsCount')}\n </p>\n </div>\n </div>\n\n {/* Action buttons */}\n <div className=\"flex items-center gap-2 sm:gap-3 ml-auto\">\n {/* Mobile: Toggle sidebar button */}\n {isMobile && (\n <button\n type=\"button\"\n onClick={() => setIsSidebarOpen(!isSidebarOpen)}\n className=\"px-3 py-2 border border-border rounded-md hover:bg-accent flex items-center gap-2 sm:hidden\"\n >\n <Menu size={18} />\n <span className=\"text-sm\">{tr('stepEditor.steps')}</span>\n {steps.length > 0 && (\n <span className=\"px-1.5 py-0.5 text-xs bg-primary/20 rounded-full\">\n {steps.length}\n </span>\n )}\n </button>\n )}\n\n {canCreateStep && (\n <button\n type=\"button\"\n onClick={handleAddStep}\n className=\"px-3 sm:px-4 py-2 border border-border rounded-md hover:bg-accent flex items-center gap-2 text-sm sm:text-base\"\n >\n <Plus size={18} />\n <span className=\"hidden xs:inline\">{tr('stepEditor.addStep')}</span>\n </button>\n )}\n <PermissionGate permission={TOUR_PERMISSIONS.TOUR_STEP_UPDATE}>\n <button\n type=\"button\"\n onClick={handleSaveSteps}\n disabled={saving || !canUpdateStep}\n className=\"px-3 sm:px-4 py-2 bg-primary text-primary-foreground rounded-md hover:bg-primary/90 disabled:opacity-50 flex items-center gap-2 text-sm sm:text-base\"\n >\n <Save size={18} />\n <span className=\"hidden xs:inline\">\n {saving ? tr('stepEditor.saving') : tr('stepEditor.save')}\n </span>\n </button>\n </PermissionGate>\n </div>\n </div>\n\n <div className=\"flex-1 flex overflow-hidden relative\">\n {/* Mobile Sidebar Overlay */}\n {isMobile && isSidebarOpen && (\n <button\n type=\"button\"\n aria-label={tr('stepEditor.closeSteps')}\n className=\"fixed inset-0 bg-foreground/40 z-40 md:hidden\"\n onClick={() => setIsSidebarOpen(false)}\n />\n )}\n\n {/* Step List Sidebar */}\n <div\n className={`\n ${isMobile ? 'fixed inset-y-0 left-0 z-50 w-[min(18rem,calc(100vw-2rem))] transform transition-transform duration-300' : 'w-64 lg:w-80 shrink-0'}\n ${isMobile && !isSidebarOpen ? '-translate-x-full' : 'translate-x-0'}\n border-r border-border overflow-y-auto bg-card\n `}\n >\n {/* Mobile sidebar header */}\n {isMobile && (\n <div className=\"flex items-center justify-between p-4 border-b border-border sticky top-0 bg-card z-10\">\n <h2 className=\"font-semibold\">{tr('stepEditor.tourSteps')}</h2>\n <button\n type=\"button\"\n onClick={() => setIsSidebarOpen(false)}\n className=\"p-2 min-h-[44px] min-w-[44px] hover:bg-accent rounded-md\"\n aria-label={tr('stepEditor.closeSteps')}\n >\n <X size={20} />\n </button>\n </div>\n )}\n\n <div className=\"p-3 sm:p-4 space-y-2\">\n {steps.length === 0 ? (\n <div className=\"text-center py-8 text-muted-foreground\">\n <p className=\"text-sm\">{tr('stepEditor.noStepsYet')}</p>\n <p className=\"text-xs mt-1\">{tr('stepEditor.clickAddStep')}</p>\n </div>\n ) : (\n steps.map((step, index) => (\n <div\n key={step.id}\n role=\"button\"\n tabIndex={0}\n onClick={() => handleSelectStep(step)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n handleSelectStep(step);\n }\n }}\n className={`p-3 border rounded-md cursor-pointer transition-colors ${\n selectedStep?.id === step.id\n ? 'border-primary bg-primary/10'\n : 'border-border hover:bg-accent'\n }`}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-xs text-muted-foreground mb-1\">\n {tr('stepEditor.stepNumber')} {index + 1}\n </div>\n <div className=\"font-medium text-sm truncate\">\n {step.title || tr('stepEditor.untitled')}\n </div>\n {step.targetSelector && (\n <div className=\"text-xs text-muted-foreground mt-1 truncate font-mono\">\n {step.targetSelector}\n </div>\n )}\n </div>\n {canDeleteStep && (\n <div className=\"flex items-center gap-1 shrink-0\">\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n if (index > 0) {\n moveStep(index, index - 1);\n }\n }}\n className=\"p-1.5 sm:p-2 min-h-[32px] min-w-[32px] sm:min-h-[40px] sm:min-w-[40px] hover:bg-accent rounded\"\n title=\"Move step up\"\n aria-label=\"Move step up\"\n disabled={index === 0}\n >\n <ChevronUp size={14} />\n </button>\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n if (index < steps.length - 1) {\n moveStep(index, index + 1);\n }\n }}\n className=\"p-1.5 sm:p-2 min-h-[32px] min-w-[32px] sm:min-h-[40px] sm:min-w-[40px] hover:bg-accent rounded\"\n title=\"Move step down\"\n aria-label=\"Move step down\"\n disabled={index === steps.length - 1}\n >\n <ChevronDown size={14} />\n </button>\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n deleteStep(step.id);\n }}\n className=\"p-1.5 sm:p-2 min-h-[32px] min-w-[32px] sm:min-h-[40px] sm:min-w-[40px] hover:bg-destructive/10 rounded text-destructive\"\n title={tr('stepEditor.deleteStep')}\n aria-label={tr('stepEditor.deleteStep')}\n >\n <Trash2 size={14} />\n </button>\n </div>\n )}\n </div>\n </div>\n ))\n )}\n </div>\n </div>\n\n {/* Step Editor */}\n <div className=\"flex-1 overflow-y-auto p-4 sm:p-6\">\n {selectedStep ? (\n <div className=\"max-w-2xl mx-auto space-y-4 sm:space-y-6\">\n {/* Mobile: Step navigation */}\n {isMobile && steps.length > 1 && (\n <div className=\"flex items-center justify-between bg-muted/50 rounded-lg p-2 mb-4\">\n <button\n type=\"button\"\n onClick={() => {\n const currentIndex = steps.findIndex((s) => s.id === selectedStep.id);\n if (currentIndex > 0) {\n selectStep(steps[currentIndex - 1]);\n }\n }}\n disabled={steps.findIndex((s) => s.id === selectedStep.id) === 0}\n className=\"p-2 min-h-[44px] min-w-[44px] hover:bg-accent rounded-md disabled:opacity-30\"\n aria-label={tr('stepEditor.previousStep')}\n >\n <ChevronLeft size={20} />\n </button>\n <span className=\"text-sm text-muted-foreground\">\n {tr('stepEditor.stepNumber')}{' '}\n {steps.findIndex((s) => s.id === selectedStep.id) + 1} {tr('stepEditor.of')}{' '}\n {steps.length}\n </span>\n <button\n type=\"button\"\n onClick={() => {\n const currentIndex = steps.findIndex((s) => s.id === selectedStep.id);\n if (currentIndex < steps.length - 1) {\n selectStep(steps[currentIndex + 1]);\n }\n }}\n disabled={steps.findIndex((s) => s.id === selectedStep.id) === steps.length - 1}\n className=\"p-2 min-h-[44px] min-w-[44px] hover:bg-accent rounded-md disabled:opacity-30\"\n aria-label={tr('stepEditor.nextStep')}\n >\n <ChevronRight size={20} />\n </button>\n </div>\n )}\n\n <h2 className=\"text-lg sm:text-xl font-semibold\">{tr('stepEditor.editStep')}</h2>\n\n {/* Title */}\n <div>\n <label className=\"block text-sm font-medium mb-2\" htmlFor=\"step-editor-title\">\n {tr('stepEditor.stepTitle')} *\n </label>\n <input\n id=\"step-editor-title\"\n type=\"text\"\n value={selectedStep.title}\n onChange={(e) => updateStepField(selectedStep.id, 'title', e.target.value)}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-sm sm:text-base\"\n placeholder={tr('stepEditor.stepTitlePlaceholder')}\n aria-label={tr('stepEditor.stepTitle')}\n />\n </div>\n\n {/* Content */}\n <div>\n <label className=\"block text-sm font-medium mb-2\" htmlFor=\"step-editor-content\">\n {tr('stepEditor.content')} *\n </label>\n <textarea\n id=\"step-editor-content\"\n value={selectedStep.content}\n onChange={(e) => updateStepField(selectedStep.id, 'content', e.target.value)}\n rows={4}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-sm sm:text-base resize-y min-h-[100px]\"\n placeholder={tr('stepEditor.contentPlaceholder')}\n aria-label={tr('stepEditor.content')}\n />\n </div>\n\n {/* Selector */}\n <div>\n <label\n className=\"block text-sm font-medium mb-2\"\n htmlFor=\"step-editor-css-selector\"\n >\n {tr('stepEditor.cssSelector')} *\n <span className=\"text-muted-foreground font-normal ml-2\">\n ({tr('stepEditor.targetElement')})\n </span>\n </label>\n <input\n id=\"step-editor-css-selector\"\n type=\"text\"\n value={selectedStep.targetSelector || ''}\n onChange={(e) =>\n updateStepField(selectedStep.id, 'targetSelector', e.target.value)\n }\n placeholder={tr('stepEditor.cssSelectorPlaceholder')}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background font-mono text-sm\"\n aria-label=\"{tr('stepEditor.cssSelector')} *\n \n ({tr('stepEditor.targetElement')})\"\n />\n <p className=\"text-xs text-muted-foreground mt-1\">\n {tr('stepEditor.dataTourHint')}\n </p>\n </div>\n\n {/* Placement */}\n <div>\n <label className=\"block text-sm font-medium mb-2\" htmlFor=\"step-editor-placement\">\n {tr('stepEditor.tooltipPlacement')}\n </label>\n <select\n id=\"step-editor-placement\"\n value={selectedStep.placement}\n onChange={(e) => updateStepField(selectedStep.id, 'placement', e.target.value)}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-sm sm:text-base\"\n aria-label={tr('stepEditor.tooltipPlacement')}\n >\n <option value=\"AUTO\">{tr('stepEditor.placementAuto')}</option>\n <option value=\"TOP\">{tr('stepEditor.placementTop')}</option>\n <option value=\"BOTTOM\">{tr('stepEditor.placementBottom')}</option>\n <option value=\"LEFT\">{tr('stepEditor.placementLeft')}</option>\n <option value=\"RIGHT\">{tr('stepEditor.placementRight')}</option>\n <option value=\"CENTER\">{tr('stepEditor.placementCenter')}</option>\n </select>\n </div>\n\n {/* Device-specific selectors */}\n <details className=\"border border-border rounded-md\">\n <summary className=\"px-4 py-3 cursor-pointer font-medium text-sm hover:bg-accent/50 rounded-t-md\">\n {tr('stepEditor.deviceSpecificSelectors')}\n </summary>\n <div className=\"p-4 pt-0 space-y-3 border-t border-border\">\n <p className=\"text-xs text-muted-foreground mb-3\">\n {tr('stepEditor.deviceSelectorHint')}\n </p>\n <div>\n <label\n className=\"block text-xs font-medium mb-1\"\n htmlFor=\"step-editor-mobile-selector\"\n >\n {tr('stepEditor.mobileSelector')}\n </label>\n <input\n id=\"step-editor-mobile-selector\"\n type=\"text\"\n value={selectedStep.targetSelectorMobile || ''}\n onChange={(e) =>\n updateStepField(selectedStep.id, 'targetSelectorMobile', e.target.value)\n }\n placeholder={tr('stepEditor.leaveEmptyDefault')}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-sm font-mono\"\n aria-label={tr('stepEditor.mobileSelector')}\n />\n </div>\n <div>\n <label\n className=\"block text-xs font-medium mb-1\"\n htmlFor=\"step-editor-tablet-selector\"\n >\n {tr('stepEditor.tabletSelector')}\n </label>\n <input\n id=\"step-editor-tablet-selector\"\n type=\"text\"\n value={selectedStep.targetSelectorTablet || ''}\n onChange={(e) =>\n updateStepField(selectedStep.id, 'targetSelectorTablet', e.target.value)\n }\n placeholder={tr('stepEditor.leaveEmptyDefault')}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-sm font-mono\"\n aria-label={tr('stepEditor.tabletSelector')}\n />\n </div>\n <div>\n <label\n className=\"block text-xs font-medium mb-1\"\n htmlFor=\"step-editor-desktop-selector\"\n >\n {tr('stepEditor.desktopSelector')}\n </label>\n <input\n id=\"step-editor-desktop-selector\"\n type=\"text\"\n value={selectedStep.targetSelectorDesktop || ''}\n onChange={(e) =>\n updateStepField(selectedStep.id, 'targetSelectorDesktop', e.target.value)\n }\n placeholder={tr('stepEditor.leaveEmptyDefault')}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-sm font-mono\"\n aria-label={tr('stepEditor.desktopSelector')}\n />\n </div>\n </div>\n </details>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <label className=\"flex items-center gap-3 cursor-pointer rounded-md border border-border p-3\">\n <input\n type=\"checkbox\"\n checked={selectedStep.requireInteraction ?? false}\n onChange={(e) =>\n updateStepField(selectedStep.id, 'requireInteraction', e.target.checked)\n }\n className=\"size-4 rounded\"\n aria-label=\"Require interaction\"\n />\n <div>\n <div className=\"text-sm font-medium\">Require interaction</div>\n <div className=\"text-xs text-muted-foreground\">\n User must interact with the highlighted element before advancing.\n </div>\n </div>\n </label>\n\n <div>\n <label\n className=\"block text-sm font-medium mb-2\"\n htmlFor=\"step-editor-wait-timeout\"\n >\n Wait for timeout (ms)\n </label>\n <input\n id=\"step-editor-wait-timeout\"\n type=\"number\"\n min=\"0\"\n value={selectedStep.waitForTimeout ?? ''}\n onChange={(e) =>\n updateStepField(\n selectedStep.id,\n 'waitForTimeout',\n e.target.value ? Number(e.target.value) : undefined\n )\n }\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-sm\"\n placeholder=\"1500\"\n aria-label=\"Wait for timeout (ms)\"\n />\n </div>\n </div>\n\n {/* Advanced: step timing / skip conditions / analytics tags — collapse the long-tail knobs */}\n <OptionalFields\n title=\"Advanced settings\"\n description=\"Step-timing waits, skip conditions, and analytics tags.\"\n >\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label\n className=\"block text-sm font-medium mb-2\"\n htmlFor=\"step-editor-wait-selector\"\n >\n Wait for selector\n </label>\n <input\n id=\"step-editor-wait-selector\"\n type=\"text\"\n value={selectedStep.waitForSelector || ''}\n onChange={(e) =>\n updateStepField(\n selectedStep.id,\n 'waitForSelector',\n e.target.value || undefined\n )\n }\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-sm font-mono\"\n placeholder=\"[data-tour='agents-tabs']\"\n aria-label=\"Wait for selector\"\n />\n </div>\n\n <div>\n <label\n className=\"block text-sm font-medium mb-2\"\n htmlFor=\"step-editor-wait-event\"\n >\n Wait for event\n </label>\n <input\n id=\"step-editor-wait-event\"\n type=\"text\"\n value={selectedStep.waitForEvent || ''}\n onChange={(e) =>\n updateStepField(\n selectedStep.id,\n 'waitForEvent',\n e.target.value || undefined\n )\n }\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-sm\"\n placeholder=\"tour:ready\"\n aria-label=\"Wait for event\"\n />\n </div>\n </div>\n\n <div className=\"mt-4\">\n <label\n className=\"block text-sm font-medium mb-2\"\n htmlFor=\"step-editor-skip-conditions\"\n >\n Skip conditions (JSON)\n </label>\n <textarea\n id=\"step-editor-skip-conditions\"\n value={\n selectedStep.skipConditions\n ? JSON.stringify(selectedStep.skipConditions, null, 2)\n : ''\n }\n onChange={(e) => {\n const rawValue = e.target.value.trim();\n if (!rawValue) {\n updateStepField(selectedStep.id, 'skipConditions', undefined);\n return;\n }\n\n try {\n updateStepField(selectedStep.id, 'skipConditions', JSON.parse(rawValue));\n } catch {\n updateStepField(selectedStep.id, 'skipConditions', rawValue);\n }\n }}\n rows={4}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-sm font-mono\"\n placeholder='{\"selectorMissing\":\"[data-tour=\\\"missing\\\"]\"}'\n aria-label=\"Skip conditions (JSON)\"\n />\n </div>\n </OptionalFields>\n\n <div className=\"border border-border rounded-md p-4 space-y-4\">\n <div className=\"flex items-center gap-2\">\n <Paperclip size={18} />\n <h3 className=\"text-sm font-semibold\">Step media</h3>\n </div>\n\n {selectedStep.media && selectedStep.media.length > 0 ? (\n <div className=\"space-y-2\">\n {selectedStep.media.map((item) => (\n <div\n key={item.id}\n className=\"flex items-center justify-between rounded-md border border-border p-2 text-sm\"\n >\n <div>\n <div className=\"font-medium\">{item.media.name}</div>\n <div className=\"text-xs text-muted-foreground\">{item.position}</div>\n </div>\n <span className=\"text-xs text-muted-foreground\">{item.media.type}</span>\n </div>\n ))}\n </div>\n ) : (\n <p className=\"text-sm text-muted-foreground\">\n No media attached to this step yet.\n </p>\n )}\n\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-[minmax(0,1fr)_160px_auto]\">\n <select\n value={attachmentMediaId}\n onChange={(e) => setAttachmentMediaId(e.target.value)}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-sm\"\n aria-label=\"Select media to attach\"\n >\n <option value=\"\">\n {mediaLoading ? 'Loading media...' : 'Select uploaded media'}\n </option>\n {media.map((item) => (\n <option key={item.id} value={item.id}>\n {item.name} ({item.type})\n </option>\n ))}\n </select>\n\n <select\n value={attachmentPosition}\n onChange={(e) =>\n setAttachmentPosition(e.target.value as 'header' | 'body' | 'footer')\n }\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-sm\"\n aria-label=\"Attachment position\"\n >\n <option value=\"header\">Header</option>\n <option value=\"body\">Body</option>\n <option value=\"footer\">Footer</option>\n </select>\n\n <button\n type=\"button\"\n onClick={handleAttachMedia}\n disabled={attachingMedia || !attachmentMediaId}\n className=\"px-4 py-2 min-h-[44px] border border-border rounded-md hover:bg-accent disabled:opacity-50\"\n >\n Attach\n </button>\n </div>\n </div>\n </div>\n ) : (\n <div className=\"flex flex-col items-center justify-center h-full text-center px-4\">\n <div className=\"size-16 bg-muted rounded-full flex items-center justify-center mb-4\">\n <Plus size={24} className=\"text-muted-foreground\" />\n </div>\n <p className=\"text-muted-foreground mb-2\">{tr('stepEditor.noStepSelected')}</p>\n <p className=\"text-sm text-muted-foreground mb-4\">\n {steps.length > 0\n ? tr('stepEditor.selectStepToEdit')\n : tr('stepEditor.createFirstStep')}\n </p>\n {steps.length === 0 && canCreateStep && (\n <button\n type=\"button\"\n onClick={handleAddStep}\n className=\"px-4 py-2 min-h-[44px] bg-primary text-primary-foreground rounded-md hover:bg-primary/90 flex items-center gap-2\"\n >\n <Plus size={18} />\n {tr('stepEditor.addFirstStep')}\n </button>\n )}\n </div>\n )}\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"StepEditorPage.js","names":[],"sources":["../../../src/tours/pages/StepEditorPage.tsx"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport { useParams, useNavigate } from 'react-router-dom';\nimport {\n ArrowLeft,\n Plus,\n Save,\n Trash2,\n ChevronLeft,\n ChevronRight,\n ChevronUp,\n ChevronDown,\n Menu,\n Paperclip,\n X,\n} from 'lucide-react';\nimport { PermissionGate } from '@burdenoff/fe-libs/shared/components';\nimport { useEventBus } from '@burdenoff/fe-libs/shared/events';\nimport { OptionalFields } from '@burdenoff/fe-libs/ui';\nimport { useStepSequencer } from '../hooks/useStepSequencer';\nimport { useTourBuilder } from '../hooks/useTourBuilder';\nimport { useMediaLibrary } from '../hooks/useMediaLibrary';\nimport { useToursPermissionAccess } from '../hooks/useToursPermissionAccess';\nimport { useToursContext } from '../providers/ToursProvider';\nimport { TOUR_PERMISSIONS } from '../../constants/permissions';\nimport { useToursI18n } from '../i18n';\nimport { emitToursApiFailed } from '../telemetry';\n\n/**\n * Step editor page\n * Manage tour steps with sequencer and editor\n * Responsive: sidebar drawer on mobile, side panel on desktop\n */\nexport function StepEditorPage() {\n const { tr } = useToursI18n();\n\n const { tourId, stepId } = useParams();\n const navigate = useNavigate();\n const toursContext = useToursContext();\n const { basePath = '/' } = toursContext;\n const eventBus = useEventBus();\n const { hasPermission } = useToursPermissionAccess();\n const canCreateStep = hasPermission(TOUR_PERMISSIONS.TOUR_STEP_CREATE);\n const canUpdateStep = hasPermission(TOUR_PERMISSIONS.TOUR_STEP_UPDATE);\n const canDeleteStep = hasPermission(TOUR_PERMISSIONS.TOUR_STEP_DELETE);\n\n const { tour, loadTour, syncSteps, saving } = useTourBuilder(tourId);\n const { steps, selectedStep, selectStep, createStep, deleteStep, updateStepField, moveStep } =\n useStepSequencer();\n const { media, fetchMedia, attachToStep, loading: mediaLoading } = useMediaLibrary();\n\n // Mobile sidebar state\n const [isSidebarOpen, setIsSidebarOpen] = useState(false);\n const [isMobile, setIsMobile] = useState(\n () => typeof window !== 'undefined' && window.innerWidth < 768\n );\n const [attachmentMediaId, setAttachmentMediaId] = useState('');\n const [attachmentPosition, setAttachmentPosition] = useState<'header' | 'body' | 'footer'>(\n 'body'\n );\n const [attachingMedia, setAttachingMedia] = useState(false);\n\n // Detect mobile viewport\n useEffect(() => {\n const checkMobile = () => {\n const mobile = window.innerWidth < 768;\n setIsMobile(mobile);\n // Auto-close sidebar on desktop\n if (!mobile) {\n setIsSidebarOpen(false);\n }\n };\n window.addEventListener('resize', checkMobile);\n return () => window.removeEventListener('resize', checkMobile);\n }, []);\n\n useEffect(() => {\n if (tourId) {\n loadTour(tourId);\n }\n }, [tourId, loadTour]);\n\n useEffect(() => {\n void fetchMedia();\n }, [fetchMedia]);\n\n useEffect(() => {\n const selectedStepId = stepId || selectedStep?.id;\n if (selectedStepId && steps.length > 0) {\n const step = steps.find((s) => s.id === selectedStepId);\n if (step) {\n selectStep(step);\n }\n }\n }, [stepId, steps, selectStep, selectedStep?.id]);\n\n const handleAddStep = () => {\n createStep();\n };\n\n const handleSaveSteps = async () => {\n if (tourId) {\n try {\n await syncSteps(tourId, steps);\n } catch {\n emitToursApiFailed(eventBus, 'step.save', toursContext);\n }\n }\n };\n\n const handleBack = () => {\n navigate(`${basePath}/${tourId}/edit`);\n };\n\n const handleAttachMedia = async () => {\n if (!selectedStep || !tourId || !attachmentMediaId) return;\n if (selectedStep.id.startsWith('temp_')) {\n window.alert('Save your steps before attaching media to them.');\n return;\n }\n\n try {\n setAttachingMedia(true);\n await attachToStep(\n selectedStep.id,\n attachmentMediaId,\n attachmentPosition,\n (selectedStep.media?.length ?? 0) + 1\n );\n await loadTour(tourId);\n setAttachmentMediaId('');\n } catch {\n emitToursApiFailed(eventBus, 'media.attach', toursContext);\n } finally {\n setAttachingMedia(false);\n }\n };\n\n const handleSelectStep = (step: (typeof steps)[0]) => {\n selectStep(step);\n // Close sidebar on mobile after selecting\n if (isMobile) {\n setIsSidebarOpen(false);\n }\n };\n\n return (\n <div className=\"flex flex-col h-full bg-bg-surface\">\n {/* Header */}\n <div className=\"border-b border-border-subtle p-3 sm:p-4 flex flex-col sm:flex-row sm:items-center gap-3 sm:gap-4 bg-bg-surface\">\n <div className=\"flex items-center gap-3\">\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"p-2 hover:bg-accent rounded-md shrink-0\"\n aria-label={tr('stepEditor.goBack')}\n >\n <ArrowLeft size={20} />\n </button>\n <div className=\"flex-1 min-w-0\">\n <h1 className=\"text-base sm:text-lg font-semibold truncate\">\n {tour?.name || tr('stepEditor.tourFallback')} - {tr('stepEditor.stepsLabel')}\n </h1>\n <p className=\"text-xs sm:text-sm text-text-secondary\">\n {steps.length} {tr('stepEditor.stepsCount')}\n </p>\n </div>\n </div>\n\n {/* Action buttons */}\n <div className=\"flex items-center gap-2 sm:gap-3 ml-auto\">\n {/* Mobile: Toggle sidebar button */}\n {isMobile && (\n <button\n type=\"button\"\n onClick={() => setIsSidebarOpen(!isSidebarOpen)}\n className=\"px-3 py-2 border border-border-subtle rounded-md hover:bg-accent flex items-center gap-2 sm:hidden\"\n >\n <Menu size={18} />\n <span className=\"text-sm\">{tr('stepEditor.steps')}</span>\n {steps.length > 0 && (\n <span className=\"px-1.5 py-0.5 text-xs bg-action-primary-bg/20 rounded-full\">\n {steps.length}\n </span>\n )}\n </button>\n )}\n\n {canCreateStep && (\n <button\n type=\"button\"\n onClick={handleAddStep}\n className=\"px-3 sm:px-4 py-2 border border-border-subtle rounded-md hover:bg-accent flex items-center gap-2 text-sm sm:text-base\"\n >\n <Plus size={18} />\n <span className=\"hidden xs:inline\">{tr('stepEditor.addStep')}</span>\n </button>\n )}\n <PermissionGate permission={TOUR_PERMISSIONS.TOUR_STEP_UPDATE}>\n <button\n type=\"button\"\n onClick={handleSaveSteps}\n disabled={saving || !canUpdateStep}\n className=\"px-3 sm:px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg/90 disabled:opacity-50 flex items-center gap-2 text-sm sm:text-base\"\n >\n <Save size={18} />\n <span className=\"hidden xs:inline\">\n {saving ? tr('stepEditor.saving') : tr('stepEditor.save')}\n </span>\n </button>\n </PermissionGate>\n </div>\n </div>\n\n <div className=\"flex-1 flex overflow-hidden relative\">\n {/* Mobile Sidebar Overlay */}\n {isMobile && isSidebarOpen && (\n <button\n type=\"button\"\n aria-label={tr('stepEditor.closeSteps')}\n className=\"fixed inset-0 bg-foreground/40 z-40 md:hidden\"\n onClick={() => setIsSidebarOpen(false)}\n />\n )}\n\n {/* Step List Sidebar */}\n <div\n className={`\n ${isMobile ? 'fixed inset-y-0 left-0 z-50 w-[min(18rem,calc(100vw-2rem))] transform transition-transform duration-300' : 'w-64 lg:w-80 shrink-0'}\n ${isMobile && !isSidebarOpen ? '-translate-x-full' : 'translate-x-0'}\n border-r border-border-subtle overflow-y-auto bg-bg-surface\n `}\n >\n {/* Mobile sidebar header */}\n {isMobile && (\n <div className=\"flex items-center justify-between p-4 border-b border-border-subtle sticky top-0 bg-bg-surface z-10\">\n <h2 className=\"font-semibold\">{tr('stepEditor.tourSteps')}</h2>\n <button\n type=\"button\"\n onClick={() => setIsSidebarOpen(false)}\n className=\"p-2 min-h-[44px] min-w-[44px] hover:bg-accent rounded-md\"\n aria-label={tr('stepEditor.closeSteps')}\n >\n <X size={20} />\n </button>\n </div>\n )}\n\n <div className=\"p-3 sm:p-4 space-y-2\">\n {steps.length === 0 ? (\n <div className=\"text-center py-8 text-text-secondary\">\n <p className=\"text-sm\">{tr('stepEditor.noStepsYet')}</p>\n <p className=\"text-xs mt-1\">{tr('stepEditor.clickAddStep')}</p>\n </div>\n ) : (\n steps.map((step, index) => (\n <div\n key={step.id}\n role=\"button\"\n tabIndex={0}\n onClick={() => handleSelectStep(step)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n handleSelectStep(step);\n }\n }}\n className={`p-3 border rounded-md cursor-pointer transition-colors ${\n selectedStep?.id === step.id\n ? 'border-primary bg-action-primary-bg/10'\n : 'border-border-subtle hover:bg-accent'\n }`}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-xs text-text-secondary mb-1\">\n {tr('stepEditor.stepNumber')} {index + 1}\n </div>\n <div className=\"font-medium text-sm truncate\">\n {step.title || tr('stepEditor.untitled')}\n </div>\n {step.targetSelector && (\n <div className=\"text-xs text-text-secondary mt-1 truncate font-mono\">\n {step.targetSelector}\n </div>\n )}\n </div>\n {canDeleteStep && (\n <div className=\"flex items-center gap-1 shrink-0\">\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n if (index > 0) {\n moveStep(index, index - 1);\n }\n }}\n className=\"p-1.5 sm:p-2 min-h-[32px] min-w-[32px] sm:min-h-[40px] sm:min-w-[40px] hover:bg-accent rounded\"\n title=\"Move step up\"\n aria-label=\"Move step up\"\n disabled={index === 0}\n >\n <ChevronUp size={14} />\n </button>\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n if (index < steps.length - 1) {\n moveStep(index, index + 1);\n }\n }}\n className=\"p-1.5 sm:p-2 min-h-[32px] min-w-[32px] sm:min-h-[40px] sm:min-w-[40px] hover:bg-accent rounded\"\n title=\"Move step down\"\n aria-label=\"Move step down\"\n disabled={index === steps.length - 1}\n >\n <ChevronDown size={14} />\n </button>\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n deleteStep(step.id);\n }}\n className=\"p-1.5 sm:p-2 min-h-[32px] min-w-[32px] sm:min-h-[40px] sm:min-w-[40px] hover:bg-status-error-bg/10 rounded text-status-error-text\"\n title={tr('stepEditor.deleteStep')}\n aria-label={tr('stepEditor.deleteStep')}\n >\n <Trash2 size={14} />\n </button>\n </div>\n )}\n </div>\n </div>\n ))\n )}\n </div>\n </div>\n\n {/* Step Editor */}\n <div className=\"flex-1 overflow-y-auto p-4 sm:p-6\">\n {selectedStep ? (\n <div className=\"max-w-2xl mx-auto space-y-4 sm:space-y-6\">\n {/* Mobile: Step navigation */}\n {isMobile && steps.length > 1 && (\n <div className=\"flex items-center justify-between bg-bg-sunken/50 rounded-lg p-2 mb-4\">\n <button\n type=\"button\"\n onClick={() => {\n const currentIndex = steps.findIndex((s) => s.id === selectedStep.id);\n if (currentIndex > 0) {\n selectStep(steps[currentIndex - 1]);\n }\n }}\n disabled={steps.findIndex((s) => s.id === selectedStep.id) === 0}\n className=\"p-2 min-h-[44px] min-w-[44px] hover:bg-accent rounded-md disabled:opacity-30\"\n aria-label={tr('stepEditor.previousStep')}\n >\n <ChevronLeft size={20} />\n </button>\n <span className=\"text-sm text-text-secondary\">\n {tr('stepEditor.stepNumber')}{' '}\n {steps.findIndex((s) => s.id === selectedStep.id) + 1} {tr('stepEditor.of')}{' '}\n {steps.length}\n </span>\n <button\n type=\"button\"\n onClick={() => {\n const currentIndex = steps.findIndex((s) => s.id === selectedStep.id);\n if (currentIndex < steps.length - 1) {\n selectStep(steps[currentIndex + 1]);\n }\n }}\n disabled={steps.findIndex((s) => s.id === selectedStep.id) === steps.length - 1}\n className=\"p-2 min-h-[44px] min-w-[44px] hover:bg-accent rounded-md disabled:opacity-30\"\n aria-label={tr('stepEditor.nextStep')}\n >\n <ChevronRight size={20} />\n </button>\n </div>\n )}\n\n <h2 className=\"text-lg sm:text-xl font-semibold\">{tr('stepEditor.editStep')}</h2>\n\n {/* Title */}\n <div>\n <label className=\"block text-sm font-medium mb-2\" htmlFor=\"step-editor-title\">\n {tr('stepEditor.stepTitle')} *\n </label>\n <input\n id=\"step-editor-title\"\n type=\"text\"\n value={selectedStep.title}\n onChange={(e) => updateStepField(selectedStep.id, 'title', e.target.value)}\n className=\"w-full px-3 py-2 border border-border-subtle rounded-md bg-bg-surface text-sm sm:text-base\"\n placeholder={tr('stepEditor.stepTitlePlaceholder')}\n aria-label={tr('stepEditor.stepTitle')}\n />\n </div>\n\n {/* Content */}\n <div>\n <label className=\"block text-sm font-medium mb-2\" htmlFor=\"step-editor-content\">\n {tr('stepEditor.content')} *\n </label>\n <textarea\n id=\"step-editor-content\"\n value={selectedStep.content}\n onChange={(e) => updateStepField(selectedStep.id, 'content', e.target.value)}\n rows={4}\n className=\"w-full px-3 py-2 border border-border-subtle rounded-md bg-bg-surface text-sm sm:text-base resize-y min-h-[100px]\"\n placeholder={tr('stepEditor.contentPlaceholder')}\n aria-label={tr('stepEditor.content')}\n />\n </div>\n\n {/* Selector */}\n <div>\n <label\n className=\"block text-sm font-medium mb-2\"\n htmlFor=\"step-editor-css-selector\"\n >\n {tr('stepEditor.cssSelector')} *\n <span className=\"text-text-secondary font-normal ml-2\">\n ({tr('stepEditor.targetElement')})\n </span>\n </label>\n <input\n id=\"step-editor-css-selector\"\n type=\"text\"\n value={selectedStep.targetSelector || ''}\n onChange={(e) =>\n updateStepField(selectedStep.id, 'targetSelector', e.target.value)\n }\n placeholder={tr('stepEditor.cssSelectorPlaceholder')}\n className=\"w-full px-3 py-2 border border-border-subtle rounded-md bg-bg-surface font-mono text-sm\"\n aria-label=\"{tr('stepEditor.cssSelector')} *\n \n ({tr('stepEditor.targetElement')})\"\n />\n <p className=\"text-xs text-text-secondary mt-1\">\n {tr('stepEditor.dataTourHint')}\n </p>\n </div>\n\n {/* Placement */}\n <div>\n <label className=\"block text-sm font-medium mb-2\" htmlFor=\"step-editor-placement\">\n {tr('stepEditor.tooltipPlacement')}\n </label>\n <select\n id=\"step-editor-placement\"\n value={selectedStep.placement}\n onChange={(e) => updateStepField(selectedStep.id, 'placement', e.target.value)}\n className=\"w-full px-3 py-2 border border-border-subtle rounded-md bg-bg-surface text-sm sm:text-base\"\n aria-label={tr('stepEditor.tooltipPlacement')}\n >\n <option value=\"AUTO\">{tr('stepEditor.placementAuto')}</option>\n <option value=\"TOP\">{tr('stepEditor.placementTop')}</option>\n <option value=\"BOTTOM\">{tr('stepEditor.placementBottom')}</option>\n <option value=\"LEFT\">{tr('stepEditor.placementLeft')}</option>\n <option value=\"RIGHT\">{tr('stepEditor.placementRight')}</option>\n <option value=\"CENTER\">{tr('stepEditor.placementCenter')}</option>\n </select>\n </div>\n\n {/* Device-specific selectors */}\n <details className=\"border border-border-subtle rounded-md\">\n <summary className=\"px-4 py-3 cursor-pointer font-medium text-sm hover:bg-accent/50 rounded-t-md\">\n {tr('stepEditor.deviceSpecificSelectors')}\n </summary>\n <div className=\"p-4 pt-0 space-y-3 border-t border-border-subtle\">\n <p className=\"text-xs text-text-secondary mb-3\">\n {tr('stepEditor.deviceSelectorHint')}\n </p>\n <div>\n <label\n className=\"block text-xs font-medium mb-1\"\n htmlFor=\"step-editor-mobile-selector\"\n >\n {tr('stepEditor.mobileSelector')}\n </label>\n <input\n id=\"step-editor-mobile-selector\"\n type=\"text\"\n value={selectedStep.targetSelectorMobile || ''}\n onChange={(e) =>\n updateStepField(selectedStep.id, 'targetSelectorMobile', e.target.value)\n }\n placeholder={tr('stepEditor.leaveEmptyDefault')}\n className=\"w-full px-3 py-2 border border-border-subtle rounded-md bg-bg-surface text-sm font-mono\"\n aria-label={tr('stepEditor.mobileSelector')}\n />\n </div>\n <div>\n <label\n className=\"block text-xs font-medium mb-1\"\n htmlFor=\"step-editor-tablet-selector\"\n >\n {tr('stepEditor.tabletSelector')}\n </label>\n <input\n id=\"step-editor-tablet-selector\"\n type=\"text\"\n value={selectedStep.targetSelectorTablet || ''}\n onChange={(e) =>\n updateStepField(selectedStep.id, 'targetSelectorTablet', e.target.value)\n }\n placeholder={tr('stepEditor.leaveEmptyDefault')}\n className=\"w-full px-3 py-2 border border-border-subtle rounded-md bg-bg-surface text-sm font-mono\"\n aria-label={tr('stepEditor.tabletSelector')}\n />\n </div>\n <div>\n <label\n className=\"block text-xs font-medium mb-1\"\n htmlFor=\"step-editor-desktop-selector\"\n >\n {tr('stepEditor.desktopSelector')}\n </label>\n <input\n id=\"step-editor-desktop-selector\"\n type=\"text\"\n value={selectedStep.targetSelectorDesktop || ''}\n onChange={(e) =>\n updateStepField(selectedStep.id, 'targetSelectorDesktop', e.target.value)\n }\n placeholder={tr('stepEditor.leaveEmptyDefault')}\n className=\"w-full px-3 py-2 border border-border-subtle rounded-md bg-bg-surface text-sm font-mono\"\n aria-label={tr('stepEditor.desktopSelector')}\n />\n </div>\n </div>\n </details>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <label className=\"flex items-center gap-3 cursor-pointer rounded-md border border-border-subtle p-3\">\n <input\n type=\"checkbox\"\n checked={selectedStep.requireInteraction ?? false}\n onChange={(e) =>\n updateStepField(selectedStep.id, 'requireInteraction', e.target.checked)\n }\n className=\"size-4 rounded\"\n aria-label=\"Require interaction\"\n />\n <div>\n <div className=\"text-sm font-medium\">Require interaction</div>\n <div className=\"text-xs text-text-secondary\">\n User must interact with the highlighted element before advancing.\n </div>\n </div>\n </label>\n\n <div>\n <label\n className=\"block text-sm font-medium mb-2\"\n htmlFor=\"step-editor-wait-timeout\"\n >\n Wait for timeout (ms)\n </label>\n <input\n id=\"step-editor-wait-timeout\"\n type=\"number\"\n min=\"0\"\n value={selectedStep.waitForTimeout ?? ''}\n onChange={(e) =>\n updateStepField(\n selectedStep.id,\n 'waitForTimeout',\n e.target.value ? Number(e.target.value) : undefined\n )\n }\n className=\"w-full px-3 py-2 border border-border-subtle rounded-md bg-bg-surface text-sm\"\n placeholder=\"1500\"\n aria-label=\"Wait for timeout (ms)\"\n />\n </div>\n </div>\n\n {/* Advanced: step timing / skip conditions / analytics tags — collapse the long-tail knobs */}\n <OptionalFields\n title=\"Advanced settings\"\n description=\"Step-timing waits, skip conditions, and analytics tags.\"\n >\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label\n className=\"block text-sm font-medium mb-2\"\n htmlFor=\"step-editor-wait-selector\"\n >\n Wait for selector\n </label>\n <input\n id=\"step-editor-wait-selector\"\n type=\"text\"\n value={selectedStep.waitForSelector || ''}\n onChange={(e) =>\n updateStepField(\n selectedStep.id,\n 'waitForSelector',\n e.target.value || undefined\n )\n }\n className=\"w-full px-3 py-2 border border-border-subtle rounded-md bg-bg-surface text-sm font-mono\"\n placeholder=\"[data-tour='agents-tabs']\"\n aria-label=\"Wait for selector\"\n />\n </div>\n\n <div>\n <label\n className=\"block text-sm font-medium mb-2\"\n htmlFor=\"step-editor-wait-event\"\n >\n Wait for event\n </label>\n <input\n id=\"step-editor-wait-event\"\n type=\"text\"\n value={selectedStep.waitForEvent || ''}\n onChange={(e) =>\n updateStepField(\n selectedStep.id,\n 'waitForEvent',\n e.target.value || undefined\n )\n }\n className=\"w-full px-3 py-2 border border-border-subtle rounded-md bg-bg-surface text-sm\"\n placeholder=\"tour:ready\"\n aria-label=\"Wait for event\"\n />\n </div>\n </div>\n\n <div className=\"mt-4\">\n <label\n className=\"block text-sm font-medium mb-2\"\n htmlFor=\"step-editor-skip-conditions\"\n >\n Skip conditions (JSON)\n </label>\n <textarea\n id=\"step-editor-skip-conditions\"\n value={\n selectedStep.skipConditions\n ? JSON.stringify(selectedStep.skipConditions, null, 2)\n : ''\n }\n onChange={(e) => {\n const rawValue = e.target.value.trim();\n if (!rawValue) {\n updateStepField(selectedStep.id, 'skipConditions', undefined);\n return;\n }\n\n try {\n updateStepField(selectedStep.id, 'skipConditions', JSON.parse(rawValue));\n } catch {\n updateStepField(selectedStep.id, 'skipConditions', rawValue);\n }\n }}\n rows={4}\n className=\"w-full px-3 py-2 border border-border-subtle rounded-md bg-bg-surface text-sm font-mono\"\n placeholder='{\"selectorMissing\":\"[data-tour=\\\"missing\\\"]\"}'\n aria-label=\"Skip conditions (JSON)\"\n />\n </div>\n </OptionalFields>\n\n <div className=\"border border-border-subtle rounded-md p-4 space-y-4\">\n <div className=\"flex items-center gap-2\">\n <Paperclip size={18} />\n <h3 className=\"text-sm font-semibold\">Step media</h3>\n </div>\n\n {selectedStep.media && selectedStep.media.length > 0 ? (\n <div className=\"space-y-2\">\n {selectedStep.media.map((item) => (\n <div\n key={item.id}\n className=\"flex items-center justify-between rounded-md border border-border-subtle p-2 text-sm\"\n >\n <div>\n <div className=\"font-medium\">{item.media.name}</div>\n <div className=\"text-xs text-text-secondary\">{item.position}</div>\n </div>\n <span className=\"text-xs text-text-secondary\">{item.media.type}</span>\n </div>\n ))}\n </div>\n ) : (\n <p className=\"text-sm text-text-secondary\">\n No media attached to this step yet.\n </p>\n )}\n\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-[minmax(0,1fr)_160px_auto]\">\n <select\n value={attachmentMediaId}\n onChange={(e) => setAttachmentMediaId(e.target.value)}\n className=\"w-full px-3 py-2 border border-border-subtle rounded-md bg-bg-surface text-sm\"\n aria-label=\"Select media to attach\"\n >\n <option value=\"\">\n {mediaLoading ? 'Loading media...' : 'Select uploaded media'}\n </option>\n {media.map((item) => (\n <option key={item.id} value={item.id}>\n {item.name} ({item.type})\n </option>\n ))}\n </select>\n\n <select\n value={attachmentPosition}\n onChange={(e) =>\n setAttachmentPosition(e.target.value as 'header' | 'body' | 'footer')\n }\n className=\"w-full px-3 py-2 border border-border-subtle rounded-md bg-bg-surface text-sm\"\n aria-label=\"Attachment position\"\n >\n <option value=\"header\">Header</option>\n <option value=\"body\">Body</option>\n <option value=\"footer\">Footer</option>\n </select>\n\n <button\n type=\"button\"\n onClick={handleAttachMedia}\n disabled={attachingMedia || !attachmentMediaId}\n className=\"px-4 py-2 min-h-[44px] border border-border-subtle rounded-md hover:bg-accent disabled:opacity-50\"\n >\n Attach\n </button>\n </div>\n </div>\n </div>\n ) : (\n <div className=\"flex flex-col items-center justify-center h-full text-center px-4\">\n <div className=\"size-16 bg-bg-sunken rounded-full flex items-center justify-center mb-4\">\n <Plus size={24} className=\"text-text-secondary\" />\n </div>\n <p className=\"text-text-secondary mb-2\">{tr('stepEditor.noStepSelected')}</p>\n <p className=\"text-sm text-text-secondary mb-4\">\n {steps.length > 0\n ? tr('stepEditor.selectStepToEdit')\n : tr('stepEditor.createFirstStep')}\n </p>\n {steps.length === 0 && canCreateStep && (\n <button\n type=\"button\"\n onClick={handleAddStep}\n className=\"px-4 py-2 min-h-[44px] bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg/90 flex items-center gap-2\"\n >\n <Plus size={18} />\n {tr('stepEditor.addFirstStep')}\n </button>\n )}\n </div>\n )}\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|