@contentful/experiences-visual-editor-react 1.0.2 → 1.0.3-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/renderApp.js CHANGED
@@ -37997,6 +37997,7 @@ const structureComponents = new Set([
37997
37997
  CONTENTFUL_COMPONENTS$1.singleColumn.id,
37998
37998
  ]);
37999
37999
  const isContentfulStructureComponent = (componentId) => structureComponents.has(componentId ?? '');
38000
+ const isComponentAllowedOnRoot = (componentId) => isContentfulStructureComponent(componentId) || componentId === CONTENTFUL_COMPONENTS$1.divider.id;
38000
38001
  const isEmptyStructureWithRelativeHeight = (children, componentId, height) => {
38001
38002
  return (children === 0 &&
38002
38003
  isContentfulStructureComponent(componentId) &&
@@ -51668,7 +51669,7 @@ const DraggableChildComponent = (props) => {
51668
51669
  })));
51669
51670
  };
51670
51671
 
51671
- var css_248z$2 = ".styles-module_container__te-1H {\n margin-left: auto;\n margin-right: auto;\n position: relative;\n height: 100%;\n width: 100%;\n background-color: transparent;\n transition: background-color 0.2s;\n pointer-events: all !important;\n}\n\n.styles-module_container__te-1H:not(.styles-module_isRoot__5cn-i):before {\n content: '';\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n outline-offset: -1px;\n outline: 2px solid transparent;\n z-index: 1;\n transition: outline 0.2s;\n pointer-events: none;\n}\n\n.styles-module_isRoot__5cn-i,\n.styles-module_isEmptyCanvas__0XHZR {\n flex: 1;\n}\n\n.styles-module_isEmptyZone__zVpnZ {\n min-height: 80px;\n}\n\n.styles-module_isDragging__Gm8v5:not(.styles-module_isRoot__5cn-i):before {\n outline: 2px dashed var(--exp-builder-gray300);\n}\n\n.styles-module_isDestination__5sCQx:not(.styles-module_isRoot__5cn-i):before {\n transition:\n outline 0.2s,\n background-color 0.2s;\n outline: 2px dashed var(--exp-builder-blue400);\n background-color: rgba(var(--exp-builder-blue100-rgb), 0.5);\n z-index: 2;\n}\n\n.styles-module_hitbox__YQ-1Z {\n position: fixed;\n pointer-events: all !important;\n}\n\n.styles-module_hitbox__YQ-1Z {\n position: fixed;\n pointer-events: all !important;\n}\n";
51672
+ var css_248z$2 = ".styles-module_container__te-1H {\n margin-left: auto;\n margin-right: auto;\n position: relative;\n height: 100%;\n width: 100%;\n background-color: transparent;\n transition: background-color 0.2s;\n pointer-events: all;\n}\n\n.styles-module_container__te-1H:not(.styles-module_isRoot__5cn-i):before {\n content: '';\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n outline-offset: -1px;\n outline: 2px solid transparent;\n z-index: 1;\n transition: outline 0.2s;\n pointer-events: none;\n}\n\n.styles-module_isRoot__5cn-i,\n.styles-module_isEmptyCanvas__0XHZR {\n flex: 1;\n}\n\n.styles-module_isEmptyZone__zVpnZ {\n min-height: 80px;\n}\n\n.styles-module_isDragging__Gm8v5:not(.styles-module_isRoot__5cn-i):before {\n outline: 2px dashed var(--exp-builder-gray300);\n}\n\n.styles-module_isDestination__5sCQx:not(.styles-module_isRoot__5cn-i):before {\n transition:\n outline 0.2s,\n background-color 0.2s;\n outline: 2px dashed var(--exp-builder-blue400);\n background-color: rgba(var(--exp-builder-blue100-rgb), 0.5);\n z-index: 2;\n}\n\n.styles-module_hitbox__YQ-1Z {\n position: fixed;\n pointer-events: all;\n}\n";
51672
51673
  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"};
51673
51674
  styleInject(css_248z$2);
51674
51675
 
