@iconify/css-solid 1.0.0
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/basic.d.ts +9 -0
- package/dist/basic.js +31 -0
- package/dist/content-CDW-lEJw.js +164 -0
- package/dist/create-Dw3RUxi7.js +66 -0
- package/dist/defaults-Chz3Ncto.js +26 -0
- package/dist/helpers/add.d.ts +6 -0
- package/dist/helpers/add.js +4 -0
- package/dist/helpers/api.d.ts +63 -0
- package/dist/helpers/api.js +4 -0
- package/dist/helpers/get-icon.d.ts +9 -0
- package/dist/helpers/get-icon.js +16 -0
- package/dist/helpers/ids.d.ts +5 -0
- package/dist/helpers/ids.js +3 -0
- package/dist/helpers/load-icon.d.ts +7 -0
- package/dist/helpers/load-icon.js +32 -0
- package/dist/helpers/load-icons.d.ts +16 -0
- package/dist/helpers/load-icons.js +84 -0
- package/dist/helpers/preload.d.ts +7 -0
- package/dist/helpers/preload.js +16 -0
- package/dist/helpers/size.d.ts +16 -0
- package/dist/helpers/size.js +3 -0
- package/dist/helpers/subscribe.d.ts +17 -0
- package/dist/helpers/subscribe.js +7 -0
- package/dist/helpers/support.d.ts +7 -0
- package/dist/helpers/support.js +3 -0
- package/dist/id-T2WpjqBw.js +42 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +83 -0
- package/dist/loaders-DBdOeKSg.js +22 -0
- package/dist/name-DNHxp3hA.d.ts +12 -0
- package/dist/name-IUXED86s.js +58 -0
- package/dist/parse-BHmkG8X9.js +104 -0
- package/dist/props.d.ts +17 -0
- package/dist/props.js +1 -0
- package/dist/queue-Bmgy8iLP.js +135 -0
- package/dist/size-B1gNk5pj.js +59 -0
- package/dist/status-AnfUd3wQ.js +5 -0
- package/dist/storage-B47thT4x.js +99 -0
- package/dist/subscribe-B6af4-2Z.js +68 -0
- package/dist/subscription-CamYRvPj.js +23 -0
- package/dist/support-CYSnYd4U.js +14 -0
- package/license.txt +21 -0
- package/package.json +50 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regular expression for finding ids
|
|
3
|
+
*/
|
|
4
|
+
const regex = /\sid="(\S+)"/g;
|
|
5
|
+
/**
|
|
6
|
+
* Counters
|
|
7
|
+
*/
|
|
8
|
+
const counters = /* @__PURE__ */ new Map();
|
|
9
|
+
/**
|
|
10
|
+
* Get unique new ID
|
|
11
|
+
*/
|
|
12
|
+
function nextID(id) {
|
|
13
|
+
id = id.replace(/[0-9]+$/, "") || "a";
|
|
14
|
+
const count = counters.get(id) || 0;
|
|
15
|
+
counters.set(id, count + 1);
|
|
16
|
+
return count ? `${id}${count}` : id;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Replace IDs in SVG output with unique IDs
|
|
20
|
+
*/
|
|
21
|
+
function replaceIDs(body) {
|
|
22
|
+
const ids = [];
|
|
23
|
+
let match;
|
|
24
|
+
while (match = regex.exec(body)) ids.push(match[1]);
|
|
25
|
+
if (!ids.length) return body;
|
|
26
|
+
const suffix = "suffix" + (Math.random() * 16777216 | Date.now()).toString(16);
|
|
27
|
+
ids.forEach((id) => {
|
|
28
|
+
const newID = nextID(id);
|
|
29
|
+
const escapedID = id.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
30
|
+
body = body.replace(new RegExp("([#;\"])(" + escapedID + ")([\")]|\\.[a-z])", "g"), "$1" + newID + suffix + "$3");
|
|
31
|
+
});
|
|
32
|
+
body = body.replace(new RegExp(suffix, "g"), "");
|
|
33
|
+
return body;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Clear ID cache
|
|
37
|
+
*/
|
|
38
|
+
function clearIDCache() {
|
|
39
|
+
counters.clear();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export { replaceIDs as n, clearIDCache as t };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { CSSIconComponentProps, CSSIconComponentViewbox, CSSIconElementProps } from "./props.js";
|
|
2
|
+
import { t as IconifyIconName } from "./name-DNHxp3hA.js";
|
|
3
|
+
import { JSX } from "solid-js";
|
|
4
|
+
/**
|
|
5
|
+
* Basic icon component, without fallback
|
|
6
|
+
*
|
|
7
|
+
* Can be used when you do not need a fallback icon
|
|
8
|
+
*/
|
|
9
|
+
declare function Icon(props: CSSIconElementProps): JSX.Element;
|
|
10
|
+
export { type CSSIconComponentProps, type CSSIconComponentViewbox, type CSSIconElementProps, Icon, type IconifyIconName };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { t as renderContent } from "./content-CDW-lEJw.js";
|
|
2
|
+
import { t as getSizeProps } from "./size-B1gNk5pj.js";
|
|
3
|
+
import { r as setProviderLoader } from "./loaders-DBdOeKSg.js";
|
|
4
|
+
import "./parse-BHmkG8X9.js";
|
|
5
|
+
import { t as createIconifyAPILoader } from "./create-Dw3RUxi7.js";
|
|
6
|
+
import "./storage-B47thT4x.js";
|
|
7
|
+
import "./queue-Bmgy8iLP.js";
|
|
8
|
+
import { t as subscribeToIconData } from "./subscribe-B6af4-2Z.js";
|
|
9
|
+
import { t as renderCSS } from "./status-AnfUd3wQ.js";
|
|
10
|
+
import { createEffect, createMemo, createSignal, splitProps } from "solid-js";
|
|
11
|
+
import { mergeProps, spread, template } from "solid-js/web";
|
|
12
|
+
|
|
13
|
+
let policy;
|
|
14
|
+
/**
|
|
15
|
+
* Attempt to create policy
|
|
16
|
+
*/
|
|
17
|
+
function createPolicy() {
|
|
18
|
+
try {
|
|
19
|
+
policy = window.trustedTypes.createPolicy("iconify", { createHTML: (s) => s });
|
|
20
|
+
} catch (err) {
|
|
21
|
+
policy = null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Clean up value for innerHTML assignment
|
|
26
|
+
*
|
|
27
|
+
* This code doesn't actually clean up anything.
|
|
28
|
+
* It is intended be used with Iconify icon data, which has already been validated
|
|
29
|
+
*/
|
|
30
|
+
function cleanUpInnerHTML(html) {
|
|
31
|
+
if (policy === void 0) createPolicy();
|
|
32
|
+
return policy ? policy.createHTML(html) : html;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
setProviderLoader("", createIconifyAPILoader([
|
|
36
|
+
"https://api.iconify.design",
|
|
37
|
+
"https://api.simplesvg.com",
|
|
38
|
+
"https://api.unisvg.com"
|
|
39
|
+
]));
|
|
40
|
+
|
|
41
|
+
const _tmpl$ = /* @__PURE__ */ template(`<svg xmlns=http://www.w3.org/2000/svg>`);
|
|
42
|
+
/**
|
|
43
|
+
* Basic icon component, without fallback
|
|
44
|
+
*
|
|
45
|
+
* Can be used when you do not need a fallback icon
|
|
46
|
+
*/
|
|
47
|
+
function Icon(props) {
|
|
48
|
+
const [local, others] = splitProps(props, [
|
|
49
|
+
"content",
|
|
50
|
+
"fallback",
|
|
51
|
+
"width",
|
|
52
|
+
"height",
|
|
53
|
+
"viewBox"
|
|
54
|
+
]);
|
|
55
|
+
const [iconData, setIconData] = createSignal(null);
|
|
56
|
+
const [subscriberState, setSubscriber] = createSignal(null);
|
|
57
|
+
const renderedContent = createMemo(() => renderContent(local.content || ""));
|
|
58
|
+
const fallbackToRender = createMemo(() => renderCSS && local.content ? "" : local.fallback || "");
|
|
59
|
+
createEffect(() => {
|
|
60
|
+
const subscriber = subscribeToIconData(fallbackToRender(), setIconData);
|
|
61
|
+
setIconData(subscriber.data);
|
|
62
|
+
setSubscriber(subscriber);
|
|
63
|
+
return subscriber.unsubscribe;
|
|
64
|
+
}, []);
|
|
65
|
+
createEffect(() => {
|
|
66
|
+
subscriberState()?.change(fallbackToRender());
|
|
67
|
+
}, [fallbackToRender]);
|
|
68
|
+
const fallbackIcon = createMemo(() => {
|
|
69
|
+
const data = iconData();
|
|
70
|
+
return data ? renderContent(data) : "";
|
|
71
|
+
});
|
|
72
|
+
const size = createMemo(() => getSizeProps(local.width, local.height, local.viewBox));
|
|
73
|
+
const finalContent = createMemo(() => cleanUpInnerHTML(fallbackIcon() || renderedContent()));
|
|
74
|
+
return (() => {
|
|
75
|
+
const _el$ = _tmpl$();
|
|
76
|
+
spread(_el$, mergeProps(size, others, { get innerHTML() {
|
|
77
|
+
return finalContent();
|
|
78
|
+
} }), true, false);
|
|
79
|
+
return _el$;
|
|
80
|
+
})();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export { Icon };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const providerSpecificLoaders = Object.create(null);
|
|
2
|
+
const prefixSpecificLoaders = Object.create(null);
|
|
3
|
+
/**
|
|
4
|
+
* Set custom loader for an icon set
|
|
5
|
+
*/
|
|
6
|
+
function setLoader(prefix, loader) {
|
|
7
|
+
prefixSpecificLoaders[prefix] = loader;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Set custom loader for a provider
|
|
11
|
+
*/
|
|
12
|
+
function setProviderLoader(provider, loader) {
|
|
13
|
+
providerSpecificLoaders[provider] = loader;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Get loader
|
|
17
|
+
*/
|
|
18
|
+
function getLoader(provider, prefix) {
|
|
19
|
+
return provider ? providerSpecificLoaders[provider] : prefixSpecificLoaders[prefix] || providerSpecificLoaders[""];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export { setLoader as n, setProviderLoader as r, getLoader as t };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Expression to test part of icon name.
|
|
3
|
+
*
|
|
4
|
+
* Used when loading icons from Iconify API due to project naming convension.
|
|
5
|
+
* Ignored when using custom icon sets - convension does not apply.
|
|
6
|
+
*/
|
|
7
|
+
const matchIconName = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
8
|
+
/**
|
|
9
|
+
* Convert string icon name to IconifyIconName object.
|
|
10
|
+
*/
|
|
11
|
+
const stringToIcon = (value, validate, allowSimpleName, provider = "") => {
|
|
12
|
+
const colonSeparated = value.split(":");
|
|
13
|
+
if (value.slice(0, 1) === "@") {
|
|
14
|
+
if (colonSeparated.length < 2 || colonSeparated.length > 3) return null;
|
|
15
|
+
provider = colonSeparated.shift().slice(1);
|
|
16
|
+
}
|
|
17
|
+
if (colonSeparated.length > 3 || !colonSeparated.length) return null;
|
|
18
|
+
if (colonSeparated.length > 1) {
|
|
19
|
+
const name = colonSeparated.pop();
|
|
20
|
+
const prefix = colonSeparated.pop();
|
|
21
|
+
const result = {
|
|
22
|
+
provider: colonSeparated.length > 0 ? colonSeparated[0] : provider,
|
|
23
|
+
prefix,
|
|
24
|
+
name
|
|
25
|
+
};
|
|
26
|
+
return validate && !validateIconName(result) ? null : result;
|
|
27
|
+
}
|
|
28
|
+
const name = colonSeparated[0];
|
|
29
|
+
const dashSeparated = name.split("-");
|
|
30
|
+
if (dashSeparated.length > 1) {
|
|
31
|
+
const result = {
|
|
32
|
+
provider,
|
|
33
|
+
prefix: dashSeparated.shift(),
|
|
34
|
+
name: dashSeparated.join("-")
|
|
35
|
+
};
|
|
36
|
+
return validate && !validateIconName(result) ? null : result;
|
|
37
|
+
}
|
|
38
|
+
if (allowSimpleName && provider === "") {
|
|
39
|
+
const result = {
|
|
40
|
+
provider,
|
|
41
|
+
prefix: "",
|
|
42
|
+
name
|
|
43
|
+
};
|
|
44
|
+
return validate && !validateIconName(result, allowSimpleName) ? null : result;
|
|
45
|
+
}
|
|
46
|
+
return null;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Check if icon is valid.
|
|
50
|
+
*
|
|
51
|
+
* This function is not part of stringToIcon because validation is not needed for most code.
|
|
52
|
+
*/
|
|
53
|
+
const validateIconName = (icon, allowSimpleName) => {
|
|
54
|
+
if (!icon) return false;
|
|
55
|
+
return !!((allowSimpleName && icon.prefix === "" || !!icon.prefix) && !!icon.name);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export { stringToIcon as n, matchIconName as t };
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { r as defaultIconTransformations, t as defaultExtendedIconProps } from "./defaults-Chz3Ncto.js";
|
|
2
|
+
import { t as getIconStorage } from "./storage-B47thT4x.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Merge transformations
|
|
6
|
+
*/
|
|
7
|
+
function mergeIconTransformations(obj1, obj2) {
|
|
8
|
+
const result = {};
|
|
9
|
+
if (!obj1.hFlip !== !obj2.hFlip) result.hFlip = true;
|
|
10
|
+
if (!obj1.vFlip !== !obj2.vFlip) result.vFlip = true;
|
|
11
|
+
const rotate = ((obj1.rotate || 0) + (obj2.rotate || 0)) % 4;
|
|
12
|
+
if (rotate) result.rotate = rotate;
|
|
13
|
+
return result;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Merge icon and alias
|
|
18
|
+
*
|
|
19
|
+
* Can also be used to merge default values and icon
|
|
20
|
+
*/
|
|
21
|
+
function mergeIconData(parent, child) {
|
|
22
|
+
const result = mergeIconTransformations(parent, child);
|
|
23
|
+
for (const key in defaultExtendedIconProps) if (key in defaultIconTransformations) {
|
|
24
|
+
if (key in parent && !(key in result)) result[key] = defaultIconTransformations[key];
|
|
25
|
+
} else if (key in child) result[key] = child[key];
|
|
26
|
+
else if (key in parent) result[key] = parent[key];
|
|
27
|
+
return result;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Resolve icon set icons
|
|
32
|
+
*
|
|
33
|
+
* Returns parent icon for each icon
|
|
34
|
+
*/
|
|
35
|
+
function getIconsTree(data, names) {
|
|
36
|
+
const icons = data.icons;
|
|
37
|
+
const aliases = data.aliases || Object.create(null);
|
|
38
|
+
const resolved = Object.create(null);
|
|
39
|
+
function resolve(name) {
|
|
40
|
+
if (icons[name]) return resolved[name] = [];
|
|
41
|
+
if (!(name in resolved)) {
|
|
42
|
+
resolved[name] = null;
|
|
43
|
+
const parent = aliases[name] && aliases[name].parent;
|
|
44
|
+
const value = parent && resolve(parent);
|
|
45
|
+
if (value) resolved[name] = [parent].concat(value);
|
|
46
|
+
}
|
|
47
|
+
return resolved[name];
|
|
48
|
+
}
|
|
49
|
+
(names || Object.keys(icons).concat(Object.keys(aliases))).forEach(resolve);
|
|
50
|
+
return resolved;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Get icon data, using prepared aliases tree
|
|
55
|
+
*/
|
|
56
|
+
function internalGetIconData(data, name, tree) {
|
|
57
|
+
const icons = data.icons;
|
|
58
|
+
const aliases = data.aliases || Object.create(null);
|
|
59
|
+
let currentProps = {};
|
|
60
|
+
function parse(name) {
|
|
61
|
+
currentProps = mergeIconData(icons[name] || aliases[name], currentProps);
|
|
62
|
+
}
|
|
63
|
+
parse(name);
|
|
64
|
+
tree.forEach(parse);
|
|
65
|
+
return mergeIconData(data, currentProps);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Extract icons from an icon set
|
|
70
|
+
*
|
|
71
|
+
* Returns list of icons that were found in icon set
|
|
72
|
+
*/
|
|
73
|
+
function parseIconSet(data, callback) {
|
|
74
|
+
const names = [];
|
|
75
|
+
if (typeof data !== "object" || typeof data.icons !== "object") return names;
|
|
76
|
+
if (data.not_found instanceof Array) data.not_found.forEach((name) => {
|
|
77
|
+
callback(name, null);
|
|
78
|
+
names.push(name);
|
|
79
|
+
});
|
|
80
|
+
const tree = getIconsTree(data);
|
|
81
|
+
for (const name in tree) {
|
|
82
|
+
const item = tree[name];
|
|
83
|
+
if (item) {
|
|
84
|
+
callback(name, internalGetIconData(data, name, item));
|
|
85
|
+
names.push(name);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return names;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Add icon set to storage
|
|
93
|
+
*/
|
|
94
|
+
function addIconSetToStorage(data, provider = "") {
|
|
95
|
+
const added = /* @__PURE__ */ new Set();
|
|
96
|
+
const storage = getIconStorage(provider, data.prefix);
|
|
97
|
+
parseIconSet(data, (name, icon) => {
|
|
98
|
+
storage.update(name, icon);
|
|
99
|
+
added.add(name);
|
|
100
|
+
});
|
|
101
|
+
return added;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export { addIconSetToStorage as t };
|
package/dist/props.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { JSX } from "solid-js";
|
|
2
|
+
import { IconifyIcon } from "@iconify/types";
|
|
3
|
+
interface CSSIconComponentViewbox {
|
|
4
|
+
left?: number;
|
|
5
|
+
top?: number;
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
}
|
|
9
|
+
interface CSSIconComponentProps {
|
|
10
|
+
width?: string;
|
|
11
|
+
height?: string;
|
|
12
|
+
viewBox: CSSIconComponentViewbox;
|
|
13
|
+
content?: string | IconifyIcon;
|
|
14
|
+
fallback?: string | IconifyIcon;
|
|
15
|
+
}
|
|
16
|
+
interface CSSIconElementProps extends CSSIconComponentProps, Omit<JSX.SvgSVGAttributes<SVGSVGElement>, 'viewBox' | 'width' | 'height' | 'xmlns'> {}
|
|
17
|
+
export { CSSIconComponentProps, CSSIconComponentViewbox, CSSIconElementProps };
|
package/dist/props.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { t as getLoader } from "./loaders-DBdOeKSg.js";
|
|
2
|
+
import { n as stringToIcon, t as matchIconName } from "./name-IUXED86s.js";
|
|
3
|
+
import { t as addIconSetToStorage } from "./parse-BHmkG8X9.js";
|
|
4
|
+
import { r as triggerCallbackAsync, t as getIconStorage } from "./storage-B47thT4x.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Empty split icon names data
|
|
8
|
+
*/
|
|
9
|
+
function mergeSplitIconNames(data, addData) {
|
|
10
|
+
for (const provider in addData) {
|
|
11
|
+
const addProviderData = addData[provider];
|
|
12
|
+
const providerData = data[provider] || (data[provider] = Object.create(null));
|
|
13
|
+
for (const prefix in addProviderData) {
|
|
14
|
+
const prefixes = addProviderData[prefix];
|
|
15
|
+
if (!providerData[prefix]?.length) providerData[prefix] = prefixes.slice(0);
|
|
16
|
+
else providerData[prefix] = Array.from(new Set([...prefixes, ...providerData[prefix]]));
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Get list of icon names by provider and prefix
|
|
23
|
+
*/
|
|
24
|
+
function splitIconNames(names, oldData) {
|
|
25
|
+
const results = oldData || Object.create(null);
|
|
26
|
+
for (const iconName of names) {
|
|
27
|
+
const icon = typeof iconName === "string" ? stringToIcon(iconName) : iconName;
|
|
28
|
+
if (icon) {
|
|
29
|
+
const providerData = results[icon.provider] || (results[icon.provider] = Object.create(null));
|
|
30
|
+
const prefixData = providerData[icon.prefix] || (providerData[icon.prefix] = []);
|
|
31
|
+
if (!prefixData.includes(icon.name)) prefixData.push(icon.name);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return results;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Split icon names into queues
|
|
39
|
+
*/
|
|
40
|
+
function splitForBatchLoading(icons, config) {
|
|
41
|
+
const { maxCount, maxLength } = config;
|
|
42
|
+
icons.sort((a, b) => a.localeCompare(b));
|
|
43
|
+
const results = [];
|
|
44
|
+
let list = [];
|
|
45
|
+
let currentLength = 0;
|
|
46
|
+
for (const name of icons) {
|
|
47
|
+
const itemLength = name.length + 1;
|
|
48
|
+
if (currentLength) {
|
|
49
|
+
if (maxLength && currentLength + itemLength > maxLength || maxCount && list.length >= maxCount) {
|
|
50
|
+
results.push(list);
|
|
51
|
+
list = [];
|
|
52
|
+
currentLength = 0;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
currentLength += itemLength;
|
|
56
|
+
list.push(name);
|
|
57
|
+
}
|
|
58
|
+
if (list.length > 0) results.push(list);
|
|
59
|
+
return results;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
let queue = Object.create(null);
|
|
63
|
+
/**
|
|
64
|
+
* Parse queue
|
|
65
|
+
*/
|
|
66
|
+
function parseQueuedIcons() {
|
|
67
|
+
const oldQueue = queue;
|
|
68
|
+
queue = Object.create(null);
|
|
69
|
+
for (const provider in oldQueue) {
|
|
70
|
+
const providerData = oldQueue[provider];
|
|
71
|
+
for (const prefix in providerData) {
|
|
72
|
+
const names = providerData[prefix];
|
|
73
|
+
if (names.length) {
|
|
74
|
+
const storage = getIconStorage(provider, prefix);
|
|
75
|
+
const loader = getLoader(provider, prefix);
|
|
76
|
+
const allowReload = loader?.allowReload ?? false;
|
|
77
|
+
const validateNames = loader?.validateNames ?? true;
|
|
78
|
+
const namesToLoad = [];
|
|
79
|
+
names.forEach((name) => {
|
|
80
|
+
if (storage.pending.has(name)) return;
|
|
81
|
+
if (storage.icons[name] || storage.missing.has(name)) {
|
|
82
|
+
if (!allowReload) return;
|
|
83
|
+
}
|
|
84
|
+
if (!loader || validateNames && !matchIconName.test(name)) {
|
|
85
|
+
storage.update(name, null);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
namesToLoad.push(name);
|
|
89
|
+
storage.pending.add(name);
|
|
90
|
+
});
|
|
91
|
+
if (loader && namesToLoad.length) {
|
|
92
|
+
const promises = [];
|
|
93
|
+
if ("loadIcon" in loader) for (const name of namesToLoad) promises.push(new Promise((resolve) => {
|
|
94
|
+
loader.loadIcon(name, provider, prefix).then((data) => {
|
|
95
|
+
storage.update(name, data);
|
|
96
|
+
resolve();
|
|
97
|
+
}).catch(() => {
|
|
98
|
+
storage.update(name, null);
|
|
99
|
+
resolve();
|
|
100
|
+
});
|
|
101
|
+
}));
|
|
102
|
+
else {
|
|
103
|
+
const batches = splitForBatchLoading(namesToLoad, loader);
|
|
104
|
+
for (const batch of batches) {
|
|
105
|
+
const parse = (data) => {
|
|
106
|
+
const added = data ? addIconSetToStorage(data, provider) : /* @__PURE__ */ new Set();
|
|
107
|
+
for (const name of batch) if (!added.has(name)) storage.update(name, null);
|
|
108
|
+
};
|
|
109
|
+
promises.push(new Promise((resolve) => {
|
|
110
|
+
loader.loadIcons(batch, prefix, provider).then((data) => {
|
|
111
|
+
parse(data);
|
|
112
|
+
resolve();
|
|
113
|
+
}).catch(() => {
|
|
114
|
+
parse();
|
|
115
|
+
resolve();
|
|
116
|
+
});
|
|
117
|
+
}));
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
Promise.all(promises).catch(console.error);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Add icons to queue
|
|
128
|
+
*/
|
|
129
|
+
function loadIcons(iconNames, instant = false) {
|
|
130
|
+
const icons = Array.isArray(iconNames) ? splitIconNames(iconNames) : iconNames;
|
|
131
|
+
mergeSplitIconNames(queue, icons);
|
|
132
|
+
triggerCallbackAsync(parseQueuedIcons, instant);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export { splitIconNames as n, loadIcons as t };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regular expressions for calculating dimensions
|
|
3
|
+
*/
|
|
4
|
+
const unitsSplit = /(-?[0-9.]*[0-9]+[0-9.]*)/g;
|
|
5
|
+
const unitsTest = /^-?[0-9.]*[0-9]+[0-9.]*$/g;
|
|
6
|
+
function calculateSize(size, ratio, precision) {
|
|
7
|
+
if (ratio === 1) return size;
|
|
8
|
+
precision = precision || 100;
|
|
9
|
+
if (typeof size === "number") return Math.ceil(size * ratio * precision) / precision;
|
|
10
|
+
if (typeof size !== "string") return size;
|
|
11
|
+
const oldParts = size.split(unitsSplit);
|
|
12
|
+
if (oldParts === null || !oldParts.length) return size;
|
|
13
|
+
const newParts = [];
|
|
14
|
+
let code = oldParts.shift();
|
|
15
|
+
let isNumber = unitsTest.test(code);
|
|
16
|
+
while (true) {
|
|
17
|
+
if (isNumber) {
|
|
18
|
+
const num = parseFloat(code);
|
|
19
|
+
if (isNaN(num)) newParts.push(code);
|
|
20
|
+
else newParts.push(Math.ceil(num * ratio * precision) / precision);
|
|
21
|
+
} else newParts.push(code);
|
|
22
|
+
code = oldParts.shift();
|
|
23
|
+
if (code === void 0) return newParts.join("");
|
|
24
|
+
isNumber = !isNumber;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Convert IconViewBox to string
|
|
30
|
+
*/
|
|
31
|
+
function getIconViewBox(viewBox) {
|
|
32
|
+
return `${viewBox.left ?? 0} ${viewBox.top ?? 0} ${viewBox.width} ${viewBox.height}`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Get size properties for icon
|
|
37
|
+
*/
|
|
38
|
+
function getSizeProps(width, height, ratio) {
|
|
39
|
+
const viewBox = typeof ratio === "object" ? getIconViewBox(ratio) : void 0;
|
|
40
|
+
const ratioValue = typeof ratio === "number" ? ratio : ratio.width / ratio.height;
|
|
41
|
+
if (width && height) return {
|
|
42
|
+
width,
|
|
43
|
+
height,
|
|
44
|
+
viewBox
|
|
45
|
+
};
|
|
46
|
+
if (height) return {
|
|
47
|
+
width: calculateSize(height, ratioValue),
|
|
48
|
+
height,
|
|
49
|
+
viewBox
|
|
50
|
+
};
|
|
51
|
+
if (width) return {
|
|
52
|
+
width,
|
|
53
|
+
height: calculateSize(width, 1 / ratioValue),
|
|
54
|
+
viewBox
|
|
55
|
+
};
|
|
56
|
+
return { viewBox };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export { calculateSize as n, getSizeProps as t };
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
const queue = /* @__PURE__ */ new Set();
|
|
2
|
+
let isPending = false;
|
|
3
|
+
/**
|
|
4
|
+
* Parse callback
|
|
5
|
+
*/
|
|
6
|
+
function parseCallback(callback) {
|
|
7
|
+
try {
|
|
8
|
+
const result = callback();
|
|
9
|
+
if (result instanceof Promise) result.catch((error) => {
|
|
10
|
+
console.error(error);
|
|
11
|
+
});
|
|
12
|
+
} catch (error) {
|
|
13
|
+
console.error(error);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Asynchronous callback trigger
|
|
18
|
+
*/
|
|
19
|
+
function triggerCallbackAsync(callback, instant = false) {
|
|
20
|
+
if (instant) {
|
|
21
|
+
parseCallback(callback);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
queue.add(callback);
|
|
25
|
+
if (!isPending) {
|
|
26
|
+
isPending = true;
|
|
27
|
+
setTimeout(() => {
|
|
28
|
+
isPending = false;
|
|
29
|
+
const callbacks = Array.from(queue);
|
|
30
|
+
queue.clear();
|
|
31
|
+
callbacks.forEach(parseCallback);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Create icon storage
|
|
38
|
+
*/
|
|
39
|
+
function createIconStorage() {
|
|
40
|
+
const updated = /* @__PURE__ */ new Set();
|
|
41
|
+
let updatePending = false;
|
|
42
|
+
const icons = Object.create(null);
|
|
43
|
+
const missing = /* @__PURE__ */ new Set();
|
|
44
|
+
const pending = /* @__PURE__ */ new Set();
|
|
45
|
+
const subscribers = [];
|
|
46
|
+
function update(name, data) {
|
|
47
|
+
pending.delete(name);
|
|
48
|
+
if (data) {
|
|
49
|
+
if (icons[name] === data) return;
|
|
50
|
+
icons[name] = data;
|
|
51
|
+
missing.delete(name);
|
|
52
|
+
} else {
|
|
53
|
+
if (missing.has(name)) return;
|
|
54
|
+
delete icons[name];
|
|
55
|
+
missing.add(name);
|
|
56
|
+
}
|
|
57
|
+
updated.add(name);
|
|
58
|
+
if (!updatePending) {
|
|
59
|
+
updatePending = true;
|
|
60
|
+
setTimeout(() => {
|
|
61
|
+
updatePending = false;
|
|
62
|
+
subscribers.forEach((subscriber) => {
|
|
63
|
+
for (const name of subscriber.names) if (name === "*" || updated.has(name)) {
|
|
64
|
+
triggerCallbackAsync(subscriber.callback);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
updated.clear();
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
icons,
|
|
74
|
+
missing,
|
|
75
|
+
pending,
|
|
76
|
+
subscribers,
|
|
77
|
+
update
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const storage = Object.create(null);
|
|
82
|
+
/**
|
|
83
|
+
* Get storage for provider and prefix
|
|
84
|
+
*/
|
|
85
|
+
function getIconStorage(provider, prefix) {
|
|
86
|
+
const providerData = storage[provider] || (storage[provider] = Object.create(null));
|
|
87
|
+
return providerData[prefix] || (providerData[prefix] = createIconStorage());
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Iterate all available icon storage
|
|
91
|
+
*/
|
|
92
|
+
function iterateIconStorage(callback) {
|
|
93
|
+
for (const provider in storage) {
|
|
94
|
+
const providerData = storage[provider];
|
|
95
|
+
for (const prefix in providerData) callback(providerData[prefix], prefix, provider);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export { iterateIconStorage as n, triggerCallbackAsync as r, getIconStorage as t };
|