@contentful/experiences-visual-editor-react 1.0.8 → 1.0.9-beta.0

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.js CHANGED
@@ -1716,8 +1716,8 @@ function gatherDeepReferencesFromTree(startingNode, dataSource) {
1716
1716
  return deepReferences;
1717
1717
  }
1718
1718
 
1719
- var css_248z$8 = ".styles-module_DraggableComponent__m5-dA {\n pointer-events: all;\n position: relative;\n transition: outline 0.2s;\n cursor: grab;\n box-sizing: border-box;\n display: flex;\n}\n\n.styles-module_DraggableComponent__m5-dA:before {\n content: '';\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n outline-offset: -2px;\n outline: 2px solid transparent;\n z-index: 1;\n pointer-events: none;\n}\n\n.styles-module_DraggableClone__X8zTA:before {\n outline: 2px solid var(--exp-builder-blue500);\n}\n\n.styles-module_DraggableClone__X8zTA,\n.styles-module_DraggableClone__X8zTA * {\n pointer-events: none !important;\n}\n\n.styles-module_DraggableComponent__m5-dA:not(.styles-module_userIsDragging__lqbjG) :not(.styles-module_DraggableComponent__m5-dA) {\n pointer-events: none;\n}\n\n.styles-module_isDragging__WHjPU {\n overflow: hidden;\n}\n\n.styles-module_isSelected__BzICQ:before {\n outline: 2px solid transparent !important;\n}\n\n.styles-module_overlay__r4th9 {\n position: absolute;\n display: flex;\n align-items: center;\n min-width: max-content;\n height: 24px;\n z-index: 1;\n font-family: var(--exp-builder-font-stack-primary);\n font-size: 14px;\n font-weight: 500;\n background-color: var(--exp-builder-gray500);\n color: var(--exp-builder-color-white);\n border-radius: 0 0 2px 0;\n padding: 4px 12px 4px 12px;\n transition: opacity 0.2s;\n opacity: 0;\n text-wrap: nowrap;\n}\n\n.styles-module_overlayContainer__eiX-5 {\n opacity: 0;\n}\n\n.styles-module_overlayAssembly__tOzZU {\n background-color: var(--exp-builder-purple600);\n}\n\n.styles-module_userIsDragging__lqbjG > .styles-module_overlay__r4th9,\n.styles-module_userIsDragging__lqbjG > .styles-module_overlayContainer__eiX-5 {\n opacity: 0 !important;\n}\n\n.styles-module_userIsDragging__lqbjG:before {\n outline: 2px solid transparent !important;\n}\n\n.styles-module_DraggableComponent__m5-dA:hover:not(:has(div[data-rfd-draggable-id]:hover)) > .styles-module_overlay__r4th9 {\n opacity: 1;\n}\n\n.styles-module_DraggableComponent__m5-dA:hover:before,\n.styles-module_DraggableComponent__m5-dA:hover div[data-rfd-draggable-id]:before {\n outline: 2px dashed var(--exp-builder-gray500);\n}\n\n.styles-module_DraggableComponent__m5-dA:hover:not(:has(div[data-rfd-draggable-id]:hover)):before {\n outline: 2px solid var(--exp-builder-gray500);\n}\n\n.styles-module_isAssemblyBlock__Y3Avk:hover:before,\n.styles-module_isAssemblyBlock__Y3Avk:hover div[data-rfd-draggable-id]:before,\n.styles-module_DraggableComponent__m5-dA:hover div[data-rfd-draggable-id][data-cf-node-block-type^='assembly']:before {\n outline: 2px dashed var(--exp-builder-purple600);\n}\n\n.styles-module_isAssemblyBlock__Y3Avk:hover:not(:has(div[data-rfd-draggable-id]:hover)):before {\n outline: 2px solid var(--exp-builder-purple600);\n}\n";
1720
- var styles$3 = {"DraggableComponent":"styles-module_DraggableComponent__m5-dA","DraggableClone":"styles-module_DraggableClone__X8zTA","userIsDragging":"styles-module_userIsDragging__lqbjG","isDragging":"styles-module_isDragging__WHjPU","isSelected":"styles-module_isSelected__BzICQ","overlay":"styles-module_overlay__r4th9","overlayContainer":"styles-module_overlayContainer__eiX-5","overlayAssembly":"styles-module_overlayAssembly__tOzZU","isAssemblyBlock":"styles-module_isAssemblyBlock__Y3Avk"};
1719
+ var css_248z$8 = ".styles-module_DraggableComponent__m5-dA {\n pointer-events: all;\n position: relative;\n transition: outline 0.2s;\n cursor: grab;\n box-sizing: border-box;\n display: flex;\n}\n\n.styles-module_DraggableComponent__m5-dA:before {\n content: '';\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n outline-offset: -2px;\n outline: 2px solid transparent;\n z-index: 1;\n pointer-events: none;\n}\n\n.styles-module_DraggableClone__X8zTA:before {\n outline: 2px solid var(--exp-builder-blue500);\n}\n\n.styles-module_DraggableClone__X8zTA,\n.styles-module_DraggableClone__X8zTA * {\n pointer-events: none !important;\n}\n\n.styles-module_DraggableComponent__m5-dA:not(.styles-module_userIsDragging__lqbjG) :not(.styles-module_DraggableComponent__m5-dA) {\n pointer-events: none;\n}\n\n.styles-module_isDragging__WHjPU {\n overflow: hidden;\n}\n\n.styles-module_isSelected__BzICQ:before {\n outline: 2px solid transparent !important;\n}\n\n.styles-module_overlay__r4th9 {\n position: absolute;\n display: flex;\n align-items: center;\n min-width: max-content;\n height: 24px;\n z-index: 2;\n font-family: var(--exp-builder-font-stack-primary);\n font-size: 14px;\n font-weight: 500;\n background-color: var(--exp-builder-gray500);\n color: var(--exp-builder-color-white);\n padding: 4px 12px 4px 12px;\n transition: opacity 0.1s;\n opacity: 0;\n text-wrap: nowrap;\n}\n\n.styles-module_overlayContainer__eiX-5 {\n opacity: 0;\n}\n\n.styles-module_overlayAssembly__tOzZU {\n background-color: var(--exp-builder-purple600);\n}\n\n.styles-module_userIsDragging__lqbjG > .styles-module_overlay__r4th9,\n.styles-module_userIsDragging__lqbjG > .styles-module_overlayContainer__eiX-5 {\n opacity: 0 !important;\n}\n\n.styles-module_userIsDragging__lqbjG:before {\n outline: 2px solid transparent !important;\n}\n\n.styles-module_isHoveringComponent__RSeDG > .styles-module_overlay__r4th9,\n.styles-module_DraggableComponent__m5-dA:hover:not(:has(.styles-module_DraggableComponent__m5-dA:hover)) > .styles-module_overlay__r4th9 {\n opacity: 1;\n}\n\n/* hovering related component in layers tab */\n\n.styles-module_DraggableComponent__m5-dA:has(.styles-module_isHoveringComponent__RSeDG):not(.styles-module_isAssemblyBlock__Y3Avk):before,\n.styles-module_DraggableComponent__m5-dA:has(.styles-module_isHoveringComponent__RSeDG):not(.styles-module_isAssemblyBlock__Y3Avk) .styles-module_DraggableComponent__m5-dA:not(.styles-module_isHoveringComponent__RSeDG):not(.styles-module_isAssemblyBlock__Y3Avk):before,\n.styles-module_isHoveringComponent__RSeDG:not(.styles-module_isAssemblyBlock__Y3Avk) .styles-module_DraggableComponent__m5-dA:not(.styles-module_isAssemblyBlock__Y3Avk):before,\n\n.styles-module_DraggableComponent__m5-dA:hover:before,\n.styles-module_DraggableComponent__m5-dA:hover .styles-module_DraggableComponent__m5-dA:before {\n outline: 2px dashed var(--exp-builder-gray500);\n}\n\n/* hovering component in layers tab */\n\n.styles-module_isHoveringComponent__RSeDG:not(.styles-module_isAssemblyBlock__Y3Avk):before,\n\n.styles-module_DraggableComponent__m5-dA:hover:not(:has(.styles-module_DraggableComponent__m5-dA:hover)):before {\n outline: 2px solid var(--exp-builder-gray500);\n}\n\n/* hovering related pattern in layers tab */\n\n.styles-module_isAssemblyBlock__Y3Avk:has(.styles-module_isHoveringComponent__RSeDG):before,\n.styles-module_isAssemblyBlock__Y3Avk:has(.styles-module_isHoveringComponent__RSeDG) .styles-module_isAssemblyBlock__Y3Avk:not(.styles-module_isHoveringComponent__RSeDG):before,\n.styles-module_isHoveringComponent__RSeDG .styles-module_isAssemblyBlock__Y3Avk:before,\n\n.styles-module_isAssemblyBlock__Y3Avk:hover:before,\n.styles-module_isAssemblyBlock__Y3Avk:hover .styles-module_DraggableComponent__m5-dA:before,\n.styles-module_DraggableComponent__m5-dA:hover .styles-module_isAssemblyBlock__Y3Avk:before {\n outline: 2px dashed var(--exp-builder-purple600);\n}\n\n/* hovering pattern in layers tab */\n\n.styles-module_isAssemblyBlock__Y3Avk.styles-module_isHoveringComponent__RSeDG:before,\n\n.styles-module_isAssemblyBlock__Y3Avk:hover:not(:has(.styles-module_DraggableComponent__m5-dA:hover)):before {\n outline: 2px solid var(--exp-builder-purple600);\n}\n";
1720
+ var styles$3 = {"DraggableComponent":"styles-module_DraggableComponent__m5-dA","DraggableClone":"styles-module_DraggableClone__X8zTA","userIsDragging":"styles-module_userIsDragging__lqbjG","isDragging":"styles-module_isDragging__WHjPU","isSelected":"styles-module_isSelected__BzICQ","overlay":"styles-module_overlay__r4th9","overlayContainer":"styles-module_overlayContainer__eiX-5","overlayAssembly":"styles-module_overlayAssembly__tOzZU","isHoveringComponent":"styles-module_isHoveringComponent__RSeDG","isAssemblyBlock":"styles-module_isAssemblyBlock__Y3Avk"};
1721
1721
  styleInject(css_248z$8);
