@contentful/experiences-visual-editor-react 0.0.1-alpha.2 → 0.0.1-alpha.3

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
@@ -11,7 +11,7 @@ import { produce } from 'immer';
11
11
  import { createPortal } from 'react-dom';
12
12
  import { v4 } from 'uuid';
13
13
 
14
- var css_248z$7 = "html,\nbody {\n margin: 0;\n padding: 0;\n}\n\n\n/*\n * All of these variables are tokens from Forma-36 and should not be adjusted as these\n * are global variables that may affect multiple places.\n * As our customers may use other design libraries, we try to avoid overlapping global\n * variables by always using the prefix `--exp-builder-` inside this SDK.\n */\n\n\n:root {\n /* Color tokens from Forma 36: https://f36.contentful.com/tokens/color-system */\n --exp-builder-blue100: #e8f5ff;\n --exp-builder-blue200: #ceecff;\n --exp-builder-blue300: #98cbff;\n --exp-builder-blue400: #40a0ff;\n --exp-builder-blue500: #036fe3;\n --exp-builder-blue600: #0059c8;\n --exp-builder-blue700: #0041ab;\n --exp-builder-blue800: #003298;\n --exp-builder-blue900: #002a8e;\n --exp-builder-gray100: #f7f9fa;\n --exp-builder-gray200: #e7ebee;\n --exp-builder-gray300: #cfd9e0;\n --exp-builder-gray400: #aec1cc;\n --exp-builder-gray500: #67728a;\n --exp-builder-gray600: #5a657c;\n --exp-builder-gray700: #414d63;\n --exp-builder-gray800: #1b273a;\n --exp-builder-gray900: #111b2b;\n --exp-builder-purple600: #6c3ecf;\n --exp-builder-red200: #ffe0e0;\n --exp-builder-red800: #7f0010;\n --exp-builder-color-white: #ffffff;\n --exp-builder-glow-primary: 0px 0px 0px 3px #e8f5ff;\n\n /* RGB colors for applying opacity */\n --exp-builder-blue100-rgb: 232, 245, 255;\n --exp-builder-blue300-rgb: 152, 203, 255;\n\n /* Spacing tokens from Forma 36: https://f36.contentful.com/tokens/spacing */\n --exp-builder-spacing-s: 0.75rem;\n --exp-builder-spacing-2xs: 0.25rem;\n\n /* Typography tokens from Forma 36: https://f36.contentful.com/tokens/typography */\n --exp-builder-font-size-l: 1rem;\n --exp-builder-font-size-m: 0.875rem;\n --exp-builder-font-stack-primary: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial,\n sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;\n --exp-builder-line-height-condensed: 1.25;\n}\n";
14
+ var css_248z$7 = "html,\nbody {\n margin: 0;\n padding: 0;\n}\n\n/*\n * All of these variables are tokens from Forma-36 and should not be adjusted as these\n * are global variables that may affect multiple places.\n * As our customers may use other design libraries, we try to avoid overlapping global\n * variables by always using the prefix `--exp-builder-` inside this SDK.\n */\n\n:root {\n /* Color tokens from Forma 36: https://f36.contentful.com/tokens/color-system */\n --exp-builder-blue100: #e8f5ff;\n --exp-builder-blue200: #ceecff;\n --exp-builder-blue300: #98cbff;\n --exp-builder-blue400: #40a0ff;\n --exp-builder-blue500: #036fe3;\n --exp-builder-blue600: #0059c8;\n --exp-builder-blue700: #0041ab;\n --exp-builder-blue800: #003298;\n --exp-builder-blue900: #002a8e;\n --exp-builder-gray100: #f7f9fa;\n --exp-builder-gray200: #e7ebee;\n --exp-builder-gray300: #cfd9e0;\n --exp-builder-gray400: #aec1cc;\n --exp-builder-gray500: #67728a;\n --exp-builder-gray600: #5a657c;\n --exp-builder-gray700: #414d63;\n --exp-builder-gray800: #1b273a;\n --exp-builder-gray900: #111b2b;\n --exp-builder-purple600: #6c3ecf;\n --exp-builder-red200: #ffe0e0;\n --exp-builder-red800: #7f0010;\n --exp-builder-color-white: #ffffff;\n --exp-builder-glow-primary: 0px 0px 0px 3px #e8f5ff;\n\n /* RGB colors for applying opacity */\n --exp-builder-blue100-rgb: 232, 245, 255;\n --exp-builder-blue300-rgb: 152, 203, 255;\n\n /* Spacing tokens from Forma 36: https://f36.contentful.com/tokens/spacing */\n --exp-builder-spacing-s: 0.75rem;\n --exp-builder-spacing-2xs: 0.25rem;\n\n /* Typography tokens from Forma 36: https://f36.contentful.com/tokens/typography */\n --exp-builder-font-size-l: 1rem;\n --exp-builder-font-size-m: 0.875rem;\n --exp-builder-font-stack-primary: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial,\n sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;\n --exp-builder-line-height-condensed: 1.25;\n}\n";
15
15
  styleInject(css_248z$7);
16
16
 
