@contentful/experiences-visual-editor-react 0.0.1-alpha.5 → 0.0.1-alpha.7

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
@@ -1442,8 +1442,8 @@ function gatherDeepReferencesFromTree(startingNode, dataSource) {
1442
1442
  return deepReferences;
1443
1443
  }
1444
1444
 
1445
- var css_248z$6 = ".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}\n\n.styles-module_DraggableClone__X8zTA:before {\n outline: 2px solid var(--exp-builder-blue500);\n}\n\n.styles-module_DraggableComponent__m5-dA > * {\n pointer-events: none;\n}\n\n.styles-module_isDragging__WHjPU {\n overflow: hidden;\n}\n\n.styles-module_isDragging__WHjPU * {\n pointer-events: none !important;\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";
1446
- var styles$3 = {"DraggableComponent":"styles-module_DraggableComponent__m5-dA","DraggableClone":"styles-module_DraggableClone__X8zTA","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","userIsDragging":"styles-module_userIsDragging__lqbjG","isAssemblyBlock":"styles-module_isAssemblyBlock__Y3Avk"};
1445
+ var css_248z$6 = ".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";
1446
+ 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"};
1447
1447
  styleInject(css_248z$6);
1448
1448
 
1449
1449
  const SCROLL_STATES = {
@@ -1703,7 +1703,7 @@ const NEW_COMPONENT_ID = 'ctfl-new-draggable';
1703
1703
  const CTFL_ZONE_ID = 'data-ctfl-zone-id';
1704
1704
  const CTFL_DRAGGING_ELEMENT = 'data-ctfl-dragging-element';
1705
1705
  const HITBOX = {
1706
- WIDTH: 80,
1706
+ WIDTH: 70,
1707
1707
  HEIGHT: 20,
1708
1708
  INITIAL_OFFSET: 10,
1709
1709
  OFFSET_INCREMENT: 8,
@@ -1741,6 +1741,41 @@ var DraggablePosition;
1741
1741
  DraggablePosition[DraggablePosition["MOUSE_POSITION"] = 1] = "MOUSE_POSITION";
1742
1742
  })(DraggablePosition || (DraggablePosition = {}));
1743
1743
 