1722
1722
 
1723
1723
  const SCROLL_STATES = {
@@ -1947,6 +1947,7 @@ const Tooltip = ({ coordinates, id, label, isAssemblyBlock, isContainer }) => {
1947
1947
 
1948
1948
  const useDraggedItemStore = create((set) => ({
1949
1949
  draggedItem: undefined,
1950
+ hoveredComponentId: undefined,
1950
1951
  domRect: undefined,
1951
1952
  componentId: '',
1952
1953
  isDraggingOnCanvas: false,
@@ -1957,6 +1958,9 @@ const useDraggedItemStore = create((set) => ({
1957
1958
  setComponentId(id) {
1958
1959
  set({ componentId: id });
1959
1960
  },
1961
+ setHoveredComponentId(id) {
1962
+ set({ hoveredComponentId: id });
1963
+ },
1960
1964
  updateItem: (item) => {
1961
1965
  set({ draggedItem: item });
1962
1966
  },
@@ -2207,6 +2211,7 @@ function getStyle$2(style, snapshot) {
2207
2211
  const DraggableComponent = ({ children, id, index, isAssemblyBlock = false, isSelected = false, onClick = () => null, coordinates, userIsDragging, style, wrapperProps, isContainer, blockId, isDragDisabled = false, placeholder, definition, ...rest }) => {
2208
2212
  const ref = useRef(null);
2209
2213
  const setDomRect = useDraggedItemStore((state) => state.setDomRect);
2214
+ const isHoveredComponent = useDraggedItemStore((state) => state.hoveredComponentId === id);
2210
2215
  useDraggablePosition({
2211
2216
  draggableId: id,
2212
2217
  draggableRef: ref,
@@ -2220,6 +2225,7 @@ const DraggableComponent = ({ children, id, index, isAssemblyBlock = false, isSe
2220
2225
  [styles$3.isDragging]: snapshot.isDragging,
2221
2226
  [styles$3.isSelected]: isSelected,
2222
2227
  [styles$3.userIsDragging]: userIsDragging,
2228
+ [styles$3.isHoveringComponent]: isHoveredComponent,
2223
2229
  }), style: {
2224
2230
  ...style,
2225
2231
  ...getStyle$2(provided.draggableProps.style, snapshot),
@@ -2859,6 +2865,7 @@ const useComponent = ({ node: rawNode, resolveDesignValue, renderDropzone, userI
2859
2865
  */
2860
2866
  const DraggableChildComponent = (props) => {
2861
2867
  const { elementToRender, id, index, isAssemblyBlock = false, isSelected = false, onClick = () => null, coordinates, userIsDragging, style, isContainer, blockId, isDragDisabled = false, wrapperProps, definition, } = props;
2868
+ const isHoveredComponent = useDraggedItemStore((state) => state.hoveredComponentId === id);
2862
2869
  return (React.createElement(Draggable, { key: id, draggableId: id, index: index, isDragDisabled: isDragDisabled }, (provided, snapshot) => elementToRender({
2863
2870
  ['data-ctfl-draggable-id']: id,
2864
2871
  ['data-test-id']: `draggable-${blockId}`,
@@ -2870,6 +2877,7 @@ const DraggableChildComponent = (props) => {
2870
2877
  [styles$3.isDragging]: snapshot.isDragging,
2871
2878
  [styles$3.isSelected]: isSelected,
2872
2879
  [styles$3.userIsDragging]: userIsDragging,
2880
+ [styles$3.isHoveringComponent]: isHoveredComponent,
2873
2881
  }),
2874
2882
  dragHandleProps: provided.dragHandleProps,
2875
2883
  style: {
@@ -3428,10 +3436,10 @@ const EditorBlock = ({ node: rawNode, resolveDesignValue, renderDropzone, index,
3428
3436
  };
3429
3437
  if (node.data.blockId === CONTENTFUL_COMPONENTS.singleColumn.id) {
3430
3438
  return (React.createElement(React.Fragment, null,
3431
- React.createElement(DraggableChildComponent, { elementToRender: elementToRender, id: componentId, index: index, isAssemblyBlock: isAssemblyBlock, isDragDisabled: isSingleColumn, isSelected: selectedNodeId === componentId, userIsDragging: userIsDragging, isContainer: isContainer, blockId: node.data.blockId, coordinates: coordinates, wrapperProps: wrapperProps, onClick: onClick, definition: definition }),
3439
+ React.createElement(DraggableChildComponent, { elementToRender: elementToRender, id: componentId, index: index, isAssemblyBlock: isAssembly || isAssemblyBlock, isDragDisabled: isSingleColumn, isSelected: selectedNodeId === componentId, userIsDragging: userIsDragging, isContainer: isContainer, blockId: node.data.blockId, coordinates: coordinates, wrapperProps: wrapperProps, onClick: onClick, definition: definition }),
3432
3440
  isStructureComponent && !isSingleColumn && userIsDragging && (React.createElement(Hitboxes, { parentZoneId: zoneId, zoneId: componentId, isEmptyZone: isEmptyZone }))));
3433
3441
  }
3434
- return (React.createElement(DraggableComponent, { placeholder: placeholder, definition: definition, id: componentId, index: index, isAssemblyBlock: isAssemblyBlock, isDragDisabled: isAssemblyBlock, isSelected: selectedNodeId === componentId, userIsDragging: userIsDragging, isContainer: isContainer, blockId: node.data.blockId, coordinates: coordinates, wrapperProps: wrapperProps, onClick: onClick },
3442
+ return (React.createElement(DraggableComponent, { placeholder: placeholder, definition: definition, id: componentId, index: index, isAssemblyBlock: isAssembly || isAssemblyBlock, isDragDisabled: isAssemblyBlock, isSelected: selectedNodeId === componentId, userIsDragging: userIsDragging, isContainer: isContainer, blockId: node.data.blockId, coordinates: coordinates, wrapperProps: wrapperProps, onClick: onClick },
3435
3443
  elementToRender(),
3436
3444
  isStructureComponent && !isSingleColumn && userIsDragging && (React.createElement(Hitboxes, { parentZoneId: zoneId, zoneId: componentId, isEmptyZone: isEmptyZone }))));
3437
3445
  };
@@ -3530,8 +3538,8 @@ function DropzoneClone({ node, zoneId, resolveDesignValue, className, WrapperCom
3530
3538
  function Dropzone({ node, zoneId, resolveDesignValue, className, WrapperComponent = 'div', ...rest }) {
3531
3539
  const userIsDragging = useDraggedItemStore((state) => state.isDraggingOnCanvas);
3532
3540
  const draggedItem = useDraggedItemStore((state) => state.draggedItem);
3533
- const newComponentId = useDraggedItemStore((state) => state.componentId);
3534
- const hoveringZone = useZoneStore((state) => state.hoveringZone);
3541
+ const isDraggingNewComponent = useDraggedItemStore((state) => Boolean(state.componentId));
3542
+ const isHoveringZone = useZoneStore((state) => state.hoveringZone === zoneId);
3535
3543
  const tree = useTreeStore((state) => state.tree);
3536
3544
  const content = node?.children || tree.root?.children || [];
3537
3545
  const direction = useDropzoneDirection({ resolveDesignValue, node, zoneId });
@@ -3541,8 +3549,6 @@ function Dropzone({ node, zoneId, resolveDesignValue, className, WrapperComponen
3541
3549
  return;
3542
3550
  return getItem({ id: draggedItem.draggableId }, tree)?.data.blockId;
3543
3551
  }, [draggedItem, tree]);
3544
- const isDraggingNewComponent = !!newComponentId;
3545
- const isHoveringZone = hoveringZone === zoneId;
3546
3552
  const isRootZone = zoneId === ROOT_ID;
3547
3553
  const isDestination = draggedDestinationId === zoneId;
3548
3554
  const isEmptyCanvas = isRootZone && !content.length;
@@ -3682,173 +3688,6 @@ const useBreakpoints = (breakpoints) => {
3682
3688
  return { resolveDesignValue };
3683
3689
  };
3684
3690
 
3685
- class MouseOverHandler {
3686
- constructor() {
3687
- this.currentHoveredElementId = null;
3688
- this.getMargins = (element) => {
3689
- if (typeof window === 'undefined')
3690
- return undefined;
3691
- const styles = window.getComputedStyle(element);
3692
- const top = parseInt(styles.marginTop);
3693
- const bottom = parseInt(styles.marginBottom);
3694
- const left = parseInt(styles.marginLeft);
3695
- const right = parseInt(styles.marginRight);
3696
- return { top, bottom, left, right };
3697
- };
3698
- this.getFullCoordinates = (element) => {
3699
- const validChildren = Array.from(element.children).filter((child) => child instanceof HTMLElement && child.dataset.cfNodeBlockType === 'block');
3700
- const { left, top, width, height } = this.getBoundingClientRect(element);
3701
- const margins = this.getMargins(element);
3702
- const childrenCoordinates = validChildren.map((child) => {
3703
- const { left, top, width, height } = this.getBoundingClientRect(child);
3704
- return { left, top, width, height, margins };
3705
- });
3706
- return {
3707
- left,
3708
- top,
3709
- width,
3710
- height,
3711
- margins,
3712
- childrenCoordinates,
3713
- };
3714
- };
3715
- this.getClosestComponentInformation = (element) => {
3716
- let target = element;
3717
- // If the target is outside on the root or anywhere else on the iframes body
3718
- if (target?.id === 'VisualEditorRoot' || target?.tagName === 'BODY') {
3719
- const rootElement = document.getElementById('VisualEditorRoot');
3720
- const hoveredRootElement = {
3721
- nodeId: 'root',
3722
- blockType: 'root',
3723
- blockId: 'root',
3724
- };
3725
- return [rootElement, hoveredRootElement];
3726
- }
3727
- // Find the closest contentful container or direct parent that is a contentful container
3728
- while (target) {
3729
- if (
3730
- // is itself a section?
3731
- target.dataset.cfNodeId ||
3732
- // Or a direct child of a section
3733
- (target.parentElement && target.parentElement.dataset.cfNodeBlockId === 'ContentfulSection')) {
3734
- const sectionId = target.dataset.cfNodeId;
3735
- const sectionBlockId = target.dataset.cfNodeBlockId;
3736
- const sectionBlockType = target.dataset.cfNodeBlockType;
3737
- const hoveredElement = {
3738
- nodeId: sectionId,
3739
- blockId: sectionBlockId,
3740
- blockType: sectionBlockType,
3741
- };
3742
- return [target, hoveredElement];
3743
- }
3744
- target = target.parentElement;
3745
- }
3746
- };
3747
- this.getNewlyHoveredElement = (element) => {
3748
- let parentElement = null;
3749
- let parentSectionIndex = -1;
3750
- const [hoveredElement, hoveredInfo] = this.getClosestComponentInformation(element) || [
3751
- null,
3752
- null,
3753
- ];
3754
- if (!hoveredElement)
3755
- return;
3756
- // if hovered element is already hovered and the information is already sent
3757
- // ignore the rest and don't proceed.
3758
- if (hoveredInfo.nodeId === this.currentHoveredElementId)
3759
- return;
3760
- let parentHTMLElement = hoveredElement?.parentElement || null;
3761
- while (parentHTMLElement) {
3762
- const parentIsRoot = parentHTMLElement.id === 'VisualEditorRoot';
3763
- if (parentHTMLElement.dataset.cfNodeId || parentIsRoot) {
3764
- parentElement = {
3765
- nodeId: parentIsRoot ? 'root' : parentHTMLElement.dataset.cfNodeId,
3766
- blockType: parentHTMLElement.dataset.cfNodeBlockType,
3767
- blockId: parentHTMLElement.dataset.cfNodeBlockId,
3768
- };
3769
- const parentChildrenElements = parentHTMLElement.children;
3770
- parentSectionIndex = Array.from(parentChildrenElements).findIndex((child) => child === hoveredElement);
3771
- break;
3772
- }
3773
- parentHTMLElement = parentHTMLElement.parentElement;
3774
- }
3775
- const coordinates = this.getFullCoordinates(hoveredElement);
3776
- return { coordinates, hoveredElement: hoveredInfo, parentElement, parentSectionIndex };
3777
- };
3778
- this.handleMouseMove = (target) => {
3779
- const hoveredElementInfo = this.getNewlyHoveredElement(target);
3780
- if (!hoveredElementInfo) {
3781
- return;
3782
- }
3783
- const { coordinates, hoveredElement, parentElement, parentSectionIndex } = hoveredElementInfo;
3784
- this.currentHoveredElementId = hoveredElementInfo.hoveredElement.nodeId || null;
3785
- sendMessage(OUTGOING_EVENTS.NewHoveredElement, {
3786
- hoveredElement,
3787
- parentElement,
3788
- parentSectionIndex,
3789
- coordinates,
3790
- });
3791
- };
3792
- this.onMouseMove = (event) => {
3793
- const target = event.target;
3794
- this.handleMouseMove(target);
3795
- };
3796
- this.onMouseLeave = () => {
3797
- this.currentHoveredElementId = null;
3798
- };
3799
- }
3800
- getBoundingClientRect(element) {
3801
- const isAssembly = element.getAttribute('data-cf-node-block-type') === ASSEMBLY_NODE_TYPE;
3802
- if (!isAssembly) {
3803
- return element.getBoundingClientRect();
3804
- }
3805
- else {
3806
- // As we use `display: contents` for assemblies, there is no real "block"
3807
- // in the DOM and thus the browser fails to calculate the bounding rect.
3808
- // Instead, we calculate it for each child and add it up:
3809
- if (!element.firstElementChild) {
3810
- return { left: 0, top: 0, width: 0, height: 0 };
3811
- }
3812
- const firstChildRect = element.firstElementChild.getBoundingClientRect();
3813
- let fullHeight = firstChildRect.height;
3814
- let nextChild = element.firstElementChild.nextElementSibling;
3815
- while (nextChild) {
3816
- const nextChildRect = nextChild.getBoundingClientRect();
3817
- fullHeight += nextChildRect.height;
3818
- nextChild = nextChild.nextElementSibling;
3819
- }
3820
- // The root of a assembly positions its first level containers vertically.
3821
- // So we just need to add up the height and use the remaining properties from the first child.
3822
- return {
3823
- left: firstChildRect.left,
3824
- top: firstChildRect.top,
3825
- width: firstChildRect.width,
3826
- height: fullHeight,
3827
- };
3828
- }
3829
- }
3830
- attachEvent() {
3831
- document.addEventListener('mousemove', this.onMouseMove);
3832
- document.addEventListener('mouseout', this.onMouseLeave);
3833
- }
3834
- detachEvent() {
3835
- document.removeEventListener('mousemove', this.onMouseMove);
3836
- document.removeEventListener('mouseout', this.onMouseLeave);
3837
- }
3838
- }
3839
-
3840
- /**
3841
- * This function gets the element co-ordinates of a specified component in the DOM and its parent
3842
- * and sends the DOM Rect to the client app
3843
- */
3844
- const sendHoveredComponentCoordinates = (instanceId) => {
3845
- const selectedElement = instanceId
3846
- ? document.querySelector(`[data-cf-node-id="${instanceId}"]`)
3847
- : undefined;
3848
- const mouseOverHandler = new MouseOverHandler();
3849
- mouseOverHandler.handleMouseMove(selectedElement || null);
3850
- };
3851
-
3852
3691
  class DragState {
3853
3692
  constructor() {
3854
3693
  this.isDragStartedOnParent = false;
@@ -3935,6 +3774,7 @@ function useEditorSubscriber() {
3935
3774
  const selectedNodeId = useEditorStore((state) => state.selectedNodeId);
3936
3775
  const resetEntityStore = useEntityStore((state) => state.resetEntityStore);
3937
3776
  const setComponentId = useDraggedItemStore((state) => state.setComponentId);
3777
+ const setHoveredComponentId = useDraggedItemStore((state) => state.setHoveredComponentId);
3938
3778
  const setDraggingOnCanvas = useDraggedItemStore((state) => state.setDraggingOnCanvas);
3939
3779
  const setMousePosition = useDraggedItemStore((state) => state.setMousePosition);
3940
3780
  const setScrollY = useDraggedItemStore((state) => state.setScrollY);
@@ -4128,7 +3968,7 @@ function useEditorSubscriber() {
4128
3968
  }
4129
3969
  case INCOMING_EVENTS.HoverComponent: {
4130
3970
  const { hoveredNodeId } = payload;
4131
- sendHoveredComponentCoordinates(hoveredNodeId);
3971
+ setHoveredComponentId(hoveredNodeId);
4132
3972
  break;
4133
3973
  }
4134
3974
  case INCOMING_EVENTS.ComponentDraggingChanged: {
@@ -4224,6 +4064,7 @@ function useEditorSubscriber() {
4224
4064
  updateNodesByUpdatedEntity,
4225
4065
  setMousePosition,
4226
4066
  resetEntityStore,
4067
+ setHoveredComponentId,
4227
4068
  ]);
4228
4069
  /*
4229
4070
  * Handles on scroll business
@@ -4494,12 +4335,17 @@ const RootRenderer = ({ onChange }) => {
4494
4335
  useEditorSubscriber();
4495
4336
  const dragItem = useDraggedItemStore((state) => state.componentId);
4496
4337
  const userIsDragging = useDraggedItemStore((state) => state.isDraggingOnCanvas);
4338
+ const setHoveredComponentId = useDraggedItemStore((state) => state.setHoveredComponentId);
4497
4339
  const breakpoints = useTreeStore((state) => state.breakpoints);
4498
4340
  const setSelectedNodeId = useEditorStore((state) => state.setSelectedNodeId);
4499
4341
  const containerRef = useRef(null);
4500
4342
  const { resolveDesignValue } = useBreakpoints(breakpoints);
4501
4343
  const [containerStyles, setContainerStyles] = useState({});
4502
4344
  const tree = useTreeStore((state) => state.tree);
4345
+ const handleMouseOver = useCallback(() => {
4346
+ // Remove hover state set by UI when mouse is over canvas
4347
+ setHoveredComponentId();
4348
+ }, [setHoveredComponentId]);
4503
4349
  const handleClickOutside = useCallback((e) => {
4504
4350
  const element = e.target;
4505
4351
  const isRoot = element.getAttribute('data-ctfl-zone-id') === ROOT_ID;
@@ -4548,6 +4394,12 @@ const RootRenderer = ({ onChange }) => {
4548
4394
  if (onChange)
4549
4395
  onChange(tree);
4550
4396
  }, [tree, onChange]);
4397
+ useEffect(() => {
4398
+ window.addEventListener('mouseover', handleMouseOver);
4399
+ return () => {
4400
+ window.removeEventListener('mouseover', handleMouseOver);
4401
+ };
4402
+ }, [handleMouseOver]);
4551
4403
  useEffect(() => {
4552
4404
  document.addEventListener('click', handleClickOutside);
4553
4405
  return () => {