veo-sdk 0.3.5 → 0.3.7
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/builder-7MBMYL26.mjs +5 -0
- package/dist/{builder-FBNBSKCL.mjs.map → builder-7MBMYL26.mjs.map} +1 -1
- package/dist/builder.cjs +502 -151
- package/dist/builder.cjs.map +1 -1
- package/dist/builder.d.cts +2 -2
- package/dist/builder.d.ts +2 -2
- package/dist/builder.mjs +4 -4
- package/dist/{chunk-GHP7ZJCW.mjs → chunk-4VJIILXF.mjs} +504 -153
- package/dist/chunk-4VJIILXF.mjs.map +1 -0
- package/dist/{chunk-TAZXRQYY.mjs → chunk-734ORVMM.mjs} +3 -3
- package/dist/{chunk-TAZXRQYY.mjs.map → chunk-734ORVMM.mjs.map} +1 -1
- package/dist/{chunk-R4E3LIDB.mjs → chunk-RNHOBE2D.mjs} +34 -4
- package/dist/chunk-RNHOBE2D.mjs.map +1 -0
- package/dist/{guide-preview-CO5ShtNf.d.cts → guide-preview-DewCTa-B.d.cts} +26 -1
- package/dist/{guide-preview-CO5ShtNf.d.ts → guide-preview-DewCTa-B.d.ts} +26 -1
- package/dist/index.cjs +552 -158
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +5 -5
- package/dist/veo-builder.js +49 -16
- package/dist/veo-builder.js.map +1 -1
- package/dist/veo-guides.js +44 -11
- package/dist/veo-guides.js.map +1 -1
- package/dist/veo.js +2 -2
- package/dist/veo.js.map +1 -1
- package/package.json +1 -1
- package/dist/builder-FBNBSKCL.mjs +0 -5
- package/dist/chunk-GHP7ZJCW.mjs.map +0 -1
- package/dist/chunk-R4E3LIDB.mjs.map +0 -1
|
@@ -25,6 +25,8 @@ function hasNavigatorSendBeacon() {
|
|
|
25
25
|
|
|
26
26
|
// src/core/builder-token.ts
|
|
27
27
|
var CTX_KEY = "veo:builder_ctx";
|
|
28
|
+
var LS_PREFIX = "veo:builder_ctx:";
|
|
29
|
+
var PERSIST_TTL_MS = 12 * 60 * 60 * 1e3;
|
|
28
30
|
function session() {
|
|
29
31
|
try {
|
|
30
32
|
return window.sessionStorage;
|
|
@@ -32,6 +34,59 @@ function session() {
|
|
|
32
34
|
return null;
|
|
33
35
|
}
|
|
34
36
|
}
|
|
37
|
+
function local() {
|
|
38
|
+
try {
|
|
39
|
+
return window.localStorage;
|
|
40
|
+
} catch {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function lsKey(guide) {
|
|
45
|
+
return LS_PREFIX + (guide || "default");
|
|
46
|
+
}
|
|
47
|
+
function persist(ctx) {
|
|
48
|
+
try {
|
|
49
|
+
session()?.setItem(CTX_KEY, JSON.stringify(ctx));
|
|
50
|
+
} catch {
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
const stored = { ...ctx, savedAt: Date.now() };
|
|
54
|
+
local()?.setItem(lsKey(ctx.guide), JSON.stringify(stored));
|
|
55
|
+
} catch {
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function readFreshFromLocal() {
|
|
59
|
+
const store = local();
|
|
60
|
+
if (!store) return null;
|
|
61
|
+
let best = null;
|
|
62
|
+
try {
|
|
63
|
+
for (let i = 0; i < store.length; i++) {
|
|
64
|
+
const key = store.key(i);
|
|
65
|
+
if (!key?.startsWith(LS_PREFIX)) continue;
|
|
66
|
+
const raw = store.getItem(key);
|
|
67
|
+
if (!raw) continue;
|
|
68
|
+
let parsed = null;
|
|
69
|
+
try {
|
|
70
|
+
parsed = JSON.parse(raw);
|
|
71
|
+
} catch {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
if (typeof parsed?.savedAt !== "number" || Date.now() - parsed.savedAt > PERSIST_TTL_MS) {
|
|
75
|
+
try {
|
|
76
|
+
store.removeItem(key);
|
|
77
|
+
} catch {
|
|
78
|
+
}
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
if (!best || parsed.savedAt > best.savedAt) best = parsed;
|
|
82
|
+
}
|
|
83
|
+
} catch {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
if (!best) return null;
|
|
87
|
+
const { savedAt: _savedAt, ...ctx } = best;
|
|
88
|
+
return ctx;
|
|
89
|
+
}
|
|
35
90
|
function urlParams() {
|
|
36
91
|
try {
|
|
37
92
|
return new URLSearchParams(window.location.search);
|
|
@@ -51,18 +106,22 @@ function resolveBuilderContext() {
|
|
|
51
106
|
guide: params?.get(BUILDER_GUIDE_PARAM) ?? null,
|
|
52
107
|
panelPath: params?.get(BUILDER_PANEL_PATH_PARAM) ?? null
|
|
53
108
|
};
|
|
54
|
-
|
|
55
|
-
session()?.setItem(CTX_KEY, JSON.stringify(ctx));
|
|
56
|
-
} catch {
|
|
57
|
-
}
|
|
109
|
+
persist(ctx);
|
|
58
110
|
return ctx;
|
|
59
111
|
}
|
|
60
112
|
try {
|
|
61
113
|
const raw = session()?.getItem(CTX_KEY);
|
|
62
|
-
|
|
114
|
+
if (raw) return JSON.parse(raw);
|
|
63
115
|
} catch {
|
|
64
|
-
return null;
|
|
65
116
|
}
|
|
117
|
+
const fromLocal = readFreshFromLocal();
|
|
118
|
+
if (fromLocal) {
|
|
119
|
+
try {
|
|
120
|
+
session()?.setItem(CTX_KEY, JSON.stringify(fromLocal));
|
|
121
|
+
} catch {
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return fromLocal;
|
|
66
125
|
}
|
|
67
126
|
function resolveBuilderToken() {
|
|
68
127
|
return resolveBuilderContext()?.token ?? null;
|
|
@@ -72,10 +131,20 @@ function isBuilderMode() {
|
|
|
72
131
|
}
|
|
73
132
|
function clearBuilderToken() {
|
|
74
133
|
if (!hasWindow()) return;
|
|
134
|
+
let guide = null;
|
|
135
|
+
try {
|
|
136
|
+
const raw = session()?.getItem(CTX_KEY);
|
|
137
|
+
if (raw) guide = JSON.parse(raw).guide ?? null;
|
|
138
|
+
} catch {
|
|
139
|
+
}
|
|
75
140
|
try {
|
|
76
141
|
session()?.removeItem(CTX_KEY);
|
|
77
142
|
} catch {
|
|
78
143
|
}
|
|
144
|
+
try {
|
|
145
|
+
local()?.removeItem(lsKey(guide));
|
|
146
|
+
} catch {
|
|
147
|
+
}
|
|
79
148
|
}
|
|
80
149
|
|
|
81
150
|
// src/plugins/guides/constants.ts
|
|
@@ -97,6 +166,16 @@ var WALKTHROUGH_STEP_SELECTOR_TIMEOUT_MS = 5e3;
|
|
|
97
166
|
function buildStepContent(step, doc, callbacks) {
|
|
98
167
|
const container = doc.createElement("div");
|
|
99
168
|
container.className = "veo-guide-content";
|
|
169
|
+
const blocks = normalizeBlocks(step);
|
|
170
|
+
if (blocks) {
|
|
171
|
+
renderBlocks(container, blocks, doc, callbacks);
|
|
172
|
+
} else {
|
|
173
|
+
renderLegacyStep(container, step, doc, callbacks);
|
|
174
|
+
}
|
|
175
|
+
container.appendChild(createCloseButton(doc, () => callbacks.onDismiss()));
|
|
176
|
+
return container;
|
|
177
|
+
}
|
|
178
|
+
function renderLegacyStep(container, step, doc, callbacks) {
|
|
100
179
|
if (typeof step.imageUrl === "string" && step.imageUrl && isSafeUrl(step.imageUrl)) {
|
|
101
180
|
const img = doc.createElement("img");
|
|
102
181
|
img.className = "veo-guide-image";
|
|
@@ -131,14 +210,119 @@ function buildStepContent(step, doc, callbacks) {
|
|
|
131
210
|
actions.appendChild(cta);
|
|
132
211
|
}
|
|
133
212
|
container.appendChild(actions);
|
|
213
|
+
}
|
|
214
|
+
function normalizeBlocks(step) {
|
|
215
|
+
if (!Array.isArray(step.blocks) || step.blocks.length === 0) return null;
|
|
216
|
+
const valid = step.blocks.filter((b) => {
|
|
217
|
+
if (!b || typeof b !== "object") return false;
|
|
218
|
+
if (b.type === "image") return typeof b.url === "string" && isSafeUrl(b.url);
|
|
219
|
+
return b.type === "title" || b.type === "text" || b.type === "button";
|
|
220
|
+
});
|
|
221
|
+
return valid.length > 0 ? valid : null;
|
|
222
|
+
}
|
|
223
|
+
function renderBlocks(container, blocks, doc, callbacks) {
|
|
224
|
+
let i = 0;
|
|
225
|
+
while (i < blocks.length) {
|
|
226
|
+
const block = blocks[i];
|
|
227
|
+
if (block?.type === "button") {
|
|
228
|
+
const actions = doc.createElement("div");
|
|
229
|
+
actions.className = "veo-guide-actions";
|
|
230
|
+
while (i < blocks.length && blocks[i]?.type === "button") {
|
|
231
|
+
const btnBlock = blocks[i];
|
|
232
|
+
actions.appendChild(buildButtonBlock(btnBlock, doc, callbacks));
|
|
233
|
+
i++;
|
|
234
|
+
}
|
|
235
|
+
container.appendChild(actions);
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
const node = buildContentBlock(block, doc);
|
|
239
|
+
if (node) container.appendChild(node);
|
|
240
|
+
i++;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
function buildContentBlock(block, doc) {
|
|
244
|
+
switch (block.type) {
|
|
245
|
+
case "title": {
|
|
246
|
+
const el = doc.createElement("h2");
|
|
247
|
+
el.className = "veo-guide-title";
|
|
248
|
+
el.textContent = typeof block.text === "string" ? block.text : "";
|
|
249
|
+
applyBlockStyle(el, block.style, "text");
|
|
250
|
+
return el;
|
|
251
|
+
}
|
|
252
|
+
case "text": {
|
|
253
|
+
const el = doc.createElement("p");
|
|
254
|
+
el.className = "veo-guide-text";
|
|
255
|
+
el.textContent = typeof block.text === "string" ? block.text : "";
|
|
256
|
+
applyBlockStyle(el, block.style, "text");
|
|
257
|
+
return el;
|
|
258
|
+
}
|
|
259
|
+
case "image": {
|
|
260
|
+
if (typeof block.url !== "string" || !isSafeUrl(block.url)) return null;
|
|
261
|
+
const el = doc.createElement("img");
|
|
262
|
+
el.className = "veo-guide-image";
|
|
263
|
+
el.src = block.url;
|
|
264
|
+
el.alt = "";
|
|
265
|
+
applyBlockStyle(el, block.style, "image");
|
|
266
|
+
return el;
|
|
267
|
+
}
|
|
268
|
+
default:
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
function buildButtonBlock(block, doc, callbacks) {
|
|
273
|
+
const btn = doc.createElement("button");
|
|
274
|
+
btn.type = "button";
|
|
275
|
+
btn.className = "veo-guide-cta";
|
|
276
|
+
btn.textContent = typeof block.text === "string" && block.text ? block.text : "OK";
|
|
277
|
+
applyBlockStyle(btn, block.style, "button");
|
|
278
|
+
btn.addEventListener("click", () => {
|
|
279
|
+
const action = block.action ?? "dismiss";
|
|
280
|
+
const url = action === "url" && typeof block.url === "string" && isSafeUrl(block.url) ? block.url : void 0;
|
|
281
|
+
callbacks.onCtaClick(action, url);
|
|
282
|
+
});
|
|
283
|
+
return btn;
|
|
284
|
+
}
|
|
285
|
+
var BLOCK_ALIGN_SELF = {
|
|
286
|
+
left: "flex-start",
|
|
287
|
+
center: "center",
|
|
288
|
+
right: "flex-end"
|
|
289
|
+
};
|
|
290
|
+
function clampNum(n, min, max) {
|
|
291
|
+
return Math.min(max, Math.max(min, n));
|
|
292
|
+
}
|
|
293
|
+
function applyBlockStyle(el, style, kind) {
|
|
294
|
+
if (!style || typeof style !== "object") return;
|
|
295
|
+
const s = style;
|
|
296
|
+
const align = typeof s.align === "string" ? s.align : null;
|
|
297
|
+
if (align && (align === "left" || align === "center" || align === "right")) {
|
|
298
|
+
if (kind === "text") el.style.textAlign = align;
|
|
299
|
+
else el.style.alignSelf = BLOCK_ALIGN_SELF[align];
|
|
300
|
+
}
|
|
301
|
+
if (kind !== "image" && typeof s.color === "string") el.style.color = s.color;
|
|
302
|
+
if (kind === "text" && typeof s.fontSize === "number" && Number.isFinite(s.fontSize)) {
|
|
303
|
+
el.style.fontSize = `${clampNum(s.fontSize, 8, 72)}px`;
|
|
304
|
+
}
|
|
305
|
+
if (kind === "image" && typeof s.width === "number" && Number.isFinite(s.width)) {
|
|
306
|
+
el.style.width = `${clampNum(s.width, 10, 100)}%`;
|
|
307
|
+
}
|
|
308
|
+
if (kind === "image" && typeof s.radius === "number" && Number.isFinite(s.radius)) {
|
|
309
|
+
el.style.borderRadius = `${clampNum(s.radius, 0, 48)}px`;
|
|
310
|
+
}
|
|
311
|
+
if (typeof s.marginTop === "number" && Number.isFinite(s.marginTop)) {
|
|
312
|
+
el.style.marginTop = `${clampNum(s.marginTop, 0, 64)}px`;
|
|
313
|
+
}
|
|
314
|
+
if (typeof s.marginBottom === "number" && Number.isFinite(s.marginBottom)) {
|
|
315
|
+
el.style.marginBottom = `${clampNum(s.marginBottom, 0, 64)}px`;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
function createCloseButton(doc, onClose, className = "veo-guide-close") {
|
|
134
319
|
const closeBtn = doc.createElement("button");
|
|
135
320
|
closeBtn.type = "button";
|
|
136
|
-
closeBtn.className =
|
|
321
|
+
closeBtn.className = className;
|
|
137
322
|
closeBtn.setAttribute("aria-label", "Cerrar");
|
|
138
323
|
closeBtn.textContent = "\xD7";
|
|
139
|
-
closeBtn.addEventListener("click",
|
|
140
|
-
|
|
141
|
-
return container;
|
|
324
|
+
closeBtn.addEventListener("click", onClose);
|
|
325
|
+
return closeBtn;
|
|
142
326
|
}
|
|
143
327
|
function isSafeUrl(url) {
|
|
144
328
|
if (typeof url !== "string" || url.length === 0) return false;
|
|
@@ -156,6 +340,78 @@ function readCtaUrl(step) {
|
|
|
156
340
|
return isSafeUrl(candidate) ? candidate : void 0;
|
|
157
341
|
}
|
|
158
342
|
|
|
343
|
+
// src/plugins/guides/walkthrough-block-builder.ts
|
|
344
|
+
function buildWalkthroughStepContent(step, stepIndex, totalSteps, doc, callbacks) {
|
|
345
|
+
const container = doc.createElement("div");
|
|
346
|
+
container.className = "veo-guide-content";
|
|
347
|
+
const counter = doc.createElement("div");
|
|
348
|
+
counter.className = "veo-walkthrough-counter";
|
|
349
|
+
counter.textContent = `Paso ${stepIndex + 1} de ${totalSteps}`;
|
|
350
|
+
container.appendChild(counter);
|
|
351
|
+
const progress = doc.createElement("div");
|
|
352
|
+
progress.className = "veo-walkthrough-progress";
|
|
353
|
+
for (let i = 0; i < totalSteps; i++) {
|
|
354
|
+
const dot = doc.createElement("span");
|
|
355
|
+
dot.className = "veo-walkthrough-progress-dot";
|
|
356
|
+
if (i < stepIndex) dot.classList.add("completed");
|
|
357
|
+
if (i === stepIndex) dot.classList.add("active");
|
|
358
|
+
progress.appendChild(dot);
|
|
359
|
+
}
|
|
360
|
+
container.appendChild(progress);
|
|
361
|
+
if (typeof step.imageUrl === "string" && step.imageUrl && isSafeUrl(step.imageUrl)) {
|
|
362
|
+
const img = doc.createElement("img");
|
|
363
|
+
img.className = "veo-guide-image";
|
|
364
|
+
img.src = step.imageUrl;
|
|
365
|
+
img.alt = typeof step.title === "string" ? step.title : "";
|
|
366
|
+
container.appendChild(img);
|
|
367
|
+
}
|
|
368
|
+
if (typeof step.title === "string" && step.title) {
|
|
369
|
+
const heading = doc.createElement("h2");
|
|
370
|
+
heading.className = "veo-guide-title";
|
|
371
|
+
heading.textContent = step.title;
|
|
372
|
+
container.appendChild(heading);
|
|
373
|
+
}
|
|
374
|
+
if (typeof step.content === "string" && step.content) {
|
|
375
|
+
const paragraph = doc.createElement("p");
|
|
376
|
+
paragraph.className = "veo-guide-text";
|
|
377
|
+
paragraph.textContent = step.content;
|
|
378
|
+
container.appendChild(paragraph);
|
|
379
|
+
}
|
|
380
|
+
const actions = doc.createElement("div");
|
|
381
|
+
actions.className = "veo-walkthrough-actions";
|
|
382
|
+
const skipBtn = doc.createElement("button");
|
|
383
|
+
skipBtn.type = "button";
|
|
384
|
+
skipBtn.className = "veo-walkthrough-skip";
|
|
385
|
+
skipBtn.textContent = "Omitir";
|
|
386
|
+
skipBtn.addEventListener("click", () => callbacks.onSkip());
|
|
387
|
+
actions.appendChild(skipBtn);
|
|
388
|
+
const rightGroup = doc.createElement("div");
|
|
389
|
+
rightGroup.className = "veo-walkthrough-actions-right";
|
|
390
|
+
if (stepIndex > 0) {
|
|
391
|
+
const backBtn = doc.createElement("button");
|
|
392
|
+
backBtn.type = "button";
|
|
393
|
+
backBtn.className = "veo-walkthrough-btn-secondary";
|
|
394
|
+
backBtn.textContent = "Atr\xE1s";
|
|
395
|
+
backBtn.addEventListener("click", () => callbacks.onBack());
|
|
396
|
+
rightGroup.appendChild(backBtn);
|
|
397
|
+
}
|
|
398
|
+
const isLastStep = stepIndex === totalSteps - 1;
|
|
399
|
+
const primaryBtn = doc.createElement("button");
|
|
400
|
+
primaryBtn.type = "button";
|
|
401
|
+
primaryBtn.className = "veo-guide-cta";
|
|
402
|
+
const defaultLabel = isLastStep ? "Finalizar" : "Siguiente";
|
|
403
|
+
primaryBtn.textContent = typeof step.ctaText === "string" && step.ctaText ? step.ctaText : defaultLabel;
|
|
404
|
+
primaryBtn.addEventListener("click", () => {
|
|
405
|
+
if (isLastStep) callbacks.onComplete();
|
|
406
|
+
else callbacks.onNext();
|
|
407
|
+
});
|
|
408
|
+
rightGroup.appendChild(primaryBtn);
|
|
409
|
+
actions.appendChild(rightGroup);
|
|
410
|
+
container.appendChild(actions);
|
|
411
|
+
container.appendChild(createCloseButton(doc, () => callbacks.onSkip()));
|
|
412
|
+
return container;
|
|
413
|
+
}
|
|
414
|
+
|
|
159
415
|
// src/plugins/guides/guide-design.ts
|
|
160
416
|
var DARK_THEME = {
|
|
161
417
|
"--veo-bg": "#1f2937",
|
|
@@ -168,6 +424,16 @@ var ALIGN_JUSTIFY = {
|
|
|
168
424
|
center: "center",
|
|
169
425
|
right: "flex-end"
|
|
170
426
|
};
|
|
427
|
+
var ALIGN_SELF = {
|
|
428
|
+
left: "flex-start",
|
|
429
|
+
center: "center",
|
|
430
|
+
right: "flex-end"
|
|
431
|
+
};
|
|
432
|
+
var ELEMENT_ALIGN_MODE = {
|
|
433
|
+
title: "text",
|
|
434
|
+
text: "text",
|
|
435
|
+
image: "self"
|
|
436
|
+
};
|
|
171
437
|
var SHADOW = {
|
|
172
438
|
none: "none",
|
|
173
439
|
soft: "0 4px 14px rgba(0, 0, 0, 0.10)",
|
|
@@ -195,6 +461,9 @@ function applyDesignVars(host, style) {
|
|
|
195
461
|
if (typeof s.accentColor === "string" && COLOR_RE.test(s.accentColor.trim())) {
|
|
196
462
|
host.style.setProperty("--veo-primary", s.accentColor.trim());
|
|
197
463
|
}
|
|
464
|
+
if (typeof s.fontFamily === "string" && s.fontFamily.length <= 200 && !/[<>{}]/.test(s.fontFamily)) {
|
|
465
|
+
host.style.setProperty("--veo-font", s.fontFamily.trim());
|
|
466
|
+
}
|
|
198
467
|
if (s.theme === "dark") {
|
|
199
468
|
for (const [key, value] of Object.entries(DARK_THEME)) {
|
|
200
469
|
host.style.setProperty(key, value);
|
|
@@ -236,6 +505,43 @@ function applyDesignVars(host, style) {
|
|
|
236
505
|
host.style.setProperty("--veo-pos-x", `${px * 100}%`);
|
|
237
506
|
host.style.setProperty("--veo-pos-y", `${py * 100}%`);
|
|
238
507
|
}
|
|
508
|
+
if (s.elements && typeof s.elements === "object") {
|
|
509
|
+
const el = s.elements;
|
|
510
|
+
applyElementVars(host, "title", el.title);
|
|
511
|
+
applyElementVars(host, "text", el.text);
|
|
512
|
+
applyElementVars(host, "image", el.image);
|
|
513
|
+
const cta = el.cta;
|
|
514
|
+
if (cta && typeof cta.align === "string" && ALIGN_JUSTIFY[cta.align]) {
|
|
515
|
+
host.style.setProperty("--veo-actions-justify", ALIGN_JUSTIFY[cta.align]);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
function applyElementVars(host, prefix, raw) {
|
|
520
|
+
if (!raw || typeof raw !== "object") return;
|
|
521
|
+
const el = raw;
|
|
522
|
+
if (typeof el.align === "string" && (el.align === "left" || el.align === "center" || el.align === "right")) {
|
|
523
|
+
const mode = ELEMENT_ALIGN_MODE[prefix] ?? "text";
|
|
524
|
+
const value = mode === "self" ? ALIGN_SELF[el.align] : el.align;
|
|
525
|
+
host.style.setProperty(`--veo-${prefix}-align`, value);
|
|
526
|
+
}
|
|
527
|
+
if (typeof el.color === "string" && COLOR_RE.test(el.color.trim())) {
|
|
528
|
+
host.style.setProperty(`--veo-${prefix}-color`, el.color.trim());
|
|
529
|
+
}
|
|
530
|
+
if (typeof el.fontSize === "number" && Number.isFinite(el.fontSize)) {
|
|
531
|
+
host.style.setProperty(`--veo-${prefix}-size`, `${clamp(el.fontSize, 8, 72)}px`);
|
|
532
|
+
}
|
|
533
|
+
if (typeof el.width === "number" && Number.isFinite(el.width)) {
|
|
534
|
+
host.style.setProperty(`--veo-${prefix}-width`, `${clamp(el.width, 10, 100)}%`);
|
|
535
|
+
}
|
|
536
|
+
if (typeof el.radius === "number" && Number.isFinite(el.radius)) {
|
|
537
|
+
host.style.setProperty(`--veo-${prefix}-radius`, `${clamp(el.radius, 0, 48)}px`);
|
|
538
|
+
}
|
|
539
|
+
if (typeof el.marginTop === "number" && Number.isFinite(el.marginTop)) {
|
|
540
|
+
host.style.setProperty(`--veo-${prefix}-mt`, `${clamp(el.marginTop, 0, 64)}px`);
|
|
541
|
+
}
|
|
542
|
+
if (typeof el.marginBottom === "number" && Number.isFinite(el.marginBottom)) {
|
|
543
|
+
host.style.setProperty(`--veo-${prefix}-mb`, `${clamp(el.marginBottom, 0, 64)}px`);
|
|
544
|
+
}
|
|
239
545
|
}
|
|
240
546
|
|
|
241
547
|
// src/plugins/guides/styles.ts
|
|
@@ -251,7 +557,7 @@ var GUIDE_STYLES = `
|
|
|
251
557
|
--veo-actions-justify: flex-end;
|
|
252
558
|
all: initial;
|
|
253
559
|
}
|
|
254
|
-
* { box-sizing: border-box; font-family: -apple-system, system-ui, "Segoe UI", Roboto, sans-serif; }
|
|
560
|
+
* { box-sizing: border-box; font-family: var(--veo-font, -apple-system, system-ui, "Segoe UI", Roboto, sans-serif); }
|
|
255
561
|
|
|
256
562
|
.veo-modal-overlay {
|
|
257
563
|
position: fixed; inset: 0;
|
|
@@ -302,6 +608,15 @@ var GUIDE_STYLES = `
|
|
|
302
608
|
box-shadow: var(--veo-shadow, 0 8px 30px rgba(0, 0, 0, 0.18));
|
|
303
609
|
animation: veo-fade-in 150ms ease-out;
|
|
304
610
|
}
|
|
611
|
+
.veo-tooltip-arrow {
|
|
612
|
+
position: absolute;
|
|
613
|
+
width: 12px;
|
|
614
|
+
height: 12px;
|
|
615
|
+
background: var(--veo-bg);
|
|
616
|
+
border: var(--veo-border-width, 0) solid var(--veo-border-color, transparent);
|
|
617
|
+
transform: rotate(45deg);
|
|
618
|
+
pointer-events: none;
|
|
619
|
+
}
|
|
305
620
|
|
|
306
621
|
.veo-inline {
|
|
307
622
|
background: var(--veo-bg);
|
|
@@ -320,17 +635,25 @@ var GUIDE_STYLES = `
|
|
|
320
635
|
display: flex; flex-direction: column;
|
|
321
636
|
}
|
|
322
637
|
.veo-guide-image {
|
|
323
|
-
display: block;
|
|
324
|
-
|
|
325
|
-
|
|
638
|
+
display: block;
|
|
639
|
+
width: var(--veo-image-width, 100%);
|
|
640
|
+
max-height: 180px;
|
|
641
|
+
object-fit: cover;
|
|
642
|
+
align-self: var(--veo-image-align, stretch);
|
|
643
|
+
border-radius: var(--veo-image-radius, 8px);
|
|
644
|
+
margin: var(--veo-image-mt, 0) 0 var(--veo-image-mb, 12px);
|
|
326
645
|
}
|
|
327
646
|
.veo-guide-title {
|
|
328
|
-
font-size: 18px; font-weight: 600; line-height: 1.3;
|
|
329
|
-
|
|
647
|
+
font-size: var(--veo-title-size, 18px); font-weight: 600; line-height: 1.3;
|
|
648
|
+
text-align: var(--veo-title-align, left);
|
|
649
|
+
margin: var(--veo-title-mt, 0) 0 var(--veo-title-mb, 6px);
|
|
650
|
+
color: var(--veo-title-color, var(--veo-text));
|
|
330
651
|
}
|
|
331
652
|
.veo-guide-text {
|
|
332
|
-
font-size: 14px; line-height: 1.5;
|
|
333
|
-
|
|
653
|
+
font-size: var(--veo-text-size, 14px); line-height: 1.5;
|
|
654
|
+
text-align: var(--veo-text-align, left);
|
|
655
|
+
margin: var(--veo-text-mt, 0) 0 var(--veo-text-mb, 16px);
|
|
656
|
+
color: var(--veo-text-color, var(--veo-text-secondary));
|
|
334
657
|
}
|
|
335
658
|
.veo-guide-actions {
|
|
336
659
|
display: flex; gap: 8px; justify-content: var(--veo-actions-justify);
|
|
@@ -467,6 +790,7 @@ var GUIDE_STYLES = `
|
|
|
467
790
|
}
|
|
468
791
|
.veo-custom-inline {
|
|
469
792
|
display: block;
|
|
793
|
+
position: relative;
|
|
470
794
|
margin: 12px 0;
|
|
471
795
|
}
|
|
472
796
|
.veo-custom-frame {
|
|
@@ -476,6 +800,21 @@ var GUIDE_STYLES = `
|
|
|
476
800
|
background: transparent;
|
|
477
801
|
color-scheme: normal;
|
|
478
802
|
}
|
|
803
|
+
/*
|
|
804
|
+
* X de cerrar de las gu\xEDas custom: el HTML del cliente vive en un iframe
|
|
805
|
+
* sandbox, as\xED que el bot\xF3n lo pone el host POR ENCIMA del iframe. Con fondo
|
|
806
|
+
* propio para ser visible sobre cualquier contenido.
|
|
807
|
+
*/
|
|
808
|
+
.veo-custom-close {
|
|
809
|
+
position: absolute; top: 6px; right: 6px; z-index: 1;
|
|
810
|
+
width: 22px; height: 22px; padding: 0;
|
|
811
|
+
display: flex; align-items: center; justify-content: center;
|
|
812
|
+
font-size: 16px; line-height: 1; color: #6b7280;
|
|
813
|
+
background: rgba(255, 255, 255, 0.92);
|
|
814
|
+
border: 1px solid rgba(0, 0, 0, 0.08); border-radius: 50%;
|
|
815
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.14); cursor: pointer;
|
|
816
|
+
}
|
|
817
|
+
.veo-custom-close:hover { color: #111827; }
|
|
479
818
|
|
|
480
819
|
@keyframes veo-fade-in { from { opacity: 0; } to { opacity: 1; } }
|
|
481
820
|
@keyframes veo-slide-up {
|
|
@@ -549,7 +888,8 @@ var BaseRenderer = class {
|
|
|
549
888
|
// src/plugins/guides/renderers/banner-renderer.ts
|
|
550
889
|
var BannerRenderer = class extends BaseRenderer {
|
|
551
890
|
render(context) {
|
|
552
|
-
const
|
|
891
|
+
const idx = context.nav?.stepIndex ?? 0;
|
|
892
|
+
const step = context.guide.guideSteps[idx];
|
|
553
893
|
if (!step) return;
|
|
554
894
|
const { root } = this.createHost();
|
|
555
895
|
this.applyDesign(step.style);
|
|
@@ -558,27 +898,25 @@ var BannerRenderer = class extends BaseRenderer {
|
|
|
558
898
|
const banner = ownerDocument.createElement("div");
|
|
559
899
|
banner.className = `veo-banner veo-banner-${position}`;
|
|
560
900
|
const dismiss = (action, ctaUrl) => {
|
|
561
|
-
context.onInteraction({
|
|
562
|
-
guideId: context.guide.guideId,
|
|
563
|
-
stepIndex: 0,
|
|
564
|
-
action
|
|
565
|
-
});
|
|
901
|
+
context.onInteraction({ guideId: context.guide.guideId, stepIndex: idx, action });
|
|
566
902
|
if (ctaUrl) window.open(ctaUrl, "_blank", "noopener,noreferrer");
|
|
567
903
|
context.onClose();
|
|
568
904
|
};
|
|
569
|
-
const content =
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
905
|
+
const content = context.nav ? buildWalkthroughStepContent(
|
|
906
|
+
step,
|
|
907
|
+
context.nav.stepIndex,
|
|
908
|
+
context.nav.totalSteps,
|
|
909
|
+
ownerDocument,
|
|
910
|
+
context.nav.callbacks
|
|
911
|
+
) : buildStepContent(step, ownerDocument, {
|
|
912
|
+
onCtaClick: (action, url) => dismiss("cta_clicked", action === "url" ? url : void 0),
|
|
573
913
|
onDismiss: () => dismiss("dismissed")
|
|
574
914
|
});
|
|
575
915
|
banner.appendChild(content);
|
|
576
916
|
root.appendChild(banner);
|
|
577
|
-
context.
|
|
578
|
-
guideId: context.guide.guideId,
|
|
579
|
-
|
|
580
|
-
action: "shown"
|
|
581
|
-
});
|
|
917
|
+
if (!context.nav) {
|
|
918
|
+
context.onInteraction({ guideId: context.guide.guideId, stepIndex: 0, action: "shown" });
|
|
919
|
+
}
|
|
582
920
|
}
|
|
583
921
|
};
|
|
584
922
|
|
|
@@ -648,7 +986,11 @@ function mountCustomFrame(doc, step, context, opts) {
|
|
|
648
986
|
const hasFixedHeight = opts.fixedHeight !== void 0 && opts.fixedHeight !== null;
|
|
649
987
|
if (hasFixedHeight) iframe.style.height = toCssSize(opts.fixedHeight);
|
|
650
988
|
const token = uuidv7();
|
|
651
|
-
|
|
989
|
+
const wantsTailwind = step.style?.tailwind === true;
|
|
990
|
+
iframe.srcdoc = buildSrcdoc(step.html ?? "", step.css ?? "", step.js ?? "", token, {
|
|
991
|
+
tokens: collectHostTokens(),
|
|
992
|
+
tailwind: wantsTailwind
|
|
993
|
+
});
|
|
652
994
|
const close = () => context.onClose();
|
|
653
995
|
const onMessage = (event) => {
|
|
654
996
|
if (event.source !== iframe.contentWindow) return;
|
|
@@ -697,12 +1039,37 @@ function mountCustomFrame(doc, step, context, opts) {
|
|
|
697
1039
|
function toCssSize(value) {
|
|
698
1040
|
return typeof value === "number" ? `${value}px` : value;
|
|
699
1041
|
}
|
|
1042
|
+
function collectHostTokens() {
|
|
1043
|
+
if (typeof window === "undefined" || typeof document === "undefined") return "";
|
|
1044
|
+
try {
|
|
1045
|
+
const rootStyle = getComputedStyle(document.documentElement);
|
|
1046
|
+
const decls = [];
|
|
1047
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1048
|
+
for (let i = 0; i < rootStyle.length && decls.length < 400; i++) {
|
|
1049
|
+
const name = rootStyle.item(i);
|
|
1050
|
+
if (!name.startsWith("--") || seen.has(name)) continue;
|
|
1051
|
+
seen.add(name);
|
|
1052
|
+
const value = rootStyle.getPropertyValue(name).trim();
|
|
1053
|
+
if (!value || value.length > 200 || /[<>{}]/.test(value)) continue;
|
|
1054
|
+
decls.push(`${name}:${value}`);
|
|
1055
|
+
}
|
|
1056
|
+
const bodyFont = getComputedStyle(document.body).fontFamily;
|
|
1057
|
+
if (bodyFont && bodyFont.length <= 200 && !/[<>{}]/.test(bodyFont)) {
|
|
1058
|
+
decls.push(`--veo-host-font:${bodyFont}`);
|
|
1059
|
+
}
|
|
1060
|
+
return decls.length ? `:root{${decls.join(";")}}` : "";
|
|
1061
|
+
} catch {
|
|
1062
|
+
return "";
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
700
1065
|
function isRecord(value) {
|
|
701
1066
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
702
1067
|
}
|
|
703
|
-
function buildSrcdoc(html, css, js, token) {
|
|
1068
|
+
function buildSrcdoc(html, css, js, token, opts) {
|
|
704
1069
|
const bridge = `(function(){var T=${JSON.stringify(token)};function P(m){m.__veo=T;parent.postMessage(m,'*');}window.veo={dismiss:function(){P({type:'dismiss'});},cta:function(u){P({type:'cta',url:u});},track:function(n,p){P({type:'track',name:n,props:p||{}});},navigate:function(u){P({type:'navigate',url:u});}};document.addEventListener('click',function(e){var a=e.target&&e.target.closest?e.target.closest('a[href]'):null;if(!a)return;var h=a.getAttribute('href');if(!h||h.charAt(0)==='#'||/^(javascript|mailto|tel):/i.test(h))return;e.preventDefault();if(a.target==='_blank'){P({type:'cta',url:a.href,close:false});}else{P({type:'navigate',url:h});}},true);function H(){P({type:'resize',height:Math.ceil(document.documentElement.scrollHeight)});}window.addEventListener('load',H);try{if(typeof ResizeObserver!=='undefined'){new ResizeObserver(H).observe(document.documentElement);}}catch(e){}})();`;
|
|
705
|
-
|
|
1070
|
+
const tokensStyle = opts.tokens ? `<style>${escapeClosing(opts.tokens, "style")}</style>` : "";
|
|
1071
|
+
const tailwind = opts.tailwind ? '<script src="https://cdn.tailwindcss.com"></script>' : "";
|
|
1072
|
+
return '<!DOCTYPE html><html><head><meta charset="utf-8"><style>html,body{margin:0;padding:0;background:transparent;font-family:var(--veo-host-font,system-ui,sans-serif);}</style>' + tokensStyle + tailwind + `<style>${escapeClosing(css, "style")}</style></head><body>${html}<script>${bridge}</script>` + (js ? `<script>${escapeClosing(js, "script")}</script>` : "") + "</body></html>";
|
|
706
1073
|
}
|
|
707
1074
|
function escapeClosing(code, tag) {
|
|
708
1075
|
const rx = tag === "script" ? /<\/script/gi : /<\/style/gi;
|
|
@@ -735,6 +1102,20 @@ var CustomRenderer = class extends BaseRenderer {
|
|
|
735
1102
|
});
|
|
736
1103
|
this.registerCleanup(cleanup);
|
|
737
1104
|
wrapper.appendChild(iframe);
|
|
1105
|
+
wrapper.appendChild(
|
|
1106
|
+
createCloseButton(
|
|
1107
|
+
doc,
|
|
1108
|
+
() => {
|
|
1109
|
+
context.onInteraction({
|
|
1110
|
+
guideId: context.guide.guideId,
|
|
1111
|
+
stepIndex: 0,
|
|
1112
|
+
action: "dismissed"
|
|
1113
|
+
});
|
|
1114
|
+
context.onClose();
|
|
1115
|
+
},
|
|
1116
|
+
"veo-custom-close"
|
|
1117
|
+
)
|
|
1118
|
+
);
|
|
738
1119
|
root.appendChild(wrapper);
|
|
739
1120
|
if (placement.mode === "floating") {
|
|
740
1121
|
applyFloatingPosition(wrapper, placement);
|
|
@@ -872,13 +1253,7 @@ function mountFormContent(card, context, doc) {
|
|
|
872
1253
|
});
|
|
873
1254
|
});
|
|
874
1255
|
content.appendChild(form);
|
|
875
|
-
|
|
876
|
-
closeBtn.type = "button";
|
|
877
|
-
closeBtn.className = "veo-guide-close";
|
|
878
|
-
closeBtn.setAttribute("aria-label", "Cerrar");
|
|
879
|
-
closeBtn.textContent = "\xD7";
|
|
880
|
-
closeBtn.addEventListener("click", dismiss);
|
|
881
|
-
content.appendChild(closeBtn);
|
|
1256
|
+
content.appendChild(createCloseButton(doc, dismiss));
|
|
882
1257
|
card.appendChild(content);
|
|
883
1258
|
}
|
|
884
1259
|
function showThanks(card, doc, note) {
|
|
@@ -1142,6 +1517,20 @@ var InlineCustomRenderer = class extends BaseRenderer {
|
|
|
1142
1517
|
const { iframe, cleanup } = mountCustomFrame(doc, step, context, { width: "100%" });
|
|
1143
1518
|
this.registerCleanup(cleanup);
|
|
1144
1519
|
wrapper.appendChild(iframe);
|
|
1520
|
+
wrapper.appendChild(
|
|
1521
|
+
createCloseButton(
|
|
1522
|
+
doc,
|
|
1523
|
+
() => {
|
|
1524
|
+
context.onInteraction({
|
|
1525
|
+
guideId: context.guide.guideId,
|
|
1526
|
+
stepIndex: 0,
|
|
1527
|
+
action: "dismissed"
|
|
1528
|
+
});
|
|
1529
|
+
context.onClose();
|
|
1530
|
+
},
|
|
1531
|
+
"veo-custom-close"
|
|
1532
|
+
)
|
|
1533
|
+
);
|
|
1145
1534
|
root.appendChild(wrapper);
|
|
1146
1535
|
context.onInteraction({ guideId: context.guide.guideId, stepIndex: 0, action: "shown" });
|
|
1147
1536
|
}
|
|
@@ -1207,7 +1596,8 @@ var InlineRenderer = class extends BaseRenderer {
|
|
|
1207
1596
|
// src/plugins/guides/renderers/modal-renderer.ts
|
|
1208
1597
|
var ModalRenderer = class extends BaseRenderer {
|
|
1209
1598
|
render(context) {
|
|
1210
|
-
const
|
|
1599
|
+
const idx = context.nav?.stepIndex ?? 0;
|
|
1600
|
+
const step = context.guide.guideSteps[idx];
|
|
1211
1601
|
if (!step) return;
|
|
1212
1602
|
const { root } = this.createHost();
|
|
1213
1603
|
this.applyDesign(step.style);
|
|
@@ -1217,38 +1607,59 @@ var ModalRenderer = class extends BaseRenderer {
|
|
|
1217
1607
|
const card = ownerDocument.createElement("div");
|
|
1218
1608
|
card.className = "veo-modal-card";
|
|
1219
1609
|
const dismiss = (action, ctaUrl) => {
|
|
1220
|
-
context.onInteraction({
|
|
1221
|
-
guideId: context.guide.guideId,
|
|
1222
|
-
stepIndex: 0,
|
|
1223
|
-
action
|
|
1224
|
-
});
|
|
1610
|
+
context.onInteraction({ guideId: context.guide.guideId, stepIndex: idx, action });
|
|
1225
1611
|
if (ctaUrl) window.open(ctaUrl, "_blank", "noopener,noreferrer");
|
|
1226
1612
|
context.onClose();
|
|
1227
1613
|
};
|
|
1228
|
-
const
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1614
|
+
const onBackdropOrEsc = () => {
|
|
1615
|
+
if (context.nav) context.nav.callbacks.onSkip();
|
|
1616
|
+
else dismiss("dismissed");
|
|
1617
|
+
};
|
|
1618
|
+
const content = context.nav ? buildWalkthroughStepContent(
|
|
1619
|
+
step,
|
|
1620
|
+
context.nav.stepIndex,
|
|
1621
|
+
context.nav.totalSteps,
|
|
1622
|
+
ownerDocument,
|
|
1623
|
+
context.nav.callbacks
|
|
1624
|
+
) : buildStepContent(step, ownerDocument, {
|
|
1625
|
+
onCtaClick: (action, url) => dismiss("cta_clicked", action === "url" ? url : void 0),
|
|
1232
1626
|
onDismiss: () => dismiss("dismissed")
|
|
1233
1627
|
});
|
|
1234
1628
|
card.appendChild(content);
|
|
1235
1629
|
overlay.appendChild(card);
|
|
1236
1630
|
root.appendChild(overlay);
|
|
1237
1631
|
overlay.addEventListener("click", (e) => {
|
|
1238
|
-
if (e.target === overlay)
|
|
1632
|
+
if (e.target === overlay) onBackdropOrEsc();
|
|
1239
1633
|
});
|
|
1240
1634
|
const onKey = (e) => {
|
|
1241
|
-
if (e.key === "Escape")
|
|
1635
|
+
if (e.key === "Escape") onBackdropOrEsc();
|
|
1242
1636
|
};
|
|
1243
1637
|
document.addEventListener("keydown", onKey);
|
|
1244
1638
|
this.registerCleanup(() => document.removeEventListener("keydown", onKey));
|
|
1245
|
-
context.
|
|
1246
|
-
guideId: context.guide.guideId,
|
|
1247
|
-
|
|
1248
|
-
action: "shown"
|
|
1249
|
-
});
|
|
1639
|
+
if (!context.nav) {
|
|
1640
|
+
context.onInteraction({ guideId: context.guide.guideId, stepIndex: 0, action: "shown" });
|
|
1641
|
+
}
|
|
1250
1642
|
}
|
|
1251
1643
|
};
|
|
1644
|
+
|
|
1645
|
+
// src/plugins/guides/renderers/floating-arrow.ts
|
|
1646
|
+
var STATIC_SIDE = {
|
|
1647
|
+
top: "bottom",
|
|
1648
|
+
bottom: "top",
|
|
1649
|
+
left: "right",
|
|
1650
|
+
right: "left"
|
|
1651
|
+
};
|
|
1652
|
+
function positionArrow(arrowEl, placement, data) {
|
|
1653
|
+
const side = STATIC_SIDE[placement.split("-")[0] ?? "bottom"] ?? "top";
|
|
1654
|
+
for (const prop of ["top", "bottom", "left", "right"]) {
|
|
1655
|
+
arrowEl.style.setProperty(prop, "");
|
|
1656
|
+
}
|
|
1657
|
+
if (data?.x != null) arrowEl.style.setProperty("left", `${data.x}px`);
|
|
1658
|
+
if (data?.y != null) arrowEl.style.setProperty("top", `${data.y}px`);
|
|
1659
|
+
arrowEl.style.setProperty(side, "-6px");
|
|
1660
|
+
}
|
|
1661
|
+
|
|
1662
|
+
// src/plugins/guides/renderers/tooltip-renderer.ts
|
|
1252
1663
|
var TooltipRenderer = class extends BaseRenderer {
|
|
1253
1664
|
async render(context) {
|
|
1254
1665
|
const step = context.guide.guideSteps[0];
|
|
@@ -1278,14 +1689,18 @@ var TooltipRenderer = class extends BaseRenderer {
|
|
|
1278
1689
|
onDismiss: () => dismiss("dismissed")
|
|
1279
1690
|
});
|
|
1280
1691
|
tooltip.appendChild(content);
|
|
1692
|
+
const arrowEl = ownerDocument.createElement("div");
|
|
1693
|
+
arrowEl.className = "veo-tooltip-arrow";
|
|
1694
|
+
tooltip.appendChild(arrowEl);
|
|
1281
1695
|
root.appendChild(tooltip);
|
|
1282
1696
|
const updatePosition = async () => {
|
|
1283
|
-
const { x, y } = await computePosition(anchor, tooltip, {
|
|
1697
|
+
const { x, y, placement, middlewareData } = await computePosition(anchor, tooltip, {
|
|
1284
1698
|
placement: "bottom",
|
|
1285
|
-
middleware: [offset(
|
|
1699
|
+
middleware: [offset(10), flip(), shift({ padding: 8 }), arrow({ element: arrowEl })]
|
|
1286
1700
|
});
|
|
1287
1701
|
tooltip.style.left = `${x}px`;
|
|
1288
1702
|
tooltip.style.top = `${y}px`;
|
|
1703
|
+
positionArrow(arrowEl, placement, middlewareData.arrow);
|
|
1289
1704
|
};
|
|
1290
1705
|
await updatePosition();
|
|
1291
1706
|
const reposition = () => {
|
|
@@ -1304,79 +1719,6 @@ var TooltipRenderer = class extends BaseRenderer {
|
|
|
1304
1719
|
});
|
|
1305
1720
|
}
|
|
1306
1721
|
};
|
|
1307
|
-
|
|
1308
|
-
// src/plugins/guides/walkthrough-block-builder.ts
|
|
1309
|
-
function buildWalkthroughStepContent(step, stepIndex, totalSteps, doc, callbacks) {
|
|
1310
|
-
const container = doc.createElement("div");
|
|
1311
|
-
container.className = "veo-guide-content";
|
|
1312
|
-
const counter = doc.createElement("div");
|
|
1313
|
-
counter.className = "veo-walkthrough-counter";
|
|
1314
|
-
counter.textContent = `Paso ${stepIndex + 1} de ${totalSteps}`;
|
|
1315
|
-
container.appendChild(counter);
|
|
1316
|
-
const progress = doc.createElement("div");
|
|
1317
|
-
progress.className = "veo-walkthrough-progress";
|
|
1318
|
-
for (let i = 0; i < totalSteps; i++) {
|
|
1319
|
-
const dot = doc.createElement("span");
|
|
1320
|
-
dot.className = "veo-walkthrough-progress-dot";
|
|
1321
|
-
if (i < stepIndex) dot.classList.add("completed");
|
|
1322
|
-
if (i === stepIndex) dot.classList.add("active");
|
|
1323
|
-
progress.appendChild(dot);
|
|
1324
|
-
}
|
|
1325
|
-
container.appendChild(progress);
|
|
1326
|
-
if (typeof step.imageUrl === "string" && step.imageUrl && isSafeUrl(step.imageUrl)) {
|
|
1327
|
-
const img = doc.createElement("img");
|
|
1328
|
-
img.className = "veo-guide-image";
|
|
1329
|
-
img.src = step.imageUrl;
|
|
1330
|
-
img.alt = typeof step.title === "string" ? step.title : "";
|
|
1331
|
-
container.appendChild(img);
|
|
1332
|
-
}
|
|
1333
|
-
if (typeof step.title === "string" && step.title) {
|
|
1334
|
-
const heading = doc.createElement("h2");
|
|
1335
|
-
heading.className = "veo-guide-title";
|
|
1336
|
-
heading.textContent = step.title;
|
|
1337
|
-
container.appendChild(heading);
|
|
1338
|
-
}
|
|
1339
|
-
if (typeof step.content === "string" && step.content) {
|
|
1340
|
-
const paragraph = doc.createElement("p");
|
|
1341
|
-
paragraph.className = "veo-guide-text";
|
|
1342
|
-
paragraph.textContent = step.content;
|
|
1343
|
-
container.appendChild(paragraph);
|
|
1344
|
-
}
|
|
1345
|
-
const actions = doc.createElement("div");
|
|
1346
|
-
actions.className = "veo-walkthrough-actions";
|
|
1347
|
-
const skipBtn = doc.createElement("button");
|
|
1348
|
-
skipBtn.type = "button";
|
|
1349
|
-
skipBtn.className = "veo-walkthrough-skip";
|
|
1350
|
-
skipBtn.textContent = "Omitir";
|
|
1351
|
-
skipBtn.addEventListener("click", () => callbacks.onSkip());
|
|
1352
|
-
actions.appendChild(skipBtn);
|
|
1353
|
-
const rightGroup = doc.createElement("div");
|
|
1354
|
-
rightGroup.className = "veo-walkthrough-actions-right";
|
|
1355
|
-
if (stepIndex > 0) {
|
|
1356
|
-
const backBtn = doc.createElement("button");
|
|
1357
|
-
backBtn.type = "button";
|
|
1358
|
-
backBtn.className = "veo-walkthrough-btn-secondary";
|
|
1359
|
-
backBtn.textContent = "Atr\xE1s";
|
|
1360
|
-
backBtn.addEventListener("click", () => callbacks.onBack());
|
|
1361
|
-
rightGroup.appendChild(backBtn);
|
|
1362
|
-
}
|
|
1363
|
-
const isLastStep = stepIndex === totalSteps - 1;
|
|
1364
|
-
const primaryBtn = doc.createElement("button");
|
|
1365
|
-
primaryBtn.type = "button";
|
|
1366
|
-
primaryBtn.className = "veo-guide-cta";
|
|
1367
|
-
const defaultLabel = isLastStep ? "Finalizar" : "Siguiente";
|
|
1368
|
-
primaryBtn.textContent = typeof step.ctaText === "string" && step.ctaText ? step.ctaText : defaultLabel;
|
|
1369
|
-
primaryBtn.addEventListener("click", () => {
|
|
1370
|
-
if (isLastStep) callbacks.onComplete();
|
|
1371
|
-
else callbacks.onNext();
|
|
1372
|
-
});
|
|
1373
|
-
rightGroup.appendChild(primaryBtn);
|
|
1374
|
-
actions.appendChild(rightGroup);
|
|
1375
|
-
container.appendChild(actions);
|
|
1376
|
-
return container;
|
|
1377
|
-
}
|
|
1378
|
-
|
|
1379
|
-
// src/plugins/guides/renderers/walkthrough-renderer.ts
|
|
1380
1722
|
var WalkthroughRenderer = class extends BaseRenderer {
|
|
1381
1723
|
async render(context) {
|
|
1382
1724
|
const step = context.guide.guideSteps[context.currentStepIndex];
|
|
@@ -1424,27 +1766,13 @@ var WalkthroughRenderer = class extends BaseRenderer {
|
|
|
1424
1766
|
return true;
|
|
1425
1767
|
}
|
|
1426
1768
|
};
|
|
1427
|
-
var STATIC_SIDE = {
|
|
1428
|
-
top: "bottom",
|
|
1429
|
-
bottom: "top",
|
|
1430
|
-
left: "right",
|
|
1431
|
-
right: "left"
|
|
1432
|
-
};
|
|
1433
|
-
function positionArrow(arrowEl, placement, data) {
|
|
1434
|
-
const side = STATIC_SIDE[placement.split("-")[0] ?? "bottom"] ?? "top";
|
|
1435
|
-
for (const prop of ["top", "bottom", "left", "right"]) {
|
|
1436
|
-
arrowEl.style.setProperty(prop, "");
|
|
1437
|
-
}
|
|
1438
|
-
if (data?.x != null) arrowEl.style.setProperty("left", `${data.x}px`);
|
|
1439
|
-
if (data?.y != null) arrowEl.style.setProperty("top", `${data.y}px`);
|
|
1440
|
-
arrowEl.style.setProperty(side, "-6px");
|
|
1441
|
-
}
|
|
1442
1769
|
|
|
1443
1770
|
// src/plugins/guides/guide-preview.ts
|
|
1444
1771
|
var PREVIEW_GUIDE_ID = "__veo_preview__";
|
|
1445
1772
|
var GuidePreviewController = class {
|
|
1446
1773
|
constructor() {
|
|
1447
1774
|
this.singleStep = null;
|
|
1775
|
+
/** Renderer del paso de walkthrough activo (walkthrough tooltip o modal/banner). */
|
|
1448
1776
|
this.walkthrough = null;
|
|
1449
1777
|
this.walkthroughGuide = null;
|
|
1450
1778
|
this.walkthroughIndex = 0;
|
|
@@ -1517,7 +1845,6 @@ var GuidePreviewController = class {
|
|
|
1517
1845
|
safeDestroy(this.walkthrough);
|
|
1518
1846
|
this.walkthrough = null;
|
|
1519
1847
|
}
|
|
1520
|
-
const renderer = new WalkthroughRenderer();
|
|
1521
1848
|
const callbacks = {
|
|
1522
1849
|
onNext: () => {
|
|
1523
1850
|
const next = this.walkthroughIndex + 1;
|
|
@@ -1537,6 +1864,30 @@ var GuidePreviewController = class {
|
|
|
1537
1864
|
onSkip: () => this.close(),
|
|
1538
1865
|
onComplete: () => this.close()
|
|
1539
1866
|
};
|
|
1867
|
+
const step = guide.guideSteps[index];
|
|
1868
|
+
const render = step?.style?.render;
|
|
1869
|
+
if (render === "modal" || render === "banner") {
|
|
1870
|
+
const renderer2 = render === "modal" ? new ModalRenderer() : new BannerRenderer();
|
|
1871
|
+
try {
|
|
1872
|
+
renderer2.render({
|
|
1873
|
+
guide,
|
|
1874
|
+
onInteraction: () => {
|
|
1875
|
+
},
|
|
1876
|
+
onClose: () => this.close(),
|
|
1877
|
+
nav: { stepIndex: index, totalSteps: guide.guideSteps.length, callbacks }
|
|
1878
|
+
});
|
|
1879
|
+
} catch {
|
|
1880
|
+
safeDestroy(renderer2);
|
|
1881
|
+
return false;
|
|
1882
|
+
}
|
|
1883
|
+
if (this.walkthroughGuide !== guide) {
|
|
1884
|
+
safeDestroy(renderer2);
|
|
1885
|
+
return false;
|
|
1886
|
+
}
|
|
1887
|
+
this.walkthrough = renderer2;
|
|
1888
|
+
return true;
|
|
1889
|
+
}
|
|
1890
|
+
const renderer = new WalkthroughRenderer();
|
|
1540
1891
|
let success = false;
|
|
1541
1892
|
try {
|
|
1542
1893
|
success = await renderer.render({ guide, currentStepIndex: index, callbacks });
|
|
@@ -1743,5 +2094,5 @@ function buildSelectorPath(element, maxAncestors = 5) {
|
|
|
1743
2094
|
}
|
|
1744
2095
|
|
|
1745
2096
|
export { ALWAYS_BLOCK_SELECTORS, BannerRenderer, CustomRenderer, DEFAULT_AUTOCAPTURE_CONFIG, DEFAULT_TRACKER_BATCH_SIZE, DEFAULT_TRACKER_FLUSH_INTERVAL_MS, DEFAULT_TRACKER_MAX_RETRIES, FREQUENCY_CACHE_KEY_PREFIX, FREQUENCY_CACHE_MAX_ENTRIES, FREQUENCY_CACHE_TTL_MS, FormRenderer, InlineCustomRenderer, InlineFormRenderer, InlineRenderer, MAX_ANCESTORS, ModalRenderer, PRIORITY_ATTRIBUTES, SENSITIVE_ATTRIBUTES, TooltipRenderer, WALKTHROUGH_ABANDONMENT_TIMEOUT_MS, WALKTHROUGH_STATE_KEY_PREFIX, WalkthroughRenderer, buildSelectorPath, clearBuilderToken, closeGuidePreview, filterHumanClasses, hasDocument, hasLocalStorage, hasNavigatorSendBeacon, hasWindow, isBuilderMode, previewGuide, resolveBuilderContext, resolveBuilderToken, uuidv7 };
|
|
1746
|
-
//# sourceMappingURL=chunk-
|
|
1747
|
-
//# sourceMappingURL=chunk-
|
|
2097
|
+
//# sourceMappingURL=chunk-4VJIILXF.mjs.map
|
|
2098
|
+
//# sourceMappingURL=chunk-4VJIILXF.mjs.map
|