@elementor/editor-canvas 4.2.0-946 → 4.2.0-beta2
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/index.d.mts +8 -2
- package/dist/index.d.ts +8 -2
- package/dist/index.js +406 -242
- package/dist/index.mjs +336 -173
- package/package.json +20 -19
- package/src/__tests__/parse-xml.ts +2 -0
- package/src/components/__tests__/elements-overlays.test.tsx +7 -0
- package/src/components/elements-overlays.tsx +17 -6
- package/src/components/grid-outline/__tests__/grid-outline-overlay.test.tsx +13 -15
- package/src/components/grid-outline/grid-empty-cell-positioner.tsx +46 -0
- package/src/components/grid-outline/grid-outline-overlay.tsx +3 -4
- package/src/components/grid-outline/grid-outline.tsx +11 -1
- package/src/components/grid-outline/index.ts +1 -0
- package/src/components/outline-overlay.tsx +9 -2
- package/src/composition-builder/composition-builder.ts +12 -0
- package/src/form-structure/__tests__/form-structure-utils.test.ts +218 -0
- package/src/form-structure/enforce-form-ancestor-commands.ts +11 -4
- package/src/form-structure/utils.ts +47 -0
- package/src/index.ts +1 -0
- package/src/mcp/tools/build-composition/tool.ts +58 -2
- package/src/mcp/tools/configure-element/tool.ts +3 -0
- package/src/types/element-overlay.ts +2 -0
- package/src/utils/__tests__/outline-offset-utils.test.ts +39 -0
- package/src/utils/outline-offset-utils.ts +11 -0
- package/src/utils/tracking.ts +14 -0
package/dist/index.mjs
CHANGED
|
@@ -384,12 +384,8 @@ import {
|
|
|
384
384
|
windowEvent as windowEvent2
|
|
385
385
|
} from "@elementor/editor-v1-adapters";
|
|
386
386
|
|
|
387
|
-
// src/components/grid-outline/grid-
|
|
388
|
-
import
|
|
389
|
-
import { useSelectedElementSettings } from "@elementor/editor-elements";
|
|
390
|
-
import { booleanPropTypeUtil } from "@elementor/editor-props";
|
|
391
|
-
import { Box as Box2 } from "@elementor/ui";
|
|
392
|
-
import { FloatingPortal as FloatingPortal2 } from "@floating-ui/react";
|
|
387
|
+
// src/components/grid-outline/grid-empty-cell-positioner.tsx
|
|
388
|
+
import { useEffect as useEffect5 } from "react";
|
|
393
389
|
|
|
394
390
|
// src/hooks/use-element-rect.ts
|
|
395
391
|
import { useEffect as useEffect2, useState } from "react";
|
|
@@ -454,49 +450,8 @@ function useMutationsListener({ element, onChange }) {
|
|
|
454
450
|
}, [element, onChange]);
|
|
455
451
|
}
|
|
456
452
|
|
|
457
|
-
// src/hooks/use-floating-on-element.ts
|
|
458
|
-
import { useEffect as useEffect3, useState as useState2 } from "react";
|
|
459
|
-
import { autoUpdate, offset, size, useFloating } from "@floating-ui/react";
|
|
460
|
-
function useFloatingOnElement({ element, isSelected }) {
|
|
461
|
-
const [isOpen, setIsOpen] = useState2(false);
|
|
462
|
-
const sizeModifier = 2;
|
|
463
|
-
const { refs, floatingStyles, context } = useFloating({
|
|
464
|
-
// Must be controlled for interactions (like hover) to work.
|
|
465
|
-
open: isOpen || isSelected,
|
|
466
|
-
onOpenChange: setIsOpen,
|
|
467
|
-
whileElementsMounted: autoUpdate,
|
|
468
|
-
middleware: [
|
|
469
|
-
// Match the floating element's size to the reference element.
|
|
470
|
-
size(() => {
|
|
471
|
-
return {
|
|
472
|
-
apply({ elements, rects }) {
|
|
473
|
-
Object.assign(elements.floating.style, {
|
|
474
|
-
width: `${rects.reference.width + sizeModifier}px`,
|
|
475
|
-
height: `${rects.reference.height + sizeModifier}px`
|
|
476
|
-
});
|
|
477
|
-
}
|
|
478
|
-
};
|
|
479
|
-
}),
|
|
480
|
-
// Center the floating element on the reference element.
|
|
481
|
-
offset(({ rects }) => -rects.reference.height / 2 - rects.floating.height / 2)
|
|
482
|
-
]
|
|
483
|
-
});
|
|
484
|
-
useEffect3(() => {
|
|
485
|
-
refs.setReference(element);
|
|
486
|
-
}, [element, refs]);
|
|
487
|
-
return {
|
|
488
|
-
isVisible: isOpen || isSelected,
|
|
489
|
-
context,
|
|
490
|
-
floating: {
|
|
491
|
-
setRef: refs.setFloating,
|
|
492
|
-
ref: refs.floating,
|
|
493
|
-
styles: floatingStyles
|
|
494
|
-
}
|
|
495
|
-
};
|
|
496
|
-
}
|
|
497
|
-
|
|
498
453
|
// src/hooks/use-grid-tracks.ts
|
|
499
|
-
import { useEffect as
|
|
454
|
+
import { useEffect as useEffect4, useState as useState3 } from "react";
|
|
500
455
|
import { ELEMENT_STYLE_CHANGE_EVENT } from "@elementor/editor-elements";
|
|
501
456
|
import { __privateUseListenTo as useListenTo, windowEvent } from "@elementor/editor-v1-adapters";
|
|
502
457
|
|
|
@@ -583,10 +538,10 @@ function toPx(value) {
|
|
|
583
538
|
}
|
|
584
539
|
|
|
585
540
|
// src/hooks/use-grid-children.ts
|
|
586
|
-
import { useEffect as
|
|
541
|
+
import { useEffect as useEffect3, useState as useState2 } from "react";
|
|
587
542
|
function useGridChildren(element) {
|
|
588
|
-
const [signal, setSignal] =
|
|
589
|
-
|
|
543
|
+
const [signal, setSignal] = useState2(0);
|
|
544
|
+
useEffect3(() => {
|
|
590
545
|
if (!element) {
|
|
591
546
|
return;
|
|
592
547
|
}
|
|
@@ -633,13 +588,13 @@ var EMPTY = {
|
|
|
633
588
|
};
|
|
634
589
|
var DEVICE_MODE_CHANGE_EVENT = "elementor/device-mode/change";
|
|
635
590
|
function useGridTracks(element, rect) {
|
|
636
|
-
const [tracks, setTracks] =
|
|
591
|
+
const [tracks, setTracks] = useState3(EMPTY);
|
|
637
592
|
const trigger = useListenTo(
|
|
638
593
|
[windowEvent(ELEMENT_STYLE_CHANGE_EVENT), windowEvent(DEVICE_MODE_CHANGE_EVENT)],
|
|
639
594
|
() => ({})
|
|
640
595
|
);
|
|
641
596
|
const childrenTrigger = useGridChildren(element);
|
|
642
|
-
|
|
597
|
+
useEffect4(() => {
|
|
643
598
|
const previewWindow = element?.ownerDocument?.defaultView;
|
|
644
599
|
if (!element || !previewWindow) {
|
|
645
600
|
setTracks(EMPTY);
|
|
@@ -655,98 +610,6 @@ function useGridTracks(element, rect) {
|
|
|
655
610
|
return tracks;
|
|
656
611
|
}
|
|
657
612
|
|
|
658
|
-
// src/components/outline-overlay.tsx
|
|
659
|
-
import * as React from "react";
|
|
660
|
-
import { Box, styled } from "@elementor/ui";
|
|
661
|
-
import { FloatingPortal, useHover, useInteractions } from "@floating-ui/react";
|
|
662
|
-
|
|
663
|
-
// src/hooks/use-bind-react-props-to-element.ts
|
|
664
|
-
import { useEffect as useEffect6 } from "react";
|
|
665
|
-
function useBindReactPropsToElement(element, getProps) {
|
|
666
|
-
useEffect6(() => {
|
|
667
|
-
const el = element;
|
|
668
|
-
const { events, attrs } = groupProps(getProps());
|
|
669
|
-
events.forEach(([eventName, listener]) => el.addEventListener(eventName, listener));
|
|
670
|
-
attrs.forEach(([attrName, attrValue]) => el.setAttribute(attrName, attrValue));
|
|
671
|
-
return () => {
|
|
672
|
-
events.forEach(([eventName, listener]) => el.removeEventListener(eventName, listener));
|
|
673
|
-
attrs.forEach(([attrName]) => el.removeAttribute(attrName));
|
|
674
|
-
};
|
|
675
|
-
}, [getProps, element]);
|
|
676
|
-
}
|
|
677
|
-
function groupProps(props) {
|
|
678
|
-
const eventRegex = /^on(?=[A-Z])/;
|
|
679
|
-
return Object.entries(props).reduce(
|
|
680
|
-
(acc, [propName, propValue]) => {
|
|
681
|
-
if (!eventRegex.test(propName)) {
|
|
682
|
-
acc.attrs.push([propName, propValue]);
|
|
683
|
-
return acc;
|
|
684
|
-
}
|
|
685
|
-
const eventName = propName.replace(eventRegex, "").toLowerCase();
|
|
686
|
-
const listener = propValue;
|
|
687
|
-
acc.events.push([eventName, listener]);
|
|
688
|
-
return acc;
|
|
689
|
-
},
|
|
690
|
-
{
|
|
691
|
-
events: [],
|
|
692
|
-
attrs: []
|
|
693
|
-
}
|
|
694
|
-
);
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
// src/hooks/use-has-overlapping.ts
|
|
698
|
-
var possibleOverlappingSelectors = [".e-off-canvas"];
|
|
699
|
-
var useHasOverlapping = () => {
|
|
700
|
-
const preview = window.elementor?.$preview?.[0];
|
|
701
|
-
if (!preview) {
|
|
702
|
-
return false;
|
|
703
|
-
}
|
|
704
|
-
const hasOverlapping = possibleOverlappingSelectors.map((selector) => Array.from(preview?.contentWindow?.document.body.querySelectorAll(selector) ?? [])).flat().some(
|
|
705
|
-
(elem) => elem.checkVisibility({
|
|
706
|
-
opacityProperty: true,
|
|
707
|
-
visibilityProperty: true,
|
|
708
|
-
contentVisibilityAuto: true
|
|
709
|
-
})
|
|
710
|
-
);
|
|
711
|
-
return hasOverlapping;
|
|
712
|
-
};
|
|
713
|
-
|
|
714
|
-
// src/components/outline-overlay.tsx
|
|
715
|
-
var CANVAS_WRAPPER_ID = "elementor-preview-responsive-wrapper";
|
|
716
|
-
var OverlayBox = styled(Box, {
|
|
717
|
-
shouldForwardProp: (prop) => prop !== "isSelected" && prop !== "isSmallerOffset" && prop !== "isGlobal"
|
|
718
|
-
})(
|
|
719
|
-
({ theme, isSelected, isSmallerOffset, isGlobal }) => ({
|
|
720
|
-
outline: `${isSelected ? "2px" : "1px"} solid ${isGlobal ? theme.palette.global.main : theme.palette.primary.light}`,
|
|
721
|
-
outlineOffset: isSelected && !isSmallerOffset ? "-2px" : "-1px",
|
|
722
|
-
pointerEvents: "none"
|
|
723
|
-
})
|
|
724
|
-
);
|
|
725
|
-
var OutlineOverlay = ({ element, isSelected, id, isGlobal = false }) => {
|
|
726
|
-
const { context, floating, isVisible } = useFloatingOnElement({ element, isSelected });
|
|
727
|
-
const { getFloatingProps, getReferenceProps } = useInteractions([useHover(context)]);
|
|
728
|
-
const hasOverlapping = useHasOverlapping();
|
|
729
|
-
useBindReactPropsToElement(element, getReferenceProps);
|
|
730
|
-
const isSmallerOffset = element.offsetHeight <= 1;
|
|
731
|
-
return isVisible && !hasOverlapping && /* @__PURE__ */ React.createElement(FloatingPortal, { id: CANVAS_WRAPPER_ID }, /* @__PURE__ */ React.createElement(
|
|
732
|
-
OverlayBox,
|
|
733
|
-
{
|
|
734
|
-
ref: floating.setRef,
|
|
735
|
-
isSelected,
|
|
736
|
-
isGlobal,
|
|
737
|
-
style: floating.styles,
|
|
738
|
-
"data-element-overlay": id,
|
|
739
|
-
role: "presentation",
|
|
740
|
-
isSmallerOffset,
|
|
741
|
-
...getFloatingProps()
|
|
742
|
-
}
|
|
743
|
-
));
|
|
744
|
-
};
|
|
745
|
-
|
|
746
|
-
// src/components/grid-outline/grid-outline.tsx
|
|
747
|
-
import * as React5 from "react";
|
|
748
|
-
import { useMemo } from "react";
|
|
749
|
-
|
|
750
613
|
// src/utils/find-first-empty-cell.ts
|
|
751
614
|
function findFirstEmptyCell(element, columnCount, rowCount) {
|
|
752
615
|
if (!element || columnCount === 0 || rowCount === 0) {
|
|
@@ -909,6 +772,194 @@ function scanFirstEmpty(matrix, flowsByColumn) {
|
|
|
909
772
|
return null;
|
|
910
773
|
}
|
|
911
774
|
|
|
775
|
+
// src/components/grid-outline/grid-empty-cell-positioner.tsx
|
|
776
|
+
var CSS_VAR_ROW = "--e-grid-empty-cell-row";
|
|
777
|
+
var CSS_VAR_COL = "--e-grid-empty-cell-col";
|
|
778
|
+
var CSS_VAR_VISIBILITY = "--e-grid-empty-cell-visibility";
|
|
779
|
+
var clearGridEmptyCellStyles = (target) => {
|
|
780
|
+
target.style.removeProperty(CSS_VAR_ROW);
|
|
781
|
+
target.style.removeProperty(CSS_VAR_COL);
|
|
782
|
+
target.style.removeProperty(CSS_VAR_VISIBILITY);
|
|
783
|
+
};
|
|
784
|
+
var GridEmptyCellPositioner = ({ element }) => {
|
|
785
|
+
const rect = useElementRect(element);
|
|
786
|
+
const tracks = useGridTracks(element, rect);
|
|
787
|
+
useEffect5(() => {
|
|
788
|
+
if (!element) {
|
|
789
|
+
return;
|
|
790
|
+
}
|
|
791
|
+
const firstEmpty = findFirstEmptyCell(element, tracks.columns.length, tracks.rows.length);
|
|
792
|
+
if (!firstEmpty) {
|
|
793
|
+
element.style.removeProperty(CSS_VAR_ROW);
|
|
794
|
+
element.style.removeProperty(CSS_VAR_COL);
|
|
795
|
+
element.style.setProperty(CSS_VAR_VISIBILITY, "hidden");
|
|
796
|
+
return () => clearGridEmptyCellStyles(element);
|
|
797
|
+
}
|
|
798
|
+
element.style.setProperty(CSS_VAR_ROW, String(firstEmpty.row + 1));
|
|
799
|
+
element.style.setProperty(CSS_VAR_COL, String(firstEmpty.col + 1));
|
|
800
|
+
element.style.setProperty(CSS_VAR_VISIBILITY, "visible");
|
|
801
|
+
return () => {
|
|
802
|
+
clearGridEmptyCellStyles(element);
|
|
803
|
+
};
|
|
804
|
+
}, [element, tracks]);
|
|
805
|
+
return null;
|
|
806
|
+
};
|
|
807
|
+
|
|
808
|
+
// src/components/grid-outline/grid-outline-overlay.tsx
|
|
809
|
+
import * as React6 from "react";
|
|
810
|
+
import { useElementEditorSettings } from "@elementor/editor-elements";
|
|
811
|
+
import { Box as Box2 } from "@elementor/ui";
|
|
812
|
+
import { FloatingPortal as FloatingPortal2 } from "@floating-ui/react";
|
|
813
|
+
|
|
814
|
+
// src/hooks/use-floating-on-element.ts
|
|
815
|
+
import { useEffect as useEffect6, useState as useState4 } from "react";
|
|
816
|
+
import { autoUpdate, offset, size, useFloating } from "@floating-ui/react";
|
|
817
|
+
function useFloatingOnElement({ element, isSelected }) {
|
|
818
|
+
const [isOpen, setIsOpen] = useState4(false);
|
|
819
|
+
const sizeModifier = 2;
|
|
820
|
+
const { refs, floatingStyles, context } = useFloating({
|
|
821
|
+
// Must be controlled for interactions (like hover) to work.
|
|
822
|
+
open: isOpen || isSelected,
|
|
823
|
+
onOpenChange: setIsOpen,
|
|
824
|
+
whileElementsMounted: autoUpdate,
|
|
825
|
+
middleware: [
|
|
826
|
+
// Match the floating element's size to the reference element.
|
|
827
|
+
size(() => {
|
|
828
|
+
return {
|
|
829
|
+
apply({ elements, rects }) {
|
|
830
|
+
Object.assign(elements.floating.style, {
|
|
831
|
+
width: `${rects.reference.width + sizeModifier}px`,
|
|
832
|
+
height: `${rects.reference.height + sizeModifier}px`
|
|
833
|
+
});
|
|
834
|
+
}
|
|
835
|
+
};
|
|
836
|
+
}),
|
|
837
|
+
// Center the floating element on the reference element.
|
|
838
|
+
offset(({ rects }) => -rects.reference.height / 2 - rects.floating.height / 2)
|
|
839
|
+
]
|
|
840
|
+
});
|
|
841
|
+
useEffect6(() => {
|
|
842
|
+
refs.setReference(element);
|
|
843
|
+
}, [element, refs]);
|
|
844
|
+
return {
|
|
845
|
+
isVisible: isOpen || isSelected,
|
|
846
|
+
context,
|
|
847
|
+
floating: {
|
|
848
|
+
setRef: refs.setFloating,
|
|
849
|
+
ref: refs.floating,
|
|
850
|
+
styles: floatingStyles
|
|
851
|
+
}
|
|
852
|
+
};
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
// src/components/outline-overlay.tsx
|
|
856
|
+
import * as React from "react";
|
|
857
|
+
import { Box, styled } from "@elementor/ui";
|
|
858
|
+
import { FloatingPortal, useHover, useInteractions } from "@floating-ui/react";
|
|
859
|
+
|
|
860
|
+
// src/hooks/use-bind-react-props-to-element.ts
|
|
861
|
+
import { useEffect as useEffect7 } from "react";
|
|
862
|
+
function useBindReactPropsToElement(element, getProps) {
|
|
863
|
+
useEffect7(() => {
|
|
864
|
+
const el = element;
|
|
865
|
+
const { events, attrs } = groupProps(getProps());
|
|
866
|
+
events.forEach(([eventName, listener]) => el.addEventListener(eventName, listener));
|
|
867
|
+
attrs.forEach(([attrName, attrValue]) => el.setAttribute(attrName, attrValue));
|
|
868
|
+
return () => {
|
|
869
|
+
events.forEach(([eventName, listener]) => el.removeEventListener(eventName, listener));
|
|
870
|
+
attrs.forEach(([attrName]) => el.removeAttribute(attrName));
|
|
871
|
+
};
|
|
872
|
+
}, [getProps, element]);
|
|
873
|
+
}
|
|
874
|
+
function groupProps(props) {
|
|
875
|
+
const eventRegex = /^on(?=[A-Z])/;
|
|
876
|
+
return Object.entries(props).reduce(
|
|
877
|
+
(acc, [propName, propValue]) => {
|
|
878
|
+
if (!eventRegex.test(propName)) {
|
|
879
|
+
acc.attrs.push([propName, propValue]);
|
|
880
|
+
return acc;
|
|
881
|
+
}
|
|
882
|
+
const eventName = propName.replace(eventRegex, "").toLowerCase();
|
|
883
|
+
const listener = propValue;
|
|
884
|
+
acc.events.push([eventName, listener]);
|
|
885
|
+
return acc;
|
|
886
|
+
},
|
|
887
|
+
{
|
|
888
|
+
events: [],
|
|
889
|
+
attrs: []
|
|
890
|
+
}
|
|
891
|
+
);
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
// src/hooks/use-has-overlapping.ts
|
|
895
|
+
var possibleOverlappingSelectors = [".e-off-canvas"];
|
|
896
|
+
var useHasOverlapping = () => {
|
|
897
|
+
const preview = window.elementor?.$preview?.[0];
|
|
898
|
+
if (!preview) {
|
|
899
|
+
return false;
|
|
900
|
+
}
|
|
901
|
+
const hasOverlapping = possibleOverlappingSelectors.map((selector) => Array.from(preview?.contentWindow?.document.body.querySelectorAll(selector) ?? [])).flat().some(
|
|
902
|
+
(elem) => elem.checkVisibility({
|
|
903
|
+
opacityProperty: true,
|
|
904
|
+
visibilityProperty: true,
|
|
905
|
+
contentVisibilityAuto: true
|
|
906
|
+
})
|
|
907
|
+
);
|
|
908
|
+
return hasOverlapping;
|
|
909
|
+
};
|
|
910
|
+
|
|
911
|
+
// src/utils/outline-offset-utils.ts
|
|
912
|
+
var THIN_ELEMENT_MAX_HEIGHT_PX = 1;
|
|
913
|
+
var SMALLER_OUTLINE_OFFSET_WIDGET_TYPES = /* @__PURE__ */ new Set(["e-form-input"]);
|
|
914
|
+
function shouldUseSmallerOutlineOffset(element, widgetType) {
|
|
915
|
+
if (element.offsetHeight <= THIN_ELEMENT_MAX_HEIGHT_PX) {
|
|
916
|
+
return true;
|
|
917
|
+
}
|
|
918
|
+
return widgetType !== void 0 && SMALLER_OUTLINE_OFFSET_WIDGET_TYPES.has(widgetType);
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
// src/components/outline-overlay.tsx
|
|
922
|
+
var CANVAS_WRAPPER_ID = "elementor-preview-responsive-wrapper";
|
|
923
|
+
var OverlayBox = styled(Box, {
|
|
924
|
+
shouldForwardProp: (prop) => prop !== "isSelected" && prop !== "isSmallerOffset" && prop !== "isGlobal"
|
|
925
|
+
})(
|
|
926
|
+
({ theme, isSelected, isSmallerOffset, isGlobal }) => ({
|
|
927
|
+
outline: `${isSelected ? "2px" : "1px"} solid ${isGlobal ? theme.palette.global.main : theme.palette.primary.light}`,
|
|
928
|
+
outlineOffset: isSelected && !isSmallerOffset ? "-2px" : "-1px",
|
|
929
|
+
pointerEvents: "none"
|
|
930
|
+
})
|
|
931
|
+
);
|
|
932
|
+
var OutlineOverlay = ({
|
|
933
|
+
element,
|
|
934
|
+
isSelected,
|
|
935
|
+
id,
|
|
936
|
+
isGlobal = false,
|
|
937
|
+
widgetType
|
|
938
|
+
}) => {
|
|
939
|
+
const { context, floating, isVisible } = useFloatingOnElement({ element, isSelected });
|
|
940
|
+
const { getFloatingProps, getReferenceProps } = useInteractions([useHover(context)]);
|
|
941
|
+
const hasOverlapping = useHasOverlapping();
|
|
942
|
+
useBindReactPropsToElement(element, getReferenceProps);
|
|
943
|
+
const isSmallerOffset = shouldUseSmallerOutlineOffset(element, widgetType);
|
|
944
|
+
return isVisible && !hasOverlapping && /* @__PURE__ */ React.createElement(FloatingPortal, { id: CANVAS_WRAPPER_ID }, /* @__PURE__ */ React.createElement(
|
|
945
|
+
OverlayBox,
|
|
946
|
+
{
|
|
947
|
+
ref: floating.setRef,
|
|
948
|
+
isSelected,
|
|
949
|
+
isGlobal,
|
|
950
|
+
style: floating.styles,
|
|
951
|
+
"data-element-overlay": id,
|
|
952
|
+
role: "presentation",
|
|
953
|
+
isSmallerOffset,
|
|
954
|
+
...getFloatingProps()
|
|
955
|
+
}
|
|
956
|
+
));
|
|
957
|
+
};
|
|
958
|
+
|
|
959
|
+
// src/components/grid-outline/grid-outline.tsx
|
|
960
|
+
import * as React5 from "react";
|
|
961
|
+
import { useMemo } from "react";
|
|
962
|
+
|
|
912
963
|
// src/components/grid-outline/cell.tsx
|
|
913
964
|
import * as React2 from "react";
|
|
914
965
|
var FALLBACK_COLOR = "rgba(0, 0, 0, 0.12)";
|
|
@@ -1016,6 +1067,13 @@ var renderLines = (tracks, width, height) => {
|
|
|
1016
1067
|
))
|
|
1017
1068
|
];
|
|
1018
1069
|
};
|
|
1070
|
+
var isDragActiveFromDom = (element) => {
|
|
1071
|
+
return Boolean(
|
|
1072
|
+
element?.querySelector(
|
|
1073
|
+
".e-dragging-over, .elementor-dragging-on-child, .elementor-draggable-over, .elementor-widget-placeholder, .elementor-sortable-placeholder"
|
|
1074
|
+
)
|
|
1075
|
+
);
|
|
1076
|
+
};
|
|
1019
1077
|
function GridOutline({ element, tracks, width, height }) {
|
|
1020
1078
|
const cells = useMemo(() => computeCellRects(tracks, width, height), [tracks, width, height]);
|
|
1021
1079
|
const hasGap = tracks.columnGap > 0 || tracks.rowGap > 0;
|
|
@@ -1033,13 +1091,13 @@ function GridOutline({ element, tracks, width, height }) {
|
|
|
1033
1091
|
xmlns: "http://www.w3.org/2000/svg"
|
|
1034
1092
|
},
|
|
1035
1093
|
hasGap ? renderCells(cells, tracks.borderColor) : renderLines(tracks, width, height)
|
|
1036
|
-
), emptyCellRect && /* @__PURE__ */ React5.createElement(FirstEmptyCell, { rect: emptyCellRect, color: tracks.borderColor }));
|
|
1094
|
+
), emptyCellRect && !isDragActiveFromDom(element) && /* @__PURE__ */ React5.createElement(FirstEmptyCell, { rect: emptyCellRect, color: tracks.borderColor }));
|
|
1037
1095
|
}
|
|
1038
1096
|
|
|
1039
1097
|
// src/components/grid-outline/grid-outline-overlay.tsx
|
|
1040
1098
|
var GridOutlineOverlay = ({ element, id, isSelected }) => {
|
|
1041
|
-
const
|
|
1042
|
-
const enabled =
|
|
1099
|
+
const settings = useElementEditorSettings(id);
|
|
1100
|
+
const enabled = settings?.grid_outline;
|
|
1043
1101
|
const rect = useElementRect(element);
|
|
1044
1102
|
const tracks = useGridTracks(element, rect);
|
|
1045
1103
|
const { floating } = useFloatingOnElement({ element, isSelected });
|
|
@@ -1062,15 +1120,22 @@ var GridOutlineOverlay = ({ element, id, isSelected }) => {
|
|
|
1062
1120
|
};
|
|
1063
1121
|
|
|
1064
1122
|
// src/components/elements-overlays.tsx
|
|
1123
|
+
var hasGridStyleDisplay = (element) => {
|
|
1124
|
+
return element.computedStyleMap().get("display")?.toString() === "grid";
|
|
1125
|
+
};
|
|
1065
1126
|
var ELEMENTS_DATA_ATTR = "atomic";
|
|
1066
1127
|
var overlayRegistry = [
|
|
1067
1128
|
{
|
|
1068
1129
|
component: OutlineOverlay,
|
|
1069
1130
|
shouldRender: () => true
|
|
1070
1131
|
},
|
|
1132
|
+
{
|
|
1133
|
+
component: GridEmptyCellPositioner,
|
|
1134
|
+
shouldRender: ({ element }) => hasGridStyleDisplay(element)
|
|
1135
|
+
},
|
|
1071
1136
|
{
|
|
1072
1137
|
component: GridOutlineOverlay,
|
|
1073
|
-
shouldRender: ({
|
|
1138
|
+
shouldRender: ({ isSelected, element }) => isSelected && hasGridStyleDisplay(element)
|
|
1074
1139
|
}
|
|
1075
1140
|
];
|
|
1076
1141
|
function ElementsOverlays() {
|
|
@@ -1083,17 +1148,18 @@ function ElementsOverlays() {
|
|
|
1083
1148
|
if (!isActive) {
|
|
1084
1149
|
return null;
|
|
1085
1150
|
}
|
|
1086
|
-
return elements.map(({ id, domElement, isGlobal }) => {
|
|
1151
|
+
return elements.map(({ id, domElement, isGlobal, widgetType }) => {
|
|
1087
1152
|
const isSelected = selected.element?.id === id;
|
|
1088
1153
|
return overlayRegistry.map(
|
|
1089
|
-
({ shouldRender, component: Overlay }, index) => shouldRender({ id, element: domElement, isSelected }) && /* @__PURE__ */ React7.createElement(
|
|
1154
|
+
({ shouldRender, component: Overlay }, index) => shouldRender({ id, element: domElement, isSelected, widgetType }) && /* @__PURE__ */ React7.createElement(
|
|
1090
1155
|
Overlay,
|
|
1091
1156
|
{
|
|
1092
1157
|
key: `${id}-${index}`,
|
|
1093
1158
|
id,
|
|
1094
1159
|
element: domElement,
|
|
1095
1160
|
isSelected,
|
|
1096
|
-
isGlobal
|
|
1161
|
+
isGlobal,
|
|
1162
|
+
widgetType
|
|
1097
1163
|
}
|
|
1098
1164
|
)
|
|
1099
1165
|
);
|
|
@@ -1106,7 +1172,8 @@ function useElementsDom() {
|
|
|
1106
1172
|
return getElements().filter((el) => isV4Element(el.view?.el?.dataset)).map((element) => ({
|
|
1107
1173
|
id: element.id,
|
|
1108
1174
|
domElement: element.view?.getDomElement?.()?.get?.(0),
|
|
1109
|
-
isGlobal: element.model.get("isGlobal") ?? false
|
|
1175
|
+
isGlobal: element.model.get("isGlobal") ?? false,
|
|
1176
|
+
widgetType: element.model.get("widgetType")
|
|
1110
1177
|
})).filter((item) => !!item.domElement);
|
|
1111
1178
|
}
|
|
1112
1179
|
);
|
|
@@ -1128,15 +1195,15 @@ import {
|
|
|
1128
1195
|
import { Portal } from "@elementor/ui";
|
|
1129
1196
|
|
|
1130
1197
|
// src/hooks/use-interactions-items.ts
|
|
1131
|
-
import { useEffect as
|
|
1198
|
+
import { useEffect as useEffect9, useMemo as useMemo2, useState as useState5 } from "react";
|
|
1132
1199
|
import { interactionsRepository } from "@elementor/editor-interactions";
|
|
1133
1200
|
import { registerDataHook } from "@elementor/editor-v1-adapters";
|
|
1134
1201
|
|
|
1135
1202
|
// src/hooks/use-on-mount.ts
|
|
1136
|
-
import { useEffect as
|
|
1203
|
+
import { useEffect as useEffect8, useRef } from "react";
|
|
1137
1204
|
function useOnMount(cb) {
|
|
1138
1205
|
const mounted = useRef(false);
|
|
1139
|
-
|
|
1206
|
+
useEffect8(() => {
|
|
1140
1207
|
if (!mounted.current) {
|
|
1141
1208
|
mounted.current = true;
|
|
1142
1209
|
cb();
|
|
@@ -1164,7 +1231,7 @@ function useInteractionsItems() {
|
|
|
1164
1231
|
return [];
|
|
1165
1232
|
}
|
|
1166
1233
|
}, []);
|
|
1167
|
-
|
|
1234
|
+
useEffect9(() => {
|
|
1168
1235
|
if (providerAndSubscribers.length === 0) {
|
|
1169
1236
|
return;
|
|
1170
1237
|
}
|
|
@@ -1301,7 +1368,7 @@ function getLinkAttrs(el) {
|
|
|
1301
1368
|
}
|
|
1302
1369
|
|
|
1303
1370
|
// src/hooks/use-style-items.ts
|
|
1304
|
-
import { useEffect as
|
|
1371
|
+
import { useEffect as useEffect10, useMemo as useMemo5, useRef as useRef2, useState as useState6 } from "react";
|
|
1305
1372
|
import { useBreakpoints } from "@elementor/editor-responsive";
|
|
1306
1373
|
import { isClassState } from "@elementor/editor-styles";
|
|
1307
1374
|
import { stylesRepository as stylesRepository2 } from "@elementor/editor-styles-repository";
|
|
@@ -1679,7 +1746,7 @@ function useStyleItems() {
|
|
|
1679
1746
|
})
|
|
1680
1747
|
);
|
|
1681
1748
|
}, [renderStyles]);
|
|
1682
|
-
|
|
1749
|
+
useEffect10(() => {
|
|
1683
1750
|
const unsubscribes = providerAndSubscribers.map(
|
|
1684
1751
|
({ provider, subscriber }) => provider.subscribe(subscriber)
|
|
1685
1752
|
);
|
|
@@ -1935,6 +2002,46 @@ function clipboardRootsAreAtomicForms(elements) {
|
|
|
1935
2002
|
}
|
|
1936
2003
|
return elements.every((el) => getClipboardElementType(el) === FORM_ELEMENT_TYPE);
|
|
1937
2004
|
}
|
|
2005
|
+
function hasFormAncestor(node) {
|
|
2006
|
+
return node.closest(FORM_ELEMENT_TYPE) !== null;
|
|
2007
|
+
}
|
|
2008
|
+
function collectFormAncestorErrors(xml) {
|
|
2009
|
+
const errors = [];
|
|
2010
|
+
for (const node of xml.querySelectorAll("*")) {
|
|
2011
|
+
if (!FORM_FIELD_ELEMENT_TYPES.has(node.tagName.toLowerCase())) {
|
|
2012
|
+
continue;
|
|
2013
|
+
}
|
|
2014
|
+
if (hasFormAncestor(node)) {
|
|
2015
|
+
continue;
|
|
2016
|
+
}
|
|
2017
|
+
const id = node.getAttribute("configuration-id");
|
|
2018
|
+
errors.push(
|
|
2019
|
+
`<${node.tagName}${id ? ` configuration-id="${id}"` : ""}> must be nested inside <e-form> (any ancestor depth is allowed).`
|
|
2020
|
+
);
|
|
2021
|
+
}
|
|
2022
|
+
return errors;
|
|
2023
|
+
}
|
|
2024
|
+
function collectSubmitButtonErrors(xml) {
|
|
2025
|
+
const errors = [];
|
|
2026
|
+
for (const form of xml.querySelectorAll("e-form")) {
|
|
2027
|
+
const submitButtons = form.querySelectorAll("e-form-submit-button");
|
|
2028
|
+
if (submitButtons.length === 0) {
|
|
2029
|
+
errors.push(`<e-form> has no <e-form-submit-button>.`);
|
|
2030
|
+
} else if (submitButtons.length > 1) {
|
|
2031
|
+
errors.push(`<e-form> has ${submitButtons.length} submit buttons \u2014 only 1 is allowed.`);
|
|
2032
|
+
}
|
|
2033
|
+
}
|
|
2034
|
+
return errors;
|
|
2035
|
+
}
|
|
2036
|
+
function collectEmptyMessageErrors(xml) {
|
|
2037
|
+
const errors = [];
|
|
2038
|
+
for (const node of xml.querySelectorAll("e-form-success-message, e-form-error-message")) {
|
|
2039
|
+
if (node.children.length === 0) {
|
|
2040
|
+
errors.push(`<${node.tagName}> must have at least one child element (e.g. <e-atomic-paragraph>).`);
|
|
2041
|
+
}
|
|
2042
|
+
}
|
|
2043
|
+
return errors;
|
|
2044
|
+
}
|
|
1938
2045
|
|
|
1939
2046
|
// src/form-structure/enforce-form-ancestor-commands.ts
|
|
1940
2047
|
var FORM_FIELDS_OUTSIDE_ALERT = {
|
|
@@ -1961,7 +2068,8 @@ function blockFormFieldCreate(args) {
|
|
|
1961
2068
|
if (!elementType || !FORM_FIELD_ELEMENT_TYPES.has(elementType)) {
|
|
1962
2069
|
return false;
|
|
1963
2070
|
}
|
|
1964
|
-
|
|
2071
|
+
const containers = args.containers ?? [args.container];
|
|
2072
|
+
if (containers.some((container) => !isWithinForm(container))) {
|
|
1965
2073
|
handleBlockedFormField();
|
|
1966
2074
|
return true;
|
|
1967
2075
|
}
|
|
@@ -1969,10 +2077,10 @@ function blockFormFieldCreate(args) {
|
|
|
1969
2077
|
}
|
|
1970
2078
|
function blockFormFieldMove(args) {
|
|
1971
2079
|
const { containers = [args.container], target } = args;
|
|
1972
|
-
const
|
|
1973
|
-
(container) => container ? hasElementTypes(container, FORM_FIELD_ELEMENT_TYPES) : false
|
|
2080
|
+
const hasLooseFormFields = containers.some(
|
|
2081
|
+
(container) => container ? !hasElementType(container, FORM_ELEMENT_TYPE) && hasElementTypes(container, FORM_FIELD_ELEMENT_TYPES) : false
|
|
1974
2082
|
);
|
|
1975
|
-
if (
|
|
2083
|
+
if (hasLooseFormFields && !isWithinForm(target) && !movedContainersIncludeAtomicFormRoot(containers)) {
|
|
1976
2084
|
handleBlockedFormField();
|
|
1977
2085
|
return true;
|
|
1978
2086
|
}
|
|
@@ -3387,13 +3495,13 @@ var ReplacementBase = class {
|
|
|
3387
3495
|
|
|
3388
3496
|
// src/legacy/replacements/inline-editing/canvas-inline-editor.tsx
|
|
3389
3497
|
import * as React10 from "react";
|
|
3390
|
-
import { useCallback as useCallback2, useEffect as
|
|
3498
|
+
import { useCallback as useCallback2, useEffect as useEffect12, useLayoutEffect, useState as useState8 } from "react";
|
|
3391
3499
|
import { InlineEditor, InlineEditorToolbar } from "@elementor/editor-controls";
|
|
3392
3500
|
import { Box as Box3, ThemeProvider } from "@elementor/ui";
|
|
3393
3501
|
import { autoUpdate as autoUpdate2, flip, FloatingPortal as FloatingPortal3, useFloating as useFloating2 } from "@floating-ui/react";
|
|
3394
3502
|
|
|
3395
3503
|
// src/legacy/replacements/inline-editing/inline-editing-utils.ts
|
|
3396
|
-
import { useCallback, useEffect as
|
|
3504
|
+
import { useCallback, useEffect as useEffect11, useState as useState7 } from "react";
|
|
3397
3505
|
var TOP_BAR_SELECTOR = "#elementor-editor-wrapper-v2";
|
|
3398
3506
|
var NAVIGATOR_SELECTOR = "#elementor-navigator";
|
|
3399
3507
|
var EDITING_PANEL = "#elementor-panel";
|
|
@@ -3425,7 +3533,7 @@ var getInlineEditorElement = (elementWrapper, expectedTag) => {
|
|
|
3425
3533
|
};
|
|
3426
3534
|
var useOnClickOutsideIframe = (handleUnmount) => {
|
|
3427
3535
|
const asyncUnmountInlineEditor = useCallback(() => queueMicrotask(handleUnmount), [handleUnmount]);
|
|
3428
|
-
|
|
3536
|
+
useEffect11(() => {
|
|
3429
3537
|
EDITOR_ELEMENTS_OUT_OF_IFRAME.forEach(
|
|
3430
3538
|
(selector) => document?.querySelector(selector)?.addEventListener("mousedown", asyncUnmountInlineEditor)
|
|
3431
3539
|
);
|
|
@@ -3436,7 +3544,7 @@ var useOnClickOutsideIframe = (handleUnmount) => {
|
|
|
3436
3544
|
};
|
|
3437
3545
|
var useRenderToolbar = (ownerDocument, id) => {
|
|
3438
3546
|
const [anchor, setAnchor] = useState7(null);
|
|
3439
|
-
|
|
3547
|
+
useEffect11(() => {
|
|
3440
3548
|
if (!anchor) {
|
|
3441
3549
|
removeToolbarAnchor(ownerDocument, id);
|
|
3442
3550
|
}
|
|
@@ -3533,7 +3641,7 @@ var CanvasInlineEditor = ({
|
|
|
3533
3641
|
const [active, setActive] = useState8(true);
|
|
3534
3642
|
const [editor, setEditor] = useState8(null);
|
|
3535
3643
|
const { onSelectionEnd, anchor: toolbarAnchor, clearAnchor } = useRenderToolbar(rootElement.ownerDocument, id);
|
|
3536
|
-
|
|
3644
|
+
useEffect12(() => {
|
|
3537
3645
|
if (!active) {
|
|
3538
3646
|
clearAnchor();
|
|
3539
3647
|
requestDestroy();
|
|
@@ -3544,7 +3652,7 @@ var CanvasInlineEditor = ({
|
|
|
3544
3652
|
setActive(false);
|
|
3545
3653
|
}, []);
|
|
3546
3654
|
useOnClickOutsideIframe(dismiss);
|
|
3547
|
-
|
|
3655
|
+
useEffect12(() => {
|
|
3548
3656
|
const ownerDocument = contentElement.ownerDocument;
|
|
3549
3657
|
const handleClickAway = (event) => {
|
|
3550
3658
|
if (contentElement.contains(event.target)) {
|
|
@@ -3584,7 +3692,7 @@ var InlineEditingOverlay = ({
|
|
|
3584
3692
|
}) => {
|
|
3585
3693
|
const inlineEditedElement = getInlineEditorElement(rootElement, expectedTag);
|
|
3586
3694
|
const [overlayRefElement, setOverlayElement] = useState8(inlineEditedElement);
|
|
3587
|
-
|
|
3695
|
+
useEffect12(() => {
|
|
3588
3696
|
setOverlayElement(getInlineEditorElement(rootElement, expectedTag));
|
|
3589
3697
|
}, [expectedTag, rootElement]);
|
|
3590
3698
|
return overlayRefElement ? /* @__PURE__ */ React10.createElement(OutlineOverlay, { element: overlayRefElement, id, isSelected: true }) : null;
|
|
@@ -4630,6 +4738,7 @@ import {
|
|
|
4630
4738
|
getContainer as getContainer5,
|
|
4631
4739
|
getWidgetsCache as getWidgetsCache9
|
|
4632
4740
|
} from "@elementor/editor-elements";
|
|
4741
|
+
import { dispatchMcpStylesAppliedEvent } from "@elementor/editor-mcp";
|
|
4633
4742
|
|
|
4634
4743
|
// src/composition-builder/composition-builder.ts
|
|
4635
4744
|
import {
|
|
@@ -5108,6 +5217,11 @@ var CompositionBuilder = class _CompositionBuilder {
|
|
|
5108
5217
|
throw new Error(`Invalid element structure:
|
|
5109
5218
|
${childTypeErrors.join("\n")}`);
|
|
5110
5219
|
}
|
|
5220
|
+
const formErrors = [
|
|
5221
|
+
...collectFormAncestorErrors(this.xml),
|
|
5222
|
+
...collectSubmitButtonErrors(this.xml),
|
|
5223
|
+
...collectEmptyMessageErrors(this.xml)
|
|
5224
|
+
];
|
|
5111
5225
|
const children = Array.from(this.xml.children);
|
|
5112
5226
|
for (const childNode of children) {
|
|
5113
5227
|
const modelTree = this.buildModelTree(childNode, widgetsCache);
|
|
@@ -5142,11 +5256,18 @@ ${childTypeErrors.join("\n")}`);
|
|
|
5142
5256
|
return {
|
|
5143
5257
|
configErrors,
|
|
5144
5258
|
styleErrors,
|
|
5259
|
+
formErrors,
|
|
5145
5260
|
rootContainers: [...this.rootContainers]
|
|
5146
5261
|
};
|
|
5147
5262
|
}
|
|
5148
5263
|
};
|
|
5149
5264
|
|
|
5265
|
+
// src/utils/tracking.ts
|
|
5266
|
+
import { trackEvent } from "@elementor/events";
|
|
5267
|
+
var trackCanvasEvent = (data) => {
|
|
5268
|
+
trackEvent(data);
|
|
5269
|
+
};
|
|
5270
|
+
|
|
5150
5271
|
// src/mcp/utils/get-composition-target-container.ts
|
|
5151
5272
|
import { COMPONENT_DOCUMENT_TYPE } from "@elementor/editor-documents";
|
|
5152
5273
|
function getCompositionTargetContainer(documentContainer, documentType) {
|
|
@@ -5394,6 +5515,7 @@ function serializeWrapped(doc, rootElement, wrapperConfigId) {
|
|
|
5394
5515
|
}
|
|
5395
5516
|
|
|
5396
5517
|
// src/mcp/tools/build-composition/tool.ts
|
|
5518
|
+
var ELEMENT_ADDED_EVENT = "elementor/canvas/element-added";
|
|
5397
5519
|
var initBuildCompositionsTool = (reg) => {
|
|
5398
5520
|
const { addTool, resource } = reg;
|
|
5399
5521
|
resource(
|
|
@@ -5445,12 +5567,28 @@ var initBuildCompositionsTool = (reg) => {
|
|
|
5445
5567
|
compositionBuilder.setElementConfig(elementConfig);
|
|
5446
5568
|
compositionBuilder.setStylesConfig(stylesConfig);
|
|
5447
5569
|
compositionBuilder.setCustomCSS(customCSS);
|
|
5448
|
-
const {
|
|
5570
|
+
const {
|
|
5571
|
+
configErrors,
|
|
5572
|
+
formErrors,
|
|
5573
|
+
rootContainers: generatedRootContainers
|
|
5574
|
+
} = await compositionBuilder.build(targetContainer);
|
|
5449
5575
|
rootContainers.push(...generatedRootContainers);
|
|
5450
5576
|
generatedXML = new XMLSerializer().serializeToString(compositionBuilder.getXML());
|
|
5577
|
+
rootContainers.forEach((container) => {
|
|
5578
|
+
const elementData = container.model?.toJSON();
|
|
5579
|
+
if (elementData) {
|
|
5580
|
+
onElementAdded(elementData);
|
|
5581
|
+
}
|
|
5582
|
+
});
|
|
5583
|
+
Object.values(stylesConfig).forEach((styleValue) => {
|
|
5584
|
+
dispatchMcpStylesAppliedEvent({ styleValue });
|
|
5585
|
+
});
|
|
5451
5586
|
if (configErrors.length) {
|
|
5452
5587
|
errors.push(...configErrors.map((msg) => new Error(msg)));
|
|
5453
5588
|
}
|
|
5589
|
+
if (formErrors.length) {
|
|
5590
|
+
errors.push(...formErrors.map((msg) => new Error(msg)));
|
|
5591
|
+
}
|
|
5454
5592
|
} catch (error) {
|
|
5455
5593
|
errors.push(error);
|
|
5456
5594
|
}
|
|
@@ -5540,9 +5678,32 @@ function assertCompositionXmlUsesV4WidgetsOnly(xmlStructure) {
|
|
|
5540
5678
|
}
|
|
5541
5679
|
}
|
|
5542
5680
|
}
|
|
5681
|
+
function onElementAdded(element) {
|
|
5682
|
+
const elType = element.elType ?? "";
|
|
5683
|
+
const widgetType = element.widgetType ?? "";
|
|
5684
|
+
const elementName = elType === "widget" ? widgetType : elType;
|
|
5685
|
+
trackCanvasEvent({
|
|
5686
|
+
eventName: "add_element",
|
|
5687
|
+
executed_by: "mcp_tool",
|
|
5688
|
+
element_name: elementName,
|
|
5689
|
+
element_type: elType,
|
|
5690
|
+
widget_type: widgetType
|
|
5691
|
+
});
|
|
5692
|
+
const event = {
|
|
5693
|
+
element,
|
|
5694
|
+
executedBy: "mcp_tool"
|
|
5695
|
+
};
|
|
5696
|
+
window.dispatchEvent(new CustomEvent(ELEMENT_ADDED_EVENT, { detail: event }));
|
|
5697
|
+
if (element.elements?.length) {
|
|
5698
|
+
element.elements?.forEach((childElement) => {
|
|
5699
|
+
onElementAdded(childElement);
|
|
5700
|
+
});
|
|
5701
|
+
}
|
|
5702
|
+
}
|
|
5543
5703
|
|
|
5544
5704
|
// src/mcp/tools/configure-element/tool.ts
|
|
5545
5705
|
import { getContainer as getContainer6, getWidgetsCache as getWidgetsCache10 } from "@elementor/editor-elements";
|
|
5706
|
+
import { dispatchMcpStylesAppliedEvent as dispatchMcpStylesAppliedEvent2 } from "@elementor/editor-mcp";
|
|
5546
5707
|
import { Schema as Schema4 } from "@elementor/editor-props";
|
|
5547
5708
|
|
|
5548
5709
|
// src/mcp/tools/configure-element/prompt.ts
|
|
@@ -5781,6 +5942,7 @@ async function applyStyleFromCss(opts) {
|
|
|
5781
5942
|
propertyValue: styleValue,
|
|
5782
5943
|
customCssWriteMode: "merge-with-stored"
|
|
5783
5944
|
});
|
|
5945
|
+
dispatchMcpStylesAppliedEvent2({ styleValue });
|
|
5784
5946
|
} catch (error) {
|
|
5785
5947
|
throw new Error(
|
|
5786
5948
|
createUpdateErrorMessage({
|
|
@@ -6522,9 +6684,9 @@ function useCanvasDocument() {
|
|
|
6522
6684
|
}
|
|
6523
6685
|
|
|
6524
6686
|
// src/hooks/use-escape-on-canvas.ts
|
|
6525
|
-
import { useEffect as
|
|
6687
|
+
import { useEffect as useEffect13 } from "react";
|
|
6526
6688
|
function useEscapeOnCanvas(canvasDocument, onEscape) {
|
|
6527
|
-
|
|
6689
|
+
useEffect13(() => {
|
|
6528
6690
|
if (!canvasDocument) {
|
|
6529
6691
|
return;
|
|
6530
6692
|
}
|
|
@@ -6563,6 +6725,7 @@ export {
|
|
|
6563
6725
|
BREAKPOINTS_SCHEMA_FULL_URI,
|
|
6564
6726
|
BREAKPOINTS_SCHEMA_URI,
|
|
6565
6727
|
DOCUMENT_STRUCTURE_URI,
|
|
6728
|
+
ELEMENT_ADDED_EVENT,
|
|
6566
6729
|
GLOBAL_STYLES_IMPORTED_EVENT,
|
|
6567
6730
|
SpotlightBackdrop,
|
|
6568
6731
|
UnknownStyleStateError,
|