veo-sdk 0.3.6 → 0.3.8
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-YYMD7MNK.mjs +5 -0
- package/dist/{builder-MIPJRGOD.mjs.map → builder-YYMD7MNK.mjs.map} +1 -1
- package/dist/builder.cjs +267 -112
- 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-B5GO6PTO.mjs → chunk-7OMKQH5J.mjs} +34 -4
- package/dist/chunk-7OMKQH5J.mjs.map +1 -0
- package/dist/{chunk-FUMGOQJR.mjs → chunk-E2KQJBUT.mjs} +269 -114
- package/dist/chunk-E2KQJBUT.mjs.map +1 -0
- package/dist/{chunk-A73VSAZP.mjs → chunk-T4BZ53QV.mjs} +3 -3
- package/dist/{chunk-A73VSAZP.mjs.map → chunk-T4BZ53QV.mjs.map} +1 -1
- 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 +306 -116
- 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 +15 -9
- package/dist/veo-builder.js.map +1 -1
- package/dist/veo-guides.js +10 -4
- package/dist/veo-guides.js.map +1 -1
- package/package.json +1 -1
- package/dist/builder-MIPJRGOD.mjs +0 -5
- package/dist/chunk-B5GO6PTO.mjs.map +0 -1
- package/dist/chunk-FUMGOQJR.mjs.map +0 -1
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { createBuilderSession, initBuilderMode, startElementPicker, stopElementPicker } from './chunk-T4BZ53QV.mjs';
|
|
2
|
+
import './chunk-E2KQJBUT.mjs';
|
|
3
|
+
import './chunk-PTG3BTJE.mjs';
|
|
4
|
+
//# sourceMappingURL=builder-YYMD7MNK.mjs.map
|
|
5
|
+
//# sourceMappingURL=builder-YYMD7MNK.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"builder-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"builder-YYMD7MNK.mjs"}
|
package/dist/builder.cjs
CHANGED
|
@@ -146,6 +146,16 @@ var WALKTHROUGH_STEP_SELECTOR_TIMEOUT_MS = 5e3;
|
|
|
146
146
|
function buildStepContent(step, doc, callbacks) {
|
|
147
147
|
const container = doc.createElement("div");
|
|
148
148
|
container.className = "veo-guide-content";
|
|
149
|
+
const blocks = normalizeBlocks(step);
|
|
150
|
+
if (blocks) {
|
|
151
|
+
renderBlocks(container, blocks, doc, callbacks);
|
|
152
|
+
} else {
|
|
153
|
+
renderLegacyStep(container, step, doc, callbacks);
|
|
154
|
+
}
|
|
155
|
+
container.appendChild(createCloseButton(doc, () => callbacks.onDismiss()));
|
|
156
|
+
return container;
|
|
157
|
+
}
|
|
158
|
+
function renderLegacyStep(container, step, doc, callbacks) {
|
|
149
159
|
if (typeof step.imageUrl === "string" && step.imageUrl && isSafeUrl(step.imageUrl)) {
|
|
150
160
|
const img = doc.createElement("img");
|
|
151
161
|
img.className = "veo-guide-image";
|
|
@@ -180,8 +190,116 @@ function buildStepContent(step, doc, callbacks) {
|
|
|
180
190
|
actions.appendChild(cta);
|
|
181
191
|
}
|
|
182
192
|
container.appendChild(actions);
|
|
183
|
-
|
|
184
|
-
|
|
193
|
+
}
|
|
194
|
+
function normalizeBlocks(step) {
|
|
195
|
+
if (!Array.isArray(step.blocks) || step.blocks.length === 0) return null;
|
|
196
|
+
const valid = step.blocks.filter((b) => {
|
|
197
|
+
if (!b || typeof b !== "object") return false;
|
|
198
|
+
if (b.type === "image") return typeof b.url === "string" && isSafeUrl(b.url);
|
|
199
|
+
return b.type === "title" || b.type === "text" || b.type === "button";
|
|
200
|
+
});
|
|
201
|
+
return valid.length > 0 ? valid : null;
|
|
202
|
+
}
|
|
203
|
+
function renderBlocks(container, blocks, doc, callbacks) {
|
|
204
|
+
let i = 0;
|
|
205
|
+
while (i < blocks.length) {
|
|
206
|
+
const block = blocks[i];
|
|
207
|
+
if (block?.type === "button") {
|
|
208
|
+
const actions = doc.createElement("div");
|
|
209
|
+
actions.className = "veo-guide-actions";
|
|
210
|
+
let rowAlign;
|
|
211
|
+
while (i < blocks.length && blocks[i]?.type === "button") {
|
|
212
|
+
const btnBlock = blocks[i];
|
|
213
|
+
if (!rowAlign) {
|
|
214
|
+
const a = btnBlock.style?.align;
|
|
215
|
+
if (a === "left" || a === "center" || a === "right") rowAlign = a;
|
|
216
|
+
}
|
|
217
|
+
actions.appendChild(buildButtonBlock(btnBlock, doc, callbacks));
|
|
218
|
+
i++;
|
|
219
|
+
}
|
|
220
|
+
if (rowAlign) actions.style.justifyContent = BLOCK_ALIGN_SELF[rowAlign];
|
|
221
|
+
container.appendChild(actions);
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
const node = buildContentBlock(block, doc);
|
|
225
|
+
if (node) container.appendChild(node);
|
|
226
|
+
i++;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
function buildContentBlock(block, doc) {
|
|
230
|
+
switch (block.type) {
|
|
231
|
+
case "title": {
|
|
232
|
+
const el = doc.createElement("h2");
|
|
233
|
+
el.className = "veo-guide-title";
|
|
234
|
+
el.textContent = typeof block.text === "string" ? block.text : "";
|
|
235
|
+
applyBlockStyle(el, block.style, "text");
|
|
236
|
+
return el;
|
|
237
|
+
}
|
|
238
|
+
case "text": {
|
|
239
|
+
const el = doc.createElement("p");
|
|
240
|
+
el.className = "veo-guide-text";
|
|
241
|
+
el.textContent = typeof block.text === "string" ? block.text : "";
|
|
242
|
+
applyBlockStyle(el, block.style, "text");
|
|
243
|
+
return el;
|
|
244
|
+
}
|
|
245
|
+
case "image": {
|
|
246
|
+
if (typeof block.url !== "string" || !isSafeUrl(block.url)) return null;
|
|
247
|
+
const el = doc.createElement("img");
|
|
248
|
+
el.className = "veo-guide-image";
|
|
249
|
+
el.src = block.url;
|
|
250
|
+
el.alt = "";
|
|
251
|
+
applyBlockStyle(el, block.style, "image");
|
|
252
|
+
return el;
|
|
253
|
+
}
|
|
254
|
+
default:
|
|
255
|
+
return null;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
function buildButtonBlock(block, doc, callbacks) {
|
|
259
|
+
const btn = doc.createElement("button");
|
|
260
|
+
btn.type = "button";
|
|
261
|
+
btn.className = "veo-guide-cta";
|
|
262
|
+
btn.textContent = typeof block.text === "string" && block.text ? block.text : "OK";
|
|
263
|
+
applyBlockStyle(btn, block.style, "button");
|
|
264
|
+
btn.addEventListener("click", () => {
|
|
265
|
+
const action = block.action ?? "dismiss";
|
|
266
|
+
const url = action === "url" && typeof block.url === "string" && isSafeUrl(block.url) ? block.url : void 0;
|
|
267
|
+
callbacks.onCtaClick(action, url);
|
|
268
|
+
});
|
|
269
|
+
return btn;
|
|
270
|
+
}
|
|
271
|
+
var BLOCK_ALIGN_SELF = {
|
|
272
|
+
left: "flex-start",
|
|
273
|
+
center: "center",
|
|
274
|
+
right: "flex-end"
|
|
275
|
+
};
|
|
276
|
+
function clampNum(n, min, max) {
|
|
277
|
+
return Math.min(max, Math.max(min, n));
|
|
278
|
+
}
|
|
279
|
+
function applyBlockStyle(el, style, kind) {
|
|
280
|
+
if (!style || typeof style !== "object") return;
|
|
281
|
+
const s = style;
|
|
282
|
+
const align = typeof s.align === "string" ? s.align : null;
|
|
283
|
+
if (align && (align === "left" || align === "center" || align === "right")) {
|
|
284
|
+
if (kind === "text") el.style.textAlign = align;
|
|
285
|
+
else if (kind === "image") el.style.alignSelf = BLOCK_ALIGN_SELF[align];
|
|
286
|
+
}
|
|
287
|
+
if (kind !== "image" && typeof s.color === "string") el.style.color = s.color;
|
|
288
|
+
if (kind === "text" && typeof s.fontSize === "number" && Number.isFinite(s.fontSize)) {
|
|
289
|
+
el.style.fontSize = `${clampNum(s.fontSize, 8, 72)}px`;
|
|
290
|
+
}
|
|
291
|
+
if (kind === "image" && typeof s.width === "number" && Number.isFinite(s.width)) {
|
|
292
|
+
el.style.width = `${clampNum(s.width, 10, 100)}%`;
|
|
293
|
+
}
|
|
294
|
+
if (kind === "image" && typeof s.radius === "number" && Number.isFinite(s.radius)) {
|
|
295
|
+
el.style.borderRadius = `${clampNum(s.radius, 0, 48)}px`;
|
|
296
|
+
}
|
|
297
|
+
if (typeof s.marginTop === "number" && Number.isFinite(s.marginTop)) {
|
|
298
|
+
el.style.marginTop = `${clampNum(s.marginTop, 0, 64)}px`;
|
|
299
|
+
}
|
|
300
|
+
if (typeof s.marginBottom === "number" && Number.isFinite(s.marginBottom)) {
|
|
301
|
+
el.style.marginBottom = `${clampNum(s.marginBottom, 0, 64)}px`;
|
|
302
|
+
}
|
|
185
303
|
}
|
|
186
304
|
function createCloseButton(doc, onClose, className = "veo-guide-close") {
|
|
187
305
|
const closeBtn = doc.createElement("button");
|
|
@@ -208,6 +326,78 @@ function readCtaUrl(step) {
|
|
|
208
326
|
return isSafeUrl(candidate) ? candidate : void 0;
|
|
209
327
|
}
|
|
210
328
|
|
|
329
|
+
// src/plugins/guides/walkthrough-block-builder.ts
|
|
330
|
+
function buildWalkthroughStepContent(step, stepIndex, totalSteps, doc, callbacks) {
|
|
331
|
+
const container = doc.createElement("div");
|
|
332
|
+
container.className = "veo-guide-content";
|
|
333
|
+
const counter = doc.createElement("div");
|
|
334
|
+
counter.className = "veo-walkthrough-counter";
|
|
335
|
+
counter.textContent = `Paso ${stepIndex + 1} de ${totalSteps}`;
|
|
336
|
+
container.appendChild(counter);
|
|
337
|
+
const progress = doc.createElement("div");
|
|
338
|
+
progress.className = "veo-walkthrough-progress";
|
|
339
|
+
for (let i = 0; i < totalSteps; i++) {
|
|
340
|
+
const dot = doc.createElement("span");
|
|
341
|
+
dot.className = "veo-walkthrough-progress-dot";
|
|
342
|
+
if (i < stepIndex) dot.classList.add("completed");
|
|
343
|
+
if (i === stepIndex) dot.classList.add("active");
|
|
344
|
+
progress.appendChild(dot);
|
|
345
|
+
}
|
|
346
|
+
container.appendChild(progress);
|
|
347
|
+
if (typeof step.imageUrl === "string" && step.imageUrl && isSafeUrl(step.imageUrl)) {
|
|
348
|
+
const img = doc.createElement("img");
|
|
349
|
+
img.className = "veo-guide-image";
|
|
350
|
+
img.src = step.imageUrl;
|
|
351
|
+
img.alt = typeof step.title === "string" ? step.title : "";
|
|
352
|
+
container.appendChild(img);
|
|
353
|
+
}
|
|
354
|
+
if (typeof step.title === "string" && step.title) {
|
|
355
|
+
const heading = doc.createElement("h2");
|
|
356
|
+
heading.className = "veo-guide-title";
|
|
357
|
+
heading.textContent = step.title;
|
|
358
|
+
container.appendChild(heading);
|
|
359
|
+
}
|
|
360
|
+
if (typeof step.content === "string" && step.content) {
|
|
361
|
+
const paragraph = doc.createElement("p");
|
|
362
|
+
paragraph.className = "veo-guide-text";
|
|
363
|
+
paragraph.textContent = step.content;
|
|
364
|
+
container.appendChild(paragraph);
|
|
365
|
+
}
|
|
366
|
+
const actions = doc.createElement("div");
|
|
367
|
+
actions.className = "veo-walkthrough-actions";
|
|
368
|
+
const skipBtn = doc.createElement("button");
|
|
369
|
+
skipBtn.type = "button";
|
|
370
|
+
skipBtn.className = "veo-walkthrough-skip";
|
|
371
|
+
skipBtn.textContent = "Omitir";
|
|
372
|
+
skipBtn.addEventListener("click", () => callbacks.onSkip());
|
|
373
|
+
actions.appendChild(skipBtn);
|
|
374
|
+
const rightGroup = doc.createElement("div");
|
|
375
|
+
rightGroup.className = "veo-walkthrough-actions-right";
|
|
376
|
+
if (stepIndex > 0) {
|
|
377
|
+
const backBtn = doc.createElement("button");
|
|
378
|
+
backBtn.type = "button";
|
|
379
|
+
backBtn.className = "veo-walkthrough-btn-secondary";
|
|
380
|
+
backBtn.textContent = "Atr\xE1s";
|
|
381
|
+
backBtn.addEventListener("click", () => callbacks.onBack());
|
|
382
|
+
rightGroup.appendChild(backBtn);
|
|
383
|
+
}
|
|
384
|
+
const isLastStep = stepIndex === totalSteps - 1;
|
|
385
|
+
const primaryBtn = doc.createElement("button");
|
|
386
|
+
primaryBtn.type = "button";
|
|
387
|
+
primaryBtn.className = "veo-guide-cta";
|
|
388
|
+
const defaultLabel = isLastStep ? "Finalizar" : "Siguiente";
|
|
389
|
+
primaryBtn.textContent = typeof step.ctaText === "string" && step.ctaText ? step.ctaText : defaultLabel;
|
|
390
|
+
primaryBtn.addEventListener("click", () => {
|
|
391
|
+
if (isLastStep) callbacks.onComplete();
|
|
392
|
+
else callbacks.onNext();
|
|
393
|
+
});
|
|
394
|
+
rightGroup.appendChild(primaryBtn);
|
|
395
|
+
actions.appendChild(rightGroup);
|
|
396
|
+
container.appendChild(actions);
|
|
397
|
+
container.appendChild(createCloseButton(doc, () => callbacks.onSkip()));
|
|
398
|
+
return container;
|
|
399
|
+
}
|
|
400
|
+
|
|
211
401
|
// src/plugins/guides/guide-design.ts
|
|
212
402
|
var DARK_THEME = {
|
|
213
403
|
"--veo-bg": "#1f2937",
|
|
@@ -257,6 +447,9 @@ function applyDesignVars(host, style) {
|
|
|
257
447
|
if (typeof s.accentColor === "string" && COLOR_RE.test(s.accentColor.trim())) {
|
|
258
448
|
host.style.setProperty("--veo-primary", s.accentColor.trim());
|
|
259
449
|
}
|
|
450
|
+
if (typeof s.fontFamily === "string" && s.fontFamily.length <= 200 && !/[<>{}]/.test(s.fontFamily)) {
|
|
451
|
+
host.style.setProperty("--veo-font", s.fontFamily.trim());
|
|
452
|
+
}
|
|
260
453
|
if (s.theme === "dark") {
|
|
261
454
|
for (const [key, value] of Object.entries(DARK_THEME)) {
|
|
262
455
|
host.style.setProperty(key, value);
|
|
@@ -350,7 +543,7 @@ var GUIDE_STYLES = `
|
|
|
350
543
|
--veo-actions-justify: flex-end;
|
|
351
544
|
all: initial;
|
|
352
545
|
}
|
|
353
|
-
* { box-sizing: border-box; font-family: -apple-system, system-ui, "Segoe UI", Roboto, sans-serif; }
|
|
546
|
+
* { box-sizing: border-box; font-family: var(--veo-font, -apple-system, system-ui, "Segoe UI", Roboto, sans-serif); }
|
|
354
547
|
|
|
355
548
|
.veo-modal-overlay {
|
|
356
549
|
position: fixed; inset: 0;
|
|
@@ -427,6 +620,12 @@ var GUIDE_STYLES = `
|
|
|
427
620
|
position: relative;
|
|
428
621
|
display: flex; flex-direction: column;
|
|
429
622
|
}
|
|
623
|
+
/* Reserva espacio para la \u2715 (esquina sup. derecha) SOLO en el primer bloque:
|
|
624
|
+
as\xED el texto alineado a la derecha no queda tapado por el bot\xF3n de cerrar. */
|
|
625
|
+
.veo-guide-content > .veo-guide-title:first-child,
|
|
626
|
+
.veo-guide-content > .veo-guide-text:first-child {
|
|
627
|
+
padding-right: 20px;
|
|
628
|
+
}
|
|
430
629
|
.veo-guide-image {
|
|
431
630
|
display: block;
|
|
432
631
|
width: var(--veo-image-width, 100%);
|
|
@@ -681,7 +880,8 @@ var BaseRenderer = class {
|
|
|
681
880
|
// src/plugins/guides/renderers/banner-renderer.ts
|
|
682
881
|
var BannerRenderer = class extends BaseRenderer {
|
|
683
882
|
render(context) {
|
|
684
|
-
const
|
|
883
|
+
const idx = context.nav?.stepIndex ?? 0;
|
|
884
|
+
const step = context.guide.guideSteps[idx];
|
|
685
885
|
if (!step) return;
|
|
686
886
|
const { root } = this.createHost();
|
|
687
887
|
this.applyDesign(step.style);
|
|
@@ -690,27 +890,25 @@ var BannerRenderer = class extends BaseRenderer {
|
|
|
690
890
|
const banner = ownerDocument.createElement("div");
|
|
691
891
|
banner.className = `veo-banner veo-banner-${position}`;
|
|
692
892
|
const dismiss = (action, ctaUrl) => {
|
|
693
|
-
context.onInteraction({
|
|
694
|
-
guideId: context.guide.guideId,
|
|
695
|
-
stepIndex: 0,
|
|
696
|
-
action
|
|
697
|
-
});
|
|
893
|
+
context.onInteraction({ guideId: context.guide.guideId, stepIndex: idx, action });
|
|
698
894
|
if (ctaUrl) window.open(ctaUrl, "_blank", "noopener,noreferrer");
|
|
699
895
|
context.onClose();
|
|
700
896
|
};
|
|
701
|
-
const content =
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
897
|
+
const content = context.nav ? buildWalkthroughStepContent(
|
|
898
|
+
step,
|
|
899
|
+
context.nav.stepIndex,
|
|
900
|
+
context.nav.totalSteps,
|
|
901
|
+
ownerDocument,
|
|
902
|
+
context.nav.callbacks
|
|
903
|
+
) : buildStepContent(step, ownerDocument, {
|
|
904
|
+
onCtaClick: (action, url) => dismiss("cta_clicked", action === "url" ? url : void 0),
|
|
705
905
|
onDismiss: () => dismiss("dismissed")
|
|
706
906
|
});
|
|
707
907
|
banner.appendChild(content);
|
|
708
908
|
root.appendChild(banner);
|
|
709
|
-
context.
|
|
710
|
-
guideId: context.guide.guideId,
|
|
711
|
-
|
|
712
|
-
action: "shown"
|
|
713
|
-
});
|
|
909
|
+
if (!context.nav) {
|
|
910
|
+
context.onInteraction({ guideId: context.guide.guideId, stepIndex: 0, action: "shown" });
|
|
911
|
+
}
|
|
714
912
|
}
|
|
715
913
|
};
|
|
716
914
|
|
|
@@ -1390,7 +1588,8 @@ var InlineRenderer = class extends BaseRenderer {
|
|
|
1390
1588
|
// src/plugins/guides/renderers/modal-renderer.ts
|
|
1391
1589
|
var ModalRenderer = class extends BaseRenderer {
|
|
1392
1590
|
render(context) {
|
|
1393
|
-
const
|
|
1591
|
+
const idx = context.nav?.stepIndex ?? 0;
|
|
1592
|
+
const step = context.guide.guideSteps[idx];
|
|
1394
1593
|
if (!step) return;
|
|
1395
1594
|
const { root } = this.createHost();
|
|
1396
1595
|
this.applyDesign(step.style);
|
|
@@ -1400,36 +1599,38 @@ var ModalRenderer = class extends BaseRenderer {
|
|
|
1400
1599
|
const card = ownerDocument.createElement("div");
|
|
1401
1600
|
card.className = "veo-modal-card";
|
|
1402
1601
|
const dismiss = (action, ctaUrl) => {
|
|
1403
|
-
context.onInteraction({
|
|
1404
|
-
guideId: context.guide.guideId,
|
|
1405
|
-
stepIndex: 0,
|
|
1406
|
-
action
|
|
1407
|
-
});
|
|
1602
|
+
context.onInteraction({ guideId: context.guide.guideId, stepIndex: idx, action });
|
|
1408
1603
|
if (ctaUrl) window.open(ctaUrl, "_blank", "noopener,noreferrer");
|
|
1409
1604
|
context.onClose();
|
|
1410
1605
|
};
|
|
1411
|
-
const
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1606
|
+
const onBackdropOrEsc = () => {
|
|
1607
|
+
if (context.nav) context.nav.callbacks.onSkip();
|
|
1608
|
+
else dismiss("dismissed");
|
|
1609
|
+
};
|
|
1610
|
+
const content = context.nav ? buildWalkthroughStepContent(
|
|
1611
|
+
step,
|
|
1612
|
+
context.nav.stepIndex,
|
|
1613
|
+
context.nav.totalSteps,
|
|
1614
|
+
ownerDocument,
|
|
1615
|
+
context.nav.callbacks
|
|
1616
|
+
) : buildStepContent(step, ownerDocument, {
|
|
1617
|
+
onCtaClick: (action, url) => dismiss("cta_clicked", action === "url" ? url : void 0),
|
|
1415
1618
|
onDismiss: () => dismiss("dismissed")
|
|
1416
1619
|
});
|
|
1417
1620
|
card.appendChild(content);
|
|
1418
1621
|
overlay.appendChild(card);
|
|
1419
1622
|
root.appendChild(overlay);
|
|
1420
1623
|
overlay.addEventListener("click", (e) => {
|
|
1421
|
-
if (e.target === overlay)
|
|
1624
|
+
if (e.target === overlay) onBackdropOrEsc();
|
|
1422
1625
|
});
|
|
1423
1626
|
const onKey = (e) => {
|
|
1424
|
-
if (e.key === "Escape")
|
|
1627
|
+
if (e.key === "Escape") onBackdropOrEsc();
|
|
1425
1628
|
};
|
|
1426
1629
|
document.addEventListener("keydown", onKey);
|
|
1427
1630
|
this.registerCleanup(() => document.removeEventListener("keydown", onKey));
|
|
1428
|
-
context.
|
|
1429
|
-
guideId: context.guide.guideId,
|
|
1430
|
-
|
|
1431
|
-
action: "shown"
|
|
1432
|
-
});
|
|
1631
|
+
if (!context.nav) {
|
|
1632
|
+
context.onInteraction({ guideId: context.guide.guideId, stepIndex: 0, action: "shown" });
|
|
1633
|
+
}
|
|
1433
1634
|
}
|
|
1434
1635
|
};
|
|
1435
1636
|
|
|
@@ -1459,6 +1660,8 @@ var TooltipRenderer = class extends BaseRenderer {
|
|
|
1459
1660
|
if (typeof selector !== "string" || selector.length === 0) return;
|
|
1460
1661
|
const anchor = await waitForElement(selector);
|
|
1461
1662
|
if (!anchor) return;
|
|
1663
|
+
const rawSide = step.style?.tooltipPlacement;
|
|
1664
|
+
const side = rawSide === "top" || rawSide === "left" || rawSide === "right" ? rawSide : "bottom";
|
|
1462
1665
|
const { root } = this.createHost();
|
|
1463
1666
|
this.applyDesign(step.style);
|
|
1464
1667
|
const ownerDocument = root.ownerDocument ?? document;
|
|
@@ -1486,7 +1689,7 @@ var TooltipRenderer = class extends BaseRenderer {
|
|
|
1486
1689
|
root.appendChild(tooltip);
|
|
1487
1690
|
const updatePosition = async () => {
|
|
1488
1691
|
const { x, y, placement, middlewareData } = await dom.computePosition(anchor, tooltip, {
|
|
1489
|
-
placement:
|
|
1692
|
+
placement: side,
|
|
1490
1693
|
middleware: [dom.offset(10), dom.flip(), dom.shift({ padding: 8 }), dom.arrow({ element: arrowEl })]
|
|
1491
1694
|
});
|
|
1492
1695
|
tooltip.style.left = `${x}px`;
|
|
@@ -1510,80 +1713,6 @@ var TooltipRenderer = class extends BaseRenderer {
|
|
|
1510
1713
|
});
|
|
1511
1714
|
}
|
|
1512
1715
|
};
|
|
1513
|
-
|
|
1514
|
-
// src/plugins/guides/walkthrough-block-builder.ts
|
|
1515
|
-
function buildWalkthroughStepContent(step, stepIndex, totalSteps, doc, callbacks) {
|
|
1516
|
-
const container = doc.createElement("div");
|
|
1517
|
-
container.className = "veo-guide-content";
|
|
1518
|
-
const counter = doc.createElement("div");
|
|
1519
|
-
counter.className = "veo-walkthrough-counter";
|
|
1520
|
-
counter.textContent = `Paso ${stepIndex + 1} de ${totalSteps}`;
|
|
1521
|
-
container.appendChild(counter);
|
|
1522
|
-
const progress = doc.createElement("div");
|
|
1523
|
-
progress.className = "veo-walkthrough-progress";
|
|
1524
|
-
for (let i = 0; i < totalSteps; i++) {
|
|
1525
|
-
const dot = doc.createElement("span");
|
|
1526
|
-
dot.className = "veo-walkthrough-progress-dot";
|
|
1527
|
-
if (i < stepIndex) dot.classList.add("completed");
|
|
1528
|
-
if (i === stepIndex) dot.classList.add("active");
|
|
1529
|
-
progress.appendChild(dot);
|
|
1530
|
-
}
|
|
1531
|
-
container.appendChild(progress);
|
|
1532
|
-
if (typeof step.imageUrl === "string" && step.imageUrl && isSafeUrl(step.imageUrl)) {
|
|
1533
|
-
const img = doc.createElement("img");
|
|
1534
|
-
img.className = "veo-guide-image";
|
|
1535
|
-
img.src = step.imageUrl;
|
|
1536
|
-
img.alt = typeof step.title === "string" ? step.title : "";
|
|
1537
|
-
container.appendChild(img);
|
|
1538
|
-
}
|
|
1539
|
-
if (typeof step.title === "string" && step.title) {
|
|
1540
|
-
const heading = doc.createElement("h2");
|
|
1541
|
-
heading.className = "veo-guide-title";
|
|
1542
|
-
heading.textContent = step.title;
|
|
1543
|
-
container.appendChild(heading);
|
|
1544
|
-
}
|
|
1545
|
-
if (typeof step.content === "string" && step.content) {
|
|
1546
|
-
const paragraph = doc.createElement("p");
|
|
1547
|
-
paragraph.className = "veo-guide-text";
|
|
1548
|
-
paragraph.textContent = step.content;
|
|
1549
|
-
container.appendChild(paragraph);
|
|
1550
|
-
}
|
|
1551
|
-
const actions = doc.createElement("div");
|
|
1552
|
-
actions.className = "veo-walkthrough-actions";
|
|
1553
|
-
const skipBtn = doc.createElement("button");
|
|
1554
|
-
skipBtn.type = "button";
|
|
1555
|
-
skipBtn.className = "veo-walkthrough-skip";
|
|
1556
|
-
skipBtn.textContent = "Omitir";
|
|
1557
|
-
skipBtn.addEventListener("click", () => callbacks.onSkip());
|
|
1558
|
-
actions.appendChild(skipBtn);
|
|
1559
|
-
const rightGroup = doc.createElement("div");
|
|
1560
|
-
rightGroup.className = "veo-walkthrough-actions-right";
|
|
1561
|
-
if (stepIndex > 0) {
|
|
1562
|
-
const backBtn = doc.createElement("button");
|
|
1563
|
-
backBtn.type = "button";
|
|
1564
|
-
backBtn.className = "veo-walkthrough-btn-secondary";
|
|
1565
|
-
backBtn.textContent = "Atr\xE1s";
|
|
1566
|
-
backBtn.addEventListener("click", () => callbacks.onBack());
|
|
1567
|
-
rightGroup.appendChild(backBtn);
|
|
1568
|
-
}
|
|
1569
|
-
const isLastStep = stepIndex === totalSteps - 1;
|
|
1570
|
-
const primaryBtn = doc.createElement("button");
|
|
1571
|
-
primaryBtn.type = "button";
|
|
1572
|
-
primaryBtn.className = "veo-guide-cta";
|
|
1573
|
-
const defaultLabel = isLastStep ? "Finalizar" : "Siguiente";
|
|
1574
|
-
primaryBtn.textContent = typeof step.ctaText === "string" && step.ctaText ? step.ctaText : defaultLabel;
|
|
1575
|
-
primaryBtn.addEventListener("click", () => {
|
|
1576
|
-
if (isLastStep) callbacks.onComplete();
|
|
1577
|
-
else callbacks.onNext();
|
|
1578
|
-
});
|
|
1579
|
-
rightGroup.appendChild(primaryBtn);
|
|
1580
|
-
actions.appendChild(rightGroup);
|
|
1581
|
-
container.appendChild(actions);
|
|
1582
|
-
container.appendChild(createCloseButton(doc, () => callbacks.onSkip()));
|
|
1583
|
-
return container;
|
|
1584
|
-
}
|
|
1585
|
-
|
|
1586
|
-
// src/plugins/guides/renderers/walkthrough-renderer.ts
|
|
1587
1716
|
var WalkthroughRenderer = class extends BaseRenderer {
|
|
1588
1717
|
async render(context) {
|
|
1589
1718
|
const step = context.guide.guideSteps[context.currentStepIndex];
|
|
@@ -1592,6 +1721,8 @@ var WalkthroughRenderer = class extends BaseRenderer {
|
|
|
1592
1721
|
if (typeof selector !== "string" || selector.length === 0) return false;
|
|
1593
1722
|
const anchor = await waitForElement(selector, WALKTHROUGH_STEP_SELECTOR_TIMEOUT_MS);
|
|
1594
1723
|
if (!anchor) return false;
|
|
1724
|
+
const rawSide = step.style?.tooltipPlacement;
|
|
1725
|
+
const side = rawSide === "top" || rawSide === "left" || rawSide === "right" ? rawSide : "bottom";
|
|
1595
1726
|
const { root } = this.createHost();
|
|
1596
1727
|
this.applyDesign(step.style);
|
|
1597
1728
|
const ownerDocument = root.ownerDocument ?? document;
|
|
@@ -1611,7 +1742,7 @@ var WalkthroughRenderer = class extends BaseRenderer {
|
|
|
1611
1742
|
root.appendChild(tooltip);
|
|
1612
1743
|
const updatePosition = async () => {
|
|
1613
1744
|
const { x, y, placement, middlewareData } = await dom.computePosition(anchor, tooltip, {
|
|
1614
|
-
placement:
|
|
1745
|
+
placement: side,
|
|
1615
1746
|
middleware: [dom.offset(10), dom.flip(), dom.shift({ padding: 8 }), dom.arrow({ element: arrowEl })]
|
|
1616
1747
|
});
|
|
1617
1748
|
tooltip.style.left = `${x}px`;
|
|
@@ -1637,6 +1768,7 @@ var PREVIEW_GUIDE_ID = "__veo_preview__";
|
|
|
1637
1768
|
var GuidePreviewController = class {
|
|
1638
1769
|
constructor() {
|
|
1639
1770
|
this.singleStep = null;
|
|
1771
|
+
/** Renderer del paso de walkthrough activo (walkthrough tooltip o modal/banner). */
|
|
1640
1772
|
this.walkthrough = null;
|
|
1641
1773
|
this.walkthroughGuide = null;
|
|
1642
1774
|
this.walkthroughIndex = 0;
|
|
@@ -1709,7 +1841,6 @@ var GuidePreviewController = class {
|
|
|
1709
1841
|
safeDestroy(this.walkthrough);
|
|
1710
1842
|
this.walkthrough = null;
|
|
1711
1843
|
}
|
|
1712
|
-
const renderer = new WalkthroughRenderer();
|
|
1713
1844
|
const callbacks = {
|
|
1714
1845
|
onNext: () => {
|
|
1715
1846
|
const next = this.walkthroughIndex + 1;
|
|
@@ -1729,6 +1860,30 @@ var GuidePreviewController = class {
|
|
|
1729
1860
|
onSkip: () => this.close(),
|
|
1730
1861
|
onComplete: () => this.close()
|
|
1731
1862
|
};
|
|
1863
|
+
const step = guide.guideSteps[index];
|
|
1864
|
+
const render = step?.style?.render;
|
|
1865
|
+
if (render === "modal" || render === "banner") {
|
|
1866
|
+
const renderer2 = render === "modal" ? new ModalRenderer() : new BannerRenderer();
|
|
1867
|
+
try {
|
|
1868
|
+
renderer2.render({
|
|
1869
|
+
guide,
|
|
1870
|
+
onInteraction: () => {
|
|
1871
|
+
},
|
|
1872
|
+
onClose: () => this.close(),
|
|
1873
|
+
nav: { stepIndex: index, totalSteps: guide.guideSteps.length, callbacks }
|
|
1874
|
+
});
|
|
1875
|
+
} catch {
|
|
1876
|
+
safeDestroy(renderer2);
|
|
1877
|
+
return false;
|
|
1878
|
+
}
|
|
1879
|
+
if (this.walkthroughGuide !== guide) {
|
|
1880
|
+
safeDestroy(renderer2);
|
|
1881
|
+
return false;
|
|
1882
|
+
}
|
|
1883
|
+
this.walkthrough = renderer2;
|
|
1884
|
+
return true;
|
|
1885
|
+
}
|
|
1886
|
+
const renderer = new WalkthroughRenderer();
|
|
1732
1887
|
let success = false;
|
|
1733
1888
|
try {
|
|
1734
1889
|
success = await renderer.render({ guide, currentStepIndex: index, callbacks });
|