@contentful/experiences-visual-editor-react 3.0.0 → 3.1.0-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
@@ -47012,6 +47012,7 @@ const OUTGOING_EVENTS = {
47012
47012
  SDKFeatures: 'sdkFeatures',
47013
47013
  RequestEntities: 'REQUEST_ENTITIES',
47014
47014
  CanvasGeometryUpdated: 'canvasGeometryUpdated',
47015
+ CanvasPan: 'canvasPan',
47015
47016
  };
47016
47017
  const INCOMING_EVENTS = {
47017
47018
  RequestEditorMode: 'requestEditorMode',
@@ -50183,7 +50184,6 @@ const EmptyCanvasMessage = () => {
50183
50184
  */
50184
50185
  const sendCanvasGeometryUpdatedMessage = async (tree, sourceEvent) => {
50185
50186
  const nodeToCoordinatesMap = {};
50186
- await waitForAllImagesToBeLoaded();
50187
50187
  collectNodeCoordinates(tree.root, nodeToCoordinatesMap);
50188
50188
  sendMessage(OUTGOING_EVENTS.CanvasGeometryUpdated, {
50189
50189
  size: {
@@ -50212,30 +50212,26 @@ const collectNodeCoordinates = (node, nodeToCoordinatesMap) => {
50212
50212
  }
50213
50213
  node.children.forEach((child) => collectNodeCoordinates(child, nodeToCoordinatesMap));
50214
50214
  };
50215
- const waitForAllImagesToBeLoaded = () => {
50216
- // If the document contains an image, wait for this image to be loaded before collecting & sending all geometry data.
50217
- const allImageNodes = document.querySelectorAll('img');
50218
- return Promise.all(Array.from(allImageNodes).map((imageNode) => {
50219
- if (imageNode.complete) {
50220
- return Promise.resolve();
50221
- }
50222
- return new Promise((resolve, reject) => {
50223
- const handleImageLoad = (event) => {
50224
- imageNode.removeEventListener('load', handleImageLoad);
50225
- imageNode.removeEventListener('error', handleImageLoad);
50226
- if (event.type === 'error') {
50227
- console.warn('Image failed to load:', imageNode);
50228
- reject();
50229
- }
50230
- else {
50231
- resolve();
50232
- }
50233
- };
50234
- imageNode.addEventListener('load', handleImageLoad);
50235
- imageNode.addEventListener('error', handleImageLoad);
50236
- });
50237
- }));
50238
- };
50215
+ function waitForImageToBeLoaded(imageNode) {
50216
+ if (imageNode.complete) {
50217
+ return Promise.resolve();
50218
+ }
50219
+ return new Promise((resolve, reject) => {
50220
+ const handleImageLoad = (event) => {
50221
+ imageNode.removeEventListener('load', handleImageLoad);
50222
+ imageNode.removeEventListener('error', handleImageLoad);
50223
+ if (event.type === 'error') {
50224
+ console.warn('Image failed to load:', imageNode);
50225
+ reject();
50226
+ }
50227
+ else {
50228
+ resolve();
50229
+ }
50230
+ };
50231
+ imageNode.addEventListener('load', handleImageLoad);
50232
+ imageNode.addEventListener('error', handleImageLoad);
50233
+ });
50234
+ }
50239
50235
 
50240
50236
  const useCanvasGeometryUpdates = ({ tree }) => {
50241
50237
  const debouncedUpdateGeometry = reactExports.useMemo(() => debounce((tree, sourceEvent) => {
@@ -50250,6 +50246,9 @@ const useCanvasGeometryUpdates = ({ tree }) => {
50250
50246
  // yet show the need for this. So we might be able to drop this later to boost performance.
50251
50247
  trailing: true,
50252
50248
  }), []);
50249
+ const debouncedCollectImages = reactExports.useMemo(() => debounce(() => {
50250
+ return Array.from(document.querySelectorAll('img'));
50251
+ }, 300, { leading: true, trailing: true }), []);
50253
50252
  // Store tree in a ref to avoid the need to deactivate & reactivate the mutation observer
50254
50253
  // when the tree changes. This is important to avoid missing out on some mutation events.
50255
50254
  const treeRef = reactExports.useRef(tree);
@@ -50262,9 +50261,19 @@ const useCanvasGeometryUpdates = ({ tree }) => {
50262
50261
  window.addEventListener('resize', resizeEventListener);
50263
50262
  return () => window.removeEventListener('resize', resizeEventListener);
50264
50263
  }, [debouncedUpdateGeometry]);
50264
+ const [{ allImages, loadedImages }, setImages] = reactExports.useState(() => {
50265
+ const allImages = debouncedCollectImages();
50266
+ const loadedImages = new WeakSet();
50267
+ return { allImages, loadedImages };
50268
+ });
50265
50269
  // Handling DOM mutations
50266
50270
  reactExports.useEffect(() => {
50267
- const observer = new MutationObserver(() => debouncedUpdateGeometry(treeRef.current, 'mutation'));
50271
+ const observer = new MutationObserver(() => {
50272
+ debouncedUpdateGeometry(treeRef.current, 'mutation');
50273
+ // find all images on any DOM change
50274
+ const allImages = debouncedCollectImages();
50275
+ setImages((prevState) => ({ ...prevState, allImages }));
50276
+ });
50268
50277
  // send initial geometry in case the tree is empty
50269
50278
  debouncedUpdateGeometry(treeRef.current, 'mutation');
50270
50279
  observer.observe(document.documentElement, {
@@ -50273,7 +50282,42 @@ const useCanvasGeometryUpdates = ({ tree }) => {
50273
50282
  attributes: true,
50274
50283
  });
50275
50284
  return () => observer.disconnect();
50276
- }, [debouncedUpdateGeometry]);
50285
+ }, [debouncedCollectImages, debouncedUpdateGeometry]);
50286
+ // Handling image loading separately,
50287
+ // as each image can load at a different time, some might be hidden or lazy loaded
50288
+ reactExports.useEffect(() => {
50289
+ let isCurrent = true;
50290
+ allImages.forEach(async (imageNode) => {
50291
+ if (loadedImages.has(imageNode)) {
50292
+ return;
50293
+ }
50294
+ // update the geometry after each image is loaded, as it can shift the layout
50295
+ await waitForImageToBeLoaded(imageNode);
50296
+ if (isCurrent) {
50297
+ loadedImages.add(imageNode);
50298
+ debouncedUpdateGeometry(treeRef.current, 'imageLoad');
50299
+ }
50300
+ });
50301
+ return () => {
50302
+ isCurrent = false;
50303
+ };
50304
+ }, [allImages, loadedImages, debouncedUpdateGeometry]);
50305
+ // Delegate scrolling to the canvas
50306
+ reactExports.useEffect(() => {
50307
+ const onWheel = (e) => {
50308
+ e.preventDefault();
50309
+ sendMessage(OUTGOING_EVENTS.CanvasPan, {
50310
+ ctrlKey: e.ctrlKey,
50311
+ metaKey: e.metaKey,
50312
+ clientX: e.clientX,
50313
+ clientY: e.clientY,
50314
+ deltaX: e.deltaX,
50315
+ deltaY: e.deltaY,
50316
+ });
50317
+ };
50318
+ document.addEventListener('wheel', onWheel, { passive: false });
50319
+ return () => document.removeEventListener('wheel', onWheel);
50320
+ }, []);
50277
50321
  };
50278
50322
 
50279
50323
  const RootRenderer = ({ inMemoryEntitiesStore }) => {