veo-sdk 0.6.2 → 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-ENKEIVF2.mjs.map → builder-PPLIAUCM.mjs.map} +1 -1
- package/dist/builder.cjs +354 -92
- 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-3JEAPZ6A.mjs} +3 -3
- package/dist/{chunk-L3QQJLDJ.mjs.map → chunk-3JEAPZ6A.mjs.map} +1 -1
- package/dist/{chunk-4QZDNJJE.mjs → chunk-DU6I4ZU2.mjs} +284 -15
- package/dist/chunk-DU6I4ZU2.mjs.map +1 -0
- package/dist/{chunk-ZILDR4YE.mjs → chunk-SZCIXA5X.mjs} +70 -69
- package/dist/chunk-SZCIXA5X.mjs.map +1 -0
- package/dist/index.cjs +601 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.mjs +306 -6
- 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.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
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { INTERACTIVE_SELECTOR, VEO_BLOCK_MIME, attachBlockDropTarget, attachDesignManipulator, closestInteractive, createBuilderSession, elementLabelText, initBuilderMode, isInteractiveElement, startElementPicker, stopElementPicker } from './chunk-DU6I4ZU2.mjs';
|
|
2
|
+
import './chunk-SZCIXA5X.mjs';
|
|
3
|
+
import './chunk-PTG3BTJE.mjs';
|
|
4
|
+
//# sourceMappingURL=builder-PPLIAUCM.mjs.map
|
|
5
|
+
//# sourceMappingURL=builder-PPLIAUCM.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"builder-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"builder-PPLIAUCM.mjs"}
|
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) {
|
|
@@ -5217,14 +5303,19 @@ function injectBuilderChrome(opts) {
|
|
|
5217
5303
|
let previewOn = false;
|
|
5218
5304
|
let hiddenOn = false;
|
|
5219
5305
|
let heightCb = null;
|
|
5220
|
-
|
|
5306
|
+
let tagging = false;
|
|
5307
|
+
const height = () => CHROME_TOPBAR_H + (collapsed || tagging ? 0 : CHROME_STEPS_H);
|
|
5221
5308
|
const applyHeight = () => {
|
|
5222
5309
|
const h = previewOn || hiddenOn ? 0 : height();
|
|
5223
5310
|
html.style.marginTop = dock === "top" ? `${h}px` : prevMarginTop;
|
|
5224
5311
|
html.style.marginBottom = dock === "bottom" ? `${h}px` : prevMarginBottom;
|
|
5225
5312
|
root.style.setProperty("--veo-chrome-h", `${height()}px`);
|
|
5226
5313
|
root.classList.toggle("is-bottom", dock === "bottom");
|
|
5227
|
-
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";
|
|
5228
5319
|
const open = dock === "top" ? "chevronUp" : "chevronDown";
|
|
5229
5320
|
const closedIcon = dock === "top" ? "chevronDown" : "chevronUp";
|
|
5230
5321
|
togglePill.innerHTML = `<span>${collapsed ? "Mostrar pasos" : "Ocultar pasos"}</span>${svg(
|
|
@@ -5277,8 +5368,13 @@ function injectBuilderChrome(opts) {
|
|
|
5277
5368
|
const render = () => {
|
|
5278
5369
|
const s = current;
|
|
5279
5370
|
if (!s) return;
|
|
5371
|
+
const nextTagging = s.variant === "tagging";
|
|
5372
|
+
if (nextTagging !== tagging) {
|
|
5373
|
+
tagging = nextTagging;
|
|
5374
|
+
applyHeight();
|
|
5375
|
+
}
|
|
5280
5376
|
const date = shortDate(s.createdAt);
|
|
5281
|
-
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}` : ""}`;
|
|
5282
5378
|
if (s.status) {
|
|
5283
5379
|
statusEl.hidden = false;
|
|
5284
5380
|
statusEl.textContent = s.status.label;
|
|
@@ -5377,6 +5473,8 @@ var CHROME_CSS = `
|
|
|
5377
5473
|
font-size: 14px; color: #1c1917;
|
|
5378
5474
|
}
|
|
5379
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; }
|
|
5380
5478
|
.veo-chrome.is-bottom { top: auto; bottom: 0; flex-direction: column-reverse; }
|
|
5381
5479
|
.veo-chrome.is-bottom .veo-tb-menu { top: auto; bottom: calc(100% + 8px); }
|
|
5382
5480
|
.veo-chrome.is-bottom .veo-steps { border-bottom: 0; border-top: 1px solid #d6cfc8; }
|
|
@@ -5996,90 +6094,51 @@ function attachBanner(opts, shadow, banner) {
|
|
|
5996
6094
|
};
|
|
5997
6095
|
}
|
|
5998
6096
|
|
|
5999
|
-
// src/plugins/
|
|
6000
|
-
var
|
|
6001
|
-
|
|
6002
|
-
|
|
6003
|
-
|
|
6004
|
-
|
|
6005
|
-
|
|
6006
|
-
|
|
6007
|
-
|
|
6008
|
-
|
|
6009
|
-
|
|
6010
|
-
|
|
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"
|
|
6011
6114
|
];
|
|
6012
|
-
|
|
6013
|
-
|
|
6014
|
-
|
|
6015
|
-
|
|
6016
|
-
|
|
6017
|
-
|
|
6018
|
-
|
|
6019
|
-
|
|
6020
|
-
|
|
6021
|
-
"
|
|
6022
|
-
"data-
|
|
6023
|
-
"
|
|
6024
|
-
|
|
6025
|
-
|
|
6026
|
-
|
|
6027
|
-
|
|
6028
|
-
|
|
6029
|
-
|
|
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"
|
|
6036
|
-
];
|
|
6037
|
-
var MAX_ATTR_VALUE_LENGTH = 100;
|
|
6038
|
-
function cssEscape(value) {
|
|
6039
|
-
if (typeof CSS !== "undefined" && typeof CSS.escape === "function") {
|
|
6040
|
-
return CSS.escape(value);
|
|
6041
|
-
}
|
|
6042
|
-
return value.replace(/[!"#$%&'()*+,./:;<=>?@[\\\]^`{|}~]/g, "\\$&");
|
|
6043
|
-
}
|
|
6044
|
-
function escapeAttrValue(value) {
|
|
6045
|
-
return value.replace(/[\\"]/g, "\\$&");
|
|
6046
|
-
}
|
|
6047
|
-
function stableAttributeSelector(element, tag) {
|
|
6048
|
-
for (const attr of STABLE_ATTRIBUTES) {
|
|
6049
|
-
const value = element.getAttribute(attr);
|
|
6050
|
-
if (value && value.length > 0 && value.length <= MAX_ATTR_VALUE_LENGTH) {
|
|
6051
|
-
return `${tag}[${attr}="${escapeAttrValue(value)}"]`;
|
|
6052
|
-
}
|
|
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;
|
|
6053
6133
|
}
|
|
6054
|
-
return null;
|
|
6055
6134
|
}
|
|
6056
|
-
|
|
6057
|
-
|
|
6058
|
-
const
|
|
6059
|
-
|
|
6060
|
-
|
|
6061
|
-
|
|
6062
|
-
|
|
6063
|
-
const classes2 = filterHumanClasses(element);
|
|
6064
|
-
const classPart2 = classes2.length > 0 ? `.${classes2.map(cssEscape).join(".")}` : "";
|
|
6065
|
-
return `${tag}#${cssEscape(element.id)}${classPart2}`;
|
|
6066
|
-
}
|
|
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
|
-
}
|
|
6073
|
-
function buildSelectorPath(element, maxAncestors = 5) {
|
|
6074
|
-
const parts = [];
|
|
6075
|
-
let current = element;
|
|
6076
|
-
let depth = 0;
|
|
6077
|
-
while (current && current !== document.documentElement && depth <= maxAncestors) {
|
|
6078
|
-
parts.unshift(buildElementSelector(current));
|
|
6079
|
-
current = current.parentElement;
|
|
6080
|
-
depth++;
|
|
6081
|
-
}
|
|
6082
|
-
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);
|
|
6083
6142
|
}
|
|
6084
6143
|
|
|
6085
6144
|
// src/plugins/builder/element-picker.ts
|
|
@@ -6152,21 +6211,24 @@ var ElementPicker = class {
|
|
|
6152
6211
|
this.label = null;
|
|
6153
6212
|
this.current = null;
|
|
6154
6213
|
this.maxAncestors = DEFAULT_MAX_ANCESTORS;
|
|
6214
|
+
this.only = null;
|
|
6155
6215
|
this.onPick = null;
|
|
6156
6216
|
this.onCancel = null;
|
|
6157
6217
|
this.onMove = (event) => {
|
|
6158
|
-
|
|
6159
|
-
|
|
6218
|
+
if (!(event.target instanceof Element) || this.isOwn(event.target)) return;
|
|
6219
|
+
const target = this.resolveTarget(event.target);
|
|
6160
6220
|
this.current = target;
|
|
6161
|
-
this.draw(target);
|
|
6221
|
+
if (target) this.draw(target);
|
|
6222
|
+
else this.hideBox();
|
|
6162
6223
|
};
|
|
6163
6224
|
this.onClick = (event) => {
|
|
6164
6225
|
if (event.altKey) return;
|
|
6165
|
-
|
|
6166
|
-
if (!target || this.isOwn(target)) return;
|
|
6226
|
+
if (this.isOwn(event.target)) return;
|
|
6167
6227
|
event.preventDefault();
|
|
6168
6228
|
event.stopPropagation();
|
|
6169
6229
|
event.stopImmediatePropagation();
|
|
6230
|
+
const target = this.current ?? this.resolveTarget(event.target);
|
|
6231
|
+
if (!target) return;
|
|
6170
6232
|
const picked = this.describe(target);
|
|
6171
6233
|
const cb = this.onPick;
|
|
6172
6234
|
this.stop();
|
|
@@ -6193,6 +6255,7 @@ var ElementPicker = class {
|
|
|
6193
6255
|
start(options) {
|
|
6194
6256
|
this.stop();
|
|
6195
6257
|
this.maxAncestors = options.maxAncestors ?? DEFAULT_MAX_ANCESTORS;
|
|
6258
|
+
this.only = options.only ?? null;
|
|
6196
6259
|
this.onPick = options.onPick;
|
|
6197
6260
|
this.onCancel = options.onCancel ?? null;
|
|
6198
6261
|
const host = document.createElement("div");
|
|
@@ -6255,9 +6318,19 @@ var ElementPicker = class {
|
|
|
6255
6318
|
this.box = null;
|
|
6256
6319
|
this.label = null;
|
|
6257
6320
|
this.current = null;
|
|
6321
|
+
this.only = null;
|
|
6258
6322
|
this.onPick = null;
|
|
6259
6323
|
this.onCancel = null;
|
|
6260
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
|
+
}
|
|
6261
6334
|
/** ¿Es un nodo de nuestro propio overlay? (no debe ser seleccionable). */
|
|
6262
6335
|
isOwn(target) {
|
|
6263
6336
|
return target instanceof Node && this.host !== null && this.host.contains(target);
|
|
@@ -6294,7 +6367,7 @@ var ElementPicker = class {
|
|
|
6294
6367
|
tag: element.tagName.toLowerCase(),
|
|
6295
6368
|
id: element.id || null,
|
|
6296
6369
|
classes: filterHumanClasses(element),
|
|
6297
|
-
text: (element
|
|
6370
|
+
text: elementLabelText(element),
|
|
6298
6371
|
rect: {
|
|
6299
6372
|
x: Math.round(rect.left),
|
|
6300
6373
|
y: Math.round(rect.top),
|
|
@@ -6319,6 +6392,41 @@ function stopElementPicker() {
|
|
|
6319
6392
|
}
|
|
6320
6393
|
|
|
6321
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
|
+
`;
|
|
6322
6430
|
function initBuilderMode() {
|
|
6323
6431
|
if (!hasWindow() || !hasDocument()) return null;
|
|
6324
6432
|
const ctx = resolveBuilderContext();
|
|
@@ -7300,7 +7408,7 @@ function initBuilderMode() {
|
|
|
7300
7408
|
if (h && hoverCard && !previewMode) renderCardChrome(h, previewStepIndex);
|
|
7301
7409
|
}
|
|
7302
7410
|
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"
|
|
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")
|
|
7304
7412
|
);
|
|
7305
7413
|
break;
|
|
7306
7414
|
case "panel-visibility":
|
|
@@ -7338,7 +7446,8 @@ function initBuilderMode() {
|
|
|
7338
7446
|
post({ type: "pick-cancelled" });
|
|
7339
7447
|
},
|
|
7340
7448
|
...cmd.maxAncestors !== void 0 ? { maxAncestors: cmd.maxAncestors } : {},
|
|
7341
|
-
...cmd.hint !== void 0 ? { hint: cmd.hint } : {}
|
|
7449
|
+
...cmd.hint !== void 0 ? { hint: cmd.hint } : {},
|
|
7450
|
+
...cmd.only !== void 0 ? { only: cmd.only } : {}
|
|
7342
7451
|
});
|
|
7343
7452
|
break;
|
|
7344
7453
|
}
|
|
@@ -7347,6 +7456,15 @@ function initBuilderMode() {
|
|
|
7347
7456
|
picker = null;
|
|
7348
7457
|
chrome?.setHidden(false);
|
|
7349
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;
|
|
7350
7468
|
case "preview":
|
|
7351
7469
|
if (!cmd.guide) break;
|
|
7352
7470
|
if (manipulator?.isDragging()) pendingPreview = cmd;
|
|
@@ -7431,10 +7549,154 @@ function initBuilderMode() {
|
|
|
7431
7549
|
post({ type: "closed" });
|
|
7432
7550
|
panel?.teardown();
|
|
7433
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;
|
|
7434
7558
|
chrome?.teardown();
|
|
7435
7559
|
chrome = null;
|
|
7436
7560
|
clearBuilderToken();
|
|
7437
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
|
+
};
|
|
7438
7700
|
if (ctx.panel) {
|
|
7439
7701
|
chrome = injectBuilderChrome({
|
|
7440
7702
|
appLabel: window.location.hostname,
|