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

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
@@ -520,7 +520,7 @@ const builtInStyles = {
520
520
  type: 'Text',
521
521
  group: 'style',
522
522
  description: 'The border of the section',
523
- defaultValue: '1px solid rgba(0, 0, 0, 0)',
523
+ defaultValue: '0px solid rgba(0, 0, 0, 0)',
524
524
  },
525
525
  cfGap: {
526
526
  displayName: 'Gap',
@@ -1442,8 +1442,8 @@ function gatherDeepReferencesFromTree(startingNode, dataSource) {
1442
1442
  return deepReferences;
1443
1443
  }
1444
1444
 
1445
- var css_248z$6 = ".styles-module_DraggableComponent__m5-dA {\n pointer-events: all;\n position: relative;\n transition: outline 0.2s;\n cursor: grab;\n 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"};
1445
+ var css_248z$6 = ".styles-module_DraggableComponent__m5-dA {\n pointer-events: all;\n position: relative;\n transition: outline 0.2s;\n cursor: grab;\n box-sizing: border-box;\n display: flex;\n}\n\n.styles-module_DraggableComponent__m5-dA:before {\n content: '';\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n outline-offset: -2px;\n outline: 2px solid transparent;\n z-index: 1;\n pointer-events: none;\n}\n\n.styles-module_DraggableClone__X8zTA:before {\n outline: 2px solid var(--exp-builder-blue500);\n}\n\n.styles-module_DraggableClone__X8zTA,\n.styles-module_DraggableClone__X8zTA * {\n pointer-events: none !important;\n}\n\n.styles-module_DraggableComponent__m5-dA:not(.styles-module_userIsDragging__lqbjG) :not(.styles-module_DraggableComponent__m5-dA) {\n pointer-events: none;\n}\n\n.styles-module_isDragging__WHjPU {\n overflow: hidden;\n}\n\n.styles-module_isSelected__BzICQ:before {\n outline: 2px solid transparent !important;\n}\n\n.styles-module_overlay__r4th9 {\n position: absolute;\n display: flex;\n align-items: center;\n min-width: max-content;\n height: 24px;\n z-index: 1;\n font-family: var(--exp-builder-font-stack-primary);\n font-size: 14px;\n font-weight: 500;\n background-color: var(--exp-builder-gray500);\n color: var(--exp-builder-color-white);\n border-radius: 0 0 2px 0;\n padding: 4px 12px 4px 12px;\n transition: opacity 0.2s;\n opacity: 0;\n text-wrap: nowrap;\n}\n\n.styles-module_overlayContainer__eiX-5 {\n opacity: 0;\n}\n\n.styles-module_overlayAssembly__tOzZU {\n background-color: var(--exp-builder-purple600);\n}\n\n.styles-module_userIsDragging__lqbjG > .styles-module_overlay__r4th9,\n.styles-module_userIsDragging__lqbjG > .styles-module_overlayContainer__eiX-5 {\n opacity: 0 !important;\n}\n\n.styles-module_userIsDragging__lqbjG:before {\n outline: 2px solid transparent !important;\n}\n\n.styles-module_DraggableComponent__m5-dA:hover:not(:has(div[data-rfd-draggable-id]:hover)) > .styles-module_overlay__r4th9 {\n opacity: 1;\n}\n\n.styles-module_DraggableComponent__m5-dA:hover:before,\n.styles-module_DraggableComponent__m5-dA:hover div[data-rfd-draggable-id]:before {\n outline: 2px dashed var(--exp-builder-gray500);\n}\n\n.styles-module_DraggableComponent__m5-dA:hover:not(:has(div[data-rfd-draggable-id]:hover)):before {\n outline: 2px solid var(--exp-builder-gray500);\n}\n\n.styles-module_isAssemblyBlock__Y3Avk:hover:before,\n.styles-module_isAssemblyBlock__Y3Avk:hover div[data-rfd-draggable-id]:before,\n.styles-module_DraggableComponent__m5-dA:hover div[data-rfd-draggable-id][data-cf-node-block-type^='assembly']:before {\n outline: 2px dashed var(--exp-builder-purple600);\n}\n\n.styles-module_isAssemblyBlock__Y3Avk:hover:not(:has(div[data-rfd-draggable-id]:hover)):before {\n outline: 2px solid var(--exp-builder-purple600);\n}\n";
1446
+ var styles$3 = {"DraggableComponent":"styles-module_DraggableComponent__m5-dA","DraggableClone":"styles-module_DraggableClone__X8zTA","userIsDragging":"styles-module_userIsDragging__lqbjG","isDragging":"styles-module_isDragging__WHjPU","isSelected":"styles-module_isSelected__BzICQ","overlay":"styles-module_overlay__r4th9","overlayContainer":"styles-module_overlayContainer__eiX-5","overlayAssembly":"styles-module_overlayAssembly__tOzZU","isAssemblyBlock":"styles-module_isAssemblyBlock__Y3Avk"};
1447
1447
  styleInject(css_248z$6);
1448
1448
 
