@icones/core 0.0.1
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/README.md +72 -0
- package/RUNTIME.md +81 -0
- package/UTILITIES.md +30 -0
- package/dist/catalog.d.ts +17 -0
- package/dist/catalog.js +115 -0
- package/dist/controller.d.ts +27 -0
- package/dist/controller.js +156 -0
- package/dist/data-DtdeiZ5o.d.ts +18 -0
- package/dist/data-N59s4mFY.js +189 -0
- package/dist/data.d.ts +4 -0
- package/dist/data.js +36 -0
- package/dist/element-types-C9jOyda4.d.ts +9 -0
- package/dist/element-types.d.ts +2 -0
- package/dist/element-types.js +0 -0
- package/dist/elements-DLSCanEZ.d.ts +16 -0
- package/dist/elements.d.ts +3 -0
- package/dist/elements.js +29 -0
- package/dist/icon-data-HGvJGwoB.d.ts +42 -0
- package/dist/icon-data.d.ts +2 -0
- package/dist/icon-data.js +95 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +15 -0
- package/dist/loaders-DxxA-L6t.d.ts +58 -0
- package/dist/loaders.d.ts +2 -0
- package/dist/loaders.js +112 -0
- package/dist/manifest.d.ts +9 -0
- package/dist/manifest.js +87 -0
- package/dist/presentation.d.ts +94 -0
- package/dist/presentation.js +189 -0
- package/dist/registry.d.ts +25 -0
- package/dist/registry.js +66 -0
- package/dist/resource-types.d.ts +68 -0
- package/dist/resource-types.js +0 -0
- package/dist/runtime.d.ts +7 -0
- package/dist/runtime.js +12 -0
- package/dist/set-options-C2BMGh-r.d.ts +11 -0
- package/dist/set-options.d.ts +2 -0
- package/dist/set-options.js +23 -0
- package/dist/sizes-CMxyEIpX.d.ts +10 -0
- package/dist/sizes.d.ts +2 -0
- package/dist/sizes.js +0 -0
- package/dist/slug.d.ts +5 -0
- package/dist/slug.js +7 -0
- package/dist/sources-CXcG9DjB.d.ts +11 -0
- package/dist/store.d.ts +36 -0
- package/dist/store.js +265 -0
- package/dist/svg-data.d.ts +2 -0
- package/dist/svg-data.js +2 -0
- package/dist/svg.d.ts +19 -0
- package/dist/svg.js +49 -0
- package/dist/symbol.d.ts +7 -0
- package/dist/symbol.js +22 -0
- package/dist/types.d.ts +30 -0
- package/dist/types.js +0 -0
- package/dist/view-box.d.ts +6 -0
- package/dist/view-box.js +9 -0
- package/package.json +133 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { parseViewBox } from "./view-box.js";
|
|
2
|
+
//#region src/svg/attributes.ts
|
|
3
|
+
const toReact = new Map([
|
|
4
|
+
"accent-height",
|
|
5
|
+
"alignment-baseline",
|
|
6
|
+
"arabic-form",
|
|
7
|
+
"baseline-shift",
|
|
8
|
+
"cap-height",
|
|
9
|
+
"clip-path",
|
|
10
|
+
"clip-rule",
|
|
11
|
+
"color-interpolation",
|
|
12
|
+
"color-interpolation-filters",
|
|
13
|
+
"color-profile",
|
|
14
|
+
"color-rendering",
|
|
15
|
+
"dominant-baseline",
|
|
16
|
+
"enable-background",
|
|
17
|
+
"fill-opacity",
|
|
18
|
+
"fill-rule",
|
|
19
|
+
"flood-color",
|
|
20
|
+
"flood-opacity",
|
|
21
|
+
"font-family",
|
|
22
|
+
"font-size",
|
|
23
|
+
"font-size-adjust",
|
|
24
|
+
"font-stretch",
|
|
25
|
+
"font-style",
|
|
26
|
+
"font-variant",
|
|
27
|
+
"font-weight",
|
|
28
|
+
"glyph-name",
|
|
29
|
+
"glyph-orientation-horizontal",
|
|
30
|
+
"glyph-orientation-vertical",
|
|
31
|
+
"horiz-adv-x",
|
|
32
|
+
"horiz-origin-x",
|
|
33
|
+
"image-rendering",
|
|
34
|
+
"letter-spacing",
|
|
35
|
+
"lighting-color",
|
|
36
|
+
"marker-end",
|
|
37
|
+
"marker-mid",
|
|
38
|
+
"marker-start",
|
|
39
|
+
"overline-position",
|
|
40
|
+
"overline-thickness",
|
|
41
|
+
"paint-order",
|
|
42
|
+
"panose-1",
|
|
43
|
+
"pointer-events",
|
|
44
|
+
"rendering-intent",
|
|
45
|
+
"shape-rendering",
|
|
46
|
+
"stop-color",
|
|
47
|
+
"stop-opacity",
|
|
48
|
+
"strikethrough-position",
|
|
49
|
+
"strikethrough-thickness",
|
|
50
|
+
"stroke-dasharray",
|
|
51
|
+
"stroke-dashoffset",
|
|
52
|
+
"stroke-linecap",
|
|
53
|
+
"stroke-linejoin",
|
|
54
|
+
"stroke-miterlimit",
|
|
55
|
+
"stroke-opacity",
|
|
56
|
+
"stroke-width",
|
|
57
|
+
"text-anchor",
|
|
58
|
+
"text-decoration",
|
|
59
|
+
"text-rendering",
|
|
60
|
+
"transform-origin",
|
|
61
|
+
"underline-position",
|
|
62
|
+
"underline-thickness",
|
|
63
|
+
"unicode-bidi",
|
|
64
|
+
"unicode-range",
|
|
65
|
+
"units-per-em",
|
|
66
|
+
"v-alphabetic",
|
|
67
|
+
"v-hanging",
|
|
68
|
+
"v-ideographic",
|
|
69
|
+
"v-mathematical",
|
|
70
|
+
"vector-effect",
|
|
71
|
+
"vert-adv-y",
|
|
72
|
+
"vert-origin-x",
|
|
73
|
+
"vert-origin-y",
|
|
74
|
+
"word-spacing",
|
|
75
|
+
"writing-mode",
|
|
76
|
+
"x-height",
|
|
77
|
+
"xlink:actuate",
|
|
78
|
+
"xlink:arcrole",
|
|
79
|
+
"xlink:href",
|
|
80
|
+
"xlink:role",
|
|
81
|
+
"xlink:show",
|
|
82
|
+
"xlink:title",
|
|
83
|
+
"xlink:type",
|
|
84
|
+
"xml:base",
|
|
85
|
+
"xml:lang",
|
|
86
|
+
"xml:space",
|
|
87
|
+
"xmlns:xlink"
|
|
88
|
+
].map((name) => [name, name.replace(/[-:]([a-z])/g, (_, letter) => letter.toUpperCase())]));
|
|
89
|
+
toReact.set("class", "className");
|
|
90
|
+
toReact.set("for", "htmlFor");
|
|
91
|
+
const toSvg = new Map([...toReact].map(([svg, react]) => [react, svg]));
|
|
92
|
+
/** Convert SVG attribute names to React-safe prop names. */
|
|
93
|
+
function reactAttributeName(name) {
|
|
94
|
+
return toReact.get(name) ?? name;
|
|
95
|
+
}
|
|
96
|
+
/** Convert tuple prop names back to SVG attributes; preserve unknown names. */
|
|
97
|
+
function svgAttributeName(name) {
|
|
98
|
+
return toSvg.get(name) ?? name;
|
|
99
|
+
}
|
|
100
|
+
//#endregion
|
|
101
|
+
//#region src/svg/data.ts
|
|
102
|
+
/** Escape reserved XML characters before string-based SVG serialization. */
|
|
103
|
+
function escapeXml(value) {
|
|
104
|
+
return String(value).replaceAll("&", "&").replaceAll("\"", """).replaceAll("<", "<").replaceAll(">", ">");
|
|
105
|
+
}
|
|
106
|
+
/** Wrap an already-rendered SVG body without parsing it or imposing collection rules. */
|
|
107
|
+
function createSvgSymbolDocument(body, viewBox, id = "icon") {
|
|
108
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><symbol id="${escapeXml(id)}" viewBox="${escapeXml(viewBox)}">${body}</symbol></defs></svg>`;
|
|
109
|
+
}
|
|
110
|
+
/** Render one tuple child and its descendants to a raw SVG snippet. */
|
|
111
|
+
function renderChild(child) {
|
|
112
|
+
if (typeof child === "string") return escapeXml(child);
|
|
113
|
+
const [tag, attributes] = child;
|
|
114
|
+
const props = Object.entries(attributes).filter(([key]) => key !== "key" && key !== "children").map(([key, value]) => ` ${svgAttributeName(key)}="${escapeXml(value)}"`).join("");
|
|
115
|
+
const children = attributes.children;
|
|
116
|
+
return children?.length ? `<${tag}${props}>${children.map(renderChild).join("")}</${tag}>` : `<${tag}${props}/>`;
|
|
117
|
+
}
|
|
118
|
+
/** Serialize tuples for SVG, SSR and Iconify-compatible APIs. No DOM/parser in the client. */
|
|
119
|
+
function elementDataToIcon(data, defaultFill = "none") {
|
|
120
|
+
const renderRoot = (child) => {
|
|
121
|
+
if (typeof child === "string") return renderChild(child);
|
|
122
|
+
const [tag, attributes] = child;
|
|
123
|
+
return renderChild([tag, attributes.fill === void 0 ? {
|
|
124
|
+
...attributes,
|
|
125
|
+
fill: defaultFill
|
|
126
|
+
} : attributes]);
|
|
127
|
+
};
|
|
128
|
+
if (data.length === 1 && data[0][0] === "svg") {
|
|
129
|
+
const [, { viewBox = "0 0 24 24", children = [], key: _key, ...attributes }] = data[0];
|
|
130
|
+
const dimensions = parseViewBox(String(viewBox));
|
|
131
|
+
if (!dimensions) throw new TypeError("Invalid tuple SVG viewBox.");
|
|
132
|
+
const [left, top, width, height] = dimensions;
|
|
133
|
+
return {
|
|
134
|
+
left,
|
|
135
|
+
top,
|
|
136
|
+
width,
|
|
137
|
+
height,
|
|
138
|
+
body: Object.keys(attributes).length ? renderRoot(["g", {
|
|
139
|
+
...attributes,
|
|
140
|
+
children
|
|
141
|
+
}]) : children.map(renderRoot).join("")
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
return {
|
|
145
|
+
width: 24,
|
|
146
|
+
height: 24,
|
|
147
|
+
body: data.map(renderRoot).join("")
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Minimal SVG viewport/quarter-turn renderer. No XML parsing, sizing presets or SDK.
|
|
152
|
+
* Body-only objects keep their historical 16×16 default; tuples carry explicit 24×24.
|
|
153
|
+
* Source transforms precede presentation transforms. SVG definitions remain intact.
|
|
154
|
+
*/
|
|
155
|
+
function renderSvgData(data, options = {}) {
|
|
156
|
+
let { left = 0, top = 0, width = 16, height = 16, body } = data;
|
|
157
|
+
if (![
|
|
158
|
+
left,
|
|
159
|
+
top,
|
|
160
|
+
width,
|
|
161
|
+
height
|
|
162
|
+
].every(Number.isFinite) || width <= 0 || height <= 0) throw new TypeError("Invalid SVG viewport.");
|
|
163
|
+
for (const { rotate = 0, hFlip = false, vFlip = false } of [data, options]) {
|
|
164
|
+
if (!Number.isInteger(rotate)) throw new TypeError("SVG rotation must use quarter turns.");
|
|
165
|
+
let turns = (rotate % 4 + 4) % 4;
|
|
166
|
+
const transforms = [];
|
|
167
|
+
if (hFlip && vFlip) turns = (turns + 2) % 4;
|
|
168
|
+
else if (hFlip || vFlip) {
|
|
169
|
+
transforms.push(`translate(${hFlip ? left + width : -left} ${vFlip ? top + height : -top})`, `scale(${hFlip ? -1 : 1} ${vFlip ? -1 : 1})`);
|
|
170
|
+
left = top = 0;
|
|
171
|
+
}
|
|
172
|
+
if (turns) {
|
|
173
|
+
const x = turns === 1 ? top + height / 2 : left + width / 2;
|
|
174
|
+
const y = turns === 2 ? top + height / 2 : x;
|
|
175
|
+
transforms.unshift(`rotate(${turns === 3 ? -90 : turns * 90} ${x} ${y})`);
|
|
176
|
+
if (turns % 2) {
|
|
177
|
+
[left, top] = [top, left];
|
|
178
|
+
[width, height] = [height, width];
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
if (transforms.length) body = `<g transform="${transforms.join(" ")}">${body}</g>`;
|
|
182
|
+
}
|
|
183
|
+
return {
|
|
184
|
+
body,
|
|
185
|
+
viewBox: `${left} ${top} ${width} ${height}`
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
//#endregion
|
|
189
|
+
export { svgAttributeName as a, reactAttributeName as i, elementDataToIcon as n, renderSvgData as r, createSvgSymbolDocument as t };
|
package/dist/data.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { t as isElementData } from "./elements-DLSCanEZ.js";
|
|
2
|
+
import { o as isIconData, s as isIconSet } from "./icon-data-HGvJGwoB.js";
|
|
3
|
+
import { n as resolveIconSetData, r as toData, t as parseIconName } from "./sources-CXcG9DjB.js";
|
|
4
|
+
export { isElementData, isIconData, isIconSet, parseIconName, resolveIconSetData, toData };
|
package/dist/data.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { isIconData, isIconSet, resolveSetIcon } from "./icon-data.js";
|
|
2
|
+
import { isElementData } from "./elements.js";
|
|
3
|
+
//#region src/runtime/sources.ts
|
|
4
|
+
/** Resolve an icon name from a full icon set payload when prefix/provider match. */
|
|
5
|
+
function resolveIconSetData(data, name) {
|
|
6
|
+
const parsedName = parseIconName(name);
|
|
7
|
+
const iconName = parsedName && parsedName.prefix === data.prefix && parsedName.provider === (data.provider ?? "") ? parsedName.name : name;
|
|
8
|
+
return resolveSetIcon(data, iconName);
|
|
9
|
+
}
|
|
10
|
+
/** Parse user icon refs and keep provider-aware prefix/name fields. */
|
|
11
|
+
function parseIconName(value) {
|
|
12
|
+
const parts = value.split(":");
|
|
13
|
+
let provider = "";
|
|
14
|
+
if (value.startsWith("@")) provider = parts.shift().slice(1);
|
|
15
|
+
else if (parts.length === 3) provider = parts.shift();
|
|
16
|
+
if (parts.length === 1) {
|
|
17
|
+
const dash = parts[0].indexOf("-");
|
|
18
|
+
if (dash <= 0) return null;
|
|
19
|
+
parts.splice(0, 1, parts[0].slice(0, dash), parts[0].slice(dash + 1));
|
|
20
|
+
}
|
|
21
|
+
if (parts.length !== 2 || !parts[0] || !parts[1]) return null;
|
|
22
|
+
return {
|
|
23
|
+
provider,
|
|
24
|
+
prefix: parts[0],
|
|
25
|
+
name: parts[1]
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/** Convert loaded results from loaders into a canonical runtime data shape. */
|
|
29
|
+
function toData(value, name) {
|
|
30
|
+
if (value == null) return null;
|
|
31
|
+
if (isElementData(value) || isIconData(value)) return value;
|
|
32
|
+
if (isIconSet(value)) return resolveIconSetData(value, name);
|
|
33
|
+
throw new TypeError(`Invalid icon data for ${name}.`);
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
export { isElementData, isIconData, isIconSet, parseIconName, resolveIconSetData, toData };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
//#region src/data/element-types.d.ts
|
|
2
|
+
type ElementNode = readonly [string, ElementAttributes];
|
|
3
|
+
type ElementChild = ElementNode | string;
|
|
4
|
+
type ElementAttributes = {
|
|
5
|
+
readonly [key: string]: string | number | readonly ElementChild[];
|
|
6
|
+
};
|
|
7
|
+
type ElementData = readonly ElementNode[];
|
|
8
|
+
//#endregion
|
|
9
|
+
export { ElementNode as i, ElementChild as n, ElementData as r, ElementAttributes as t };
|
|
File without changes
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { r as ElementData } from "./element-types-C9jOyda4.js";
|
|
2
|
+
//#region src/svg/attributes.d.ts
|
|
3
|
+
/** Convert SVG attribute names to React-safe prop names. */
|
|
4
|
+
declare function reactAttributeName(name: string): string;
|
|
5
|
+
/** Convert tuple prop names back to SVG attributes; preserve unknown names. */
|
|
6
|
+
declare function svgAttributeName(name: string): string;
|
|
7
|
+
//#endregion
|
|
8
|
+
//#region src/data/elements.d.ts
|
|
9
|
+
/** Check whether a value matches the `[tag, attrs]` tuple format. */
|
|
10
|
+
declare function isElementData(value: unknown): value is ElementData;
|
|
11
|
+
/** JSON imports are inferred as arrays, not fixed tuples. Validate once at the boundary. */
|
|
12
|
+
declare function parseElementData(value: unknown): ElementData;
|
|
13
|
+
/** Validate non-empty persisted tuples without loading an SVG/XML parser. */
|
|
14
|
+
declare function readElementData(value: unknown, name: string): ElementData;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { svgAttributeName as a, reactAttributeName as i, parseElementData as n, readElementData as r, isElementData as t };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { a as svgAttributeName, i as reactAttributeName, n as parseElementData, r as readElementData, t as isElementData } from "./elements-DLSCanEZ.js";
|
|
2
|
+
import { n as elementDataToIcon } from "./data-DtdeiZ5o.js";
|
|
3
|
+
export { elementDataToIcon, isElementData, parseElementData, reactAttributeName, readElementData, svgAttributeName };
|
package/dist/elements.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { a as svgAttributeName, i as reactAttributeName, n as elementDataToIcon } from "./data-N59s4mFY.js";
|
|
2
|
+
//#region src/data/elements.ts
|
|
3
|
+
const xmlName = /^[a-zA-Z_][a-zA-Z0-9_.:-]*$/;
|
|
4
|
+
/** Check whether a value matches the `[tag, attrs]` tuple format. */
|
|
5
|
+
function isElementData(value) {
|
|
6
|
+
return Array.isArray(value) && value.every(isElementNode);
|
|
7
|
+
}
|
|
8
|
+
/** JSON imports are inferred as arrays, not fixed tuples. Validate once at the boundary. */
|
|
9
|
+
function parseElementData(value) {
|
|
10
|
+
if (!isElementData(value)) throw new TypeError("Invalid icon element tuples.");
|
|
11
|
+
return value;
|
|
12
|
+
}
|
|
13
|
+
/** Validate non-empty persisted tuples without loading an SVG/XML parser. */
|
|
14
|
+
function readElementData(value, name) {
|
|
15
|
+
if (!isElementData(value) || !value.length) throw new TypeError(`Invalid element tuple JSON: ${name}`);
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
/** Validate element node shape recursively to prevent malformed trees at runtime. */
|
|
19
|
+
function isElementNode(value) {
|
|
20
|
+
if (!Array.isArray(value) || value.length !== 2 || typeof value[0] !== "string" || !xmlName.test(value[0])) return false;
|
|
21
|
+
const attributes = value[1];
|
|
22
|
+
if (!attributes || typeof attributes !== "object" || Array.isArray(attributes)) return false;
|
|
23
|
+
return Object.entries(attributes).every(([key, value]) => {
|
|
24
|
+
if (key === "children") return Array.isArray(value) && value.every((child) => typeof child === "string" || isElementNode(child));
|
|
25
|
+
return xmlName.test(key) && (typeof value === "string" || typeof value === "number" && Number.isFinite(value));
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
//#endregion
|
|
29
|
+
export { elementDataToIcon, isElementData, parseElementData, reactAttributeName, readElementData, svgAttributeName };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
//#region src/data/icon-data.d.ts
|
|
2
|
+
/** Native SVG payloads: structural types, not an SDK or a remote service contract. */
|
|
3
|
+
type IconDimensions = {
|
|
4
|
+
left?: number;
|
|
5
|
+
top?: number;
|
|
6
|
+
width?: number;
|
|
7
|
+
height?: number;
|
|
8
|
+
};
|
|
9
|
+
type IconTransform = {
|
|
10
|
+
/** Clockwise quarter turns. */
|
|
11
|
+
rotate?: number;
|
|
12
|
+
hFlip?: boolean;
|
|
13
|
+
vFlip?: boolean;
|
|
14
|
+
};
|
|
15
|
+
type IconData = IconDimensions & IconTransform & {
|
|
16
|
+
body: string;
|
|
17
|
+
hidden?: boolean;
|
|
18
|
+
};
|
|
19
|
+
type IconAlias = IconDimensions & IconTransform & {
|
|
20
|
+
parent: string;
|
|
21
|
+
hidden?: boolean;
|
|
22
|
+
};
|
|
23
|
+
/** Optional local collection shorthand. Metadata is not needed by the renderer. */
|
|
24
|
+
type IconSet = IconDimensions & {
|
|
25
|
+
prefix: string;
|
|
26
|
+
provider?: string;
|
|
27
|
+
icons: Record<string, IconData>;
|
|
28
|
+
aliases?: Record<string, IconAlias>;
|
|
29
|
+
/** Optional metadata for callers/build tools; runtime lookup does not read it. */
|
|
30
|
+
categories?: Record<string, string[]>;
|
|
31
|
+
};
|
|
32
|
+
/** Shallow single-body discriminator; use readIconData for import validation. */
|
|
33
|
+
declare function isIconData(value: unknown): value is IconData;
|
|
34
|
+
/** Check if a value is a full icon set payload. */
|
|
35
|
+
declare function isIconSet(value: unknown): value is IconSet;
|
|
36
|
+
declare function readIconData(value: unknown, name: string): IconData;
|
|
37
|
+
/** Validate collection payloads without interpreting provider-specific metadata. */
|
|
38
|
+
declare function readIconSet(value: unknown): IconSet;
|
|
39
|
+
/** Resolve local inheritance only; cycles/missing parents produce no icon. */
|
|
40
|
+
declare function resolveSetIcon(set: IconSet, name: string): IconData | null;
|
|
41
|
+
//#endregion
|
|
42
|
+
export { IconTransform as a, readIconData as c, IconSet as i, readIconSet as l, IconData as n, isIconData as o, IconDimensions as r, isIconSet as s, IconAlias as t, resolveSetIcon as u };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as IconTransform, c as readIconData, i as IconSet, l as readIconSet, n as IconData, o as isIconData, r as IconDimensions, s as isIconSet, t as IconAlias, u as resolveSetIcon } from "./icon-data-HGvJGwoB.js";
|
|
2
|
+
export { IconAlias, IconData, IconDimensions, IconSet, IconTransform, isIconData, isIconSet, readIconData, readIconSet, resolveSetIcon };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
//#region src/data/icon-data.ts
|
|
2
|
+
const object = (value) => !!value && typeof value === "object" && !Array.isArray(value);
|
|
3
|
+
/** Shallow single-body discriminator; use readIconData for import validation. */
|
|
4
|
+
function isIconData(value) {
|
|
5
|
+
return object(value) && "body" in value && typeof value.body === "string";
|
|
6
|
+
}
|
|
7
|
+
/** Check if a value is a full icon set payload. */
|
|
8
|
+
function isIconSet(value) {
|
|
9
|
+
return object(value) && "prefix" in value && typeof value.prefix === "string" && "icons" in value && object(value.icons);
|
|
10
|
+
}
|
|
11
|
+
function readIconData(value, name) {
|
|
12
|
+
if (!value || typeof value !== "object" || !("body" in value) || typeof value.body !== "string" || !value.body.trim()) throw new TypeError(`Invalid icon data: ${name}`);
|
|
13
|
+
const icon = value;
|
|
14
|
+
for (const key of [
|
|
15
|
+
"width",
|
|
16
|
+
"height",
|
|
17
|
+
"left",
|
|
18
|
+
"top",
|
|
19
|
+
"rotate"
|
|
20
|
+
]) {
|
|
21
|
+
const item = icon[key];
|
|
22
|
+
if (item !== void 0 && (!Number.isFinite(item) || (key === "width" || key === "height") && item <= 0)) throw new TypeError(`Invalid ${key} for ${name}`);
|
|
23
|
+
}
|
|
24
|
+
return icon;
|
|
25
|
+
}
|
|
26
|
+
/** Validate collection payloads without interpreting provider-specific metadata. */
|
|
27
|
+
function readIconSet(value) {
|
|
28
|
+
if (!isIconSet(value)) throw new TypeError("Invalid icon set.");
|
|
29
|
+
const properties = (item) => {
|
|
30
|
+
for (const key of [
|
|
31
|
+
"left",
|
|
32
|
+
"top",
|
|
33
|
+
"width",
|
|
34
|
+
"height",
|
|
35
|
+
"rotate"
|
|
36
|
+
]) {
|
|
37
|
+
const number = item[key];
|
|
38
|
+
if (number !== void 0 && (!Number.isFinite(number) || (key === "width" || key === "height") && number <= 0)) throw new TypeError(`Invalid icon set ${key}.`);
|
|
39
|
+
}
|
|
40
|
+
for (const key of ["hFlip", "vFlip"]) if (item[key] !== void 0 && typeof item[key] !== "boolean") throw new TypeError(`Invalid icon set ${key}.`);
|
|
41
|
+
};
|
|
42
|
+
properties(value);
|
|
43
|
+
if (value.provider !== void 0 && typeof value.provider !== "string") throw new TypeError("Invalid icon set provider.");
|
|
44
|
+
for (const [name, icon] of Object.entries(value.icons)) {
|
|
45
|
+
if (!name || !isIconData(icon)) throw new TypeError("Invalid icon set entry.");
|
|
46
|
+
properties(icon);
|
|
47
|
+
}
|
|
48
|
+
if (value.aliases !== void 0) {
|
|
49
|
+
if (!object(value.aliases)) throw new TypeError("Invalid icon aliases.");
|
|
50
|
+
for (const [name, alias] of Object.entries(value.aliases)) {
|
|
51
|
+
if (!name || !object(alias) || typeof alias.parent !== "string" || !(Object.hasOwn(value.icons, alias.parent) || Object.hasOwn(value.aliases, alias.parent))) throw new TypeError("Invalid icon alias parent.");
|
|
52
|
+
properties(alias);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return value;
|
|
56
|
+
}
|
|
57
|
+
/** Resolve local inheritance only; cycles/missing parents produce no icon. */
|
|
58
|
+
function resolveSetIcon(set, name) {
|
|
59
|
+
const chain = [];
|
|
60
|
+
const visited = /* @__PURE__ */ new Set();
|
|
61
|
+
let current = name;
|
|
62
|
+
while (!visited.has(current)) {
|
|
63
|
+
visited.add(current);
|
|
64
|
+
if (Object.hasOwn(set.icons, current)) {
|
|
65
|
+
const icon = set.icons[current];
|
|
66
|
+
if (!isIconData(icon)) return null;
|
|
67
|
+
const result = { body: icon.body };
|
|
68
|
+
for (const layer of [
|
|
69
|
+
set,
|
|
70
|
+
icon,
|
|
71
|
+
...chain.reverse()
|
|
72
|
+
]) {
|
|
73
|
+
const item = layer;
|
|
74
|
+
for (const key of [
|
|
75
|
+
"left",
|
|
76
|
+
"top",
|
|
77
|
+
"width",
|
|
78
|
+
"height",
|
|
79
|
+
"body",
|
|
80
|
+
"hidden"
|
|
81
|
+
]) if (Object.hasOwn(item, key)) Object.assign(result, { [key]: item[key] });
|
|
82
|
+
for (const key of ["hFlip", "vFlip"]) if (Object.hasOwn(item, key)) result[key] = !!result[key] !== !!item[key];
|
|
83
|
+
if (Object.hasOwn(item, "rotate")) result.rotate = ((result.rotate ?? 0) + (item.rotate ?? 0)) % 4;
|
|
84
|
+
}
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
const alias = set.aliases && Object.hasOwn(set.aliases, current) ? set.aliases[current] : void 0;
|
|
88
|
+
if (!alias || typeof alias.parent !== "string") return null;
|
|
89
|
+
chain.push(alias);
|
|
90
|
+
current = alias.parent;
|
|
91
|
+
}
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
//#endregion
|
|
95
|
+
export { isIconData, isIconSet, readIconData, readIconSet, resolveSetIcon };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { i as ElementNode, n as ElementChild, r as ElementData, t as ElementAttributes } from "./element-types-C9jOyda4.js";
|
|
2
|
+
import { a as svgAttributeName, i as reactAttributeName, n as parseElementData, r as readElementData, t as isElementData } from "./elements-DLSCanEZ.js";
|
|
3
|
+
import { a as IconTransform, c as readIconData, i as IconSet, l as readIconSet, n as IconData, o as isIconData, r as IconDimensions, s as isIconSet, t as IconAlias, u as resolveSetIcon } from "./icon-data-HGvJGwoB.js";
|
|
4
|
+
import { n as elementDataToIcon, r as renderSvgData, t as createSvgSymbolDocument } from "./data-DtdeiZ5o.js";
|
|
5
|
+
import { Data, IconLoadState, IconLoadStatus, IconLoader, IconLoaderResult, IconName, IconNamesBySet, IconSetName, IconSource, IconSources, Name, ParsedIconName, RuntimeIcon } from "./types.js";
|
|
6
|
+
import { a as ownValue, i as mergeSetOptions, n as IconSetOptions, o as resolveSetOption, r as isSetMap, t as IconSetMap } from "./set-options-C2BMGh-r.js";
|
|
7
|
+
import { _ as mergeIconApi, a as IconFetch, c as IconSymbolApiOptions, d as createIconApiLoader, f as createIconesIconLoader, g as isSymbolApi, h as defaultIconServiceDomain, i as IconApiOptions, l as IconesIconLoaderOptions, m as defaultIconLoader, n as IconApi, o as IconFetchApi, p as createStaticIconLoader, r as IconApiConfig, s as IconRequestOptions, t as FileIconLoaderOptions, u as createFileIconLoader, v as resolveIconApi } from "./loaders-DxxA-L6t.js";
|
|
8
|
+
import { n as resolveIconSetData, t as parseIconName } from "./sources-CXcG9DjB.js";
|
|
9
|
+
import { IconStore, IconStoreOptions, createIconStore } from "./store.js";
|
|
10
|
+
import { addIconData, addIconSet, clearIconData, getIconLoadState, loadIconData, registeredName, registeredSources, registryStore, resolveIconData, subscribeIconData } from "./registry.js";
|
|
11
|
+
import { n as DefaultSizeName, r as ResolveSizeName, t as CSSSize } from "./sizes-CMxyEIpX.js";
|
|
12
|
+
import { IconAppearance, IconDefaultSize, IconOptions, IconPresentation, IconRenderResult, IconSize, IconSizePresets, IconSizeValues, IconSourceProps, createIconSourceValidator, defaultIconAppearance, iconOptionKeys, iconStyleText, mergeIconAppearance, mergeIconDefaultSize, mergeIconSizeValues, renderIcon, selectIconSource } from "./presentation.js";
|
|
13
|
+
import { IconController, IconScope, IconScopeOptions, createIconController, createIconScope, createIconScopeResolver, defaultIconScope } from "./controller.js";
|
|
14
|
+
import { getIconViewBox, iconViewBoxes, replaceSvgIds, rewriteStrokeWidths } from "./svg.js";
|
|
15
|
+
import { ViewBox, parseViewBox } from "./view-box.js";
|
|
16
|
+
import { toAsciiSlug } from "./slug.js";
|
|
17
|
+
export { type CSSSize, Data, type DefaultSizeName, type ElementAttributes, type ElementChild, type ElementData, type ElementNode, FileIconLoaderOptions, IconAlias, IconApi, IconApiConfig, IconApiOptions, IconAppearance, IconController, IconData, IconDefaultSize, IconDimensions, IconFetch, IconFetchApi, IconLoadState, IconLoadStatus, IconLoader, IconLoaderResult, type IconName, type IconNamesBySet, IconOptions, IconPresentation, IconRenderResult, IconRequestOptions, IconScope, IconScopeOptions, IconSet, IconSetMap, type IconSetName, IconSetOptions, IconSize, IconSizePresets, IconSizeValues, IconSource, IconSourceProps, IconSources, type IconStore, type IconStoreOptions, IconSymbolApiOptions, IconTransform, IconesIconLoaderOptions, Name, ParsedIconName, type ResolveSizeName, RuntimeIcon, ViewBox, addIconData, addIconSet, clearIconData, createFileIconLoader, createIconApiLoader, createIconController, createIconScope, createIconScopeResolver, createIconSourceValidator, createIconStore, createIconesIconLoader, createStaticIconLoader, createSvgSymbolDocument, defaultIconAppearance, defaultIconLoader, defaultIconScope, defaultIconServiceDomain, elementDataToIcon, getIconLoadState, getIconViewBox, iconOptionKeys, iconStyleText, iconViewBoxes, isElementData, isIconData, isIconSet, isSetMap, isSymbolApi, loadIconData, mergeIconApi, mergeIconAppearance, mergeIconDefaultSize, mergeIconSizeValues, mergeSetOptions, ownValue, parseElementData, parseIconName, parseViewBox, reactAttributeName, readElementData, readIconData, readIconSet, registeredName, registeredSources, registryStore, renderIcon, renderSvgData, replaceSvgIds, resolveIconApi, resolveIconData, resolveIconSetData, resolveSetIcon, resolveSetOption, rewriteStrokeWidths, selectIconSource, subscribeIconData, svgAttributeName, toAsciiSlug };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import "./types.js";
|
|
2
|
+
import { isIconData, isIconSet, readIconData, readIconSet, resolveSetIcon } from "./icon-data.js";
|
|
3
|
+
import { a as svgAttributeName, i as reactAttributeName, n as elementDataToIcon, r as renderSvgData, t as createSvgSymbolDocument } from "./data-N59s4mFY.js";
|
|
4
|
+
import { parseViewBox } from "./view-box.js";
|
|
5
|
+
import { isElementData, parseElementData, readElementData } from "./elements.js";
|
|
6
|
+
import { parseIconName, resolveIconSetData } from "./data.js";
|
|
7
|
+
import { isSetMap, mergeSetOptions, ownValue, resolveSetOption } from "./set-options.js";
|
|
8
|
+
import { createFileIconLoader, createIconApiLoader, createIconesIconLoader, createStaticIconLoader, defaultIconLoader, defaultIconServiceDomain, isSymbolApi, mergeIconApi, resolveIconApi } from "./loaders.js";
|
|
9
|
+
import { getIconViewBox, iconViewBoxes, replaceSvgIds, rewriteStrokeWidths } from "./svg.js";
|
|
10
|
+
import { createIconStore } from "./store.js";
|
|
11
|
+
import { addIconData, addIconSet, clearIconData, getIconLoadState, loadIconData, registeredName, registeredSources, registryStore, resolveIconData, subscribeIconData } from "./registry.js";
|
|
12
|
+
import { createIconSourceValidator, defaultIconAppearance, iconOptionKeys, iconStyleText, mergeIconAppearance, mergeIconDefaultSize, mergeIconSizeValues, renderIcon, selectIconSource } from "./presentation.js";
|
|
13
|
+
import { createIconController, createIconScope, createIconScopeResolver, defaultIconScope } from "./controller.js";
|
|
14
|
+
import { toAsciiSlug } from "./slug.js";
|
|
15
|
+
export { addIconData, addIconSet, clearIconData, createFileIconLoader, createIconApiLoader, createIconController, createIconScope, createIconScopeResolver, createIconSourceValidator, createIconStore, createIconesIconLoader, createStaticIconLoader, createSvgSymbolDocument, defaultIconAppearance, defaultIconLoader, defaultIconScope, defaultIconServiceDomain, elementDataToIcon, getIconLoadState, getIconViewBox, iconOptionKeys, iconStyleText, iconViewBoxes, isElementData, isIconData, isIconSet, isSetMap, isSymbolApi, loadIconData, mergeIconApi, mergeIconAppearance, mergeIconDefaultSize, mergeIconSizeValues, mergeSetOptions, ownValue, parseElementData, parseIconName, parseViewBox, reactAttributeName, readElementData, readIconData, readIconSet, registeredName, registeredSources, registryStore, renderIcon, renderSvgData, replaceSvgIds, resolveIconApi, resolveIconData, resolveIconSetData, resolveSetIcon, resolveSetOption, rewriteStrokeWidths, selectIconSource, subscribeIconData, svgAttributeName, toAsciiSlug };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { IconLoader, IconLoaderResult, ParsedIconName } from "./types.js";
|
|
2
|
+
import { t as IconSetMap } from "./set-options-C2BMGh-r.js";
|
|
3
|
+
//#region src/runtime/loaders.d.ts
|
|
4
|
+
/** Fetch call contract only; runtime-specific properties (e.g. Bun.preconnect) are not required. */
|
|
5
|
+
type IconFetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
|
|
6
|
+
type IconRequestOptions = {
|
|
7
|
+
baseUrl?: string;
|
|
8
|
+
fetch?: IconFetch;
|
|
9
|
+
requestInit?: RequestInit;
|
|
10
|
+
};
|
|
11
|
+
type IconesIconLoaderOptions = Omit<IconRequestOptions, "baseUrl"> & {
|
|
12
|
+
/** Domain hosting one static deployment per icon set. */
|
|
13
|
+
domain?: string;
|
|
14
|
+
};
|
|
15
|
+
/** Default first-party static icon service used by the framework adapters. */
|
|
16
|
+
declare const defaultIconServiceDomain = "icones.go-slim.dev";
|
|
17
|
+
type IconApiOptions = IconRequestOptions & {
|
|
18
|
+
default?: never;
|
|
19
|
+
type?: "fetch";
|
|
20
|
+
/** Override the complete URL, including query parameters. */
|
|
21
|
+
url?: (name: string, parsed: ParsedIconName | null) => string | URL;
|
|
22
|
+
/** Adapt an application-specific response envelope to icon data. */
|
|
23
|
+
transform?: (json: unknown, name: string) => IconLoaderResult | Promise<IconLoaderResult>;
|
|
24
|
+
};
|
|
25
|
+
type IconSymbolApiOptions = {
|
|
26
|
+
default?: never;
|
|
27
|
+
type: "symbol";
|
|
28
|
+
/** Same-origin protocol endpoint. Defaults to /icons. */
|
|
29
|
+
baseUrl?: string;
|
|
30
|
+
/** Pure URL builder; include the single symbol's fragment ID. */
|
|
31
|
+
url?: (name: string, parsed: ParsedIconName | null) => string | URL;
|
|
32
|
+
/** Override built-in name-based viewports (24 × 24, or native Flag coordinates). */
|
|
33
|
+
viewBox?: string;
|
|
34
|
+
};
|
|
35
|
+
type IconFetchApi = false | string | IconApiOptions | IconLoader;
|
|
36
|
+
type IconApi = IconFetchApi | IconSymbolApiOptions;
|
|
37
|
+
/** A shared API or per-set APIs, with `default` for unmatched sets. */
|
|
38
|
+
type IconApiConfig = IconApi | (IconSetMap<IconApi> & Partial<Record<Exclude<keyof IconApiOptions | keyof IconSymbolApiOptions, "default">, never>>);
|
|
39
|
+
declare function mergeIconApi(parent: IconApiConfig | undefined, next: IconApiConfig | undefined): IconApiConfig | undefined;
|
|
40
|
+
declare function resolveIconApi(api: IconApiConfig | undefined, name: string): IconApi | undefined;
|
|
41
|
+
/** Check whether a resolved API entry points to an external symbol sprite. */
|
|
42
|
+
declare function isSymbolApi(api: IconApi | undefined): api is IconSymbolApiOptions;
|
|
43
|
+
/** Build a fetch-based icon loader from API option object, URL or callback. */
|
|
44
|
+
declare function createIconApiLoader(api?: IconFetchApi): IconLoader;
|
|
45
|
+
type FileIconLoaderOptions = {
|
|
46
|
+
baseUrl?: string;
|
|
47
|
+
extension?: string;
|
|
48
|
+
fetch?: IconFetch;
|
|
49
|
+
};
|
|
50
|
+
/** Opt in to mirrored static assets: <base>/<set>/data/<slug>.json. */
|
|
51
|
+
declare function createStaticIconLoader(options?: IconRequestOptions | string): IconLoader;
|
|
52
|
+
/** Load <set>:<name> from https://<set>.<domain>/data/<name>.json. */
|
|
53
|
+
declare function createIconesIconLoader(options?: IconesIconLoaderOptions): IconLoader;
|
|
54
|
+
declare function createFileIconLoader(options?: FileIconLoaderOptions | string): IconLoader;
|
|
55
|
+
/** Unconfigured adapters fall back to the first-party per-collection service. */
|
|
56
|
+
declare const defaultIconLoader: IconLoader;
|
|
57
|
+
//#endregion
|
|
58
|
+
export { mergeIconApi as _, IconFetch as a, IconSymbolApiOptions as c, createIconApiLoader as d, createIconesIconLoader as f, isSymbolApi as g, defaultIconServiceDomain as h, IconApiOptions as i, IconesIconLoaderOptions as l, defaultIconLoader as m, IconApi as n, IconFetchApi as o, createStaticIconLoader as p, IconApiConfig as r, IconRequestOptions as s, FileIconLoaderOptions as t, createFileIconLoader as u, resolveIconApi as v };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { _ as mergeIconApi, a as IconFetch, c as IconSymbolApiOptions, d as createIconApiLoader, f as createIconesIconLoader, g as isSymbolApi, h as defaultIconServiceDomain, i as IconApiOptions, l as IconesIconLoaderOptions, m as defaultIconLoader, n as IconApi, o as IconFetchApi, p as createStaticIconLoader, r as IconApiConfig, s as IconRequestOptions, t as FileIconLoaderOptions, u as createFileIconLoader, v as resolveIconApi } from "./loaders-DxxA-L6t.js";
|
|
2
|
+
export { FileIconLoaderOptions, IconApi, IconApiConfig, IconApiOptions, IconFetch, IconFetchApi, IconRequestOptions, IconSymbolApiOptions, IconesIconLoaderOptions, createFileIconLoader, createIconApiLoader, createIconesIconLoader, createStaticIconLoader, defaultIconLoader, defaultIconServiceDomain, isSymbolApi, mergeIconApi, resolveIconApi };
|