veo-sdk 0.6.1 → 0.6.3
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/builder-PPLIAUCM.mjs +5 -0
- package/dist/{builder-BKPMANUB.mjs.map → builder-PPLIAUCM.mjs.map} +1 -1
- package/dist/builder.cjs +641 -105
- package/dist/builder.cjs.map +1 -1
- package/dist/builder.d.cts +78 -8
- package/dist/builder.d.ts +78 -8
- package/dist/builder.mjs +4 -4
- package/dist/{chunk-GVPAJFNW.mjs → chunk-3JEAPZ6A.mjs} +3 -3
- package/dist/{chunk-GVPAJFNW.mjs.map → chunk-3JEAPZ6A.mjs.map} +1 -1
- package/dist/{chunk-VWF4UHUU.mjs → chunk-DU6I4ZU2.mjs} +284 -15
- package/dist/chunk-DU6I4ZU2.mjs.map +1 -0
- package/dist/{chunk-NGP7IJVE.mjs → chunk-SZCIXA5X.mjs} +357 -82
- package/dist/chunk-SZCIXA5X.mjs.map +1 -0
- package/dist/detect-theme-X4K3TLUL.mjs +446 -0
- package/dist/detect-theme-X4K3TLUL.mjs.map +1 -0
- package/dist/{guide-preview-DylsEhrg.d.cts → guide-preview-DEFhfA4o.d.cts} +115 -0
- package/dist/{guide-preview-DylsEhrg.d.ts → guide-preview-DEFhfA4o.d.ts} +115 -0
- package/dist/index.cjs +1515 -56
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -1
- package/dist/index.d.ts +18 -1
- package/dist/index.mjs +442 -17
- package/dist/index.mjs.map +1 -1
- package/dist/veo-builder.js +132 -25
- package/dist/veo-builder.js.map +1 -1
- package/dist/veo-guides.js +84 -12
- package/dist/veo-guides.js.map +1 -1
- package/dist/veo-theme.js +2 -0
- package/dist/veo-theme.js.map +1 -0
- package/dist/veo.js +2 -2
- package/dist/veo.js.map +1 -1
- package/package.json +2 -2
- package/dist/builder-BKPMANUB.mjs +0 -5
- package/dist/chunk-NGP7IJVE.mjs.map +0 -1
- package/dist/chunk-VWF4UHUU.mjs.map +0 -1
package/dist/builder.cjs
CHANGED
|
@@ -283,6 +283,92 @@ function clearBuilderToken() {
|
|
|
283
283
|
}
|
|
284
284
|
}
|
|
285
285
|
|
|
286
|
+
// src/plugins/autocapture/constants.ts
|
|
287
|
+
var HASHED_CLASS_PATTERNS = [
|
|
288
|
+
/^css-[a-z0-9]{4,}$/i,
|
|
289
|
+
// emotion, styled-components nuevas
|
|
290
|
+
/^_[a-z0-9]+_[a-z0-9]{4,}_\d+$/,
|
|
291
|
+
// CSS Modules con hash
|
|
292
|
+
/^[a-z]{2,4}-[a-z0-9]{6,}$/i,
|
|
293
|
+
// Tailwind JIT (a veces)
|
|
294
|
+
/^[a-f0-9]{6,}$/i,
|
|
295
|
+
// hashes hex puros
|
|
296
|
+
/^sc-[a-z0-9]+$/i
|
|
297
|
+
// styled-components legacy
|
|
298
|
+
];
|
|
299
|
+
|
|
300
|
+
// src/plugins/autocapture/selector-builder.ts
|
|
301
|
+
function isHashedClass(className) {
|
|
302
|
+
return HASHED_CLASS_PATTERNS.some((pattern) => pattern.test(className));
|
|
303
|
+
}
|
|
304
|
+
function filterHumanClasses(element) {
|
|
305
|
+
return Array.from(element.classList).filter((c) => !isHashedClass(c) && c.length < 64);
|
|
306
|
+
}
|
|
307
|
+
var STABLE_ATTRIBUTES = [
|
|
308
|
+
"data-testid",
|
|
309
|
+
"data-test",
|
|
310
|
+
"data-cy",
|
|
311
|
+
"name",
|
|
312
|
+
"aria-label",
|
|
313
|
+
"placeholder",
|
|
314
|
+
"alt",
|
|
315
|
+
"title",
|
|
316
|
+
// `href` identifica muy bien a los links (`<a>`), un target frecuente de
|
|
317
|
+
// autocapture; va después de los atributos semánticos pero antes de los
|
|
318
|
+
// genéricos. Valores largos (URLs absolutas con query) se descartan por
|
|
319
|
+
// MAX_ATTR_VALUE_LENGTH.
|
|
320
|
+
"href",
|
|
321
|
+
"role",
|
|
322
|
+
"type"
|
|
323
|
+
];
|
|
324
|
+
var MAX_ATTR_VALUE_LENGTH = 100;
|
|
325
|
+
function cssEscape(value) {
|
|
326
|
+
if (typeof CSS !== "undefined" && typeof CSS.escape === "function") {
|
|
327
|
+
return CSS.escape(value);
|
|
328
|
+
}
|
|
329
|
+
return value.replace(/[!"#$%&'()*+,./:;<=>?@[\\\]^`{|}~]/g, "\\$&");
|
|
330
|
+
}
|
|
331
|
+
function escapeAttrValue(value) {
|
|
332
|
+
return value.replace(/[\\"]/g, "\\$&");
|
|
333
|
+
}
|
|
334
|
+
function stableAttributeSelector(element, tag) {
|
|
335
|
+
for (const attr of STABLE_ATTRIBUTES) {
|
|
336
|
+
const value = element.getAttribute(attr);
|
|
337
|
+
if (value && value.length > 0 && value.length <= MAX_ATTR_VALUE_LENGTH) {
|
|
338
|
+
return `${tag}[${attr}="${escapeAttrValue(value)}"]`;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
return null;
|
|
342
|
+
}
|
|
343
|
+
function buildElementSelector(element) {
|
|
344
|
+
const tag = element.tagName.toLowerCase();
|
|
345
|
+
const veoTag = element.getAttribute("data-veo-tag");
|
|
346
|
+
if (veoTag) {
|
|
347
|
+
return `${tag}[data-veo-tag="${escapeAttrValue(veoTag)}"]`;
|
|
348
|
+
}
|
|
349
|
+
if (element.id) {
|
|
350
|
+
const classes2 = filterHumanClasses(element);
|
|
351
|
+
const classPart2 = classes2.length > 0 ? `.${classes2.map(cssEscape).join(".")}` : "";
|
|
352
|
+
return `${tag}#${cssEscape(element.id)}${classPart2}`;
|
|
353
|
+
}
|
|
354
|
+
const attrSelector = stableAttributeSelector(element, tag);
|
|
355
|
+
if (attrSelector) return attrSelector;
|
|
356
|
+
const classes = filterHumanClasses(element);
|
|
357
|
+
const classPart = classes.length > 0 ? `.${classes.map(cssEscape).join(".")}` : "";
|
|
358
|
+
return `${tag}${classPart}`;
|
|
359
|
+
}
|
|
360
|
+
function buildSelectorPath(element, maxAncestors = 5) {
|
|
361
|
+
const parts = [];
|
|
362
|
+
let current = element;
|
|
363
|
+
let depth = 0;
|
|
364
|
+
while (current && current !== document.documentElement && depth <= maxAncestors) {
|
|
365
|
+
parts.unshift(buildElementSelector(current));
|
|
366
|
+
current = current.parentElement;
|
|
367
|
+
depth++;
|
|
368
|
+
}
|
|
369
|
+
return parts.join(" > ");
|
|
370
|
+
}
|
|
371
|
+
|
|
286
372
|
// src/plugins/guides/activation-devices.ts
|
|
287
373
|
var MOBILE_MAX_WIDTH = 767;
|
|
288
374
|
function isDeviceAllowed(devices, viewportWidth = typeof window === "undefined" ? 1024 : window.innerWidth) {
|
|
@@ -756,6 +842,10 @@ var TEXT_PRESETS = {
|
|
|
756
842
|
small: { size: 12, weight: 400, lineHeight: 1.5 }
|
|
757
843
|
};
|
|
758
844
|
function applyBlockStyle(el2, style, kind) {
|
|
845
|
+
if (kind === "text") {
|
|
846
|
+
const explicit = style && typeof style === "object" ? style.preset : void 0;
|
|
847
|
+
el2.dataset.veoPreset = typeof explicit === "string" ? explicit : el2.classList.contains("veo-guide-title") ? "title" : "paragraph";
|
|
848
|
+
}
|
|
759
849
|
if (!style || typeof style !== "object") return;
|
|
760
850
|
const s = style;
|
|
761
851
|
if (kind === "image" && s.bleed === true) {
|
|
@@ -772,8 +862,9 @@ function applyBlockStyle(el2, style, kind) {
|
|
|
772
862
|
if (kind === "text" && typeof s.preset === "string" && s.preset in TEXT_PRESETS) {
|
|
773
863
|
const preset = TEXT_PRESETS[s.preset];
|
|
774
864
|
if (preset) {
|
|
775
|
-
|
|
776
|
-
el2.style.
|
|
865
|
+
const token = s.preset === "small" ? null : `--veo-t-${s.preset}`;
|
|
866
|
+
el2.style.fontSize = token ? `var(${token}-size, ${preset.size}px)` : `${preset.size}px`;
|
|
867
|
+
el2.style.fontWeight = token ? `var(${token}-weight, ${preset.weight})` : String(preset.weight);
|
|
777
868
|
el2.style.lineHeight = String(preset.lineHeight);
|
|
778
869
|
}
|
|
779
870
|
}
|
|
@@ -1710,20 +1801,92 @@ var GUIDE_STYLES = `
|
|
|
1710
1801
|
.veo-guide-actions {
|
|
1711
1802
|
display: flex; gap: 8px; justify-content: var(--veo-actions-justify);
|
|
1712
1803
|
}
|
|
1804
|
+
/* Tema del workspace (design system): cada preset de texto toma sus tokens de
|
|
1805
|
+
las variables que publica \`applyThemeVars\` en la tarjeta. Las reglas solo
|
|
1806
|
+
existen bajo .veo-card--themed; los estilos inline del bloque las pisan. El
|
|
1807
|
+
\`*\` cubre el rich text (la regla global de fuente aplica a cada hijo). */
|
|
1808
|
+
.veo-card--themed [data-veo-preset="title"] {
|
|
1809
|
+
color: var(--veo-t-title-color); font-size: var(--veo-t-title-size);
|
|
1810
|
+
font-weight: var(--veo-t-title-weight); text-align: var(--veo-t-title-align);
|
|
1811
|
+
}
|
|
1812
|
+
.veo-card--themed [data-veo-preset="subtitle"] {
|
|
1813
|
+
color: var(--veo-t-subtitle-color); font-size: var(--veo-t-subtitle-size);
|
|
1814
|
+
font-weight: var(--veo-t-subtitle-weight); text-align: var(--veo-t-subtitle-align);
|
|
1815
|
+
}
|
|
1816
|
+
.veo-card--themed [data-veo-preset="paragraph"] {
|
|
1817
|
+
color: var(--veo-t-paragraph-color); font-size: var(--veo-t-paragraph-size);
|
|
1818
|
+
font-weight: var(--veo-t-paragraph-weight); text-align: var(--veo-t-paragraph-align);
|
|
1819
|
+
}
|
|
1820
|
+
.veo-card--themed [data-veo-preset="small"] { color: var(--veo-t-paragraph-color); }
|
|
1821
|
+
.veo-card--themed [data-veo-preset="title"], .veo-card--themed [data-veo-preset="title"] * {
|
|
1822
|
+
font-family: var(--veo-t-title-font, var(--veo-font));
|
|
1823
|
+
}
|
|
1824
|
+
.veo-card--themed [data-veo-preset="subtitle"], .veo-card--themed [data-veo-preset="subtitle"] * {
|
|
1825
|
+
font-family: var(--veo-t-subtitle-font, var(--veo-font));
|
|
1826
|
+
}
|
|
1827
|
+
.veo-card--themed [data-veo-preset="paragraph"], .veo-card--themed [data-veo-preset="paragraph"] *,
|
|
1828
|
+
.veo-card--themed [data-veo-preset="small"], .veo-card--themed [data-veo-preset="small"] * {
|
|
1829
|
+
font-family: var(--veo-t-paragraph-font, var(--veo-font));
|
|
1830
|
+
}
|
|
1831
|
+
/* Formulario del tema (pesta\xF1a Formulario). Dentro de un .veo-form los tokens
|
|
1832
|
+
de texto \`--veo-t-*\` se REDEFINEN con \xABTexto principal\xBB: la pregunta es un
|
|
1833
|
+
bloque con preset (su tama\xF1o va inline con esas variables), as\xED toma los del
|
|
1834
|
+
formulario y no los del modal. Etiquetas y opciones = \xABTexto secundario\xBB. */
|
|
1835
|
+
.veo-card--themed-form .veo-form {
|
|
1836
|
+
background: var(--veo-f-bg); padding: var(--veo-f-pad);
|
|
1837
|
+
border: var(--veo-f-border, none); border-radius: var(--veo-f-radius, 8px);
|
|
1838
|
+
box-shadow: var(--veo-f-shadow, none);
|
|
1839
|
+
--veo-t-title-color: var(--veo-f-primary-color); --veo-t-title-size: var(--veo-f-primary-size);
|
|
1840
|
+
--veo-t-title-weight: var(--veo-f-primary-weight); --veo-t-title-align: var(--veo-f-primary-align);
|
|
1841
|
+
--veo-t-title-font: var(--veo-f-primary-font);
|
|
1842
|
+
--veo-t-subtitle-color: var(--veo-f-primary-color); --veo-t-subtitle-size: var(--veo-f-primary-size);
|
|
1843
|
+
--veo-t-subtitle-weight: var(--veo-f-primary-weight); --veo-t-subtitle-align: var(--veo-f-primary-align);
|
|
1844
|
+
--veo-t-subtitle-font: var(--veo-f-primary-font);
|
|
1845
|
+
--veo-t-paragraph-color: var(--veo-f-primary-color); --veo-t-paragraph-size: var(--veo-f-primary-size);
|
|
1846
|
+
--veo-t-paragraph-weight: var(--veo-f-primary-weight); --veo-t-paragraph-align: var(--veo-f-primary-align);
|
|
1847
|
+
--veo-t-paragraph-font: var(--veo-f-primary-font);
|
|
1848
|
+
}
|
|
1849
|
+
.veo-card--themed-form .veo-form-label,
|
|
1850
|
+
.veo-card--themed-form .veo-form-option,
|
|
1851
|
+
.veo-card--themed-form .veo-scale-label {
|
|
1852
|
+
color: var(--veo-f-secondary-color); font-weight: var(--veo-f-secondary-weight);
|
|
1853
|
+
font-family: var(--veo-f-secondary-font, var(--veo-font));
|
|
1854
|
+
}
|
|
1855
|
+
.veo-card--themed-form .veo-form-label,
|
|
1856
|
+
.veo-card--themed-form .veo-form-option {
|
|
1857
|
+
font-size: var(--veo-f-secondary-size); text-align: var(--veo-f-secondary-align);
|
|
1858
|
+
}
|
|
1859
|
+
.veo-card--themed-form .veo-form-input:focus { outline-color: var(--veo-f-accent); }
|
|
1860
|
+
.veo-card--themed-form .veo-form-option input { accent-color: var(--veo-f-accent); }
|
|
1861
|
+
.veo-card--themed-form .veo-nps-btn:hover { border-color: var(--veo-scale-color, var(--veo-f-accent)); }
|
|
1862
|
+
.veo-card--themed-form .veo-scale-active.veo-nps-btn {
|
|
1863
|
+
background: var(--veo-scale-color, var(--veo-f-accent)); color: var(--veo-f-on-accent);
|
|
1864
|
+
border-color: var(--veo-scale-color, var(--veo-f-accent));
|
|
1865
|
+
}
|
|
1713
1866
|
.veo-guide-cta {
|
|
1714
1867
|
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;
|
|
1868
|
+
color: var(--veo-cta-color, #fff); border: var(--veo-cta-border, none);
|
|
1869
|
+
padding: var(--veo-cta-pad, 9px 18px); border-radius: var(--veo-cta-radius, 8px);
|
|
1870
|
+
font-size: var(--veo-cta-size, 14px); font-weight: var(--veo-cta-weight, 500); cursor: pointer;
|
|
1718
1871
|
transition: opacity 120ms ease;
|
|
1719
1872
|
}
|
|
1720
1873
|
.veo-guide-cta:hover { opacity: 0.9; }
|
|
1721
1874
|
/* Presets del boton (editor): secundario = contorno; enlace = solo texto. */
|
|
1722
1875
|
.veo-guide-cta--secondary {
|
|
1723
|
-
background: transparent; color: var(--veo-primary);
|
|
1724
|
-
border: 1px solid var(--veo-primary);
|
|
1876
|
+
background: var(--veo-cta2-bg, transparent); color: var(--veo-cta2-color, var(--veo-primary));
|
|
1877
|
+
border: var(--veo-cta2-border, 1px solid var(--veo-primary));
|
|
1878
|
+
padding: var(--veo-cta2-pad, var(--veo-cta-pad, 9px 18px));
|
|
1879
|
+
border-radius: var(--veo-cta2-radius, var(--veo-cta-radius, 8px));
|
|
1880
|
+
font-size: var(--veo-cta2-size, var(--veo-cta-size, 14px));
|
|
1881
|
+
font-weight: var(--veo-cta2-weight, var(--veo-cta-weight, 500));
|
|
1882
|
+
}
|
|
1883
|
+
.veo-guide-cta--link {
|
|
1884
|
+
background: transparent; color: var(--veo-cta3-color, var(--veo-primary));
|
|
1885
|
+
border: var(--veo-cta3-border, none); padding: var(--veo-cta3-pad, 0);
|
|
1886
|
+
border-radius: var(--veo-cta3-radius, 0);
|
|
1887
|
+
font-size: var(--veo-cta3-size, var(--veo-cta-size, 14px));
|
|
1888
|
+
font-weight: var(--veo-cta3-weight, var(--veo-cta-weight, 500));
|
|
1725
1889
|
}
|
|
1726
|
-
.veo-guide-cta--link { background: transparent; color: var(--veo-primary); padding: 0; }
|
|
1727
1890
|
.veo-guide-cta--link:hover { opacity: 1; text-decoration: underline; }
|
|
1728
1891
|
.veo-guide-cta:active { transform: translateY(1px); }
|
|
1729
1892
|
.veo-guide-close {
|
|
@@ -2093,6 +2256,12 @@ var STATIC_SIDE = {
|
|
|
2093
2256
|
left: "right",
|
|
2094
2257
|
right: "left"
|
|
2095
2258
|
};
|
|
2259
|
+
var OUTER_EDGES = {
|
|
2260
|
+
top: ["top", "left"],
|
|
2261
|
+
right: ["top", "right"],
|
|
2262
|
+
bottom: ["bottom", "right"],
|
|
2263
|
+
left: ["bottom", "left"]
|
|
2264
|
+
};
|
|
2096
2265
|
function positionArrow(arrowEl, placement, data) {
|
|
2097
2266
|
const side = STATIC_SIDE[placement.split("-")[0] ?? "bottom"] ?? "top";
|
|
2098
2267
|
for (const prop of ["top", "bottom", "left", "right"]) {
|
|
@@ -2101,6 +2270,16 @@ function positionArrow(arrowEl, placement, data) {
|
|
|
2101
2270
|
if (data?.x != null) arrowEl.style.setProperty("left", `${data.x}px`);
|
|
2102
2271
|
if (data?.y != null) arrowEl.style.setProperty("top", `${data.y}px`);
|
|
2103
2272
|
arrowEl.style.setProperty(side, "-6px");
|
|
2273
|
+
const width = arrowEl.dataset.veoBorder;
|
|
2274
|
+
if (width) {
|
|
2275
|
+
for (const edge of ["top", "right", "bottom", "left"]) {
|
|
2276
|
+
arrowEl.style.setProperty(
|
|
2277
|
+
`border-${edge}-width`,
|
|
2278
|
+
OUTER_EDGES[side].includes(edge) ? `${width}px` : "0"
|
|
2279
|
+
);
|
|
2280
|
+
}
|
|
2281
|
+
arrowEl.style.zIndex = "1";
|
|
2282
|
+
}
|
|
2104
2283
|
}
|
|
2105
2284
|
|
|
2106
2285
|
// src/plugins/guides/renderers/badge-renderer.ts
|
|
@@ -2989,6 +3168,168 @@ function buildScale(wrapper, doc, min, max, btnClass, symbol, opts = { labels: [
|
|
|
2989
3168
|
return { wrapper, read: () => selected };
|
|
2990
3169
|
}
|
|
2991
3170
|
|
|
3171
|
+
// src/plugins/guides/guide-theme.ts
|
|
3172
|
+
var WORKSPACE_THEME_ID = "workspace";
|
|
3173
|
+
var SHADOW_SPEC = {
|
|
3174
|
+
soft: { y: 4, blur: 14, alpha: 0.12 },
|
|
3175
|
+
medium: { y: 12, blur: 32, alpha: 0.22 },
|
|
3176
|
+
strong: { y: 24, blur: 64, alpha: 0.38 }
|
|
3177
|
+
};
|
|
3178
|
+
var JUSTIFY = {
|
|
3179
|
+
left: "flex-start",
|
|
3180
|
+
center: "center",
|
|
3181
|
+
right: "flex-end",
|
|
3182
|
+
distribute: "space-between"
|
|
3183
|
+
};
|
|
3184
|
+
function channels(hex) {
|
|
3185
|
+
const h = hex.replace("#", "");
|
|
3186
|
+
const full = h.length === 3 ? [...h].map((x) => x + x).join("") : h.slice(0, 6);
|
|
3187
|
+
const ch = (i) => Number.parseInt(full.slice(i, i + 2), 16) || 0;
|
|
3188
|
+
return [ch(0), ch(2), ch(4)];
|
|
3189
|
+
}
|
|
3190
|
+
function boxShadow(shadow, hex) {
|
|
3191
|
+
if (shadow === "none") return "none";
|
|
3192
|
+
const spec = SHADOW_SPEC[shadow];
|
|
3193
|
+
const [r, g, b] = channels(hex);
|
|
3194
|
+
return `0 ${spec.y}px ${spec.blur}px rgba(${r}, ${g}, ${b}, ${spec.alpha})`;
|
|
3195
|
+
}
|
|
3196
|
+
function readableOn(hex) {
|
|
3197
|
+
const [r, g, b] = channels(hex);
|
|
3198
|
+
return (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255 > 0.6 ? "#111827" : "#ffffff";
|
|
3199
|
+
}
|
|
3200
|
+
function themeModeFor(theme, design) {
|
|
3201
|
+
if (!theme || design.theme !== WORKSPACE_THEME_ID) return null;
|
|
3202
|
+
return (design.colorMode === "dark" ? theme.dark : theme.light) ?? null;
|
|
3203
|
+
}
|
|
3204
|
+
function themeRowJustify(mode, inline, preset) {
|
|
3205
|
+
const box = inline ? mode.embedded : mode.overlay;
|
|
3206
|
+
if (box.align === "distribute") return null;
|
|
3207
|
+
const button = preset === "secondary" ? mode.buttons?.secondary : preset === "link" ? mode.buttons?.tertiary : preset === void 0 || preset === null || preset === "primary" ? mode.buttons?.primary : void 0;
|
|
3208
|
+
return button ? JUSTIFY[button.align] ?? null : null;
|
|
3209
|
+
}
|
|
3210
|
+
function appFont(ref, doc) {
|
|
3211
|
+
const view = doc.defaultView;
|
|
3212
|
+
if (!view) return null;
|
|
3213
|
+
if (ref === "inherit") return view.getComputedStyle(doc.body).fontFamily || null;
|
|
3214
|
+
if (ref === "app-heading") {
|
|
3215
|
+
const heading = Array.from(doc.querySelectorAll("h1,h2,h3")).find(
|
|
3216
|
+
(el2) => el2.getClientRects().length > 0
|
|
3217
|
+
);
|
|
3218
|
+
return view.getComputedStyle(heading ?? doc.body).fontFamily || null;
|
|
3219
|
+
}
|
|
3220
|
+
return ref;
|
|
3221
|
+
}
|
|
3222
|
+
function themeContainerDesign(mode, inline, tooltip = false) {
|
|
3223
|
+
const box = inline ? mode.embedded : mode.overlay;
|
|
3224
|
+
const tip = tooltip ? mode.tooltip : void 0;
|
|
3225
|
+
const padding = tip?.padding ?? box.padding;
|
|
3226
|
+
const out = {
|
|
3227
|
+
// El embebido va en el flujo de la página: sin fondo propio.
|
|
3228
|
+
background: tip ? tip.background : inline ? "transparent" : box.background ?? mode.colors.background,
|
|
3229
|
+
color: mode.colors.text,
|
|
3230
|
+
paddingTop: padding.top,
|
|
3231
|
+
paddingRight: padding.right,
|
|
3232
|
+
paddingBottom: padding.bottom,
|
|
3233
|
+
paddingLeft: padding.left,
|
|
3234
|
+
borderColor: tip?.borderColor ?? box.borderColor,
|
|
3235
|
+
borderWidth: tip?.borderWidth ?? box.borderWidth,
|
|
3236
|
+
radius: tip?.borderRadius ?? box.borderRadius
|
|
3237
|
+
};
|
|
3238
|
+
const shadow = tip?.shadow ?? box.shadow;
|
|
3239
|
+
const shadowColor = tip?.shadowColor ?? box.shadowColor;
|
|
3240
|
+
if (shadow === "none") {
|
|
3241
|
+
Object.assign(out, { shadowColor: "transparent", shadowBlur: 0 });
|
|
3242
|
+
} else {
|
|
3243
|
+
const spec = SHADOW_SPEC[shadow];
|
|
3244
|
+
const [r, g, b] = channels(shadowColor);
|
|
3245
|
+
Object.assign(out, {
|
|
3246
|
+
shadowX: 0,
|
|
3247
|
+
shadowY: spec.y,
|
|
3248
|
+
shadowBlur: spec.blur,
|
|
3249
|
+
shadowSpread: 0,
|
|
3250
|
+
shadowColor: `rgba(${r}, ${g}, ${b}, ${spec.alpha})`
|
|
3251
|
+
});
|
|
3252
|
+
}
|
|
3253
|
+
return out;
|
|
3254
|
+
}
|
|
3255
|
+
function applyThemeVars(card, mode, inline, tooltip = false) {
|
|
3256
|
+
const doc = card.ownerDocument ?? document;
|
|
3257
|
+
const box = inline ? mode.embedded : mode.overlay;
|
|
3258
|
+
const set = (name, value) => {
|
|
3259
|
+
if (value) card.style.setProperty(name, value);
|
|
3260
|
+
};
|
|
3261
|
+
card.classList.add("veo-card--themed");
|
|
3262
|
+
set("--veo-primary", mode.colors.accent);
|
|
3263
|
+
set("--veo-cta-color", readableOn(mode.colors.accent));
|
|
3264
|
+
const primary = mode.buttons?.primary;
|
|
3265
|
+
const publish = (prefix, b) => {
|
|
3266
|
+
if (!b) return;
|
|
3267
|
+
const p = b.padding;
|
|
3268
|
+
set(`${prefix}-bg`, b.background);
|
|
3269
|
+
set(`${prefix}-color`, b.color);
|
|
3270
|
+
set(`${prefix}-pad`, `${p.top}px ${p.right}px ${p.bottom}px ${p.left}px`);
|
|
3271
|
+
set(`${prefix}-size`, `${b.fontSize}px`);
|
|
3272
|
+
set(`${prefix}-weight`, String(b.fontWeight));
|
|
3273
|
+
set(`${prefix}-radius`, `${b.borderRadius}px`);
|
|
3274
|
+
set(
|
|
3275
|
+
`${prefix}-border`,
|
|
3276
|
+
b.borderWidth > 0 ? `${b.borderWidth}px solid ${b.borderColor}` : "none"
|
|
3277
|
+
);
|
|
3278
|
+
};
|
|
3279
|
+
publish("--veo-cta", primary);
|
|
3280
|
+
publish("--veo-cta2", mode.buttons?.secondary);
|
|
3281
|
+
publish("--veo-cta3", mode.buttons?.tertiary);
|
|
3282
|
+
set("--veo-text", mode.colors.text);
|
|
3283
|
+
set("--veo-text-secondary", mode.colors.textMuted);
|
|
3284
|
+
set("--veo-font", appFont("inherit", doc));
|
|
3285
|
+
set(
|
|
3286
|
+
"--veo-actions-justify",
|
|
3287
|
+
box.align === "distribute" || !primary ? JUSTIFY[box.align] : JUSTIFY[primary.align]
|
|
3288
|
+
);
|
|
3289
|
+
const form = mode.form;
|
|
3290
|
+
if (form) {
|
|
3291
|
+
card.classList.add("veo-card--themed-form");
|
|
3292
|
+
const fp = form.padding;
|
|
3293
|
+
set("--veo-f-bg", form.background);
|
|
3294
|
+
set("--veo-f-accent", form.accent);
|
|
3295
|
+
set("--veo-f-on-accent", form.onAccent);
|
|
3296
|
+
set("--veo-f-pad", `${fp.top}px ${fp.right}px ${fp.bottom}px ${fp.left}px`);
|
|
3297
|
+
if (typeof form.borderWidth === "number" && form.borderColor) {
|
|
3298
|
+
set(
|
|
3299
|
+
"--veo-f-border",
|
|
3300
|
+
form.borderWidth > 0 ? `${form.borderWidth}px solid ${form.borderColor}` : "none"
|
|
3301
|
+
);
|
|
3302
|
+
}
|
|
3303
|
+
if (typeof form.borderRadius === "number") set("--veo-f-radius", `${form.borderRadius}px`);
|
|
3304
|
+
if (form.shadow && form.shadowColor) {
|
|
3305
|
+
set("--veo-f-shadow", boxShadow(form.shadow, form.shadowColor));
|
|
3306
|
+
}
|
|
3307
|
+
for (const [name, t] of [
|
|
3308
|
+
["primary", form.text.primary],
|
|
3309
|
+
["secondary", form.text.secondary]
|
|
3310
|
+
]) {
|
|
3311
|
+
set(`--veo-f-${name}-color`, t.color);
|
|
3312
|
+
set(`--veo-f-${name}-size`, `${t.fontSize}px`);
|
|
3313
|
+
set(`--veo-f-${name}-weight`, String(t.fontWeight));
|
|
3314
|
+
set(`--veo-f-${name}-align`, t.align);
|
|
3315
|
+
set(`--veo-f-${name}-font`, appFont(t.fontFamily, doc));
|
|
3316
|
+
}
|
|
3317
|
+
}
|
|
3318
|
+
const tip = tooltip ? mode.tooltip?.text : void 0;
|
|
3319
|
+
const tokens = [
|
|
3320
|
+
["title", tip?.primary ?? mode.text.title],
|
|
3321
|
+
["subtitle", tip?.secondary ?? mode.text.subtitle],
|
|
3322
|
+
["paragraph", tip?.secondary ?? mode.text.paragraph]
|
|
3323
|
+
];
|
|
3324
|
+
for (const [name, t] of tokens) {
|
|
3325
|
+
set(`--veo-t-${name}-color`, t.color);
|
|
3326
|
+
set(`--veo-t-${name}-size`, `${t.fontSize}px`);
|
|
3327
|
+
set(`--veo-t-${name}-weight`, String(t.fontWeight));
|
|
3328
|
+
set(`--veo-t-${name}-align`, t.align);
|
|
3329
|
+
set(`--veo-t-${name}-font`, appFont(t.fontFamily, doc));
|
|
3330
|
+
}
|
|
3331
|
+
}
|
|
3332
|
+
|
|
2992
3333
|
// src/plugins/guides/layout.ts
|
|
2993
3334
|
function groupLayout(blocks) {
|
|
2994
3335
|
const rows = /* @__PURE__ */ new Map();
|
|
@@ -3370,6 +3711,11 @@ function applyRowStyle(rowEl, style) {
|
|
|
3370
3711
|
if (style.valign && ROW_VALIGN[style.valign]) s.alignItems = ROW_VALIGN[style.valign];
|
|
3371
3712
|
}
|
|
3372
3713
|
var CompositeRenderer = class extends BaseRenderer {
|
|
3714
|
+
constructor() {
|
|
3715
|
+
super(...arguments);
|
|
3716
|
+
/** Alineación de filas de botones según el tema del workspace (null = sin tema). */
|
|
3717
|
+
this.themeRowJustify = null;
|
|
3718
|
+
}
|
|
3373
3719
|
async render(context) {
|
|
3374
3720
|
const idx = context.nav?.stepIndex ?? 0;
|
|
3375
3721
|
const step = context.guide.guideSteps[idx];
|
|
@@ -3400,7 +3746,13 @@ var CompositeRenderer = class extends BaseRenderer {
|
|
|
3400
3746
|
if (typeof design.zIndex === "number") host.style.zIndex = String(design.zIndex);
|
|
3401
3747
|
const card = doc.createElement("div");
|
|
3402
3748
|
card.className = "veo-card";
|
|
3403
|
-
|
|
3749
|
+
const themeMode = themeModeFor(context.guide.theme, design);
|
|
3750
|
+
const inline = step.presentation === "inline";
|
|
3751
|
+
const tooltipLike = !inline && (badgeMode || step.position === "relative-to-element");
|
|
3752
|
+
if (themeMode) applyThemeVars(card, themeMode, inline, tooltipLike);
|
|
3753
|
+
this.themeRowJustify = themeMode ? (preset) => themeRowJustify(themeMode, inline, preset) : null;
|
|
3754
|
+
const cardDesign = themeMode ? { ...themeContainerDesign(themeMode, inline, tooltipLike), ...design } : design;
|
|
3755
|
+
applyCompositeDesign(card, cardDesign);
|
|
3404
3756
|
if (typeof design.ariaLabel === "string" && design.ariaLabel.trim()) {
|
|
3405
3757
|
card.setAttribute("role", "dialog");
|
|
3406
3758
|
card.setAttribute("aria-label", design.ariaLabel.trim());
|
|
@@ -3471,7 +3823,7 @@ var CompositeRenderer = class extends BaseRenderer {
|
|
|
3471
3823
|
});
|
|
3472
3824
|
}
|
|
3473
3825
|
card.appendChild(closeBtn);
|
|
3474
|
-
reserveCloseSpace(card, blocks, closePos,
|
|
3826
|
+
reserveCloseSpace(card, blocks, closePos, cardDesign);
|
|
3475
3827
|
}
|
|
3476
3828
|
if (badgeMode && anchor) {
|
|
3477
3829
|
closeTooltip = this.renderBadgeMode(
|
|
@@ -3484,7 +3836,8 @@ var CompositeRenderer = class extends BaseRenderer {
|
|
|
3484
3836
|
doc,
|
|
3485
3837
|
context,
|
|
3486
3838
|
idx,
|
|
3487
|
-
|
|
3839
|
+
// Con el tema ya fundido: la flecha del tooltip toma su fondo y borde.
|
|
3840
|
+
cardDesign
|
|
3488
3841
|
);
|
|
3489
3842
|
return;
|
|
3490
3843
|
}
|
|
@@ -3507,7 +3860,7 @@ var CompositeRenderer = class extends BaseRenderer {
|
|
|
3507
3860
|
}
|
|
3508
3861
|
const wrapper = doc.createElement("div");
|
|
3509
3862
|
wrapper.className = "veo-composite-anchored";
|
|
3510
|
-
const caretEl = design.caret === false ? null : makeCaret(doc,
|
|
3863
|
+
const caretEl = design.caret === false ? null : makeCaret(doc, cardDesign);
|
|
3511
3864
|
if (caretEl) wrapper.appendChild(caretEl);
|
|
3512
3865
|
wrapper.appendChild(card);
|
|
3513
3866
|
root.appendChild(wrapper);
|
|
@@ -3567,6 +3920,7 @@ var CompositeRenderer = class extends BaseRenderer {
|
|
|
3567
3920
|
const row = doc.createElement("div");
|
|
3568
3921
|
row.className = "veo-guide-actions";
|
|
3569
3922
|
let rowAlign;
|
|
3923
|
+
const firstPreset = b.style?.preset;
|
|
3570
3924
|
while (i < cell.length && cell[i]?.block.type === "button") {
|
|
3571
3925
|
const { block: bb, index: bi } = cell[i];
|
|
3572
3926
|
if (!rowAlign) {
|
|
@@ -3577,6 +3931,10 @@ var CompositeRenderer = class extends BaseRenderer {
|
|
|
3577
3931
|
i++;
|
|
3578
3932
|
}
|
|
3579
3933
|
if (rowAlign) row.style.justifyContent = ROW_ALIGN[rowAlign] ?? "flex-end";
|
|
3934
|
+
else {
|
|
3935
|
+
const themed = this.themeRowJustify?.(firstPreset);
|
|
3936
|
+
if (themed) row.style.justifyContent = themed;
|
|
3937
|
+
}
|
|
3580
3938
|
container.appendChild(row);
|
|
3581
3939
|
continue;
|
|
3582
3940
|
}
|
|
@@ -3989,6 +4347,7 @@ function makeCaret(doc, design) {
|
|
|
3989
4347
|
if (typeof design.borderWidth === "number" && design.borderWidth > 0) {
|
|
3990
4348
|
const bc = typeof design.borderColor === "string" ? design.borderColor : "#bbbbbb";
|
|
3991
4349
|
s.border = `${design.borderWidth}px solid ${bc}`;
|
|
4350
|
+
caret.dataset.veoBorder = String(design.borderWidth);
|
|
3992
4351
|
}
|
|
3993
4352
|
return caret;
|
|
3994
4353
|
}
|
|
@@ -4723,7 +5082,8 @@ function normalize(input) {
|
|
|
4723
5082
|
guideSteps: input.guideSteps,
|
|
4724
5083
|
activationRules,
|
|
4725
5084
|
displayFrequency: "always",
|
|
4726
|
-
displayPriority: 0
|
|
5085
|
+
displayPriority: 0,
|
|
5086
|
+
...input.theme ? { theme: input.theme } : {}
|
|
4727
5087
|
};
|
|
4728
5088
|
}
|
|
4729
5089
|
function createSingleStepRenderer(type) {
|
|
@@ -4943,14 +5303,19 @@ function injectBuilderChrome(opts) {
|
|
|
4943
5303
|
let previewOn = false;
|
|
4944
5304
|
let hiddenOn = false;
|
|
4945
5305
|
let heightCb = null;
|
|
4946
|
-
|
|
5306
|
+
let tagging = false;
|
|
5307
|
+
const height = () => CHROME_TOPBAR_H + (collapsed || tagging ? 0 : CHROME_STEPS_H);
|
|
4947
5308
|
const applyHeight = () => {
|
|
4948
5309
|
const h = previewOn || hiddenOn ? 0 : height();
|
|
4949
5310
|
html.style.marginTop = dock === "top" ? `${h}px` : prevMarginTop;
|
|
4950
5311
|
html.style.marginBottom = dock === "bottom" ? `${h}px` : prevMarginBottom;
|
|
4951
5312
|
root.style.setProperty("--veo-chrome-h", `${height()}px`);
|
|
4952
5313
|
root.classList.toggle("is-bottom", dock === "bottom");
|
|
4953
|
-
stepsBar.hidden = collapsed;
|
|
5314
|
+
stepsBar.hidden = collapsed || tagging;
|
|
5315
|
+
togglePill.hidden = tagging;
|
|
5316
|
+
preview.hidden = tagging;
|
|
5317
|
+
saveGroup.hidden = tagging;
|
|
5318
|
+
showPanel.title = tagging ? "Mostrar el panel" : "Mostrar el editor";
|
|
4954
5319
|
const open = dock === "top" ? "chevronUp" : "chevronDown";
|
|
4955
5320
|
const closedIcon = dock === "top" ? "chevronDown" : "chevronUp";
|
|
4956
5321
|
togglePill.innerHTML = `<span>${collapsed ? "Mostrar pasos" : "Ocultar pasos"}</span>${svg(
|
|
@@ -5003,8 +5368,13 @@ function injectBuilderChrome(opts) {
|
|
|
5003
5368
|
const render = () => {
|
|
5004
5369
|
const s = current;
|
|
5005
5370
|
if (!s) return;
|
|
5371
|
+
const nextTagging = s.variant === "tagging";
|
|
5372
|
+
if (nextTagging !== tagging) {
|
|
5373
|
+
tagging = nextTagging;
|
|
5374
|
+
applyHeight();
|
|
5375
|
+
}
|
|
5006
5376
|
const date = shortDate(s.createdAt);
|
|
5007
|
-
nameEl.textContent = `${s.guideName.trim() || "Sin nombre"}${date ? ` \xB7 ${date}` : ""}`;
|
|
5377
|
+
nameEl.textContent = tagging ? s.guideName.trim() || "Modo tagging" : `${s.guideName.trim() || "Sin nombre"}${date ? ` \xB7 ${date}` : ""}`;
|
|
5008
5378
|
if (s.status) {
|
|
5009
5379
|
statusEl.hidden = false;
|
|
5010
5380
|
statusEl.textContent = s.status.label;
|
|
@@ -5103,6 +5473,8 @@ var CHROME_CSS = `
|
|
|
5103
5473
|
font-size: 14px; color: #1c1917;
|
|
5104
5474
|
}
|
|
5105
5475
|
.veo-chrome[hidden] { display: none; }
|
|
5476
|
+
/* Modo tagging oculta controles por atributo: gana a los display de sus clases. */
|
|
5477
|
+
.veo-chrome [hidden], .veo-steps-toggle[hidden] { display: none !important; }
|
|
5106
5478
|
.veo-chrome.is-bottom { top: auto; bottom: 0; flex-direction: column-reverse; }
|
|
5107
5479
|
.veo-chrome.is-bottom .veo-tb-menu { top: auto; bottom: calc(100% + 8px); }
|
|
5108
5480
|
.veo-chrome.is-bottom .veo-steps { border-bottom: 0; border-top: 1px solid #d6cfc8; }
|
|
@@ -5722,90 +6094,51 @@ function attachBanner(opts, shadow, banner) {
|
|
|
5722
6094
|
};
|
|
5723
6095
|
}
|
|
5724
6096
|
|
|
5725
|
-
// src/plugins/
|
|
5726
|
-
var
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
|
|
5740
|
-
|
|
5741
|
-
|
|
5742
|
-
}
|
|
5743
|
-
function filterHumanClasses(element) {
|
|
5744
|
-
return Array.from(element.classList).filter((c) => !isHashedClass(c) && c.length < 64);
|
|
5745
|
-
}
|
|
5746
|
-
var STABLE_ATTRIBUTES = [
|
|
5747
|
-
"data-testid",
|
|
5748
|
-
"data-test",
|
|
5749
|
-
"data-cy",
|
|
5750
|
-
"name",
|
|
5751
|
-
"aria-label",
|
|
5752
|
-
"placeholder",
|
|
5753
|
-
"alt",
|
|
5754
|
-
"title",
|
|
5755
|
-
// `href` identifica muy bien a los links (`<a>`), un target frecuente de
|
|
5756
|
-
// autocapture; va después de los atributos semánticos pero antes de los
|
|
5757
|
-
// genéricos. Valores largos (URLs absolutas con query) se descartan por
|
|
5758
|
-
// MAX_ATTR_VALUE_LENGTH.
|
|
5759
|
-
"href",
|
|
5760
|
-
"role",
|
|
5761
|
-
"type"
|
|
6097
|
+
// src/plugins/builder/interactive-elements.ts
|
|
6098
|
+
var INTERACTIVE_ROLES = [
|
|
6099
|
+
"button",
|
|
6100
|
+
"link",
|
|
6101
|
+
"tab",
|
|
6102
|
+
"menuitem",
|
|
6103
|
+
"menuitemcheckbox",
|
|
6104
|
+
"menuitemradio",
|
|
6105
|
+
"checkbox",
|
|
6106
|
+
"radio",
|
|
6107
|
+
"switch",
|
|
6108
|
+
"option",
|
|
6109
|
+
"combobox",
|
|
6110
|
+
"textbox",
|
|
6111
|
+
"searchbox",
|
|
6112
|
+
"slider",
|
|
6113
|
+
"spinbutton"
|
|
5762
6114
|
];
|
|
5763
|
-
var
|
|
5764
|
-
|
|
5765
|
-
|
|
5766
|
-
|
|
5767
|
-
|
|
5768
|
-
|
|
5769
|
-
|
|
5770
|
-
|
|
5771
|
-
|
|
5772
|
-
|
|
5773
|
-
|
|
5774
|
-
|
|
5775
|
-
|
|
5776
|
-
|
|
5777
|
-
|
|
5778
|
-
|
|
5779
|
-
}
|
|
5780
|
-
|
|
5781
|
-
}
|
|
5782
|
-
function buildElementSelector(element) {
|
|
5783
|
-
const tag = element.tagName.toLowerCase();
|
|
5784
|
-
const veoTag = element.getAttribute("data-veo-tag");
|
|
5785
|
-
if (veoTag) {
|
|
5786
|
-
return `${tag}[data-veo-tag="${escapeAttrValue(veoTag)}"]`;
|
|
5787
|
-
}
|
|
5788
|
-
if (element.id) {
|
|
5789
|
-
const classes2 = filterHumanClasses(element);
|
|
5790
|
-
const classPart2 = classes2.length > 0 ? `.${classes2.map(cssEscape).join(".")}` : "";
|
|
5791
|
-
return `${tag}#${cssEscape(element.id)}${classPart2}`;
|
|
6115
|
+
var INTERACTIVE_SELECTOR = [
|
|
6116
|
+
"button",
|
|
6117
|
+
"a[href]",
|
|
6118
|
+
'input:not([type="hidden"])',
|
|
6119
|
+
"select",
|
|
6120
|
+
"textarea",
|
|
6121
|
+
"form",
|
|
6122
|
+
"summary",
|
|
6123
|
+
'[contenteditable="true"]',
|
|
6124
|
+
"[onclick]",
|
|
6125
|
+
"[data-veo-tag]",
|
|
6126
|
+
...INTERACTIVE_ROLES.map((r) => `[role="${r}"]`)
|
|
6127
|
+
].join(", ");
|
|
6128
|
+
function closestInteractive(element) {
|
|
6129
|
+
try {
|
|
6130
|
+
return element.closest(INTERACTIVE_SELECTOR);
|
|
6131
|
+
} catch {
|
|
6132
|
+
return null;
|
|
5792
6133
|
}
|
|
5793
|
-
const attrSelector = stableAttributeSelector(element, tag);
|
|
5794
|
-
if (attrSelector) return attrSelector;
|
|
5795
|
-
const classes = filterHumanClasses(element);
|
|
5796
|
-
const classPart = classes.length > 0 ? `.${classes.map(cssEscape).join(".")}` : "";
|
|
5797
|
-
return `${tag}${classPart}`;
|
|
5798
6134
|
}
|
|
5799
|
-
|
|
5800
|
-
|
|
5801
|
-
|
|
5802
|
-
|
|
5803
|
-
|
|
5804
|
-
|
|
5805
|
-
|
|
5806
|
-
depth++;
|
|
5807
|
-
}
|
|
5808
|
-
return parts.join(" > ");
|
|
6135
|
+
var EMOJI_RE = /\p{Extended_Pictographic}|\p{Emoji_Modifier}|\u{FE0F}|\u{200D}|\u{20E3}/gu;
|
|
6136
|
+
function elementLabelText(element, max = 120) {
|
|
6137
|
+
const clean = (raw) => (raw ?? "").replace(EMOJI_RE, "").replace(/\s+/g, " ").trim();
|
|
6138
|
+
const text = clean(element.textContent);
|
|
6139
|
+
if (text) return text.slice(0, max);
|
|
6140
|
+
const fallback = clean(element.getAttribute("aria-label")) || clean(element.getAttribute("title"));
|
|
6141
|
+
return fallback.slice(0, max);
|
|
5809
6142
|
}
|
|
5810
6143
|
|
|
5811
6144
|
// src/plugins/builder/element-picker.ts
|
|
@@ -5878,21 +6211,24 @@ var ElementPicker = class {
|
|
|
5878
6211
|
this.label = null;
|
|
5879
6212
|
this.current = null;
|
|
5880
6213
|
this.maxAncestors = DEFAULT_MAX_ANCESTORS;
|
|
6214
|
+
this.only = null;
|
|
5881
6215
|
this.onPick = null;
|
|
5882
6216
|
this.onCancel = null;
|
|
5883
6217
|
this.onMove = (event) => {
|
|
5884
|
-
|
|
5885
|
-
|
|
6218
|
+
if (!(event.target instanceof Element) || this.isOwn(event.target)) return;
|
|
6219
|
+
const target = this.resolveTarget(event.target);
|
|
5886
6220
|
this.current = target;
|
|
5887
|
-
this.draw(target);
|
|
6221
|
+
if (target) this.draw(target);
|
|
6222
|
+
else this.hideBox();
|
|
5888
6223
|
};
|
|
5889
6224
|
this.onClick = (event) => {
|
|
5890
6225
|
if (event.altKey) return;
|
|
5891
|
-
|
|
5892
|
-
if (!target || this.isOwn(target)) return;
|
|
6226
|
+
if (this.isOwn(event.target)) return;
|
|
5893
6227
|
event.preventDefault();
|
|
5894
6228
|
event.stopPropagation();
|
|
5895
6229
|
event.stopImmediatePropagation();
|
|
6230
|
+
const target = this.current ?? this.resolveTarget(event.target);
|
|
6231
|
+
if (!target) return;
|
|
5896
6232
|
const picked = this.describe(target);
|
|
5897
6233
|
const cb = this.onPick;
|
|
5898
6234
|
this.stop();
|
|
@@ -5919,6 +6255,7 @@ var ElementPicker = class {
|
|
|
5919
6255
|
start(options) {
|
|
5920
6256
|
this.stop();
|
|
5921
6257
|
this.maxAncestors = options.maxAncestors ?? DEFAULT_MAX_ANCESTORS;
|
|
6258
|
+
this.only = options.only ?? null;
|
|
5922
6259
|
this.onPick = options.onPick;
|
|
5923
6260
|
this.onCancel = options.onCancel ?? null;
|
|
5924
6261
|
const host = document.createElement("div");
|
|
@@ -5981,9 +6318,19 @@ var ElementPicker = class {
|
|
|
5981
6318
|
this.box = null;
|
|
5982
6319
|
this.label = null;
|
|
5983
6320
|
this.current = null;
|
|
6321
|
+
this.only = null;
|
|
5984
6322
|
this.onPick = null;
|
|
5985
6323
|
this.onCancel = null;
|
|
5986
6324
|
}
|
|
6325
|
+
/** Elemento que se elegiría para el nodo bajo el cursor (o null si no hay). */
|
|
6326
|
+
resolveTarget(target) {
|
|
6327
|
+
if (!(target instanceof Element) || this.isOwn(target)) return null;
|
|
6328
|
+
return this.only === "interactive" ? closestInteractive(target) : target;
|
|
6329
|
+
}
|
|
6330
|
+
hideBox() {
|
|
6331
|
+
if (this.box) this.box.style.display = "none";
|
|
6332
|
+
if (this.label) this.label.style.display = "none";
|
|
6333
|
+
}
|
|
5987
6334
|
/** ¿Es un nodo de nuestro propio overlay? (no debe ser seleccionable). */
|
|
5988
6335
|
isOwn(target) {
|
|
5989
6336
|
return target instanceof Node && this.host !== null && this.host.contains(target);
|
|
@@ -6020,7 +6367,7 @@ var ElementPicker = class {
|
|
|
6020
6367
|
tag: element.tagName.toLowerCase(),
|
|
6021
6368
|
id: element.id || null,
|
|
6022
6369
|
classes: filterHumanClasses(element),
|
|
6023
|
-
text: (element
|
|
6370
|
+
text: elementLabelText(element),
|
|
6024
6371
|
rect: {
|
|
6025
6372
|
x: Math.round(rect.left),
|
|
6026
6373
|
y: Math.round(rect.top),
|
|
@@ -6045,6 +6392,41 @@ function stopElementPicker() {
|
|
|
6045
6392
|
}
|
|
6046
6393
|
|
|
6047
6394
|
// src/plugins/builder/builder-mode.ts
|
|
6395
|
+
var CONFIRMATION_STYLES = `
|
|
6396
|
+
:host { all: initial; }
|
|
6397
|
+
.veo-confirm-backdrop {
|
|
6398
|
+
position: fixed; inset: 0; z-index: 2147483645;
|
|
6399
|
+
background: rgba(20, 16, 14, 0.45);
|
|
6400
|
+
}
|
|
6401
|
+
.veo-confirm {
|
|
6402
|
+
position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%);
|
|
6403
|
+
z-index: 2147483646; box-sizing: border-box;
|
|
6404
|
+
width: min(432px, calc(100vw - 32px)); padding: 28px 24px 24px;
|
|
6405
|
+
border-radius: 16px; background: #fff; color: #1d1917;
|
|
6406
|
+
box-shadow: 0 24px 64px rgba(0,0,0,0.28);
|
|
6407
|
+
font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
|
|
6408
|
+
text-align: center;
|
|
6409
|
+
}
|
|
6410
|
+
.veo-confirm-check {
|
|
6411
|
+
width: 64px; height: 64px; margin: 0 auto; border-radius: 50%;
|
|
6412
|
+
background: #e6f6df; color: #2f9a4e; display: flex; align-items: center; justify-content: center;
|
|
6413
|
+
}
|
|
6414
|
+
.veo-confirm-check svg { width: 30px; height: 30px; }
|
|
6415
|
+
.veo-confirm-title { margin: 18px 0 0; font-size: 17px; font-weight: 600; }
|
|
6416
|
+
.veo-confirm-msg { margin: 8px 0 0; font-size: 13px; color: #6b6461; }
|
|
6417
|
+
.veo-confirm-rows {
|
|
6418
|
+
margin: 18px 0 0; padding: 12px 14px; border-radius: 12px; background: #f6f2ef; text-align: left;
|
|
6419
|
+
}
|
|
6420
|
+
.veo-confirm-row { display: flex; justify-content: space-between; gap: 16px; font-size: 13px; padding: 4px 0; }
|
|
6421
|
+
.veo-confirm-row dt { color: #6b6461; margin: 0; }
|
|
6422
|
+
.veo-confirm-row dd { margin: 0; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
6423
|
+
.veo-confirm-btn {
|
|
6424
|
+
display: block; width: 100%; margin-top: 18px; height: 44px; border: 0; border-radius: 10px;
|
|
6425
|
+
background: #b74d00; color: #fff; font: inherit; font-size: 15px; font-weight: 600; cursor: pointer;
|
|
6426
|
+
}
|
|
6427
|
+
.veo-confirm-btn:hover { background: #953c00; }
|
|
6428
|
+
.veo-confirm-btn:focus-visible { outline: 3px solid rgba(183,77,0,0.35); outline-offset: 2px; }
|
|
6429
|
+
`;
|
|
6048
6430
|
function initBuilderMode() {
|
|
6049
6431
|
if (!hasWindow() || !hasDocument()) return null;
|
|
6050
6432
|
const ctx = resolveBuilderContext();
|
|
@@ -7026,7 +7408,7 @@ function initBuilderMode() {
|
|
|
7026
7408
|
if (h && hoverCard && !previewMode) renderCardChrome(h, previewStepIndex);
|
|
7027
7409
|
}
|
|
7028
7410
|
panel?.setTitle(
|
|
7029
|
-
cmd.state.section === "activation" ? "Ajustes de activaci\xF3n" : cmd.state.section === "badge" ? "Ajustes de badge" : cmd.state.section === "target" ? "Ajustes del elemento objetivo" : cmd.state.section === "row" ? "Editar fila" : cmd.state.blockLabel ? `Editor \xB7 ${cmd.state.blockLabel}` : cmd.state.steps[cmd.state.activeStep]?.label ?? "Paso"
|
|
7411
|
+
cmd.state.panelTitle ?? (cmd.state.section === "activation" ? "Ajustes de activaci\xF3n" : cmd.state.section === "badge" ? "Ajustes de badge" : cmd.state.section === "target" ? "Ajustes del elemento objetivo" : cmd.state.section === "row" ? "Editar fila" : cmd.state.blockLabel ? `Editor \xB7 ${cmd.state.blockLabel}` : cmd.state.steps[cmd.state.activeStep]?.label ?? "Paso")
|
|
7030
7412
|
);
|
|
7031
7413
|
break;
|
|
7032
7414
|
case "panel-visibility":
|
|
@@ -7064,7 +7446,8 @@ function initBuilderMode() {
|
|
|
7064
7446
|
post({ type: "pick-cancelled" });
|
|
7065
7447
|
},
|
|
7066
7448
|
...cmd.maxAncestors !== void 0 ? { maxAncestors: cmd.maxAncestors } : {},
|
|
7067
|
-
...cmd.hint !== void 0 ? { hint: cmd.hint } : {}
|
|
7449
|
+
...cmd.hint !== void 0 ? { hint: cmd.hint } : {},
|
|
7450
|
+
...cmd.only !== void 0 ? { only: cmd.only } : {}
|
|
7068
7451
|
});
|
|
7069
7452
|
break;
|
|
7070
7453
|
}
|
|
@@ -7073,6 +7456,15 @@ function initBuilderMode() {
|
|
|
7073
7456
|
picker = null;
|
|
7074
7457
|
chrome?.setHidden(false);
|
|
7075
7458
|
break;
|
|
7459
|
+
case "scan-page":
|
|
7460
|
+
post({ type: "page-scan", payload: scanPage(cmd.selectors) });
|
|
7461
|
+
break;
|
|
7462
|
+
case "highlight":
|
|
7463
|
+
setHighlight(cmd.selector);
|
|
7464
|
+
break;
|
|
7465
|
+
case "show-confirmation":
|
|
7466
|
+
showConfirmation(cmd.payload);
|
|
7467
|
+
break;
|
|
7076
7468
|
case "preview":
|
|
7077
7469
|
if (!cmd.guide) break;
|
|
7078
7470
|
if (manipulator?.isDragging()) pendingPreview = cmd;
|
|
@@ -7157,10 +7549,154 @@ function initBuilderMode() {
|
|
|
7157
7549
|
post({ type: "closed" });
|
|
7158
7550
|
panel?.teardown();
|
|
7159
7551
|
panel = null;
|
|
7552
|
+
highlightBox?.remove();
|
|
7553
|
+
highlightBox = null;
|
|
7554
|
+
confirmation?.remove();
|
|
7555
|
+
confirmation = null;
|
|
7556
|
+
if (confirmationKey) document.removeEventListener("keydown", confirmationKey, true);
|
|
7557
|
+
confirmationKey = null;
|
|
7160
7558
|
chrome?.teardown();
|
|
7161
7559
|
chrome = null;
|
|
7162
7560
|
clearBuilderToken();
|
|
7163
7561
|
};
|
|
7562
|
+
const scanPage = (selectors) => {
|
|
7563
|
+
const present = selectors.filter((sel) => {
|
|
7564
|
+
try {
|
|
7565
|
+
return document.querySelector(sel) !== null;
|
|
7566
|
+
} catch {
|
|
7567
|
+
return false;
|
|
7568
|
+
}
|
|
7569
|
+
});
|
|
7570
|
+
const taggedEls = /* @__PURE__ */ new Set();
|
|
7571
|
+
for (const sel of present) {
|
|
7572
|
+
try {
|
|
7573
|
+
for (const e of Array.from(document.querySelectorAll(sel))) taggedEls.add(e);
|
|
7574
|
+
} catch {
|
|
7575
|
+
}
|
|
7576
|
+
}
|
|
7577
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7578
|
+
const candidates = [];
|
|
7579
|
+
const nodes = document.querySelectorAll(INTERACTIVE_SELECTOR);
|
|
7580
|
+
for (const element of Array.from(nodes)) {
|
|
7581
|
+
if (candidates.length >= 200) break;
|
|
7582
|
+
if (element.closest("[data-veo-builder-chrome],[data-veo-builder-panel],[data-veo-picker]")) {
|
|
7583
|
+
continue;
|
|
7584
|
+
}
|
|
7585
|
+
if (element.getClientRects().length === 0) continue;
|
|
7586
|
+
let tagged = false;
|
|
7587
|
+
for (let n = element; n; n = n.parentElement) {
|
|
7588
|
+
if (taggedEls.has(n)) {
|
|
7589
|
+
tagged = true;
|
|
7590
|
+
break;
|
|
7591
|
+
}
|
|
7592
|
+
}
|
|
7593
|
+
if (tagged) continue;
|
|
7594
|
+
const selector = buildSelectorPath(element, 5);
|
|
7595
|
+
if (!selector || seen.has(selector)) continue;
|
|
7596
|
+
seen.add(selector);
|
|
7597
|
+
candidates.push({
|
|
7598
|
+
selector,
|
|
7599
|
+
shortSelector: buildSelectorPath(element, 0),
|
|
7600
|
+
tag: element.tagName.toLowerCase(),
|
|
7601
|
+
id: element.id || null,
|
|
7602
|
+
classes: filterHumanClasses(element),
|
|
7603
|
+
text: elementLabelText(element)
|
|
7604
|
+
});
|
|
7605
|
+
}
|
|
7606
|
+
const { pathname, hash } = window.location;
|
|
7607
|
+
const routePath = /^#\/./.test(hash) ? `${pathname}${hash}` : pathname;
|
|
7608
|
+
return { pagePath: pathname, routePath, candidates, present };
|
|
7609
|
+
};
|
|
7610
|
+
let confirmation = null;
|
|
7611
|
+
let confirmationKey = null;
|
|
7612
|
+
const closeConfirmation = () => {
|
|
7613
|
+
if (!confirmation) return;
|
|
7614
|
+
confirmation.remove();
|
|
7615
|
+
confirmation = null;
|
|
7616
|
+
if (confirmationKey) document.removeEventListener("keydown", confirmationKey, true);
|
|
7617
|
+
confirmationKey = null;
|
|
7618
|
+
panel?.setVisible(true);
|
|
7619
|
+
post({ type: "confirmation-closed" });
|
|
7620
|
+
};
|
|
7621
|
+
const showConfirmation = (card) => {
|
|
7622
|
+
if (confirmation) {
|
|
7623
|
+
confirmation.remove();
|
|
7624
|
+
confirmation = null;
|
|
7625
|
+
}
|
|
7626
|
+
panel?.setVisible(false);
|
|
7627
|
+
const host = document.createElement("div");
|
|
7628
|
+
host.setAttribute("data-veo-builder-chrome", "");
|
|
7629
|
+
host.setAttribute("data-veo-confirmation", "");
|
|
7630
|
+
const shadow = host.attachShadow({ mode: "open" });
|
|
7631
|
+
const style = document.createElement("style");
|
|
7632
|
+
style.textContent = CONFIRMATION_STYLES;
|
|
7633
|
+
const backdrop = document.createElement("div");
|
|
7634
|
+
backdrop.className = "veo-confirm-backdrop";
|
|
7635
|
+
const dialog = document.createElement("div");
|
|
7636
|
+
dialog.className = "veo-confirm";
|
|
7637
|
+
dialog.setAttribute("role", "dialog");
|
|
7638
|
+
dialog.setAttribute("aria-modal", "true");
|
|
7639
|
+
dialog.setAttribute("aria-label", card.title);
|
|
7640
|
+
const badge = document.createElement("div");
|
|
7641
|
+
badge.className = "veo-confirm-check";
|
|
7642
|
+
badge.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg>';
|
|
7643
|
+
const title = document.createElement("h2");
|
|
7644
|
+
title.className = "veo-confirm-title";
|
|
7645
|
+
title.textContent = card.title;
|
|
7646
|
+
const message = document.createElement("p");
|
|
7647
|
+
message.className = "veo-confirm-msg";
|
|
7648
|
+
message.textContent = card.message;
|
|
7649
|
+
const rows = document.createElement("dl");
|
|
7650
|
+
rows.className = "veo-confirm-rows";
|
|
7651
|
+
for (const r of card.rows) {
|
|
7652
|
+
const row = document.createElement("div");
|
|
7653
|
+
row.className = "veo-confirm-row";
|
|
7654
|
+
const dt = document.createElement("dt");
|
|
7655
|
+
dt.textContent = r.label;
|
|
7656
|
+
const dd = document.createElement("dd");
|
|
7657
|
+
dd.textContent = r.value;
|
|
7658
|
+
row.append(dt, dd);
|
|
7659
|
+
rows.appendChild(row);
|
|
7660
|
+
}
|
|
7661
|
+
const button = document.createElement("button");
|
|
7662
|
+
button.type = "button";
|
|
7663
|
+
button.className = "veo-confirm-btn";
|
|
7664
|
+
button.textContent = card.buttonLabel ?? "Listo";
|
|
7665
|
+
button.addEventListener("click", closeConfirmation);
|
|
7666
|
+
dialog.append(badge, title, message);
|
|
7667
|
+
if (card.rows.length > 0) dialog.appendChild(rows);
|
|
7668
|
+
dialog.appendChild(button);
|
|
7669
|
+
shadow.append(style, backdrop, dialog);
|
|
7670
|
+
document.body.appendChild(host);
|
|
7671
|
+
confirmation = host;
|
|
7672
|
+
confirmationKey = (e) => {
|
|
7673
|
+
if (e.key !== "Escape") return;
|
|
7674
|
+
e.preventDefault();
|
|
7675
|
+
e.stopPropagation();
|
|
7676
|
+
closeConfirmation();
|
|
7677
|
+
};
|
|
7678
|
+
document.addEventListener("keydown", confirmationKey, true);
|
|
7679
|
+
button.focus();
|
|
7680
|
+
};
|
|
7681
|
+
let highlightBox = null;
|
|
7682
|
+
const setHighlight = (selector) => {
|
|
7683
|
+
highlightBox?.remove();
|
|
7684
|
+
highlightBox = null;
|
|
7685
|
+
if (!selector) return;
|
|
7686
|
+
let target = null;
|
|
7687
|
+
try {
|
|
7688
|
+
target = document.querySelector(selector);
|
|
7689
|
+
} catch {
|
|
7690
|
+
return;
|
|
7691
|
+
}
|
|
7692
|
+
if (!target) return;
|
|
7693
|
+
const r = target.getBoundingClientRect();
|
|
7694
|
+
const box = document.createElement("div");
|
|
7695
|
+
box.setAttribute("data-veo-builder-chrome", "");
|
|
7696
|
+
box.style.cssText = `position:fixed;left:${r.left - 3}px;top:${r.top - 3}px;width:${r.width + 6}px;height:${r.height + 6}px;border:2px solid #FF5B35;border-radius:6px;background:rgba(255,91,53,0.10);pointer-events:none;z-index:2147483646;`;
|
|
7697
|
+
document.body.appendChild(box);
|
|
7698
|
+
highlightBox = box;
|
|
7699
|
+
};
|
|
7164
7700
|
if (ctx.panel) {
|
|
7165
7701
|
chrome = injectBuilderChrome({
|
|
7166
7702
|
appLabel: window.location.hostname,
|