1449
1449
  const SCROLL_STATES = {
@@ -1741,6 +1741,41 @@ var DraggablePosition;
1741
1741
  DraggablePosition[DraggablePosition["MOUSE_POSITION"] = 1] = "MOUSE_POSITION";
1742
1742
  })(DraggablePosition || (DraggablePosition = {}));
1743
1743
 
1744
+ const calcOffsetLeft = (parentElement, placeholderWidth, nodeWidth) => {
1745
+ if (!parentElement) {
1746
+ return 0;
1747
+ }
1748
+ const alignItems = window.getComputedStyle(parentElement).alignItems;
1749
+ if (alignItems === 'center') {
1750
+ return -(placeholderWidth - nodeWidth) / 2;
1751
+ }
1752
+ if (alignItems === 'end') {
1753
+ return -placeholderWidth + nodeWidth + 2;
1754
+ }
1755
+ return 0;
1756
+ };
1757
+ const calcOffsetTop = (parentElement, placeholderHeight, nodeHeight) => {
1758
+ if (!parentElement) {
1759
+ return 0;
1760
+ }
1761
+ const alignItems = window.getComputedStyle(parentElement).alignItems;
1762
+ if (alignItems === 'center') {
1763
+ return -(placeholderHeight - nodeHeight) / 2;
1764
+ }
1765
+ if (alignItems === 'end') {
1766
+ return -placeholderHeight + nodeHeight + 2;
1767
+ }
1768
+ return 0;
1769
+ };
1770
+ const getPaddingOffset = (element) => {
1771
+ const paddingLeft = parseFloat(window.getComputedStyle(element).paddingLeft);
1772
+ const paddingRight = parseFloat(window.getComputedStyle(element).paddingRight);
1773
+ const paddingTop = parseFloat(window.getComputedStyle(element).paddingTop);
1774
+ const paddingBottom = parseFloat(window.getComputedStyle(element).paddingBottom);
1775
+ const horizontalOffset = paddingLeft + paddingRight;
1776
+ const verticalOffset = paddingTop + paddingBottom;
1777
+ return [horizontalOffset, verticalOffset];
1778
+ };
1744
1779
  /**
1745
1780
  * Calculate the size and position of the dropzone indicator
1746
1781
  * when dragging a new component onto the canvas
@@ -1758,10 +1793,15 @@ const calcNewComponentStyles = (params) => {
1758
1793
  }
1759
1794
  const elementSizes = element.getBoundingClientRect();
1760
1795
  const dropzoneSizes = dropzone.getBoundingClientRect();
1761
- const width = isHorizontal ? DRAGGABLE_WIDTH : dropzoneSizes.width;
1762
- const height = isHorizontal ? dropzoneSizes.height : DRAGGABLE_HEIGHT;
1763
- const top = isHorizontal ? -(height - elementSizes.height) / 2 : -height;
1764
- const left = isHorizontal ? -width : -(width - elementSizes.width) / 2;
1796
+ const [horizontalPadding, verticalPadding] = getPaddingOffset(dropzone);
1797
+ const width = isHorizontal ? DRAGGABLE_WIDTH : dropzoneSizes.width - horizontalPadding;
1798
+ const height = isHorizontal ? dropzoneSizes.height - verticalPadding : DRAGGABLE_HEIGHT;
1799
+ const top = isHorizontal
1800
+ ? calcOffsetTop(element.parentElement, height, elementSizes.height)
1801
+ : -height;
1802
+ const left = isHorizontal
1803
+ ? -width
1804
+ : calcOffsetLeft(element.parentElement, width, elementSizes.width);
1765
1805
  return {
1766
1806
  width,
1767
1807
  height,
@@ -1792,10 +1832,15 @@ const calcMovementStyles = (params) => {
1792
1832
  const elementSizes = element.getBoundingClientRect();
1793
1833
  const dropzoneSizes = dropzone.getBoundingClientRect();
1794
1834
  const draggableSizes = draggable.getBoundingClientRect();
1795
- const width = isHorizontal ? draggableSizes.width : dropzoneSizes.width;
1796
- const height = isHorizontal ? dropzoneSizes.height : draggableSizes.height;
1797
- const top = isHorizontal ? -(height - elementSizes.height) / 2 : -height;
1798
- const left = isHorizontal ? -width : -(width - elementSizes.width) / 2;
1835
+ const [horizontalPadding, verticalPadding] = getPaddingOffset(dropzone);
1836
+ const width = isHorizontal ? draggableSizes.width : dropzoneSizes.width - horizontalPadding;
1837
+ const height = isHorizontal ? dropzoneSizes.height - verticalPadding : draggableSizes.height;
1838
+ const top = isHorizontal
1839
+ ? calcOffsetTop(element.parentElement, height, elementSizes.height)
1840
+ : -height;
1841
+ const left = isHorizontal
1842
+ ? -width
1843
+ : calcOffsetLeft(element.parentElement, width, elementSizes.width);
1799
1844
  return {
1800
1845
  width,
1801
1846
  height,
@@ -2016,9 +2061,11 @@ const useSelectedInstanceCoordinates = ({ node }) => {
2016
2061
  if (selectedNodeId !== node.data.id) {
2017
2062
  return;
2018
2063
  }
2064
+ // Allows the drop animation to finish before
2065
+ // calculating the components coordinates
2019
2066
  setTimeout(() => {
2020
2067
  sendSelectedComponentCoordinates(node.data.id);
2021
- }, 200);
2068
+ }, 10);
2022
2069
  }, [node, selectedNodeId]);
2023
2070
  const selectedElement = node.data.id
2024
2071
  ? document.querySelector(`[data-cf-node-id="${selectedNodeId}"]`)
@@ -2511,7 +2558,7 @@ const DraggableChildComponent = (props) => {
2511
2558
  })));
2512
2559
  };
2513
2560
 
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";
2561
+ 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";
2515
2562
  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"};
2516
2563
  styleInject(css_248z$2);
2517
2564
 
@@ -4143,27 +4190,28 @@ const RootRenderer = ({ onChange }) => {
4143
4190
  const dragItem = useDraggedItemStore((state) => state.componentId);
4144
4191
  const userIsDragging = useDraggedItemStore((state) => state.isDraggingOnCanvas);
4145
4192
  const breakpoints = useTreeStore((state) => state.breakpoints);
4193
+ const setSelectedNodeId = useEditorStore((state) => state.setSelectedNodeId);
4146
4194
  const draggableSourceId = useDraggedItemStore((state) => state.draggedItem?.source.droppableId);
4147
4195
  const draggingNewComponent = !!draggableSourceId?.startsWith(COMPONENT_LIST_ID);
4148
4196
  const containerRef = useRef(null);
4149
4197
  const { resolveDesignValue } = useBreakpoints(breakpoints);
4150
4198
  const [containerStyles, setContainerStyles] = useState({});
4151
4199
  const tree = useTreeStore((state) => state.tree);
4152
- useEffect(() => {
4153
- if (onChange)
4154
- onChange(tree);
4155
- }, [tree, onChange]);
4156
- useEffect(() => {
4157
- document.addEventListener('click', handleClickOutside);
4158
- return () => {
4159
- document.removeEventListener('click', handleClickOutside);
4160
- };
4161
- }, []);
4162
- const handleClickOutside = () => {
4200
+ const handleClickOutside = useCallback((e) => {
4201
+ const element = e.target;
4202
+ const isRoot = element.getAttribute('data-ctfl-zone-id') === ROOT_ID;
4203
+ const clickedOnCanvas = element.closest(`[data-ctfl-root]`);
4204
+ if (clickedOnCanvas && !isRoot) {
4205
+ return;
4206
+ }
4163
4207
  sendMessage(OUTGOING_EVENTS.OutsideCanvasClick, {
4164
4208
  outsideCanvasClick: true,
4165
4209
  });
4166
- };
4210
+ sendMessage(OUTGOING_EVENTS.ComponentSelected, {
4211
+ selectedId: '',
4212
+ });
4213
+ setSelectedNodeId('');
4214
+ }, [setSelectedNodeId]);
4167
4215
  const handleResizeCanvas = useCallback(() => {
4168
4216
  const parentElement = containerRef.current?.parentElement;
4169
4217
  if (!parentElement) {
@@ -4193,6 +4241,16 @@ const RootRenderer = ({ onChange }) => {
4193
4241
  });
4194
4242
  // eslint-disable-next-line react-hooks/exhaustive-deps
4195
4243
  }, [containerRef.current]);
4244
+ useEffect(() => {
4245
+ if (onChange)
4246
+ onChange(tree);
4247
+ }, [tree, onChange]);
4248
+ useEffect(() => {
4249
+ document.addEventListener('click', handleClickOutside);
4250
+ return () => {
4251
+ document.removeEventListener('click', handleClickOutside);
4252
+ };
4253
+ }, [handleClickOutside]);
4196
4254
  useEffect(() => {
4197
4255
  handleResizeCanvas();
4198
4256
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -4244,16 +4302,6 @@ const useInitializeEditor = () => {
4244
4302
  return initialized;
4245
4303
  };
4246
4304
 
4247
- const findNearestDropzone = (element) => {
4248
- const zoneId = element.getAttribute(CTFL_ZONE_ID);
4249
- if (!element.parentElement) {
4250
- return null;
4251
- }
4252
- if (element.tagName === 'BODY') {
4253
- return null;
4254
- }
4255
- return zoneId ?? findNearestDropzone(element.parentElement);
4256
- };
4257
4305
  const VisualEditorRoot = () => {
4258
4306
  const initialized = useInitializeEditor();
4259
4307
  const locale = useEditorStore((state) => state.locale);
@@ -4274,7 +4322,7 @@ const VisualEditorRoot = () => {
4274
4322
  const onMouseMove = (e) => {
4275
4323
  setMousePosition(e.clientX, e.clientY);
4276
4324
  const target = e.target;
4277
- const zoneId = findNearestDropzone(target);
4325
+ const zoneId = target.closest(`[${CTFL_ZONE_ID}]`)?.getAttribute(CTFL_ZONE_ID);
4278
4326
  if (zoneId) {
4279
4327
  setHoveringZone(zoneId);
4280
4328
  }