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.
package/dist/index.cjs CHANGED
@@ -439,11 +439,17 @@ function renderBlocks(container, blocks, doc, callbacks) {
439
439
  if (block?.type === "button") {
440
440
  const actions = doc.createElement("div");
441
441
  actions.className = "veo-guide-actions";
442
+ let rowAlign;
442
443
  while (i < blocks.length && blocks[i]?.type === "button") {
443
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
+ }
444
449
  actions.appendChild(buildButtonBlock(btnBlock, doc, callbacks));
445
450
  i++;
446
451
  }
452
+ if (rowAlign) actions.style.justifyContent = BLOCK_ALIGN_SELF[rowAlign];
447
453
  container.appendChild(actions);
448
454
  continue;
449
455
  }
@@ -503,7 +509,7 @@ function applyBlockStyle(el, style, kind) {
503
509
  const align = typeof s.align === "string" ? s.align : null;
504
510
  if (align && (align === "left" || align === "center" || align === "right")) {
505
511
  if (kind === "text") el.style.textAlign = align;
506
- else el.style.alignSelf = BLOCK_ALIGN_SELF[align];
512
+ else if (kind === "image") el.style.alignSelf = BLOCK_ALIGN_SELF[align];
507
513
  }
508
514
  if (kind !== "image" && typeof s.color === "string") el.style.color = s.color;
509
515
  if (kind === "text" && typeof s.fontSize === "number" && Number.isFinite(s.fontSize)) {
@@ -866,6 +872,12 @@ var init_styles = __esm({
866
872
  position: relative;
867
873
  display: flex; flex-direction: column;
868
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
+ }
869
881
  .veo-guide-image {
870
882
  display: block;
871
883
  width: var(--veo-image-width, 100%);
@@ -1032,21 +1044,6 @@ var init_styles = __esm({
1032
1044
  background: transparent;
1033
1045
  color-scheme: normal;
1034
1046
  }
1035
- /*
1036
- * X de cerrar de las gu\xEDas custom: el HTML del cliente vive en un iframe
1037
- * sandbox, as\xED que el bot\xF3n lo pone el host POR ENCIMA del iframe. Con fondo
1038
- * propio para ser visible sobre cualquier contenido.
1039
- */
1040
- .veo-custom-close {
1041
- position: absolute; top: 6px; right: 6px; z-index: 1;
1042
- width: 22px; height: 22px; padding: 0;
1043
- display: flex; align-items: center; justify-content: center;
1044
- font-size: 16px; line-height: 1; color: #6b7280;
1045
- background: rgba(255, 255, 255, 0.92);
1046
- border: 1px solid rgba(0, 0, 0, 0.08); border-radius: 50%;
1047
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.14); cursor: pointer;
1048
- }
1049
- .veo-custom-close:hover { color: #111827; }
1050
1047
 
1051
1048
  @keyframes veo-fade-in { from { opacity: 0; } to { opacity: 1; } }
1052
1049
  @keyframes veo-slide-up {
@@ -1219,7 +1216,8 @@ function mountCustomFrame(doc, step, context, opts) {
1219
1216
  const token = uuidv7();
1220
1217
  const wantsTailwind = step.style?.tailwind === true;
1221
1218
  iframe.srcdoc = buildSrcdoc(step.html ?? "", step.css ?? "", step.js ?? "", token, {
1222
- tokens: collectHostTokens(),
1219
+ hostCss: collectHostStyles(),
1220
+ htmlAttrs: hostHtmlAttrs(),
1223
1221
  tailwind: wantsTailwind
1224
1222
  });
1225
1223
  const close = () => context.onClose();
@@ -1270,25 +1268,39 @@ function mountCustomFrame(doc, step, context, opts) {
1270
1268
  function toCssSize(value) {
1271
1269
  return typeof value === "number" ? `${value}px` : value;
1272
1270
  }
1273
- function collectHostTokens() {
1274
- if (typeof window === "undefined" || typeof document === "undefined") return "";
1271
+ function collectHostStyles() {
1272
+ if (typeof document === "undefined") return "";
1273
+ let out = "";
1275
1274
  try {
1276
- const rootStyle = getComputedStyle(document.documentElement);
1277
- const decls = [];
1278
- const seen = /* @__PURE__ */ new Set();
1279
- for (let i = 0; i < rootStyle.length && decls.length < 400; i++) {
1280
- const name = rootStyle.item(i);
1281
- if (!name.startsWith("--") || seen.has(name)) continue;
1282
- seen.add(name);
1283
- const value = rootStyle.getPropertyValue(name).trim();
1284
- if (!value || value.length > 200 || /[<>{}]/.test(value)) continue;
1285
- decls.push(`${name}:${value}`);
1275
+ for (const sheet of Array.from(document.styleSheets)) {
1276
+ let rules = null;
1277
+ try {
1278
+ rules = sheet.cssRules;
1279
+ } catch {
1280
+ continue;
1281
+ }
1282
+ if (!rules) continue;
1283
+ for (const rule of Array.from(rules)) {
1284
+ out += `${rule.cssText}
1285
+ `;
1286
+ if (out.length > MAX_HOST_CSS) return out;
1287
+ }
1286
1288
  }
1287
- const bodyFont = getComputedStyle(document.body).fontFamily;
1288
- if (bodyFont && bodyFont.length <= 200 && !/[<>{}]/.test(bodyFont)) {
1289
- decls.push(`--veo-host-font:${bodyFont}`);
1289
+ } catch {
1290
+ return out;
1291
+ }
1292
+ return out;
1293
+ }
1294
+ function hostHtmlAttrs() {
1295
+ if (typeof document === "undefined") return "";
1296
+ try {
1297
+ const el = document.documentElement;
1298
+ const attrs = [];
1299
+ for (const name of ["class", "style", "data-theme", "data-mode", "data-color-mode"]) {
1300
+ const v = el.getAttribute(name);
1301
+ if (v && v.length <= 1e3 && !/["<>]/.test(v)) attrs.push(`${name}="${v}"`);
1290
1302
  }
1291
- return decls.length ? `:root{${decls.join(";")}}` : "";
1303
+ return attrs.join(" ");
1292
1304
  } catch {
1293
1305
  return "";
1294
1306
  }
@@ -1298,18 +1310,24 @@ function isRecord(value) {
1298
1310
  }
1299
1311
  function buildSrcdoc(html, css, js, token, opts) {
1300
1312
  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){}})();`;
1301
- const tokensStyle = opts.tokens ? `<style>${escapeClosing(opts.tokens, "style")}</style>` : "";
1313
+ const hostStyle = opts.hostCss ? `<style>${escapeClosing(opts.hostCss, "style")}</style>` : "";
1302
1314
  const tailwind = opts.tailwind ? '<script src="https://cdn.tailwindcss.com"></script>' : "";
1303
- 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>";
1315
+ return (
1316
+ // Orden: base → CSS del host (utilidades+clases propias+:root) → reset
1317
+ // flotante (fondo transparente, sin márgenes) → Tailwind → CSS del autor (gana).
1318
+ `<!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>"
1319
+ );
1304
1320
  }
1305
1321
  function escapeClosing(code, tag) {
1306
1322
  const rx = tag === "script" ? /<\/script/gi : /<\/style/gi;
1307
1323
  return code.replace(rx, `<\\/${tag}`);
1308
1324
  }
1325
+ var MAX_HOST_CSS;
1309
1326
  var init_custom_frame = __esm({
1310
1327
  "src/plugins/guides/renderers/custom-frame.ts"() {
1311
1328
  init_uuid();
1312
1329
  init_block_builder();
1330
+ MAX_HOST_CSS = 800 * 1024;
1313
1331
  }
1314
1332
  });
1315
1333
  function applyFloatingPosition(wrapper, placement) {
@@ -1338,7 +1356,6 @@ function applyFloatingPosition(wrapper, placement) {
1338
1356
  var DEFAULT_PLACEMENT, DEFAULT_OFFSET, DEFAULT_WIDTH, CustomRenderer;
1339
1357
  var init_custom_renderer = __esm({
1340
1358
  "src/plugins/guides/renderers/custom-renderer.ts"() {
1341
- init_block_builder();
1342
1359
  init_wait_for_element();
1343
1360
  init_base_renderer();
1344
1361
  init_custom_frame();
@@ -1367,20 +1384,6 @@ var init_custom_renderer = __esm({
1367
1384
  });
1368
1385
  this.registerCleanup(cleanup);
1369
1386
  wrapper.appendChild(iframe);
1370
- wrapper.appendChild(
1371
- createCloseButton(
1372
- doc,
1373
- () => {
1374
- context.onInteraction({
1375
- guideId: context.guide.guideId,
1376
- stepIndex: 0,
1377
- action: "dismissed"
1378
- });
1379
- context.onClose();
1380
- },
1381
- "veo-custom-close"
1382
- )
1383
- );
1384
1387
  root.appendChild(wrapper);
1385
1388
  if (placement.mode === "floating") {
1386
1389
  applyFloatingPosition(wrapper, placement);
@@ -1761,7 +1764,6 @@ var init_inline_host = __esm({
1761
1764
  var InlineCustomRenderer;
1762
1765
  var init_inline_custom_renderer = __esm({
1763
1766
  "src/plugins/guides/renderers/inline-custom-renderer.ts"() {
1764
- init_block_builder();
1765
1767
  init_inline_host();
1766
1768
  init_wait_for_element();
1767
1769
  init_base_renderer();
@@ -1785,20 +1787,6 @@ var init_inline_custom_renderer = __esm({
1785
1787
  const { iframe, cleanup } = mountCustomFrame(doc, step, context, { width: "100%" });
1786
1788
  this.registerCleanup(cleanup);
1787
1789
  wrapper.appendChild(iframe);
1788
- wrapper.appendChild(
1789
- createCloseButton(
1790
- doc,
1791
- () => {
1792
- context.onInteraction({
1793
- guideId: context.guide.guideId,
1794
- stepIndex: 0,
1795
- action: "dismissed"
1796
- });
1797
- context.onClose();
1798
- },
1799
- "veo-custom-close"
1800
- )
1801
- );
1802
1790
  root.appendChild(wrapper);
1803
1791
  context.onInteraction({ guideId: context.guide.guideId, stepIndex: 0, action: "shown" });
1804
1792
  }
@@ -1974,6 +1962,8 @@ var init_tooltip_renderer = __esm({
1974
1962
  if (typeof selector !== "string" || selector.length === 0) return;
1975
1963
  const anchor = await waitForElement(selector);
1976
1964
  if (!anchor) return;
1965
+ const rawSide = step.style?.tooltipPlacement;
1966
+ const side = rawSide === "top" || rawSide === "left" || rawSide === "right" ? rawSide : "bottom";
1977
1967
  const { root } = this.createHost();
1978
1968
  this.applyDesign(step.style);
1979
1969
  const ownerDocument = root.ownerDocument ?? document;
@@ -2001,7 +1991,7 @@ var init_tooltip_renderer = __esm({
2001
1991
  root.appendChild(tooltip);
2002
1992
  const updatePosition = async () => {
2003
1993
  const { x, y, placement, middlewareData } = await dom.computePosition(anchor, tooltip, {
2004
- placement: "bottom",
1994
+ placement: side,
2005
1995
  middleware: [dom.offset(10), dom.flip(), dom.shift({ padding: 8 }), dom.arrow({ element: arrowEl })]
2006
1996
  });
2007
1997
  tooltip.style.left = `${x}px`;
@@ -2043,6 +2033,8 @@ var init_walkthrough_renderer = __esm({
2043
2033
  if (typeof selector !== "string" || selector.length === 0) return false;
2044
2034
  const anchor = await waitForElement(selector, WALKTHROUGH_STEP_SELECTOR_TIMEOUT_MS);
2045
2035
  if (!anchor) return false;
2036
+ const rawSide = step.style?.tooltipPlacement;
2037
+ const side = rawSide === "top" || rawSide === "left" || rawSide === "right" ? rawSide : "bottom";
2046
2038
  const { root } = this.createHost();
2047
2039
  this.applyDesign(step.style);
2048
2040
  const ownerDocument = root.ownerDocument ?? document;
@@ -2062,7 +2054,7 @@ var init_walkthrough_renderer = __esm({
2062
2054
  root.appendChild(tooltip);
2063
2055
  const updatePosition = async () => {
2064
2056
  const { x, y, placement, middlewareData } = await dom.computePosition(anchor, tooltip, {
2065
- placement: "bottom",
2057
+ placement: side,
2066
2058
  middleware: [dom.offset(10), dom.flip(), dom.shift({ padding: 8 }), dom.arrow({ element: arrowEl })]
2067
2059
  });
2068
2060
  tooltip.style.left = `${x}px`;