veo-sdk 0.5.31 → 0.5.33
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-MUTQMYAH.mjs +5 -0
- package/dist/{builder-3WIW4RPE.mjs.map → builder-MUTQMYAH.mjs.map} +1 -1
- package/dist/builder.cjs +1004 -161
- 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-RNGJTSQP.mjs → chunk-3ZOKCQ54.mjs} +694 -73
- package/dist/chunk-3ZOKCQ54.mjs.map +1 -0
- package/dist/{chunk-MM2LLFTD.mjs → chunk-FZ72JUAR.mjs} +193 -9
- package/dist/chunk-FZ72JUAR.mjs.map +1 -0
- package/dist/{chunk-PK2YOBFO.mjs → chunk-M6PB5UMW.mjs} +238 -16
- package/dist/chunk-M6PB5UMW.mjs.map +1 -0
- package/dist/{guide-preview-XUnTmzUO.d.cts → guide-preview-C73rKO0u.d.cts} +32 -0
- package/dist/{guide-preview-XUnTmzUO.d.ts → guide-preview-C73rKO0u.d.ts} +32 -0
- package/dist/index.cjs +1219 -169
- 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-3WIW4RPE.mjs +0 -5
- package/dist/chunk-MM2LLFTD.mjs.map +0 -1
- package/dist/chunk-PK2YOBFO.mjs.map +0 -1
- package/dist/chunk-RNGJTSQP.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,14 @@ 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
|
+
|
|
286
294
|
// src/plugins/guides/constants.ts
|
|
287
295
|
var GUIDE_Z_INDEX = 2147483640;
|
|
288
296
|
var DEFAULT_ANCHOR_WAIT_MS = 5e3;
|
|
@@ -357,22 +365,22 @@ function rebuildNode(node, doc, depth, budget) {
|
|
|
357
365
|
return doc.createTextNode(node.textContent ?? "");
|
|
358
366
|
}
|
|
359
367
|
if (node.nodeType !== Node.ELEMENT_NODE) return null;
|
|
360
|
-
const
|
|
361
|
-
if (DROP_TAGS.has(
|
|
362
|
-
const mapped = ALLOWED_TAGS[
|
|
368
|
+
const el2 = node;
|
|
369
|
+
if (DROP_TAGS.has(el2.tagName)) return null;
|
|
370
|
+
const mapped = ALLOWED_TAGS[el2.tagName];
|
|
363
371
|
if (!mapped) {
|
|
364
372
|
const frag = doc.createDocumentFragment();
|
|
365
|
-
for (const child of Array.from(
|
|
373
|
+
for (const child of Array.from(el2.childNodes)) {
|
|
366
374
|
const rebuilt2 = rebuildNode(child, doc, depth + 1, budget);
|
|
367
375
|
if (rebuilt2) frag.appendChild(rebuilt2);
|
|
368
376
|
}
|
|
369
377
|
return frag;
|
|
370
378
|
}
|
|
371
379
|
if (mapped === "a") {
|
|
372
|
-
const href =
|
|
380
|
+
const href = el2.getAttribute("href") ?? "";
|
|
373
381
|
if (!isSafeUrl(href)) {
|
|
374
382
|
const frag = doc.createDocumentFragment();
|
|
375
|
-
for (const child of Array.from(
|
|
383
|
+
for (const child of Array.from(el2.childNodes)) {
|
|
376
384
|
const rebuilt2 = rebuildNode(child, doc, depth + 1, budget);
|
|
377
385
|
if (rebuilt2) frag.appendChild(rebuilt2);
|
|
378
386
|
}
|
|
@@ -382,14 +390,14 @@ function rebuildNode(node, doc, depth, budget) {
|
|
|
382
390
|
a.setAttribute("href", href);
|
|
383
391
|
a.setAttribute("target", "_blank");
|
|
384
392
|
a.setAttribute("rel", "noopener noreferrer nofollow");
|
|
385
|
-
for (const child of Array.from(
|
|
393
|
+
for (const child of Array.from(el2.childNodes)) {
|
|
386
394
|
const rebuilt2 = rebuildNode(child, doc, depth + 1, budget);
|
|
387
395
|
if (rebuilt2) a.appendChild(rebuilt2);
|
|
388
396
|
}
|
|
389
397
|
return a;
|
|
390
398
|
}
|
|
391
399
|
const rebuilt = doc.createElement(mapped);
|
|
392
|
-
for (const child of Array.from(
|
|
400
|
+
for (const child of Array.from(el2.childNodes)) {
|
|
393
401
|
const childNode = rebuildNode(child, doc, depth + 1, budget);
|
|
394
402
|
if (childNode) rebuilt.appendChild(childNode);
|
|
395
403
|
}
|
|
@@ -523,31 +531,31 @@ function renderBlocks(container, blocks, doc, callbacks) {
|
|
|
523
531
|
function buildContentBlock(block, doc) {
|
|
524
532
|
switch (block.type) {
|
|
525
533
|
case "title": {
|
|
526
|
-
const
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
applyBlockStyle(
|
|
530
|
-
return
|
|
534
|
+
const el2 = doc.createElement("h2");
|
|
535
|
+
el2.className = "veo-guide-title";
|
|
536
|
+
el2.textContent = typeof block.text === "string" ? block.text : "";
|
|
537
|
+
applyBlockStyle(el2, block.style, "text");
|
|
538
|
+
return el2;
|
|
531
539
|
}
|
|
532
540
|
case "text": {
|
|
533
|
-
const
|
|
534
|
-
|
|
541
|
+
const el2 = doc.createElement("div");
|
|
542
|
+
el2.className = "veo-guide-text";
|
|
535
543
|
if (typeof block.html === "string" && block.html) {
|
|
536
|
-
|
|
544
|
+
el2.appendChild(renderRichText(block.html, doc));
|
|
537
545
|
} else {
|
|
538
|
-
|
|
546
|
+
el2.textContent = typeof block.text === "string" ? block.text : "";
|
|
539
547
|
}
|
|
540
|
-
applyBlockStyle(
|
|
541
|
-
return
|
|
548
|
+
applyBlockStyle(el2, block.style, "text");
|
|
549
|
+
return el2;
|
|
542
550
|
}
|
|
543
551
|
case "image": {
|
|
544
552
|
if (typeof block.url !== "string" || !isSafeUrl(block.url)) return null;
|
|
545
|
-
const
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
applyBlockStyle(
|
|
550
|
-
return
|
|
553
|
+
const el2 = doc.createElement("img");
|
|
554
|
+
el2.className = "veo-guide-image";
|
|
555
|
+
el2.src = block.url;
|
|
556
|
+
el2.alt = "";
|
|
557
|
+
applyBlockStyle(el2, block.style, "image");
|
|
558
|
+
return el2;
|
|
551
559
|
}
|
|
552
560
|
default:
|
|
553
561
|
return null;
|
|
@@ -579,68 +587,74 @@ var BLOCK_ALIGN_SELF = {
|
|
|
579
587
|
function clampNum(n, min, max) {
|
|
580
588
|
return Math.min(max, Math.max(min, n));
|
|
581
589
|
}
|
|
582
|
-
function applyBlockStyle(
|
|
590
|
+
function applyBlockStyle(el2, style, kind) {
|
|
583
591
|
if (!style || typeof style !== "object") return;
|
|
584
592
|
const s = style;
|
|
585
593
|
if (kind === "image" && s.bleed === true) {
|
|
586
|
-
|
|
594
|
+
el2.classList.add("veo-guide-image--bleed");
|
|
587
595
|
return;
|
|
588
596
|
}
|
|
589
597
|
const align = typeof s.align === "string" ? s.align : null;
|
|
590
598
|
if (align && (align === "left" || align === "center" || align === "right")) {
|
|
591
|
-
if (kind === "text")
|
|
592
|
-
else if (kind === "image")
|
|
599
|
+
if (kind === "text") el2.style.textAlign = align;
|
|
600
|
+
else if (kind === "image") el2.style.alignSelf = BLOCK_ALIGN_SELF[align];
|
|
593
601
|
}
|
|
594
|
-
if (kind !== "image" && typeof s.color === "string")
|
|
602
|
+
if (kind !== "image" && typeof s.color === "string") el2.style.color = s.color;
|
|
595
603
|
if (kind === "text" && typeof s.fontSize === "number" && Number.isFinite(s.fontSize)) {
|
|
596
|
-
|
|
604
|
+
el2.style.fontSize = `${clampNum(s.fontSize, 8, 72)}px`;
|
|
597
605
|
}
|
|
598
606
|
if (kind === "image" && typeof s.width === "number" && Number.isFinite(s.width)) {
|
|
599
|
-
|
|
607
|
+
el2.style.width = `${clampNum(s.width, 10, 100)}%`;
|
|
600
608
|
}
|
|
601
609
|
if (kind === "image" && typeof s.radius === "number" && Number.isFinite(s.radius)) {
|
|
602
|
-
|
|
610
|
+
el2.style.borderRadius = `${clampNum(s.radius, 0, 48)}px`;
|
|
603
611
|
}
|
|
604
612
|
if (typeof s.marginTop === "number" && Number.isFinite(s.marginTop)) {
|
|
605
|
-
|
|
613
|
+
el2.style.marginTop = `${clampNum(s.marginTop, 0, 64)}px`;
|
|
606
614
|
}
|
|
607
615
|
if (typeof s.marginBottom === "number" && Number.isFinite(s.marginBottom)) {
|
|
608
|
-
|
|
616
|
+
el2.style.marginBottom = `${clampNum(s.marginBottom, 0, 64)}px`;
|
|
609
617
|
}
|
|
610
618
|
if (kind !== "image") {
|
|
611
619
|
if (typeof s.fontSize === "number" && Number.isFinite(s.fontSize)) {
|
|
612
|
-
|
|
620
|
+
el2.style.fontSize = `${clampNum(s.fontSize, 8, 96)}px`;
|
|
613
621
|
}
|
|
614
622
|
if (typeof s.fontFamily === "string" && s.fontFamily && s.fontFamily !== "inherit") {
|
|
615
|
-
|
|
623
|
+
el2.style.fontFamily = s.fontFamily;
|
|
616
624
|
}
|
|
617
|
-
if (typeof s.fontWeight === "string" && s.fontWeight)
|
|
625
|
+
if (typeof s.fontWeight === "string" && s.fontWeight) el2.style.fontWeight = s.fontWeight;
|
|
618
626
|
if (typeof s.textTransform === "string" && s.textTransform && s.textTransform !== "none") {
|
|
619
|
-
|
|
627
|
+
el2.style.textTransform = s.textTransform;
|
|
620
628
|
}
|
|
621
629
|
if (typeof s.lineHeight === "number" && Number.isFinite(s.lineHeight)) {
|
|
622
|
-
|
|
630
|
+
el2.style.lineHeight = `${clampNum(s.lineHeight, 50, 300)}%`;
|
|
623
631
|
}
|
|
624
632
|
if (typeof s.letterSpacing === "number" && Number.isFinite(s.letterSpacing)) {
|
|
625
|
-
|
|
633
|
+
el2.style.letterSpacing = `${clampNum(s.letterSpacing, -5, 20)}px`;
|
|
626
634
|
}
|
|
627
635
|
}
|
|
628
|
-
if (typeof s.background === "string" && s.background)
|
|
636
|
+
if (typeof s.background === "string" && s.background) el2.style.background = s.background;
|
|
629
637
|
if (typeof s.borderWidth === "number" && s.borderWidth > 0) {
|
|
630
638
|
const bc = typeof s.borderColor === "string" && s.borderColor ? s.borderColor : "#bbbbbb";
|
|
631
|
-
|
|
639
|
+
el2.style.border = `${clampNum(s.borderWidth, 0, 20)}px solid ${bc}`;
|
|
632
640
|
}
|
|
633
641
|
if (kind !== "image" && typeof s.radius === "number" && Number.isFinite(s.radius)) {
|
|
634
|
-
|
|
642
|
+
el2.style.borderRadius = `${clampNum(s.radius, 0, 64)}px`;
|
|
643
|
+
}
|
|
644
|
+
if (typeof s.height === "number" && Number.isFinite(s.height) && s.height > 0) {
|
|
645
|
+
el2.style.height = `${clampNum(s.height, 1, 2e3)}px`;
|
|
646
|
+
}
|
|
647
|
+
if (kind !== "image" && typeof s.width === "number" && Number.isFinite(s.width) && s.width > 0) {
|
|
648
|
+
el2.style.width = `${clampNum(s.width, 1, 2e3)}px`;
|
|
635
649
|
}
|
|
636
650
|
for (const side of ["Top", "Right", "Bottom", "Left"]) {
|
|
637
651
|
const p = s[`padding${side}`];
|
|
638
652
|
if (typeof p === "number" && Number.isFinite(p)) {
|
|
639
|
-
|
|
653
|
+
el2.style.setProperty(`padding-${side.toLowerCase()}`, `${clampNum(p, 0, 128)}px`);
|
|
640
654
|
}
|
|
641
655
|
const m = s[`margin${side}`];
|
|
642
656
|
if (typeof m === "number" && Number.isFinite(m)) {
|
|
643
|
-
|
|
657
|
+
el2.style.setProperty(`margin-${side.toLowerCase()}`, `${clampNum(m, 0, 128)}px`);
|
|
644
658
|
}
|
|
645
659
|
}
|
|
646
660
|
}
|
|
@@ -775,11 +789,11 @@ function applyDesignVars(host, style) {
|
|
|
775
789
|
host.style.setProperty("--veo-pos-y", `${py * 100}%`);
|
|
776
790
|
}
|
|
777
791
|
if (s.elements && typeof s.elements === "object") {
|
|
778
|
-
const
|
|
779
|
-
applyElementVars(host, "title",
|
|
780
|
-
applyElementVars(host, "text",
|
|
781
|
-
applyElementVars(host, "image",
|
|
782
|
-
applyCtaVars(host,
|
|
792
|
+
const el2 = s.elements;
|
|
793
|
+
applyElementVars(host, "title", el2.title);
|
|
794
|
+
applyElementVars(host, "text", el2.text);
|
|
795
|
+
applyElementVars(host, "image", el2.image);
|
|
796
|
+
applyCtaVars(host, el2.cta);
|
|
783
797
|
}
|
|
784
798
|
}
|
|
785
799
|
function applyCtaVars(host, raw) {
|
|
@@ -803,29 +817,29 @@ function applyCtaVars(host, raw) {
|
|
|
803
817
|
}
|
|
804
818
|
function applyElementVars(host, prefix, raw) {
|
|
805
819
|
if (!raw || typeof raw !== "object") return;
|
|
806
|
-
const
|
|
807
|
-
if (typeof
|
|
820
|
+
const el2 = raw;
|
|
821
|
+
if (typeof el2.align === "string" && (el2.align === "left" || el2.align === "center" || el2.align === "right")) {
|
|
808
822
|
const mode = ELEMENT_ALIGN_MODE[prefix] ?? "text";
|
|
809
|
-
const value = mode === "self" ? ALIGN_SELF[
|
|
823
|
+
const value = mode === "self" ? ALIGN_SELF[el2.align] : el2.align;
|
|
810
824
|
host.style.setProperty(`--veo-${prefix}-align`, value);
|
|
811
825
|
}
|
|
812
|
-
if (typeof
|
|
813
|
-
host.style.setProperty(`--veo-${prefix}-color`,
|
|
826
|
+
if (typeof el2.color === "string" && COLOR_RE.test(el2.color.trim())) {
|
|
827
|
+
host.style.setProperty(`--veo-${prefix}-color`, el2.color.trim());
|
|
814
828
|
}
|
|
815
|
-
if (typeof
|
|
816
|
-
host.style.setProperty(`--veo-${prefix}-size`, `${clamp(
|
|
829
|
+
if (typeof el2.fontSize === "number" && Number.isFinite(el2.fontSize)) {
|
|
830
|
+
host.style.setProperty(`--veo-${prefix}-size`, `${clamp(el2.fontSize, 8, 72)}px`);
|
|
817
831
|
}
|
|
818
|
-
if (typeof
|
|
819
|
-
host.style.setProperty(`--veo-${prefix}-width`, `${clamp(
|
|
832
|
+
if (typeof el2.width === "number" && Number.isFinite(el2.width)) {
|
|
833
|
+
host.style.setProperty(`--veo-${prefix}-width`, `${clamp(el2.width, 10, 100)}%`);
|
|
820
834
|
}
|
|
821
|
-
if (typeof
|
|
822
|
-
host.style.setProperty(`--veo-${prefix}-radius`, `${clamp(
|
|
835
|
+
if (typeof el2.radius === "number" && Number.isFinite(el2.radius)) {
|
|
836
|
+
host.style.setProperty(`--veo-${prefix}-radius`, `${clamp(el2.radius, 0, 48)}px`);
|
|
823
837
|
}
|
|
824
|
-
if (typeof
|
|
825
|
-
host.style.setProperty(`--veo-${prefix}-mt`, `${clamp(
|
|
838
|
+
if (typeof el2.marginTop === "number" && Number.isFinite(el2.marginTop)) {
|
|
839
|
+
host.style.setProperty(`--veo-${prefix}-mt`, `${clamp(el2.marginTop, 0, 64)}px`);
|
|
826
840
|
}
|
|
827
|
-
if (typeof
|
|
828
|
-
host.style.setProperty(`--veo-${prefix}-mb`, `${clamp(
|
|
841
|
+
if (typeof el2.marginBottom === "number" && Number.isFinite(el2.marginBottom)) {
|
|
842
|
+
host.style.setProperty(`--veo-${prefix}-mb`, `${clamp(el2.marginBottom, 0, 64)}px`);
|
|
829
843
|
}
|
|
830
844
|
}
|
|
831
845
|
|
|
@@ -875,16 +889,16 @@ function waitForElement(selector, timeoutMs = DEFAULT_ANCHOR_WAIT_MS) {
|
|
|
875
889
|
return;
|
|
876
890
|
}
|
|
877
891
|
let resolved = false;
|
|
878
|
-
const finish = (
|
|
892
|
+
const finish = (el2) => {
|
|
879
893
|
if (resolved) return;
|
|
880
894
|
resolved = true;
|
|
881
895
|
observer.disconnect();
|
|
882
896
|
clearTimeout(timer);
|
|
883
|
-
resolve(
|
|
897
|
+
resolve(el2);
|
|
884
898
|
};
|
|
885
899
|
const observer = new MutationObserver(() => {
|
|
886
|
-
const
|
|
887
|
-
if (
|
|
900
|
+
const el2 = safeQuery();
|
|
901
|
+
if (el2) finish(el2);
|
|
888
902
|
});
|
|
889
903
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
890
904
|
const timer = setTimeout(() => finish(null), timeoutMs);
|
|
@@ -1944,10 +1958,10 @@ function collectHostStyles() {
|
|
|
1944
1958
|
function hostHtmlAttrs() {
|
|
1945
1959
|
if (typeof document === "undefined") return "";
|
|
1946
1960
|
try {
|
|
1947
|
-
const
|
|
1961
|
+
const el2 = document.documentElement;
|
|
1948
1962
|
const attrs = [];
|
|
1949
1963
|
for (const name of ["class", "style", "data-theme", "data-mode", "data-color-mode"]) {
|
|
1950
|
-
const v =
|
|
1964
|
+
const v = el2.getAttribute(name);
|
|
1951
1965
|
if (v && v.length <= 1e3 && !/["<>]/.test(v)) attrs.push(`${name}="${v}"`);
|
|
1952
1966
|
}
|
|
1953
1967
|
return attrs.join(" ");
|
|
@@ -2330,6 +2344,188 @@ function buildScale(wrapper, doc, min, max, btnClass, symbol) {
|
|
|
2330
2344
|
wrapper.appendChild(row);
|
|
2331
2345
|
return { wrapper, read: () => selected };
|
|
2332
2346
|
}
|
|
2347
|
+
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";
|
|
2348
|
+
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";
|
|
2349
|
+
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";
|
|
2350
|
+
var CIRCLE = "M21 12a9 9 0 11-18 0 9 9 0 0118 0z";
|
|
2351
|
+
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";
|
|
2352
|
+
var BADGE_ICONS = {
|
|
2353
|
+
info: { paths: [CIRCLE, INFO_GLYPH], dots: [[12, 8.25]] },
|
|
2354
|
+
exclamation: { paths: [CIRCLE, "M12 8v4.5"], dots: [[12, 15.75]] },
|
|
2355
|
+
question: { paths: [CIRCLE, QUESTION_GLYPH], dots: [[12, 17.25]] },
|
|
2356
|
+
star: { paths: [STAR_GLYPH] },
|
|
2357
|
+
"info-solid": { paths: [INFO_GLYPH], dots: [[12, 8.25]], solid: true, scale: 0.8 },
|
|
2358
|
+
"exclamation-solid": { paths: ["M12 8v4.5"], dots: [[12, 15.75]], solid: true, scale: 0.8 },
|
|
2359
|
+
"question-solid": { paths: [QUESTION_GLYPH], dots: [[12, 17.25]], solid: true, scale: 0.8 },
|
|
2360
|
+
"star-solid": { paths: [STAR_GLYPH], solid: true, scale: 0.55 },
|
|
2361
|
+
"target-solid": { paths: [TARGET_GLYPH], solid: true, scale: 0.6 },
|
|
2362
|
+
new: { paths: [], text: "New" }
|
|
2363
|
+
};
|
|
2364
|
+
var DEFAULT_MARKER_SIZE = 14;
|
|
2365
|
+
var DEFAULT_MARKER_Z = 19e3;
|
|
2366
|
+
var SIDE_GAP = 8;
|
|
2367
|
+
function num(v, fallback) {
|
|
2368
|
+
return typeof v === "number" && Number.isFinite(v) ? v : fallback;
|
|
2369
|
+
}
|
|
2370
|
+
function iconNode(doc, name, size, color) {
|
|
2371
|
+
const def = BADGE_ICONS[name] ?? BADGE_ICONS.info;
|
|
2372
|
+
if (def.text) {
|
|
2373
|
+
const t = doc.createElement("span");
|
|
2374
|
+
t.textContent = def.text;
|
|
2375
|
+
t.style.font = `700 ${Math.round(size * 0.85)}px/1 system-ui, -apple-system, sans-serif`;
|
|
2376
|
+
t.style.color = color;
|
|
2377
|
+
return t;
|
|
2378
|
+
}
|
|
2379
|
+
const ns = "http://www.w3.org/2000/svg";
|
|
2380
|
+
const svg2 = doc.createElementNS(ns, "svg");
|
|
2381
|
+
svg2.setAttribute("viewBox", "0 0 24 24");
|
|
2382
|
+
svg2.setAttribute("width", String(size));
|
|
2383
|
+
svg2.setAttribute("height", String(size));
|
|
2384
|
+
svg2.setAttribute("fill", "none");
|
|
2385
|
+
svg2.setAttribute("aria-hidden", "true");
|
|
2386
|
+
const glyphColor = def.solid ? "#ffffff" : color;
|
|
2387
|
+
if (def.solid) {
|
|
2388
|
+
const bg = doc.createElementNS(ns, "circle");
|
|
2389
|
+
bg.setAttribute("cx", "12");
|
|
2390
|
+
bg.setAttribute("cy", "12");
|
|
2391
|
+
bg.setAttribute("r", "12");
|
|
2392
|
+
bg.setAttribute("fill", color);
|
|
2393
|
+
svg2.appendChild(bg);
|
|
2394
|
+
}
|
|
2395
|
+
const g = doc.createElementNS(ns, "g");
|
|
2396
|
+
g.setAttribute("stroke", glyphColor);
|
|
2397
|
+
g.setAttribute("stroke-width", def.solid ? "2" : "1.8");
|
|
2398
|
+
g.setAttribute("stroke-linecap", "round");
|
|
2399
|
+
g.setAttribute("stroke-linejoin", "round");
|
|
2400
|
+
if (def.scale && def.scale !== 1) {
|
|
2401
|
+
const k = def.scale;
|
|
2402
|
+
const t = 12 - 12 * k;
|
|
2403
|
+
g.setAttribute("transform", `translate(${t} ${t}) scale(${k})`);
|
|
2404
|
+
}
|
|
2405
|
+
for (const d of def.paths) {
|
|
2406
|
+
const path = doc.createElementNS(ns, "path");
|
|
2407
|
+
path.setAttribute("d", d);
|
|
2408
|
+
g.appendChild(path);
|
|
2409
|
+
}
|
|
2410
|
+
for (const [cx, cy] of def.dots ?? []) {
|
|
2411
|
+
const dot = doc.createElementNS(ns, "circle");
|
|
2412
|
+
dot.setAttribute("cx", String(cx));
|
|
2413
|
+
dot.setAttribute("cy", String(cy));
|
|
2414
|
+
dot.setAttribute("r", "0.9");
|
|
2415
|
+
dot.setAttribute("fill", glyphColor);
|
|
2416
|
+
dot.setAttribute("stroke", "none");
|
|
2417
|
+
g.appendChild(dot);
|
|
2418
|
+
}
|
|
2419
|
+
svg2.appendChild(g);
|
|
2420
|
+
return svg2;
|
|
2421
|
+
}
|
|
2422
|
+
function buildMarkerElement(doc, marker) {
|
|
2423
|
+
const size = num(marker.size, DEFAULT_MARKER_SIZE);
|
|
2424
|
+
const color = marker.color || "#000000";
|
|
2425
|
+
const el2 = doc.createElement("span");
|
|
2426
|
+
el2.className = `veo-badge-marker veo-badge-marker-${marker.kind}`;
|
|
2427
|
+
el2.style.display = "inline-flex";
|
|
2428
|
+
el2.style.alignItems = "center";
|
|
2429
|
+
el2.style.justifyContent = "center";
|
|
2430
|
+
el2.style.boxSizing = "border-box";
|
|
2431
|
+
el2.style.lineHeight = "1";
|
|
2432
|
+
if (marker.kind === "image") {
|
|
2433
|
+
const img = doc.createElement("img");
|
|
2434
|
+
img.alt = "";
|
|
2435
|
+
img.src = marker.imageUrl || "";
|
|
2436
|
+
img.style.width = `${size}px`;
|
|
2437
|
+
img.style.height = `${size}px`;
|
|
2438
|
+
img.style.objectFit = "contain";
|
|
2439
|
+
img.style.display = "block";
|
|
2440
|
+
el2.appendChild(img);
|
|
2441
|
+
return el2;
|
|
2442
|
+
}
|
|
2443
|
+
if (marker.kind === "icon-text") {
|
|
2444
|
+
el2.style.gap = "6px";
|
|
2445
|
+
el2.style.color = color;
|
|
2446
|
+
el2.style.fontSize = `${size}px`;
|
|
2447
|
+
el2.style.fontFamily = "inherit";
|
|
2448
|
+
el2.style.fontWeight = "600";
|
|
2449
|
+
el2.style.whiteSpace = "nowrap";
|
|
2450
|
+
el2.style.background = marker.bgColor || "transparent";
|
|
2451
|
+
const bw = num(marker.borderWidth, 0);
|
|
2452
|
+
if (bw > 0) el2.style.border = `${bw}px solid ${marker.borderColor || color}`;
|
|
2453
|
+
el2.style.padding = `${num(marker.paddingY, 6)}px ${num(marker.paddingX, 10)}px`;
|
|
2454
|
+
el2.style.borderRadius = `${num(marker.radius, 999)}px`;
|
|
2455
|
+
if (marker.showIcon !== false)
|
|
2456
|
+
el2.appendChild(iconNode(doc, marker.icon || "star", size, color));
|
|
2457
|
+
const text = doc.createElement("span");
|
|
2458
|
+
text.textContent = marker.text || "";
|
|
2459
|
+
el2.appendChild(text);
|
|
2460
|
+
return el2;
|
|
2461
|
+
}
|
|
2462
|
+
el2.style.width = `${size}px`;
|
|
2463
|
+
el2.style.height = `${size}px`;
|
|
2464
|
+
el2.appendChild(iconNode(doc, marker.icon || "info", size, color));
|
|
2465
|
+
return el2;
|
|
2466
|
+
}
|
|
2467
|
+
function markerOffset(anchor, marker, position, offset6) {
|
|
2468
|
+
const right = anchor.left + anchor.width;
|
|
2469
|
+
const bottom = anchor.top + anchor.height;
|
|
2470
|
+
const midY = anchor.top + anchor.height / 2 - marker.height / 2;
|
|
2471
|
+
const midX = anchor.left + anchor.width / 2 - marker.width / 2;
|
|
2472
|
+
let x;
|
|
2473
|
+
let y;
|
|
2474
|
+
switch (position) {
|
|
2475
|
+
case "top-left":
|
|
2476
|
+
x = anchor.left - marker.width / 2;
|
|
2477
|
+
y = anchor.top - marker.height / 2;
|
|
2478
|
+
break;
|
|
2479
|
+
case "bottom-left":
|
|
2480
|
+
x = anchor.left - marker.width / 2;
|
|
2481
|
+
y = bottom - marker.height / 2;
|
|
2482
|
+
break;
|
|
2483
|
+
case "bottom-right":
|
|
2484
|
+
x = right - marker.width / 2;
|
|
2485
|
+
y = bottom - marker.height / 2;
|
|
2486
|
+
break;
|
|
2487
|
+
case "left":
|
|
2488
|
+
x = anchor.left - marker.width - SIDE_GAP;
|
|
2489
|
+
y = midY;
|
|
2490
|
+
break;
|
|
2491
|
+
case "right":
|
|
2492
|
+
x = right + SIDE_GAP;
|
|
2493
|
+
y = midY;
|
|
2494
|
+
break;
|
|
2495
|
+
case "center":
|
|
2496
|
+
x = midX;
|
|
2497
|
+
y = midY;
|
|
2498
|
+
break;
|
|
2499
|
+
default:
|
|
2500
|
+
x = right - marker.width / 2;
|
|
2501
|
+
y = anchor.top - marker.height / 2;
|
|
2502
|
+
}
|
|
2503
|
+
return { x: x + offset6.x, y: y + offset6.y };
|
|
2504
|
+
}
|
|
2505
|
+
function attachMarker(anchor, host, marker) {
|
|
2506
|
+
host.style.position = "absolute";
|
|
2507
|
+
host.style.zIndex = String(num(marker.zIndex, DEFAULT_MARKER_Z));
|
|
2508
|
+
host.style.margin = "0";
|
|
2509
|
+
const update = () => {
|
|
2510
|
+
const a = anchor.getBoundingClientRect();
|
|
2511
|
+
const m = host.getBoundingClientRect();
|
|
2512
|
+
const { x, y } = markerOffset(
|
|
2513
|
+
{
|
|
2514
|
+
left: a.left + window.scrollX,
|
|
2515
|
+
top: a.top + window.scrollY,
|
|
2516
|
+
width: a.width,
|
|
2517
|
+
height: a.height
|
|
2518
|
+
},
|
|
2519
|
+
{ width: m.width, height: m.height },
|
|
2520
|
+
marker.position ?? "top-right",
|
|
2521
|
+
{ x: num(marker.offsetX, 0), y: num(marker.offsetY, 0) }
|
|
2522
|
+
);
|
|
2523
|
+
host.style.left = `${Math.round(x)}px`;
|
|
2524
|
+
host.style.top = `${Math.round(y)}px`;
|
|
2525
|
+
};
|
|
2526
|
+
update();
|
|
2527
|
+
return dom.autoUpdate(anchor, host, update);
|
|
2528
|
+
}
|
|
2333
2529
|
|
|
2334
2530
|
// src/plugins/guides/renderers/composite-renderer.ts
|
|
2335
2531
|
var ROW_ALIGN = {
|
|
@@ -2625,7 +2821,9 @@ var CompositeRenderer = class extends BaseRenderer {
|
|
|
2625
2821
|
badge.style.cursor = "pointer";
|
|
2626
2822
|
badge.style.display = "inline-flex";
|
|
2627
2823
|
badge.style.alignItems = "center";
|
|
2628
|
-
|
|
2824
|
+
const marker = step.badge?.marker ?? null;
|
|
2825
|
+
if (marker) badge.appendChild(buildMarkerElement(doc, marker));
|
|
2826
|
+
else this.buildContent(badge, step.badge?.blocks ?? [], doc, context, idx, [], host);
|
|
2629
2827
|
root.appendChild(badge);
|
|
2630
2828
|
if (design.fullWidth === true) {
|
|
2631
2829
|
card.style.width = "auto";
|
|
@@ -2640,10 +2838,17 @@ var CompositeRenderer = class extends BaseRenderer {
|
|
|
2640
2838
|
if (caretEl) wrapper.appendChild(caretEl);
|
|
2641
2839
|
wrapper.appendChild(card);
|
|
2642
2840
|
root.appendChild(wrapper);
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2841
|
+
if (marker) {
|
|
2842
|
+
host.style.display = "inline-block";
|
|
2843
|
+
(anchor.ownerDocument ?? document).body.appendChild(host);
|
|
2844
|
+
this.registerCleanup(attachMarker(anchor, host, marker));
|
|
2845
|
+
this.registerCleanup(() => host.remove());
|
|
2846
|
+
} else {
|
|
2847
|
+
host.style.display = "inline-block";
|
|
2848
|
+
const pos = inlinePosOf(step.inlinePosition);
|
|
2849
|
+
insertHost(anchor, host, pos);
|
|
2850
|
+
this.registerCleanup(keepHostAttached(host, anchorSelector, pos));
|
|
2851
|
+
}
|
|
2647
2852
|
let open = false;
|
|
2648
2853
|
let stopFloat = null;
|
|
2649
2854
|
let closeTimer = null;
|
|
@@ -2696,6 +2901,7 @@ var CompositeRenderer = class extends BaseRenderer {
|
|
|
2696
2901
|
stopFloat?.();
|
|
2697
2902
|
if (closeTimer !== null) clearTimeout(closeTimer);
|
|
2698
2903
|
});
|
|
2904
|
+
if (context.badgeOpen) openTip();
|
|
2699
2905
|
return closeTip;
|
|
2700
2906
|
}
|
|
2701
2907
|
};
|
|
@@ -2749,14 +2955,14 @@ function makeCaret(doc, design) {
|
|
|
2749
2955
|
return caret;
|
|
2750
2956
|
}
|
|
2751
2957
|
function liftTarget(anchor, zIndex) {
|
|
2752
|
-
const
|
|
2753
|
-
const prevPosition =
|
|
2754
|
-
const prevZ =
|
|
2755
|
-
if (getComputedStyle(
|
|
2756
|
-
|
|
2958
|
+
const el2 = anchor;
|
|
2959
|
+
const prevPosition = el2.style.position;
|
|
2960
|
+
const prevZ = el2.style.zIndex;
|
|
2961
|
+
if (getComputedStyle(el2).position === "static") el2.style.position = "relative";
|
|
2962
|
+
el2.style.zIndex = String(zIndex);
|
|
2757
2963
|
return () => {
|
|
2758
|
-
|
|
2759
|
-
|
|
2964
|
+
el2.style.position = prevPosition;
|
|
2965
|
+
el2.style.zIndex = prevZ;
|
|
2760
2966
|
};
|
|
2761
2967
|
}
|
|
2762
2968
|
async function anchorPosition(anchor, wrapper, caret, preferred = "bottom") {
|
|
@@ -3272,7 +3478,8 @@ var GuidePreviewController = class {
|
|
|
3272
3478
|
}
|
|
3273
3479
|
preview(input) {
|
|
3274
3480
|
const nextStep = input.guideSteps[0];
|
|
3275
|
-
if (this.singleStep && this.input && input.guideType === this.input.guideType && input.guideType !== "walkthrough" &&
|
|
3481
|
+
if (this.singleStep && this.input && input.guideType === this.input.guideType && input.guideType !== "walkthrough" && // Abrir/cerrar el tooltip del badge requiere remontar.
|
|
3482
|
+
input.badgeOpen === true === (this.input.badgeOpen === true) && nextStep && this.singleStep.updateStep(nextStep)) {
|
|
3276
3483
|
this.input = input;
|
|
3277
3484
|
return {
|
|
3278
3485
|
close: () => this.close(),
|
|
@@ -3302,7 +3509,8 @@ var GuidePreviewController = class {
|
|
|
3302
3509
|
}
|
|
3303
3510
|
return null;
|
|
3304
3511
|
}
|
|
3305
|
-
close() {
|
|
3512
|
+
close(byUser = false) {
|
|
3513
|
+
const onClosed = byUser ? this.input?.onClosed : void 0;
|
|
3306
3514
|
if (this.singleStep) {
|
|
3307
3515
|
safeDestroy(this.singleStep);
|
|
3308
3516
|
this.singleStep = null;
|
|
@@ -3314,6 +3522,7 @@ var GuidePreviewController = class {
|
|
|
3314
3522
|
this.walkthroughGuide = null;
|
|
3315
3523
|
this.walkthroughIndex = 0;
|
|
3316
3524
|
this.input = null;
|
|
3525
|
+
onClosed?.();
|
|
3317
3526
|
}
|
|
3318
3527
|
async renderSingleStep(guide) {
|
|
3319
3528
|
const renderer = createSingleStepRenderer(guide.guideType);
|
|
@@ -3326,7 +3535,8 @@ var GuidePreviewController = class {
|
|
|
3326
3535
|
onInteraction: (event) => {
|
|
3327
3536
|
if (event.action === "shown") shown = true;
|
|
3328
3537
|
},
|
|
3329
|
-
onClose: () => this.close(),
|
|
3538
|
+
onClose: () => this.close(true),
|
|
3539
|
+
badgeOpen: this.input?.badgeOpen === true,
|
|
3330
3540
|
onTrack: () => {
|
|
3331
3541
|
},
|
|
3332
3542
|
// Encadenado en preview: no-op — el editor no puede montar otra guía
|
|
@@ -3392,7 +3602,7 @@ var GuidePreviewController = class {
|
|
|
3392
3602
|
guide,
|
|
3393
3603
|
onInteraction: () => {
|
|
3394
3604
|
},
|
|
3395
|
-
onClose: () => this.close(),
|
|
3605
|
+
onClose: () => this.close(true),
|
|
3396
3606
|
nav: { stepIndex: index, totalSteps: guide.guideSteps.length, callbacks }
|
|
3397
3607
|
});
|
|
3398
3608
|
} catch {
|
|
@@ -3486,15 +3696,27 @@ function safeDestroy(renderer) {
|
|
|
3486
3696
|
}
|
|
3487
3697
|
|
|
3488
3698
|
// src/plugins/guides/url-match.ts
|
|
3699
|
+
function urlCandidates(pageUrl) {
|
|
3700
|
+
const out = [pageUrl];
|
|
3701
|
+
try {
|
|
3702
|
+
const u = new URL(pageUrl);
|
|
3703
|
+
out.push(`${u.pathname}${u.search}${u.hash}`);
|
|
3704
|
+
if (u.hash.startsWith("#/")) out.push(u.hash.slice(1));
|
|
3705
|
+
} catch {
|
|
3706
|
+
}
|
|
3707
|
+
return out;
|
|
3708
|
+
}
|
|
3489
3709
|
function matchesUrl(matcher, pageUrl) {
|
|
3710
|
+
const candidates = urlCandidates(pageUrl);
|
|
3490
3711
|
switch (matcher.type) {
|
|
3491
3712
|
case "exact":
|
|
3492
|
-
return
|
|
3713
|
+
return candidates.some((c) => c === matcher.pattern);
|
|
3493
3714
|
case "prefix":
|
|
3494
|
-
return
|
|
3715
|
+
return candidates.some((c) => c.startsWith(matcher.pattern));
|
|
3495
3716
|
case "regex":
|
|
3496
3717
|
try {
|
|
3497
|
-
|
|
3718
|
+
const re = new RegExp(matcher.pattern);
|
|
3719
|
+
return candidates.some((c) => re.test(c));
|
|
3498
3720
|
} catch {
|
|
3499
3721
|
return false;
|
|
3500
3722
|
}
|
|
@@ -3508,17 +3730,375 @@ function stepMatchesPage(loc, pageUrl) {
|
|
|
3508
3730
|
// src/plugins/builder/bridge-protocol.ts
|
|
3509
3731
|
var VEO_BUILDER_SOURCE = "veo-builder";
|
|
3510
3732
|
|
|
3733
|
+
// src/plugins/builder/builder-chrome.ts
|
|
3734
|
+
var CHROME_TOPBAR_H = 64;
|
|
3735
|
+
var CHROME_STEPS_H = 128;
|
|
3736
|
+
var ICONS = {
|
|
3737
|
+
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"/>',
|
|
3738
|
+
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"/>',
|
|
3739
|
+
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"/>',
|
|
3740
|
+
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"/>',
|
|
3741
|
+
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"/>',
|
|
3742
|
+
chevronDown: '<path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5"/>',
|
|
3743
|
+
chevronUp: '<path stroke-linecap="round" stroke-linejoin="round" d="m4.5 15.75 7.5-7.5 7.5 7.5"/>',
|
|
3744
|
+
plus: '<path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15"/>',
|
|
3745
|
+
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"/>',
|
|
3746
|
+
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"/>'
|
|
3747
|
+
};
|
|
3748
|
+
function svg(name, size = 20) {
|
|
3749
|
+
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>`;
|
|
3750
|
+
}
|
|
3751
|
+
function shortDate(iso) {
|
|
3752
|
+
if (!iso) return "";
|
|
3753
|
+
const d = new Date(iso);
|
|
3754
|
+
if (Number.isNaN(d.getTime())) return "";
|
|
3755
|
+
return d.toLocaleDateString("es", { day: "numeric", month: "short" }).replace(".", "");
|
|
3756
|
+
}
|
|
3757
|
+
function el(tag, className, html) {
|
|
3758
|
+
const node = document.createElement(tag);
|
|
3759
|
+
node.className = className;
|
|
3760
|
+
if (html !== void 0) node.innerHTML = html;
|
|
3761
|
+
return node;
|
|
3762
|
+
}
|
|
3763
|
+
function iconButton(name, title, className = "") {
|
|
3764
|
+
const b = el("button", `veo-tb-icon ${className}`.trim(), svg(name));
|
|
3765
|
+
b.type = "button";
|
|
3766
|
+
b.title = title;
|
|
3767
|
+
b.setAttribute("aria-label", title);
|
|
3768
|
+
return b;
|
|
3769
|
+
}
|
|
3770
|
+
function injectBuilderChrome(opts) {
|
|
3771
|
+
if (!hasWindow() || !hasDocument()) {
|
|
3772
|
+
return {
|
|
3773
|
+
setState: () => {
|
|
3774
|
+
},
|
|
3775
|
+
height: () => 0,
|
|
3776
|
+
dock: () => "top",
|
|
3777
|
+
setPreview: () => {
|
|
3778
|
+
},
|
|
3779
|
+
setHidden: () => {
|
|
3780
|
+
},
|
|
3781
|
+
onHeightChange: () => {
|
|
3782
|
+
},
|
|
3783
|
+
teardown: () => {
|
|
3784
|
+
}
|
|
3785
|
+
};
|
|
3786
|
+
}
|
|
3787
|
+
const host = document.createElement("div");
|
|
3788
|
+
host.setAttribute("data-veo-builder-chrome", "");
|
|
3789
|
+
host.setAttribute("data-veo-ignore", "");
|
|
3790
|
+
const shadow = host.attachShadow({ mode: "open" });
|
|
3791
|
+
const style = document.createElement("style");
|
|
3792
|
+
style.textContent = CHROME_CSS;
|
|
3793
|
+
const root = el("div", "veo-chrome");
|
|
3794
|
+
const topbar = el("div", "veo-tb");
|
|
3795
|
+
const brand = el("div", "veo-tb-brand", svg("bolt", 18));
|
|
3796
|
+
const nameEl = el("div", "veo-tb-name");
|
|
3797
|
+
const statusEl = el("span", "veo-tb-status");
|
|
3798
|
+
statusEl.hidden = true;
|
|
3799
|
+
const sep = el("span", "veo-tb-sep");
|
|
3800
|
+
const appEl = el("div", "veo-tb-app", `${svg("desktop", 16)}<span></span>`);
|
|
3801
|
+
appEl.querySelector("span").textContent = opts.appLabel;
|
|
3802
|
+
const left = el("div", "veo-tb-left");
|
|
3803
|
+
left.append(brand, nameEl, statusEl, sep, appEl);
|
|
3804
|
+
const right = el("div", "veo-tb-right");
|
|
3805
|
+
const dockBtn = iconButton("updown", "Mover la barra abajo");
|
|
3806
|
+
const showPanel = iconButton("map", "Mostrar el editor");
|
|
3807
|
+
const preview = iconButton("eye", "Vista previa");
|
|
3808
|
+
const exit = el("button", "veo-tb-text", "Salir");
|
|
3809
|
+
exit.type = "button";
|
|
3810
|
+
const saveGroup = el("div", "veo-tb-save");
|
|
3811
|
+
const save = el("button", "veo-tb-save-main", "<span>Guardar</span>");
|
|
3812
|
+
save.type = "button";
|
|
3813
|
+
const saveMore = el("button", "veo-tb-save-more", svg("chevronDown", 16));
|
|
3814
|
+
saveMore.type = "button";
|
|
3815
|
+
saveMore.title = "M\xE1s opciones de guardado";
|
|
3816
|
+
saveMore.setAttribute("aria-label", "M\xE1s opciones de guardado");
|
|
3817
|
+
const saveMenu = el("div", "veo-tb-menu");
|
|
3818
|
+
const saveExit = el("button", "veo-tb-menu-item", "Guardar y salir");
|
|
3819
|
+
saveExit.type = "button";
|
|
3820
|
+
saveMenu.append(saveExit);
|
|
3821
|
+
saveMenu.hidden = true;
|
|
3822
|
+
saveGroup.append(save, saveMore, saveMenu);
|
|
3823
|
+
right.append(dockBtn, showPanel, preview, el("span", "veo-tb-vsep"), exit, saveGroup);
|
|
3824
|
+
topbar.append(left, right);
|
|
3825
|
+
const stepsBar = el("div", "veo-steps");
|
|
3826
|
+
const stepsList = el("div", "veo-steps-list");
|
|
3827
|
+
stepsBar.append(stepsList);
|
|
3828
|
+
const togglePill = el("button", "veo-steps-toggle");
|
|
3829
|
+
togglePill.type = "button";
|
|
3830
|
+
root.append(topbar, stepsBar, togglePill);
|
|
3831
|
+
const previewPill = el("div", "veo-preview-pill");
|
|
3832
|
+
const previewLabel = el(
|
|
3833
|
+
"span",
|
|
3834
|
+
"veo-preview-label",
|
|
3835
|
+
`${svg("eye", 18)}<span>Est\xE1s en vista previa</span>`
|
|
3836
|
+
);
|
|
3837
|
+
const previewExit = el("button", "veo-preview-exit", "Salir");
|
|
3838
|
+
previewExit.type = "button";
|
|
3839
|
+
previewPill.append(previewLabel, previewExit);
|
|
3840
|
+
previewPill.hidden = true;
|
|
3841
|
+
shadow.append(style, root, previewPill);
|
|
3842
|
+
document.body.appendChild(host);
|
|
3843
|
+
const html = document.documentElement;
|
|
3844
|
+
const prevMarginTop = html.style.marginTop;
|
|
3845
|
+
const prevMarginBottom = html.style.marginBottom;
|
|
3846
|
+
let collapsed = false;
|
|
3847
|
+
let dock = "top";
|
|
3848
|
+
let previewOn = false;
|
|
3849
|
+
let hiddenOn = false;
|
|
3850
|
+
let heightCb = null;
|
|
3851
|
+
const height = () => CHROME_TOPBAR_H + (collapsed ? 0 : CHROME_STEPS_H);
|
|
3852
|
+
const applyHeight = () => {
|
|
3853
|
+
const h = previewOn || hiddenOn ? 0 : height();
|
|
3854
|
+
html.style.marginTop = dock === "top" ? `${h}px` : prevMarginTop;
|
|
3855
|
+
html.style.marginBottom = dock === "bottom" ? `${h}px` : prevMarginBottom;
|
|
3856
|
+
root.style.setProperty("--veo-chrome-h", `${height()}px`);
|
|
3857
|
+
root.classList.toggle("is-bottom", dock === "bottom");
|
|
3858
|
+
stepsBar.hidden = collapsed;
|
|
3859
|
+
const open = dock === "top" ? "chevronUp" : "chevronDown";
|
|
3860
|
+
const closedIcon = dock === "top" ? "chevronDown" : "chevronUp";
|
|
3861
|
+
togglePill.innerHTML = `<span>${collapsed ? "Mostrar pasos" : "Ocultar pasos"}</span>${svg(
|
|
3862
|
+
collapsed ? closedIcon : open,
|
|
3863
|
+
16
|
|
3864
|
+
)}`;
|
|
3865
|
+
dockBtn.title = dock === "top" ? "Mover la barra abajo" : "Mover la barra arriba";
|
|
3866
|
+
dockBtn.setAttribute("aria-label", dockBtn.title);
|
|
3867
|
+
heightCb?.(h);
|
|
3868
|
+
};
|
|
3869
|
+
const setPreview = (on) => {
|
|
3870
|
+
previewOn = on;
|
|
3871
|
+
root.hidden = on || hiddenOn;
|
|
3872
|
+
previewPill.hidden = !on;
|
|
3873
|
+
applyHeight();
|
|
3874
|
+
};
|
|
3875
|
+
const setHidden = (on) => {
|
|
3876
|
+
hiddenOn = on;
|
|
3877
|
+
root.hidden = on || previewOn;
|
|
3878
|
+
applyHeight();
|
|
3879
|
+
};
|
|
3880
|
+
togglePill.addEventListener("click", () => {
|
|
3881
|
+
collapsed = !collapsed;
|
|
3882
|
+
applyHeight();
|
|
3883
|
+
});
|
|
3884
|
+
const act = (a) => opts.onAction(a);
|
|
3885
|
+
dockBtn.addEventListener("click", () => {
|
|
3886
|
+
dock = dock === "top" ? "bottom" : "top";
|
|
3887
|
+
applyHeight();
|
|
3888
|
+
act({ action: "dock", position: dock });
|
|
3889
|
+
});
|
|
3890
|
+
showPanel.addEventListener("click", () => act({ action: "show-panel" }));
|
|
3891
|
+
preview.addEventListener("click", () => act({ action: "preview" }));
|
|
3892
|
+
previewExit.addEventListener("click", () => act({ action: "exit-preview" }));
|
|
3893
|
+
exit.addEventListener("click", () => act({ action: "exit" }));
|
|
3894
|
+
save.addEventListener("click", () => act({ action: "save", exit: false }));
|
|
3895
|
+
saveMore.addEventListener("click", (e) => {
|
|
3896
|
+
e.stopPropagation();
|
|
3897
|
+
saveMenu.hidden = !saveMenu.hidden;
|
|
3898
|
+
});
|
|
3899
|
+
saveExit.addEventListener("click", () => {
|
|
3900
|
+
saveMenu.hidden = true;
|
|
3901
|
+
act({ action: "save", exit: true });
|
|
3902
|
+
});
|
|
3903
|
+
const closeMenu = () => {
|
|
3904
|
+
saveMenu.hidden = true;
|
|
3905
|
+
};
|
|
3906
|
+
document.addEventListener("click", closeMenu);
|
|
3907
|
+
let current = null;
|
|
3908
|
+
const render = () => {
|
|
3909
|
+
const s = current;
|
|
3910
|
+
if (!s) return;
|
|
3911
|
+
const date = shortDate(s.createdAt);
|
|
3912
|
+
nameEl.textContent = `${s.guideName.trim() || "Sin nombre"}${date ? ` \xB7 ${date}` : ""}`;
|
|
3913
|
+
if (s.status) {
|
|
3914
|
+
statusEl.hidden = false;
|
|
3915
|
+
statusEl.textContent = s.status.label;
|
|
3916
|
+
statusEl.dataset.tone = s.status.tone;
|
|
3917
|
+
statusEl.title = "Estado de la gu\xEDa (se cambia desde la lista de gu\xEDas)";
|
|
3918
|
+
} else {
|
|
3919
|
+
statusEl.hidden = true;
|
|
3920
|
+
}
|
|
3921
|
+
save.innerHTML = s.saving ? `${svg("spinner", 16)}<span>Guardando\u2026</span>` : "<span>Guardar</span>";
|
|
3922
|
+
save.disabled = s.saving;
|
|
3923
|
+
saveExit.disabled = s.saving;
|
|
3924
|
+
stepsList.replaceChildren();
|
|
3925
|
+
const activation = stepCard(svg("cursor", 22), "Activaci\xF3n", s.section === "activation");
|
|
3926
|
+
activation.addEventListener("click", () => act({ action: "select-activation" }));
|
|
3927
|
+
stepsList.append(activation);
|
|
3928
|
+
s.steps.forEach((st, i) => {
|
|
3929
|
+
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>';
|
|
3930
|
+
const card = stepCard(thumb, st.label, s.section === "step" && s.activeStep === i);
|
|
3931
|
+
card.addEventListener("click", () => act({ action: "select-step", index: i }));
|
|
3932
|
+
stepsList.append(card);
|
|
3933
|
+
});
|
|
3934
|
+
const add = el("button", "veo-step-add", `${svg("plus", 18)}<span>Agregar paso</span>`);
|
|
3935
|
+
add.type = "button";
|
|
3936
|
+
add.addEventListener("click", () => act({ action: "add-step" }));
|
|
3937
|
+
stepsList.append(add);
|
|
3938
|
+
};
|
|
3939
|
+
applyHeight();
|
|
3940
|
+
return {
|
|
3941
|
+
setState: (state) => {
|
|
3942
|
+
current = state;
|
|
3943
|
+
render();
|
|
3944
|
+
},
|
|
3945
|
+
height,
|
|
3946
|
+
dock: () => dock,
|
|
3947
|
+
setPreview,
|
|
3948
|
+
setHidden,
|
|
3949
|
+
onHeightChange: (cb) => {
|
|
3950
|
+
heightCb = cb;
|
|
3951
|
+
},
|
|
3952
|
+
teardown: () => {
|
|
3953
|
+
document.removeEventListener("click", closeMenu);
|
|
3954
|
+
html.style.marginTop = prevMarginTop;
|
|
3955
|
+
html.style.marginBottom = prevMarginBottom;
|
|
3956
|
+
host.remove();
|
|
3957
|
+
}
|
|
3958
|
+
};
|
|
3959
|
+
}
|
|
3960
|
+
function stepCard(inner, label, active) {
|
|
3961
|
+
const b = el(
|
|
3962
|
+
"button",
|
|
3963
|
+
`veo-step${active ? " is-active" : ""}`,
|
|
3964
|
+
`<div class="veo-step-box">${inner}</div><span class="veo-step-label"></span>`
|
|
3965
|
+
);
|
|
3966
|
+
b.type = "button";
|
|
3967
|
+
b.querySelector(".veo-step-label").textContent = label;
|
|
3968
|
+
b.setAttribute("aria-pressed", active ? "true" : "false");
|
|
3969
|
+
return b;
|
|
3970
|
+
}
|
|
3971
|
+
var CHROME_CSS = `
|
|
3972
|
+
:host { all: initial; }
|
|
3973
|
+
.veo-chrome {
|
|
3974
|
+
position: fixed; top: 0; left: 0; right: 0;
|
|
3975
|
+
display: flex; flex-direction: column;
|
|
3976
|
+
z-index: 2147483646;
|
|
3977
|
+
font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
|
|
3978
|
+
font-size: 14px; color: #1c1917;
|
|
3979
|
+
}
|
|
3980
|
+
.veo-chrome[hidden] { display: none; }
|
|
3981
|
+
.veo-chrome.is-bottom { top: auto; bottom: 0; flex-direction: column-reverse; }
|
|
3982
|
+
.veo-chrome.is-bottom .veo-tb-menu { top: auto; bottom: calc(100% + 8px); }
|
|
3983
|
+
.veo-chrome.is-bottom .veo-steps { border-bottom: 0; border-top: 1px solid #d6cfc8; }
|
|
3984
|
+
.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%); }
|
|
3985
|
+
.veo-preview-pill {
|
|
3986
|
+
position: fixed; top: 28px; left: 50%; transform: translateX(-50%);
|
|
3987
|
+
z-index: 2147483646;
|
|
3988
|
+
display: inline-flex; align-items: center; gap: 12px;
|
|
3989
|
+
background: #2b2623; color: #fff; border-radius: 999px; padding: 12px 20px;
|
|
3990
|
+
font-family: system-ui, -apple-system, "Segoe UI", sans-serif; font-size: 15px; font-weight: 500;
|
|
3991
|
+
box-shadow: 0 8px 24px rgba(0,0,0,0.3);
|
|
3992
|
+
}
|
|
3993
|
+
.veo-preview-pill[hidden] { display: none; }
|
|
3994
|
+
.veo-preview-label { display: inline-flex; align-items: center; gap: 10px; padding-right: 12px; border-right: 1px solid rgba(255,255,255,0.3); }
|
|
3995
|
+
.veo-preview-exit { border: 0; background: transparent; color: #fff; font: inherit; cursor: pointer; padding: 0 2px; }
|
|
3996
|
+
.veo-preview-exit:hover { text-decoration: underline; }
|
|
3997
|
+
.veo-tb {
|
|
3998
|
+
height: ${CHROME_TOPBAR_H}px; box-sizing: border-box;
|
|
3999
|
+
display: flex; align-items: center; justify-content: space-between;
|
|
4000
|
+
padding: 0 20px; gap: 16px;
|
|
4001
|
+
background: #2b2623; color: #fff;
|
|
4002
|
+
}
|
|
4003
|
+
.veo-tb-left, .veo-tb-right { display: flex; align-items: center; gap: 12px; min-width: 0; }
|
|
4004
|
+
.veo-tb-brand {
|
|
4005
|
+
width: 36px; height: 36px; border-radius: 999px; background: #b74d00;
|
|
4006
|
+
display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
|
|
4007
|
+
}
|
|
4008
|
+
.veo-tb-name { font-weight: 700; font-size: 16px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
4009
|
+
.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; }
|
|
4010
|
+
.veo-tb-status[data-tone="live"] { background: #16a34a; }
|
|
4011
|
+
.veo-tb-status[data-tone="testing"] { background: #b45309; }
|
|
4012
|
+
.veo-tb-status[data-tone="review"] { background: #7c3aed; }
|
|
4013
|
+
.veo-tb-status[data-tone="draft"] { background: #0f766e; }
|
|
4014
|
+
.veo-tb-status[data-tone="paused"] { background: rgba(255,255,255,0.28); }
|
|
4015
|
+
.veo-tb-sep { width: 1px; height: 24px; background: rgba(255,255,255,0.25); }
|
|
4016
|
+
.veo-tb-vsep { width: 1px; height: 28px; background: rgba(255,255,255,0.25); margin: 0 4px; }
|
|
4017
|
+
.veo-tb-app { display: inline-flex; align-items: center; gap: 8px; color: rgba(255,255,255,0.85); white-space: nowrap; }
|
|
4018
|
+
.veo-tb-icon {
|
|
4019
|
+
width: 42px; height: 42px; border-radius: 10px; border: 0;
|
|
4020
|
+
background: rgba(255,255,255,0.12); color: #fff; cursor: pointer;
|
|
4021
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
4022
|
+
}
|
|
4023
|
+
.veo-tb-icon:hover { background: rgba(255,255,255,0.22); }
|
|
4024
|
+
.veo-tb-text { border: 0; background: transparent; color: #fff; font: inherit; font-size: 15px; cursor: pointer; padding: 8px 6px; }
|
|
4025
|
+
.veo-tb-text:hover { text-decoration: underline; }
|
|
4026
|
+
.veo-tb-save { position: relative; display: inline-flex; border-radius: 10px; overflow: visible; }
|
|
4027
|
+
.veo-tb-save-main, .veo-tb-save-more {
|
|
4028
|
+
border: 0; background: #b74d00; color: #fff; font: inherit; font-weight: 600; font-size: 15px;
|
|
4029
|
+
cursor: pointer; display: inline-flex; align-items: center; gap: 8px; height: 42px;
|
|
4030
|
+
}
|
|
4031
|
+
.veo-tb-save-main { padding: 0 8px 0 18px; border-radius: 10px 0 0 10px; }
|
|
4032
|
+
.veo-tb-save-more { padding: 0 12px 0 6px; border-radius: 0 10px 10px 0; }
|
|
4033
|
+
.veo-tb-save-main:hover, .veo-tb-save-more:hover { background: #953c00; }
|
|
4034
|
+
.veo-tb-save-main:disabled { opacity: 0.7; cursor: default; }
|
|
4035
|
+
.veo-tb-menu {
|
|
4036
|
+
position: absolute; right: 0; top: calc(100% + 8px); min-width: 220px;
|
|
4037
|
+
background: #fff; color: #1c1917; border-radius: 12px; padding: 6px;
|
|
4038
|
+
box-shadow: 0 12px 32px rgba(0,0,0,0.22);
|
|
4039
|
+
}
|
|
4040
|
+
.veo-tb-menu-item {
|
|
4041
|
+
display: block; width: 100%; text-align: left; border: 0; background: transparent;
|
|
4042
|
+
font: inherit; font-size: 15px; padding: 10px 14px; border-radius: 8px; cursor: pointer;
|
|
4043
|
+
}
|
|
4044
|
+
.veo-tb-menu-item:hover { background: #f5efe9; }
|
|
4045
|
+
.veo-steps {
|
|
4046
|
+
height: ${CHROME_STEPS_H}px; box-sizing: border-box;
|
|
4047
|
+
background: #e7e1dc; border-bottom: 1px solid #d6cfc8;
|
|
4048
|
+
padding: 16px 28px 0; overflow-x: auto;
|
|
4049
|
+
}
|
|
4050
|
+
.veo-steps[hidden] { display: none; }
|
|
4051
|
+
.veo-steps-list { display: flex; align-items: flex-start; gap: 20px; }
|
|
4052
|
+
.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; }
|
|
4053
|
+
.veo-step-box {
|
|
4054
|
+
width: 116px; height: 64px; border-radius: 10px; background: #fff; border: 2px solid transparent;
|
|
4055
|
+
display: flex; align-items: center; justify-content: center; color: #2b2623;
|
|
4056
|
+
box-shadow: 0 1px 2px rgba(0,0,0,0.06);
|
|
4057
|
+
}
|
|
4058
|
+
.veo-step.is-active .veo-step-box { border-color: #b74d00; }
|
|
4059
|
+
.veo-step-label { font-size: 13px; color: #6b635d; }
|
|
4060
|
+
.veo-step.is-active .veo-step-label { color: #2b2623; font-weight: 600; }
|
|
4061
|
+
.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; }
|
|
4062
|
+
.veo-thumb i { display: block; height: 3px; border-radius: 2px; background: #2b2623; width: 70%; }
|
|
4063
|
+
.veo-thumb i + i { width: 45%; background: #c9c2bb; }
|
|
4064
|
+
.veo-thumb b { display: block; height: 6px; width: 24px; border-radius: 2px; background: #b74d00; align-self: flex-end; }
|
|
4065
|
+
.veo-thumb-inline { border-style: dashed; }
|
|
4066
|
+
.veo-thumb-inline i { width: 100%; }
|
|
4067
|
+
.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; }
|
|
4068
|
+
.veo-step-add:hover { color: #2b2623; }
|
|
4069
|
+
.veo-steps-toggle {
|
|
4070
|
+
position: absolute; left: 50%; top: var(--veo-chrome-h, ${CHROME_TOPBAR_H + CHROME_STEPS_H}px);
|
|
4071
|
+
transform: translate(-50%, -50%);
|
|
4072
|
+
border: 0; background: #2b2623; color: #fff; font: inherit; font-size: 14px; font-weight: 500;
|
|
4073
|
+
border-radius: 999px; padding: 10px 18px; cursor: pointer;
|
|
4074
|
+
display: inline-flex; align-items: center; gap: 8px;
|
|
4075
|
+
box-shadow: 0 6px 18px rgba(0,0,0,0.25);
|
|
4076
|
+
}
|
|
4077
|
+
`;
|
|
4078
|
+
|
|
3511
4079
|
// src/plugins/builder/builder-panel.ts
|
|
3512
4080
|
var DEFAULT_PANEL_PATH = "/guides/design";
|
|
3513
|
-
var PANEL_W =
|
|
3514
|
-
var PANEL_H =
|
|
4081
|
+
var PANEL_W = 484;
|
|
4082
|
+
var PANEL_H = 660;
|
|
3515
4083
|
var MIN_W = 320;
|
|
3516
4084
|
var MIN_H = 320;
|
|
3517
4085
|
var MARGIN = 16;
|
|
4086
|
+
var HEADER_H = 52;
|
|
3518
4087
|
function injectBuilderPanel(opts) {
|
|
3519
4088
|
if (!hasWindow() || !hasDocument()) {
|
|
3520
|
-
return {
|
|
3521
|
-
|
|
4089
|
+
return {
|
|
4090
|
+
target: () => null,
|
|
4091
|
+
frameRect: () => null,
|
|
4092
|
+
teardown: () => {
|
|
4093
|
+
},
|
|
4094
|
+
setTitle: () => {
|
|
4095
|
+
},
|
|
4096
|
+
setVisible: () => {
|
|
4097
|
+
},
|
|
4098
|
+
isVisible: () => false,
|
|
4099
|
+
setTopOffset: () => {
|
|
4100
|
+
}
|
|
4101
|
+
};
|
|
3522
4102
|
}
|
|
3523
4103
|
const panelUrl = buildPanelUrl(opts);
|
|
3524
4104
|
const host = document.createElement("div");
|
|
@@ -3528,43 +4108,68 @@ function injectBuilderPanel(opts) {
|
|
|
3528
4108
|
style.textContent = PANEL_CSS;
|
|
3529
4109
|
const card = document.createElement("div");
|
|
3530
4110
|
card.className = "veo-panel";
|
|
3531
|
-
let
|
|
3532
|
-
let
|
|
4111
|
+
let topOffset = opts.topOffset ?? 0;
|
|
4112
|
+
let left = 40;
|
|
4113
|
+
let top = topOffset + MARGIN;
|
|
3533
4114
|
card.style.left = `${left}px`;
|
|
3534
4115
|
card.style.top = `${top}px`;
|
|
3535
4116
|
card.style.width = `${PANEL_W}px`;
|
|
3536
4117
|
card.style.height = `${PANEL_H}px`;
|
|
3537
4118
|
const header = document.createElement("div");
|
|
3538
4119
|
header.className = "veo-panel-header";
|
|
4120
|
+
const grip = document.createElement("span");
|
|
4121
|
+
grip.className = "veo-panel-grip";
|
|
4122
|
+
grip.setAttribute("aria-hidden", "true");
|
|
4123
|
+
grip.textContent = "\xB7\xB7\xB7";
|
|
3539
4124
|
const title = document.createElement("span");
|
|
3540
4125
|
title.className = "veo-panel-title";
|
|
3541
4126
|
title.textContent = "OnUser \xB7 Editor";
|
|
3542
4127
|
const actions = document.createElement("div");
|
|
3543
4128
|
actions.className = "veo-panel-actions";
|
|
3544
|
-
const popout =
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
popout
|
|
3548
|
-
|
|
3549
|
-
popout.textContent = "\u29C9";
|
|
3550
|
-
const close = document.createElement("button");
|
|
3551
|
-
close.className = "veo-panel-btn veo-panel-close";
|
|
3552
|
-
close.type = "button";
|
|
3553
|
-
close.title = "Cerrar";
|
|
3554
|
-
close.setAttribute("aria-label", "Cerrar");
|
|
3555
|
-
close.textContent = "\u2715";
|
|
3556
|
-
actions.append(popout, close);
|
|
3557
|
-
header.append(title, actions);
|
|
4129
|
+
const popout = panelButton(ICON_POPOUT, "Abrir en ventana aparte");
|
|
4130
|
+
const maximize = panelButton(ICON_EXPAND, "Maximizar");
|
|
4131
|
+
const minimize = panelButton(ICON_MINUS, "Minimizar");
|
|
4132
|
+
actions.append(popout, maximize, minimize);
|
|
4133
|
+
header.append(grip, title, actions);
|
|
3558
4134
|
const iframe = document.createElement("iframe");
|
|
3559
4135
|
iframe.className = "veo-panel-frame";
|
|
3560
4136
|
iframe.title = "Editor de Veo";
|
|
3561
4137
|
iframe.src = panelUrl;
|
|
3562
|
-
const
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
card.append(header, iframe,
|
|
4138
|
+
const resizeGrip = document.createElement("div");
|
|
4139
|
+
resizeGrip.className = "veo-panel-resize";
|
|
4140
|
+
resizeGrip.setAttribute("aria-hidden", "true");
|
|
4141
|
+
card.append(header, iframe, resizeGrip);
|
|
3566
4142
|
shadow.append(style, card);
|
|
3567
4143
|
document.body.appendChild(host);
|
|
4144
|
+
let visible = true;
|
|
4145
|
+
let maximized = false;
|
|
4146
|
+
let restore = null;
|
|
4147
|
+
const setVisible = (next) => {
|
|
4148
|
+
visible = next;
|
|
4149
|
+
card.style.display = next && !(popped && !popped.closed) ? "" : "none";
|
|
4150
|
+
};
|
|
4151
|
+
minimize.addEventListener("click", () => setVisible(false));
|
|
4152
|
+
maximize.addEventListener("click", () => {
|
|
4153
|
+
maximized = !maximized;
|
|
4154
|
+
if (maximized) {
|
|
4155
|
+
restore = { left, top, w: card.offsetWidth, h: card.offsetHeight };
|
|
4156
|
+
left = MARGIN;
|
|
4157
|
+
top = topOffset + MARGIN;
|
|
4158
|
+
card.style.left = `${left}px`;
|
|
4159
|
+
card.style.top = `${top}px`;
|
|
4160
|
+
card.style.width = `${Math.max(MIN_W, window.innerWidth - MARGIN * 2)}px`;
|
|
4161
|
+
card.style.height = `${Math.max(MIN_H, window.innerHeight - top - MARGIN)}px`;
|
|
4162
|
+
maximize.title = "Restaurar";
|
|
4163
|
+
} else if (restore) {
|
|
4164
|
+
left = restore.left;
|
|
4165
|
+
top = restore.top;
|
|
4166
|
+
card.style.left = `${left}px`;
|
|
4167
|
+
card.style.top = `${top}px`;
|
|
4168
|
+
card.style.width = `${restore.w}px`;
|
|
4169
|
+
card.style.height = `${restore.h}px`;
|
|
4170
|
+
maximize.title = "Maximizar";
|
|
4171
|
+
}
|
|
4172
|
+
});
|
|
3568
4173
|
let popped = null;
|
|
3569
4174
|
let pollTimer;
|
|
3570
4175
|
const stopPoll = () => {
|
|
@@ -3573,7 +4178,6 @@ function injectBuilderPanel(opts) {
|
|
|
3573
4178
|
pollTimer = void 0;
|
|
3574
4179
|
}
|
|
3575
4180
|
};
|
|
3576
|
-
close.addEventListener("click", () => opts.onClose());
|
|
3577
4181
|
popout.addEventListener("click", () => {
|
|
3578
4182
|
const win = window.open(
|
|
3579
4183
|
panelUrl,
|
|
@@ -3591,7 +4195,7 @@ function injectBuilderPanel(opts) {
|
|
|
3591
4195
|
}, 600);
|
|
3592
4196
|
});
|
|
3593
4197
|
header.addEventListener("mousedown", (e) => {
|
|
3594
|
-
if (e.target?.
|
|
4198
|
+
if (e.target?.closest(".veo-panel-btn")) return;
|
|
3595
4199
|
e.preventDefault();
|
|
3596
4200
|
const sx = e.clientX;
|
|
3597
4201
|
const sy = e.clientY;
|
|
@@ -3600,7 +4204,7 @@ function injectBuilderPanel(opts) {
|
|
|
3600
4204
|
iframe.style.pointerEvents = "none";
|
|
3601
4205
|
const move = (ev) => {
|
|
3602
4206
|
left = clamp3(ol + (ev.clientX - sx), 0, Math.max(0, window.innerWidth - card.offsetWidth));
|
|
3603
|
-
top = clamp3(ot + (ev.clientY - sy),
|
|
4207
|
+
top = clamp3(ot + (ev.clientY - sy), topOffset, Math.max(topOffset, window.innerHeight - 40));
|
|
3604
4208
|
card.style.left = `${left}px`;
|
|
3605
4209
|
card.style.top = `${top}px`;
|
|
3606
4210
|
};
|
|
@@ -3612,7 +4216,7 @@ function injectBuilderPanel(opts) {
|
|
|
3612
4216
|
window.addEventListener("mousemove", move);
|
|
3613
4217
|
window.addEventListener("mouseup", up);
|
|
3614
4218
|
});
|
|
3615
|
-
|
|
4219
|
+
resizeGrip.addEventListener("mousedown", (e) => {
|
|
3616
4220
|
e.preventDefault();
|
|
3617
4221
|
e.stopPropagation();
|
|
3618
4222
|
const sx = e.clientX;
|
|
@@ -3639,9 +4243,33 @@ function injectBuilderPanel(opts) {
|
|
|
3639
4243
|
stopPoll();
|
|
3640
4244
|
if (popped && !popped.closed) popped.close();
|
|
3641
4245
|
host.remove();
|
|
4246
|
+
},
|
|
4247
|
+
setTitle: (t) => {
|
|
4248
|
+
title.textContent = t;
|
|
4249
|
+
},
|
|
4250
|
+
setVisible,
|
|
4251
|
+
isVisible: () => visible,
|
|
4252
|
+
setTopOffset: (px) => {
|
|
4253
|
+
topOffset = px;
|
|
4254
|
+
if (top < topOffset + MARGIN) {
|
|
4255
|
+
top = topOffset + MARGIN;
|
|
4256
|
+
card.style.top = `${top}px`;
|
|
4257
|
+
}
|
|
3642
4258
|
}
|
|
3643
4259
|
};
|
|
3644
4260
|
}
|
|
4261
|
+
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"/>';
|
|
4262
|
+
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"/>';
|
|
4263
|
+
var ICON_MINUS = '<path stroke-linecap="round" stroke-linejoin="round" d="M5 12h14"/>';
|
|
4264
|
+
function panelButton(iconPath, label) {
|
|
4265
|
+
const b = document.createElement("button");
|
|
4266
|
+
b.className = "veo-panel-btn";
|
|
4267
|
+
b.type = "button";
|
|
4268
|
+
b.title = label;
|
|
4269
|
+
b.setAttribute("aria-label", label);
|
|
4270
|
+
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>`;
|
|
4271
|
+
return b;
|
|
4272
|
+
}
|
|
3645
4273
|
function clamp3(v, min, max) {
|
|
3646
4274
|
return Math.min(Math.max(v, min), max);
|
|
3647
4275
|
}
|
|
@@ -3661,28 +4289,33 @@ var PANEL_CSS = `
|
|
|
3661
4289
|
max-width: 96vw; max-height: 94vh;
|
|
3662
4290
|
display: flex; flex-direction: column;
|
|
3663
4291
|
background: #fff;
|
|
3664
|
-
border-radius:
|
|
3665
|
-
box-shadow: 0 12px 40px rgba(0,0,0,0.
|
|
4292
|
+
border-radius: 14px;
|
|
4293
|
+
box-shadow: 0 12px 40px rgba(0,0,0,0.22);
|
|
3666
4294
|
overflow: hidden;
|
|
3667
4295
|
z-index: 2147483647;
|
|
3668
4296
|
font-family: system-ui, -apple-system, sans-serif;
|
|
3669
4297
|
}
|
|
3670
4298
|
.veo-panel-header {
|
|
3671
|
-
flex: 0 0 auto;
|
|
4299
|
+
position: relative; flex: 0 0 auto; height: ${HEADER_H}px; box-sizing: border-box;
|
|
3672
4300
|
display: flex; align-items: center; justify-content: space-between;
|
|
3673
|
-
padding:
|
|
3674
|
-
background: #
|
|
3675
|
-
font-size:
|
|
4301
|
+
padding: 10px 14px 0 22px;
|
|
4302
|
+
background: #fbf8f5; color: #1c1917; border-bottom: 1px solid #e8e2dc;
|
|
4303
|
+
font-size: 17px; font-weight: 700;
|
|
3676
4304
|
cursor: grab;
|
|
3677
4305
|
}
|
|
3678
4306
|
.veo-panel-header:active { cursor: grabbing; }
|
|
4307
|
+
.veo-panel-grip {
|
|
4308
|
+
position: absolute; top: 0; left: 50%; transform: translateX(-50%);
|
|
4309
|
+
color: #b5aca4; font-size: 14px; letter-spacing: 1px; line-height: 12px;
|
|
4310
|
+
}
|
|
4311
|
+
.veo-panel-title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
3679
4312
|
.veo-panel-actions { display: flex; gap: 2px; }
|
|
3680
4313
|
.veo-panel-btn {
|
|
3681
|
-
border: 0; background: transparent; color: #
|
|
3682
|
-
|
|
3683
|
-
padding:
|
|
4314
|
+
border: 0; background: transparent; color: #4b4540;
|
|
4315
|
+
cursor: pointer; line-height: 1; display: inline-flex; align-items: center;
|
|
4316
|
+
padding: 6px; border-radius: 8px;
|
|
3684
4317
|
}
|
|
3685
|
-
.veo-panel-btn:hover { background: rgba(
|
|
4318
|
+
.veo-panel-btn:hover { background: rgba(0,0,0,0.06); color: #1c1917; }
|
|
3686
4319
|
.veo-panel-frame { flex: 1 1 auto; width: 100%; border: 0; background: #fff; }
|
|
3687
4320
|
.veo-panel-resize {
|
|
3688
4321
|
position: absolute; right: 0; bottom: 0;
|
|
@@ -4022,9 +4655,9 @@ var PICKER_STYLES = `
|
|
|
4022
4655
|
z-index: ${PICKER_Z};
|
|
4023
4656
|
pointer-events: none;
|
|
4024
4657
|
box-sizing: border-box;
|
|
4025
|
-
background:
|
|
4026
|
-
border:
|
|
4027
|
-
border-radius:
|
|
4658
|
+
background: transparent;
|
|
4659
|
+
border: 3px dashed #b74d00;
|
|
4660
|
+
border-radius: 8px;
|
|
4028
4661
|
transition: top 60ms ease-out, left 60ms ease-out, width 60ms ease-out, height 60ms ease-out;
|
|
4029
4662
|
}
|
|
4030
4663
|
.veo-pick-label {
|
|
@@ -4032,30 +4665,48 @@ var PICKER_STYLES = `
|
|
|
4032
4665
|
z-index: ${PICKER_Z};
|
|
4033
4666
|
pointer-events: none;
|
|
4034
4667
|
max-width: 360px;
|
|
4035
|
-
background: #
|
|
4036
|
-
color: #
|
|
4668
|
+
background: #2b2623;
|
|
4669
|
+
color: #f5efe9;
|
|
4037
4670
|
font: 12px/1.45 ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
4038
4671
|
padding: 6px 9px;
|
|
4039
4672
|
border-radius: 6px;
|
|
4040
4673
|
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.35);
|
|
4041
4674
|
}
|
|
4042
|
-
.veo-pick-label .veo-pick-sel { color: #
|
|
4043
|
-
.veo-pick-label .veo-pick-dim { color: #
|
|
4675
|
+
.veo-pick-label .veo-pick-sel { color: #ffd1ad; word-break: break-all; }
|
|
4676
|
+
.veo-pick-label .veo-pick-dim { color: #c9c2bb; margin-top: 3px; }
|
|
4044
4677
|
.veo-pick-hint {
|
|
4045
4678
|
position: fixed;
|
|
4046
|
-
top:
|
|
4679
|
+
top: 28px;
|
|
4047
4680
|
left: 50%;
|
|
4048
4681
|
transform: translateX(-50%);
|
|
4049
4682
|
z-index: ${PICKER_Z};
|
|
4050
4683
|
pointer-events: none;
|
|
4051
|
-
|
|
4684
|
+
display: flex; align-items: center; gap: 16px;
|
|
4685
|
+
max-width: min(760px, calc(100vw - 32px));
|
|
4686
|
+
background: #2b2623;
|
|
4052
4687
|
color: #fff;
|
|
4053
|
-
font:
|
|
4054
|
-
padding:
|
|
4055
|
-
border-radius:
|
|
4056
|
-
box-shadow: 0
|
|
4688
|
+
font: 15px/1.4 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
4689
|
+
padding: 14px 18px 14px 16px;
|
|
4690
|
+
border-radius: 14px;
|
|
4691
|
+
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
|
|
4692
|
+
}
|
|
4693
|
+
.veo-pick-hint-icon {
|
|
4694
|
+
flex: 0 0 auto; width: 44px; height: 44px; border-radius: 999px;
|
|
4695
|
+
background: rgba(255,255,255,0.12);
|
|
4696
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
4697
|
+
}
|
|
4698
|
+
.veo-pick-hint-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
|
|
4699
|
+
.veo-pick-hint-title { font-weight: 700; }
|
|
4700
|
+
.veo-pick-hint-sub { font-size: 13px; color: rgba(255,255,255,0.75); }
|
|
4701
|
+
.veo-pick-cancel {
|
|
4702
|
+
flex: 0 0 auto; pointer-events: auto;
|
|
4703
|
+
border: 0; border-radius: 10px; padding: 12px 18px;
|
|
4704
|
+
background: rgba(255,255,255,0.14); color: #fff;
|
|
4705
|
+
font: inherit; font-weight: 600; cursor: pointer;
|
|
4057
4706
|
}
|
|
4707
|
+
.veo-pick-cancel:hover { background: rgba(255,255,255,0.24); }
|
|
4058
4708
|
`;
|
|
4709
|
+
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>';
|
|
4059
4710
|
var ElementPicker = class {
|
|
4060
4711
|
constructor() {
|
|
4061
4712
|
this.host = null;
|
|
@@ -4072,6 +4723,7 @@ var ElementPicker = class {
|
|
|
4072
4723
|
this.draw(target);
|
|
4073
4724
|
};
|
|
4074
4725
|
this.onClick = (event) => {
|
|
4726
|
+
if (event.altKey) return;
|
|
4075
4727
|
const target = this.current ?? (event.target instanceof Element ? event.target : null);
|
|
4076
4728
|
if (!target || this.isOwn(target)) return;
|
|
4077
4729
|
event.preventDefault();
|
|
@@ -4092,7 +4744,7 @@ var ElementPicker = class {
|
|
|
4092
4744
|
};
|
|
4093
4745
|
/** Traga mousedown/mouseup durante el picking (evita focus/active de la app). */
|
|
4094
4746
|
this.swallow = (event) => {
|
|
4095
|
-
if (this.isOwn(event.target)) return;
|
|
4747
|
+
if (event.altKey || this.isOwn(event.target)) return;
|
|
4096
4748
|
event.preventDefault();
|
|
4097
4749
|
event.stopPropagation();
|
|
4098
4750
|
};
|
|
@@ -4118,7 +4770,29 @@ var ElementPicker = class {
|
|
|
4118
4770
|
this.label.style.display = "none";
|
|
4119
4771
|
const hint = document.createElement("div");
|
|
4120
4772
|
hint.className = "veo-pick-hint";
|
|
4121
|
-
|
|
4773
|
+
const icon = document.createElement("span");
|
|
4774
|
+
icon.className = "veo-pick-hint-icon";
|
|
4775
|
+
icon.innerHTML = HINT_ICON;
|
|
4776
|
+
const text = document.createElement("div");
|
|
4777
|
+
text.className = "veo-pick-hint-text";
|
|
4778
|
+
const title = document.createElement("span");
|
|
4779
|
+
title.className = "veo-pick-hint-title";
|
|
4780
|
+
title.textContent = options.hint ?? "Selecciona un elemento existente para colocar la gu\xEDa.";
|
|
4781
|
+
const sub = document.createElement("span");
|
|
4782
|
+
sub.className = "veo-pick-hint-sub";
|
|
4783
|
+
sub.textContent = options.subhint ?? "Usa Alt + clic u Opci\xF3n + clic para abrir men\xFAs y desplegables.";
|
|
4784
|
+
text.append(title, sub);
|
|
4785
|
+
const cancel = document.createElement("button");
|
|
4786
|
+
cancel.className = "veo-pick-cancel";
|
|
4787
|
+
cancel.type = "button";
|
|
4788
|
+
cancel.textContent = "Cancelar";
|
|
4789
|
+
cancel.addEventListener("click", (e) => {
|
|
4790
|
+
e.stopPropagation();
|
|
4791
|
+
const cb = this.onCancel;
|
|
4792
|
+
this.stop();
|
|
4793
|
+
cb?.();
|
|
4794
|
+
});
|
|
4795
|
+
hint.append(icon, text, cancel);
|
|
4122
4796
|
shadow.append(style, this.box, this.label, hint);
|
|
4123
4797
|
document.body.appendChild(host);
|
|
4124
4798
|
this.host = host;
|
|
@@ -4216,6 +4890,7 @@ function initBuilderMode() {
|
|
|
4216
4890
|
if (!dashboardOrigin) return null;
|
|
4217
4891
|
let picker = null;
|
|
4218
4892
|
let panel = null;
|
|
4893
|
+
let chrome = null;
|
|
4219
4894
|
let staticTarget = null;
|
|
4220
4895
|
let manipulator = null;
|
|
4221
4896
|
let dropTarget = null;
|
|
@@ -4223,26 +4898,89 @@ function initBuilderMode() {
|
|
|
4223
4898
|
let previewStepIndex = 0;
|
|
4224
4899
|
let pendingPreview = null;
|
|
4225
4900
|
let lastPreview = null;
|
|
4901
|
+
let previewMode = false;
|
|
4902
|
+
let previewTrigger = null;
|
|
4903
|
+
let previewFired = false;
|
|
4904
|
+
let previewDelay = null;
|
|
4905
|
+
let panelWasVisible = true;
|
|
4226
4906
|
const getTarget = () => panel ? panel.target() : staticTarget;
|
|
4227
4907
|
const post = (event) => {
|
|
4228
4908
|
getTarget()?.postMessage({ source: VEO_BUILDER_SOURCE, token, ...event }, dashboardOrigin);
|
|
4229
4909
|
};
|
|
4230
|
-
const
|
|
4910
|
+
const previewStep = (cmd) => {
|
|
4231
4911
|
const steps = cmd.guide.guideSteps;
|
|
4232
|
-
|
|
4233
|
-
|
|
4912
|
+
return steps?.[cmd.guide.startStepIndex ?? 0];
|
|
4913
|
+
};
|
|
4914
|
+
const previewMatchesPage = (cmd) => stepMatchesPage(previewStep(cmd)?.pageLocation, window.location.href);
|
|
4915
|
+
const postPreviewStatus = (payload) => post({ type: "preview-status", payload });
|
|
4916
|
+
const withholdPreview = () => {
|
|
4917
|
+
manipulator?.detach();
|
|
4918
|
+
manipulator = null;
|
|
4919
|
+
dropTarget?.detach();
|
|
4920
|
+
dropTarget = null;
|
|
4921
|
+
closeGuidePreview();
|
|
4234
4922
|
};
|
|
4235
4923
|
const applyPreviewGated = (cmd) => {
|
|
4236
4924
|
lastPreview = cmd;
|
|
4237
|
-
if (previewMatchesPage(cmd)) {
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4925
|
+
if (!previewMatchesPage(cmd)) {
|
|
4926
|
+
cancelPreviewDelay();
|
|
4927
|
+
withholdPreview();
|
|
4928
|
+
postPreviewStatus({
|
|
4929
|
+
state: "page-mismatch",
|
|
4930
|
+
pattern: previewStep(cmd)?.pageLocation?.pattern ?? ""
|
|
4931
|
+
});
|
|
4932
|
+
return;
|
|
4933
|
+
}
|
|
4934
|
+
const devices = cmd.guide.activationRules?.devices;
|
|
4935
|
+
if (cmd.honorTrigger && !previewMode && devices && !isDeviceAllowed(devices)) {
|
|
4936
|
+
cancelPreviewDelay();
|
|
4937
|
+
withholdPreview();
|
|
4938
|
+
postPreviewStatus({ state: "device-mismatch", devices });
|
|
4939
|
+
return;
|
|
4245
4940
|
}
|
|
4941
|
+
applyPreview(cmd);
|
|
4942
|
+
};
|
|
4943
|
+
const disarmPreviewTrigger = () => {
|
|
4944
|
+
previewTrigger?.();
|
|
4945
|
+
previewTrigger = null;
|
|
4946
|
+
};
|
|
4947
|
+
const cancelPreviewDelay = () => {
|
|
4948
|
+
if (previewDelay) clearTimeout(previewDelay);
|
|
4949
|
+
previewDelay = null;
|
|
4950
|
+
};
|
|
4951
|
+
const armPreviewTrigger = (selector, trigger) => {
|
|
4952
|
+
disarmPreviewTrigger();
|
|
4953
|
+
const onFire = (e) => {
|
|
4954
|
+
const target = e.target;
|
|
4955
|
+
if (!(target instanceof Element)) return;
|
|
4956
|
+
if (target.closest("[data-veo-builder-chrome],[data-veo-builder-panel],[data-veo-picker]")) {
|
|
4957
|
+
return;
|
|
4958
|
+
}
|
|
4959
|
+
try {
|
|
4960
|
+
if (!target.closest(selector)) return;
|
|
4961
|
+
} catch {
|
|
4962
|
+
return;
|
|
4963
|
+
}
|
|
4964
|
+
disarmPreviewTrigger();
|
|
4965
|
+
previewFired = true;
|
|
4966
|
+
if (lastPreview) applyPreviewGated(lastPreview);
|
|
4967
|
+
};
|
|
4968
|
+
document.addEventListener("click", onFire, true);
|
|
4969
|
+
if (trigger === "on_hover") document.addEventListener("mouseover", onFire, true);
|
|
4970
|
+
previewTrigger = () => {
|
|
4971
|
+
document.removeEventListener("click", onFire, true);
|
|
4972
|
+
document.removeEventListener("mouseover", onFire, true);
|
|
4973
|
+
};
|
|
4974
|
+
postPreviewStatus({ state: "waiting-trigger", trigger, selector });
|
|
4975
|
+
};
|
|
4976
|
+
const armPreviewDelay = (delayMs) => {
|
|
4977
|
+
cancelPreviewDelay();
|
|
4978
|
+
previewDelay = setTimeout(() => {
|
|
4979
|
+
previewDelay = null;
|
|
4980
|
+
previewFired = true;
|
|
4981
|
+
if (lastPreview) applyPreviewGated(lastPreview);
|
|
4982
|
+
}, delayMs);
|
|
4983
|
+
postPreviewStatus({ state: "waiting-delay", delayMs });
|
|
4246
4984
|
};
|
|
4247
4985
|
const applyPreview = (cmd) => {
|
|
4248
4986
|
manipulator?.detach();
|
|
@@ -4250,8 +4988,38 @@ function initBuilderMode() {
|
|
|
4250
4988
|
dropTarget?.detach();
|
|
4251
4989
|
dropTarget = null;
|
|
4252
4990
|
previewStepIndex = cmd.guide.startStepIndex ?? 0;
|
|
4253
|
-
const
|
|
4254
|
-
|
|
4991
|
+
const rules = cmd.guide.activationRules;
|
|
4992
|
+
const trig = rules?.trigger;
|
|
4993
|
+
const sel = rules?.selector?.trim();
|
|
4994
|
+
const gate = cmd.honorTrigger && !previewFired && !previewMode;
|
|
4995
|
+
if (gate && (trig === "on_click" || trig === "on_hover") && sel) {
|
|
4996
|
+
cancelPreviewDelay();
|
|
4997
|
+
closeGuidePreview();
|
|
4998
|
+
armPreviewTrigger(sel, trig);
|
|
4999
|
+
return;
|
|
5000
|
+
}
|
|
5001
|
+
const delayMs = trig === "delayed" ? rules?.delayMs ?? 0 : 0;
|
|
5002
|
+
if (gate && delayMs > 0) {
|
|
5003
|
+
disarmPreviewTrigger();
|
|
5004
|
+
closeGuidePreview();
|
|
5005
|
+
if (!previewDelay) armPreviewDelay(delayMs);
|
|
5006
|
+
return;
|
|
5007
|
+
}
|
|
5008
|
+
disarmPreviewTrigger();
|
|
5009
|
+
cancelPreviewDelay();
|
|
5010
|
+
const handle = previewGuide({
|
|
5011
|
+
...cmd.guide,
|
|
5012
|
+
onClosed: () => {
|
|
5013
|
+
manipulator?.detach();
|
|
5014
|
+
manipulator = null;
|
|
5015
|
+
dropTarget?.detach();
|
|
5016
|
+
dropTarget = null;
|
|
5017
|
+
previewFired = false;
|
|
5018
|
+
if (lastPreview) applyPreviewGated(lastPreview);
|
|
5019
|
+
}
|
|
5020
|
+
});
|
|
5021
|
+
if (cmd.honorTrigger) postPreviewStatus({ state: "shown" });
|
|
5022
|
+
if (!cmd.editable || previewMode) return;
|
|
4255
5023
|
void handle.ready.then((result) => {
|
|
4256
5024
|
if (!result.rendered) return;
|
|
4257
5025
|
const host = handle.host();
|
|
@@ -4319,26 +5087,57 @@ function initBuilderMode() {
|
|
|
4319
5087
|
const handleCommand = (cmd) => {
|
|
4320
5088
|
switch (cmd.type) {
|
|
4321
5089
|
case "panel-ready":
|
|
4322
|
-
post({ type: "ready" });
|
|
5090
|
+
post(chrome ? { type: "ready", chrome: true } : { type: "ready" });
|
|
5091
|
+
break;
|
|
5092
|
+
case "editor-state":
|
|
5093
|
+
chrome?.setState(cmd.state);
|
|
5094
|
+
panel?.setTitle(
|
|
5095
|
+
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"
|
|
5096
|
+
);
|
|
5097
|
+
break;
|
|
5098
|
+
case "panel-visibility":
|
|
5099
|
+
panel?.setVisible(cmd.visible);
|
|
4323
5100
|
break;
|
|
4324
|
-
case "start-picker":
|
|
5101
|
+
case "start-picker": {
|
|
4325
5102
|
picker?.stop();
|
|
5103
|
+
const panelWasShown = panel?.isVisible() ?? false;
|
|
5104
|
+
if (panelWasShown) panel?.setVisible(false);
|
|
5105
|
+
chrome?.setHidden(true);
|
|
5106
|
+
const previewToRestore = lastPreview;
|
|
5107
|
+
if (previewToRestore) {
|
|
5108
|
+
manipulator?.detach();
|
|
5109
|
+
manipulator = null;
|
|
5110
|
+
dropTarget?.detach();
|
|
5111
|
+
dropTarget = null;
|
|
5112
|
+
closeGuidePreview();
|
|
5113
|
+
}
|
|
5114
|
+
const restorePanel = () => {
|
|
5115
|
+
chrome?.setHidden(false);
|
|
5116
|
+
if (panelWasShown) panel?.setVisible(true);
|
|
5117
|
+
if (previewToRestore && lastPreview === previewToRestore) {
|
|
5118
|
+
applyPreviewGated(previewToRestore);
|
|
5119
|
+
}
|
|
5120
|
+
};
|
|
4326
5121
|
picker = startElementPicker({
|
|
4327
5122
|
onPick: (payload) => {
|
|
4328
5123
|
picker = null;
|
|
5124
|
+
restorePanel();
|
|
4329
5125
|
post({ type: "picked", payload });
|
|
4330
5126
|
},
|
|
4331
5127
|
onCancel: () => {
|
|
4332
5128
|
picker = null;
|
|
5129
|
+
restorePanel();
|
|
4333
5130
|
post({ type: "pick-cancelled" });
|
|
4334
5131
|
},
|
|
4335
5132
|
...cmd.maxAncestors !== void 0 ? { maxAncestors: cmd.maxAncestors } : {},
|
|
4336
5133
|
...cmd.hint !== void 0 ? { hint: cmd.hint } : {}
|
|
4337
5134
|
});
|
|
4338
5135
|
break;
|
|
5136
|
+
}
|
|
4339
5137
|
case "stop-picker":
|
|
4340
5138
|
picker?.stop();
|
|
4341
5139
|
picker = null;
|
|
5140
|
+
chrome?.setHidden(false);
|
|
4342
5141
|
break;
|
|
4343
5142
|
case "preview":
|
|
4344
5143
|
if (!cmd.guide) break;
|
|
@@ -4356,6 +5155,9 @@ function initBuilderMode() {
|
|
|
4356
5155
|
hideDragGhost();
|
|
4357
5156
|
pendingPreview = null;
|
|
4358
5157
|
lastPreview = null;
|
|
5158
|
+
disarmPreviewTrigger();
|
|
5159
|
+
cancelPreviewDelay();
|
|
5160
|
+
previewFired = false;
|
|
4359
5161
|
closeGuidePreview();
|
|
4360
5162
|
break;
|
|
4361
5163
|
case "teardown":
|
|
@@ -4407,21 +5209,62 @@ function initBuilderMode() {
|
|
|
4407
5209
|
dropTarget = null;
|
|
4408
5210
|
hideDragGhost();
|
|
4409
5211
|
pendingPreview = null;
|
|
5212
|
+
disarmPreviewTrigger();
|
|
5213
|
+
cancelPreviewDelay();
|
|
4410
5214
|
closeGuidePreview();
|
|
4411
5215
|
post({ type: "closed" });
|
|
4412
5216
|
panel?.teardown();
|
|
4413
5217
|
panel = null;
|
|
5218
|
+
chrome?.teardown();
|
|
5219
|
+
chrome = null;
|
|
4414
5220
|
clearBuilderToken();
|
|
4415
5221
|
};
|
|
4416
5222
|
if (ctx.panel) {
|
|
5223
|
+
chrome = injectBuilderChrome({
|
|
5224
|
+
appLabel: window.location.hostname,
|
|
5225
|
+
onAction: (action) => {
|
|
5226
|
+
switch (action.action) {
|
|
5227
|
+
// Controles que resuelve el SDK solo (no van al panel).
|
|
5228
|
+
case "dock":
|
|
5229
|
+
panel?.setTopOffset(action.position === "top" ? chrome?.height() ?? 0 : 0);
|
|
5230
|
+
return;
|
|
5231
|
+
case "show-panel":
|
|
5232
|
+
panel?.setVisible(true);
|
|
5233
|
+
return;
|
|
5234
|
+
case "preview":
|
|
5235
|
+
if (previewMode) return;
|
|
5236
|
+
previewMode = true;
|
|
5237
|
+
panelWasVisible = panel?.isVisible() ?? true;
|
|
5238
|
+
panel?.setVisible(false);
|
|
5239
|
+
chrome?.setPreview(true);
|
|
5240
|
+
if (lastPreview) applyPreviewGated(lastPreview);
|
|
5241
|
+
return;
|
|
5242
|
+
case "exit-preview":
|
|
5243
|
+
if (!previewMode) return;
|
|
5244
|
+
previewMode = false;
|
|
5245
|
+
chrome?.setPreview(false);
|
|
5246
|
+
panel?.setVisible(panelWasVisible);
|
|
5247
|
+
if (lastPreview) applyPreviewGated(lastPreview);
|
|
5248
|
+
return;
|
|
5249
|
+
case "select-activation":
|
|
5250
|
+
case "select-step":
|
|
5251
|
+
case "add-step":
|
|
5252
|
+
panel?.setVisible(true);
|
|
5253
|
+
break;
|
|
5254
|
+
}
|
|
5255
|
+
post({ type: "chrome-action", payload: action });
|
|
5256
|
+
}
|
|
5257
|
+
});
|
|
4417
5258
|
panel = injectBuilderPanel({
|
|
4418
5259
|
dashboardOrigin,
|
|
4419
5260
|
token,
|
|
4420
5261
|
appOrigin: window.location.origin,
|
|
4421
5262
|
guide: ctx.guide,
|
|
4422
5263
|
panelPath: ctx.panelPath,
|
|
4423
|
-
onClose: () => teardown()
|
|
5264
|
+
onClose: () => teardown(),
|
|
5265
|
+
topOffset: chrome.height()
|
|
4424
5266
|
});
|
|
5267
|
+
chrome.onHeightChange((h) => panel?.setTopOffset(chrome?.dock() === "top" ? h : 0));
|
|
4425
5268
|
} else {
|
|
4426
5269
|
staticTarget = resolveTarget();
|
|
4427
5270
|
if (!staticTarget) return null;
|