veo-sdk 0.3.4 → 0.3.6

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
@@ -58,6 +58,59 @@ function session() {
58
58
  return null;
59
59
  }
60
60
  }
61
+ function local() {
62
+ try {
63
+ return window.localStorage;
64
+ } catch {
65
+ return null;
66
+ }
67
+ }
68
+ function lsKey(guide) {
69
+ return LS_PREFIX + (guide || "default");
70
+ }
71
+ function persist(ctx) {
72
+ try {
73
+ session()?.setItem(CTX_KEY, JSON.stringify(ctx));
74
+ } catch {
75
+ }
76
+ try {
77
+ const stored = { ...ctx, savedAt: Date.now() };
78
+ local()?.setItem(lsKey(ctx.guide), JSON.stringify(stored));
79
+ } catch {
80
+ }
81
+ }
82
+ function readFreshFromLocal() {
83
+ const store = local();
84
+ if (!store) return null;
85
+ let best = null;
86
+ try {
87
+ for (let i = 0; i < store.length; i++) {
88
+ const key = store.key(i);
89
+ if (!key?.startsWith(LS_PREFIX)) continue;
90
+ const raw = store.getItem(key);
91
+ if (!raw) continue;
92
+ let parsed = null;
93
+ try {
94
+ parsed = JSON.parse(raw);
95
+ } catch {
96
+ continue;
97
+ }
98
+ if (typeof parsed?.savedAt !== "number" || Date.now() - parsed.savedAt > PERSIST_TTL_MS) {
99
+ try {
100
+ store.removeItem(key);
101
+ } catch {
102
+ }
103
+ continue;
104
+ }
105
+ if (!best || parsed.savedAt > best.savedAt) best = parsed;
106
+ }
107
+ } catch {
108
+ return null;
109
+ }
110
+ if (!best) return null;
111
+ const { savedAt: _savedAt, ...ctx } = best;
112
+ return ctx;
113
+ }
61
114
  function urlParams() {
62
115
  try {
63
116
  return new URLSearchParams(window.location.search);
@@ -77,18 +130,22 @@ function resolveBuilderContext() {
77
130
  guide: params?.get(BUILDER_GUIDE_PARAM) ?? null,
78
131
  panelPath: params?.get(BUILDER_PANEL_PATH_PARAM) ?? null
79
132
  };
80
- try {
81
- session()?.setItem(CTX_KEY, JSON.stringify(ctx));
82
- } catch {
83
- }
133
+ persist(ctx);
84
134
  return ctx;
85
135
  }
86
136
  try {
87
137
  const raw = session()?.getItem(CTX_KEY);
88
- return raw ? JSON.parse(raw) : null;
138
+ if (raw) return JSON.parse(raw);
89
139
  } catch {
90
- return null;
91
140
  }
141
+ const fromLocal = readFreshFromLocal();
142
+ if (fromLocal) {
143
+ try {
144
+ session()?.setItem(CTX_KEY, JSON.stringify(fromLocal));
145
+ } catch {
146
+ }
147
+ }
148
+ return fromLocal;
92
149
  }
93
150
  function resolveBuilderToken() {
94
151
  return resolveBuilderContext()?.token ?? null;
@@ -98,18 +155,30 @@ function isBuilderMode() {
98
155
  }
99
156
  function clearBuilderToken() {
100
157
  if (!hasWindow()) return;
158
+ let guide = null;
159
+ try {
160
+ const raw = session()?.getItem(CTX_KEY);
161
+ if (raw) guide = JSON.parse(raw).guide ?? null;
162
+ } catch {
163
+ }
101
164
  try {
102
165
  session()?.removeItem(CTX_KEY);
103
166
  } catch {
104
167
  }
168
+ try {
169
+ local()?.removeItem(lsKey(guide));
170
+ } catch {
171
+ }
105
172
  }
106
- var CTX_KEY;
173
+ var CTX_KEY, LS_PREFIX, PERSIST_TTL_MS;
107
174
  var init_builder_token = __esm({
108
175
  "src/core/builder-token.ts"() {
109
176
  init_safe_env();
110
177
  init_builder_constants();
111
178
  init_builder_constants();
112
179
  CTX_KEY = "veo:builder_ctx";
180
+ LS_PREFIX = "veo:builder_ctx:";
181
+ PERSIST_TTL_MS = 12 * 60 * 60 * 1e3;
113
182
  }
114
183
  });
115
184
 
@@ -343,14 +412,17 @@ function buildStepContent(step, doc, callbacks) {
343
412
  actions.appendChild(cta);
344
413
  }
345
414
  container.appendChild(actions);
415
+ container.appendChild(createCloseButton(doc, () => callbacks.onDismiss()));
416
+ return container;
417
+ }
418
+ function createCloseButton(doc, onClose, className = "veo-guide-close") {
346
419
  const closeBtn = doc.createElement("button");
347
420
  closeBtn.type = "button";
348
- closeBtn.className = "veo-guide-close";
421
+ closeBtn.className = className;
349
422
  closeBtn.setAttribute("aria-label", "Cerrar");
350
423
  closeBtn.textContent = "\xD7";
351
- closeBtn.addEventListener("click", () => callbacks.onDismiss());
352
- container.appendChild(closeBtn);
353
- return container;
424
+ closeBtn.addEventListener("click", onClose);
425
+ return closeBtn;
354
426
  }
