@qeetrix/icons 1.0.7 โ†’ 1.0.8

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.
Files changed (2) hide show
  1. package/README.md +219 -117
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,14 +1,16 @@
1
1
  <div align="center">
2
2
 
3
- # Qeetrix Icons
3
+ # ๐ŸŽจ Qeetrix Icons
4
4
 
5
5
  **The icon and brand logo library for Qeet Group products.**
6
6
 
7
- 1,863 Lucide icons in round and sharp shapes, 794 filled variants, and 7,429 brand logos, as
8
- tree-shakeable, fully typed React 19 components, all from one import.
7
+ 1,863 Lucide icons in **round** and **sharp** shapes, **775 filled** variants, and **7,429 brand
8
+ logos**, as tree-shakeable, fully typed React 19 components, all from one import.
9
9
 
10
+ [![npm](https://img.shields.io/npm/v/@qeetrix/icons?style=flat-square&color=111111&label=npm)](https://www.npmjs.com/package/@qeetrix/icons)
11
+ [![CI](https://img.shields.io/github/actions/workflow/status/qeetgroup/qeetrix-icons/ci.yml?branch=main&style=flat-square&label=CI)](https://github.com/qeetgroup/qeetrix-icons/actions/workflows/ci.yml)
10
12
  ![Icons](https://img.shields.io/badge/icons-1%2C863-111111?style=flat-square)
11
- ![Filled](https://img.shields.io/badge/filled-794-111111?style=flat-square)
13
+ ![Filled](https://img.shields.io/badge/filled-775-111111?style=flat-square)
12
14
  ![Shapes](https://img.shields.io/badge/shapes-round%20%C2%B7%20sharp-111111?style=flat-square)
13
15
  ![Logos](https://img.shields.io/badge/brand%20logos-7%2C429-111111?style=flat-square)
14
16
  ![React](https://img.shields.io/badge/React-19-149ECA?style=flat-square&logo=react&logoColor=white)
@@ -28,72 +30,103 @@ import { TrashIcon, StarIcon, GithubLogo } from "@qeetrix/icons";
28
30
  ```
29
31
 
30
32
  > [!IMPORTANT]
31
- > **2.0 is unreleased.** It replaces the 1.x catalogue entirely: do not rely on any 1.x icon name,
32
- > prop, type, or import path. Versions already published to the registry are unchanged, and the
33
- > package version stays `1.0.4` until the major release (see [Releases](#releases)).
33
+ > **Versions 1.0.5 and later are a new library.** They replace the 1.0.0โ€“1.0.4 catalogue entirely
34
+ > with Lucide-based icons and brand logos. No earlier icon name, prop, type, or import path carries
35
+ > over. If you depend on the old set, pin `@qeetrix/icons@1.0.4` until you migrate.
34
36
 
35
37
  ---
36
38
 
37
- ## Contents
38
-
39
- - [Why Qeetrix Icons](#why-qeetrix-icons)
40
- - [At a glance](#at-a-glance)
41
- - [Installation](#installation)
42
- - [Icons](#icons)
43
- - [Brand logos](#brand-logos)
44
- - [Catalogue and search](#catalogue-and-search)
45
- - [Playground](#playground)
46
- - [Performance](#performance)
47
- - [How it is built](#how-it-is-built)
48
- - [Development](#development)
49
- - [Documentation](#documentation)
50
- - [Releases](#releases)
51
- - [License](#license)
52
-
53
- ## Why Qeetrix Icons
39
+ ## ๐Ÿ“‘ Contents
40
+
41
+ - [โœจ Why Qeetrix Icons](#-why-qeetrix-icons)
42
+ - [๐Ÿ“Š At a glance](#-at-a-glance)
43
+ - [๐Ÿ“ฆ Installation](#-installation)
44
+ - [๐Ÿš€ Quick start](#-quick-start)
45
+ - [๐ŸŽจ Icons](#-icons)
46
+ - [๐Ÿท๏ธ Brand logos](#๏ธ-brand-logos)
47
+ - [๐Ÿ”Ž Catalogue and search](#-catalogue-and-search)
48
+ - [๐Ÿ” Coming from lucide-react](#-coming-from-lucide-react)
49
+ - [๐Ÿ“ Design rules](#-design-rules)
50
+ - [๐Ÿงช Playground](#-playground)
51
+ - [โšก Performance and package size](#-performance-and-package-size)
52
+ - [๐Ÿ—๏ธ How it is built](#๏ธ-how-it-is-built)
53
+ - [โœ… Quality](#-quality)
54
+ - [๐Ÿ› ๏ธ Development](#๏ธ-development)
55
+ - [๐Ÿ“š Documentation](#-documentation)
56
+ - [๐Ÿšข Releases](#-releases)
57
+ - [โš–๏ธ License](#๏ธ-license)
58
+
59
+ ## โœจ Why Qeetrix Icons
54
60
 
55
61
  [Lucide](https://lucide.dev) is a superb outline icon set, and [theSVG](https://thesvg.org)
56
62
  collects thousands of brand logos. Qeetrix Icons turns them into one consistent, typed library for
57
63
  every Qeet product (Qeet ID, Qeet Pay, Qeet Logs, Qeet Notify, Qeet People, Qeet AI) and adds what
58
64
  neither provides:
59
65
 
60
- - **Filled variants.** Lucide is outline-only. 794 icons gain a filled drawing for selected,
66
+ - ๐ŸŒ“ **Filled variants.** Lucide is outline-only. 775 icons gain a filled drawing for selected,
61
67
  active, and favourite states, derived from the outline with Skia path operations and reviewed
62
- one by one.
63
- - **A complete sharp style.** Every icon, outline and filled, also comes with square caps,
68
+ one by one, category by category.
69
+ - ๐Ÿ”ท **A complete sharp style.** Every icon, outline and filled, also comes with square caps,
64
70
  mitered joins, and squared corners, behind a single `shape` prop.
65
- - **One API for everything.** Icons and logos share naming, sizing, accessibility defaults, and
71
+ - ๐Ÿงฉ **One API for everything.** Icons and logos share naming, sizing, accessibility defaults, and
66
72
  typing. A `variant` the icon or logo doesn't have is a compile-time error.
67
- - **Logos you can trust.** Every logo is embedded byte for byte as published, validated for
73
+ - ๐Ÿ›ก๏ธ **Logos you can trust.** Every logo is embedded byte for byte as published, validated for
68
74
  safety, labelled with the background it is drawn for, and carries its own license metadata.
69
- - **Searchable catalogues.** Tags, categories, Lucide's former names, RTL behaviour, logo
75
+ - ๐Ÿ”Ž **Searchable catalogues.** Tags, categories, Lucide's former names, RTL behaviour, logo
70
76
  collections, colours, and licenses, published as data for docs sites and pickers.
77
+ - ๐ŸŒฒ **Zero runtime cost you didn't ask for.** No runtime dependencies, no hooks, no side
78
+ effects: bundlers keep only the icons and logos you import.
71
79
 
72
- ## At a glance
80
+ ## ๐Ÿ“Š At a glance
73
81
 
74
82
  | | |
75
83
  |:--|:--|
76
- | **Icons** | 1,863 from Lucide 1.52.0, in 42 categories, with Lucide's names and tags |
77
- | **Shapes** | `round` (Lucide's drawing, the default) and `sharp`, for every icon |
78
- | **Variants** | `outline` for every icon; `filled` for 794 |
79
- | **Brand logos** | 7,429 from theSVG 3.3.12: brands, community, auth badges, AWS, Azure, Google Cloud, Kubernetes |
80
- | **Logo files** | 13,401 variants (default, mono, wordmark, light, dark, colour, โ€ฆ), embedded unmodified |
81
- | **Grid** | 24 ร— 24, 2-unit stroke, 1-unit padding, `currentColor` |
82
- | **Runtime** | React 19 peer dependency only; no runtime dependencies; no hooks |
83
- | **Module format** | ESM with TypeScript declarations; every module free of side effects |
84
-
85
- ## Installation
84
+ | ๐ŸŽจ **Icons** | 1,863 from Lucide 1.52.0, in Lucide's 42 categories, with Lucide's names and tags |
85
+ | ๐Ÿ”ท **Shapes** | `round` (Lucide's drawing, the default) and `sharp`, for every icon |
86
+ | ๐ŸŒ“ **Variants** | `outline` for every icon; `filled` for 775, in both shapes |
87
+ | ๐Ÿท๏ธ **Brand logos** | 7,429 from theSVG 3.3.12: brands, community, auth badges, AWS, Azure, Google Cloud, Kubernetes |
88
+ | ๐Ÿ—‚๏ธ **Logo files** | 13,401 variants (default, mono, wordmark, light, dark, colour, โ€ฆ), embedded unmodified |
89
+ | ๐Ÿ“ **Grid** | 24 ร— 24, 2-unit stroke, 1-unit padding, `currentColor` |
90
+ | โš›๏ธ **Runtime** | React 19 peer dependency only; no runtime dependencies; no hooks |
91
+ | ๐Ÿ“ฆ **Module format** | ESM with TypeScript declarations; every module free of side effects |
92
+ | โ†”๏ธ **RTL** | 18 reading-direction concepts flagged `mirror` in the catalogue |
93
+ | โœ… **Tests** | 638 tests in 11 suites, including a packed-tarball consumer test |
94
+
95
+ ## ๐Ÿ“ฆ Installation
86
96
 
87
97
  ```bash
88
98
  bun add @qeetrix/icons
99
+ # or: npm install @qeetrix/icons
89
100
  ```
90
101
 
91
102
  React 19 is the only peer dependency. The package ships compiled ESM with type declarations, so
92
103
  it works in Vite, Next.js, TanStack Start, and React Server Components without extra setup.
93
104
 
94
- ## Icons
105
+ ## ๐Ÿš€ Quick start
106
+
107
+ ```tsx
108
+ import { BellIcon, SearchIcon, SettingsIcon, StarIcon } from "@qeetrix/icons";
109
+
110
+ export function Toolbar({ starred }: { starred: boolean }) {
111
+ return (
112
+ <nav className="flex items-center gap-3 text-zinc-700">
113
+ <SearchIcon size={20} />
114
+ <BellIcon variant="filled" aria-label="Notifications" />
115
+ <StarIcon variant={starred ? "filled" : "outline"} className="text-amber-500" />
116
+ <SettingsIcon shape="sharp" strokeWidth={1.5} />
117
+ </nav>
118
+ );
119
+ }
120
+ ```
121
+
122
+ - ๐ŸŽจ Icons draw in `currentColor`: they follow the text colour around them.
123
+ - ๐Ÿ“ `size` takes pixels or any CSS length; the default is 24.
124
+ - ๐Ÿ”ท Switch a whole UI to the sharp style by passing `shape="sharp"`, for example from your own
125
+ wrapper or theme.
126
+
127
+ ## ๐ŸŽจ Icons
95
128
 
96
- ### Shapes and variants
129
+ ### ๐Ÿ”ท Shapes and variants
97
130
 
98
131
  Every icon has two shapes, and some icons have two variants. Pick one with two props:
99
132
 
@@ -103,10 +136,11 @@ Every icon has two shapes, and some icons have two variants. Pick one with two p
103
136
  | **`shape="sharp"`** | `<StarIcon shape="sharp" />` | `<StarIcon shape="sharp" variant="filled" />` |
104
137
 
105
138
  Filled drawings exist only where the solid form is clean and meaningful: badges, toggles, nav
106
- items, devices, media, and many more. Open-line icons such as arrows, chevrons, and text marks are
107
- outline-only by design.
139
+ items, devices, media, files, people, and many more. Open-line icons such as arrows, chevrons,
140
+ and text marks, and icons whose outline is clipped open around a badge, are outline-only by
141
+ design.
108
142
 
109
- ### Props
143
+ ### ๐ŸŽ›๏ธ Props
110
144
 
111
145
  Every icon accepts the native `<svg>` props (including `ref`, `className`, `style`, and event
112
146
  handlers) plus:
@@ -119,16 +153,14 @@ handlers) plus:
119
153
  | `strokeWidth` | `number \| string` | `2` | Overrides the outline stroke (try 1.5 for dense UIs). |
120
154
  | `aria-label` | `string` | | Names the icon for assistive technology. |
121
155
 
122
- Icons draw in `currentColor`, so they follow the surrounding text colour: set `color` with CSS or
123
- a utility class.
124
-
125
156
  ```tsx
126
157
  <SearchIcon size={20} className="text-muted" />
127
158
  <BellIcon variant="filled" aria-label="Notifications" />
128
159
  <SettingsIcon shape="sharp" strokeWidth={1.5} />
160
+ <HeartIcon size="1.25em" style={{ color: "crimson" }} />
129
161
  ```
130
162
 
131
- ### Naming
163
+ ### ๐Ÿ”ค Naming
132
164
 
133
165
  Each icon is one named export: its Lucide name in PascalCase plus `Icon`. Categories never appear
134
166
  in names or import paths.
@@ -142,13 +174,13 @@ in names or import paths.
142
174
  Lucide's former names (`trash-2` for `trash`, for example) are listed in the catalogue for search
143
175
  and migration, but are not exported.
144
176
 
145
- ### Type safety
177
+ ### ๐Ÿงท Type safety
146
178
 
147
179
  `variant` is narrowed per icon, so asking for a drawing that doesn't exist fails at compile time:
148
180
 
149
181
  ```tsx
150
- <StarIcon variant="filled" /> // โœ“ star has a filled drawing
151
- <ArrowLeftIcon variant="filled" /> // โœ— type error: arrow-left is outline-only
182
+ <StarIcon variant="filled" /> // โœ… star has a filled drawing
183
+ <ArrowLeftIcon variant="filled" /> // โŒ type error: arrow-left is outline-only
152
184
  ```
153
185
 
154
186
  To accept any icon, for example in a button component, type the prop as
@@ -167,15 +199,16 @@ function ToolbarButton({ icon: Icon, label }: { icon: ComponentType<IconProps<"o
167
199
  }
168
200
  ```
169
201
 
170
- ### Accessibility and RTL
202
+ ### โ™ฟ Accessibility and RTL
171
203
 
172
204
  - Icons are **decorative by default**: `aria-hidden="true"` and `focusable="false"`. A non-empty
173
205
  `aria-label` or `aria-labelledby` turns an icon into `role="img"`. Explicit props always win.
174
206
  - Each icon's **directionality** is in the catalogue: `mirror` for reading-direction concepts
175
207
  such as undo, reply, send, log-in, and indentation, and `preserve` for everything else.
176
- Physical arrows and chevrons never mirror. See [docs/rtl.md](docs/rtl.md).
208
+ Physical arrows and chevrons never mirror. The library never flips an icon itself; your RTL
209
+ layer decides. See [docs/rtl.md](docs/rtl.md).
177
210
 
178
- ## Brand logos
211
+ ## ๐Ÿท๏ธ Brand logos
179
212
 
180
213
  ```tsx
181
214
  import { GithubLogo, SlackLogo, StripeLogo } from "@qeetrix/icons";
@@ -183,6 +216,7 @@ import { GithubLogo, SlackLogo, StripeLogo } from "@qeetrix/icons";
183
216
  <GithubLogo /> // the default file, 24 px tall
184
217
  <GithubLogo variant="wordmark" height={32} /> // any file the logo has
185
218
  <SlackLogo height="2em" aria-label="Slack" /> // CSS lengths work too
219
+ <StripeLogo variant="mono" loading="lazy" /> // native <img> props pass through
186
220
  ```
187
221
 
188
222
  Each logo renders its **published SVG file, unmodified**, as an `<img>`. Nothing in the artwork is
@@ -200,7 +234,7 @@ Components.
200
234
  Other native `<img>` props (`className`, `style`, `loading`, `decoding`, โ€ฆ) pass through. Logos
201
235
  keep their brand colours by design, so CSS cannot recolour them.
202
236
 
203
- ### Names and collections
237
+ ### ๐Ÿ—‚๏ธ Names and collections
204
238
 
205
239
  A logo's name is its slug in PascalCase plus `Logo`: `GithubLogo`, `GoogleCloudLogo`. Slugs that
206
240
  start with a digit get a `Brand` prefix (`Brand1passwordLogo`). Icons always end in `Icon` and
@@ -208,14 +242,14 @@ logos in `Logo`, so the two families never collide.
208
242
 
209
243
  | Collection | Logos |
210
244
  |:--|--:|
211
- | Brands | 4,691 |
212
- | Auth badges | 860 |
213
- | AWS architecture | 739 |
214
- | Azure architecture | 626 |
215
- | Community | 259 |
216
- | Google Cloud architecture | 214 |
217
- | Kubernetes architecture | 38 |
218
- | Unlisted | 2 |
245
+ | ๐Ÿข Brands | 4,691 |
246
+ | ๐Ÿ” Auth badges | 860 |
247
+ | โ˜๏ธ AWS architecture | 739 |
248
+ | โ˜๏ธ Azure architecture | 626 |
249
+ | ๐Ÿ‘ฅ Community | 259 |
250
+ | โ˜๏ธ Google Cloud architecture | 214 |
251
+ | โ˜ธ๏ธ Kubernetes architecture | 38 |
252
+ | ๐Ÿ—ƒ๏ธ Unlisted | 2 |
219
253
 
220
254
  theSVG's own `light` and `dark` labels are inverted for most logos, so the catalogue records the
221
255
  background each file is actually drawn for (`light`, `dark`, or `any`), measured from its colours.
@@ -228,7 +262,7 @@ background each file is actually drawn for (`light`, `dark`, or `any`), measured
228
262
  > see [licenses/third-party-logos.md](licenses/third-party-logos.md) and
229
263
  > [docs/logos.md](docs/logos.md#licensing-and-trademarks).
230
264
 
231
- ## Catalogue and search
265
+ ## ๐Ÿ”Ž Catalogue and search
232
266
 
233
267
  Machine-readable catalogues for docs sites, icon pickers, and tooling. They are never needed to
234
268
  render, and the package root never imports them.
@@ -261,7 +295,44 @@ const wordmarks = logoManifest.logos.filter(
261
295
  | `tags`, `aliases` | `aliases`, `hex` (brand colour) |
262
296
  | `directionality` | `license`, `website`, `guidelines`, `source` |
263
297
 
264
- ## Playground
298
+ ## ๐Ÿ” Coming from lucide-react
299
+
300
+ The artwork is Lucide's, so most screens move over with an import change:
301
+
302
+ | `lucide-react` | `@qeetrix/icons` |
303
+ |:--|:--|
304
+ | `import { Star } from "lucide-react"` | `import { StarIcon } from "@qeetrix/icons"` |
305
+ | `<Star size={20} strokeWidth={1.5} />` | `<StarIcon size={20} strokeWidth={1.5} />` (same props) |
306
+ | `<Star className="text-amber-500" />` | `<StarIcon className="text-amber-500" />` (same `currentColor`) |
307
+ | Outline only | Add `variant="filled"` where a filled drawing exists |
308
+ | Round only | Add `shape="sharp"` for the sharp style |
309
+ | Logos not included | `GithubLogo`, `SlackLogo`, โ€ฆ from the same package |
310
+
311
+ Names follow Lucide 1.52.0, so a few older lucide-react names differ (`Trash2` is `TrashIcon`
312
+ here); the catalogue's `aliases` field maps them. `absoluteStrokeWidth` is not supported.
313
+
314
+ ## ๐Ÿ“ Design rules
315
+
316
+ Every derived drawing follows the same rules, so families look alike and nothing surprises you at
317
+ 16 px.
318
+
319
+ | | Round filled | Sharp (outline and filled) |
320
+ |:--|:--|:--|
321
+ | ๐Ÿ“ **Footprint** | Same painted extent as the outline | Same drawing, square caps, mitered joins (miter limit 4) |
322
+ | ๐Ÿงฑ **Bodies and details** | Bodies solid; details cut as 2-unit negative lines | Small corner roundings become sharp corners; acute tips come to a point |
323
+ | โœ‚๏ธ **Cuts that reach an edge** | Run straight through, so parts separate cleanly (calendar header, file dog-ear, mail flap) | Identical to round: both shapes part the same way |
324
+ | ๐Ÿ”— **Attached parts** | Legs, handles, stands, cords stay joined | Line ends that stop on another stroke are trimmed so no cap pokes out |
325
+ | ๐ŸชŸ **Layers** | Front parts sit in a 1-unit gap (clipboard clip, copy's front sheet, wheels) | Same roles as round, part for part |
326
+ | ๐Ÿ”ฒ **Border** | Inside Lucide's 1-unit padding | Never crosses it: a corner that would is cut flat, minimally, symmetrically |
327
+ | โšช **Dots** | Round holes | UI dots square (ellipsis, bullets, keys, pips); figurative dots round (eyes, spots, drops) |
328
+ | ๐ŸŒฟ **Organic shapes** | As the outline | Circles, faces, animals, fruit, hands, and coastlines stay round |
329
+ | ๐Ÿ”ค **Letters** | As the outline | An A's apex stays level with the letters beside it |
330
+
331
+ Where no rule gives a clean result, a reviewed, hand-drawn override takes the derivation's place.
332
+ Full detail: [docs/filled.md](docs/filled.md), [docs/sharp.md](docs/sharp.md), and
333
+ [docs/design.md](docs/design.md).
334
+
335
+ ## ๐Ÿงช Playground
265
336
 
266
337
  An internal, unpublished playground for browsing and visual review, with separate **Icons** and
267
338
  **Logos** pages:
@@ -270,30 +341,33 @@ An internal, unpublished playground for browsing and visual review, with separat
270
341
  bun run playground
271
342
  ```
272
343
 
273
- - **Icons:** category sidebar, search across names, tags, and former names, Round/Sharp and
344
+ - ๐ŸŽจ **Icons:** category sidebar, search across names, tags, and former names, Round/Sharp and
274
345
  variant switches, size, stroke, and colour controls, and an inspector with every shape and
275
346
  variant, real-size previews, construction grid, light/dark surfaces, RTL preview, and copyable
276
347
  JSX.
277
- - **Logos:** collections, license and variant filters, a light/dark/transparent background
348
+ - ๐Ÿท๏ธ **Logos:** collections, license and variant filters, a light/dark/transparent background
278
349
  switch, cards at each logo's true aspect ratio, and an inspector with every file on the
279
350
  background it's drawn for, license warnings, and brand links.
280
- - **Everywhere:** a โŒ˜K command palette across icons and logos, shareable URLs, keyboard
351
+ - โŒจ๏ธ **Everywhere:** a โŒ˜K command palette across icons and logos, shareable URLs, keyboard
281
352
  navigation, and light and dark themes.
282
353
 
283
- ## Performance
354
+ ## โšก Performance and package size
284
355
 
285
- - **Production builds include only what you import.** Every module is free of side effects and
286
- the root is a list of static re-exports, so bundlers drop every unused icon and logo.
287
- - **One import, everything included.** Importing `@qeetrix/icons` gives you all icons and logos.
356
+ - ๐ŸŒฒ **Production builds include only what you import.** Every module is free of side effects and
357
+ the root is a list of static re-exports, so bundlers drop every unused icon and logo. Tests
358
+ bundle real consumers to prove it.
359
+ - ๐Ÿ“ฅ **One import, everything included.** Importing `@qeetrix/icons` gives you all icons and logos.
288
360
  In Node (server rendering, test runners) the first import therefore loads every module:
289
361
  measured cold on a development laptop, about 20 s and 360 MB with the logos, against about
290
362
  1.8 s for icons alone. It is paid once per process.
291
- - **Dev servers** that pre-bundle a dependency's root, such as Vite and Next.js, process the whole
363
+ - ๐Ÿ”ฅ **Dev servers** that pre-bundle a dependency's root, such as Vite and Next.js, process the whole
292
364
  package on the first start after installing or upgrading, then reuse their cache.
293
- - **Per-icon imports** are available when you need the leanest possible module graph:
365
+ - ๐Ÿชถ **Per-icon imports** are available when you need the leanest possible module graph:
294
366
  `import { TrashIcon } from "@qeetrix/icons/icons/trash"`.
367
+ - ๐Ÿ“ฆ **Package:** about 10.7 MB packed and 50.7 MB unpacked, almost all of it logo data. Only
368
+ compiled code and licenses ship; no source SVGs.
295
369
 
296
- ## How it is built
370
+ ## ๐Ÿ—๏ธ How it is built
297
371
 
298
372
  Every source file is written by a tool from a pinned upstream release, and everything generated
299
373
  is committed, validated in CI, and reproducible.
@@ -304,6 +378,7 @@ flowchart LR
304
378
  RO -->|derive:filled| RF["icons/round-filled"]
305
379
  RO -->|derive:sharp| SO["icons/sharp-outline"]
306
380
  SO -->|derive:sharp| SF["icons/sharp-filled"]
381
+ C["config/derived ยท config/overrides"] -.-> RF & SO & SF
307
382
  RO & RF & SO & SF -->|check:icons ยท generate| GI["src/generated/icons"]
308
383
  T["theSVG 3.3.12"] -->|sync:brands| B["icons/brand-icons"]
309
384
  B -->|check:brands ยท generate:logos| GL["src/generated/logos"]
@@ -311,22 +386,28 @@ flowchart LR
311
386
  GL --> P
312
387
  ```
313
388
 
314
- - **Filled drawings** are derived with CanvasKit (Skia) path operations from per-category recipes
389
+ - ๐ŸŒ“ **Filled drawings** are derived with CanvasKit (Skia) path operations from per-category recipes
315
390
  in [config/derived/](config/derived/README.md): bodies filled to the outline's painted extent,
316
- details cut as negative lines (running cleanly through the edge they reach), crossing lines
317
- cleared by a gap. A few hand-drawn, hash-stamped overrides in `config/overrides/` replace
318
- derivations that rules cannot get right. See [docs/filled.md](docs/filled.md).
319
- - **Sharp drawings** square corner roundings at their tangent intersections, point acute tips with
320
- a miter limit of 4, and keep circles, pills, and organic curves round. See
391
+ details cut as negative lines, crossing lines cleared by a gap. See
392
+ [docs/filled.md](docs/filled.md).
393
+ - ๐Ÿ”ท **Sharp drawings** square corner roundings at their tangent intersections, point acute tips,
394
+ and then fit the whole icon: nothing crosses the padding, no cap pokes past the stroke it ends
395
+ on, joined strokes form one corner, and mirror twins get the same cut. See
321
396
  [docs/sharp.md](docs/sharp.md).
322
- - **Logos** are copied byte for byte from a pinned theSVG commit, validated (no scripts, event
397
+ - โœ๏ธ **Overrides:** 78 hand-drawn replacements in `config/overrides/` cover the few drawings rules
398
+ cannot get right. Each is stamped with the SHA-256 of the outline it was drawn against, so a
399
+ Lucide upgrade flags it for review instead of silently drifting.
400
+ - ๐Ÿท๏ธ **Logos** are copied byte for byte from a pinned theSVG commit, validated (no scripts, event
323
401
  handlers, or external references), and embedded as lossless `data:` URIs. See
324
402
  [docs/logos.md](docs/logos.md).
325
403
 
326
- ### Repository layout
404
+ ### ๐Ÿ—ƒ๏ธ Repository layout
327
405
 
328
406
  ```text
329
- config/ Pinned upstream data and recipes (lucide.json, brands.json, filled.ts, โ€ฆ)
407
+ config/
408
+ derived/ Per-category tables: filled recipes and roles, keepRound, tipHeight
409
+ overrides/ Hand-drawn, hash-stamped replacements for derived drawings
410
+ lucide.json, brands.json, categories.ts, icon-system.ts, icon-metadata.ts, โ€ฆ
330
411
  icons/
331
412
  round-outline/ Lucide outlines, unchanged
332
413
  round-filled/ Derived filled drawings
@@ -345,7 +426,23 @@ tests/ Vitest suites, including a packed-tarball consumer test
345
426
  docs/ Design, API, pipeline, and process documentation
346
427
  ```
347
428
 
348
- ## Development
429
+ ## โœ… Quality
430
+
431
+ - ๐Ÿงพ **Validation:** every source SVG is checked against 24 rules (`QXI-*` codes): structure,
432
+ allowed elements and attributes, paint, the grid, naming, categories, duplicates, and that every
433
+ icon has all its drawings in both shapes. See [docs/validation.md](docs/validation.md).
434
+ - ๐Ÿ”ฒ **Border proof:** a test measures every sharp drawing with CanvasKit and fails if anything
435
+ paints past the padding where the round drawing doesn't. The few curved ends too short to trim
436
+ are listed with their measured overshoot, and none may get worse.
437
+ - ๐Ÿ” **Reproducibility:** `check:filled`, `check:sharp`, `check:generated`, and `check:logos` fail
438
+ if any derived or generated file differs from what the tools produce.
439
+ - ๐Ÿ“ฆ **Real consumers:** the package test packs the tarball, installs it in a fresh project,
440
+ typechecks strict consumers under `bundler` and `nodenext` resolution, renders icons in both
441
+ shapes, and bundles them to prove tree-shaking.
442
+ - ๐Ÿ‘€ **Visual review:** every filled and sharp drawing was reviewed by eye at 64, 24, and 16 px,
443
+ category by category. See [docs/visual-qa.md](docs/visual-qa.md).
444
+
445
+ ## ๐Ÿ› ๏ธ Development
349
446
 
350
447
  Bun only (1.3.14), strict TypeScript, ESM, Biome, and Vitest.
351
448
 
@@ -356,56 +453,61 @@ bun run lint && bun run typecheck && bun run test
356
453
 
357
454
  | Area | Commands |
358
455
  |:--|:--|
359
- | Quality | `lint`, `typecheck`, `test`, `build` |
360
- | Icons | `sync:lucide [version]`, `derive:filled`, `derive:sharp`, `generate` |
361
- | Icon checks | `check:icons`, `check:filled`, `check:sharp`, `check:generated` |
362
- | Logos | `sync:brands [commit]`, `generate:logos` |
363
- | Logo checks | `check:brands`, `check:logos` |
364
- | Playground | `playground`, `playground:build` |
456
+ | โœ… Quality | `lint`, `typecheck`, `test`, `build` |
457
+ | ๐ŸŽจ Icons | `sync:lucide [version]`, `derive:filled`, `derive:sharp`, `generate` |
458
+ | ๐ŸŽฏ One category | `derive:filled --category <id>`, `derive:sharp --category <id>` |
459
+ | โœ๏ธ Overrides | `stamp:override <file>` |
460
+ | ๐Ÿ” Icon checks | `check:icons`, `check:filled`, `check:sharp`, `check:generated` |
461
+ | ๐Ÿท๏ธ Logos | `sync:brands [commit]`, `generate:logos` |
462
+ | ๐Ÿ” Logo checks | `check:brands`, `check:logos` |
463
+ | ๐Ÿงช Playground | `playground`, `playground:build` |
365
464
 
366
465
  Ground rules:
367
466
 
368
- - **Never hand-edit tool-written files**: `icons/`, `config/lucide.json`, `config/brands.json`,
467
+ - ๐Ÿšซ **Never hand-edit tool-written files**: `icons/`, `config/lucide.json`, `config/brands.json`,
369
468
  `config/categories.ts`, `src/generated/`, `icon-manifest.json`, or `licenses/third-party-logos.md`.
370
469
  Change the inputs and rerun the tool.
371
- - **`sync:lucide` and `sync:brands` leave the repository consistent**: they re-derive and
470
+ - ๐Ÿ”„ **`sync:lucide` and `sync:brands` leave the repository consistent**: they re-derive and
372
471
  regenerate everything downstream.
373
- - **A missing or flawed outline belongs upstream** in Lucide; a filled or sharp result is changed
472
+ - โฌ†๏ธ **A missing or flawed outline belongs upstream** in Lucide; a filled or sharp result is changed
374
473
  through its category's file in [config/derived/](config/derived/README.md), an override, or the
375
474
  sharp rules.
376
- - **CI and the release gate run** lint, typecheck, tests, every `check:*` command, the build, and
475
+ - ๐Ÿค– **CI and the release gate run** lint, typecheck, tests, every `check:*` command, the build, and
377
476
  the playground build.
378
477
 
379
- ## Documentation
478
+ ## ๐Ÿ“š Documentation
380
479
 
381
480
  | Guide | |
382
481
  |:--|:--|
383
- | [API](docs/api.md) | Entry points, props, types, the catalogue schema, and versioning |
384
- | [Design](docs/design.md) | Grid, stroke, padding, and how filled and sharp drawings are formed |
385
- | [Filled drawings](docs/filled.md) | Roles, inference, recipes, and how to add a filled icon |
386
- | [Sharp style](docs/sharp.md) | Sharpening rules, exceptions, and parity |
387
- | [Brand logos](docs/logos.md) | Sync, catalogue, components, licensing, and performance |
388
- | [Lucide](docs/lucide.md) | What comes from Lucide, syncing, and upgrading |
389
- | [Naming](docs/naming.md) ยท [Accessibility](docs/accessibility.md) ยท [RTL](docs/rtl.md) | Conventions |
390
- | [Architecture](docs/architecture.md) ยท [Generation](docs/generation.md) ยท [Validation](docs/validation.md) | How the pipeline works |
391
- | [Visual QA](docs/visual-qa.md) ยท [Contributing](docs/contributing.md) ยท [Releases](docs/releases.md) | Process |
482
+ | ๐Ÿงฉ [API](docs/api.md) | Entry points, props, types, the catalogue schema, and versioning |
483
+ | ๐Ÿ“ [Design](docs/design.md) | Grid, stroke, padding, and how filled and sharp drawings are formed |
484
+ | ๐ŸŒ“ [Filled drawings](docs/filled.md) | Roles, inference, recipes, overrides, and how to add a filled icon |
485
+ | ๐Ÿ”ท [Sharp style](docs/sharp.md) | Sharpening rules, fitting, kept-round elements, letter heights |
486
+ | ๐Ÿท๏ธ [Brand logos](docs/logos.md) | Sync, catalogue, components, licensing, and performance |
487
+ | ๐Ÿชถ [Lucide](docs/lucide.md) | What comes from Lucide, syncing, and upgrading |
488
+ | ๐Ÿ”ค [Naming](docs/naming.md) ยท โ™ฟ [Accessibility](docs/accessibility.md) ยท โ†”๏ธ [RTL](docs/rtl.md) | Conventions |
489
+ | ๐Ÿ—๏ธ [Architecture](docs/architecture.md) ยท โš™๏ธ [Generation](docs/generation.md) ยท ๐Ÿงพ [Validation](docs/validation.md) | How the pipeline works |
490
+ | ๐Ÿ‘€ [Visual QA](docs/visual-qa.md) ยท ๐Ÿค [Contributing](docs/contributing.md) ยท ๐Ÿšข [Releases](docs/releases.md) | Process |
392
491
 
393
492
  The full index is [docs/README.md](docs/README.md).
394
493
 
395
- ## Releases
494
+ ## ๐Ÿšข Releases
396
495
 
397
- The package version stays `1.0.4` for now. The existing workflows patch-bump pull requests and
398
- publish on merge to `main`, so keep 2.0 off `main` until the major release is prepared, or it
399
- could ship as an incompatible 1.x patch. Read [docs/releases.md](docs/releases.md) before any
400
- release work.
496
+ - ๐Ÿท๏ธ **Published on npm** as [`@qeetrix/icons`](https://www.npmjs.com/package/@qeetrix/icons),
497
+ with signed provenance from GitHub Actions, and as a GitHub Release for each version.
498
+ - ๐Ÿ”ข **Versioning:** the Version workflow raises the patch version on every pull request unless
499
+ it is already raised; merging to `main` publishes that version, tags it, and opens the GitHub
500
+ Release. A Rollback workflow moves the `latest` tag back to an earlier version.
501
+ - ๐Ÿ“ **Changes** are recorded in [CHANGELOG.md](CHANGELOG.md). Read
502
+ [docs/releases.md](docs/releases.md) before any release work.
401
503
 
402
- ## License
504
+ ## โš–๏ธ License
403
505
 
404
- - **Package code:** MIT ยฉ Qeet Group.
405
- - **Icons:** the artwork, the derived filled and sharp drawings, and the generated icon components
506
+ - ๐Ÿ’ป **Package code:** MIT ยฉ Qeet Group.
507
+ - ๐ŸŽจ **Icons:** the artwork, the derived filled and sharp drawings, and the generated icon components
406
508
  are based on [Lucide](https://lucide.dev), ISC ยฉ Lucide Icons and Contributors. Some Lucide icons
407
509
  derive from Feather, MIT ยฉ Cole Bemis.
408
- - **Brand logos:** each logo keeps its own license (public domain, permissive, attribution,
510
+ - ๐Ÿท๏ธ **Brand logos:** each logo keeps its own license (public domain, permissive, attribution,
409
511
  share-alike, no-derivatives, non-commercial, copyleft, or none), listed in
410
512
  [licenses/third-party-logos.md](licenses/third-party-logos.md). theSVG's own code is MIT ยฉ
411
513
  thesvg.org. Logos are trademarks of their owners, shown for identification only.
@@ -413,7 +515,7 @@ release work.
413
515
  `package.json` declares `"license": "SEE LICENSE IN LICENSE"`; the full notices are in
414
516
  [LICENSE](LICENSE).
415
517
 
416
- ### Acknowledgements
518
+ ### ๐Ÿ™ Acknowledgements
417
519
 
418
520
  Built on [Lucide](https://lucide.dev) and [Feather](https://feathericons.com) for the icons,
419
521
  [theSVG](https://thesvg.org), [Simple Icons](https://simpleicons.org),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qeetrix/icons",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "private": false,
5
5
  "description": "Qeetrix Icons โ€” Lucide icons in round and sharp shapes with derived filled variants, plus theSVG brand logos, as tree-shakeable React components.",
6
6
  "license": "SEE LICENSE IN LICENSE",