@unocss/preset-icons 0.44.3 → 0.44.7

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.
@@ -0,0 +1,437 @@
1
+ import { $fetch } from 'ohmyfetch';
2
+
3
+ const defaults = Object.freeze({
4
+ inline: false,
5
+ width: null,
6
+ height: null,
7
+ hAlign: "center",
8
+ vAlign: "middle",
9
+ slice: false,
10
+ hFlip: false,
11
+ vFlip: false,
12
+ rotate: 0
13
+ });
14
+
15
+ const iconDefaults = Object.freeze({
16
+ left: 0,
17
+ top: 0,
18
+ width: 16,
19
+ height: 16,
20
+ rotate: 0,
21
+ vFlip: false,
22
+ hFlip: false
23
+ });
24
+ function fullIcon(data) {
25
+ return { ...iconDefaults, ...data };
26
+ }
27
+
28
+ function mergeIconData(icon, alias) {
29
+ const result = { ...icon };
30
+ for (const key in iconDefaults) {
31
+ const prop = key;
32
+ if (alias[prop] !== void 0) {
33
+ const value = alias[prop];
34
+ if (result[prop] === void 0) {
35
+ result[prop] = value;
36
+ continue;
37
+ }
38
+ switch (prop) {
39
+ case "rotate":
40
+ result[prop] = (result[prop] + value) % 4;
41
+ break;
42
+ case "hFlip":
43
+ case "vFlip":
44
+ result[prop] = value !== result[prop];
45
+ break;
46
+ default:
47
+ result[prop] = value;
48
+ }
49
+ }
50
+ }
51
+ return result;
52
+ }
53
+
54
+ function getIconData(data, name, full = false) {
55
+ function getIcon(name2, iteration) {
56
+ if (data.icons[name2] !== void 0) {
57
+ return Object.assign({}, data.icons[name2]);
58
+ }
59
+ if (iteration > 5) {
60
+ return null;
61
+ }
62
+ const aliases = data.aliases;
63
+ if (aliases && aliases[name2] !== void 0) {
64
+ const item = aliases[name2];
65
+ const result2 = getIcon(item.parent, iteration + 1);
66
+ if (result2) {
67
+ return mergeIconData(result2, item);
68
+ }
69
+ return result2;
70
+ }
71
+ const chars = data.chars;
72
+ if (!iteration && chars && chars[name2] !== void 0) {
73
+ return getIcon(chars[name2], iteration + 1);
74
+ }
75
+ return null;
76
+ }
77
+ const result = getIcon(name, 0);
78
+ if (result) {
79
+ for (const key in iconDefaults) {
80
+ if (result[key] === void 0 && data[key] !== void 0) {
81
+ result[key] = data[key];
82
+ }
83
+ }
84
+ }
85
+ return result && full ? fullIcon(result) : result;
86
+ }
87
+
88
+ const unitsSplit = /(-?[0-9.]*[0-9]+[0-9.]*)/g;
89
+ const unitsTest = /^-?[0-9.]*[0-9]+[0-9.]*$/g;
90
+ function calculateSize(size, ratio, precision) {
91
+ if (ratio === 1) {
92
+ return size;
93
+ }
94
+ precision = precision === void 0 ? 100 : precision;
95
+ if (typeof size === "number") {
96
+ return Math.ceil(size * ratio * precision) / precision;
97
+ }
98
+ if (typeof size !== "string") {
99
+ return size;
100
+ }
101
+ const oldParts = size.split(unitsSplit);
102
+ if (oldParts === null || !oldParts.length) {
103
+ return size;
104
+ }
105
+ const newParts = [];
106
+ let code = oldParts.shift();
107
+ let isNumber = unitsTest.test(code);
108
+ while (true) {
109
+ if (isNumber) {
110
+ const num = parseFloat(code);
111
+ if (isNaN(num)) {
112
+ newParts.push(code);
113
+ } else {
114
+ newParts.push(Math.ceil(num * ratio * precision) / precision);
115
+ }
116
+ } else {
117
+ newParts.push(code);
118
+ }
119
+ code = oldParts.shift();
120
+ if (code === void 0) {
121
+ return newParts.join("");
122
+ }
123
+ isNumber = !isNumber;
124
+ }
125
+ }
126
+
127
+ function preserveAspectRatio(props) {
128
+ let result = "";
129
+ switch (props.hAlign) {
130
+ case "left":
131
+ result += "xMin";
132
+ break;
133
+ case "right":
134
+ result += "xMax";
135
+ break;
136
+ default:
137
+ result += "xMid";
138
+ }
139
+ switch (props.vAlign) {
140
+ case "top":
141
+ result += "YMin";
142
+ break;
143
+ case "bottom":
144
+ result += "YMax";
145
+ break;
146
+ default:
147
+ result += "YMid";
148
+ }
149
+ result += props.slice ? " slice" : " meet";
150
+ return result;
151
+ }
152
+ function iconToSVG(icon, customisations) {
153
+ const box = {
154
+ left: icon.left,
155
+ top: icon.top,
156
+ width: icon.width,
157
+ height: icon.height
158
+ };
159
+ let body = icon.body;
160
+ [icon, customisations].forEach((props) => {
161
+ const transformations = [];
162
+ const hFlip = props.hFlip;
163
+ const vFlip = props.vFlip;
164
+ let rotation = props.rotate;
165
+ if (hFlip) {
166
+ if (vFlip) {
167
+ rotation += 2;
168
+ } else {
169
+ transformations.push("translate(" + (box.width + box.left).toString() + " " + (0 - box.top).toString() + ")");
170
+ transformations.push("scale(-1 1)");
171
+ box.top = box.left = 0;
172
+ }
173
+ } else if (vFlip) {
174
+ transformations.push("translate(" + (0 - box.left).toString() + " " + (box.height + box.top).toString() + ")");
175
+ transformations.push("scale(1 -1)");
176
+ box.top = box.left = 0;
177
+ }
178
+ let tempValue;
179
+ if (rotation < 0) {
180
+ rotation -= Math.floor(rotation / 4) * 4;
181
+ }
182
+ rotation = rotation % 4;
183
+ switch (rotation) {
184
+ case 1:
185
+ tempValue = box.height / 2 + box.top;
186
+ transformations.unshift("rotate(90 " + tempValue.toString() + " " + tempValue.toString() + ")");
187
+ break;
188
+ case 2:
189
+ transformations.unshift("rotate(180 " + (box.width / 2 + box.left).toString() + " " + (box.height / 2 + box.top).toString() + ")");
190
+ break;
191
+ case 3:
192
+ tempValue = box.width / 2 + box.left;
193
+ transformations.unshift("rotate(-90 " + tempValue.toString() + " " + tempValue.toString() + ")");
194
+ break;
195
+ }
196
+ if (rotation % 2 === 1) {
197
+ if (box.left !== 0 || box.top !== 0) {
198
+ tempValue = box.left;
199
+ box.left = box.top;
200
+ box.top = tempValue;
201
+ }
202
+ if (box.width !== box.height) {
203
+ tempValue = box.width;
204
+ box.width = box.height;
205
+ box.height = tempValue;
206
+ }
207
+ }
208
+ if (transformations.length) {
209
+ body = '<g transform="' + transformations.join(" ") + '">' + body + "</g>";
210
+ }
211
+ });
212
+ let width, height;
213
+ if (customisations.width === null && customisations.height === null) {
214
+ height = "1em";
215
+ width = calculateSize(height, box.width / box.height);
216
+ } else if (customisations.width !== null && customisations.height !== null) {
217
+ width = customisations.width;
218
+ height = customisations.height;
219
+ } else if (customisations.height !== null) {
220
+ height = customisations.height;
221
+ width = calculateSize(height, box.width / box.height);
222
+ } else {
223
+ width = customisations.width;
224
+ height = calculateSize(width, box.height / box.width);
225
+ }
226
+ if (width === "auto") {
227
+ width = box.width;
228
+ }
229
+ if (height === "auto") {
230
+ height = box.height;
231
+ }
232
+ width = typeof width === "string" ? width : width.toString() + "";
233
+ height = typeof height === "string" ? height : height.toString() + "";
234
+ const result = {
235
+ attributes: {
236
+ width,
237
+ height,
238
+ preserveAspectRatio: preserveAspectRatio(customisations),
239
+ viewBox: box.left.toString() + " " + box.top.toString() + " " + box.width.toString() + " " + box.height.toString()
240
+ },
241
+ body
242
+ };
243
+ if (customisations.inline) {
244
+ result.inline = true;
245
+ }
246
+ return result;
247
+ }
248
+
249
+ function trimSVG(str) {
250
+ return str.replace(/(["';{}><])\s*\n\s*/g, "$1").replace(/\s*\n\s*/g, " ").replace(/\s+"/g, '"').replace(/="\s+/g, '="').trim();
251
+ }
252
+
253
+ const svgWidthRegex = /width\s*=\s*["'](\w+)["']/;
254
+ const svgHeightRegex = /height\s*=\s*["'](\w+)["']/;
255
+ function configureSvgSize(svg, props, scale) {
256
+ const svgNode = svg.slice(0, svg.indexOf(">"));
257
+ let result = svgWidthRegex.exec(svgNode);
258
+ const w = result != null;
259
+ if (typeof props.width === "undefined" || props.width === null) {
260
+ if (typeof scale === "number") {
261
+ props.width = `${scale}em`;
262
+ } else if (result) {
263
+ props.width = result[1];
264
+ }
265
+ }
266
+ result = svgHeightRegex.exec(svgNode);
267
+ const h = result != null;
268
+ if (typeof props.height === "undefined" || props.height === null) {
269
+ if (typeof scale === "number") {
270
+ props.height = `${scale}em`;
271
+ } else if (result) {
272
+ props.height = result[1];
273
+ }
274
+ }
275
+ return [w, h];
276
+ }
277
+ async function mergeIconProps(svg, collection, icon, options, propsProvider, afterCustomizations) {
278
+ const { scale, addXmlNs = false } = options ?? {};
279
+ const { additionalProps = {}, iconCustomizer } = options?.customizations ?? {};
280
+ const props = await propsProvider?.() ?? {};
281
+ await iconCustomizer?.(collection, icon, props);
282
+ Object.keys(additionalProps).forEach((p) => {
283
+ const v = additionalProps[p];
284
+ if (v !== void 0 && v !== null)
285
+ props[p] = v;
286
+ });
287
+ afterCustomizations?.(props);
288
+ const [widthOnSvg, heightOnSvg] = configureSvgSize(svg, props, scale);
289
+ if (addXmlNs) {
290
+ if (!svg.includes(" xmlns=") && !props["xmlns"]) {
291
+ props["xmlns"] = "http://www.w3.org/2000/svg";
292
+ }
293
+ if (!svg.includes(" xmlns:xlink=") && svg.includes("xlink:") && !props["xmlns:xlink"]) {
294
+ props["xmlns:xlink"] = "http://www.w3.org/1999/xlink";
295
+ }
296
+ }
297
+ const propsToAdd = Object.keys(props).map((p) => p === "width" && widthOnSvg || p === "height" && heightOnSvg ? null : `${p}="${props[p]}"`).filter((p) => p != null);
298
+ if (propsToAdd.length) {
299
+ svg = svg.replace("<svg ", `<svg ${propsToAdd.join(" ")} `);
300
+ }
301
+ if (options) {
302
+ const { defaultStyle, defaultClass } = options;
303
+ if (defaultClass && !svg.includes(" class=")) {
304
+ svg = svg.replace("<svg ", `<svg class="${defaultClass}" `);
305
+ }
306
+ if (defaultStyle && !svg.includes(" style=")) {
307
+ svg = svg.replace("<svg ", `<svg style="${defaultStyle}" `);
308
+ }
309
+ }
310
+ const usedProps = options?.usedProps;
311
+ if (usedProps) {
312
+ Object.keys(additionalProps).forEach((p) => {
313
+ const v = props[p];
314
+ if (v !== void 0 && v !== null)
315
+ usedProps[p] = v;
316
+ });
317
+ if (typeof props.width !== "undefined" && props.width !== null) {
318
+ usedProps.width = props.width;
319
+ }
320
+ if (typeof props.height !== "undefined" && props.height !== null) {
321
+ usedProps.height = props.height;
322
+ }
323
+ }
324
+ return svg;
325
+ }
326
+
327
+ async function getCustomIcon(custom, collection, icon, options) {
328
+ let result;
329
+ if (typeof custom === "function") {
330
+ result = await custom(icon);
331
+ } else {
332
+ const inline = custom[icon];
333
+ result = typeof inline === "function" ? await inline() : inline;
334
+ }
335
+ if (result) {
336
+ const cleanupIdx = result.indexOf("<svg");
337
+ if (cleanupIdx > 0)
338
+ result = result.slice(cleanupIdx);
339
+ const { transform } = options?.customizations ?? {};
340
+ result = typeof transform === "function" ? await transform(result, collection, icon) : result;
341
+ if (!result.startsWith("<svg")) {
342
+ console.warn(`Custom icon "${icon}" in "${collection}" is not a valid SVG`);
343
+ return result;
344
+ }
345
+ return await mergeIconProps(options?.customizations?.trimCustomSvg === true ? trimSVG(result) : result, collection, icon, options, void 0);
346
+ }
347
+ }
348
+
349
+ async function searchForIcon(iconSet, collection, ids, options) {
350
+ let iconData;
351
+ const { customize } = options?.customizations ?? {};
352
+ for (const id of ids) {
353
+ iconData = getIconData(iconSet, id, true);
354
+ if (iconData) {
355
+ let defaultCustomizations = { ...defaults };
356
+ if (typeof customize === "function")
357
+ defaultCustomizations = customize(defaultCustomizations);
358
+ const {
359
+ attributes: { width, height, ...restAttributes },
360
+ body
361
+ } = iconToSVG(iconData, defaultCustomizations);
362
+ const scale = options?.scale;
363
+ return await mergeIconProps(`<svg >${body}</svg>`, collection, id, options, () => {
364
+ return { ...restAttributes };
365
+ }, (props) => {
366
+ if (typeof props.width === "undefined" || props.width === null) {
367
+ if (typeof scale === "number") {
368
+ props.width = `${scale}em`;
369
+ } else {
370
+ props.width = width;
371
+ }
372
+ }
373
+ if (typeof props.height === "undefined" || props.height === null) {
374
+ if (typeof scale === "number") {
375
+ props.height = `${scale}em`;
376
+ } else {
377
+ props.height = height;
378
+ }
379
+ }
380
+ });
381
+ }
382
+ }
383
+ }
384
+
385
+ const loadIcon = async (collection, icon, options) => {
386
+ const custom = options?.customCollections?.[collection];
387
+ if (custom) {
388
+ if (typeof custom === "function") {
389
+ const result = await custom(icon);
390
+ if (result) {
391
+ if (typeof result === "string") {
392
+ return await getCustomIcon(() => result, collection, icon, options);
393
+ }
394
+ if ("icons" in result) {
395
+ const ids = [
396
+ icon,
397
+ icon.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase(),
398
+ icon.replace(/([a-z])(\d+)/g, "$1-$2")
399
+ ];
400
+ return await searchForIcon(result, collection, ids, options);
401
+ }
402
+ }
403
+ } else {
404
+ return await getCustomIcon(custom, collection, icon, options);
405
+ }
406
+ }
407
+ return void 0;
408
+ };
409
+
410
+ const supportedCollection = ["material-symbols", "ic", "mdi", "ph", "ri", "carbon", "bi", "tabler", "ion", "uil", "teenyicons", "clarity", "iconoir", "majesticons", "zondicons", "ant-design", "bx", "bxs", "gg", "cil", "lucide", "pixelarticons", "system-uicons", "ci", "akar-icons", "typcn", "radix-icons", "ep", "mdi-light", "fe", "eos-icons", "line-md", "charm", "prime", "heroicons-outline", "heroicons-solid", "uiw", "uim", "uit", "uis", "maki", "gridicons", "mi", "quill", "gala", "fluent", "icon-park-outline", "icon-park", "vscode-icons", "jam", "codicon", "pepicons", "bytesize", "ei", "fa6-solid", "fa6-regular", "octicon", "ooui", "nimbus", "openmoji", "twemoji", "noto", "noto-v1", "emojione", "emojione-monotone", "emojione-v1", "fxemoji", "bxl", "logos", "simple-icons", "cib", "fa6-brands", "arcticons", "file-icons", "brandico", "entypo-social", "cryptocurrency", "flag", "circle-flags", "flagpack", "cif", "gis", "map", "geo", "fad", "academicons", "wi", "healthicons", "medical-icon", "la", "eva", "dashicons", "flat-color-icons", "entypo", "foundation", "raphael", "icons8", "iwwa", "fa-solid", "fa-regular", "fa-brands", "fa", "fontisto", "icomoon-free", "ps", "subway", "oi", "wpf", "simple-line-icons", "et", "el", "vaadin", "grommet-icons", "whh", "si-glyph", "zmdi", "ls", "bpmn", "flat-ui", "vs", "topcoat", "il", "websymbol", "fontelico", "feather", "mono-icons"];
411
+ function createCDNLoader(cdnBase) {
412
+ const cache = /* @__PURE__ */ new Map();
413
+ function fetchCollection(name) {
414
+ if (!supportedCollection.includes(name))
415
+ return void 0;
416
+ if (!cache.has(name))
417
+ cache.set(name, $fetch(`${cdnBase}@iconify-json/${name}/icons.json`));
418
+ return cache.get(name);
419
+ }
420
+ return async (collection, icon, options) => {
421
+ let result = await loadIcon(collection, icon, options);
422
+ if (result)
423
+ return result;
424
+ const iconSet = await fetchCollection(collection);
425
+ if (iconSet) {
426
+ const ids = [
427
+ icon,
428
+ icon.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase(),
429
+ icon.replace(/([a-z])(\d+)/g, "$1-$2")
430
+ ];
431
+ result = await searchForIcon(iconSet, collection, ids, options);
432
+ }
433
+ return result;
434
+ };
435
+ }
436
+
437
+ export { createCDNLoader as c, loadIcon as l };
package/dist/core.cjs ADDED
@@ -0,0 +1,114 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ const core = require('@unocss/core');
6
+
7
+ function encodeSvgForCss(svg) {
8
+ let useSvg = svg.startsWith("<svg>") ? svg.replace("<svg>", "<svg >") : svg;
9
+ if (!useSvg.includes(" xmlns:xlink=") && useSvg.includes(" xlink:")) {
10
+ useSvg = useSvg.replace("<svg ", '<svg xmlns:xlink="http://www.w3.org/1999/xlink" ');
11
+ }
12
+ if (!useSvg.includes(" xmlns=")) {
13
+ useSvg = useSvg.replace("<svg ", '<svg xmlns="http://www.w3.org/2000/svg" ');
14
+ }
15
+ return useSvg.replace(/"/g, "'").replace(/%/g, "%25").replace(/#/g, "%23").replace(/{/g, "%7B").replace(/}/g, "%7D").replace(/</g, "%3C").replace(/>/g, "%3E");
16
+ }
17
+
18
+ const COLLECTION_NAME_PARTS_MAX = 3;
19
+ function createPresetIcons(lookupIconLoader) {
20
+ return function presetIcons(options = {}) {
21
+ const {
22
+ scale = 1,
23
+ mode = "auto",
24
+ prefix = "i-",
25
+ warn = false,
26
+ collections: customCollections,
27
+ extraProperties = {},
28
+ customizations = {},
29
+ autoInstall = false,
30
+ layer = "icons",
31
+ unit
32
+ } = options;
33
+ const loaderOptions = {
34
+ addXmlNs: true,
35
+ scale,
36
+ customCollections,
37
+ autoInstall,
38
+ warn: void 0,
39
+ customizations: {
40
+ ...customizations,
41
+ additionalProps: { ...extraProperties },
42
+ trimCustomSvg: true,
43
+ async iconCustomizer(collection, icon, props) {
44
+ await customizations.iconCustomizer?.(collection, icon, props);
45
+ if (unit) {
46
+ if (!props.width)
47
+ props.width = `${scale}${unit}`;
48
+ if (!props.height)
49
+ props.height = `${scale}${unit}`;
50
+ }
51
+ }
52
+ }
53
+ };
54
+ let iconLoader;
55
+ return {
56
+ name: "@unocss/preset-icons",
57
+ enforce: "pre",
58
+ options,
59
+ layers: { icons: -30 },
60
+ rules: [[
61
+ /^([a-z0-9:-]+)(?:\?(mask|bg|auto))?$/,
62
+ async ([full, body, _mode = mode]) => {
63
+ let collection = "";
64
+ let name = "";
65
+ let svg;
66
+ iconLoader = iconLoader || await lookupIconLoader(options);
67
+ const usedProps = {};
68
+ if (body.includes(":")) {
69
+ [collection, name] = body.split(":");
70
+ svg = await iconLoader(collection, name, { ...loaderOptions, usedProps });
71
+ } else {
72
+ const parts = body.split(/-/g);
73
+ for (let i = COLLECTION_NAME_PARTS_MAX; i >= 1; i--) {
74
+ collection = parts.slice(0, i).join("-");
75
+ name = parts.slice(i).join("-");
76
+ svg = await iconLoader(collection, name, { ...loaderOptions, usedProps });
77
+ if (svg)
78
+ break;
79
+ }
80
+ }
81
+ if (!svg) {
82
+ if (warn)
83
+ core.warnOnce(`failed to load icon "${full}"`);
84
+ return;
85
+ }
86
+ const url = `url("data:image/svg+xml;utf8,${encodeSvgForCss(svg)}")`;
87
+ if (_mode === "auto")
88
+ _mode = svg.includes("currentColor") ? "mask" : "bg";
89
+ if (_mode === "mask") {
90
+ return {
91
+ "--un-icon": url,
92
+ "mask": "var(--un-icon) no-repeat",
93
+ "mask-size": "100% 100%",
94
+ "-webkit-mask": "var(--un-icon) no-repeat",
95
+ "-webkit-mask-size": "100% 100%",
96
+ "background-color": "currentColor",
97
+ ...usedProps
98
+ };
99
+ } else {
100
+ return {
101
+ "background": `${url} no-repeat`,
102
+ "background-size": "100% 100%",
103
+ "background-color": "transparent",
104
+ ...usedProps
105
+ };
106
+ }
107
+ },
108
+ { layer, prefix }
109
+ ]]
110
+ };
111
+ };
112
+ }
113
+
114
+ exports.createPresetIcons = createPresetIcons;
package/dist/core.d.ts ADDED
@@ -0,0 +1,82 @@
1
+ import { Awaitable, Preset } from '@unocss/core';
2
+ import { CustomIconLoader, InlineCollection, IconCustomizations, UniversalIconLoader } from '@iconify/utils/lib/loader/types';
3
+ import { IconifyJSON } from '@iconify/types';
4
+
5
+ interface IconsOptions {
6
+ /**
7
+ * Scale related to the current font size (1em).
8
+ *
9
+ * @default 1
10
+ */
11
+ scale?: number;
12
+ /**
13
+ * Mode of generated CSS icons.
14
+ *
15
+ * - `mask` - use background color and the `mask` property for monochrome icons
16
+ * - `background-img` - use background image for the icons, colors are static
17
+ * - `auto` - smartly decide mode between `mask` and `background-img` per icon based on its style
18
+ *
19
+ * @default 'auto'
20
+ * @see https://antfu.me/posts/icons-in-pure-css
21
+ */
22
+ mode?: 'mask' | 'background-img' | 'auto';
23
+ /**
24
+ * Class prefix for matching icon rules.
25
+ *
26
+ * @default `i-`
27
+ */
28
+ prefix?: string;
29
+ /**
30
+ * Extra CSS properties applied to the generated CSS
31
+ *
32
+ * @default {}
33
+ */
34
+ extraProperties?: Record<string, string>;
35
+ /**
36
+ * Emit warning when missing icons are matched
37
+ *
38
+ * @default false
39
+ */
40
+ warn?: boolean;
41
+ /**
42
+ * In Node.js environment, the preset will search for the installed iconify dataset automatically.
43
+ * When using in the browser, this options is provided to provide dataset with custom loading mechanism.
44
+ */
45
+ collections?: Record<string, (() => Awaitable<IconifyJSON>) | undefined | CustomIconLoader | InlineCollection>;
46
+ /**
47
+ * Rule layer
48
+ *
49
+ * @default 'icons'
50
+ */
51
+ layer?: string;
52
+ /**
53
+ * Custom icon customizations.
54
+ */
55
+ customizations?: Omit<IconCustomizations, 'additionalProps' | 'trimCustomSvg'>;
56
+ /**
57
+ * Auto install icon sources package when the usages is detected
58
+ *
59
+ * **WARNING**: only on `node` environment, on `browser` this option will be ignored.
60
+ *
61
+ * @default false
62
+ */
63
+ autoInstall?: boolean;
64
+ /**
65
+ * Custom icon unit.
66
+ *
67
+ * @default `em`
68
+ */
69
+ unit?: string;
70
+ /**
71
+ * Load icons from CDN. Should starts with `https://` and ends with `/`
72
+ *
73
+ * Recommends:
74
+ * - https://esm.sh/
75
+ * - https://cdn.skypack.dev/
76
+ */
77
+ cdn?: string;
78
+ }
79
+
80
+ declare function createPresetIcons(lookupIconLoader: (options: IconsOptions) => Promise<UniversalIconLoader>): (options?: IconsOptions) => Preset;
81
+
82
+ export { IconsOptions, createPresetIcons };