@elementor/editor-controls 4.4.0-1110 → 4.4.0-1112

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@elementor/editor-controls",
3
3
  "description": "This package contains the controls model and utils for the Elementor editor",
4
- "version": "4.4.0-1110",
4
+ "version": "4.4.0-1112",
5
5
  "private": false,
6
6
  "author": "Elementor Team",
7
7
  "homepage": "https://elementor.com/",
@@ -40,23 +40,23 @@
40
40
  "dev": "tsup --config=../../tsup.dev.ts"
41
41
  },
42
42
  "dependencies": {
43
- "@elementor/editor-current-user": "4.4.0-1110",
44
- "@elementor/editor-elements": "4.4.0-1110",
45
- "@elementor/editor-props": "4.4.0-1110",
46
- "@elementor/editor-responsive": "4.4.0-1110",
47
- "@elementor/editor-ui": "4.4.0-1110",
48
- "@elementor/editor-v1-adapters": "4.4.0-1110",
49
- "@elementor/env": "4.4.0-1110",
50
- "@elementor/events": "4.4.0-1110",
51
- "@elementor/http-client": "4.4.0-1110",
43
+ "@elementor/editor-current-user": "4.4.0-1112",
44
+ "@elementor/editor-elements": "4.4.0-1112",
45
+ "@elementor/editor-props": "4.4.0-1112",
46
+ "@elementor/editor-responsive": "4.4.0-1112",
47
+ "@elementor/editor-ui": "4.4.0-1112",
48
+ "@elementor/editor-v1-adapters": "4.4.0-1112",
49
+ "@elementor/env": "4.4.0-1112",
50
+ "@elementor/events": "4.4.0-1112",
51
+ "@elementor/http-client": "4.4.0-1112",
52
52
  "@elementor/icons": "~1.75.1",
53
- "@elementor/locations": "4.4.0-1110",
54
- "@elementor/query": "4.4.0-1110",
55
- "@elementor/schema": "4.4.0-1110",
56
- "@elementor/session": "4.4.0-1110",
53
+ "@elementor/locations": "4.4.0-1112",
54
+ "@elementor/query": "4.4.0-1112",
55
+ "@elementor/schema": "4.4.0-1112",
56
+ "@elementor/session": "4.4.0-1112",
57
57
  "@elementor/ui": "1.37.5",
58
- "@elementor/utils": "4.4.0-1110",
59
- "@elementor/wp-media": "4.4.0-1110",
58
+ "@elementor/utils": "4.4.0-1112",
59
+ "@elementor/wp-media": "4.4.0-1112",
60
60
  "@monaco-editor/react": "^4.7.0",
61
61
  "@tanstack/react-virtual": "^3.13.3",
62
62
  "@tiptap/extension-bold": "^3.11.1",
@@ -0,0 +1,556 @@
1
+ import { type HttpResponse, httpService } from '@elementor/http-client';
2
+ import { useQuery } from '@elementor/query';
3
+
4
+ import { enqueueIconFonts } from '../open-icon-library';
5
+ import { type FontAwesome7Icon } from './font-awesome-7-catalog';
6
+ import { parseFontelloSvgFont } from './fontello-svg-font';
7
+ import { parseIcomoonSelection } from './icomoon-selection';
8
+
9
+ const NATIVE_TAB_NAMES = new Set( [ 'all', 'recommended', 'GoPro' ] );
10
+ const DEFAULT_ICON_SIZE = 512;
11
+ const CUSTOM_ICON_LIBRARIES_QUERY_KEY = [ 'custom-icon-libraries' ];
12
+ const CUSTOM_ICON_SVG_URL = 'elementor/v1/atomic-widgets/custom-icon-svg';
13
+
14
+ type CustomIconLibraryConfig = {
15
+ name: string;
16
+ prefix: string;
17
+ displayPrefix?: string;
18
+ fetchJson?: string;
19
+ configUrl?: string;
20
+ fontUrl?: string;
21
+ selectionUrl?: string;
22
+ custom_icon_type?: string;
23
+ icons?: unknown;
24
+ native?: boolean;
25
+ };
26
+
27
+ const SUPPORTED_CUSTOM_ICON_TYPES = new Set( [ 'fontello', 'icomoon', 'fontastic' ] );
28
+
29
+ const svgMapCache = new Map< string, Record< string, string > >();
30
+ const inFlightSvgMaps = new Map< string, Promise< Record< string, string > > >();
31
+
32
+ export function resetCustomIconSvgCache() {
33
+ svgMapCache.clear();
34
+ inFlightSvgMaps.clear();
35
+ }
36
+
37
+ export function isDeletedCustomIconLibrary( library: string, iconValue: string ): boolean {
38
+ const libraryName = String( library );
39
+
40
+ if ( ! libraryName || ! iconValue ) {
41
+ return false;
42
+ }
43
+
44
+ if ( NATIVE_TAB_NAMES.has( libraryName ) || libraryName.startsWith( 'fa-' ) ) {
45
+ return false;
46
+ }
47
+
48
+ return ! getCustomIconLibraryConfigs().some( ( item ) => item.name === libraryName );
49
+ }
50
+
51
+ export function useCustomIconLibraries( enabled: boolean ) {
52
+ return useQuery< FontAwesome7Icon[] >( {
53
+ queryKey: CUSTOM_ICON_LIBRARIES_QUERY_KEY,
54
+ queryFn: ( { signal } ) => loadCustomIconLibraries( signal ),
55
+ enabled: enabled && areCustomIconLibrariesEnabled(),
56
+ staleTime: Infinity,
57
+ } );
58
+ }
59
+
60
+ export async function loadCustomIconLibraries( signal?: AbortSignal ): Promise< FontAwesome7Icon[] > {
61
+ const catalogs = await Promise.all(
62
+ getCustomIconLibraryConfigs().map( ( library ) => loadCustomLibrary( library, signal ) )
63
+ );
64
+
65
+ return catalogs.flat();
66
+ }
67
+
68
+ export async function resolveCustomIconSvg(
69
+ library: string,
70
+ iconValue: string,
71
+ signal?: AbortSignal
72
+ ): Promise< string | null > {
73
+ const config = getCustomIconLibraryConfigs().find( ( item ) => item.name === String( library ) );
74
+
75
+ if ( ! config ) {
76
+ svgMapCache.delete( String( library ) );
77
+
78
+ return null;
79
+ }
80
+
81
+ const map = await loadLibrarySvgMap( String( library ), config, signal );
82
+ const markup = map[ iconValue ];
83
+
84
+ return typeof markup === 'string' && markup !== '' ? markup : null;
85
+ }
86
+
87
+ function areCustomIconLibrariesEnabled(): boolean {
88
+ return true === window.elementorCommon?.config?.fontAwesome?.v7?.customIconLibrariesEnabled;
89
+ }
90
+
91
+ function getCustomIconLibraryConfigs(): CustomIconLibraryConfig[] {
92
+ if ( ! areCustomIconLibrariesEnabled() ) {
93
+ return [];
94
+ }
95
+
96
+ const libraries = window.elementor?.config as { icons?: { libraries?: unknown } } | undefined;
97
+ const items = Array.isArray( libraries?.icons?.libraries ) ? libraries.icons.libraries : [];
98
+
99
+ return items.flatMap( ( value ) => {
100
+ const library = normalizeCustomIconLibraryConfig( value );
101
+
102
+ return library ? [ library ] : [];
103
+ } );
104
+ }
105
+
106
+ function normalizeCustomIconLibraryConfig( value: unknown ): CustomIconLibraryConfig | null {
107
+ if ( ! value || typeof value !== 'object' ) {
108
+ return null;
109
+ }
110
+
111
+ const library = value as CustomIconLibraryConfig & { name?: unknown; prefix?: unknown };
112
+ const name = coerceLibraryName( library.name );
113
+
114
+ if ( name === '' || NATIVE_TAB_NAMES.has( name ) || library.native === true || name.startsWith( 'fa-' ) ) {
115
+ return null;
116
+ }
117
+
118
+ if ( typeof library.prefix !== 'string' ) {
119
+ return null;
120
+ }
121
+
122
+ if ( ! library.fetchJson && library.icons === undefined ) {
123
+ return null;
124
+ }
125
+
126
+ const resolved: CustomIconLibraryConfig = {
127
+ ...library,
128
+ name,
129
+ prefix: library.prefix,
130
+ ...getPackUrls( name, library ),
131
+ };
132
+
133
+ if ( ! resolveCustomIconType( resolved ) ) {
134
+ return null;
135
+ }
136
+
137
+ return resolved;
138
+ }
139
+
140
+ function coerceLibraryName( value: unknown ): string {
141
+ if ( typeof value === 'string' ) {
142
+ return value;
143
+ }
144
+
145
+ if ( typeof value === 'number' && Number.isFinite( value ) ) {
146
+ return String( value );
147
+ }
148
+
149
+ return '';
150
+ }
151
+
152
+ function getPackUrls(
153
+ library: string,
154
+ config: CustomIconLibraryConfig
155
+ ): Pick< CustomIconLibraryConfig, 'configUrl' | 'fontUrl' | 'selectionUrl' | 'custom_icon_type' > {
156
+ const derived = derivePackAssetUrls( config.fetchJson, resolveCustomIconType( config ) );
157
+ const packs = window.elementorCommon?.config?.fontAwesome?.v7?.customIconPacks;
158
+
159
+ if ( ! packs || typeof packs !== 'object' ) {
160
+ return derived;
161
+ }
162
+
163
+ const pack = packs[ library ];
164
+
165
+ if ( ! pack || typeof pack !== 'object' ) {
166
+ return derived;
167
+ }
168
+
169
+ const packType = typeof pack.type === 'string' ? pack.type : config.custom_icon_type;
170
+
171
+ return {
172
+ ...derived,
173
+ configUrl: typeof pack.configUrl === 'string' ? pack.configUrl : derived.configUrl,
174
+ fontUrl: typeof pack.fontUrl === 'string' ? pack.fontUrl : derived.fontUrl,
175
+ selectionUrl: typeof pack.selectionUrl === 'string' ? pack.selectionUrl : derived.selectionUrl,
176
+ custom_icon_type: packType ?? derived.custom_icon_type,
177
+ };
178
+ }
179
+
180
+ function resolveCustomIconType( library: CustomIconLibraryConfig ): string {
181
+ const type = typeof library.custom_icon_type === 'string' ? library.custom_icon_type.toLowerCase() : '';
182
+
183
+ return SUPPORTED_CUSTOM_ICON_TYPES.has( type ) ? type : '';
184
+ }
185
+
186
+ function derivePackAssetUrls(
187
+ fetchJson: string | undefined,
188
+ type: string
189
+ ): Pick< CustomIconLibraryConfig, 'configUrl' | 'fontUrl' | 'selectionUrl' | 'custom_icon_type' > {
190
+ if ( ! fetchJson ) {
191
+ return type ? { custom_icon_type: type } : {};
192
+ }
193
+
194
+ try {
195
+ const url = new URL( fetchJson, window.location.origin );
196
+ const base = url.href.replace( /\/[^/?#]+(?:\?.*)?$/, '' );
197
+
198
+ if ( 'icomoon' === type ) {
199
+ return {
200
+ custom_icon_type: type,
201
+ selectionUrl: `${ base }/selection.json`,
202
+ fontUrl: `${ base }/fonts/icomoon.svg`,
203
+ };
204
+ }
205
+
206
+ if ( 'fontastic' === type ) {
207
+ return {
208
+ custom_icon_type: type,
209
+ fontUrl: `${ base }/fonts/fontastic.svg`,
210
+ };
211
+ }
212
+
213
+ if ( 'fontello' === type ) {
214
+ return {
215
+ custom_icon_type: type,
216
+ configUrl: `${ base }/config.json`,
217
+ fontUrl: `${ base }/font/fontello.svg`,
218
+ };
219
+ }
220
+
221
+ return {};
222
+ } catch {
223
+ return type ? { custom_icon_type: type } : {};
224
+ }
225
+ }
226
+
227
+ async function loadCustomLibrary(
228
+ library: CustomIconLibraryConfig,
229
+ signal?: AbortSignal
230
+ ): Promise< FontAwesome7Icon[] > {
231
+ enqueueIconFonts( library.name );
232
+
233
+ const names = parseIconNames( await loadLibraryPayload( library, signal ) );
234
+ const svgMap = await loadLibrarySvgMap( library.name, library, signal );
235
+
236
+ return names.map( ( name ) => {
237
+ const value = createCustomIconSelectionValue( library, name );
238
+
239
+ return {
240
+ id: `${ library.name }:${ name }`,
241
+ name,
242
+ label: name.replace( /-/g, ' ' ),
243
+ library: library.name,
244
+ value,
245
+ aliases: [],
246
+ width: DEFAULT_ICON_SIZE,
247
+ height: DEFAULT_ICON_SIZE,
248
+ paths: [],
249
+ glyphClass: value,
250
+ svgMarkup: svgMap[ value ],
251
+ };
252
+ } );
253
+ }
254
+
255
+ async function loadLibrarySvgMap(
256
+ library: string,
257
+ config?: CustomIconLibraryConfig,
258
+ signal?: AbortSignal
259
+ ): Promise< Record< string, string > > {
260
+ if ( ! config ) {
261
+ svgMapCache.delete( library );
262
+ inFlightSvgMaps.delete( library );
263
+
264
+ return {};
265
+ }
266
+
267
+ const cached = svgMapCache.get( library );
268
+
269
+ if ( cached && Object.keys( cached ).length > 0 ) {
270
+ return cached;
271
+ }
272
+
273
+ const pending = inFlightSvgMaps.get( library );
274
+
275
+ if ( pending ) {
276
+ return pending;
277
+ }
278
+
279
+ const request = fetchLibrarySvgMap( library, config, signal ).finally( () => {
280
+ inFlightSvgMaps.delete( library );
281
+ } );
282
+
283
+ inFlightSvgMaps.set( library, request );
284
+
285
+ return request;
286
+ }
287
+
288
+ async function fetchLibrarySvgMap(
289
+ library: string,
290
+ config: CustomIconLibraryConfig,
291
+ signal?: AbortSignal
292
+ ): Promise< Record< string, string > > {
293
+ const fromRest = await loadSvgMapFromRest( library, signal );
294
+ const restIcons = fromRest.icons;
295
+
296
+ if ( Object.keys( restIcons ).length > 0 && ! fromRest.truncated ) {
297
+ svgMapCache.set( library, restIcons );
298
+
299
+ return restIcons;
300
+ }
301
+
302
+ const fromPack = await loadSvgMapFromPackFiles( config, signal );
303
+ const merged = { ...fromPack, ...restIcons };
304
+
305
+ if ( Object.keys( merged ).length > 0 ) {
306
+ svgMapCache.set( library, merged );
307
+
308
+ return merged;
309
+ }
310
+
311
+ return {};
312
+ }
313
+
314
+ async function loadSvgMapFromRest(
315
+ library: string,
316
+ signal?: AbortSignal
317
+ ): Promise< { icons: Record< string, string >; truncated: boolean } > {
318
+ try {
319
+ const response = await httpService().get<
320
+ HttpResponse< { icons?: Record< string, unknown >; truncated?: unknown } >
321
+ >( CUSTOM_ICON_SVG_URL, { params: { library: String( library ) }, signal } );
322
+
323
+ return unwrapIconMap( response );
324
+ } catch {
325
+ return { icons: {}, truncated: false };
326
+ }
327
+ }
328
+
329
+ function unwrapIconMap( payload: unknown ): { icons: Record< string, string >; truncated: boolean } {
330
+ let current: unknown = payload;
331
+
332
+ for ( let depth = 0; depth < 4; depth++ ) {
333
+ if ( ! current || typeof current !== 'object' ) {
334
+ return { icons: {}, truncated: false };
335
+ }
336
+
337
+ const record = current as Record< string, unknown >;
338
+
339
+ if ( record.icons && typeof record.icons === 'object' && ! Array.isArray( record.icons ) ) {
340
+ const icons: Record< string, string > = {};
341
+
342
+ Object.entries( record.icons as Record< string, unknown > ).forEach( ( [ key, value ] ) => {
343
+ if ( typeof value === 'string' && value !== '' ) {
344
+ icons[ key ] = value;
345
+ }
346
+ } );
347
+
348
+ return {
349
+ icons,
350
+ truncated: true === record.truncated,
351
+ };
352
+ }
353
+
354
+ current = 'data' in record ? record.data : undefined;
355
+ }
356
+
357
+ return { icons: {}, truncated: false };
358
+ }
359
+
360
+ async function loadSvgMapFromPackFiles(
361
+ library: CustomIconLibraryConfig,
362
+ signal?: AbortSignal
363
+ ): Promise< Record< string, string > > {
364
+ const type = resolveCustomIconType( library );
365
+
366
+ if ( ! type ) {
367
+ return {};
368
+ }
369
+
370
+ if ( 'icomoon' === type && library.selectionUrl ) {
371
+ try {
372
+ const response = await fetch( library.selectionUrl, { signal, mode: 'cors' } );
373
+
374
+ if ( response.ok ) {
375
+ const selectionJson = await response.text();
376
+ const names = parseIconNames( safeJson( selectionJson ) );
377
+ const payloadNames = names.length > 0 ? names : parseIconNames( { icons: library.icons } );
378
+ const fromSelection = parseIcomoonSelection(
379
+ selectionJson,
380
+ library.prefix,
381
+ library.displayPrefix ?? '',
382
+ payloadNames
383
+ );
384
+
385
+ if ( Object.keys( fromSelection ).length > 0 ) {
386
+ return fromSelection;
387
+ }
388
+ }
389
+ } catch {
390
+ // Continue with SVG-font fallback.
391
+ }
392
+ }
393
+
394
+ const fontUrls = uniqueUrls( [
395
+ library.fontUrl,
396
+ 'fontello' === type && library.fetchJson ? packSiblingUrl( library.fetchJson, 'font/fontello.svg' ) : null,
397
+ 'fontastic' === type && library.fetchJson ? packSiblingUrl( library.fetchJson, 'fonts/fontastic.svg' ) : null,
398
+ 'icomoon' === type && library.fetchJson ? packSiblingUrl( library.fetchJson, 'fonts/icomoon.svg' ) : null,
399
+ ] );
400
+
401
+ if ( fontUrls.length === 0 ) {
402
+ return {};
403
+ }
404
+
405
+ let configJson = '{}';
406
+
407
+ if ( library.configUrl ) {
408
+ try {
409
+ const configResponse = await fetch( library.configUrl, { signal, mode: 'cors' } );
410
+
411
+ if ( configResponse.ok ) {
412
+ configJson = await configResponse.text();
413
+ }
414
+ } catch {
415
+ configJson = '{}';
416
+ }
417
+ }
418
+
419
+ const names = parseIconNames( safeJson( configJson ) );
420
+ const payloadNames = names.length > 0 ? names : parseIconNames( { icons: library.icons } );
421
+
422
+ for ( const fontUrl of fontUrls ) {
423
+ try {
424
+ const fontResponse = await fetch( fontUrl, { signal, mode: 'cors' } );
425
+
426
+ if ( ! fontResponse.ok ) {
427
+ continue;
428
+ }
429
+
430
+ const fromFont = parseFontelloSvgFont(
431
+ configJson,
432
+ await fontResponse.text(),
433
+ library.prefix,
434
+ library.displayPrefix ?? '',
435
+ payloadNames
436
+ );
437
+
438
+ if ( Object.keys( fromFont ).length > 0 ) {
439
+ return fromFont;
440
+ }
441
+ } catch {
442
+ continue;
443
+ }
444
+ }
445
+
446
+ return {};
447
+ }
448
+
449
+ function packSiblingUrl( fetchJson: string, relativePath: string ): string | null {
450
+ try {
451
+ const url = new URL( fetchJson, window.location.origin );
452
+
453
+ url.pathname = url.pathname.replace( /\/[^/]+$/, `/${ relativePath }` );
454
+
455
+ return url.href;
456
+ } catch {
457
+ return null;
458
+ }
459
+ }
460
+
461
+ function uniqueUrls( urls: Array< string | null | undefined > ): string[] {
462
+ return [ ...new Set( urls.filter( ( url ): url is string => typeof url === 'string' && url !== '' ) ) ];
463
+ }
464
+
465
+ function safeJson( value: string ): unknown {
466
+ try {
467
+ return JSON.parse( value );
468
+ } catch {
469
+ return null;
470
+ }
471
+ }
472
+
473
+ async function loadLibraryPayload( library: CustomIconLibraryConfig, signal?: AbortSignal ): Promise< unknown > {
474
+ if ( library.icons !== undefined ) {
475
+ return { icons: library.icons };
476
+ }
477
+
478
+ if ( ! library.fetchJson ) {
479
+ return null;
480
+ }
481
+
482
+ try {
483
+ const response = await fetch( library.fetchJson, { signal, mode: 'cors' } );
484
+
485
+ return response.ok ? response.json() : null;
486
+ } catch {
487
+ return null;
488
+ }
489
+ }
490
+
491
+ function parseIconNames( payload: unknown ): string[] {
492
+ if ( ! payload || typeof payload !== 'object' ) {
493
+ return [];
494
+ }
495
+
496
+ const icons = ( payload as { icons?: unknown } ).icons;
497
+
498
+ if ( Array.isArray( icons ) ) {
499
+ return icons
500
+ .flatMap( ( entry ) => {
501
+ if ( typeof entry === 'string' ) {
502
+ return [ normalizeIconName( entry ) ];
503
+ }
504
+
505
+ if ( entry && typeof entry === 'object' && 'name' in entry && typeof entry.name === 'string' ) {
506
+ return [ normalizeIconName( entry.name ) ];
507
+ }
508
+
509
+ if (
510
+ entry &&
511
+ typeof entry === 'object' &&
512
+ 'properties' in entry &&
513
+ entry.properties &&
514
+ typeof entry.properties === 'object' &&
515
+ 'name' in entry.properties &&
516
+ typeof entry.properties.name === 'string'
517
+ ) {
518
+ return [ normalizeIconName( entry.properties.name ) ];
519
+ }
520
+
521
+ return [];
522
+ } )
523
+ .filter( Boolean );
524
+ }
525
+
526
+ if ( icons && typeof icons === 'object' ) {
527
+ return Object.keys( icons ).map( normalizeIconName ).filter( Boolean );
528
+ }
529
+
530
+ const glyphs = ( payload as { glyphs?: unknown } ).glyphs;
531
+
532
+ if ( Array.isArray( glyphs ) ) {
533
+ return glyphs
534
+ .flatMap( ( entry ) => {
535
+ if ( entry && typeof entry === 'object' && 'css' in entry && typeof entry.css === 'string' ) {
536
+ return [ normalizeIconName( entry.css ) ];
537
+ }
538
+
539
+ return [];
540
+ } )
541
+ .filter( Boolean );
542
+ }
543
+
544
+ return [];
545
+ }
546
+
547
+ function normalizeIconName( name: string ): string {
548
+ return name.trim().replace( /^:/, '' ).replace( /:$/, '' );
549
+ }
550
+
551
+ function createCustomIconSelectionValue( library: CustomIconLibraryConfig, name: string ): string {
552
+ const prefix = library.prefix;
553
+ const displayPrefix = library.displayPrefix || prefix.replace( /-$/, '' );
554
+
555
+ return `${ displayPrefix } ${ prefix }${ name }`.trim();
556
+ }
@@ -9,13 +9,15 @@ import {
9
9
  export { FONT_AWESOME_7_LIBRARIES, getFontAwesome7EditorConfig } from './font-awesome-7-data';
10
10
 
11
11
  export type FontAwesome7Library = ( typeof FONT_AWESOME_7_LIBRARIES )[ number ][ 'library' ];
12
- export type FontAwesome7LibraryFilter = FontAwesome7Library[];
12
+ export type FontAwesome7LibraryFilter = string[];
13
13
 
14
14
  export type FontAwesome7Icon = FontAwesome7IconDefinition & {
15
15
  id: string;
16
16
  label: string;
17
- library: FontAwesome7Library;
17
+ library: string;
18
18
  value: string;
19
+ glyphClass?: string;
20
+ svgMarkup?: string;
19
21
  };
20
22
 
21
23
  export async function loadFontAwesome7Catalog( signal?: AbortSignal ): Promise< FontAwesome7Icon[] > {
@@ -85,20 +87,27 @@ export function findFontAwesome7Icon(
85
87
  iconClass: string | null,
86
88
  library: string | null
87
89
  ): FontAwesome7Icon | undefined {
88
- const selectedId = getSelectedIconId( iconClass, library );
89
-
90
- if ( ! selectedId || ! library ) {
90
+ if ( ! iconClass || ! library ) {
91
91
  return undefined;
92
92
  }
93
93
 
94
- const selectedName = selectedId.slice( `${ library }:`.length );
94
+ const selectedId = getSelectedIconId( iconClass, library );
95
+ const selectedName = selectedId?.slice( `${ library }:`.length );
95
96
 
96
97
  return icons.find( ( icon ) => {
97
98
  if ( icon.library !== library ) {
98
99
  return false;
99
100
  }
100
101
 
101
- return icon.id === selectedId || icon.name === selectedName || icon.aliases.includes( selectedName );
102
+ if ( icon.value === iconClass || icon.id === selectedId ) {
103
+ return true;
104
+ }
105
+
106
+ if ( ! selectedName ) {
107
+ return false;
108
+ }
109
+
110
+ return icon.name === selectedName || icon.aliases.includes( selectedName );
102
111
  } );
103
112
  }
104
113
 
@@ -17,6 +17,7 @@ type FontAwesomeIconJson = [ number, number, unknown[], unknown, string | string
17
17
  export type FontAwesome7EditorConfig = {
18
18
  jsonFiles: string[];
19
19
  jsonBaseUrl: string;
20
+ filter?: unknown;
20
21
  };
21
22
 
22
23
  export type FontAwesome7IconDefinition = {
@@ -50,6 +51,7 @@ export function getFontAwesome7EditorConfig(): FontAwesome7EditorConfig | null {
50
51
  return {
51
52
  jsonFiles: config.jsonFiles,
52
53
  jsonBaseUrl,
54
+ filter: config.filter,
53
55
  };
54
56
  }
55
57