@purposeinplay/feral-icons 0.1.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/README.md ADDED
@@ -0,0 +1,431 @@
1
+ # @purposeinplay/feral-icons
2
+
3
+ Custom React icon library with full tree-shaking support and TypeScript autocomplete.
4
+
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+
7
+ ## Features
8
+
9
+ - 🎯 **Name-based API** - `<FeralIcon name="camera" />` - simple and clean
10
+ - 🌲 **Tree-shakable** - Only imports what you use
11
+ - 📦 **Tiny bundle** - ~0.3KB per icon gzipped
12
+ - 🔷 **TypeScript** - Full type safety with icon name autocomplete
13
+ - âš¡ **Fast** - Optimized SVGs with SVGO
14
+ - 🎨 **Customizable** - Control size, color, and all SVG props
15
+ - 🔧 **Easy to extend** - Add new icons by dropping SVG files
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ npm install @purposeinplay/feral-icons
21
+ # or
22
+ yarn add @purposeinplay/feral-icons
23
+ # or
24
+ pnpm add @purposeinplay/feral-icons
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ ### Basic Usage
30
+
31
+ ```tsx
32
+ import { FeralIcon } from "@purposeinplay/feral-icons";
33
+
34
+ function App() {
35
+ return (
36
+ <>
37
+ <FeralIcon name="arrow-left" size={24} />
38
+ <FeralIcon name="camera" fill="red" />
39
+ <FeralIcon name="user" className="text-blue-500" fill="#3B82F6" />
40
+ </>
41
+ );
42
+ }
43
+ ```
44
+
45
+ ### With Dynamic Names
46
+
47
+ ```tsx
48
+ import { FeralIcon, type IconName } from "@purposeinplay/feral-icons";
49
+
50
+ function IconDisplay({ iconName }: { iconName: IconName }) {
51
+ return <FeralIcon name={iconName} size={24} />;
52
+ }
53
+
54
+ // Usage
55
+ <IconDisplay iconName="camera" />;
56
+ ```
57
+
58
+ ### With Tailwind CSS
59
+
60
+ Icons work seamlessly with Tailwind CSS color utilities:
61
+
62
+ ```tsx
63
+ // Using Tailwind text color classes (recommended)
64
+ <FeralIcon name="camera" className="text-blue-600" />
65
+ <FeralIcon name="user" className="text-red-500 hover:text-red-700" />
66
+
67
+ // Using Tailwind colors with fill prop
68
+ <FeralIcon name="arrow-left" fill="rgb(59 130 246)" />
69
+
70
+ // Responsive colors
71
+ <FeralIcon name="camera" className="text-blue-500 md:text-purple-500" />
72
+ ```
73
+
74
+ **Pro tip:** Since icons default to `fill="currentColor"`, you can control their color with Tailwind's `text-*` utility classes!
75
+
76
+ ## Props
77
+
78
+ The `FeralIcon` component accepts these props:
79
+
80
+ - `name: IconName` - **Required**. The icon name (e.g., `"camera"`, `"user"`, `"arrow-left"`)
81
+ - `size?: number | string` - Icon size (default: 24)
82
+ - `fill?: string` - Fill color (default: 'currentColor')
83
+ - `className?: string` - Additional CSS classes
84
+ - All standard SVG attributes (`onClick`, `onMouseEnter`, etc.)
85
+
86
+ ## Available Icons
87
+
88
+ - `arrow-left` - Navigation arrow pointing left
89
+ - `camera` - Camera icon
90
+ - `user` - User profile icon
91
+
92
+ All icon names are available as the `IconName` type for TypeScript autocomplete.
93
+
94
+ ## Tree-Shaking
95
+
96
+ This library is fully tree-shakable. Only imported icons are included in your bundle.
97
+
98
+ **Example bundle impact:**
99
+
100
+ - Importing all icons: ~2KB gzipped
101
+ - Importing single icon: ~0.3KB gzipped
102
+
103
+ ## Local Development & Testing
104
+
105
+ ### Test Locally with npm link
106
+
107
+ ```bash
108
+ # In the @purposeinplay/feral-icons directory
109
+ npm link
110
+
111
+ # In your app directory
112
+ npm link @purposeinplay/feral-icons
113
+ ```
114
+
115
+ ### Use in Your App
116
+
117
+ ```tsx
118
+ import { FeralIcon } from "@purposeinplay/feral-icons";
119
+
120
+ function MyComponent() {
121
+ return <FeralIcon name="arrow-left" size={32} fill="#3B82F6" />;
122
+ }
123
+ ```
124
+
125
+ ## Adding New Icons
126
+
127
+ ### Quick Start
128
+
129
+ 1. **Add your SVG file** to the `svgs/` directory
130
+
131
+ ```bash
132
+ # Example: Add a new icon called "heart"
133
+ cp ~/Downloads/heart.svg svgs/heart.svg
134
+ ```
135
+
136
+ 2. **Build the library**
137
+
138
+ ```bash
139
+ npm run build
140
+ ```
141
+
142
+ 3. **Use your new icon**
143
+ ```tsx
144
+ <FeralIcon name="heart" size={24} />
145
+ ```
146
+
147
+ That's it! The build process automatically:
148
+
149
+ - ✅ Optimizes the SVG
150
+ - ✅ Generates a React component (`Heart.tsx`)
151
+ - ✅ Adds it to the icon registry
152
+ - ✅ Updates TypeScript types for autocomplete
153
+
154
+ ### SVG Requirements
155
+
156
+ Your SVG files should follow these guidelines:
157
+
158
+ **Required:**
159
+
160
+ - ✅ 24x24 viewBox (e.g., `viewBox="0 0 24 24"`)
161
+ - ✅ Path-based design with filled paths (not strokes)
162
+ - ✅ Kebab-case naming (e.g., `arrow-left.svg`, `user-circle.svg`)
163
+
164
+ **Recommended:**
165
+
166
+ - ✅ Use `fill="currentColor"` or no fill attribute (will inherit from parent)
167
+ - ✅ Remove any `stroke` attributes (optimizer will strip them anyway)
168
+ - ✅ Remove unnecessary attributes like `id`, `class`, `data-*`
169
+
170
+ **Example SVG:**
171
+
172
+ ```svg
173
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
174
+ <path d="M12 2L2 7v10c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V7l-10-5z"/>
175
+ </svg>
176
+ ```
177
+
178
+ ### Icon Naming Convention
179
+
180
+ SVG filenames are converted to icon names:
181
+
182
+ - `arrow-left.svg` → `name="arrow-left"`
183
+ - `user-circle.svg` → `name="user-circle"`
184
+ - `chevron-down.svg` → `name="chevron-down"`
185
+
186
+ Component names are PascalCase internally:
187
+
188
+ - `arrow-left.svg` → `ArrowLeft` component
189
+ - `user-circle.svg` → `UserCircle` component
190
+
191
+ ## Development Scripts
192
+
193
+ ### Main Commands
194
+
195
+ ```bash
196
+ # Full build (clean + generate + compile)
197
+ npm run build
198
+
199
+ # Clean generated files (icons, registry, index)
200
+ npm run clean
201
+
202
+ # Generate components from SVGs (without building)
203
+ npm run generate
204
+
205
+ # Build and watch for changes
206
+ npm run dev
207
+ ```
208
+
209
+ ### Development Workflow
210
+
211
+ **Adding/updating icons:**
212
+
213
+ ```bash
214
+ # 1. Add SVG to svgs/ directory
215
+ cp new-icon.svg svgs/
216
+
217
+ # 2. Full rebuild
218
+ npm run build
219
+
220
+ # 3. Icons are now available!
221
+ ```
222
+
223
+ **During development:**
224
+
225
+ ```bash
226
+ # Watch mode - rebuilds on changes
227
+ npm run dev
228
+
229
+ # In another terminal, run the demo
230
+ cd demo
231
+ npm run dev
232
+ ```
233
+
234
+ ### Testing Changes Locally
235
+
236
+ ```bash
237
+ # In the icon library directory
238
+ npm link
239
+
240
+ # In your app directory
241
+ npm link @purposeinplay/feral-icons
242
+
243
+ # Make changes, rebuild, and test
244
+ npm run build
245
+ ```
246
+
247
+ ## How It Works
248
+
249
+ ### Architecture Overview
250
+
251
+ ```
252
+ User Code Internal System SVG Files
253
+ ───────── ──────────────── ─────────
254
+
255
+ <FeralIcon → iconRegistry svgs/
256
+ name="camera" { ├── arrow-left.svg
257
+ size={24} 'camera': Camera, ├── camera.svg
258
+ /> 'user': User, └── user.svg
259
+ ... ↓
260
+ } [Build Process]
261
+ ↓ ↓
262
+ Camera component Generated Components
263
+ renders with props ├── ArrowLeft.tsx
264
+ ├── Camera.tsx
265
+ └── User.tsx
266
+ ```
267
+
268
+ ### Build Process
269
+
270
+ When you run `npm run build`, here's what happens:
271
+
272
+ 1. **Clean** - Removes old generated files
273
+ 2. **Generate** - For each SVG in `svgs/`:
274
+ - Optimizes SVG with SVGO (removes strokes, dimensions, etc.)
275
+ - Extracts SVG path content
276
+ - Generates React component file
277
+ - Adds to icon registry
278
+ - Updates TypeScript types
279
+ 3. **Compile** - TypeScript generates `.d.ts` files
280
+ 4. **Bundle** - Vite creates ESM output with tree-shaking
281
+
282
+ ### File Structure
283
+
284
+ ```
285
+ feral-icon-pack/
286
+ ├── svgs/ # Source SVG files (you add here)
287
+ │ ├── arrow-left.svg
288
+ │ ├── camera.svg
289
+ │ └── user.svg
290
+ ├── src/
291
+ │ ├── icons/ # Generated (gitignored)
292
+ │ │ ├── ArrowLeft.tsx
293
+ │ │ ├── Camera.tsx
294
+ │ │ └── User.tsx
295
+ │ ├── shared/
296
+ │ │ ├── Icon.tsx # Base SVG wrapper
297
+ │ │ └── types.ts # Internal types
298
+ │ ├── iconRegistry.ts # Generated (gitignored)
299
+ │ ├── FeralIcon.tsx # Public component
300
+ │ └── index.ts # Generated (gitignored)
301
+ ├── dist/ # Build output (gitignored)
302
+ │ ├── index.js
303
+ │ ├── index.d.ts
304
+ │ ├── FeralIcon.js
305
+ │ └── ...
306
+ └── scripts/
307
+ ├── generate.ts # SVG → React converter
308
+ └── optimize.ts # SVGO configuration
309
+ ```
310
+
311
+ ### Package Exports
312
+
313
+ Only these are exported publicly:
314
+
315
+ ```typescript
316
+ // From @purposeinplay/feral-icons
317
+ export { FeralIcon } from "./FeralIcon";
318
+ export type { FeralIconProps, IconName } from "./FeralIcon";
319
+ ```
320
+
321
+ Everything else (individual icon components, base Icon, internal types) stays internal for the registry system.
322
+
323
+ ## TypeScript Support
324
+
325
+ This library is written in TypeScript and includes full type definitions.
326
+
327
+ ```tsx
328
+ import { FeralIcon, type FeralIconProps, type IconName } from "@purposeinplay/feral-icons";
329
+
330
+ // Type for icon props
331
+ const CustomIconWrapper: React.FC<FeralIconProps> = (props) => {
332
+ return <FeralIcon {...props} />;
333
+ };
334
+
335
+ // Type for icon names (with autocomplete)
336
+ const iconName: IconName = "camera"; // TypeScript will suggest: "arrow-left" | "camera" | "user"
337
+
338
+ // Dynamic icon selection with type safety
339
+ function DynamicIcon({ name }: { name: IconName }) {
340
+ return <FeralIcon name={name} size={24} />;
341
+ }
342
+ ```
343
+
344
+ **Available Types:**
345
+
346
+ - `IconName` - Union type of all valid icon names (`"arrow-left" | "camera" | "user"`)
347
+ - `FeralIconProps` - Props interface for the FeralIcon component (`name`, `size`, `fill`, `className`, etc.)
348
+
349
+ ## Browser Support
350
+
351
+ - Modern browsers with ES2020 support
352
+ - React 18.0.0 or higher
353
+ - React 19.x supported
354
+
355
+ ## License
356
+
357
+ MIT
358
+
359
+ ## Contributing
360
+
361
+ ### Adding Icons
362
+
363
+ 1. **Fork and clone** this repository
364
+ 2. **Add SVG files** to `svgs/` directory
365
+ 3. **Follow SVG requirements** (24x24, fill-based, kebab-case)
366
+ 4. **Build and test**
367
+ ```bash
368
+ npm run build
369
+ cd demo && npm run dev
370
+ ```
371
+ 5. **Commit and PR**
372
+ ```bash
373
+ git add svgs/your-icon.svg
374
+ git commit -m "Add your-icon"
375
+ ```
376
+
377
+ ### Guidelines
378
+
379
+ - One icon per file
380
+ - Use semantic names (`chevron-down`, not `icon-1`)
381
+ - Test in the demo app before submitting
382
+ - Include icon source/license if applicable
383
+
384
+ ## Troubleshooting
385
+
386
+ ### Icon not showing up?
387
+
388
+ 1. **Check the SVG file name**
389
+
390
+ ```bash
391
+ ls svgs/
392
+ # Should see your-icon.svg
393
+ ```
394
+
395
+ 2. **Rebuild the library**
396
+
397
+ ```bash
398
+ npm run build
399
+ ```
400
+
401
+ 3. **Check TypeScript autocomplete**
402
+ ```tsx
403
+ <FeralIcon name="your-icon" />
404
+ // ^ Should autocomplete
405
+ ```
406
+
407
+ ### TypeScript errors?
408
+
409
+ If you see `Type '"my-icon"' is not assignable to type 'IconName'`:
410
+
411
+ 1. Make sure you rebuilt: `npm run build`
412
+ 2. Restart your TypeScript server (VS Code: `Cmd+Shift+P` → "Restart TS Server")
413
+ 3. Check that `src/iconRegistry.ts` includes your icon
414
+
415
+ ### Icons look wrong?
416
+
417
+ - Check SVG uses `fill` not `stroke`
418
+ - Verify 24x24 viewBox
419
+ - Remove hardcoded colors (use `fill="currentColor"`)
420
+
421
+ ### Demo not updating?
422
+
423
+ ```bash
424
+ # Rebuild the library
425
+ npm run build
426
+
427
+ # Reinstall in demo
428
+ cd demo
429
+ npm install
430
+ npm run dev
431
+ ```
@@ -0,0 +1,18 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ import { iconRegistry } from "./iconRegistry.js";
4
+ const FeralIcon = forwardRef(
5
+ ({ name, ...props }, ref) => {
6
+ const IconComponent = iconRegistry[name];
7
+ if (!IconComponent) {
8
+ console.warn(`[FeralIcon] Icon "${name}" not found in registry`);
9
+ return null;
10
+ }
11
+ return /* @__PURE__ */ jsx(IconComponent, { ref, ...props });
12
+ }
13
+ );
14
+ FeralIcon.displayName = "FeralIcon";
15
+ export {
16
+ FeralIcon
17
+ };
18
+ //# sourceMappingURL=FeralIcon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FeralIcon.js","sources":["../src/FeralIcon.tsx"],"sourcesContent":["import { forwardRef } from 'react';\nimport { iconRegistry, type IconName } from './iconRegistry';\nimport type { IconProps } from './shared/types';\n\nexport interface FeralIconProps extends IconProps {\n name: IconName;\n}\n\nexport type { IconName };\n\nexport const FeralIcon = forwardRef<SVGSVGElement, FeralIconProps>(\n ({ name, ...props }, ref) => {\n const IconComponent = iconRegistry[name];\n\n if (!IconComponent) {\n console.warn(`[FeralIcon] Icon \"${name}\" not found in registry`);\n return null;\n }\n\n return <IconComponent ref={ref} {...props} />;\n }\n);\n\nFeralIcon.displayName = 'FeralIcon';\n\n"],"names":[],"mappings":";;;AAUO,MAAM,YAAY;AAAA,EACvB,CAAC,EAAE,MAAM,GAAG,MAAA,GAAS,QAAQ;AAC3B,UAAM,gBAAgB,aAAa,IAAI;AAEvC,QAAI,CAAC,eAAe;AAClB,cAAQ,KAAK,qBAAqB,IAAI,yBAAyB;AAC/D,aAAO;AAAA,IACT;AAEA,WAAO,oBAAC,eAAA,EAAc,KAAW,GAAG,MAAA,CAAO;AAAA,EAC7C;AACF;AAEA,UAAU,cAAc;"}
@@ -0,0 +1,12 @@
1
+ import { ArrowLeft } from "./icons/ArrowLeft.js";
2
+ import { Camera } from "./icons/Camera.js";
3
+ import { User } from "./icons/User.js";
4
+ const iconRegistry = {
5
+ "arrow-left": ArrowLeft,
6
+ "camera": Camera,
7
+ "user": User
8
+ };
9
+ export {
10
+ iconRegistry
11
+ };
12
+ //# sourceMappingURL=iconRegistry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"iconRegistry.js","sources":["../src/iconRegistry.ts"],"sourcesContent":["// Auto-generated file. Do not edit manually.\nimport { ArrowLeft } from './icons/ArrowLeft';\nimport { Camera } from './icons/Camera';\nimport { User } from './icons/User';\nimport type { IconComponent } from './shared/types';\n\nexport const iconRegistry: Record<string, IconComponent> = {\n 'arrow-left': ArrowLeft,\n 'camera': Camera,\n 'user': User,\n};\n\nexport type IconName = 'arrow-left' | 'camera' | 'user';\n"],"names":[],"mappings":";;;AAMO,MAAM,eAA8C;AAAA,EACzD,cAAc;AAAA,EACd,UAAU;AAAA,EACV,QAAQ;AACV;"}
@@ -0,0 +1,13 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ import { Icon } from "../shared/Icon.js";
4
+ const ArrowLeft = forwardRef(
5
+ (props, ref) => {
6
+ return /* @__PURE__ */ jsx(Icon, { ref, ...props, children: /* @__PURE__ */ jsx("path", { d: "M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20z" }) });
7
+ }
8
+ );
9
+ ArrowLeft.displayName = "ArrowLeft";
10
+ export {
11
+ ArrowLeft
12
+ };
13
+ //# sourceMappingURL=ArrowLeft.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ArrowLeft.js","sources":["../../src/icons/ArrowLeft.tsx"],"sourcesContent":["import { forwardRef } from 'react';\nimport { Icon } from '../shared/Icon';\nimport type { IconProps } from '../shared/types';\n\nexport const ArrowLeft = forwardRef<SVGSVGElement, IconProps>(\n (props, ref) => {\n return (\n <Icon ref={ref} {...props}>\n <path d=\"M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20z\"/>\n </Icon>\n );\n }\n);\n\nArrowLeft.displayName = 'ArrowLeft';\n"],"names":[],"mappings":";;;AAIO,MAAM,YAAY;AAAA,EACvB,CAAC,OAAO,QAAQ;AACd,WACE,oBAAC,QAAK,KAAW,GAAG,OAClB,UAAA,oBAAC,QAAA,EAAK,GAAE,4DAAA,CAA2D,EAAA,CACrE;AAAA,EAEJ;AACF;AAEA,UAAU,cAAc;"}
@@ -0,0 +1,16 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ import { Icon } from "../shared/Icon.js";
4
+ const Camera = forwardRef(
5
+ (props, ref) => {
6
+ return /* @__PURE__ */ jsxs(Icon, { ref, ...props, children: [
7
+ /* @__PURE__ */ jsx("path", { d: "M12 15.2c1.77 0 3.2-1.43 3.2-3.2S13.77 8.8 12 8.8 8.8 10.23 8.8 12s1.43 3.2 3.2 3.2" }),
8
+ /* @__PURE__ */ jsx("path", { d: "M9 2 7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2h-3.17L15 2zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5" })
9
+ ] });
10
+ }
11
+ );
12
+ Camera.displayName = "Camera";
13
+ export {
14
+ Camera
15
+ };
16
+ //# sourceMappingURL=Camera.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Camera.js","sources":["../../src/icons/Camera.tsx"],"sourcesContent":["import { forwardRef } from 'react';\nimport { Icon } from '../shared/Icon';\nimport type { IconProps } from '../shared/types';\n\nexport const Camera = forwardRef<SVGSVGElement, IconProps>(\n (props, ref) => {\n return (\n <Icon ref={ref} {...props}>\n <path d=\"M12 15.2c1.77 0 3.2-1.43 3.2-3.2S13.77 8.8 12 8.8 8.8 10.23 8.8 12s1.43 3.2 3.2 3.2\"/><path d=\"M9 2 7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2h-3.17L15 2zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5\"/>\n </Icon>\n );\n }\n);\n\nCamera.displayName = 'Camera';\n"],"names":[],"mappings":";;;AAIO,MAAM,SAAS;AAAA,EACpB,CAAC,OAAO,QAAQ;AACd,WACE,qBAAC,MAAA,EAAK,KAAW,GAAG,OAClB,UAAA;AAAA,MAAA,oBAAC,QAAA,EAAK,GAAE,sFAAA,CAAqF;AAAA,MAAE,oBAAC,QAAA,EAAK,GAAE,yJAAA,CAAwJ;AAAA,IAAA,GACjQ;AAAA,EAEJ;AACF;AAEA,OAAO,cAAc;"}
@@ -0,0 +1,13 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ import { Icon } from "../shared/Icon.js";
4
+ const User = forwardRef(
5
+ (props, ref) => {
6
+ return /* @__PURE__ */ jsx(Icon, { ref, ...props, children: /* @__PURE__ */ jsx("path", { d: "M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4m0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4" }) });
7
+ }
8
+ );
9
+ User.displayName = "User";
10
+ export {
11
+ User
12
+ };
13
+ //# sourceMappingURL=User.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"User.js","sources":["../../src/icons/User.tsx"],"sourcesContent":["import { forwardRef } from 'react';\nimport { Icon } from '../shared/Icon';\nimport type { IconProps } from '../shared/types';\n\nexport const User = forwardRef<SVGSVGElement, IconProps>(\n (props, ref) => {\n return (\n <Icon ref={ref} {...props}>\n <path d=\"M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4m0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4\"/>\n </Icon>\n );\n }\n);\n\nUser.displayName = 'User';\n"],"names":[],"mappings":";;;AAIO,MAAM,OAAO;AAAA,EAClB,CAAC,OAAO,QAAQ;AACd,WACE,oBAAC,QAAK,KAAW,GAAG,OAClB,UAAA,oBAAC,QAAA,EAAK,GAAE,8GAAA,CAA6G,EAAA,CACvH;AAAA,EAEJ;AACF;AAEA,KAAK,cAAc;"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ import { FeralIcon } from "./FeralIcon.js";
2
+ export {
3
+ FeralIcon
4
+ };
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
@@ -0,0 +1,25 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ const Icon = forwardRef(
4
+ ({ size = 24, fill = "currentColor", className = "", children, ...props }, ref) => {
5
+ return /* @__PURE__ */ jsx(
6
+ "svg",
7
+ {
8
+ ref,
9
+ xmlns: "http://www.w3.org/2000/svg",
10
+ width: size,
11
+ height: size,
12
+ viewBox: "0 0 24 24",
13
+ fill,
14
+ className,
15
+ ...props,
16
+ children
17
+ }
18
+ );
19
+ }
20
+ );
21
+ Icon.displayName = "Icon";
22
+ export {
23
+ Icon
24
+ };
25
+ //# sourceMappingURL=Icon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Icon.js","sources":["../../src/shared/Icon.tsx"],"sourcesContent":["import { forwardRef } from \"react\";\nimport type { IconProps } from \"./types\";\n\nconst Icon = forwardRef<\n SVGSVGElement,\n IconProps & { children: React.ReactNode }\n>(\n (\n { size = 24, fill = \"currentColor\", className = \"\", children, ...props },\n ref\n ) => {\n return (\n <svg\n ref={ref}\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill={fill}\n className={className}\n {...props}\n >\n {children}\n </svg>\n );\n }\n);\n\nIcon.displayName = \"Icon\";\n\nexport { Icon };\n"],"names":[],"mappings":";;AAGA,MAAM,OAAO;AAAA,EAIX,CACE,EAAE,OAAO,IAAI,OAAO,gBAAgB,YAAY,IAAI,UAAU,GAAG,MAAA,GACjE,QACG;AACH,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,OAAM;AAAA,QACN,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,SAAQ;AAAA,QACR;AAAA,QACA;AAAA,QACC,GAAG;AAAA,QAEH;AAAA,MAAA;AAAA,IAAA;AAAA,EAGP;AACF;AAEA,KAAK,cAAc;"}
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@purposeinplay/feral-icons",
3
+ "version": "0.1.0",
4
+ "description": "Custom React icon library with tree-shaking support",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ },
14
+ "./icons/*": {
15
+ "types": "./dist/icons/*.d.ts",
16
+ "import": "./dist/icons/*.js"
17
+ }
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "README.md"
22
+ ],
23
+ "sideEffects": false,
24
+ "scripts": {
25
+ "clean": "rimraf dist src/icons src/index.ts",
26
+ "generate": "tsx scripts/generate.ts",
27
+ "build:lib": "tsc && vite build",
28
+ "build": "npm run clean && npm run generate && npm run build:lib",
29
+ "dev": "npm run generate && vite build --watch",
30
+ "prepublishOnly": "npm run build"
31
+ },
32
+ "keywords": [
33
+ "react",
34
+ "icons",
35
+ "svg",
36
+ "components"
37
+ ],
38
+ "author": "",
39
+ "license": "MIT",
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "git+https://github.com/purposeinplay/feral-icon-pack.git"
43
+ },
44
+ "bugs": {
45
+ "url": "https://github.com/purposeinplay/feral-icon-pack/issues"
46
+ },
47
+ "homepage": "https://github.com/purposeinplay/feral-icon-pack#readme",
48
+ "peerDependencies": {
49
+ "react": "^18.0.0 || ^19.0.0",
50
+ "react-dom": "^18.0.0 || ^19.0.0"
51
+ },
52
+ "dependencies": {
53
+ "react": "^18.0.0 || ^19.0.0",
54
+ "react-dom": "^18.0.0 || ^19.0.0"
55
+ },
56
+ "devDependencies": {
57
+ "@types/node": "^24.10.0",
58
+ "@types/react": "^19.2.2",
59
+ "@types/react-dom": "^19.2.2",
60
+ "@vitejs/plugin-react": "^5.1.0",
61
+ "knip": "^5.67.1",
62
+ "rimraf": "^6.1.0",
63
+ "svgo": "^4.0.0",
64
+ "tsx": "^4.20.6",
65
+ "typescript": "^5.9.3",
66
+ "vite": "^7.2.0"
67
+ }
68
+ }