veo-sdk 0.6.2 → 0.6.4
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-5F2EFT4X.mjs +5 -0
- package/dist/{builder-ENKEIVF2.mjs.map → builder-5F2EFT4X.mjs.map} +1 -1
- package/dist/builder.cjs +396 -103
- package/dist/builder.cjs.map +1 -1
- package/dist/builder.d.cts +76 -6
- package/dist/builder.d.ts +76 -6
- package/dist/builder.mjs +4 -4
- package/dist/{chunk-L3QQJLDJ.mjs → chunk-72YH2GXC.mjs} +3 -3
- package/dist/{chunk-L3QQJLDJ.mjs.map → chunk-72YH2GXC.mjs.map} +1 -1
- package/dist/{chunk-ZILDR4YE.mjs → chunk-CMPOHTUM.mjs} +112 -80
- package/dist/chunk-CMPOHTUM.mjs.map +1 -0
- package/dist/{chunk-4QZDNJJE.mjs → chunk-YEKCBVNJ.mjs} +284 -15
- package/dist/chunk-YEKCBVNJ.mjs.map +1 -0
- package/dist/index.cjs +653 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.mjs +308 -7
- package/dist/index.mjs.map +1 -1
- package/dist/veo-builder.js +54 -19
- package/dist/veo-builder.js.map +1 -1
- package/dist/veo-guides.js +6 -6
- package/dist/veo-guides.js.map +1 -1
- package/dist/veo.js +2 -2
- package/dist/veo.js.map +1 -1
- package/package.json +1 -1
- package/dist/builder-ENKEIVF2.mjs +0 -5
- package/dist/chunk-4QZDNJJE.mjs.map +0 -1
- package/dist/chunk-ZILDR4YE.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) {
|
|
@@ -309,6 +395,7 @@ var GUIDE_Z_INDEX = 2147483640;
|
|
|
309
395
|
var DEFAULT_ANCHOR_WAIT_MS = 5e3;
|
|
310
396
|
var SAFE_URL_PROTOCOLS = ["http:", "https:"];
|
|
311
397
|
var GUIDE_HOST_ATTR = "data-veo-guide";
|
|
398
|
+
var BADGE_MARKER_HOST_ATTR = "data-veo-badge";
|
|
312
399
|
var WALKTHROUGH_STEP_SELECTOR_TIMEOUT_MS = 5e3;
|
|
313
400
|
|
|
314
401
|
// src/plugins/guides/rich-text.ts
|
|
@@ -2123,6 +2210,25 @@ var BaseRenderer = class {
|
|
|
2123
2210
|
this.shadow = shadow;
|
|
2124
2211
|
return { host, shadow, root };
|
|
2125
2212
|
}
|
|
2213
|
+
/**
|
|
2214
|
+
* Host SUELTO con los mismos estilos (shadow DOM), sin agregarlo al DOM ni
|
|
2215
|
+
* registrarlo como `this.host`. Para piezas que deben vivir dentro de la app
|
|
2216
|
+
* (el marcador de un badge, junto a su ancla) mientras la tarjeta se queda
|
|
2217
|
+
* en `body`: si la tarjeta viajara dentro del ancla, un ancestro con
|
|
2218
|
+
* `transform`/`overflow` la recortaría y su z-index quedaría atrapado.
|
|
2219
|
+
*/
|
|
2220
|
+
createDetachedHost(attr = BADGE_MARKER_HOST_ATTR) {
|
|
2221
|
+
const host = document.createElement("div");
|
|
2222
|
+
host.setAttribute(attr, "");
|
|
2223
|
+
const shadow = host.attachShadow({ mode: "open" });
|
|
2224
|
+
const style = document.createElement("style");
|
|
2225
|
+
style.textContent = GUIDE_STYLES;
|
|
2226
|
+
shadow.appendChild(style);
|
|
2227
|
+
const root = document.createElement("div");
|
|
2228
|
+
shadow.appendChild(root);
|
|
2229
|
+
this.registerCleanup(() => host.remove());
|
|
2230
|
+
return { host, root };
|
|
2231
|
+
}
|
|
2126
2232
|
/**
|
|
2127
2233
|
* Aplica la tematización por datos del step (`step.style`) como variables
|
|
2128
2234
|
* CSS sobre el host. Llamar tras `createHost()`. No-op si no hay host o
|
|
@@ -3335,6 +3441,13 @@ function snoozeGuide(guideId, every, unit, now = Date.now()) {
|
|
|
3335
3441
|
} catch {
|
|
3336
3442
|
}
|
|
3337
3443
|
}
|
|
3444
|
+
|
|
3445
|
+
// src/plugins/guides/z-index.ts
|
|
3446
|
+
var MAX_Z_INDEX = 2147483647;
|
|
3447
|
+
function clampZIndex(value, fallback) {
|
|
3448
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return fallback;
|
|
3449
|
+
return Math.max(-MAX_Z_INDEX, Math.min(MAX_Z_INDEX, Math.round(value)));
|
|
3450
|
+
}
|
|
3338
3451
|
var INFO_GLYPH = "M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021";
|
|
3339
3452
|
var QUESTION_GLYPH = "M9.879 7.519c1.171-1.025 3.071-1.025 4.242 0 1.172 1.025 1.172 2.687 0 3.712-.203.179-.43.326-.67.442-.745.361-1.45.999-1.45 1.827v.75";
|
|
3340
3453
|
var STAR_GLYPH = "M11.48 3.499a.562.562 0 011.04 0l2.125 5.111a.563.563 0 00.475.345l5.518.442c.499.04.701.663.321.988l-4.204 3.602a.563.563 0 00-.182.557l1.285 5.385a.562.562 0 01-.84.61l-4.725-2.885a.563.563 0 00-.586 0L6.982 20.54a.562.562 0 01-.84-.61l1.285-5.386a.562.562 0 00-.182-.557l-4.204-3.602a.563.563 0 01.321-.988l5.518-.442a.563.563 0 00.475-.345L11.48 3.5z";
|
|
@@ -3519,7 +3632,7 @@ function canNest(anchor) {
|
|
|
3519
3632
|
}
|
|
3520
3633
|
function attachMarker(anchor, host, marker) {
|
|
3521
3634
|
host.style.position = "absolute";
|
|
3522
|
-
host.style.zIndex = String(
|
|
3635
|
+
host.style.zIndex = String(clampZIndex(marker.zIndex, DEFAULT_MARKER_Z));
|
|
3523
3636
|
host.style.margin = "0";
|
|
3524
3637
|
const position = marker.position ?? "top-right";
|
|
3525
3638
|
const offset6 = { x: num(marker.offsetX, 0), y: num(marker.offsetY, 0) };
|
|
@@ -3657,7 +3770,9 @@ var CompositeRenderer = class extends BaseRenderer {
|
|
|
3657
3770
|
const { host, root } = this.createHost();
|
|
3658
3771
|
const doc = root.ownerDocument ?? document;
|
|
3659
3772
|
const design = step.design ?? {};
|
|
3660
|
-
if (typeof design.zIndex === "number")
|
|
3773
|
+
if (typeof design.zIndex === "number") {
|
|
3774
|
+
host.style.zIndex = String(clampZIndex(design.zIndex, 0));
|
|
3775
|
+
}
|
|
3661
3776
|
const card = doc.createElement("div");
|
|
3662
3777
|
card.className = "veo-card";
|
|
3663
3778
|
const themeMode = themeModeFor(context.guide.theme, design);
|
|
@@ -3766,7 +3881,7 @@ var CompositeRenderer = class extends BaseRenderer {
|
|
|
3766
3881
|
const bg = doc.createElement("div");
|
|
3767
3882
|
bg.className = "veo-composite-overlay veo-composite-overlay--dim";
|
|
3768
3883
|
if (typeof design.backdropColor === "string") bg.style.background = design.backdropColor;
|
|
3769
|
-
const bz =
|
|
3884
|
+
const bz = clampZIndex(design.backdropZIndex, 2e5);
|
|
3770
3885
|
bg.style.zIndex = String(bz);
|
|
3771
3886
|
root.appendChild(bg);
|
|
3772
3887
|
this.registerCleanup(lockScroll(doc));
|
|
@@ -3788,7 +3903,7 @@ var CompositeRenderer = class extends BaseRenderer {
|
|
|
3788
3903
|
overlay.style.background = design.backdropColor;
|
|
3789
3904
|
}
|
|
3790
3905
|
if (typeof design.backdropZIndex === "number") {
|
|
3791
|
-
overlay.style.zIndex = String(design.backdropZIndex);
|
|
3906
|
+
overlay.style.zIndex = String(clampZIndex(design.backdropZIndex, 0));
|
|
3792
3907
|
}
|
|
3793
3908
|
overlay.addEventListener("click", (e) => {
|
|
3794
3909
|
if (e.target === overlay) {
|
|
@@ -4109,6 +4224,7 @@ var CompositeRenderer = class extends BaseRenderer {
|
|
|
4109
4224
|
renderBadgeMode(step, card, anchor, anchorSelector, host, root, doc, context, idx, design) {
|
|
4110
4225
|
const trigger = step.badge?.trigger === "click" ? "click" : "hover";
|
|
4111
4226
|
const placement = step.badge?.placement === "top" || step.badge?.placement === "left" || step.badge?.placement === "right" ? step.badge.placement : "bottom";
|
|
4227
|
+
const { host: markerHost, root: markerRoot } = this.createDetachedHost();
|
|
4112
4228
|
const badge = doc.createElement("div");
|
|
4113
4229
|
badge.className = "veo-composite-badge";
|
|
4114
4230
|
badge.setAttribute("role", "button");
|
|
@@ -4119,7 +4235,8 @@ var CompositeRenderer = class extends BaseRenderer {
|
|
|
4119
4235
|
const marker = step.badge?.marker ?? null;
|
|
4120
4236
|
if (marker) badge.appendChild(buildMarkerElement(doc, marker));
|
|
4121
4237
|
else this.buildContent(badge, step.badge?.blocks ?? [], doc, context, idx, [], host);
|
|
4122
|
-
|
|
4238
|
+
markerRoot.appendChild(badge);
|
|
4239
|
+
host.style.display = "block";
|
|
4123
4240
|
if (design.fullWidth === true) {
|
|
4124
4241
|
card.style.width = "auto";
|
|
4125
4242
|
card.style.maxWidth = "320px";
|
|
@@ -4134,13 +4251,13 @@ var CompositeRenderer = class extends BaseRenderer {
|
|
|
4134
4251
|
wrapper.appendChild(card);
|
|
4135
4252
|
root.appendChild(wrapper);
|
|
4136
4253
|
if (marker) {
|
|
4137
|
-
|
|
4138
|
-
this.registerCleanup(attachMarker(anchor,
|
|
4254
|
+
markerHost.style.display = "inline-block";
|
|
4255
|
+
this.registerCleanup(attachMarker(anchor, markerHost, marker));
|
|
4139
4256
|
} else {
|
|
4140
|
-
|
|
4257
|
+
markerHost.style.display = "inline-block";
|
|
4141
4258
|
const pos = inlinePosOf(step.inlinePosition);
|
|
4142
|
-
insertHost(anchor,
|
|
4143
|
-
this.registerCleanup(keepHostAttached(
|
|
4259
|
+
insertHost(anchor, markerHost, pos);
|
|
4260
|
+
this.registerCleanup(keepHostAttached(markerHost, anchorSelector, pos));
|
|
4144
4261
|
}
|
|
4145
4262
|
let open = false;
|
|
4146
4263
|
let stopFloat = null;
|
|
@@ -4270,7 +4387,7 @@ function liftTarget(anchor, zIndex) {
|
|
|
4270
4387
|
const prevPosition = el2.style.position;
|
|
4271
4388
|
const prevZ = el2.style.zIndex;
|
|
4272
4389
|
if (getComputedStyle(el2).position === "static") el2.style.position = "relative";
|
|
4273
|
-
el2.style.zIndex = String(zIndex);
|
|
4390
|
+
el2.style.zIndex = String(clampZIndex(zIndex, 0));
|
|
4274
4391
|
return () => {
|
|
4275
4392
|
el2.style.position = prevPosition;
|
|
4276
4393
|
el2.style.zIndex = prevZ;
|
|
@@ -5217,14 +5334,19 @@ function injectBuilderChrome(opts) {
|
|
|
5217
5334
|
let previewOn = false;
|
|
5218
5335
|
let hiddenOn = false;
|
|
5219
5336
|
let heightCb = null;
|
|
5220
|
-
|
|
5337
|
+
let tagging = false;
|
|
5338
|
+
const height = () => CHROME_TOPBAR_H + (collapsed || tagging ? 0 : CHROME_STEPS_H);
|
|
5221
5339
|
const applyHeight = () => {
|
|
5222
5340
|
const h = previewOn || hiddenOn ? 0 : height();
|
|
5223
5341
|
html.style.marginTop = dock === "top" ? `${h}px` : prevMarginTop;
|
|
5224
5342
|
html.style.marginBottom = dock === "bottom" ? `${h}px` : prevMarginBottom;
|
|
5225
5343
|
root.style.setProperty("--veo-chrome-h", `${height()}px`);
|
|
5226
5344
|
root.classList.toggle("is-bottom", dock === "bottom");
|
|
5227
|
-
stepsBar.hidden = collapsed;
|
|
5345
|
+
stepsBar.hidden = collapsed || tagging;
|
|
5346
|
+
togglePill.hidden = tagging;
|
|
5347
|
+
preview.hidden = tagging;
|
|
5348
|
+
saveGroup.hidden = tagging;
|
|
5349
|
+
showPanel.title = tagging ? "Mostrar el panel" : "Mostrar el editor";
|
|
5228
5350
|
const open = dock === "top" ? "chevronUp" : "chevronDown";
|
|
5229
5351
|
const closedIcon = dock === "top" ? "chevronDown" : "chevronUp";
|
|
5230
5352
|
togglePill.innerHTML = `<span>${collapsed ? "Mostrar pasos" : "Ocultar pasos"}</span>${svg(
|
|
@@ -5277,8 +5399,13 @@ function injectBuilderChrome(opts) {
|
|
|
5277
5399
|
const render = () => {
|
|
5278
5400
|
const s = current;
|
|
5279
5401
|
if (!s) return;
|
|
5402
|
+
const nextTagging = s.variant === "tagging";
|
|
5403
|
+
if (nextTagging !== tagging) {
|
|
5404
|
+
tagging = nextTagging;
|
|
5405
|
+
applyHeight();
|
|
5406
|
+
}
|
|
5280
5407
|
const date = shortDate(s.createdAt);
|
|
5281
|
-
nameEl.textContent = `${s.guideName.trim() || "Sin nombre"}${date ? ` \xB7 ${date}` : ""}`;
|
|
5408
|
+
nameEl.textContent = tagging ? s.guideName.trim() || "Modo tagging" : `${s.guideName.trim() || "Sin nombre"}${date ? ` \xB7 ${date}` : ""}`;
|
|
5282
5409
|
if (s.status) {
|
|
5283
5410
|
statusEl.hidden = false;
|
|
5284
5411
|
statusEl.textContent = s.status.label;
|
|
@@ -5377,6 +5504,8 @@ var CHROME_CSS = `
|
|
|
5377
5504
|
font-size: 14px; color: #1c1917;
|
|
5378
5505
|
}
|
|
5379
5506
|
.veo-chrome[hidden] { display: none; }
|
|
5507
|
+
/* Modo tagging oculta controles por atributo: gana a los display de sus clases. */
|
|
5508
|
+
.veo-chrome [hidden], .veo-steps-toggle[hidden] { display: none !important; }
|
|
5380
5509
|
.veo-chrome.is-bottom { top: auto; bottom: 0; flex-direction: column-reverse; }
|
|
5381
5510
|
.veo-chrome.is-bottom .veo-tb-menu { top: auto; bottom: calc(100% + 8px); }
|
|
5382
5511
|
.veo-chrome.is-bottom .veo-steps { border-bottom: 0; border-top: 1px solid #d6cfc8; }
|
|
@@ -5996,90 +6125,51 @@ function attachBanner(opts, shadow, banner) {
|
|
|
5996
6125
|
};
|
|
5997
6126
|
}
|
|
5998
6127
|
|
|
5999
|
-
// src/plugins/
|
|
6000
|
-
var
|
|
6001
|
-
|
|
6002
|
-
|
|
6003
|
-
|
|
6004
|
-
|
|
6005
|
-
|
|
6006
|
-
|
|
6007
|
-
|
|
6008
|
-
|
|
6009
|
-
|
|
6010
|
-
|
|
6011
|
-
|
|
6012
|
-
|
|
6013
|
-
|
|
6014
|
-
|
|
6015
|
-
|
|
6016
|
-
}
|
|
6017
|
-
function filterHumanClasses(element) {
|
|
6018
|
-
return Array.from(element.classList).filter((c) => !isHashedClass(c) && c.length < 64);
|
|
6019
|
-
}
|
|
6020
|
-
var STABLE_ATTRIBUTES = [
|
|
6021
|
-
"data-testid",
|
|
6022
|
-
"data-test",
|
|
6023
|
-
"data-cy",
|
|
6024
|
-
"name",
|
|
6025
|
-
"aria-label",
|
|
6026
|
-
"placeholder",
|
|
6027
|
-
"alt",
|
|
6028
|
-
"title",
|
|
6029
|
-
// `href` identifica muy bien a los links (`<a>`), un target frecuente de
|
|
6030
|
-
// autocapture; va después de los atributos semánticos pero antes de los
|
|
6031
|
-
// genéricos. Valores largos (URLs absolutas con query) se descartan por
|
|
6032
|
-
// MAX_ATTR_VALUE_LENGTH.
|
|
6033
|
-
"href",
|
|
6034
|
-
"role",
|
|
6035
|
-
"type"
|
|
6128
|
+
// src/plugins/builder/interactive-elements.ts
|
|
6129
|
+
var INTERACTIVE_ROLES = [
|
|
6130
|
+
"button",
|
|
6131
|
+
"link",
|
|
6132
|
+
"tab",
|
|
6133
|
+
"menuitem",
|
|
6134
|
+
"menuitemcheckbox",
|
|
6135
|
+
"menuitemradio",
|
|
6136
|
+
"checkbox",
|
|
6137
|
+
"radio",
|
|
6138
|
+
"switch",
|
|
6139
|
+
"option",
|
|
6140
|
+
"combobox",
|
|
6141
|
+
"textbox",
|
|
6142
|
+
"searchbox",
|
|
6143
|
+
"slider",
|
|
6144
|
+
"spinbutton"
|
|
6036
6145
|
];
|
|
6037
|
-
var
|
|
6038
|
-
|
|
6039
|
-
|
|
6040
|
-
|
|
6041
|
-
|
|
6042
|
-
|
|
6043
|
-
|
|
6044
|
-
|
|
6045
|
-
|
|
6046
|
-
|
|
6047
|
-
|
|
6048
|
-
|
|
6049
|
-
|
|
6050
|
-
|
|
6051
|
-
|
|
6052
|
-
|
|
6053
|
-
}
|
|
6054
|
-
|
|
6055
|
-
}
|
|
6056
|
-
function buildElementSelector(element) {
|
|
6057
|
-
const tag = element.tagName.toLowerCase();
|
|
6058
|
-
const veoTag = element.getAttribute("data-veo-tag");
|
|
6059
|
-
if (veoTag) {
|
|
6060
|
-
return `${tag}[data-veo-tag="${escapeAttrValue(veoTag)}"]`;
|
|
6061
|
-
}
|
|
6062
|
-
if (element.id) {
|
|
6063
|
-
const classes2 = filterHumanClasses(element);
|
|
6064
|
-
const classPart2 = classes2.length > 0 ? `.${classes2.map(cssEscape).join(".")}` : "";
|
|
6065
|
-
return `${tag}#${cssEscape(element.id)}${classPart2}`;
|
|
6146
|
+
var INTERACTIVE_SELECTOR = [
|
|
6147
|
+
"button",
|
|
6148
|
+
"a[href]",
|
|
6149
|
+
'input:not([type="hidden"])',
|
|
6150
|
+
"select",
|
|
6151
|
+
"textarea",
|
|
6152
|
+
"form",
|
|
6153
|
+
"summary",
|
|
6154
|
+
'[contenteditable="true"]',
|
|
6155
|
+
"[onclick]",
|
|
6156
|
+
"[data-veo-tag]",
|
|
6157
|
+
...INTERACTIVE_ROLES.map((r) => `[role="${r}"]`)
|
|
6158
|
+
].join(", ");
|
|
6159
|
+
function closestInteractive(element) {
|
|
6160
|
+
try {
|
|
6161
|
+
return element.closest(INTERACTIVE_SELECTOR);
|
|
6162
|
+
} catch {
|
|
6163
|
+
return null;
|
|
6066
6164
|
}
|
|
6067
|
-
const attrSelector = stableAttributeSelector(element, tag);
|
|
6068
|
-
if (attrSelector) return attrSelector;
|
|
6069
|
-
const classes = filterHumanClasses(element);
|
|
6070
|
-
const classPart = classes.length > 0 ? `.${classes.map(cssEscape).join(".")}` : "";
|
|
6071
|
-
return `${tag}${classPart}`;
|
|
6072
6165
|
}
|
|
6073
|
-
|
|
6074
|
-
|
|
6075
|
-
|
|
6076
|
-
|
|
6077
|
-
|
|
6078
|
-
|
|
6079
|
-
|
|
6080
|
-
depth++;
|
|
6081
|
-
}
|
|
6082
|
-
return parts.join(" > ");
|
|
6166
|
+
var EMOJI_RE = /\p{Extended_Pictographic}|\p{Emoji_Modifier}|\u{FE0F}|\u{200D}|\u{20E3}/gu;
|
|
6167
|
+
function elementLabelText(element, max = 120) {
|
|
6168
|
+
const clean = (raw) => (raw ?? "").replace(EMOJI_RE, "").replace(/\s+/g, " ").trim();
|
|
6169
|
+
const text = clean(element.textContent);
|
|
6170
|
+
if (text) return text.slice(0, max);
|
|
6171
|
+
const fallback = clean(element.getAttribute("aria-label")) || clean(element.getAttribute("title"));
|
|
6172
|
+
return fallback.slice(0, max);
|
|
6083
6173
|
}
|
|
6084
6174
|
|
|
6085
6175
|
// src/plugins/builder/element-picker.ts
|
|
@@ -6152,21 +6242,24 @@ var ElementPicker = class {
|
|
|
6152
6242
|
this.label = null;
|
|
6153
6243
|
this.current = null;
|
|
6154
6244
|
this.maxAncestors = DEFAULT_MAX_ANCESTORS;
|
|
6245
|
+
this.only = null;
|
|
6155
6246
|
this.onPick = null;
|
|
6156
6247
|
this.onCancel = null;
|
|
6157
6248
|
this.onMove = (event) => {
|
|
6158
|
-
|
|
6159
|
-
|
|
6249
|
+
if (!(event.target instanceof Element) || this.isOwn(event.target)) return;
|
|
6250
|
+
const target = this.resolveTarget(event.target);
|
|
6160
6251
|
this.current = target;
|
|
6161
|
-
this.draw(target);
|
|
6252
|
+
if (target) this.draw(target);
|
|
6253
|
+
else this.hideBox();
|
|
6162
6254
|
};
|
|
6163
6255
|
this.onClick = (event) => {
|
|
6164
6256
|
if (event.altKey) return;
|
|
6165
|
-
|
|
6166
|
-
if (!target || this.isOwn(target)) return;
|
|
6257
|
+
if (this.isOwn(event.target)) return;
|
|
6167
6258
|
event.preventDefault();
|
|
6168
6259
|
event.stopPropagation();
|
|
6169
6260
|
event.stopImmediatePropagation();
|
|
6261
|
+
const target = this.current ?? this.resolveTarget(event.target);
|
|
6262
|
+
if (!target) return;
|
|
6170
6263
|
const picked = this.describe(target);
|
|
6171
6264
|
const cb = this.onPick;
|
|
6172
6265
|
this.stop();
|
|
@@ -6193,6 +6286,7 @@ var ElementPicker = class {
|
|
|
6193
6286
|
start(options) {
|
|
6194
6287
|
this.stop();
|
|
6195
6288
|
this.maxAncestors = options.maxAncestors ?? DEFAULT_MAX_ANCESTORS;
|
|
6289
|
+
this.only = options.only ?? null;
|
|
6196
6290
|
this.onPick = options.onPick;
|
|
6197
6291
|
this.onCancel = options.onCancel ?? null;
|
|
6198
6292
|
const host = document.createElement("div");
|
|
@@ -6255,9 +6349,19 @@ var ElementPicker = class {
|
|
|
6255
6349
|
this.box = null;
|
|
6256
6350
|
this.label = null;
|
|
6257
6351
|
this.current = null;
|
|
6352
|
+
this.only = null;
|
|
6258
6353
|
this.onPick = null;
|
|
6259
6354
|
this.onCancel = null;
|
|
6260
6355
|
}
|
|
6356
|
+
/** Elemento que se elegiría para el nodo bajo el cursor (o null si no hay). */
|
|
6357
|
+
resolveTarget(target) {
|
|
6358
|
+
if (!(target instanceof Element) || this.isOwn(target)) return null;
|
|
6359
|
+
return this.only === "interactive" ? closestInteractive(target) : target;
|
|
6360
|
+
}
|
|
6361
|
+
hideBox() {
|
|
6362
|
+
if (this.box) this.box.style.display = "none";
|
|
6363
|
+
if (this.label) this.label.style.display = "none";
|
|
6364
|
+
}
|
|
6261
6365
|
/** ¿Es un nodo de nuestro propio overlay? (no debe ser seleccionable). */
|
|
6262
6366
|
isOwn(target) {
|
|
6263
6367
|
return target instanceof Node && this.host !== null && this.host.contains(target);
|
|
@@ -6294,7 +6398,7 @@ var ElementPicker = class {
|
|
|
6294
6398
|
tag: element.tagName.toLowerCase(),
|
|
6295
6399
|
id: element.id || null,
|
|
6296
6400
|
classes: filterHumanClasses(element),
|
|
6297
|
-
text: (element
|
|
6401
|
+
text: elementLabelText(element),
|
|
6298
6402
|
rect: {
|
|
6299
6403
|
x: Math.round(rect.left),
|
|
6300
6404
|
y: Math.round(rect.top),
|
|
@@ -6319,6 +6423,41 @@ function stopElementPicker() {
|
|
|
6319
6423
|
}
|
|
6320
6424
|
|
|
6321
6425
|
// src/plugins/builder/builder-mode.ts
|
|
6426
|
+
var CONFIRMATION_STYLES = `
|
|
6427
|
+
:host { all: initial; }
|
|
6428
|
+
.veo-confirm-backdrop {
|
|
6429
|
+
position: fixed; inset: 0; z-index: 2147483645;
|
|
6430
|
+
background: rgba(20, 16, 14, 0.45);
|
|
6431
|
+
}
|
|
6432
|
+
.veo-confirm {
|
|
6433
|
+
position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%);
|
|
6434
|
+
z-index: 2147483646; box-sizing: border-box;
|
|
6435
|
+
width: min(432px, calc(100vw - 32px)); padding: 28px 24px 24px;
|
|
6436
|
+
border-radius: 16px; background: #fff; color: #1d1917;
|
|
6437
|
+
box-shadow: 0 24px 64px rgba(0,0,0,0.28);
|
|
6438
|
+
font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
|
|
6439
|
+
text-align: center;
|
|
6440
|
+
}
|
|
6441
|
+
.veo-confirm-check {
|
|
6442
|
+
width: 64px; height: 64px; margin: 0 auto; border-radius: 50%;
|
|
6443
|
+
background: #e6f6df; color: #2f9a4e; display: flex; align-items: center; justify-content: center;
|
|
6444
|
+
}
|
|
6445
|
+
.veo-confirm-check svg { width: 30px; height: 30px; }
|
|
6446
|
+
.veo-confirm-title { margin: 18px 0 0; font-size: 17px; font-weight: 600; }
|
|
6447
|
+
.veo-confirm-msg { margin: 8px 0 0; font-size: 13px; color: #6b6461; }
|
|
6448
|
+
.veo-confirm-rows {
|
|
6449
|
+
margin: 18px 0 0; padding: 12px 14px; border-radius: 12px; background: #f6f2ef; text-align: left;
|
|
6450
|
+
}
|
|
6451
|
+
.veo-confirm-row { display: flex; justify-content: space-between; gap: 16px; font-size: 13px; padding: 4px 0; }
|
|
6452
|
+
.veo-confirm-row dt { color: #6b6461; margin: 0; }
|
|
6453
|
+
.veo-confirm-row dd { margin: 0; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
6454
|
+
.veo-confirm-btn {
|
|
6455
|
+
display: block; width: 100%; margin-top: 18px; height: 44px; border: 0; border-radius: 10px;
|
|
6456
|
+
background: #b74d00; color: #fff; font: inherit; font-size: 15px; font-weight: 600; cursor: pointer;
|
|
6457
|
+
}
|
|
6458
|
+
.veo-confirm-btn:hover { background: #953c00; }
|
|
6459
|
+
.veo-confirm-btn:focus-visible { outline: 3px solid rgba(183,77,0,0.35); outline-offset: 2px; }
|
|
6460
|
+
`;
|
|
6322
6461
|
function initBuilderMode() {
|
|
6323
6462
|
if (!hasWindow() || !hasDocument()) return null;
|
|
6324
6463
|
const ctx = resolveBuilderContext();
|
|
@@ -7300,7 +7439,7 @@ function initBuilderMode() {
|
|
|
7300
7439
|
if (h && hoverCard && !previewMode) renderCardChrome(h, previewStepIndex);
|
|
7301
7440
|
}
|
|
7302
7441
|
panel?.setTitle(
|
|
7303
|
-
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"
|
|
7442
|
+
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")
|
|
7304
7443
|
);
|
|
7305
7444
|
break;
|
|
7306
7445
|
case "panel-visibility":
|
|
@@ -7338,7 +7477,8 @@ function initBuilderMode() {
|
|
|
7338
7477
|
post({ type: "pick-cancelled" });
|
|
7339
7478
|
},
|
|
7340
7479
|
...cmd.maxAncestors !== void 0 ? { maxAncestors: cmd.maxAncestors } : {},
|
|
7341
|
-
...cmd.hint !== void 0 ? { hint: cmd.hint } : {}
|
|
7480
|
+
...cmd.hint !== void 0 ? { hint: cmd.hint } : {},
|
|
7481
|
+
...cmd.only !== void 0 ? { only: cmd.only } : {}
|
|
7342
7482
|
});
|
|
7343
7483
|
break;
|
|
7344
7484
|
}
|
|
@@ -7347,6 +7487,15 @@ function initBuilderMode() {
|
|
|
7347
7487
|
picker = null;
|
|
7348
7488
|
chrome?.setHidden(false);
|
|
7349
7489
|
break;
|
|
7490
|
+
case "scan-page":
|
|
7491
|
+
post({ type: "page-scan", payload: scanPage(cmd.selectors) });
|
|
7492
|
+
break;
|
|
7493
|
+
case "highlight":
|
|
7494
|
+
setHighlight(cmd.selector);
|
|
7495
|
+
break;
|
|
7496
|
+
case "show-confirmation":
|
|
7497
|
+
showConfirmation(cmd.payload);
|
|
7498
|
+
break;
|
|
7350
7499
|
case "preview":
|
|
7351
7500
|
if (!cmd.guide) break;
|
|
7352
7501
|
if (manipulator?.isDragging()) pendingPreview = cmd;
|
|
@@ -7431,10 +7580,154 @@ function initBuilderMode() {
|
|
|
7431
7580
|
post({ type: "closed" });
|
|
7432
7581
|
panel?.teardown();
|
|
7433
7582
|
panel = null;
|
|
7583
|
+
highlightBox?.remove();
|
|
7584
|
+
highlightBox = null;
|
|
7585
|
+
confirmation?.remove();
|
|
7586
|
+
confirmation = null;
|
|
7587
|
+
if (confirmationKey) document.removeEventListener("keydown", confirmationKey, true);
|
|
7588
|
+
confirmationKey = null;
|
|
7434
7589
|
chrome?.teardown();
|
|
7435
7590
|
chrome = null;
|
|
7436
7591
|
clearBuilderToken();
|
|
7437
7592
|
};
|
|
7593
|
+
const scanPage = (selectors) => {
|
|
7594
|
+
const present = selectors.filter((sel) => {
|
|
7595
|
+
try {
|
|
7596
|
+
return document.querySelector(sel) !== null;
|
|
7597
|
+
} catch {
|
|
7598
|
+
return false;
|
|
7599
|
+
}
|
|
7600
|
+
});
|
|
7601
|
+
const taggedEls = /* @__PURE__ */ new Set();
|
|
7602
|
+
for (const sel of present) {
|
|
7603
|
+
try {
|
|
7604
|
+
for (const e of Array.from(document.querySelectorAll(sel))) taggedEls.add(e);
|
|
7605
|
+
} catch {
|
|
7606
|
+
}
|
|
7607
|
+
}
|
|
7608
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7609
|
+
const candidates = [];
|
|
7610
|
+
const nodes = document.querySelectorAll(INTERACTIVE_SELECTOR);
|
|
7611
|
+
for (const element of Array.from(nodes)) {
|
|
7612
|
+
if (candidates.length >= 200) break;
|
|
7613
|
+
if (element.closest("[data-veo-builder-chrome],[data-veo-builder-panel],[data-veo-picker]")) {
|
|
7614
|
+
continue;
|
|
7615
|
+
}
|
|
7616
|
+
if (element.getClientRects().length === 0) continue;
|
|
7617
|
+
let tagged = false;
|
|
7618
|
+
for (let n = element; n; n = n.parentElement) {
|
|
7619
|
+
if (taggedEls.has(n)) {
|
|
7620
|
+
tagged = true;
|
|
7621
|
+
break;
|
|
7622
|
+
}
|
|
7623
|
+
}
|
|
7624
|
+
if (tagged) continue;
|
|
7625
|
+
const selector = buildSelectorPath(element, 5);
|
|
7626
|
+
if (!selector || seen.has(selector)) continue;
|
|
7627
|
+
seen.add(selector);
|
|
7628
|
+
candidates.push({
|
|
7629
|
+
selector,
|
|
7630
|
+
shortSelector: buildSelectorPath(element, 0),
|
|
7631
|
+
tag: element.tagName.toLowerCase(),
|
|
7632
|
+
id: element.id || null,
|
|
7633
|
+
classes: filterHumanClasses(element),
|
|
7634
|
+
text: elementLabelText(element)
|
|
7635
|
+
});
|
|
7636
|
+
}
|
|
7637
|
+
const { pathname, hash } = window.location;
|
|
7638
|
+
const routePath = /^#\/./.test(hash) ? `${pathname}${hash}` : pathname;
|
|
7639
|
+
return { pagePath: pathname, routePath, candidates, present };
|
|
7640
|
+
};
|
|
7641
|
+
let confirmation = null;
|
|
7642
|
+
let confirmationKey = null;
|
|
7643
|
+
const closeConfirmation = () => {
|
|
7644
|
+
if (!confirmation) return;
|
|
7645
|
+
confirmation.remove();
|
|
7646
|
+
confirmation = null;
|
|
7647
|
+
if (confirmationKey) document.removeEventListener("keydown", confirmationKey, true);
|
|
7648
|
+
confirmationKey = null;
|
|
7649
|
+
panel?.setVisible(true);
|
|
7650
|
+
post({ type: "confirmation-closed" });
|
|
7651
|
+
};
|
|
7652
|
+
const showConfirmation = (card) => {
|
|
7653
|
+
if (confirmation) {
|
|
7654
|
+
confirmation.remove();
|
|
7655
|
+
confirmation = null;
|
|
7656
|
+
}
|
|
7657
|
+
panel?.setVisible(false);
|
|
7658
|
+
const host = document.createElement("div");
|
|
7659
|
+
host.setAttribute("data-veo-builder-chrome", "");
|
|
7660
|
+
host.setAttribute("data-veo-confirmation", "");
|
|
7661
|
+
const shadow = host.attachShadow({ mode: "open" });
|
|
7662
|
+
const style = document.createElement("style");
|
|
7663
|
+
style.textContent = CONFIRMATION_STYLES;
|
|
7664
|
+
const backdrop = document.createElement("div");
|
|
7665
|
+
backdrop.className = "veo-confirm-backdrop";
|
|
7666
|
+
const dialog = document.createElement("div");
|
|
7667
|
+
dialog.className = "veo-confirm";
|
|
7668
|
+
dialog.setAttribute("role", "dialog");
|
|
7669
|
+
dialog.setAttribute("aria-modal", "true");
|
|
7670
|
+
dialog.setAttribute("aria-label", card.title);
|
|
7671
|
+
const badge = document.createElement("div");
|
|
7672
|
+
badge.className = "veo-confirm-check";
|
|
7673
|
+
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>';
|
|
7674
|
+
const title = document.createElement("h2");
|
|
7675
|
+
title.className = "veo-confirm-title";
|
|
7676
|
+
title.textContent = card.title;
|
|
7677
|
+
const message = document.createElement("p");
|
|
7678
|
+
message.className = "veo-confirm-msg";
|
|
7679
|
+
message.textContent = card.message;
|
|
7680
|
+
const rows = document.createElement("dl");
|
|
7681
|
+
rows.className = "veo-confirm-rows";
|
|
7682
|
+
for (const r of card.rows) {
|
|
7683
|
+
const row = document.createElement("div");
|
|
7684
|
+
row.className = "veo-confirm-row";
|
|
7685
|
+
const dt = document.createElement("dt");
|
|
7686
|
+
dt.textContent = r.label;
|
|
7687
|
+
const dd = document.createElement("dd");
|
|
7688
|
+
dd.textContent = r.value;
|
|
7689
|
+
row.append(dt, dd);
|
|
7690
|
+
rows.appendChild(row);
|
|
7691
|
+
}
|
|
7692
|
+
const button = document.createElement("button");
|
|
7693
|
+
button.type = "button";
|
|
7694
|
+
button.className = "veo-confirm-btn";
|
|
7695
|
+
button.textContent = card.buttonLabel ?? "Listo";
|
|
7696
|
+
button.addEventListener("click", closeConfirmation);
|
|
7697
|
+
dialog.append(badge, title, message);
|
|
7698
|
+
if (card.rows.length > 0) dialog.appendChild(rows);
|
|
7699
|
+
dialog.appendChild(button);
|
|
7700
|
+
shadow.append(style, backdrop, dialog);
|
|
7701
|
+
document.body.appendChild(host);
|
|
7702
|
+
confirmation = host;
|
|
7703
|
+
confirmationKey = (e) => {
|
|
7704
|
+
if (e.key !== "Escape") return;
|
|
7705
|
+
e.preventDefault();
|
|
7706
|
+
e.stopPropagation();
|
|
7707
|
+
closeConfirmation();
|
|
7708
|
+
};
|
|
7709
|
+
document.addEventListener("keydown", confirmationKey, true);
|
|
7710
|
+
button.focus();
|
|
7711
|
+
};
|
|
7712
|
+
let highlightBox = null;
|
|
7713
|
+
const setHighlight = (selector) => {
|
|
7714
|
+
highlightBox?.remove();
|
|
7715
|
+
highlightBox = null;
|
|
7716
|
+
if (!selector) return;
|
|
7717
|
+
let target = null;
|
|
7718
|
+
try {
|
|
7719
|
+
target = document.querySelector(selector);
|
|
7720
|
+
} catch {
|
|
7721
|
+
return;
|
|
7722
|
+
}
|
|
7723
|
+
if (!target) return;
|
|
7724
|
+
const r = target.getBoundingClientRect();
|
|
7725
|
+
const box = document.createElement("div");
|
|
7726
|
+
box.setAttribute("data-veo-builder-chrome", "");
|
|
7727
|
+
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;`;
|
|
7728
|
+
document.body.appendChild(box);
|
|
7729
|
+
highlightBox = box;
|
|
7730
|
+
};
|
|
7438
7731
|
if (ctx.panel) {
|
|
7439
7732
|
chrome = injectBuilderChrome({
|
|
7440
7733
|
appLabel: window.location.hostname,
|