veo-sdk 0.5.33 → 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-MUTQMYAH.mjs.map → builder-3QPHB2VJ.mjs.map} +1 -1
- package/dist/builder.cjs +2470 -577
- 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-FZ72JUAR.mjs → chunk-GMXQMZ4X.mjs} +123 -27
- package/dist/chunk-GMXQMZ4X.mjs.map +1 -0
- package/dist/{chunk-3ZOKCQ54.mjs → chunk-N4VFMZFA.mjs} +917 -44
- package/dist/chunk-N4VFMZFA.mjs.map +1 -0
- package/dist/{chunk-M6PB5UMW.mjs → chunk-O6USA4TU.mjs} +1133 -99
- package/dist/chunk-O6USA4TU.mjs.map +1 -0
- package/dist/{guide-preview-C73rKO0u.d.cts → guide-preview-DylsEhrg.d.cts} +109 -6
- package/dist/{guide-preview-C73rKO0u.d.ts → guide-preview-DylsEhrg.d.ts} +109 -6
- package/dist/index.cjs +2213 -164
- 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-MUTQMYAH.mjs +0 -5
- package/dist/chunk-3ZOKCQ54.mjs.map +0 -1
- package/dist/chunk-FZ72JUAR.mjs.map +0 -1
- package/dist/chunk-M6PB5UMW.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;
|
|
@@ -1196,6 +1271,7 @@ function initBuilderMode() {
|
|
|
1196
1271
|
let previewTrigger = null;
|
|
1197
1272
|
let previewFired = false;
|
|
1198
1273
|
let previewDelay = null;
|
|
1274
|
+
let previewDismissed = false;
|
|
1199
1275
|
let panelWasVisible = true;
|
|
1200
1276
|
const getTarget = () => panel ? panel.target() : staticTarget;
|
|
1201
1277
|
const post = (event) => {
|
|
@@ -1207,15 +1283,751 @@ function initBuilderMode() {
|
|
|
1207
1283
|
};
|
|
1208
1284
|
const previewMatchesPage = (cmd) => stepMatchesPage(previewStep(cmd)?.pageLocation, window.location.href);
|
|
1209
1285
|
const postPreviewStatus = (payload) => post({ type: "preview-status", payload });
|
|
1210
|
-
const
|
|
1286
|
+
const detachPreviewTools = () => {
|
|
1211
1287
|
manipulator?.detach();
|
|
1212
1288
|
manipulator = null;
|
|
1213
1289
|
dropTarget?.detach();
|
|
1214
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;
|
|
1215
1304
|
closeGuidePreview();
|
|
1216
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
|
+
};
|
|
1217
2022
|
const applyPreviewGated = (cmd) => {
|
|
1218
|
-
|
|
2023
|
+
const showNow = !cmd.honorTrigger;
|
|
2024
|
+
if (showNow) {
|
|
2025
|
+
disarmPreviewTrigger();
|
|
2026
|
+
cancelPreviewDelay();
|
|
2027
|
+
previewFired = true;
|
|
2028
|
+
previewDismissed = false;
|
|
2029
|
+
}
|
|
2030
|
+
lastPreview = showNow ? { ...cmd, honorTrigger: true } : cmd;
|
|
1219
2031
|
if (!previewMatchesPage(cmd)) {
|
|
1220
2032
|
cancelPreviewDelay();
|
|
1221
2033
|
withholdPreview();
|
|
@@ -1226,13 +2038,13 @@ function initBuilderMode() {
|
|
|
1226
2038
|
return;
|
|
1227
2039
|
}
|
|
1228
2040
|
const devices = cmd.guide.activationRules?.devices;
|
|
1229
|
-
if (
|
|
2041
|
+
if (!showNow && previewMode && devices && !isDeviceAllowed(devices)) {
|
|
1230
2042
|
cancelPreviewDelay();
|
|
1231
2043
|
withholdPreview();
|
|
1232
2044
|
postPreviewStatus({ state: "device-mismatch", devices });
|
|
1233
2045
|
return;
|
|
1234
2046
|
}
|
|
1235
|
-
applyPreview(
|
|
2047
|
+
applyPreview(lastPreview);
|
|
1236
2048
|
};
|
|
1237
2049
|
const disarmPreviewTrigger = () => {
|
|
1238
2050
|
previewTrigger?.();
|
|
@@ -1257,6 +2069,7 @@ function initBuilderMode() {
|
|
|
1257
2069
|
}
|
|
1258
2070
|
disarmPreviewTrigger();
|
|
1259
2071
|
previewFired = true;
|
|
2072
|
+
previewDismissed = false;
|
|
1260
2073
|
if (lastPreview) applyPreviewGated(lastPreview);
|
|
1261
2074
|
};
|
|
1262
2075
|
document.addEventListener("click", onFire, true);
|
|
@@ -1277,22 +2090,24 @@ function initBuilderMode() {
|
|
|
1277
2090
|
postPreviewStatus({ state: "waiting-delay", delayMs });
|
|
1278
2091
|
};
|
|
1279
2092
|
const applyPreview = (cmd) => {
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
2093
|
+
if (cmd.editable && !previewMode && tryPatchPreview(cmd)) {
|
|
2094
|
+
previewStepIndex = cmd.guide.startStepIndex ?? 0;
|
|
2095
|
+
return;
|
|
2096
|
+
}
|
|
2097
|
+
detachPreviewTools();
|
|
1284
2098
|
previewStepIndex = cmd.guide.startStepIndex ?? 0;
|
|
1285
2099
|
const rules = cmd.guide.activationRules;
|
|
1286
2100
|
const trig = rules?.trigger;
|
|
1287
2101
|
const sel = rules?.selector?.trim();
|
|
1288
|
-
const gate = cmd.honorTrigger && !previewFired &&
|
|
1289
|
-
|
|
2102
|
+
const gate = cmd.honorTrigger && !previewFired && previewMode;
|
|
2103
|
+
const waitsForTarget = (trig === "on_click" || trig === "on_hover") && (!isAutomaticActivation(rules) || previewDismissed);
|
|
2104
|
+
if (gate && waitsForTarget && sel) {
|
|
1290
2105
|
cancelPreviewDelay();
|
|
1291
2106
|
closeGuidePreview();
|
|
1292
2107
|
armPreviewTrigger(sel, trig);
|
|
1293
2108
|
return;
|
|
1294
2109
|
}
|
|
1295
|
-
const delayMs =
|
|
2110
|
+
const delayMs = activationDelayMs(rules);
|
|
1296
2111
|
if (gate && delayMs > 0) {
|
|
1297
2112
|
disarmPreviewTrigger();
|
|
1298
2113
|
closeGuidePreview();
|
|
@@ -1301,15 +2116,21 @@ function initBuilderMode() {
|
|
|
1301
2116
|
}
|
|
1302
2117
|
disarmPreviewTrigger();
|
|
1303
2118
|
cancelPreviewDelay();
|
|
2119
|
+
const fetchProgress = previewProgressFetcher();
|
|
1304
2120
|
const handle = previewGuide({
|
|
1305
2121
|
...cmd.guide,
|
|
2122
|
+
...fetchProgress ? { fetchProgress } : {},
|
|
1306
2123
|
onClosed: () => {
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
dropTarget?.detach();
|
|
1310
|
-
dropTarget = null;
|
|
2124
|
+
detachPreviewTools();
|
|
2125
|
+
shownPreview = null;
|
|
1311
2126
|
previewFired = false;
|
|
1312
|
-
|
|
2127
|
+
previewDismissed = true;
|
|
2128
|
+
if (previewMode) {
|
|
2129
|
+
const r = lastPreview?.guide.activationRules;
|
|
2130
|
+
const t = r?.trigger;
|
|
2131
|
+
const selector = r?.selector?.trim();
|
|
2132
|
+
if ((t === "on_click" || t === "on_hover") && selector) armPreviewTrigger(selector, t);
|
|
2133
|
+
}
|
|
1313
2134
|
}
|
|
1314
2135
|
});
|
|
1315
2136
|
if (cmd.honorTrigger) postPreviewStatus({ state: "shown" });
|
|
@@ -1317,7 +2138,23 @@ function initBuilderMode() {
|
|
|
1317
2138
|
void handle.ready.then((result) => {
|
|
1318
2139
|
if (!result.rendered) return;
|
|
1319
2140
|
const host = handle.host();
|
|
1320
|
-
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);
|
|
1321
2158
|
manipulator = attachDesignManipulator({
|
|
1322
2159
|
host,
|
|
1323
2160
|
guideType: cmd.guide.guideType,
|
|
@@ -1385,13 +2222,21 @@ function initBuilderMode() {
|
|
|
1385
2222
|
break;
|
|
1386
2223
|
case "editor-state":
|
|
1387
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
|
+
}
|
|
1388
2230
|
panel?.setTitle(
|
|
1389
|
-
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"
|
|
1390
2232
|
);
|
|
1391
2233
|
break;
|
|
1392
2234
|
case "panel-visibility":
|
|
1393
2235
|
panel?.setVisible(cmd.visible);
|
|
1394
2236
|
break;
|
|
2237
|
+
case "panel-size":
|
|
2238
|
+
panel?.setSize(cmd.size);
|
|
2239
|
+
break;
|
|
1395
2240
|
case "start-picker": {
|
|
1396
2241
|
picker?.stop();
|
|
1397
2242
|
const panelWasShown = panel?.isVisible() ?? false;
|
|
@@ -1399,10 +2244,7 @@ function initBuilderMode() {
|
|
|
1399
2244
|
chrome?.setHidden(true);
|
|
1400
2245
|
const previewToRestore = lastPreview;
|
|
1401
2246
|
if (previewToRestore) {
|
|
1402
|
-
|
|
1403
|
-
manipulator = null;
|
|
1404
|
-
dropTarget?.detach();
|
|
1405
|
-
dropTarget = null;
|
|
2247
|
+
detachPreviewTools();
|
|
1406
2248
|
closeGuidePreview();
|
|
1407
2249
|
}
|
|
1408
2250
|
const restorePanel = () => {
|
|
@@ -1441,17 +2283,28 @@ function initBuilderMode() {
|
|
|
1441
2283
|
case "block-drag":
|
|
1442
2284
|
handleBlockDrag(cmd);
|
|
1443
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
|
+
}
|
|
1444
2299
|
case "close-preview":
|
|
1445
|
-
|
|
1446
|
-
manipulator = null;
|
|
1447
|
-
dropTarget?.detach();
|
|
1448
|
-
dropTarget = null;
|
|
2300
|
+
detachPreviewTools();
|
|
1449
2301
|
hideDragGhost();
|
|
1450
2302
|
pendingPreview = null;
|
|
1451
2303
|
lastPreview = null;
|
|
1452
2304
|
disarmPreviewTrigger();
|
|
1453
2305
|
cancelPreviewDelay();
|
|
1454
2306
|
previewFired = false;
|
|
2307
|
+
previewDismissed = false;
|
|
1455
2308
|
closeGuidePreview();
|
|
1456
2309
|
break;
|
|
1457
2310
|
case "teardown":
|
|
@@ -1497,10 +2350,7 @@ function initBuilderMode() {
|
|
|
1497
2350
|
removeNavWatcher();
|
|
1498
2351
|
picker?.stop();
|
|
1499
2352
|
picker = null;
|
|
1500
|
-
|
|
1501
|
-
manipulator = null;
|
|
1502
|
-
dropTarget?.detach();
|
|
1503
|
-
dropTarget = null;
|
|
2353
|
+
detachPreviewTools();
|
|
1504
2354
|
hideDragGhost();
|
|
1505
2355
|
pendingPreview = null;
|
|
1506
2356
|
disarmPreviewTrigger();
|
|
@@ -1528,6 +2378,8 @@ function initBuilderMode() {
|
|
|
1528
2378
|
case "preview":
|
|
1529
2379
|
if (previewMode) return;
|
|
1530
2380
|
previewMode = true;
|
|
2381
|
+
previewFired = false;
|
|
2382
|
+
previewDismissed = false;
|
|
1531
2383
|
panelWasVisible = panel?.isVisible() ?? true;
|
|
1532
2384
|
panel?.setVisible(false);
|
|
1533
2385
|
chrome?.setPreview(true);
|
|
@@ -1536,6 +2388,8 @@ function initBuilderMode() {
|
|
|
1536
2388
|
case "exit-preview":
|
|
1537
2389
|
if (!previewMode) return;
|
|
1538
2390
|
previewMode = false;
|
|
2391
|
+
disarmPreviewTrigger();
|
|
2392
|
+
cancelPreviewDelay();
|
|
1539
2393
|
chrome?.setPreview(false);
|
|
1540
2394
|
panel?.setVisible(panelWasVisible);
|
|
1541
2395
|
if (lastPreview) applyPreviewGated(lastPreview);
|
|
@@ -1617,6 +2471,25 @@ function resolveDashboardOrigin(originHint) {
|
|
|
1617
2471
|
}
|
|
1618
2472
|
return null;
|
|
1619
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
|
+
}
|
|
1620
2493
|
|
|
1621
2494
|
// src/plugins/builder/builder-session.ts
|
|
1622
2495
|
var DEFAULT_FEATURES = "popup,width=1280,height=860";
|
|
@@ -1738,5 +2611,5 @@ function noopSession() {
|
|
|
1738
2611
|
}
|
|
1739
2612
|
|
|
1740
2613
|
export { VEO_BLOCK_MIME, attachBlockDropTarget, attachDesignManipulator, createBuilderSession, initBuilderMode, startElementPicker, stopElementPicker };
|
|
1741
|
-
//# sourceMappingURL=chunk-
|
|
1742
|
-
//# sourceMappingURL=chunk-
|
|
2614
|
+
//# sourceMappingURL=chunk-N4VFMZFA.mjs.map
|
|
2615
|
+
//# sourceMappingURL=chunk-N4VFMZFA.mjs.map
|