veo-sdk 0.5.5 → 0.5.10
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-2TBF3NZF.mjs +5 -0
- package/dist/{builder-O2QHV2DV.mjs.map → builder-2TBF3NZF.mjs.map} +1 -1
- package/dist/builder.cjs +544 -75
- 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-JPA46JBS.mjs → chunk-END325ZM.mjs} +547 -78
- package/dist/chunk-END325ZM.mjs.map +1 -0
- package/dist/{chunk-GKJW5TOZ.mjs → chunk-RO5IHBTJ.mjs} +123 -3
- package/dist/chunk-RO5IHBTJ.mjs.map +1 -0
- package/dist/{chunk-XPB4DL2Y.mjs → chunk-S2CLUAAC.mjs} +3 -3
- package/dist/{chunk-XPB4DL2Y.mjs.map → chunk-S2CLUAAC.mjs.map} +1 -1
- package/dist/{guide-preview-B912Y6UY.d.cts → guide-preview-XUnTmzUO.d.cts} +22 -4
- package/dist/{guide-preview-B912Y6UY.d.ts → guide-preview-XUnTmzUO.d.ts} +22 -4
- package/dist/index.cjs +691 -83
- 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 +39 -10
- package/dist/veo-builder.js.map +1 -1
- package/dist/veo-guides.js +34 -5
- package/dist/veo-guides.js.map +1 -1
- package/package.json +1 -1
- package/dist/builder-O2QHV2DV.mjs +0 -5
- package/dist/chunk-GKJW5TOZ.mjs.map +0 -1
- package/dist/chunk-JPA46JBS.mjs.map +0 -1
|
@@ -436,7 +436,8 @@ function buildButtonBlock(block, doc, callbacks) {
|
|
|
436
436
|
btn.textContent = typeof block.text === "string" && block.text ? block.text : "OK";
|
|
437
437
|
applyBlockStyle(btn, block.style, "button");
|
|
438
438
|
btn.addEventListener("click", () => {
|
|
439
|
-
const
|
|
439
|
+
const raw = block.action ?? "dismiss";
|
|
440
|
+
const action = raw === "next" || raw === "url" || raw === "guide" ? raw : "dismiss";
|
|
440
441
|
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;
|
|
441
442
|
const meta = {
|
|
442
443
|
...typeof block.id === "string" && block.id ? { buttonId: block.id } : {},
|
|
@@ -482,6 +483,42 @@ function applyBlockStyle(el, style, kind) {
|
|
|
482
483
|
if (typeof s.marginBottom === "number" && Number.isFinite(s.marginBottom)) {
|
|
483
484
|
el.style.marginBottom = `${clampNum(s.marginBottom, 0, 64)}px`;
|
|
484
485
|
}
|
|
486
|
+
if (kind !== "image") {
|
|
487
|
+
if (typeof s.fontSize === "number" && Number.isFinite(s.fontSize)) {
|
|
488
|
+
el.style.fontSize = `${clampNum(s.fontSize, 8, 96)}px`;
|
|
489
|
+
}
|
|
490
|
+
if (typeof s.fontFamily === "string" && s.fontFamily && s.fontFamily !== "inherit") {
|
|
491
|
+
el.style.fontFamily = s.fontFamily;
|
|
492
|
+
}
|
|
493
|
+
if (typeof s.fontWeight === "string" && s.fontWeight) el.style.fontWeight = s.fontWeight;
|
|
494
|
+
if (typeof s.textTransform === "string" && s.textTransform && s.textTransform !== "none") {
|
|
495
|
+
el.style.textTransform = s.textTransform;
|
|
496
|
+
}
|
|
497
|
+
if (typeof s.lineHeight === "number" && Number.isFinite(s.lineHeight)) {
|
|
498
|
+
el.style.lineHeight = `${clampNum(s.lineHeight, 50, 300)}%`;
|
|
499
|
+
}
|
|
500
|
+
if (typeof s.letterSpacing === "number" && Number.isFinite(s.letterSpacing)) {
|
|
501
|
+
el.style.letterSpacing = `${clampNum(s.letterSpacing, -5, 20)}px`;
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
if (typeof s.background === "string" && s.background) el.style.background = s.background;
|
|
505
|
+
if (typeof s.borderWidth === "number" && s.borderWidth > 0) {
|
|
506
|
+
const bc = typeof s.borderColor === "string" && s.borderColor ? s.borderColor : "#bbbbbb";
|
|
507
|
+
el.style.border = `${clampNum(s.borderWidth, 0, 20)}px solid ${bc}`;
|
|
508
|
+
}
|
|
509
|
+
if (kind !== "image" && typeof s.radius === "number" && Number.isFinite(s.radius)) {
|
|
510
|
+
el.style.borderRadius = `${clampNum(s.radius, 0, 64)}px`;
|
|
511
|
+
}
|
|
512
|
+
for (const side of ["Top", "Right", "Bottom", "Left"]) {
|
|
513
|
+
const p = s[`padding${side}`];
|
|
514
|
+
if (typeof p === "number" && Number.isFinite(p)) {
|
|
515
|
+
el.style.setProperty(`padding-${side.toLowerCase()}`, `${clampNum(p, 0, 128)}px`);
|
|
516
|
+
}
|
|
517
|
+
const m = s[`margin${side}`];
|
|
518
|
+
if (typeof m === "number" && Number.isFinite(m)) {
|
|
519
|
+
el.style.setProperty(`margin-${side.toLowerCase()}`, `${clampNum(m, 0, 128)}px`);
|
|
520
|
+
}
|
|
521
|
+
}
|
|
485
522
|
}
|
|
486
523
|
function createCloseButton(doc, onClose, className = "veo-guide-close") {
|
|
487
524
|
const closeBtn = doc.createElement("button");
|
|
@@ -832,6 +869,35 @@ var GUIDE_STYLES = `
|
|
|
832
869
|
animation: veo-fade-in 160ms ease-out;
|
|
833
870
|
}
|
|
834
871
|
|
|
872
|
+
/* \u2500\u2500 Modelo unificado (composite) \u2500\u2500 */
|
|
873
|
+
.veo-composite-overlay {
|
|
874
|
+
position: fixed; inset: 0;
|
|
875
|
+
z-index: ${GUIDE_Z_INDEX};
|
|
876
|
+
pointer-events: none;
|
|
877
|
+
}
|
|
878
|
+
/* Backdrop atenuado (solo centro con backdrop activo). */
|
|
879
|
+
.veo-composite-overlay--dim {
|
|
880
|
+
background: rgba(0, 0, 0, 0.5);
|
|
881
|
+
pointer-events: auto;
|
|
882
|
+
}
|
|
883
|
+
.veo-composite-anchored {
|
|
884
|
+
position: fixed;
|
|
885
|
+
z-index: ${GUIDE_Z_INDEX};
|
|
886
|
+
}
|
|
887
|
+
/* Card gen\xE9rica del modelo unificado. El dise\xF1o (bg/borde/padding/\u2026) lo aplica
|
|
888
|
+
el renderer como estilos inline desde step.design; ac\xE1 van los defaults. */
|
|
889
|
+
.veo-card {
|
|
890
|
+
pointer-events: auto;
|
|
891
|
+
background: var(--veo-bg, #ffffff);
|
|
892
|
+
color: var(--veo-text, #1f2937);
|
|
893
|
+
border-radius: var(--veo-radius, 12px);
|
|
894
|
+
padding: 20px;
|
|
895
|
+
max-width: 90vw;
|
|
896
|
+
box-shadow: var(--veo-shadow, 0 12px 40px rgba(0, 0, 0, 0.18));
|
|
897
|
+
animation: veo-fade-in 160ms ease-out;
|
|
898
|
+
}
|
|
899
|
+
.veo-composite-anchored .veo-card, .veo-composite-overlay .veo-card { position: relative; }
|
|
900
|
+
|
|
835
901
|
.veo-guide-content {
|
|
836
902
|
position: relative;
|
|
837
903
|
display: flex; flex-direction: column;
|
|
@@ -1794,85 +1860,53 @@ function escapeClosing(code, tag) {
|
|
|
1794
1860
|
return code.replace(rx, `<\\/${tag}`);
|
|
1795
1861
|
}
|
|
1796
1862
|
|
|
1797
|
-
// src/plugins/guides/
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
async render(context) {
|
|
1803
|
-
const step = context.guide.guideSteps[0];
|
|
1804
|
-
if (!step || typeof step.html !== "string" || step.html.length === 0) return;
|
|
1805
|
-
const placement = step.placement ?? DEFAULT_PLACEMENT;
|
|
1806
|
-
let anchor = null;
|
|
1807
|
-
if (placement.mode === "anchored") {
|
|
1808
|
-
const selector = placement.selector ?? step.selector ?? context.guide.activationRules.selector;
|
|
1809
|
-
if (typeof selector !== "string" || selector.length === 0) return;
|
|
1810
|
-
anchor = await waitForElement(selector);
|
|
1811
|
-
if (!anchor) return;
|
|
1812
|
-
}
|
|
1813
|
-
const { root } = this.createHost();
|
|
1814
|
-
const doc = root.ownerDocument ?? document;
|
|
1863
|
+
// src/plugins/guides/code-block.ts
|
|
1864
|
+
function mountCodeBlock(block, doc, context) {
|
|
1865
|
+
if (block.sandboxed) {
|
|
1866
|
+
const step = { html: block.html ?? "", css: block.css, js: block.js };
|
|
1867
|
+
const { iframe, cleanup } = mountCustomFrame(doc, step, context, { width: "100%" });
|
|
1815
1868
|
const wrapper = doc.createElement("div");
|
|
1816
|
-
wrapper.className =
|
|
1817
|
-
const { iframe, cleanup } = mountCustomFrame(doc, step, context, {
|
|
1818
|
-
width: toCssSize(placement.width ?? DEFAULT_WIDTH),
|
|
1819
|
-
fixedHeight: placement.height ?? null
|
|
1820
|
-
});
|
|
1821
|
-
this.registerCleanup(cleanup);
|
|
1869
|
+
wrapper.className = "veo-code-sandbox";
|
|
1822
1870
|
wrapper.appendChild(iframe);
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1871
|
+
return { node: wrapper, cleanup };
|
|
1872
|
+
}
|
|
1873
|
+
const hostDoc = doc;
|
|
1874
|
+
const injected = [];
|
|
1875
|
+
if (typeof block.css === "string" && block.css.trim()) {
|
|
1876
|
+
const style = hostDoc.createElement("style");
|
|
1877
|
+
style.textContent = block.css;
|
|
1878
|
+
hostDoc.head.appendChild(style);
|
|
1879
|
+
injected.push(style);
|
|
1880
|
+
}
|
|
1881
|
+
let node = null;
|
|
1882
|
+
if (typeof block.html === "string" && block.html.trim()) {
|
|
1883
|
+
node = doc.createElement("div");
|
|
1884
|
+
node.className = "veo-code-html";
|
|
1885
|
+
node.innerHTML = block.html;
|
|
1886
|
+
for (const old of Array.from(node.querySelectorAll("script"))) {
|
|
1887
|
+
injected.push(runScript(old, hostDoc));
|
|
1888
|
+
old.remove();
|
|
1828
1889
|
}
|
|
1829
|
-
context.onInteraction({ guideId: context.guide.guideId, stepIndex: 0, action: "shown" });
|
|
1830
|
-
}
|
|
1831
|
-
async setupAnchoredPosition(anchor, wrapper, placement) {
|
|
1832
|
-
const side = placement.side ?? "bottom";
|
|
1833
|
-
const update = async () => {
|
|
1834
|
-
const { x, y } = await computePosition(anchor, wrapper, {
|
|
1835
|
-
placement: side,
|
|
1836
|
-
strategy: "fixed",
|
|
1837
|
-
middleware: [offset(placement.offsetY ?? 8), flip(), shift({ padding: 8 })]
|
|
1838
|
-
});
|
|
1839
|
-
wrapper.style.left = `${x}px`;
|
|
1840
|
-
wrapper.style.top = `${y}px`;
|
|
1841
|
-
};
|
|
1842
|
-
await update();
|
|
1843
|
-
const reposition = () => {
|
|
1844
|
-
void update();
|
|
1845
|
-
};
|
|
1846
|
-
window.addEventListener("scroll", reposition, true);
|
|
1847
|
-
window.addEventListener("resize", reposition);
|
|
1848
|
-
return () => {
|
|
1849
|
-
window.removeEventListener("scroll", reposition, true);
|
|
1850
|
-
window.removeEventListener("resize", reposition);
|
|
1851
|
-
};
|
|
1852
|
-
}
|
|
1853
|
-
};
|
|
1854
|
-
function applyFloatingPosition(wrapper, placement) {
|
|
1855
|
-
const position = placement.position ?? "bottom-right";
|
|
1856
|
-
const ox = `${placement.offsetX ?? DEFAULT_OFFSET}px`;
|
|
1857
|
-
const oy = `${placement.offsetY ?? DEFAULT_OFFSET}px`;
|
|
1858
|
-
const s = wrapper.style;
|
|
1859
|
-
if (position === "center") {
|
|
1860
|
-
s.top = "50%";
|
|
1861
|
-
s.left = "50%";
|
|
1862
|
-
s.transform = "translate(-50%, -50%)";
|
|
1863
|
-
return;
|
|
1864
1890
|
}
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
s
|
|
1870
|
-
} else if (horizontal === "right") {
|
|
1871
|
-
s.right = ox;
|
|
1872
|
-
} else {
|
|
1873
|
-
s.left = "50%";
|
|
1874
|
-
s.transform = "translateX(-50%)";
|
|
1891
|
+
if (typeof block.js === "string" && block.js.trim()) {
|
|
1892
|
+
const s = hostDoc.createElement("script");
|
|
1893
|
+
s.textContent = block.js;
|
|
1894
|
+
hostDoc.body.appendChild(s);
|
|
1895
|
+
injected.push(s);
|
|
1875
1896
|
}
|
|
1897
|
+
return {
|
|
1898
|
+
node,
|
|
1899
|
+
cleanup: () => {
|
|
1900
|
+
for (const n of injected) n.parentNode?.removeChild(n);
|
|
1901
|
+
}
|
|
1902
|
+
};
|
|
1903
|
+
}
|
|
1904
|
+
function runScript(old, hostDoc) {
|
|
1905
|
+
const s = hostDoc.createElement("script");
|
|
1906
|
+
for (const attr of Array.from(old.attributes)) s.setAttribute(attr.name, attr.value);
|
|
1907
|
+
if (!old.src) s.textContent = old.textContent;
|
|
1908
|
+
hostDoc.body.appendChild(s);
|
|
1909
|
+
return s;
|
|
1876
1910
|
}
|
|
1877
1911
|
|
|
1878
1912
|
// src/plugins/guides/form-content.ts
|
|
@@ -2140,6 +2174,430 @@ function buildScale(wrapper, doc, min, max, btnClass, symbol) {
|
|
|
2140
2174
|
return { wrapper, read: () => selected };
|
|
2141
2175
|
}
|
|
2142
2176
|
|
|
2177
|
+
// src/plugins/guides/renderers/composite-renderer.ts
|
|
2178
|
+
var CompositeRenderer = class extends BaseRenderer {
|
|
2179
|
+
async render(context) {
|
|
2180
|
+
const idx = context.nav?.stepIndex ?? 0;
|
|
2181
|
+
const step = context.guide.guideSteps[idx];
|
|
2182
|
+
if (!step) return;
|
|
2183
|
+
const anchorSelector = step.position === "relative-to-element" || step.presentation === "inline" ? step.anchorSelector?.trim() || void 0 : void 0;
|
|
2184
|
+
let anchor = null;
|
|
2185
|
+
if (anchorSelector) {
|
|
2186
|
+
anchor = await waitForElement(anchorSelector);
|
|
2187
|
+
if (!anchor) return;
|
|
2188
|
+
}
|
|
2189
|
+
const { host, root } = this.createHost();
|
|
2190
|
+
const doc = root.ownerDocument ?? document;
|
|
2191
|
+
const design = step.design ?? {};
|
|
2192
|
+
if (typeof design.zIndex === "number") host.style.zIndex = String(design.zIndex);
|
|
2193
|
+
const card = doc.createElement("div");
|
|
2194
|
+
card.className = "veo-card";
|
|
2195
|
+
applyCompositeDesign(card, design);
|
|
2196
|
+
const dismiss = (action, meta) => {
|
|
2197
|
+
context.onInteraction({
|
|
2198
|
+
guideId: context.guide.guideId,
|
|
2199
|
+
stepIndex: idx,
|
|
2200
|
+
action,
|
|
2201
|
+
...{}
|
|
2202
|
+
});
|
|
2203
|
+
};
|
|
2204
|
+
const readers = [];
|
|
2205
|
+
this.buildContent(card, step.blocks ?? [], doc, context, idx, readers);
|
|
2206
|
+
if (design.closeButton !== false) {
|
|
2207
|
+
const closeBtn = createCloseButton(doc, () => {
|
|
2208
|
+
dismiss("dismissed");
|
|
2209
|
+
this.closeOrSkip(context);
|
|
2210
|
+
});
|
|
2211
|
+
const closeColor = typeof design.closeColor === "string" ? design.closeColor : null;
|
|
2212
|
+
const hoverColor = typeof design.closeHoverColor === "string" ? design.closeHoverColor : null;
|
|
2213
|
+
if (closeColor) closeBtn.style.color = closeColor;
|
|
2214
|
+
if (hoverColor) {
|
|
2215
|
+
closeBtn.addEventListener("mouseenter", () => {
|
|
2216
|
+
closeBtn.style.color = hoverColor;
|
|
2217
|
+
});
|
|
2218
|
+
closeBtn.addEventListener("mouseleave", () => {
|
|
2219
|
+
closeBtn.style.color = closeColor ?? "";
|
|
2220
|
+
});
|
|
2221
|
+
}
|
|
2222
|
+
card.appendChild(closeBtn);
|
|
2223
|
+
}
|
|
2224
|
+
if (step.presentation === "inline" && anchor) {
|
|
2225
|
+
host.style.display = "block";
|
|
2226
|
+
const pos = inlinePosOf(step.inlinePosition);
|
|
2227
|
+
root.appendChild(card);
|
|
2228
|
+
insertHost(anchor, host, pos);
|
|
2229
|
+
this.registerCleanup(keepHostAttached(host, anchorSelector, pos));
|
|
2230
|
+
} else if (step.position === "relative-to-element" && anchor) {
|
|
2231
|
+
if (design.backdrop === true) {
|
|
2232
|
+
const bg = doc.createElement("div");
|
|
2233
|
+
bg.className = "veo-composite-overlay veo-composite-overlay--dim";
|
|
2234
|
+
if (typeof design.backdropColor === "string") bg.style.background = design.backdropColor;
|
|
2235
|
+
const bz = typeof design.backdropZIndex === "number" ? design.backdropZIndex : 2e5;
|
|
2236
|
+
bg.style.zIndex = String(bz);
|
|
2237
|
+
root.appendChild(bg);
|
|
2238
|
+
if (design.targetAbove === true) this.registerCleanup(liftTarget(anchor, bz + 1));
|
|
2239
|
+
}
|
|
2240
|
+
const wrapper = doc.createElement("div");
|
|
2241
|
+
wrapper.className = "veo-composite-anchored";
|
|
2242
|
+
const caretEl = design.caret === false ? null : makeCaret(doc, design);
|
|
2243
|
+
if (caretEl) wrapper.appendChild(caretEl);
|
|
2244
|
+
wrapper.appendChild(card);
|
|
2245
|
+
root.appendChild(wrapper);
|
|
2246
|
+
this.registerCleanup(await anchorPosition(anchor, wrapper, caretEl));
|
|
2247
|
+
} else {
|
|
2248
|
+
const overlay = doc.createElement("div");
|
|
2249
|
+
overlay.className = "veo-composite-overlay";
|
|
2250
|
+
if (step.position === "center" && design.backdrop !== false) {
|
|
2251
|
+
overlay.classList.add("veo-composite-overlay--dim");
|
|
2252
|
+
if (typeof design.backdropColor === "string") {
|
|
2253
|
+
overlay.style.background = design.backdropColor;
|
|
2254
|
+
}
|
|
2255
|
+
if (typeof design.backdropZIndex === "number") {
|
|
2256
|
+
overlay.style.zIndex = String(design.backdropZIndex);
|
|
2257
|
+
}
|
|
2258
|
+
overlay.addEventListener("click", (e) => {
|
|
2259
|
+
if (e.target === overlay) {
|
|
2260
|
+
dismiss("dismissed");
|
|
2261
|
+
this.closeOrSkip(context);
|
|
2262
|
+
}
|
|
2263
|
+
});
|
|
2264
|
+
}
|
|
2265
|
+
applyViewportPosition(card, step.position, design);
|
|
2266
|
+
overlay.appendChild(card);
|
|
2267
|
+
root.appendChild(overlay);
|
|
2268
|
+
}
|
|
2269
|
+
context.onInteraction({ guideId: context.guide.guideId, stepIndex: idx, action: "shown" });
|
|
2270
|
+
}
|
|
2271
|
+
/** Recorre los bloques en orden y los pinta en la card. */
|
|
2272
|
+
buildContent(card, blocks, doc, context, idx, readers) {
|
|
2273
|
+
const emit = (block) => {
|
|
2274
|
+
context.onInteraction({
|
|
2275
|
+
guideId: context.guide.guideId,
|
|
2276
|
+
stepIndex: idx,
|
|
2277
|
+
action: "cta_clicked",
|
|
2278
|
+
...block.id ? { metadata: { buttonId: block.id } } : {}
|
|
2279
|
+
});
|
|
2280
|
+
};
|
|
2281
|
+
let i = 0;
|
|
2282
|
+
while (i < blocks.length) {
|
|
2283
|
+
const b = blocks[i];
|
|
2284
|
+
if (!b) {
|
|
2285
|
+
i++;
|
|
2286
|
+
continue;
|
|
2287
|
+
}
|
|
2288
|
+
if (b.type === "button") {
|
|
2289
|
+
const row = doc.createElement("div");
|
|
2290
|
+
row.className = "veo-guide-actions";
|
|
2291
|
+
while (i < blocks.length && blocks[i]?.type === "button") {
|
|
2292
|
+
row.appendChild(
|
|
2293
|
+
this.buildButton(blocks[i], doc, context, idx, readers, emit)
|
|
2294
|
+
);
|
|
2295
|
+
i++;
|
|
2296
|
+
}
|
|
2297
|
+
card.appendChild(row);
|
|
2298
|
+
continue;
|
|
2299
|
+
}
|
|
2300
|
+
if (b.type === "code") {
|
|
2301
|
+
const { node: node2, cleanup } = mountCodeBlock(b, doc, context);
|
|
2302
|
+
if (node2) card.appendChild(node2);
|
|
2303
|
+
this.registerCleanup(cleanup);
|
|
2304
|
+
i++;
|
|
2305
|
+
continue;
|
|
2306
|
+
}
|
|
2307
|
+
if (b.type === "form") {
|
|
2308
|
+
const form = doc.createElement("div");
|
|
2309
|
+
form.className = "veo-form";
|
|
2310
|
+
for (const field of b.fields ?? []) {
|
|
2311
|
+
const { wrapper, read } = buildField(field, doc);
|
|
2312
|
+
readers.push({ field, read });
|
|
2313
|
+
form.appendChild(wrapper);
|
|
2314
|
+
}
|
|
2315
|
+
card.appendChild(form);
|
|
2316
|
+
i++;
|
|
2317
|
+
continue;
|
|
2318
|
+
}
|
|
2319
|
+
const node = buildContentBlock(b, doc);
|
|
2320
|
+
if (node) card.appendChild(node);
|
|
2321
|
+
i++;
|
|
2322
|
+
}
|
|
2323
|
+
}
|
|
2324
|
+
/** Botón con enrutado de acción (navegación / cierre / url / guía / envío de forms). */
|
|
2325
|
+
buildButton(block, doc, context, idx, readers, emit) {
|
|
2326
|
+
const btn = doc.createElement("button");
|
|
2327
|
+
btn.type = "button";
|
|
2328
|
+
btn.className = "veo-guide-cta";
|
|
2329
|
+
btn.textContent = block.text?.trim() || "OK";
|
|
2330
|
+
const nav = context.nav?.callbacks;
|
|
2331
|
+
btn.addEventListener("click", () => {
|
|
2332
|
+
switch (block.action) {
|
|
2333
|
+
case "next":
|
|
2334
|
+
emit(block);
|
|
2335
|
+
if (nav) nav.onNext();
|
|
2336
|
+
else context.onClose();
|
|
2337
|
+
break;
|
|
2338
|
+
case "prev":
|
|
2339
|
+
emit(block);
|
|
2340
|
+
nav?.onBack();
|
|
2341
|
+
break;
|
|
2342
|
+
case "url":
|
|
2343
|
+
emit(block);
|
|
2344
|
+
if (typeof block.url === "string" && isSafeUrl(block.url)) {
|
|
2345
|
+
window.open(block.url, "_blank", "noopener,noreferrer");
|
|
2346
|
+
}
|
|
2347
|
+
break;
|
|
2348
|
+
case "guide":
|
|
2349
|
+
emit(block);
|
|
2350
|
+
if (block.targetGuideId) context.onOpenGuide?.(block.targetGuideId);
|
|
2351
|
+
this.closeOrSkip(context);
|
|
2352
|
+
break;
|
|
2353
|
+
case "submit-forms":
|
|
2354
|
+
case "submit-forms-advance":
|
|
2355
|
+
case "submit-forms-goto":
|
|
2356
|
+
this.submitForms(readers, context, idx, btn, () => {
|
|
2357
|
+
emit(block);
|
|
2358
|
+
if (block.action === "submit-forms" || !nav) {
|
|
2359
|
+
context.onClose();
|
|
2360
|
+
} else if (block.action === "submit-forms-goto" && typeof block.targetStep === "number" && nav.onGoto) {
|
|
2361
|
+
nav.onGoto(block.targetStep);
|
|
2362
|
+
} else {
|
|
2363
|
+
nav.onNext();
|
|
2364
|
+
}
|
|
2365
|
+
});
|
|
2366
|
+
break;
|
|
2367
|
+
default:
|
|
2368
|
+
emit(block);
|
|
2369
|
+
this.closeOrSkip(context);
|
|
2370
|
+
}
|
|
2371
|
+
});
|
|
2372
|
+
return btn;
|
|
2373
|
+
}
|
|
2374
|
+
/** Recoge respuestas de todos los form-blocks del paso, valida y envía. */
|
|
2375
|
+
submitForms(readers, context, idx, btn, onDone) {
|
|
2376
|
+
const answers = {};
|
|
2377
|
+
for (const { field, read } of readers) {
|
|
2378
|
+
const value = read();
|
|
2379
|
+
const empty = value === void 0 || value === null || value === "";
|
|
2380
|
+
if (empty) {
|
|
2381
|
+
if (field.required) {
|
|
2382
|
+
btn.textContent = `Completa "${field.label}"`;
|
|
2383
|
+
return;
|
|
2384
|
+
}
|
|
2385
|
+
continue;
|
|
2386
|
+
}
|
|
2387
|
+
answers[field.key] = value;
|
|
2388
|
+
}
|
|
2389
|
+
if (readers.length > 0 && Object.keys(answers).length === 0) return;
|
|
2390
|
+
btn.disabled = true;
|
|
2391
|
+
const submitFn = context.onFormSubmit ?? (() => Promise.resolve(true));
|
|
2392
|
+
void submitFn(answers).then((ok) => {
|
|
2393
|
+
btn.disabled = false;
|
|
2394
|
+
if (!ok) return;
|
|
2395
|
+
context.onInteraction({
|
|
2396
|
+
guideId: context.guide.guideId,
|
|
2397
|
+
stepIndex: idx,
|
|
2398
|
+
action: "completed"
|
|
2399
|
+
});
|
|
2400
|
+
onDone();
|
|
2401
|
+
});
|
|
2402
|
+
}
|
|
2403
|
+
closeOrSkip(context) {
|
|
2404
|
+
if (context.nav?.callbacks) context.nav.callbacks.onSkip();
|
|
2405
|
+
else context.onClose();
|
|
2406
|
+
}
|
|
2407
|
+
};
|
|
2408
|
+
function inlinePosOf(p) {
|
|
2409
|
+
return p === "before" || p === "prepend" || p === "append" ? p : "after";
|
|
2410
|
+
}
|
|
2411
|
+
function applyViewportPosition(card, position, design) {
|
|
2412
|
+
const s = card.style;
|
|
2413
|
+
s.position = "fixed";
|
|
2414
|
+
const M = "16px";
|
|
2415
|
+
const hAlign = design.hAlign === "left" ? "left" : design.hAlign === "right" ? "right" : null;
|
|
2416
|
+
const v = position.includes("top") ? "top" : position.includes("bottom") ? "bottom" : "middle";
|
|
2417
|
+
const h = hAlign ?? (position.includes("left") ? "left" : position.includes("right") ? "right" : "middle");
|
|
2418
|
+
if (v === "top") s.top = M;
|
|
2419
|
+
else if (v === "bottom") s.bottom = M;
|
|
2420
|
+
else s.top = "50%";
|
|
2421
|
+
if (h === "left") s.left = M;
|
|
2422
|
+
else if (h === "right") s.right = M;
|
|
2423
|
+
else s.left = "50%";
|
|
2424
|
+
const tx = h === "middle" ? "-50%" : "0";
|
|
2425
|
+
const ty = v === "middle" ? "-50%" : "0";
|
|
2426
|
+
s.transform = tx === "0" && ty === "0" ? "" : `translate(${tx}, ${ty})`;
|
|
2427
|
+
}
|
|
2428
|
+
function makeCaret(doc, design) {
|
|
2429
|
+
const caret = doc.createElement("div");
|
|
2430
|
+
caret.className = "veo-composite-caret";
|
|
2431
|
+
const w = typeof design.caretWidth === "number" ? design.caretWidth : 12;
|
|
2432
|
+
const h = typeof design.caretHeight === "number" ? design.caretHeight : 12;
|
|
2433
|
+
const s = caret.style;
|
|
2434
|
+
s.position = "absolute";
|
|
2435
|
+
s.width = `${w}px`;
|
|
2436
|
+
s.height = `${h}px`;
|
|
2437
|
+
s.transform = "rotate(45deg)";
|
|
2438
|
+
s.background = typeof design.background === "string" ? design.background : "#ffffff";
|
|
2439
|
+
if (typeof design.borderWidth === "number" && design.borderWidth > 0) {
|
|
2440
|
+
const bc = typeof design.borderColor === "string" ? design.borderColor : "#bbbbbb";
|
|
2441
|
+
s.border = `${design.borderWidth}px solid ${bc}`;
|
|
2442
|
+
}
|
|
2443
|
+
return caret;
|
|
2444
|
+
}
|
|
2445
|
+
function liftTarget(anchor, zIndex) {
|
|
2446
|
+
const el = anchor;
|
|
2447
|
+
const prevPosition = el.style.position;
|
|
2448
|
+
const prevZ = el.style.zIndex;
|
|
2449
|
+
if (getComputedStyle(el).position === "static") el.style.position = "relative";
|
|
2450
|
+
el.style.zIndex = String(zIndex);
|
|
2451
|
+
return () => {
|
|
2452
|
+
el.style.position = prevPosition;
|
|
2453
|
+
el.style.zIndex = prevZ;
|
|
2454
|
+
};
|
|
2455
|
+
}
|
|
2456
|
+
async function anchorPosition(anchor, wrapper, caret) {
|
|
2457
|
+
const update = async () => {
|
|
2458
|
+
const { x, y, placement, middlewareData } = await computePosition(anchor, wrapper, {
|
|
2459
|
+
placement: "bottom",
|
|
2460
|
+
strategy: "fixed",
|
|
2461
|
+
middleware: [
|
|
2462
|
+
offset(caret ? 10 : 8),
|
|
2463
|
+
flip(),
|
|
2464
|
+
shift({ padding: 8 }),
|
|
2465
|
+
...caret ? [arrow({ element: caret })] : []
|
|
2466
|
+
]
|
|
2467
|
+
});
|
|
2468
|
+
wrapper.style.left = `${x}px`;
|
|
2469
|
+
wrapper.style.top = `${y}px`;
|
|
2470
|
+
if (caret) positionArrow(caret, placement, middlewareData.arrow);
|
|
2471
|
+
};
|
|
2472
|
+
await update();
|
|
2473
|
+
const reposition = () => void update();
|
|
2474
|
+
window.addEventListener("scroll", reposition, true);
|
|
2475
|
+
window.addEventListener("resize", reposition);
|
|
2476
|
+
return () => {
|
|
2477
|
+
window.removeEventListener("scroll", reposition, true);
|
|
2478
|
+
window.removeEventListener("resize", reposition);
|
|
2479
|
+
};
|
|
2480
|
+
}
|
|
2481
|
+
function applyCompositeDesign(card, design) {
|
|
2482
|
+
const s = card.style;
|
|
2483
|
+
const px = (v) => typeof v === "number" && Number.isFinite(v) ? `${v}px` : null;
|
|
2484
|
+
const strv = (v) => typeof v === "string" && v ? v : null;
|
|
2485
|
+
if (strv(design.background)) s.background = design.background;
|
|
2486
|
+
const textColor = strv(design.color) ?? strv(design.textColor);
|
|
2487
|
+
if (textColor) s.color = textColor;
|
|
2488
|
+
if (px(design.fontSize)) s.fontSize = px(design.fontSize);
|
|
2489
|
+
if (strv(design.fontWeight)) s.fontWeight = design.fontWeight;
|
|
2490
|
+
if (strv(design.fontFamily) && design.fontFamily !== "inherit") {
|
|
2491
|
+
s.fontFamily = design.fontFamily;
|
|
2492
|
+
}
|
|
2493
|
+
if (strv(design.textTransform) && design.textTransform !== "none") {
|
|
2494
|
+
s.textTransform = design.textTransform;
|
|
2495
|
+
}
|
|
2496
|
+
if (typeof design.letterSpacing === "number") s.letterSpacing = `${design.letterSpacing}px`;
|
|
2497
|
+
if (strv(design.align)) s.textAlign = design.align;
|
|
2498
|
+
if (typeof design.lineHeight === "number") s.lineHeight = `${design.lineHeight}%`;
|
|
2499
|
+
if (px(design.radius)) s.borderRadius = px(design.radius);
|
|
2500
|
+
const bw = px(design.borderWidth);
|
|
2501
|
+
if (bw) s.border = `${bw} solid ${strv(design.borderColor) ?? "#e5e5e5"}`;
|
|
2502
|
+
if (strv(design.shadowColor) || typeof design.shadowBlur === "number") {
|
|
2503
|
+
const n = (k) => typeof design[k] === "number" ? design[k] : 0;
|
|
2504
|
+
s.boxShadow = `${n("shadowX")}px ${n("shadowY")}px ${n("shadowBlur")}px ${n("shadowSpread")}px ${strv(design.shadowColor) ?? "rgba(0,0,0,0.2)"}`;
|
|
2505
|
+
}
|
|
2506
|
+
if (design.fullWidth === true) {
|
|
2507
|
+
s.width = "100%";
|
|
2508
|
+
} else if (design.widthType === "fluid") {
|
|
2509
|
+
s.width = "auto";
|
|
2510
|
+
if (px(design.width)) s.maxWidth = px(design.width);
|
|
2511
|
+
} else if (px(design.width)) {
|
|
2512
|
+
s.width = px(design.width);
|
|
2513
|
+
}
|
|
2514
|
+
for (const side of ["Top", "Right", "Bottom", "Left"]) {
|
|
2515
|
+
const p = px(design[`padding${side}`]);
|
|
2516
|
+
if (p) s.setProperty(`padding-${side.toLowerCase()}`, p);
|
|
2517
|
+
const m = px(design[`margin${side}`]);
|
|
2518
|
+
if (m) s.setProperty(`margin-${side.toLowerCase()}`, m);
|
|
2519
|
+
}
|
|
2520
|
+
}
|
|
2521
|
+
var DEFAULT_PLACEMENT = { mode: "floating", position: "bottom-right" };
|
|
2522
|
+
var DEFAULT_OFFSET = 16;
|
|
2523
|
+
var DEFAULT_WIDTH = 360;
|
|
2524
|
+
var CustomRenderer = class extends BaseRenderer {
|
|
2525
|
+
async render(context) {
|
|
2526
|
+
const step = context.guide.guideSteps[0];
|
|
2527
|
+
if (!step || typeof step.html !== "string" || step.html.length === 0) return;
|
|
2528
|
+
const placement = step.placement ?? DEFAULT_PLACEMENT;
|
|
2529
|
+
let anchor = null;
|
|
2530
|
+
if (placement.mode === "anchored") {
|
|
2531
|
+
const selector = placement.selector ?? step.selector ?? context.guide.activationRules.selector;
|
|
2532
|
+
if (typeof selector !== "string" || selector.length === 0) return;
|
|
2533
|
+
anchor = await waitForElement(selector);
|
|
2534
|
+
if (!anchor) return;
|
|
2535
|
+
}
|
|
2536
|
+
const { root } = this.createHost();
|
|
2537
|
+
const doc = root.ownerDocument ?? document;
|
|
2538
|
+
const wrapper = doc.createElement("div");
|
|
2539
|
+
wrapper.className = placement.mode === "anchored" ? "veo-custom-anchored" : "veo-custom-floating";
|
|
2540
|
+
const { iframe, cleanup } = mountCustomFrame(doc, step, context, {
|
|
2541
|
+
width: toCssSize(placement.width ?? DEFAULT_WIDTH),
|
|
2542
|
+
fixedHeight: placement.height ?? null
|
|
2543
|
+
});
|
|
2544
|
+
this.registerCleanup(cleanup);
|
|
2545
|
+
wrapper.appendChild(iframe);
|
|
2546
|
+
root.appendChild(wrapper);
|
|
2547
|
+
if (placement.mode === "floating") {
|
|
2548
|
+
applyFloatingPosition(wrapper, placement);
|
|
2549
|
+
} else if (anchor) {
|
|
2550
|
+
this.registerCleanup(await this.setupAnchoredPosition(anchor, wrapper, placement));
|
|
2551
|
+
}
|
|
2552
|
+
context.onInteraction({ guideId: context.guide.guideId, stepIndex: 0, action: "shown" });
|
|
2553
|
+
}
|
|
2554
|
+
async setupAnchoredPosition(anchor, wrapper, placement) {
|
|
2555
|
+
const side = placement.side ?? "bottom";
|
|
2556
|
+
const update = async () => {
|
|
2557
|
+
const { x, y } = await computePosition(anchor, wrapper, {
|
|
2558
|
+
placement: side,
|
|
2559
|
+
strategy: "fixed",
|
|
2560
|
+
middleware: [offset(placement.offsetY ?? 8), flip(), shift({ padding: 8 })]
|
|
2561
|
+
});
|
|
2562
|
+
wrapper.style.left = `${x}px`;
|
|
2563
|
+
wrapper.style.top = `${y}px`;
|
|
2564
|
+
};
|
|
2565
|
+
await update();
|
|
2566
|
+
const reposition = () => {
|
|
2567
|
+
void update();
|
|
2568
|
+
};
|
|
2569
|
+
window.addEventListener("scroll", reposition, true);
|
|
2570
|
+
window.addEventListener("resize", reposition);
|
|
2571
|
+
return () => {
|
|
2572
|
+
window.removeEventListener("scroll", reposition, true);
|
|
2573
|
+
window.removeEventListener("resize", reposition);
|
|
2574
|
+
};
|
|
2575
|
+
}
|
|
2576
|
+
};
|
|
2577
|
+
function applyFloatingPosition(wrapper, placement) {
|
|
2578
|
+
const position = placement.position ?? "bottom-right";
|
|
2579
|
+
const ox = `${placement.offsetX ?? DEFAULT_OFFSET}px`;
|
|
2580
|
+
const oy = `${placement.offsetY ?? DEFAULT_OFFSET}px`;
|
|
2581
|
+
const s = wrapper.style;
|
|
2582
|
+
if (position === "center") {
|
|
2583
|
+
s.top = "50%";
|
|
2584
|
+
s.left = "50%";
|
|
2585
|
+
s.transform = "translate(-50%, -50%)";
|
|
2586
|
+
return;
|
|
2587
|
+
}
|
|
2588
|
+
const [vertical, horizontal] = position.split("-");
|
|
2589
|
+
if (vertical === "top") s.top = oy;
|
|
2590
|
+
else s.bottom = oy;
|
|
2591
|
+
if (horizontal === "left") {
|
|
2592
|
+
s.left = ox;
|
|
2593
|
+
} else if (horizontal === "right") {
|
|
2594
|
+
s.right = ox;
|
|
2595
|
+
} else {
|
|
2596
|
+
s.left = "50%";
|
|
2597
|
+
s.transform = "translateX(-50%)";
|
|
2598
|
+
}
|
|
2599
|
+
}
|
|
2600
|
+
|
|
2143
2601
|
// src/plugins/guides/renderers/form-renderer.ts
|
|
2144
2602
|
var FormRenderer = class extends BaseRenderer {
|
|
2145
2603
|
render(context) {
|
|
@@ -2520,6 +2978,13 @@ var GuidePreviewController = class {
|
|
|
2520
2978
|
this.input = input;
|
|
2521
2979
|
const guide = normalize(input);
|
|
2522
2980
|
const start = typeof input.startStepIndex === "number" ? input.startStepIndex : 0;
|
|
2981
|
+
if (guide.guideType === "composite") {
|
|
2982
|
+
const s = Math.min(Math.max(0, start), guide.guideSteps.length - 1);
|
|
2983
|
+
const active = guide.guideSteps[s];
|
|
2984
|
+
if (active) guide.guideSteps = [active];
|
|
2985
|
+
const ready2 = this.renderSingleStep(guide);
|
|
2986
|
+
return { close: () => this.close(), ready: ready2, host: () => this.activeHost() };
|
|
2987
|
+
}
|
|
2523
2988
|
const ready = guide.guideType === "walkthrough" ? this.startWalkthrough(guide, start) : this.renderSingleStep(guide);
|
|
2524
2989
|
return { close: () => this.close(), ready, host: () => this.activeHost() };
|
|
2525
2990
|
}
|
|
@@ -2699,8 +3164,12 @@ function createSingleStepRenderer(type) {
|
|
|
2699
3164
|
return new InlineFormRenderer();
|
|
2700
3165
|
case "badge":
|
|
2701
3166
|
return new BadgeRenderer();
|
|
3167
|
+
case "composite":
|
|
3168
|
+
return new CompositeRenderer();
|
|
2702
3169
|
case "walkthrough":
|
|
2703
3170
|
return null;
|
|
3171
|
+
default:
|
|
3172
|
+
return null;
|
|
2704
3173
|
}
|
|
2705
3174
|
}
|
|
2706
3175
|
function safeDestroy(renderer) {
|
|
@@ -2843,6 +3312,6 @@ function buildSelectorPath(element, maxAncestors = 5) {
|
|
|
2843
3312
|
return parts.join(" > ");
|
|
2844
3313
|
}
|
|
2845
3314
|
|
|
2846
|
-
export { ALWAYS_BLOCK_SELECTORS, BadgeRenderer, 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 };
|
|
2847
|
-
//# sourceMappingURL=chunk-
|
|
2848
|
-
//# sourceMappingURL=chunk-
|
|
3315
|
+
export { ALWAYS_BLOCK_SELECTORS, BadgeRenderer, BannerRenderer, CompositeRenderer, 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 };
|
|
3316
|
+
//# sourceMappingURL=chunk-END325ZM.mjs.map
|
|
3317
|
+
//# sourceMappingURL=chunk-END325ZM.mjs.map
|