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
package/dist/index.cjs
CHANGED
|
@@ -378,6 +378,16 @@ var init_constants2 = __esm({
|
|
|
378
378
|
function buildStepContent(step, doc, callbacks) {
|
|
379
379
|
const container = doc.createElement("div");
|
|
380
380
|
container.className = "veo-guide-content";
|
|
381
|
+
const blocks = normalizeBlocks(step);
|
|
382
|
+
if (blocks) {
|
|
383
|
+
renderBlocks(container, blocks, doc, callbacks);
|
|
384
|
+
} else {
|
|
385
|
+
renderLegacyStep(container, step, doc, callbacks);
|
|
386
|
+
}
|
|
387
|
+
container.appendChild(createCloseButton(doc, () => callbacks.onDismiss()));
|
|
388
|
+
return container;
|
|
389
|
+
}
|
|
390
|
+
function renderLegacyStep(container, step, doc, callbacks) {
|
|
381
391
|
if (typeof step.imageUrl === "string" && step.imageUrl && isSafeUrl(step.imageUrl)) {
|
|
382
392
|
const img = doc.createElement("img");
|
|
383
393
|
img.className = "veo-guide-image";
|
|
@@ -412,8 +422,111 @@ function buildStepContent(step, doc, callbacks) {
|
|
|
412
422
|
actions.appendChild(cta);
|
|
413
423
|
}
|
|
414
424
|
container.appendChild(actions);
|
|
415
|
-
|
|
416
|
-
|
|
425
|
+
}
|
|
426
|
+
function normalizeBlocks(step) {
|
|
427
|
+
if (!Array.isArray(step.blocks) || step.blocks.length === 0) return null;
|
|
428
|
+
const valid = step.blocks.filter((b) => {
|
|
429
|
+
if (!b || typeof b !== "object") return false;
|
|
430
|
+
if (b.type === "image") return typeof b.url === "string" && isSafeUrl(b.url);
|
|
431
|
+
return b.type === "title" || b.type === "text" || b.type === "button";
|
|
432
|
+
});
|
|
433
|
+
return valid.length > 0 ? valid : null;
|
|
434
|
+
}
|
|
435
|
+
function renderBlocks(container, blocks, doc, callbacks) {
|
|
436
|
+
let i = 0;
|
|
437
|
+
while (i < blocks.length) {
|
|
438
|
+
const block = blocks[i];
|
|
439
|
+
if (block?.type === "button") {
|
|
440
|
+
const actions = doc.createElement("div");
|
|
441
|
+
actions.className = "veo-guide-actions";
|
|
442
|
+
let rowAlign;
|
|
443
|
+
while (i < blocks.length && blocks[i]?.type === "button") {
|
|
444
|
+
const btnBlock = blocks[i];
|
|
445
|
+
if (!rowAlign) {
|
|
446
|
+
const a = btnBlock.style?.align;
|
|
447
|
+
if (a === "left" || a === "center" || a === "right") rowAlign = a;
|
|
448
|
+
}
|
|
449
|
+
actions.appendChild(buildButtonBlock(btnBlock, doc, callbacks));
|
|
450
|
+
i++;
|
|
451
|
+
}
|
|
452
|
+
if (rowAlign) actions.style.justifyContent = BLOCK_ALIGN_SELF[rowAlign];
|
|
453
|
+
container.appendChild(actions);
|
|
454
|
+
continue;
|
|
455
|
+
}
|
|
456
|
+
const node = buildContentBlock(block, doc);
|
|
457
|
+
if (node) container.appendChild(node);
|
|
458
|
+
i++;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
function buildContentBlock(block, doc) {
|
|
462
|
+
switch (block.type) {
|
|
463
|
+
case "title": {
|
|
464
|
+
const el = doc.createElement("h2");
|
|
465
|
+
el.className = "veo-guide-title";
|
|
466
|
+
el.textContent = typeof block.text === "string" ? block.text : "";
|
|
467
|
+
applyBlockStyle(el, block.style, "text");
|
|
468
|
+
return el;
|
|
469
|
+
}
|
|
470
|
+
case "text": {
|
|
471
|
+
const el = doc.createElement("p");
|
|
472
|
+
el.className = "veo-guide-text";
|
|
473
|
+
el.textContent = typeof block.text === "string" ? block.text : "";
|
|
474
|
+
applyBlockStyle(el, block.style, "text");
|
|
475
|
+
return el;
|
|
476
|
+
}
|
|
477
|
+
case "image": {
|
|
478
|
+
if (typeof block.url !== "string" || !isSafeUrl(block.url)) return null;
|
|
479
|
+
const el = doc.createElement("img");
|
|
480
|
+
el.className = "veo-guide-image";
|
|
481
|
+
el.src = block.url;
|
|
482
|
+
el.alt = "";
|
|
483
|
+
applyBlockStyle(el, block.style, "image");
|
|
484
|
+
return el;
|
|
485
|
+
}
|
|
486
|
+
default:
|
|
487
|
+
return null;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
function buildButtonBlock(block, doc, callbacks) {
|
|
491
|
+
const btn = doc.createElement("button");
|
|
492
|
+
btn.type = "button";
|
|
493
|
+
btn.className = "veo-guide-cta";
|
|
494
|
+
btn.textContent = typeof block.text === "string" && block.text ? block.text : "OK";
|
|
495
|
+
applyBlockStyle(btn, block.style, "button");
|
|
496
|
+
btn.addEventListener("click", () => {
|
|
497
|
+
const action = block.action ?? "dismiss";
|
|
498
|
+
const url = action === "url" && typeof block.url === "string" && isSafeUrl(block.url) ? block.url : void 0;
|
|
499
|
+
callbacks.onCtaClick(action, url);
|
|
500
|
+
});
|
|
501
|
+
return btn;
|
|
502
|
+
}
|
|
503
|
+
function clampNum(n, min, max) {
|
|
504
|
+
return Math.min(max, Math.max(min, n));
|
|
505
|
+
}
|
|
506
|
+
function applyBlockStyle(el, style, kind) {
|
|
507
|
+
if (!style || typeof style !== "object") return;
|
|
508
|
+
const s = style;
|
|
509
|
+
const align = typeof s.align === "string" ? s.align : null;
|
|
510
|
+
if (align && (align === "left" || align === "center" || align === "right")) {
|
|
511
|
+
if (kind === "text") el.style.textAlign = align;
|
|
512
|
+
else if (kind === "image") el.style.alignSelf = BLOCK_ALIGN_SELF[align];
|
|
513
|
+
}
|
|
514
|
+
if (kind !== "image" && typeof s.color === "string") el.style.color = s.color;
|
|
515
|
+
if (kind === "text" && typeof s.fontSize === "number" && Number.isFinite(s.fontSize)) {
|
|
516
|
+
el.style.fontSize = `${clampNum(s.fontSize, 8, 72)}px`;
|
|
517
|
+
}
|
|
518
|
+
if (kind === "image" && typeof s.width === "number" && Number.isFinite(s.width)) {
|
|
519
|
+
el.style.width = `${clampNum(s.width, 10, 100)}%`;
|
|
520
|
+
}
|
|
521
|
+
if (kind === "image" && typeof s.radius === "number" && Number.isFinite(s.radius)) {
|
|
522
|
+
el.style.borderRadius = `${clampNum(s.radius, 0, 48)}px`;
|
|
523
|
+
}
|
|
524
|
+
if (typeof s.marginTop === "number" && Number.isFinite(s.marginTop)) {
|
|
525
|
+
el.style.marginTop = `${clampNum(s.marginTop, 0, 64)}px`;
|
|
526
|
+
}
|
|
527
|
+
if (typeof s.marginBottom === "number" && Number.isFinite(s.marginBottom)) {
|
|
528
|
+
el.style.marginBottom = `${clampNum(s.marginBottom, 0, 64)}px`;
|
|
529
|
+
}
|
|
417
530
|
}
|
|
418
531
|
function createCloseButton(doc, onClose, className = "veo-guide-close") {
|
|
419
532
|
const closeBtn = doc.createElement("button");
|
|
@@ -439,9 +552,92 @@ function readCtaUrl(step) {
|
|
|
439
552
|
if (typeof candidate !== "string") return void 0;
|
|
440
553
|
return isSafeUrl(candidate) ? candidate : void 0;
|
|
441
554
|
}
|
|
555
|
+
var BLOCK_ALIGN_SELF;
|
|
442
556
|
var init_block_builder = __esm({
|
|
443
557
|
"src/plugins/guides/block-builder.ts"() {
|
|
444
558
|
init_constants2();
|
|
559
|
+
BLOCK_ALIGN_SELF = {
|
|
560
|
+
left: "flex-start",
|
|
561
|
+
center: "center",
|
|
562
|
+
right: "flex-end"
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
});
|
|
566
|
+
|
|
567
|
+
// src/plugins/guides/walkthrough-block-builder.ts
|
|
568
|
+
function buildWalkthroughStepContent(step, stepIndex, totalSteps, doc, callbacks) {
|
|
569
|
+
const container = doc.createElement("div");
|
|
570
|
+
container.className = "veo-guide-content";
|
|
571
|
+
const counter = doc.createElement("div");
|
|
572
|
+
counter.className = "veo-walkthrough-counter";
|
|
573
|
+
counter.textContent = `Paso ${stepIndex + 1} de ${totalSteps}`;
|
|
574
|
+
container.appendChild(counter);
|
|
575
|
+
const progress = doc.createElement("div");
|
|
576
|
+
progress.className = "veo-walkthrough-progress";
|
|
577
|
+
for (let i = 0; i < totalSteps; i++) {
|
|
578
|
+
const dot = doc.createElement("span");
|
|
579
|
+
dot.className = "veo-walkthrough-progress-dot";
|
|
580
|
+
if (i < stepIndex) dot.classList.add("completed");
|
|
581
|
+
if (i === stepIndex) dot.classList.add("active");
|
|
582
|
+
progress.appendChild(dot);
|
|
583
|
+
}
|
|
584
|
+
container.appendChild(progress);
|
|
585
|
+
if (typeof step.imageUrl === "string" && step.imageUrl && isSafeUrl(step.imageUrl)) {
|
|
586
|
+
const img = doc.createElement("img");
|
|
587
|
+
img.className = "veo-guide-image";
|
|
588
|
+
img.src = step.imageUrl;
|
|
589
|
+
img.alt = typeof step.title === "string" ? step.title : "";
|
|
590
|
+
container.appendChild(img);
|
|
591
|
+
}
|
|
592
|
+
if (typeof step.title === "string" && step.title) {
|
|
593
|
+
const heading = doc.createElement("h2");
|
|
594
|
+
heading.className = "veo-guide-title";
|
|
595
|
+
heading.textContent = step.title;
|
|
596
|
+
container.appendChild(heading);
|
|
597
|
+
}
|
|
598
|
+
if (typeof step.content === "string" && step.content) {
|
|
599
|
+
const paragraph = doc.createElement("p");
|
|
600
|
+
paragraph.className = "veo-guide-text";
|
|
601
|
+
paragraph.textContent = step.content;
|
|
602
|
+
container.appendChild(paragraph);
|
|
603
|
+
}
|
|
604
|
+
const actions = doc.createElement("div");
|
|
605
|
+
actions.className = "veo-walkthrough-actions";
|
|
606
|
+
const skipBtn = doc.createElement("button");
|
|
607
|
+
skipBtn.type = "button";
|
|
608
|
+
skipBtn.className = "veo-walkthrough-skip";
|
|
609
|
+
skipBtn.textContent = "Omitir";
|
|
610
|
+
skipBtn.addEventListener("click", () => callbacks.onSkip());
|
|
611
|
+
actions.appendChild(skipBtn);
|
|
612
|
+
const rightGroup = doc.createElement("div");
|
|
613
|
+
rightGroup.className = "veo-walkthrough-actions-right";
|
|
614
|
+
if (stepIndex > 0) {
|
|
615
|
+
const backBtn = doc.createElement("button");
|
|
616
|
+
backBtn.type = "button";
|
|
617
|
+
backBtn.className = "veo-walkthrough-btn-secondary";
|
|
618
|
+
backBtn.textContent = "Atr\xE1s";
|
|
619
|
+
backBtn.addEventListener("click", () => callbacks.onBack());
|
|
620
|
+
rightGroup.appendChild(backBtn);
|
|
621
|
+
}
|
|
622
|
+
const isLastStep = stepIndex === totalSteps - 1;
|
|
623
|
+
const primaryBtn = doc.createElement("button");
|
|
624
|
+
primaryBtn.type = "button";
|
|
625
|
+
primaryBtn.className = "veo-guide-cta";
|
|
626
|
+
const defaultLabel = isLastStep ? "Finalizar" : "Siguiente";
|
|
627
|
+
primaryBtn.textContent = typeof step.ctaText === "string" && step.ctaText ? step.ctaText : defaultLabel;
|
|
628
|
+
primaryBtn.addEventListener("click", () => {
|
|
629
|
+
if (isLastStep) callbacks.onComplete();
|
|
630
|
+
else callbacks.onNext();
|
|
631
|
+
});
|
|
632
|
+
rightGroup.appendChild(primaryBtn);
|
|
633
|
+
actions.appendChild(rightGroup);
|
|
634
|
+
container.appendChild(actions);
|
|
635
|
+
container.appendChild(createCloseButton(doc, () => callbacks.onSkip()));
|
|
636
|
+
return container;
|
|
637
|
+
}
|
|
638
|
+
var init_walkthrough_block_builder = __esm({
|
|
639
|
+
"src/plugins/guides/walkthrough-block-builder.ts"() {
|
|
640
|
+
init_block_builder();
|
|
445
641
|
}
|
|
446
642
|
});
|
|
447
643
|
|
|
@@ -455,6 +651,9 @@ function applyDesignVars(host, style) {
|
|
|
455
651
|
if (typeof s.accentColor === "string" && COLOR_RE.test(s.accentColor.trim())) {
|
|
456
652
|
host.style.setProperty("--veo-primary", s.accentColor.trim());
|
|
457
653
|
}
|
|
654
|
+
if (typeof s.fontFamily === "string" && s.fontFamily.length <= 200 && !/[<>{}]/.test(s.fontFamily)) {
|
|
655
|
+
host.style.setProperty("--veo-font", s.fontFamily.trim());
|
|
656
|
+
}
|
|
458
657
|
if (s.theme === "dark") {
|
|
459
658
|
for (const [key, value] of Object.entries(DARK_THEME)) {
|
|
460
659
|
host.style.setProperty(key, value);
|
|
@@ -596,7 +795,7 @@ var init_styles = __esm({
|
|
|
596
795
|
--veo-actions-justify: flex-end;
|
|
597
796
|
all: initial;
|
|
598
797
|
}
|
|
599
|
-
* { box-sizing: border-box; font-family: -apple-system, system-ui, "Segoe UI", Roboto, sans-serif; }
|
|
798
|
+
* { box-sizing: border-box; font-family: var(--veo-font, -apple-system, system-ui, "Segoe UI", Roboto, sans-serif); }
|
|
600
799
|
|
|
601
800
|
.veo-modal-overlay {
|
|
602
801
|
position: fixed; inset: 0;
|
|
@@ -673,6 +872,12 @@ var init_styles = __esm({
|
|
|
673
872
|
position: relative;
|
|
674
873
|
display: flex; flex-direction: column;
|
|
675
874
|
}
|
|
875
|
+
/* Reserva espacio para la \u2715 (esquina sup. derecha) SOLO en el primer bloque:
|
|
876
|
+
as\xED el texto alineado a la derecha no queda tapado por el bot\xF3n de cerrar. */
|
|
877
|
+
.veo-guide-content > .veo-guide-title:first-child,
|
|
878
|
+
.veo-guide-content > .veo-guide-text:first-child {
|
|
879
|
+
padding-right: 20px;
|
|
880
|
+
}
|
|
676
881
|
.veo-guide-image {
|
|
677
882
|
display: block;
|
|
678
883
|
width: var(--veo-image-width, 100%);
|
|
@@ -939,10 +1144,12 @@ var BannerRenderer;
|
|
|
939
1144
|
var init_banner_renderer = __esm({
|
|
940
1145
|
"src/plugins/guides/renderers/banner-renderer.ts"() {
|
|
941
1146
|
init_block_builder();
|
|
1147
|
+
init_walkthrough_block_builder();
|
|
942
1148
|
init_base_renderer();
|
|
943
1149
|
BannerRenderer = class extends BaseRenderer {
|
|
944
1150
|
render(context) {
|
|
945
|
-
const
|
|
1151
|
+
const idx = context.nav?.stepIndex ?? 0;
|
|
1152
|
+
const step = context.guide.guideSteps[idx];
|
|
946
1153
|
if (!step) return;
|
|
947
1154
|
const { root } = this.createHost();
|
|
948
1155
|
this.applyDesign(step.style);
|
|
@@ -951,27 +1158,25 @@ var init_banner_renderer = __esm({
|
|
|
951
1158
|
const banner = ownerDocument.createElement("div");
|
|
952
1159
|
banner.className = `veo-banner veo-banner-${position}`;
|
|
953
1160
|
const dismiss = (action, ctaUrl) => {
|
|
954
|
-
context.onInteraction({
|
|
955
|
-
guideId: context.guide.guideId,
|
|
956
|
-
stepIndex: 0,
|
|
957
|
-
action
|
|
958
|
-
});
|
|
1161
|
+
context.onInteraction({ guideId: context.guide.guideId, stepIndex: idx, action });
|
|
959
1162
|
if (ctaUrl) window.open(ctaUrl, "_blank", "noopener,noreferrer");
|
|
960
1163
|
context.onClose();
|
|
961
1164
|
};
|
|
962
|
-
const content =
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
1165
|
+
const content = context.nav ? buildWalkthroughStepContent(
|
|
1166
|
+
step,
|
|
1167
|
+
context.nav.stepIndex,
|
|
1168
|
+
context.nav.totalSteps,
|
|
1169
|
+
ownerDocument,
|
|
1170
|
+
context.nav.callbacks
|
|
1171
|
+
) : buildStepContent(step, ownerDocument, {
|
|
1172
|
+
onCtaClick: (action, url) => dismiss("cta_clicked", action === "url" ? url : void 0),
|
|
966
1173
|
onDismiss: () => dismiss("dismissed")
|
|
967
1174
|
});
|
|
968
1175
|
banner.appendChild(content);
|
|
969
1176
|
root.appendChild(banner);
|
|
970
|
-
context.
|
|
971
|
-
guideId: context.guide.guideId,
|
|
972
|
-
|
|
973
|
-
action: "shown"
|
|
974
|
-
});
|
|
1177
|
+
if (!context.nav) {
|
|
1178
|
+
context.onInteraction({ guideId: context.guide.guideId, stepIndex: 0, action: "shown" });
|
|
1179
|
+
}
|
|
975
1180
|
}
|
|
976
1181
|
};
|
|
977
1182
|
}
|
|
@@ -1693,10 +1898,12 @@ var ModalRenderer;
|
|
|
1693
1898
|
var init_modal_renderer = __esm({
|
|
1694
1899
|
"src/plugins/guides/renderers/modal-renderer.ts"() {
|
|
1695
1900
|
init_block_builder();
|
|
1901
|
+
init_walkthrough_block_builder();
|
|
1696
1902
|
init_base_renderer();
|
|
1697
1903
|
ModalRenderer = class extends BaseRenderer {
|
|
1698
1904
|
render(context) {
|
|
1699
|
-
const
|
|
1905
|
+
const idx = context.nav?.stepIndex ?? 0;
|
|
1906
|
+
const step = context.guide.guideSteps[idx];
|
|
1700
1907
|
if (!step) return;
|
|
1701
1908
|
const { root } = this.createHost();
|
|
1702
1909
|
this.applyDesign(step.style);
|
|
@@ -1706,36 +1913,38 @@ var init_modal_renderer = __esm({
|
|
|
1706
1913
|
const card = ownerDocument.createElement("div");
|
|
1707
1914
|
card.className = "veo-modal-card";
|
|
1708
1915
|
const dismiss = (action, ctaUrl) => {
|
|
1709
|
-
context.onInteraction({
|
|
1710
|
-
guideId: context.guide.guideId,
|
|
1711
|
-
stepIndex: 0,
|
|
1712
|
-
action
|
|
1713
|
-
});
|
|
1916
|
+
context.onInteraction({ guideId: context.guide.guideId, stepIndex: idx, action });
|
|
1714
1917
|
if (ctaUrl) window.open(ctaUrl, "_blank", "noopener,noreferrer");
|
|
1715
1918
|
context.onClose();
|
|
1716
1919
|
};
|
|
1717
|
-
const
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1920
|
+
const onBackdropOrEsc = () => {
|
|
1921
|
+
if (context.nav) context.nav.callbacks.onSkip();
|
|
1922
|
+
else dismiss("dismissed");
|
|
1923
|
+
};
|
|
1924
|
+
const content = context.nav ? buildWalkthroughStepContent(
|
|
1925
|
+
step,
|
|
1926
|
+
context.nav.stepIndex,
|
|
1927
|
+
context.nav.totalSteps,
|
|
1928
|
+
ownerDocument,
|
|
1929
|
+
context.nav.callbacks
|
|
1930
|
+
) : buildStepContent(step, ownerDocument, {
|
|
1931
|
+
onCtaClick: (action, url) => dismiss("cta_clicked", action === "url" ? url : void 0),
|
|
1721
1932
|
onDismiss: () => dismiss("dismissed")
|
|
1722
1933
|
});
|
|
1723
1934
|
card.appendChild(content);
|
|
1724
1935
|
overlay.appendChild(card);
|
|
1725
1936
|
root.appendChild(overlay);
|
|
1726
1937
|
overlay.addEventListener("click", (e) => {
|
|
1727
|
-
if (e.target === overlay)
|
|
1938
|
+
if (e.target === overlay) onBackdropOrEsc();
|
|
1728
1939
|
});
|
|
1729
1940
|
const onKey = (e) => {
|
|
1730
|
-
if (e.key === "Escape")
|
|
1941
|
+
if (e.key === "Escape") onBackdropOrEsc();
|
|
1731
1942
|
};
|
|
1732
1943
|
document.addEventListener("keydown", onKey);
|
|
1733
1944
|
this.registerCleanup(() => document.removeEventListener("keydown", onKey));
|
|
1734
|
-
context.
|
|
1735
|
-
guideId: context.guide.guideId,
|
|
1736
|
-
|
|
1737
|
-
action: "shown"
|
|
1738
|
-
});
|
|
1945
|
+
if (!context.nav) {
|
|
1946
|
+
context.onInteraction({ guideId: context.guide.guideId, stepIndex: 0, action: "shown" });
|
|
1947
|
+
}
|
|
1739
1948
|
}
|
|
1740
1949
|
};
|
|
1741
1950
|
}
|
|
@@ -1777,6 +1986,8 @@ var init_tooltip_renderer = __esm({
|
|
|
1777
1986
|
if (typeof selector !== "string" || selector.length === 0) return;
|
|
1778
1987
|
const anchor = await waitForElement(selector);
|
|
1779
1988
|
if (!anchor) return;
|
|
1989
|
+
const rawSide = step.style?.tooltipPlacement;
|
|
1990
|
+
const side = rawSide === "top" || rawSide === "left" || rawSide === "right" ? rawSide : "bottom";
|
|
1780
1991
|
const { root } = this.createHost();
|
|
1781
1992
|
this.applyDesign(step.style);
|
|
1782
1993
|
const ownerDocument = root.ownerDocument ?? document;
|
|
@@ -1804,7 +2015,7 @@ var init_tooltip_renderer = __esm({
|
|
|
1804
2015
|
root.appendChild(tooltip);
|
|
1805
2016
|
const updatePosition = async () => {
|
|
1806
2017
|
const { x, y, placement, middlewareData } = await dom.computePosition(anchor, tooltip, {
|
|
1807
|
-
placement:
|
|
2018
|
+
placement: side,
|
|
1808
2019
|
middleware: [dom.offset(10), dom.flip(), dom.shift({ padding: 8 }), dom.arrow({ element: arrowEl })]
|
|
1809
2020
|
});
|
|
1810
2021
|
tooltip.style.left = `${x}px`;
|
|
@@ -1830,83 +2041,6 @@ var init_tooltip_renderer = __esm({
|
|
|
1830
2041
|
};
|
|
1831
2042
|
}
|
|
1832
2043
|
});
|
|
1833
|
-
|
|
1834
|
-
// src/plugins/guides/walkthrough-block-builder.ts
|
|
1835
|
-
function buildWalkthroughStepContent(step, stepIndex, totalSteps, doc, callbacks) {
|
|
1836
|
-
const container = doc.createElement("div");
|
|
1837
|
-
container.className = "veo-guide-content";
|
|
1838
|
-
const counter = doc.createElement("div");
|
|
1839
|
-
counter.className = "veo-walkthrough-counter";
|
|
1840
|
-
counter.textContent = `Paso ${stepIndex + 1} de ${totalSteps}`;
|
|
1841
|
-
container.appendChild(counter);
|
|
1842
|
-
const progress = doc.createElement("div");
|
|
1843
|
-
progress.className = "veo-walkthrough-progress";
|
|
1844
|
-
for (let i = 0; i < totalSteps; i++) {
|
|
1845
|
-
const dot = doc.createElement("span");
|
|
1846
|
-
dot.className = "veo-walkthrough-progress-dot";
|
|
1847
|
-
if (i < stepIndex) dot.classList.add("completed");
|
|
1848
|
-
if (i === stepIndex) dot.classList.add("active");
|
|
1849
|
-
progress.appendChild(dot);
|
|
1850
|
-
}
|
|
1851
|
-
container.appendChild(progress);
|
|
1852
|
-
if (typeof step.imageUrl === "string" && step.imageUrl && isSafeUrl(step.imageUrl)) {
|
|
1853
|
-
const img = doc.createElement("img");
|
|
1854
|
-
img.className = "veo-guide-image";
|
|
1855
|
-
img.src = step.imageUrl;
|
|
1856
|
-
img.alt = typeof step.title === "string" ? step.title : "";
|
|
1857
|
-
container.appendChild(img);
|
|
1858
|
-
}
|
|
1859
|
-
if (typeof step.title === "string" && step.title) {
|
|
1860
|
-
const heading = doc.createElement("h2");
|
|
1861
|
-
heading.className = "veo-guide-title";
|
|
1862
|
-
heading.textContent = step.title;
|
|
1863
|
-
container.appendChild(heading);
|
|
1864
|
-
}
|
|
1865
|
-
if (typeof step.content === "string" && step.content) {
|
|
1866
|
-
const paragraph = doc.createElement("p");
|
|
1867
|
-
paragraph.className = "veo-guide-text";
|
|
1868
|
-
paragraph.textContent = step.content;
|
|
1869
|
-
container.appendChild(paragraph);
|
|
1870
|
-
}
|
|
1871
|
-
const actions = doc.createElement("div");
|
|
1872
|
-
actions.className = "veo-walkthrough-actions";
|
|
1873
|
-
const skipBtn = doc.createElement("button");
|
|
1874
|
-
skipBtn.type = "button";
|
|
1875
|
-
skipBtn.className = "veo-walkthrough-skip";
|
|
1876
|
-
skipBtn.textContent = "Omitir";
|
|
1877
|
-
skipBtn.addEventListener("click", () => callbacks.onSkip());
|
|
1878
|
-
actions.appendChild(skipBtn);
|
|
1879
|
-
const rightGroup = doc.createElement("div");
|
|
1880
|
-
rightGroup.className = "veo-walkthrough-actions-right";
|
|
1881
|
-
if (stepIndex > 0) {
|
|
1882
|
-
const backBtn = doc.createElement("button");
|
|
1883
|
-
backBtn.type = "button";
|
|
1884
|
-
backBtn.className = "veo-walkthrough-btn-secondary";
|
|
1885
|
-
backBtn.textContent = "Atr\xE1s";
|
|
1886
|
-
backBtn.addEventListener("click", () => callbacks.onBack());
|
|
1887
|
-
rightGroup.appendChild(backBtn);
|
|
1888
|
-
}
|
|
1889
|
-
const isLastStep = stepIndex === totalSteps - 1;
|
|
1890
|
-
const primaryBtn = doc.createElement("button");
|
|
1891
|
-
primaryBtn.type = "button";
|
|
1892
|
-
primaryBtn.className = "veo-guide-cta";
|
|
1893
|
-
const defaultLabel = isLastStep ? "Finalizar" : "Siguiente";
|
|
1894
|
-
primaryBtn.textContent = typeof step.ctaText === "string" && step.ctaText ? step.ctaText : defaultLabel;
|
|
1895
|
-
primaryBtn.addEventListener("click", () => {
|
|
1896
|
-
if (isLastStep) callbacks.onComplete();
|
|
1897
|
-
else callbacks.onNext();
|
|
1898
|
-
});
|
|
1899
|
-
rightGroup.appendChild(primaryBtn);
|
|
1900
|
-
actions.appendChild(rightGroup);
|
|
1901
|
-
container.appendChild(actions);
|
|
1902
|
-
container.appendChild(createCloseButton(doc, () => callbacks.onSkip()));
|
|
1903
|
-
return container;
|
|
1904
|
-
}
|
|
1905
|
-
var init_walkthrough_block_builder = __esm({
|
|
1906
|
-
"src/plugins/guides/walkthrough-block-builder.ts"() {
|
|
1907
|
-
init_block_builder();
|
|
1908
|
-
}
|
|
1909
|
-
});
|
|
1910
2044
|
var WalkthroughRenderer;
|
|
1911
2045
|
var init_walkthrough_renderer = __esm({
|
|
1912
2046
|
"src/plugins/guides/renderers/walkthrough-renderer.ts"() {
|
|
@@ -1923,6 +2057,8 @@ var init_walkthrough_renderer = __esm({
|
|
|
1923
2057
|
if (typeof selector !== "string" || selector.length === 0) return false;
|
|
1924
2058
|
const anchor = await waitForElement(selector, WALKTHROUGH_STEP_SELECTOR_TIMEOUT_MS);
|
|
1925
2059
|
if (!anchor) return false;
|
|
2060
|
+
const rawSide = step.style?.tooltipPlacement;
|
|
2061
|
+
const side = rawSide === "top" || rawSide === "left" || rawSide === "right" ? rawSide : "bottom";
|
|
1926
2062
|
const { root } = this.createHost();
|
|
1927
2063
|
this.applyDesign(step.style);
|
|
1928
2064
|
const ownerDocument = root.ownerDocument ?? document;
|
|
@@ -1942,7 +2078,7 @@ var init_walkthrough_renderer = __esm({
|
|
|
1942
2078
|
root.appendChild(tooltip);
|
|
1943
2079
|
const updatePosition = async () => {
|
|
1944
2080
|
const { x, y, placement, middlewareData } = await dom.computePosition(anchor, tooltip, {
|
|
1945
|
-
placement:
|
|
2081
|
+
placement: side,
|
|
1946
2082
|
middleware: [dom.offset(10), dom.flip(), dom.shift({ padding: 8 }), dom.arrow({ element: arrowEl })]
|
|
1947
2083
|
});
|
|
1948
2084
|
tooltip.style.left = `${x}px`;
|
|
@@ -2039,6 +2175,7 @@ var init_guide_preview = __esm({
|
|
|
2039
2175
|
GuidePreviewController = class {
|
|
2040
2176
|
constructor() {
|
|
2041
2177
|
this.singleStep = null;
|
|
2178
|
+
/** Renderer del paso de walkthrough activo (walkthrough tooltip o modal/banner). */
|
|
2042
2179
|
this.walkthrough = null;
|
|
2043
2180
|
this.walkthroughGuide = null;
|
|
2044
2181
|
this.walkthroughIndex = 0;
|
|
@@ -2111,7 +2248,6 @@ var init_guide_preview = __esm({
|
|
|
2111
2248
|
safeDestroy(this.walkthrough);
|
|
2112
2249
|
this.walkthrough = null;
|
|
2113
2250
|
}
|
|
2114
|
-
const renderer = new WalkthroughRenderer();
|
|
2115
2251
|
const callbacks = {
|
|
2116
2252
|
onNext: () => {
|
|
2117
2253
|
const next = this.walkthroughIndex + 1;
|
|
@@ -2131,6 +2267,30 @@ var init_guide_preview = __esm({
|
|
|
2131
2267
|
onSkip: () => this.close(),
|
|
2132
2268
|
onComplete: () => this.close()
|
|
2133
2269
|
};
|
|
2270
|
+
const step = guide.guideSteps[index];
|
|
2271
|
+
const render = step?.style?.render;
|
|
2272
|
+
if (render === "modal" || render === "banner") {
|
|
2273
|
+
const renderer2 = render === "modal" ? new ModalRenderer() : new BannerRenderer();
|
|
2274
|
+
try {
|
|
2275
|
+
renderer2.render({
|
|
2276
|
+
guide,
|
|
2277
|
+
onInteraction: () => {
|
|
2278
|
+
},
|
|
2279
|
+
onClose: () => this.close(),
|
|
2280
|
+
nav: { stepIndex: index, totalSteps: guide.guideSteps.length, callbacks }
|
|
2281
|
+
});
|
|
2282
|
+
} catch {
|
|
2283
|
+
safeDestroy(renderer2);
|
|
2284
|
+
return false;
|
|
2285
|
+
}
|
|
2286
|
+
if (this.walkthroughGuide !== guide) {
|
|
2287
|
+
safeDestroy(renderer2);
|
|
2288
|
+
return false;
|
|
2289
|
+
}
|
|
2290
|
+
this.walkthrough = renderer2;
|
|
2291
|
+
return true;
|
|
2292
|
+
}
|
|
2293
|
+
const renderer = new WalkthroughRenderer();
|
|
2134
2294
|
let success = false;
|
|
2135
2295
|
try {
|
|
2136
2296
|
success = await renderer.render({ guide, currentStepIndex: index, callbacks });
|
|
@@ -4198,6 +4358,11 @@ var GuidesController = class {
|
|
|
4198
4358
|
*/
|
|
4199
4359
|
this.activeByGuideId = /* @__PURE__ */ new Map();
|
|
4200
4360
|
this.dispatched = /* @__PURE__ */ new Set();
|
|
4361
|
+
/**
|
|
4362
|
+
* Renderer del paso de walkthrough activo. Puede ser el `WalkthroughRenderer`
|
|
4363
|
+
* (tooltip anclado) o un Modal/Banner con navegación (walkthrough heterogéneo);
|
|
4364
|
+
* tipamos por `destroy()`, lo único que el controller necesita.
|
|
4365
|
+
*/
|
|
4201
4366
|
this.activeWalkthroughRenderer = null;
|
|
4202
4367
|
this.activeWalkthroughGuide = null;
|
|
4203
4368
|
this.debug = config.debug === true;
|
|
@@ -4378,7 +4543,6 @@ var GuidesController = class {
|
|
|
4378
4543
|
this.activeWalkthroughRenderer.destroy();
|
|
4379
4544
|
this.activeWalkthroughRenderer = null;
|
|
4380
4545
|
}
|
|
4381
|
-
const renderer = new WalkthroughRenderer();
|
|
4382
4546
|
this.activeWalkthroughGuide = guide;
|
|
4383
4547
|
const callbacks = {
|
|
4384
4548
|
onNext: () => this.handleWalkthroughNext(endUserId, sessionId, pageUrl),
|
|
@@ -4386,6 +4550,28 @@ var GuidesController = class {
|
|
|
4386
4550
|
onSkip: () => this.handleWalkthroughSkip(endUserId, sessionId, pageUrl),
|
|
4387
4551
|
onComplete: () => this.handleWalkthroughComplete(endUserId, sessionId, pageUrl)
|
|
4388
4552
|
};
|
|
4553
|
+
const step = guide.guideSteps[stepIndex];
|
|
4554
|
+
const render = readStepRender(step);
|
|
4555
|
+
if (render === "modal" || render === "banner") {
|
|
4556
|
+
const renderer2 = render === "modal" ? new ModalRenderer() : new BannerRenderer();
|
|
4557
|
+
try {
|
|
4558
|
+
renderer2.render({
|
|
4559
|
+
guide,
|
|
4560
|
+
onInteraction: () => {
|
|
4561
|
+
},
|
|
4562
|
+
onClose: () => {
|
|
4563
|
+
},
|
|
4564
|
+
nav: { stepIndex, totalSteps: guide.guideSteps.length, callbacks }
|
|
4565
|
+
});
|
|
4566
|
+
} catch (err) {
|
|
4567
|
+
if (this.debug) console.error("[veo] sequence renderer threw:", err);
|
|
4568
|
+
this.tearDownWalkthrough();
|
|
4569
|
+
return false;
|
|
4570
|
+
}
|
|
4571
|
+
this.activeWalkthroughRenderer = renderer2;
|
|
4572
|
+
return true;
|
|
4573
|
+
}
|
|
4574
|
+
const renderer = new WalkthroughRenderer();
|
|
4389
4575
|
let success = false;
|
|
4390
4576
|
try {
|
|
4391
4577
|
success = await renderer.render({ guide, currentStepIndex: stepIndex, callbacks });
|
|
@@ -4608,6 +4794,10 @@ function extractPath(url) {
|
|
|
4608
4794
|
return "/";
|
|
4609
4795
|
}
|
|
4610
4796
|
}
|
|
4797
|
+
function readStepRender(step) {
|
|
4798
|
+
const r = step?.style?.render;
|
|
4799
|
+
return typeof r === "string" ? r : "walkthrough";
|
|
4800
|
+
}
|
|
4611
4801
|
|
|
4612
4802
|
// src/plugins/guides/index.ts
|
|
4613
4803
|
init_guide_preview();
|