1744
+ const calcOffsetLeft = (parentElement, placeholderWidth, nodeWidth) => {
1745
+ if (!parentElement) {
1746
+ return 0;
1747
+ }
1748
+ const alignItems = window.getComputedStyle(parentElement).alignItems;
1749
+ if (alignItems === 'center') {
1750
+ return -(placeholderWidth - nodeWidth) / 2;
1751
+ }
1752
+ if (alignItems === 'end') {
1753
+ return -placeholderWidth + nodeWidth + 2;
1754
+ }
1755
+ return 0;
1756
+ };
1757
+ const calcOffsetTop = (parentElement, placeholderHeight, nodeHeight) => {
1758
+ if (!parentElement) {
1759
+ return 0;
1760
+ }
1761
+ const alignItems = window.getComputedStyle(parentElement).alignItems;
1762
+ if (alignItems === 'center') {
1763
+ return -(placeholderHeight - nodeHeight) / 2;
1764
+ }
1765
+ if (alignItems === 'end') {
1766
+ return -placeholderHeight + nodeHeight + 2;
1767
+ }
1768
+ return 0;
1769
+ };
1770
+ const getPaddingOffset = (element) => {
1771
+ const paddingLeft = parseFloat(window.getComputedStyle(element).paddingLeft);
1772
+ const paddingRight = parseFloat(window.getComputedStyle(element).paddingRight);
1773
+ const paddingTop = parseFloat(window.getComputedStyle(element).paddingTop);
1774
+ const paddingBottom = parseFloat(window.getComputedStyle(element).paddingBottom);
1775
+ const horizontalOffset = paddingLeft + paddingRight;
1776
+ const verticalOffset = paddingTop + paddingBottom;
1777
+ return [horizontalOffset, verticalOffset];
1778
+ };
1744
1779
  /**
1745
1780
  * Calculate the size and position of the dropzone indicator
1746
1781
  * when dragging a new component onto the canvas
@@ -1758,10 +1793,15 @@ const calcNewComponentStyles = (params) => {
1758
1793
  }
1759
1794
  const elementSizes = element.getBoundingClientRect();
1760
1795
  const dropzoneSizes = dropzone.getBoundingClientRect();
1761
- const width = isHorizontal ? DRAGGABLE_WIDTH : dropzoneSizes.width;
1762
- const height = isHorizontal ? dropzoneSizes.height : DRAGGABLE_HEIGHT;
1763
- const top = isHorizontal ? -(height - elementSizes.height) / 2 : -height;
1764
- const left = isHorizontal ? -width : -(width - elementSizes.width) / 2;
1796
+ const [horizontalPadding, verticalPadding] = getPaddingOffset(dropzone);
1797
+ const width = isHorizontal ? DRAGGABLE_WIDTH : dropzoneSizes.width - horizontalPadding;
1798
+ const height = isHorizontal ? dropzoneSizes.height - verticalPadding : DRAGGABLE_HEIGHT;
1799
+ const top = isHorizontal
1800
+ ? calcOffsetTop(element.parentElement, height, elementSizes.height)
1801
+ : -height;
1802
+ const left = isHorizontal
1803
+ ? -width
1804
+ : calcOffsetLeft(element.parentElement, width, elementSizes.width);
1765
1805
  return {
1766
1806
  width,
1767
1807
  height,
@@ -1792,10 +1832,15 @@ const calcMovementStyles = (params) => {
1792
1832
  const elementSizes = element.getBoundingClientRect();
1793
1833
  const dropzoneSizes = dropzone.getBoundingClientRect();
1794
1834
  const draggableSizes = draggable.getBoundingClientRect();
1795
- const width = isHorizontal ? draggableSizes.width : dropzoneSizes.width;
1796
- const height = isHorizontal ? dropzoneSizes.height : draggableSizes.height;
1797
- const top = isHorizontal ? -(height - elementSizes.height) / 2 : -height;
1798
- const left = isHorizontal ? -width : -(width - elementSizes.width) / 2;
1835
+ const [horizontalPadding, verticalPadding] = getPaddingOffset(dropzone);
1836
+ const width = isHorizontal ? draggableSizes.width : dropzoneSizes.width - horizontalPadding;
1837
+ const height = isHorizontal ? dropzoneSizes.height - verticalPadding : draggableSizes.height;
1838
+ const top = isHorizontal
1839
+ ? calcOffsetTop(element.parentElement, height, elementSizes.height)
1840
+ : -height;
1841
+ const left = isHorizontal
1842
+ ? -width
1843
+ : calcOffsetLeft(element.parentElement, width, elementSizes.width);
1799
1844
  return {
1800
1845
  width,
1801
1846
  height,
@@ -2075,10 +2120,12 @@ const useEntityStore = create((set) => ({
2075
2120
  },
2076
2121
  resetEntityStore(locale, entities = []) {
2077
2122
  console.debug(`[experiences-sdk-react] Resetting entity store because the locale changed to '${locale}'.`);
2123
+ const newEntityStore = new EditorModeEntityStore({ locale, entities });
2078
2124
  set({
2079
- entityStore: new EditorModeEntityStore({ locale, entities }),
2125
+ entityStore: newEntityStore,
2080
2126
  areEntitiesFetched: false,
2081
2127
  });
2128
+ return newEntityStore;
2082
2129
  },
2083
2130
  }));
2084
2131
 
@@ -2513,7 +2560,7 @@ const DraggableChildComponent = (props) => {
2513
2560
  })));
2514
2561
  };
2515
2562
 
2516
- var css_248z$2 = ".styles-module_container__te-1H {\n margin-left: auto;\n margin-right: auto;\n position: relative;\n height: 100%;\n width: 100%;\n background-color: transparent;\n transition: background-color 0.2s;\n pointer-events: all;\n}\n\n.styles-module_container__te-1H:not(.styles-module_isRoot__5cn-i):before {\n content: \"\";\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n outline-offset: -1px;\n outline: 2px solid transparent;\n z-index: 1;\n transition: outline 0.2s;\n}\n\n.styles-module_isRoot__5cn-i,\n.styles-module_isEmptyCanvas__0XHZR {\n flex: 1;\n}\n\n.styles-module_isEmptyZone__zVpnZ {\n min-height: 80px;\n}\n\n.styles-module_isDragging__Gm8v5:not(.styles-module_isRoot__5cn-i):before {\n outline: 2px dashed var(--exp-builder-gray300);\n}\n\n.styles-module_isDestination__5sCQx:not(.styles-module_isRoot__5cn-i):before {\n transition: outline 0.2s, background-color 0.2s;\n outline: 2px dashed var(--exp-builder-blue400);\n background-color: rgba(var(--exp-builder-blue100-rgb), 0.5);\n z-index: 2;\n}\n\n.styles-module_hitbox__YQ-1Z {\n position: fixed;\n pointer-events: all !important;\n}\n";
2563
+ var css_248z$2 = ".styles-module_container__te-1H {\n margin-left: auto;\n margin-right: auto;\n position: relative;\n height: 100%;\n width: 100%;\n background-color: transparent;\n transition: background-color 0.2s;\n pointer-events: all !important;\n}\n\n.styles-module_container__te-1H:not(.styles-module_isRoot__5cn-i):before {\n content: '';\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n outline-offset: -1px;\n outline: 2px solid transparent;\n z-index: 1;\n transition: outline 0.2s;\n pointer-events: none;\n}\n\n.styles-module_isRoot__5cn-i,\n.styles-module_isEmptyCanvas__0XHZR {\n flex: 1;\n}\n\n.styles-module_isEmptyZone__zVpnZ {\n min-height: 80px;\n}\n\n.styles-module_isDragging__Gm8v5:not(.styles-module_isRoot__5cn-i):before {\n outline: 2px dashed var(--exp-builder-gray300);\n}\n\n.styles-module_isDestination__5sCQx:not(.styles-module_isRoot__5cn-i):before {\n transition:\n outline 0.2s,\n background-color 0.2s;\n outline: 2px dashed var(--exp-builder-blue400);\n background-color: rgba(var(--exp-builder-blue100-rgb), 0.5);\n z-index: 2;\n}\n\n.styles-module_hitbox__YQ-1Z {\n position: fixed;\n pointer-events: all !important;\n}\n";
2517
2564
  var styles$2 = {"container":"styles-module_container__te-1H","isRoot":"styles-module_isRoot__5cn-i","isEmptyCanvas":"styles-module_isEmptyCanvas__0XHZR","isEmptyZone":"styles-module_isEmptyZone__zVpnZ","isDragging":"styles-module_isDragging__Gm8v5","isDestination":"styles-module_isDestination__5sCQx","hitbox":"styles-module_hitbox__YQ-1Z"};
2518
2565
  styleInject(css_248z$2);
2519
2566
 
@@ -3057,11 +3104,11 @@ const EditorBlock = ({ node: rawNode, resolveDesignValue, renderDropzone, draggi
3057
3104
  if (node.data.blockId === CONTENTFUL_COMPONENTS.singleColumn.id) {
3058
3105
  return (React.createElement(React.Fragment, null,
3059
3106
  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 }),
3060
- isStructureComponent && userIsDragging && (React.createElement(Hitboxes, { parentZoneId: zoneId, zoneId: componentId, enableRootHitboxes: enableRootHitboxes }))));
3107
+ isStructureComponent && !isSingleColumn && userIsDragging && (React.createElement(Hitboxes, { parentZoneId: zoneId, zoneId: componentId, enableRootHitboxes: enableRootHitboxes }))));
3061
3108
  }
3062
3109
  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 },
3063
3110
  elementToRender(),
3064
- isStructureComponent && userIsDragging && (React.createElement(Hitboxes, { parentZoneId: zoneId, zoneId: componentId, enableRootHitboxes: enableRootHitboxes }))));
3111
+ isStructureComponent && !isSingleColumn && userIsDragging && (React.createElement(Hitboxes, { parentZoneId: zoneId, zoneId: componentId, enableRootHitboxes: enableRootHitboxes }))));
3065
3112
  };
3066
3113
 
3067
3114
  var css_248z$1 = ".EmptyContainer-module_container__XPH5b {\n height: 200px;\n display: flex;\n width: 100%;\n position: absolute;\n align-items: center;\n justify-content: center;\n flex-direction: row;\n transition: all 0.2s;\n color: var(--exp-builder-gray400);\n font-size: var(--exp-builder-font-size-l);\n font-family: var(--exp-builder-font-stack-primary);\n outline: 2px dashed var(--exp-builder-gray400);\n outline-offset: -2px;\n}\n\n.EmptyContainer-module_highlight__lcICy:hover {\n outline: 2px dashed var(--exp-builder-blue500);\n background-color: rgba(var(--exp-builder-blue100-rgb), 0.5);\n cursor: grabbing;\n}\n\n.EmptyContainer-module_icon__82-2O rect {\n fill: var(--exp-builder-gray400);\n}\n\n.EmptyContainer-module_label__4TxRa {\n margin-left: var(--exp-builder-spacing-s);\n}\n";
@@ -3588,6 +3635,7 @@ function useEditorSubscriber() {
3588
3635
  const setDataSource = useEditorStore((state) => state.setDataSource);
3589
3636
  const setSelectedNodeId = useEditorStore((state) => state.setSelectedNodeId);
3590
3637
  const selectedNodeId = useEditorStore((state) => state.selectedNodeId);
3638
+ const resetEntityStore = useEntityStore((state) => state.resetEntityStore);
3591
3639
  const setComponentId = useDraggedItemStore((state) => state.setComponentId);
3592
3640
  const setDraggingOnCanvas = useDraggedItemStore((state) => state.setDraggingOnCanvas);
3593
3641
  const setMousePosition = useDraggedItemStore((state) => state.setMousePosition);
@@ -3609,7 +3657,7 @@ function useEditorSubscriber() {
3609
3657
  * Fills up entityStore with entities from newDataSource and from the tree.
3610
3658
  * Also manages "entity status" variables (areEntitiesFetched, isFetchingEntities)
3611
3659
  */
