huspy-icons 0.1.1 → 0.1.3
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 +181 -117
- package/dist/fonts/HuspyIcons.css +28 -0
- package/dist/fonts/HuspyIcons.eot +0 -0
- package/dist/fonts/HuspyIcons.json +5 -0
- package/dist/fonts/HuspyIcons.ts +16 -0
- package/dist/fonts/HuspyIcons.ttf +0 -0
- package/dist/fonts/HuspyIcons.woff +0 -0
- package/dist/fonts/HuspyIcons.woff2 +0 -0
- package/dist/native/index.d.ts +30 -46
- package/dist/native/index.js +44 -172
- package/dist/native/index.js.map +1 -1
- package/package.json +7 -8
- package/src/native/Icon.tsx +60 -66
- package/src/native/glyphMap.ts +22 -0
- package/src/native/index.ts +16 -14
- package/src/native/ArrowLeft.tsx +0 -27
- package/src/native/ArrowUpRight.tsx +0 -27
- package/src/native/IconSlot.tsx +0 -19
- package/src/native/index.tsx +0 -3
package/README.md
CHANGED
|
@@ -1,157 +1,125 @@
|
|
|
1
1
|
# huspy-icons
|
|
2
2
|
|
|
3
|
-
A cross-platform icon package generated from raw SVGs. Ships separate builds for **web (React / Next.js)** and **native (Expo / React Native)** with
|
|
3
|
+
A cross-platform icon package generated from raw SVGs. Ships separate builds for **web (React / Next.js)** with **SVG icons** and **native (Expo / React Native)** with **font-based icons** for optimal performance.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
## ✨ Features
|
|
8
8
|
|
|
9
9
|
* **Single source of truth**: raw SVGs → codegen → typed components
|
|
10
|
-
* **Two
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
* **
|
|
14
|
-
* **
|
|
10
|
+
* **Two rendering strategies**:
|
|
11
|
+
- **Web**: Inline SVG (tree-shakable, full styling control)
|
|
12
|
+
- **Native**: Font-based icons (better performance, smaller bundle)
|
|
13
|
+
* **Unified API**: Same `<Icon name="..." />` syntax for both platforms
|
|
14
|
+
* **TypeScript-first**: Auto-generated types with full autocomplete
|
|
15
|
+
* **Theming ready**: `color` and `size` props on all icons
|
|
16
|
+
* **A11y**: Proper accessibility labels for both platforms
|
|
17
|
+
* **Scales**: Hundreds of icons with auto-generated exports
|
|
15
18
|
|
|
16
19
|
---
|
|
17
20
|
|
|
18
|
-
## 📦
|
|
21
|
+
## 📦 Installation
|
|
19
22
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
**Next.js (web):**
|
|
23
|
+
**Next.js / React (Web):**
|
|
23
24
|
|
|
24
25
|
```bash
|
|
25
26
|
npm install huspy-icons
|
|
26
27
|
```
|
|
27
28
|
|
|
28
|
-
**Expo
|
|
29
|
+
**Expo / React Native:**
|
|
29
30
|
|
|
30
31
|
```bash
|
|
31
|
-
npx expo install react-native-svg
|
|
32
32
|
npm install huspy-icons
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
-
>
|
|
35
|
+
> **Note**: Native build uses custom fonts - no need for `react-native-svg`!
|
|
36
|
+
> See [FONT_SETUP.md](./FONT_SETUP.md) for font installation instructions.
|
|
36
37
|
|
|
37
38
|
---
|
|
38
39
|
|
|
39
40
|
## 🚀 Quick Start
|
|
40
41
|
|
|
41
|
-
|
|
42
|
+
### Web (React / Next.js)
|
|
42
43
|
|
|
43
44
|
```tsx
|
|
44
|
-
import {
|
|
45
|
+
import { Icon } from 'huspy-icons/react';
|
|
45
46
|
|
|
46
47
|
export default function Example() {
|
|
47
48
|
return (
|
|
48
|
-
<div
|
|
49
|
-
<
|
|
49
|
+
<div>
|
|
50
|
+
<Icon name="arrow-left" size={24} color="#000" />
|
|
51
|
+
<Icon name="arrow-up-right" size={32} color="#6b7280" />
|
|
50
52
|
</div>
|
|
51
53
|
);
|
|
52
54
|
}
|
|
53
55
|
```
|
|
54
56
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
```tsx
|
|
58
|
-
import { ArrowLeft } from 'huspy-icons/native';
|
|
59
|
-
|
|
60
|
-
export default function Example() {
|
|
61
|
-
return <ArrowLeft size={20} color="#111" accessibilityLabel="Back" />;
|
|
62
|
-
}
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
---
|
|
57
|
+
### Expo / React Native
|
|
66
58
|
|
|
67
|
-
|
|
59
|
+
**1. First, set up the font** (one-time setup):
|
|
68
60
|
|
|
69
|
-
|
|
70
|
-
packages/huspy-icons/
|
|
71
|
-
icons-src/ # raw .svg files (single source of truth)
|
|
72
|
-
src/
|
|
73
|
-
react/ # generated TSX for web
|
|
74
|
-
native/ # generated TSX for expo
|
|
75
|
-
shared/ # helper types/utilities (createIcon, resolveSize)
|
|
76
|
-
scripts/ # codegen utilities (svgr, registry, typedefs)
|
|
77
|
-
svgo.config.js
|
|
78
|
-
package.json
|
|
79
|
-
tsconfig.json
|
|
80
|
-
```
|
|
61
|
+
See [FONT_SETUP.md](./FONT_SETUP.md) for detailed instructions.
|
|
81
62
|
|
|
82
|
-
|
|
63
|
+
**2. Use the icons:**
|
|
83
64
|
|
|
84
|
-
|
|
65
|
+
```tsx
|
|
66
|
+
import { Icon } from 'huspy-icons/native';
|
|
85
67
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
"build": "tsup src/**/index.ts --format esm,cjs --dts --out-dir dist --clean",
|
|
94
|
-
"prepare": "npm run gen && npm run build"
|
|
95
|
-
}
|
|
68
|
+
export default function Example() {
|
|
69
|
+
return (
|
|
70
|
+
<>
|
|
71
|
+
<Icon name="arrow-left" size={24} color="#000" />
|
|
72
|
+
<Icon name="arrow-up-right" size={32} color="#6b7280" />
|
|
73
|
+
</>
|
|
74
|
+
);
|
|
96
75
|
}
|
|
97
76
|
```
|
|
98
77
|
|
|
99
|
-
* **`svgo`**: normalize SVGs (remove width/height, hardcoded colors).
|
|
100
|
-
* **`gen:*`**: generate typed components for each target using SVGR.
|
|
101
|
-
* **`build`**: bundle per-target outputs with types.
|
|
102
|
-
|
|
103
78
|
---
|
|
104
79
|
|
|
105
|
-
##
|
|
80
|
+
## 🎨 API
|
|
106
81
|
|
|
107
|
-
|
|
82
|
+
Both platforms use the same API:
|
|
108
83
|
|
|
109
84
|
```tsx
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
85
|
+
<Icon
|
|
86
|
+
name="arrow-left" // Icon name (TypeScript autocomplete available)
|
|
87
|
+
size={24} // Size in pixels (default: 16)
|
|
88
|
+
color="#000" // Any valid color (default: 'currentColor' for web, '#000' for native)
|
|
89
|
+
/>
|
|
113
90
|
```
|
|
114
91
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
---
|
|
118
|
-
|
|
119
|
-
## 🎨 Props & Theming
|
|
120
|
-
|
|
121
|
-
All icons share a consistent API:
|
|
92
|
+
### Available Icons
|
|
122
93
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
> Because paths default to `currentColor`, icons inherit text color out of the box. Style a parent `color` (web) or pass `color` directly.
|
|
94
|
+
TypeScript will autocomplete available icon names. Current icons:
|
|
95
|
+
- `arrow-left`
|
|
96
|
+
- `arrow-up-right`
|
|
97
|
+
- `icon-slot`
|
|
129
98
|
|
|
130
99
|
---
|
|
131
100
|
|
|
132
|
-
##
|
|
133
|
-
|
|
134
|
-
Icons are designed with logical naming. For RTL support:
|
|
101
|
+
## 🏗️ Architecture
|
|
135
102
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
// native
|
|
143
|
-
<View style={{ transform: [{ scaleX: I18nManager.isRTL ? -1 : 1 }] }}>
|
|
144
|
-
<ArrowLeft />
|
|
145
|
-
</View>
|
|
146
|
-
```
|
|
103
|
+
### Web (SVG-based)
|
|
104
|
+
- Individual SVG components generated from source files
|
|
105
|
+
- Tree-shakable - only icons you use are bundled
|
|
106
|
+
- Full CSS styling support
|
|
107
|
+
- Color inherits from parent by default (`currentColor`)
|
|
147
108
|
|
|
148
|
-
|
|
109
|
+
### Native (Font-based)
|
|
110
|
+
- Custom font generated from SVG files
|
|
111
|
+
- Single font file for all icons
|
|
112
|
+
- Better performance than SVG rendering
|
|
113
|
+
- Smaller bundle size for large icon sets
|
|
114
|
+
- Uses React Native `Text` component
|
|
149
115
|
|
|
150
116
|
---
|
|
151
117
|
|
|
152
|
-
##
|
|
118
|
+
## 🔧 Development
|
|
153
119
|
|
|
154
|
-
|
|
120
|
+
### Adding New Icons
|
|
121
|
+
|
|
122
|
+
1. Drop SVG files into `icons-src/` (24×24 viewBox recommended)
|
|
155
123
|
|
|
156
124
|
2. Run codegen:
|
|
157
125
|
|
|
@@ -159,53 +127,139 @@ You can also add a `rtlFlip` prop or generate RTL variants if your design system
|
|
|
159
127
|
npm run gen
|
|
160
128
|
```
|
|
161
129
|
|
|
162
|
-
|
|
130
|
+
This will:
|
|
131
|
+
- Optimize SVGs with SVGO
|
|
132
|
+
- Generate React components (web)
|
|
133
|
+
- Generate icon font + glyph map (native)
|
|
134
|
+
- Generate TypeScript types
|
|
135
|
+
|
|
136
|
+
3. Build the package:
|
|
163
137
|
|
|
164
138
|
```bash
|
|
165
|
-
npm
|
|
166
|
-
npm publish --access public
|
|
139
|
+
npm run build
|
|
167
140
|
```
|
|
168
141
|
|
|
169
|
-
|
|
142
|
+
4. Publish:
|
|
170
143
|
|
|
144
|
+
```bash
|
|
145
|
+
npm version minor
|
|
146
|
+
npm publish
|
|
147
|
+
```
|
|
171
148
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
### Next.js
|
|
149
|
+
### Project Structure
|
|
175
150
|
|
|
176
|
-
|
|
177
|
-
|
|
151
|
+
```
|
|
152
|
+
huspy-icons/
|
|
153
|
+
├── icons-src/ # Source SVG files (single source of truth)
|
|
154
|
+
├── src/
|
|
155
|
+
│ ├── react/ # Generated web components (SVG)
|
|
156
|
+
│ ├── native/ # Native Icon component (font-based)
|
|
157
|
+
│ └── shared/ # Shared types and utilities
|
|
158
|
+
├── dist/
|
|
159
|
+
│ ├── fonts/ # Generated font files (TTF, WOFF, etc.)
|
|
160
|
+
│ ├── react/ # Built web components
|
|
161
|
+
│ └── native/ # Built native component
|
|
162
|
+
├── scripts/
|
|
163
|
+
│ ├── generate-font.js # Font generation script (Fantasticon)
|
|
164
|
+
│ ├── generate-types.js # TypeScript type generation
|
|
165
|
+
│ └── add-size-prop.js # Post-processing for SVGR output
|
|
166
|
+
└── package.json
|
|
167
|
+
```
|
|
178
168
|
|
|
179
|
-
###
|
|
169
|
+
### Available Scripts
|
|
180
170
|
|
|
181
|
-
|
|
182
|
-
|
|
171
|
+
```json
|
|
172
|
+
{
|
|
173
|
+
"svgo": "Optimize SVG files",
|
|
174
|
+
"gen:react": "Generate React/SVG components",
|
|
175
|
+
"gen:native": "Generate icon font and glyph map",
|
|
176
|
+
"gen:types": "Generate TypeScript types",
|
|
177
|
+
"gen": "Run all generation scripts",
|
|
178
|
+
"build": "Build TypeScript to JavaScript",
|
|
179
|
+
"prepare": "Full build (runs on npm install)"
|
|
180
|
+
}
|
|
181
|
+
```
|
|
183
182
|
|
|
184
183
|
---
|
|
185
184
|
|
|
186
|
-
## 📦 Exports
|
|
185
|
+
## 📦 Package Exports
|
|
187
186
|
|
|
188
187
|
```json
|
|
189
188
|
{
|
|
190
189
|
"exports": {
|
|
191
|
-
"./react":
|
|
192
|
-
|
|
190
|
+
"./react": {
|
|
191
|
+
"import": "./dist/react/index.mjs",
|
|
192
|
+
"require": "./dist/react/index.js",
|
|
193
|
+
"types": "./dist/react/index.d.ts"
|
|
194
|
+
},
|
|
195
|
+
"./native": {
|
|
196
|
+
"require": "./dist/native/index.js",
|
|
197
|
+
"types": "./dist/native/index.d.ts"
|
|
198
|
+
}
|
|
193
199
|
}
|
|
194
200
|
}
|
|
195
201
|
```
|
|
196
202
|
|
|
197
|
-
|
|
198
|
-
|
|
203
|
+
Usage:
|
|
204
|
+
```tsx
|
|
205
|
+
// Web
|
|
206
|
+
import { Icon } from 'huspy-icons/react';
|
|
207
|
+
|
|
208
|
+
// Native
|
|
209
|
+
import { Icon } from 'huspy-icons/native';
|
|
210
|
+
```
|
|
199
211
|
|
|
200
212
|
---
|
|
201
213
|
|
|
202
214
|
## 🔒 Versioning
|
|
203
215
|
|
|
204
|
-
* **Patch**:
|
|
205
|
-
* **Minor**:
|
|
206
|
-
* **Major**: removals/renames, breaking
|
|
216
|
+
* **Patch**: Path tweaks, bug fixes, metadata changes
|
|
217
|
+
* **Minor**: New icons, non-breaking API additions
|
|
218
|
+
* **Major**: Icon removals/renames, breaking API changes
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## 🐛 Troubleshooting
|
|
223
|
+
|
|
224
|
+
### Native: Font Not Loading
|
|
225
|
+
|
|
226
|
+
See [FONT_SETUP.md](./FONT_SETUP.md) for detailed setup instructions.
|
|
227
|
+
|
|
228
|
+
Common issues:
|
|
229
|
+
- Font file not copied to correct location
|
|
230
|
+
- Font not registered in app config
|
|
231
|
+
- App not restarted after adding font
|
|
207
232
|
|
|
208
|
-
|
|
233
|
+
### Web: Icons Not Showing
|
|
234
|
+
|
|
235
|
+
- Ensure you're importing from `huspy-icons/react`
|
|
236
|
+
- Check that the icon name is correct (TypeScript will help)
|
|
237
|
+
- Verify the package is installed and built
|
|
238
|
+
|
|
239
|
+
### TypeScript Errors
|
|
240
|
+
|
|
241
|
+
If you see type errors after adding new icons:
|
|
242
|
+
1. Run `npm run gen` to regenerate types
|
|
243
|
+
2. Restart your TypeScript server
|
|
244
|
+
3. Check that the built files in `dist/` are up to date
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## 🎯 Why This Architecture?
|
|
249
|
+
|
|
250
|
+
### Web uses SVG because:
|
|
251
|
+
- ✅ Tree-shakable (only bundle icons you use)
|
|
252
|
+
- ✅ Full CSS styling support
|
|
253
|
+
- ✅ Can animate individual paths
|
|
254
|
+
- ✅ No font loading required
|
|
255
|
+
- ✅ Modern browsers handle SVG efficiently
|
|
256
|
+
|
|
257
|
+
### Native uses Fonts because:
|
|
258
|
+
- ✅ Better performance at scale
|
|
259
|
+
- ✅ Smaller bundle size for large icon sets
|
|
260
|
+
- ✅ Native text rendering (faster than SVG)
|
|
261
|
+
- ✅ Single font file vs. many SVG components
|
|
262
|
+
- ✅ Consistent with native icon patterns
|
|
209
263
|
|
|
210
264
|
---
|
|
211
265
|
|
|
@@ -215,9 +269,19 @@ MIT © Huspy
|
|
|
215
269
|
|
|
216
270
|
---
|
|
217
271
|
|
|
218
|
-
## 💡
|
|
272
|
+
## 💡 Best Practices
|
|
273
|
+
|
|
274
|
+
* Keep `icons-src/` clean and consistent (same viewBox, stroke width)
|
|
275
|
+
* Use descriptive, kebab-case filenames (`arrow-left.svg`, not `arrow.svg`)
|
|
276
|
+
* Default to outline style; namespace filled variants if needed
|
|
277
|
+
* Test icons on both platforms before publishing
|
|
278
|
+
* Document any platform-specific differences
|
|
279
|
+
* Consider publishing a Storybook for visual reference
|
|
280
|
+
|
|
281
|
+
---
|
|
219
282
|
|
|
220
|
-
|
|
221
|
-
* Default to outlines; if you ship `filled` variants, namespace as `HomeIcon` / `HomeFilledIcon` or `HomeIcon` with a `variant="filled"` prop (generated).
|
|
222
|
-
* Consider publishing a Storybook or gallery page in your web app to preview all icons.
|
|
283
|
+
## 🔗 Related Docs
|
|
223
284
|
|
|
285
|
+
- [FONT_SETUP.md](./FONT_SETUP.md) - React Native font setup guide
|
|
286
|
+
- [USAGE.md](./USAGE.md) - Detailed usage examples
|
|
287
|
+
- [PROJECT_SUMMARY.md](./PROJECT_SUMMARY.md) - Technical architecture
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
@font-face {
|
|
2
|
+
font-family: "HuspyIcons";
|
|
3
|
+
src: url(".//HuspyIcons.ttf?25d92884ac0b766c69d414744c2ffbc2") format("truetype"),
|
|
4
|
+
url(".//HuspyIcons.woff?25d92884ac0b766c69d414744c2ffbc2") format("woff"),
|
|
5
|
+
url(".//HuspyIcons.woff2?25d92884ac0b766c69d414744c2ffbc2") format("woff2"),
|
|
6
|
+
url(".//HuspyIcons.eot?25d92884ac0b766c69d414744c2ffbc2#iefix") format("embedded-opentype");
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.icon:before {
|
|
10
|
+
font-family: HuspyIcons !important;
|
|
11
|
+
font-style: normal;
|
|
12
|
+
font-weight: normal !important;
|
|
13
|
+
font-variant: normal;
|
|
14
|
+
text-transform: none;
|
|
15
|
+
line-height: 1;
|
|
16
|
+
-webkit-font-smoothing: antialiased;
|
|
17
|
+
-moz-osx-font-smoothing: grayscale;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.icon.huspy-icon-icon-slot:before {
|
|
21
|
+
content: "\f101";
|
|
22
|
+
}
|
|
23
|
+
.icon.huspy-icon-arrow-up-right:before {
|
|
24
|
+
content: "\f102";
|
|
25
|
+
}
|
|
26
|
+
.icon.huspy-icon-arrow-left:before {
|
|
27
|
+
content: "\f103";
|
|
28
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type HuspyIconsId =
|
|
2
|
+
| "icon-slot"
|
|
3
|
+
| "arrow-up-right"
|
|
4
|
+
| "arrow-left";
|
|
5
|
+
|
|
6
|
+
export enum HuspyIcons {
|
|
7
|
+
IconSlot = "icon-slot",
|
|
8
|
+
ArrowUpRight = "arrow-up-right",
|
|
9
|
+
ArrowLeft = "arrow-left",
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const HUSPY_ICONS_CODEPOINTS: { [key in HuspyIcons]: string } = {
|
|
13
|
+
[HuspyIcons.IconSlot]: "61697",
|
|
14
|
+
[HuspyIcons.ArrowUpRight]: "61698",
|
|
15
|
+
[HuspyIcons.ArrowLeft]: "61699",
|
|
16
|
+
};
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/dist/native/index.d.ts
CHANGED
|
@@ -1,63 +1,47 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
+
import { TextProps } from 'react-native';
|
|
2
3
|
|
|
3
|
-
type IconSize = number | 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* Available icon names in the HuspyIcons font
|
|
6
6
|
*/
|
|
7
|
-
|
|
8
|
-
readonly xs: 8;
|
|
9
|
-
readonly sm: 12;
|
|
10
|
-
readonly md: 16;
|
|
11
|
-
readonly lg: 20;
|
|
12
|
-
readonly xl: 24;
|
|
13
|
-
};
|
|
7
|
+
type IconName = 'icon-slot' | 'arrow-up-right' | 'arrow-left';
|
|
14
8
|
/**
|
|
15
|
-
*
|
|
9
|
+
* Mapping of icon names to unicode codepoints
|
|
10
|
+
* Used by the Icon component to render the correct glyph
|
|
16
11
|
*/
|
|
17
|
-
|
|
12
|
+
declare const glyphMap: Record<IconName, number>;
|
|
18
13
|
/**
|
|
19
|
-
*
|
|
14
|
+
* Font family name for React Native
|
|
20
15
|
*/
|
|
21
|
-
|
|
22
|
-
size?: IconSize;
|
|
23
|
-
width?: number;
|
|
24
|
-
height?: number;
|
|
25
|
-
color?: string;
|
|
26
|
-
style?: any;
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Resolves an icon size to a numeric value
|
|
30
|
-
* @param size - Size value or token
|
|
31
|
-
* @returns Numeric size in pixels
|
|
32
|
-
*/
|
|
33
|
-
declare function resolveSize(size?: IconSize): number;
|
|
34
|
-
|
|
35
|
-
declare const SvgArrowLeft: ({ size, ...props }: NativeIconProps) => React.JSX.Element;
|
|
36
|
-
|
|
37
|
-
declare const SvgArrowUpRight: ({ size, ...props }: NativeIconProps) => React.JSX.Element;
|
|
16
|
+
declare const fontFamily = "HuspyIcons";
|
|
38
17
|
|
|
39
|
-
declare const SvgIconSlot: ({ size, ...props }: NativeIconProps) => React.JSX.Element;
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Icon imports - using dynamic imports for tree-shaking
|
|
43
|
-
* Auto-generated - do not edit manually
|
|
44
|
-
*/
|
|
45
|
-
/**
|
|
46
|
-
* Available icon names
|
|
47
|
-
*/
|
|
48
|
-
type IconName = 'arrow-left' | 'arrow-up-right' | 'icon-slot';
|
|
49
18
|
/**
|
|
50
|
-
* Props for the
|
|
19
|
+
* Props for the Icon component (React Native)
|
|
51
20
|
*/
|
|
52
|
-
interface IconProps extends Omit<
|
|
21
|
+
interface IconProps extends Omit<TextProps, 'children'> {
|
|
22
|
+
/**
|
|
23
|
+
* Name of the icon to display
|
|
24
|
+
*/
|
|
53
25
|
name: IconName;
|
|
54
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Size of the icon (default: 16)
|
|
28
|
+
*/
|
|
29
|
+
size?: number;
|
|
30
|
+
/**
|
|
31
|
+
* Color of the icon (default: inherits from parent or 'black')
|
|
32
|
+
*/
|
|
55
33
|
color?: string;
|
|
56
34
|
}
|
|
57
35
|
/**
|
|
58
|
-
*
|
|
59
|
-
*
|
|
36
|
+
* Icon component for React Native
|
|
37
|
+
*
|
|
38
|
+
* Renders icons using a custom font (HuspyIcons)
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```tsx
|
|
42
|
+
* <Icon name="arrow-left" size={24} color="#000" />
|
|
43
|
+
* ```
|
|
60
44
|
*/
|
|
61
|
-
declare const Icon: ({ name, size, color, ...props }: IconProps) => React.JSX.Element | null;
|
|
45
|
+
declare const Icon: ({ name, size, color, style, ...props }: IconProps) => React.JSX.Element | null;
|
|
62
46
|
|
|
63
|
-
export {
|
|
47
|
+
export { Icon, type IconName, type IconProps, fontFamily, glyphMap };
|
package/dist/native/index.js
CHANGED
|
@@ -5,9 +5,6 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __esm = (fn, res) => function __init() {
|
|
9
|
-
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
10
|
-
};
|
|
11
8
|
var __export = (target, all) => {
|
|
12
9
|
for (var name in all)
|
|
13
10
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -30,189 +27,64 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
30
27
|
));
|
|
31
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
32
29
|
|
|
33
|
-
// src/shared/types.ts
|
|
34
|
-
function resolveSize(size = "lg") {
|
|
35
|
-
if (typeof size === "number") {
|
|
36
|
-
return size;
|
|
37
|
-
}
|
|
38
|
-
return ICON_SIZES[size] ?? ICON_SIZES.lg;
|
|
39
|
-
}
|
|
40
|
-
var ICON_SIZES;
|
|
41
|
-
var init_types = __esm({
|
|
42
|
-
"src/shared/types.ts"() {
|
|
43
|
-
"use strict";
|
|
44
|
-
ICON_SIZES = {
|
|
45
|
-
xs: 8,
|
|
46
|
-
sm: 12,
|
|
47
|
-
md: 16,
|
|
48
|
-
lg: 20,
|
|
49
|
-
xl: 24
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
// src/native/ArrowLeft.tsx
|
|
55
|
-
var ArrowLeft_exports = {};
|
|
56
|
-
__export(ArrowLeft_exports, {
|
|
57
|
-
default: () => ArrowLeft_default
|
|
58
|
-
});
|
|
59
|
-
var React, import_react_native_svg, SvgArrowLeft, ArrowLeft_default;
|
|
60
|
-
var init_ArrowLeft = __esm({
|
|
61
|
-
"src/native/ArrowLeft.tsx"() {
|
|
62
|
-
"use strict";
|
|
63
|
-
React = __toESM(require("react"));
|
|
64
|
-
import_react_native_svg = __toESM(require("react-native-svg"));
|
|
65
|
-
init_types();
|
|
66
|
-
SvgArrowLeft = ({ size = 16, ...props }) => {
|
|
67
|
-
const sizeValue = resolveSize(size);
|
|
68
|
-
return /* @__PURE__ */ React.createElement(import_react_native_svg.default, { width: sizeValue, height: sizeValue, viewBox: "0 0 24 24", fill: "none", ...props }, /* @__PURE__ */ React.createElement(
|
|
69
|
-
import_react_native_svg.Path,
|
|
70
|
-
{
|
|
71
|
-
fillRule: "evenodd",
|
|
72
|
-
clipRule: "evenodd",
|
|
73
|
-
d: "M12.7071 4.29289C13.0976 4.68342 13.0976 5.31658 12.7071 5.70711L6.41421 12L12.7071 18.2929C13.0976 18.6834 13.0976 19.3166 12.7071 19.7071C12.3166 20.0976 11.6834 20.0976 11.2929 19.7071L4.29289 12.7071C3.90237 12.3166 3.90237 11.6834 4.29289 11.2929L11.2929 4.29289C11.6834 3.90237 12.3166 3.90237 12.7071 4.29289Z",
|
|
74
|
-
fill: "currentColor"
|
|
75
|
-
}
|
|
76
|
-
), /* @__PURE__ */ React.createElement(
|
|
77
|
-
import_react_native_svg.Path,
|
|
78
|
-
{
|
|
79
|
-
fillRule: "evenodd",
|
|
80
|
-
clipRule: "evenodd",
|
|
81
|
-
d: "M4 12C4 11.4477 4.44772 11 5 11H19C19.5523 11 20 11.4477 20 12C20 12.5523 19.5523 13 19 13H5C4.44772 13 4 12.5523 4 12Z",
|
|
82
|
-
fill: "currentColor"
|
|
83
|
-
}
|
|
84
|
-
));
|
|
85
|
-
};
|
|
86
|
-
ArrowLeft_default = SvgArrowLeft;
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
// src/native/ArrowUpRight.tsx
|
|
91
|
-
var ArrowUpRight_exports = {};
|
|
92
|
-
__export(ArrowUpRight_exports, {
|
|
93
|
-
default: () => ArrowUpRight_default
|
|
94
|
-
});
|
|
95
|
-
var React2, import_react_native_svg2, SvgArrowUpRight, ArrowUpRight_default;
|
|
96
|
-
var init_ArrowUpRight = __esm({
|
|
97
|
-
"src/native/ArrowUpRight.tsx"() {
|
|
98
|
-
"use strict";
|
|
99
|
-
React2 = __toESM(require("react"));
|
|
100
|
-
import_react_native_svg2 = __toESM(require("react-native-svg"));
|
|
101
|
-
init_types();
|
|
102
|
-
SvgArrowUpRight = ({ size = 16, ...props }) => {
|
|
103
|
-
const sizeValue = resolveSize(size);
|
|
104
|
-
return /* @__PURE__ */ React2.createElement(import_react_native_svg2.default, { width: sizeValue, height: sizeValue, viewBox: "0 0 24 24", fill: "none", ...props }, /* @__PURE__ */ React2.createElement(
|
|
105
|
-
import_react_native_svg2.Path,
|
|
106
|
-
{
|
|
107
|
-
fillRule: "evenodd",
|
|
108
|
-
clipRule: "evenodd",
|
|
109
|
-
d: "M6 7C6 6.44772 6.44772 6 7 6H17C17.5523 6 18 6.44772 18 7V17C18 17.5523 17.5523 18 17 18C16.4477 18 16 17.5523 16 17V8H7C6.44772 8 6 7.55228 6 7Z",
|
|
110
|
-
fill: "currentColor"
|
|
111
|
-
}
|
|
112
|
-
), /* @__PURE__ */ React2.createElement(
|
|
113
|
-
import_react_native_svg2.Path,
|
|
114
|
-
{
|
|
115
|
-
fillRule: "evenodd",
|
|
116
|
-
clipRule: "evenodd",
|
|
117
|
-
d: "M17.7071 6.29289C18.0976 6.68342 18.0976 7.31658 17.7071 7.70711L7.70711 17.7071C7.31658 18.0976 6.68342 18.0976 6.29289 17.7071C5.90237 17.3166 5.90237 16.6834 6.29289 16.2929L16.2929 6.29289C16.6834 5.90237 17.3166 5.90237 17.7071 6.29289Z",
|
|
118
|
-
fill: "currentColor"
|
|
119
|
-
}
|
|
120
|
-
));
|
|
121
|
-
};
|
|
122
|
-
ArrowUpRight_default = SvgArrowUpRight;
|
|
123
|
-
}
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
// src/native/IconSlot.tsx
|
|
127
|
-
var IconSlot_exports = {};
|
|
128
|
-
__export(IconSlot_exports, {
|
|
129
|
-
default: () => IconSlot_default
|
|
130
|
-
});
|
|
131
|
-
var React3, import_react_native_svg3, SvgIconSlot, IconSlot_default;
|
|
132
|
-
var init_IconSlot = __esm({
|
|
133
|
-
"src/native/IconSlot.tsx"() {
|
|
134
|
-
"use strict";
|
|
135
|
-
React3 = __toESM(require("react"));
|
|
136
|
-
import_react_native_svg3 = __toESM(require("react-native-svg"));
|
|
137
|
-
init_types();
|
|
138
|
-
SvgIconSlot = ({ size = 16, ...props }) => {
|
|
139
|
-
const sizeValue = resolveSize(size);
|
|
140
|
-
return /* @__PURE__ */ React3.createElement(import_react_native_svg3.default, { width: sizeValue, height: sizeValue, viewBox: "0 0 15 15", fill: "none", ...props }, /* @__PURE__ */ React3.createElement(
|
|
141
|
-
import_react_native_svg3.Path,
|
|
142
|
-
{
|
|
143
|
-
d: "M13.3333 7.33333C13.3333 4.01962 10.647 1.33333 7.33333 1.33333C4.01962 1.33333 1.33333 4.01962 1.33333 7.33333C1.33333 10.647 4.01962 13.3333 7.33333 13.3333C10.647 13.3333 13.3333 10.647 13.3333 7.33333ZM14.6667 7.33333C14.6667 11.3834 11.3834 14.6667 7.33333 14.6667C3.28325 14.6667 0 11.3834 0 7.33333C0 3.28325 3.28325 0 7.33333 0C11.3834 0 14.6667 3.28325 14.6667 7.33333Z",
|
|
144
|
-
fill: "currentColor"
|
|
145
|
-
}
|
|
146
|
-
));
|
|
147
|
-
};
|
|
148
|
-
IconSlot_default = SvgIconSlot;
|
|
149
|
-
}
|
|
150
|
-
});
|
|
151
|
-
|
|
152
30
|
// src/native/index.ts
|
|
153
31
|
var native_exports = {};
|
|
154
32
|
__export(native_exports, {
|
|
155
|
-
ArrowLeft: () => ArrowLeft_default,
|
|
156
|
-
ArrowUpRight: () => ArrowUpRight_default,
|
|
157
|
-
ICON_SIZES: () => ICON_SIZES,
|
|
158
33
|
Icon: () => Icon_default,
|
|
159
|
-
|
|
160
|
-
|
|
34
|
+
fontFamily: () => fontFamily,
|
|
35
|
+
glyphMap: () => glyphMap
|
|
161
36
|
});
|
|
162
37
|
module.exports = __toCommonJS(native_exports);
|
|
163
|
-
init_ArrowLeft();
|
|
164
|
-
init_ArrowUpRight();
|
|
165
|
-
init_IconSlot();
|
|
166
38
|
|
|
167
39
|
// src/native/Icon.tsx
|
|
168
|
-
var
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
setLoading(true);
|
|
187
|
-
setError(null);
|
|
188
|
-
loadIcon(name).then((Component) => {
|
|
189
|
-
setIconComponent(() => Component);
|
|
190
|
-
setLoading(false);
|
|
191
|
-
}).catch((err) => {
|
|
192
|
-
console.warn(err.message);
|
|
193
|
-
setError(err.message);
|
|
194
|
-
setLoading(false);
|
|
195
|
-
});
|
|
196
|
-
}, [name]);
|
|
197
|
-
if (loading) {
|
|
198
|
-
return null;
|
|
199
|
-
}
|
|
200
|
-
if (error || !IconComponent) {
|
|
40
|
+
var React = __toESM(require("react"));
|
|
41
|
+
var import_react_native = require("react-native");
|
|
42
|
+
|
|
43
|
+
// src/native/glyphMap.ts
|
|
44
|
+
var glyphMap = {
|
|
45
|
+
"icon-slot": 61697,
|
|
46
|
+
"arrow-up-right": 61698,
|
|
47
|
+
"arrow-left": 61699
|
|
48
|
+
};
|
|
49
|
+
var fontFamily = "HuspyIcons";
|
|
50
|
+
|
|
51
|
+
// src/native/Icon.tsx
|
|
52
|
+
var Icon = ({ name, size = 16, color = "#000", style, ...props }) => {
|
|
53
|
+
const codepoint = glyphMap[name];
|
|
54
|
+
if (!codepoint) {
|
|
55
|
+
if (__DEV__) {
|
|
56
|
+
console.warn(`Icon "${name}" not found in HuspyIcons font`);
|
|
57
|
+
}
|
|
201
58
|
return null;
|
|
202
59
|
}
|
|
203
|
-
|
|
60
|
+
const glyph = String.fromCharCode(codepoint);
|
|
61
|
+
return /* @__PURE__ */ React.createElement(
|
|
62
|
+
import_react_native.Text,
|
|
63
|
+
{
|
|
64
|
+
...props,
|
|
65
|
+
style: [
|
|
66
|
+
{
|
|
67
|
+
fontFamily,
|
|
68
|
+
fontSize: size,
|
|
69
|
+
color,
|
|
70
|
+
// Ensure icon doesn't inherit text styles
|
|
71
|
+
fontWeight: "normal",
|
|
72
|
+
fontStyle: "normal"
|
|
73
|
+
},
|
|
74
|
+
style
|
|
75
|
+
],
|
|
76
|
+
accessible: true,
|
|
77
|
+
accessibilityLabel: props.accessibilityLabel || name,
|
|
78
|
+
accessibilityRole: "image"
|
|
79
|
+
},
|
|
80
|
+
glyph
|
|
81
|
+
);
|
|
204
82
|
};
|
|
205
83
|
var Icon_default = Icon;
|
|
206
|
-
|
|
207
|
-
// src/native/index.ts
|
|
208
|
-
init_types();
|
|
209
84
|
// Annotate the CommonJS export names for ESM import in node:
|
|
210
85
|
0 && (module.exports = {
|
|
211
|
-
ArrowLeft,
|
|
212
|
-
ArrowUpRight,
|
|
213
|
-
ICON_SIZES,
|
|
214
86
|
Icon,
|
|
215
|
-
|
|
216
|
-
|
|
87
|
+
fontFamily,
|
|
88
|
+
glyphMap
|
|
217
89
|
});
|
|
218
90
|
//# sourceMappingURL=index.js.map
|
package/dist/native/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/
|
|
1
|
+
{"version":3,"sources":["../../src/native/index.ts","../../src/native/Icon.tsx","../../src/native/glyphMap.ts"],"sourcesContent":["/**\n * Huspy Icons - React Native (Font-based)\n * \n * This package provides icon components for React Native using a custom font.\n * \n * @example\n * ```tsx\n * import { Icon } from 'huspy-icons/native';\n * \n * function MyComponent() {\n * return <Icon name=\"arrow-left\" size={24} color=\"#000\" />;\n * }\n * ```\n */\n\nexport { default as Icon } from './Icon';\nexport type { IconProps, IconName } from './Icon';\nexport { glyphMap, fontFamily } from './glyphMap';\n\n","import * as React from 'react';\nimport { Text, TextProps, Platform } from 'react-native';\nimport { glyphMap, fontFamily, IconName } from './glyphMap';\n\n/**\n * Props for the Icon component (React Native)\n */\nexport interface IconProps extends Omit<TextProps, 'children'> {\n /**\n * Name of the icon to display\n */\n name: IconName;\n \n /**\n * Size of the icon (default: 16)\n */\n size?: number;\n \n /**\n * Color of the icon (default: inherits from parent or 'black')\n */\n color?: string;\n}\n\n/**\n * Icon component for React Native\n * \n * Renders icons using a custom font (HuspyIcons)\n * \n * @example\n * ```tsx\n * <Icon name=\"arrow-left\" size={24} color=\"#000\" />\n * ```\n */\nconst Icon = ({ name, size = 16, color = '#000', style, ...props }: IconProps) => {\n const codepoint = glyphMap[name];\n \n if (!codepoint) {\n if (__DEV__) {\n console.warn(`Icon \"${name}\" not found in HuspyIcons font`);\n }\n return null;\n }\n \n // Convert codepoint to character\n const glyph = String.fromCharCode(codepoint);\n \n return (\n <Text\n {...props}\n style={[\n {\n fontFamily: fontFamily,\n fontSize: size,\n color: color,\n // Ensure icon doesn't inherit text styles\n fontWeight: 'normal',\n fontStyle: 'normal',\n },\n style,\n ]}\n // Accessibility\n accessible\n accessibilityLabel={props.accessibilityLabel || name}\n accessibilityRole=\"image\"\n >\n {glyph}\n </Text>\n );\n};\n\nexport default Icon;\nexport type { IconName };\n\n","// Auto-generated by generate-font.js - do not edit manually\n// Source: icons-src/*.svg → dist/fonts/HuspyIcons.*\n\n/**\n * Available icon names in the HuspyIcons font\n */\nexport type IconName = 'icon-slot' | 'arrow-up-right' | 'arrow-left';\n\n/**\n * Mapping of icon names to unicode codepoints\n * Used by the Icon component to render the correct glyph\n */\nexport const glyphMap: Record<IconName, number> = {\n \"icon-slot\": 61697,\n \"arrow-up-right\": 61698,\n \"arrow-left\": 61699\n};\n\n/**\n * Font family name for React Native\n */\nexport const fontFamily = 'HuspyIcons';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,YAAuB;AACvB,0BAA0C;;;ACWnC,IAAM,WAAqC;AAAA,EAChD,aAAa;AAAA,EACb,kBAAkB;AAAA,EAClB,cAAc;AAChB;AAKO,IAAM,aAAa;;;ADa1B,IAAM,OAAO,CAAC,EAAE,MAAM,OAAO,IAAI,QAAQ,QAAQ,OAAO,GAAG,MAAM,MAAiB;AAChF,QAAM,YAAY,SAAS,IAAI;AAE/B,MAAI,CAAC,WAAW;AACd,QAAI,SAAS;AACX,cAAQ,KAAK,SAAS,IAAI,gCAAgC;AAAA,IAC5D;AACA,WAAO;AAAA,EACT;AAGA,QAAM,QAAQ,OAAO,aAAa,SAAS;AAE3C,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ,OAAO;AAAA,QACL;AAAA,UACE;AAAA,UACA,UAAU;AAAA,UACV;AAAA;AAAA,UAEA,YAAY;AAAA,UACZ,WAAW;AAAA,QACb;AAAA,QACA;AAAA,MACF;AAAA,MAEA,YAAU;AAAA,MACV,oBAAoB,MAAM,sBAAsB;AAAA,MAChD,mBAAkB;AAAA;AAAA,IAEjB;AAAA,EACH;AAEJ;AAEA,IAAO,eAAQ;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "huspy-icons",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Cross-platform icon package for Huspy - React and React Native compatible",
|
|
5
5
|
"author": "Huspy",
|
|
6
6
|
"license": "MIT",
|
|
@@ -32,12 +32,14 @@
|
|
|
32
32
|
},
|
|
33
33
|
"files": [
|
|
34
34
|
"dist",
|
|
35
|
-
"src"
|
|
35
|
+
"src",
|
|
36
|
+
"README.md",
|
|
37
|
+
"LICENSE"
|
|
36
38
|
],
|
|
37
39
|
"scripts": {
|
|
38
40
|
"svgo": "svgo -f icons-src -o icons-src --config=svgo.config.js",
|
|
39
41
|
"gen:react": "svgr icons-src -d src/react --ext tsx --typescript --icon && node scripts/add-size-prop.js --react",
|
|
40
|
-
"gen:native": "
|
|
42
|
+
"gen:native": "node scripts/generate-font.js",
|
|
41
43
|
"gen:types": "node scripts/generate-types.js",
|
|
42
44
|
"gen": "npm run svgo && npm run gen:react && npm run gen:native && npm run gen:types",
|
|
43
45
|
"build": "tsup",
|
|
@@ -51,21 +53,18 @@
|
|
|
51
53
|
"@types/react": "^18.2.48",
|
|
52
54
|
"@types/react-native": "^0.73.0",
|
|
53
55
|
"esbuild": "^0.19.11",
|
|
56
|
+
"fantasticon": "^3.0.0",
|
|
54
57
|
"svgo": "^3.3.2",
|
|
55
58
|
"tsup": "^8.0.1",
|
|
56
59
|
"typescript": "^5.3.3"
|
|
57
60
|
},
|
|
58
61
|
"peerDependencies": {
|
|
59
62
|
"react": ">=16.8.0",
|
|
60
|
-
"react-native": ">=0.73.0"
|
|
61
|
-
"react-native-svg": "^15.14.0"
|
|
63
|
+
"react-native": ">=0.73.0"
|
|
62
64
|
},
|
|
63
65
|
"peerDependenciesMeta": {
|
|
64
66
|
"react-native": {
|
|
65
67
|
"optional": true
|
|
66
|
-
},
|
|
67
|
-
"react-native-svg": {
|
|
68
|
-
"optional": true
|
|
69
68
|
}
|
|
70
69
|
},
|
|
71
70
|
"publishConfig": {
|
package/src/native/Icon.tsx
CHANGED
|
@@ -1,80 +1,74 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import
|
|
2
|
+
import { Text, TextProps, Platform } from 'react-native';
|
|
3
|
+
import { glyphMap, fontFamily, IconName } from './glyphMap';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
|
-
*
|
|
6
|
-
* Auto-generated - do not edit manually
|
|
6
|
+
* Props for the Icon component (React Native)
|
|
7
7
|
*/
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Available icon names
|
|
14
|
-
*/
|
|
15
|
-
export type IconName = 'arrow-left' | 'arrow-up-right' | 'icon-slot';
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Props for the unified Icon component (React Native)
|
|
19
|
-
*/
|
|
20
|
-
export interface IconProps extends Omit<NativeIconProps, 'size'> {
|
|
8
|
+
export interface IconProps extends Omit<TextProps, 'children'> {
|
|
9
|
+
/**
|
|
10
|
+
* Name of the icon to display
|
|
11
|
+
*/
|
|
21
12
|
name: IconName;
|
|
22
|
-
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Size of the icon (default: 16)
|
|
16
|
+
*/
|
|
17
|
+
size?: number;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Color of the icon (default: inherits from parent or 'black')
|
|
21
|
+
*/
|
|
23
22
|
color?: string;
|
|
24
23
|
}
|
|
25
24
|
|
|
26
25
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
case 'arrow-up-right':
|
|
36
|
-
return import('./ArrowUpRight').then(m => m.default);
|
|
37
|
-
case 'icon-slot':
|
|
38
|
-
return import('./IconSlot').then(m => m.default);
|
|
39
|
-
default:
|
|
40
|
-
return Promise.reject(new Error(`Icon "${name}" not found`));
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Unified Icon component that renders icons by name (React Native)
|
|
46
|
-
* Uses dynamic imports for tree-shaking support
|
|
26
|
+
* Icon component for React Native
|
|
27
|
+
*
|
|
28
|
+
* Renders icons using a custom font (HuspyIcons)
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```tsx
|
|
32
|
+
* <Icon name="arrow-left" size={24} color="#000" />
|
|
33
|
+
* ```
|
|
47
34
|
*/
|
|
48
|
-
const Icon = ({ name, size = 16, color, ...props }: IconProps) => {
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
setError(null);
|
|
56
|
-
|
|
57
|
-
loadIcon(name)
|
|
58
|
-
.then((Component) => {
|
|
59
|
-
setIconComponent(() => Component);
|
|
60
|
-
setLoading(false);
|
|
61
|
-
})
|
|
62
|
-
.catch((err) => {
|
|
63
|
-
console.warn(err.message);
|
|
64
|
-
setError(err.message);
|
|
65
|
-
setLoading(false);
|
|
66
|
-
});
|
|
67
|
-
}, [name]);
|
|
68
|
-
|
|
69
|
-
if (loading) {
|
|
35
|
+
const Icon = ({ name, size = 16, color = '#000', style, ...props }: IconProps) => {
|
|
36
|
+
const codepoint = glyphMap[name];
|
|
37
|
+
|
|
38
|
+
if (!codepoint) {
|
|
39
|
+
if (__DEV__) {
|
|
40
|
+
console.warn(`Icon "${name}" not found in HuspyIcons font`);
|
|
41
|
+
}
|
|
70
42
|
return null;
|
|
71
43
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
44
|
+
|
|
45
|
+
// Convert codepoint to character
|
|
46
|
+
const glyph = String.fromCharCode(codepoint);
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<Text
|
|
50
|
+
{...props}
|
|
51
|
+
style={[
|
|
52
|
+
{
|
|
53
|
+
fontFamily: fontFamily,
|
|
54
|
+
fontSize: size,
|
|
55
|
+
color: color,
|
|
56
|
+
// Ensure icon doesn't inherit text styles
|
|
57
|
+
fontWeight: 'normal',
|
|
58
|
+
fontStyle: 'normal',
|
|
59
|
+
},
|
|
60
|
+
style,
|
|
61
|
+
]}
|
|
62
|
+
// Accessibility
|
|
63
|
+
accessible
|
|
64
|
+
accessibilityLabel={props.accessibilityLabel || name}
|
|
65
|
+
accessibilityRole="image"
|
|
66
|
+
>
|
|
67
|
+
{glyph}
|
|
68
|
+
</Text>
|
|
69
|
+
);
|
|
78
70
|
};
|
|
79
71
|
|
|
80
|
-
export default Icon;
|
|
72
|
+
export default Icon;
|
|
73
|
+
export type { IconName };
|
|
74
|
+
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Auto-generated by generate-font.js - do not edit manually
|
|
2
|
+
// Source: icons-src/*.svg → dist/fonts/HuspyIcons.*
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Available icon names in the HuspyIcons font
|
|
6
|
+
*/
|
|
7
|
+
export type IconName = 'icon-slot' | 'arrow-up-right' | 'arrow-left';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Mapping of icon names to unicode codepoints
|
|
11
|
+
* Used by the Icon component to render the correct glyph
|
|
12
|
+
*/
|
|
13
|
+
export const glyphMap: Record<IconName, number> = {
|
|
14
|
+
"icon-slot": 61697,
|
|
15
|
+
"arrow-up-right": 61698,
|
|
16
|
+
"arrow-left": 61699
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Font family name for React Native
|
|
21
|
+
*/
|
|
22
|
+
export const fontFamily = 'HuspyIcons';
|
package/src/native/index.ts
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Huspy Icons - React Native (Font-based)
|
|
3
|
+
*
|
|
4
|
+
* This package provides icon components for React Native using a custom font.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```tsx
|
|
8
|
+
* import { Icon } from 'huspy-icons/native';
|
|
9
|
+
*
|
|
10
|
+
* function MyComponent() {
|
|
11
|
+
* return <Icon name="arrow-left" size={24} color="#000" />;
|
|
12
|
+
* }
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
5
15
|
|
|
6
|
-
// Unified Icon component
|
|
7
16
|
export { default as Icon } from './Icon';
|
|
8
|
-
export type {
|
|
17
|
+
export type { IconProps, IconName } from './Icon';
|
|
18
|
+
export { glyphMap, fontFamily } from './glyphMap';
|
|
9
19
|
|
|
10
|
-
// Export types
|
|
11
|
-
export type {
|
|
12
|
-
IconSize,
|
|
13
|
-
IconSizeToken,
|
|
14
|
-
NativeIconProps,
|
|
15
|
-
} from '../shared/types';
|
|
16
|
-
|
|
17
|
-
export { ICON_SIZES, resolveSize } from '../shared/types';
|
package/src/native/ArrowLeft.tsx
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import Svg, { Path } from 'react-native-svg';
|
|
3
|
-
import type { NativeIconProps } from '../shared/types';
|
|
4
|
-
import { resolveSize } from '../shared/types';
|
|
5
|
-
|
|
6
|
-
const SvgArrowLeft = ({ size = 16, ...props }: NativeIconProps) => {
|
|
7
|
-
const sizeValue = resolveSize(size);
|
|
8
|
-
|
|
9
|
-
return (
|
|
10
|
-
<Svg width={sizeValue} height={sizeValue} viewBox="0 0 24 24" fill="none" {...props}>
|
|
11
|
-
<Path
|
|
12
|
-
fillRule="evenodd"
|
|
13
|
-
clipRule="evenodd"
|
|
14
|
-
d="M12.7071 4.29289C13.0976 4.68342 13.0976 5.31658 12.7071 5.70711L6.41421 12L12.7071 18.2929C13.0976 18.6834 13.0976 19.3166 12.7071 19.7071C12.3166 20.0976 11.6834 20.0976 11.2929 19.7071L4.29289 12.7071C3.90237 12.3166 3.90237 11.6834 4.29289 11.2929L11.2929 4.29289C11.6834 3.90237 12.3166 3.90237 12.7071 4.29289Z"
|
|
15
|
-
fill="currentColor"
|
|
16
|
-
/>
|
|
17
|
-
<Path
|
|
18
|
-
fillRule="evenodd"
|
|
19
|
-
clipRule="evenodd"
|
|
20
|
-
d="M4 12C4 11.4477 4.44772 11 5 11H19C19.5523 11 20 11.4477 20 12C20 12.5523 19.5523 13 19 13H5C4.44772 13 4 12.5523 4 12Z"
|
|
21
|
-
fill="currentColor"
|
|
22
|
-
/>
|
|
23
|
-
</Svg>
|
|
24
|
-
);
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
export default SvgArrowLeft;
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import Svg, { Path } from 'react-native-svg';
|
|
3
|
-
import type { NativeIconProps } from '../shared/types';
|
|
4
|
-
import { resolveSize } from '../shared/types';
|
|
5
|
-
|
|
6
|
-
const SvgArrowUpRight = ({ size = 16, ...props }: NativeIconProps) => {
|
|
7
|
-
const sizeValue = resolveSize(size);
|
|
8
|
-
|
|
9
|
-
return (
|
|
10
|
-
<Svg width={sizeValue} height={sizeValue} viewBox="0 0 24 24" fill="none" {...props}>
|
|
11
|
-
<Path
|
|
12
|
-
fillRule="evenodd"
|
|
13
|
-
clipRule="evenodd"
|
|
14
|
-
d="M6 7C6 6.44772 6.44772 6 7 6H17C17.5523 6 18 6.44772 18 7V17C18 17.5523 17.5523 18 17 18C16.4477 18 16 17.5523 16 17V8H7C6.44772 8 6 7.55228 6 7Z"
|
|
15
|
-
fill="currentColor"
|
|
16
|
-
/>
|
|
17
|
-
<Path
|
|
18
|
-
fillRule="evenodd"
|
|
19
|
-
clipRule="evenodd"
|
|
20
|
-
d="M17.7071 6.29289C18.0976 6.68342 18.0976 7.31658 17.7071 7.70711L7.70711 17.7071C7.31658 18.0976 6.68342 18.0976 6.29289 17.7071C5.90237 17.3166 5.90237 16.6834 6.29289 16.2929L16.2929 6.29289C16.6834 5.90237 17.3166 5.90237 17.7071 6.29289Z"
|
|
21
|
-
fill="currentColor"
|
|
22
|
-
/>
|
|
23
|
-
</Svg>
|
|
24
|
-
);
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
export default SvgArrowUpRight;
|
package/src/native/IconSlot.tsx
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import Svg, { Path } from 'react-native-svg';
|
|
3
|
-
import type { NativeIconProps } from '../shared/types';
|
|
4
|
-
import { resolveSize } from '../shared/types';
|
|
5
|
-
|
|
6
|
-
const SvgIconSlot = ({ size = 16, ...props }: NativeIconProps) => {
|
|
7
|
-
const sizeValue = resolveSize(size);
|
|
8
|
-
|
|
9
|
-
return (
|
|
10
|
-
<Svg width={sizeValue} height={sizeValue} viewBox="0 0 15 15" fill="none" {...props}>
|
|
11
|
-
<Path
|
|
12
|
-
d="M13.3333 7.33333C13.3333 4.01962 10.647 1.33333 7.33333 1.33333C4.01962 1.33333 1.33333 4.01962 1.33333 7.33333C1.33333 10.647 4.01962 13.3333 7.33333 13.3333C10.647 13.3333 13.3333 10.647 13.3333 7.33333ZM14.6667 7.33333C14.6667 11.3834 11.3834 14.6667 7.33333 14.6667C3.28325 14.6667 0 11.3834 0 7.33333C0 3.28325 3.28325 0 7.33333 0C11.3834 0 14.6667 3.28325 14.6667 7.33333Z"
|
|
13
|
-
fill="currentColor"
|
|
14
|
-
/>
|
|
15
|
-
</Svg>
|
|
16
|
-
);
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export default SvgIconSlot;
|
package/src/native/index.tsx
DELETED