veo-sdk 0.6.0 → 0.6.2

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.
Files changed (34) hide show
  1. package/dist/builder-ENKEIVF2.mjs +5 -0
  2. package/dist/{builder-3QPHB2VJ.mjs.map → builder-ENKEIVF2.mjs.map} +1 -1
  3. package/dist/builder.cjs +366 -20
  4. package/dist/builder.cjs.map +1 -1
  5. package/dist/builder.d.cts +2 -2
  6. package/dist/builder.d.ts +2 -2
  7. package/dist/builder.mjs +4 -4
  8. package/dist/{chunk-N4VFMZFA.mjs → chunk-4QZDNJJE.mjs} +3 -3
  9. package/dist/{chunk-N4VFMZFA.mjs.map → chunk-4QZDNJJE.mjs.map} +1 -1
  10. package/dist/{chunk-GMXQMZ4X.mjs → chunk-L3QQJLDJ.mjs} +3 -3
  11. package/dist/{chunk-GMXQMZ4X.mjs.map → chunk-L3QQJLDJ.mjs.map} +1 -1
  12. package/dist/{chunk-O6USA4TU.mjs → chunk-ZILDR4YE.mjs} +368 -22
  13. package/dist/chunk-ZILDR4YE.mjs.map +1 -0
  14. package/dist/detect-theme-X4K3TLUL.mjs +446 -0
  15. package/dist/detect-theme-X4K3TLUL.mjs.map +1 -0
  16. package/dist/{guide-preview-DylsEhrg.d.cts → guide-preview-DEFhfA4o.d.cts} +115 -0
  17. package/dist/{guide-preview-DylsEhrg.d.ts → guide-preview-DEFhfA4o.d.ts} +115 -0
  18. package/dist/index.cjs +994 -51
  19. package/dist/index.cjs.map +1 -1
  20. package/dist/index.d.cts +13 -1
  21. package/dist/index.d.ts +13 -1
  22. package/dist/index.mjs +141 -16
  23. package/dist/index.mjs.map +1 -1
  24. package/dist/veo-builder.js +92 -20
  25. package/dist/veo-builder.js.map +1 -1
  26. package/dist/veo-guides.js +84 -12
  27. package/dist/veo-guides.js.map +1 -1
  28. package/dist/veo-theme.js +2 -0
  29. package/dist/veo-theme.js.map +1 -0
  30. package/dist/veo.js +2 -2
  31. package/dist/veo.js.map +1 -1
  32. package/package.json +2 -2
  33. package/dist/builder-3QPHB2VJ.mjs +0 -5
  34. package/dist/chunk-O6USA4TU.mjs.map +0 -1
@@ -0,0 +1,5 @@
1
+ export { VEO_BLOCK_MIME, attachBlockDropTarget, attachDesignManipulator, createBuilderSession, initBuilderMode, startElementPicker, stopElementPicker } from './chunk-4QZDNJJE.mjs';
2
+ import './chunk-ZILDR4YE.mjs';
3
+ import './chunk-PTG3BTJE.mjs';
4
+ //# sourceMappingURL=builder-ENKEIVF2.mjs.map
5
+ //# sourceMappingURL=builder-ENKEIVF2.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"builder-3QPHB2VJ.mjs"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"builder-ENKEIVF2.mjs"}
package/dist/builder.cjs CHANGED
@@ -756,6 +756,10 @@ var TEXT_PRESETS = {
756
756
  small: { size: 12, weight: 400, lineHeight: 1.5 }
757
757
  };
