veo-sdk 0.5.32 → 0.5.34
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-ZKWVTSTP.mjs +5 -0
- package/dist/{builder-MNYSDJFT.mjs.map → builder-ZKWVTSTP.mjs.map} +1 -1
- package/dist/builder.cjs +1035 -164
- package/dist/builder.cjs.map +1 -1
- package/dist/builder.d.cts +93 -3
- package/dist/builder.d.ts +93 -3
- package/dist/builder.mjs +4 -4
- package/dist/{chunk-JPANNXIK.mjs → chunk-HAAT6XVN.mjs} +213 -20
- package/dist/chunk-HAAT6XVN.mjs.map +1 -0
- package/dist/{chunk-AFU5ZG6Z.mjs → chunk-IZXJA55N.mjs} +714 -74
- package/dist/chunk-IZXJA55N.mjs.map +1 -0
- package/dist/{chunk-X27GD7IT.mjs → chunk-W4R4XCWL.mjs} +247 -16
- package/dist/chunk-W4R4XCWL.mjs.map +1 -0
- package/dist/{guide-preview-XUnTmzUO.d.cts → guide-preview-DbEZdGBV.d.cts} +43 -1
- package/dist/{guide-preview-XUnTmzUO.d.ts → guide-preview-DbEZdGBV.d.ts} +43 -1
- package/dist/index.cjs +1278 -183
- 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 +162 -33
- package/dist/veo-builder.js.map +1 -1
- package/dist/veo-guides.js +6 -6
- package/dist/veo-guides.js.map +1 -1
- package/package.json +16 -16
- package/dist/builder-MNYSDJFT.mjs +0 -5
- package/dist/chunk-AFU5ZG6Z.mjs.map +0 -1
- package/dist/chunk-JPANNXIK.mjs.map +0 -1
- package/dist/chunk-X27GD7IT.mjs.map +0 -1
package/dist/builder.cjs
CHANGED
|
@@ -11,7 +11,7 @@ function attachBlockDropTarget(options) {
|
|
|
11
11
|
let spot = null;
|
|
12
12
|
const contentEl = () => host.shadowRoot?.querySelector(".veo-guide-content") ?? null;
|
|
13
13
|
const blockChildren = (container) => Array.from(container.children).filter(
|
|
14
|
-
(
|
|
14
|
+
(el2) => el2 instanceof HTMLElement && el2.dataset.veoIdx !== void 0
|
|
15
15
|
);
|
|
16
16
|
const hideLine = () => {
|
|
17
17
|
line?.remove();
|
|
@@ -283,6 +283,27 @@ function clearBuilderToken() {
|
|
|
283
283
|
}
|
|
284
284
|
}
|
|
285
285
|
|
|
286
|
+
// src/plugins/guides/activation-devices.ts
|
|
287
|
+
var MOBILE_MAX_WIDTH = 767;
|
|
288
|
+
function isDeviceAllowed(devices, viewportWidth = typeof window === "undefined" ? 1024 : window.innerWidth) {
|
|
289
|
+
if (!devices || devices === "all") return true;
|
|
290
|
+
const mobile = viewportWidth <= MOBILE_MAX_WIDTH;
|
|
291
|
+
return devices === "mobile" ? mobile : !mobile;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// src/plugins/guides/activation-rules.ts
|
|
295
|
+
function isAutomaticActivation(rules) {
|
|
296
|
+
const trigger = rules?.trigger ?? "immediate";
|
|
297
|
+
if (trigger === "immediate" || trigger === "delayed") return true;
|
|
298
|
+
if (trigger === "on_click" || trigger === "on_hover") return rules?.autoShow === true;
|
|
299
|
+
return false;
|
|
300
|
+
}
|
|
301
|
+
function activationDelayMs(rules) {
|
|
302
|
+
if (!isAutomaticActivation(rules)) return 0;
|
|
303
|
+
const ms = rules?.delayMs ?? 0;
|
|
304
|
+
return Number.isFinite(ms) && ms > 0 ? ms : 0;
|
|
305
|
+
}
|
|
306
|
+
|
|
286
307
|
// src/plugins/guides/constants.ts
|
|
287
308
|
var GUIDE_Z_INDEX = 2147483640;
|
|
288
309
|
var DEFAULT_ANCHOR_WAIT_MS = 5e3;
|
|
@@ -357,22 +378,22 @@ function rebuildNode(node, doc, depth, budget) {
|
|
|
357
378
|
return doc.createTextNode(node.textContent ?? "");
|
|
358
379
|
}
|
|
359
380
|
if (node.nodeType !== Node.ELEMENT_NODE) return null;
|
|
360
|
-
const
|
|
361
|
-
if (DROP_TAGS.has(
|
|
362
|
-
const mapped = ALLOWED_TAGS[
|
|
381
|
+
const el2 = node;
|
|
382
|
+
if (DROP_TAGS.has(el2.tagName)) return null;
|
|
383
|
+
const mapped = ALLOWED_TAGS[el2.tagName];
|
|
363
384
|
if (!mapped) {
|
|
364
385
|
const frag = doc.createDocumentFragment();
|
|
365
|
-
for (const child of Array.from(
|
|
386
|
+
for (const child of Array.from(el2.childNodes)) {
|
|
366
387
|
const rebuilt2 = rebuildNode(child, doc, depth + 1, budget);
|
|
367
388
|
if (rebuilt2) frag.appendChild(rebuilt2);
|
|
368
389
|
}
|
|
369
390
|
return frag;
|
|
370
391
|
}
|
|
371
392
|
if (mapped === "a") {
|
|
372
|
-
const href =
|
|
393
|
+
const href = el2.getAttribute("href") ?? "";
|
|
373
394
|
if (!isSafeUrl(href)) {
|
|
374
395
|
const frag = doc.createDocumentFragment();
|
|
375
|
-
for (const child of Array.from(
|
|
396
|
+
for (const child of Array.from(el2.childNodes)) {
|
|
376
397
|
const rebuilt2 = rebuildNode(child, doc, depth + 1, budget);
|
|
377
398
|
if (rebuilt2) frag.appendChild(rebuilt2);
|
|
378
399
|
}
|
|
@@ -382,14 +403,14 @@ function rebuildNode(node, doc, depth, budget) {
|
|
|
382
403
|
a.setAttribute("href", href);
|
|
383
404
|
a.setAttribute("target", "_blank");
|
|
384
405
|
a.setAttribute("rel", "noopener noreferrer nofollow");
|
|
385
|
-
for (const child of Array.from(
|
|
406
|
+
for (const child of Array.from(el2.childNodes)) {
|
|
386
407
|
const rebuilt2 = rebuildNode(child, doc, depth + 1, budget);
|
|
387
408
|
if (rebuilt2) a.appendChild(rebuilt2);
|
|
388
409
|
}
|
|
389
410
|
return a;
|
|
390
411
|
}
|
|
391
412
|
const rebuilt = doc.createElement(mapped);
|
|
392
|
-
for (const child of Array.from(
|
|
413
|
+
for (const child of Array.from(el2.childNodes)) {
|
|
393
414
|
const childNode = rebuildNode(child, doc, depth + 1, budget);
|
|
394
415
|
if (childNode) rebuilt.appendChild(childNode);
|
|
395
416
|
}
|
|
@@ -523,31 +544,31 @@ function renderBlocks(container, blocks, doc, callbacks) {
|
|
|
523
544
|
function buildContentBlock(block, doc) {
|
|
524
545
|
switch (block.type) {
|
|
525
546
|
case "title": {
|
|
526
|
-
const
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
applyBlockStyle(
|
|
530
|
-
return
|
|
547
|
+
const el2 = doc.createElement("h2");
|
|
548
|
+
el2.className = "veo-guide-title";
|
|
549
|
+
el2.textContent = typeof block.text === "string" ? block.text : "";
|
|
550
|
+
applyBlockStyle(el2, block.style, "text");
|
|
551
|
+
return el2;
|
|
531
552
|
}
|
|
532
553
|
case "text": {
|
|
533
|
-
const
|
|
534
|
-
|
|
554
|
+
const el2 = doc.createElement("div");
|
|
555
|
+
el2.className = "veo-guide-text";
|
|
535
556
|
if (typeof block.html === "string" && block.html) {
|
|
536
|
-
|
|
557
|
+
el2.appendChild(renderRichText(block.html, doc));
|
|
537
558
|
} else {
|
|
538
|
-
|
|
559
|
+
el2.textContent = typeof block.text === "string" ? block.text : "";
|
|
539
560
|
}
|
|
540
|
-
applyBlockStyle(
|
|
541
|
-
return
|
|
561
|
+
applyBlockStyle(el2, block.style, "text");
|
|
562
|
+
return el2;
|
|
542
563
|
}
|
|
543
564
|
case "image": {
|
|
544
565
|
if (typeof block.url !== "string" || !isSafeUrl(block.url)) return null;
|
|
545
|
-
const
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
applyBlockStyle(
|
|
550
|
-
return
|
|
566
|
+
const el2 = doc.createElement("img");
|
|
567
|
+
el2.className = "veo-guide-image";
|
|
568
|
+
el2.src = block.url;
|
|
569
|
+
el2.alt = "";
|
|
570
|
+
applyBlockStyle(el2, block.style, "image");
|
|
571
|
+
return el2;
|
|
551
572
|
}
|
|
552
573
|
default:
|
|
553
574
|
return null;
|
|
@@ -579,74 +600,74 @@ var BLOCK_ALIGN_SELF = {
|
|
|
579
600
|
function clampNum(n, min, max) {
|
|
580
601
|
return Math.min(max, Math.max(min, n));
|
|
581
602
|
}
|
|
582
|
-
function applyBlockStyle(
|
|
603
|
+
function applyBlockStyle(el2, style, kind) {
|
|
583
604
|
if (!style || typeof style !== "object") return;
|
|
584
605
|
const s = style;
|
|
585
606
|
if (kind === "image" && s.bleed === true) {
|
|
586
|
-
|
|
607
|
+
el2.classList.add("veo-guide-image--bleed");
|
|
587
608
|
return;
|
|
588
609
|
}
|
|
589
610
|
const align = typeof s.align === "string" ? s.align : null;
|
|
590
611
|
if (align && (align === "left" || align === "center" || align === "right")) {
|
|
591
|
-
if (kind === "text")
|
|
592
|
-
else if (kind === "image")
|
|
612
|
+
if (kind === "text") el2.style.textAlign = align;
|
|
613
|
+
else if (kind === "image") el2.style.alignSelf = BLOCK_ALIGN_SELF[align];
|
|
593
614
|
}
|
|
594
|
-
if (kind !== "image" && typeof s.color === "string")
|
|
615
|
+
if (kind !== "image" && typeof s.color === "string") el2.style.color = s.color;
|
|
595
616
|
if (kind === "text" && typeof s.fontSize === "number" && Number.isFinite(s.fontSize)) {
|
|
596
|
-
|
|
617
|
+
el2.style.fontSize = `${clampNum(s.fontSize, 8, 72)}px`;
|
|
597
618
|
}
|
|
598
619
|
if (kind === "image" && typeof s.width === "number" && Number.isFinite(s.width)) {
|
|
599
|
-
|
|
620
|
+
el2.style.width = `${clampNum(s.width, 10, 100)}%`;
|
|
600
621
|
}
|
|
601
622
|
if (kind === "image" && typeof s.radius === "number" && Number.isFinite(s.radius)) {
|
|
602
|
-
|
|
623
|
+
el2.style.borderRadius = `${clampNum(s.radius, 0, 48)}px`;
|
|
603
624
|
}
|
|
604
625
|
if (typeof s.marginTop === "number" && Number.isFinite(s.marginTop)) {
|
|
605
|
-
|
|
626
|
+
el2.style.marginTop = `${clampNum(s.marginTop, 0, 64)}px`;
|
|
606
627
|
}
|
|
607
628
|
if (typeof s.marginBottom === "number" && Number.isFinite(s.marginBottom)) {
|
|
608
|
-
|
|
629
|
+
el2.style.marginBottom = `${clampNum(s.marginBottom, 0, 64)}px`;
|
|
609
630
|
}
|
|
610
631
|
if (kind !== "image") {
|
|
611
632
|
if (typeof s.fontSize === "number" && Number.isFinite(s.fontSize)) {
|
|
612
|
-
|
|
633
|
+
el2.style.fontSize = `${clampNum(s.fontSize, 8, 96)}px`;
|
|
613
634
|
}
|
|
614
635
|
if (typeof s.fontFamily === "string" && s.fontFamily && s.fontFamily !== "inherit") {
|
|
615
|
-
|
|
636
|
+
el2.style.fontFamily = s.fontFamily;
|
|
616
637
|
}
|
|
617
|
-
if (typeof s.fontWeight === "string" && s.fontWeight)
|
|
638
|
+
if (typeof s.fontWeight === "string" && s.fontWeight) el2.style.fontWeight = s.fontWeight;
|
|
618
639
|
if (typeof s.textTransform === "string" && s.textTransform && s.textTransform !== "none") {
|
|
619
|
-
|
|
640
|
+
el2.style.textTransform = s.textTransform;
|
|
620
641
|
}
|
|
621
642
|
if (typeof s.lineHeight === "number" && Number.isFinite(s.lineHeight)) {
|
|
622
|
-
|
|
643
|
+
el2.style.lineHeight = `${clampNum(s.lineHeight, 50, 300)}%`;
|
|
623
644
|
}
|
|
624
645
|
if (typeof s.letterSpacing === "number" && Number.isFinite(s.letterSpacing)) {
|
|
625
|
-
|
|
646
|
+
el2.style.letterSpacing = `${clampNum(s.letterSpacing, -5, 20)}px`;
|
|
626
647
|
}
|
|
627
648
|
}
|
|
628
|
-
if (typeof s.background === "string" && s.background)
|
|
649
|
+
if (typeof s.background === "string" && s.background) el2.style.background = s.background;
|
|
629
650
|
if (typeof s.borderWidth === "number" && s.borderWidth > 0) {
|
|
630
651
|
const bc = typeof s.borderColor === "string" && s.borderColor ? s.borderColor : "#bbbbbb";
|
|
631
|
-
|
|
652
|
+
el2.style.border = `${clampNum(s.borderWidth, 0, 20)}px solid ${bc}`;
|
|
632
653
|
}
|
|
633
654
|
if (kind !== "image" && typeof s.radius === "number" && Number.isFinite(s.radius)) {
|
|
634
|
-
|
|
655
|
+
el2.style.borderRadius = `${clampNum(s.radius, 0, 64)}px`;
|
|
635
656
|
}
|
|
636
657
|
if (typeof s.height === "number" && Number.isFinite(s.height) && s.height > 0) {
|
|
637
|
-
|
|
658
|
+
el2.style.height = `${clampNum(s.height, 1, 2e3)}px`;
|
|
638
659
|
}
|
|
639
660
|
if (kind !== "image" && typeof s.width === "number" && Number.isFinite(s.width) && s.width > 0) {
|
|
640
|
-
|
|
661
|
+
el2.style.width = `${clampNum(s.width, 1, 2e3)}px`;
|
|
641
662
|
}
|
|
642
663
|
for (const side of ["Top", "Right", "Bottom", "Left"]) {
|
|
643
664
|
const p = s[`padding${side}`];
|
|
644
665
|
if (typeof p === "number" && Number.isFinite(p)) {
|
|
645
|
-
|
|
666
|
+
el2.style.setProperty(`padding-${side.toLowerCase()}`, `${clampNum(p, 0, 128)}px`);
|
|
646
667
|
}
|
|
647
668
|
const m = s[`margin${side}`];
|
|
648
669
|
if (typeof m === "number" && Number.isFinite(m)) {
|
|
649
|
-
|
|
670
|
+
el2.style.setProperty(`margin-${side.toLowerCase()}`, `${clampNum(m, 0, 128)}px`);
|
|
650
671
|
}
|
|
651
672
|
}
|
|
652
673
|
}
|
|
@@ -781,11 +802,11 @@ function applyDesignVars(host, style) {
|
|
|
781
802
|
host.style.setProperty("--veo-pos-y", `${py * 100}%`);
|
|
782
803
|
}
|
|
783
804
|
if (s.elements && typeof s.elements === "object") {
|
|
784
|
-
const
|
|
785
|
-
applyElementVars(host, "title",
|
|
786
|
-
applyElementVars(host, "text",
|
|
787
|
-
applyElementVars(host, "image",
|
|
788
|
-
applyCtaVars(host,
|
|
805
|
+
const el2 = s.elements;
|
|
806
|
+
applyElementVars(host, "title", el2.title);
|
|
807
|
+
applyElementVars(host, "text", el2.text);
|
|
808
|
+
applyElementVars(host, "image", el2.image);
|
|
809
|
+
applyCtaVars(host, el2.cta);
|
|
789
810
|
}
|
|
790
811
|
}
|
|
791
812
|
function applyCtaVars(host, raw) {
|
|
@@ -809,29 +830,29 @@ function applyCtaVars(host, raw) {
|
|
|
809
830
|
}
|
|
810
831
|
function applyElementVars(host, prefix, raw) {
|
|
811
832
|
if (!raw || typeof raw !== "object") return;
|
|
812
|
-
const
|
|
813
|
-
if (typeof
|
|
833
|
+
const el2 = raw;
|
|
834
|
+
if (typeof el2.align === "string" && (el2.align === "left" || el2.align === "center" || el2.align === "right")) {
|
|
814
835
|
const mode = ELEMENT_ALIGN_MODE[prefix] ?? "text";
|
|
815
|
-
const value = mode === "self" ? ALIGN_SELF[
|
|
836
|
+
const value = mode === "self" ? ALIGN_SELF[el2.align] : el2.align;
|
|
816
837
|
host.style.setProperty(`--veo-${prefix}-align`, value);
|
|
817
838
|
}
|
|
818
|
-
if (typeof
|
|
819
|
-
host.style.setProperty(`--veo-${prefix}-color`,
|
|
839
|
+
if (typeof el2.color === "string" && COLOR_RE.test(el2.color.trim())) {
|
|
840
|
+
host.style.setProperty(`--veo-${prefix}-color`, el2.color.trim());
|
|
820
841
|
}
|
|
821
|
-
if (typeof
|
|
822
|
-
host.style.setProperty(`--veo-${prefix}-size`, `${clamp(
|
|
842
|
+
if (typeof el2.fontSize === "number" && Number.isFinite(el2.fontSize)) {
|
|
843
|
+
host.style.setProperty(`--veo-${prefix}-size`, `${clamp(el2.fontSize, 8, 72)}px`);
|
|
823
844
|
}
|
|
824
|
-
if (typeof
|
|
825
|
-
host.style.setProperty(`--veo-${prefix}-width`, `${clamp(
|
|
845
|
+
if (typeof el2.width === "number" && Number.isFinite(el2.width)) {
|
|
846
|
+
host.style.setProperty(`--veo-${prefix}-width`, `${clamp(el2.width, 10, 100)}%`);
|
|
826
847
|
}
|
|
827
|
-
if (typeof
|
|
828
|
-
host.style.setProperty(`--veo-${prefix}-radius`, `${clamp(
|
|
848
|
+
if (typeof el2.radius === "number" && Number.isFinite(el2.radius)) {
|
|
849
|
+
host.style.setProperty(`--veo-${prefix}-radius`, `${clamp(el2.radius, 0, 48)}px`);
|
|
829
850
|
}
|
|
830
|
-
if (typeof
|
|
831
|
-
host.style.setProperty(`--veo-${prefix}-mt`, `${clamp(
|
|
851
|
+
if (typeof el2.marginTop === "number" && Number.isFinite(el2.marginTop)) {
|
|
852
|
+
host.style.setProperty(`--veo-${prefix}-mt`, `${clamp(el2.marginTop, 0, 64)}px`);
|
|
832
853
|
}
|
|
833
|
-
if (typeof
|
|
834
|
-
host.style.setProperty(`--veo-${prefix}-mb`, `${clamp(
|
|
854
|
+
if (typeof el2.marginBottom === "number" && Number.isFinite(el2.marginBottom)) {
|
|
855
|
+
host.style.setProperty(`--veo-${prefix}-mb`, `${clamp(el2.marginBottom, 0, 64)}px`);
|
|
835
856
|
}
|
|
836
857
|
}
|
|
837
858
|
|
|
@@ -881,16 +902,16 @@ function waitForElement(selector, timeoutMs = DEFAULT_ANCHOR_WAIT_MS) {
|
|
|
881
902
|
return;
|
|
882
903
|
}
|
|
883
904
|
let resolved = false;
|
|
884
|
-
const finish = (
|
|
905
|
+
const finish = (el2) => {
|
|
885
906
|
if (resolved) return;
|
|
886
907
|
resolved = true;
|
|
887
908
|
observer.disconnect();
|
|
888
909
|
clearTimeout(timer);
|
|
889
|
-
resolve(
|
|
910
|
+
resolve(el2);
|
|
890
911
|
};
|
|
891
912
|
const observer = new MutationObserver(() => {
|
|
892
|
-
const
|
|
893
|
-
if (
|
|
913
|
+
const el2 = safeQuery();
|
|
914
|
+
if (el2) finish(el2);
|
|
894
915
|
});
|
|
895
916
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
896
917
|
const timer = setTimeout(() => finish(null), timeoutMs);
|
|
@@ -1950,10 +1971,10 @@ function collectHostStyles() {
|
|
|
1950
1971
|
function hostHtmlAttrs() {
|
|
1951
1972
|
if (typeof document === "undefined") return "";
|
|
1952
1973
|
try {
|
|
1953
|
-
const
|
|
1974
|
+
const el2 = document.documentElement;
|
|
1954
1975
|
const attrs = [];
|
|
1955
1976
|
for (const name of ["class", "style", "data-theme", "data-mode", "data-color-mode"]) {
|
|
1956
|
-
const v =
|
|
1977
|
+
const v = el2.getAttribute(name);
|
|
1957
1978
|
if (v && v.length <= 1e3 && !/["<>]/.test(v)) attrs.push(`${name}="${v}"`);
|
|
1958
1979
|
}
|
|
1959
1980
|
return attrs.join(" ");
|
|
@@ -2336,6 +2357,188 @@ function buildScale(wrapper, doc, min, max, btnClass, symbol) {
|
|
|
2336
2357
|
wrapper.appendChild(row);
|
|
2337
2358
|
return { wrapper, read: () => selected };
|
|
2338
2359
|
}
|
|
2360
|
+
var INFO_GLYPH = "M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021";
|
|
2361
|
+
var QUESTION_GLYPH = "M9.879 7.519c1.171-1.025 3.071-1.025 4.242 0 1.172 1.025 1.172 2.687 0 3.712-.203.179-.43.326-.67.442-.745.361-1.45.999-1.45 1.827v.75";
|
|
2362
|
+
var STAR_GLYPH = "M11.48 3.499a.562.562 0 011.04 0l2.125 5.111a.563.563 0 00.475.345l5.518.442c.499.04.701.663.321.988l-4.204 3.602a.563.563 0 00-.182.557l1.285 5.385a.562.562 0 01-.84.61l-4.725-2.885a.563.563 0 00-.586 0L6.982 20.54a.562.562 0 01-.84-.61l1.285-5.386a.562.562 0 00-.182-.557l-4.204-3.602a.563.563 0 01.321-.988l5.518-.442a.563.563 0 00.475-.345L11.48 3.5z";
|
|
2363
|
+
var CIRCLE = "M21 12a9 9 0 11-18 0 9 9 0 0118 0z";
|
|
2364
|
+
var TARGET_GLYPH = "M7.5 3.75H6A2.25 2.25 0 0 0 3.75 6v1.5M16.5 3.75H18A2.25 2.25 0 0 1 20.25 6v1.5m0 9V18A2.25 2.25 0 0 1 18 20.25h-1.5m-9 0H6A2.25 2.25 0 0 1 3.75 18v-1.5M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z";
|
|
2365
|
+
var BADGE_ICONS = {
|
|
2366
|
+
info: { paths: [CIRCLE, INFO_GLYPH], dots: [[12, 8.25]] },
|
|
2367
|
+
exclamation: { paths: [CIRCLE, "M12 8v4.5"], dots: [[12, 15.75]] },
|
|
2368
|
+
question: { paths: [CIRCLE, QUESTION_GLYPH], dots: [[12, 17.25]] },
|
|
2369
|
+
star: { paths: [STAR_GLYPH] },
|
|
2370
|
+
"info-solid": { paths: [INFO_GLYPH], dots: [[12, 8.25]], solid: true, scale: 0.8 },
|
|
2371
|
+
"exclamation-solid": { paths: ["M12 8v4.5"], dots: [[12, 15.75]], solid: true, scale: 0.8 },
|
|
2372
|
+
"question-solid": { paths: [QUESTION_GLYPH], dots: [[12, 17.25]], solid: true, scale: 0.8 },
|
|
2373
|
+
"star-solid": { paths: [STAR_GLYPH], solid: true, scale: 0.55 },
|
|
2374
|
+
"target-solid": { paths: [TARGET_GLYPH], solid: true, scale: 0.6 },
|
|
2375
|
+
new: { paths: [], text: "New" }
|
|
2376
|
+
};
|
|
2377
|
+
var DEFAULT_MARKER_SIZE = 14;
|
|
2378
|
+
var DEFAULT_MARKER_Z = 19e3;
|
|
2379
|
+
var SIDE_GAP = 8;
|
|
2380
|
+
function num(v, fallback) {
|
|
2381
|
+
return typeof v === "number" && Number.isFinite(v) ? v : fallback;
|
|
2382
|
+
}
|
|
2383
|
+
function iconNode(doc, name, size, color) {
|
|
2384
|
+
const def = BADGE_ICONS[name] ?? BADGE_ICONS.info;
|
|
2385
|
+
if (def.text) {
|
|
2386
|
+
const t = doc.createElement("span");
|
|
2387
|
+
t.textContent = def.text;
|
|
2388
|
+
t.style.font = `700 ${Math.round(size * 0.85)}px/1 system-ui, -apple-system, sans-serif`;
|
|
2389
|
+
t.style.color = color;
|
|
2390
|
+
return t;
|
|
2391
|
+
}
|
|
2392
|
+
const ns = "http://www.w3.org/2000/svg";
|
|
2393
|
+
const svg2 = doc.createElementNS(ns, "svg");
|
|
2394
|
+
svg2.setAttribute("viewBox", "0 0 24 24");
|
|
2395
|
+
svg2.setAttribute("width", String(size));
|
|
2396
|
+
svg2.setAttribute("height", String(size));
|
|
2397
|
+
svg2.setAttribute("fill", "none");
|
|
2398
|
+
svg2.setAttribute("aria-hidden", "true");
|
|
2399
|
+
const glyphColor = def.solid ? "#ffffff" : color;
|
|
2400
|
+
if (def.solid) {
|
|
2401
|
+
const bg = doc.createElementNS(ns, "circle");
|
|
2402
|
+
bg.setAttribute("cx", "12");
|
|
2403
|
+
bg.setAttribute("cy", "12");
|
|
2404
|
+
bg.setAttribute("r", "12");
|
|
2405
|
+
bg.setAttribute("fill", color);
|
|
2406
|
+
svg2.appendChild(bg);
|
|
2407
|
+
}
|
|
2408
|
+
const g = doc.createElementNS(ns, "g");
|
|
2409
|
+
g.setAttribute("stroke", glyphColor);
|
|
2410
|
+
g.setAttribute("stroke-width", def.solid ? "2" : "1.8");
|
|
2411
|
+
g.setAttribute("stroke-linecap", "round");
|
|
2412
|
+
g.setAttribute("stroke-linejoin", "round");
|
|
2413
|
+
if (def.scale && def.scale !== 1) {
|
|
2414
|
+
const k = def.scale;
|
|
2415
|
+
const t = 12 - 12 * k;
|
|
2416
|
+
g.setAttribute("transform", `translate(${t} ${t}) scale(${k})`);
|
|
2417
|
+
}
|
|
2418
|
+
for (const d of def.paths) {
|
|
2419
|
+
const path = doc.createElementNS(ns, "path");
|
|
2420
|
+
path.setAttribute("d", d);
|
|
2421
|
+
g.appendChild(path);
|
|
2422
|
+
}
|
|
2423
|
+
for (const [cx, cy] of def.dots ?? []) {
|
|
2424
|
+
const dot = doc.createElementNS(ns, "circle");
|
|
2425
|
+
dot.setAttribute("cx", String(cx));
|
|
2426
|
+
dot.setAttribute("cy", String(cy));
|
|
2427
|
+
dot.setAttribute("r", "0.9");
|
|
2428
|
+
dot.setAttribute("fill", glyphColor);
|
|
2429
|
+
dot.setAttribute("stroke", "none");
|
|
2430
|
+
g.appendChild(dot);
|
|
2431
|
+
}
|
|
2432
|
+
svg2.appendChild(g);
|
|
2433
|
+
return svg2;
|
|
2434
|
+
}
|
|
2435
|
+
function buildMarkerElement(doc, marker) {
|
|
2436
|
+
const size = num(marker.size, DEFAULT_MARKER_SIZE);
|
|
2437
|
+
const color = marker.color || "#000000";
|
|
2438
|
+
const el2 = doc.createElement("span");
|
|
2439
|
+
el2.className = `veo-badge-marker veo-badge-marker-${marker.kind}`;
|
|
2440
|
+
el2.style.display = "inline-flex";
|
|
2441
|
+
el2.style.alignItems = "center";
|
|
2442
|
+
el2.style.justifyContent = "center";
|
|
2443
|
+
el2.style.boxSizing = "border-box";
|
|
2444
|
+
el2.style.lineHeight = "1";
|
|
2445
|
+
if (marker.kind === "image") {
|
|
2446
|
+
const img = doc.createElement("img");
|
|
2447
|
+
img.alt = "";
|
|
2448
|
+
img.src = marker.imageUrl || "";
|
|
2449
|
+
img.style.width = `${size}px`;
|
|
2450
|
+
img.style.height = `${size}px`;
|
|
2451
|
+
img.style.objectFit = "contain";
|
|
2452
|
+
img.style.display = "block";
|
|
2453
|
+
el2.appendChild(img);
|
|
2454
|
+
return el2;
|
|
2455
|
+
}
|
|
2456
|
+
if (marker.kind === "icon-text") {
|
|
2457
|
+
el2.style.gap = "6px";
|
|
2458
|
+
el2.style.color = color;
|
|
2459
|
+
el2.style.fontSize = `${size}px`;
|
|
2460
|
+
el2.style.fontFamily = "inherit";
|
|
2461
|
+
el2.style.fontWeight = "600";
|
|
2462
|
+
el2.style.whiteSpace = "nowrap";
|
|
2463
|
+
el2.style.background = marker.bgColor || "transparent";
|
|
2464
|
+
const bw = num(marker.borderWidth, 0);
|
|
2465
|
+
if (bw > 0) el2.style.border = `${bw}px solid ${marker.borderColor || color}`;
|
|
2466
|
+
el2.style.padding = `${num(marker.paddingY, 6)}px ${num(marker.paddingX, 10)}px`;
|
|
2467
|
+
el2.style.borderRadius = `${num(marker.radius, 999)}px`;
|
|
2468
|
+
if (marker.showIcon !== false)
|
|
2469
|
+
el2.appendChild(iconNode(doc, marker.icon || "star", size, color));
|
|
2470
|
+
const text = doc.createElement("span");
|
|
2471
|
+
text.textContent = marker.text || "";
|
|
2472
|
+
el2.appendChild(text);
|
|
2473
|
+
return el2;
|
|
2474
|
+
}
|
|
2475
|
+
el2.style.width = `${size}px`;
|
|
2476
|
+
el2.style.height = `${size}px`;
|
|
2477
|
+
el2.appendChild(iconNode(doc, marker.icon || "info", size, color));
|
|
2478
|
+
return el2;
|
|
2479
|
+
}
|
|
2480
|
+
function markerOffset(anchor, marker, position, offset6) {
|
|
2481
|
+
const right = anchor.left + anchor.width;
|
|
2482
|
+
const bottom = anchor.top + anchor.height;
|
|
2483
|
+
const midY = anchor.top + anchor.height / 2 - marker.height / 2;
|
|
2484
|
+
const midX = anchor.left + anchor.width / 2 - marker.width / 2;
|
|
2485
|
+
let x;
|
|
2486
|
+
let y;
|
|
2487
|
+
switch (position) {
|
|
2488
|
+
case "top-left":
|
|
2489
|
+
x = anchor.left - marker.width / 2;
|
|
2490
|
+
y = anchor.top - marker.height / 2;
|
|
2491
|
+
break;
|
|
2492
|
+
case "bottom-left":
|
|
2493
|
+
x = anchor.left - marker.width / 2;
|
|
2494
|
+
y = bottom - marker.height / 2;
|
|
2495
|
+
break;
|
|
2496
|
+
case "bottom-right":
|
|
2497
|
+
x = right - marker.width / 2;
|
|
2498
|
+
y = bottom - marker.height / 2;
|
|
2499
|
+
break;
|
|
2500
|
+
case "left":
|
|
2501
|
+
x = anchor.left - marker.width - SIDE_GAP;
|
|
2502
|
+
y = midY;
|
|
2503
|
+
break;
|
|
2504
|
+
case "right":
|
|
2505
|
+
x = right + SIDE_GAP;
|
|
2506
|
+
y = midY;
|
|
2507
|
+
break;
|
|
2508
|
+
case "center":
|
|
2509
|
+
x = midX;
|
|
2510
|
+
y = midY;
|
|
2511
|
+
break;
|
|
2512
|
+
default:
|
|
2513
|
+
x = right - marker.width / 2;
|
|
2514
|
+
y = anchor.top - marker.height / 2;
|
|
2515
|
+
}
|
|
2516
|
+
return { x: x + offset6.x, y: y + offset6.y };
|
|
2517
|
+
}
|
|
2518
|
+
function attachMarker(anchor, host, marker) {
|
|
2519
|
+
host.style.position = "absolute";
|
|
2520
|
+
host.style.zIndex = String(num(marker.zIndex, DEFAULT_MARKER_Z));
|
|
2521
|
+
host.style.margin = "0";
|
|
2522
|
+
const update = () => {
|
|
2523
|
+
const a = anchor.getBoundingClientRect();
|
|
2524
|
+
const m = host.getBoundingClientRect();
|
|
2525
|
+
const { x, y } = markerOffset(
|
|
2526
|
+
{
|
|
2527
|
+
left: a.left + window.scrollX,
|
|
2528
|
+
top: a.top + window.scrollY,
|
|
2529
|
+
width: a.width,
|
|
2530
|
+
height: a.height
|
|
2531
|
+
},
|
|
2532
|
+
{ width: m.width, height: m.height },
|
|
2533
|
+
marker.position ?? "top-right",
|
|
2534
|
+
{ x: num(marker.offsetX, 0), y: num(marker.offsetY, 0) }
|
|
2535
|
+
);
|
|
2536
|
+
host.style.left = `${Math.round(x)}px`;
|
|
2537
|
+
host.style.top = `${Math.round(y)}px`;
|
|
2538
|
+
};
|
|
2539
|
+
update();
|
|
2540
|
+
return dom.autoUpdate(anchor, host, update);
|
|
2541
|
+
}
|
|
2339
2542
|
|
|
2340
2543
|
// src/plugins/guides/renderers/composite-renderer.ts
|
|
2341
2544
|
var ROW_ALIGN = {
|
|
@@ -2631,7 +2834,9 @@ var CompositeRenderer = class extends BaseRenderer {
|
|
|
2631
2834
|
badge.style.cursor = "pointer";
|
|
2632
2835
|
badge.style.display = "inline-flex";
|
|
2633
2836
|
badge.style.alignItems = "center";
|
|
2634
|
-
|
|
2837
|
+
const marker = step.badge?.marker ?? null;
|
|
2838
|
+
if (marker) badge.appendChild(buildMarkerElement(doc, marker));
|
|
2839
|
+
else this.buildContent(badge, step.badge?.blocks ?? [], doc, context, idx, [], host);
|
|
2635
2840
|
root.appendChild(badge);
|
|
2636
2841
|
if (design.fullWidth === true) {
|
|
2637
2842
|
card.style.width = "auto";
|
|
@@ -2646,10 +2851,17 @@ var CompositeRenderer = class extends BaseRenderer {
|
|
|
2646
2851
|
if (caretEl) wrapper.appendChild(caretEl);
|
|
2647
2852
|
wrapper.appendChild(card);
|
|
2648
2853
|
root.appendChild(wrapper);
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2854
|
+
if (marker) {
|
|
2855
|
+
host.style.display = "inline-block";
|
|
2856
|
+
(anchor.ownerDocument ?? document).body.appendChild(host);
|
|
2857
|
+
this.registerCleanup(attachMarker(anchor, host, marker));
|
|
2858
|
+
this.registerCleanup(() => host.remove());
|
|
2859
|
+
} else {
|
|
2860
|
+
host.style.display = "inline-block";
|
|
2861
|
+
const pos = inlinePosOf(step.inlinePosition);
|
|
2862
|
+
insertHost(anchor, host, pos);
|
|
2863
|
+
this.registerCleanup(keepHostAttached(host, anchorSelector, pos));
|
|
2864
|
+
}
|
|
2653
2865
|
let open = false;
|
|
2654
2866
|
let stopFloat = null;
|
|
2655
2867
|
let closeTimer = null;
|
|
@@ -2702,6 +2914,7 @@ var CompositeRenderer = class extends BaseRenderer {
|
|
|
2702
2914
|
stopFloat?.();
|
|
2703
2915
|
if (closeTimer !== null) clearTimeout(closeTimer);
|
|
2704
2916
|
});
|
|
2917
|
+
if (context.badgeOpen) openTip();
|
|
2705
2918
|
return closeTip;
|
|
2706
2919
|
}
|
|
2707
2920
|
};
|
|
@@ -2755,14 +2968,14 @@ function makeCaret(doc, design) {
|
|
|
2755
2968
|
return caret;
|
|
2756
2969
|
}
|
|
2757
2970
|
function liftTarget(anchor, zIndex) {
|
|
2758
|
-
const
|
|
2759
|
-
const prevPosition =
|
|
2760
|
-
const prevZ =
|
|
2761
|
-
if (getComputedStyle(
|
|
2762
|
-
|
|
2971
|
+
const el2 = anchor;
|
|
2972
|
+
const prevPosition = el2.style.position;
|
|
2973
|
+
const prevZ = el2.style.zIndex;
|
|
2974
|
+
if (getComputedStyle(el2).position === "static") el2.style.position = "relative";
|
|
2975
|
+
el2.style.zIndex = String(zIndex);
|
|
2763
2976
|
return () => {
|
|
2764
|
-
|
|
2765
|
-
|
|
2977
|
+
el2.style.position = prevPosition;
|
|
2978
|
+
el2.style.zIndex = prevZ;
|
|
2766
2979
|
};
|
|
2767
2980
|
}
|
|
2768
2981
|
async function anchorPosition(anchor, wrapper, caret, preferred = "bottom") {
|
|
@@ -3278,7 +3491,8 @@ var GuidePreviewController = class {
|
|
|
3278
3491
|
}
|
|
3279
3492
|
preview(input) {
|
|
3280
3493
|
const nextStep = input.guideSteps[0];
|
|
3281
|
-
if (this.singleStep && this.input && input.guideType === this.input.guideType && input.guideType !== "walkthrough" &&
|
|
3494
|
+
if (this.singleStep && this.input && input.guideType === this.input.guideType && input.guideType !== "walkthrough" && // Abrir/cerrar el tooltip del badge requiere remontar.
|
|
3495
|
+
input.badgeOpen === true === (this.input.badgeOpen === true) && nextStep && this.singleStep.updateStep(nextStep)) {
|
|
3282
3496
|
this.input = input;
|
|
3283
3497
|
return {
|
|
3284
3498
|
close: () => this.close(),
|
|
@@ -3308,7 +3522,8 @@ var GuidePreviewController = class {
|
|
|
3308
3522
|
}
|
|
3309
3523
|
return null;
|
|
3310
3524
|
}
|
|
3311
|
-
close() {
|
|
3525
|
+
close(byUser = false) {
|
|
3526
|
+
const onClosed = byUser ? this.input?.onClosed : void 0;
|
|
3312
3527
|
if (this.singleStep) {
|
|
3313
3528
|
safeDestroy(this.singleStep);
|
|
3314
3529
|
this.singleStep = null;
|
|
@@ -3320,6 +3535,7 @@ var GuidePreviewController = class {
|
|
|
3320
3535
|
this.walkthroughGuide = null;
|
|
3321
3536
|
this.walkthroughIndex = 0;
|
|
3322
3537
|
this.input = null;
|
|
3538
|
+
onClosed?.();
|
|
3323
3539
|
}
|
|
3324
3540
|
async renderSingleStep(guide) {
|
|
3325
3541
|
const renderer = createSingleStepRenderer(guide.guideType);
|
|
@@ -3332,7 +3548,10 @@ var GuidePreviewController = class {
|
|
|
3332
3548
|
onInteraction: (event) => {
|
|
3333
3549
|
if (event.action === "shown") shown = true;
|
|
3334
3550
|
},
|
|
3335
|
-
onClose: () => this.close(),
|
|
3551
|
+
onClose: () => this.close(true),
|
|
3552
|
+
// Sin indicación explícita, el badge se abre solo si la guía arranca
|
|
3553
|
+
// sola (como en el runtime); `manual` lo deja cerrado.
|
|
3554
|
+
badgeOpen: this.input?.badgeOpen ?? isAutomaticActivation(this.input?.activationRules),
|
|
3336
3555
|
onTrack: () => {
|
|
3337
3556
|
},
|
|
3338
3557
|
// Encadenado en preview: no-op — el editor no puede montar otra guía
|
|
@@ -3398,7 +3617,7 @@ var GuidePreviewController = class {
|
|
|
3398
3617
|
guide,
|
|
3399
3618
|
onInteraction: () => {
|
|
3400
3619
|
},
|
|
3401
|
-
onClose: () => this.close(),
|
|
3620
|
+
onClose: () => this.close(true),
|
|
3402
3621
|
nav: { stepIndex: index, totalSteps: guide.guideSteps.length, callbacks }
|
|
3403
3622
|
});
|
|
3404
3623
|
} catch {
|
|
@@ -3492,15 +3711,27 @@ function safeDestroy(renderer) {
|
|
|
3492
3711
|
}
|
|
3493
3712
|
|
|
3494
3713
|
// src/plugins/guides/url-match.ts
|
|
3714
|
+
function urlCandidates(pageUrl) {
|
|
3715
|
+
const out = [pageUrl];
|
|
3716
|
+
try {
|
|
3717
|
+
const u = new URL(pageUrl);
|
|
3718
|
+
out.push(`${u.pathname}${u.search}${u.hash}`);
|
|
3719
|
+
if (u.hash.startsWith("#/")) out.push(u.hash.slice(1));
|
|
3720
|
+
} catch {
|
|
3721
|
+
}
|
|
3722
|
+
return out;
|
|
3723
|
+
}
|
|
3495
3724
|
function matchesUrl(matcher, pageUrl) {
|
|
3725
|
+
const candidates = urlCandidates(pageUrl);
|
|
3496
3726
|
switch (matcher.type) {
|
|
3497
3727
|
case "exact":
|
|
3498
|
-
return
|
|
3728
|
+
return candidates.some((c) => c === matcher.pattern);
|
|
3499
3729
|
case "prefix":
|
|
3500
|
-
return
|
|
3730
|
+
return candidates.some((c) => c.startsWith(matcher.pattern));
|
|
3501
3731
|
case "regex":
|
|
3502
3732
|
try {
|
|
3503
|
-
|
|
3733
|
+
const re = new RegExp(matcher.pattern);
|
|
3734
|
+
return candidates.some((c) => re.test(c));
|
|
3504
3735
|
} catch {
|
|
3505
3736
|
return false;
|
|
3506
3737
|
}
|
|
@@ -3514,17 +3745,375 @@ function stepMatchesPage(loc, pageUrl) {
|
|
|
3514
3745
|
// src/plugins/builder/bridge-protocol.ts
|
|
3515
3746
|
var VEO_BUILDER_SOURCE = "veo-builder";
|
|
3516
3747
|
|
|
3748
|
+
// src/plugins/builder/builder-chrome.ts
|
|
3749
|
+
var CHROME_TOPBAR_H = 64;
|
|
3750
|
+
var CHROME_STEPS_H = 128;
|
|
3751
|
+
var ICONS = {
|
|
3752
|
+
bolt: '<path stroke-linecap="round" stroke-linejoin="round" d="m3.75 13.5 10.5-11.25L12 10.5h8.25L9.75 21.75 12 13.5H3.75Z"/>',
|
|
3753
|
+
desktop: '<path stroke-linecap="round" stroke-linejoin="round" d="M9 17.25v1.007a3 3 0 0 1-.879 2.122L7.5 21h9l-.621-.621A3 3 0 0 1 15 18.257V17.25m6-12V15a2.25 2.25 0 0 1-2.25 2.25H5.25A2.25 2.25 0 0 1 3 15V5.25m18 0A2.25 2.25 0 0 0 18.75 3H5.25A2.25 2.25 0 0 0 3 5.25m18 0V12a2.25 2.25 0 0 1-2.25 2.25H5.25A2.25 2.25 0 0 1 3 12V5.25"/>',
|
|
3754
|
+
updown: '<path stroke-linecap="round" stroke-linejoin="round" d="M3 7.5 7.5 3m0 0L12 7.5M7.5 3v13.5m13.5 0L16.5 21m0 0L12 16.5m4.5 4.5V7.5"/>',
|
|
3755
|
+
map: '<path stroke-linecap="round" stroke-linejoin="round" d="M9 6.75V15m6-6v8.25m.503 3.498 4.875-2.437c.381-.19.622-.58.622-1.006V4.82c0-.836-.88-1.38-1.628-1.006l-3.869 1.934c-.317.159-.69.159-1.006 0L9.503 3.252a1.125 1.125 0 0 0-1.006 0L3.622 5.689C3.24 5.88 3 6.27 3 6.695V19.18c0 .836.88 1.38 1.628 1.006l3.869-1.934c.317-.159.69-.159 1.006 0l4.994 2.497c.317.158.69.158 1.006 0Z"/>',
|
|
3756
|
+
eye: '<path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z"/><path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"/>',
|
|
3757
|
+
chevronDown: '<path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5"/>',
|
|
3758
|
+
chevronUp: '<path stroke-linecap="round" stroke-linejoin="round" d="m4.5 15.75 7.5-7.5 7.5 7.5"/>',
|
|
3759
|
+
plus: '<path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15"/>',
|
|
3760
|
+
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"/>',
|
|
3761
|
+
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"/>'
|
|
3762
|
+
};
|
|
3763
|
+
function svg(name, size = 20) {
|
|
3764
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" aria-hidden="true">${ICONS[name]}</svg>`;
|
|
3765
|
+
}
|
|
3766
|
+
function shortDate(iso) {
|
|
3767
|
+
if (!iso) return "";
|
|
3768
|
+
const d = new Date(iso);
|
|
3769
|
+
if (Number.isNaN(d.getTime())) return "";
|
|
3770
|
+
return d.toLocaleDateString("es", { day: "numeric", month: "short" }).replace(".", "");
|
|
3771
|
+
}
|
|
3772
|
+
function el(tag, className, html) {
|
|
3773
|
+
const node = document.createElement(tag);
|
|
3774
|
+
node.className = className;
|
|
3775
|
+
if (html !== void 0) node.innerHTML = html;
|
|
3776
|
+
return node;
|
|
3777
|
+
}
|
|
3778
|
+
function iconButton(name, title, className = "") {
|
|
3779
|
+
const b = el("button", `veo-tb-icon ${className}`.trim(), svg(name));
|
|
3780
|
+
b.type = "button";
|
|
3781
|
+
b.title = title;
|
|
3782
|
+
b.setAttribute("aria-label", title);
|
|
3783
|
+
return b;
|
|
3784
|
+
}
|
|
3785
|
+
function injectBuilderChrome(opts) {
|
|
3786
|
+
if (!hasWindow() || !hasDocument()) {
|
|
3787
|
+
return {
|
|
3788
|
+
setState: () => {
|
|
3789
|
+
},
|
|
3790
|
+
height: () => 0,
|
|
3791
|
+
dock: () => "top",
|
|
3792
|
+
setPreview: () => {
|
|
3793
|
+
},
|
|
3794
|
+
setHidden: () => {
|
|
3795
|
+
},
|
|
3796
|
+
onHeightChange: () => {
|
|
3797
|
+
},
|
|
3798
|
+
teardown: () => {
|
|
3799
|
+
}
|
|
3800
|
+
};
|
|
3801
|
+
}
|
|
3802
|
+
const host = document.createElement("div");
|
|
3803
|
+
host.setAttribute("data-veo-builder-chrome", "");
|
|
3804
|
+
host.setAttribute("data-veo-ignore", "");
|
|
3805
|
+
const shadow = host.attachShadow({ mode: "open" });
|
|
3806
|
+
const style = document.createElement("style");
|
|
3807
|
+
style.textContent = CHROME_CSS;
|
|
3808
|
+
const root = el("div", "veo-chrome");
|
|
3809
|
+
const topbar = el("div", "veo-tb");
|
|
3810
|
+
const brand = el("div", "veo-tb-brand", svg("bolt", 18));
|
|
3811
|
+
const nameEl = el("div", "veo-tb-name");
|
|
3812
|
+
const statusEl = el("span", "veo-tb-status");
|
|
3813
|
+
statusEl.hidden = true;
|
|
3814
|
+
const sep = el("span", "veo-tb-sep");
|
|
3815
|
+
const appEl = el("div", "veo-tb-app", `${svg("desktop", 16)}<span></span>`);
|
|
3816
|
+
appEl.querySelector("span").textContent = opts.appLabel;
|
|
3817
|
+
const left = el("div", "veo-tb-left");
|
|
3818
|
+
left.append(brand, nameEl, statusEl, sep, appEl);
|
|
3819
|
+
const right = el("div", "veo-tb-right");
|
|
3820
|
+
const dockBtn = iconButton("updown", "Mover la barra abajo");
|
|
3821
|
+
const showPanel = iconButton("map", "Mostrar el editor");
|
|
3822
|
+
const preview = iconButton("eye", "Vista previa");
|
|
3823
|
+
const exit = el("button", "veo-tb-text", "Salir");
|
|
3824
|
+
exit.type = "button";
|
|
3825
|
+
const saveGroup = el("div", "veo-tb-save");
|
|
3826
|
+
const save = el("button", "veo-tb-save-main", "<span>Guardar</span>");
|
|
3827
|
+
save.type = "button";
|
|
3828
|
+
const saveMore = el("button", "veo-tb-save-more", svg("chevronDown", 16));
|
|
3829
|
+
saveMore.type = "button";
|
|
3830
|
+
saveMore.title = "M\xE1s opciones de guardado";
|
|
3831
|
+
saveMore.setAttribute("aria-label", "M\xE1s opciones de guardado");
|
|
3832
|
+
const saveMenu = el("div", "veo-tb-menu");
|
|
3833
|
+
const saveExit = el("button", "veo-tb-menu-item", "Guardar y salir");
|
|
3834
|
+
saveExit.type = "button";
|
|
3835
|
+
saveMenu.append(saveExit);
|
|
3836
|
+
saveMenu.hidden = true;
|
|
3837
|
+
saveGroup.append(save, saveMore, saveMenu);
|
|
3838
|
+
right.append(dockBtn, showPanel, preview, el("span", "veo-tb-vsep"), exit, saveGroup);
|
|
3839
|
+
topbar.append(left, right);
|
|
3840
|
+
const stepsBar = el("div", "veo-steps");
|
|
3841
|
+
const stepsList = el("div", "veo-steps-list");
|
|
3842
|
+
stepsBar.append(stepsList);
|
|
3843
|
+
const togglePill = el("button", "veo-steps-toggle");
|
|
3844
|
+
togglePill.type = "button";
|
|
3845
|
+
root.append(topbar, stepsBar, togglePill);
|
|
3846
|
+
const previewPill = el("div", "veo-preview-pill");
|
|
3847
|
+
const previewLabel = el(
|
|
3848
|
+
"span",
|
|
3849
|
+
"veo-preview-label",
|
|
3850
|
+
`${svg("eye", 18)}<span>Est\xE1s en vista previa</span>`
|
|
3851
|
+
);
|
|
3852
|
+
const previewExit = el("button", "veo-preview-exit", "Salir");
|
|
3853
|
+
previewExit.type = "button";
|
|
3854
|
+
previewPill.append(previewLabel, previewExit);
|
|
3855
|
+
previewPill.hidden = true;
|
|
3856
|
+
shadow.append(style, root, previewPill);
|
|
3857
|
+
document.body.appendChild(host);
|
|
3858
|
+
const html = document.documentElement;
|
|
3859
|
+
const prevMarginTop = html.style.marginTop;
|
|
3860
|
+
const prevMarginBottom = html.style.marginBottom;
|
|
3861
|
+
let collapsed = false;
|
|
3862
|
+
let dock = "top";
|
|
3863
|
+
let previewOn = false;
|
|
3864
|
+
let hiddenOn = false;
|
|
3865
|
+
let heightCb = null;
|
|
3866
|
+
const height = () => CHROME_TOPBAR_H + (collapsed ? 0 : CHROME_STEPS_H);
|
|
3867
|
+
const applyHeight = () => {
|
|
3868
|
+
const h = previewOn || hiddenOn ? 0 : height();
|
|
3869
|
+
html.style.marginTop = dock === "top" ? `${h}px` : prevMarginTop;
|
|
3870
|
+
html.style.marginBottom = dock === "bottom" ? `${h}px` : prevMarginBottom;
|
|
3871
|
+
root.style.setProperty("--veo-chrome-h", `${height()}px`);
|
|
3872
|
+
root.classList.toggle("is-bottom", dock === "bottom");
|
|
3873
|
+
stepsBar.hidden = collapsed;
|
|
3874
|
+
const open = dock === "top" ? "chevronUp" : "chevronDown";
|
|
3875
|
+
const closedIcon = dock === "top" ? "chevronDown" : "chevronUp";
|
|
3876
|
+
togglePill.innerHTML = `<span>${collapsed ? "Mostrar pasos" : "Ocultar pasos"}</span>${svg(
|
|
3877
|
+
collapsed ? closedIcon : open,
|
|
3878
|
+
16
|
|
3879
|
+
)}`;
|
|
3880
|
+
dockBtn.title = dock === "top" ? "Mover la barra abajo" : "Mover la barra arriba";
|
|
3881
|
+
dockBtn.setAttribute("aria-label", dockBtn.title);
|
|
3882
|
+
heightCb?.(h);
|
|
3883
|
+
};
|
|
3884
|
+
const setPreview = (on) => {
|
|
3885
|
+
previewOn = on;
|
|
3886
|
+
root.hidden = on || hiddenOn;
|
|
3887
|
+
previewPill.hidden = !on;
|
|
3888
|
+
applyHeight();
|
|
3889
|
+
};
|
|
3890
|
+
const setHidden = (on) => {
|
|
3891
|
+
hiddenOn = on;
|
|
3892
|
+
root.hidden = on || previewOn;
|
|
3893
|
+
applyHeight();
|
|
3894
|
+
};
|
|
3895
|
+
togglePill.addEventListener("click", () => {
|
|
3896
|
+
collapsed = !collapsed;
|
|
3897
|
+
applyHeight();
|
|
3898
|
+
});
|
|
3899
|
+
const act = (a) => opts.onAction(a);
|
|
3900
|
+
dockBtn.addEventListener("click", () => {
|
|
3901
|
+
dock = dock === "top" ? "bottom" : "top";
|
|
3902
|
+
applyHeight();
|
|
3903
|
+
act({ action: "dock", position: dock });
|
|
3904
|
+
});
|
|
3905
|
+
showPanel.addEventListener("click", () => act({ action: "show-panel" }));
|
|
3906
|
+
preview.addEventListener("click", () => act({ action: "preview" }));
|
|
3907
|
+
previewExit.addEventListener("click", () => act({ action: "exit-preview" }));
|
|
3908
|
+
exit.addEventListener("click", () => act({ action: "exit" }));
|
|
3909
|
+
save.addEventListener("click", () => act({ action: "save", exit: false }));
|
|
3910
|
+
saveMore.addEventListener("click", (e) => {
|
|
3911
|
+
e.stopPropagation();
|
|
3912
|
+
saveMenu.hidden = !saveMenu.hidden;
|
|
3913
|
+
});
|
|
3914
|
+
saveExit.addEventListener("click", () => {
|
|
3915
|
+
saveMenu.hidden = true;
|
|
3916
|
+
act({ action: "save", exit: true });
|
|
3917
|
+
});
|
|
3918
|
+
const closeMenu = () => {
|
|
3919
|
+
saveMenu.hidden = true;
|
|
3920
|
+
};
|
|
3921
|
+
document.addEventListener("click", closeMenu);
|
|
3922
|
+
let current = null;
|
|
3923
|
+
const render = () => {
|
|
3924
|
+
const s = current;
|
|
3925
|
+
if (!s) return;
|
|
3926
|
+
const date = shortDate(s.createdAt);
|
|
3927
|
+
nameEl.textContent = `${s.guideName.trim() || "Sin nombre"}${date ? ` \xB7 ${date}` : ""}`;
|
|
3928
|
+
if (s.status) {
|
|
3929
|
+
statusEl.hidden = false;
|
|
3930
|
+
statusEl.textContent = s.status.label;
|
|
3931
|
+
statusEl.dataset.tone = s.status.tone;
|
|
3932
|
+
statusEl.title = "Estado de la gu\xEDa (se cambia desde la lista de gu\xEDas)";
|
|
3933
|
+
} else {
|
|
3934
|
+
statusEl.hidden = true;
|
|
3935
|
+
}
|
|
3936
|
+
save.innerHTML = s.saving ? `${svg("spinner", 16)}<span>Guardando\u2026</span>` : "<span>Guardar</span>";
|
|
3937
|
+
save.disabled = s.saving;
|
|
3938
|
+
saveExit.disabled = s.saving;
|
|
3939
|
+
stepsList.replaceChildren();
|
|
3940
|
+
const activation = stepCard(svg("cursor", 22), "Activaci\xF3n", s.section === "activation");
|
|
3941
|
+
activation.addEventListener("click", () => act({ action: "select-activation" }));
|
|
3942
|
+
stepsList.append(activation);
|
|
3943
|
+
s.steps.forEach((st, i) => {
|
|
3944
|
+
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>';
|
|
3945
|
+
const card = stepCard(thumb, st.label, s.section === "step" && s.activeStep === i);
|
|
3946
|
+
card.addEventListener("click", () => act({ action: "select-step", index: i }));
|
|
3947
|
+
stepsList.append(card);
|
|
3948
|
+
});
|
|
3949
|
+
const add = el("button", "veo-step-add", `${svg("plus", 18)}<span>Agregar paso</span>`);
|
|
3950
|
+
add.type = "button";
|
|
3951
|
+
add.addEventListener("click", () => act({ action: "add-step" }));
|
|
3952
|
+
stepsList.append(add);
|
|
3953
|
+
};
|
|
3954
|
+
applyHeight();
|
|
3955
|
+
return {
|
|
3956
|
+
setState: (state) => {
|
|
3957
|
+
current = state;
|
|
3958
|
+
render();
|
|
3959
|
+
},
|
|
3960
|
+
height,
|
|
3961
|
+
dock: () => dock,
|
|
3962
|
+
setPreview,
|
|
3963
|
+
setHidden,
|
|
3964
|
+
onHeightChange: (cb) => {
|
|
3965
|
+
heightCb = cb;
|
|
3966
|
+
},
|
|
3967
|
+
teardown: () => {
|
|
3968
|
+
document.removeEventListener("click", closeMenu);
|
|
3969
|
+
html.style.marginTop = prevMarginTop;
|
|
3970
|
+
html.style.marginBottom = prevMarginBottom;
|
|
3971
|
+
host.remove();
|
|
3972
|
+
}
|
|
3973
|
+
};
|
|
3974
|
+
}
|
|
3975
|
+
function stepCard(inner, label, active) {
|
|
3976
|
+
const b = el(
|
|
3977
|
+
"button",
|
|
3978
|
+
`veo-step${active ? " is-active" : ""}`,
|
|
3979
|
+
`<div class="veo-step-box">${inner}</div><span class="veo-step-label"></span>`
|
|
3980
|
+
);
|
|
3981
|
+
b.type = "button";
|
|
3982
|
+
b.querySelector(".veo-step-label").textContent = label;
|
|
3983
|
+
b.setAttribute("aria-pressed", active ? "true" : "false");
|
|
3984
|
+
return b;
|
|
3985
|
+
}
|
|
3986
|
+
var CHROME_CSS = `
|
|
3987
|
+
:host { all: initial; }
|
|
3988
|
+
.veo-chrome {
|
|
3989
|
+
position: fixed; top: 0; left: 0; right: 0;
|
|
3990
|
+
display: flex; flex-direction: column;
|
|
3991
|
+
z-index: 2147483646;
|
|
3992
|
+
font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
|
|
3993
|
+
font-size: 14px; color: #1c1917;
|
|
3994
|
+
}
|
|
3995
|
+
.veo-chrome[hidden] { display: none; }
|
|
3996
|
+
.veo-chrome.is-bottom { top: auto; bottom: 0; flex-direction: column-reverse; }
|
|
3997
|
+
.veo-chrome.is-bottom .veo-tb-menu { top: auto; bottom: calc(100% + 8px); }
|
|
3998
|
+
.veo-chrome.is-bottom .veo-steps { border-bottom: 0; border-top: 1px solid #d6cfc8; }
|
|
3999
|
+
.veo-chrome.is-bottom .veo-steps-toggle { top: auto; bottom: var(--veo-chrome-h, ${CHROME_TOPBAR_H + CHROME_STEPS_H}px); transform: translate(-50%, 50%); }
|
|
4000
|
+
.veo-preview-pill {
|
|
4001
|
+
position: fixed; top: 28px; left: 50%; transform: translateX(-50%);
|
|
4002
|
+
z-index: 2147483646;
|
|
4003
|
+
display: inline-flex; align-items: center; gap: 12px;
|
|
4004
|
+
background: #2b2623; color: #fff; border-radius: 999px; padding: 12px 20px;
|
|
4005
|
+
font-family: system-ui, -apple-system, "Segoe UI", sans-serif; font-size: 15px; font-weight: 500;
|
|
4006
|
+
box-shadow: 0 8px 24px rgba(0,0,0,0.3);
|
|
4007
|
+
}
|
|
4008
|
+
.veo-preview-pill[hidden] { display: none; }
|
|
4009
|
+
.veo-preview-label { display: inline-flex; align-items: center; gap: 10px; padding-right: 12px; border-right: 1px solid rgba(255,255,255,0.3); }
|
|
4010
|
+
.veo-preview-exit { border: 0; background: transparent; color: #fff; font: inherit; cursor: pointer; padding: 0 2px; }
|
|
4011
|
+
.veo-preview-exit:hover { text-decoration: underline; }
|
|
4012
|
+
.veo-tb {
|
|
4013
|
+
height: ${CHROME_TOPBAR_H}px; box-sizing: border-box;
|
|
4014
|
+
display: flex; align-items: center; justify-content: space-between;
|
|
4015
|
+
padding: 0 20px; gap: 16px;
|
|
4016
|
+
background: #2b2623; color: #fff;
|
|
4017
|
+
}
|
|
4018
|
+
.veo-tb-left, .veo-tb-right { display: flex; align-items: center; gap: 12px; min-width: 0; }
|
|
4019
|
+
.veo-tb-brand {
|
|
4020
|
+
width: 36px; height: 36px; border-radius: 999px; background: #b74d00;
|
|
4021
|
+
display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
|
|
4022
|
+
}
|
|
4023
|
+
.veo-tb-name { font-weight: 700; font-size: 16px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
4024
|
+
.veo-tb-status { display: inline-flex; align-items: center; padding: 2px 8px; border-radius: 999px; font-size: 11px; font-weight: 600; letter-spacing: 0.02em; white-space: nowrap; background: rgba(255,255,255,0.18); color: #fff; }
|
|
4025
|
+
.veo-tb-status[data-tone="live"] { background: #16a34a; }
|
|
4026
|
+
.veo-tb-status[data-tone="testing"] { background: #b45309; }
|
|
4027
|
+
.veo-tb-status[data-tone="review"] { background: #7c3aed; }
|
|
4028
|
+
.veo-tb-status[data-tone="draft"] { background: #0f766e; }
|
|
4029
|
+
.veo-tb-status[data-tone="paused"] { background: rgba(255,255,255,0.28); }
|
|
4030
|
+
.veo-tb-sep { width: 1px; height: 24px; background: rgba(255,255,255,0.25); }
|
|
4031
|
+
.veo-tb-vsep { width: 1px; height: 28px; background: rgba(255,255,255,0.25); margin: 0 4px; }
|
|
4032
|
+
.veo-tb-app { display: inline-flex; align-items: center; gap: 8px; color: rgba(255,255,255,0.85); white-space: nowrap; }
|
|
4033
|
+
.veo-tb-icon {
|
|
4034
|
+
width: 42px; height: 42px; border-radius: 10px; border: 0;
|
|
4035
|
+
background: rgba(255,255,255,0.12); color: #fff; cursor: pointer;
|
|
4036
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
4037
|
+
}
|
|
4038
|
+
.veo-tb-icon:hover { background: rgba(255,255,255,0.22); }
|
|
4039
|
+
.veo-tb-text { border: 0; background: transparent; color: #fff; font: inherit; font-size: 15px; cursor: pointer; padding: 8px 6px; }
|
|
4040
|
+
.veo-tb-text:hover { text-decoration: underline; }
|
|
4041
|
+
.veo-tb-save { position: relative; display: inline-flex; border-radius: 10px; overflow: visible; }
|
|
4042
|
+
.veo-tb-save-main, .veo-tb-save-more {
|
|
4043
|
+
border: 0; background: #b74d00; color: #fff; font: inherit; font-weight: 600; font-size: 15px;
|
|
4044
|
+
cursor: pointer; display: inline-flex; align-items: center; gap: 8px; height: 42px;
|
|
4045
|
+
}
|
|
4046
|
+
.veo-tb-save-main { padding: 0 8px 0 18px; border-radius: 10px 0 0 10px; }
|
|
4047
|
+
.veo-tb-save-more { padding: 0 12px 0 6px; border-radius: 0 10px 10px 0; }
|
|
4048
|
+
.veo-tb-save-main:hover, .veo-tb-save-more:hover { background: #953c00; }
|
|
4049
|
+
.veo-tb-save-main:disabled { opacity: 0.7; cursor: default; }
|
|
4050
|
+
.veo-tb-menu {
|
|
4051
|
+
position: absolute; right: 0; top: calc(100% + 8px); min-width: 220px;
|
|
4052
|
+
background: #fff; color: #1c1917; border-radius: 12px; padding: 6px;
|
|
4053
|
+
box-shadow: 0 12px 32px rgba(0,0,0,0.22);
|
|
4054
|
+
}
|
|
4055
|
+
.veo-tb-menu-item {
|
|
4056
|
+
display: block; width: 100%; text-align: left; border: 0; background: transparent;
|
|
4057
|
+
font: inherit; font-size: 15px; padding: 10px 14px; border-radius: 8px; cursor: pointer;
|
|
4058
|
+
}
|
|
4059
|
+
.veo-tb-menu-item:hover { background: #f5efe9; }
|
|
4060
|
+
.veo-steps {
|
|
4061
|
+
height: ${CHROME_STEPS_H}px; box-sizing: border-box;
|
|
4062
|
+
background: #e7e1dc; border-bottom: 1px solid #d6cfc8;
|
|
4063
|
+
padding: 16px 28px 0; overflow-x: auto;
|
|
4064
|
+
}
|
|
4065
|
+
.veo-steps[hidden] { display: none; }
|
|
4066
|
+
.veo-steps-list { display: flex; align-items: flex-start; gap: 20px; }
|
|
4067
|
+
.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; }
|
|
4068
|
+
.veo-step-box {
|
|
4069
|
+
width: 116px; height: 64px; border-radius: 10px; background: #fff; border: 2px solid transparent;
|
|
4070
|
+
display: flex; align-items: center; justify-content: center; color: #2b2623;
|
|
4071
|
+
box-shadow: 0 1px 2px rgba(0,0,0,0.06);
|
|
4072
|
+
}
|
|
4073
|
+
.veo-step.is-active .veo-step-box { border-color: #b74d00; }
|
|
4074
|
+
.veo-step-label { font-size: 13px; color: #6b635d; }
|
|
4075
|
+
.veo-step.is-active .veo-step-label { color: #2b2623; font-weight: 600; }
|
|
4076
|
+
.veo-thumb { width: 72px; height: 36px; border: 1.5px solid #c9c2bb; border-radius: 6px; padding: 6px 7px; box-sizing: border-box; display: flex; flex-direction: column; gap: 4px; }
|
|
4077
|
+
.veo-thumb i { display: block; height: 3px; border-radius: 2px; background: #2b2623; width: 70%; }
|
|
4078
|
+
.veo-thumb i + i { width: 45%; background: #c9c2bb; }
|
|
4079
|
+
.veo-thumb b { display: block; height: 6px; width: 24px; border-radius: 2px; background: #b74d00; align-self: flex-end; }
|
|
4080
|
+
.veo-thumb-inline { border-style: dashed; }
|
|
4081
|
+
.veo-thumb-inline i { width: 100%; }
|
|
4082
|
+
.veo-step-add { border: 0; background: transparent; font: inherit; font-size: 15px; color: #6b635d; cursor: pointer; display: inline-flex; align-items: center; gap: 8px; height: 64px; padding: 0 8px; }
|
|
4083
|
+
.veo-step-add:hover { color: #2b2623; }
|
|
4084
|
+
.veo-steps-toggle {
|
|
4085
|
+
position: absolute; left: 50%; top: var(--veo-chrome-h, ${CHROME_TOPBAR_H + CHROME_STEPS_H}px);
|
|
4086
|
+
transform: translate(-50%, -50%);
|
|
4087
|
+
border: 0; background: #2b2623; color: #fff; font: inherit; font-size: 14px; font-weight: 500;
|
|
4088
|
+
border-radius: 999px; padding: 10px 18px; cursor: pointer;
|
|
4089
|
+
display: inline-flex; align-items: center; gap: 8px;
|
|
4090
|
+
box-shadow: 0 6px 18px rgba(0,0,0,0.25);
|
|
4091
|
+
}
|
|
4092
|
+
`;
|
|
4093
|
+
|
|
3517
4094
|
// src/plugins/builder/builder-panel.ts
|
|
3518
4095
|
var DEFAULT_PANEL_PATH = "/guides/design";
|
|
3519
|
-
var PANEL_W =
|
|
3520
|
-
var PANEL_H =
|
|
4096
|
+
var PANEL_W = 484;
|
|
4097
|
+
var PANEL_H = 660;
|
|
3521
4098
|
var MIN_W = 320;
|
|
3522
4099
|
var MIN_H = 320;
|
|
3523
4100
|
var MARGIN = 16;
|
|
4101
|
+
var HEADER_H = 52;
|
|
3524
4102
|
function injectBuilderPanel(opts) {
|
|
3525
4103
|
if (!hasWindow() || !hasDocument()) {
|
|
3526
|
-
return {
|
|
3527
|
-
|
|
4104
|
+
return {
|
|
4105
|
+
target: () => null,
|
|
4106
|
+
frameRect: () => null,
|
|
4107
|
+
teardown: () => {
|
|
4108
|
+
},
|
|
4109
|
+
setTitle: () => {
|
|
4110
|
+
},
|
|
4111
|
+
setVisible: () => {
|
|
4112
|
+
},
|
|
4113
|
+
isVisible: () => false,
|
|
4114
|
+
setTopOffset: () => {
|
|
4115
|
+
}
|
|
4116
|
+
};
|
|
3528
4117
|
}
|
|
3529
4118
|
const panelUrl = buildPanelUrl(opts);
|
|
3530
4119
|
const host = document.createElement("div");
|
|
@@ -3534,43 +4123,68 @@ function injectBuilderPanel(opts) {
|
|
|
3534
4123
|
style.textContent = PANEL_CSS;
|
|
3535
4124
|
const card = document.createElement("div");
|
|
3536
4125
|
card.className = "veo-panel";
|
|
3537
|
-
let
|
|
3538
|
-
let
|
|
4126
|
+
let topOffset = opts.topOffset ?? 0;
|
|
4127
|
+
let left = 40;
|
|
4128
|
+
let top = topOffset + MARGIN;
|
|
3539
4129
|
card.style.left = `${left}px`;
|
|
3540
4130
|
card.style.top = `${top}px`;
|
|
3541
4131
|
card.style.width = `${PANEL_W}px`;
|
|
3542
4132
|
card.style.height = `${PANEL_H}px`;
|
|
3543
4133
|
const header = document.createElement("div");
|
|
3544
4134
|
header.className = "veo-panel-header";
|
|
4135
|
+
const grip = document.createElement("span");
|
|
4136
|
+
grip.className = "veo-panel-grip";
|
|
4137
|
+
grip.setAttribute("aria-hidden", "true");
|
|
4138
|
+
grip.textContent = "\xB7\xB7\xB7";
|
|
3545
4139
|
const title = document.createElement("span");
|
|
3546
4140
|
title.className = "veo-panel-title";
|
|
3547
4141
|
title.textContent = "OnUser \xB7 Editor";
|
|
3548
4142
|
const actions = document.createElement("div");
|
|
3549
4143
|
actions.className = "veo-panel-actions";
|
|
3550
|
-
const popout =
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
popout
|
|
3554
|
-
|
|
3555
|
-
popout.textContent = "\u29C9";
|
|
3556
|
-
const close = document.createElement("button");
|
|
3557
|
-
close.className = "veo-panel-btn veo-panel-close";
|
|
3558
|
-
close.type = "button";
|
|
3559
|
-
close.title = "Cerrar";
|
|
3560
|
-
close.setAttribute("aria-label", "Cerrar");
|
|
3561
|
-
close.textContent = "\u2715";
|
|
3562
|
-
actions.append(popout, close);
|
|
3563
|
-
header.append(title, actions);
|
|
4144
|
+
const popout = panelButton(ICON_POPOUT, "Abrir en ventana aparte");
|
|
4145
|
+
const maximize = panelButton(ICON_EXPAND, "Maximizar");
|
|
4146
|
+
const minimize = panelButton(ICON_MINUS, "Minimizar");
|
|
4147
|
+
actions.append(popout, maximize, minimize);
|
|
4148
|
+
header.append(grip, title, actions);
|
|
3564
4149
|
const iframe = document.createElement("iframe");
|
|
3565
4150
|
iframe.className = "veo-panel-frame";
|
|
3566
4151
|
iframe.title = "Editor de Veo";
|
|
3567
4152
|
iframe.src = panelUrl;
|
|
3568
|
-
const
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
card.append(header, iframe,
|
|
4153
|
+
const resizeGrip = document.createElement("div");
|
|
4154
|
+
resizeGrip.className = "veo-panel-resize";
|
|
4155
|
+
resizeGrip.setAttribute("aria-hidden", "true");
|
|
4156
|
+
card.append(header, iframe, resizeGrip);
|
|
3572
4157
|
shadow.append(style, card);
|
|
3573
4158
|
document.body.appendChild(host);
|
|
4159
|
+
let visible = true;
|
|
4160
|
+
let maximized = false;
|
|
4161
|
+
let restore = null;
|
|
4162
|
+
const setVisible = (next) => {
|
|
4163
|
+
visible = next;
|
|
4164
|
+
card.style.display = next && !(popped && !popped.closed) ? "" : "none";
|
|
4165
|
+
};
|
|
4166
|
+
minimize.addEventListener("click", () => setVisible(false));
|
|
4167
|
+
maximize.addEventListener("click", () => {
|
|
4168
|
+
maximized = !maximized;
|
|
4169
|
+
if (maximized) {
|
|
4170
|
+
restore = { left, top, w: card.offsetWidth, h: card.offsetHeight };
|
|
4171
|
+
left = MARGIN;
|
|
4172
|
+
top = topOffset + MARGIN;
|
|
4173
|
+
card.style.left = `${left}px`;
|
|
4174
|
+
card.style.top = `${top}px`;
|
|
4175
|
+
card.style.width = `${Math.max(MIN_W, window.innerWidth - MARGIN * 2)}px`;
|
|
4176
|
+
card.style.height = `${Math.max(MIN_H, window.innerHeight - top - MARGIN)}px`;
|
|
4177
|
+
maximize.title = "Restaurar";
|
|
4178
|
+
} else if (restore) {
|
|
4179
|
+
left = restore.left;
|
|
4180
|
+
top = restore.top;
|
|
4181
|
+
card.style.left = `${left}px`;
|
|
4182
|
+
card.style.top = `${top}px`;
|
|
4183
|
+
card.style.width = `${restore.w}px`;
|
|
4184
|
+
card.style.height = `${restore.h}px`;
|
|
4185
|
+
maximize.title = "Maximizar";
|
|
4186
|
+
}
|
|
4187
|
+
});
|
|
3574
4188
|
let popped = null;
|
|
3575
4189
|
let pollTimer;
|
|
3576
4190
|
const stopPoll = () => {
|
|
@@ -3579,7 +4193,6 @@ function injectBuilderPanel(opts) {
|
|
|
3579
4193
|
pollTimer = void 0;
|
|
3580
4194
|
}
|
|
3581
4195
|
};
|
|
3582
|
-
close.addEventListener("click", () => opts.onClose());
|
|
3583
4196
|
popout.addEventListener("click", () => {
|
|
3584
4197
|
const win = window.open(
|
|
3585
4198
|
panelUrl,
|
|
@@ -3597,7 +4210,7 @@ function injectBuilderPanel(opts) {
|
|
|
3597
4210
|
}, 600);
|
|
3598
4211
|
});
|
|
3599
4212
|
header.addEventListener("mousedown", (e) => {
|
|
3600
|
-
if (e.target?.
|
|
4213
|
+
if (e.target?.closest(".veo-panel-btn")) return;
|
|
3601
4214
|
e.preventDefault();
|
|
3602
4215
|
const sx = e.clientX;
|
|
3603
4216
|
const sy = e.clientY;
|
|
@@ -3606,7 +4219,7 @@ function injectBuilderPanel(opts) {
|
|
|
3606
4219
|
iframe.style.pointerEvents = "none";
|
|
3607
4220
|
const move = (ev) => {
|
|
3608
4221
|
left = clamp3(ol + (ev.clientX - sx), 0, Math.max(0, window.innerWidth - card.offsetWidth));
|
|
3609
|
-
top = clamp3(ot + (ev.clientY - sy),
|
|
4222
|
+
top = clamp3(ot + (ev.clientY - sy), topOffset, Math.max(topOffset, window.innerHeight - 40));
|
|
3610
4223
|
card.style.left = `${left}px`;
|
|
3611
4224
|
card.style.top = `${top}px`;
|
|
3612
4225
|
};
|
|
@@ -3618,7 +4231,7 @@ function injectBuilderPanel(opts) {
|
|
|
3618
4231
|
window.addEventListener("mousemove", move);
|
|
3619
4232
|
window.addEventListener("mouseup", up);
|
|
3620
4233
|
});
|
|
3621
|
-
|
|
4234
|
+
resizeGrip.addEventListener("mousedown", (e) => {
|
|
3622
4235
|
e.preventDefault();
|
|
3623
4236
|
e.stopPropagation();
|
|
3624
4237
|
const sx = e.clientX;
|
|
@@ -3645,9 +4258,33 @@ function injectBuilderPanel(opts) {
|
|
|
3645
4258
|
stopPoll();
|
|
3646
4259
|
if (popped && !popped.closed) popped.close();
|
|
3647
4260
|
host.remove();
|
|
4261
|
+
},
|
|
4262
|
+
setTitle: (t) => {
|
|
4263
|
+
title.textContent = t;
|
|
4264
|
+
},
|
|
4265
|
+
setVisible,
|
|
4266
|
+
isVisible: () => visible,
|
|
4267
|
+
setTopOffset: (px) => {
|
|
4268
|
+
topOffset = px;
|
|
4269
|
+
if (top < topOffset + MARGIN) {
|
|
4270
|
+
top = topOffset + MARGIN;
|
|
4271
|
+
card.style.top = `${top}px`;
|
|
4272
|
+
}
|
|
3648
4273
|
}
|
|
3649
4274
|
};
|
|
3650
4275
|
}
|
|
4276
|
+
var ICON_POPOUT = '<path stroke-linecap="round" stroke-linejoin="round" d="m6.75 7.5 3 2.25-3 2.25m4.5 0h3m-9 8.25h13.5A2.25 2.25 0 0 0 21 18V6a2.25 2.25 0 0 0-2.25-2.25H5.25A2.25 2.25 0 0 0 3 6v12a2.25 2.25 0 0 0 2.25 2.25Z"/>';
|
|
4277
|
+
var ICON_EXPAND = '<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 3.75v4.5m0-4.5h4.5m-4.5 0L9 9M3.75 20.25v-4.5m0 4.5h4.5m-4.5 0L9 15M20.25 3.75h-4.5m4.5 0v4.5m0-4.5L15 9m5.25 11.25h-4.5m4.5 0v-4.5m0 4.5L15 15"/>';
|
|
4278
|
+
var ICON_MINUS = '<path stroke-linecap="round" stroke-linejoin="round" d="M5 12h14"/>';
|
|
4279
|
+
function panelButton(iconPath, label) {
|
|
4280
|
+
const b = document.createElement("button");
|
|
4281
|
+
b.className = "veo-panel-btn";
|
|
4282
|
+
b.type = "button";
|
|
4283
|
+
b.title = label;
|
|
4284
|
+
b.setAttribute("aria-label", label);
|
|
4285
|
+
b.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" aria-hidden="true">${iconPath}</svg>`;
|
|
4286
|
+
return b;
|
|
4287
|
+
}
|
|
3651
4288
|
function clamp3(v, min, max) {
|
|
3652
4289
|
return Math.min(Math.max(v, min), max);
|
|
3653
4290
|
}
|
|
@@ -3667,28 +4304,33 @@ var PANEL_CSS = `
|
|
|
3667
4304
|
max-width: 96vw; max-height: 94vh;
|
|
3668
4305
|
display: flex; flex-direction: column;
|
|
3669
4306
|
background: #fff;
|
|
3670
|
-
border-radius:
|
|
3671
|
-
box-shadow: 0 12px 40px rgba(0,0,0,0.
|
|
4307
|
+
border-radius: 14px;
|
|
4308
|
+
box-shadow: 0 12px 40px rgba(0,0,0,0.22);
|
|
3672
4309
|
overflow: hidden;
|
|
3673
4310
|
z-index: 2147483647;
|
|
3674
4311
|
font-family: system-ui, -apple-system, sans-serif;
|
|
3675
4312
|
}
|
|
3676
4313
|
.veo-panel-header {
|
|
3677
|
-
flex: 0 0 auto;
|
|
4314
|
+
position: relative; flex: 0 0 auto; height: ${HEADER_H}px; box-sizing: border-box;
|
|
3678
4315
|
display: flex; align-items: center; justify-content: space-between;
|
|
3679
|
-
padding:
|
|
3680
|
-
background: #
|
|
3681
|
-
font-size:
|
|
4316
|
+
padding: 10px 14px 0 22px;
|
|
4317
|
+
background: #fbf8f5; color: #1c1917; border-bottom: 1px solid #e8e2dc;
|
|
4318
|
+
font-size: 17px; font-weight: 700;
|
|
3682
4319
|
cursor: grab;
|
|
3683
4320
|
}
|
|
3684
4321
|
.veo-panel-header:active { cursor: grabbing; }
|
|
4322
|
+
.veo-panel-grip {
|
|
4323
|
+
position: absolute; top: 0; left: 50%; transform: translateX(-50%);
|
|
4324
|
+
color: #b5aca4; font-size: 14px; letter-spacing: 1px; line-height: 12px;
|
|
4325
|
+
}
|
|
4326
|
+
.veo-panel-title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
3685
4327
|
.veo-panel-actions { display: flex; gap: 2px; }
|
|
3686
4328
|
.veo-panel-btn {
|
|
3687
|
-
border: 0; background: transparent; color: #
|
|
3688
|
-
|
|
3689
|
-
padding:
|
|
4329
|
+
border: 0; background: transparent; color: #4b4540;
|
|
4330
|
+
cursor: pointer; line-height: 1; display: inline-flex; align-items: center;
|
|
4331
|
+
padding: 6px; border-radius: 8px;
|
|
3690
4332
|
}
|
|
3691
|
-
.veo-panel-btn:hover { background: rgba(
|
|
4333
|
+
.veo-panel-btn:hover { background: rgba(0,0,0,0.06); color: #1c1917; }
|
|
3692
4334
|
.veo-panel-frame { flex: 1 1 auto; width: 100%; border: 0; background: #fff; }
|
|
3693
4335
|
.veo-panel-resize {
|
|
3694
4336
|
position: absolute; right: 0; bottom: 0;
|
|
@@ -4028,9 +4670,9 @@ var PICKER_STYLES = `
|
|
|
4028
4670
|
z-index: ${PICKER_Z};
|
|
4029
4671
|
pointer-events: none;
|
|
4030
4672
|
box-sizing: border-box;
|
|
4031
|
-
background:
|
|
4032
|
-
border:
|
|
4033
|
-
border-radius:
|
|
4673
|
+
background: transparent;
|
|
4674
|
+
border: 3px dashed #b74d00;
|
|
4675
|
+
border-radius: 8px;
|
|
4034
4676
|
transition: top 60ms ease-out, left 60ms ease-out, width 60ms ease-out, height 60ms ease-out;
|
|
4035
4677
|
}
|
|
4036
4678
|
.veo-pick-label {
|
|
@@ -4038,30 +4680,48 @@ var PICKER_STYLES = `
|
|
|
4038
4680
|
z-index: ${PICKER_Z};
|
|
4039
4681
|
pointer-events: none;
|
|
4040
4682
|
max-width: 360px;
|
|
4041
|
-
background: #
|
|
4042
|
-
color: #
|
|
4683
|
+
background: #2b2623;
|
|
4684
|
+
color: #f5efe9;
|
|
4043
4685
|
font: 12px/1.45 ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
4044
4686
|
padding: 6px 9px;
|
|
4045
4687
|
border-radius: 6px;
|
|
4046
4688
|
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.35);
|
|
4047
4689
|
}
|
|
4048
|
-
.veo-pick-label .veo-pick-sel { color: #
|
|
4049
|
-
.veo-pick-label .veo-pick-dim { color: #
|
|
4690
|
+
.veo-pick-label .veo-pick-sel { color: #ffd1ad; word-break: break-all; }
|
|
4691
|
+
.veo-pick-label .veo-pick-dim { color: #c9c2bb; margin-top: 3px; }
|
|
4050
4692
|
.veo-pick-hint {
|
|
4051
4693
|
position: fixed;
|
|
4052
|
-
top:
|
|
4694
|
+
top: 28px;
|
|
4053
4695
|
left: 50%;
|
|
4054
4696
|
transform: translateX(-50%);
|
|
4055
4697
|
z-index: ${PICKER_Z};
|
|
4056
4698
|
pointer-events: none;
|
|
4057
|
-
|
|
4699
|
+
display: flex; align-items: center; gap: 16px;
|
|
4700
|
+
max-width: min(760px, calc(100vw - 32px));
|
|
4701
|
+
background: #2b2623;
|
|
4058
4702
|
color: #fff;
|
|
4059
|
-
font:
|
|
4060
|
-
padding:
|
|
4061
|
-
border-radius:
|
|
4062
|
-
box-shadow: 0
|
|
4703
|
+
font: 15px/1.4 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
4704
|
+
padding: 14px 18px 14px 16px;
|
|
4705
|
+
border-radius: 14px;
|
|
4706
|
+
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
|
|
4707
|
+
}
|
|
4708
|
+
.veo-pick-hint-icon {
|
|
4709
|
+
flex: 0 0 auto; width: 44px; height: 44px; border-radius: 999px;
|
|
4710
|
+
background: rgba(255,255,255,0.12);
|
|
4711
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
4063
4712
|
}
|
|
4713
|
+
.veo-pick-hint-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
|
|
4714
|
+
.veo-pick-hint-title { font-weight: 700; }
|
|
4715
|
+
.veo-pick-hint-sub { font-size: 13px; color: rgba(255,255,255,0.75); }
|
|
4716
|
+
.veo-pick-cancel {
|
|
4717
|
+
flex: 0 0 auto; pointer-events: auto;
|
|
4718
|
+
border: 0; border-radius: 10px; padding: 12px 18px;
|
|
4719
|
+
background: rgba(255,255,255,0.14); color: #fff;
|
|
4720
|
+
font: inherit; font-weight: 600; cursor: pointer;
|
|
4721
|
+
}
|
|
4722
|
+
.veo-pick-cancel:hover { background: rgba(255,255,255,0.24); }
|
|
4064
4723
|
`;
|
|
4724
|
+
var HINT_ICON = '<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" d="M7.5 3.75H6A2.25 2.25 0 0 0 3.75 6v1.5M16.5 3.75H18A2.25 2.25 0 0 1 20.25 6v1.5m0 9V18A2.25 2.25 0 0 1 18 20.25h-1.5m-9 0H6A2.25 2.25 0 0 1 3.75 18v-1.5M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"/></svg>';
|
|
4065
4725
|
var ElementPicker = class {
|
|
4066
4726
|
constructor() {
|
|
4067
4727
|
this.host = null;
|
|
@@ -4078,6 +4738,7 @@ var ElementPicker = class {
|
|
|
4078
4738
|
this.draw(target);
|
|
4079
4739
|
};
|
|
4080
4740
|
this.onClick = (event) => {
|
|
4741
|
+
if (event.altKey) return;
|
|
4081
4742
|
const target = this.current ?? (event.target instanceof Element ? event.target : null);
|
|
4082
4743
|
if (!target || this.isOwn(target)) return;
|
|
4083
4744
|
event.preventDefault();
|
|
@@ -4098,7 +4759,7 @@ var ElementPicker = class {
|
|
|
4098
4759
|
};
|
|
4099
4760
|
/** Traga mousedown/mouseup durante el picking (evita focus/active de la app). */
|
|
4100
4761
|
this.swallow = (event) => {
|
|
4101
|
-
if (this.isOwn(event.target)) return;
|
|
4762
|
+
if (event.altKey || this.isOwn(event.target)) return;
|
|
4102
4763
|
event.preventDefault();
|
|
4103
4764
|
event.stopPropagation();
|
|
4104
4765
|
};
|
|
@@ -4124,7 +4785,29 @@ var ElementPicker = class {
|
|
|
4124
4785
|
this.label.style.display = "none";
|
|
4125
4786
|
const hint = document.createElement("div");
|
|
4126
4787
|
hint.className = "veo-pick-hint";
|
|
4127
|
-
|
|
4788
|
+
const icon = document.createElement("span");
|
|
4789
|
+
icon.className = "veo-pick-hint-icon";
|
|
4790
|
+
icon.innerHTML = HINT_ICON;
|
|
4791
|
+
const text = document.createElement("div");
|
|
4792
|
+
text.className = "veo-pick-hint-text";
|
|
4793
|
+
const title = document.createElement("span");
|
|
4794
|
+
title.className = "veo-pick-hint-title";
|
|
4795
|
+
title.textContent = options.hint ?? "Selecciona un elemento existente para colocar la gu\xEDa.";
|
|
4796
|
+
const sub = document.createElement("span");
|
|
4797
|
+
sub.className = "veo-pick-hint-sub";
|
|
4798
|
+
sub.textContent = options.subhint ?? "Usa Alt + clic u Opci\xF3n + clic para abrir men\xFAs y desplegables.";
|
|
4799
|
+
text.append(title, sub);
|
|
4800
|
+
const cancel = document.createElement("button");
|
|
4801
|
+
cancel.className = "veo-pick-cancel";
|
|
4802
|
+
cancel.type = "button";
|
|
4803
|
+
cancel.textContent = "Cancelar";
|
|
4804
|
+
cancel.addEventListener("click", (e) => {
|
|
4805
|
+
e.stopPropagation();
|
|
4806
|
+
const cb = this.onCancel;
|
|
4807
|
+
this.stop();
|
|
4808
|
+
cb?.();
|
|
4809
|
+
});
|
|
4810
|
+
hint.append(icon, text, cancel);
|
|
4128
4811
|
shadow.append(style, this.box, this.label, hint);
|
|
4129
4812
|
document.body.appendChild(host);
|
|
4130
4813
|
this.host = host;
|
|
@@ -4222,6 +4905,7 @@ function initBuilderMode() {
|
|
|
4222
4905
|
if (!dashboardOrigin) return null;
|
|
4223
4906
|
let picker = null;
|
|
4224
4907
|
let panel = null;
|
|
4908
|
+
let chrome = null;
|
|
4225
4909
|
let staticTarget = null;
|
|
4226
4910
|
let manipulator = null;
|
|
4227
4911
|
let dropTarget = null;
|
|
@@ -4229,26 +4913,98 @@ function initBuilderMode() {
|
|
|
4229
4913
|
let previewStepIndex = 0;
|
|
4230
4914
|
let pendingPreview = null;
|
|
4231
4915
|
let lastPreview = null;
|
|
4916
|
+
let previewMode = false;
|
|
4917
|
+
let previewTrigger = null;
|
|
4918
|
+
let previewFired = false;
|
|
4919
|
+
let previewDelay = null;
|
|
4920
|
+
let previewDismissed = false;
|
|
4921
|
+
let panelWasVisible = true;
|
|
4232
4922
|
const getTarget = () => panel ? panel.target() : staticTarget;
|
|
4233
4923
|
const post = (event) => {
|
|
4234
4924
|
getTarget()?.postMessage({ source: VEO_BUILDER_SOURCE, token, ...event }, dashboardOrigin);
|
|
4235
4925
|
};
|
|
4236
|
-
const
|
|
4926
|
+
const previewStep = (cmd) => {
|
|
4237
4927
|
const steps = cmd.guide.guideSteps;
|
|
4238
|
-
|
|
4239
|
-
|
|
4928
|
+
return steps?.[cmd.guide.startStepIndex ?? 0];
|
|
4929
|
+
};
|
|
4930
|
+
const previewMatchesPage = (cmd) => stepMatchesPage(previewStep(cmd)?.pageLocation, window.location.href);
|
|
4931
|
+
const postPreviewStatus = (payload) => post({ type: "preview-status", payload });
|
|
4932
|
+
const withholdPreview = () => {
|
|
4933
|
+
manipulator?.detach();
|
|
4934
|
+
manipulator = null;
|
|
4935
|
+
dropTarget?.detach();
|
|
4936
|
+
dropTarget = null;
|
|
4937
|
+
closeGuidePreview();
|
|
4240
4938
|
};
|
|
4241
4939
|
const applyPreviewGated = (cmd) => {
|
|
4242
|
-
|
|
4243
|
-
if (
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
|
|
4940
|
+
const showNow = !cmd.honorTrigger;
|
|
4941
|
+
if (showNow) {
|
|
4942
|
+
disarmPreviewTrigger();
|
|
4943
|
+
cancelPreviewDelay();
|
|
4944
|
+
previewFired = true;
|
|
4945
|
+
previewDismissed = false;
|
|
4946
|
+
}
|
|
4947
|
+
lastPreview = showNow ? { ...cmd, honorTrigger: true } : cmd;
|
|
4948
|
+
if (!previewMatchesPage(cmd)) {
|
|
4949
|
+
cancelPreviewDelay();
|
|
4950
|
+
withholdPreview();
|
|
4951
|
+
postPreviewStatus({
|
|
4952
|
+
state: "page-mismatch",
|
|
4953
|
+
pattern: previewStep(cmd)?.pageLocation?.pattern ?? ""
|
|
4954
|
+
});
|
|
4955
|
+
return;
|
|
4251
4956
|
}
|
|
4957
|
+
const devices = cmd.guide.activationRules?.devices;
|
|
4958
|
+
if (!showNow && !previewMode && devices && !isDeviceAllowed(devices)) {
|
|
4959
|
+
cancelPreviewDelay();
|
|
4960
|
+
withholdPreview();
|
|
4961
|
+
postPreviewStatus({ state: "device-mismatch", devices });
|
|
4962
|
+
return;
|
|
4963
|
+
}
|
|
4964
|
+
applyPreview(lastPreview);
|
|
4965
|
+
};
|
|
4966
|
+
const disarmPreviewTrigger = () => {
|
|
4967
|
+
previewTrigger?.();
|
|
4968
|
+
previewTrigger = null;
|
|
4969
|
+
};
|
|
4970
|
+
const cancelPreviewDelay = () => {
|
|
4971
|
+
if (previewDelay) clearTimeout(previewDelay);
|
|
4972
|
+
previewDelay = null;
|
|
4973
|
+
};
|
|
4974
|
+
const armPreviewTrigger = (selector, trigger) => {
|
|
4975
|
+
disarmPreviewTrigger();
|
|
4976
|
+
const onFire = (e) => {
|
|
4977
|
+
const target = e.target;
|
|
4978
|
+
if (!(target instanceof Element)) return;
|
|
4979
|
+
if (target.closest("[data-veo-builder-chrome],[data-veo-builder-panel],[data-veo-picker]")) {
|
|
4980
|
+
return;
|
|
4981
|
+
}
|
|
4982
|
+
try {
|
|
4983
|
+
if (!target.closest(selector)) return;
|
|
4984
|
+
} catch {
|
|
4985
|
+
return;
|
|
4986
|
+
}
|
|
4987
|
+
disarmPreviewTrigger();
|
|
4988
|
+
previewFired = true;
|
|
4989
|
+
previewDismissed = false;
|
|
4990
|
+
if (lastPreview) applyPreviewGated(lastPreview);
|
|
4991
|
+
};
|
|
4992
|
+
document.addEventListener("click", onFire, true);
|
|
4993
|
+
if (trigger === "on_hover") document.addEventListener("mouseover", onFire, true);
|
|
4994
|
+
previewTrigger = () => {
|
|
4995
|
+
document.removeEventListener("click", onFire, true);
|
|
4996
|
+
document.removeEventListener("mouseover", onFire, true);
|
|
4997
|
+
};
|
|
4998
|
+
postPreviewStatus({ state: "waiting-trigger", trigger, selector });
|
|
4999
|
+
};
|
|
5000
|
+
const armPreviewDelay = (delayMs) => {
|
|
5001
|
+
cancelPreviewDelay();
|
|
5002
|
+
previewDelay = setTimeout(() => {
|
|
5003
|
+
previewDelay = null;
|
|
5004
|
+
previewFired = true;
|
|
5005
|
+
if (lastPreview) applyPreviewGated(lastPreview);
|
|
5006
|
+
}, delayMs);
|
|
5007
|
+
postPreviewStatus({ state: "waiting-delay", delayMs });
|
|
4252
5008
|
};
|
|
4253
5009
|
const applyPreview = (cmd) => {
|
|
4254
5010
|
manipulator?.detach();
|
|
@@ -4256,8 +5012,47 @@ function initBuilderMode() {
|
|
|
4256
5012
|
dropTarget?.detach();
|
|
4257
5013
|
dropTarget = null;
|
|
4258
5014
|
previewStepIndex = cmd.guide.startStepIndex ?? 0;
|
|
4259
|
-
const
|
|
4260
|
-
|
|
5015
|
+
const rules = cmd.guide.activationRules;
|
|
5016
|
+
const trig = rules?.trigger;
|
|
5017
|
+
const sel = rules?.selector?.trim();
|
|
5018
|
+
const gate = cmd.honorTrigger && !previewFired && !previewMode;
|
|
5019
|
+
const waitsForTarget = (trig === "on_click" || trig === "on_hover") && (!isAutomaticActivation(rules) || previewDismissed);
|
|
5020
|
+
if (gate && waitsForTarget && sel) {
|
|
5021
|
+
cancelPreviewDelay();
|
|
5022
|
+
closeGuidePreview();
|
|
5023
|
+
armPreviewTrigger(sel, trig);
|
|
5024
|
+
return;
|
|
5025
|
+
}
|
|
5026
|
+
const delayMs = activationDelayMs(rules);
|
|
5027
|
+
if (gate && delayMs > 0) {
|
|
5028
|
+
disarmPreviewTrigger();
|
|
5029
|
+
closeGuidePreview();
|
|
5030
|
+
if (!previewDelay) armPreviewDelay(delayMs);
|
|
5031
|
+
return;
|
|
5032
|
+
}
|
|
5033
|
+
disarmPreviewTrigger();
|
|
5034
|
+
cancelPreviewDelay();
|
|
5035
|
+
const handle = previewGuide({
|
|
5036
|
+
...cmd.guide,
|
|
5037
|
+
onClosed: () => {
|
|
5038
|
+
manipulator?.detach();
|
|
5039
|
+
manipulator = null;
|
|
5040
|
+
dropTarget?.detach();
|
|
5041
|
+
dropTarget = null;
|
|
5042
|
+
previewFired = false;
|
|
5043
|
+
previewDismissed = true;
|
|
5044
|
+
if (previewMode) {
|
|
5045
|
+
const r = lastPreview?.guide.activationRules;
|
|
5046
|
+
const t = r?.trigger;
|
|
5047
|
+
const selector = r?.selector?.trim();
|
|
5048
|
+
if ((t === "on_click" || t === "on_hover") && selector) armPreviewTrigger(selector, t);
|
|
5049
|
+
return;
|
|
5050
|
+
}
|
|
5051
|
+
if (lastPreview) applyPreviewGated(lastPreview);
|
|
5052
|
+
}
|
|
5053
|
+
});
|
|
5054
|
+
if (cmd.honorTrigger) postPreviewStatus({ state: "shown" });
|
|
5055
|
+
if (!cmd.editable || previewMode) return;
|
|
4261
5056
|
void handle.ready.then((result) => {
|
|
4262
5057
|
if (!result.rendered) return;
|
|
4263
5058
|
const host = handle.host();
|
|
@@ -4325,26 +5120,57 @@ function initBuilderMode() {
|
|
|
4325
5120
|
const handleCommand = (cmd) => {
|
|
4326
5121
|
switch (cmd.type) {
|
|
4327
5122
|
case "panel-ready":
|
|
4328
|
-
post({ type: "ready" });
|
|
5123
|
+
post(chrome ? { type: "ready", chrome: true } : { type: "ready" });
|
|
5124
|
+
break;
|
|
5125
|
+
case "editor-state":
|
|
5126
|
+
chrome?.setState(cmd.state);
|
|
5127
|
+
panel?.setTitle(
|
|
5128
|
+
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"
|
|
5129
|
+
);
|
|
5130
|
+
break;
|
|
5131
|
+
case "panel-visibility":
|
|
5132
|
+
panel?.setVisible(cmd.visible);
|
|
4329
5133
|
break;
|
|
4330
|
-
case "start-picker":
|
|
5134
|
+
case "start-picker": {
|
|
4331
5135
|
picker?.stop();
|
|
5136
|
+
const panelWasShown = panel?.isVisible() ?? false;
|
|
5137
|
+
if (panelWasShown) panel?.setVisible(false);
|
|
5138
|
+
chrome?.setHidden(true);
|
|
5139
|
+
const previewToRestore = lastPreview;
|
|
5140
|
+
if (previewToRestore) {
|
|
5141
|
+
manipulator?.detach();
|
|
5142
|
+
manipulator = null;
|
|
5143
|
+
dropTarget?.detach();
|
|
5144
|
+
dropTarget = null;
|
|
5145
|
+
closeGuidePreview();
|
|
5146
|
+
}
|
|
5147
|
+
const restorePanel = () => {
|
|
5148
|
+
chrome?.setHidden(false);
|
|
5149
|
+
if (panelWasShown) panel?.setVisible(true);
|
|
5150
|
+
if (previewToRestore && lastPreview === previewToRestore) {
|
|
5151
|
+
applyPreviewGated(previewToRestore);
|
|
5152
|
+
}
|
|
5153
|
+
};
|
|
4332
5154
|
picker = startElementPicker({
|
|
4333
5155
|
onPick: (payload) => {
|
|
4334
5156
|
picker = null;
|
|
5157
|
+
restorePanel();
|
|
4335
5158
|
post({ type: "picked", payload });
|
|
4336
5159
|
},
|
|
4337
5160
|
onCancel: () => {
|
|
4338
5161
|
picker = null;
|
|
5162
|
+
restorePanel();
|
|
4339
5163
|
post({ type: "pick-cancelled" });
|
|
4340
5164
|
},
|
|
4341
5165
|
...cmd.maxAncestors !== void 0 ? { maxAncestors: cmd.maxAncestors } : {},
|
|
4342
5166
|
...cmd.hint !== void 0 ? { hint: cmd.hint } : {}
|
|
4343
5167
|
});
|
|
4344
5168
|
break;
|
|
5169
|
+
}
|
|
4345
5170
|
case "stop-picker":
|
|
4346
5171
|
picker?.stop();
|
|
4347
5172
|
picker = null;
|
|
5173
|
+
chrome?.setHidden(false);
|
|
4348
5174
|
break;
|
|
4349
5175
|
case "preview":
|
|
4350
5176
|
if (!cmd.guide) break;
|
|
@@ -4362,6 +5188,10 @@ function initBuilderMode() {
|
|
|
4362
5188
|
hideDragGhost();
|
|
4363
5189
|
pendingPreview = null;
|
|
4364
5190
|
lastPreview = null;
|
|
5191
|
+
disarmPreviewTrigger();
|
|
5192
|
+
cancelPreviewDelay();
|
|
5193
|
+
previewFired = false;
|
|
5194
|
+
previewDismissed = false;
|
|
4365
5195
|
closeGuidePreview();
|
|
4366
5196
|
break;
|
|
4367
5197
|
case "teardown":
|
|
@@ -4413,21 +5243,62 @@ function initBuilderMode() {
|
|
|
4413
5243
|
dropTarget = null;
|
|
4414
5244
|
hideDragGhost();
|
|
4415
5245
|
pendingPreview = null;
|
|
5246
|
+
disarmPreviewTrigger();
|
|
5247
|
+
cancelPreviewDelay();
|
|
4416
5248
|
closeGuidePreview();
|
|
4417
5249
|
post({ type: "closed" });
|
|
4418
5250
|
panel?.teardown();
|
|
4419
5251
|
panel = null;
|
|
5252
|
+
chrome?.teardown();
|
|
5253
|
+
chrome = null;
|
|
4420
5254
|
clearBuilderToken();
|
|
4421
5255
|
};
|
|
4422
5256
|
if (ctx.panel) {
|
|
5257
|
+
chrome = injectBuilderChrome({
|
|
5258
|
+
appLabel: window.location.hostname,
|
|
5259
|
+
onAction: (action) => {
|
|
5260
|
+
switch (action.action) {
|
|
5261
|
+
// Controles que resuelve el SDK solo (no van al panel).
|
|
5262
|
+
case "dock":
|
|
5263
|
+
panel?.setTopOffset(action.position === "top" ? chrome?.height() ?? 0 : 0);
|
|
5264
|
+
return;
|
|
5265
|
+
case "show-panel":
|
|
5266
|
+
panel?.setVisible(true);
|
|
5267
|
+
return;
|
|
5268
|
+
case "preview":
|
|
5269
|
+
if (previewMode) return;
|
|
5270
|
+
previewMode = true;
|
|
5271
|
+
panelWasVisible = panel?.isVisible() ?? true;
|
|
5272
|
+
panel?.setVisible(false);
|
|
5273
|
+
chrome?.setPreview(true);
|
|
5274
|
+
if (lastPreview) applyPreviewGated(lastPreview);
|
|
5275
|
+
return;
|
|
5276
|
+
case "exit-preview":
|
|
5277
|
+
if (!previewMode) return;
|
|
5278
|
+
previewMode = false;
|
|
5279
|
+
chrome?.setPreview(false);
|
|
5280
|
+
panel?.setVisible(panelWasVisible);
|
|
5281
|
+
if (lastPreview) applyPreviewGated(lastPreview);
|
|
5282
|
+
return;
|
|
5283
|
+
case "select-activation":
|
|
5284
|
+
case "select-step":
|
|
5285
|
+
case "add-step":
|
|
5286
|
+
panel?.setVisible(true);
|
|
5287
|
+
break;
|
|
5288
|
+
}
|
|
5289
|
+
post({ type: "chrome-action", payload: action });
|
|
5290
|
+
}
|
|
5291
|
+
});
|
|
4423
5292
|
panel = injectBuilderPanel({
|
|
4424
5293
|
dashboardOrigin,
|
|
4425
5294
|
token,
|
|
4426
5295
|
appOrigin: window.location.origin,
|
|
4427
5296
|
guide: ctx.guide,
|
|
4428
5297
|
panelPath: ctx.panelPath,
|
|
4429
|
-
onClose: () => teardown()
|
|
5298
|
+
onClose: () => teardown(),
|
|
5299
|
+
topOffset: chrome.height()
|
|
4430
5300
|
});
|
|
5301
|
+
chrome.onHeightChange((h) => panel?.setTopOffset(chrome?.dock() === "top" ? h : 0));
|
|
4431
5302
|
} else {
|
|
4432
5303
|
staticTarget = resolveTarget();
|
|
4433
5304
|
if (!staticTarget) return null;
|