react-icons-sprite 0.7.0 → 0.7.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 +3 -2
- package/dist/collector-BCsSIe1N.mjs +7 -0
- package/dist/{core-TIimc90M.mjs → core-Di2t0EYk.mjs} +77 -10
- package/dist/icon.mjs +15 -1
- package/dist/index.mjs +1 -1
- package/dist/vite/plugin.mjs +1 -1
- package/dist/webpack/loader.mjs +3 -4
- package/dist/webpack/plugin.d.mts +2 -2
- package/dist/webpack/plugin.mjs +2 -2
- package/package.json +36 -18
- package/dist/collector-BbjpnJS-.mjs +0 -7
- package/dist/icon-DB53krat.mjs +0 -17
package/README.md
CHANGED
|
@@ -18,13 +18,14 @@ Out of the box, imports from the following libraries are detected and transforme
|
|
|
18
18
|
- `react-feather`
|
|
19
19
|
- `react-bootstrap-icons`
|
|
20
20
|
- `grommet-icons`
|
|
21
|
-
- `remixicon-react`
|
|
22
21
|
- `@remixicon/react`
|
|
23
22
|
- `devicons-react`
|
|
24
23
|
- `@fortawesome/free-solid-svg-icons` (and other Font Awesome icon packs)
|
|
25
24
|
- `@fortawesome/react-fontawesome`
|
|
26
25
|
- `@mui/icons-material`
|
|
27
|
-
|
|
26
|
+
|
|
27
|
+
> [!NOTE]
|
|
28
|
+
> `react-icons-sprite` does not bundle these libraries. You must install whichever icon packages you intend to use in your project.
|
|
28
29
|
|
|
29
30
|
## Motivation
|
|
30
31
|
|
|
@@ -21,12 +21,11 @@ const DEFAULT_ICON_SOURCES = [
|
|
|
21
21
|
/^react-feather$/,
|
|
22
22
|
/^react-bootstrap-icons$/,
|
|
23
23
|
/^grommet-icons$/,
|
|
24
|
-
/^remixicon-react$/,
|
|
25
24
|
/^@remixicon\/react$/,
|
|
26
25
|
/^devicons-react$/,
|
|
27
26
|
/^@fortawesome\/react-fontawesome$/,
|
|
28
27
|
/^@fortawesome\/[\w-]+-svg-icons$/,
|
|
29
|
-
/^@mui\/icons-material
|
|
28
|
+
/^@mui\/icons-material(?:\/.*)?$/,
|
|
30
29
|
/^@iconscout\/react-unicons$/
|
|
31
30
|
];
|
|
32
31
|
const sourceMatchesSupported = (source, sources = DEFAULT_ICON_SOURCES) => sources.some((re) => re.test(source));
|
|
@@ -56,6 +55,15 @@ const collectIconImports = (ast, sources = DEFAULT_ICON_SOURCES) => {
|
|
|
56
55
|
decl: node,
|
|
57
56
|
spec
|
|
58
57
|
});
|
|
58
|
+
} else if (t.isImportDefaultSpecifier(spec) && t.isIdentifier(spec.local)) {
|
|
59
|
+
const exportName = "default";
|
|
60
|
+
const localName = spec.local.name;
|
|
61
|
+
map.set(localName, {
|
|
62
|
+
pack,
|
|
63
|
+
exportName,
|
|
64
|
+
decl: node,
|
|
65
|
+
spec
|
|
66
|
+
});
|
|
59
67
|
}
|
|
60
68
|
}
|
|
61
69
|
return map;
|
|
@@ -88,14 +96,31 @@ const replaceJsxWithSprite = (ast, localNameToImport, iconLocalName, register) =
|
|
|
88
96
|
const meta = localNameToImport.get(local);
|
|
89
97
|
if (!meta) return;
|
|
90
98
|
if (isAlreadyIcon(name)) return;
|
|
99
|
+
let iconPack = meta.pack;
|
|
100
|
+
let iconExport = meta.exportName;
|
|
101
|
+
let usedLocal = local;
|
|
102
|
+
if (meta.pack === "@fortawesome/react-fontawesome" && meta.exportName === "FontAwesomeIcon") {
|
|
103
|
+
const iconAttr = path.node.attributes.find((a) => t.isJSXAttribute(a) && t.isJSXIdentifier(a.name, { name: "icon" }));
|
|
104
|
+
if (iconAttr && t.isJSXExpressionContainer(iconAttr.value) && t.isIdentifier(iconAttr.value.expression)) {
|
|
105
|
+
const iconLocalName = iconAttr.value.expression.name;
|
|
106
|
+
const iconMeta = localNameToImport.get(iconLocalName);
|
|
107
|
+
if (iconMeta) {
|
|
108
|
+
iconPack = iconMeta.pack;
|
|
109
|
+
iconExport = iconMeta.exportName;
|
|
110
|
+
usedLocal = iconLocalName;
|
|
111
|
+
path.node.attributes = path.node.attributes.filter((a) => a !== iconAttr);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
91
115
|
path.node.name = t.jSXIdentifier(iconLocalName);
|
|
92
116
|
if (!path.node.attributes.some((a) => t.isJSXAttribute(a) && t.isJSXIdentifier(a.name, { name: "iconId" }))) {
|
|
93
|
-
const idValue = computeIconId(
|
|
117
|
+
const idValue = computeIconId(iconPack, iconExport);
|
|
94
118
|
path.node.attributes.unshift(t.jSXAttribute(t.jSXIdentifier("iconId"), t.stringLiteral(idValue)));
|
|
95
119
|
}
|
|
96
120
|
usedLocalNames.add(local);
|
|
121
|
+
if (usedLocal !== local) usedLocalNames.add(usedLocal);
|
|
97
122
|
anyReplacements = true;
|
|
98
|
-
register(
|
|
123
|
+
register(iconPack, iconExport);
|
|
99
124
|
},
|
|
100
125
|
JSXClosingElement(path) {
|
|
101
126
|
const name = path.node.name;
|
|
@@ -118,8 +143,8 @@ const insertIconImport = (ast, iconLocalName = ICON_COMPONENT_NAME) => {
|
|
|
118
143
|
};
|
|
119
144
|
const pruneUsedSpecifiers = (ast, localNameToImport, usedLocalNames) => {
|
|
120
145
|
for (const { decl } of new Set([...localNameToImport.values()])) decl.specifiers = decl.specifiers.filter((s) => {
|
|
121
|
-
if (
|
|
122
|
-
return
|
|
146
|
+
if ((t.isImportSpecifier(s) || t.isImportDefaultSpecifier(s)) && t.isIdentifier(s.local)) return !usedLocalNames.has(s.local.name);
|
|
147
|
+
return true;
|
|
123
148
|
});
|
|
124
149
|
ast.program.body = ast.program.body.filter((n) => !t.isImportDeclaration(n) || n.specifiers.length > 0);
|
|
125
150
|
};
|
|
@@ -173,14 +198,56 @@ const PRESENTATION_ATTRS = new Set([
|
|
|
173
198
|
"vector-effect"
|
|
174
199
|
]);
|
|
175
200
|
const ATTR_RE = /([a-zA-Z_:.-]+)\s*=\s*"([^"]*)"/g;
|
|
201
|
+
const toKebab = (s) => s.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/([A-Z])([A-Z][a-z])/g, "$1-$2").toLowerCase();
|
|
202
|
+
const resolveSpecificImportPath = (pack, exportName) => {
|
|
203
|
+
if (/^@mui\/icons-material(?:\/.*)?$/.test(pack)) {
|
|
204
|
+
if (pack.split("/").length > 2) return pack;
|
|
205
|
+
return `${pack}/${exportName}`;
|
|
206
|
+
}
|
|
207
|
+
if (/^@radix-ui\/react-icons$/.test(pack)) return `${pack}/${exportName}`;
|
|
208
|
+
if (/^@heroicons\/react\/(?:\d{2})\/(?:outline|solid)$/.test(pack)) return `${pack}/${exportName}`;
|
|
209
|
+
if (/^@fortawesome\/[\w-]+-svg-icons$/.test(pack)) return `${pack}/${exportName}`;
|
|
210
|
+
if (/^lucide-react$/.test(pack)) return `${pack}/icons/${toKebab(exportName)}`;
|
|
211
|
+
if (/^@phosphor-icons\/react$/.test(pack)) return `${pack}/dist/ssr/${exportName}.es.js`;
|
|
212
|
+
if (/^phosphor-react$/.test(pack)) return `${pack}/dist/icons/${exportName}.esm.js`;
|
|
213
|
+
if (/^@tabler\/icons-react$/.test(pack)) return `${pack}/dist/esm/icons/${exportName}.mjs`;
|
|
214
|
+
if (/^react-feather$/.test(pack)) return `${pack}/dist/icons/${toKebab(exportName)}`;
|
|
215
|
+
if (/^react-bootstrap-icons$/.test(pack)) return `${pack}/dist/icons/${toKebab(exportName)}`;
|
|
216
|
+
return null;
|
|
217
|
+
};
|
|
176
218
|
const renderOneIcon = async (pack, exportName) => {
|
|
177
|
-
|
|
219
|
+
let mod;
|
|
220
|
+
const specificPath = resolveSpecificImportPath(pack, exportName);
|
|
221
|
+
if (specificPath) try {
|
|
222
|
+
mod = await import(
|
|
223
|
+
/* @vite-ignore */
|
|
224
|
+
specificPath
|
|
225
|
+
);
|
|
226
|
+
if (mod && "default" in mod && Object.keys(mod).length === 1) mod[exportName] = mod.default;
|
|
227
|
+
} catch {
|
|
228
|
+
mod = await import(
|
|
229
|
+
/* @vite-ignore */
|
|
230
|
+
pack
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
else mod = await import(
|
|
178
234
|
/* @vite-ignore */
|
|
179
235
|
pack
|
|
180
|
-
)
|
|
236
|
+
);
|
|
237
|
+
let Comp = mod[exportName] ?? mod.default;
|
|
238
|
+
if (pack.includes("fortawesome") && Comp && typeof Comp === "object" && "icon" in Comp && Array.isArray(Comp.icon)) {
|
|
239
|
+
const [width, height, , , pathData] = Comp.icon;
|
|
240
|
+
const viewBox = `0 0 ${width} ${height}`;
|
|
241
|
+
const id = computeIconId(pack, exportName);
|
|
242
|
+
return {
|
|
243
|
+
id,
|
|
244
|
+
symbol: `<symbol id="${id}" viewBox="${viewBox}">${(Array.isArray(pathData) ? pathData : [pathData]).map((d) => `<path d="${d}" />`).join("")}</symbol>`
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
if (Comp && typeof Comp === "object" && "default" in Comp && !("$$typeof" in Comp)) Comp = Comp.default;
|
|
181
248
|
if (!Comp) throw new Error(`Icon export not found: ${pack} -> ${exportName}`);
|
|
182
249
|
const id = computeIconId(pack, exportName);
|
|
183
|
-
const html = renderToStaticMarkup(createElement(Comp));
|
|
250
|
+
const html = renderToStaticMarkup(createElement(Comp, {}));
|
|
184
251
|
const viewBox = html.match(/viewBox="([^"]+)"/i)?.[1] ?? "0 0 24 24";
|
|
185
252
|
const svgAttrsRaw = html.match(/^<svg\b([^>]*)>/i)?.[1] ?? "";
|
|
186
253
|
const attrs = [];
|
|
@@ -188,7 +255,7 @@ const renderOneIcon = async (pack, exportName) => {
|
|
|
188
255
|
const key = k.toLowerCase();
|
|
189
256
|
if (PRESENTATION_ATTRS.has(key)) attrs.push(`${key}="${v}"`);
|
|
190
257
|
}
|
|
191
|
-
const inner = html.replace(/^<svg[^>]*>/i, "").replace(/<\/svg>\s*$/i, "");
|
|
258
|
+
const inner = html.replace(/^<svg[^>]*>/i, "").replace(/<\/svg>\s*$/i, "").replace(/<svg[^>]*>/gi, "").replace(/<\/svg>/gi, "");
|
|
192
259
|
return {
|
|
193
260
|
id,
|
|
194
261
|
symbol: `<symbol id="${id}" viewBox="${viewBox}"${attrs.length ? ` ${attrs.join(" ")}` : ""}>${inner}</symbol>`
|
package/dist/icon.mjs
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
2
|
|
|
3
|
+
//#region src/icon.tsx
|
|
4
|
+
const ReactIconsSpriteIcon = ({ iconId, ...rest }) => {
|
|
5
|
+
const iconHref = `__SPRITE_URL_PLACEHOLDER__#${iconId}`;
|
|
6
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
7
|
+
height: "1em",
|
|
8
|
+
width: "1em",
|
|
9
|
+
preserveAspectRatio: "xMidYMid meet",
|
|
10
|
+
viewBox: "0 0 24 24",
|
|
11
|
+
...rest,
|
|
12
|
+
children: /* @__PURE__ */ jsx("use", { href: iconHref })
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
//#endregion
|
|
3
17
|
export { ReactIconsSpriteIcon };
|
package/dist/index.mjs
CHANGED
package/dist/vite/plugin.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { REACT_ICONS_SPRITE_URL_PLACEHOLDER } from "../index.mjs";
|
|
2
|
-
import { i as transformModule, n as buildSprite, r as createCollector, t as DEFAULT_ICON_SOURCES } from "../core-
|
|
2
|
+
import { i as transformModule, n as buildSprite, r as createCollector, t as DEFAULT_ICON_SOURCES } from "../core-Di2t0EYk.mjs";
|
|
3
3
|
import { createHash } from "node:crypto";
|
|
4
4
|
|
|
5
5
|
//#region src/vite/plugin.ts
|
package/dist/webpack/loader.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { i as transformModule } from "../core-
|
|
2
|
-
import { t as collector } from "../collector-
|
|
1
|
+
import { i as transformModule } from "../core-Di2t0EYk.mjs";
|
|
2
|
+
import { t as collector } from "../collector-BCsSIe1N.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/webpack/loader.ts
|
|
5
5
|
const reactIconsSpriteLoader = async function(source) {
|
|
@@ -16,7 +16,6 @@ const reactIconsSpriteLoader = async function(source) {
|
|
|
16
16
|
return source;
|
|
17
17
|
}
|
|
18
18
|
};
|
|
19
|
-
var loader_default = reactIconsSpriteLoader;
|
|
20
19
|
|
|
21
20
|
//#endregion
|
|
22
|
-
export {
|
|
21
|
+
export { reactIconsSpriteLoader as default };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Compiler
|
|
1
|
+
import { Compiler } from "webpack";
|
|
2
2
|
|
|
3
3
|
//#region src/webpack/plugin.d.ts
|
|
4
4
|
type ReactIconsSpriteWebpackPluginOptions = {
|
|
@@ -9,7 +9,7 @@ type ReactIconsSpriteWebpackPluginOptions = {
|
|
|
9
9
|
*/
|
|
10
10
|
fileName?: string;
|
|
11
11
|
};
|
|
12
|
-
declare class ReactIconsSpriteWebpackPlugin
|
|
12
|
+
declare class ReactIconsSpriteWebpackPlugin {
|
|
13
13
|
private readonly fileName?;
|
|
14
14
|
constructor(options?: ReactIconsSpriteWebpackPluginOptions);
|
|
15
15
|
apply(compiler: Compiler): void;
|
package/dist/webpack/plugin.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { REACT_ICONS_SPRITE_URL_PLACEHOLDER } from "../index.mjs";
|
|
2
|
-
import { n as buildSprite } from "../core-
|
|
3
|
-
import { t as collector } from "../collector-
|
|
2
|
+
import { n as buildSprite } from "../core-Di2t0EYk.mjs";
|
|
3
|
+
import { t as collector } from "../collector-BCsSIe1N.mjs";
|
|
4
4
|
import { createHash } from "node:crypto";
|
|
5
5
|
|
|
6
6
|
//#region src/webpack/plugin.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-icons-sprite",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "",
|
|
@@ -47,10 +47,10 @@
|
|
|
47
47
|
"scripts": {
|
|
48
48
|
"build": "tsdown",
|
|
49
49
|
"dev": "tsdown --watch",
|
|
50
|
-
"format": "biome format --no-errors-on-unmatched",
|
|
51
|
-
"format
|
|
52
|
-
"lint": "biome lint --no-errors-on-unmatched",
|
|
53
|
-
"lint
|
|
50
|
+
"format:check": "biome format --no-errors-on-unmatched",
|
|
51
|
+
"format": "biome format --write --no-errors-on-unmatched",
|
|
52
|
+
"lint:check": "biome lint --no-errors-on-unmatched",
|
|
53
|
+
"lint": "biome lint --write --no-errors-on-unmatched",
|
|
54
54
|
"type-check": "tsgo",
|
|
55
55
|
"test": "vitest run",
|
|
56
56
|
"prepublishOnly": "npm run build",
|
|
@@ -58,28 +58,46 @@
|
|
|
58
58
|
},
|
|
59
59
|
"peerDependencies": {
|
|
60
60
|
"react": ">= 16",
|
|
61
|
-
"react-dom": ">= 16"
|
|
62
|
-
|
|
61
|
+
"react-dom": ">= 16"
|
|
62
|
+
},
|
|
63
|
+
"dependencies": {
|
|
64
|
+
"@babel/generator": "7.29.1",
|
|
65
|
+
"@babel/parser": "7.29.0",
|
|
66
|
+
"@babel/traverse": "7.29.0",
|
|
67
|
+
"@babel/types": "7.29.0"
|
|
63
68
|
},
|
|
64
69
|
"devDependencies": {
|
|
65
|
-
"@
|
|
66
|
-
"@
|
|
67
|
-
"@
|
|
68
|
-
"@
|
|
69
|
-
"@
|
|
70
|
+
"@biomejs/biome": "2.3.14",
|
|
71
|
+
"@emotion/react": "11.14.0",
|
|
72
|
+
"@emotion/styled": "11.14.1",
|
|
73
|
+
"@fortawesome/free-solid-svg-icons": "7.2.0",
|
|
74
|
+
"@fortawesome/react-fontawesome": "3.2.0",
|
|
75
|
+
"@heroicons/react": "2.2.0",
|
|
76
|
+
"@iconscout/react-unicons": "2.2.5",
|
|
77
|
+
"@mui/icons-material": "7.3.7",
|
|
78
|
+
"@phosphor-icons/react": "2.1.10",
|
|
79
|
+
"@radix-ui/react-icons": "1.3.2",
|
|
80
|
+
"@remixicon/react": "4.9.0",
|
|
81
|
+
"@tabler/icons-react": "3.36.1",
|
|
70
82
|
"@types/babel__generator": "7.27.0",
|
|
71
83
|
"@types/babel__traverse": "7.28.0",
|
|
72
|
-
"@types/node": "25.
|
|
84
|
+
"@types/node": "25.2.3",
|
|
73
85
|
"@types/react-dom": "19.2.3",
|
|
74
|
-
"@typescript/native-preview": "7.0.0-dev.
|
|
75
|
-
"react": "
|
|
76
|
-
"
|
|
86
|
+
"@typescript/native-preview": "7.0.0-dev.20260211.1",
|
|
87
|
+
"devicons-react": "1.5.0",
|
|
88
|
+
"grommet-icons": "4.14.0",
|
|
89
|
+
"lucide-react": "0.563.0",
|
|
90
|
+
"phosphor-react": "1.4.1",
|
|
91
|
+
"react": "19.2.4",
|
|
92
|
+
"react-bootstrap-icons": "1.11.6",
|
|
93
|
+
"react-dom": "19.2.4",
|
|
94
|
+
"react-feather": "2.0.10",
|
|
77
95
|
"react-icons": "5.5.0",
|
|
78
|
-
"tsdown": "0.20.
|
|
96
|
+
"tsdown": "0.20.3",
|
|
79
97
|
"typescript": "5.9.3",
|
|
80
98
|
"vite": "7.3.1",
|
|
81
99
|
"vitest": "4.0.18",
|
|
82
|
-
"webpack": "5.
|
|
100
|
+
"webpack": "5.105.1"
|
|
83
101
|
},
|
|
84
102
|
"keywords": [
|
|
85
103
|
"vite",
|
package/dist/icon-DB53krat.mjs
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { jsx } from "react/jsx-runtime";
|
|
2
|
-
|
|
3
|
-
//#region src/icon.tsx
|
|
4
|
-
const ReactIconsSpriteIcon = ({ iconId, ...rest }) => {
|
|
5
|
-
const iconHref = `__SPRITE_URL_PLACEHOLDER__#${iconId}`;
|
|
6
|
-
return /* @__PURE__ */ jsx("svg", {
|
|
7
|
-
height: "1em",
|
|
8
|
-
width: "1em",
|
|
9
|
-
preserveAspectRatio: "xMidYMid meet",
|
|
10
|
-
viewBox: "0 0 24 24",
|
|
11
|
-
...rest,
|
|
12
|
-
children: /* @__PURE__ */ jsx("use", { href: iconHref })
|
|
13
|
-
});
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
//#endregion
|
|
17
|
-
export { ReactIconsSpriteIcon as t };
|