veo-sdk 0.5.32 → 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-MNYSDJFT.mjs.map → builder-MUTQMYAH.mjs.map} +1 -1
- package/dist/builder.cjs +1000 -163
- 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-AFU5ZG6Z.mjs → chunk-3ZOKCQ54.mjs} +694 -73
- package/dist/chunk-3ZOKCQ54.mjs.map +1 -0
- package/dist/{chunk-JPANNXIK.mjs → chunk-FZ72JUAR.mjs} +193 -9
- package/dist/chunk-FZ72JUAR.mjs.map +1 -0
- package/dist/{chunk-X27GD7IT.mjs → chunk-M6PB5UMW.mjs} +232 -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 +1215 -171
- 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,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,74 +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`;
|
|
635
643
|
}
|
|
636
644
|
if (typeof s.height === "number" && Number.isFinite(s.height) && s.height > 0) {
|
|
637
|
-
|
|
645
|
+
el2.style.height = `${clampNum(s.height, 1, 2e3)}px`;
|
|
638
646
|
}
|
|
639
647
|
if (kind !== "image" && typeof s.width === "number" && Number.isFinite(s.width) && s.width > 0) {
|
|
640
|
-
|
|
648
|
+
el2.style.width = `${clampNum(s.width, 1, 2e3)}px`;
|
|
641
649
|
}
|
|
642
650
|
for (const side of ["Top", "Right", "Bottom", "Left"]) {
|
|
643
651
|
const p = s[`padding${side}`];
|
|
644
652
|
if (typeof p === "number" && Number.isFinite(p)) {
|
|
645
|
-
|
|
653
|
+
el2.style.setProperty(`padding-${side.toLowerCase()}`, `${clampNum(p, 0, 128)}px`);
|
|
646
654
|
}
|
|
647
655
|
const m = s[`margin${side}`];
|
|
648
656
|
if (typeof m === "number" && Number.isFinite(m)) {
|
|
649
|
-
|
|
657
|
+
el2.style.setProperty(`margin-${side.toLowerCase()}`, `${clampNum(m, 0, 128)}px`);
|
|
650
658
|
}
|
|
651
659
|
}
|
|
652
660
|
}
|
|
@@ -781,11 +789,11 @@ function applyDesignVars(host, style) {
|
|
|
781
789
|
host.style.setProperty("--veo-pos-y", `${py * 100}%`);
|
|
782
790
|
}
|
|
783
791
|
if (s.elements && typeof s.elements === "object") {
|
|
784
|
-
const
|
|
785
|
-
applyElementVars(host, "title",
|
|
786
|
-
applyElementVars(host, "text",
|
|
787
|
-
applyElementVars(host, "image",
|
|
788
|
-
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);
|
|
789
797
|
}
|
|
790
798
|
}
|
|
791
799
|
function applyCtaVars(host, raw) {
|
|
@@ -809,29 +817,29 @@ function applyCtaVars(host, raw) {
|
|
|
809
817
|
}
|
|
810
818
|
function applyElementVars(host, prefix, raw) {
|
|
811
819
|
if (!raw || typeof raw !== "object") return;
|
|
812
|
-
const
|
|
813
|
-
if (typeof
|
|
820
|
+
const el2 = raw;
|
|
821
|
+
if (typeof el2.align === "string" && (el2.align === "left" || el2.align === "center" || el2.align === "right")) {
|
|
814
822
|
const mode = ELEMENT_ALIGN_MODE[prefix] ?? "text";
|
|
815
|
-
const value = mode === "self" ? ALIGN_SELF[
|
|
823
|
+
const value = mode === "self" ? ALIGN_SELF[el2.align] : el2.align;
|
|
816
824
|
host.style.setProperty(`--veo-${prefix}-align`, value);
|
|
817
825
|
}
|
|
818
|
-
if (typeof
|
|
819
|
-
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());
|
|
820
828
|
}
|
|
821
|
-
if (typeof
|
|
822
|
-
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`);
|
|
823
831
|
}
|
|
824
|
-
if (typeof
|
|
825
|
-
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)}%`);
|
|
826
834
|
}
|
|
827
|
-
if (typeof
|
|
828
|
-
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`);
|
|
829
837
|
}
|
|
830
|
-
if (typeof
|
|
831
|
-
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`);
|
|
832
840
|
}
|
|
833
|
-
if (typeof
|
|
834
|
-
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`);
|
|
835
843
|
}
|
|
836
844
|
}
|
|
837
845
|
|
|
@@ -881,16 +889,16 @@ function waitForElement(selector, timeoutMs = DEFAULT_ANCHOR_WAIT_MS) {
|
|
|
881
889
|
return;
|
|
882
890
|
}
|
|
883
891
|
let resolved = false;
|
|
884
|
-
const finish = (
|
|
892
|
+
const finish = (el2) => {
|
|
885
893
|
if (resolved) return;
|
|
886
894
|
resolved = true;
|
|
887
895
|
observer.disconnect();
|
|
888
896
|
clearTimeout(timer);
|
|
889
|
-
resolve(
|
|
897
|
+
resolve(el2);
|
|
890
898
|
};
|
|
891
899
|
const observer = new MutationObserver(() => {
|
|
892
|
-
const
|
|
893
|
-
if (
|
|
900
|
+
const el2 = safeQuery();
|
|
901
|
+
if (el2) finish(el2);
|
|
894
902
|
});
|
|
895
903
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
896
904
|
const timer = setTimeout(() => finish(null), timeoutMs);
|
|
@@ -1950,10 +1958,10 @@ function collectHostStyles() {
|
|
|
1950
1958
|
function hostHtmlAttrs() {
|
|
1951
1959
|
if (typeof document === "undefined") return "";
|
|
1952
1960
|
try {
|
|
1953
|
-
const
|
|
1961
|
+
const el2 = document.documentElement;
|
|
1954
1962
|
const attrs = [];
|
|
1955
1963
|
for (const name of ["class", "style", "data-theme", "data-mode", "data-color-mode"]) {
|
|
1956
|
-
const v =
|
|
1964
|
+
const v = el2.getAttribute(name);
|
|
1957
1965
|
if (v && v.length <= 1e3 && !/["<>]/.test(v)) attrs.push(`${name}="${v}"`);
|
|
1958
1966
|
}
|
|
1959
1967
|
return attrs.join(" ");
|
|
@@ -2336,6 +2344,188 @@ function buildScale(wrapper, doc, min, max, btnClass, symbol) {
|
|
|
2336
2344
|
wrapper.appendChild(row);
|
|
2337
2345
|
return { wrapper, read: () => selected };
|
|
2338
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
|
+
}
|
|
2339
2529
|
|
|
2340
2530
|
// src/plugins/guides/renderers/composite-renderer.ts
|
|
2341
2531
|
var ROW_ALIGN = {
|
|
@@ -2631,7 +2821,9 @@ var CompositeRenderer = class extends BaseRenderer {
|
|
|
2631
2821
|
badge.style.cursor = "pointer";
|
|
2632
2822
|
badge.style.display = "inline-flex";
|
|
2633
2823
|
badge.style.alignItems = "center";
|
|
2634
|
-
|
|
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);
|
|
2635
2827
|
root.appendChild(badge);
|
|
2636
2828
|
if (design.fullWidth === true) {
|
|
2637
2829
|
card.style.width = "auto";
|
|
@@ -2646,10 +2838,17 @@ var CompositeRenderer = class extends BaseRenderer {
|
|
|
2646
2838
|
if (caretEl) wrapper.appendChild(caretEl);
|
|
2647
2839
|
wrapper.appendChild(card);
|
|
2648
2840
|
root.appendChild(wrapper);
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
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
|
+
}
|
|
2653
2852
|
let open = false;
|
|
2654
2853
|
let stopFloat = null;
|
|
2655
2854
|
let closeTimer = null;
|
|
@@ -2702,6 +2901,7 @@ var CompositeRenderer = class extends BaseRenderer {
|
|
|
2702
2901
|
stopFloat?.();
|
|
2703
2902
|
if (closeTimer !== null) clearTimeout(closeTimer);
|
|
2704
2903
|
});
|
|
2904
|
+
if (context.badgeOpen) openTip();
|
|
2705
2905
|
return closeTip;
|
|
2706
2906
|
}
|
|
2707
2907
|
};
|
|
@@ -2755,14 +2955,14 @@ function makeCaret(doc, design) {
|
|
|
2755
2955
|
return caret;
|
|
2756
2956
|
}
|
|
2757
2957
|
function liftTarget(anchor, zIndex) {
|
|
2758
|
-
const
|
|
2759
|
-
const prevPosition =
|
|
2760
|
-
const prevZ =
|
|
2761
|
-
if (getComputedStyle(
|
|
2762
|
-
|
|
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);
|
|
2763
2963
|
return () => {
|
|
2764
|
-
|
|
2765
|
-
|
|
2964
|
+
el2.style.position = prevPosition;
|
|
2965
|
+
el2.style.zIndex = prevZ;
|
|
2766
2966
|
};
|
|
2767
2967
|
}
|
|
2768
2968
|
async function anchorPosition(anchor, wrapper, caret, preferred = "bottom") {
|
|
@@ -3278,7 +3478,8 @@ var GuidePreviewController = class {
|
|
|
3278
3478
|
}
|
|
3279
3479
|
preview(input) {
|
|
3280
3480
|
const nextStep = input.guideSteps[0];
|
|
3281
|
-
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)) {
|
|
3282
3483
|
this.input = input;
|
|
3283
3484
|
return {
|
|
3284
3485
|
close: () => this.close(),
|
|
@@ -3308,7 +3509,8 @@ var GuidePreviewController = class {
|
|
|
3308
3509
|
}
|
|
3309
3510
|
return null;
|
|
3310
3511
|
}
|
|
3311
|
-
close() {
|
|
3512
|
+
close(byUser = false) {
|
|
3513
|
+
const onClosed = byUser ? this.input?.onClosed : void 0;
|
|
3312
3514
|
if (this.singleStep) {
|
|
3313
3515
|
safeDestroy(this.singleStep);
|
|
3314
3516
|
this.singleStep = null;
|
|
@@ -3320,6 +3522,7 @@ var GuidePreviewController = class {
|
|
|
3320
3522
|
this.walkthroughGuide = null;
|
|
3321
3523
|
this.walkthroughIndex = 0;
|
|
3322
3524
|
this.input = null;
|
|
3525
|
+
onClosed?.();
|
|
3323
3526
|
}
|
|
3324
3527
|
async renderSingleStep(guide) {
|
|
3325
3528
|
const renderer = createSingleStepRenderer(guide.guideType);
|
|
@@ -3332,7 +3535,8 @@ var GuidePreviewController = class {
|
|
|
3332
3535
|
onInteraction: (event) => {
|
|
3333
3536
|
if (event.action === "shown") shown = true;
|
|
3334
3537
|
},
|
|
3335
|
-
onClose: () => this.close(),
|
|
3538
|
+
onClose: () => this.close(true),
|
|
3539
|
+
badgeOpen: this.input?.badgeOpen === true,
|
|
3336
3540
|
onTrack: () => {
|
|
3337
3541
|
},
|
|
3338
3542
|
// Encadenado en preview: no-op — el editor no puede montar otra guía
|
|
@@ -3398,7 +3602,7 @@ var GuidePreviewController = class {
|
|
|
3398
3602
|
guide,
|
|
3399
3603
|
onInteraction: () => {
|
|
3400
3604
|
},
|
|
3401
|
-
onClose: () => this.close(),
|
|
3605
|
+
onClose: () => this.close(true),
|
|
3402
3606
|
nav: { stepIndex: index, totalSteps: guide.guideSteps.length, callbacks }
|
|
3403
3607
|
});
|
|
3404
3608
|
} catch {
|
|
@@ -3492,15 +3696,27 @@ function safeDestroy(renderer) {
|
|
|
3492
3696
|
}
|
|
3493
3697
|
|
|
3494
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
|
+
}
|
|
3495
3709
|
function matchesUrl(matcher, pageUrl) {
|
|
3710
|
+
const candidates = urlCandidates(pageUrl);
|
|
3496
3711
|
switch (matcher.type) {
|
|
3497
3712
|
case "exact":
|
|
3498
|
-
return
|
|
3713
|
+
return candidates.some((c) => c === matcher.pattern);
|
|
3499
3714
|
case "prefix":
|
|
3500
|
-
return
|
|
3715
|
+
return candidates.some((c) => c.startsWith(matcher.pattern));
|
|
3501
3716
|
case "regex":
|
|
3502
3717
|
try {
|
|
3503
|
-
|
|
3718
|
+
const re = new RegExp(matcher.pattern);
|
|
3719
|
+
return candidates.some((c) => re.test(c));
|
|
3504
3720
|
} catch {
|
|
3505
3721
|
return false;
|
|
3506
3722
|
}
|
|
@@ -3514,17 +3730,375 @@ function stepMatchesPage(loc, pageUrl) {
|
|
|
3514
3730
|
// src/plugins/builder/bridge-protocol.ts
|
|
3515
3731
|
var VEO_BUILDER_SOURCE = "veo-builder";
|
|
3516
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
|
+
|
|
3517
4079
|
// src/plugins/builder/builder-panel.ts
|
|
3518
4080
|
var DEFAULT_PANEL_PATH = "/guides/design";
|
|
3519
|
-
var PANEL_W =
|
|
3520
|
-
var PANEL_H =
|
|
4081
|
+
var PANEL_W = 484;
|
|
4082
|
+
var PANEL_H = 660;
|
|
3521
4083
|
var MIN_W = 320;
|
|
3522
4084
|
var MIN_H = 320;
|
|
3523
4085
|
var MARGIN = 16;
|
|
4086
|
+
var HEADER_H = 52;
|
|
3524
4087
|
function injectBuilderPanel(opts) {
|
|
3525
4088
|
if (!hasWindow() || !hasDocument()) {
|
|
3526
|
-
return {
|
|
3527
|
-
|
|
4089
|
+
return {
|
|
4090
|
+
target: () => null,
|
|
4091
|
+
frameRect: () => null,
|
|
4092
|
+
teardown: () => {
|
|
4093
|
+
},
|
|
4094
|
+
setTitle: () => {
|
|
4095
|
+
},
|
|
4096
|
+
setVisible: () => {
|
|
4097
|
+
},
|
|
4098
|
+
isVisible: () => false,
|
|
4099
|
+
setTopOffset: () => {
|
|
4100
|
+
}
|
|
4101
|
+
};
|
|
3528
4102
|
}
|
|
3529
4103
|
const panelUrl = buildPanelUrl(opts);
|
|
3530
4104
|
const host = document.createElement("div");
|
|
@@ -3534,43 +4108,68 @@ function injectBuilderPanel(opts) {
|
|
|
3534
4108
|
style.textContent = PANEL_CSS;
|
|
3535
4109
|
const card = document.createElement("div");
|
|
3536
4110
|
card.className = "veo-panel";
|
|
3537
|
-
let
|
|
3538
|
-
let
|
|
4111
|
+
let topOffset = opts.topOffset ?? 0;
|
|
4112
|
+
let left = 40;
|
|
4113
|
+
let top = topOffset + MARGIN;
|
|
3539
4114
|
card.style.left = `${left}px`;
|
|
3540
4115
|
card.style.top = `${top}px`;
|
|
3541
4116
|
card.style.width = `${PANEL_W}px`;
|
|
3542
4117
|
card.style.height = `${PANEL_H}px`;
|
|
3543
4118
|
const header = document.createElement("div");
|
|
3544
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";
|
|
3545
4124
|
const title = document.createElement("span");
|
|
3546
4125
|
title.className = "veo-panel-title";
|
|
3547
4126
|
title.textContent = "OnUser \xB7 Editor";
|
|
3548
4127
|
const actions = document.createElement("div");
|
|
3549
4128
|
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);
|
|
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);
|
|
3564
4134
|
const iframe = document.createElement("iframe");
|
|
3565
4135
|
iframe.className = "veo-panel-frame";
|
|
3566
4136
|
iframe.title = "Editor de Veo";
|
|
3567
4137
|
iframe.src = panelUrl;
|
|
3568
|
-
const
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
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);
|
|
3572
4142
|
shadow.append(style, card);
|
|
3573
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
|
+
});
|
|
3574
4173
|
let popped = null;
|
|
3575
4174
|
let pollTimer;
|
|
3576
4175
|
const stopPoll = () => {
|
|
@@ -3579,7 +4178,6 @@ function injectBuilderPanel(opts) {
|
|
|
3579
4178
|
pollTimer = void 0;
|
|
3580
4179
|
}
|
|
3581
4180
|
};
|
|
3582
|
-
close.addEventListener("click", () => opts.onClose());
|
|
3583
4181
|
popout.addEventListener("click", () => {
|
|
3584
4182
|
const win = window.open(
|
|
3585
4183
|
panelUrl,
|
|
@@ -3597,7 +4195,7 @@ function injectBuilderPanel(opts) {
|
|
|
3597
4195
|
}, 600);
|
|
3598
4196
|
});
|
|
3599
4197
|
header.addEventListener("mousedown", (e) => {
|
|
3600
|
-
if (e.target?.
|
|
4198
|
+
if (e.target?.closest(".veo-panel-btn")) return;
|
|
3601
4199
|
e.preventDefault();
|
|
3602
4200
|
const sx = e.clientX;
|
|
3603
4201
|
const sy = e.clientY;
|
|
@@ -3606,7 +4204,7 @@ function injectBuilderPanel(opts) {
|
|
|
3606
4204
|
iframe.style.pointerEvents = "none";
|
|
3607
4205
|
const move = (ev) => {
|
|
3608
4206
|
left = clamp3(ol + (ev.clientX - sx), 0, Math.max(0, window.innerWidth - card.offsetWidth));
|
|
3609
|
-
top = clamp3(ot + (ev.clientY - sy),
|
|
4207
|
+
top = clamp3(ot + (ev.clientY - sy), topOffset, Math.max(topOffset, window.innerHeight - 40));
|
|
3610
4208
|
card.style.left = `${left}px`;
|
|
3611
4209
|
card.style.top = `${top}px`;
|
|
3612
4210
|
};
|
|
@@ -3618,7 +4216,7 @@ function injectBuilderPanel(opts) {
|
|
|
3618
4216
|
window.addEventListener("mousemove", move);
|
|
3619
4217
|
window.addEventListener("mouseup", up);
|
|
3620
4218
|
});
|
|
3621
|
-
|
|
4219
|
+
resizeGrip.addEventListener("mousedown", (e) => {
|
|
3622
4220
|
e.preventDefault();
|
|
3623
4221
|
e.stopPropagation();
|
|
3624
4222
|
const sx = e.clientX;
|
|
@@ -3645,9 +4243,33 @@ function injectBuilderPanel(opts) {
|
|
|
3645
4243
|
stopPoll();
|
|
3646
4244
|
if (popped && !popped.closed) popped.close();
|
|
3647
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
|
+
}
|
|
3648
4258
|
}
|
|
3649
4259
|
};
|
|
3650
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
|
+
}
|
|
3651
4273
|
function clamp3(v, min, max) {
|
|
3652
4274
|
return Math.min(Math.max(v, min), max);
|
|
3653
4275
|
}
|
|
@@ -3667,28 +4289,33 @@ var PANEL_CSS = `
|
|
|
3667
4289
|
max-width: 96vw; max-height: 94vh;
|
|
3668
4290
|
display: flex; flex-direction: column;
|
|
3669
4291
|
background: #fff;
|
|
3670
|
-
border-radius:
|
|
3671
|
-
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);
|
|
3672
4294
|
overflow: hidden;
|
|
3673
4295
|
z-index: 2147483647;
|
|
3674
4296
|
font-family: system-ui, -apple-system, sans-serif;
|
|
3675
4297
|
}
|
|
3676
4298
|
.veo-panel-header {
|
|
3677
|
-
flex: 0 0 auto;
|
|
4299
|
+
position: relative; flex: 0 0 auto; height: ${HEADER_H}px; box-sizing: border-box;
|
|
3678
4300
|
display: flex; align-items: center; justify-content: space-between;
|
|
3679
|
-
padding:
|
|
3680
|
-
background: #
|
|
3681
|
-
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;
|
|
3682
4304
|
cursor: grab;
|
|
3683
4305
|
}
|
|
3684
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; }
|
|
3685
4312
|
.veo-panel-actions { display: flex; gap: 2px; }
|
|
3686
4313
|
.veo-panel-btn {
|
|
3687
|
-
border: 0; background: transparent; color: #
|
|
3688
|
-
|
|
3689
|
-
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;
|
|
3690
4317
|
}
|
|
3691
|
-
.veo-panel-btn:hover { background: rgba(
|
|
4318
|
+
.veo-panel-btn:hover { background: rgba(0,0,0,0.06); color: #1c1917; }
|
|
3692
4319
|
.veo-panel-frame { flex: 1 1 auto; width: 100%; border: 0; background: #fff; }
|
|
3693
4320
|
.veo-panel-resize {
|
|
3694
4321
|
position: absolute; right: 0; bottom: 0;
|
|
@@ -4028,9 +4655,9 @@ var PICKER_STYLES = `
|
|
|
4028
4655
|
z-index: ${PICKER_Z};
|
|
4029
4656
|
pointer-events: none;
|
|
4030
4657
|
box-sizing: border-box;
|
|
4031
|
-
background:
|
|
4032
|
-
border:
|
|
4033
|
-
border-radius:
|
|
4658
|
+
background: transparent;
|
|
4659
|
+
border: 3px dashed #b74d00;
|
|
4660
|
+
border-radius: 8px;
|
|
4034
4661
|
transition: top 60ms ease-out, left 60ms ease-out, width 60ms ease-out, height 60ms ease-out;
|
|
4035
4662
|
}
|
|
4036
4663
|
.veo-pick-label {
|
|
@@ -4038,30 +4665,48 @@ var PICKER_STYLES = `
|
|
|
4038
4665
|
z-index: ${PICKER_Z};
|
|
4039
4666
|
pointer-events: none;
|
|
4040
4667
|
max-width: 360px;
|
|
4041
|
-
background: #
|
|
4042
|
-
color: #
|
|
4668
|
+
background: #2b2623;
|
|
4669
|
+
color: #f5efe9;
|
|
4043
4670
|
font: 12px/1.45 ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
4044
4671
|
padding: 6px 9px;
|
|
4045
4672
|
border-radius: 6px;
|
|
4046
4673
|
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.35);
|
|
4047
4674
|
}
|
|
4048
|
-
.veo-pick-label .veo-pick-sel { color: #
|
|
4049
|
-
.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; }
|
|
4050
4677
|
.veo-pick-hint {
|
|
4051
4678
|
position: fixed;
|
|
4052
|
-
top:
|
|
4679
|
+
top: 28px;
|
|
4053
4680
|
left: 50%;
|
|
4054
4681
|
transform: translateX(-50%);
|
|
4055
4682
|
z-index: ${PICKER_Z};
|
|
4056
4683
|
pointer-events: none;
|
|
4057
|
-
|
|
4684
|
+
display: flex; align-items: center; gap: 16px;
|
|
4685
|
+
max-width: min(760px, calc(100vw - 32px));
|
|
4686
|
+
background: #2b2623;
|
|
4058
4687
|
color: #fff;
|
|
4059
|
-
font:
|
|
4060
|
-
padding:
|
|
4061
|
-
border-radius:
|
|
4062
|
-
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;
|
|
4063
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;
|
|
4706
|
+
}
|
|
4707
|
+
.veo-pick-cancel:hover { background: rgba(255,255,255,0.24); }
|
|
4064
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>';
|
|
4065
4710
|
var ElementPicker = class {
|
|
4066
4711
|
constructor() {
|
|
4067
4712
|
this.host = null;
|
|
@@ -4078,6 +4723,7 @@ var ElementPicker = class {
|
|
|
4078
4723
|
this.draw(target);
|
|
4079
4724
|
};
|
|
4080
4725
|
this.onClick = (event) => {
|
|
4726
|
+
if (event.altKey) return;
|
|
4081
4727
|
const target = this.current ?? (event.target instanceof Element ? event.target : null);
|
|
4082
4728
|
if (!target || this.isOwn(target)) return;
|
|
4083
4729
|
event.preventDefault();
|
|
@@ -4098,7 +4744,7 @@ var ElementPicker = class {
|
|
|
4098
4744
|
};
|
|
4099
4745
|
/** Traga mousedown/mouseup durante el picking (evita focus/active de la app). */
|
|
4100
4746
|
this.swallow = (event) => {
|
|
4101
|
-
if (this.isOwn(event.target)) return;
|
|
4747
|
+
if (event.altKey || this.isOwn(event.target)) return;
|
|
4102
4748
|
event.preventDefault();
|
|
4103
4749
|
event.stopPropagation();
|
|
4104
4750
|
};
|
|
@@ -4124,7 +4770,29 @@ var ElementPicker = class {
|
|
|
4124
4770
|
this.label.style.display = "none";
|
|
4125
4771
|
const hint = document.createElement("div");
|
|
4126
4772
|
hint.className = "veo-pick-hint";
|
|
4127
|
-
|
|
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);
|
|
4128
4796
|
shadow.append(style, this.box, this.label, hint);
|
|
4129
4797
|
document.body.appendChild(host);
|
|
4130
4798
|
this.host = host;
|
|
@@ -4222,6 +4890,7 @@ function initBuilderMode() {
|
|
|
4222
4890
|
if (!dashboardOrigin) return null;
|
|
4223
4891
|
let picker = null;
|
|
4224
4892
|
let panel = null;
|
|
4893
|
+
let chrome = null;
|
|
4225
4894
|
let staticTarget = null;
|
|
4226
4895
|
let manipulator = null;
|
|
4227
4896
|
let dropTarget = null;
|
|
@@ -4229,26 +4898,89 @@ function initBuilderMode() {
|
|
|
4229
4898
|
let previewStepIndex = 0;
|
|
4230
4899
|
let pendingPreview = null;
|
|
4231
4900
|
let lastPreview = null;
|
|
4901
|
+
let previewMode = false;
|
|
4902
|
+
let previewTrigger = null;
|
|
4903
|
+
let previewFired = false;
|
|
4904
|
+
let previewDelay = null;
|
|
4905
|
+
let panelWasVisible = true;
|
|
4232
4906
|
const getTarget = () => panel ? panel.target() : staticTarget;
|
|
4233
4907
|
const post = (event) => {
|
|
4234
4908
|
getTarget()?.postMessage({ source: VEO_BUILDER_SOURCE, token, ...event }, dashboardOrigin);
|
|
4235
4909
|
};
|
|
4236
|
-
const
|
|
4910
|
+
const previewStep = (cmd) => {
|
|
4237
4911
|
const steps = cmd.guide.guideSteps;
|
|
4238
|
-
|
|
4239
|
-
|
|
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();
|
|
4240
4922
|
};
|
|
4241
4923
|
const applyPreviewGated = (cmd) => {
|
|
4242
4924
|
lastPreview = cmd;
|
|
4243
|
-
if (previewMatchesPage(cmd)) {
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
|
|
4925
|
+
if (!previewMatchesPage(cmd)) {
|
|
4926
|
+
cancelPreviewDelay();
|
|
4927
|
+
withholdPreview();
|
|
4928
|
+
postPreviewStatus({
|
|
4929
|
+
state: "page-mismatch",
|
|
4930
|
+
pattern: previewStep(cmd)?.pageLocation?.pattern ?? ""
|
|
4931
|
+
});
|
|
4932
|
+
return;
|
|
4251
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;
|
|
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 });
|
|
4252
4984
|
};
|
|
4253
4985
|
const applyPreview = (cmd) => {
|
|
4254
4986
|
manipulator?.detach();
|
|
@@ -4256,8 +4988,38 @@ function initBuilderMode() {
|
|
|
4256
4988
|
dropTarget?.detach();
|
|
4257
4989
|
dropTarget = null;
|
|
4258
4990
|
previewStepIndex = cmd.guide.startStepIndex ?? 0;
|
|
4259
|
-
const
|
|
4260
|
-
|
|
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;
|
|
4261
5023
|
void handle.ready.then((result) => {
|
|
4262
5024
|
if (!result.rendered) return;
|
|
4263
5025
|
const host = handle.host();
|
|
@@ -4325,26 +5087,57 @@ function initBuilderMode() {
|
|
|
4325
5087
|
const handleCommand = (cmd) => {
|
|
4326
5088
|
switch (cmd.type) {
|
|
4327
5089
|
case "panel-ready":
|
|
4328
|
-
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);
|
|
4329
5100
|
break;
|
|
4330
|
-
case "start-picker":
|
|
5101
|
+
case "start-picker": {
|
|
4331
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
|
+
};
|
|
4332
5121
|
picker = startElementPicker({
|
|
4333
5122
|
onPick: (payload) => {
|
|
4334
5123
|
picker = null;
|
|
5124
|
+
restorePanel();
|
|
4335
5125
|
post({ type: "picked", payload });
|
|
4336
5126
|
},
|
|
4337
5127
|
onCancel: () => {
|
|
4338
5128
|
picker = null;
|
|
5129
|
+
restorePanel();
|
|
4339
5130
|
post({ type: "pick-cancelled" });
|
|
4340
5131
|
},
|
|
4341
5132
|
...cmd.maxAncestors !== void 0 ? { maxAncestors: cmd.maxAncestors } : {},
|
|
4342
5133
|
...cmd.hint !== void 0 ? { hint: cmd.hint } : {}
|
|
4343
5134
|
});
|
|
4344
5135
|
break;
|
|
5136
|
+
}
|
|
4345
5137
|
case "stop-picker":
|
|
4346
5138
|
picker?.stop();
|
|
4347
5139
|
picker = null;
|
|
5140
|
+
chrome?.setHidden(false);
|
|
4348
5141
|
break;
|
|
4349
5142
|
case "preview":
|
|
4350
5143
|
if (!cmd.guide) break;
|
|
@@ -4362,6 +5155,9 @@ function initBuilderMode() {
|
|
|
4362
5155
|
hideDragGhost();
|
|
4363
5156
|
pendingPreview = null;
|
|
4364
5157
|
lastPreview = null;
|
|
5158
|
+
disarmPreviewTrigger();
|
|
5159
|
+
cancelPreviewDelay();
|
|
5160
|
+
previewFired = false;
|
|
4365
5161
|
closeGuidePreview();
|
|
4366
5162
|
break;
|
|
4367
5163
|
case "teardown":
|
|
@@ -4413,21 +5209,62 @@ function initBuilderMode() {
|
|
|
4413
5209
|
dropTarget = null;
|
|
4414
5210
|
hideDragGhost();
|
|
4415
5211
|
pendingPreview = null;
|
|
5212
|
+
disarmPreviewTrigger();
|
|
5213
|
+
cancelPreviewDelay();
|
|
4416
5214
|
closeGuidePreview();
|
|
4417
5215
|
post({ type: "closed" });
|
|
4418
5216
|
panel?.teardown();
|
|
4419
5217
|
panel = null;
|
|
5218
|
+
chrome?.teardown();
|
|
5219
|
+
chrome = null;
|
|
4420
5220
|
clearBuilderToken();
|
|
4421
5221
|
};
|
|
4422
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
|
+
});
|
|
4423
5258
|
panel = injectBuilderPanel({
|
|
4424
5259
|
dashboardOrigin,
|
|
4425
5260
|
token,
|
|
4426
5261
|
appOrigin: window.location.origin,
|
|
4427
5262
|
guide: ctx.guide,
|
|
4428
5263
|
panelPath: ctx.panelPath,
|
|
4429
|
-
onClose: () => teardown()
|
|
5264
|
+
onClose: () => teardown(),
|
|
5265
|
+
topOffset: chrome.height()
|
|
4430
5266
|
});
|
|
5267
|
+
chrome.onHeightChange((h) => panel?.setTopOffset(chrome?.dock() === "top" ? h : 0));
|
|
4431
5268
|
} else {
|
|
4432
5269
|
staticTarget = resolveTarget();
|
|
4433
5270
|
if (!staticTarget) return null;
|