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

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,33 +11,25 @@ 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 = {
18
18
  RequestEditorMode: 'requestEditorMode',
19
- CompositionUpdated: 'componentTreeUpdated',
19
+ ExperienceUpdated: 'componentTreeUpdated',
20
20
  ComponentDraggingChanged: 'componentDraggingChanged',
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: {
@@ -1195,6 +1187,13 @@ class EntityStoreBase {
1195
1187
  }
1196
1188
  return this.entryMap.get(id);
1197
1189
  }
1190
+ toJSON() {
1191
+ return {
1192
+ entryMap: Object.fromEntries(this.entryMap),
1193
+ assetMap: Object.fromEntries(this.assetMap),
1194
+ locale: this.locale,
1195
+ };
1196
+ }
1198
1197
  }
1199
1198
 
1200
1199
  /**
@@ -1443,32 +1442,8 @@ function gatherDeepReferencesFromTree(startingNode, dataSource) {
1443
1442
  return deepReferences;
1444
1443
  }
1445
1444
 
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"};
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 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";
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"};
1472
1447
  styleInject(css_248z$6);
1473
1448
 
1474
1449
  const SCROLL_STATES = {
@@ -1493,32 +1468,26 @@ const OUTGOING_EVENTS = {
1493
1468
  UpdateHoveredComponentCoordinates: 'updateHoveredComponentCoordinates',
1494
1469
  CanvasScroll: 'canvasScrolling',
1495
1470
  CanvasError: 'canvasError',
1471
+ ComponentMoveStarted: 'componentMoveStarted',
1472
+ ComponentMoveEnded: 'componentMoveEnded',
1496
1473
  OutsideCanvasClick: 'outsideCanvasClick',
1497
1474
  };
1498
1475
  const INCOMING_EVENTS = {
1499
1476
  RequestEditorMode: 'requestEditorMode',
1500
- CompositionUpdated: 'componentTreeUpdated',
1477
+ ExperienceUpdated: 'componentTreeUpdated',
1501
1478
  ComponentDraggingChanged: 'componentDraggingChanged',
1502
1479
  ComponentDragCanceled: 'componentDragCanceled',
1503
1480
  ComponentDragStarted: 'componentDragStarted',
1504
1481
  ComponentDragEnded: 'componentDragEnded',
1482
+ ComponentMoveEnded: 'componentMoveEnded',
1505
1483
  CanvasResized: 'canvasResized',
1506
1484
  SelectComponent: 'selectComponent',
1507
1485
  HoverComponent: 'hoverComponent',
1508
1486
  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
1487
  AssembliesAdded: 'assembliesAdded',
1520
1488
  AssembliesRegistered: 'assembliesRegistered',
1521
1489
  InitEditor: 'initEditor',
1490
+ MouseMove: 'mouseMove',
1522
1491
  };
1523
1492
  const INTERNAL_EVENTS = {
1524
1493
  ComponentsRegistered: 'cfComponentsRegistered',
@@ -1569,15 +1538,6 @@ const ASSEMBLY_NODE_TYPE = 'assembly';
1569
1538
  const ASSEMBLY_DEFAULT_CATEGORY = 'Assemblies';
1570
1539
  const ASSEMBLY_BLOCK_NODE_TYPE = 'assemblyBlock';
1571
1540
  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
1541
  const CF_STYLE_ATTRIBUTES = [
1582
1542
  'cfHorizontalAlignment',
1583
1543
  'cfVerticalAlignment',
@@ -1704,8 +1664,13 @@ const Tooltip = ({ coordinates, id, label, isAssemblyBlock, isContainer }) => {
1704
1664
 
1705
1665
  const useDraggedItemStore = create((set) => ({
1706
1666
  draggedItem: undefined,
1667
+ domRect: undefined,
1707
1668
  componentId: '',
1708
1669
  isDraggingOnCanvas: false,
1670
+ onBeforeCaptureId: '',
1671
+ mouseX: 0,
1672
+ mouseY: 0,
1673
+ scrollY: 0,
1709
1674
  setComponentId(id) {
1710
1675
  set({ componentId: id });
1711
1676
  },
@@ -1715,6 +1680,18 @@ const useDraggedItemStore = create((set) => ({
1715
1680
  setDraggingOnCanvas: (isDraggingOnCanvas) => {
1716
1681
  set({ isDraggingOnCanvas });
1717
1682
  },
1683
+ setOnBeforeCaptureId: (onBeforeCaptureId) => {
1684
+ set({ onBeforeCaptureId });
1685
+ },
1686
+ setMousePosition(x, y) {
1687
+ set({ mouseX: x, mouseY: y });
1688
+ },
1689
+ setDomRect(domRect) {
1690
+ set({ domRect });
1691
+ },
1692
+ setScrollY(y) {
1693
+ set({ scrollY: y });
1694
+ },
1718
1695
  }));
1719
1696
 
1720
1697
  const DRAGGABLE_HEIGHT = 30;
@@ -1722,7 +1699,9 @@ const DRAGGABLE_WIDTH = 50;
1722
1699
  const DRAG_PADDING = 4;
1723
1700
  const ROOT_ID = 'root';
1724
1701
  const COMPONENT_LIST_ID = 'component-list';
1702
+ const NEW_COMPONENT_ID = 'ctfl-new-draggable';
1725
1703
  const CTFL_ZONE_ID = 'data-ctfl-zone-id';
1704
+ const CTFL_DRAGGING_ELEMENT = 'data-ctfl-dragging-element';
1726
1705
  const HITBOX = {
1727
1706
  WIDTH: 80,
1728
1707
  HEIGHT: 20,
@@ -1756,6 +1735,11 @@ var HitboxDirection;
1756
1735
  HitboxDirection[HitboxDirection["SELF_VERTICAL"] = 4] = "SELF_VERTICAL";
1757
1736
  HitboxDirection[HitboxDirection["SELF_HORIZONTAL"] = 5] = "SELF_HORIZONTAL";
1758
1737
  })(HitboxDirection || (HitboxDirection = {}));
1738
+ var DraggablePosition;
1739
+ (function (DraggablePosition) {
1740
+ DraggablePosition[DraggablePosition["CENTERED"] = 0] = "CENTERED";
1741
+ DraggablePosition[DraggablePosition["MOUSE_POSITION"] = 1] = "MOUSE_POSITION";
1742
+ })(DraggablePosition || (DraggablePosition = {}));
1759
1743
 
1760
1744
  /**
1761
1745
  * Calculate the size and position of the dropzone indicator
@@ -1859,6 +1843,28 @@ const Placeholder = (props) => {
1859
1843
  } })));
1860
1844
  };
1861
1845
 
1846
+ function useDraggablePosition({ draggableId, draggableRef, position }) {
1847
+ const isDraggingOnCanvas = useDraggedItemStore((state) => state.isDraggingOnCanvas);
1848
+ const draggingId = useDraggedItemStore((state) => state.onBeforeCaptureId);
1849
+ const preDragDomRect = useDraggedItemStore((state) => state.domRect);
1850
+ useEffect(() => {
1851
+ const el = draggableRef?.current;
1852
+ if (!isDraggingOnCanvas || draggingId !== draggableId || !el) {
1853
+ return;
1854
+ }
1855
+ const isCentered = position === DraggablePosition.CENTERED || !preDragDomRect;
1856
+ const domRect = isCentered ? el.getBoundingClientRect() : preDragDomRect;
1857
+ const { mouseX, mouseY } = useDraggedItemStore.getState();
1858
+ const top = isCentered ? mouseY - domRect.height / 2 : domRect.top;
1859
+ const left = isCentered ? mouseX - domRect.width / 2 : domRect.left;
1860
+ el.style.position = 'fixed';
1861
+ el.style.left = `${left}px`;
1862
+ el.style.top = `${top}px`;
1863
+ el.style.width = `${domRect.width}px`;
1864
+ el.style.height = `${domRect.height}px`;
1865
+ }, [draggableRef, draggableId, isDraggingOnCanvas, draggingId, position, preDragDomRect]);
1866
+ }
1867
+
1862
1868
  function getStyle$2(style, snapshot) {
1863
1869
  if (!snapshot.isDropAnimating) {
1864
1870
  return style;
@@ -1869,8 +1875,18 @@ function getStyle$2(style, snapshot) {
1869
1875
  transitionDuration: `0.001s`,
1870
1876
  };
1871
1877
  }
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, {
1878
+ const DraggableComponent = ({ children, id, index, isAssemblyBlock = false, isSelected = false, onClick = () => null, coordinates, userIsDragging, style, wrapperProps, isContainer, blockId, isDragDisabled = false, placeholder, definition, ...rest }) => {
1879
+ const ref = useRef(null);
1880
+ const setDomRect = useDraggedItemStore((state) => state.setDomRect);
1881
+ useDraggablePosition({
1882
+ draggableId: id,
1883
+ draggableRef: ref,
1884
+ position: DraggablePosition.MOUSE_POSITION,
1885
+ });
1886
+ 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) => {
1887
+ provided?.innerRef(refNode);
1888
+ ref.current = refNode;
1889
+ }, ...wrapperProps, ...provided.draggableProps, ...provided.dragHandleProps, ...rest, className: classNames(styles$3.DraggableComponent, wrapperProps.className, {
1874
1890
  [styles$3.isAssemblyBlock]: isAssemblyBlock,
1875
1891
  [styles$3.isDragging]: snapshot.isDragging,
1876
1892
  [styles$3.isSelected]: isSelected,
@@ -1878,8 +1894,14 @@ const DraggableComponent = ({ children, id, index, isAssemblyBlock = false, isSe
1878
1894
  }), style: {
1879
1895
  ...style,
1880
1896
  ...getStyle$2(provided.draggableProps.style, snapshot),
1897
+ }, onMouseDown: (e) => {
1898
+ if (isDragDisabled) {
1899
+ return;
1900
+ }
1901
+ e.stopPropagation();
1902
+ setDomRect(e.currentTarget.getBoundingClientRect());
1881
1903
  }, onClick: onClick },
1882
- React.createElement(Tooltip, { id: id, coordinates: coordinates, isAssemblyBlock: isAssemblyBlock, isContainer: isContainer, label: label }),
1904
+ React.createElement(Tooltip, { id: id, coordinates: coordinates, isAssemblyBlock: isAssemblyBlock, isContainer: isContainer, label: definition.name || 'No label specified' }),
1883
1905
  React.createElement(Placeholder, { ...placeholder, id: id }),
1884
1906
  children))));
1885
1907
  };
@@ -2061,14 +2083,10 @@ const useEntityStore = create((set) => ({
2061
2083
  const useComponentProps = ({ node, areEntitiesFetched, resolveDesignValue, renderDropzone, definition, userIsDragging, }) => {
2062
2084
  const unboundValues = useEditorStore((state) => state.unboundValues);
2063
2085
  const dataSource = useEditorStore((state) => state.dataSource);
2064
- const newComponentId = useDraggedItemStore((state) => state.componentId);
2065
- const isDraggingNewCompont = !!newComponentId;
2066
2086
  const entityStore = useEntityStore((state) => state.entityStore);
2067
2087
  const props = useMemo(() => {
2068
2088
  // 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) {
2089
+ if (!definition || node.type === ASSEMBLY_NODE_TYPE) {
2072
2090
  return {};
2073
2091
  }
2074
2092
  return Object.entries(definition.variables).reduce((acc, [variableName, variableDefinition]) => {
@@ -2195,7 +2213,6 @@ const useComponentProps = ({ node, areEntitiesFetched, resolveDesignValue, rende
2195
2213
  minHeight: EMPTY_CONTAINER_HEIGHT,
2196
2214
  }),
2197
2215
  ...(userIsDragging &&
2198
- isDraggingNewCompont &&
2199
2216
  isContentfulStructureComponent(node?.data.blockId) &&
2200
2217
  node?.data.blockId !== CONTENTFUL_COMPONENTS.columns.id && {
2201
2218
  padding: addExtraDropzonePadding(componentStyles.padding?.toString() || '0 0 0 0'),
@@ -2367,7 +2384,7 @@ const deserializeAssemblyNode = ({ node, nodeId, nodeLocation, parentId, assembl
2367
2384
  };
2368
2385
  };
2369
2386
  const resolveAssembly = ({ node, entityStore, }) => {
2370
- if (node.type !== DESIGN_COMPONENT_NODE_TYPE && node.type !== ASSEMBLY_NODE_TYPE) {
2387
+ if (node.type !== ASSEMBLY_NODE_TYPE) {
2371
2388
  return node;
2372
2389
  }
2373
2390
  const componentId = node.data.blockId;
@@ -2378,7 +2395,9 @@ const resolveAssembly = ({ node, entityStore, }) => {
2378
2395
  });
2379
2396
  return node;
2380
2397
  }
2381
- const componentFields = entityStore?.getValue(assembly, ['fields']);
2398
+ const componentFields = entityStore?.getValue(assembly, [
2399
+ 'fields',
2400
+ ]);
2382
2401
  if (!componentFields) {
2383
2402
  console.warn(`Entry for assembly with ID '${componentId}' not found`, { entityStore });
2384
2403
  return node;
@@ -2412,8 +2431,7 @@ const useComponent = ({ node: rawNode, resolveDesignValue, renderDropzone, userI
2412
2431
  const areEntitiesFetched = useEntityStore((state) => state.areEntitiesFetched);
2413
2432
  const entityStore = useEntityStore((state) => state.entityStore);
2414
2433
  const node = useMemo(() => {
2415
- if ((rawNode.type === DESIGN_COMPONENT_NODE_TYPE || rawNode.type === ASSEMBLY_NODE_TYPE) &&
2416
- areEntitiesFetched) {
2434
+ if (rawNode.type === ASSEMBLY_NODE_TYPE && areEntitiesFetched) {
2417
2435
  return resolveAssembly({
2418
2436
  node: rawNode,
2419
2437
  entityStore,
@@ -2423,8 +2441,7 @@ const useComponent = ({ node: rawNode, resolveDesignValue, renderDropzone, userI
2423
2441
  }, [areEntitiesFetched, rawNode, entityStore]);
2424
2442
  const componentRegistration = useMemo(() => {
2425
2443
  const registration = componentRegistry.get(node.data.blockId);
2426
- if ((node.type === DESIGN_COMPONENT_NODE_TYPE || node.type === ASSEMBLY_NODE_TYPE) &&
2427
- !registration) {
2444
+ if (node.type === ASSEMBLY_NODE_TYPE && !registration) {
2428
2445
  return createAssemblyRegistration({
2429
2446
  definitionId: node.data.blockId,
2430
2447
  component: Assembly,
@@ -2448,7 +2465,7 @@ const useComponent = ({ node: rawNode, resolveDesignValue, renderDropzone, userI
2448
2465
  const { editorMode, renderDropzone: _renderDropzone, ...otherComponentProps } = componentProps;
2449
2466
  const elementToRender = builtInComponents.includes(node.data.blockId || '')
2450
2467
  ? (dragProps) => React.createElement(componentRegistration.component, { ...dragProps, ...componentProps })
2451
- : node.type === DESIGN_COMPONENT_NODE_TYPE || node.type === ASSEMBLY_NODE_TYPE
2468
+ : node.type === ASSEMBLY_NODE_TYPE
2452
2469
  ? // Assembly.tsx requires renderDropzone and editorMode as well
2453
2470
  () => React.createElement(componentRegistration.component, componentProps)
2454
2471
  : () => React.createElement(componentRegistration.component, otherComponentProps);
@@ -2457,7 +2474,7 @@ const useComponent = ({ node: rawNode, resolveDesignValue, renderDropzone, userI
2457
2474
  componentId,
2458
2475
  elementToRender,
2459
2476
  wrapperProps,
2460
- label: componentRegistration.definition.name,
2477
+ definition: componentRegistration.definition,
2461
2478
  };
2462
2479
  };
2463
2480
 
@@ -2471,7 +2488,7 @@ const useComponent = ({ node: rawNode, resolveDesignValue, renderDropzone, userI
2471
2488
  * component.
2472
2489
  */
