@contentful/experiences-visual-editor-react 3.0.0 → 3.0.1-dev-20250807T0745-c928267.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
@@ -50183,7 +50183,6 @@ const EmptyCanvasMessage = () => {
50183
50183
  */
50184
50184
  const sendCanvasGeometryUpdatedMessage = async (tree, sourceEvent) => {
50185
50185
  const nodeToCoordinatesMap = {};
50186
- await waitForAllImagesToBeLoaded();
50187
50186
  collectNodeCoordinates(tree.root, nodeToCoordinatesMap);
50188
50187
  sendMessage(OUTGOING_EVENTS.CanvasGeometryUpdated, {
50189
50188
  size: {
@@ -50212,30 +50211,26 @@ const collectNodeCoordinates = (node, nodeToCoordinatesMap) => {
50212
50211
  }
50213
50212
  node.children.forEach((child) => collectNodeCoordinates(child, nodeToCoordinatesMap));
50214
50213
  };
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
- };
50214
+ function waitForImageToBeLoaded(imageNode) {
50215
+ if (imageNode.complete) {
50216
+ return Promise.resolve();
50217
+ }
50218
+ return new Promise((resolve, reject) => {
50219
+ const handleImageLoad = (event) => {
50220
+ imageNode.removeEventListener('load', handleImageLoad);
50221
+ imageNode.removeEventListener('error', handleImageLoad);
50222
+ if (event.type === 'error') {
50223
+ console.warn('Image failed to load:', imageNode);
50224
+ reject();
50225
+ }
50226
+ else {
50227
+ resolve();
50228
+ }
50229
+ };
50230
+ imageNode.addEventListener('load', handleImageLoad);
50231
+ imageNode.addEventListener('error', handleImageLoad);
50232
+ });
50233
+ }
50239
50234
 
50240
50235
  const useCanvasGeometryUpdates = ({ tree }) => {
50241
50236
  const debouncedUpdateGeometry = reactExports.useMemo(() => debounce((tree, sourceEvent) => {
@@ -50250,6 +50245,9 @@ const useCanvasGeometryUpdates = ({ tree }) => {
50250
50245
  // yet show the need for this. So we might be able to drop this later to boost performance.
50251
50246
  trailing: true,
50252
50247
  }), []);
50248
+ const debouncedCollectImages = reactExports.useMemo(() => debounce(() => {
50249
+ return Array.from(document.querySelectorAll('img'));
50250
+ }, 300, { leading: true, trailing: true }), []);
50253
50251
  // Store tree in a ref to avoid the need to deactivate & reactivate the mutation observer
50254
50252
  // when the tree changes. This is important to avoid missing out on some mutation events.
50255
50253
  const treeRef = reactExports.useRef(tree);
@@ -50262,9 +50260,19 @@ const useCanvasGeometryUpdates = ({ tree }) => {
50262
50260
  window.addEventListener('resize', resizeEventListener);
50263
50261
  return () => window.removeEventListener('resize', resizeEventListener);
50264
50262
  }, [debouncedUpdateGeometry]);
50263
+ const [{ allImages, loadedImages }, setImages] = reactExports.useState(() => {
50264
+ const allImages = debouncedCollectImages();
50265
+ const loadedImages = new WeakSet();
50266
+ return { allImages, loadedImages };
50267
+ });
50265
50268
  // Handling DOM mutations
50266
50269
  reactExports.useEffect(() => {
50267
- const observer = new MutationObserver(() => debouncedUpdateGeometry(treeRef.current, 'mutation'));
50270
+ const observer = new MutationObserver(() => {
50271
+ debouncedUpdateGeometry(treeRef.current, 'mutation');
50272
+ // find all images on any DOM change
50273
+ const allImages = debouncedCollectImages();
50274
+ setImages((prevState) => ({ ...prevState, allImages }));
50275
+ });
50268
50276
  // send initial geometry in case the tree is empty
50269
50277
  debouncedUpdateGeometry(treeRef.current, 'mutation');
50270
50278
  observer.observe(document.documentElement, {
@@ -50273,7 +50281,26 @@ const useCanvasGeometryUpdates = ({ tree }) => {
50273
50281
  attributes: true,
50274
50282
  });
50275
50283
  return () => observer.disconnect();
50276
- }, [debouncedUpdateGeometry]);
50284
+ }, [debouncedCollectImages, debouncedUpdateGeometry]);
50285
+ // Handling image loading separately,
50286
+ // as each image can load at a different time, some might be hidden or lazy loaded
50287
+ reactExports.useEffect(() => {
50288
+ let isCurrent = true;
50289
+ allImages.forEach(async (imageNode) => {
50290
+ if (loadedImages.has(imageNode)) {
50291
+ return;
50292
+ }
50293
+ // update the geometry after each image is loaded, as it can shift the layout
50294
+ await waitForImageToBeLoaded(imageNode);
50295
+ if (isCurrent) {
50296
+ loadedImages.add(imageNode);
50297
+ debouncedUpdateGeometry(treeRef.current, 'imageLoad');
50298
+ }
50299
+ });
50300
+ return () => {
50301
+ isCurrent = false;
50302
+ };
50303
+ }, [allImages, loadedImages, debouncedUpdateGeometry]);
50277
50304
  };
50278
50305
 
50279
50306
  const RootRenderer = ({ inMemoryEntitiesStore }) => {