@elementor/editor-global-classes 4.1.0-830 → 4.1.0-832

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/src/store.ts CHANGED
@@ -4,6 +4,7 @@ import {
4
4
  getVariantByMeta,
5
5
  type StyleDefinition,
6
6
  type StyleDefinitionID,
7
+ type StyleDefinitionsMap,
7
8
  type StyleDefinitionVariant,
8
9
  } from '@elementor/editor-styles';
9
10
  import { type UpdateActionPayload } from '@elementor/editor-styles-repository';
@@ -19,12 +20,13 @@ import { GlobalClassNotFoundError } from './errors';
19
20
  import { SnapshotHistory } from './utils/snapshot-history';
20
21
 
21
22
  export type GlobalClasses = {
22
- items: Record< StyleDefinitionID, StyleDefinition >;
23
+ items: StyleDefinitionsMap;
23
24
  order: StyleDefinitionID[];
24
25
  };
25
26
 
26
27
  type GlobalClassesState = {
27
28
  data: GlobalClasses;
29
+ classLabels: Record< StyleDefinitionID, string >;
28
30
  initialData: {
29
31
  frontend: GlobalClasses;
30
32
  preview: GlobalClasses;
@@ -43,6 +45,7 @@ const localHistory = SnapshotHistory.get< GlobalClasses >( 'global-classes' );
43
45
 
44
46
  const initialState: GlobalClassesState = {
45
47
  data: { items: {}, order: [] },
48
+ classLabels: {},
46
49
  initialData: {
47
50
  frontend: { items: {}, order: [] },
48
51
  preview: { items: {}, order: [] },
@@ -62,15 +65,17 @@ export const slice = createSlice( {
62
65
  load(
63
66
  state,
64
67
  {
65
- payload: { frontend, preview },
68
+ payload: { frontend, preview, classLabels },
66
69
  }: PayloadAction< {
67
70
  frontend: GlobalClasses;
68
71
  preview: GlobalClasses;
72
+ classLabels: Record< StyleDefinitionID, string >;
69
73
  } >
70
74
  ) {
71
75
  state.initialData.frontend = frontend;
72
76
  state.initialData.preview = preview;
73
77
  state.data = preview;
78
+ state.classLabels = classLabels;
74
79
 
75
80
  state.isDirty = false;
76
81
  },
@@ -79,6 +84,7 @@ export const slice = createSlice( {
79
84
  localHistory.next( state.data );
80
85
  state.data.items[ payload.id ] = payload;
81
86
  state.data.order.unshift( payload.id );
87
+ state.classLabels[ payload.id ] = payload.label;
82
88
 
83
89
  state.isDirty = true;
84
90
  },
@@ -90,6 +96,8 @@ export const slice = createSlice( {
90
96
  );
91
97
 
92
98
  state.data.order = state.data.order.filter( ( id ) => id !== payload );
99
+ // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
100
+ delete state.classLabels[ payload ];
93
101
 
94
102
  state.isDirty = true;
95
103
  },
@@ -119,6 +127,7 @@ export const slice = createSlice( {
119
127
  localHistory.next( state.data );
120
128
  Object.entries( payload ).forEach( ( [ id, { modified } ] ) => {
121
129
  state.data.items[ id ].label = modified;
130
+ state.classLabels[ id ] = modified;
122
131
  } );
123
132
 
124
133
  state.isDirty = false;
@@ -208,6 +217,33 @@ export const slice = createSlice( {
208
217
  state.isDirty = true;
209
218
  }
210
219
  },
220
+
221
+ mergeExistingClasses(
222
+ state,
223
+ {
224
+ payload: { preview, frontend },
225
+ }: PayloadAction< { preview: GlobalClasses[ 'items' ]; frontend: GlobalClasses[ 'items' ] } >
226
+ ) {
227
+ Object.entries( preview ).forEach( ( [ id, previewClassData ] ) => {
228
+ const frontendClassData = frontend[ id ];
229
+
230
+ if ( previewClassData === null || previewClassData === undefined ) {
231
+ return;
232
+ }
233
+ if ( ! ( id in state.data.items ) ) {
234
+ state.data.items[ id ] = previewClassData;
235
+ }
236
+ if ( ! ( id in state.initialData.frontend.items ) ) {
237
+ state.initialData.frontend.items[ id ] = frontendClassData;
238
+ }
239
+ if ( ! ( id in state.initialData.preview.items ) ) {
240
+ state.initialData.preview.items[ id ] = previewClassData;
241
+ }
242
+ if ( ! ( id in state.classLabels ) ) {
243
+ state.classLabels[ id ] = previewClassData.label;
244
+ }
245
+ } );
246
+ },
211
247
  },
212
248
  } );
213
249
 
@@ -233,9 +269,18 @@ const getNonEmptyVariants = ( style: StyleDefinition ) => {
233
269
  );
234
270
  };
235
271
 
272
+ export const placeholderDefinition = ( id: StyleDefinitionID, label: string ): StyleDefinition => ( {
273
+ id,
274
+ type: 'class',
275
+ label,
276
+ variants: [],
277
+ } );
278
+
236
279
  // Selectors
237
280
  export const selectData = ( state: SliceState< typeof slice > ) => state[ SLICE_NAME ].data;
238
281
 
282
+ export const selectClassLabels = ( state: SliceState< typeof slice > ) => state[ SLICE_NAME ].classLabels;
283
+
239
284
  export const selectFrontendInitialData = ( state: SliceState< typeof slice > ) =>
240
285
  state[ SLICE_NAME ].initialData.frontend;
241
286
 
@@ -248,8 +293,17 @@ export const selectGlobalClasses = createSelector( selectData, ( { items } ) =>
248
293
 
249
294
  export const selectIsDirty = ( state: SliceState< typeof slice > ) => state[ SLICE_NAME ].isDirty;
250
295
 
251
- export const selectOrderedClasses = createSelector( selectGlobalClasses, selectOrder, ( items, order ) =>
252
- order.map( ( id ) => items[ id ] )
296
+ export const selectOrderedClasses = createSelector( selectData, selectClassLabels, ( { items, order }, classLabels ) =>
297
+ order
298
+ .map( ( id ) => {
299
+ const loaded = items[ id ];
300
+ if ( loaded ) {
301
+ return loaded;
302
+ }
303
+ const label = classLabels[ id ];
304
+ return label !== undefined ? placeholderDefinition( id, label ) : null;
305
+ } )
306
+ .filter( ( s ): s is StyleDefinition => s !== null )
253
307
  );
254
308
 
255
309
  export const selectClass = ( state: SliceState< typeof slice >, id: StyleDefinitionID ) =>
@@ -258,3 +312,8 @@ export const selectClass = ( state: SliceState< typeof slice >, id: StyleDefinit
258
312
  export const selectEmptyCssClass = createSelector( selectData, ( { items } ) =>
259
313
  Object.values( items ).filter( ( cssClass ) => cssClass.variants.length === 0 )
260
314
  );
315
+
316
+ export const selectIsClassFetched = ( state: SliceState< typeof slice >, id: StyleDefinitionID ) =>
317
+ !! state[ SLICE_NAME ].initialData.preview.items[ id ] ||
318
+ !! state[ SLICE_NAME ].initialData.frontend.items[ id ] ||
319
+ false;
@@ -0,0 +1,7 @@
1
+ import { type StyleDefinitionID } from '@elementor/editor-styles';
2
+
3
+ import { type GlobalClassIndexEntry } from '../api';
4
+
5
+ export function createLabelsForClasses( entries: GlobalClassIndexEntry[] ): Record< StyleDefinitionID, string > {
6
+ return Object.fromEntries( entries.map( ( e ) => [ e.id, e.label ] ) );
7
+ }
@@ -5,7 +5,7 @@ import { __getState as getState } from '@elementor/store';
5
5
  import { fetchCssClassUsage } from '../../service/css-class-usage-service';
6
6
  import { GlobalClassTrackingError } from '../errors';
7
7
  import { type FilterKey } from '../hooks/use-filtered-css-class-usage';
8
- import { selectClass } from '../store';
8
+ import { placeholderDefinition, selectClass, selectClassLabels } from '../store';
9
9
 
10
10
  type EventMap = {
11
11
  classCreated: {
@@ -220,16 +220,24 @@ const extractCssClassData = ( classId: StyleDefinitionID ) => {
220
220
  };
221
221
 
222
222
  const getCssClass = ( classId: StyleDefinitionID ) => {
223
- const cssClass = selectClass( getState(), classId );
224
- if ( ! cssClass ) {
225
- throw new Error( `CSS class with ID ${ classId } not found` );
223
+ const state = getState();
224
+ const cssClass = selectClass( state, classId );
225
+
226
+ if ( cssClass ) {
227
+ return cssClass;
228
+ }
229
+
230
+ const label = selectClassLabels( state )[ classId ];
231
+ if ( label !== undefined ) {
232
+ return placeholderDefinition( classId, label );
226
233
  }
227
- return cssClass;
234
+
235
+ throw new Error( `CSS class with ID ${ classId } not found` );
228
236
  };
229
237
 
230
238
  const trackDeleteClass = async ( classId: StyleDefinitionID ) => {
231
- const totalInstances = await getTotalInstancesByCssClassID( classId );
232
239
  const classTitle = getCssClass( classId ).label;
240
+ const totalInstances = await getTotalInstancesByCssClassID( classId );
233
241
  return { totalInstances, classTitle };
234
242
  };
235
243