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
package/dist/index.d.cts
CHANGED
|
@@ -26,6 +26,11 @@ interface VeoAutocaptureConfig {
|
|
|
26
26
|
captureElementMetadata?: boolean;
|
|
27
27
|
/** Niveles de ancestros a capturar. Default: 5. Max: 10. */
|
|
28
28
|
captureAncestors?: number;
|
|
29
|
+
/**
|
|
30
|
+
* Calidad de los clics: emite `$dead_click` (clic sin reacción), `$rage_click`
|
|
31
|
+
* (ráfaga de clics) y `$click_error` (clic seguido de un error). Default: true.
|
|
32
|
+
*/
|
|
33
|
+
captureClickQuality?: boolean;
|
|
29
34
|
}
|
|
30
35
|
/**
|
|
31
36
|
* Configuración del cliente Veo.
|
package/dist/index.d.ts
CHANGED
|
@@ -26,6 +26,11 @@ interface VeoAutocaptureConfig {
|
|
|
26
26
|
captureElementMetadata?: boolean;
|
|
27
27
|
/** Niveles de ancestros a capturar. Default: 5. Max: 10. */
|
|
28
28
|
captureAncestors?: number;
|
|
29
|
+
/**
|
|
30
|
+
* Calidad de los clics: emite `$dead_click` (clic sin reacción), `$rage_click`
|
|
31
|
+
* (ráfaga de clics) y `$click_error` (clic seguido de un error). Default: true.
|
|
32
|
+
*/
|
|
33
|
+
captureClickQuality?: boolean;
|
|
29
34
|
}
|
|
30
35
|
/**
|
|
31
36
|
* Configuración del cliente Veo.
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { definePlugin, guidesPlugin, runPreviewMode } from './chunk-
|
|
2
|
-
export { definePlugin, guidesPlugin } from './chunk-
|
|
3
|
-
import { hasWindow, hasDocument, uuidv7, DEFAULT_AUTOCAPTURE_CONFIG, MAX_ANCESTORS, hasLocalStorage, hasNavigatorSendBeacon, isBuilderMode,
|
|
4
|
-
export { closeGuidePreview, previewGuide } from './chunk-
|
|
1
|
+
import { definePlugin, guidesPlugin, runPreviewMode } from './chunk-3JEAPZ6A.mjs';
|
|
2
|
+
export { definePlugin, guidesPlugin } from './chunk-3JEAPZ6A.mjs';
|
|
3
|
+
import { hasWindow, hasDocument, uuidv7, DEFAULT_AUTOCAPTURE_CONFIG, MAX_ANCESTORS, hasLocalStorage, hasNavigatorSendBeacon, isBuilderMode, buildSelectorPath, ALWAYS_BLOCK_SELECTORS, resolveBuilderToken, filterHumanClasses, PRIORITY_ATTRIBUTES, SENSITIVE_ATTRIBUTES, getPreviewToken, previewGuide, closeGuidePreview } from './chunk-SZCIXA5X.mjs';
|
|
4
|
+
export { closeGuidePreview, previewGuide } from './chunk-SZCIXA5X.mjs';
|
|
5
5
|
import './chunk-PTG3BTJE.mjs';
|
|
6
6
|
|
|
7
7
|
// src/contract/v1.ts
|
|
@@ -62,6 +62,294 @@ function deriveBuilderUrl() {
|
|
|
62
62
|
return null;
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
// src/plugins/autocapture/click-quality.ts
|
|
66
|
+
var NO_DEAD_TAGS = /* @__PURE__ */ new Set(["input", "textarea", "select", "option", "label"]);
|
|
67
|
+
var MAX_ERROR_MESSAGE = 200;
|
|
68
|
+
var HISTORY_MS = 3e3;
|
|
69
|
+
var DEFAULTS = {
|
|
70
|
+
reactionWindowMs: 1e3,
|
|
71
|
+
errorWindowMs: 2e3,
|
|
72
|
+
rageClicks: 3,
|
|
73
|
+
rageWindowMs: 1e3,
|
|
74
|
+
rageClicksSlow: 5,
|
|
75
|
+
rageWindowSlowMs: 3e3,
|
|
76
|
+
maxPerElement: 50
|
|
77
|
+
};
|
|
78
|
+
function describeError(value) {
|
|
79
|
+
let text;
|
|
80
|
+
if (value instanceof Error) text = `${value.name}: ${value.message}`;
|
|
81
|
+
else if (typeof value === "string") text = value;
|
|
82
|
+
else {
|
|
83
|
+
try {
|
|
84
|
+
text = JSON.stringify(value) ?? String(value);
|
|
85
|
+
} catch {
|
|
86
|
+
text = String(value);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return text.slice(0, MAX_ERROR_MESSAGE);
|
|
90
|
+
}
|
|
91
|
+
var ClickQualityTracker = class {
|
|
92
|
+
constructor(emit, options = {}) {
|
|
93
|
+
this.emit = emit;
|
|
94
|
+
this.installed = false;
|
|
95
|
+
this.cleanups = [];
|
|
96
|
+
// Sensores globales (contadores: cada observación compara su foto inicial).
|
|
97
|
+
this.netCount = 0;
|
|
98
|
+
this.navCount = 0;
|
|
99
|
+
this.focusCount = 0;
|
|
100
|
+
this.unloading = false;
|
|
101
|
+
this.errors = [];
|
|
102
|
+
this.history = /* @__PURE__ */ new Map();
|
|
103
|
+
this.bursts = /* @__PURE__ */ new Map();
|
|
104
|
+
this.emitted = /* @__PURE__ */ new Map();
|
|
105
|
+
this.opts = { ...DEFAULTS, ...options };
|
|
106
|
+
}
|
|
107
|
+
install() {
|
|
108
|
+
if (this.installed || !hasWindow()) return;
|
|
109
|
+
this.installed = true;
|
|
110
|
+
const on = (type, handler, capture = true) => {
|
|
111
|
+
window.addEventListener(type, handler, capture);
|
|
112
|
+
this.cleanups.push(() => window.removeEventListener(type, handler, capture));
|
|
113
|
+
};
|
|
114
|
+
on("error", (e) => {
|
|
115
|
+
const err = e;
|
|
116
|
+
this.pushError("error", err.error ?? err.message ?? "error");
|
|
117
|
+
});
|
|
118
|
+
on("unhandledrejection", (e) => {
|
|
119
|
+
this.pushError("unhandledrejection", e.reason ?? "rejection");
|
|
120
|
+
});
|
|
121
|
+
on("popstate", () => this.navCount++);
|
|
122
|
+
on("hashchange", () => this.navCount++);
|
|
123
|
+
on("focusin", () => this.focusCount++);
|
|
124
|
+
on("pagehide", () => {
|
|
125
|
+
this.unloading = true;
|
|
126
|
+
});
|
|
127
|
+
on("beforeunload", () => {
|
|
128
|
+
this.unloading = true;
|
|
129
|
+
});
|
|
130
|
+
this.patchHistory();
|
|
131
|
+
this.patchConsole();
|
|
132
|
+
this.patchFetch();
|
|
133
|
+
this.patchXhr();
|
|
134
|
+
}
|
|
135
|
+
destroy() {
|
|
136
|
+
for (const c of this.cleanups) c();
|
|
137
|
+
this.cleanups = [];
|
|
138
|
+
for (const b of this.bursts.values()) window.clearTimeout(b.timer);
|
|
139
|
+
this.bursts.clear();
|
|
140
|
+
this.history.clear();
|
|
141
|
+
this.installed = false;
|
|
142
|
+
}
|
|
143
|
+
/** Llamar por cada clic real sobre un elemento interactivo, ANTES del throttle. */
|
|
144
|
+
onClick(element, event) {
|
|
145
|
+
if (!this.installed) return;
|
|
146
|
+
const now = Date.now();
|
|
147
|
+
const obs = { at: now, reacted: false };
|
|
148
|
+
this.remember(element, obs);
|
|
149
|
+
this.observeReaction(element, obs, event);
|
|
150
|
+
this.observeErrors(element, now);
|
|
151
|
+
this.trackRage(element, now);
|
|
152
|
+
}
|
|
153
|
+
// ---------------------------------------------------------------- dead ----
|
|
154
|
+
observeReaction(element, obs, event) {
|
|
155
|
+
const netAtClick = this.netCount;
|
|
156
|
+
const navAtClick = this.navCount;
|
|
157
|
+
const focusAtClick = this.focusCount;
|
|
158
|
+
const hrefAtClick = window.location.href;
|
|
159
|
+
const skipDead = this.isDeadExempt(element, event);
|
|
160
|
+
let observer = null;
|
|
161
|
+
if (typeof MutationObserver !== "undefined") {
|
|
162
|
+
observer = new MutationObserver(() => {
|
|
163
|
+
obs.reacted = true;
|
|
164
|
+
observer?.disconnect();
|
|
165
|
+
observer = null;
|
|
166
|
+
});
|
|
167
|
+
observer.observe(document.documentElement, {
|
|
168
|
+
childList: true,
|
|
169
|
+
attributes: true,
|
|
170
|
+
characterData: true,
|
|
171
|
+
subtree: true
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
window.setTimeout(() => {
|
|
175
|
+
observer?.disconnect();
|
|
176
|
+
const reacted = obs.reacted || this.unloading || this.netCount !== netAtClick || this.navCount !== navAtClick || this.focusCount !== focusAtClick || window.location.href !== hrefAtClick;
|
|
177
|
+
obs.reacted = reacted;
|
|
178
|
+
if (!reacted && !skipDead) this.report("$dead_click", element, {});
|
|
179
|
+
}, this.opts.reactionWindowMs);
|
|
180
|
+
}
|
|
181
|
+
isDeadExempt(element, event) {
|
|
182
|
+
if (event && (event.ctrlKey || event.metaKey || event.shiftKey || event.altKey)) return true;
|
|
183
|
+
if (event && typeof event.button === "number" && event.button !== 0) return true;
|
|
184
|
+
const tag = element.tagName.toLowerCase();
|
|
185
|
+
if (NO_DEAD_TAGS.has(tag)) return true;
|
|
186
|
+
if (element.closest('[contenteditable=""],[contenteditable="true"]')) return true;
|
|
187
|
+
const anchor = element.closest("a");
|
|
188
|
+
if (anchor) {
|
|
189
|
+
if (anchor.target === "_blank" || anchor.hasAttribute("download")) return true;
|
|
190
|
+
const href = anchor.getAttribute("href") ?? "";
|
|
191
|
+
if (/^(mailto|tel|sms):/i.test(href)) return true;
|
|
192
|
+
}
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
// --------------------------------------------------------------- error ----
|
|
196
|
+
observeErrors(element, clickedAt) {
|
|
197
|
+
const deadline = clickedAt + this.opts.errorWindowMs;
|
|
198
|
+
const check = () => {
|
|
199
|
+
const err = this.errors.find((e) => e.at >= clickedAt && e.at <= deadline);
|
|
200
|
+
if (err) {
|
|
201
|
+
this.report("$click_error", element, {
|
|
202
|
+
$error_source: err.source,
|
|
203
|
+
$error_message: err.message
|
|
204
|
+
});
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
if (Date.now() < deadline) window.setTimeout(check, 250);
|
|
208
|
+
};
|
|
209
|
+
window.setTimeout(check, 250);
|
|
210
|
+
}
|
|
211
|
+
pushError(source, value) {
|
|
212
|
+
const message = describeError(value);
|
|
213
|
+
if (message.startsWith("[veo]")) return;
|
|
214
|
+
this.errors.push({ at: Date.now(), source, message });
|
|
215
|
+
const cutoff = Date.now() - this.opts.errorWindowMs - 1e3;
|
|
216
|
+
while (this.errors.length > 0 && this.errors[0].at < cutoff) {
|
|
217
|
+
this.errors.shift();
|
|
218
|
+
}
|
|
219
|
+
if (this.errors.length > 50) this.errors.splice(0, this.errors.length - 50);
|
|
220
|
+
}
|
|
221
|
+
// ---------------------------------------------------------------- rage ----
|
|
222
|
+
remember(element, obs) {
|
|
223
|
+
const list = this.history.get(element) ?? [];
|
|
224
|
+
const cutoff = obs.at - HISTORY_MS;
|
|
225
|
+
const kept = list.filter((o) => o.at >= cutoff);
|
|
226
|
+
kept.push(obs);
|
|
227
|
+
this.history.set(element, kept);
|
|
228
|
+
if (this.history.size > 100) {
|
|
229
|
+
for (const [el, obsList] of this.history) {
|
|
230
|
+
if (obsList.every((o) => o.at < cutoff)) this.history.delete(el);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
trackRage(element, now) {
|
|
235
|
+
const list = this.history.get(element) ?? [];
|
|
236
|
+
const fast = list.filter((o) => o.at >= now - this.opts.rageWindowMs).length;
|
|
237
|
+
const slow = list.filter((o) => o.at >= now - this.opts.rageWindowSlowMs).length;
|
|
238
|
+
const existing = this.bursts.get(element);
|
|
239
|
+
const isRage = fast >= this.opts.rageClicks || slow >= this.opts.rageClicksSlow;
|
|
240
|
+
if (!existing && !isRage) return;
|
|
241
|
+
const burst = existing ?? {
|
|
242
|
+
startedAt: (list.find((o) => o.at >= now - this.opts.rageWindowSlowMs) ?? { at: now }).at,
|
|
243
|
+
count: 0,
|
|
244
|
+
timer: 0
|
|
245
|
+
};
|
|
246
|
+
burst.count = list.filter((o) => o.at >= burst.startedAt).length;
|
|
247
|
+
window.clearTimeout(burst.timer);
|
|
248
|
+
burst.timer = window.setTimeout(() => {
|
|
249
|
+
this.bursts.delete(element);
|
|
250
|
+
const clicks = (this.history.get(element) ?? []).filter((o) => o.at >= burst.startedAt);
|
|
251
|
+
this.report("$rage_click", element, {
|
|
252
|
+
$click_count: Math.max(clicks.length, burst.count),
|
|
253
|
+
$reacted_clicks: clicks.filter((o) => o.reacted).length
|
|
254
|
+
});
|
|
255
|
+
}, this.opts.reactionWindowMs + 50);
|
|
256
|
+
this.bursts.set(element, burst);
|
|
257
|
+
}
|
|
258
|
+
// ---------------------------------------------------------------- emit ----
|
|
259
|
+
report(kind, element, extra) {
|
|
260
|
+
const key = buildSelectorPath(element, 5);
|
|
261
|
+
const counts = this.emitted.get(key) ?? { $dead_click: 0, $rage_click: 0, $click_error: 0 };
|
|
262
|
+
if (counts[kind] >= this.opts.maxPerElement) return;
|
|
263
|
+
counts[kind]++;
|
|
264
|
+
this.emitted.set(key, counts);
|
|
265
|
+
try {
|
|
266
|
+
this.emit(kind, element, extra);
|
|
267
|
+
} catch {
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
// ------------------------------------------------------------- patches ----
|
|
271
|
+
patchHistory() {
|
|
272
|
+
const h = window.history;
|
|
273
|
+
if (!h) return;
|
|
274
|
+
const origPush = h.pushState;
|
|
275
|
+
const origReplace = h.replaceState;
|
|
276
|
+
const self = this;
|
|
277
|
+
h.pushState = function(...args) {
|
|
278
|
+
self.navCount++;
|
|
279
|
+
return origPush.apply(this, args);
|
|
280
|
+
};
|
|
281
|
+
h.replaceState = function(...args) {
|
|
282
|
+
self.navCount++;
|
|
283
|
+
return origReplace.apply(this, args);
|
|
284
|
+
};
|
|
285
|
+
this.cleanups.push(() => {
|
|
286
|
+
h.pushState = origPush;
|
|
287
|
+
h.replaceState = origReplace;
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
patchConsole() {
|
|
291
|
+
const orig = console.error;
|
|
292
|
+
const self = this;
|
|
293
|
+
console.error = function(...args) {
|
|
294
|
+
try {
|
|
295
|
+
self.pushError("console", args.map(describeError).join(" "));
|
|
296
|
+
} catch {
|
|
297
|
+
}
|
|
298
|
+
return orig.apply(this, args);
|
|
299
|
+
};
|
|
300
|
+
this.cleanups.push(() => {
|
|
301
|
+
console.error = orig;
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* `fetch`: cuenta la petición (reacción) y registra respuestas ≥500 o
|
|
306
|
+
* rechazos como error. Se observa con `.then(ok, err)` sobre la promesa
|
|
307
|
+
* original: eso marca el rechazo como manejado para el navegador, así que
|
|
308
|
+
* un fetch fallido sin catch de la app no dispara `unhandledrejection` —
|
|
309
|
+
* lo registramos nosotros como error de red.
|
|
310
|
+
*/
|
|
311
|
+
patchFetch() {
|
|
312
|
+
if (typeof window.fetch !== "function") return;
|
|
313
|
+
const orig = window.fetch;
|
|
314
|
+
const self = this;
|
|
315
|
+
window.fetch = function(...args) {
|
|
316
|
+
self.netCount++;
|
|
317
|
+
const p = orig.apply(this, args);
|
|
318
|
+
if (p && typeof p.then === "function") {
|
|
319
|
+
p.then(
|
|
320
|
+
(res) => {
|
|
321
|
+
if (res && res.status >= 500) self.pushError("fetch", `${res.status} ${res.url}`);
|
|
322
|
+
},
|
|
323
|
+
(err) => self.pushError("fetch", err)
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
return p;
|
|
327
|
+
};
|
|
328
|
+
this.cleanups.push(() => {
|
|
329
|
+
window.fetch = orig;
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
patchXhr() {
|
|
333
|
+
const proto = typeof XMLHttpRequest !== "undefined" ? XMLHttpRequest.prototype : null;
|
|
334
|
+
if (!proto) return;
|
|
335
|
+
const origSend = proto.send;
|
|
336
|
+
const self = this;
|
|
337
|
+
proto.send = function(...args) {
|
|
338
|
+
self.netCount++;
|
|
339
|
+
try {
|
|
340
|
+
this.addEventListener("loadend", () => {
|
|
341
|
+
if (this.status >= 500) self.pushError("xhr", `${this.status} ${this.responseURL}`);
|
|
342
|
+
});
|
|
343
|
+
} catch {
|
|
344
|
+
}
|
|
345
|
+
return origSend.apply(this, args);
|
|
346
|
+
};
|
|
347
|
+
this.cleanups.push(() => {
|
|
348
|
+
proto.send = origSend;
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
|
|
65
353
|
// src/plugins/autocapture/pii-guard.ts
|
|
66
354
|
function isElementBlocked(element, extraBlockSelectors = []) {
|
|
67
355
|
const allBlockers = [...ALWAYS_BLOCK_SELECTORS, ...extraBlockSelectors];
|
|
@@ -165,6 +453,7 @@ var DomListener = class {
|
|
|
165
453
|
constructor(client, config) {
|
|
166
454
|
this.client = client;
|
|
167
455
|
this.cleanups = [];
|
|
456
|
+
this.quality = null;
|
|
168
457
|
const d = DEFAULT_AUTOCAPTURE_CONFIG;
|
|
169
458
|
this.config = {
|
|
170
459
|
enabled: config.enabled ?? d.enabled,
|
|
@@ -177,12 +466,20 @@ var DomListener = class {
|
|
|
177
466
|
throttleMs: config.throttleMs ?? d.throttleMs,
|
|
178
467
|
maxTextLength: config.maxTextLength ?? d.maxTextLength,
|
|
179
468
|
captureElementMetadata: config.captureElementMetadata ?? d.captureElementMetadata,
|
|
180
|
-
captureAncestors: Math.min(config.captureAncestors ?? d.captureAncestors, MAX_ANCESTORS)
|
|
469
|
+
captureAncestors: Math.min(config.captureAncestors ?? d.captureAncestors, MAX_ANCESTORS),
|
|
470
|
+
captureClickQuality: config.captureClickQuality ?? d.captureClickQuality
|
|
181
471
|
};
|
|
182
472
|
this.throttle = new ElementThrottle(this.config.throttleMs);
|
|
183
473
|
}
|
|
184
474
|
install() {
|
|
185
475
|
if (!hasDocument() || !this.config.enabled) return;
|
|
476
|
+
if (this.config.captureClicks && this.config.captureClickQuality) {
|
|
477
|
+
this.quality = new ClickQualityTracker((kind, element, extra) => {
|
|
478
|
+
const payload = buildAutocapturePayload("click", element, this.config);
|
|
479
|
+
this.client.track(kind, { ...payload, ...extra });
|
|
480
|
+
});
|
|
481
|
+
this.quality.install();
|
|
482
|
+
}
|
|
186
483
|
if (this.config.captureClicks) this.attach("click", (e) => this.handleClick(e));
|
|
187
484
|
if (this.config.captureSubmits) this.attach("submit", (e) => this.handleSubmit(e), true);
|
|
188
485
|
if (this.config.captureChanges) this.attach("change", (e) => this.handleChange(e), true);
|
|
@@ -190,6 +487,8 @@ var DomListener = class {
|
|
|
190
487
|
destroy() {
|
|
191
488
|
for (const cleanup of this.cleanups) cleanup();
|
|
192
489
|
this.cleanups = [];
|
|
490
|
+
this.quality?.destroy();
|
|
491
|
+
this.quality = null;
|
|
193
492
|
}
|
|
194
493
|
attach(eventName, handler, useCapture = false) {
|
|
195
494
|
const listener = (e) => {
|
|
@@ -208,6 +507,7 @@ var DomListener = class {
|
|
|
208
507
|
const meaningful = this.findMeaningfulAncestor(target);
|
|
209
508
|
if (!meaningful) return;
|
|
210
509
|
if (isElementBlocked(meaningful, this.config.blockSelectors)) return;
|
|
510
|
+
this.quality?.onClick(meaningful, event);
|
|
211
511
|
if (!this.throttle.shouldFire(meaningful)) return;
|
|
212
512
|
this.emit("click", meaningful);
|
|
213
513
|
}
|
|
@@ -966,7 +1266,7 @@ function init(config) {
|
|
|
966
1266
|
// Fallback de carga del builder para bundlers: `import()` dinámico → el bundler
|
|
967
1267
|
// lo code-splitea (solo se descarga en modo builder). Así el consumidor por
|
|
968
1268
|
// bundler NO necesita copiar `veo-builder.js` ni setear `builderUrl`.
|
|
969
|
-
() => import('./builder-
|
|
1269
|
+
() => import('./builder-PPLIAUCM.mjs').then((m) => m.initBuilderMode()),
|
|
970
1270
|
// Detector de tema: también por `import()` dinámico → chunk aparte que el
|
|
971
1271
|
// bundler solo descarga cuando toca detectar (como mucho una vez al día).
|
|
972
1272
|
() => import('./detect-theme-X4K3TLUL.mjs')
|