@juo/blocks 1.7.1 → 1.8.1

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/editor.js CHANGED
@@ -2,8 +2,8 @@ var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
4
  import { onRegisterBlock, getDefinedBlocks } from "@juo/blocks";
5
- import { a as createEditorBridge, f as createRemoveBlockMessage, g as createRegisterBlocksMessage, h as createRegisterRoutesMessage } from "./bridge-DAUIcGuq.js";
6
- import { i, b, j, k, l, m, n, c, o, p, q, r, s, e, t, u, v, w, d, x, y, z, A } from "./bridge-DAUIcGuq.js";
5
+ import { a as createEditorBridge, f as createOpenAddBlockMenuMessage, g as createRemoveBlockMessage, h as createRegisterBlocksMessage, i as createRegisterRoutesMessage } from "./bridge-BOcO9toS.js";
6
+ import { j, k, b, l, m, n, o, p, c, q, r, s, t, u, e, v, w, x, y, d, z, A, B, C } from "./bridge-BOcO9toS.js";
7
7
  import { h as createBlockInstanceFromObject } from "./block-C8lPBCF8.js";
8
8
  import { i as indexOverrides } from "./theme-state-LZS5T-Xb.js";
9
9
  function createEditorHandler(options) {
@@ -128,17 +128,17 @@ function createEditorHandler(options) {
128
128
  if (location.type === "before" || location.type === "after") {
129
129
  let findAndInsertBlock = function(blocks, targetId, newBlock2, position) {
130
130
  var _a2;
131
- for (let i2 = 0; i2 < blocks.length; i2++) {
132
- if (blocks[i2].id === targetId) {
131
+ for (let i = 0; i < blocks.length; i++) {
132
+ if (blocks[i].id === targetId) {
133
133
  if (position === "before") {
134
- blocks.splice(i2, 0, newBlock2);
134
+ blocks.splice(i, 0, newBlock2);
135
135
  } else {
136
- blocks.splice(i2 + 1, 0, newBlock2);
136
+ blocks.splice(i + 1, 0, newBlock2);
137
137
  }
138
138
  return true;
139
139
  }
140
- for (const slotKey of Object.keys(blocks[i2].slots || {})) {
141
- const slotBlocks = blocks[i2].slots[slotKey];
140
+ for (const slotKey of Object.keys(blocks[i].slots || {})) {
141
+ const slotBlocks = blocks[i].slots[slotKey];
142
142
  const slotArray = Array.isArray(slotBlocks) ? slotBlocks : [slotBlocks];
143
143
  for (let j2 = 0; j2 < slotArray.length; j2++) {
144
144
  if (typeof slotArray[j2] !== "string" && ((_a2 = slotArray[j2]) == null ? void 0 : _a2.id) === targetId) {
@@ -147,7 +147,7 @@ function createEditorHandler(options) {
147
147
  } else {
148
148
  slotArray.splice(j2 + 1, 0, newBlock2);
149
149
  }
150
- blocks[i2].slots[slotKey] = slotArray;
150
+ blocks[i].slots[slotKey] = slotArray;
151
151
  return true;
152
152
  }
153
153
  }
@@ -201,21 +201,21 @@ function createEditorHandler(options) {
201
201
  } else if (message.type === "REMOVE_BLOCK") {
202
202
  let findAndRemoveBlock = function(blocks, blockId, slot, parentId) {
203
203
  var _a2;
204
- for (let i2 = 0; i2 < blocks.length; i2++) {
205
- if (blocks[i2].id === parentId && ((_a2 = blocks[i2].slots) == null ? void 0 : _a2[slot])) {
206
- const slotBlocks = blocks[i2].slots[slot];
204
+ for (let i = 0; i < blocks.length; i++) {
205
+ if (blocks[i].id === parentId && ((_a2 = blocks[i].slots) == null ? void 0 : _a2[slot])) {
206
+ const slotBlocks = blocks[i].slots[slot];
207
207
  const slotArray = Array.isArray(slotBlocks) ? slotBlocks : [slotBlocks];
208
208
  const index = slotArray.findIndex(
209
209
  (b2) => typeof b2 !== "string" && (b2 == null ? void 0 : b2.id) === blockId
210
210
  );
211
211
  if (index !== -1) {
212
212
  slotArray.splice(index, 1);
213
- blocks[i2].slots[slot] = slotArray;
213
+ blocks[i].slots[slot] = slotArray;
214
214
  return true;
215
215
  }
216
216
  }
217
- for (const slotKey of Object.keys(blocks[i2].slots || {})) {
218
- const slotBlocks = blocks[i2].slots[slotKey];
217
+ for (const slotKey of Object.keys(blocks[i].slots || {})) {
218
+ const slotBlocks = blocks[i].slots[slotKey];
219
219
  const slotArray = Array.isArray(slotBlocks) ? slotBlocks : [slotBlocks];
220
220
  for (const child of slotArray) {
221
221
  if (typeof child !== "string" && (child == null ? void 0 : child.id)) {
@@ -309,14 +309,6 @@ const styles = `
309
309
  box-sizing: border-box;
310
310
  }
311
311
 
312
- :host(:hover:not(.active)) .block-wrapper {
313
- outline: 1px dashed #060606;
314
- /* 4px gap between the block content and the dashed outline so the
315
- * outline reads as a hover affordance rather than a touching border.
316
- * Outline doesn't participate in layout, so this stays layout-neutral. */
317
- outline-offset: 4px;
318
- }
319
-
320
312
  /*
321
313
  * Stacking model for the active state (no negative z-index, no isolation):
322
314
  * - .block-wrapper__chrome z-index: 100 → visual frame above neighbours
@@ -518,6 +510,262 @@ const styles = `
518
510
  background: #e9e9e9;
519
511
  flex-shrink: 0;
520
512
  }
513
+
514
+ /*
515
+ * Add-block UI — full-width rail (absolute, inset of .block-wrapper) so
516
+ * spill line widths use 50% of the block without container-type / cqw
517
+ * (which breaks flex layout in workflow overlays). Each chrome edge is an
518
+ * .add-edge row; the button and ::before/::after spills live on that edge.
519
+ *
520
+ * Chrome extends 44px above and 12px below the block content:
521
+ * .add-edge--top → top: -44px
522
+ * .add-edge--bottom → bottom: -12px
523
+ */
524
+ .block-wrapper__add-rail {
525
+ position: absolute;
526
+ left: 0;
527
+ right: 0;
528
+ top: 0;
529
+ bottom: 0;
530
+ pointer-events: none;
531
+ z-index: 103;
532
+ }
533
+
534
+ .block-wrapper__add-edge {
535
+ position: absolute;
536
+ left: 0;
537
+ right: 0;
538
+ height: 0;
539
+ pointer-events: none;
540
+ }
541
+
542
+ .block-wrapper__add-edge--top {
543
+ top: -44px;
544
+ }
545
+
546
+ .block-wrapper__add-edge--bottom {
547
+ bottom: -12px;
548
+ }
549
+
550
+ .block-wrapper__add-btn {
551
+ position: absolute;
552
+ left: 50%;
553
+ display: inline-flex;
554
+ align-items: center;
555
+ justify-content: center;
556
+ /* Above ::before/::after spills on the same .add-edge */
557
+ z-index: 1;
558
+ pointer-events: none;
559
+ appearance: none;
560
+ border: none;
561
+ background: none;
562
+ padding: 0;
563
+ margin: 0;
564
+ cursor: pointer;
565
+ /* Larger hit target than the 14×14 icon (lines are pointer-events: none). */
566
+ min-width: 28px;
567
+ min-height: 28px;
568
+ overflow: visible;
569
+ line-height: 1;
570
+ font-family: inherit;
571
+ opacity: 0;
572
+ transition: opacity 180ms ease;
573
+ }
574
+
575
+ .block-wrapper__add-btn--top {
576
+ top: 0;
577
+ transform: translate(-50%, -50%);
578
+ }
579
+
580
+ .block-wrapper__add-btn--bottom {
581
+ bottom: 0;
582
+ top: auto;
583
+ transform: translate(-50%, 50%);
584
+ }
585
+
586
+ /* B — active chrome hovered: fade buttons in (opacity only). */
587
+ :host(.active:hover) .block-wrapper__add-btn {
588
+ opacity: 1;
589
+ pointer-events: auto;
590
+ }
591
+
592
+ /*
593
+ * Entering the chrome from outside often lands on the button at once — skip
594
+ * the fade so only the + → pill morph runs (avoids end-of-animation snap).
595
+ */
596
+ :host(.active:hover)
597
+ .block-wrapper__add-edge:has(.block-wrapper__add-btn:hover)
598
+ .block-wrapper__add-btn,
599
+ :host(.active)
600
+ .block-wrapper__add-edge:has(.block-wrapper__add-btn--menu-open)
601
+ .block-wrapper__add-btn {
602
+ transition: opacity 0s;
603
+ }
604
+
605
+ .block-wrapper__add-btn-inner {
606
+ position: relative;
607
+ z-index: 1;
608
+ display: inline-flex;
609
+ align-items: center;
610
+ justify-content: center;
611
+ height: 14px;
612
+ overflow: visible;
613
+ }
614
+
615
+ /*
616
+ * Single surface morphs 14×14 circle → 60×14 pill (plus scales away, text
617
+ * fades in). No overlapping icon + label layers.
618
+ */
619
+ .block-wrapper__add-btn-surface {
620
+ position: relative;
621
+ display: inline-flex;
622
+ align-items: center;
623
+ justify-content: center;
624
+ box-sizing: border-box;
625
+ width: 14px;
626
+ height: 14px;
627
+ padding: 0;
628
+ background: #121212;
629
+ border: 0.5px solid #121212;
630
+ border-radius: 50%;
631
+ overflow: visible;
632
+ isolation: isolate;
633
+ transition:
634
+ width 200ms cubic-bezier(0.34, 1.12, 0.64, 1),
635
+ border-radius 200ms cubic-bezier(0.34, 1.12, 0.64, 1),
636
+ padding 200ms cubic-bezier(0.34, 1.12, 0.64, 1);
637
+ }
638
+
639
+ .block-wrapper__add-btn-plus {
640
+ display: inline-flex;
641
+ flex-shrink: 0;
642
+ align-items: center;
643
+ justify-content: center;
644
+ width: 14px;
645
+ height: 14px;
646
+ transition:
647
+ opacity 160ms ease,
648
+ transform 200ms cubic-bezier(0.34, 1.12, 0.64, 1),
649
+ width 200ms cubic-bezier(0.34, 1.12, 0.64, 1);
650
+ }
651
+
652
+ .block-wrapper__add-btn-plus svg {
653
+ display: block;
654
+ filter: drop-shadow(0 0 7px rgba(0, 0, 0, 0.1));
655
+ }
656
+
657
+ .block-wrapper__add-btn-text {
658
+ max-width: 0;
659
+ opacity: 0;
660
+ overflow: hidden;
661
+ color: #ffffff;
662
+ font-size: 9px;
663
+ font-weight: 600;
664
+ letter-spacing: -0.036px;
665
+ line-height: 1;
666
+ white-space: nowrap;
667
+ transition:
668
+ max-width 200ms cubic-bezier(0.34, 1.12, 0.64, 1) 35ms,
669
+ opacity 140ms ease 70ms;
670
+ }
671
+
672
+ /*
673
+ * 0.5px spill on the chrome border — ::before/::after meet at 50% (no gap
674
+ * for the pill) so the line stays continuous when the button fades out.
675
+ * The button paints above (z-index). Vertical: fixed translateY (never
676
+ * transitioned). Horizontal: width 0 → full (not scale — Safari thickens /
677
+ * shifts 0.5px lines when scale is composited with translateY on transform).
678
+ */
679
+ .block-wrapper__add-edge::before,
680
+ .block-wrapper__add-edge::after {
681
+ content: "";
682
+ position: absolute;
683
+ top: 50%;
684
+ width: 0;
685
+ min-width: 0;
686
+ height: 0.5px;
687
+ pointer-events: none;
688
+ z-index: 0;
689
+ overflow: hidden;
690
+ transition-property: width;
691
+ transition-duration: 260ms;
692
+ transition-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
693
+ transition-delay: 50ms;
694
+ }
695
+
696
+ .block-wrapper__add-edge::before {
697
+ right: 50%;
698
+ background: linear-gradient(to left, #121212 0%, #b5b5b5 100%);
699
+ }
700
+
701
+ .block-wrapper__add-edge::after {
702
+ left: 50%;
703
+ background: linear-gradient(to right, #121212 0%, #b5b5b5 100%);
704
+ }
705
+
706
+ .block-wrapper__add-edge--top::before,
707
+ .block-wrapper__add-edge--top::after {
708
+ transform: translateY(calc(-50% + 0.25px));
709
+ }
710
+
711
+ .block-wrapper__add-edge--bottom::before,
712
+ .block-wrapper__add-edge--bottom::after {
713
+ transform: translateY(calc(-50% - 0.25px));
714
+ }
715
+
716
+ /* C — hover / menu-open: morph + spill extend */
717
+ :host(.active:hover) .block-wrapper__add-btn:hover .block-wrapper__add-btn-surface,
718
+ :host(.active) .block-wrapper__add-btn--menu-open .block-wrapper__add-btn-surface {
719
+ width: 60px;
720
+ border-radius: 32px;
721
+ padding: 0 6px;
722
+ }
723
+
724
+ :host(.active:hover) .block-wrapper__add-btn:hover .block-wrapper__add-btn-plus,
725
+ :host(.active) .block-wrapper__add-btn--menu-open .block-wrapper__add-btn-plus {
726
+ width: 0;
727
+ opacity: 0;
728
+ transform: scale(0.35);
729
+ }
730
+
731
+ :host(.active:hover) .block-wrapper__add-btn:hover .block-wrapper__add-btn-text,
732
+ :host(.active) .block-wrapper__add-btn--menu-open .block-wrapper__add-btn-text {
733
+ max-width: 52px;
734
+ opacity: 1;
735
+ }
736
+
737
+ :host(.active:hover) .block-wrapper__add-edge:has(.block-wrapper__add-btn:hover)::before,
738
+ :host(.active:hover) .block-wrapper__add-edge:has(.block-wrapper__add-btn:hover)::after,
739
+ :host(.active) .block-wrapper__add-edge:has(.block-wrapper__add-btn--menu-open)::before,
740
+ :host(.active) .block-wrapper__add-edge:has(.block-wrapper__add-btn--menu-open)::after {
741
+ width: calc(50% - 24px);
742
+ min-width: 40px;
743
+ }
744
+
745
+ /*
746
+ * --menu-open keeps the button in pill state while the editor's AddMenu
747
+ * is open against this button — so the user has a visual anchor of
748
+ * where the menu was triggered from. Note: we explicitly do NOT require
749
+ * :host(:hover) here because the user's pointer is over the menu (which
750
+ * lives outside the iframe) once the menu opens, so :host(:hover) has
751
+ * dropped.
752
+ */
753
+ :host(.active) .block-wrapper__add-btn--menu-open {
754
+ opacity: 1;
755
+ pointer-events: auto;
756
+ }
757
+
758
+ @media (prefers-reduced-motion: reduce) {
759
+ .block-wrapper__add-btn,
760
+ .block-wrapper__add-btn-inner,
761
+ .block-wrapper__add-btn-surface,
762
+ .block-wrapper__add-edge::before,
763
+ .block-wrapper__add-edge::after,
764
+ .block-wrapper__add-btn-plus,
765
+ .block-wrapper__add-btn-text {
766
+ transition: none;
767
+ }
768
+ }
521
769
  </style>
522
770
  `;
523
771
  const blockIconSvg = `
@@ -531,6 +779,12 @@ const moreIconSvg = `
531
779
  <path d="M1.5 0C2.32843 2.0934e-07 3 0.671573 3 1.5C3 2.32843 2.32843 3 1.5 3C0.671573 3 3.62117e-08 2.32843 0 1.5C6.04266e-08 0.671573 0.671573 3.62117e-08 1.5 0ZM6.5 0C7.32843 2.0934e-07 8 0.671573 8 1.5C8 2.32843 7.32843 3 6.5 3C5.67157 3 5 2.32843 5 1.5C5 0.671573 5.67157 3.62117e-08 6.5 0ZM11.5 0C12.3284 2.0934e-07 13 0.671573 13 1.5C13 2.32843 12.3284 3 11.5 3C10.6716 3 10 2.32843 10 1.5C10 0.671573 10.6716 3.62117e-08 11.5 0Z" fill="currentColor"/>
532
780
  </svg>
533
781
  `;
782
+ const addBlockIconSvg = `
783
+ <svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
784
+ <circle cx="7" cy="7" r="7" fill="#121212"/>
785
+ <path d="M7 4.77V9.23M4.77 7H9.23" stroke="white" stroke-width="1.14" stroke-linecap="round"/>
786
+ </svg>
787
+ `;
534
788
  const trashIconSvg = `
535
789
  <svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
536
790
  <path d="M2 4H12" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/>
@@ -550,7 +804,25 @@ class BlockWrapper extends HTMLElement {
550
804
  __publicField(this, "menuElement", null);
551
805
  __publicField(this, "isMenuOpen", false);
552
806
  __publicField(this, "closeMenuOnOutsideClick", null);
553
- __publicField(this, "emptyObserver", null);
807
+ __publicField(this, "addButtons", []);
808
+ __publicField(this, "addRail", null);
809
+ __publicField(this, "hoverOutlineTarget", null);
810
+ __publicField(this, "handleHoverEnter", () => {
811
+ if (this.classList.contains("active")) return;
812
+ const slotted = this.firstElementChild;
813
+ if (!slotted || slotted.hasAttribute("data-empty")) return;
814
+ const target = BlockWrapper.resolveOutlineTarget(slotted);
815
+ if (!target) return;
816
+ this.hoverOutlineTarget = target;
817
+ target.style.outline = "1px solid #060606";
818
+ target.style.outlineOffset = "0";
819
+ });
820
+ __publicField(this, "handleHoverLeave", () => {
821
+ if (!this.hoverOutlineTarget) return;
822
+ this.hoverOutlineTarget.style.outline = "";
823
+ this.hoverOutlineTarget.style.outlineOffset = "";
824
+ this.hoverOutlineTarget = null;
825
+ });
554
826
  this.attachShadow({ mode: "open" });
555
827
  this.setupStyles();
556
828
  this.setupTemplate();
@@ -617,16 +889,91 @@ class BlockWrapper extends HTMLElement {
617
889
  const slot = document.createElement("slot");
618
890
  slotHost.appendChild(slot);
619
891
  wrapper.appendChild(slotHost);
892
+ const addRail = document.createElement("div");
893
+ addRail.className = "block-wrapper__add-rail";
894
+ this.addRail = addRail;
895
+ const topEdge = document.createElement("div");
896
+ topEdge.className = "block-wrapper__add-edge block-wrapper__add-edge--top";
897
+ const topAddBtn = this.createAddButton("before");
898
+ topAddBtn.classList.add("block-wrapper__add-btn--top");
899
+ topEdge.appendChild(topAddBtn);
900
+ addRail.appendChild(topEdge);
901
+ const bottomEdge = document.createElement("div");
902
+ bottomEdge.className = "block-wrapper__add-edge block-wrapper__add-edge--bottom";
903
+ const bottomAddBtn = this.createAddButton("after");
904
+ bottomAddBtn.classList.add("block-wrapper__add-btn--bottom");
905
+ bottomEdge.appendChild(bottomAddBtn);
906
+ addRail.appendChild(bottomEdge);
907
+ wrapper.appendChild(addRail);
908
+ this.addButtons = [topAddBtn, bottomAddBtn];
620
909
  this.shadowRoot.appendChild(wrapper);
621
910
  this.nameElement = nameSpan;
622
911
  this.menuElement = menuEl;
623
912
  this.editorBridge.onMessage((message) => {
624
- var _a;
913
+ var _a, _b;
625
914
  if (message.type === "SELECT_BLOCK") {
626
915
  this.updateActiveState(message.payload.blockId === ((_a = this.block) == null ? void 0 : _a.id));
916
+ } else if (message.type === "ADD_BLOCK_MENU_CLOSED" && message.payload.targetBlockId === ((_b = this.block) == null ? void 0 : _b.id)) {
917
+ this.clearAddButtonMenuState(message.payload.position);
627
918
  }
628
919
  });
629
920
  }
921
+ createAddButton(position) {
922
+ const btn = document.createElement("button");
923
+ btn.type = "button";
924
+ btn.className = "block-wrapper__add-btn";
925
+ btn.setAttribute("aria-label", "Add block");
926
+ btn.dataset.position = position;
927
+ const inner = document.createElement("span");
928
+ inner.className = "block-wrapper__add-btn-inner";
929
+ const surface = document.createElement("span");
930
+ surface.className = "block-wrapper__add-btn-surface";
931
+ const plus = document.createElement("span");
932
+ plus.className = "block-wrapper__add-btn-plus";
933
+ plus.setAttribute("aria-hidden", "true");
934
+ plus.innerHTML = addBlockIconSvg;
935
+ const text = document.createElement("span");
936
+ text.className = "block-wrapper__add-btn-text";
937
+ text.textContent = "Add block";
938
+ surface.appendChild(plus);
939
+ surface.appendChild(text);
940
+ inner.appendChild(surface);
941
+ btn.appendChild(inner);
942
+ btn.addEventListener("click", (e2) => {
943
+ e2.stopPropagation();
944
+ e2.preventDefault();
945
+ this.handleAddBlock(position, btn);
946
+ });
947
+ return btn;
948
+ }
949
+ handleAddBlock(position, button) {
950
+ if (!this.block) return;
951
+ const rect = button.getBoundingClientRect();
952
+ const anchor = {
953
+ x: rect.right,
954
+ // Top edge of the button — menu opens to the right with align=start.
955
+ y: rect.top
956
+ };
957
+ for (const btn of this.addButtons) {
958
+ btn.classList.toggle(
959
+ "block-wrapper__add-btn--menu-open",
960
+ btn === button
961
+ );
962
+ }
963
+ this.editorBridge.sendMessage(
964
+ createOpenAddBlockMenuMessage({
965
+ targetBlockId: this.block.id,
966
+ position,
967
+ anchor
968
+ })
969
+ );
970
+ }
971
+ clearAddButtonMenuState(position) {
972
+ for (const btn of this.addButtons) {
973
+ if (position != null && btn.dataset.position !== position) continue;
974
+ btn.classList.remove("block-wrapper__add-btn--menu-open");
975
+ }
976
+ }
630
977
  connectedCallback() {
631
978
  const isInOverlay = this.closest('juo-extension-root[surface="overlay"]') !== null;
632
979
  if (isInOverlay) {
@@ -638,6 +985,9 @@ class BlockWrapper extends HTMLElement {
638
985
  ".block-wrapper__menu-item--danger"
639
986
  );
640
987
  if (deleteBtn) deleteBtn.style.display = "none";
988
+ if (this.addRail) {
989
+ this.addRail.style.display = "none";
990
+ }
641
991
  }
642
992
  const isWorkflowPreview = (() => {
643
993
  try {
@@ -650,50 +1000,40 @@ class BlockWrapper extends HTMLElement {
650
1000
  if (isWorkflowPreview && !isInOverlay) {
651
1001
  this.style.pointerEvents = "none";
652
1002
  }
653
- this.observeSlotEmptyState();
1003
+ this.addEventListener("mouseenter", this.handleHoverEnter);
1004
+ this.addEventListener("mouseleave", this.handleHoverLeave);
654
1005
  }
655
1006
  /**
656
- * Mirror `data-empty` from the slotted block wrapper onto this editor
657
- * wrapper so page-level divider CSS (and live-data preview) treat empty
658
- * blocks the same as in view mode.
1007
+ * Resolve the slotted block's first painted descendant — the
1008
+ * card-like surface we paint the hover outline on. We can't use
1009
+ * ::slotted() (CE blocks' own :host rules win the cascade) and we
1010
+ * can't put outline on .block-wrapper directly (it has no radius and
1011
+ * adopting one is more code than this), so we apply outline as an
1012
+ * inline style on the visible element. Skips:
1013
+ * - <style> nodes (Vue's defineCustomElement injects styles into
1014
+ * the CE shadow root next to the rendered tree).
1015
+ * - display:contents wrappers (Vue's <ContextProvider> sits between
1016
+ * the slotted div and the actual UiCard for createVueRenderer).
1017
+ * Crosses one shadow-root boundary for createVueCeRenderer blocks
1018
+ * whose slotted element is itself a CE host.
659
1019
  */
660
- observeSlotEmptyState() {
661
- var _a;
662
- (_a = this.emptyObserver) == null ? void 0 : _a.disconnect();
663
- const sync = () => {
664
- const slotted = this.firstElementChild;
665
- const empty = slotted == null || slotted.hasAttribute("data-empty");
666
- this.toggleAttribute("data-empty", empty);
667
- };
668
- const bindObservers = () => {
669
- this.emptyObserver.observe(this, { childList: true });
670
- const slotted = this.firstElementChild;
671
- if (slotted) {
672
- this.emptyObserver.observe(slotted, {
673
- attributes: true,
674
- attributeFilter: ["data-empty"]
675
- });
1020
+ static resolveOutlineTarget(slotted) {
1021
+ const root = slotted.shadowRoot ?? slotted;
1022
+ let el = root.firstElementChild;
1023
+ while (el) {
1024
+ if (el.tagName === "STYLE") {
1025
+ el = el.nextElementSibling;
1026
+ continue;
676
1027
  }
677
- };
678
- sync();
679
- this.emptyObserver = new MutationObserver((records) => {
680
- const slottedChildChanged = records.some(
681
- (record) => record.type === "childList" && record.target === this
682
- );
683
- if (slottedChildChanged) {
684
- this.emptyObserver.disconnect();
685
- sync();
686
- bindObservers();
687
- return;
1028
+ if (getComputedStyle(el).display === "contents") {
1029
+ el = el.firstElementChild;
1030
+ continue;
688
1031
  }
689
- sync();
690
- });
691
- bindObservers();
1032
+ return el;
1033
+ }
1034
+ return slotted.shadowRoot ? null : slotted;
692
1035
  }
693
1036
  disconnectedCallback() {
694
- var _a;
695
- (_a = this.emptyObserver) == null ? void 0 : _a.disconnect();
696
- this.emptyObserver = null;
697
1037
  this.closeMenu();
698
1038
  }
699
1039
  toggleMenu() {
@@ -733,6 +1073,7 @@ class BlockWrapper extends HTMLElement {
733
1073
  updateActiveState(isActive) {
734
1074
  if (isActive) {
735
1075
  this.classList.add("active");
1076
+ this.handleHoverLeave();
736
1077
  } else {
737
1078
  this.classList.remove("active");
738
1079
  this.closeMenu();
@@ -863,33 +1204,35 @@ async function setupEditorMode(deps) {
863
1204
  }
864
1205
  export {
865
1206
  BlockWrapper,
866
- i as createAddBlockMessage,
1207
+ j as createAddBlockMenuClosedMessage,
1208
+ k as createAddBlockMessage,
867
1209
  createEditorBridge,
868
1210
  createEditorHandler,
869
1211
  b as createFocusInlineTextMessage,
870
- j as createMoveBlockMessage,
871
- k as createProvideGlobalStylesMessage,
872
- l as createProvideInitialGlobalStylesMessage,
873
- m as createProvideThemeStateMessage,
874
- n as createProvideTranslationOverridesMessage,
1212
+ l as createMoveBlockMessage,
1213
+ createOpenAddBlockMenuMessage,
1214
+ m as createProvideGlobalStylesMessage,
1215
+ n as createProvideInitialGlobalStylesMessage,
1216
+ o as createProvideThemeStateMessage,
1217
+ p as createProvideTranslationOverridesMessage,
875
1218
  c as createRegisterBlockTranslationKeysMessage,
876
1219
  createRegisterBlocksMessage,
877
1220
  createRegisterRoutesMessage,
878
1221
  createRemoveBlockMessage,
879
- o as createReportContentHeightMessage,
880
- p as createRequestGlobalStylesMessage,
881
- q as createRequestThemeStateMessage,
882
- r as createRequestTranslationOverridesMessage,
883
- s as createScrollSyncMessage,
1222
+ q as createReportContentHeightMessage,
1223
+ r as createRequestGlobalStylesMessage,
1224
+ s as createRequestThemeStateMessage,
1225
+ t as createRequestTranslationOverridesMessage,
1226
+ u as createScrollSyncMessage,
884
1227
  e as createSelectBlockMessage,
885
- t as createSetBlockPresetMessage,
886
- u as createSetGlobalStylesMessage,
887
- v as createSetLocaleMessage,
888
- w as createUpdateBlockPropsMessage,
1228
+ v as createSetBlockPresetMessage,
1229
+ w as createSetGlobalStylesMessage,
1230
+ x as createSetLocaleMessage,
1231
+ y as createUpdateBlockPropsMessage,
889
1232
  d as createUpdateBlockTranslationMessage,
890
- x as createUpsertThemeStateMessage,
891
- y as getEditorBridge,
892
- z as isEditorMessage,
893
- A as isIframeMessage,
1233
+ z as createUpsertThemeStateMessage,
1234
+ A as getEditorBridge,
1235
+ B as isEditorMessage,
1236
+ C as isIframeMessage,
894
1237
  setupEditorMode
895
1238
  };
@@ -2,7 +2,7 @@ var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
4
  import { c as createContext, d, E, m as getDefinedBlocks, f as createBlockInstance, w, r as registerBlock, k as defineBlock, v as subscribeContext } from "./block-C8lPBCF8.js";
5
- import { a as createEditorBridge, e as createSelectBlockMessage } from "./bridge-DAUIcGuq.js";
5
+ import { a as createEditorBridge, e as createSelectBlockMessage } from "./bridge-BOcO9toS.js";
6
6
  const TranslationContext = createContext("translation");
7
7
  function toStringRecord(input) {
8
8
  if (input == null) return {};
package/dist/preact.js CHANGED
@@ -6,7 +6,7 @@ import { useState, useRef, useEffect, useContext as useContext$1, useMemo } from
6
6
  import { g as getSignalValue, s as setSignalValue, w as wrapContext, c as createSlotChildren } from "./block-VhmfGB3N.js";
7
7
  import { t } from "./block-VhmfGB3N.js";
8
8
  import { createContext, h, render } from "preact";
9
- import { a as createEditorBridge } from "./bridge-DAUIcGuq.js";
9
+ import { a as createEditorBridge } from "./bridge-BOcO9toS.js";
10
10
  function toState(signal) {
11
11
  const [value, setValue] = useState(() => getSignalValue(signal));
12
12
  const disposeRef = useRef(null);
package/dist/react.js CHANGED
@@ -6,7 +6,7 @@ import React, { useSyncExternalStore, createContext, useState, useContext as use
6
6
  import { g as getSignalValue, s as setSignalValue, w as wrapContext, c as createSlotChildren } from "./block-VhmfGB3N.js";
7
7
  import { t } from "./block-VhmfGB3N.js";
8
8
  import { createRoot } from "react-dom/client";
9
- import { a as createEditorBridge } from "./bridge-DAUIcGuq.js";
9
+ import { a as createEditorBridge } from "./bridge-BOcO9toS.js";
10
10
  function toState(signal) {
11
11
  const subscribe = (callback) => {
12
12
  const dispose = effect(() => {