@@ -52762,13 +52763,14 @@ const { WIDTH, HEIGHT, INITIAL_OFFSET, OFFSET_INCREMENT, MIN_HEIGHT, MIN_DEPTH_H
52762
52763
  const calcOffsetDepth = (depth) => {
52763
52764
  return INITIAL_OFFSET - OFFSET_INCREMENT * depth;
52764
52765
  };
52765
- const getHitboxStyles = ({ direction, zoneDepth, domRect }) => {
52766
+ const getHitboxStyles = ({ direction, zoneDepth, domRect, scrollY, offsetRect, }) => {
52766
52767
  if (!domRect) {
52767
52768
  return {
52768
52769
  display: 'none',
52769
52770
  };
52770
52771
  }
52771
52772
  const { width, height, top, left, bottom, right } = domRect;
52773
+ const { height: offsetHeight, width: offsetWidth } = offsetRect || { height: 0, width: 0 };
52772
52774
  const MAX_SELF_HEIGHT = DRAGGABLE_HEIGHT * 2;
52773
52775
  const isDeepZone = zoneDepth > DEEP_ZONE;
52774
52776
  const isAboveMaxHeight = height > MAX_SELF_HEIGHT;
@@ -52777,7 +52779,7 @@ const getHitboxStyles = ({ direction, zoneDepth, domRect }) => {
52777
52779
  return {
52778
52780
  width,
52779
52781
  height: HEIGHT,
52780
- top: top - calcOffsetDepth(zoneDepth) - scrollY,
52782
+ top: top + offsetHeight - calcOffsetDepth(zoneDepth) - scrollY,
52781
52783
  left,
52782
52784
  zIndex: 100 + zoneDepth,
52783
52785
  };
@@ -52785,7 +52787,7 @@ const getHitboxStyles = ({ direction, zoneDepth, domRect }) => {
52785
52787
  return {
52786
52788
  width,
52787
52789
  height: HEIGHT,
52788
- top: bottom + calcOffsetDepth(zoneDepth) - scrollY,
52790
+ top: bottom + offsetHeight + calcOffsetDepth(zoneDepth) - scrollY,
52789
52791
  left,
52790
52792
  zIndex: 100 + zoneDepth,
52791
52793
  };
@@ -52793,7 +52795,7 @@ const getHitboxStyles = ({ direction, zoneDepth, domRect }) => {
52793
52795
  return {
52794
52796
  width: WIDTH,
52795
52797
  height: height - HEIGHT,
52796
- left: left - calcOffsetDepth(zoneDepth) - WIDTH / 2,
52798
+ left: left + offsetWidth - calcOffsetDepth(zoneDepth) - WIDTH / 2,
52797
52799
  top: top + HEIGHT / 2 - scrollY,
52798
52800
  zIndex: 100 + zoneDepth,
52799
52801
  };
@@ -52801,7 +52803,7 @@ const getHitboxStyles = ({ direction, zoneDepth, domRect }) => {
52801
52803
  return {
52802
52804
  width: WIDTH,
52803
52805
  height: height - HEIGHT,
52804
- left: right - calcOffsetDepth(zoneDepth) - WIDTH / 2,
52806
+ left: right + offsetWidth - calcOffsetDepth(zoneDepth) - WIDTH / 2,
52805
52807
  top: top + HEIGHT / 2 - scrollY,
52806
52808
  zIndex: 100 + zoneDepth,
52807
52809
  };
@@ -52835,12 +52837,14 @@ const getHitboxStyles = ({ direction, zoneDepth, domRect }) => {
52835
52837
  }
52836
52838
  };
52837
52839
 
52838
- const Hitboxes = ({ zoneId, parentZoneId, enableRootHitboxes }) => {
52840
+ const Hitboxes = ({ zoneId, parentZoneId, isEmptyZone }) => {
52839
52841
  const tree = useTreeStore((state) => state.tree);
52840
52842
  const isDraggingOnCanvas = useDraggedItemStore((state) => state.isDraggingOnCanvas);
52841
52843
  const scrollY = useDraggedItemStore((state) => state.scrollY);
52842
52844
  const zoneDepth = reactExports.useMemo(() => getItemDepthFromNode({ id: parentZoneId }, tree.root), [tree, parentZoneId]);
52843
52845
  const [fetchDomRect, setFetchDomRect] = reactExports.useState(Date.now());
52846
+ const { zones, hoveringZone } = useZoneStore();
52847
+ const isHoveringZone = hoveringZone === zoneId;
52844
52848
  reactExports.useEffect(() => {
52845
52849
  /**
52846
52850
  * A bit hacky but we need to wait a very small amount
@@ -52859,16 +52863,27 @@ const Hitboxes = ({ zoneId, parentZoneId, enableRootHitboxes }) => {
52859
52863
  return document.querySelector(`[${CTFL_ZONE_ID}="${zoneId}"]`)?.getBoundingClientRect();
52860
52864
  // eslint-disable-next-line react-hooks/exhaustive-deps
52861
52865
  }, [zoneId, fetchDomRect]);
52862
- const zones = useZoneStore((state) => state.zones);
52866
+ // Use the size of the cloned dragging element to offset the position of the hitboxes
52867
+ // So that when dragging causes a dropzone to expand, the hitboxes will be in the correct position
52868
+ const offsetRect = reactExports.useMemo(() => {
52869
+ if (isEmptyZone || !isHoveringZone)
52870
+ return;
52871
+ return document.querySelector(`[${CTFL_DRAGGING_ELEMENT}]`)?.getBoundingClientRect();
52872
+ // eslint-disable-next-line react-hooks/exhaustive-deps
52873
+ }, [isEmptyZone, isHoveringZone, fetchDomRect]);
52863
52874
  const zoneDirection = zones[parentZoneId]?.direction || 'vertical';
52864
52875
  const isVertical = zoneDirection === 'vertical';
52865
52876
  const isRoot = parentZoneId === ROOT_ID;
52866
- const showRootHitboxes = isRoot && enableRootHitboxes;
52867
- const getStyles = reactExports.useCallback((direction) => getHitboxStyles({ direction, zoneDepth, domRect, scrollY }), [zoneDepth, domRect, scrollY]);
52877
+ const getStyles = reactExports.useCallback((direction) => getHitboxStyles({
52878
+ direction,
52879
+ zoneDepth,
52880
+ domRect,
52881
+ scrollY,
52882
+ offsetRect,
52883
+ }), [zoneDepth, domRect, scrollY, offsetRect]);
52868
52884
  const ActiveHitboxes = (React.createElement(React.Fragment, null,
52869
52885
  React.createElement("div", { "data-ctfl-zone-id": zoneId, className: styles$2.hitbox, style: getStyles(isVertical ? HitboxDirection.SELF_VERTICAL : HitboxDirection.SELF_HORIZONTAL) }),
52870
- showRootHitboxes && (React.createElement("div", { "data-ctfl-zone-id": parentZoneId, className: styles$2.hitbox, style: getStyles(HitboxDirection.BOTTOM) })),
52871
- !isRoot && (React.createElement(React.Fragment, null,
52886
+ isRoot ? (React.createElement("div", { "data-ctfl-zone-id": parentZoneId, className: styles$2.hitbox, style: getStyles(HitboxDirection.BOTTOM) })) : (React.createElement(React.Fragment, null,
52872
52887
  React.createElement("div", { "data-ctfl-zone-id": parentZoneId, className: styles$2.hitbox, style: getStyles(isVertical ? HitboxDirection.TOP : HitboxDirection.LEFT) }),
52873
52888
  React.createElement("div", { "data-ctfl-zone-id": parentZoneId, className: styles$2.hitbox, style: getStyles(isVertical ? HitboxDirection.BOTTOM : HitboxDirection.RIGHT) })))));
52874
52889
  if (!hitboxContainer) {
@@ -52877,7 +52892,7 @@ const Hitboxes = ({ zoneId, parentZoneId, enableRootHitboxes }) => {
52877
52892
  return reactDomExports.createPortal(ActiveHitboxes, hitboxContainer);
52878
52893
  };
52879
52894
 
52880
- const EditorBlock = ({ node: rawNode, resolveDesignValue, renderDropzone, draggingNewComponent, index, zoneId, userIsDragging, placeholder, }) => {
52895
+ const EditorBlock = ({ node: rawNode, resolveDesignValue, renderDropzone, index, zoneId, userIsDragging, placeholder, }) => {
52881
52896
  const setSelectedNodeId = useEditorStore((state) => state.setSelectedNodeId);
52882
52897
  const selectedNodeId = useEditorStore((state) => state.selectedNodeId);
52883
52898
  const { node, componentId, wrapperProps, definition, elementToRender } = useComponent({
@@ -52892,8 +52907,7 @@ const EditorBlock = ({ node: rawNode, resolveDesignValue, renderDropzone, draggi
52892
52907
  const isAssemblyBlock = node.type === ASSEMBLY_BLOCK_NODE_TYPE;
52893
52908
  const isAssembly = node.type === ASSEMBLY_NODE_TYPE;
52894
52909
  const isStructureComponent = isContentfulStructureComponent(node.data.blockId);
52895
- const isRootComponent = zoneId === ROOT_ID;
52896
- const enableRootHitboxes = isRootComponent && !!draggingNewComponent;
52910
+ const isEmptyZone = !node.children.length;
52897
52911
  const onClick = (e) => {
52898
52912
  e.stopPropagation();
52899
52913
  if (!userIsDragging) {
@@ -52914,11 +52928,11 @@ const EditorBlock = ({ node: rawNode, resolveDesignValue, renderDropzone, draggi
52914
52928
  if (node.data.blockId === CONTENTFUL_COMPONENTS.singleColumn.id) {
52915
52929
  return (React.createElement(React.Fragment, null,
52916
52930
  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 }),
52917
- isStructureComponent && !isSingleColumn && userIsDragging && (React.createElement(Hitboxes, { parentZoneId: zoneId, zoneId: componentId, enableRootHitboxes: enableRootHitboxes }))));
52931
+ isStructureComponent && !isSingleColumn && userIsDragging && (React.createElement(Hitboxes, { parentZoneId: zoneId, zoneId: componentId, isEmptyZone: isEmptyZone }))));
52918
52932
  }
52919
52933
  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 },
52920
52934
  elementToRender(),
52921
- isStructureComponent && !isSingleColumn && userIsDragging && (React.createElement(Hitboxes, { parentZoneId: zoneId, zoneId: componentId, enableRootHitboxes: enableRootHitboxes }))));
52935
+ isStructureComponent && !isSingleColumn && userIsDragging && (React.createElement(Hitboxes, { parentZoneId: zoneId, zoneId: componentId, isEmptyZone: isEmptyZone }))));
52922
52936
  };
52923
52937
 
52924
52938
  var css_248z$1 = ".EmptyContainer-module_container__XPH5b {\n height: 200px;\n display: flex;\n width: 100%;\n position: absolute;\n align-items: center;\n justify-content: center;\n flex-direction: row;\n transition: all 0.2s;\n color: var(--exp-builder-gray400);\n font-size: var(--exp-builder-font-size-l);\n font-family: var(--exp-builder-font-stack-primary);\n outline: 2px dashed var(--exp-builder-gray400);\n outline-offset: -2px;\n}\n\n.EmptyContainer-module_highlight__lcICy:hover {\n outline: 2px dashed var(--exp-builder-blue500);\n background-color: rgba(var(--exp-builder-blue100-rgb), 0.5);\n cursor: grabbing;\n}\n\n.EmptyContainer-module_icon__82-2O rect {\n fill: var(--exp-builder-gray400);\n}\n\n.EmptyContainer-module_label__4TxRa {\n margin-left: var(--exp-builder-spacing-s);\n}\n";
@@ -52938,27 +52952,6 @@ const EmptyContainer = ({ isDragging }) => {
52938
52952
  React.createElement("span", { className: styles$1.label }, "Add components to begin")));
52939
52953
  };
52940
52954
 
52941
- const getZoneParents = (zoneId) => {
52942
- const element = document.querySelector(`[data-rfd-droppable-id='${zoneId}']`);
52943
- if (!element) {
52944
- return [];
52945
- }
52946
- function getZonesToRoot(element, parentIds = []) {
52947
- if (!element) {
52948
- return parentIds;
52949
- }
52950
- const attribute = element.getAttribute('data-rfd-droppable-id');
52951
- if (attribute === ROOT_ID) {
52952
- return parentIds;
52953
- }
52954
- if (attribute) {
52955
- parentIds.push(attribute);
52956
- }
52957
- return getZonesToRoot(element.parentElement, parentIds);
52958
- }
52959
- return getZonesToRoot(element);
52960
- };
52961
-
52962
52955
  const useDropzoneDirection = ({ resolveDesignValue, node, zoneId }) => {
52963
52956
  const zone = useZoneStore((state) => state.zones);
52964
52957
  const upsertZone = useZoneStore((state) => state.upsertZone);
@@ -53041,8 +53034,12 @@ function Dropzone({ node, zoneId, resolveDesignValue, className, WrapperComponen
53041
53034
  const tree = useTreeStore((state) => state.tree);
53042
53035
  const content = node?.children || tree.root?.children || [];
53043
53036
  const direction = useDropzoneDirection({ resolveDesignValue, node, zoneId });
53044
- const draggedSourceId = draggedItem && draggedItem.source.droppableId;
53045
53037
  const draggedDestinationId = draggedItem && draggedItem.destination?.droppableId;
53038
+ const draggedBlockId = reactExports.useMemo(() => {
53039
+ if (!draggedItem)
53040
+ return;
53041
+ return getItem({ id: draggedItem.draggableId }, tree)?.data.blockId;
53042
+ }, [draggedItem, tree]);
53046
53043
  const isDraggingNewComponent = !!newComponentId;
53047
53044
  const isHoveringZone = hoveringZone === zoneId;
53048
53045
  const isRootZone = zoneId === ROOT_ID;
@@ -53056,43 +53053,33 @@ function Dropzone({ node, zoneId, resolveDesignValue, className, WrapperComponen
53056
53053
  const renderClonedDropzone = reactExports.useCallback((node, props) => {
53057
53054
  return (React.createElement(DropzoneClone, { zoneId: node.data.id, node: node, resolveDesignValue: resolveDesignValue, renderDropzone: renderClonedDropzone, ...props }));
53058
53055
  }, [resolveDesignValue]);
53059
- if (!resolveDesignValue) {
53060
- return null;
53061
- }
53062
- /**
53063
- * The Rules of Dropzones
53064
- *
53065
- * 1. A dropzone is disabled unless the mouse is hovering over it
53066
- *
53067
- * 2. Dragging a new component onto the canvas has no addtional rules
53068
- * besides rule #1
53069
- *
53070
- * 3. Dragging a component that is a direct descendant of the root
53071
- * (parentId === ROOT_ID) then only the Root Dropzone is enabled
53072
- *
53073
- * 4. Dragging a nested component (parentId !== ROOT_ID) then the Root
53074
- * Dropzone is disabled, all other Dropzones follow rule #1
53075
- *
53076
- * 5. Assemblies and the SingleColumn component are always disabled
53077
- *
53078
- */
53079
- const isDropzoneEnabled = () => {
53056
+ const isDropzoneEnabled = reactExports.useMemo(() => {
53057
+ // Disable dropzone for Columns component
53080
53058
  if (node?.data.blockId === CONTENTFUL_COMPONENTS.columns.id) {
53081
53059
  return false;
53082
53060
  }
53061
+ // Disable dropzone for Assembly
53083
53062
  if (isAssembly) {
53084
53063
  return false;
53085
53064
  }
53086
- if (isDraggingNewComponent) {
53087
- return isHoveringZone;
53065
+ // Enable dropzone for the non-root hovered zones if component is not allowed on root
53066
+ if (!isDraggingNewComponent && !isComponentAllowedOnRoot(draggedBlockId)) {
53067
+ return isHoveringZone && !isRootZone;
53088
53068
  }
53089
- const draggingParentIds = getZoneParents(draggedSourceId || '');
53090
- if (!draggingParentIds.length) {
53091
- return isRootZone;
53092
- }
53093
- return isHoveringZone && !isRootZone;
53094
- };
53095
- return (React.createElement(ConnectedDroppable$1, { droppableId: zoneId, direction: direction, isDropDisabled: !isDropzoneEnabled(), renderClone: (provided, snapshot, rubic) => (React.createElement(EditorBlockClone, { node: content[rubic.source.index], resolveDesignValue: resolveDesignValue, provided: provided, snapshot: snapshot, renderDropzone: renderClonedDropzone })) }, (provided, snapshot) => {
53069
+ // Enable dropzone for the hovered zone only
53070
+ return isHoveringZone;
53071
+ }, [
53072
+ node?.data.blockId,
53073
+ isAssembly,
53074
+ isHoveringZone,
53075
+ isRootZone,
53076
+ isDraggingNewComponent,
53077
+ draggedBlockId,
53078
+ ]);
53079
+ if (!resolveDesignValue) {
53080
+ return null;
53081
+ }
53082
+ return (React.createElement(ConnectedDroppable$1, { droppableId: zoneId, direction: direction, isDropDisabled: !isDropzoneEnabled, renderClone: (provided, snapshot, rubic) => (React.createElement(EditorBlockClone, { node: content[rubic.source.index], resolveDesignValue: resolveDesignValue, provided: provided, snapshot: snapshot, renderDropzone: renderClonedDropzone })) }, (provided, snapshot) => {
53096
53083
  return (React.createElement(WrapperComponent, { ...(provided || { droppableProps: {} }).droppableProps, ref: provided?.innerRef, id: zoneId, "data-ctfl-zone-id": zoneId, className: classNames(styles$2.container, {
53097
53084
  [styles$2.isEmptyCanvas]: isEmptyCanvas,
53098
53085
  [styles$2.isDragging]: userIsDragging && !isAssembly,