355
427
  function isSafeUrl(url) {
356
428
  if (typeof url !== "string" || url.length === 0) return false;
@@ -424,8 +496,45 @@ function applyDesignVars(host, style) {
424
496
  host.style.setProperty("--veo-pos-x", `${px * 100}%`);
425
497
  host.style.setProperty("--veo-pos-y", `${py * 100}%`);
426
498
  }
499
+ if (s.elements && typeof s.elements === "object") {
500
+ const el = s.elements;
501
+ applyElementVars(host, "title", el.title);
502
+ applyElementVars(host, "text", el.text);
503
+ applyElementVars(host, "image", el.image);
504
+ const cta = el.cta;
505
+ if (cta && typeof cta.align === "string" && ALIGN_JUSTIFY[cta.align]) {
506
+ host.style.setProperty("--veo-actions-justify", ALIGN_JUSTIFY[cta.align]);
507
+ }
508
+ }
427
509
  }
428
- var DARK_THEME, ALIGN_JUSTIFY, SHADOW, PRESET_POS, COLOR_RE;
510
+ function applyElementVars(host, prefix, raw) {
511
+ if (!raw || typeof raw !== "object") return;
512
+ const el = raw;
513
+ if (typeof el.align === "string" && (el.align === "left" || el.align === "center" || el.align === "right")) {
514
+ const mode = ELEMENT_ALIGN_MODE[prefix] ?? "text";
515
+ const value = mode === "self" ? ALIGN_SELF[el.align] : el.align;
516
+ host.style.setProperty(`--veo-${prefix}-align`, value);
517
+ }
518
+ if (typeof el.color === "string" && COLOR_RE.test(el.color.trim())) {
519
+ host.style.setProperty(`--veo-${prefix}-color`, el.color.trim());
520
+ }
521
+ if (typeof el.fontSize === "number" && Number.isFinite(el.fontSize)) {
522
+ host.style.setProperty(`--veo-${prefix}-size`, `${clamp(el.fontSize, 8, 72)}px`);
523
+ }
524
+ if (typeof el.width === "number" && Number.isFinite(el.width)) {
525
+ host.style.setProperty(`--veo-${prefix}-width`, `${clamp(el.width, 10, 100)}%`);
526
+ }
527
+ if (typeof el.radius === "number" && Number.isFinite(el.radius)) {
528
+ host.style.setProperty(`--veo-${prefix}-radius`, `${clamp(el.radius, 0, 48)}px`);
529
+ }
530
+ if (typeof el.marginTop === "number" && Number.isFinite(el.marginTop)) {
531
+ host.style.setProperty(`--veo-${prefix}-mt`, `${clamp(el.marginTop, 0, 64)}px`);
532
+ }
533
+ if (typeof el.marginBottom === "number" && Number.isFinite(el.marginBottom)) {
534
+ host.style.setProperty(`--veo-${prefix}-mb`, `${clamp(el.marginBottom, 0, 64)}px`);
535
+ }
536
+ }
537
+ var DARK_THEME, ALIGN_JUSTIFY, ALIGN_SELF, ELEMENT_ALIGN_MODE, SHADOW, PRESET_POS, COLOR_RE;
429
538
  var init_guide_design = __esm({
430
539
  "src/plugins/guides/guide-design.ts"() {
431
540
  DARK_THEME = {
@@ -439,6 +548,16 @@ var init_guide_design = __esm({
439
548
  center: "center",
440
549
  right: "flex-end"
441
550
  };
551
+ ALIGN_SELF = {
552
+ left: "flex-start",
553
+ center: "center",
554
+ right: "flex-end"
555
+ };
556
+ ELEMENT_ALIGN_MODE = {
557
+ title: "text",
558
+ text: "text",
559
+ image: "self"
560
+ };
442
561
  SHADOW = {
443
562
  none: "none",
444
563
  soft: "0 4px 14px rgba(0, 0, 0, 0.10)",
@@ -528,6 +647,15 @@ var init_styles = __esm({
528
647
  box-shadow: var(--veo-shadow, 0 8px 30px rgba(0, 0, 0, 0.18));
529
648
  animation: veo-fade-in 150ms ease-out;
530
649
  }
650
+ .veo-tooltip-arrow {
651
+ position: absolute;
652
+ width: 12px;
653
+ height: 12px;
654
+ background: var(--veo-bg);
655
+ border: var(--veo-border-width, 0) solid var(--veo-border-color, transparent);
656
+ transform: rotate(45deg);
657
+ pointer-events: none;
658
+ }
531
659
 
532
660
  .veo-inline {
533
661
  background: var(--veo-bg);
@@ -546,17 +674,25 @@ var init_styles = __esm({
546
674
  display: flex; flex-direction: column;
547
675
  }
548
676
  .veo-guide-image {
549
- display: block; width: 100%; max-height: 180px;
550
- object-fit: cover; border-radius: 8px;
551
- margin-bottom: 12px;
677
+ display: block;
678
+ width: var(--veo-image-width, 100%);
679
+ max-height: 180px;
680
+ object-fit: cover;
681
+ align-self: var(--veo-image-align, stretch);
682
+ border-radius: var(--veo-image-radius, 8px);
683
+ margin: var(--veo-image-mt, 0) 0 var(--veo-image-mb, 12px);
552
684
  }
553
685
  .veo-guide-title {
554
- font-size: 18px; font-weight: 600; line-height: 1.3;
555
- margin: 0 0 6px; color: var(--veo-text);
686
+ font-size: var(--veo-title-size, 18px); font-weight: 600; line-height: 1.3;
687
+ text-align: var(--veo-title-align, left);
688
+ margin: var(--veo-title-mt, 0) 0 var(--veo-title-mb, 6px);
689
+ color: var(--veo-title-color, var(--veo-text));
556
690
  }
557
691
  .veo-guide-text {
558
- font-size: 14px; line-height: 1.5;
559
- margin: 0 0 16px; color: var(--veo-text-secondary);
692
+ font-size: var(--veo-text-size, 14px); line-height: 1.5;
693
+ text-align: var(--veo-text-align, left);
694
+ margin: var(--veo-text-mt, 0) 0 var(--veo-text-mb, 16px);
695
+ color: var(--veo-text-color, var(--veo-text-secondary));
560
696
  }
561
697
  .veo-guide-actions {
562
698
  display: flex; gap: 8px; justify-content: var(--veo-actions-justify);
@@ -693,6 +829,7 @@ var init_styles = __esm({
693
829
  }
694
830
  .veo-custom-inline {
695
831
  display: block;
832
+ position: relative;
696
833
  margin: 12px 0;
697
834
  }
698
835
  .veo-custom-frame {
@@ -702,6 +839,21 @@ var init_styles = __esm({
702
839
  background: transparent;
703
840
  color-scheme: normal;
704
841
  }
842
+ /*
843
+ * X de cerrar de las gu\xEDas custom: el HTML del cliente vive en un iframe
844
+ * sandbox, as\xED que el bot\xF3n lo pone el host POR ENCIMA del iframe. Con fondo
845
+ * propio para ser visible sobre cualquier contenido.
846
+ */
847
+ .veo-custom-close {
848
+ position: absolute; top: 6px; right: 6px; z-index: 1;
849
+ width: 22px; height: 22px; padding: 0;
850
+ display: flex; align-items: center; justify-content: center;
851
+ font-size: 16px; line-height: 1; color: #6b7280;
852
+ background: rgba(255, 255, 255, 0.92);
853
+ border: 1px solid rgba(0, 0, 0, 0.08); border-radius: 50%;
854
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.14); cursor: pointer;
855
+ }
856
+ .veo-custom-close:hover { color: #111827; }
705
857
 
706
858
  @keyframes veo-fade-in { from { opacity: 0; } to { opacity: 1; } }
707
859
  @keyframes veo-slide-up {
@@ -872,7 +1024,11 @@ function mountCustomFrame(doc, step, context, opts) {
872
1024
  const hasFixedHeight = opts.fixedHeight !== void 0 && opts.fixedHeight !== null;
873
1025
  if (hasFixedHeight) iframe.style.height = toCssSize(opts.fixedHeight);
874
1026
  const token = uuidv7();
875
- iframe.srcdoc = buildSrcdoc(step.html ?? "", step.css ?? "", step.js ?? "", token);
1027
+ const wantsTailwind = step.style?.tailwind === true;
1028
+ iframe.srcdoc = buildSrcdoc(step.html ?? "", step.css ?? "", step.js ?? "", token, {
1029
+ tokens: collectHostTokens(),
1030
+ tailwind: wantsTailwind
1031
+ });
876
1032
  const close = () => context.onClose();
877
1033
  const onMessage = (event) => {
878
1034
  if (event.source !== iframe.contentWindow) return;
@@ -921,12 +1077,37 @@ function mountCustomFrame(doc, step, context, opts) {
921
1077
  function toCssSize(value) {
922
1078
  return typeof value === "number" ? `${value}px` : value;
923
1079
  }
1080
+ function collectHostTokens() {
1081
+ if (typeof window === "undefined" || typeof document === "undefined") return "";
1082
+ try {
1083
+ const rootStyle = getComputedStyle(document.documentElement);
1084
+ const decls = [];
1085
+ const seen = /* @__PURE__ */ new Set();
1086
+ for (let i = 0; i < rootStyle.length && decls.length < 400; i++) {
1087
+ const name = rootStyle.item(i);
1088
+ if (!name.startsWith("--") || seen.has(name)) continue;
1089
+ seen.add(name);
1090
+ const value = rootStyle.getPropertyValue(name).trim();
1091
+ if (!value || value.length > 200 || /[<>{}]/.test(value)) continue;
1092
+ decls.push(`${name}:${value}`);
1093
+ }
1094
+ const bodyFont = getComputedStyle(document.body).fontFamily;
1095
+ if (bodyFont && bodyFont.length <= 200 && !/[<>{}]/.test(bodyFont)) {
1096
+ decls.push(`--veo-host-font:${bodyFont}`);
1097
+ }
1098
+ return decls.length ? `:root{${decls.join(";")}}` : "";
1099
+ } catch {
1100
+ return "";
1101
+ }
1102
+ }
924
1103
  function isRecord(value) {
925
1104
  return typeof value === "object" && value !== null && !Array.isArray(value);
926
1105
  }
927
- function buildSrcdoc(html, css, js, token) {
1106
+ function buildSrcdoc(html, css, js, token, opts) {
928
1107
  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){}})();`;
929
- return `<!DOCTYPE html><html><head><meta charset="utf-8"><style>html,body{margin:0;padding:0;background:transparent;}</style><style>${escapeClosing(css, "style")}</style></head><body>${html}<script>${bridge}</script>` + (js ? `<script>${escapeClosing(js, "script")}</script>` : "") + "</body></html>";
1108
+ const tokensStyle = opts.tokens ? `<style>${escapeClosing(opts.tokens, "style")}</style>` : "";
1109
+ const tailwind = opts.tailwind ? '<script src="https://cdn.tailwindcss.com"></script>' : "";
1110
+ 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>";
930
1111
  }
931
1112
  function escapeClosing(code, tag) {
932
1113
  const rx = tag === "script" ? /<\/script/gi : /<\/style/gi;
@@ -964,6 +1145,7 @@ function applyFloatingPosition(wrapper, placement) {
964
1145
  var DEFAULT_PLACEMENT, DEFAULT_OFFSET, DEFAULT_WIDTH, CustomRenderer;
965
1146
  var init_custom_renderer = __esm({
966
1147
  "src/plugins/guides/renderers/custom-renderer.ts"() {
1148
+ init_block_builder();
967
1149
  init_wait_for_element();
968
1150
  init_base_renderer();
969
1151
  init_custom_frame();
@@ -992,6 +1174,20 @@ var init_custom_renderer = __esm({
992
1174
  });
993
1175
  this.registerCleanup(cleanup);
994
1176
  wrapper.appendChild(iframe);
1177
+ wrapper.appendChild(
1178
+ createCloseButton(
1179
+ doc,
1180
+ () => {
1181
+ context.onInteraction({
1182
+ guideId: context.guide.guideId,
1183
+ stepIndex: 0,
1184
+ action: "dismissed"
1185
+ });
1186
+ context.onClose();
1187
+ },
1188
+ "veo-custom-close"
1189
+ )
1190
+ );
995
1191
  root.appendChild(wrapper);
996
1192
  if (placement.mode === "floating") {
997
1193
  applyFloatingPosition(wrapper, placement);
@@ -1108,13 +1304,7 @@ function mountFormContent(card, context, doc) {
1108
1304
  });
1109
1305
  });
1110
1306
  content.appendChild(form);
1111
- const closeBtn = doc.createElement("button");
1112
- closeBtn.type = "button";
1113
- closeBtn.className = "veo-guide-close";
1114
- closeBtn.setAttribute("aria-label", "Cerrar");
1115
- closeBtn.textContent = "\xD7";
1116
- closeBtn.addEventListener("click", dismiss);
1117
- content.appendChild(closeBtn);
1307
+ content.appendChild(createCloseButton(doc, dismiss));
1118
1308
  card.appendChild(content);
1119
1309
  }
1120
1310
  function showThanks(card, doc, note) {
@@ -1298,6 +1488,7 @@ function buildScale(wrapper, doc, min, max, btnClass, symbol) {
1298
1488
  }
1299
1489
  var init_form_content = __esm({
1300
1490
  "src/plugins/guides/form-content.ts"() {
1491
+ init_block_builder();
1301
1492
  }
1302
1493
  });
1303
1494
 
@@ -1377,6 +1568,7 @@ var init_inline_host = __esm({
1377
1568
  var InlineCustomRenderer;
1378
1569
  var init_inline_custom_renderer = __esm({
1379
1570
  "src/plugins/guides/renderers/inline-custom-renderer.ts"() {
1571
+ init_block_builder();
1380
1572
  init_inline_host();
1381
1573
  init_wait_for_element();
1382
1574
  init_base_renderer();
@@ -1400,6 +1592,20 @@ var init_inline_custom_renderer = __esm({
1400
1592
  const { iframe, cleanup } = mountCustomFrame(doc, step, context, { width: "100%" });
1401
1593
  this.registerCleanup(cleanup);
1402
1594
  wrapper.appendChild(iframe);
1595
+ wrapper.appendChild(
1596
+ createCloseButton(
1597
+ doc,
1598
+ () => {
1599
+ context.onInteraction({
1600
+ guideId: context.guide.guideId,
1601
+ stepIndex: 0,
1602
+ action: "dismissed"
1603
+ });
1604
+ context.onClose();
1605
+ },
1606
+ "veo-custom-close"
1607
+ )
1608
+ );
1403
1609
  root.appendChild(wrapper);
1404
1610
  context.onInteraction({ guideId: context.guide.guideId, stepIndex: 0, action: "shown" });
1405
1611
  }
@@ -1534,12 +1740,35 @@ var init_modal_renderer = __esm({
1534
1740
  };
1535
1741
  }
1536
1742
  });
1743
+
1744
+ // src/plugins/guides/renderers/floating-arrow.ts
1745
+ function positionArrow(arrowEl, placement, data) {
1746
+ const side = STATIC_SIDE[placement.split("-")[0] ?? "bottom"] ?? "top";
1747
+ for (const prop of ["top", "bottom", "left", "right"]) {
1748
+ arrowEl.style.setProperty(prop, "");
1749
+ }
1750
+ if (data?.x != null) arrowEl.style.setProperty("left", `${data.x}px`);
1751
+ if (data?.y != null) arrowEl.style.setProperty("top", `${data.y}px`);
1752
+ arrowEl.style.setProperty(side, "-6px");
1753
+ }
1754
+ var STATIC_SIDE;
1755
+ var init_floating_arrow = __esm({
1756
+ "src/plugins/guides/renderers/floating-arrow.ts"() {
1757
+ STATIC_SIDE = {
1758
+ top: "bottom",
1759
+ bottom: "top",
1760
+ left: "right",
1761
+ right: "left"
1762
+ };
1763
+ }
1764
+ });
1537
1765
  var TooltipRenderer;
1538
1766
  var init_tooltip_renderer = __esm({
1539
1767
  "src/plugins/guides/renderers/tooltip-renderer.ts"() {
1540
1768
  init_block_builder();
1541
1769
  init_wait_for_element();
1542
1770
  init_base_renderer();
1771
+ init_floating_arrow();
1543
1772
  TooltipRenderer = class extends BaseRenderer {
1544
1773
  async render(context) {
1545
1774
  const step = context.guide.guideSteps[0];
@@ -1569,14 +1798,18 @@ var init_tooltip_renderer = __esm({
1569
1798
  onDismiss: () => dismiss("dismissed")
1570
1799
  });
1571
1800
  tooltip.appendChild(content);
1801
+ const arrowEl = ownerDocument.createElement("div");
1802
+ arrowEl.className = "veo-tooltip-arrow";
1803
+ tooltip.appendChild(arrowEl);
1572
1804
  root.appendChild(tooltip);
1573
1805
  const updatePosition = async () => {
1574
- const { x, y } = await dom.computePosition(anchor, tooltip, {
1806
+ const { x, y, placement, middlewareData } = await dom.computePosition(anchor, tooltip, {
1575
1807
  placement: "bottom",
1576
- middleware: [dom.offset(8), dom.flip(), dom.shift({ padding: 8 })]
1808
+ middleware: [dom.offset(10), dom.flip(), dom.shift({ padding: 8 }), dom.arrow({ element: arrowEl })]
1577
1809
  });
1578
1810
  tooltip.style.left = `${x}px`;
1579
1811
  tooltip.style.top = `${y}px`;
1812
+ positionArrow(arrowEl, placement, middlewareData.arrow);
1580
1813
  };
1581
1814
  await updatePosition();
1582
1815
  const reposition = () => {
@@ -1666,6 +1899,7 @@ function buildWalkthroughStepContent(step, stepIndex, totalSteps, doc, callbacks
1666
1899
  rightGroup.appendChild(primaryBtn);
1667
1900
  actions.appendChild(rightGroup);
1668
1901
  container.appendChild(actions);
1902
+ container.appendChild(createCloseButton(doc, () => callbacks.onSkip()));
1669
1903
  return container;
1670
1904
  }
1671
1905
  var init_walkthrough_block_builder = __esm({
@@ -1673,22 +1907,14 @@ var init_walkthrough_block_builder = __esm({
1673
1907
  init_block_builder();
1674
1908
  }
1675
1909
  });
1676
- function positionArrow(arrowEl, placement, data) {
1677
- const side = STATIC_SIDE[placement.split("-")[0] ?? "bottom"] ?? "top";
1678
- for (const prop of ["top", "bottom", "left", "right"]) {
1679
- arrowEl.style.setProperty(prop, "");
1680
- }
1681
- if (data?.x != null) arrowEl.style.setProperty("left", `${data.x}px`);
1682
- if (data?.y != null) arrowEl.style.setProperty("top", `${data.y}px`);
1683
- arrowEl.style.setProperty(side, "-6px");
1684
- }
1685
- var WalkthroughRenderer, STATIC_SIDE;
1910
+ var WalkthroughRenderer;
1686
1911
  var init_walkthrough_renderer = __esm({
1687
1912
  "src/plugins/guides/renderers/walkthrough-renderer.ts"() {
1688
1913
  init_constants2();
1689
1914
  init_wait_for_element();
1690
1915
  init_walkthrough_block_builder();
1691
1916
  init_base_renderer();
1917
+ init_floating_arrow();
1692
1918
  WalkthroughRenderer = class extends BaseRenderer {
1693
1919
  async render(context) {
1694
1920
  const step = context.guide.guideSteps[context.currentStepIndex];
@@ -1736,12 +1962,6 @@ var init_walkthrough_renderer = __esm({
1736
1962
  return true;
1737
1963
  }
1738
1964
  };
1739
- STATIC_SIDE = {
1740
- top: "bottom",
1741
- bottom: "top",
1742
- left: "right",
1743
- right: "left"
1744
- };
1745
1965
  }
1746
1966
  });
1747
1967
 
@@ -2418,7 +2638,7 @@ function initBuilderMode() {
2418
2638
  if (!ctx.panel) post({ type: "ready" });
2419
2639
  };
2420
2640
  const cfg = window.__veoBuilder;
2421
- if (cfg?.apiKey && cfg?.apiUrl) {
2641
+ if (!ctx.panel && cfg?.apiKey && cfg?.apiUrl) {
2422
2642
  void verifyBuilderToken(cfg.apiUrl, cfg.apiKey, token).then((ok) => {
2423
2643
  if (ok) activate();
2424
2644
  else if (window.console) console.warn("[veo] token de builder inv\xE1lido \u2014 modo no activado");