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 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
- - `@iconscout/react-unicons`
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
 
@@ -0,0 +1,7 @@
1
+ import { r as createCollector } from "./core-Di2t0EYk.mjs";
2
+
3
+ //#region src/collector.ts
4
+ const collector = createCollector();
5
+
6
+ //#endregion
7
+ export { collector as t };
@@ -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(meta.pack, meta.exportName);
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(meta.pack, meta.exportName);
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 (!t.isImportSpecifier(s) || !t.isIdentifier(s.local)) return true;
122
- return !usedLocalNames.has(s.local.name);
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
- const Comp = (await import(
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
- ))[exportName];
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 { t as ReactIconsSpriteIcon } from "./icon-DB53krat.mjs";
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
@@ -1,4 +1,4 @@
1
- import { t as ReactIconsSpriteIcon } from "./icon-DB53krat.mjs";
1
+ import { ReactIconsSpriteIcon } from "./icon.mjs";
2
2
 
3
3
  //#region src/index.ts
4
4
  const REACT_ICONS_SPRITE_URL_PLACEHOLDER = "__SPRITE_URL_PLACEHOLDER__";
@@ -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-TIimc90M.mjs";
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
@@ -1,5 +1,5 @@
1
- import { i as transformModule } from "../core-TIimc90M.mjs";
2
- import { t as collector } from "../collector-BbjpnJS-.mjs";
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 { loader_default as default };
21
+ export { reactIconsSpriteLoader as default };
@@ -1,4 +1,4 @@
1
- import { Compiler, WebpackPluginInstance } from "webpack";
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 implements WebpackPluginInstance {
12
+ declare class ReactIconsSpriteWebpackPlugin {
13
13
  private readonly fileName?;
14
14
  constructor(options?: ReactIconsSpriteWebpackPluginOptions);
15
15
  apply(compiler: Compiler): void;
@@ -1,6 +1,6 @@
1
1
  import { REACT_ICONS_SPRITE_URL_PLACEHOLDER } from "../index.mjs";
2
- import { n as buildSprite } from "../core-TIimc90M.mjs";
3
- import { t as collector } from "../collector-BbjpnJS-.mjs";
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.0",
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:fix": "biome format --write --no-errors-on-unmatched",
52
- "lint": "biome lint --no-errors-on-unmatched",
53
- "lint:fix": "biome lint --write --no-errors-on-unmatched",
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
- "react-icons": ">= 5"
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
- "@babel/generator": "7.28.6",
66
- "@babel/parser": "7.28.6",
67
- "@babel/traverse": "7.28.6",
68
- "@babel/types": "7.28.6",
69
- "@biomejs/biome": "2.3.13",
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.0.10",
84
+ "@types/node": "25.2.3",
73
85
  "@types/react-dom": "19.2.3",
74
- "@typescript/native-preview": "7.0.0-dev.20260127.1",
75
- "react": "19.2.1",
76
- "react-dom": "19.2.1",
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.1",
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.104.1"
100
+ "webpack": "5.105.1"
83
101
  },
84
102
  "keywords": [
85
103
  "vite",
@@ -1,7 +0,0 @@
1
- import { r as createCollector } from "./core-TIimc90M.mjs";
2
-
3
- //#region src/collector.ts
4
- const collector = createCollector();
5
-
6
- //#endregion
7
- export { collector as t };
@@ -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 };