veo-sdk 0.3.7 → 0.3.9

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.
@@ -227,11 +227,17 @@ function renderBlocks(container, blocks, doc, callbacks) {
227
227
  if (block?.type === "button") {
228
228
  const actions = doc.createElement("div");
229
229
  actions.className = "veo-guide-actions";
230
+ let rowAlign;
230
231
  while (i < blocks.length && blocks[i]?.type === "button") {
231
232
  const btnBlock = blocks[i];
233
+ if (!rowAlign) {
234
+ const a = btnBlock.style?.align;
235
+ if (a === "left" || a === "center" || a === "right") rowAlign = a;
236
+ }
232
237
  actions.appendChild(buildButtonBlock(btnBlock, doc, callbacks));
233
238
  i++;
234
239
  }
240
+ if (rowAlign) actions.style.justifyContent = BLOCK_ALIGN_SELF[rowAlign];
235
241
  container.appendChild(actions);
236
242
  continue;
237
243
  }
@@ -296,7 +302,7 @@ function applyBlockStyle(el, style, kind) {
296
302
  const align = typeof s.align === "string" ? s.align : null;
297
303
  if (align && (align === "left" || align === "center" || align === "right")) {
298
304
  if (kind === "text") el.style.textAlign = align;
299
- else el.style.alignSelf = BLOCK_ALIGN_SELF[align];
305
+ else if (kind === "image") el.style.alignSelf = BLOCK_ALIGN_SELF[align];
300
306
  }
301
307
  if (kind !== "image" && typeof s.color === "string") el.style.color = s.color;
302
308
  if (kind === "text" && typeof s.fontSize === "number" && Number.isFinite(s.fontSize)) {
@@ -634,6 +640,12 @@ var GUIDE_STYLES = `
634
640
  position: relative;
635
641
  display: flex; flex-direction: column;
636
642
  }
643
+ /* Reserva espacio para la \u2715 (esquina sup. derecha) SOLO en el primer bloque:
644
+ as\xED el texto alineado a la derecha no queda tapado por el bot\xF3n de cerrar. */
645
+ .veo-guide-content > .veo-guide-title:first-child,
646
+ .veo-guide-content > .veo-guide-text:first-child {
647
+ padding-right: 20px;
648
+ }
637
649
  .veo-guide-image {
638
650
  display: block;
639
651
  width: var(--veo-image-width, 100%);
@@ -800,21 +812,6 @@ var GUIDE_STYLES = `
800
812
  background: transparent;
801
813
  color-scheme: normal;
802
814
  }
803
- /*
804
- * X de cerrar de las gu\xEDas custom: el HTML del cliente vive en un iframe
805
- * sandbox, as\xED que el bot\xF3n lo pone el host POR ENCIMA del iframe. Con fondo
806
- * propio para ser visible sobre cualquier contenido.
807
- */
808
- .veo-custom-close {
809
- position: absolute; top: 6px; right: 6px; z-index: 1;
810
- width: 22px; height: 22px; padding: 0;
811
- display: flex; align-items: center; justify-content: center;
812
- font-size: 16px; line-height: 1; color: #6b7280;
813
- background: rgba(255, 255, 255, 0.92);
814
- border: 1px solid rgba(0, 0, 0, 0.08); border-radius: 50%;
815
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.14); cursor: pointer;
816
- }
817
- .veo-custom-close:hover { color: #111827; }
818
815
 
819
816
  @keyframes veo-fade-in { from { opacity: 0; } to { opacity: 1; } }
820
817
  @keyframes veo-slide-up {
@@ -988,7 +985,8 @@ function mountCustomFrame(doc, step, context, opts) {
988
985
  const token = uuidv7();
989
986
  const wantsTailwind = step.style?.tailwind === true;
990
987
  iframe.srcdoc = buildSrcdoc(step.html ?? "", step.css ?? "", step.js ?? "", token, {
991
- tokens: collectHostTokens(),
988
+ hostCss: collectHostStyles(),
989
+ htmlAttrs: hostHtmlAttrs(),
992
990
  tailwind: wantsTailwind
993
991
  });
994
992
  const close = () => context.onClose();
@@ -1039,25 +1037,40 @@ function mountCustomFrame(doc, step, context, opts) {
1039
1037
  function toCssSize(value) {
1040
1038
  return typeof value === "number" ? `${value}px` : value;
1041
1039
  }
1042
- function collectHostTokens() {
1043
- if (typeof window === "undefined" || typeof document === "undefined") return "";
1040
+ var MAX_HOST_CSS = 800 * 1024;
1041
+ function collectHostStyles() {
1042
+ if (typeof document === "undefined") return "";
1043
+ let out = "";
1044
1044
  try {
1045
- const rootStyle = getComputedStyle(document.documentElement);
1046
- const decls = [];
1047
- const seen = /* @__PURE__ */ new Set();
1048
- for (let i = 0; i < rootStyle.length && decls.length < 400; i++) {
1049
- const name = rootStyle.item(i);
1050
- if (!name.startsWith("--") || seen.has(name)) continue;
1051
- seen.add(name);
1052
- const value = rootStyle.getPropertyValue(name).trim();
1053
- if (!value || value.length > 200 || /[<>{}]/.test(value)) continue;
1054
- decls.push(`${name}:${value}`);
1045
+ for (const sheet of Array.from(document.styleSheets)) {
1046
+ let rules = null;
1047
+ try {
1048
+ rules = sheet.cssRules;
1049
+ } catch {
1050
+ continue;
1051
+ }
1052
+ if (!rules) continue;
1053
+ for (const rule of Array.from(rules)) {
1054
+ out += `${rule.cssText}
1055
+ `;
1056
+ if (out.length > MAX_HOST_CSS) return out;
1057
+ }
1055
1058
  }
1056
- const bodyFont = getComputedStyle(document.body).fontFamily;
1057
- if (bodyFont && bodyFont.length <= 200 && !/[<>{}]/.test(bodyFont)) {
1058
- decls.push(`--veo-host-font:${bodyFont}`);
1059
+ } catch {
1060
+ return out;
1061
+ }
1062
+ return out;
1063
+ }
1064
+ function hostHtmlAttrs() {
1065
+ if (typeof document === "undefined") return "";
1066
+ try {
1067
+ const el = document.documentElement;
1068
+ const attrs = [];
1069
+ for (const name of ["class", "style", "data-theme", "data-mode", "data-color-mode"]) {
1070
+ const v = el.getAttribute(name);
1071
+ if (v && v.length <= 1e3 && !/["<>]/.test(v)) attrs.push(`${name}="${v}"`);
1059
1072
  }
1060
- return decls.length ? `:root{${decls.join(";")}}` : "";
1073
+ return attrs.join(" ");
1061
1074
  } catch {
1062
1075
  return "";
1063
1076
  }
@@ -1067,9 +1080,13 @@ function isRecord(value) {
1067
1080
  }
1068
1081
  function buildSrcdoc(html, css, js, token, opts) {
1069
1082
  const bridge = `(function(){var T=${JSON.stringify(token)};function P(m){m.__veo=T;parent.postMessage(m,'*');}window.veo={dismiss:function(){P({type:'dismiss'});},cta:function(u){P({type:'cta',url:u});},track:function(n,p){P({type:'track',name:n,props:p||{}});},navigate:function(u){P({type:'navigate',url:u});}};document.addEventListener('click',function(e){var a=e.target&&e.target.closest?e.target.closest('a[href]'):null;if(!a)return;var h=a.getAttribute('href');if(!h||h.charAt(0)==='#'||/^(javascript|mailto|tel):/i.test(h))return;e.preventDefault();if(a.target==='_blank'){P({type:'cta',url:a.href,close:false});}else{P({type:'navigate',url:h});}},true);function H(){P({type:'resize',height:Math.ceil(document.documentElement.scrollHeight)});}window.addEventListener('load',H);try{if(typeof ResizeObserver!=='undefined'){new ResizeObserver(H).observe(document.documentElement);}}catch(e){}})();`;
1070
- const tokensStyle = opts.tokens ? `<style>${escapeClosing(opts.tokens, "style")}</style>` : "";
1083
+ const hostStyle = opts.hostCss ? `<style>${escapeClosing(opts.hostCss, "style")}</style>` : "";
1071
1084
  const tailwind = opts.tailwind ? '<script src="https://cdn.tailwindcss.com"></script>' : "";
1072
- return '<!DOCTYPE html><html><head><meta charset="utf-8"><style>html,body{margin:0;padding:0;background:transparent;font-family:var(--veo-host-font,system-ui,sans-serif);}</style>' + tokensStyle + tailwind + `<style>${escapeClosing(css, "style")}</style></head><body>${html}<script>${bridge}</script>` + (js ? `<script>${escapeClosing(js, "script")}</script>` : "") + "</body></html>";
1085
+ return (
1086
+ // Orden: base → CSS del host (utilidades+clases propias+:root) → reset
1087
+ // flotante (fondo transparente, sin márgenes) → Tailwind → CSS del autor (gana).
1088
+ `<!DOCTYPE html><html ${opts.htmlAttrs}><head><meta charset="utf-8"><style>html,body{margin:0;padding:0;}body{font-family:system-ui,-apple-system,sans-serif;}</style>` + hostStyle + "<style>html,body{margin:0!important;padding:0!important;background:transparent!important;}</style>" + tailwind + `<style>${escapeClosing(css, "style")}</style></head><body>${html}<script>${bridge}</script>` + (js ? `<script>${escapeClosing(js, "script")}</script>` : "") + "</body></html>"
1089
+ );
1073
1090
  }
1074
1091
  function escapeClosing(code, tag) {
1075
1092
  const rx = tag === "script" ? /<\/script/gi : /<\/style/gi;
@@ -1102,20 +1119,6 @@ var CustomRenderer = class extends BaseRenderer {
1102
1119
  });
1103
1120
  this.registerCleanup(cleanup);
1104
1121
  wrapper.appendChild(iframe);
1105
- wrapper.appendChild(
1106
- createCloseButton(
1107
- doc,
1108
- () => {
1109
- context.onInteraction({
1110
- guideId: context.guide.guideId,
1111
- stepIndex: 0,
1112
- action: "dismissed"
1113
- });
1114
- context.onClose();
1115
- },
1116
- "veo-custom-close"
1117
- )
1118
- );
1119
1122
  root.appendChild(wrapper);
1120
1123
  if (placement.mode === "floating") {
1121
1124
  applyFloatingPosition(wrapper, placement);
@@ -1517,20 +1520,6 @@ var InlineCustomRenderer = class extends BaseRenderer {
1517
1520
  const { iframe, cleanup } = mountCustomFrame(doc, step, context, { width: "100%" });
1518
1521
  this.registerCleanup(cleanup);
1519
1522
  wrapper.appendChild(iframe);
1520
- wrapper.appendChild(
1521
- createCloseButton(
1522
- doc,
1523
- () => {
1524
- context.onInteraction({
1525
- guideId: context.guide.guideId,
1526
- stepIndex: 0,
1527
- action: "dismissed"
1528
- });
1529
- context.onClose();
1530
- },
1531
- "veo-custom-close"
1532
- )
1533
- );
1534
1523
  root.appendChild(wrapper);
1535
1524
  context.onInteraction({ guideId: context.guide.guideId, stepIndex: 0, action: "shown" });
1536
1525
  }
@@ -1668,6 +1657,8 @@ var TooltipRenderer = class extends BaseRenderer {
1668
1657
  if (typeof selector !== "string" || selector.length === 0) return;
1669
1658
  const anchor = await waitForElement(selector);
1670
1659
  if (!anchor) return;
1660
+ const rawSide = step.style?.tooltipPlacement;
1661
+ const side = rawSide === "top" || rawSide === "left" || rawSide === "right" ? rawSide : "bottom";
1671
1662
  const { root } = this.createHost();
1672
1663
  this.applyDesign(step.style);
1673
1664
  const ownerDocument = root.ownerDocument ?? document;
@@ -1695,7 +1686,7 @@ var TooltipRenderer = class extends BaseRenderer {
1695
1686
  root.appendChild(tooltip);
1696
1687
  const updatePosition = async () => {
1697
1688
  const { x, y, placement, middlewareData } = await computePosition(anchor, tooltip, {
1698
- placement: "bottom",
1689
+ placement: side,
1699
1690
  middleware: [offset(10), flip(), shift({ padding: 8 }), arrow({ element: arrowEl })]
1700
1691
  });
1701
1692
  tooltip.style.left = `${x}px`;
@@ -1727,6 +1718,8 @@ var WalkthroughRenderer = class extends BaseRenderer {
1727
1718
  if (typeof selector !== "string" || selector.length === 0) return false;
1728
1719
  const anchor = await waitForElement(selector, WALKTHROUGH_STEP_SELECTOR_TIMEOUT_MS);
1729
1720
  if (!anchor) return false;
1721
+ const rawSide = step.style?.tooltipPlacement;
1722
+ const side = rawSide === "top" || rawSide === "left" || rawSide === "right" ? rawSide : "bottom";
1730
1723
  const { root } = this.createHost();
1731
1724
  this.applyDesign(step.style);
1732
1725
  const ownerDocument = root.ownerDocument ?? document;
@@ -1746,7 +1739,7 @@ var WalkthroughRenderer = class extends BaseRenderer {
1746
1739
  root.appendChild(tooltip);
1747
1740
  const updatePosition = async () => {
1748
1741
  const { x, y, placement, middlewareData } = await computePosition(anchor, tooltip, {
1749
- placement: "bottom",
1742
+ placement: side,
1750
1743
  middleware: [offset(10), flip(), shift({ padding: 8 }), arrow({ element: arrowEl })]
1751
1744
  });
1752
1745
  tooltip.style.left = `${x}px`;
@@ -2094,5 +2087,5 @@ function buildSelectorPath(element, maxAncestors = 5) {
2094
2087
  }
2095
2088
 
2096
2089
  export { ALWAYS_BLOCK_SELECTORS, BannerRenderer, CustomRenderer, DEFAULT_AUTOCAPTURE_CONFIG, DEFAULT_TRACKER_BATCH_SIZE, DEFAULT_TRACKER_FLUSH_INTERVAL_MS, DEFAULT_TRACKER_MAX_RETRIES, FREQUENCY_CACHE_KEY_PREFIX, FREQUENCY_CACHE_MAX_ENTRIES, FREQUENCY_CACHE_TTL_MS, FormRenderer, InlineCustomRenderer, InlineFormRenderer, InlineRenderer, MAX_ANCESTORS, ModalRenderer, PRIORITY_ATTRIBUTES, SENSITIVE_ATTRIBUTES, TooltipRenderer, WALKTHROUGH_ABANDONMENT_TIMEOUT_MS, WALKTHROUGH_STATE_KEY_PREFIX, WalkthroughRenderer, buildSelectorPath, clearBuilderToken, closeGuidePreview, filterHumanClasses, hasDocument, hasLocalStorage, hasNavigatorSendBeacon, hasWindow, isBuilderMode, previewGuide, resolveBuilderContext, resolveBuilderToken, uuidv7 };
2097
- //# sourceMappingURL=chunk-4VJIILXF.mjs.map
2098
- //# sourceMappingURL=chunk-4VJIILXF.mjs.map
2090
+ //# sourceMappingURL=chunk-S522B64R.mjs.map
2091
+ //# sourceMappingURL=chunk-S522B64R.mjs.map