veo-sdk 0.5.34 → 0.6.0
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-3QPHB2VJ.mjs +5 -0
- package/dist/{builder-ZKWVTSTP.mjs.map → builder-3QPHB2VJ.mjs.map} +1 -1
- package/dist/builder.cjs +2271 -412
- package/dist/builder.cjs.map +1 -1
- package/dist/builder.d.cts +92 -4
- package/dist/builder.d.ts +92 -4
- package/dist/builder.mjs +4 -4
- package/dist/{chunk-HAAT6XVN.mjs → chunk-GMXQMZ4X.mjs} +97 -10
- package/dist/chunk-GMXQMZ4X.mjs.map +1 -0
- package/dist/{chunk-IZXJA55N.mjs → chunk-N4VFMZFA.mjs} +895 -41
- package/dist/chunk-N4VFMZFA.mjs.map +1 -0
- package/dist/{chunk-W4R4XCWL.mjs → chunk-O6USA4TU.mjs} +1117 -98
- package/dist/chunk-O6USA4TU.mjs.map +1 -0
- package/dist/{guide-preview-DbEZdGBV.d.cts → guide-preview-DylsEhrg.d.cts} +98 -5
- package/dist/{guide-preview-DbEZdGBV.d.ts → guide-preview-DylsEhrg.d.ts} +98 -5
- package/dist/index.cjs +2141 -143
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +5 -5
- package/dist/veo-builder.js +261 -28
- package/dist/veo-builder.js.map +1 -1
- package/dist/veo-guides.js +228 -16
- package/dist/veo-guides.js.map +1 -1
- package/package.json +1 -1
- package/dist/builder-ZKWVTSTP.mjs +0 -5
- package/dist/chunk-HAAT6XVN.mjs.map +0 -1
- package/dist/chunk-IZXJA55N.mjs.map +0 -1
- package/dist/chunk-W4R4XCWL.mjs.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { hasDocument, hasWindow, resolveBuilderContext, closeGuidePreview, clearBuilderToken, buildSelectorPath, filterHumanClasses,
|
|
1
|
+
import { hasDocument, hasWindow, resolveBuilderContext, closeGuidePreview, clearBuilderToken, buildSelectorPath, filterHumanClasses, groupLayout, stepMatchesPage, isAutomaticActivation, activationDelayMs, previewGuide, applyBlockStyle, buildContentBlock, RAW_BLOCK_ATTR, GUIDE_STYLES, isDeviceAllowed } from './chunk-O6USA4TU.mjs';
|
|
2
2
|
import { BUILDER_TOKEN_PARAM, BUILDER_ORIGIN_PARAM } from './chunk-PTG3BTJE.mjs';
|
|
3
3
|
|
|
4
4
|
// src/plugins/builder/block-drop-target.ts
|
|
@@ -122,6 +122,9 @@ var ICONS = {
|
|
|
122
122
|
chevronDown: '<path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5"/>',
|
|
123
123
|
chevronUp: '<path stroke-linecap="round" stroke-linejoin="round" d="m4.5 15.75 7.5-7.5 7.5 7.5"/>',
|
|
124
124
|
plus: '<path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15"/>',
|
|
125
|
+
pencil: '<path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L10.582 16.07a4.5 4.5 0 0 1-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 0 1 1.13-1.897l8.932-8.931Zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0 1 15.75 21H5.25A2.25 2.25 0 0 1 3 18.75V8.25A2.25 2.25 0 0 1 5.25 6H10"/>',
|
|
126
|
+
copy: '<path stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 0 0-2.25-2.25H6A2.25 2.25 0 0 0 3.75 6v8.25A2.25 2.25 0 0 0 6 16.5h2.25m8.25-8.25H18a2.25 2.25 0 0 1 2.25 2.25V18A2.25 2.25 0 0 1 18 20.25h-7.5A2.25 2.25 0 0 1 8.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 0 0-2.25 2.25v6"/>',
|
|
127
|
+
trash: '<path stroke-linecap="round" stroke-linejoin="round" d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0"/>',
|
|
125
128
|
cursor: '<path stroke-linecap="round" stroke-linejoin="round" d="M15.042 21.672 13.684 16.6m0 0-2.51 2.225.569-9.47 5.227 7.917-3.286-.672ZM12 2.25V4.5m5.834.166-1.591 1.591M20.25 10.5H18M7.757 14.743l-1.59 1.59M6 10.5H3.75m4.007-4.243-1.59-1.59"/>',
|
|
126
129
|
spinner: '<path stroke-linecap="round" stroke-linejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182"/>'
|
|
127
130
|
};
|
|
@@ -307,8 +310,14 @@ function injectBuilderChrome(opts) {
|
|
|
307
310
|
stepsList.append(activation);
|
|
308
311
|
s.steps.forEach((st, i) => {
|
|
309
312
|
const thumb = st.presentation === "inline" ? '<div class="veo-thumb veo-thumb-inline"><i></i><i></i><i></i></div>' : '<div class="veo-thumb"><i></i><i></i><b></b></div>';
|
|
310
|
-
const
|
|
311
|
-
card
|
|
313
|
+
const isStepView = s.section === "step" || s.section === "block" || s.section === "add-block" || s.section === "row" || s.section === "structure";
|
|
314
|
+
const card = stepCard(thumb, st.label, isStepView && s.activeStep === i, {
|
|
315
|
+
// Se pueden borrar TODOS los pasos (el panel vuelve a Activación).
|
|
316
|
+
canRemove: true,
|
|
317
|
+
onEdit: () => act({ action: "select-step", index: i }),
|
|
318
|
+
onDuplicate: () => act({ action: "duplicate-step", index: i }),
|
|
319
|
+
onRemove: () => act({ action: "remove-step", index: i })
|
|
320
|
+
});
|
|
312
321
|
stepsList.append(card);
|
|
313
322
|
});
|
|
314
323
|
const add = el("button", "veo-step-add", `${svg("plus", 18)}<span>Agregar paso</span>`);
|
|
@@ -337,16 +346,40 @@ function injectBuilderChrome(opts) {
|
|
|
337
346
|
}
|
|
338
347
|
};
|
|
339
348
|
}
|
|
340
|
-
function stepCard(inner, label, active) {
|
|
341
|
-
const
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
349
|
+
function stepCard(inner, label, active, actions) {
|
|
350
|
+
const cls = `veo-step${active ? " is-active" : ""}`;
|
|
351
|
+
if (!actions) {
|
|
352
|
+
const b = el(
|
|
353
|
+
"button",
|
|
354
|
+
cls,
|
|
355
|
+
`<div class="veo-step-box">${inner}</div><span class="veo-step-label"></span>`
|
|
356
|
+
);
|
|
357
|
+
b.type = "button";
|
|
358
|
+
b.querySelector(".veo-step-label").textContent = label;
|
|
359
|
+
b.setAttribute("aria-pressed", active ? "true" : "false");
|
|
360
|
+
return b;
|
|
361
|
+
}
|
|
362
|
+
const card = el(
|
|
363
|
+
"div",
|
|
364
|
+
cls,
|
|
365
|
+
`<div class="veo-step-box">${inner}<div class="veo-step-hover"><div class="veo-step-hover-top"><button type="button" class="veo-step-icon veo-step-remove" title="Eliminar paso" aria-label="Eliminar paso">${svg("trash", 14)}</button><button type="button" class="veo-step-icon veo-step-duplicate" title="Duplicar paso" aria-label="Duplicar paso">${svg("copy", 14)}</button></div><div class="veo-step-hover-main"><button type="button" class="veo-step-edit">${svg("pencil", 14)}<span>Editar</span></button></div></div></div><span class="veo-step-label"></span>`
|
|
345
366
|
);
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
367
|
+
card.querySelector(".veo-step-label").textContent = label;
|
|
368
|
+
card.setAttribute("aria-current", active ? "step" : "false");
|
|
369
|
+
const remove = card.querySelector(".veo-step-remove");
|
|
370
|
+
remove.disabled = !actions.canRemove;
|
|
371
|
+
if (!actions.canRemove) remove.title = "La gu\xEDa necesita al menos un paso";
|
|
372
|
+
const on = (sel, fn) => {
|
|
373
|
+
card.querySelector(sel)?.addEventListener("click", (e) => {
|
|
374
|
+
e.stopPropagation();
|
|
375
|
+
fn();
|
|
376
|
+
});
|
|
377
|
+
};
|
|
378
|
+
on(".veo-step-edit", actions.onEdit);
|
|
379
|
+
on(".veo-step-duplicate", actions.onDuplicate);
|
|
380
|
+
on(".veo-step-remove", actions.onRemove);
|
|
381
|
+
card.addEventListener("click", actions.onEdit);
|
|
382
|
+
return card;
|
|
350
383
|
}
|
|
351
384
|
var CHROME_CSS = `
|
|
352
385
|
:host { all: initial; }
|
|
@@ -431,10 +464,31 @@ var CHROME_CSS = `
|
|
|
431
464
|
.veo-steps-list { display: flex; align-items: flex-start; gap: 20px; }
|
|
432
465
|
.veo-step { border: 0; background: transparent; padding: 0; cursor: pointer; font: inherit; display: flex; flex-direction: column; align-items: center; gap: 8px; flex: 0 0 auto; }
|
|
433
466
|
.veo-step-box {
|
|
467
|
+
position: relative; overflow: hidden;
|
|
434
468
|
width: 116px; height: 64px; border-radius: 10px; background: #fff; border: 2px solid transparent;
|
|
435
469
|
display: flex; align-items: center; justify-content: center; color: #2b2623;
|
|
436
470
|
box-shadow: 0 1px 2px rgba(0,0,0,0.06);
|
|
437
471
|
}
|
|
472
|
+
/* Capa de acciones del paso: aparece al pasar el mouse o al enfocar un bot\xF3n. */
|
|
473
|
+
.veo-step-hover {
|
|
474
|
+
position: absolute; inset: 0; background: #2b2623; border-radius: 8px;
|
|
475
|
+
display: flex; flex-direction: column; padding: 3px 4px 6px; box-sizing: border-box;
|
|
476
|
+
opacity: 0; transition: opacity 120ms ease-out;
|
|
477
|
+
}
|
|
478
|
+
.veo-step:hover .veo-step-hover, .veo-step:focus-within .veo-step-hover { opacity: 1; }
|
|
479
|
+
.veo-step-hover-top { display: flex; justify-content: space-between; align-items: center; }
|
|
480
|
+
.veo-step-hover-main { flex: 1; display: flex; align-items: center; justify-content: center; }
|
|
481
|
+
.veo-step-icon {
|
|
482
|
+
border: 0; background: transparent; color: #fff; cursor: pointer; padding: 0;
|
|
483
|
+
width: 20px; height: 20px; border-radius: 5px; display: inline-flex; align-items: center; justify-content: center;
|
|
484
|
+
}
|
|
485
|
+
.veo-step-icon:hover { background: rgba(255,255,255,0.14); }
|
|
486
|
+
.veo-step-icon:disabled { opacity: 0.35; cursor: default; background: transparent; }
|
|
487
|
+
.veo-step-edit {
|
|
488
|
+
width: 100%; margin: 0 6px; border: 0; background: #dbeefc; color: #1d6fb8; font: inherit; font-size: 13px; font-weight: 600;
|
|
489
|
+
border-radius: 6px; padding: 5px 10px; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; gap: 6px;
|
|
490
|
+
}
|
|
491
|
+
.veo-step-edit:hover { background: #cbe4f9; }
|
|
438
492
|
.veo-step.is-active .veo-step-box { border-color: #b74d00; }
|
|
439
493
|
.veo-step-label { font-size: 13px; color: #6b635d; }
|
|
440
494
|
.veo-step.is-active .veo-step-label { color: #2b2623; font-weight: 600; }
|
|
@@ -477,6 +531,8 @@ function injectBuilderPanel(opts) {
|
|
|
477
531
|
},
|
|
478
532
|
isVisible: () => false,
|
|
479
533
|
setTopOffset: () => {
|
|
534
|
+
},
|
|
535
|
+
setSize: () => {
|
|
480
536
|
}
|
|
481
537
|
};
|
|
482
538
|
}
|
|
@@ -529,6 +585,21 @@ function injectBuilderPanel(opts) {
|
|
|
529
585
|
card.style.display = next && !(popped && !popped.closed) ? "" : "none";
|
|
530
586
|
};
|
|
531
587
|
minimize.addEventListener("click", () => setVisible(false));
|
|
588
|
+
let compactRestore = null;
|
|
589
|
+
const setSize = (size) => {
|
|
590
|
+
if (maximized || popped && !popped.closed) return;
|
|
591
|
+
if (size) {
|
|
592
|
+
if (!compactRestore) compactRestore = { w: card.offsetWidth, h: card.offsetHeight };
|
|
593
|
+
card.style.minHeight = "0";
|
|
594
|
+
card.style.width = `${clamp(Math.round(size.width), MIN_W, window.innerWidth - MARGIN * 2)}px`;
|
|
595
|
+
card.style.height = `${clamp(Math.round(size.height) + HEADER_H, HEADER_H + 80, window.innerHeight - top - MARGIN)}px`;
|
|
596
|
+
} else if (compactRestore) {
|
|
597
|
+
card.style.minHeight = "";
|
|
598
|
+
card.style.width = `${compactRestore.w}px`;
|
|
599
|
+
card.style.height = `${compactRestore.h}px`;
|
|
600
|
+
compactRestore = null;
|
|
601
|
+
}
|
|
602
|
+
};
|
|
532
603
|
maximize.addEventListener("click", () => {
|
|
533
604
|
maximized = !maximized;
|
|
534
605
|
if (maximized) {
|
|
@@ -628,6 +699,7 @@ function injectBuilderPanel(opts) {
|
|
|
628
699
|
title.textContent = t;
|
|
629
700
|
},
|
|
630
701
|
setVisible,
|
|
702
|
+
setSize,
|
|
631
703
|
isVisible: () => visible,
|
|
632
704
|
setTopOffset: (px) => {
|
|
633
705
|
topOffset = px;
|
|
@@ -1188,6 +1260,9 @@ function initBuilderMode() {
|
|
|
1188
1260
|
let staticTarget = null;
|
|
1189
1261
|
let manipulator = null;
|
|
1190
1262
|
let dropTarget = null;
|
|
1263
|
+
let cardClick = null;
|
|
1264
|
+
let rawBlock = null;
|
|
1265
|
+
let selectedBlockId = null;
|
|
1191
1266
|
let dragGhost = null;
|
|
1192
1267
|
let previewStepIndex = 0;
|
|
1193
1268
|
let pendingPreview = null;
|
|
@@ -1208,13 +1283,742 @@ function initBuilderMode() {
|
|
|
1208
1283
|
};
|
|
1209
1284
|
const previewMatchesPage = (cmd) => stepMatchesPage(previewStep(cmd)?.pageLocation, window.location.href);
|
|
1210
1285
|
const postPreviewStatus = (payload) => post({ type: "preview-status", payload });
|
|
1211
|
-
const
|
|
1286
|
+
const detachPreviewTools = () => {
|
|
1212
1287
|
manipulator?.detach();
|
|
1213
1288
|
manipulator = null;
|
|
1214
1289
|
dropTarget?.detach();
|
|
1215
1290
|
dropTarget = null;
|
|
1291
|
+
cardClick?.();
|
|
1292
|
+
cardClick = null;
|
|
1293
|
+
rowHover?.();
|
|
1294
|
+
rowHover = null;
|
|
1295
|
+
hoverRowId = null;
|
|
1296
|
+
hoverCard = false;
|
|
1297
|
+
rawBlock?.detach();
|
|
1298
|
+
rawBlock = null;
|
|
1299
|
+
shownPreview = null;
|
|
1300
|
+
};
|
|
1301
|
+
const withholdPreview = () => {
|
|
1302
|
+
detachPreviewTools();
|
|
1303
|
+
shownPreview = null;
|
|
1216
1304
|
closeGuidePreview();
|
|
1217
1305
|
};
|
|
1306
|
+
const FRAME_PAD = 4;
|
|
1307
|
+
const FRAME_MIN_H = 0;
|
|
1308
|
+
const TOOLBAR_H = 30;
|
|
1309
|
+
const ICON = {
|
|
1310
|
+
pencil: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125"/></svg>',
|
|
1311
|
+
copy: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M16.5 8.25V6a2.25 2.25 0 0 0-2.25-2.25H6A2.25 2.25 0 0 0 3.75 6v8.25A2.25 2.25 0 0 0 6 16.5h2.25m8.25-8.25H18a2.25 2.25 0 0 1 2.25 2.25V18A2.25 2.25 0 0 1 18 20.25h-7.5A2.25 2.25 0 0 1 8.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 0 0-2.25 2.25v6"/></svg>',
|
|
1312
|
+
trash: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0"/></svg>'
|
|
1313
|
+
};
|
|
1314
|
+
const ICON_MOVE = {
|
|
1315
|
+
left: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M19.5 12h-15m0 0 6.75 6.75M4.5 12l6.75-6.75"/></svg>',
|
|
1316
|
+
right: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4.5 12h15m0 0-6.75-6.75M19.5 12l-6.75 6.75"/></svg>'
|
|
1317
|
+
};
|
|
1318
|
+
const moveAbility = (blocks, blockId) => {
|
|
1319
|
+
for (const row of groupLayout(blocks)) {
|
|
1320
|
+
for (let c = 0; c < row.columns.length; c++) {
|
|
1321
|
+
const col = row.columns[c];
|
|
1322
|
+
if (!col.blocks.some((b) => b.block.editorId === blockId)) continue;
|
|
1323
|
+
return { left: c > 0, right: c < row.columns.length - 1 };
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
return { left: false, right: false };
|
|
1327
|
+
};
|
|
1328
|
+
let previewBlocks = [];
|
|
1329
|
+
let hoverRowId = null;
|
|
1330
|
+
let selectedRowId = null;
|
|
1331
|
+
let rowHover = null;
|
|
1332
|
+
let hoverCard = false;
|
|
1333
|
+
let panelSection = null;
|
|
1334
|
+
let shownPreview = null;
|
|
1335
|
+
const structureOf = (step) => {
|
|
1336
|
+
if (!step) return "";
|
|
1337
|
+
const { blocks, ...rest } = step;
|
|
1338
|
+
return JSON.stringify({
|
|
1339
|
+
rest,
|
|
1340
|
+
blocks: (blocks ?? []).map((b) => {
|
|
1341
|
+
const { text: _t, html: _h, style: _s, ...keep } = b;
|
|
1342
|
+
return keep;
|
|
1343
|
+
})
|
|
1344
|
+
});
|
|
1345
|
+
};
|
|
1346
|
+
const tryPatchPreview = (cmd) => {
|
|
1347
|
+
const prev = shownPreview;
|
|
1348
|
+
if (!prev || cmd.guide.guideType !== "composite" || prev.guide.guideType !== "composite") {
|
|
1349
|
+
return false;
|
|
1350
|
+
}
|
|
1351
|
+
const idx = cmd.guide.startStepIndex ?? 0;
|
|
1352
|
+
if ((prev.guide.startStepIndex ?? 0) !== idx) return false;
|
|
1353
|
+
const guideSig = (g) => JSON.stringify({ ...g, guideSteps: void 0 });
|
|
1354
|
+
if (guideSig(prev.guide) !== guideSig(cmd.guide) || prev.editable !== cmd.editable)
|
|
1355
|
+
return false;
|
|
1356
|
+
const host = document.querySelector("[data-veo-guide]");
|
|
1357
|
+
const card = host ? previewCard(host) : null;
|
|
1358
|
+
if (!host || !card) return false;
|
|
1359
|
+
const prevStep = prev.guide.guideSteps[idx];
|
|
1360
|
+
const nextStep = cmd.guide.guideSteps[idx];
|
|
1361
|
+
if (!prevStep || !nextStep) return false;
|
|
1362
|
+
if (structureOf(prevStep) !== structureOf(nextStep)) return false;
|
|
1363
|
+
const doc = card.ownerDocument;
|
|
1364
|
+
const prevBlocks = prevStep.blocks ?? [];
|
|
1365
|
+
const nextBlocks = nextStep.blocks ?? [];
|
|
1366
|
+
for (let i = 0; i < nextBlocks.length; i++) {
|
|
1367
|
+
const a = prevBlocks[i];
|
|
1368
|
+
const b = nextBlocks[i];
|
|
1369
|
+
if (a.text === b.text && a.html === b.html && JSON.stringify(a.style) === JSON.stringify(b.style)) {
|
|
1370
|
+
continue;
|
|
1371
|
+
}
|
|
1372
|
+
if (!b.editorId) return false;
|
|
1373
|
+
const node = card.querySelector(`[data-veo-block-id="${b.editorId}"]`);
|
|
1374
|
+
if (!node) return false;
|
|
1375
|
+
if (b.type === "button") {
|
|
1376
|
+
node.textContent = b.text?.trim() || "OK";
|
|
1377
|
+
node.removeAttribute("style");
|
|
1378
|
+
node.classList.remove("veo-guide-cta--secondary", "veo-guide-cta--link");
|
|
1379
|
+
const st = b.style ?? {};
|
|
1380
|
+
if (st.preset === "secondary" || st.preset === "link") {
|
|
1381
|
+
node.classList.add(`veo-guide-cta--${st.preset}`);
|
|
1382
|
+
}
|
|
1383
|
+
if (typeof st.ariaLabel === "string" && st.ariaLabel.trim()) {
|
|
1384
|
+
node.setAttribute("aria-label", st.ariaLabel.trim());
|
|
1385
|
+
} else node.removeAttribute("aria-label");
|
|
1386
|
+
applyBlockStyle(node, b.style, "button");
|
|
1387
|
+
continue;
|
|
1388
|
+
}
|
|
1389
|
+
if (b.type === "code" || b.type === "form") return false;
|
|
1390
|
+
const fresh = buildContentBlock(b, doc, { editing: true }) ?? (() => {
|
|
1391
|
+
const el2 = doc.createElement("div");
|
|
1392
|
+
el2.className = "veo-block-placeholder";
|
|
1393
|
+
el2.textContent = b.type === "image" ? "Imagen (sin URL)" : b.type === "video" ? "Video (elige proveedor y pega la URL)" : "Bloque vac\xEDo";
|
|
1394
|
+
return el2;
|
|
1395
|
+
})();
|
|
1396
|
+
fresh.dataset.veoBlock = node.dataset.veoBlock ?? String(i);
|
|
1397
|
+
fresh.dataset.veoBlockId = b.editorId;
|
|
1398
|
+
node.replaceWith(fresh);
|
|
1399
|
+
}
|
|
1400
|
+
shownPreview = cmd;
|
|
1401
|
+
previewBlocks = nextBlocks;
|
|
1402
|
+
applyBlockHighlight(host, idx);
|
|
1403
|
+
renderGapZones(host, idx, nextBlocks);
|
|
1404
|
+
return true;
|
|
1405
|
+
};
|
|
1406
|
+
const previewCard = (host) => host.shadowRoot?.querySelector(".veo-card") ?? null;
|
|
1407
|
+
const clearBlockHighlight = (host) => {
|
|
1408
|
+
const card = previewCard(host);
|
|
1409
|
+
if (!card) return;
|
|
1410
|
+
for (const el2 of card.querySelectorAll(".veo-block--selected")) {
|
|
1411
|
+
el2.classList.remove("veo-block--selected");
|
|
1412
|
+
}
|
|
1413
|
+
card.querySelector(".veo-block-toolbar")?.remove();
|
|
1414
|
+
card.querySelector(".veo-block-frame")?.remove();
|
|
1415
|
+
};
|
|
1416
|
+
const applyBlockHighlight = (host, stepIndex) => {
|
|
1417
|
+
clearBlockHighlight(host);
|
|
1418
|
+
const card = previewCard(host);
|
|
1419
|
+
if (!card) return;
|
|
1420
|
+
const el2 = selectedBlockId ? card.querySelector(`[data-veo-block-id="${selectedBlockId}"]`) : null;
|
|
1421
|
+
if (!el2 || !selectedBlockId) {
|
|
1422
|
+
renderRowChrome(host, stepIndex);
|
|
1423
|
+
return;
|
|
1424
|
+
}
|
|
1425
|
+
el2.classList.add("veo-block--selected");
|
|
1426
|
+
const doc = card.ownerDocument;
|
|
1427
|
+
const cs = getComputedStyle(card);
|
|
1428
|
+
const padL = Number.parseFloat(cs.paddingLeft) || 0;
|
|
1429
|
+
const padT = Number.parseFloat(cs.paddingTop) || 0;
|
|
1430
|
+
const padR = Number.parseFloat(cs.paddingRight) || 0;
|
|
1431
|
+
const padB = Number.parseFloat(cs.paddingBottom) || 0;
|
|
1432
|
+
const parent = el2.parentElement;
|
|
1433
|
+
const inCol = parent?.classList.contains("veo-col") ? parent : null;
|
|
1434
|
+
const boxL = inCol ? inCol.offsetLeft : padL;
|
|
1435
|
+
const boxR = inCol ? inCol.offsetLeft + inCol.offsetWidth : card.clientWidth - padR;
|
|
1436
|
+
const boxT = padT;
|
|
1437
|
+
const boxB = card.clientHeight - padB;
|
|
1438
|
+
const fx = Math.max(boxL, el2.offsetLeft - FRAME_PAD);
|
|
1439
|
+
const fr = Math.min(boxR, el2.offsetLeft + el2.offsetWidth + FRAME_PAD);
|
|
1440
|
+
const fw = Math.max(0, fr - fx);
|
|
1441
|
+
const fy = Math.max(boxT, el2.offsetTop - FRAME_PAD);
|
|
1442
|
+
const fb = Math.min(boxB, el2.offsetTop + el2.offsetHeight + FRAME_PAD);
|
|
1443
|
+
const fh = Math.max(FRAME_MIN_H, fb - fy);
|
|
1444
|
+
const frame = doc.createElement("div");
|
|
1445
|
+
frame.className = "veo-block-frame";
|
|
1446
|
+
frame.setAttribute("data-veo-builder-chrome", "");
|
|
1447
|
+
frame.style.left = `${fx}px`;
|
|
1448
|
+
frame.style.top = `${fy}px`;
|
|
1449
|
+
frame.style.width = `${fw}px`;
|
|
1450
|
+
frame.style.height = `${fh}px`;
|
|
1451
|
+
card.appendChild(frame);
|
|
1452
|
+
const bar = doc.createElement("div");
|
|
1453
|
+
bar.className = "veo-block-toolbar";
|
|
1454
|
+
bar.setAttribute("data-veo-builder-chrome", "");
|
|
1455
|
+
const blockId = selectedBlockId;
|
|
1456
|
+
const mk = (action, label, icon, enabled = true) => {
|
|
1457
|
+
const b = doc.createElement("button");
|
|
1458
|
+
b.type = "button";
|
|
1459
|
+
b.title = label;
|
|
1460
|
+
b.setAttribute("aria-label", label);
|
|
1461
|
+
b.className = `veo-block-toolbar-${action}`;
|
|
1462
|
+
b.innerHTML = icon;
|
|
1463
|
+
b.disabled = !enabled;
|
|
1464
|
+
b.addEventListener("click", (e) => {
|
|
1465
|
+
e.preventDefault();
|
|
1466
|
+
e.stopPropagation();
|
|
1467
|
+
post({ type: "block-action", payload: { stepIndex, blockId, action } });
|
|
1468
|
+
});
|
|
1469
|
+
bar.appendChild(b);
|
|
1470
|
+
};
|
|
1471
|
+
const can = moveAbility(previewBlocks, blockId);
|
|
1472
|
+
mk("edit", "Editar", ICON.pencil);
|
|
1473
|
+
mk("duplicate", "Duplicar", ICON.copy);
|
|
1474
|
+
mk("remove", "Eliminar", ICON.trash);
|
|
1475
|
+
mk("move-left", "Mover a la izquierda", ICON_MOVE.left, can.left);
|
|
1476
|
+
mk("move-right", "Mover a la derecha", ICON_MOVE.right, can.right);
|
|
1477
|
+
bar.style.right = `${Math.max(0, card.clientWidth - fr)}px`;
|
|
1478
|
+
card.appendChild(bar);
|
|
1479
|
+
const barH = bar.offsetHeight || TOOLBAR_H;
|
|
1480
|
+
bar.dataset.veoTopAbove = String(fy - barH - 6);
|
|
1481
|
+
bar.dataset.veoTopBelow = String(fb + 6);
|
|
1482
|
+
bar.style.top = bar.dataset.veoTopAbove;
|
|
1483
|
+
renderRowChrome(host, stepIndex);
|
|
1484
|
+
};
|
|
1485
|
+
const chromeRect = (el2) => ({
|
|
1486
|
+
left: el2.offsetLeft,
|
|
1487
|
+
top: el2.offsetTop,
|
|
1488
|
+
right: el2.offsetLeft + el2.offsetWidth,
|
|
1489
|
+
bottom: el2.offsetTop + el2.offsetHeight
|
|
1490
|
+
});
|
|
1491
|
+
const intersects = (a, b) => a.left < b.right && b.left < a.right && a.top < b.bottom && b.top < a.bottom;
|
|
1492
|
+
const resolveToolbarOverlaps = (card) => {
|
|
1493
|
+
const cardBar = card.querySelector(".veo-card-toolbar");
|
|
1494
|
+
const blockBar = card.querySelector(".veo-block-toolbar");
|
|
1495
|
+
const rowBar = card.querySelector(".veo-row-toolbar");
|
|
1496
|
+
if (blockBar?.dataset.veoTopAbove) {
|
|
1497
|
+
blockBar.style.top = `${blockBar.dataset.veoTopAbove}px`;
|
|
1498
|
+
if (cardBar && intersects(chromeRect(blockBar), chromeRect(cardBar))) {
|
|
1499
|
+
blockBar.style.top = `${blockBar.dataset.veoTopBelow}px`;
|
|
1500
|
+
}
|
|
1501
|
+
}
|
|
1502
|
+
if (rowBar?.dataset.veoRight) {
|
|
1503
|
+
rowBar.style.left = "";
|
|
1504
|
+
rowBar.style.right = `${rowBar.dataset.veoRight}px`;
|
|
1505
|
+
rowBar.style.top = `${rowBar.dataset.veoTopBelow}px`;
|
|
1506
|
+
const others = [cardBar, blockBar].filter((b) => !!b);
|
|
1507
|
+
const clashes = () => others.some((o) => intersects(chromeRect(rowBar), chromeRect(o)));
|
|
1508
|
+
if (clashes()) {
|
|
1509
|
+
rowBar.style.right = "";
|
|
1510
|
+
rowBar.style.left = `${rowBar.dataset.veoLeft}px`;
|
|
1511
|
+
}
|
|
1512
|
+
if (clashes() && blockBar) {
|
|
1513
|
+
rowBar.style.left = "";
|
|
1514
|
+
rowBar.style.right = `${rowBar.dataset.veoRight}px`;
|
|
1515
|
+
rowBar.style.top = `${chromeRect(blockBar).bottom + 6}px`;
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
};
|
|
1519
|
+
const rectOf = (el2) => ({
|
|
1520
|
+
left: el2.offsetLeft,
|
|
1521
|
+
top: el2.offsetTop,
|
|
1522
|
+
right: el2.offsetLeft + el2.offsetWidth,
|
|
1523
|
+
bottom: el2.offsetTop + el2.offsetHeight
|
|
1524
|
+
});
|
|
1525
|
+
const union = (rs) => rs.length === 0 ? null : rs.reduce((acc, r) => ({
|
|
1526
|
+
left: Math.min(acc.left, r.left),
|
|
1527
|
+
top: Math.min(acc.top, r.top),
|
|
1528
|
+
right: Math.max(acc.right, r.right),
|
|
1529
|
+
bottom: Math.max(acc.bottom, r.bottom)
|
|
1530
|
+
}));
|
|
1531
|
+
const layoutRows = (card, blocks) => {
|
|
1532
|
+
const elOf = (b) => b.editorId ? card.querySelector(`[data-veo-block-id="${b.editorId}"]`) : null;
|
|
1533
|
+
const cs = getComputedStyle(card);
|
|
1534
|
+
const padL = Number.parseFloat(cs.paddingLeft) || 0;
|
|
1535
|
+
const padR = Number.parseFloat(cs.paddingRight) || 0;
|
|
1536
|
+
const contentLeft = padL;
|
|
1537
|
+
const contentRight = card.clientWidth - padR;
|
|
1538
|
+
const rows = groupLayout(blocks).map((row) => {
|
|
1539
|
+
const columns = row.columns.map((col) => {
|
|
1540
|
+
const items = col.blocks.map(({ block }) => ({ block, el: elOf(block) })).filter(
|
|
1541
|
+
(x) => !!x.el && !!x.block.editorId
|
|
1542
|
+
);
|
|
1543
|
+
const blocksRect2 = union(items.map((x) => rectOf(x.el)));
|
|
1544
|
+
if (!blocksRect2) return null;
|
|
1545
|
+
const colEl = items[0]?.el.parentElement;
|
|
1546
|
+
const rect2 = colEl?.classList.contains("veo-col") ? rectOf(colEl) : blocksRect2;
|
|
1547
|
+
return { items, rect: rect2 };
|
|
1548
|
+
}).filter((c) => c !== null);
|
|
1549
|
+
const blocksRect = union(columns.map((c) => c.rect));
|
|
1550
|
+
if (!blocksRect) return null;
|
|
1551
|
+
const rowEl = columns[0]?.items[0]?.el.parentElement?.parentElement;
|
|
1552
|
+
const rect = rowEl?.classList.contains("veo-row") ? rectOf(rowEl) : { ...blocksRect, left: contentLeft, right: contentRight };
|
|
1553
|
+
const id = columns[0]?.items[0]?.block.editorId;
|
|
1554
|
+
return { id, row: row.row, columns, rect };
|
|
1555
|
+
}).filter((r) => r !== null);
|
|
1556
|
+
return { rows, content: { left: contentLeft, right: contentRight } };
|
|
1557
|
+
};
|
|
1558
|
+
const clearRowChrome = (card) => {
|
|
1559
|
+
card.querySelector(".veo-row-frame")?.remove();
|
|
1560
|
+
card.querySelector(".veo-row-toolbar")?.remove();
|
|
1561
|
+
};
|
|
1562
|
+
const renderRowChrome = (host, stepIndex) => {
|
|
1563
|
+
const card = previewCard(host);
|
|
1564
|
+
if (!card) return;
|
|
1565
|
+
clearRowChrome(card);
|
|
1566
|
+
resolveToolbarOverlaps(card);
|
|
1567
|
+
const { rows } = layoutRows(card, previewBlocks);
|
|
1568
|
+
const rowOfSelected = selectedBlockId ? rows.find(
|
|
1569
|
+
(r) => r.columns.some((c) => c.items.some((i) => i.block.editorId === selectedBlockId))
|
|
1570
|
+
) : void 0;
|
|
1571
|
+
const target = (selectedRowId ? rows.find((r) => r.id === selectedRowId) : void 0) ?? rowOfSelected ?? (hoverRowId ? rows.find((r) => r.id === hoverRowId) : void 0);
|
|
1572
|
+
if (!target) return;
|
|
1573
|
+
const doc = card.ownerDocument;
|
|
1574
|
+
const cs = getComputedStyle(card);
|
|
1575
|
+
const padT = Number.parseFloat(cs.paddingTop) || 0;
|
|
1576
|
+
const padB = Number.parseFloat(cs.paddingBottom) || 0;
|
|
1577
|
+
const PAD = 6;
|
|
1578
|
+
const fx = Math.max(0, target.rect.left - PAD);
|
|
1579
|
+
const fr = Math.min(card.clientWidth, target.rect.right + PAD);
|
|
1580
|
+
const fy = Math.max(Math.min(padT, target.rect.top), target.rect.top - PAD);
|
|
1581
|
+
const fb = Math.min(
|
|
1582
|
+
Math.max(card.clientHeight - padB, target.rect.bottom),
|
|
1583
|
+
target.rect.bottom + PAD
|
|
1584
|
+
);
|
|
1585
|
+
const frame = doc.createElement("div");
|
|
1586
|
+
frame.className = "veo-row-frame";
|
|
1587
|
+
frame.setAttribute("data-veo-builder-chrome", "");
|
|
1588
|
+
frame.style.left = `${fx}px`;
|
|
1589
|
+
frame.style.top = `${fy}px`;
|
|
1590
|
+
frame.style.width = `${Math.max(0, fr - fx)}px`;
|
|
1591
|
+
frame.style.height = `${Math.max(0, fb - fy)}px`;
|
|
1592
|
+
card.appendChild(frame);
|
|
1593
|
+
const bar = doc.createElement("div");
|
|
1594
|
+
bar.className = "veo-row-toolbar";
|
|
1595
|
+
bar.setAttribute("data-veo-builder-chrome", "");
|
|
1596
|
+
const blockId = target.id;
|
|
1597
|
+
const mk = (action, label, icon, text) => {
|
|
1598
|
+
const b = doc.createElement("button");
|
|
1599
|
+
b.type = "button";
|
|
1600
|
+
b.title = label;
|
|
1601
|
+
b.setAttribute("aria-label", label);
|
|
1602
|
+
b.className = `veo-row-toolbar-${action}`;
|
|
1603
|
+
b.innerHTML = icon;
|
|
1604
|
+
if (text) b.append(text);
|
|
1605
|
+
b.addEventListener("click", (e) => {
|
|
1606
|
+
e.preventDefault();
|
|
1607
|
+
e.stopPropagation();
|
|
1608
|
+
post({ type: "row-action", payload: { stepIndex, blockId, action } });
|
|
1609
|
+
});
|
|
1610
|
+
bar.appendChild(b);
|
|
1611
|
+
};
|
|
1612
|
+
mk("edit", "Editar fila", ICON.pencil, "Editar fila");
|
|
1613
|
+
mk("duplicate", "Duplicar fila", ICON.copy);
|
|
1614
|
+
mk("remove", "Eliminar fila", ICON.trash);
|
|
1615
|
+
card.appendChild(bar);
|
|
1616
|
+
bar.dataset.veoRight = String(Math.max(0, card.clientWidth - fr));
|
|
1617
|
+
bar.dataset.veoLeft = String(fx);
|
|
1618
|
+
bar.dataset.veoTopBelow = String(fb + 6);
|
|
1619
|
+
resolveToolbarOverlaps(card);
|
|
1620
|
+
};
|
|
1621
|
+
const renderCardChrome = (host, stepIndex) => {
|
|
1622
|
+
const card = previewCard(host);
|
|
1623
|
+
if (!card) return;
|
|
1624
|
+
card.querySelector(".veo-card-frame")?.remove();
|
|
1625
|
+
card.querySelector(".veo-card-toolbar")?.remove();
|
|
1626
|
+
if (!hoverCard) {
|
|
1627
|
+
resolveToolbarOverlaps(card);
|
|
1628
|
+
return;
|
|
1629
|
+
}
|
|
1630
|
+
const doc = card.ownerDocument;
|
|
1631
|
+
const frame = doc.createElement("div");
|
|
1632
|
+
frame.className = "veo-card-frame";
|
|
1633
|
+
frame.setAttribute("data-veo-builder-chrome", "");
|
|
1634
|
+
card.appendChild(frame);
|
|
1635
|
+
const bar = doc.createElement("div");
|
|
1636
|
+
bar.className = "veo-card-toolbar";
|
|
1637
|
+
bar.setAttribute("data-veo-builder-chrome", "");
|
|
1638
|
+
const mk = (action, label, active) => {
|
|
1639
|
+
const b = doc.createElement("button");
|
|
1640
|
+
b.type = "button";
|
|
1641
|
+
b.className = `veo-card-toolbar-${action}${active ? " is-active" : ""}`;
|
|
1642
|
+
b.setAttribute("aria-pressed", active ? "true" : "false");
|
|
1643
|
+
b.textContent = label;
|
|
1644
|
+
b.addEventListener("click", (e) => {
|
|
1645
|
+
e.preventDefault();
|
|
1646
|
+
e.stopPropagation();
|
|
1647
|
+
post({ type: "card-action", payload: { stepIndex, action } });
|
|
1648
|
+
});
|
|
1649
|
+
bar.appendChild(b);
|
|
1650
|
+
};
|
|
1651
|
+
mk("edit-container", "Editar contenedor", panelSection === "step");
|
|
1652
|
+
mk("edit-rows", "Editar filas", panelSection === "structure");
|
|
1653
|
+
card.appendChild(bar);
|
|
1654
|
+
bar.style.top = `${-Math.round((bar.offsetHeight || 34) / 2)}px`;
|
|
1655
|
+
resolveToolbarOverlaps(card);
|
|
1656
|
+
};
|
|
1657
|
+
const attachRowHover = (host, stepIndex) => {
|
|
1658
|
+
const onMove = (e) => {
|
|
1659
|
+
const card = previewCard(host);
|
|
1660
|
+
if (!card) return;
|
|
1661
|
+
const overCard = e.composedPath().some(
|
|
1662
|
+
(n) => n instanceof Element && (n.classList.contains("veo-card") || n.classList.contains("veo-card-toolbar"))
|
|
1663
|
+
);
|
|
1664
|
+
if (overCard !== hoverCard) {
|
|
1665
|
+
hoverCard = overCard;
|
|
1666
|
+
renderCardChrome(host, stepIndex);
|
|
1667
|
+
}
|
|
1668
|
+
if (e.composedPath().some((n) => n instanceof Element && n.classList.contains("veo-row-toolbar"))) {
|
|
1669
|
+
return;
|
|
1670
|
+
}
|
|
1671
|
+
const rect = card.getBoundingClientRect();
|
|
1672
|
+
const x = e.clientX - rect.left - card.clientLeft;
|
|
1673
|
+
const y = e.clientY - rect.top - card.clientTop;
|
|
1674
|
+
const bar = card.querySelector(".veo-row-toolbar");
|
|
1675
|
+
if (bar) {
|
|
1676
|
+
const AIR = 10;
|
|
1677
|
+
if (x >= bar.offsetLeft - AIR && x <= bar.offsetLeft + bar.offsetWidth + AIR && y >= bar.offsetTop - 14 && y <= bar.offsetTop + bar.offsetHeight + AIR) {
|
|
1678
|
+
return;
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1681
|
+
const TOL = 6;
|
|
1682
|
+
const hit = layoutRows(card, previewBlocks).rows.find(
|
|
1683
|
+
(r) => x >= r.rect.left - TOL && x <= r.rect.right + TOL && y >= r.rect.top - TOL && y <= r.rect.bottom + TOL
|
|
1684
|
+
);
|
|
1685
|
+
const next = hit?.id ?? null;
|
|
1686
|
+
if (next === hoverRowId) return;
|
|
1687
|
+
hoverRowId = next;
|
|
1688
|
+
renderRowChrome(host, stepIndex);
|
|
1689
|
+
};
|
|
1690
|
+
const onLeave = () => {
|
|
1691
|
+
if (hoverCard) {
|
|
1692
|
+
hoverCard = false;
|
|
1693
|
+
renderCardChrome(host, stepIndex);
|
|
1694
|
+
}
|
|
1695
|
+
if (hoverRowId === null) return;
|
|
1696
|
+
hoverRowId = null;
|
|
1697
|
+
renderRowChrome(host, stepIndex);
|
|
1698
|
+
};
|
|
1699
|
+
host.addEventListener("mousemove", onMove);
|
|
1700
|
+
host.addEventListener("mouseleave", onLeave);
|
|
1701
|
+
return () => {
|
|
1702
|
+
host.removeEventListener("mousemove", onMove);
|
|
1703
|
+
host.removeEventListener("mouseleave", onLeave);
|
|
1704
|
+
};
|
|
1705
|
+
};
|
|
1706
|
+
const renderGapZones = (host, stepIndex, blocks) => {
|
|
1707
|
+
const card = previewCard(host);
|
|
1708
|
+
if (!card) return;
|
|
1709
|
+
for (const z of card.querySelectorAll(".veo-gap")) z.remove();
|
|
1710
|
+
const doc = card.ownerDocument;
|
|
1711
|
+
const GAP = 18;
|
|
1712
|
+
const EDGE2 = 4;
|
|
1713
|
+
const zone = (kind, x, y, w, h, label, blockId, action) => {
|
|
1714
|
+
const z = doc.createElement("div");
|
|
1715
|
+
z.className = `veo-gap veo-gap--${kind}`;
|
|
1716
|
+
z.setAttribute("data-veo-builder-chrome", "");
|
|
1717
|
+
z.dataset.veoGapAction = action;
|
|
1718
|
+
z.style.left = `${x}px`;
|
|
1719
|
+
z.style.top = `${y}px`;
|
|
1720
|
+
z.style.width = `${Math.max(w, GAP)}px`;
|
|
1721
|
+
z.style.height = `${Math.max(h, GAP)}px`;
|
|
1722
|
+
const line = doc.createElement("i");
|
|
1723
|
+
const btn = doc.createElement("button");
|
|
1724
|
+
btn.type = "button";
|
|
1725
|
+
btn.title = label;
|
|
1726
|
+
btn.setAttribute("aria-label", label);
|
|
1727
|
+
btn.textContent = "+";
|
|
1728
|
+
btn.addEventListener("click", (e) => {
|
|
1729
|
+
e.preventDefault();
|
|
1730
|
+
e.stopPropagation();
|
|
1731
|
+
post({ type: "block-layout", payload: { stepIndex, blockId, action } });
|
|
1732
|
+
});
|
|
1733
|
+
z.append(line, btn);
|
|
1734
|
+
card.appendChild(z);
|
|
1735
|
+
};
|
|
1736
|
+
const { rows, content } = layoutRows(card, blocks);
|
|
1737
|
+
if (rows.length === 0) return;
|
|
1738
|
+
const cw = content.right - content.left;
|
|
1739
|
+
rows.forEach((row, k) => {
|
|
1740
|
+
const first = row.columns[0]?.items[0]?.block.editorId;
|
|
1741
|
+
if (k === 0) {
|
|
1742
|
+
zone(
|
|
1743
|
+
"h",
|
|
1744
|
+
content.left,
|
|
1745
|
+
row.rect.top - EDGE2 - GAP,
|
|
1746
|
+
cw,
|
|
1747
|
+
GAP,
|
|
1748
|
+
"Agregar fila",
|
|
1749
|
+
first,
|
|
1750
|
+
"row-before"
|
|
1751
|
+
);
|
|
1752
|
+
} else {
|
|
1753
|
+
const prev = rows[k - 1];
|
|
1754
|
+
const y = (prev.rect.bottom + row.rect.top) / 2 - GAP / 2;
|
|
1755
|
+
zone("h", content.left, y, cw, GAP, "Agregar fila", first, "row-before");
|
|
1756
|
+
}
|
|
1757
|
+
if (k === rows.length - 1) {
|
|
1758
|
+
zone(
|
|
1759
|
+
"h",
|
|
1760
|
+
content.left,
|
|
1761
|
+
row.rect.bottom + EDGE2,
|
|
1762
|
+
cw,
|
|
1763
|
+
GAP,
|
|
1764
|
+
"Agregar fila",
|
|
1765
|
+
first,
|
|
1766
|
+
"row-after"
|
|
1767
|
+
);
|
|
1768
|
+
}
|
|
1769
|
+
});
|
|
1770
|
+
for (const row of rows) {
|
|
1771
|
+
const rh = row.rect.bottom - row.rect.top;
|
|
1772
|
+
row.columns.forEach((col, j) => {
|
|
1773
|
+
const id = col.items[0]?.block.editorId;
|
|
1774
|
+
if (j === 0) {
|
|
1775
|
+
zone(
|
|
1776
|
+
"v",
|
|
1777
|
+
row.rect.left - EDGE2 - GAP,
|
|
1778
|
+
row.rect.top,
|
|
1779
|
+
GAP,
|
|
1780
|
+
rh,
|
|
1781
|
+
"Agregar columna",
|
|
1782
|
+
id,
|
|
1783
|
+
"col-before"
|
|
1784
|
+
);
|
|
1785
|
+
} else {
|
|
1786
|
+
const prev = row.columns[j - 1];
|
|
1787
|
+
const x = (prev.rect.right + col.rect.left) / 2 - GAP / 2;
|
|
1788
|
+
zone("v", x, row.rect.top, GAP, rh, "Agregar columna", id, "col-before");
|
|
1789
|
+
}
|
|
1790
|
+
if (j === row.columns.length - 1) {
|
|
1791
|
+
zone(
|
|
1792
|
+
"v",
|
|
1793
|
+
row.rect.right + EDGE2,
|
|
1794
|
+
row.rect.top,
|
|
1795
|
+
GAP,
|
|
1796
|
+
rh,
|
|
1797
|
+
"Agregar columna",
|
|
1798
|
+
id,
|
|
1799
|
+
"col-after"
|
|
1800
|
+
);
|
|
1801
|
+
}
|
|
1802
|
+
});
|
|
1803
|
+
}
|
|
1804
|
+
for (const row of rows) {
|
|
1805
|
+
for (const col of row.columns) {
|
|
1806
|
+
const w = col.rect.right - col.rect.left;
|
|
1807
|
+
col.items.forEach((it, i) => {
|
|
1808
|
+
const next = col.items[i + 1];
|
|
1809
|
+
if (next) {
|
|
1810
|
+
const a = rectOf(it.el);
|
|
1811
|
+
const b = rectOf(next.el);
|
|
1812
|
+
const y = (a.bottom + b.top) / 2 - GAP / 2;
|
|
1813
|
+
zone(
|
|
1814
|
+
"h",
|
|
1815
|
+
col.rect.left,
|
|
1816
|
+
y,
|
|
1817
|
+
w,
|
|
1818
|
+
GAP,
|
|
1819
|
+
"Agregar bloque",
|
|
1820
|
+
it.block.editorId,
|
|
1821
|
+
"stack-after"
|
|
1822
|
+
);
|
|
1823
|
+
} else if (row.columns.length > 1 && col.rect.bottom < row.rect.bottom - GAP) {
|
|
1824
|
+
zone(
|
|
1825
|
+
"h",
|
|
1826
|
+
col.rect.left,
|
|
1827
|
+
col.rect.bottom + EDGE2,
|
|
1828
|
+
w,
|
|
1829
|
+
GAP,
|
|
1830
|
+
"Agregar bloque",
|
|
1831
|
+
it.block.editorId,
|
|
1832
|
+
"stack-after"
|
|
1833
|
+
);
|
|
1834
|
+
}
|
|
1835
|
+
});
|
|
1836
|
+
}
|
|
1837
|
+
}
|
|
1838
|
+
};
|
|
1839
|
+
const attachCardClick = (host, stepIndex) => {
|
|
1840
|
+
let downAt = null;
|
|
1841
|
+
const onDown = (e) => {
|
|
1842
|
+
downAt = { x: e.clientX, y: e.clientY };
|
|
1843
|
+
};
|
|
1844
|
+
const onClick = (e) => {
|
|
1845
|
+
const path = e.composedPath();
|
|
1846
|
+
if (path.some(
|
|
1847
|
+
(n) => n instanceof Element && (n.classList.contains("veo-block-toolbar") || n.classList.contains("veo-row-toolbar") || n.classList.contains("veo-card-toolbar") || n.classList.contains("veo-gap"))
|
|
1848
|
+
)) {
|
|
1849
|
+
return;
|
|
1850
|
+
}
|
|
1851
|
+
const inCard = path.some((n) => n instanceof Element && n.classList.contains("veo-card"));
|
|
1852
|
+
if (!inCard) return;
|
|
1853
|
+
if (downAt && Math.hypot(e.clientX - downAt.x, e.clientY - downAt.y) > 4) return;
|
|
1854
|
+
const blockEl = path.find(
|
|
1855
|
+
(n) => n instanceof HTMLElement && !!n.dataset.veoBlockId
|
|
1856
|
+
);
|
|
1857
|
+
if (blockEl) {
|
|
1858
|
+
if (path.some((n) => n instanceof Element && n.matches("button, a"))) {
|
|
1859
|
+
e.preventDefault();
|
|
1860
|
+
e.stopPropagation();
|
|
1861
|
+
}
|
|
1862
|
+
selectedBlockId = blockEl.dataset.veoBlockId ?? null;
|
|
1863
|
+
applyBlockHighlight(host, stepIndex);
|
|
1864
|
+
if (selectedBlockId) {
|
|
1865
|
+
post({ type: "block-clicked", payload: { stepIndex, blockId: selectedBlockId } });
|
|
1866
|
+
}
|
|
1867
|
+
return;
|
|
1868
|
+
}
|
|
1869
|
+
const interactive = path.some(
|
|
1870
|
+
(n) => n instanceof Element && n.matches("button, a, input, textarea, select, label, [contenteditable]")
|
|
1871
|
+
);
|
|
1872
|
+
if (interactive) return;
|
|
1873
|
+
selectedBlockId = null;
|
|
1874
|
+
clearBlockHighlight(host);
|
|
1875
|
+
renderRowChrome(host, stepIndex);
|
|
1876
|
+
post({ type: "card-clicked", payload: { stepIndex } });
|
|
1877
|
+
};
|
|
1878
|
+
host.addEventListener("mousedown", onDown, true);
|
|
1879
|
+
host.addEventListener("click", onClick, true);
|
|
1880
|
+
return () => {
|
|
1881
|
+
host.removeEventListener("mousedown", onDown, true);
|
|
1882
|
+
host.removeEventListener("click", onClick, true);
|
|
1883
|
+
};
|
|
1884
|
+
};
|
|
1885
|
+
const attachRawBlock = (stepIndex, blockId) => {
|
|
1886
|
+
const nodes = Array.from(
|
|
1887
|
+
document.querySelectorAll(`[${RAW_BLOCK_ATTR}="${blockId}"]`)
|
|
1888
|
+
);
|
|
1889
|
+
if (nodes.length === 0) return null;
|
|
1890
|
+
const doc = document;
|
|
1891
|
+
const box = doc.createElement("div");
|
|
1892
|
+
box.setAttribute("data-veo-builder-chrome", "");
|
|
1893
|
+
box.style.cssText = "position:fixed;left:0;top:0;width:0;height:0;z-index:2147483646;";
|
|
1894
|
+
box.style.display = "none";
|
|
1895
|
+
const shadow = box.attachShadow({ mode: "open" });
|
|
1896
|
+
const style = doc.createElement("style");
|
|
1897
|
+
style.textContent = GUIDE_STYLES;
|
|
1898
|
+
shadow.appendChild(style);
|
|
1899
|
+
const frame = doc.createElement("div");
|
|
1900
|
+
frame.className = "veo-block-frame";
|
|
1901
|
+
frame.style.position = "fixed";
|
|
1902
|
+
const bar = doc.createElement("div");
|
|
1903
|
+
bar.className = "veo-block-toolbar";
|
|
1904
|
+
bar.style.position = "fixed";
|
|
1905
|
+
const mk = (action, label, icon, enabled = true) => {
|
|
1906
|
+
const b = doc.createElement("button");
|
|
1907
|
+
b.type = "button";
|
|
1908
|
+
b.title = label;
|
|
1909
|
+
b.setAttribute("aria-label", label);
|
|
1910
|
+
b.className = `veo-block-toolbar-${action}`;
|
|
1911
|
+
b.innerHTML = icon;
|
|
1912
|
+
b.disabled = !enabled;
|
|
1913
|
+
b.addEventListener("click", (e) => {
|
|
1914
|
+
e.preventDefault();
|
|
1915
|
+
e.stopPropagation();
|
|
1916
|
+
post({ type: "block-action", payload: { stepIndex, blockId, action } });
|
|
1917
|
+
});
|
|
1918
|
+
bar.appendChild(b);
|
|
1919
|
+
};
|
|
1920
|
+
mk("edit", "Editar", ICON.pencil);
|
|
1921
|
+
mk("duplicate", "Duplicar", ICON.copy, false);
|
|
1922
|
+
mk("remove", "Eliminar", ICON.trash);
|
|
1923
|
+
mk("move-left", "Mover a la izquierda", ICON_MOVE.left, false);
|
|
1924
|
+
mk("move-right", "Mover a la derecha", ICON_MOVE.right, false);
|
|
1925
|
+
frame.style.display = "none";
|
|
1926
|
+
bar.style.display = "none";
|
|
1927
|
+
const GAP = 18;
|
|
1928
|
+
const EDGE2 = 4;
|
|
1929
|
+
const gap = (kind, label, action) => {
|
|
1930
|
+
const z = doc.createElement("div");
|
|
1931
|
+
z.className = `veo-gap veo-gap--${kind}`;
|
|
1932
|
+
z.style.position = "fixed";
|
|
1933
|
+
z.dataset.veoGapAction = action;
|
|
1934
|
+
const line = doc.createElement("i");
|
|
1935
|
+
const btn = doc.createElement("button");
|
|
1936
|
+
btn.type = "button";
|
|
1937
|
+
btn.title = label;
|
|
1938
|
+
btn.setAttribute("aria-label", label);
|
|
1939
|
+
btn.textContent = "+";
|
|
1940
|
+
btn.addEventListener("click", (e) => {
|
|
1941
|
+
e.preventDefault();
|
|
1942
|
+
e.stopPropagation();
|
|
1943
|
+
post({ type: "block-layout", payload: { stepIndex, blockId, action } });
|
|
1944
|
+
});
|
|
1945
|
+
z.append(line, btn);
|
|
1946
|
+
return z;
|
|
1947
|
+
};
|
|
1948
|
+
const gaps = {
|
|
1949
|
+
top: gap("h", "Agregar fila", "row-before"),
|
|
1950
|
+
bottom: gap("h", "Agregar fila", "row-after"),
|
|
1951
|
+
left: gap("v", "Agregar columna", "col-before"),
|
|
1952
|
+
right: gap("v", "Agregar columna", "col-after")
|
|
1953
|
+
};
|
|
1954
|
+
shadow.append(frame, bar, gaps.top, gaps.bottom, gaps.left, gaps.right);
|
|
1955
|
+
doc.body.appendChild(box);
|
|
1956
|
+
box.style.display = "";
|
|
1957
|
+
let visible = false;
|
|
1958
|
+
const place = (el2, x, y, w, h) => {
|
|
1959
|
+
el2.style.left = `${x}px`;
|
|
1960
|
+
el2.style.top = `${y}px`;
|
|
1961
|
+
el2.style.width = `${w}px`;
|
|
1962
|
+
el2.style.height = `${h}px`;
|
|
1963
|
+
};
|
|
1964
|
+
const reposition = () => {
|
|
1965
|
+
const live = nodes.filter((n) => n.isConnected);
|
|
1966
|
+
if (live.length === 0) return;
|
|
1967
|
+
let l = Number.POSITIVE_INFINITY;
|
|
1968
|
+
let t = Number.POSITIVE_INFINITY;
|
|
1969
|
+
let r = Number.NEGATIVE_INFINITY;
|
|
1970
|
+
let b = Number.NEGATIVE_INFINITY;
|
|
1971
|
+
for (const n of live) {
|
|
1972
|
+
const rc = n.getBoundingClientRect();
|
|
1973
|
+
if (rc.width === 0 && rc.height === 0) continue;
|
|
1974
|
+
l = Math.min(l, rc.left);
|
|
1975
|
+
t = Math.min(t, rc.top);
|
|
1976
|
+
r = Math.max(r, rc.right);
|
|
1977
|
+
b = Math.max(b, rc.bottom);
|
|
1978
|
+
}
|
|
1979
|
+
if (!Number.isFinite(l)) return;
|
|
1980
|
+
place(gaps.top, l, t - EDGE2 - GAP, r - l, GAP);
|
|
1981
|
+
place(gaps.bottom, l, b + EDGE2, r - l, GAP);
|
|
1982
|
+
place(gaps.left, l - EDGE2 - GAP, t, GAP, b - t);
|
|
1983
|
+
place(gaps.right, r + EDGE2, t, GAP, b - t);
|
|
1984
|
+
if (!visible) return;
|
|
1985
|
+
place(frame, l, t, r - l, b - t);
|
|
1986
|
+
const bh = bar.offsetHeight || TOOLBAR_H;
|
|
1987
|
+
const bw = bar.offsetWidth;
|
|
1988
|
+
bar.style.left = `${Math.max(0, r - bw)}px`;
|
|
1989
|
+
bar.style.top = `${Math.max(0, t - bh - 6)}px`;
|
|
1990
|
+
};
|
|
1991
|
+
const select = (id) => {
|
|
1992
|
+
visible = id === blockId;
|
|
1993
|
+
frame.style.display = visible ? "" : "none";
|
|
1994
|
+
bar.style.display = visible ? "" : "none";
|
|
1995
|
+
reposition();
|
|
1996
|
+
};
|
|
1997
|
+
reposition();
|
|
1998
|
+
const onClick = (e) => {
|
|
1999
|
+
const path = e.composedPath();
|
|
2000
|
+
if (!nodes.some((n) => path.includes(n))) return;
|
|
2001
|
+
if (path.some((n) => n instanceof Element && n.matches("button, a"))) {
|
|
2002
|
+
e.preventDefault();
|
|
2003
|
+
e.stopPropagation();
|
|
2004
|
+
}
|
|
2005
|
+
selectedBlockId = blockId;
|
|
2006
|
+
select(blockId);
|
|
2007
|
+
post({ type: "block-clicked", payload: { stepIndex, blockId } });
|
|
2008
|
+
};
|
|
2009
|
+
doc.addEventListener("click", onClick, true);
|
|
2010
|
+
window.addEventListener("scroll", reposition, true);
|
|
2011
|
+
window.addEventListener("resize", reposition);
|
|
2012
|
+
return {
|
|
2013
|
+
select,
|
|
2014
|
+
detach: () => {
|
|
2015
|
+
doc.removeEventListener("click", onClick, true);
|
|
2016
|
+
window.removeEventListener("scroll", reposition, true);
|
|
2017
|
+
window.removeEventListener("resize", reposition);
|
|
2018
|
+
box.remove();
|
|
2019
|
+
}
|
|
2020
|
+
};
|
|
2021
|
+
};
|
|
1218
2022
|
const applyPreviewGated = (cmd) => {
|
|
1219
2023
|
const showNow = !cmd.honorTrigger;
|
|
1220
2024
|
if (showNow) {
|
|
@@ -1234,7 +2038,7 @@ function initBuilderMode() {
|
|
|
1234
2038
|
return;
|
|
1235
2039
|
}
|
|
1236
2040
|
const devices = cmd.guide.activationRules?.devices;
|
|
1237
|
-
if (!showNow &&
|
|
2041
|
+
if (!showNow && previewMode && devices && !isDeviceAllowed(devices)) {
|
|
1238
2042
|
cancelPreviewDelay();
|
|
1239
2043
|
withholdPreview();
|
|
1240
2044
|
postPreviewStatus({ state: "device-mismatch", devices });
|
|
@@ -1286,15 +2090,16 @@ function initBuilderMode() {
|
|
|
1286
2090
|
postPreviewStatus({ state: "waiting-delay", delayMs });
|
|
1287
2091
|
};
|
|
1288
2092
|
const applyPreview = (cmd) => {
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
2093
|
+
if (cmd.editable && !previewMode && tryPatchPreview(cmd)) {
|
|
2094
|
+
previewStepIndex = cmd.guide.startStepIndex ?? 0;
|
|
2095
|
+
return;
|
|
2096
|
+
}
|
|
2097
|
+
detachPreviewTools();
|
|
1293
2098
|
previewStepIndex = cmd.guide.startStepIndex ?? 0;
|
|
1294
2099
|
const rules = cmd.guide.activationRules;
|
|
1295
2100
|
const trig = rules?.trigger;
|
|
1296
2101
|
const sel = rules?.selector?.trim();
|
|
1297
|
-
const gate = cmd.honorTrigger && !previewFired &&
|
|
2102
|
+
const gate = cmd.honorTrigger && !previewFired && previewMode;
|
|
1298
2103
|
const waitsForTarget = (trig === "on_click" || trig === "on_hover") && (!isAutomaticActivation(rules) || previewDismissed);
|
|
1299
2104
|
if (gate && waitsForTarget && sel) {
|
|
1300
2105
|
cancelPreviewDelay();
|
|
@@ -1311,13 +2116,13 @@ function initBuilderMode() {
|
|
|
1311
2116
|
}
|
|
1312
2117
|
disarmPreviewTrigger();
|
|
1313
2118
|
cancelPreviewDelay();
|
|
2119
|
+
const fetchProgress = previewProgressFetcher();
|
|
1314
2120
|
const handle = previewGuide({
|
|
1315
2121
|
...cmd.guide,
|
|
2122
|
+
...fetchProgress ? { fetchProgress } : {},
|
|
1316
2123
|
onClosed: () => {
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
dropTarget?.detach();
|
|
1320
|
-
dropTarget = null;
|
|
2124
|
+
detachPreviewTools();
|
|
2125
|
+
shownPreview = null;
|
|
1321
2126
|
previewFired = false;
|
|
1322
2127
|
previewDismissed = true;
|
|
1323
2128
|
if (previewMode) {
|
|
@@ -1325,9 +2130,7 @@ function initBuilderMode() {
|
|
|
1325
2130
|
const t = r?.trigger;
|
|
1326
2131
|
const selector = r?.selector?.trim();
|
|
1327
2132
|
if ((t === "on_click" || t === "on_hover") && selector) armPreviewTrigger(selector, t);
|
|
1328
|
-
return;
|
|
1329
2133
|
}
|
|
1330
|
-
if (lastPreview) applyPreviewGated(lastPreview);
|
|
1331
2134
|
}
|
|
1332
2135
|
});
|
|
1333
2136
|
if (cmd.honorTrigger) postPreviewStatus({ state: "shown" });
|
|
@@ -1335,7 +2138,23 @@ function initBuilderMode() {
|
|
|
1335
2138
|
void handle.ready.then((result) => {
|
|
1336
2139
|
if (!result.rendered) return;
|
|
1337
2140
|
const host = handle.host();
|
|
1338
|
-
if (!host)
|
|
2141
|
+
if (!host) {
|
|
2142
|
+
const idx = cmd.guide.startStepIndex ?? 0;
|
|
2143
|
+
const only = cmd.guide.guideSteps[idx]?.blocks?.[0];
|
|
2144
|
+
if (only?.type === "code" && only.editorId) {
|
|
2145
|
+
rawBlock = attachRawBlock(idx, only.editorId);
|
|
2146
|
+
rawBlock?.select(selectedBlockId);
|
|
2147
|
+
}
|
|
2148
|
+
return;
|
|
2149
|
+
}
|
|
2150
|
+
host.classList.add("veo-no-anim");
|
|
2151
|
+
shownPreview = cmd;
|
|
2152
|
+
cardClick = attachCardClick(host, cmd.guide.startStepIndex ?? 0);
|
|
2153
|
+
const stepBlocks = cmd.guide.guideSteps[cmd.guide.startStepIndex ?? 0]?.blocks ?? [];
|
|
2154
|
+
previewBlocks = stepBlocks;
|
|
2155
|
+
applyBlockHighlight(host, cmd.guide.startStepIndex ?? 0);
|
|
2156
|
+
renderGapZones(host, cmd.guide.startStepIndex ?? 0, stepBlocks);
|
|
2157
|
+
rowHover = attachRowHover(host, cmd.guide.startStepIndex ?? 0);
|
|
1339
2158
|
manipulator = attachDesignManipulator({
|
|
1340
2159
|
host,
|
|
1341
2160
|
guideType: cmd.guide.guideType,
|
|
@@ -1403,13 +2222,21 @@ function initBuilderMode() {
|
|
|
1403
2222
|
break;
|
|
1404
2223
|
case "editor-state":
|
|
1405
2224
|
chrome?.setState(cmd.state);
|
|
2225
|
+
if (panelSection !== cmd.state.section) {
|
|
2226
|
+
panelSection = cmd.state.section;
|
|
2227
|
+
const h = document.querySelector("[data-veo-guide]");
|
|
2228
|
+
if (h && hoverCard && !previewMode) renderCardChrome(h, previewStepIndex);
|
|
2229
|
+
}
|
|
1406
2230
|
panel?.setTitle(
|
|
1407
|
-
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.steps[cmd.state.activeStep]?.label ?? "Paso"
|
|
2231
|
+
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"
|
|
1408
2232
|
);
|
|
1409
2233
|
break;
|
|
1410
2234
|
case "panel-visibility":
|
|
1411
2235
|
panel?.setVisible(cmd.visible);
|
|
1412
2236
|
break;
|
|
2237
|
+
case "panel-size":
|
|
2238
|
+
panel?.setSize(cmd.size);
|
|
2239
|
+
break;
|
|
1413
2240
|
case "start-picker": {
|
|
1414
2241
|
picker?.stop();
|
|
1415
2242
|
const panelWasShown = panel?.isVisible() ?? false;
|
|
@@ -1417,10 +2244,7 @@ function initBuilderMode() {
|
|
|
1417
2244
|
chrome?.setHidden(true);
|
|
1418
2245
|
const previewToRestore = lastPreview;
|
|
1419
2246
|
if (previewToRestore) {
|
|
1420
|
-
|
|
1421
|
-
manipulator = null;
|
|
1422
|
-
dropTarget?.detach();
|
|
1423
|
-
dropTarget = null;
|
|
2247
|
+
detachPreviewTools();
|
|
1424
2248
|
closeGuidePreview();
|
|
1425
2249
|
}
|
|
1426
2250
|
const restorePanel = () => {
|
|
@@ -1459,11 +2283,21 @@ function initBuilderMode() {
|
|
|
1459
2283
|
case "block-drag":
|
|
1460
2284
|
handleBlockDrag(cmd);
|
|
1461
2285
|
break;
|
|
2286
|
+
case "select-block": {
|
|
2287
|
+
selectedBlockId = cmd.blockId;
|
|
2288
|
+
const h = document.querySelector("[data-veo-guide]");
|
|
2289
|
+
if (h && !previewMode) applyBlockHighlight(h, previewStepIndex);
|
|
2290
|
+
if (!previewMode) rawBlock?.select(cmd.blockId);
|
|
2291
|
+
break;
|
|
2292
|
+
}
|
|
2293
|
+
case "select-row": {
|
|
2294
|
+
selectedRowId = cmd.blockId;
|
|
2295
|
+
const h = document.querySelector("[data-veo-guide]");
|
|
2296
|
+
if (h && !previewMode) renderRowChrome(h, previewStepIndex);
|
|
2297
|
+
break;
|
|
2298
|
+
}
|
|
1462
2299
|
case "close-preview":
|
|
1463
|
-
|
|
1464
|
-
manipulator = null;
|
|
1465
|
-
dropTarget?.detach();
|
|
1466
|
-
dropTarget = null;
|
|
2300
|
+
detachPreviewTools();
|
|
1467
2301
|
hideDragGhost();
|
|
1468
2302
|
pendingPreview = null;
|
|
1469
2303
|
lastPreview = null;
|
|
@@ -1516,10 +2350,7 @@ function initBuilderMode() {
|
|
|
1516
2350
|
removeNavWatcher();
|
|
1517
2351
|
picker?.stop();
|
|
1518
2352
|
picker = null;
|
|
1519
|
-
|
|
1520
|
-
manipulator = null;
|
|
1521
|
-
dropTarget?.detach();
|
|
1522
|
-
dropTarget = null;
|
|
2353
|
+
detachPreviewTools();
|
|
1523
2354
|
hideDragGhost();
|
|
1524
2355
|
pendingPreview = null;
|
|
1525
2356
|
disarmPreviewTrigger();
|
|
@@ -1547,6 +2378,8 @@ function initBuilderMode() {
|
|
|
1547
2378
|
case "preview":
|
|
1548
2379
|
if (previewMode) return;
|
|
1549
2380
|
previewMode = true;
|
|
2381
|
+
previewFired = false;
|
|
2382
|
+
previewDismissed = false;
|
|
1550
2383
|
panelWasVisible = panel?.isVisible() ?? true;
|
|
1551
2384
|
panel?.setVisible(false);
|
|
1552
2385
|
chrome?.setPreview(true);
|
|
@@ -1555,6 +2388,8 @@ function initBuilderMode() {
|
|
|
1555
2388
|
case "exit-preview":
|
|
1556
2389
|
if (!previewMode) return;
|
|
1557
2390
|
previewMode = false;
|
|
2391
|
+
disarmPreviewTrigger();
|
|
2392
|
+
cancelPreviewDelay();
|
|
1558
2393
|
chrome?.setPreview(false);
|
|
1559
2394
|
panel?.setVisible(panelWasVisible);
|
|
1560
2395
|
if (lastPreview) applyPreviewGated(lastPreview);
|
|
@@ -1636,6 +2471,25 @@ function resolveDashboardOrigin(originHint) {
|
|
|
1636
2471
|
}
|
|
1637
2472
|
return null;
|
|
1638
2473
|
}
|
|
2474
|
+
function previewProgressFetcher() {
|
|
2475
|
+
const cfg = window.__veoBuilder;
|
|
2476
|
+
if (!cfg?.apiKey || !cfg?.apiUrl) return void 0;
|
|
2477
|
+
const apiUrl = cfg.apiUrl.replace(/\/+$/, "");
|
|
2478
|
+
const apiKey = cfg.apiKey;
|
|
2479
|
+
return async (guideIds) => {
|
|
2480
|
+
const params = new URLSearchParams({
|
|
2481
|
+
endUserId: "veo_preview",
|
|
2482
|
+
guideIds: guideIds.join(","),
|
|
2483
|
+
includeUnpublished: "1"
|
|
2484
|
+
});
|
|
2485
|
+
const res = await fetch(`${apiUrl}/v1/guides/progress?${params}`, {
|
|
2486
|
+
headers: { "X-Api-Key": apiKey }
|
|
2487
|
+
});
|
|
2488
|
+
if (!res.ok) return [];
|
|
2489
|
+
const data = await res.json();
|
|
2490
|
+
return data.items ?? [];
|
|
2491
|
+
};
|
|
2492
|
+
}
|
|
1639
2493
|
|
|
1640
2494
|
// src/plugins/builder/builder-session.ts
|
|
1641
2495
|
var DEFAULT_FEATURES = "popup,width=1280,height=860";
|
|
@@ -1757,5 +2611,5 @@ function noopSession() {
|
|
|
1757
2611
|
}
|
|
1758
2612
|
|
|
1759
2613
|
export { VEO_BLOCK_MIME, attachBlockDropTarget, attachDesignManipulator, createBuilderSession, initBuilderMode, startElementPicker, stopElementPicker };
|
|
1760
|
-
//# sourceMappingURL=chunk-
|
|
1761
|
-
//# sourceMappingURL=chunk-
|
|
2614
|
+
//# sourceMappingURL=chunk-N4VFMZFA.mjs.map
|
|
2615
|
+
//# sourceMappingURL=chunk-N4VFMZFA.mjs.map
|