veo-sdk 0.4.2 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/builder-R2BHDQZH.mjs +5 -0
- package/dist/{builder-S6ZODU2M.mjs.map → builder-R2BHDQZH.mjs.map} +1 -1
- package/dist/builder.cjs +70 -25
- 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-KLN46YQI.mjs → chunk-GRPUHGYZ.mjs} +105 -19
- package/dist/chunk-GRPUHGYZ.mjs.map +1 -0
- package/dist/{chunk-F2ZWZUTR.mjs → chunk-L3JSRBVO.mjs} +72 -27
- package/dist/chunk-L3JSRBVO.mjs.map +1 -0
- package/dist/{chunk-ULH64GMX.mjs → chunk-PGGUVH4V.mjs} +3 -3
- package/dist/{chunk-ULH64GMX.mjs.map → chunk-PGGUVH4V.mjs.map} +1 -1
- package/dist/{guide-preview-D_xhRVLe.d.cts → guide-preview-B912Y6UY.d.cts} +4 -2
- package/dist/{guide-preview-D_xhRVLe.d.ts → guide-preview-B912Y6UY.d.ts} +4 -2
- package/dist/index.cjs +172 -41
- 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 +19 -7
- package/dist/veo-builder.js.map +1 -1
- package/dist/veo-guides.js +19 -7
- package/dist/veo-guides.js.map +1 -1
- package/package.json +1 -1
- package/dist/builder-S6ZODU2M.mjs +0 -5
- package/dist/chunk-F2ZWZUTR.mjs.map +0 -1
- package/dist/chunk-KLN46YQI.mjs.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -615,12 +615,12 @@ function buildButtonBlock(block, doc, callbacks) {
|
|
|
615
615
|
applyBlockStyle(btn, block.style, "button");
|
|
616
616
|
btn.addEventListener("click", () => {
|
|
617
617
|
const action = block.action ?? "dismiss";
|
|
618
|
-
const
|
|
618
|
+
const target = action === "url" && typeof block.url === "string" && isSafeUrl(block.url) ? block.url : action === "guide" && typeof block.targetGuideId === "string" && block.targetGuideId ? block.targetGuideId : void 0;
|
|
619
619
|
const meta = {
|
|
620
620
|
...typeof block.id === "string" && block.id ? { buttonId: block.id } : {},
|
|
621
621
|
...typeof block.text === "string" && block.text ? { buttonText: block.text } : {}
|
|
622
622
|
};
|
|
623
|
-
callbacks.onCtaClick(action,
|
|
623
|
+
callbacks.onCtaClick(action, target, Object.keys(meta).length ? meta : void 0);
|
|
624
624
|
});
|
|
625
625
|
return btn;
|
|
626
626
|
}
|
|
@@ -1259,10 +1259,22 @@ var init_styles = __esm({
|
|
|
1259
1259
|
padding: 3px 9px;
|
|
1260
1260
|
white-space: nowrap;
|
|
1261
1261
|
}
|
|
1262
|
+
.veo-badge--text {
|
|
1263
|
+
color: var(--veo-primary);
|
|
1264
|
+
font-weight: 600;
|
|
1265
|
+
white-space: nowrap;
|
|
1266
|
+
text-decoration: underline dotted;
|
|
1267
|
+
text-underline-offset: 3px;
|
|
1268
|
+
}
|
|
1262
1269
|
.veo-badge--image img { display: block; border-radius: 4px; object-fit: cover; }
|
|
1263
1270
|
/* El tooltip del badge usa strategy fixed (el host vive dentro del flujo del
|
|
1264
|
-
cliente; un absoluto se recortar\xEDa con overflow de ancestros).
|
|
1265
|
-
|
|
1271
|
+
cliente; un absoluto se recortar\xEDa con overflow de ancestros). Su ancho es
|
|
1272
|
+
personalizable v\xEDa var dedicada (--veo-width no sirve: el :host la define
|
|
1273
|
+
en 420px siempre y pisar\xEDa el default de 300px de los tooltips). */
|
|
1274
|
+
.veo-badge-tooltip {
|
|
1275
|
+
position: fixed;
|
|
1276
|
+
max-width: var(--veo-badge-tip-width, 300px);
|
|
1277
|
+
}
|
|
1266
1278
|
@keyframes veo-badge-pulse {
|
|
1267
1279
|
0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--veo-primary) 45%, transparent); }
|
|
1268
1280
|
70% { box-shadow: 0 0 0 7px transparent; }
|
|
@@ -1439,7 +1451,7 @@ function readBadgeConfig(step) {
|
|
|
1439
1451
|
const raw = step.style?.badge;
|
|
1440
1452
|
if (!raw || typeof raw !== "object") return { kind: "icon" };
|
|
1441
1453
|
const b = raw;
|
|
1442
|
-
const kind = b.kind === "dot" || b.kind === "pill" || b.kind === "image" || b.kind === "icon" ? b.kind : "icon";
|
|
1454
|
+
const kind = b.kind === "dot" || b.kind === "pill" || b.kind === "text" || b.kind === "image" || b.kind === "icon" ? b.kind : "icon";
|
|
1443
1455
|
return {
|
|
1444
1456
|
kind,
|
|
1445
1457
|
icon: typeof b.icon === "string" ? b.icon : null,
|
|
@@ -1470,6 +1482,12 @@ function buildBadgeElement(config, doc) {
|
|
|
1470
1482
|
if (config.color) btn.style.background = config.color;
|
|
1471
1483
|
break;
|
|
1472
1484
|
}
|
|
1485
|
+
case "text": {
|
|
1486
|
+
btn.textContent = config.text?.slice(0, 32) || "Nuevo";
|
|
1487
|
+
btn.style.fontSize = `${clamp2(Math.round(size * 0.7), 9, 28)}px`;
|
|
1488
|
+
if (config.color) btn.style.color = config.color;
|
|
1489
|
+
break;
|
|
1490
|
+
}
|
|
1473
1491
|
case "image": {
|
|
1474
1492
|
if (config.imageUrl && isSafeUrl(config.imageUrl)) {
|
|
1475
1493
|
const img = doc.createElement("img");
|
|
@@ -1531,6 +1549,13 @@ var init_badge_renderer = __esm({
|
|
|
1531
1549
|
const { host, root } = this.createHost();
|
|
1532
1550
|
const ownerDocument = root.ownerDocument ?? document;
|
|
1533
1551
|
this.applyDesign(step.style);
|
|
1552
|
+
const tipWidth = step.style?.width;
|
|
1553
|
+
if (typeof tipWidth === "number" && Number.isFinite(tipWidth)) {
|
|
1554
|
+
host.style.setProperty(
|
|
1555
|
+
"--veo-badge-tip-width",
|
|
1556
|
+
`${Math.min(720, Math.max(220, tipWidth))}px`
|
|
1557
|
+
);
|
|
1558
|
+
}
|
|
1534
1559
|
this.trigger = step.style?.badgeTrigger === "click" ? "click" : "hover";
|
|
1535
1560
|
const rawSide = step.style?.tooltipPlacement;
|
|
1536
1561
|
this.side = rawSide === "bottom" || rawSide === "left" || rawSide === "right" ? rawSide : "top";
|
|
@@ -1554,20 +1579,14 @@ var init_badge_renderer = __esm({
|
|
|
1554
1579
|
});
|
|
1555
1580
|
};
|
|
1556
1581
|
const buildTooltipContent = (s) => buildStepContent(s, ownerDocument, {
|
|
1557
|
-
onCtaClick: (action,
|
|
1582
|
+
onCtaClick: (action, target, meta) => {
|
|
1558
1583
|
emit("cta_clicked", meta);
|
|
1559
|
-
if (action === "url" &&
|
|
1560
|
-
if (action === "dismiss") {
|
|
1561
|
-
emit("dismissed");
|
|
1562
|
-
context.onClose();
|
|
1563
|
-
return;
|
|
1564
|
-
}
|
|
1584
|
+
if (action === "url" && target) window.open(target, "_blank", "noopener,noreferrer");
|
|
1565
1585
|
this.closeTooltip();
|
|
1586
|
+
if (action === "guide" && target) context.onOpenGuide?.(target);
|
|
1566
1587
|
},
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
context.onClose();
|
|
1570
|
-
}
|
|
1588
|
+
// La ✕ también cierra solo el tooltip (nunca el badge, nunca dismissed).
|
|
1589
|
+
onDismiss: () => this.closeTooltip()
|
|
1571
1590
|
});
|
|
1572
1591
|
const content = buildTooltipContent(step);
|
|
1573
1592
|
tooltip.appendChild(content);
|
|
@@ -1820,7 +1839,10 @@ var init_banner_renderer = __esm({
|
|
|
1820
1839
|
ownerDocument,
|
|
1821
1840
|
context.nav.callbacks
|
|
1822
1841
|
) : buildStepContent(step, ownerDocument, {
|
|
1823
|
-
onCtaClick: (action,
|
|
1842
|
+
onCtaClick: (action, target, meta) => {
|
|
1843
|
+
dismiss("cta_clicked", action === "url" ? target : void 0, meta);
|
|
1844
|
+
if (action === "guide" && target) context.onOpenGuide?.(target);
|
|
1845
|
+
},
|
|
1824
1846
|
onDismiss: () => dismiss("dismissed")
|
|
1825
1847
|
});
|
|
1826
1848
|
banner.appendChild(content);
|
|
@@ -1835,7 +1857,10 @@ var init_banner_renderer = __esm({
|
|
|
1835
1857
|
this.liveContainer = banner;
|
|
1836
1858
|
this.liveContent = content;
|
|
1837
1859
|
this.liveBuild = (s) => buildStepContent(s, ownerDocument, {
|
|
1838
|
-
onCtaClick: (action,
|
|
1860
|
+
onCtaClick: (action, target, meta) => {
|
|
1861
|
+
dismiss("cta_clicked", action === "url" ? target : void 0, meta);
|
|
1862
|
+
if (action === "guide" && target) context.onOpenGuide?.(target);
|
|
1863
|
+
},
|
|
1839
1864
|
onDismiss: () => dismiss("dismissed")
|
|
1840
1865
|
});
|
|
1841
1866
|
this.liveKey = this.liveKeyOf(step);
|
|
@@ -2496,7 +2521,10 @@ var init_inline_renderer = __esm({
|
|
|
2496
2521
|
context.onClose();
|
|
2497
2522
|
};
|
|
2498
2523
|
const content = buildStepContent(step, ownerDocument, {
|
|
2499
|
-
onCtaClick: (action,
|
|
2524
|
+
onCtaClick: (action, target, meta) => {
|
|
2525
|
+
dismiss("cta_clicked", action === "url" ? target : void 0, meta);
|
|
2526
|
+
if (action === "guide" && target) context.onOpenGuide?.(target);
|
|
2527
|
+
},
|
|
2500
2528
|
onDismiss: () => dismiss("dismissed")
|
|
2501
2529
|
});
|
|
2502
2530
|
card.appendChild(content);
|
|
@@ -2505,7 +2533,10 @@ var init_inline_renderer = __esm({
|
|
|
2505
2533
|
this.liveContent = content;
|
|
2506
2534
|
this.liveKey = `${selector}|${position}`;
|
|
2507
2535
|
this.liveBuild = (s) => buildStepContent(s, ownerDocument, {
|
|
2508
|
-
onCtaClick: (action,
|
|
2536
|
+
onCtaClick: (action, target, meta) => {
|
|
2537
|
+
dismiss("cta_clicked", action === "url" ? target : void 0, meta);
|
|
2538
|
+
if (action === "guide" && target) context.onOpenGuide?.(target);
|
|
2539
|
+
},
|
|
2509
2540
|
onDismiss: () => dismiss("dismissed")
|
|
2510
2541
|
});
|
|
2511
2542
|
context.onInteraction({ guideId: context.guide.guideId, stepIndex: 0, action: "shown" });
|
|
@@ -2565,7 +2596,10 @@ var init_modal_renderer = __esm({
|
|
|
2565
2596
|
ownerDocument,
|
|
2566
2597
|
context.nav.callbacks
|
|
2567
2598
|
) : buildStepContent(step, ownerDocument, {
|
|
2568
|
-
onCtaClick: (action,
|
|
2599
|
+
onCtaClick: (action, target, meta) => {
|
|
2600
|
+
dismiss("cta_clicked", action === "url" ? target : void 0, meta);
|
|
2601
|
+
if (action === "guide" && target) context.onOpenGuide?.(target);
|
|
2602
|
+
},
|
|
2569
2603
|
onDismiss: () => dismiss("dismissed")
|
|
2570
2604
|
});
|
|
2571
2605
|
card.appendChild(content);
|
|
@@ -2575,7 +2609,10 @@ var init_modal_renderer = __esm({
|
|
|
2575
2609
|
this.liveContainer = card;
|
|
2576
2610
|
this.liveContent = content;
|
|
2577
2611
|
this.liveBuild = (s) => buildStepContent(s, ownerDocument, {
|
|
2578
|
-
onCtaClick: (action,
|
|
2612
|
+
onCtaClick: (action, target, meta) => {
|
|
2613
|
+
dismiss("cta_clicked", action === "url" ? target : void 0, meta);
|
|
2614
|
+
if (action === "guide" && target) context.onOpenGuide?.(target);
|
|
2615
|
+
},
|
|
2579
2616
|
onDismiss: () => dismiss("dismissed")
|
|
2580
2617
|
});
|
|
2581
2618
|
}
|
|
@@ -2640,8 +2677,9 @@ var init_tooltip_renderer = __esm({
|
|
|
2640
2677
|
context.onClose();
|
|
2641
2678
|
};
|
|
2642
2679
|
const content = buildStepContent(step, ownerDocument, {
|
|
2643
|
-
onCtaClick: (action,
|
|
2644
|
-
dismiss("cta_clicked", action === "url" ?
|
|
2680
|
+
onCtaClick: (action, target, meta) => {
|
|
2681
|
+
dismiss("cta_clicked", action === "url" ? target : void 0, meta);
|
|
2682
|
+
if (action === "guide" && target) context.onOpenGuide?.(target);
|
|
2645
2683
|
},
|
|
2646
2684
|
onDismiss: () => dismiss("dismissed")
|
|
2647
2685
|
});
|
|
@@ -2674,7 +2712,10 @@ var init_tooltip_renderer = __esm({
|
|
|
2674
2712
|
this.liveContent = content;
|
|
2675
2713
|
this.liveKey = selector;
|
|
2676
2714
|
this.liveBuild = (s) => buildStepContent(s, ownerDocument, {
|
|
2677
|
-
onCtaClick: (action,
|
|
2715
|
+
onCtaClick: (action, target, meta) => {
|
|
2716
|
+
dismiss("cta_clicked", action === "url" ? target : void 0, meta);
|
|
2717
|
+
if (action === "guide" && target) context.onOpenGuide?.(target);
|
|
2718
|
+
},
|
|
2678
2719
|
onDismiss: () => dismiss("dismissed")
|
|
2679
2720
|
});
|
|
2680
2721
|
context.onInteraction({
|
|
@@ -2891,6 +2932,10 @@ var init_guide_preview = __esm({
|
|
|
2891
2932
|
onClose: () => this.close(),
|
|
2892
2933
|
onTrack: () => {
|
|
2893
2934
|
},
|
|
2935
|
+
// Encadenado en preview: no-op — el editor no puede montar otra guía
|
|
2936
|
+
// guardada; el click igual cierra la preview actual (vía onCtaClick).
|
|
2937
|
+
onOpenGuide: () => {
|
|
2938
|
+
},
|
|
2894
2939
|
// Preview de forms: por defecto simula el envío SIN escribir props;
|
|
2895
2940
|
// el caller puede pasar `formSubmit` real (link de preview).
|
|
2896
2941
|
onFormSubmit: this.input?.formSubmit ?? (() => Promise.resolve(true)),
|
|
@@ -5333,6 +5378,12 @@ var GuidesController = class {
|
|
|
5333
5378
|
this.resolveCache = null;
|
|
5334
5379
|
/** Resolución idéntica en vuelo, para coalescer llamadas concurrentes. */
|
|
5335
5380
|
this.inflightResolve = null;
|
|
5381
|
+
/**
|
|
5382
|
+
* Disparadores por interacción armados (`on_click`/`on_hover`): guideId →
|
|
5383
|
+
* desarme del listener. Se re-arman desde cero en cada `checkGuides` (el
|
|
5384
|
+
* resolve fresco manda) y se limpian en `destroy()`.
|
|
5385
|
+
*/
|
|
5386
|
+
this.armedTriggers = /* @__PURE__ */ new Map();
|
|
5336
5387
|
this.debug = config.debug === true;
|
|
5337
5388
|
this.apiUrl = config.apiUrl;
|
|
5338
5389
|
this.apiKey = config.apiKey;
|
|
@@ -5390,26 +5441,80 @@ var GuidesController = class {
|
|
|
5390
5441
|
return;
|
|
5391
5442
|
}
|
|
5392
5443
|
if (this.debug) console.log(`[veo] guides: ${guides.length} eligible at ${pageUrl}`);
|
|
5444
|
+
this.disarmTriggers();
|
|
5393
5445
|
for (const guide of guides) {
|
|
5394
|
-
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
}
|
|
5398
|
-
if (this.activeByGuideId.has(guide.guideId)) {
|
|
5399
|
-
if (this.debug) console.log(`[veo] guides: already shown guideId=${guide.guideId}`);
|
|
5446
|
+
const trigger = guide.activationRules.trigger;
|
|
5447
|
+
if ((trigger === "on_click" || trigger === "on_hover") && guide.activationRules.selector) {
|
|
5448
|
+
this.armInteractionTrigger(guide, endUserId, sessionId, pageUrl);
|
|
5400
5449
|
continue;
|
|
5401
5450
|
}
|
|
5402
|
-
|
|
5403
|
-
|
|
5404
|
-
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
|
|
5408
|
-
|
|
5409
|
-
|
|
5451
|
+
await this.showGuide(guide, endUserId, sessionId, pageUrl);
|
|
5452
|
+
}
|
|
5453
|
+
}
|
|
5454
|
+
/**
|
|
5455
|
+
* Muestra una guía elegible (filtro de frecuencia + dedupe + dispatch por
|
|
5456
|
+
* tipo). Cuerpo original del loop de `checkGuides`, extraído para que los
|
|
5457
|
+
* disparadores por interacción pasen por LOS MISMOS chequeos al disparar.
|
|
5458
|
+
*/
|
|
5459
|
+
async showGuide(guide, endUserId, sessionId, pageUrl) {
|
|
5460
|
+
if (this.frequencyCache.shouldFilter(guide.guideId, guide.displayFrequency)) {
|
|
5461
|
+
if (this.debug) console.log(`[veo] guides: filtered locally guideId=${guide.guideId}`);
|
|
5462
|
+
return;
|
|
5463
|
+
}
|
|
5464
|
+
if (this.activeByGuideId.has(guide.guideId)) {
|
|
5465
|
+
if (this.debug) console.log(`[veo] guides: already shown guideId=${guide.guideId}`);
|
|
5466
|
+
return;
|
|
5467
|
+
}
|
|
5468
|
+
if (guide.guideType === "walkthrough" && guide.guideSteps.length > 1) {
|
|
5469
|
+
if (this.walkthroughState.hasActive()) {
|
|
5470
|
+
if (this.debug)
|
|
5471
|
+
console.log(`[veo] guides: walkthrough ${guide.guideId} skipped (another active)`);
|
|
5472
|
+
return;
|
|
5410
5473
|
}
|
|
5411
|
-
this.
|
|
5474
|
+
await this.startWalkthrough(guide, endUserId, sessionId, pageUrl);
|
|
5475
|
+
return;
|
|
5412
5476
|
}
|
|
5477
|
+
this.runSingleStepRender(guide, sessionId, pageUrl);
|
|
5478
|
+
}
|
|
5479
|
+
/**
|
|
5480
|
+
* Arma un disparador por interacción: la guía NO se muestra al cargar, sino
|
|
5481
|
+
* cuando el usuario hace click / pasa el mouse sobre `activationRules.selector`.
|
|
5482
|
+
* Listener DELEGADO en `document` (fase captura, sin preventDefault — el click
|
|
5483
|
+
* original de la app sigue funcionando). Al disparar se desarma y la guía pasa
|
|
5484
|
+
* por `showGuide` (mismos chequeos de frecuencia/dedupe). Tras cerrarse, el
|
|
5485
|
+
* próximo pageview/identify la re-arma — hover/click vuelve a mostrarla
|
|
5486
|
+
* mientras la frecuencia lo permita.
|
|
5487
|
+
*/
|
|
5488
|
+
armInteractionTrigger(guide, endUserId, sessionId, pageUrl) {
|
|
5489
|
+
if (this.frequencyCache.shouldFilter(guide.guideId, guide.displayFrequency)) return;
|
|
5490
|
+
if (this.activeByGuideId.has(guide.guideId)) return;
|
|
5491
|
+
if (this.armedTriggers.has(guide.guideId)) return;
|
|
5492
|
+
const selector = guide.activationRules.selector;
|
|
5493
|
+
const eventName = guide.activationRules.trigger === "on_hover" ? "mouseover" : "click";
|
|
5494
|
+
const onFire = (e) => {
|
|
5495
|
+
const target = e.target;
|
|
5496
|
+
if (!(target instanceof Element)) return;
|
|
5497
|
+
try {
|
|
5498
|
+
if (!target.closest(selector)) return;
|
|
5499
|
+
} catch {
|
|
5500
|
+
return;
|
|
5501
|
+
}
|
|
5502
|
+
disarm();
|
|
5503
|
+
void this.showGuide(guide, endUserId, sessionId, pageUrl);
|
|
5504
|
+
};
|
|
5505
|
+
const disarm = () => {
|
|
5506
|
+
document.removeEventListener(eventName, onFire, true);
|
|
5507
|
+
this.armedTriggers.delete(guide.guideId);
|
|
5508
|
+
};
|
|
5509
|
+
document.addEventListener(eventName, onFire, true);
|
|
5510
|
+
this.armedTriggers.set(guide.guideId, disarm);
|
|
5511
|
+
if (this.debug)
|
|
5512
|
+
console.log(`[veo] guides: armed ${eventName} trigger for ${guide.guideId} on ${selector}`);
|
|
5513
|
+
}
|
|
5514
|
+
/** Desarma todos los disparadores por interacción pendientes. */
|
|
5515
|
+
disarmTriggers() {
|
|
5516
|
+
for (const disarm of this.armedTriggers.values()) disarm();
|
|
5517
|
+
this.armedTriggers.clear();
|
|
5413
5518
|
}
|
|
5414
5519
|
/**
|
|
5415
5520
|
* `resolve` con cache de corta duración + coalescing:
|
|
@@ -5460,6 +5565,7 @@ ${pageUrl}`;
|
|
|
5460
5565
|
this.activeWalkthroughRenderer = null;
|
|
5461
5566
|
this.activeWalkthroughGuide = null;
|
|
5462
5567
|
}
|
|
5568
|
+
this.disarmTriggers();
|
|
5463
5569
|
this.dispatched.clear();
|
|
5464
5570
|
this.resolveCache = null;
|
|
5465
5571
|
this.inflightResolve = null;
|
|
@@ -5492,8 +5598,11 @@ ${pageUrl}`;
|
|
|
5492
5598
|
this.client.track(eventName, properties);
|
|
5493
5599
|
};
|
|
5494
5600
|
const onFormSubmit = (answers) => this.submitFormResponse(guide.guideId, answers);
|
|
5601
|
+
const onOpenGuide = (targetGuideId) => {
|
|
5602
|
+
void this.openGuideById(targetGuideId, sessionId, pageUrl);
|
|
5603
|
+
};
|
|
5495
5604
|
try {
|
|
5496
|
-
void renderer.render({ guide, onInteraction, onClose, onTrack, onFormSubmit });
|
|
5605
|
+
void renderer.render({ guide, onInteraction, onClose, onTrack, onFormSubmit, onOpenGuide });
|
|
5497
5606
|
} catch (err) {
|
|
5498
5607
|
if (this.debug) console.error("[veo] renderer.render threw:", err);
|
|
5499
5608
|
this.activeRenderers.delete(renderer);
|
|
@@ -5502,6 +5611,28 @@ ${pageUrl}`;
|
|
|
5502
5611
|
}
|
|
5503
5612
|
}
|
|
5504
5613
|
}
|
|
5614
|
+
/**
|
|
5615
|
+
* Abre una guía POR ID, disparada desde el botón de otra guía (encadenado).
|
|
5616
|
+
* Ignora las URL rules y el trigger (el autor lo pidió explícitamente desde
|
|
5617
|
+
* un botón); respeta el dedupe de guías activas y el flujo normal de
|
|
5618
|
+
* tracking. 404/red → no-op (la guía destino pudo borrarse).
|
|
5619
|
+
*/
|
|
5620
|
+
async openGuideById(guideId, sessionId, pageUrl) {
|
|
5621
|
+
if (this.activeByGuideId.has(guideId)) return;
|
|
5622
|
+
const guide = await this.resolver.fetchById(guideId);
|
|
5623
|
+
if (!guide) {
|
|
5624
|
+
if (this.debug) console.warn(`[veo] guides: chained guide ${guideId} not found`);
|
|
5625
|
+
return;
|
|
5626
|
+
}
|
|
5627
|
+
const endUserId = this.client.getEndUserId() ?? this.client.getAnonymousId();
|
|
5628
|
+
if (guide.guideType === "walkthrough" && guide.guideSteps.length > 1) {
|
|
5629
|
+
if (!this.walkthroughState.hasActive()) {
|
|
5630
|
+
await this.startWalkthrough(guide, endUserId, sessionId, pageUrl);
|
|
5631
|
+
}
|
|
5632
|
+
return;
|
|
5633
|
+
}
|
|
5634
|
+
this.runSingleStepRender(guide, sessionId, pageUrl);
|
|
5635
|
+
}
|
|
5505
5636
|
/**
|
|
5506
5637
|
* Si hay un walkthrough persistido, intenta pintar el step actual en
|
|
5507
5638
|
* la página actual. Retorna `true` si lo intentó (sea éxito o cancel),
|