veo-sdk 0.3.0 → 0.3.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-VPQDAUIL.mjs +5 -0
- package/dist/{builder-UEGKG2UR.mjs.map → builder-VPQDAUIL.mjs.map} +1 -1
- package/dist/builder.cjs +166 -34
- package/dist/builder.cjs.map +1 -1
- package/dist/builder.d.cts +23 -5
- package/dist/builder.d.ts +23 -5
- package/dist/builder.mjs +5 -5
- package/dist/{chunk-CI7NWEH2.mjs → chunk-GHP7ZJCW.mjs} +21 -26
- package/dist/chunk-GHP7ZJCW.mjs.map +1 -0
- package/dist/{chunk-66UQ474G.mjs → chunk-PASI5SAK.mjs} +153 -16
- package/dist/chunk-PASI5SAK.mjs.map +1 -0
- package/dist/chunk-PTG3BTJE.mjs +10 -0
- package/dist/chunk-PTG3BTJE.mjs.map +1 -0
- package/dist/{chunk-G5CKTGEG.mjs → chunk-R4E3LIDB.mjs} +3 -3
- package/dist/{chunk-G5CKTGEG.mjs.map → chunk-R4E3LIDB.mjs.map} +1 -1
- package/dist/index.cjs +178 -36
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +6 -6
- package/dist/next.cjs.map +1 -1
- package/dist/next.mjs +1 -1
- package/dist/veo-builder.js +36 -3
- 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-UEGKG2UR.mjs +0 -5
- package/dist/chunk-66UQ474G.mjs.map +0 -1
- package/dist/chunk-CI7NWEH2.mjs.map +0 -1
- package/dist/chunk-JIU5JLI3.mjs +0 -7
- package/dist/chunk-JIU5JLI3.mjs.map +0 -1
|
@@ -1,9 +1,127 @@
|
|
|
1
|
-
import { hasDocument, hasWindow,
|
|
2
|
-
import { BUILDER_TOKEN_PARAM, BUILDER_ORIGIN_PARAM } from './chunk-
|
|
1
|
+
import { hasDocument, hasWindow, resolveBuilderContext, closeGuidePreview, clearBuilderToken, buildSelectorPath, filterHumanClasses, previewGuide } from './chunk-GHP7ZJCW.mjs';
|
|
2
|
+
import { BUILDER_TOKEN_PARAM, BUILDER_ORIGIN_PARAM } from './chunk-PTG3BTJE.mjs';
|
|
3
3
|
|
|
4
4
|
// src/plugins/builder/bridge-protocol.ts
|
|
5
5
|
var VEO_BUILDER_SOURCE = "veo-builder";
|
|
6
6
|
|
|
7
|
+
// src/plugins/builder/builder-panel.ts
|
|
8
|
+
var DEFAULT_PANEL_PATH = "/guides/design";
|
|
9
|
+
var PANEL_W = 400;
|
|
10
|
+
var PANEL_H = 640;
|
|
11
|
+
var MARGIN = 16;
|
|
12
|
+
function injectBuilderPanel(opts) {
|
|
13
|
+
if (!hasWindow() || !hasDocument()) {
|
|
14
|
+
return { target: () => null, teardown: () => {
|
|
15
|
+
} };
|
|
16
|
+
}
|
|
17
|
+
const host = document.createElement("div");
|
|
18
|
+
host.setAttribute("data-veo-builder-panel", "");
|
|
19
|
+
const shadow = host.attachShadow({ mode: "open" });
|
|
20
|
+
const style = document.createElement("style");
|
|
21
|
+
style.textContent = PANEL_CSS;
|
|
22
|
+
const card = document.createElement("div");
|
|
23
|
+
card.className = "veo-panel";
|
|
24
|
+
let left = Math.max(MARGIN, window.innerWidth - PANEL_W - MARGIN);
|
|
25
|
+
let top = MARGIN;
|
|
26
|
+
card.style.left = `${left}px`;
|
|
27
|
+
card.style.top = `${top}px`;
|
|
28
|
+
const header = document.createElement("div");
|
|
29
|
+
header.className = "veo-panel-header";
|
|
30
|
+
const title = document.createElement("span");
|
|
31
|
+
title.className = "veo-panel-title";
|
|
32
|
+
title.textContent = "Veo \xB7 Editor";
|
|
33
|
+
const close = document.createElement("button");
|
|
34
|
+
close.className = "veo-panel-close";
|
|
35
|
+
close.type = "button";
|
|
36
|
+
close.setAttribute("aria-label", "Cerrar");
|
|
37
|
+
close.textContent = "\u2715";
|
|
38
|
+
close.addEventListener("click", () => opts.onClose());
|
|
39
|
+
header.append(title, close);
|
|
40
|
+
const iframe = document.createElement("iframe");
|
|
41
|
+
iframe.className = "veo-panel-frame";
|
|
42
|
+
iframe.title = "Editor de Veo";
|
|
43
|
+
iframe.src = buildPanelUrl(opts);
|
|
44
|
+
card.append(header, iframe);
|
|
45
|
+
shadow.append(style, card);
|
|
46
|
+
document.body.appendChild(host);
|
|
47
|
+
const onHeaderDown = (e) => {
|
|
48
|
+
if (e.target?.classList.contains("veo-panel-close")) return;
|
|
49
|
+
e.preventDefault();
|
|
50
|
+
const startX = e.clientX;
|
|
51
|
+
const startY = e.clientY;
|
|
52
|
+
const origLeft = left;
|
|
53
|
+
const origTop = top;
|
|
54
|
+
iframe.style.pointerEvents = "none";
|
|
55
|
+
card.classList.add("dragging");
|
|
56
|
+
const onMove = (ev) => {
|
|
57
|
+
const maxLeft = window.innerWidth - card.offsetWidth;
|
|
58
|
+
const maxTop = window.innerHeight - 40;
|
|
59
|
+
left = clamp(origLeft + (ev.clientX - startX), 0, Math.max(0, maxLeft));
|
|
60
|
+
top = clamp(origTop + (ev.clientY - startY), 0, Math.max(0, maxTop));
|
|
61
|
+
card.style.left = `${left}px`;
|
|
62
|
+
card.style.top = `${top}px`;
|
|
63
|
+
};
|
|
64
|
+
const onUp = () => {
|
|
65
|
+
window.removeEventListener("mousemove", onMove);
|
|
66
|
+
window.removeEventListener("mouseup", onUp);
|
|
67
|
+
iframe.style.pointerEvents = "";
|
|
68
|
+
card.classList.remove("dragging");
|
|
69
|
+
};
|
|
70
|
+
window.addEventListener("mousemove", onMove);
|
|
71
|
+
window.addEventListener("mouseup", onUp);
|
|
72
|
+
};
|
|
73
|
+
header.addEventListener("mousedown", onHeaderDown);
|
|
74
|
+
return {
|
|
75
|
+
target: () => iframe.contentWindow,
|
|
76
|
+
teardown: () => host.remove()
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function clamp(v, min, max) {
|
|
80
|
+
return Math.min(Math.max(v, min), max);
|
|
81
|
+
}
|
|
82
|
+
function buildPanelUrl(opts) {
|
|
83
|
+
const path = opts.panelPath ?? DEFAULT_PANEL_PATH;
|
|
84
|
+
const url = new URL(path, opts.dashboardOrigin);
|
|
85
|
+
url.searchParams.set("veoToken", opts.token);
|
|
86
|
+
url.searchParams.set("veoApp", opts.appOrigin);
|
|
87
|
+
if (opts.guide) url.searchParams.set("veoGuide", opts.guide);
|
|
88
|
+
return url.toString();
|
|
89
|
+
}
|
|
90
|
+
var PANEL_CSS = `
|
|
91
|
+
:host { all: initial; }
|
|
92
|
+
.veo-panel {
|
|
93
|
+
position: fixed;
|
|
94
|
+
width: ${PANEL_W}px; height: ${PANEL_H}px;
|
|
95
|
+
min-width: 320px; min-height: 320px;
|
|
96
|
+
max-width: 96vw; max-height: 94vh;
|
|
97
|
+
display: flex; flex-direction: column;
|
|
98
|
+
background: #fff;
|
|
99
|
+
border-radius: 12px;
|
|
100
|
+
box-shadow: 0 12px 40px rgba(0,0,0,0.28);
|
|
101
|
+
overflow: hidden;
|
|
102
|
+
resize: both;
|
|
103
|
+
z-index: 2147483647;
|
|
104
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
105
|
+
}
|
|
106
|
+
.veo-panel.dragging { user-select: none; }
|
|
107
|
+
.veo-panel-header {
|
|
108
|
+
flex: 0 0 auto;
|
|
109
|
+
display: flex; align-items: center; justify-content: space-between;
|
|
110
|
+
padding: 8px 12px;
|
|
111
|
+
background: #0f172a; color: #fff;
|
|
112
|
+
font-size: 13px; font-weight: 600;
|
|
113
|
+
cursor: grab;
|
|
114
|
+
}
|
|
115
|
+
.veo-panel-header:active { cursor: grabbing; }
|
|
116
|
+
.veo-panel-close {
|
|
117
|
+
border: 0; background: transparent; color: #fff;
|
|
118
|
+
font-size: 15px; cursor: pointer; line-height: 1;
|
|
119
|
+
padding: 4px 6px; border-radius: 6px;
|
|
120
|
+
}
|
|
121
|
+
.veo-panel-close:hover { background: rgba(255,255,255,0.15); }
|
|
122
|
+
.veo-panel-frame { flex: 1 1 auto; width: 100%; border: 0; background: #fff; }
|
|
123
|
+
`;
|
|
124
|
+
|
|
7
125
|
// src/plugins/builder/element-picker.ts
|
|
8
126
|
var PICKER_Z = 2147483646;
|
|
9
127
|
var PICKER_HOST_ATTR = "data-veo-picker";
|
|
@@ -202,18 +320,23 @@ function stopElementPicker() {
|
|
|
202
320
|
// src/plugins/builder/builder-mode.ts
|
|
203
321
|
function initBuilderMode() {
|
|
204
322
|
if (!hasWindow() || !hasDocument()) return null;
|
|
205
|
-
const
|
|
206
|
-
if (!
|
|
207
|
-
const
|
|
323
|
+
const ctx = resolveBuilderContext();
|
|
324
|
+
if (!ctx) return null;
|
|
325
|
+
const token = ctx.token;
|
|
326
|
+
const dashboardOrigin = resolveDashboardOrigin(ctx.origin);
|
|
208
327
|
if (!dashboardOrigin) return null;
|
|
209
|
-
const target = resolveTarget();
|
|
210
|
-
if (!target) return null;
|
|
211
328
|
let picker = null;
|
|
329
|
+
let panel = null;
|
|
330
|
+
let staticTarget = null;
|
|
331
|
+
const getTarget = () => panel ? panel.target() : staticTarget;
|
|
212
332
|
const post = (event) => {
|
|
213
|
-
|
|
333
|
+
getTarget()?.postMessage({ source: VEO_BUILDER_SOURCE, token, ...event }, dashboardOrigin);
|
|
214
334
|
};
|
|
215
335
|
const handleCommand = (cmd) => {
|
|
216
336
|
switch (cmd.type) {
|
|
337
|
+
case "panel-ready":
|
|
338
|
+
post({ type: "ready" });
|
|
339
|
+
break;
|
|
217
340
|
case "start-picker":
|
|
218
341
|
picker?.stop();
|
|
219
342
|
picker = startElementPicker({
|
|
@@ -257,13 +380,28 @@ function initBuilderMode() {
|
|
|
257
380
|
picker?.stop();
|
|
258
381
|
picker = null;
|
|
259
382
|
closeGuidePreview();
|
|
260
|
-
clearBuilderToken();
|
|
261
383
|
post({ type: "closed" });
|
|
384
|
+
panel?.teardown();
|
|
385
|
+
panel = null;
|
|
386
|
+
clearBuilderToken();
|
|
262
387
|
};
|
|
388
|
+
if (ctx.panel) {
|
|
389
|
+
panel = injectBuilderPanel({
|
|
390
|
+
dashboardOrigin,
|
|
391
|
+
token,
|
|
392
|
+
appOrigin: window.location.origin,
|
|
393
|
+
guide: ctx.guide,
|
|
394
|
+
panelPath: ctx.panelPath,
|
|
395
|
+
onClose: () => teardown()
|
|
396
|
+
});
|
|
397
|
+
} else {
|
|
398
|
+
staticTarget = resolveTarget();
|
|
399
|
+
if (!staticTarget) return null;
|
|
400
|
+
}
|
|
263
401
|
const activate = () => {
|
|
264
402
|
window.addEventListener("message", onMessage);
|
|
265
403
|
window.addEventListener("pagehide", onPageHide);
|
|
266
|
-
post({ type: "ready" });
|
|
404
|
+
if (!ctx.panel) post({ type: "ready" });
|
|
267
405
|
};
|
|
268
406
|
const cfg = window.__veoBuilder;
|
|
269
407
|
if (cfg?.apiKey && cfg?.apiUrl) {
|
|
@@ -296,11 +434,10 @@ function resolveTarget() {
|
|
|
296
434
|
if (window.parent && window.parent !== window) return window.parent;
|
|
297
435
|
return null;
|
|
298
436
|
}
|
|
299
|
-
function resolveDashboardOrigin() {
|
|
300
|
-
|
|
301
|
-
if (stored) {
|
|
437
|
+
function resolveDashboardOrigin(originHint) {
|
|
438
|
+
if (originHint) {
|
|
302
439
|
try {
|
|
303
|
-
return new URL(
|
|
440
|
+
return new URL(originHint).origin;
|
|
304
441
|
} catch {
|
|
305
442
|
return null;
|
|
306
443
|
}
|
|
@@ -435,5 +572,5 @@ function noopSession() {
|
|
|
435
572
|
}
|
|
436
573
|
|
|
437
574
|
export { createBuilderSession, initBuilderMode, startElementPicker, stopElementPicker };
|
|
438
|
-
//# sourceMappingURL=chunk-
|
|
439
|
-
//# sourceMappingURL=chunk-
|
|
575
|
+
//# sourceMappingURL=chunk-PASI5SAK.mjs.map
|
|
576
|
+
//# sourceMappingURL=chunk-PASI5SAK.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/plugins/builder/bridge-protocol.ts","../src/plugins/builder/builder-panel.ts","../src/plugins/builder/element-picker.ts","../src/plugins/builder/builder-mode.ts","../src/plugins/builder/builder-session.ts"],"names":[],"mappings":"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","file":"chunk-PASI5SAK.mjs","sourcesContent":["/**\n * Contrato de mensajes del puente builder (app del cliente ↔ dashboard).\n * Ambos lados validan `event.origin` y que `token` coincida antes de actuar.\n *\n * Flujo:\n * 1. El dashboard abre la app con `?veoBuilder=<token>&veoBuilderOrigin=<origen>`.\n * 2. La app (veo-builder.js) postea `ready` a la ventana que la abrió.\n * 3. El dashboard manda comandos (`start-picker`, `preview`, …).\n * 4. La app responde con eventos (`picked`, `pick-cancelled`, …).\n */\nimport type { PreviewGuideInput } from '../guides/guide-preview';\nimport type { PickedElement } from './element-picker';\n\nexport const VEO_BUILDER_SOURCE = 'veo-builder';\n// Los nombres de los query params viven en el core (`builder-token.ts`), única\n// fuente de verdad compartida con el loader y el gate del runtime de guías.\nexport { BUILDER_ORIGIN_PARAM, BUILDER_TOKEN_PARAM } from '../../core/builder-token';\n\n/** Eventos que la app del cliente envía al dashboard. */\nexport type BuilderEvent =\n | { type: 'ready' }\n | { type: 'picked'; payload: PickedElement }\n | { type: 'pick-cancelled' }\n | { type: 'closed' };\n\n/** Comandos que el dashboard/panel envía a la app del cliente. */\nexport type BuilderCommand =\n | { type: 'start-picker'; maxAncestors?: number; hint?: string }\n | { type: 'stop-picker' }\n | { type: 'preview'; guide: PreviewGuideInput }\n | { type: 'close-preview' }\n | { type: 'teardown' }\n // Modo panel inyectado: el panel avisa que cargó y está listo para recibir\n // eventos; la app responde con `ready`. Resuelve la carrera de que el iframe\n // del panel todavía no tenga su listener cuando la app postea `ready`.\n | { type: 'panel-ready' };\n\n/** Sobre común: todo mensaje del puente lleva `source` + `token`. */\nexport interface BuilderEnvelope {\n source: typeof VEO_BUILDER_SOURCE;\n token: string;\n}\n\nexport type BuilderEventMessage = BuilderEnvelope & BuilderEvent;\nexport type BuilderCommandMessage = BuilderEnvelope & BuilderCommand;\n","/**\n * Modo \"panel inyectado\" (editor en la pestaña de la app).\n *\n * Al revés del modo iframe/popup: acá **la app es la pestaña top-level** (donde\n * el usuario ya se logueó normal) y el editor de Veo se inyecta ENCIMA, como una\n * tarjeta flotante **arrastrable** (un iframe apuntando al dashboard). Así no hace\n * falta ninguna adaptación de la app (ni demo-user, ni framing, ni cookies): el\n * login real funciona porque nada está embebido en un iframe cross-origin.\n *\n * El panel corre en el origen del dashboard (tiene la sesión de Veo para guardar\n * guías) y habla con la app (su `window.parent`) por el mismo puente postMessage.\n * Este módulo inyecta el iframe, lo hace movible/redimensionable, y expone su\n * `contentWindow` como target.\n */\nimport { hasDocument, hasWindow } from '../../utils/safe-env';\n\n/** Path por defecto del panel del editor en el dashboard. */\nconst DEFAULT_PANEL_PATH = '/guides/design';\nconst PANEL_W = 400;\nconst PANEL_H = 640;\nconst MARGIN = 16;\n\nexport interface BuilderPanelOptions {\n dashboardOrigin: string;\n token: string;\n appOrigin: string;\n guide: string | null;\n panelPath: string | null;\n onClose: () => void;\n}\n\nexport interface BuilderPanelHandle {\n /** Ventana destino de los mensajes: el `contentWindow` del iframe del panel. */\n target(): Window | null;\n /** Quita el panel del DOM. */\n teardown(): void;\n}\n\n/** Inyecta el panel del editor como tarjeta flotante arrastrable y devuelve un handle. */\nexport function injectBuilderPanel(opts: BuilderPanelOptions): BuilderPanelHandle {\n if (!hasWindow() || !hasDocument()) {\n return { target: () => null, teardown: () => {} };\n }\n\n const host = document.createElement('div');\n host.setAttribute('data-veo-builder-panel', '');\n const shadow = host.attachShadow({ mode: 'open' });\n\n const style = document.createElement('style');\n style.textContent = PANEL_CSS;\n\n const card = document.createElement('div');\n card.className = 'veo-panel';\n // Posición inicial: arriba a la derecha, con margen (flotante, no pegado).\n let left = Math.max(MARGIN, window.innerWidth - PANEL_W - MARGIN);\n let top = MARGIN;\n card.style.left = `${left}px`;\n card.style.top = `${top}px`;\n\n const header = document.createElement('div');\n header.className = 'veo-panel-header';\n const title = document.createElement('span');\n title.className = 'veo-panel-title';\n title.textContent = 'Veo · Editor';\n const close = document.createElement('button');\n close.className = 'veo-panel-close';\n close.type = 'button';\n close.setAttribute('aria-label', 'Cerrar');\n close.textContent = '✕';\n close.addEventListener('click', () => opts.onClose());\n header.append(title, close);\n\n const iframe = document.createElement('iframe');\n iframe.className = 'veo-panel-frame';\n iframe.title = 'Editor de Veo';\n iframe.src = buildPanelUrl(opts);\n\n card.append(header, iframe);\n shadow.append(style, card);\n document.body.appendChild(host);\n\n // ── Arrastre por el header ──────────────────────────────────────────────\n // Durante el drag apagamos los pointer-events del iframe: si no, apenas el\n // cursor entra al iframe (cross-origin) los mousemove se los traga y el drag\n // se corta.\n const onHeaderDown = (e: MouseEvent): void => {\n if ((e.target as HTMLElement)?.classList.contains('veo-panel-close')) return;\n e.preventDefault();\n const startX = e.clientX;\n const startY = e.clientY;\n const origLeft = left;\n const origTop = top;\n iframe.style.pointerEvents = 'none';\n card.classList.add('dragging');\n\n const onMove = (ev: MouseEvent): void => {\n const maxLeft = window.innerWidth - card.offsetWidth;\n const maxTop = window.innerHeight - 40;\n left = clamp(origLeft + (ev.clientX - startX), 0, Math.max(0, maxLeft));\n top = clamp(origTop + (ev.clientY - startY), 0, Math.max(0, maxTop));\n card.style.left = `${left}px`;\n card.style.top = `${top}px`;\n };\n const onUp = (): void => {\n window.removeEventListener('mousemove', onMove);\n window.removeEventListener('mouseup', onUp);\n iframe.style.pointerEvents = '';\n card.classList.remove('dragging');\n };\n window.addEventListener('mousemove', onMove);\n window.addEventListener('mouseup', onUp);\n };\n header.addEventListener('mousedown', onHeaderDown);\n\n return {\n target: () => iframe.contentWindow,\n teardown: () => host.remove(),\n };\n}\n\nfunction clamp(v: number, min: number, max: number): number {\n return Math.min(Math.max(v, min), max);\n}\n\nfunction buildPanelUrl(opts: BuilderPanelOptions): string {\n const path = opts.panelPath ?? DEFAULT_PANEL_PATH;\n const url = new URL(path, opts.dashboardOrigin);\n url.searchParams.set('veoToken', opts.token);\n url.searchParams.set('veoApp', opts.appOrigin);\n if (opts.guide) url.searchParams.set('veoGuide', opts.guide);\n return url.toString();\n}\n\nconst PANEL_CSS = `\n:host { all: initial; }\n.veo-panel {\n position: fixed;\n width: ${PANEL_W}px; height: ${PANEL_H}px;\n min-width: 320px; min-height: 320px;\n max-width: 96vw; max-height: 94vh;\n display: flex; flex-direction: column;\n background: #fff;\n border-radius: 12px;\n box-shadow: 0 12px 40px rgba(0,0,0,0.28);\n overflow: hidden;\n resize: both;\n z-index: 2147483647;\n font-family: system-ui, -apple-system, sans-serif;\n}\n.veo-panel.dragging { user-select: none; }\n.veo-panel-header {\n flex: 0 0 auto;\n display: flex; align-items: center; justify-content: space-between;\n padding: 8px 12px;\n background: #0f172a; color: #fff;\n font-size: 13px; font-weight: 600;\n cursor: grab;\n}\n.veo-panel-header:active { cursor: grabbing; }\n.veo-panel-close {\n border: 0; background: transparent; color: #fff;\n font-size: 15px; cursor: pointer; line-height: 1;\n padding: 4px 6px; border-radius: 6px;\n}\n.veo-panel-close:hover { background: rgba(255,255,255,0.15); }\n.veo-panel-frame { flex: 1 1 auto; width: 100%; border: 0; background: #fff; }\n`;\n","/**\n * Element picker — el \"inspeccionar\" del navegador, pero del SDK. Corre\n * DENTRO de la app del cliente (no en el dashboard: son orígenes distintos\n * y el dashboard no puede leer el DOM de la app). Resalta el elemento bajo\n * el cursor, muestra su selector + dimensiones, y al hacer click captura un\n * selector CSS estable reutilizando `buildSelectorPath` del autocapture.\n *\n * Es la base del builder no-code: el dashboard abre la app del cliente en\n * modo builder, el usuario \"pincha\" un elemento y el selector resultante se\n * usa como ancla de un tooltip/walkthrough. El puente con el dashboard\n * (postMessage) es la fase siguiente; aquí exponemos el primitivo\n * `startElementPicker(onPick)`.\n *\n * No usa `innerHTML` — todo por `textContent`/DOM, igual que los renderers.\n */\n\nimport { hasDocument } from '../../utils/safe-env';\nimport { buildSelectorPath, filterHumanClasses } from '../autocapture/selector-builder';\n\n/** z-index por encima de las guías (2147483640) para tapar también una preview. */\nconst PICKER_Z = 2147483646;\nconst PICKER_HOST_ATTR = 'data-veo-picker';\nconst DEFAULT_MAX_ANCESTORS = 5;\n\n/** Datos del elemento elegido que se entregan al caller. */\nexport interface PickedElement {\n /** Selector CSS estable con ancestros (lo que se guarda como ancla). */\n selector: string;\n /** Selector corto solo del elemento (tag + id/atributo/clases). */\n shortSelector: string;\n tag: string;\n id: string | null;\n classes: string[];\n text: string;\n rect: { x: number; y: number; width: number; height: number };\n}\n\nexport interface ElementPickerOptions {\n /** Llamado al hacer click en un elemento. El picker se cierra tras esto. */\n onPick: (picked: PickedElement) => void;\n /** Llamado al cancelar (Esc). El picker se cierra. */\n onCancel?: () => void;\n /** Niveles de ancestros del selector. Default 5 (igual que autocapture). */\n maxAncestors?: number;\n /** Texto del banner superior. Default en español. */\n hint?: string;\n}\n\nexport interface ElementPickerHandle {\n /** Cierra el picker sin elegir nada. Idempotente. */\n stop(): void;\n}\n\nconst PICKER_STYLES = `\n:host { all: initial; }\n.veo-pick-box {\n position: fixed;\n z-index: ${PICKER_Z};\n pointer-events: none;\n box-sizing: border-box;\n background: rgba(99, 102, 241, 0.22);\n border: 1px dashed rgba(99, 102, 241, 0.95);\n border-radius: 2px;\n transition: top 60ms ease-out, left 60ms ease-out, width 60ms ease-out, height 60ms ease-out;\n}\n.veo-pick-label {\n position: fixed;\n z-index: ${PICKER_Z};\n pointer-events: none;\n max-width: 360px;\n background: #1e1b4b;\n color: #e0e7ff;\n font: 12px/1.45 ui-monospace, SFMono-Regular, Menlo, monospace;\n padding: 6px 9px;\n border-radius: 6px;\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.35);\n}\n.veo-pick-label .veo-pick-sel { color: #c7d2fe; word-break: break-all; }\n.veo-pick-label .veo-pick-dim { color: #a5b4fc; margin-top: 3px; }\n.veo-pick-hint {\n position: fixed;\n top: 12px;\n left: 50%;\n transform: translateX(-50%);\n z-index: ${PICKER_Z};\n pointer-events: none;\n background: #4338ca;\n color: #fff;\n font: 13px/1 -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n padding: 8px 14px;\n border-radius: 999px;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25);\n}\n`;\n\n/**\n * Controla un picker activo. Singleton a nivel de módulo: empezar otro\n * cierra el anterior. Los listeners van en fase de captura para poder\n * cancelar el click ANTES de que la app del cliente reaccione.\n */\nclass ElementPicker {\n private host: HTMLElement | null = null;\n private box: HTMLElement | null = null;\n private label: HTMLElement | null = null;\n private current: Element | null = null;\n private maxAncestors = DEFAULT_MAX_ANCESTORS;\n private onPick: ((p: PickedElement) => void) | null = null;\n private onCancel: (() => void) | null = null;\n\n start(options: ElementPickerOptions): void {\n this.stop(); // solo un picker a la vez\n\n this.maxAncestors = options.maxAncestors ?? DEFAULT_MAX_ANCESTORS;\n this.onPick = options.onPick;\n this.onCancel = options.onCancel ?? null;\n\n const host = document.createElement('div');\n host.setAttribute(PICKER_HOST_ATTR, '');\n const shadow = host.attachShadow({ mode: 'open' });\n\n const style = document.createElement('style');\n style.textContent = PICKER_STYLES;\n\n this.box = document.createElement('div');\n this.box.className = 'veo-pick-box';\n this.box.style.display = 'none';\n\n this.label = document.createElement('div');\n this.label.className = 'veo-pick-label';\n this.label.style.display = 'none';\n\n const hint = document.createElement('div');\n hint.className = 'veo-pick-hint';\n hint.textContent = options.hint ?? 'Seleccioná un elemento · Esc para cancelar';\n\n shadow.append(style, this.box, this.label, hint);\n document.body.appendChild(host);\n this.host = host;\n\n document.addEventListener('mousemove', this.onMove, true);\n document.addEventListener('click', this.onClick, true);\n document.addEventListener('mousedown', this.swallow, true);\n document.addEventListener('mouseup', this.swallow, true);\n document.addEventListener('keydown', this.onKey, true);\n window.addEventListener('scroll', this.reposition, true);\n window.addEventListener('resize', this.reposition);\n }\n\n stop(): void {\n document.removeEventListener('mousemove', this.onMove, true);\n document.removeEventListener('click', this.onClick, true);\n document.removeEventListener('mousedown', this.swallow, true);\n document.removeEventListener('mouseup', this.swallow, true);\n document.removeEventListener('keydown', this.onKey, true);\n window.removeEventListener('scroll', this.reposition, true);\n window.removeEventListener('resize', this.reposition);\n\n if (this.host?.parentNode) this.host.parentNode.removeChild(this.host);\n this.host = null;\n this.box = null;\n this.label = null;\n this.current = null;\n this.onPick = null;\n this.onCancel = null;\n }\n\n /** ¿Es un nodo de nuestro propio overlay? (no debe ser seleccionable). */\n private isOwn(target: EventTarget | null): boolean {\n return target instanceof Node && this.host !== null && this.host.contains(target);\n }\n\n private onMove = (event: MouseEvent): void => {\n const target = event.target;\n if (!(target instanceof Element) || this.isOwn(target)) return;\n this.current = target;\n this.draw(target);\n };\n\n private onClick = (event: MouseEvent): void => {\n const target = this.current ?? (event.target instanceof Element ? event.target : null);\n if (!target || this.isOwn(target)) return;\n\n // Evitar que la app reaccione al click de selección.\n event.preventDefault();\n event.stopPropagation();\n event.stopImmediatePropagation();\n\n const picked = this.describe(target);\n const cb = this.onPick;\n this.stop();\n cb?.(picked);\n };\n\n private onKey = (event: KeyboardEvent): void => {\n if (event.key !== 'Escape') return;\n event.preventDefault();\n event.stopPropagation();\n const cb = this.onCancel;\n this.stop();\n cb?.();\n };\n\n /** Traga mousedown/mouseup durante el picking (evita focus/active de la app). */\n private swallow = (event: MouseEvent): void => {\n if (this.isOwn(event.target)) return;\n event.preventDefault();\n event.stopPropagation();\n };\n\n private reposition = (): void => {\n if (this.current) this.draw(this.current);\n };\n\n /** Dibuja el recuadro de resalte y la etiqueta sobre el elemento dado. */\n private draw(element: Element): void {\n if (!this.box || !this.label) return;\n const rect = element.getBoundingClientRect();\n\n this.box.style.display = 'block';\n this.box.style.top = `${rect.top}px`;\n this.box.style.left = `${rect.left}px`;\n this.box.style.width = `${rect.width}px`;\n this.box.style.height = `${rect.height}px`;\n\n const shortSel = buildSelectorPath(element, 0);\n this.label.textContent = '';\n const sel = document.createElement('div');\n sel.className = 'veo-pick-sel';\n sel.textContent = shortSel;\n const dim = document.createElement('div');\n dim.className = 'veo-pick-dim';\n dim.textContent = `${Math.round(rect.width)} × ${Math.round(rect.height)}`;\n this.label.append(sel, dim);\n\n // Etiqueta debajo del recuadro; si no hay espacio, arriba.\n this.label.style.display = 'block';\n const LABEL_H = 48;\n const placeAbove = rect.bottom + 8 + LABEL_H > window.innerHeight;\n this.label.style.top = placeAbove\n ? `${Math.max(8, rect.top - LABEL_H - 8)}px`\n : `${rect.bottom + 8}px`;\n this.label.style.left = `${Math.max(8, rect.left)}px`;\n }\n\n private describe(element: Element): PickedElement {\n const rect = element.getBoundingClientRect();\n return {\n selector: buildSelectorPath(element, this.maxAncestors),\n shortSelector: buildSelectorPath(element, 0),\n tag: element.tagName.toLowerCase(),\n id: element.id || null,\n classes: filterHumanClasses(element),\n text: (element.textContent ?? '').trim().slice(0, 120),\n rect: {\n x: Math.round(rect.left),\n y: Math.round(rect.top),\n width: Math.round(rect.width),\n height: Math.round(rect.height),\n },\n };\n }\n}\n\nlet activePicker: ElementPicker | null = null;\n\n/**\n * Inicia el modo de selección de elementos (inspector). Resalta lo que está\n * bajo el cursor y, al hacer click, entrega un selector CSS estable.\n * Devuelve un handle con `stop()`. Iniciar otro picker cierra el anterior.\n *\n * @example\n * ```ts\n * import { startElementPicker } from '@veo/sdk';\n *\n * const picker = startElementPicker({\n * onPick: ({ selector }) => console.log('elegido:', selector),\n * onCancel: () => console.log('cancelado'),\n * });\n * // picker.stop() para abortar manualmente.\n * ```\n */\nexport function startElementPicker(options: ElementPickerOptions): ElementPickerHandle {\n if (!hasDocument()) {\n return { stop: () => {} };\n }\n if (!activePicker) activePicker = new ElementPicker();\n activePicker.start(options);\n return { stop: () => activePicker?.stop() };\n}\n\n/** Cierra el picker activo, si lo hay. Idempotente. */\nexport function stopElementPicker(): void {\n activePicker?.stop();\n}\n","/**\n * Lado APP del puente builder. Corre dentro de la app del cliente (vía\n * veo-builder.js). Si el contexto trae `?veoBuilder=<token>`, se conecta con el\n * editor de Veo, atiende comandos y devuelve el elemento elegido.\n *\n * Dos transportes:\n * - **iframe/popup** (`resolveTarget` = opener/parent): el dashboard es la\n * ventana principal y embebe/abre la app; le hablamos a esa ventana.\n * - **panel inyectado** (`ctx.panel`): la app es top-level (login real) y NOSOTROS\n * inyectamos el panel del editor encima (iframe al dashboard); le hablamos a\n * ese iframe. Es el modo sin adaptación por app.\n *\n * Seguridad: solo acepta mensajes cuyo `origin` coincida con el del dashboard\n * (`veoBuilderOrigin` / `document.referrer`) y cuyo `token` coincida.\n */\nimport {\n type BuilderClientContext,\n clearBuilderToken,\n resolveBuilderContext,\n} from '../../core/builder-token';\nimport { hasDocument, hasWindow } from '../../utils/safe-env';\nimport { closeGuidePreview, previewGuide } from '../guides/guide-preview';\nimport { type BuilderCommand, type BuilderEvent, VEO_BUILDER_SOURCE } from './bridge-protocol';\nimport { type BuilderPanelHandle, injectBuilderPanel } from './builder-panel';\nimport { type ElementPickerHandle, startElementPicker } from './element-picker';\n\nexport interface BuilderModeHandle {\n /** Desconecta el puente y limpia picker/preview/panel. */\n teardown(): void;\n}\n\n/**\n * Inicializa el modo builder si hay contexto (URL o persistido). Devuelve un\n * handle, o `null` si no estamos en modo builder o no hay canal con el editor.\n * Es seguro llamarla siempre.\n */\nexport function initBuilderMode(): BuilderModeHandle | null {\n if (!hasWindow() || !hasDocument()) return null;\n\n // Contexto de la URL o de sessionStorage: sobrevive al redirect del guard de\n // auth (que suele tirar el query string) y a un login en la misma pestaña.\n const ctx = resolveBuilderContext();\n if (!ctx) return null;\n\n const token = ctx.token;\n const dashboardOrigin = resolveDashboardOrigin(ctx.origin);\n if (!dashboardOrigin) return null;\n\n let picker: ElementPickerHandle | null = null;\n let panel: BuilderPanelHandle | null = null;\n let staticTarget: Window | null = null;\n const getTarget = (): Window | null => (panel ? panel.target() : staticTarget);\n\n const post = (event: BuilderEvent): void => {\n getTarget()?.postMessage({ source: VEO_BUILDER_SOURCE, token, ...event }, dashboardOrigin);\n };\n\n const handleCommand = (cmd: BuilderCommand): void => {\n switch (cmd.type) {\n case 'panel-ready':\n // El panel cargó y ya escucha → recién ahora le mandamos `ready`.\n post({ type: 'ready' });\n break;\n case 'start-picker':\n picker?.stop();\n picker = startElementPicker({\n onPick: (payload) => {\n picker = null;\n post({ type: 'picked', payload });\n },\n onCancel: () => {\n picker = null;\n post({ type: 'pick-cancelled' });\n },\n ...(cmd.maxAncestors !== undefined ? { maxAncestors: cmd.maxAncestors } : {}),\n ...(cmd.hint !== undefined ? { hint: cmd.hint } : {}),\n });\n break;\n case 'stop-picker':\n picker?.stop();\n picker = null;\n break;\n case 'preview':\n if (cmd.guide) void previewGuide(cmd.guide).ready;\n break;\n case 'close-preview':\n closeGuidePreview();\n break;\n case 'teardown':\n teardown();\n break;\n }\n };\n\n const onMessage = (event: MessageEvent): void => {\n if (event.origin !== dashboardOrigin) return;\n const data = event.data as { source?: unknown; token?: unknown } | null;\n if (!data || data.source !== VEO_BUILDER_SOURCE || data.token !== token) return;\n handleCommand(data as BuilderCommand);\n };\n\n const onPageHide = (): void => post({ type: 'closed' });\n\n const teardown = (): void => {\n window.removeEventListener('message', onMessage);\n window.removeEventListener('pagehide', onPageHide);\n picker?.stop();\n picker = null;\n closeGuidePreview();\n post({ type: 'closed' }); // avisar al editor ANTES de sacar el panel\n panel?.teardown();\n panel = null;\n clearBuilderToken(); // salir del modo builder: no re-activar en la próxima carga\n };\n\n // Transporte: panel inyectado (app top-level) o iframe/popup (embebida).\n if (ctx.panel) {\n panel = injectBuilderPanel({\n dashboardOrigin,\n token,\n appOrigin: window.location.origin,\n guide: ctx.guide,\n panelPath: ctx.panelPath,\n onClose: () => teardown(),\n });\n } else {\n staticTarget = resolveTarget();\n if (!staticTarget) return null;\n }\n\n const activate = (): void => {\n window.addEventListener('message', onMessage);\n window.addEventListener('pagehide', onPageHide);\n // Panel: esperamos el `panel-ready` del iframe para postear `ready` (todavía\n // puede no tener su listener). iframe/popup: el opener ya escucha → posteamos ya.\n if (!ctx.panel) post({ type: 'ready' });\n };\n\n // Verificación del token contra el backend (firmado + scopeado por workspace)\n // ANTES de activar. Si `init()` dejó la config (integración real) verificamos;\n // si el backend dice explícitamente que NO es válido, no activamos. Si no hay\n // config (demo) o el backend no responde, activamos best-effort.\n const cfg = (window as unknown as { __veoBuilder?: { apiKey?: string; apiUrl?: string } })\n .__veoBuilder;\n if (cfg?.apiKey && cfg?.apiUrl) {\n void verifyBuilderToken(cfg.apiUrl, cfg.apiKey, token).then((ok) => {\n if (ok) activate();\n else if (window.console) console.warn('[veo] token de builder inválido — modo no activado');\n });\n } else {\n activate();\n }\n\n return { teardown };\n}\n\n/**\n * Verifica el token con el backend. Solo devuelve `false` (no activar) cuando el\n * backend responde explícitamente `{valid:false}` (token forjado/expirado/de\n * otro workspace). Ante 404/red caída/errores transitorios devuelve `true`\n * (best-effort) para no brickear el modo builder.\n */\nasync function verifyBuilderToken(apiUrl: string, apiKey: string, token: string): Promise<boolean> {\n try {\n const url = `${apiUrl.replace(/\\/+$/, '')}/v1/builder/verify`;\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-Api-Key': apiKey },\n body: JSON.stringify({ token }),\n });\n if (!res.ok) return true; // no pudimos verificar → best-effort\n const data = (await res.json().catch(() => null)) as { valid?: unknown } | null;\n return data?.valid !== false;\n } catch {\n return true; // red caída / sin backend → best-effort\n }\n}\n\n/** Ventana con la que hablar en modo iframe/popup: el opener o el parent. */\nfunction resolveTarget(): Window | null {\n if (window.opener && window.opener !== window) return window.opener as Window;\n if (window.parent && window.parent !== window) return window.parent;\n return null;\n}\n\nfunction resolveDashboardOrigin(originHint: string | null): string | null {\n // Origen de la URL o persistido en el primer arranque (antes del redirect).\n if (originHint) {\n try {\n return new URL(originHint).origin;\n } catch {\n return null;\n }\n }\n // Fallback: el referrer. Poco fiable tras un redirect same-origin (apunta a la\n // propia app), por eso el origen persistido va primero.\n if (hasDocument() && document.referrer) {\n try {\n return new URL(document.referrer).origin;\n } catch {\n return null;\n }\n }\n return null;\n}\n\n// Tipo re-exportado para consumidores que tipan el contexto.\nexport type { BuilderClientContext };\n","/**\n * Lado DASHBOARD del puente builder. Abre la app del cliente en un popup,\n * en modo builder, y expone una API para pedirle que seleccione un elemento\n * o previsualice una guía. Pensado para importarse en el dashboard\n * (`import { createBuilderSession } from '@veo/sdk/builder'`).\n *\n * Seguridad: solo procesa mensajes cuyo `origin` sea el de la app y cuyo\n * `token` coincida con el de esta sesión.\n */\nimport { hasWindow } from '../../utils/safe-env';\nimport type { PreviewGuideInput } from '../guides/guide-preview';\nimport {\n BUILDER_ORIGIN_PARAM,\n BUILDER_TOKEN_PARAM,\n type BuilderCommand,\n VEO_BUILDER_SOURCE,\n} from './bridge-protocol';\nimport type { PickedElement } from './element-picker';\n\nexport interface BuilderSessionOptions {\n /** URL de la app del cliente a abrir en modo builder. */\n appUrl: string;\n /** Token de la sesión (idealmente emitido/firmado por el backend). */\n token: string;\n /** Origen al que la app debe responder. Default: `location.origin`. */\n dashboardOrigin?: string;\n /** La app está lista y escuchando comandos. */\n onReady?: () => void;\n /** El usuario eligió un elemento. */\n onPicked?: (picked: PickedElement) => void;\n /** El usuario canceló la selección (Esc). */\n onCancelled?: () => void;\n /** La app cerró el modo builder (o el popup se cerró). */\n onClosed?: () => void;\n /**\n * Si se pasa, la app se embebe en este `<iframe>` (modo estudio in-app) en\n * lugar de abrirse en un popup. El lado app ya habla con `window.parent`,\n * así que el puente funciona igual. La sesión setea el `src` del iframe.\n */\n frame?: HTMLIFrameElement;\n /** Nombre de la ventana popup. Default: `veo-builder`. */\n windowName?: string;\n /** Features del popup. Default: ventana de ~1280×860. */\n windowFeatures?: string;\n}\n\nexport interface BuilderSession {\n /** Pide a la app que entre en modo selección de elemento. */\n startPicker(options?: { maxAncestors?: number; hint?: string }): void;\n /** Cancela la selección en curso. */\n stopPicker(): void;\n /** Pide a la app que previsualice una guía. */\n preview(guide: PreviewGuideInput): void;\n /** Cierra la preview activa en la app. */\n closePreview(): void;\n /** Cierra el popup y desconecta el puente. */\n close(): void;\n}\n\nconst DEFAULT_FEATURES = 'popup,width=1280,height=860';\nconst POPUP_POLL_MS = 600;\n\nexport function createBuilderSession(options: BuilderSessionOptions): BuilderSession {\n if (!hasWindow()) return noopSession();\n\n const dashboardOrigin = options.dashboardOrigin ?? window.location.origin;\n const appOrigin = safeOrigin(options.appUrl);\n const url = buildAppUrl(options.appUrl, options.token, dashboardOrigin);\n\n const frame = options.frame ?? null;\n const useFrame = frame !== null;\n\n let popup: Window | null = null;\n if (useFrame) {\n // biome-ignore lint/style/noNonNullAssertion: useFrame garantiza frame\n frame!.src = url;\n } else {\n popup = window.open(\n url,\n options.windowName ?? 'veo-builder',\n options.windowFeatures ?? DEFAULT_FEATURES,\n );\n }\n\n /** Ventana destino de los comandos: el popup o el contentWindow del iframe. */\n const targetWindow = (): Window | null => (useFrame ? (frame?.contentWindow ?? null) : popup);\n\n const post = (command: BuilderCommand): void => {\n const w = targetWindow();\n if (!w) return;\n if (!useFrame && popup?.closed) return;\n w.postMessage(\n { source: VEO_BUILDER_SOURCE, token: options.token, ...command },\n appOrigin ?? '*',\n );\n };\n\n let pollTimer: ReturnType<typeof setInterval> | undefined;\n\n const cleanup = (): void => {\n window.removeEventListener('message', onMessage);\n if (pollTimer !== undefined) {\n clearInterval(pollTimer);\n pollTimer = undefined;\n }\n };\n\n const onMessage = (event: MessageEvent): void => {\n if (appOrigin && event.origin !== appOrigin) return;\n const data = event.data as {\n source?: unknown;\n token?: unknown;\n type?: unknown;\n payload?: unknown;\n } | null;\n if (!data || data.source !== VEO_BUILDER_SOURCE || data.token !== options.token) return;\n\n switch (data.type) {\n case 'ready':\n options.onReady?.();\n break;\n case 'picked':\n if (data.payload) options.onPicked?.(data.payload as PickedElement);\n break;\n case 'pick-cancelled':\n options.onCancelled?.();\n break;\n case 'closed':\n cleanup();\n options.onClosed?.();\n break;\n }\n };\n\n window.addEventListener('message', onMessage);\n\n // Detectar cierre manual del popup (el usuario cierra la ventana). En modo\n // iframe el ciclo de vida lo controla el dashboard (no hay nada que pollear).\n if (!useFrame) {\n pollTimer = setInterval(() => {\n if (popup?.closed) {\n cleanup();\n options.onClosed?.();\n }\n }, POPUP_POLL_MS);\n }\n\n return {\n startPicker: (o) =>\n post({\n type: 'start-picker',\n ...(o?.maxAncestors !== undefined ? { maxAncestors: o.maxAncestors } : {}),\n ...(o?.hint !== undefined ? { hint: o.hint } : {}),\n }),\n stopPicker: () => post({ type: 'stop-picker' }),\n preview: (guide) => post({ type: 'preview', guide }),\n closePreview: () => post({ type: 'close-preview' }),\n close: () => {\n post({ type: 'teardown' });\n if (useFrame) {\n if (frame) frame.src = 'about:blank';\n } else if (popup && !popup.closed) {\n popup.close();\n }\n cleanup();\n },\n };\n}\n\nfunction buildAppUrl(appUrl: string, token: string, dashboardOrigin: string): string {\n try {\n const u = new URL(appUrl, window.location.href);\n u.searchParams.set(BUILDER_TOKEN_PARAM, token);\n u.searchParams.set(BUILDER_ORIGIN_PARAM, dashboardOrigin);\n return u.toString();\n } catch {\n return appUrl;\n }\n}\n\nfunction safeOrigin(url: string): string | null {\n try {\n return new URL(url, window.location.href).origin;\n } catch {\n return null;\n }\n}\n\nfunction noopSession(): BuilderSession {\n return {\n startPicker: () => {},\n stopPicker: () => {},\n preview: () => {},\n closePreview: () => {},\n close: () => {},\n };\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// src/core/builder-constants.ts
|
|
2
|
+
var BUILDER_TOKEN_PARAM = "veoBuilder";
|
|
3
|
+
var BUILDER_ORIGIN_PARAM = "veoBuilderOrigin";
|
|
4
|
+
var BUILDER_PANEL_PARAM = "veoBuilderPanel";
|
|
5
|
+
var BUILDER_PANEL_PATH_PARAM = "veoBuilderPanelPath";
|
|
6
|
+
var BUILDER_GUIDE_PARAM = "veoGuide";
|
|
7
|
+
|
|
8
|
+
export { BUILDER_GUIDE_PARAM, BUILDER_ORIGIN_PARAM, BUILDER_PANEL_PARAM, BUILDER_PANEL_PATH_PARAM, BUILDER_TOKEN_PARAM };
|
|
9
|
+
//# sourceMappingURL=chunk-PTG3BTJE.mjs.map
|
|
10
|
+
//# sourceMappingURL=chunk-PTG3BTJE.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/builder-constants.ts"],"names":[],"mappings":";AAQO,IAAM,mBAAA,GAAsB;AAE5B,IAAM,oBAAA,GAAuB;AAE7B,IAAM,mBAAA,GAAsB;AAE5B,IAAM,wBAAA,GAA2B;AAEjC,IAAM,mBAAA,GAAsB","file":"chunk-PTG3BTJE.mjs","sourcesContent":["/**\n * Nombres de los query params del puente builder. Constantes PURAS (sin DOM ni\n * `window`) para poder compartirlas entre el core (browser: `builder-token.ts`)\n * y el helper de servidor `veo-sdk/next` (`src/next.ts`), sin arrastrar código de\n * navegador al bundle de servidor.\n */\n\n/** Token de correlación del handshake. */\nexport const BUILDER_TOKEN_PARAM = 'veoBuilder';\n/** Origen del dashboard de Veo (para postMessage / frame-ancestors). */\nexport const BUILDER_ORIGIN_PARAM = 'veoBuilderOrigin';\n/** `1` → modo \"panel inyectado\": la app es top-level y el editor se inyecta encima. */\nexport const BUILDER_PANEL_PARAM = 'veoBuilderPanel';\n/** Path del panel del editor en el dashboard (default `/guides/design`). */\nexport const BUILDER_PANEL_PATH_PARAM = 'veoBuilderPanelPath';\n/** Id de la guía que se está editando (para cargar/guardar en el panel). */\nexport const BUILDER_GUIDE_PARAM = 'veoGuide';\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { hasDocument, hasWindow, previewGuide, DEFAULT_TRACKER_MAX_RETRIES, DEFAULT_TRACKER_BATCH_SIZE, DEFAULT_TRACKER_FLUSH_INTERVAL_MS, WalkthroughRenderer, InlineFormRenderer, FormRenderer, InlineCustomRenderer, InlineRenderer, CustomRenderer, TooltipRenderer, BannerRenderer, ModalRenderer, FREQUENCY_CACHE_KEY_PREFIX, FREQUENCY_CACHE_TTL_MS, FREQUENCY_CACHE_MAX_ENTRIES, WALKTHROUGH_STATE_KEY_PREFIX, WALKTHROUGH_ABANDONMENT_TIMEOUT_MS } from './chunk-
|
|
1
|
+
import { hasDocument, hasWindow, previewGuide, DEFAULT_TRACKER_MAX_RETRIES, DEFAULT_TRACKER_BATCH_SIZE, DEFAULT_TRACKER_FLUSH_INTERVAL_MS, WalkthroughRenderer, InlineFormRenderer, FormRenderer, InlineCustomRenderer, InlineRenderer, CustomRenderer, TooltipRenderer, BannerRenderer, ModalRenderer, FREQUENCY_CACHE_KEY_PREFIX, FREQUENCY_CACHE_TTL_MS, FREQUENCY_CACHE_MAX_ENTRIES, WALKTHROUGH_STATE_KEY_PREFIX, WALKTHROUGH_ABANDONMENT_TIMEOUT_MS } from './chunk-GHP7ZJCW.mjs';
|
|
2
2
|
|
|
3
3
|
// src/plugins/plugin.ts
|
|
4
4
|
function definePlugin(plugin) {
|
|
@@ -1038,5 +1038,5 @@ function guidesPlugin(config) {
|
|
|
1038
1038
|
}
|
|
1039
1039
|
|
|
1040
1040
|
export { definePlugin, guidesPlugin, runPreviewMode };
|
|
1041
|
-
//# sourceMappingURL=chunk-
|
|
1042
|
-
//# sourceMappingURL=chunk-
|
|
1041
|
+
//# sourceMappingURL=chunk-R4E3LIDB.mjs.map
|
|
1042
|
+
//# sourceMappingURL=chunk-R4E3LIDB.mjs.map
|