@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/dist/index.d.mts +13 -1
- package/dist/index.d.ts +13 -1
- package/dist/index.js +279 -127
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +260 -111
- package/dist/index.mjs.map +1 -1
- package/package.json +20 -20
- package/src/api.ts +32 -15
- package/src/components/global-styles-import-listener.tsx +8 -33
- package/src/components/populate-store.tsx +10 -24
- package/src/global-classes-styles-provider.ts +38 -12
- package/src/index.ts +5 -0
- package/src/load-document-classes.ts +76 -0
- package/src/load-existing-classes.ts +49 -0
- package/src/mcp-integration/classes-resource.ts +3 -1
- package/src/save-global-classes.tsx +17 -2
- package/src/store.ts +63 -4
- package/src/utils/create-labels-for-classes.ts +7 -0
- package/src/utils/tracking.ts +14 -6
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:
|
|
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(
|
|
252
|
-
order
|
|
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
|
+
}
|
package/src/utils/tracking.ts
CHANGED
|
@@ -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
|
|
224
|
-
|
|
225
|
-
|
|
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
|
-
|
|
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
|
|