3612
- const fetchMissingEntities = useCallback(async (newDataSource, tree) => {
3660
+ const fetchMissingEntities = useCallback(async (entityStore, newDataSource, tree) => {
3613
3661
  // if we realize that there's nothing missing and nothing to fill-fetch before we do any async call,
3614
3662
  // then we can simply return and not lock the EntityStore at all.
3615
3663
  const startFetching = () => {
@@ -3680,10 +3728,7 @@ function useEditorSubscriber() {
3680
3728
  finally {
3681
3729
  endFetching();
3682
3730
  }
3683
- }, [
3684
- /* dataSource, */ entityStore,
3685
- setEntitiesFetched /* setFetchingEntities, assembliesRegistry */,
3686
- ]);
3731
+ }, [setEntitiesFetched /* setFetchingEntities, assembliesRegistry */]);
3687
3732
  useEffect(() => {
3688
3733
  const onMessage = async (event) => {
3689
3734
  let reason;
@@ -3713,6 +3758,11 @@ function useEditorSubscriber() {
3713
3758
  // If the assemblyEntry is not yet fetched, this will be done below by
3714
3759
  // the imperative calls to fetchMissingEntities.
3715
3760
  }
3761
+ let newEntityStore = entityStore;
3762
+ if (entityStore.locale !== locale) {
3763
+ newEntityStore = resetEntityStore(locale);
3764
+ setLocale(locale);
3765
+ }
3716
3766
  // Below are mutually exclusive cases
3717
3767
  if (changedNode) {
3718
3768
  /**
@@ -3725,7 +3775,7 @@ function useEditorSubscriber() {
3725
3775
  if (changedValueType === 'BoundValue') {
3726
3776
  const newDataSource = { ...dataSource, ...changedNode.data.dataSource };
3727
3777
  setDataSource(newDataSource);
3728
- await fetchMissingEntities(newDataSource, tree);
3778
+ await fetchMissingEntities(newEntityStore, newDataSource, tree);
3729
3779
  }
3730
3780
  else if (changedValueType === 'UnboundValue') {
3731
3781
  setUnboundValues({
@@ -3733,19 +3783,15 @@ function useEditorSubscriber() {
3733
3783
  ...changedNode.data.unboundValues,
3734
3784
  });
3735
3785
  }
3736
- // Update the tree when all necessary data is fetched and ready for rendering.
3737
- updateTree(tree);
3738
- setLocale(locale);
3739
3786
  }
3740
3787
  else {
3741
3788
  const { dataSource, unboundValues } = getDataFromTree(tree);
3742
3789
  setDataSource(dataSource);
3743
3790
  setUnboundValues(unboundValues);
3744
- await fetchMissingEntities(dataSource, tree);
3745
- // Update the tree when all necessary data is fetched and ready for rendering.
3746
- updateTree(tree);
3747
- setLocale(locale);
3791
+ await fetchMissingEntities(newEntityStore, dataSource, tree);
3748
3792
  }
3793
+ // Update the tree when all necessary data is fetched and ready for rendering.
3794
+ updateTree(tree);
3749
3795
  break;
3750
3796
  }
3751
3797
  case INCOMING_EVENTS.AssembliesRegistered: {
@@ -3879,6 +3925,7 @@ function useEditorSubscriber() {
3879
3925
  updateTree,
3880
3926
  updateNodesByUpdatedEntity,
3881
3927
  setMousePosition,
3928
+ resetEntityStore,
3882
3929
  ]);
3883
3930
  /*
3884
3931
  * Handles on scroll business
@@ -4145,23 +4192,14 @@ const RootRenderer = ({ onChange }) => {
4145
4192
  const dragItem = useDraggedItemStore((state) => state.componentId);
4146
4193
  const userIsDragging = useDraggedItemStore((state) => state.isDraggingOnCanvas);
4147
4194
  const breakpoints = useTreeStore((state) => state.breakpoints);
4195
+ const setSelectedNodeId = useEditorStore((state) => state.setSelectedNodeId);
4148
4196
  const draggableSourceId = useDraggedItemStore((state) => state.draggedItem?.source.droppableId);
4149
4197
  const draggingNewComponent = !!draggableSourceId?.startsWith(COMPONENT_LIST_ID);
4150
4198
  const containerRef = useRef(null);
4151
4199
  const { resolveDesignValue } = useBreakpoints(breakpoints);
4152
4200
  const [containerStyles, setContainerStyles] = useState({});
4153
4201
  const tree = useTreeStore((state) => state.tree);
4154
- useEffect(() => {
4155
- if (onChange)
4156
- onChange(tree);
4157
- }, [tree, onChange]);
4158
- useEffect(() => {
4159
- document.addEventListener('click', handleClickOutside);
4160
- return () => {
4161
- document.removeEventListener('click', handleClickOutside);
4162
- };
4163
- }, []);
4164
- const handleClickOutside = (e) => {
4202
+ const handleClickOutside = useCallback((e) => {
4165
4203
  const element = e.target;
4166
4204
  const isRoot = element.getAttribute('data-ctfl-zone-id') === ROOT_ID;
4167
4205
  const clickedOnCanvas = element.closest(`[data-ctfl-root]`);
@@ -4174,7 +4212,8 @@ const RootRenderer = ({ onChange }) => {
4174
4212
  sendMessage(OUTGOING_EVENTS.ComponentSelected, {
4175
4213
  selectedId: '',
4176
4214
  });
4177
- };
4215
+ setSelectedNodeId('');
4216
+ }, [setSelectedNodeId]);
4178
4217
  const handleResizeCanvas = useCallback(() => {
4179
4218
  const parentElement = containerRef.current?.parentElement;
4180
4219
  if (!parentElement) {
@@ -4204,6 +4243,16 @@ const RootRenderer = ({ onChange }) => {
4204
4243
  });
4205
4244
  // eslint-disable-next-line react-hooks/exhaustive-deps
4206
4245
  }, [containerRef.current]);
4246
+ useEffect(() => {
4247
+ if (onChange)
4248
+ onChange(tree);
4249
+ }, [tree, onChange]);
4250
+ useEffect(() => {
4251
+ document.addEventListener('click', handleClickOutside);
4252
+ return () => {
4253
+ document.removeEventListener('click', handleClickOutside);
4254
+ };
4255
+ }, [handleClickOutside]);
4207
4256
  useEffect(() => {
4208
4257
  handleResizeCanvas();
4209
4258
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -4255,37 +4304,15 @@ const useInitializeEditor = () => {
4255
4304
  return initialized;
4256
4305
  };
4257
4306
 
4258
- const findNearestDropzone = (element) => {
4259
- const zoneId = element.getAttribute(CTFL_ZONE_ID);
4260
- if (!element.parentElement) {
4261
- return null;
4262
- }
4263
- if (element.tagName === 'BODY') {
4264
- return null;
4265
- }
4266
- return zoneId ?? findNearestDropzone(element.parentElement);
4267
- };
4268
4307
  const VisualEditorRoot = () => {
4269
4308
  const initialized = useInitializeEditor();
4270
- const locale = useEditorStore((state) => state.locale);
4271
4309
  const setMousePosition = useDraggedItemStore((state) => state.setMousePosition);
4272
- const entityStore = useEntityStore((state) => state.entityStore);
4273
4310
  const setHoveringZone = useZoneStore((state) => state.setHoveringZone);
4274
- const resetEntityStore = useEntityStore((state) => state.resetEntityStore);
4275
- useEffect(() => {
4276
- if (!locale) {
4277
- return;
4278
- }
4279
- if (entityStore.locale === locale) {
4280
- return;
4281
- }
4282
- resetEntityStore(locale);
4283
- }, [locale, resetEntityStore, entityStore.locale]);
4284
4311
  useEffect(() => {
4285
4312
  const onMouseMove = (e) => {
4286
4313
  setMousePosition(e.clientX, e.clientY);
4287
4314
  const target = e.target;
4288
- const zoneId = findNearestDropzone(target);
4315
+ const zoneId = target.closest(`[${CTFL_ZONE_ID}]`)?.getAttribute(CTFL_ZONE_ID);
4289
4316
  if (zoneId) {
4290
4317
  setHoveringZone(zoneId);
4291
4318
  }