@editora/react-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,229 @@
1
+ # @editora/react-icons
2
+
3
+ React icon components and theming context for `@editora/icons`.
4
+
5
+ `@editora/react-icons` gives you:
6
+ - a generic `<Icon name="...">` renderer,
7
+ - named React icon components (e.g. `CheckIcon`, `ChartLineIcon`),
8
+ - shared defaults via `IconProvider`,
9
+ - type-safe icon names via `IconName`.
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ npm install @editora/react-icons @editora/icons
15
+ ```
16
+
17
+ Peer dependencies:
18
+ - `react` `^16.8 || ^17 || ^18 || ^19`
19
+
20
+ ## Quick Start
21
+
22
+ ```tsx
23
+ import { IconProvider, Icon, CheckIcon, ChartLineIcon } from '@editora/react-icons';
24
+
25
+ export function Example() {
26
+ return (
27
+ <IconProvider
28
+ value={{
29
+ variant: 'outline',
30
+ size: 18,
31
+ color: 'var(--ui-fg)',
32
+ strokeWidth: 1.5
33
+ }}
34
+ >
35
+ <CheckIcon ariaLabel="Saved" />
36
+ <ChartLineIcon variant="duotone" secondaryColor="var(--ui-muted)" />
37
+ <Icon name="command" title="Command palette" />
38
+ </IconProvider>
39
+ );
40
+ }
41
+ ```
42
+
43
+ ## Exported API
44
+
45
+ ### Core components
46
+ - `Icon`
47
+ - `IconProvider`
48
+ - `IconContext`
49
+ - `useIconContext()`
50
+ - `defaultIconContext`
51
+
52
+ ### Lookup and helpers
53
+ - `icons` / `Icons` map (`Record<IconName, IconComponent>`)
54
+ - `iconNames` (`IconName[]`)
55
+ - `getIconComponent(name)`
56
+ - `createIcon(name, displayName?)`
57
+
58
+ ### Named icons
59
+ All generated named exports from `src/icons.tsx`, for example:
60
+ - `CheckIcon`, `XIcon`, `SearchIcon`, `ChartBarIcon`, `CalendarIcon`, `SettingsIcon`, `CommandIcon`, and many more.
61
+
62
+ ### Type exports
63
+ - `IconName`
64
+ - `IconProps`
65
+ - `NamedIconProps`
66
+ - `IconContextValue`
67
+ - `IconComponent`
68
+ - `IconFlip`
69
+ - `IconBaseProps`
70
+
71
+ ## `Icon` Props
72
+
73
+ `Icon` accepts standard SVG props plus icon-specific props:
74
+
75
+ | Prop | Type | Default | Notes |
76
+ |---|---|---|---|
77
+ | `name` | `IconName \| string` | required | Icon key from `@editora/icons`. |
78
+ | `variant` | `'outline' \| 'solid' \| 'duotone'` | `'outline'` | Glyph variant. |
79
+ | `size` | `number \| string` | `15` | Sets `width` and `height`. |
80
+ | `color` | `string` | `'currentColor'` | Primary icon color. |
81
+ | `secondaryColor` | `string` | `color` | Used by duotone secondary paths. |
82
+ | `strokeWidth` | `number` | `1.5` | Stroke thickness for stroked paths. |
83
+ | `absoluteStrokeWidth` | `boolean` | `false` | Keeps visual stroke thickness stable across icon sizes. |
84
+ | `strokeLinecap` | `'butt' \| 'round' \| 'square'` | `'round'` | Applied when stroke exists. |
85
+ | `strokeLinejoin` | `'miter' \| 'round' \| 'bevel'` | `'round'` | Applied when stroke exists. |
86
+ | `decorative` | `boolean` | inferred | If `true`, icon is hidden from AT. |
87
+ | `title` | `string` | `undefined` | Adds `<title>` and accessible name fallback. |
88
+ | `ariaLabel` | `string` | `undefined` | Explicit accessible label. |
89
+ | `rotate` | `number` | `0` | Degrees around icon center. |
90
+ | `flip` | `'horizontal' \| 'vertical' \| 'both'` | `undefined` | Geometric flip transform. |
91
+ | `rtl` | `boolean` | `false` | Mirrors icons marked `rtlMirror` in RTL contexts. |
92
+
93
+ If an icon name cannot be resolved, `Icon` returns `null`.
94
+
95
+ ## `IconProvider` (Shared Defaults)
96
+
97
+ `IconProvider` merges with parent context, so nested providers work as expected.
98
+
99
+ ```tsx
100
+ import { IconProvider, SearchIcon, SettingsIcon } from '@editora/react-icons';
101
+
102
+ export function HeaderActions() {
103
+ return (
104
+ <IconProvider value={{ size: 16, color: 'var(--color-fg-muted)' }}>
105
+ <SearchIcon ariaLabel="Search" />
106
+ <IconProvider value={{ color: 'var(--color-primary)' }}>
107
+ <SettingsIcon ariaLabel="Settings" />
108
+ </IconProvider>
109
+ </IconProvider>
110
+ );
111
+ }
112
+ ```
113
+
114
+ Default context values:
115
+ - `variant: 'outline'`
116
+ - `size: 15`
117
+ - `color: 'currentColor'`
118
+ - `secondaryColor: 'currentColor'`
119
+ - `strokeWidth: 1.5`
120
+ - `strokeLinecap: 'round'`
121
+ - `strokeLinejoin: 'round'`
122
+
123
+ ## Usage Patterns
124
+
125
+ ### 1) Named icon imports (best tree-shaking)
126
+
127
+ ```tsx
128
+ import { CheckIcon, AlertTriangleIcon } from '@editora/react-icons';
129
+
130
+ export function Status({ ok }: { ok: boolean }) {
131
+ return ok ? <CheckIcon ariaLabel="Healthy" /> : <AlertTriangleIcon ariaLabel="Warning" />;
132
+ }
133
+ ```
134
+
135
+ ### 2) Dynamic icon rendering from string names
136
+
137
+ ```tsx
138
+ import { Icon, type IconName } from '@editora/react-icons';
139
+
140
+ type Item = { label: string; icon: IconName };
141
+
142
+ const items: Item[] = [
143
+ { label: 'Dashboard', icon: 'dashboard' },
144
+ { label: 'Orders', icon: 'order' },
145
+ { label: 'Reports', icon: 'report' }
146
+ ];
147
+
148
+ export function Sidebar() {
149
+ return (
150
+ <ul>
151
+ {items.map((item) => (
152
+ <li key={item.label}>
153
+ <Icon name={item.icon} aria-hidden size={16} />
154
+ <span>{item.label}</span>
155
+ </li>
156
+ ))}
157
+ </ul>
158
+ );
159
+ }
160
+ ```
161
+
162
+ ### 3) Runtime lookup for plugin-like UIs
163
+
164
+ ```tsx
165
+ import { getIconComponent, type IconName } from '@editora/react-icons';
166
+
167
+ export function PluginIcon({ name }: { name: IconName }) {
168
+ const Comp = getIconComponent(name);
169
+ return <Comp size={18} aria-hidden />;
170
+ }
171
+ ```
172
+
173
+ ### 4) Create custom named wrappers
174
+
175
+ ```tsx
176
+ import { createIcon } from '@editora/react-icons';
177
+
178
+ export const BillingIcon = createIcon('invoice', 'BillingIcon');
179
+ ```
180
+
181
+ ## Accessibility
182
+
183
+ - For decorative icons, use `aria-hidden` or leave `title`/`ariaLabel` unset (decorative mode is inferred).
184
+ - For meaningful icons, provide `ariaLabel` or `title`.
185
+ - Icons render with `role="img"` when semantic and `role="presentation"` when decorative.
186
+
187
+ Examples:
188
+
189
+ ```tsx
190
+ <CheckIcon aria-hidden />
191
+ <CheckIcon ariaLabel="Saved successfully" />
192
+ <Icon name="alert-circle" title="Validation error" />
193
+ ```
194
+
195
+ ## Theming
196
+
197
+ The library is `currentColor`-first. Prefer CSS tokens/classes instead of hardcoded colors.
198
+
199
+ ```tsx
200
+ <IconProvider value={{ color: 'var(--ui-fg)', secondaryColor: 'var(--ui-fg-muted)' }}>
201
+ <Icon name="chart-pie" variant="duotone" />
202
+ </IconProvider>
203
+ ```
204
+
205
+ ## Performance Notes
206
+
207
+ - Prefer named imports for static icon usage.
208
+ - Use dynamic `Icon name="..."` when icon names are data-driven.
209
+ - `@editora/react-icons` has `"sideEffects": false` for better tree-shaking.
210
+
211
+ ## Development
212
+
213
+ ```bash
214
+ cd packages/react-icons
215
+ npm run build
216
+ ```
217
+
218
+ Build notes:
219
+ - `build` and `build:tsc` run `@editora/icons` type build first.
220
+
221
+ ## Troubleshooting
222
+
223
+ - Missing icon output:
224
+ - Verify icon name exists in `iconNames`.
225
+ - Check spelling for dynamic names from API/CMS data.
226
+ - Icon appears but not semantic to screen readers:
227
+ - Provide `ariaLabel` or `title` for meaningful usage.
228
+ - Stroke thickness looks inconsistent across sizes:
229
+ - Try `absoluteStrokeWidth`.
package/dist/Icon.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+ import type { IconProps } from './types';
3
+ export declare const Icon: React.ForwardRefExoticComponent<Omit<IconProps, "ref"> & React.RefAttributes<SVGSVGElement>>;
4
+ export default Icon;
5
+ //# sourceMappingURL=Icon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Icon.d.ts","sourceRoot":"","sources":["../src/Icon.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAsHzC,eAAO,MAAM,IAAI,8FA2Ff,CAAC;AAIH,eAAe,IAAI,CAAC"}
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import type { IconContextValue } from './types';
3
+ declare const defaultIconContext: IconContextValue;
4
+ declare const IconContext: React.Context<IconContextValue>;
5
+ export type IconProviderProps = {
6
+ value?: IconContextValue;
7
+ children?: React.ReactNode;
8
+ };
9
+ export declare function IconProvider({ value, children }: IconProviderProps): JSX.Element;
10
+ export declare function useIconContext(): IconContextValue;
11
+ export { IconContext, defaultIconContext };
12
+ //# sourceMappingURL=IconContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IconContext.d.ts","sourceRoot":"","sources":["../src/IconContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhD,QAAA,MAAM,kBAAkB,EAAE,gBAQzB,CAAC;AAEF,QAAA,MAAM,WAAW,iCAA4D,CAAC;AAE9E,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,CAAC;AAEF,wBAAgB,YAAY,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,iBAAiB,GAAG,GAAG,CAAC,OAAO,CAShF;AAED,wBAAgB,cAAc,IAAI,gBAAgB,CAEjD;AAED,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { IconComponent } from './types';
2
+ export declare function createIcon(name: string, displayName?: string): IconComponent;
3
+ //# sourceMappingURL=createIcon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createIcon.d.ts","sourceRoot":"","sources":["../src/createIcon.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAkB,MAAM,SAAS,CAAC;AAE7D,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,aAAa,CAO5E"}