veo-sdk 0.3.14 → 0.3.16

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.
@@ -0,0 +1,5 @@
1
+ export { createBuilderSession, initBuilderMode, startElementPicker, stopElementPicker } from './chunk-QCIT7CGE.mjs';
2
+ import './chunk-YHUPUTWH.mjs';
3
+ import './chunk-PTG3BTJE.mjs';
4
+ //# sourceMappingURL=builder-EQYOMQFY.mjs.map
5
+ //# sourceMappingURL=builder-EQYOMQFY.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"builder-4YBB3RSZ.mjs"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"builder-EQYOMQFY.mjs"}
package/dist/builder.cjs CHANGED
@@ -692,6 +692,24 @@ var GUIDE_STYLES = `
692
692
  cursor: pointer; color: #9ca3af; padding: 0;
693
693
  }
694
694
  .veo-guide-close:hover { color: var(--veo-text); }
695
+ /*
696
+ * Si el PRIMER bloque es una imagen, la \u2715 quedar\xEDa sobre la esquina de la foto
697
+ * (invisible seg\xFAn el color). En ese caso pasa a ser una pastilla flotante con
698
+ * fondo propio, legible sobre cualquier imagen. (Sin soporte de :has() queda el
699
+ * estilo base \u2014 mismo comportamiento de antes, sin regresi\xF3n.)
700
+ */
701
+ .veo-guide-content:has(> .veo-guide-image:first-child) > .veo-guide-close {
702
+ top: 2px; right: 2px;
703
+ display: flex; align-items: center; justify-content: center;
704
+ font-size: 16px; color: #374151;
705
+ background: rgba(255, 255, 255, 0.92);
706
+ border: 1px solid rgba(0, 0, 0, 0.08);
707
+ border-radius: 50%;
708
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.18);
709
+ }
710
+ .veo-guide-content:has(> .veo-guide-image:first-child) > .veo-guide-close:hover {
711
+ color: #111827;
712
+ }
695
713
 
696
714
  .veo-form { display: flex; flex-direction: column; gap: 14px; margin-bottom: 16px; }
697
715
  .veo-form-field { display: flex; flex-direction: column; gap: 6px; }
@@ -836,6 +854,37 @@ var BaseRenderer = class {
836
854
  this.host = null;
837
855
  this.shadow = null;
838
856
  this.cleanups = [];
857
+ // ── Update in-place (preview en vivo del editor) ──
858
+ // La subclase setea estas piezas en render() para habilitarlo: el contenedor
859
+ // del contenido, el nodo de contenido actual y cómo reconstruirlo.
860
+ this.liveContainer = null;
861
+ this.liveContent = null;
862
+ this.liveBuild = null;
863
+ /** Clave de anclaje/estructura fijada en render(); si cambia → remontar. */
864
+ this.liveKey = "";
865
+ }
866
+ /** Clave de anclaje derivada del step (override por subclase). */
867
+ liveKeyOf(_step) {
868
+ return "";
869
+ }
870
+ /** Hook post-swap (reposicionar tooltip, actualizar clase del banner…). */
871
+ onLiveUpdate(_step) {
872
+ }
873
+ /**
874
+ * Actualiza el contenido del step SIN remontar el host — así el preview del
875
+ * editor no parpadea en cada tecla. Devuelve `false` cuando el renderer no
876
+ * lo soporta o el cambio requiere remontar (cambió el ancla/estructura);
877
+ * en ese caso el caller hace el re-render completo.
878
+ */
879
+ updateStep(step) {
880
+ if (!this.host || !this.liveContainer || !this.liveContent || !this.liveBuild) return false;
881
+ if (this.liveKeyOf(step) !== this.liveKey) return false;
882
+ const next = this.liveBuild(step);
883
+ this.liveContainer.replaceChild(next, this.liveContent);
884
+ this.liveContent = next;
885
+ this.applyDesign(step.style);
886
+ this.onLiveUpdate(step);
887
+ return true;
839
888
  }
840
889
  /**
841
890
  * Crea un `<div data-veo-guide>` adjunto a `document.body`, le adjunta
@@ -918,9 +967,21 @@ var BannerRenderer = class extends BaseRenderer {
918
967
  banner.appendChild(content);
919
968
  root.appendChild(banner);
920
969
  if (!context.nav) {
970
+ this.liveContainer = banner;
971
+ this.liveContent = content;
972
+ this.liveBuild = (s) => buildStepContent(s, ownerDocument, {
973
+ onCtaClick: (action, url) => dismiss("cta_clicked", action === "url" ? url : void 0),
974
+ onDismiss: () => dismiss("dismissed")
975
+ });
921
976
  context.onInteraction({ guideId: context.guide.guideId, stepIndex: 0, action: "shown" });
922
977
  }
923
978
  }
979
+ onLiveUpdate(step) {
980
+ if (this.liveContainer) {
981
+ const position = step.style?.position === "bottom" ? "bottom" : "top";
982
+ this.liveContainer.className = `veo-banner veo-banner-${position}`;
983
+ }
984
+ }
924
985
  };
925
986
 
926
987
  // src/plugins/guides/wait-for-element.ts
@@ -1244,7 +1305,7 @@ function mountFormContent(card, context, doc) {
1244
1305
  const empty = value === void 0 || value === null || value === "";
1245
1306
  if (empty) {
1246
1307
  if (field.required) {
1247
- error.textContent = `Complet\xE1 "${field.label}"`;
1308
+ error.textContent = `Completa "${field.label}"`;
1248
1309
  error.style.display = "block";
1249
1310
  return;
1250
1311
  }
@@ -1253,7 +1314,7 @@ function mountFormContent(card, context, doc) {
1253
1314
  answers[field.key] = value;
1254
1315
  }
1255
1316
  if (Object.keys(answers).length === 0) {
1256
- error.textContent = "Respond\xE9 al menos un campo";
1317
+ error.textContent = "Responde al menos un campo";
1257
1318
  error.style.display = "block";
1258
1319
  return;
1259
1320
  }
@@ -1262,7 +1323,7 @@ function mountFormContent(card, context, doc) {
1262
1323
  void submitFn(answers).then((ok) => {
1263
1324
  if (!ok) {
1264
1325
  submit.disabled = false;
1265
- error.textContent = "No se pudo enviar. Prob\xE1 de nuevo.";
1326
+ error.textContent = "No se pudo enviar. Prueba de nuevo.";
1266
1327
  error.style.display = "block";
1267
1328
  return;
1268
1329
  }
@@ -1321,7 +1382,7 @@ function buildField(field, doc) {
1321
1382
  select.className = "veo-form-input";
1322
1383
  const blank = doc.createElement("option");
1323
1384
  blank.value = "";
1324
- blank.textContent = field.placeholder || "Eleg\xED una opci\xF3n\u2026";
1385
+ blank.textContent = field.placeholder || "Elige una opci\xF3n\u2026";
1325
1386
  select.appendChild(blank);
1326
1387
  for (const opt of field.options ?? []) {
1327
1388
  const option = doc.createElement("option");
@@ -1595,8 +1656,18 @@ var InlineRenderer = class extends BaseRenderer {
1595
1656
  });
1596
1657
  card.appendChild(content);
1597
1658
  root.appendChild(card);
1659
+ this.liveContainer = card;
1660
+ this.liveContent = content;
1661
+ this.liveKey = `${selector}|${position}`;
1662
+ this.liveBuild = (s) => buildStepContent(s, ownerDocument, {
1663
+ onCtaClick: (action, url) => dismiss("cta_clicked", action === "url" ? url : void 0),
1664
+ onDismiss: () => dismiss("dismissed")
1665
+ });
1598
1666
  context.onInteraction({ guideId: context.guide.guideId, stepIndex: 0, action: "shown" });
1599
1667
  }
1668
+ liveKeyOf(step) {
1669
+ return `${step.selector ?? ""}|${readInlinePosition(step.style)}`;
1670
+ }
1600
1671
  };
1601
1672
 
1602
1673
  // src/plugins/guides/renderers/modal-renderer.ts
@@ -1634,6 +1705,14 @@ var ModalRenderer = class extends BaseRenderer {
1634
1705
  card.appendChild(content);
1635
1706
  overlay.appendChild(card);
1636
1707
  root.appendChild(overlay);
1708
+ if (!context.nav) {
1709
+ this.liveContainer = card;
1710
+ this.liveContent = content;
1711
+ this.liveBuild = (s) => buildStepContent(s, ownerDocument, {
1712
+ onCtaClick: (action, url) => dismiss("cta_clicked", action === "url" ? url : void 0),
1713
+ onDismiss: () => dismiss("dismissed")
1714
+ });
1715
+ }
1637
1716
  overlay.addEventListener("click", (e) => {
1638
1717
  if (e.target === overlay) onBackdropOrEsc();
1639
1718
  });
@@ -1667,6 +1746,12 @@ function positionArrow(arrowEl, placement, data) {
1667
1746
 
1668
1747
  // src/plugins/guides/renderers/tooltip-renderer.ts
1669
1748
  var TooltipRenderer = class extends BaseRenderer {
1749
+ constructor() {
1750
+ super(...arguments);
1751
+ /** Lado preferido (mutable: el update in-place puede cambiarlo). */
1752
+ this.side = "bottom";
1753
+ this.reposition = null;
1754
+ }
1670
1755
  async render(context) {
1671
1756
  const step = context.guide.guideSteps[0];
1672
1757
  if (!step) return;
@@ -1675,7 +1760,7 @@ var TooltipRenderer = class extends BaseRenderer {
1675
1760
  const anchor = await waitForElement(selector);
1676
1761
  if (!anchor) return;
1677
1762
  const rawSide = step.style?.tooltipPlacement;
1678
- const side = rawSide === "top" || rawSide === "left" || rawSide === "right" ? rawSide : "bottom";
1763
+ this.side = rawSide === "top" || rawSide === "left" || rawSide === "right" ? rawSide : "bottom";
1679
1764
  const { root } = this.createHost();
1680
1765
  this.applyDesign(step.style);
1681
1766
  const ownerDocument = root.ownerDocument ?? document;
@@ -1703,7 +1788,7 @@ var TooltipRenderer = class extends BaseRenderer {
1703
1788
  root.appendChild(tooltip);
1704
1789
  const updatePosition = async () => {
1705
1790
  const { x, y, placement, middlewareData } = await dom.computePosition(anchor, tooltip, {
1706
- placement: side,
1791
+ placement: this.side,
1707
1792
  middleware: [dom.offset(10), dom.flip(), dom.shift({ padding: 8 }), dom.arrow({ element: arrowEl })]
1708
1793
  });
1709
1794
  tooltip.style.left = `${x}px`;
@@ -1714,18 +1799,34 @@ var TooltipRenderer = class extends BaseRenderer {
1714
1799
  const reposition = () => {
1715
1800
  void updatePosition();
1716
1801
  };
1802
+ this.reposition = reposition;
1717
1803
  window.addEventListener("scroll", reposition, true);
1718
1804
  window.addEventListener("resize", reposition);
1719
1805
  this.registerCleanup(() => {
1720
1806
  window.removeEventListener("scroll", reposition, true);
1721
1807
  window.removeEventListener("resize", reposition);
1722
1808
  });
1809
+ this.liveContainer = tooltip;
1810
+ this.liveContent = content;
1811
+ this.liveKey = selector;
1812
+ this.liveBuild = (s) => buildStepContent(s, ownerDocument, {
1813
+ onCtaClick: (action, url) => dismiss("cta_clicked", action === "url" ? url : void 0),
1814
+ onDismiss: () => dismiss("dismissed")
1815
+ });
1723
1816
  context.onInteraction({
1724
1817
  guideId: context.guide.guideId,
1725
1818
  stepIndex: 0,
1726
1819
  action: "shown"
1727
1820
  });
1728
1821
  }
1822
+ liveKeyOf(step) {
1823
+ return step.selector ?? "";
1824
+ }
1825
+ onLiveUpdate(step) {
1826
+ const raw = step.style?.tooltipPlacement;
1827
+ this.side = raw === "top" || raw === "left" || raw === "right" ? raw : "bottom";
1828
+ this.reposition?.();
1829
+ }
1729
1830
  };
1730
1831
  var WalkthroughRenderer = class extends BaseRenderer {
1731
1832
  async render(context) {
@@ -1790,6 +1891,11 @@ var GuidePreviewController = class {
1790
1891
  this.input = null;
1791
1892
  }
1792
1893
  preview(input) {
1894
+ const nextStep = input.guideSteps[0];
1895
+ if (this.singleStep && this.input && input.guideType === this.input.guideType && input.guideType !== "walkthrough" && nextStep && this.singleStep.updateStep(nextStep)) {
1896
+ this.input = input;
1897
+ return { close: () => this.close(), ready: Promise.resolve({ rendered: true }) };
1898
+ }
1793
1899
  this.close();
1794
1900
  this.input = input;
1795
1901
  const guide = normalize(input);
@@ -2351,7 +2457,7 @@ var ElementPicker = class {
2351
2457
  this.label.style.display = "none";
2352
2458
  const hint = document.createElement("div");
2353
2459
  hint.className = "veo-pick-hint";
2354
- hint.textContent = options.hint ?? "Seleccion\xE1 un elemento \xB7 Esc para cancelar";
2460
+ hint.textContent = options.hint ?? "Selecciona un elemento \xB7 Esc para cancelar";
2355
2461
  shadow.append(style, this.box, this.label, hint);
2356
2462
  document.body.appendChild(host);
2357
2463
  this.host = host;