@elementor/editor-canvas 4.1.0-810 → 4.1.0-811

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
@@ -1173,8 +1173,9 @@ function createProviderSubscriber2({ provider, renderStyles, setStyleItems, getC
1173
1173
  ...style,
1174
1174
  cssName: provider.actions.resolveCssName(style.id)
1175
1175
  }));
1176
- return renderStyles({ styles: breakToBreakpoints(changedStyles), signal }).then((rendered) => {
1177
- updateCacheItems(cache, rendered);
1176
+ const breakpointSplit = breakToBreakpoints(changedStyles);
1177
+ return renderStyles({ styles: breakpointSplit, signal }).then((rendered) => {
1178
+ updateCacheItems(cache, changedIds, rendered);
1178
1179
  return getOrderedItems(cache);
1179
1180
  });
1180
1181
  }
@@ -1231,19 +1232,14 @@ function getChangedStyleIds(previous, current) {
1231
1232
  function getOrderedItems(cache) {
1232
1233
  return cache.orderedIds.map((id) => cache.itemsById.get(id)).filter((items) => items !== void 0).flat();
1233
1234
  }
1234
- function updateCacheItems(cache, changedItems) {
1235
+ function updateCacheItems(cache, changedIds, changedItems) {
1236
+ for (const id of changedIds) {
1237
+ cache.itemsById.delete(id);
1238
+ }
1235
1239
  for (const item of changedItems) {
1236
- const existing = cache.itemsById.get(item.id);
1237
- if (existing) {
1238
- const idx = existing.findIndex((e) => e.breakpoint === item.breakpoint && e.state === item.state);
1239
- if (idx >= 0) {
1240
- existing[idx] = item;
1241
- } else {
1242
- existing.push(item);
1243
- }
1244
- } else {
1245
- cache.itemsById.set(item.id, [item]);
1246
- }
1240
+ const existing = cache.itemsById.get(item.id) || [];
1241
+ existing.push(item);
1242
+ cache.itemsById.set(item.id, existing);
1247
1243
  }
1248
1244
  }
1249
1245
  function rebuildCache(cache, allStyles, items) {
package/dist/index.mjs CHANGED
@@ -1138,8 +1138,9 @@ function createProviderSubscriber2({ provider, renderStyles, setStyleItems, getC
1138
1138
  ...style,
1139
1139
  cssName: provider.actions.resolveCssName(style.id)
1140
1140
  }));
1141
- return renderStyles({ styles: breakToBreakpoints(changedStyles), signal }).then((rendered) => {
1142
- updateCacheItems(cache, rendered);
1141
+ const breakpointSplit = breakToBreakpoints(changedStyles);
1142
+ return renderStyles({ styles: breakpointSplit, signal }).then((rendered) => {
1143
+ updateCacheItems(cache, changedIds, rendered);
1143
1144
  return getOrderedItems(cache);
1144
1145
  });
1145
1146
  }
@@ -1196,19 +1197,14 @@ function getChangedStyleIds(previous, current) {
1196
1197
  function getOrderedItems(cache) {
1197
1198
  return cache.orderedIds.map((id) => cache.itemsById.get(id)).filter((items) => items !== void 0).flat();
1198
1199
  }
1199
- function updateCacheItems(cache, changedItems) {
1200
+ function updateCacheItems(cache, changedIds, changedItems) {
1201
+ for (const id of changedIds) {
1202
+ cache.itemsById.delete(id);
1203
+ }
1200
1204
  for (const item of changedItems) {
1201
- const existing = cache.itemsById.get(item.id);
1202
- if (existing) {
1203
- const idx = existing.findIndex((e) => e.breakpoint === item.breakpoint && e.state === item.state);
1204
- if (idx >= 0) {
1205
- existing[idx] = item;
1206
- } else {
1207
- existing.push(item);
1208
- }
1209
- } else {
1210
- cache.itemsById.set(item.id, [item]);
1211
- }
1205
+ const existing = cache.itemsById.get(item.id) || [];
1206
+ existing.push(item);
1207
+ cache.itemsById.set(item.id, existing);
1212
1208
  }
1213
1209
  }
1214
1210
  function rebuildCache(cache, allStyles, items) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@elementor/editor-canvas",
3
3
  "description": "Elementor Editor Canvas",
4
- "version": "4.1.0-810",
4
+ "version": "4.1.0-811",
5
5
  "private": false,
6
6
  "author": "Elementor Team",
7
7
  "homepage": "https://elementor.com/",
@@ -37,25 +37,25 @@
37
37
  "react-dom": "^18.3.1"
38
38
  },
39
39
  "dependencies": {
40
- "@elementor/editor": "4.1.0-810",
40
+ "@elementor/editor": "4.1.0-811",
41
41
  "dompurify": "^3.2.6",
42
- "@elementor/editor-controls": "4.1.0-810",
43
- "@elementor/editor-documents": "4.1.0-810",
44
- "@elementor/editor-elements": "4.1.0-810",
45
- "@elementor/editor-interactions": "4.1.0-810",
46
- "@elementor/editor-mcp": "4.1.0-810",
47
- "@elementor/editor-notifications": "4.1.0-810",
48
- "@elementor/editor-props": "4.1.0-810",
49
- "@elementor/editor-responsive": "4.1.0-810",
50
- "@elementor/editor-styles": "4.1.0-810",
51
- "@elementor/editor-styles-repository": "4.1.0-810",
52
- "@elementor/editor-ui": "4.1.0-810",
53
- "@elementor/editor-v1-adapters": "4.1.0-810",
54
- "@elementor/schema": "4.1.0-810",
55
- "@elementor/twing": "4.1.0-810",
42
+ "@elementor/editor-controls": "4.1.0-811",
43
+ "@elementor/editor-documents": "4.1.0-811",
44
+ "@elementor/editor-elements": "4.1.0-811",
45
+ "@elementor/editor-interactions": "4.1.0-811",
46
+ "@elementor/editor-mcp": "4.1.0-811",
47
+ "@elementor/editor-notifications": "4.1.0-811",
48
+ "@elementor/editor-props": "4.1.0-811",
49
+ "@elementor/editor-responsive": "4.1.0-811",
50
+ "@elementor/editor-styles": "4.1.0-811",
51
+ "@elementor/editor-styles-repository": "4.1.0-811",
52
+ "@elementor/editor-ui": "4.1.0-811",
53
+ "@elementor/editor-v1-adapters": "4.1.0-811",
54
+ "@elementor/schema": "4.1.0-811",
55
+ "@elementor/twing": "4.1.0-811",
56
56
  "@elementor/ui": "1.37.5",
57
- "@elementor/utils": "4.1.0-810",
58
- "@elementor/wp-media": "4.1.0-810",
57
+ "@elementor/utils": "4.1.0-811",
58
+ "@elementor/wp-media": "4.1.0-811",
59
59
  "@floating-ui/react": "^0.27.5",
60
60
  "@wordpress/i18n": "^5.13.0"
61
61
  },
@@ -408,6 +408,61 @@ describe( 'useStyleItems', () => {
408
408
  ] );
409
409
  } );
410
410
 
411
+ it( 'should remove cached items for breakpoints whose variants no longer exist', async () => {
412
+ // Arrange.
413
+ const renderStylesMock = jest.fn().mockImplementation( ( { styles } ) =>
414
+ Promise.resolve(
415
+ styles.map( ( style: StyleDefinition ) => ( {
416
+ id: style.id,
417
+ breakpoint: style?.variants[ 0 ]?.meta.breakpoint || 'desktop',
418
+ } ) )
419
+ )
420
+ );
421
+
422
+ jest.mocked( useStyleRenderer ).mockReturnValue( renderStylesMock );
423
+
424
+ const styleWithTwoBreakpoints = createMockStyleDefinitionWithVariants( {
425
+ id: 'style1',
426
+ variants: [
427
+ { meta: { breakpoint: null, state: null }, props: { 'font-family': 'Arial' }, custom_css: null },
428
+ { meta: { breakpoint: 'tablet', state: null }, props: { 'font-family': 'Roboto' }, custom_css: null },
429
+ ],
430
+ } );
431
+
432
+ const mockProvider = createMockStylesProvider( { key: 'provider1', priority: 1 }, [ styleWithTwoBreakpoints ] );
433
+
434
+ jest.mocked( stylesRepository ).getProviders.mockReturnValue( [ mockProvider ] );
435
+
436
+ const { result } = renderHook( () => useStyleItems() );
437
+
438
+ await act( async () => {
439
+ mockProvider.actions.updateProps?.( {
440
+ id: 'style1',
441
+ meta: { breakpoint: null, state: null },
442
+ props: {},
443
+ } );
444
+ } );
445
+
446
+ expect( result.current ).toEqual( [
447
+ { id: 'style1', breakpoint: 'desktop' },
448
+ { id: 'style1', breakpoint: 'tablet' },
449
+ ] );
450
+
451
+ // Act - simulate the tablet variant being removed (e.g. user cleared its only prop,
452
+ // global-classes store calls getNonEmptyVariants which drops empty variants).
453
+ await act( async () => {
454
+ mockProvider.actions.update?.( {
455
+ id: 'style1',
456
+ variants: [
457
+ { meta: { breakpoint: null, state: null }, props: { 'font-family': 'Arial' }, custom_css: null },
458
+ ],
459
+ } );
460
+ } );
461
+
462
+ // Assert - the tablet item must be evicted from the cache.
463
+ expect( result.current ).toEqual( [ { id: 'style1', breakpoint: 'desktop' } ] );
464
+ } );
465
+
411
466
  it( 'should only re-render changed styles on differential update', async () => {
412
467
  // Arrange.
413
468
  const renderStylesMock = jest.fn().mockImplementation( ( { styles } ) =>
@@ -200,8 +200,10 @@ function createProviderSubscriber( { provider, renderStyles, setStyleItems, getC
200
200
  cssName: provider.actions.resolveCssName( style.id ),
201
201
  } ) );
202
202
 
203
- return renderStyles( { styles: breakToBreakpoints( changedStyles ), signal } ).then( ( rendered ) => {
204
- updateCacheItems( cache, rendered );
203
+ const breakpointSplit = breakToBreakpoints( changedStyles );
204
+
205
+ return renderStyles( { styles: breakpointSplit, signal } ).then( ( rendered ) => {
206
+ updateCacheItems( cache, changedIds, rendered );
205
207
 
206
208
  return getOrderedItems( cache );
207
209
  } );
@@ -277,19 +279,15 @@ function getOrderedItems( cache: StyleItemsCache ): StyleItem[] {
277
279
  .flat();
278
280
  }
279
281
 
280
- function updateCacheItems( cache: StyleItemsCache, changedItems: StyleItem[] ): void {
282
+ function updateCacheItems( cache: StyleItemsCache, changedIds: string[], changedItems: StyleItem[] ): void {
283
+ for ( const id of changedIds ) {
284
+ cache.itemsById.delete( id );
285
+ }
286
+
281
287
  for ( const item of changedItems ) {
282
- const existing = cache.itemsById.get( item.id );
283
- if ( existing ) {
284
- const idx = existing.findIndex( ( e ) => e.breakpoint === item.breakpoint && e.state === item.state );
285
- if ( idx >= 0 ) {
286
- existing[ idx ] = item;
287
- } else {
288
- existing.push( item );
289
- }
290
- } else {
291
- cache.itemsById.set( item.id, [ item ] );
292
- }
288
+ const existing = cache.itemsById.get( item.id ) || [];
289
+ existing.push( item );
290
+ cache.itemsById.set( item.id, existing );
293
291
  }
294
292
  }
295
293