@elementor/editor-controls 4.4.0-1135 → 4.4.0-1137
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 +29 -3
- package/dist/index.d.ts +29 -3
- package/dist/index.js +158 -702
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +80 -626
- package/dist/index.mjs.map +1 -1
- package/package.json +16 -16
- package/src/controls/icon-library/icon-library-popover.tsx +4 -4
- package/src/controls/icon-library/icon-library-providers.ts +61 -0
- package/src/controls/svg-media-preview.tsx +5 -4
- package/src/index.ts +8 -1
- package/src/controls/icon-library/custom-icon-libraries.ts +0 -556
- package/src/controls/icon-library/fontello-svg-font.ts +0 -227
- package/src/controls/icon-library/icomoon-selection.ts +0 -104
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
type FontelloConfig = {
|
|
2
|
-
glyphs?: Array< { css?: unknown; code?: unknown; svg?: unknown } >;
|
|
3
|
-
};
|
|
4
|
-
|
|
5
|
-
type GlyphRecord = {
|
|
6
|
-
d: string;
|
|
7
|
-
units: number;
|
|
8
|
-
advance: number;
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
type GlyphIndex = {
|
|
12
|
-
byName: Map< string, GlyphRecord >;
|
|
13
|
-
byCode: Map< number, GlyphRecord >;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export function parseFontelloSvgFont(
|
|
17
|
-
configJson: string,
|
|
18
|
-
svgFont: string,
|
|
19
|
-
prefix: string,
|
|
20
|
-
displayPrefix: string,
|
|
21
|
-
iconNames: string[]
|
|
22
|
-
): Record< string, string > {
|
|
23
|
-
const codepoints = parseConfigCodepoints( configJson, prefix );
|
|
24
|
-
const configPaths = parseConfigSvgPaths( configJson, prefix );
|
|
25
|
-
const glyphs = parseSvgFontGlyphs( svgFont );
|
|
26
|
-
const resolvedDisplayPrefix = displayPrefix || prefix.replace( /-$/, '' );
|
|
27
|
-
const result: Record< string, string > = {};
|
|
28
|
-
|
|
29
|
-
for ( const name of iconNames ) {
|
|
30
|
-
const fromConfig =
|
|
31
|
-
configPaths.get( name ) ??
|
|
32
|
-
( prefix && name.startsWith( prefix ) ? configPaths.get( name.slice( prefix.length ) ) : undefined );
|
|
33
|
-
const glyph = fromConfig ?? findGlyph( glyphs, codepoints, name, prefix );
|
|
34
|
-
|
|
35
|
-
if ( ! glyph ) {
|
|
36
|
-
continue;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const value = `${ resolvedDisplayPrefix } ${ prefix }${ name }`.trim();
|
|
40
|
-
result[ value ] = buildIconSvg( glyph );
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return result;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export function fontelloSvgUrlFromConfig( fetchJson: string ): string | null {
|
|
47
|
-
try {
|
|
48
|
-
const url = new URL( fetchJson, window.location.origin );
|
|
49
|
-
url.pathname = url.pathname.replace( /\/[^/]+$/, '/font/fontello.svg' );
|
|
50
|
-
|
|
51
|
-
return url.href;
|
|
52
|
-
} catch {
|
|
53
|
-
return null;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function parseConfigCodepoints( configJson: string, prefix: string ): Map< string, number > {
|
|
58
|
-
const map = new Map< string, number >();
|
|
59
|
-
|
|
60
|
-
try {
|
|
61
|
-
const data = JSON.parse( configJson ) as FontelloConfig;
|
|
62
|
-
|
|
63
|
-
if ( ! Array.isArray( data.glyphs ) ) {
|
|
64
|
-
return map;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
for ( const glyph of data.glyphs ) {
|
|
68
|
-
if ( typeof glyph.css !== 'string' || glyph.css === '' || typeof glyph.code !== 'number' ) {
|
|
69
|
-
continue;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
map.set( glyph.css, glyph.code );
|
|
73
|
-
|
|
74
|
-
if ( prefix !== '' && ! glyph.css.startsWith( prefix ) ) {
|
|
75
|
-
map.set( `${ prefix }${ glyph.css }`, glyph.code );
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
} catch {
|
|
79
|
-
return map;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
return map;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function parseConfigSvgPaths( configJson: string, prefix: string ): Map< string, GlyphRecord > {
|
|
86
|
-
const map = new Map< string, GlyphRecord >();
|
|
87
|
-
|
|
88
|
-
try {
|
|
89
|
-
const data = JSON.parse( configJson ) as FontelloConfig;
|
|
90
|
-
|
|
91
|
-
if ( ! Array.isArray( data.glyphs ) ) {
|
|
92
|
-
return map;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
for ( const glyph of data.glyphs ) {
|
|
96
|
-
if ( typeof glyph.css !== 'string' || glyph.css === '' ) {
|
|
97
|
-
continue;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
let path = '';
|
|
101
|
-
let advance = 1000;
|
|
102
|
-
|
|
103
|
-
if ( typeof glyph.svg === 'string' ) {
|
|
104
|
-
path = glyph.svg;
|
|
105
|
-
} else if (
|
|
106
|
-
glyph.svg &&
|
|
107
|
-
typeof glyph.svg === 'object' &&
|
|
108
|
-
'path' in glyph.svg &&
|
|
109
|
-
typeof glyph.svg.path === 'string'
|
|
110
|
-
) {
|
|
111
|
-
path = glyph.svg.path;
|
|
112
|
-
if ( 'width' in glyph.svg && typeof glyph.svg.width === 'number' && glyph.svg.width > 0 ) {
|
|
113
|
-
advance = glyph.svg.width;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if ( path === '' ) {
|
|
118
|
-
continue;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
const record = { d: path, units: 1000, advance };
|
|
122
|
-
map.set( glyph.css, record );
|
|
123
|
-
|
|
124
|
-
if ( prefix !== '' && ! glyph.css.startsWith( prefix ) ) {
|
|
125
|
-
map.set( `${ prefix }${ glyph.css }`, record );
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
} catch {
|
|
129
|
-
return map;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
return map;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function parseSvgFontGlyphs( svgFont: string ): GlyphIndex {
|
|
136
|
-
const byName = new Map< string, GlyphRecord >();
|
|
137
|
-
const byCode = new Map< number, GlyphRecord >();
|
|
138
|
-
const doc = new DOMParser().parseFromString( stripDoctype( svgFont ), 'image/svg+xml' );
|
|
139
|
-
const font = doc.querySelector( 'font' );
|
|
140
|
-
const face = doc.querySelector( 'font-face' );
|
|
141
|
-
const fontAdvance = positiveInt( font?.getAttribute( 'horiz-adv-x' ), 1000 );
|
|
142
|
-
const units = positiveInt( face?.getAttribute( 'units-per-em' ), fontAdvance );
|
|
143
|
-
|
|
144
|
-
doc.querySelectorAll( 'glyph' ).forEach( ( node ) => {
|
|
145
|
-
const d = node.getAttribute( 'd' ) ?? '';
|
|
146
|
-
|
|
147
|
-
if ( d === '' ) {
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
const record: GlyphRecord = {
|
|
152
|
-
d,
|
|
153
|
-
units,
|
|
154
|
-
advance: positiveInt( node.getAttribute( 'horiz-adv-x' ), fontAdvance ),
|
|
155
|
-
};
|
|
156
|
-
const name = node.getAttribute( 'glyph-name' ) ?? '';
|
|
157
|
-
const unicode = node.getAttribute( 'unicode' ) ?? '';
|
|
158
|
-
const code = unicode.codePointAt( 0 );
|
|
159
|
-
|
|
160
|
-
if ( name ) {
|
|
161
|
-
byName.set( name, record );
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
if ( code !== undefined ) {
|
|
165
|
-
byCode.set( code, record );
|
|
166
|
-
}
|
|
167
|
-
} );
|
|
168
|
-
|
|
169
|
-
return { byName, byCode };
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
function findGlyph(
|
|
173
|
-
glyphs: GlyphIndex,
|
|
174
|
-
codepoints: Map< string, number >,
|
|
175
|
-
iconName: string,
|
|
176
|
-
prefix: string
|
|
177
|
-
): GlyphRecord | null {
|
|
178
|
-
const names = [ iconName ];
|
|
179
|
-
|
|
180
|
-
if ( prefix !== '' && iconName.startsWith( prefix ) ) {
|
|
181
|
-
names.push( iconName.slice( prefix.length ) );
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
for ( const name of names ) {
|
|
185
|
-
const byName = glyphs.byName.get( name );
|
|
186
|
-
|
|
187
|
-
if ( byName ) {
|
|
188
|
-
return byName;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
const code = codepoints.get( name );
|
|
192
|
-
const byCode = code !== undefined ? glyphs.byCode.get( code ) : undefined;
|
|
193
|
-
|
|
194
|
-
if ( byCode ) {
|
|
195
|
-
return byCode;
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
return null;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
function buildIconSvg( glyph: GlyphRecord ): string {
|
|
203
|
-
return (
|
|
204
|
-
`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${ glyph.advance } ${ glyph.units }" fill="currentColor" width="100%" height="100%">` +
|
|
205
|
-
`<g transform="translate(0,${ glyph.units }) scale(1,-1)">` +
|
|
206
|
-
`<path d="${ escapeAttribute( glyph.d ) }" fill="currentColor"></path>` +
|
|
207
|
-
`</g></svg>`
|
|
208
|
-
);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
function stripDoctype( svgFont: string ): string {
|
|
212
|
-
return svgFont.replace( /<!DOCTYPE[^>]*>/is, '' );
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
function positiveInt( value: string | null | undefined, fallback: number ): number {
|
|
216
|
-
if ( ! value ) {
|
|
217
|
-
return fallback;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
const parsed = Number.parseInt( value, 10 );
|
|
221
|
-
|
|
222
|
-
return parsed > 0 ? parsed : fallback;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
function escapeAttribute( value: string ): string {
|
|
226
|
-
return value.replace( /&/g, '&' ).replace( /"/g, '"' ).replace( /</g, '<' ).replace( />/g, '>' );
|
|
227
|
-
}
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
const DEFAULT_ICOMOON_VIEWBOX = 1024;
|
|
2
|
-
|
|
3
|
-
type IcomoonSelection = {
|
|
4
|
-
icons?: Array< {
|
|
5
|
-
icon?: { paths?: unknown; width?: unknown; tags?: unknown };
|
|
6
|
-
properties?: { name?: unknown };
|
|
7
|
-
} >;
|
|
8
|
-
preferences?: { fontPref?: { prefix?: unknown } };
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
export function parseIcomoonSelection(
|
|
12
|
-
selectionJson: string,
|
|
13
|
-
prefix: string,
|
|
14
|
-
displayPrefix: string,
|
|
15
|
-
iconNames: string[]
|
|
16
|
-
): Record< string, string > {
|
|
17
|
-
let data: IcomoonSelection;
|
|
18
|
-
|
|
19
|
-
try {
|
|
20
|
-
data = JSON.parse( selectionJson ) as IcomoonSelection;
|
|
21
|
-
} catch {
|
|
22
|
-
return {};
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const resolvedDisplayPrefix = displayPrefix || prefix.replace( /-$/, '' );
|
|
26
|
-
const names = iconNames.length > 0 ? iconNames : namesFromSelection( data );
|
|
27
|
-
const result: Record< string, string > = {};
|
|
28
|
-
|
|
29
|
-
for ( const name of names ) {
|
|
30
|
-
const markup = svgForName( data, name, prefix );
|
|
31
|
-
|
|
32
|
-
if ( ! markup ) {
|
|
33
|
-
continue;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
result[ `${ resolvedDisplayPrefix } ${ prefix }${ name }`.trim() ] = markup;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return result;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export function namesFromSelection( data: IcomoonSelection ): string[] {
|
|
43
|
-
if ( ! Array.isArray( data.icons ) ) {
|
|
44
|
-
return [];
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return data.icons.flatMap( ( icon ) => {
|
|
48
|
-
const name = iconEntryName( icon );
|
|
49
|
-
|
|
50
|
-
return name ? [ name ] : [];
|
|
51
|
-
} );
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function svgForName( data: IcomoonSelection, iconName: string, prefix: string ): string | null {
|
|
55
|
-
const candidates = [ iconName ];
|
|
56
|
-
|
|
57
|
-
if ( prefix && iconName.startsWith( prefix ) ) {
|
|
58
|
-
candidates.push( iconName.slice( prefix.length ) );
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
for ( const icon of data.icons ?? [] ) {
|
|
62
|
-
const name = iconEntryName( icon );
|
|
63
|
-
|
|
64
|
-
if ( ! name || ! candidates.includes( name ) ) {
|
|
65
|
-
continue;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const paths = Array.isArray( icon.icon?.paths )
|
|
69
|
-
? icon.icon.paths.filter( ( path ): path is string => typeof path === 'string' && path !== '' )
|
|
70
|
-
: [];
|
|
71
|
-
|
|
72
|
-
if ( paths.length === 0 ) {
|
|
73
|
-
return null;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const size =
|
|
77
|
-
typeof icon.icon?.width === 'number' && icon.icon.width > 0 ? icon.icon.width : DEFAULT_ICOMOON_VIEWBOX;
|
|
78
|
-
const pathMarkup = paths
|
|
79
|
-
.map( ( d ) => `<path d="${ escapeAttribute( d ) }" fill="currentColor"></path>` )
|
|
80
|
-
.join( '' );
|
|
81
|
-
|
|
82
|
-
return (
|
|
83
|
-
`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${ size } ${ size }" fill="currentColor" width="100%" height="100%">` +
|
|
84
|
-
pathMarkup +
|
|
85
|
-
'</svg>'
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
return null;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function iconEntryName( icon: NonNullable< IcomoonSelection[ 'icons' ] >[ number ] ): string {
|
|
93
|
-
if ( typeof icon.properties?.name === 'string' ) {
|
|
94
|
-
return icon.properties.name;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const tag = icon.icon?.tags;
|
|
98
|
-
|
|
99
|
-
return Array.isArray( tag ) && typeof tag[ 0 ] === 'string' ? tag[ 0 ] : '';
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
function escapeAttribute( value: string ): string {
|
|
103
|
-
return value.replace( /&/g, '&' ).replace( /"/g, '"' ).replace( /</g, '<' ).replace( />/g, '>' );
|
|
104
|
-
}
|