17
17
  const INCOMING_EVENTS$1 = {
@@ -21,23 +21,15 @@ const INCOMING_EVENTS$1 = {
21
21
  ComponentDragCanceled: 'componentDragCanceled',
22
22
  ComponentDragStarted: 'componentDragStarted',
23
23
  ComponentDragEnded: 'componentDragEnded',
24
+ ComponentMoveEnded: 'componentMoveEnded',
24
25
  CanvasResized: 'canvasResized',
25
26
  SelectComponent: 'selectComponent',
26
27
  HoverComponent: 'hoverComponent',
27
28
  UpdatedEntity: 'updatedEntity',
28
- /**
29
- * @deprecated use `AssembliesAdded` instead. This will be removed in version 5.
30
- * In the meanwhile, the experience builder will send the old and the new event to support multiple SDK versions.
31
- */
32
- DesignComponentsAdded: 'designComponentsAdded',
33
- /**
34
- * @deprecated use `AssembliesRegistered` instead. This will be removed in version 5.
35
- * In the meanwhile, the experience builder will send the old and the new event to support multiple SDK versions.
36
- */
37
- DesignComponentsRegistered: 'designComponentsRegistered',
38
29
  AssembliesAdded: 'assembliesAdded',
39
30
  AssembliesRegistered: 'assembliesRegistered',
40
31
  InitEditor: 'initEditor',
32
+ MouseMove: 'mouseMove',
41
33
  };
42
34
  const CONTENTFUL_COMPONENTS$1 = {
43
35
  section: {
@@ -1443,32 +1435,8 @@ function gatherDeepReferencesFromTree(startingNode, dataSource) {
1443
1435
  return deepReferences;
1444
1436
  }
1445
1437
 
1446
- class DragState {
1447
- constructor() {
1448
- this.isDragStartedOnParent = false;
1449
- this.isDraggingItem = false;
1450
- }
1451
- get isDragging() {
1452
- return this.isDraggingItem;
1453
- }
1454
- get isDragStart() {
1455
- return this.isDragStartedOnParent;
1456
- }
1457
- updateIsDragging(isDraggingItem) {
1458
- this.isDraggingItem = isDraggingItem;
1459
- }
1460
- updateIsDragStartedOnParent(isDragStartedOnParent) {
1461
- this.isDragStartedOnParent = isDragStartedOnParent;
1462
- }
1463
- reset() {
1464
- this.isDraggingItem = false;
1465
- this.isDragStartedOnParent = false;
1466
- }
1467
- }
1468
- var dragState = new DragState();
1469
-
1470
- 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 outline-offset: -2px;\n outline: 2px solid transparent;\n box-sizing: border-box;\n display: flex;\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 {\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/* .DraggableComponent:hover .overlay {\n opacity: 1;\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 {\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,\n.styles-module_DraggableComponent__m5-dA:hover div[data-rfd-draggable-id] {\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)) {\n outline: 2px solid var(--exp-builder-gray500);\n}\n\n.styles-module_isAssemblyBlock__Y3Avk:hover,\n.styles-module_isAssemblyBlock__Y3Avk:hover div[data-rfd-draggable-id],\n.styles-module_DraggableComponent__m5-dA:hover div[data-rfd-draggable-id][data-cf-node-block-type^='assembly'] {\n outline: 2px dashed var(--exp-builder-purple600) !important;\n}\n\n.styles-module_isAssemblyBlock__Y3Avk:hover:not(:has(div[data-rfd-draggable-id]:hover)) {\n outline: 2px solid var(--exp-builder-purple600) !important;\n}\n";
1471
- var styles$3 = {"DraggableComponent":"styles-module_DraggableComponent__m5-dA","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"};
1438
+ 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 outline-offset: -2px;\n outline: 2px solid transparent;\n box-sizing: border-box;\n display: flex;\n}\n\n.styles-module_DraggableClone__X8zTA {\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 {\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 {\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,\n.styles-module_DraggableComponent__m5-dA:hover div[data-rfd-draggable-id] {\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)) {\n outline: 2px solid var(--exp-builder-gray500);\n}\n\n.styles-module_isAssemblyBlock__Y3Avk:hover,\n.styles-module_isAssemblyBlock__Y3Avk:hover div[data-rfd-draggable-id],\n.styles-module_DraggableComponent__m5-dA:hover div[data-rfd-draggable-id][data-cf-node-block-type^='assembly'] {\n outline: 2px dashed var(--exp-builder-purple600);\n}\n\n.styles-module_isAssemblyBlock__Y3Avk:hover:not(:has(div[data-rfd-draggable-id]:hover)) {\n outline: 2px solid var(--exp-builder-purple600);\n}\n";
1439
+ 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"};
1472
1440
  styleInject(css_248z$6);
1473
1441
 
1474
1442
  const SCROLL_STATES = {
@@ -1493,6 +1461,8 @@ const OUTGOING_EVENTS = {
1493
1461
  UpdateHoveredComponentCoordinates: 'updateHoveredComponentCoordinates',
1494
1462
  CanvasScroll: 'canvasScrolling',
1495
1463
  CanvasError: 'canvasError',
1464
+ ComponentMoveStarted: 'componentMoveStarted',
1465
+ ComponentMoveEnded: 'componentMoveEnded',
1496
1466
  OutsideCanvasClick: 'outsideCanvasClick',
1497
1467
  };
1498
1468
  const INCOMING_EVENTS = {
@@ -1502,23 +1472,15 @@ const INCOMING_EVENTS = {
1502
1472
  ComponentDragCanceled: 'componentDragCanceled',
1503
1473
  ComponentDragStarted: 'componentDragStarted',
1504
1474
  ComponentDragEnded: 'componentDragEnded',
1475
+ ComponentMoveEnded: 'componentMoveEnded',
1505
1476
  CanvasResized: 'canvasResized',
1506
1477
  SelectComponent: 'selectComponent',
1507
1478
  HoverComponent: 'hoverComponent',
1508
1479
  UpdatedEntity: 'updatedEntity',
1509
- /**
1510
- * @deprecated use `AssembliesAdded` instead. This will be removed in version 5.
1511
- * In the meanwhile, the experience builder will send the old and the new event to support multiple SDK versions.
1512
- */
1513
- DesignComponentsAdded: 'designComponentsAdded',
1514
- /**
1515
- * @deprecated use `AssembliesRegistered` instead. This will be removed in version 5.
1516
- * In the meanwhile, the experience builder will send the old and the new event to support multiple SDK versions.
1517
- */
1518
- DesignComponentsRegistered: 'designComponentsRegistered',
1519
1480
  AssembliesAdded: 'assembliesAdded',
1520
1481
  AssembliesRegistered: 'assembliesRegistered',
1521
1482
  InitEditor: 'initEditor',
1483
+ MouseMove: 'mouseMove',
1522
1484
  };
1523
1485
  const INTERNAL_EVENTS = {
1524
1486
  ComponentsRegistered: 'cfComponentsRegistered',
@@ -1569,15 +1531,6 @@ const ASSEMBLY_NODE_TYPE = 'assembly';
1569
1531
  const ASSEMBLY_DEFAULT_CATEGORY = 'Assemblies';
1570
1532
  const ASSEMBLY_BLOCK_NODE_TYPE = 'assemblyBlock';
1571
1533
  const ASSEMBLY_NODE_TYPES = [ASSEMBLY_NODE_TYPE, ASSEMBLY_BLOCK_NODE_TYPE];
1572
- /** @deprecated use `ASSEMBLY_NODE_TYPE` instead. This will be removed in version 5. */
1573
- const DESIGN_COMPONENT_NODE_TYPE = 'designComponent';
1574
- /** @deprecated use `ASSEMBLY_BLOCK_NODE_TYPE` instead. This will be removed in version 5. */
1575
- const DESIGN_COMPONENT_BLOCK_NODE_TYPE = 'designComponentBlock';
1576
- /** @deprecated use `ASSEMBLY_NODE_TYPES` instead. This will be removed in version 5. */
1577
- const DESIGN_COMPONENT_NODE_TYPES = [
1578
- DESIGN_COMPONENT_NODE_TYPE,
1579
- DESIGN_COMPONENT_BLOCK_NODE_TYPE,
1580
- ];
1581
1534
  const CF_STYLE_ATTRIBUTES = [
1582
1535
  'cfHorizontalAlignment',
1583
1536
  'cfVerticalAlignment',
@@ -1704,8 +1657,13 @@ const Tooltip = ({ coordinates, id, label, isAssemblyBlock, isContainer }) => {
1704
1657
 
1705
1658
  const useDraggedItemStore = create((set) => ({
1706
1659
  draggedItem: undefined,
1660
+ domRect: undefined,
1707
1661
  componentId: '',
1708
1662
  isDraggingOnCanvas: false,
1663
+ onBeforeCaptureId: '',
1664
+ mouseX: 0,
1665
+ mouseY: 0,
1666
+ scrollY: 0,
1709
1667
  setComponentId(id) {
1710
1668
  set({ componentId: id });
1711
1669
  },
@@ -1715,6 +1673,18 @@ const useDraggedItemStore = create((set) => ({
1715
1673
  setDraggingOnCanvas: (isDraggingOnCanvas) => {
1716
1674
  set({ isDraggingOnCanvas });
1717
1675
  },
1676
+ setOnBeforeCaptureId: (onBeforeCaptureId) => {
1677
+ set({ onBeforeCaptureId });
1678
+ },
1679
+ setMousePosition(x, y) {
1680
+ set({ mouseX: x, mouseY: y });
1681
+ },
1682
+ setDomRect(domRect) {
1683
+ set({ domRect });
1684
+ },
1685
+ setScrollY(y) {
1686
+ set({ scrollY: y });
1687
+ },
1718
1688
  }));
1719
1689
 
1720
1690
  const DRAGGABLE_HEIGHT = 30;
@@ -1722,7 +1692,9 @@ const DRAGGABLE_WIDTH = 50;
1722
1692
  const DRAG_PADDING = 4;
1723
1693
  const ROOT_ID = 'root';
1724
1694
  const COMPONENT_LIST_ID = 'component-list';
1695
+ const NEW_COMPONENT_ID = 'ctfl-new-draggable';
1725
1696
  const CTFL_ZONE_ID = 'data-ctfl-zone-id';
1697
+ const CTFL_DRAGGING_ELEMENT = 'data-ctfl-dragging-element';
1726
1698
  const HITBOX = {
1727
1699
  WIDTH: 80,
1728
1700
  HEIGHT: 20,
@@ -1756,6 +1728,11 @@ var HitboxDirection;
1756
1728
  HitboxDirection[HitboxDirection["SELF_VERTICAL"] = 4] = "SELF_VERTICAL";
1757
1729
  HitboxDirection[HitboxDirection["SELF_HORIZONTAL"] = 5] = "SELF_HORIZONTAL";
1758
1730
  })(HitboxDirection || (HitboxDirection = {}));
1731
+ var DraggablePosition;
1732
+ (function (DraggablePosition) {
1733
+ DraggablePosition[DraggablePosition["CENTERED"] = 0] = "CENTERED";
1734
+ DraggablePosition[DraggablePosition["MOUSE_POSITION"] = 1] = "MOUSE_POSITION";
1735
+ })(DraggablePosition || (DraggablePosition = {}));
1759
1736
 
1760
1737
  /**
1761
1738
  * Calculate the size and position of the dropzone indicator
@@ -1859,6 +1836,28 @@ const Placeholder = (props) => {
1859
1836
  } })));
1860
1837
  };
1861
1838
 
1839
+ function useDraggablePosition({ draggableId, draggableRef, position }) {
1840
+ const isDraggingOnCanvas = useDraggedItemStore((state) => state.isDraggingOnCanvas);
1841
+ const draggingId = useDraggedItemStore((state) => state.onBeforeCaptureId);
1842
+ const preDragDomRect = useDraggedItemStore((state) => state.domRect);
1843
+ useEffect(() => {
1844
+ const el = draggableRef?.current;
1845
+ if (!isDraggingOnCanvas || draggingId !== draggableId || !el) {
1846
+ return;
1847
+ }
1848
+ const isCentered = position === DraggablePosition.CENTERED || !preDragDomRect;
1849
+ const domRect = isCentered ? el.getBoundingClientRect() : preDragDomRect;
1850
+ const { mouseX, mouseY } = useDraggedItemStore.getState();
1851
+ const top = isCentered ? mouseY - domRect.height / 2 : domRect.top;
1852
+ const left = isCentered ? mouseX - domRect.width / 2 : domRect.left;
1853
+ el.style.position = 'fixed';
1854
+ el.style.left = `${left}px`;
1855
+ el.style.top = `${top}px`;
1856
+ el.style.width = `${domRect.width}px`;
1857
+ el.style.height = `${domRect.height}px`;
1858
+ }, [draggableRef, draggableId, isDraggingOnCanvas, draggingId, position, preDragDomRect]);
1859
+ }
1860
+
1862
1861
  function getStyle$2(style, snapshot) {
1863
1862
  if (!snapshot.isDropAnimating) {
1864
1863
  return style;
@@ -1869,8 +1868,18 @@ function getStyle$2(style, snapshot) {
1869
1868
  transitionDuration: `0.001s`,
1870
1869
  };
1871
1870
  }
1872
- const DraggableComponent = ({ children, id, index, isAssemblyBlock = false, isSelected = false, onClick = () => null, label, coordinates, userIsDragging, style, wrapperProps, isContainer, blockId, isDragDisabled = false, placeholder, ...rest }) => {
1873
- return (React.createElement(Draggable, { key: id, draggableId: id, index: index, isDragDisabled: isDragDisabled }, (provided, snapshot) => (React.createElement("div", { "data-ctfl-draggable-id": id, "data-test-id": `draggable-${blockId ?? 'node'}`, ref: provided.innerRef, ...wrapperProps, ...provided.draggableProps, ...provided.dragHandleProps, ...rest, className: classNames(styles$3.DraggableComponent, wrapperProps.className, {
1871
+ const DraggableComponent = ({ children, id, index, isAssemblyBlock = false, isSelected = false, onClick = () => null, coordinates, userIsDragging, style, wrapperProps, isContainer, blockId, isDragDisabled = false, placeholder, definition, ...rest }) => {
1872
+ const ref = useRef(null);
1873
+ const setDomRect = useDraggedItemStore((state) => state.setDomRect);
1874
+ useDraggablePosition({
1875
+ draggableId: id,
1876
+ draggableRef: ref,
1877
+ position: DraggablePosition.MOUSE_POSITION,
1878
+ });
1879
+ return (React.createElement(Draggable, { key: id, draggableId: id, index: index, isDragDisabled: isDragDisabled }, (provided, snapshot) => (React.createElement("div", { "data-ctfl-draggable-id": id, "data-test-id": `draggable-${blockId ?? 'node'}`, ref: (refNode) => {
1880
+ provided?.innerRef(refNode);
1881
+ ref.current = refNode;
1882
+ }, ...wrapperProps, ...provided.draggableProps, ...provided.dragHandleProps, ...rest, className: classNames(styles$3.DraggableComponent, wrapperProps.className, {
1874
1883
  [styles$3.isAssemblyBlock]: isAssemblyBlock,
1875
1884
  [styles$3.isDragging]: snapshot.isDragging,
1876
1885
  [styles$3.isSelected]: isSelected,
@@ -1878,8 +1887,14 @@ const DraggableComponent = ({ children, id, index, isAssemblyBlock = false, isSe
1878
1887
  }), style: {
1879
1888
  ...style,
1880
1889
  ...getStyle$2(provided.draggableProps.style, snapshot),
1890
+ }, onMouseDown: (e) => {
1891
+ if (isDragDisabled) {
1892
+ return;
1893
+ }
1894
+ e.stopPropagation();
1895
+ setDomRect(e.currentTarget.getBoundingClientRect());
1881
1896
  }, onClick: onClick },
1882
- React.createElement(Tooltip, { id: id, coordinates: coordinates, isAssemblyBlock: isAssemblyBlock, isContainer: isContainer, label: label }),
1897
+ React.createElement(Tooltip, { id: id, coordinates: coordinates, isAssemblyBlock: isAssemblyBlock, isContainer: isContainer, label: definition.name || 'No label specified' }),
1883
1898
  React.createElement(Placeholder, { ...placeholder, id: id }),
1884
1899
  children))));
1885
1900
  };
@@ -2061,14 +2076,10 @@ const useEntityStore = create((set) => ({
2061
2076
  const useComponentProps = ({ node, areEntitiesFetched, resolveDesignValue, renderDropzone, definition, userIsDragging, }) => {
2062
2077
  const unboundValues = useEditorStore((state) => state.unboundValues);
2063
2078
  const dataSource = useEditorStore((state) => state.dataSource);
2064
- const newComponentId = useDraggedItemStore((state) => state.componentId);
2065
- const isDraggingNewCompont = !!newComponentId;
2066
2079
  const entityStore = useEntityStore((state) => state.entityStore);
2067
2080
  const props = useMemo(() => {
2068
2081
  // Don't enrich the assembly wrapper node with props
2069
- if (!definition ||
2070
- node.type === DESIGN_COMPONENT_NODE_TYPE ||
2071
- node.type === ASSEMBLY_NODE_TYPE) {
2082
+ if (!definition || node.type === ASSEMBLY_NODE_TYPE) {
2072
2083
  return {};
2073
2084
  }
2074
2085
  return Object.entries(definition.variables).reduce((acc, [variableName, variableDefinition]) => {
@@ -2195,7 +2206,6 @@ const useComponentProps = ({ node, areEntitiesFetched, resolveDesignValue, rende
2195
2206
  minHeight: EMPTY_CONTAINER_HEIGHT,
2196
2207
  }),
2197
2208
  ...(userIsDragging &&
2198
- isDraggingNewCompont &&
2199
2209
  isContentfulStructureComponent(node?.data.blockId) &&
2200
2210
  node?.data.blockId !== CONTENTFUL_COMPONENTS.columns.id && {
2201
2211
  padding: addExtraDropzonePadding(componentStyles.padding?.toString() || '0 0 0 0'),
@@ -2367,7 +2377,7 @@ const deserializeAssemblyNode = ({ node, nodeId, nodeLocation, parentId, assembl
2367
2377
  };
2368
2378
  };
2369
2379
  const resolveAssembly = ({ node, entityStore, }) => {
2370
- if (node.type !== DESIGN_COMPONENT_NODE_TYPE && node.type !== ASSEMBLY_NODE_TYPE) {
2380
+ if (node.type !== ASSEMBLY_NODE_TYPE) {
2371
2381
  return node;
2372
2382
  }
2373
2383
  const componentId = node.data.blockId;
@@ -2412,8 +2422,7 @@ const useComponent = ({ node: rawNode, resolveDesignValue, renderDropzone, userI
2412
2422
  const areEntitiesFetched = useEntityStore((state) => state.areEntitiesFetched);
2413
2423
  const entityStore = useEntityStore((state) => state.entityStore);
2414
2424
  const node = useMemo(() => {
2415
- if ((rawNode.type === DESIGN_COMPONENT_NODE_TYPE || rawNode.type === ASSEMBLY_NODE_TYPE) &&
2416
- areEntitiesFetched) {
2425
+ if (rawNode.type === ASSEMBLY_NODE_TYPE && areEntitiesFetched) {
2417
2426
  return resolveAssembly({
2418
2427
  node: rawNode,
2419
2428
  entityStore,
@@ -2423,8 +2432,7 @@ const useComponent = ({ node: rawNode, resolveDesignValue, renderDropzone, userI
2423
2432
  }, [areEntitiesFetched, rawNode, entityStore]);
2424
2433
  const componentRegistration = useMemo(() => {
2425
2434
  const registration = componentRegistry.get(node.data.blockId);
2426
- if ((node.type === DESIGN_COMPONENT_NODE_TYPE || node.type === ASSEMBLY_NODE_TYPE) &&
2427
- !registration) {
2435
+ if (node.type === ASSEMBLY_NODE_TYPE && !registration) {
2428
2436
  return createAssemblyRegistration({
2429
2437
  definitionId: node.data.blockId,
2430
2438
  component: Assembly,
@@ -2448,7 +2456,7 @@ const useComponent = ({ node: rawNode, resolveDesignValue, renderDropzone, userI
2448
2456
  const { editorMode, renderDropzone: _renderDropzone, ...otherComponentProps } = componentProps;
2449
2457
  const elementToRender = builtInComponents.includes(node.data.blockId || '')
2450
2458
  ? (dragProps) => React.createElement(componentRegistration.component, { ...dragProps, ...componentProps })
2451
- : node.type === DESIGN_COMPONENT_NODE_TYPE || node.type === ASSEMBLY_NODE_TYPE
2459
+ : node.type === ASSEMBLY_NODE_TYPE
2452
2460
  ? // Assembly.tsx requires renderDropzone and editorMode as well
2453
2461
  () => React.createElement(componentRegistration.component, componentProps)
2454
2462
  : () => React.createElement(componentRegistration.component, otherComponentProps);
@@ -2457,7 +2465,7 @@ const useComponent = ({ node: rawNode, resolveDesignValue, renderDropzone, userI
2457
2465
  componentId,
2458
2466
  elementToRender,
2459
2467
  wrapperProps,
2460
- label: componentRegistration.definition.name,
2468
+ definition: componentRegistration.definition,
2461
2469
  };
2462
2470
  };
2463
2471
 
@@ -2471,7 +2479,7 @@ const useComponent = ({ node: rawNode, resolveDesignValue, renderDropzone, userI
2471
2479
  * component.
2472
2480
  */
2473
2481
  const DraggableChildComponent = (props) => {
2474
- const { elementToRender, id, index, isAssemblyBlock = false, isSelected = false, onClick = () => null, label, coordinates, userIsDragging, style, isContainer, blockId, isDragDisabled = false, wrapperProps, } = props;
2482
+ const { elementToRender, id, index, isAssemblyBlock = false, isSelected = false, onClick = () => null, coordinates, userIsDragging, style, isContainer, blockId, isDragDisabled = false, wrapperProps, definition, } = props;
2475
2483
  return (React.createElement(Draggable, { key: id, draggableId: id, index: index, isDragDisabled: isDragDisabled }, (provided, snapshot) => elementToRender({
2476
2484
  ['data-ctfl-draggable-id']: id,
2477
2485
  ['data-test-id']: `draggable-${blockId}`,
@@ -2490,11 +2498,11 @@ const DraggableChildComponent = (props) => {
2490
2498
  ...provided.draggableProps.style,
2491
2499
  },
2492
2500
  onClick,
2493
- Tooltip: (React.createElement(Tooltip, { id: id, coordinates: coordinates, isAssemblyBlock: isAssemblyBlock, isContainer: isContainer, label: label })),
2501
+ Tooltip: (React.createElement(Tooltip, { id: id, coordinates: coordinates, isAssemblyBlock: isAssemblyBlock, isContainer: isContainer, label: definition.name || 'No label specified' })),
2494
2502
  })));
2495
2503
  };
2496
2504
 
2497
- var css_248z$2 = ".styles-module_container__te-1H {\n margin-left: auto;\n margin-right: auto;\n position: relative;\n height: 100%;\n outline-offset: -2px;\n outline: 2px solid transparent;\n width: 100%;\n transition: outline 0.2s;\n pointer-events: all;\n}\n\n.styles-module_container__te-1H:not(.styles-module_isRoot__5cn-i) {\n outline-offset: -1px;\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) {\n outline: 2px dashed var(--exp-builder-blue500);\n}\n\n.styles-module_isDestination__5sCQx:not(.styles-module_isRoot__5cn-i) {\n outline: 2px dashed var(--exp-builder-blue500);\n background-color: rgba(var(--exp-builder-blue100-rgb), 0.5);\n}\n\n.styles-module_hitbox__YQ-1Z {\n position: fixed;\n pointer-events: all !important;\n}\n";
2505
+ var css_248z$2 = ".styles-module_container__te-1H {\n margin-left: auto;\n margin-right: auto;\n position: relative;\n height: 100%;\n outline-offset: -2px;\n outline: 2px solid transparent;\n width: 100%;\n background-color: transparent;\n transition:\n outline 0.2s,\n background-color 0.2s;\n pointer-events: all;\n}\n\n.styles-module_container__te-1H:not(.styles-module_isRoot__5cn-i) {\n outline-offset: -1px;\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) {\n outline: 2px dashed var(--exp-builder-gray300);\n}\n\n.styles-module_isDestination__5sCQx:not(.styles-module_isRoot__5cn-i) {\n outline: 2px dashed var(--exp-builder-blue400);\n background-color: rgba(var(--exp-builder-blue100-rgb), 0.5);\n z-index: 100;\n}\n\n.styles-module_hitbox__YQ-1Z {\n position: fixed;\n pointer-events: all !important;\n}\n";
2498
2506
  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"};
2499
2507
  styleInject(css_248z$2);
2500
2508
 
@@ -2755,7 +2763,7 @@ function treeVisit(initialNode, onNode) {
2755
2763
  }
2756
2764
 
2757
2765
  const isAssemblyNode = (node) => {
2758
- return node.type === DESIGN_COMPONENT_NODE_TYPE || node.type === ASSEMBLY_NODE_TYPE;
2766
+ return node.type === ASSEMBLY_NODE_TYPE;
2759
2767
  };
2760
2768
  const useTreeStore = create((set, get) => ({
2761
2769
  tree: {
@@ -2901,7 +2909,7 @@ const getHitboxStyles = ({ direction, zoneDepth, domRect }) => {
2901
2909
  return {
2902
2910
  width,
2903
2911
  height: HEIGHT,
2904
- top: top - calcOffsetDepth(zoneDepth),
2912
+ top: top - calcOffsetDepth(zoneDepth) - scrollY,
2905
2913
  left,
2906
2914
  zIndex: 100 + zoneDepth,
2907
2915
  };
@@ -2909,7 +2917,7 @@ const getHitboxStyles = ({ direction, zoneDepth, domRect }) => {
2909
2917
  return {
2910
2918
  width,
2911
2919
  height: HEIGHT,
2912
- top: bottom + calcOffsetDepth(zoneDepth),
2920
+ top: bottom + calcOffsetDepth(zoneDepth) - scrollY,
2913
2921
  left,
2914
2922
  zIndex: 100 + zoneDepth,
2915
2923
  };
@@ -2918,7 +2926,7 @@ const getHitboxStyles = ({ direction, zoneDepth, domRect }) => {
2918
2926
  width: WIDTH,
2919
2927
  height: height - HEIGHT,
2920
2928
  left: left - calcOffsetDepth(zoneDepth) - WIDTH / 2,
2921
- top: top + HEIGHT / 2,
2929
+ top: top + HEIGHT / 2 - scrollY,
2922
2930
  zIndex: 100 + zoneDepth,
2923
2931
  };
2924
2932
  case HitboxDirection.RIGHT:
@@ -2926,7 +2934,7 @@ const getHitboxStyles = ({ direction, zoneDepth, domRect }) => {
2926
2934
  width: WIDTH,
2927
2935
  height: height - HEIGHT,
2928
2936
  left: right - calcOffsetDepth(zoneDepth) - WIDTH / 2,
2929
- top: top + HEIGHT / 2,
2937
+ top: top + HEIGHT / 2 - scrollY,
2930
2938
  zIndex: 100 + zoneDepth,
2931
2939
  };
2932
2940
  case HitboxDirection.SELF_VERTICAL: {
@@ -2938,7 +2946,7 @@ const getHitboxStyles = ({ direction, zoneDepth, domRect }) => {
2938
2946
  width,
2939
2947
  height: selfHeight,
2940
2948
  left,
2941
- top: top + height / 2 - selfHeight / 2,
2949
+ top: top + height / 2 - selfHeight / 2 - scrollY,
2942
2950
  zIndex: 1000 + zoneDepth,
2943
2951
  };
2944
2952
  }
@@ -2950,7 +2958,7 @@ const getHitboxStyles = ({ direction, zoneDepth, domRect }) => {
2950
2958
  width: width - DRAGGABLE_WIDTH * 2,
2951
2959
  height,
2952
2960
  left: left + (DRAGGABLE_WIDTH * 2) / 2,
2953
- top,
2961
+ top: top - scrollY,
2954
2962
  zIndex: 1000 + zoneDepth,
2955
2963
  };
2956
2964
  }
@@ -2962,6 +2970,7 @@ const getHitboxStyles = ({ direction, zoneDepth, domRect }) => {
2962
2970
  const Hitboxes = ({ zoneId, parentZoneId, enableRootHitboxes }) => {
2963
2971
  const tree = useTreeStore((state) => state.tree);
2964
2972
  const isDraggingOnCanvas = useDraggedItemStore((state) => state.isDraggingOnCanvas);
2973
+ const scrollY = useDraggedItemStore((state) => state.scrollY);
2965
2974
  const zoneDepth = useMemo(() => getItemDepthFromNode({ id: parentZoneId }, tree.root), [tree, parentZoneId]);
2966
2975
  const [fetchDomRect, setFetchDomRect] = useState(Date.now());
2967
2976
  useEffect(() => {
@@ -2987,10 +2996,11 @@ const Hitboxes = ({ zoneId, parentZoneId, enableRootHitboxes }) => {
2987
2996
  const isVertical = zoneDirection === 'vertical';
2988
2997
  const isRoot = parentZoneId === ROOT_ID;
2989
2998
  const showRootHitboxes = isRoot && enableRootHitboxes;
2990
- const getStyles = useCallback((direction) => getHitboxStyles({ direction, zoneDepth, domRect }), [zoneDepth, domRect]);
2999
+ const getStyles = useCallback((direction) => getHitboxStyles({ direction, zoneDepth, domRect, scrollY }), [zoneDepth, domRect, scrollY]);
2991
3000
  const ActiveHitboxes = (React.createElement(React.Fragment, null,
2992
3001
  React.createElement("div", { "data-ctfl-zone-id": zoneId, className: styles$2.hitbox, style: getStyles(isVertical ? HitboxDirection.SELF_VERTICAL : HitboxDirection.SELF_HORIZONTAL) }),
2993
- showRootHitboxes ? (React.createElement("div", { "data-ctfl-zone-id": parentZoneId, className: styles$2.hitbox, style: getStyles(HitboxDirection.BOTTOM) })) : (React.createElement(React.Fragment, null,
3002
+ showRootHitboxes && (React.createElement("div", { "data-ctfl-zone-id": parentZoneId, className: styles$2.hitbox, style: getStyles(HitboxDirection.BOTTOM) })),
3003
+ !isRoot && (React.createElement(React.Fragment, null,
2994
3004
  React.createElement("div", { "data-ctfl-zone-id": parentZoneId, className: styles$2.hitbox, style: getStyles(isVertical ? HitboxDirection.TOP : HitboxDirection.LEFT) }),
2995
3005
  React.createElement("div", { "data-ctfl-zone-id": parentZoneId, className: styles$2.hitbox, style: getStyles(isVertical ? HitboxDirection.BOTTOM : HitboxDirection.RIGHT) })))));
2996
3006
  if (!hitboxContainer) {
@@ -3002,7 +3012,7 @@ const Hitboxes = ({ zoneId, parentZoneId, enableRootHitboxes }) => {
3002
3012
  const EditorBlock = ({ node: rawNode, resolveDesignValue, renderDropzone, draggingNewComponent, index, zoneId, userIsDragging, placeholder, }) => {
3003
3013
  const setSelectedNodeId = useEditorStore((state) => state.setSelectedNodeId);
3004
3014
  const selectedNodeId = useEditorStore((state) => state.selectedNodeId);
3005
- const { node, componentId, wrapperProps, label, elementToRender } = useComponent({
3015
+ const { node, componentId, wrapperProps, definition, elementToRender } = useComponent({
3006
3016
  node: rawNode,
3007
3017
  resolveDesignValue,
3008
3018
  renderDropzone,
@@ -3015,7 +3025,7 @@ const EditorBlock = ({ node: rawNode, resolveDesignValue, renderDropzone, draggi
3015
3025
  const isAssembly = node.type === ASSEMBLY_NODE_TYPE;
3016
3026
  const isStructureComponent = isContentfulStructureComponent(node.data.blockId);
3017
3027
  const isRootComponent = zoneId === ROOT_ID;
3018
- const enableRootHitboxes = isRootComponent && !draggingNewComponent;
3028
+ const enableRootHitboxes = isRootComponent && !!draggingNewComponent;
3019
3029
  const onClick = (e) => {
3020
3030
  e.stopPropagation();
3021
3031
  if (!userIsDragging) {
@@ -3035,10 +3045,10 @@ const EditorBlock = ({ node: rawNode, resolveDesignValue, renderDropzone, draggi
3035
3045
  };
3036
3046
  if (node.data.blockId === CONTENTFUL_COMPONENTS.singleColumn.id) {
3037
3047
  return (React.createElement(React.Fragment, null,
3038
- React.createElement(DraggableChildComponent, { elementToRender: elementToRender, label: label || 'No Label Specified', 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 }),
3048
+ 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 }),
3039
3049
  isStructureComponent && userIsDragging && (React.createElement(Hitboxes, { parentZoneId: zoneId, zoneId: componentId, enableRootHitboxes: enableRootHitboxes }))));
3040
3050
  }
3041
- return (React.createElement(DraggableComponent, { placeholder: placeholder, label: label || 'No Label Specified', 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 },
3051
+ 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 },
3042
3052
  elementToRender(),
3043
3053
  isStructureComponent && userIsDragging && (React.createElement(Hitboxes, { parentZoneId: zoneId, zoneId: componentId, enableRootHitboxes: enableRootHitboxes }))));
3044
3054
  };
@@ -3133,7 +3143,7 @@ const EditorBlockClone = ({ node: rawNode, resolveDesignValue, snapshot, provide
3133
3143
  if (isSingleColumn) {
3134
3144
  return elementToRender();
3135
3145
  }
3136
- return (React.createElement("div", { ref: provided?.innerRef, ...wrapperProps, ...provided?.draggableProps, ...provided?.dragHandleProps, className: classNames(styles$3.DraggableComponent, wrapperProps.className, {
3146
+ return (React.createElement("div", { ref: provided?.innerRef, "data-ctfl-dragging-element": true, ...wrapperProps, ...provided?.draggableProps, ...provided?.dragHandleProps, className: classNames(styles$3.DraggableComponent, wrapperProps.className, styles$3.DraggableClone, {
3137
3147
  [styles$3.isAssemblyBlock]: isAssemblyBlock,
3138
3148
  [styles$3.isDragging]: snapshot?.isDragging,
3139
3149
  }), style: getStyle$1(provided?.draggableProps.style, snapshot) }, elementToRender()));
@@ -3170,8 +3180,7 @@ function Dropzone({ node, zoneId, resolveDesignValue, className, WrapperComponen
3170
3180
  const isRootZone = zoneId === ROOT_ID;
3171
3181
  const isDestination = draggedDestinationId === zoneId;
3172
3182
  const isEmptyCanvas = isRootZone && !content.length;
3173
- const isAssembly = DESIGN_COMPONENT_NODE_TYPES.includes(node?.type || '') ||
3174
- ASSEMBLY_NODE_TYPES.includes(node?.type || '');
3183
+ const isAssembly = ASSEMBLY_NODE_TYPES.includes(node?.type || '');
3175
3184
  // To avoid a circular dependency, we create the recursive rendering function here and trickle it down
3176
3185
  const renderDropzone = useCallback((node, props) => {
3177
3186
  return (React.createElement(Dropzone, { zoneId: node.data.id, node: node, resolveDesignValue: resolveDesignValue, ...props }));
@@ -3182,13 +3191,30 @@ function Dropzone({ node, zoneId, resolveDesignValue, className, WrapperComponen
3182
3191
  if (!resolveDesignValue) {
3183
3192
  return null;
3184
3193
  }
3185
- // Don't trigger the dropzone when it's the root because then the only hit boxes that show up will be root level zones
3186
- // Exception 1: If it comes from the component list (because we want the component list components to work for all zones
3187
- // Exception 2: If it's a child of a root level zone (because we want to be able to re-order root level containers)
3194
+ /**
3195
+ * The Rules of Dropzones
3196
+ *
3197
+ * 1. A dropzone is disabled unless the mouse is hovering over it
3198
+ *
3199
+ * 2. Dragging a new component onto the canvas has no addtional rules
3200
+ * besides rule #1
3201
+ *
3202
+ * 3. Dragging a component that is a direct descendant of the root
3203
+ * (parentId === ROOT_ID) then only the Root Dropzone is enabled
3204
+ *
3205
+ * 4. Dragging a nested component (parentId !== ROOT_ID) then the Root
3206
+ * Dropzone is disabled, all other Dropzones follow rule #1
3207
+ *
3208
+ * 5. Assemblies and the SingleColumn component are always disabled
3209
+ *
3210
+ */
3188
3211
  const isDropzoneEnabled = () => {
3189
3212
  if (node?.data.blockId === CONTENTFUL_COMPONENTS.columns.id) {
3190
3213
  return false;
3191
3214
  }
3215
+ if (isAssembly) {
3216
+ return false;
3217
+ }
3192
3218
  if (isDraggingNewComponent) {
3193
3219
  return isHoveringZone;
3194
3220
  }
@@ -3231,6 +3257,12 @@ function getStyle(style, snapshot) {
3231
3257
  };
3232
3258
  }
3233
3259
  const DraggableContainer = ({ id }) => {
3260
+ const ref = useRef(null);
3261
+ useDraggablePosition({
3262
+ draggableId: id,
3263
+ draggableRef: ref,
3264
+ position: DraggablePosition.CENTERED,
3265
+ });
3234
3266
  return (React.createElement("div", { id: COMPONENT_LIST_ID, style: {
3235
3267
  position: 'absolute',
3236
3268
  top: 0,
@@ -3239,7 +3271,10 @@ const DraggableContainer = ({ id }) => {
3239
3271
  zIndex: -1,
3240
3272
  } },
3241
3273
  React.createElement(Droppable, { droppableId: COMPONENT_LIST_ID, isDropDisabled: true }, (provided) => (React.createElement("div", { ...provided.droppableProps, ref: provided.innerRef },
3242
- React.createElement(Draggable, { draggableId: id, key: id, index: 0 }, (provided, snapshot) => (React.createElement("div", { id: "item", ref: provided.innerRef, ...provided.draggableProps, ...provided.dragHandleProps, style: {
3274
+ React.createElement(Draggable, { draggableId: id, key: id, index: 0 }, (provided, snapshot) => (React.createElement("div", { id: NEW_COMPONENT_ID, "data-ctfl-dragging-element": true, ref: (node) => {
3275
+ provided.innerRef(node);
3276
+ ref.current = node;
3277
+ }, ...provided.draggableProps, ...provided.dragHandleProps, style: {
3243
3278
  ...getStyle(provided.draggableProps.style, snapshot),
3244
3279
  width: DRAGGABLE_WIDTH,
3245
3280
  height: DRAGGABLE_HEIGHT,
@@ -3407,8 +3442,7 @@ class MouseOverHandler {
3407
3442
  };
3408
3443
  }
3409
3444
  getBoundingClientRect(element) {
3410
- const isAssembly = element.getAttribute('data-cf-node-block-type') === DESIGN_COMPONENT_NODE_TYPE ||
3411
- element.getAttribute('data-cf-node-block-type') === ASSEMBLY_NODE_TYPE;
3445
+ const isAssembly = element.getAttribute('data-cf-node-block-type') === ASSEMBLY_NODE_TYPE;
3412
3446
  if (!isAssembly) {
3413
3447
  return element.getBoundingClientRect();
3414
3448
  }
@@ -3459,39 +3493,74 @@ const sendHoveredComponentCoordinates = (instanceId) => {
3459
3493
  mouseOverHandler.handleMouseMove(selectedElement || null);
3460
3494
  };
3461
3495
 
3462
- function updateDraggableElement(x, y) {
3463
- const container = document.querySelector('#component-list');
3464
- if (!container) {
3465
- return;
3496
+ class DragState {
3497
+ constructor() {
3498
+ this.isDragStartedOnParent = false;
3499
+ this.isDraggingItem = false;
3500
+ }
3501
+ get isDragging() {
3502
+ return this.isDraggingItem;
3503
+ }
3504
+ get isDraggingOnParent() {
3505
+ return this.isDragStartedOnParent;
3506
+ }
3507
+ updateIsDragging(isDraggingItem) {
3508
+ this.isDraggingItem = isDraggingItem;
3509
+ }
3510
+ updateIsDragStartedOnParent(isDragStartedOnParent) {
3511
+ this.isDragStartedOnParent = isDragStartedOnParent;
3512
+ }
3513
+ resetState() {
3514
+ this.isDraggingItem = false;
3515
+ this.isDragStartedOnParent = false;
3466
3516
  }
3467
- container.style.setProperty('top', `${y}px`);
3468
- container.style.setProperty('left', `${x}px`);
3469
3517
  }
3470
- function simulateMouseEvent(coordX, coordY, eventName = 'mousemove') {
3471
- const element = document.querySelector('#item');
3472
- if (!dragState.isDragStart) {
3473
- return;
3518
+
3519
+ class SimulateDnD extends DragState {
3520
+ constructor() {
3521
+ super();
3522
+ this.draggingElement = null;
3474
3523
  }
3475
- if (!dragState.isDragging) {
3476
- updateDraggableElement(coordX, coordY);
3477
- eventName = 'mousedown';
3478
- dragState.updateIsDragging(true);
3479
- }
3480
- const options = {
3481
- bubbles: true,
3482
- cancelable: true,
3483
- view: window,
3484
- pageX: 0,
3485
- pageY: 0,
3486
- clientX: coordX - DRAGGABLE_WIDTH / 2,
3487
- clientY: coordY - DRAGGABLE_HEIGHT / 2 - window.scrollY,
3488
- };
3489
- if (!element) {
3490
- return;
3524
+ setupDrag() {
3525
+ this.updateIsDragStartedOnParent(true);
3526
+ }
3527
+ startDrag(coordX, coordY) {
3528
+ this.draggingElement = document.getElementById(NEW_COMPONENT_ID);
3529
+ this.updateIsDragging(true);
3530
+ this.simulateMouseEvent(coordX, coordY, 'mousedown');
3531
+ }
3532
+ updateDrag(coordX, coordY) {
3533
+ if (!this.draggingElement) {
3534
+ this.draggingElement = document.querySelector(`[${CTFL_DRAGGING_ELEMENT}]`);
3535
+ }
3536
+ this.simulateMouseEvent(coordX, coordY);
3537
+ }
3538
+ endDrag(coordX, coordY) {
3539
+ this.simulateMouseEvent(coordX, coordY, 'mouseup');
3540
+ this.reset();
3541
+ }
3542
+ reset() {
3543
+ this.draggingElement = null;
3544
+ this.resetState();
3545
+ }
3546
+ simulateMouseEvent(coordX, coordY, eventName = 'mousemove') {
3547
+ if (!this.draggingElement) {
3548
+ return;
3549
+ }
3550
+ const options = {
3551
+ bubbles: true,
3552
+ cancelable: true,
3553
+ view: window,
3554
+ pageX: 0,
3555
+ pageY: 0,
3556
+ clientX: coordX,
3557
+ clientY: coordY,
3558
+ };
3559
+ const event = new MouseEvent(eventName, options);
3560
+ this.draggingElement.dispatchEvent(event);
3491
3561
  }
3492
- const event = new MouseEvent(eventName, options);
3493
- element.dispatchEvent(event);
3494
3562
  }
3563
+ var SimulateDnD$1 = new SimulateDnD();
3495
3564
 
3496
3565
  function useEditorSubscriber() {
3497
3566
  const entityStore = useEntityStore((state) => state.entityStore);
@@ -3510,6 +3579,8 @@ function useEditorSubscriber() {
3510
3579
  const selectedNodeId = useEditorStore((state) => state.selectedNodeId);
3511
3580
  const setComponentId = useDraggedItemStore((state) => state.setComponentId);
3512
3581
  const setDraggingOnCanvas = useDraggedItemStore((state) => state.setDraggingOnCanvas);
3582
+ const setMousePosition = useDraggedItemStore((state) => state.setMousePosition);
3583
+ const setScrollY = useDraggedItemStore((state) => state.setScrollY);
3513
3584
  // TODO: As we have disabled the useEffect, we can remove these states
3514
3585
  const [, /* isFetchingEntities */ setFetchingEntities] = useState(false);
3515
3586
  const reloadApp = () => {
@@ -3666,9 +3737,6 @@ function useEditorSubscriber() {
3666
3737
  }
3667
3738
  break;
3668
3739
  }
3669
- case INCOMING_EVENTS.DesignComponentsRegistered:
3670
- // Event was deprecated and support will be discontinued with version 5
3671
- break;
3672
3740
  case INCOMING_EVENTS.AssembliesRegistered: {
3673
3741
  const { assemblies } = payload;
3674
3742
  assemblies.forEach((definition) => {
@@ -3679,9 +3747,6 @@ function useEditorSubscriber() {
3679
3747
  });
3680
3748
  break;
3681
3749
  }
3682
- case INCOMING_EVENTS.DesignComponentsAdded:
3683
- // Event was deprecated and support will be discontinued with version 5
3684
- break;
3685
3750
  case INCOMING_EVENTS.AssembliesAdded: {
3686
3751
  const { assembly, assemblyDefinition, } = payload;
3687
3752
  entityStore.updateEntity(assembly);
@@ -3700,6 +3765,10 @@ function useEditorSubscriber() {
3700
3765
  break;
3701
3766
  }
3702
3767
  case INCOMING_EVENTS.CanvasResized: {
3768
+ const { selectedNodeId } = payload;
3769
+ if (selectedNodeId) {
3770
+ sendSelectedComponentCoordinates(selectedNodeId);
3771
+ }
3703
3772
  break;
3704
3773
  }
3705
3774
  case INCOMING_EVENTS.HoverComponent: {
@@ -3712,7 +3781,7 @@ function useEditorSubscriber() {
3712
3781
  if (!isDragging) {
3713
3782
  setComponentId('');
3714
3783
  setDraggingOnCanvas(false);
3715
- dragState.reset();
3784
+ SimulateDnD$1.reset();
3716
3785
  }
3717
3786
  break;
3718
3787
  }
@@ -3733,23 +3802,23 @@ function useEditorSubscriber() {
3733
3802
  break;
3734
3803
  }
3735
3804
  case INCOMING_EVENTS.ComponentDragCanceled: {
3736
- if (dragState.isDragging) {
3805
+ if (SimulateDnD$1.isDragging) {
3737
3806
  //simulate a mouseup event to cancel the drag
3738
- simulateMouseEvent(0, 0, 'mouseup');
3807
+ SimulateDnD$1.endDrag(0, 0);
3739
3808
  }
3740
3809
  break;
3741
3810
  }
3742
3811
  case INCOMING_EVENTS.ComponentDragStarted: {
3743
- dragState.updateIsDragStartedOnParent(true);
3744
- setDraggingOnCanvas(true);
3812
+ SimulateDnD$1.setupDrag();
3745
3813
  setComponentId(payload.id || '');
3814
+ setDraggingOnCanvas(true);
3746
3815
  sendMessage(OUTGOING_EVENTS.ComponentSelected, {
3747
3816
  nodeId: '',
3748
3817
  });
3749
3818
  break;
3750
3819
  }
3751
3820
  case INCOMING_EVENTS.ComponentDragEnded: {
3752
- dragState.reset();
3821
+ SimulateDnD$1.reset();
3753
3822
  setComponentId('');
3754
3823
  setDraggingOnCanvas(false);
3755
3824
  break;
@@ -3760,6 +3829,22 @@ function useEditorSubscriber() {
3760
3829
  sendSelectedComponentCoordinates(nodeId);
3761
3830
  break;
3762
3831
  }
3832
+ case INCOMING_EVENTS.MouseMove: {
3833
+ const { mouseX, mouseY } = payload;
3834
+ setMousePosition(mouseX, mouseY);
3835
+ if (SimulateDnD$1.isDraggingOnParent && !SimulateDnD$1.isDragging) {
3836
+ SimulateDnD$1.startDrag(mouseX, mouseY);
3837
+ }
3838
+ else {
3839
+ SimulateDnD$1.updateDrag(mouseX, mouseY);
3840
+ }
3841
+ break;
3842
+ }
3843
+ case INCOMING_EVENTS.ComponentMoveEnded: {
3844
+ const { mouseX, mouseY } = payload;
3845
+ SimulateDnD$1.endDrag(mouseX, mouseY);
3846
+ break;
3847
+ }
3763
3848
  default:
3764
3849
  console.error(`[experiences-sdk-react::onMessage] Logic error, unsupported eventType: [${eventData.eventType}]`);
3765
3850
  }
@@ -3782,6 +3867,7 @@ function useEditorSubscriber() {
3782
3867
  unboundValues,
3783
3868
  updateTree,
3784
3869
  updateNodesByUpdatedEntity,
3870
+ setMousePosition,
3785
3871
  ]);
3786
3872
  /*
3787
3873
  * Handles on scroll business
@@ -3790,6 +3876,7 @@ function useEditorSubscriber() {
3790
3876
  let timeoutId = 0;
3791
3877
  let isScrolling = false;
3792
3878
  const onScroll = () => {
3879
+ setScrollY(window.scrollY);
3793
3880
  if (isScrolling === false) {
3794
3881
  sendMessage(OUTGOING_EVENTS.CanvasScroll, SCROLL_STATES.Start);
3795
3882
  }
@@ -3815,7 +3902,7 @@ function useEditorSubscriber() {
3815
3902
  window.removeEventListener('scroll', onScroll, { capture: true });
3816
3903
  clearTimeout(timeoutId);
3817
3904
  };
3818
- }, [selectedNodeId]);
3905
+ }, [selectedNodeId, setScrollY]);
3819
3906
  }
3820
3907
 
3821
3908
  const onComponentMoved = (options) => {
@@ -3978,30 +4065,36 @@ const TestDNDContainer = ({ onDragEnd, onBeforeDragStart, onDragUpdate, children
3978
4065
  const DNDProvider = ({ children }) => {
3979
4066
  const setSelectedNodeId = useEditorStore((state) => state.setSelectedNodeId);
3980
4067
  const draggedItem = useDraggedItemStore((state) => state.draggedItem);
4068
+ const setOnBeforeCaptureId = useDraggedItemStore((state) => state.setOnBeforeCaptureId);
3981
4069
  const setDraggingOnCanvas = useDraggedItemStore((state) => state.setDraggingOnCanvas);
3982
4070
  const updateItem = useDraggedItemStore((state) => state.updateItem);
3983
4071
  const { onAddComponent, onMoveComponent } = useCanvasInteractions();
3984
4072
  const selectedNodeId = useEditorStore((state) => state.selectedNodeId);
3985
4073
  const prevSelectedNodeId = useRef(null);
3986
4074
  const isTestRun = typeof window !== 'undefined' && Object.prototype.hasOwnProperty.call(window, 'Cypress');
3987
- const dragStart = () => {
4075
+ const dragStart = ({ source }) => {
3988
4076
  prevSelectedNodeId.current = selectedNodeId;
3989
4077
  //Unselect the current node when dragging and remove the outline
3990
4078
  setSelectedNodeId('');
3991
4079
  sendMessage(OUTGOING_EVENTS.ComponentSelected, {
3992
4080
  nodeId: '',
3993
4081
  });
4082
+ if (source.droppableId !== COMPONENT_LIST_ID) {
4083
+ sendMessage(OUTGOING_EVENTS.ComponentMoveStarted);
4084
+ }
3994
4085
  };
3995
- const beforeCapture = () => {
4086
+ const beforeCapture = ({ draggableId }) => {
3996
4087
  setDraggingOnCanvas(true);
4088
+ setOnBeforeCaptureId(draggableId);
3997
4089
  };
3998
4090
  const dragUpdate = (update) => {
3999
4091
  updateItem(update);
4000
4092
  };
4001
4093
  const dragEnd = (dropResult) => {
4002
4094
  setDraggingOnCanvas(false);
4095
+ setOnBeforeCaptureId('');
4003
4096
  updateItem(undefined);
4004
- dragState.reset();
4097
+ SimulateDnD$1.reset();
4005
4098
  if (!dropResult.destination) {
4006
4099
  if (!draggedItem?.destination) {
4007
4100
  // User cancel drag
@@ -4028,6 +4121,7 @@ const DNDProvider = ({ children }) => {
4028
4121
  }
4029
4122
  // If a node was previously selected prior to dragging, re-select it
4030
4123
  setSelectedNodeId(dropResult.draggableId);
4124
+ sendMessage(OUTGOING_EVENTS.ComponentMoveEnded);
4031
4125
  sendMessage(OUTGOING_EVENTS.ComponentSelected, {
4032
4126
  nodeId: dropResult.draggableId,
4033
4127
  });
@@ -4154,6 +4248,7 @@ const findNearestDropzone = (element) => {
4154
4248
  const VisualEditorRoot = () => {
4155
4249
  const initialized = useInitializeEditor();
4156
4250
  const locale = useEditorStore((state) => state.locale);
4251
+ const setMousePosition = useDraggedItemStore((state) => state.setMousePosition);
4157
4252
  const entityStore = useEntityStore((state) => state.entityStore);
4158
4253
  const setHoveringZone = useZoneStore((state) => state.setHoveringZone);
4159
4254
  const resetEntityStore = useEntityStore((state) => state.resetEntityStore);
@@ -4168,18 +4263,19 @@ const VisualEditorRoot = () => {
4168
4263
  }, [locale, resetEntityStore, entityStore.locale]);
4169
4264
  useEffect(() => {
4170
4265
  const onMouseMove = (e) => {
4266
+ setMousePosition(e.clientX, e.clientY);
4171
4267
  const target = e.target;
4172
4268
  const zoneId = findNearestDropzone(target);
4173
4269
  if (zoneId) {
4174
4270
  setHoveringZone(zoneId);
4175
4271
  }
4176
- if (e.target?.id === 'item') {
4272
+ if (!SimulateDnD$1.isDragging) {
4177
4273
  return;
4178
4274
  }
4179
- if (!dragState.isDragStart) {
4275
+ if (target.id === NEW_COMPONENT_ID) {
4180
4276
  return;
4181
4277
  }
4182
- simulateMouseEvent(e.pageX, e.pageY);
4278
+ SimulateDnD$1.updateDrag(e.clientX, e.clientY);
4183
4279
  sendMessage(OUTGOING_EVENTS.MouseMove, {
4184
4280
  clientX: e.pageX,
4185
4281
  clientY: e.pageY - window.scrollY,