758
758
  function applyBlockStyle(el2, style, kind) {
759
+ if (kind === "text") {
760
+ const explicit = style && typeof style === "object" ? style.preset : void 0;
761
+ el2.dataset.veoPreset = typeof explicit === "string" ? explicit : el2.classList.contains("veo-guide-title") ? "title" : "paragraph";
762
+ }
759
763
  if (!style || typeof style !== "object") return;
760
764
  const s = style;
761
765
  if (kind === "image" && s.bleed === true) {
@@ -772,8 +776,9 @@ function applyBlockStyle(el2, style, kind) {
772
776
  if (kind === "text" && typeof s.preset === "string" && s.preset in TEXT_PRESETS) {
773
777
  const preset = TEXT_PRESETS[s.preset];
774
778
  if (preset) {
775
- el2.style.fontSize = `${preset.size}px`;
776
- el2.style.fontWeight = String(preset.weight);
779
+ const token = s.preset === "small" ? null : `--veo-t-${s.preset}`;
780
+ el2.style.fontSize = token ? `var(${token}-size, ${preset.size}px)` : `${preset.size}px`;
781
+ el2.style.fontWeight = token ? `var(${token}-weight, ${preset.weight})` : String(preset.weight);
777
782
  el2.style.lineHeight = String(preset.lineHeight);
778
783
  }
779
784
  }
@@ -1710,20 +1715,92 @@ var GUIDE_STYLES = `
1710
1715
  .veo-guide-actions {
1711
1716
  display: flex; gap: 8px; justify-content: var(--veo-actions-justify);
1712
1717
  }
1718
+ /* Tema del workspace (design system): cada preset de texto toma sus tokens de
1719
+ las variables que publica \`applyThemeVars\` en la tarjeta. Las reglas solo
1720
+ existen bajo .veo-card--themed; los estilos inline del bloque las pisan. El
1721
+ \`*\` cubre el rich text (la regla global de fuente aplica a cada hijo). */
1722
+ .veo-card--themed [data-veo-preset="title"] {
1723
+ color: var(--veo-t-title-color); font-size: var(--veo-t-title-size);
1724
+ font-weight: var(--veo-t-title-weight); text-align: var(--veo-t-title-align);
1725
+ }
1726
+ .veo-card--themed [data-veo-preset="subtitle"] {
1727
+ color: var(--veo-t-subtitle-color); font-size: var(--veo-t-subtitle-size);
1728
+ font-weight: var(--veo-t-subtitle-weight); text-align: var(--veo-t-subtitle-align);
1729
+ }
1730
+ .veo-card--themed [data-veo-preset="paragraph"] {
1731
+ color: var(--veo-t-paragraph-color); font-size: var(--veo-t-paragraph-size);
1732
+ font-weight: var(--veo-t-paragraph-weight); text-align: var(--veo-t-paragraph-align);
1733
+ }
1734
+ .veo-card--themed [data-veo-preset="small"] { color: var(--veo-t-paragraph-color); }
1735
+ .veo-card--themed [data-veo-preset="title"], .veo-card--themed [data-veo-preset="title"] * {
1736
+ font-family: var(--veo-t-title-font, var(--veo-font));
1737
+ }
1738
+ .veo-card--themed [data-veo-preset="subtitle"], .veo-card--themed [data-veo-preset="subtitle"] * {
1739
+ font-family: var(--veo-t-subtitle-font, var(--veo-font));
1740
+ }
1741
+ .veo-card--themed [data-veo-preset="paragraph"], .veo-card--themed [data-veo-preset="paragraph"] *,
1742
+ .veo-card--themed [data-veo-preset="small"], .veo-card--themed [data-veo-preset="small"] * {
1743
+ font-family: var(--veo-t-paragraph-font, var(--veo-font));
1744
+ }
1745
+ /* Formulario del tema (pesta\xF1a Formulario). Dentro de un .veo-form los tokens
1746
+ de texto \`--veo-t-*\` se REDEFINEN con \xABTexto principal\xBB: la pregunta es un
1747
+ bloque con preset (su tama\xF1o va inline con esas variables), as\xED toma los del
1748
+ formulario y no los del modal. Etiquetas y opciones = \xABTexto secundario\xBB. */
1749
+ .veo-card--themed-form .veo-form {
1750
+ background: var(--veo-f-bg); padding: var(--veo-f-pad);
1751
+ border: var(--veo-f-border, none); border-radius: var(--veo-f-radius, 8px);
1752
+ box-shadow: var(--veo-f-shadow, none);
1753
+ --veo-t-title-color: var(--veo-f-primary-color); --veo-t-title-size: var(--veo-f-primary-size);
1754
+ --veo-t-title-weight: var(--veo-f-primary-weight); --veo-t-title-align: var(--veo-f-primary-align);
1755
+ --veo-t-title-font: var(--veo-f-primary-font);
1756
+ --veo-t-subtitle-color: var(--veo-f-primary-color); --veo-t-subtitle-size: var(--veo-f-primary-size);
1757
+ --veo-t-subtitle-weight: var(--veo-f-primary-weight); --veo-t-subtitle-align: var(--veo-f-primary-align);
1758
+ --veo-t-subtitle-font: var(--veo-f-primary-font);
1759
+ --veo-t-paragraph-color: var(--veo-f-primary-color); --veo-t-paragraph-size: var(--veo-f-primary-size);
1760
+ --veo-t-paragraph-weight: var(--veo-f-primary-weight); --veo-t-paragraph-align: var(--veo-f-primary-align);
1761
+ --veo-t-paragraph-font: var(--veo-f-primary-font);
1762
+ }
1763
+ .veo-card--themed-form .veo-form-label,
1764
+ .veo-card--themed-form .veo-form-option,
1765
+ .veo-card--themed-form .veo-scale-label {
1766
+ color: var(--veo-f-secondary-color); font-weight: var(--veo-f-secondary-weight);
1767
+ font-family: var(--veo-f-secondary-font, var(--veo-font));
1768
+ }
1769
+ .veo-card--themed-form .veo-form-label,
1770
+ .veo-card--themed-form .veo-form-option {
1771
+ font-size: var(--veo-f-secondary-size); text-align: var(--veo-f-secondary-align);
1772
+ }
1773
+ .veo-card--themed-form .veo-form-input:focus { outline-color: var(--veo-f-accent); }
1774
+ .veo-card--themed-form .veo-form-option input { accent-color: var(--veo-f-accent); }
1775
+ .veo-card--themed-form .veo-nps-btn:hover { border-color: var(--veo-scale-color, var(--veo-f-accent)); }
1776
+ .veo-card--themed-form .veo-scale-active.veo-nps-btn {
1777
+ background: var(--veo-scale-color, var(--veo-f-accent)); color: var(--veo-f-on-accent);
1778
+ border-color: var(--veo-scale-color, var(--veo-f-accent));
1779
+ }
1713
1780
  .veo-guide-cta {
1714
1781
  background: var(--veo-cta-bg, var(--veo-primary));
1715
- color: var(--veo-cta-color, #fff); border: none;
1716
- padding: 9px 18px; border-radius: var(--veo-cta-radius, 8px);
1717
- font-size: var(--veo-cta-size, 14px); font-weight: 500; cursor: pointer;
1782
+ color: var(--veo-cta-color, #fff); border: var(--veo-cta-border, none);
1783
+ padding: var(--veo-cta-pad, 9px 18px); border-radius: var(--veo-cta-radius, 8px);
1784
+ font-size: var(--veo-cta-size, 14px); font-weight: var(--veo-cta-weight, 500); cursor: pointer;
1718
1785
  transition: opacity 120ms ease;
1719
1786
  }
1720
1787
  .veo-guide-cta:hover { opacity: 0.9; }
1721
1788
  /* Presets del boton (editor): secundario = contorno; enlace = solo texto. */
1722
1789
  .veo-guide-cta--secondary {
1723
- background: transparent; color: var(--veo-primary);
1724
- border: 1px solid var(--veo-primary);
1790
+ background: var(--veo-cta2-bg, transparent); color: var(--veo-cta2-color, var(--veo-primary));
1791
+ border: var(--veo-cta2-border, 1px solid var(--veo-primary));
1792
+ padding: var(--veo-cta2-pad, var(--veo-cta-pad, 9px 18px));
1793
+ border-radius: var(--veo-cta2-radius, var(--veo-cta-radius, 8px));
1794
+ font-size: var(--veo-cta2-size, var(--veo-cta-size, 14px));
1795
+ font-weight: var(--veo-cta2-weight, var(--veo-cta-weight, 500));
1796
+ }
1797
+ .veo-guide-cta--link {
1798
+ background: transparent; color: var(--veo-cta3-color, var(--veo-primary));
1799
+ border: var(--veo-cta3-border, none); padding: var(--veo-cta3-pad, 0);
1800
+ border-radius: var(--veo-cta3-radius, 0);
1801
+ font-size: var(--veo-cta3-size, var(--veo-cta-size, 14px));
1802
+ font-weight: var(--veo-cta3-weight, var(--veo-cta-weight, 500));
1725
1803
  }
1726
- .veo-guide-cta--link { background: transparent; color: var(--veo-primary); padding: 0; }
1727
1804
  .veo-guide-cta--link:hover { opacity: 1; text-decoration: underline; }
1728
1805
  .veo-guide-cta:active { transform: translateY(1px); }
1729
1806
  .veo-guide-close {
@@ -2093,6 +2170,12 @@ var STATIC_SIDE = {
2093
2170
  left: "right",
2094
2171
  right: "left"
2095
2172
  };
2173
+ var OUTER_EDGES = {
2174
+ top: ["top", "left"],
2175
+ right: ["top", "right"],
2176
+ bottom: ["bottom", "right"],
2177
+ left: ["bottom", "left"]
2178
+ };
2096
2179
  function positionArrow(arrowEl, placement, data) {
2097
2180
  const side = STATIC_SIDE[placement.split("-")[0] ?? "bottom"] ?? "top";
2098
2181
  for (const prop of ["top", "bottom", "left", "right"]) {
@@ -2101,6 +2184,16 @@ function positionArrow(arrowEl, placement, data) {
2101
2184
  if (data?.x != null) arrowEl.style.setProperty("left", `${data.x}px`);
2102
2185
  if (data?.y != null) arrowEl.style.setProperty("top", `${data.y}px`);
2103
2186
  arrowEl.style.setProperty(side, "-6px");
2187
+ const width = arrowEl.dataset.veoBorder;
2188
+ if (width) {
2189
+ for (const edge of ["top", "right", "bottom", "left"]) {
2190
+ arrowEl.style.setProperty(
2191
+ `border-${edge}-width`,
2192
+ OUTER_EDGES[side].includes(edge) ? `${width}px` : "0"
2193
+ );
2194
+ }
2195
+ arrowEl.style.zIndex = "1";
2196
+ }
2104
2197
  }
2105
2198
 
2106
2199
  // src/plugins/guides/renderers/badge-renderer.ts
@@ -2989,6 +3082,168 @@ function buildScale(wrapper, doc, min, max, btnClass, symbol, opts = { labels: [
2989
3082
  return { wrapper, read: () => selected };
2990
3083
  }
2991
3084
 
3085
+ // src/plugins/guides/guide-theme.ts
3086
+ var WORKSPACE_THEME_ID = "workspace";
3087
+ var SHADOW_SPEC = {
3088
+ soft: { y: 4, blur: 14, alpha: 0.12 },
3089
+ medium: { y: 12, blur: 32, alpha: 0.22 },
3090
+ strong: { y: 24, blur: 64, alpha: 0.38 }
3091
+ };
3092
+ var JUSTIFY = {
3093
+ left: "flex-start",
3094
+ center: "center",
3095
+ right: "flex-end",
3096
+ distribute: "space-between"
3097
+ };
3098
+ function channels(hex) {
3099
+ const h = hex.replace("#", "");
3100
+ const full = h.length === 3 ? [...h].map((x) => x + x).join("") : h.slice(0, 6);
3101
+ const ch = (i) => Number.parseInt(full.slice(i, i + 2), 16) || 0;
3102
+ return [ch(0), ch(2), ch(4)];
3103
+ }
3104
+ function boxShadow(shadow, hex) {
3105
+ if (shadow === "none") return "none";
3106
+ const spec = SHADOW_SPEC[shadow];
3107
+ const [r, g, b] = channels(hex);
3108
+ return `0 ${spec.y}px ${spec.blur}px rgba(${r}, ${g}, ${b}, ${spec.alpha})`;
3109
+ }
3110
+ function readableOn(hex) {
3111
+ const [r, g, b] = channels(hex);
3112
+ return (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255 > 0.6 ? "#111827" : "#ffffff";
3113
+ }
3114
+ function themeModeFor(theme, design) {
3115
+ if (!theme || design.theme !== WORKSPACE_THEME_ID) return null;
3116
+ return (design.colorMode === "dark" ? theme.dark : theme.light) ?? null;
3117
+ }
3118
+ function themeRowJustify(mode, inline, preset) {
3119
+ const box = inline ? mode.embedded : mode.overlay;
3120
+ if (box.align === "distribute") return null;
3121
+ const button = preset === "secondary" ? mode.buttons?.secondary : preset === "link" ? mode.buttons?.tertiary : preset === void 0 || preset === null || preset === "primary" ? mode.buttons?.primary : void 0;
3122
+ return button ? JUSTIFY[button.align] ?? null : null;
3123
+ }
3124
+ function appFont(ref, doc) {
3125
+ const view = doc.defaultView;
3126
+ if (!view) return null;
3127
+ if (ref === "inherit") return view.getComputedStyle(doc.body).fontFamily || null;
3128
+ if (ref === "app-heading") {
3129
+ const heading = Array.from(doc.querySelectorAll("h1,h2,h3")).find(
3130
+ (el2) => el2.getClientRects().length > 0
3131
+ );
3132
+ return view.getComputedStyle(heading ?? doc.body).fontFamily || null;
3133
+ }
3134
+ return ref;
3135
+ }
3136
+ function themeContainerDesign(mode, inline, tooltip = false) {
3137
+ const box = inline ? mode.embedded : mode.overlay;
3138
+ const tip = tooltip ? mode.tooltip : void 0;
3139
+ const padding = tip?.padding ?? box.padding;
3140
+ const out = {
3141
+ // El embebido va en el flujo de la página: sin fondo propio.
3142
+ background: tip ? tip.background : inline ? "transparent" : box.background ?? mode.colors.background,
3143
+ color: mode.colors.text,
3144
+ paddingTop: padding.top,
3145
+ paddingRight: padding.right,
3146
+ paddingBottom: padding.bottom,
3147
+ paddingLeft: padding.left,
3148
+ borderColor: tip?.borderColor ?? box.borderColor,
3149
+ borderWidth: tip?.borderWidth ?? box.borderWidth,
3150
+ radius: tip?.borderRadius ?? box.borderRadius
3151
+ };
3152
+ const shadow = tip?.shadow ?? box.shadow;
3153
+ const shadowColor = tip?.shadowColor ?? box.shadowColor;
3154
+ if (shadow === "none") {
3155
+ Object.assign(out, { shadowColor: "transparent", shadowBlur: 0 });
3156
+ } else {
3157
+ const spec = SHADOW_SPEC[shadow];
3158
+ const [r, g, b] = channels(shadowColor);
3159
+ Object.assign(out, {
3160
+ shadowX: 0,
3161
+ shadowY: spec.y,
3162
+ shadowBlur: spec.blur,
3163
+ shadowSpread: 0,
3164
+ shadowColor: `rgba(${r}, ${g}, ${b}, ${spec.alpha})`
3165
+ });
3166
+ }
3167
+ return out;
3168
+ }
3169
+ function applyThemeVars(card, mode, inline, tooltip = false) {
3170
+ const doc = card.ownerDocument ?? document;
3171
+ const box = inline ? mode.embedded : mode.overlay;
3172
+ const set = (name, value) => {
3173
+ if (value) card.style.setProperty(name, value);
3174
+ };
3175
+ card.classList.add("veo-card--themed");
3176
+ set("--veo-primary", mode.colors.accent);
3177
+ set("--veo-cta-color", readableOn(mode.colors.accent));
3178
+ const primary = mode.buttons?.primary;
3179
+ const publish = (prefix, b) => {
3180
+ if (!b) return;
3181
+ const p = b.padding;
3182
+ set(`${prefix}-bg`, b.background);
3183
+ set(`${prefix}-color`, b.color);
3184
+ set(`${prefix}-pad`, `${p.top}px ${p.right}px ${p.bottom}px ${p.left}px`);
3185
+ set(`${prefix}-size`, `${b.fontSize}px`);
3186
+ set(`${prefix}-weight`, String(b.fontWeight));
3187
+ set(`${prefix}-radius`, `${b.borderRadius}px`);
3188
+ set(
3189
+ `${prefix}-border`,
3190
+ b.borderWidth > 0 ? `${b.borderWidth}px solid ${b.borderColor}` : "none"
3191
+ );
3192
+ };
3193
+ publish("--veo-cta", primary);
3194
+ publish("--veo-cta2", mode.buttons?.secondary);
3195
+ publish("--veo-cta3", mode.buttons?.tertiary);
3196
+ set("--veo-text", mode.colors.text);
3197
+ set("--veo-text-secondary", mode.colors.textMuted);
3198
+ set("--veo-font", appFont("inherit", doc));
3199
+ set(
3200
+ "--veo-actions-justify",
3201
+ box.align === "distribute" || !primary ? JUSTIFY[box.align] : JUSTIFY[primary.align]
3202
+ );
3203
+ const form = mode.form;
3204
+ if (form) {
3205
+ card.classList.add("veo-card--themed-form");
3206
+ const fp = form.padding;
3207
+ set("--veo-f-bg", form.background);
3208
+ set("--veo-f-accent", form.accent);
3209
+ set("--veo-f-on-accent", form.onAccent);
3210
+ set("--veo-f-pad", `${fp.top}px ${fp.right}px ${fp.bottom}px ${fp.left}px`);
3211
+ if (typeof form.borderWidth === "number" && form.borderColor) {
3212
+ set(
3213
+ "--veo-f-border",
3214
+ form.borderWidth > 0 ? `${form.borderWidth}px solid ${form.borderColor}` : "none"
3215
+ );
3216
+ }
3217
+ if (typeof form.borderRadius === "number") set("--veo-f-radius", `${form.borderRadius}px`);
3218
+ if (form.shadow && form.shadowColor) {
3219
+ set("--veo-f-shadow", boxShadow(form.shadow, form.shadowColor));
3220
+ }
3221
+ for (const [name, t] of [
3222
+ ["primary", form.text.primary],
3223
+ ["secondary", form.text.secondary]
3224
+ ]) {
3225
+ set(`--veo-f-${name}-color`, t.color);
3226
+ set(`--veo-f-${name}-size`, `${t.fontSize}px`);
3227
+ set(`--veo-f-${name}-weight`, String(t.fontWeight));
3228
+ set(`--veo-f-${name}-align`, t.align);
3229
+ set(`--veo-f-${name}-font`, appFont(t.fontFamily, doc));
3230
+ }
3231
+ }
3232
+ const tip = tooltip ? mode.tooltip?.text : void 0;
3233
+ const tokens = [
3234
+ ["title", tip?.primary ?? mode.text.title],
3235
+ ["subtitle", tip?.secondary ?? mode.text.subtitle],
3236
+ ["paragraph", tip?.secondary ?? mode.text.paragraph]
3237
+ ];
3238
+ for (const [name, t] of tokens) {
3239
+ set(`--veo-t-${name}-color`, t.color);
3240
+ set(`--veo-t-${name}-size`, `${t.fontSize}px`);
3241
+ set(`--veo-t-${name}-weight`, String(t.fontWeight));
3242
+ set(`--veo-t-${name}-align`, t.align);
3243
+ set(`--veo-t-${name}-font`, appFont(t.fontFamily, doc));
3244
+ }
3245
+ }
3246
+
2992
3247
  // src/plugins/guides/layout.ts
2993
3248
  function groupLayout(blocks) {
2994
3249
  const rows = /* @__PURE__ */ new Map();
@@ -3238,13 +3493,83 @@ function markerOffset(anchor, marker, position, offset6) {
3238
3493
  }
3239
3494
  return { x: x + offset6.x, y: y + offset6.y };
3240
3495
  }
3496
+ var NO_CHILDREN = /* @__PURE__ */ new Set([
3497
+ "img",
3498
+ "input",
3499
+ "textarea",
3500
+ "select",
3501
+ "iframe",
3502
+ "video",
3503
+ "audio",
3504
+ "canvas",
3505
+ "br",
3506
+ "hr",
3507
+ "svg",
3508
+ "object",
3509
+ "embed"
3510
+ ]);
3511
+ function canNest(anchor) {
3512
+ const win = anchor.ownerDocument.defaultView;
3513
+ if (!win || !(anchor instanceof win.HTMLElement)) return false;
3514
+ if (NO_CHILDREN.has(anchor.tagName.toLowerCase())) return false;
3515
+ const cs = win.getComputedStyle(anchor);
3516
+ if (cs.display === "contents") return false;
3517
+ const tokens = `${cs.overflow} ${cs.overflowX} ${cs.overflowY}`.split(/\s+/).filter(Boolean);
3518
+ return tokens.every((t) => t === "visible");
3519
+ }
3241
3520
  function attachMarker(anchor, host, marker) {
3242
3521
  host.style.position = "absolute";
3243
3522
  host.style.zIndex = String(num(marker.zIndex, DEFAULT_MARKER_Z));
3244
3523
  host.style.margin = "0";
3524
+ const position = marker.position ?? "top-right";
3525
+ const offset6 = { x: num(marker.offsetX, 0), y: num(marker.offsetY, 0) };
3526
+ const markerSize = () => {
3527
+ const m = host.getBoundingClientRect();
3528
+ return { width: m.width, height: m.height };
3529
+ };
3530
+ if (canNest(anchor)) {
3531
+ const win = anchor.ownerDocument.defaultView;
3532
+ const prevPosition = anchor.style.position;
3533
+ const computed = win.getComputedStyle(anchor).position;
3534
+ if (!computed || computed === "static") anchor.style.position = "relative";
3535
+ anchor.appendChild(host);
3536
+ const swallowClick = (e) => {
3537
+ e.preventDefault();
3538
+ e.stopPropagation();
3539
+ };
3540
+ const swallow = (e) => e.stopPropagation();
3541
+ host.addEventListener("click", swallowClick);
3542
+ host.addEventListener("pointerdown", swallow);
3543
+ host.addEventListener("mousedown", swallow);
3544
+ const update2 = () => {
3545
+ const { x, y } = markerOffset(
3546
+ {
3547
+ left: -anchor.clientLeft,
3548
+ top: -anchor.clientTop,
3549
+ width: anchor.offsetWidth,
3550
+ height: anchor.offsetHeight
3551
+ },
3552
+ markerSize(),
3553
+ position,
3554
+ offset6
3555
+ );
3556
+ host.style.left = `${Math.round(x)}px`;
3557
+ host.style.top = `${Math.round(y)}px`;
3558
+ };
3559
+ update2();
3560
+ const stop2 = dom.autoUpdate(anchor, host, update2, { ancestorScroll: false, layoutShift: false });
3561
+ return () => {
3562
+ stop2();
3563
+ host.removeEventListener("click", swallowClick);
3564
+ host.removeEventListener("pointerdown", swallow);
3565
+ host.removeEventListener("mousedown", swallow);
3566
+ host.remove();
3567
+ anchor.style.position = prevPosition;
3568
+ };
3569
+ }
3570
+ anchor.ownerDocument.body.appendChild(host);
3245
3571
  const update = () => {
3246
3572
  const a = anchor.getBoundingClientRect();
3247
- const m = host.getBoundingClientRect();
3248
3573
  const { x, y } = markerOffset(
3249
3574
  {
3250
3575
  left: a.left + window.scrollX,
@@ -3252,15 +3577,19 @@ function attachMarker(anchor, host, marker) {
3252
3577
  width: a.width,
3253
3578
  height: a.height
3254
3579
  },
3255
- { width: m.width, height: m.height },
3256
- marker.position ?? "top-right",
3257
- { x: num(marker.offsetX, 0), y: num(marker.offsetY, 0) }
3580
+ markerSize(),
3581
+ position,
3582
+ offset6
3258
3583
  );
3259
3584
  host.style.left = `${Math.round(x)}px`;
3260
3585
  host.style.top = `${Math.round(y)}px`;
3261
3586
  };
3262
3587
  update();
3263
- return dom.autoUpdate(anchor, host, update);
3588
+ const stop = dom.autoUpdate(anchor, host, update);
3589
+ return () => {
3590
+ stop();
3591
+ host.remove();
3592
+ };
3264
3593
  }
3265
3594
 
3266
3595
  // src/plugins/guides/renderers/composite-renderer.ts
@@ -3296,6 +3625,11 @@ function applyRowStyle(rowEl, style) {
3296
3625
  if (style.valign && ROW_VALIGN[style.valign]) s.alignItems = ROW_VALIGN[style.valign];
3297
3626
  }
3298
3627
  var CompositeRenderer = class extends BaseRenderer {
3628
+ constructor() {
3629
+ super(...arguments);
3630
+ /** Alineación de filas de botones según el tema del workspace (null = sin tema). */
3631
+ this.themeRowJustify = null;
3632
+ }
3299
3633
  async render(context) {
3300
3634
  const idx = context.nav?.stepIndex ?? 0;
3301
3635
  const step = context.guide.guideSteps[idx];
@@ -3326,7 +3660,13 @@ var CompositeRenderer = class extends BaseRenderer {
3326
3660
  if (typeof design.zIndex === "number") host.style.zIndex = String(design.zIndex);
3327
3661
  const card = doc.createElement("div");
3328
3662
  card.className = "veo-card";
3329
- applyCompositeDesign(card, design);
3663
+ const themeMode = themeModeFor(context.guide.theme, design);
3664
+ const inline = step.presentation === "inline";
3665
+ const tooltipLike = !inline && (badgeMode || step.position === "relative-to-element");
3666
+ if (themeMode) applyThemeVars(card, themeMode, inline, tooltipLike);
3667
+ this.themeRowJustify = themeMode ? (preset) => themeRowJustify(themeMode, inline, preset) : null;
3668
+ const cardDesign = themeMode ? { ...themeContainerDesign(themeMode, inline, tooltipLike), ...design } : design;
3669
+ applyCompositeDesign(card, cardDesign);
3330
3670
  if (typeof design.ariaLabel === "string" && design.ariaLabel.trim()) {
3331
3671
  card.setAttribute("role", "dialog");
3332
3672
  card.setAttribute("aria-label", design.ariaLabel.trim());
@@ -3397,7 +3737,7 @@ var CompositeRenderer = class extends BaseRenderer {
3397
3737
  });
3398
3738
  }
3399
3739
  card.appendChild(closeBtn);
3400
- reserveCloseSpace(card, blocks, closePos, design);
3740
+ reserveCloseSpace(card, blocks, closePos, cardDesign);
3401
3741
  }
3402
3742
  if (badgeMode && anchor) {
3403
3743
  closeTooltip = this.renderBadgeMode(
@@ -3410,7 +3750,8 @@ var CompositeRenderer = class extends BaseRenderer {
3410
3750
  doc,
3411
3751
  context,
3412
3752
  idx,
3413
- design
3753
+ // Con el tema ya fundido: la flecha del tooltip toma su fondo y borde.
3754
+ cardDesign
3414
3755
  );
3415
3756
  return;
3416
3757
  }
@@ -3433,7 +3774,7 @@ var CompositeRenderer = class extends BaseRenderer {
3433
3774
  }
3434
3775
  const wrapper = doc.createElement("div");
3435
3776
  wrapper.className = "veo-composite-anchored";
3436
- const caretEl = design.caret === false ? null : makeCaret(doc, design);
3777
+ const caretEl = design.caret === false ? null : makeCaret(doc, cardDesign);
3437
3778
  if (caretEl) wrapper.appendChild(caretEl);
3438
3779
  wrapper.appendChild(card);
3439
3780
  root.appendChild(wrapper);
@@ -3493,6 +3834,7 @@ var CompositeRenderer = class extends BaseRenderer {
3493
3834
  const row = doc.createElement("div");
3494
3835
  row.className = "veo-guide-actions";
3495
3836
  let rowAlign;
3837
+ const firstPreset = b.style?.preset;
3496
3838
  while (i < cell.length && cell[i]?.block.type === "button") {
3497
3839
  const { block: bb, index: bi } = cell[i];
3498
3840
  if (!rowAlign) {
@@ -3503,6 +3845,10 @@ var CompositeRenderer = class extends BaseRenderer {
3503
3845
  i++;
3504
3846
  }
3505
3847
  if (rowAlign) row.style.justifyContent = ROW_ALIGN[rowAlign] ?? "flex-end";
3848
+ else {
3849
+ const themed = this.themeRowJustify?.(firstPreset);
3850
+ if (themed) row.style.justifyContent = themed;
3851
+ }
3506
3852
  container.appendChild(row);
3507
3853
  continue;
3508
3854
  }
@@ -3789,9 +4135,7 @@ var CompositeRenderer = class extends BaseRenderer {
3789
4135
  root.appendChild(wrapper);
3790
4136
  if (marker) {
3791
4137
  host.style.display = "inline-block";
3792
- (anchor.ownerDocument ?? document).body.appendChild(host);
3793
4138
  this.registerCleanup(attachMarker(anchor, host, marker));
3794
- this.registerCleanup(() => host.remove());
3795
4139
  } else {
3796
4140
  host.style.display = "inline-block";
3797
4141
  const pos = inlinePosOf(step.inlinePosition);
@@ -3917,6 +4261,7 @@ function makeCaret(doc, design) {
3917
4261
  if (typeof design.borderWidth === "number" && design.borderWidth > 0) {
3918
4262
  const bc = typeof design.borderColor === "string" ? design.borderColor : "#bbbbbb";
3919
4263
  s.border = `${design.borderWidth}px solid ${bc}`;
4264
+ caret.dataset.veoBorder = String(design.borderWidth);
3920
4265
  }
3921
4266
  return caret;
3922
4267
  }
@@ -4651,7 +4996,8 @@ function normalize(input) {
4651
4996
  guideSteps: input.guideSteps,
4652
4997
  activationRules,
4653
4998
  displayFrequency: "always",
4654
- displayPriority: 0
4999
+ displayPriority: 0,
5000
+ ...input.theme ? { theme: input.theme } : {}
4655
5001
  };
4656
5002
  }
4657
5003
  function createSingleStepRenderer(type) {