2473
2490
  const DraggableChildComponent = (props) => {
2474
- const { elementToRender, id, index, isAssemblyBlock = false, isSelected = false, onClick = () => null, label, coordinates, userIsDragging, style, isContainer, blockId, isDragDisabled = false, wrapperProps, } = props;
2491
+ const { elementToRender, id, index, isAssemblyBlock = false, isSelected = false, onClick = () => null, coordinates, userIsDragging, style, isContainer, blockId, isDragDisabled = false, wrapperProps, definition, } = props;
2475
2492
  return (React.createElement(Draggable, { key: id, draggableId: id, index: index, isDragDisabled: isDragDisabled }, (provided, snapshot) => elementToRender({
2476
2493
  ['data-ctfl-draggable-id']: id,
2477
2494
  ['data-test-id']: `draggable-${blockId}`,
@@ -2490,11 +2507,11 @@ const DraggableChildComponent = (props) => {
2490
2507
  ...provided.draggableProps.style,
2491
2508
  },
2492
2509
  onClick,
2493
- Tooltip: (React.createElement(Tooltip, { id: id, coordinates: coordinates, isAssemblyBlock: isAssemblyBlock, isContainer: isContainer, label: label })),
2510
+ Tooltip: (React.createElement(Tooltip, { id: id, coordinates: coordinates, isAssemblyBlock: isAssemblyBlock, isContainer: isContainer, label: definition.name || 'No label specified' })),
2494
2511
  })));
2495
2512
  };
2496
2513
 
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";
2514
+ 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
2515
  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
2516
  styleInject(css_248z$2);
2500
2517
 
@@ -2755,7 +2772,7 @@ function treeVisit(initialNode, onNode) {
2755
2772
  }
2756
2773
 
2757
2774
  const isAssemblyNode = (node) => {
2758
- return node.type === DESIGN_COMPONENT_NODE_TYPE || node.type === ASSEMBLY_NODE_TYPE;
2775
+ return node.type === ASSEMBLY_NODE_TYPE;
2759
2776
  };
2760
2777
  const useTreeStore = create((set, get) => ({
2761
2778
  tree: {
@@ -2901,7 +2918,7 @@ const getHitboxStyles = ({ direction, zoneDepth, domRect }) => {
2901
2918
  return {
2902
2919
  width,
2903
2920
  height: HEIGHT,
2904
- top: top - calcOffsetDepth(zoneDepth),
2921
+ top: top - calcOffsetDepth(zoneDepth) - scrollY,
2905
2922
  left,
2906
2923
  zIndex: 100 + zoneDepth,
2907
2924
  };
@@ -2909,7 +2926,7 @@ const getHitboxStyles = ({ direction, zoneDepth, domRect }) => {
2909
2926
  return {
2910
2927
  width,
2911
2928
  height: HEIGHT,
2912
- top: bottom + calcOffsetDepth(zoneDepth),
2929
+ top: bottom + calcOffsetDepth(zoneDepth) - scrollY,
2913
2930
  left,
2914
2931
  zIndex: 100 + zoneDepth,
2915
2932
  };
@@ -2918,7 +2935,7 @@ const getHitboxStyles = ({ direction, zoneDepth, domRect }) => {
2918
2935
  width: WIDTH,
2919
2936
  height: height - HEIGHT,
2920
2937
  left: left - calcOffsetDepth(zoneDepth) - WIDTH / 2,
2921
- top: top + HEIGHT / 2,
2938
+ top: top + HEIGHT / 2 - scrollY,
2922
2939
  zIndex: 100 + zoneDepth,
2923
2940
  };
2924
2941
  case HitboxDirection.RIGHT:
@@ -2926,7 +2943,7 @@ const getHitboxStyles = ({ direction, zoneDepth, domRect }) => {
2926
2943
  width: WIDTH,
2927
2944
  height: height - HEIGHT,
2928
2945
  left: right - calcOffsetDepth(zoneDepth) - WIDTH / 2,
2929
- top: top + HEIGHT / 2,
2946
+ top: top + HEIGHT / 2 - scrollY,
2930
2947
  zIndex: 100 + zoneDepth,
2931
2948
  };
2932
2949
  case HitboxDirection.SELF_VERTICAL: {
@@ -2938,7 +2955,7 @@ const getHitboxStyles = ({ direction, zoneDepth, domRect }) => {
2938
2955
  width,
2939
2956
  height: selfHeight,
2940
2957
  left,
2941
- top: top + height / 2 - selfHeight / 2,
2958
+ top: top + height / 2 - selfHeight / 2 - scrollY,
2942
2959
  zIndex: 1000 + zoneDepth,
2943
2960
  };
2944
2961
  }
@@ -2950,7 +2967,7 @@ const getHitboxStyles = ({ direction, zoneDepth, domRect }) => {
2950
2967
  width: width - DRAGGABLE_WIDTH * 2,
2951
2968
  height,
2952
2969
  left: left + (DRAGGABLE_WIDTH * 2) / 2,
2953
- top,
2970
+ top: top - scrollY,
2954
2971
  zIndex: 1000 + zoneDepth,
2955
2972
  };
2956
2973
  }
@@ -2962,6 +2979,7 @@ const getHitboxStyles = ({ direction, zoneDepth, domRect }) => {
2962
2979
  const Hitboxes = ({ zoneId, parentZoneId, enableRootHitboxes }) => {
2963
2980
  const tree = useTreeStore((state) => state.tree);
2964
2981
  const isDraggingOnCanvas = useDraggedItemStore((state) => state.isDraggingOnCanvas);
2982
+ const scrollY = useDraggedItemStore((state) => state.scrollY);
2965
2983
  const zoneDepth = useMemo(() => getItemDepthFromNode({ id: parentZoneId }, tree.root), [tree, parentZoneId]);
2966
2984
  const [fetchDomRect, setFetchDomRect] = useState(Date.now());
2967
2985
  useEffect(() => {
@@ -2987,10 +3005,11 @@ const Hitboxes = ({ zoneId, parentZoneId, enableRootHitboxes }) => {
2987
3005
  const isVertical = zoneDirection === 'vertical';
2988
3006
  const isRoot = parentZoneId === ROOT_ID;
2989
3007
  const showRootHitboxes = isRoot && enableRootHitboxes;
2990
- const getStyles = useCallback((direction) => getHitboxStyles({ direction, zoneDepth, domRect }), [zoneDepth, domRect]);
3008
+ const getStyles = useCallback((direction) => getHitboxStyles({ direction, zoneDepth, domRect, scrollY }), [zoneDepth, domRect, scrollY]);
2991
3009
  const ActiveHitboxes = (React.createElement(React.Fragment, null,
2992
3010
  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,
3011
+ showRootHitboxes && (React.createElement("div", { "data-ctfl-zone-id": parentZoneId, className: styles$2.hitbox, style: getStyles(HitboxDirection.BOTTOM) })),
3012
+ !isRoot && (React.createElement(React.Fragment, null,
2994
3013
  React.createElement("div", { "data-ctfl-zone-id": parentZoneId, className: styles$2.hitbox, style: getStyles(isVertical ? HitboxDirection.TOP : HitboxDirection.LEFT) }),
2995
3014
  React.createElement("div", { "data-ctfl-zone-id": parentZoneId, className: styles$2.hitbox, style: getStyles(isVertical ? HitboxDirection.BOTTOM : HitboxDirection.RIGHT) })))));
2996
3015
  if (!hitboxContainer) {
@@ -3002,7 +3021,7 @@ const Hitboxes = ({ zoneId, parentZoneId, enableRootHitboxes }) => {
3002
3021
  const EditorBlock = ({ node: rawNode, resolveDesignValue, renderDropzone, draggingNewComponent, index, zoneId, userIsDragging, placeholder, }) => {
3003
3022
  const setSelectedNodeId = useEditorStore((state) => state.setSelectedNodeId);
3004
3023
  const selectedNodeId = useEditorStore((state) => state.selectedNodeId);
3005
- const { node, componentId, wrapperProps, label, elementToRender } = useComponent({
3024
+ const { node, componentId, wrapperProps, definition, elementToRender } = useComponent({
3006
3025
  node: rawNode,
3007
3026
  resolveDesignValue,
3008
3027
  renderDropzone,
@@ -3015,7 +3034,7 @@ const EditorBlock = ({ node: rawNode, resolveDesignValue, renderDropzone, draggi
3015
3034
  const isAssembly = node.type === ASSEMBLY_NODE_TYPE;
3016
3035
  const isStructureComponent = isContentfulStructureComponent(node.data.blockId);
3017
3036
  const isRootComponent = zoneId === ROOT_ID;
3018
- const enableRootHitboxes = isRootComponent && !draggingNewComponent;
3037
+ const enableRootHitboxes = isRootComponent && !!draggingNewComponent;
3019
3038
  const onClick = (e) => {
3020
3039
  e.stopPropagation();
3021
3040
  if (!userIsDragging) {
@@ -3035,10 +3054,10 @@ const EditorBlock = ({ node: rawNode, resolveDesignValue, renderDropzone, draggi
3035
3054
  };
3036
3055
  if (node.data.blockId === CONTENTFUL_COMPONENTS.singleColumn.id) {
3037
3056
  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 }),
3057
+ 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
3058
  isStructureComponent && userIsDragging && (React.createElement(Hitboxes, { parentZoneId: zoneId, zoneId: componentId, enableRootHitboxes: enableRootHitboxes }))));
3040
3059
  }
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 },
3060
+ 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
3061
  elementToRender(),
3043
3062
  isStructureComponent && userIsDragging && (React.createElement(Hitboxes, { parentZoneId: zoneId, zoneId: componentId, enableRootHitboxes: enableRootHitboxes }))));
3044
3063
  };
@@ -3057,7 +3076,7 @@ const EmptyContainer = ({ isDragging }) => {
3057
3076
  React.createElement("rect", { width: "11.676", height: "11.676", x: "18.011", y: "18.625", rx: "1.621", transform: "rotate(45 18.01 18.625)" }),
3058
3077
  React.createElement("rect", { width: "11.676", height: "11.676", x: "30.557", y: "10.131", rx: "1.621", transform: "rotate(60 30.557 10.13)" }),
3059
3078
  React.createElement("path", { fill: "#fff", stroke: "#fff", strokeWidth: ".243", d: "M31.113 17.038a.463.463 0 0 0-.683-.517l-1.763 1.032-1.033-1.763a.464.464 0 0 0-.8.469l1.034 1.763-1.763 1.033a.463.463 0 1 0 .468.8l1.763-1.033 1.033 1.763a.463.463 0 1 0 .8-.469l-1.033-1.763 1.763-1.033a.463.463 0 0 0 .214-.282Z" })),
3060
- React.createElement("span", { className: styles$1.label }, "Add elements to begin")));
3079
+ React.createElement("span", { className: styles$1.label }, "Add components to begin")));
3061
3080
  };
3062
3081
 
3063
3082
  const getZoneParents = (zoneId) => {
@@ -3133,7 +3152,7 @@ const EditorBlockClone = ({ node: rawNode, resolveDesignValue, snapshot, provide
3133
3152
  if (isSingleColumn) {
3134
3153
  return elementToRender();
3135
3154
  }
3136
- return (React.createElement("div", { ref: provided?.innerRef, ...wrapperProps, ...provided?.draggableProps, ...provided?.dragHandleProps, className: classNames(styles$3.DraggableComponent, wrapperProps.className, {
3155
+ 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
3156
  [styles$3.isAssemblyBlock]: isAssemblyBlock,
3138
3157
  [styles$3.isDragging]: snapshot?.isDragging,
3139
3158
  }), style: getStyle$1(provided?.draggableProps.style, snapshot) }, elementToRender()));
@@ -3170,8 +3189,7 @@ function Dropzone({ node, zoneId, resolveDesignValue, className, WrapperComponen
3170
3189
  const isRootZone = zoneId === ROOT_ID;
3171
3190
  const isDestination = draggedDestinationId === zoneId;
3172
3191
  const isEmptyCanvas = isRootZone && !content.length;
3173
- const isAssembly = DESIGN_COMPONENT_NODE_TYPES.includes(node?.type || '') ||
3174
- ASSEMBLY_NODE_TYPES.includes(node?.type || '');
3192
+ const isAssembly = ASSEMBLY_NODE_TYPES.includes(node?.type || '');
3175
3193
  // To avoid a circular dependency, we create the recursive rendering function here and trickle it down
3176
3194
  const renderDropzone = useCallback((node, props) => {
3177
3195
  return (React.createElement(Dropzone, { zoneId: node.data.id, node: node, resolveDesignValue: resolveDesignValue, ...props }));
@@ -3182,13 +3200,30 @@ function Dropzone({ node, zoneId, resolveDesignValue, className, WrapperComponen
3182
3200
  if (!resolveDesignValue) {
3183
3201
  return null;
3184
3202
  }
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)
3203
+ /**
3204
+ * The Rules of Dropzones
3205
+ *
3206
+ * 1. A dropzone is disabled unless the mouse is hovering over it
3207
+ *
3208
+ * 2. Dragging a new component onto the canvas has no addtional rules
3209
+ * besides rule #1
3210
+ *
3211
+ * 3. Dragging a component that is a direct descendant of the root
3212
+ * (parentId === ROOT_ID) then only the Root Dropzone is enabled
3213
+ *
3214
+ * 4. Dragging a nested component (parentId !== ROOT_ID) then the Root
3215
+ * Dropzone is disabled, all other Dropzones follow rule #1
3216
+ *
3217
+ * 5. Assemblies and the SingleColumn component are always disabled
3218
+ *
3219
+ */
3188
3220
  const isDropzoneEnabled = () => {
3189
3221
  if (node?.data.blockId === CONTENTFUL_COMPONENTS.columns.id) {
3190
3222
  return false;
3191
3223
  }
3224
+ if (isAssembly) {
3225
+ return false;
3226
+ }
3192
3227
  if (isDraggingNewComponent) {
3193
3228
  return isHoveringZone;
3194
3229
  }
@@ -3231,6 +3266,12 @@ function getStyle(style, snapshot) {
3231
3266
  };
3232
3267
  }
3233
3268
  const DraggableContainer = ({ id }) => {
3269
+ const ref = useRef(null);
3270
+ useDraggablePosition({
3271
+ draggableId: id,
3272
+ draggableRef: ref,
3273
+ position: DraggablePosition.CENTERED,
3274
+ });
3234
3275
  return (React.createElement("div", { id: COMPONENT_LIST_ID, style: {
3235
3276
  position: 'absolute',
3236
3277
  top: 0,
@@ -3239,7 +3280,10 @@ const DraggableContainer = ({ id }) => {
3239
3280
  zIndex: -1,
3240
3281
  } },
3241
3282
  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: {
3283
+ 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) => {
3284
+ provided.innerRef(node);
3285
+ ref.current = node;
3286
+ }, ...provided.draggableProps, ...provided.dragHandleProps, style: {
3243
3287
  ...getStyle(provided.draggableProps.style, snapshot),
3244
3288
  width: DRAGGABLE_WIDTH,
3245
3289
  height: DRAGGABLE_HEIGHT,
@@ -3407,8 +3451,7 @@ class MouseOverHandler {
3407
3451
  };
3408
3452
  }
3409
3453
  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;
3454
+ const isAssembly = element.getAttribute('data-cf-node-block-type') === ASSEMBLY_NODE_TYPE;
3412
3455
  if (!isAssembly) {
3413
3456
  return element.getBoundingClientRect();
3414
3457
  }
@@ -3459,39 +3502,74 @@ const sendHoveredComponentCoordinates = (instanceId) => {
3459
3502
  mouseOverHandler.handleMouseMove(selectedElement || null);
3460
3503
  };
3461
3504
 
3462
- function updateDraggableElement(x, y) {
3463
- const container = document.querySelector('#component-list');
3464
- if (!container) {
3465
- return;
3505
+ class DragState {
3506
+ constructor() {
3507
+ this.isDragStartedOnParent = false;
3508
+ this.isDraggingItem = false;
3509
+ }
3510
+ get isDragging() {
3511
+ return this.isDraggingItem;
3512
+ }
3513
+ get isDraggingOnParent() {
3514
+ return this.isDragStartedOnParent;
3515
+ }
3516
+ updateIsDragging(isDraggingItem) {
3517
+ this.isDraggingItem = isDraggingItem;
3518
+ }
3519
+ updateIsDragStartedOnParent(isDragStartedOnParent) {
3520
+ this.isDragStartedOnParent = isDragStartedOnParent;
3521
+ }
3522
+ resetState() {
3523
+ this.isDraggingItem = false;
3524
+ this.isDragStartedOnParent = false;
3466
3525
  }
3467
- container.style.setProperty('top', `${y}px`);
3468
- container.style.setProperty('left', `${x}px`);
3469
3526
  }
3470
- function simulateMouseEvent(coordX, coordY, eventName = 'mousemove') {
3471
- const element = document.querySelector('#item');
3472
- if (!dragState.isDragStart) {
3473
- return;
3527
+
3528
+ class SimulateDnD extends DragState {
3529
+ constructor() {
3530
+ super();
3531
+ this.draggingElement = null;
3474
3532
  }
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;
3533
+ setupDrag() {
3534
+ this.updateIsDragStartedOnParent(true);
3535
+ }
3536
+ startDrag(coordX, coordY) {
3537
+ this.draggingElement = document.getElementById(NEW_COMPONENT_ID);
3538
+ this.updateIsDragging(true);
3539
+ this.simulateMouseEvent(coordX, coordY, 'mousedown');
3540
+ }
3541
+ updateDrag(coordX, coordY) {
3542
+ if (!this.draggingElement) {
3543
+ this.draggingElement = document.querySelector(`[${CTFL_DRAGGING_ELEMENT}]`);
3544
+ }
3545
+ this.simulateMouseEvent(coordX, coordY);
3546
+ }
3547
+ endDrag(coordX, coordY) {
3548
+ this.simulateMouseEvent(coordX, coordY, 'mouseup');
3549
+ this.reset();
3550
+ }
3551
+ reset() {
3552
+ this.draggingElement = null;
3553
+ this.resetState();
3554
+ }
3555
+ simulateMouseEvent(coordX, coordY, eventName = 'mousemove') {
3556
+ if (!this.draggingElement) {
3557
+ return;
3558
+ }
3559
+ const options = {
3560
+ bubbles: true,
3561
+ cancelable: true,
3562
+ view: window,
3563
+ pageX: 0,
3564
+ pageY: 0,
3565
+ clientX: coordX,
3566
+ clientY: coordY,
3567
+ };
3568
+ const event = new MouseEvent(eventName, options);
3569
+ this.draggingElement.dispatchEvent(event);
3491
3570
  }
3492
- const event = new MouseEvent(eventName, options);
3493
- element.dispatchEvent(event);
3494
3571
  }
3572
+ var SimulateDnD$1 = new SimulateDnD();
3495
3573
 
3496
3574
  function useEditorSubscriber() {
3497
3575
  const entityStore = useEntityStore((state) => state.entityStore);
@@ -3510,6 +3588,8 @@ function useEditorSubscriber() {
3510
3588
  const selectedNodeId = useEditorStore((state) => state.selectedNodeId);
3511
3589
  const setComponentId = useDraggedItemStore((state) => state.setComponentId);
3512
3590
  const setDraggingOnCanvas = useDraggedItemStore((state) => state.setDraggingOnCanvas);
3591
+ const setMousePosition = useDraggedItemStore((state) => state.setMousePosition);
3592
+ const setScrollY = useDraggedItemStore((state) => state.setScrollY);
3513
3593
  // TODO: As we have disabled the useEffect, we can remove these states
3514
3594
  const [, /* isFetchingEntities */ setFetchingEntities] = useState(false);
3515
3595
  const reloadApp = () => {
@@ -3623,7 +3703,7 @@ function useEditorSubscriber() {
3623
3703
  console.debug(`[experiences-sdk-react::onMessage] Received message [${eventData.eventType}]`, eventData);
3624
3704
  const { payload } = eventData;
3625
3705
  switch (eventData.eventType) {
3626
- case INCOMING_EVENTS.CompositionUpdated: {
3706
+ case INCOMING_EVENTS.ExperienceUpdated: {
3627
3707
  const { tree, locale, changedNode, changedValueType, assemblies, } = payload;
3628
3708
  // Make sure to first store the assemblies before setting the tree and thus triggering a rerender
3629
3709
  if (assemblies) {
@@ -3666,9 +3746,6 @@ function useEditorSubscriber() {
3666
3746
  }
3667
3747
  break;
3668
3748
  }
3669
- case INCOMING_EVENTS.DesignComponentsRegistered:
3670
- // Event was deprecated and support will be discontinued with version 5
3671
- break;
3672
3749
  case INCOMING_EVENTS.AssembliesRegistered: {
3673
3750
  const { assemblies } = payload;
3674
3751
  assemblies.forEach((definition) => {
@@ -3679,9 +3756,6 @@ function useEditorSubscriber() {
3679
3756
  });
3680
3757
  break;
3681
3758
  }
3682
- case INCOMING_EVENTS.DesignComponentsAdded:
3683
- // Event was deprecated and support will be discontinued with version 5
3684
- break;
3685
3759
  case INCOMING_EVENTS.AssembliesAdded: {
3686
3760
  const { assembly, assemblyDefinition, } = payload;
3687
3761
  entityStore.updateEntity(assembly);
@@ -3700,6 +3774,10 @@ function useEditorSubscriber() {
3700
3774
  break;
3701
3775
  }
3702
3776
  case INCOMING_EVENTS.CanvasResized: {
3777
+ const { selectedNodeId } = payload;
3778
+ if (selectedNodeId) {
3779
+ sendSelectedComponentCoordinates(selectedNodeId);
3780
+ }
3703
3781
  break;
3704
3782
  }
3705
3783
  case INCOMING_EVENTS.HoverComponent: {
@@ -3712,7 +3790,7 @@ function useEditorSubscriber() {
3712
3790
  if (!isDragging) {
3713
3791
  setComponentId('');
3714
3792
  setDraggingOnCanvas(false);
3715
- dragState.reset();
3793
+ SimulateDnD$1.reset();
3716
3794
  }
3717
3795
  break;
3718
3796
  }
@@ -3733,23 +3811,23 @@ function useEditorSubscriber() {
3733
3811
  break;
3734
3812
  }
3735
3813
  case INCOMING_EVENTS.ComponentDragCanceled: {
3736
- if (dragState.isDragging) {
3814
+ if (SimulateDnD$1.isDragging) {
3737
3815
  //simulate a mouseup event to cancel the drag
3738
- simulateMouseEvent(0, 0, 'mouseup');
3816
+ SimulateDnD$1.endDrag(0, 0);
3739
3817
  }
3740
3818
  break;
3741
3819
  }
3742
3820
  case INCOMING_EVENTS.ComponentDragStarted: {
3743
- dragState.updateIsDragStartedOnParent(true);
3744
- setDraggingOnCanvas(true);
3821
+ SimulateDnD$1.setupDrag();
3745
3822
  setComponentId(payload.id || '');
3823
+ setDraggingOnCanvas(true);
3746
3824
  sendMessage(OUTGOING_EVENTS.ComponentSelected, {
3747
3825
  nodeId: '',
3748
3826
  });
3749
3827
  break;
3750
3828
  }
3751
3829
  case INCOMING_EVENTS.ComponentDragEnded: {
3752
- dragState.reset();
3830
+ SimulateDnD$1.reset();
3753
3831
  setComponentId('');
3754
3832
  setDraggingOnCanvas(false);
3755
3833
  break;
@@ -3760,6 +3838,22 @@ function useEditorSubscriber() {
3760
3838
  sendSelectedComponentCoordinates(nodeId);
3761
3839
  break;
3762
3840
  }
3841
+ case INCOMING_EVENTS.MouseMove: {
3842
+ const { mouseX, mouseY } = payload;
3843
+ setMousePosition(mouseX, mouseY);
3844
+ if (SimulateDnD$1.isDraggingOnParent && !SimulateDnD$1.isDragging) {
3845
+ SimulateDnD$1.startDrag(mouseX, mouseY);
3846
+ }
3847
+ else {
3848
+ SimulateDnD$1.updateDrag(mouseX, mouseY);
3849
+ }
3850
+ break;
3851
+ }
3852
+ case INCOMING_EVENTS.ComponentMoveEnded: {
3853
+ const { mouseX, mouseY } = payload;
3854
+ SimulateDnD$1.endDrag(mouseX, mouseY);
3855
+ break;
3856
+ }
3763
3857
  default:
3764
3858
  console.error(`[experiences-sdk-react::onMessage] Logic error, unsupported eventType: [${eventData.eventType}]`);
3765
3859
  }
@@ -3782,6 +3876,7 @@ function useEditorSubscriber() {
3782
3876
  unboundValues,
3783
3877
  updateTree,
3784
3878
  updateNodesByUpdatedEntity,
3879
+ setMousePosition,
3785
3880
  ]);
3786
3881
  /*
3787
3882
  * Handles on scroll business
@@ -3790,6 +3885,7 @@ function useEditorSubscriber() {
3790
3885
  let timeoutId = 0;
3791
3886
  let isScrolling = false;
3792
3887
  const onScroll = () => {
3888
+ setScrollY(window.scrollY);
3793
3889
  if (isScrolling === false) {
3794
3890
  sendMessage(OUTGOING_EVENTS.CanvasScroll, SCROLL_STATES.Start);
3795
3891
  }
@@ -3815,7 +3911,7 @@ function useEditorSubscriber() {
3815
3911
  window.removeEventListener('scroll', onScroll, { capture: true });
3816
3912
  clearTimeout(timeoutId);
3817
3913
  };
3818
- }, [selectedNodeId]);
3914
+ }, [selectedNodeId, setScrollY]);
3819
3915
  }
3820
3916
 
3821
3917
  const onComponentMoved = (options) => {
@@ -3978,30 +4074,36 @@ const TestDNDContainer = ({ onDragEnd, onBeforeDragStart, onDragUpdate, children
3978
4074
  const DNDProvider = ({ children }) => {
3979
4075
  const setSelectedNodeId = useEditorStore((state) => state.setSelectedNodeId);
3980
4076
  const draggedItem = useDraggedItemStore((state) => state.draggedItem);
4077
+ const setOnBeforeCaptureId = useDraggedItemStore((state) => state.setOnBeforeCaptureId);
3981
4078
  const setDraggingOnCanvas = useDraggedItemStore((state) => state.setDraggingOnCanvas);
3982
4079
  const updateItem = useDraggedItemStore((state) => state.updateItem);
3983
4080
  const { onAddComponent, onMoveComponent } = useCanvasInteractions();
3984
4081
  const selectedNodeId = useEditorStore((state) => state.selectedNodeId);
3985
4082
  const prevSelectedNodeId = useRef(null);
3986
4083
  const isTestRun = typeof window !== 'undefined' && Object.prototype.hasOwnProperty.call(window, 'Cypress');
3987
- const dragStart = () => {
4084
+ const dragStart = ({ source }) => {
3988
4085
  prevSelectedNodeId.current = selectedNodeId;
3989
4086
  //Unselect the current node when dragging and remove the outline
3990
4087
  setSelectedNodeId('');
3991
4088
  sendMessage(OUTGOING_EVENTS.ComponentSelected, {
3992
4089
  nodeId: '',
3993
4090
  });
4091
+ if (source.droppableId !== COMPONENT_LIST_ID) {
4092
+ sendMessage(OUTGOING_EVENTS.ComponentMoveStarted);
4093
+ }
3994
4094
  };
3995
- const beforeCapture = () => {
4095
+ const beforeCapture = ({ draggableId }) => {
3996
4096
  setDraggingOnCanvas(true);
4097
+ setOnBeforeCaptureId(draggableId);
3997
4098
  };
3998
4099
  const dragUpdate = (update) => {
3999
4100
  updateItem(update);
4000
4101
  };
4001
4102
  const dragEnd = (dropResult) => {
4002
4103
  setDraggingOnCanvas(false);
4104
+ setOnBeforeCaptureId('');
4003
4105
  updateItem(undefined);
4004
- dragState.reset();
4106
+ SimulateDnD$1.reset();
4005
4107
  if (!dropResult.destination) {
4006
4108
  if (!draggedItem?.destination) {
4007
4109
  // User cancel drag
@@ -4028,6 +4130,7 @@ const DNDProvider = ({ children }) => {
4028
4130
  }
4029
4131
  // If a node was previously selected prior to dragging, re-select it
4030
4132
  setSelectedNodeId(dropResult.draggableId);
4133
+ sendMessage(OUTGOING_EVENTS.ComponentMoveEnded);
4031
4134
  sendMessage(OUTGOING_EVENTS.ComponentSelected, {
4032
4135
  nodeId: dropResult.draggableId,
4033
4136
  });
@@ -4154,6 +4257,7 @@ const findNearestDropzone = (element) => {
4154
4257
  const VisualEditorRoot = () => {
4155
4258
  const initialized = useInitializeEditor();
4156
4259
  const locale = useEditorStore((state) => state.locale);
4260
+ const setMousePosition = useDraggedItemStore((state) => state.setMousePosition);
4157
4261
  const entityStore = useEntityStore((state) => state.entityStore);
4158
4262
  const setHoveringZone = useZoneStore((state) => state.setHoveringZone);
4159
4263
  const resetEntityStore = useEntityStore((state) => state.resetEntityStore);
@@ -4168,18 +4272,19 @@ const VisualEditorRoot = () => {
4168
4272
  }, [locale, resetEntityStore, entityStore.locale]);
4169
4273
  useEffect(() => {
4170
4274
  const onMouseMove = (e) => {
4275
+ setMousePosition(e.clientX, e.clientY);
4171
4276
  const target = e.target;
4172
4277
  const zoneId = findNearestDropzone(target);
4173
4278
  if (zoneId) {
4174
4279
  setHoveringZone(zoneId);
4175
4280
  }
4176
- if (e.target?.id === 'item') {
4281
+ if (!SimulateDnD$1.isDragging) {
4177
4282
  return;
4178
4283
  }
4179
- if (!dragState.isDragStart) {
4284
+ if (target.id === NEW_COMPONENT_ID) {
4180
4285
  return;
4181
4286
  }
4182
- simulateMouseEvent(e.pageX, e.pageY);
4287
+ SimulateDnD$1.updateDrag(e.clientX, e.clientY);
4183
4288
  sendMessage(OUTGOING_EVENTS.MouseMove, {
4184
4289
  clientX: e.pageX,
4185
4290
  clientY: e.pageY - window.scrollY,