{"_id":"@andersseen/icon","_rev":"6-f132cec9f115679132b93703b196a174","name":"@andersseen/icon","dist-tags":{"latest":"0.2.0"},"versions":{"0.0.1":{"name":"@andersseen/icon","version":"0.0.1","keywords":["icons","svg","web-components"],"author":{"name":"Andersseen"},"license":"MIT","_id":"@andersseen/icon@0.0.1","maintainers":[{"name":"andriipap","email":"andriipap01@gmail.com"}],"homepage":"https://github.com/Andersseen/and-web-components#readme","bugs":{"url":"https://github.com/Andersseen/and-web-components/issues"},"dist":{"shasum":"5b2b1d9c18427c23e73dd995432079b182b911f1","tarball":"https://registry.npmjs.org/@andersseen/icon/-/icon-0.0.1.tgz","fileCount":7,"integrity":"sha512-uGAVkwpQWUCRWPthHUjJibIBVxA5xElaUWyTS7w70VGbQgyOWSAI3VknTEKXDHqxZJGkHPJ08r+DULg/aWZxkQ==","signatures":[{"sig":"MEUCIQDuh4XitT//OiZuN8Fuqi/5R3WMQYD4FF/pK5yp9x9PZgIgfSU/rW5T2Y77+nx1EcCBqEbzNq8h65TgrWpPwUG+O3o=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":31742},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","module":"dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"273f8532cec166cd7b195034d8241a1578d4e5e6","scripts":{"build":"rm -rf dist && tsc","clean":"rm -rf dist","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"andriipap","email":"andriipap01@gmail.com"},"repository":{"url":"git+https://github.com/Andersseen/and-web-components.git","type":"git","directory":"packages/icon-library"},"_npmVersion":"11.6.2","description":"Shared icon library for Andersseen web components","directories":{},"sideEffects":false,"_nodeVersion":"24.12.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.3.3"},"_npmOperationalInternal":{"tmp":"tmp/icon_0.0.1_1772741706486_0.7975714624273711","host":"s3://npm-registry-packages-npm-production"}},"0.0.2":{"name":"@andersseen/icon","version":"0.0.2","keywords":["icons","svg","web-components"],"author":{"name":"Andersseen"},"license":"MIT","_id":"@andersseen/icon@0.0.2","maintainers":[{"name":"andriipap","email":"andriipap01@gmail.com"}],"homepage":"https://github.com/Andersseen/and-web-components#readme","bugs":{"url":"https://github.com/Andersseen/and-web-components/issues"},"dist":{"shasum":"26eccbc386f599d6b05d6c9b29bbbbc8356e2243","tarball":"https://registry.npmjs.org/@andersseen/icon/-/icon-0.0.2.tgz","fileCount":7,"integrity":"sha512-vuro1aXwBAo1ntQZcMCyzYFd/MhQAh0Q1NyoTSTyykkX/CGPjbktRzbWVDuhCJ6+PYGcReRtNdvShVuvT3TBGA==","signatures":[{"sig":"MEQCIF2HPIMp0KaXzsy5tWK8KddNg1K4AzMwqGTyWx4AW1e6AiANlTPuVE2oDW5c33xgRn30U7C+P1POMHqkchaloMHa1Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":33181},"main":"dist/index.js","type":"module","_from":"file:andersseen-icon-0.0.2.tgz","types":"dist/index.d.ts","module":"dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"build":"rm -rf dist && tsc","clean":"rm -rf dist"},"_npmUser":{"name":"andriipap","email":"andriipap01@gmail.com"},"_resolved":"/private/var/folders/wq/4bgf9dy51d5776cl3qgg362h0000gn/T/b681d8b1af5632c06f1778a00b3d1b08/andersseen-icon-0.0.2.tgz","_integrity":"sha512-vuro1aXwBAo1ntQZcMCyzYFd/MhQAh0Q1NyoTSTyykkX/CGPjbktRzbWVDuhCJ6+PYGcReRtNdvShVuvT3TBGA==","repository":{"url":"git+https://github.com/Andersseen/and-web-components.git","type":"git","directory":"packages/icon-library"},"_npmVersion":"11.6.2","description":"Shared icon library for Andersseen web components","directories":{},"sideEffects":false,"_nodeVersion":"24.12.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.3.3"},"_npmOperationalInternal":{"tmp":"tmp/icon_0.0.2_1774134736150_0.35252339358778495","host":"s3://npm-registry-packages-npm-production"}},"0.0.3":{"name":"@andersseen/icon","version":"0.0.3","keywords":["icons","svg","web-components"],"author":{"name":"Andersseen"},"license":"MIT","_id":"@andersseen/icon@0.0.3","maintainers":[{"name":"andriipap","email":"andriipap01@gmail.com"}],"homepage":"https://github.com/Andersseen/and-web-components#readme","bugs":{"url":"https://github.com/Andersseen/and-web-components/issues"},"dist":{"shasum":"6128f8fc3b23b707e6b4fe603e69f0116a82f1b2","tarball":"https://registry.npmjs.org/@andersseen/icon/-/icon-0.0.3.tgz","fileCount":13,"integrity":"sha512-DsVSdKwlNPq0n/VPx8aTOzAUNTJ8gxEwNA/wUYc5OU34XooFNISduF9jucgHfnSPxbCLG6kLBfEGUPtSS/5zbw==","signatures":[{"sig":"MEYCIQDdfBquZbYR26NVvNa2TYkiWtfPWbn9kpGnjYuEgaBIGwIhAL2joJI71wS+a3H7uksGdskqEwBDGGO0k1icRYWS3uMG","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":68963},"main":"dist/index.js","type":"module","_from":"file:andersseen-icon-0.0.3.tgz","types":"dist/index.d.ts","module":"dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist-cjs/index.js"}},"scripts":{"lint":"eslint src","build":"rm -rf dist dist-cjs && tsc && tsc -p tsconfig.cjs.json","clean":"rm -rf dist dist-cjs"},"_npmUser":{"name":"andriipap","email":"andriipap01@gmail.com"},"_resolved":"/private/var/folders/wq/4bgf9dy51d5776cl3qgg362h0000gn/T/b7d01d40ef1c98c5a46eb8200f102948/andersseen-icon-0.0.3.tgz","_integrity":"sha512-DsVSdKwlNPq0n/VPx8aTOzAUNTJ8gxEwNA/wUYc5OU34XooFNISduF9jucgHfnSPxbCLG6kLBfEGUPtSS/5zbw==","repository":{"url":"git+https://github.com/Andersseen/and-web-components.git","type":"git","directory":"packages/icon-library"},"_npmVersion":"11.6.2","description":"Shared icon library for Andersseen web components","directories":{},"sideEffects":false,"_nodeVersion":"24.12.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^10.1.0","typescript":"^5.3.3","typescript-eslint":"^8.57.1"},"_npmOperationalInternal":{"tmp":"tmp/icon_0.0.3_1774194311461_0.4297701411695867","host":"s3://npm-registry-packages-npm-production"}},"0.1.0":{"name":"@andersseen/icon","version":"0.1.0","keywords":["icons","svg","web-components"],"author":{"name":"Andersseen"},"license":"MIT","_id":"@andersseen/icon@0.1.0","maintainers":[{"name":"andriipap","email":"andriipap01@gmail.com"}],"homepage":"https://github.com/Andersseen/and-web-components#readme","bugs":{"url":"https://github.com/Andersseen/and-web-components/issues"},"dist":{"shasum":"cd38c2076d38bcbf39a4b784f69a3b73e81c74f2","tarball":"https://registry.npmjs.org/@andersseen/icon/-/icon-0.1.0.tgz","fileCount":15,"integrity":"sha512-0464M6jJB1lyIvNK0/hqzQlYTe6WcHcJSDFJxDMYuUi93CmquQ+MKZ52utdKri5g59uOXrR+xsUpUPeKjHT/Pw==","signatures":[{"sig":"MEQCIGlmML0Ag30uM502gBwFgC7wOuTC4XKHL6P6xHkBPUR/AiBcPyTcdHV2AjSjO/0t0CljelwD6KLxDsPOKz1cJajYFA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":76711},"main":"dist/index.js","type":"module","_from":"file:andersseen-icon-0.1.0.tgz","types":"dist/index.d.ts","module":"dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist-cjs/index.js"}},"scripts":{"lint":"eslint src --ext .ts,.tsx","test":"vitest run","build":"rm -rf dist dist-cjs && tsc && node ../../scripts/fix-esm-extensions.cjs dist && tsc -p tsconfig.cjs.json","clean":"rm -rf dist dist-cjs","format":"prettier --write \"src/**/*.{ts,tsx}\"","lint:fix":"eslint src --ext .ts,.tsx --fix","format:check":"prettier --check \"src/**/*.{ts,tsx}\""},"_npmUser":{"name":"andriipap","email":"andriipap01@gmail.com"},"_resolved":"/tmp/3a105263d9bc127d9d5d92e47523750e/andersseen-icon-0.1.0.tgz","_integrity":"sha512-0464M6jJB1lyIvNK0/hqzQlYTe6WcHcJSDFJxDMYuUi93CmquQ+MKZ52utdKri5g59uOXrR+xsUpUPeKjHT/Pw==","repository":{"url":"git+https://github.com/Andersseen/and-web-components.git","type":"git","directory":"packages/icon-library"},"_npmVersion":"10.9.8","description":"Shared icon library for Andersseen web components","directories":{},"sideEffects":false,"_nodeVersion":"22.23.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^10.1.0","vitest":"^4.1.0","typescript":"^5.3.3","typescript-eslint":"^8.57.1"},"_npmOperationalInternal":{"tmp":"tmp/icon_0.1.0_1784814154374_0.25478036002148263","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@andersseen/icon","version":"0.1.1","keywords":["icons","svg","web-components"],"author":{"name":"Andersseen"},"license":"MIT","_id":"@andersseen/icon@0.1.1","maintainers":[{"name":"andriipap","email":"andriipap01@gmail.com"}],"homepage":"https://github.com/Andersseen/and-web-components#readme","bugs":{"url":"https://github.com/Andersseen/and-web-components/issues"},"dist":{"shasum":"eb12cf4aeef4801dd3028c51a4a80c1b0be2abb1","tarball":"https://registry.npmjs.org/@andersseen/icon/-/icon-0.1.1.tgz","fileCount":15,"integrity":"sha512-Tkmjpx41TwjTpXOG0yal5D/j5KJSlq9NvHF2IknsA74uM/HC75P8adY2Y16sXBhjawQDm/dlXngco/3+bcyh1g==","signatures":[{"sig":"MEUCIQDkH/DvDjyG+8P3V9Yv0XtAkMLtILRl1MdpDXTpSJgQHgIgQInxyQJTxWkElOZdbEcfOCVOn4FO0n36jN9nzChGF2w=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":81667},"main":"dist/index.js","type":"module","_from":"file:andersseen-icon-0.1.1.tgz","types":"dist/index.d.ts","module":"dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist-cjs/index.js"}},"scripts":{"lint":"eslint src --ext .ts,.tsx","test":"vitest run","build":"rm -rf dist dist-cjs && tsc && node ../../scripts/fix-esm-extensions.cjs dist && tsc -p tsconfig.cjs.json","clean":"rm -rf dist dist-cjs","format":"prettier --write \"src/**/*.{ts,tsx}\"","lint:fix":"eslint src --ext .ts,.tsx --fix","format:check":"prettier --check \"src/**/*.{ts,tsx}\""},"_npmUser":{"name":"andriipap","email":"andriipap01@gmail.com"},"_resolved":"/tmp/a6bd0aa2b2952cb0f55c94e207c244c1/andersseen-icon-0.1.1.tgz","_integrity":"sha512-Tkmjpx41TwjTpXOG0yal5D/j5KJSlq9NvHF2IknsA74uM/HC75P8adY2Y16sXBhjawQDm/dlXngco/3+bcyh1g==","repository":{"url":"git+https://github.com/Andersseen/and-web-components.git","type":"git","directory":"packages/icon-library"},"_npmVersion":"10.9.8","description":"Shared icon library for Andersseen web components","directories":{},"sideEffects":false,"_nodeVersion":"22.23.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^10.1.0","vitest":"^4.1.0","typescript":"^5.3.3","typescript-eslint":"^8.57.1"},"_npmOperationalInternal":{"tmp":"tmp/icon_0.1.1_1786136211718_0.9850943044853391","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"_id":"@andersseen/icon@0.2.0","bin":{"and-icons":"dist/cli.js"},"bugs":{"url":"https://github.com/Andersseen/and-web-components/issues"},"dist":{"shasum":"a1f40ba52f16d1e610dd5355e5aa0a6c3f3e23c3","tarball":"https://registry.npmjs.org/@andersseen/icon/-/icon-0.2.0.tgz","fileCount":127,"integrity":"sha512-ufF+Eo4ieNnNb9pdZvCDYDM5u6Dyp/baB7ffO/6SvqRuki5rB0tY+yf1Av+G0LGbRlFQ06Z34KKqx7DKOv4ZIQ==","signatures":[{"sig":"MEQCIFigbw6bXvbCtnU6V1qiav8hLkOTy8uKKrdWZZckw4WnAiAP0gmXB7OMfMDuX241KKo6MHqiZdEhblqIlOz2A+i0Hw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQD55BDkIY2a9ifWGz2e7mJDaB2+eQxXIaH0f01yIXU9IgIhANM54Mx/fmES1Wals/8OD+1B2omnuzjyIvrhcyGd0cbk"}],"unpackedSize":286250},"main":"dist/index.js","name":"@andersseen/icon","type":"module","_from":"file:andersseen-icon-0.2.0.tgz","types":"dist/index.d.ts","author":{"name":"Andersseen"},"module":"dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist-cjs/index.js"},"./lazy":{"types":"./dist/lazy.d.ts","import":"./dist/lazy.js"},"./build":{"types":"./dist/build.d.ts","import":"./dist/build.js"},"./browser":{"types":"./dist/browser.d.ts","import":"./dist/browser.js"},"./base.css":"./dist/base.css","./icons.css":"./dist/icons.css","./icons/*.css":"./dist/icons/*.css","./generate-css":{"types":"./dist/generate-css.d.ts","import":"./dist/generate-css.js"}},"license":"MIT","scripts":{"lint":"eslint src --ext .ts,.tsx","test":"vitest run","build":"rm -rf dist dist-cjs && tsc && node ../../scripts/fix-esm-extensions.cjs dist && tsc -p tsconfig.cjs.json && node scripts/build-icons-css.mjs && chmod +x dist/cli.js","clean":"rm -rf dist dist-cjs","format":"prettier --write \"src/**/*.{ts,tsx}\"","lint:fix":"eslint src --ext .ts,.tsx --fix","format:check":"prettier --check \"src/**/*.{ts,tsx}\""},"version":"0.2.0","_npmUser":{"name":"andriipap","email":"andriipap01@gmail.com"},"homepage":"https://github.com/Andersseen/and-web-components#readme","keywords":["icons","svg","web-components"],"_resolved":"/tmp/d477b8cb18b26b4f8ce1b02fd7afb69c/andersseen-icon-0.2.0.tgz","_integrity":"sha512-ufF+Eo4ieNnNb9pdZvCDYDM5u6Dyp/baB7ffO/6SvqRuki5rB0tY+yf1Av+G0LGbRlFQ06Z34KKqx7DKOv4ZIQ==","repository":{"url":"git+https://github.com/Andersseen/and-web-components.git","type":"git","directory":"packages/icon-library"},"_npmVersion":"10.9.8","description":"Shared icon library for Andersseen web components","directories":{},"maintainers":[{"name":"andriipap","email":"andriipap01@gmail.com"}],"sideEffects":["*.css","./dist/browser.js"],"_nodeVersion":"22.23.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^10.1.0","vitest":"^4.1.0","typescript":"^5.3.3","@types/node":"^22.13.5","typescript-eslint":"^8.57.1"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/icon_0.2.0_1789714703500_0.38887611232095054"}}},"time":{"created":"2026-03-05T20:15:06.423Z","modified":"2026-09-18T06:58:24.118Z","0.0.1":"2026-03-05T20:15:06.665Z","0.0.2":"2026-03-21T23:12:16.311Z","0.0.3":"2026-03-22T15:45:11.596Z","0.1.0":"2026-07-23T13:42:34.508Z","0.1.1":"2026-08-07T20:56:51.872Z","0.2.0":"2026-09-18T06:58:23.574Z"},"bugs":{"url":"https://github.com/Andersseen/and-web-components/issues"},"author":{"name":"Andersseen"},"license":"MIT","homepage":"https://github.com/Andersseen/and-web-components#readme","keywords":["icons","svg","web-components"],"repository":{"url":"git+https://github.com/Andersseen/and-web-components.git","type":"git","directory":"packages/icon-library"},"description":"Shared icon library for Andersseen web components","maintainers":[{"name":"andriipap","email":"andriipap01@gmail.com"}],"readme":"# @andersseen/icon\n\nTree-shakeable SVG icon library: 86 icons as plain string constants, plus a tiny\nglobal registry that `<and-icon>` (from `@andersseen/web-components`) and\n`@andersseen/vanilla-components` read from. Framework-agnostic — usable without\nany other Andersseen package.\n\n> Part of the Andersseen **product core** — usable entirely on its own to\n> register your own icon set under `and-icon`-compatible names, even outside\n> this component ecosystem.\n\nOne package, one icon source (`ALL_ICONS`), four ways to load the CSS-only\n`and-icon=\"name\"` attribute's mask CSS — plus the **registry + `<and-icon>`**\nWeb Component, which is unaffected by any of them.\n\n## Choose your loading strategy\n\n| Strategy                                      | Runtime JS | Payload             | Best for                              |\n| --------------------------------------------- | ---------- | ------------------- | ------------------------------------- |\n| [Full CSS](#css-only-usage-no-javascript)     | 0          | all icons           | prototypes, docs, simple CDN usage    |\n| [Selective CSS](#selective-per-icon-css)      | 0          | manually selected   | you know exactly which few icons      |\n| [Build-time scanner](#build-time-scanner)     | 0          | icons actually used | production apps with a build step     |\n| [Runtime lazy loading](#runtime-lazy-loading) | small      | icons on demand     | dynamic/CMS content, unknown at build |\n\nNone of these is universally better — pick per app, and it's fine to mix them\n(e.g. selective CSS for a marketing page, the scanner for the main app). All\nfour render the exact same `and-icon=\"name\"` markup and read the same\n`ALL_ICONS` source — nothing is hand-duplicated between them.\n\n## Installation\n\n```bash\npnpm add @andersseen/icon\n```\n\n## CSS-only usage (no JavaScript)\n\n```css\n@import '@andersseen/icon/icons.css';\n```\n\n```html\n<span and-icon=\"home\" aria-hidden=\"true\"></span>\n<i and-icon=\"search\" aria-hidden=\"true\"></i>\n<div and-icon=\"close\" aria-hidden=\"true\"></div>\n```\n\nThe API is the `and-icon` attribute, not a specific element — `<span>` is the\nrecommended host (no default semantics), but any element works. Sizing and color\nare plain CSS (`font-size` controls the `1em` box, `color` controls the\n`currentColor` fill via `mask-image`) — there's no `and-icon-size`/\n`and-icon-color` attribute, standard CSS already covers it.\n\n`icons.css` is generated from `ALL_ICONS` by `generateIconsCss()` — no\nhand-maintained duplicate. Same function generates a smaller stylesheet for a\nsubset of icons:\n\n```ts\nimport { generateIconsCss } from '@andersseen/icon/generate-css';\nimport { HOME, SEARCH } from '@andersseen/icon';\nimport { writeFileSync } from 'node:fs';\n\nwriteFileSync('subset.css', generateIconsCss({ home: HOME, search: SEARCH }));\n```\n\n**Limitations:** monochromatic, `currentColor`-inheriting icons only (this\ncatalog is Lucide-style stroke icons) — no multicolor/gradient artwork, no\nruntime stroke-width, no per-path animation. Use `<and-icon>` for those.\n\n**CDN** (jsDelivr / unpkg), zero JavaScript:\n\n```html\n<link\n  rel=\"stylesheet\"\n  href=\"https://cdn.jsdelivr.net/npm/@andersseen/icon@<version>/dist/icons.css\"\n/>\n<!-- or: https://unpkg.com/@andersseen/icon@<version>/dist/icons.css -->\n\n<span and-icon=\"home\" aria-hidden=\"true\"></span>\n```\n\n**Accessibility:** icons are decorative by default — pair with\n`aria-hidden=\"true\"` and put the accessible name on the surrounding control\n(e.g. `aria-label` on a button), never on the icon itself.\n\n## Selective per-icon CSS\n\nFor when you know exactly which few icons you need and don't want the full\ncatalog. `dist/base.css` has only the shared `[and-icon] { ... }` rule (sizing,\n`currentColor`, mask geometry); `dist/icons/<name>.css` has only that one icon's\n`mask-image` rule. Both are generated from the same `ALL_ICONS` map and the same\ngenerator as `icons.css` — `base.css` + every `icons/<name>.css` you import,\nconcatenated, is byte-identical to the matching subset of `icons.css`.\n\n```css\n@import '@andersseen/icon/base.css';\n@import '@andersseen/icon/icons/home.css';\n@import '@andersseen/icon/icons/search.css';\n```\n\n```html\n<span and-icon=\"home\" aria-hidden=\"true\"></span>\n<span and-icon=\"search\" aria-hidden=\"true\"></span>\n```\n\nOnly those two icons' CSS ships — no `and-icon=\"star\"` markup would render\nanything, since `star.css` was never imported.\n\n**CDN**, zero JavaScript:\n\n```html\n<link\n  rel=\"stylesheet\"\n  href=\"https://cdn.jsdelivr.net/npm/@andersseen/icon@<version>/dist/base.css\"\n/>\n<link\n  rel=\"stylesheet\"\n  href=\"https://cdn.jsdelivr.net/npm/@andersseen/icon@<version>/dist/icons/home.css\"\n/>\n<!-- or the equivalent unpkg.com/@andersseen/icon@<version>/dist/... paths -->\n```\n\n## Build-time scanner\n\nRecommended for **production apps with a build step** — zero runtime JS, and you\ndon't have to hand-pick icon names. The `and-icons` CLI (ships with this\npackage, no separate install) scans your source for static `and-icon=\"<name>\"`\nliterals and generates one CSS file containing exactly the base rule plus the\nicons actually used — via the same `generateIconsCss()` selective-CSS generator\nabove, not a separate implementation.\n\n```bash\npnpm exec and-icons scan --out ./src/and-icons.generated.css\n# or: npx and-icons scan --out ./src/and-icons.generated.css\n```\n\n```css\n@import './and-icons.generated.css';\n```\n\n**What it detects:** static string literals across `.html`, `.htm`, `.astro`,\n`.ts`, `.tsx`, `.jsx`, `.vue`, and `.svelte` files —\n`and-icon=\"home\"`/`and-icon='home'`. It's deliberately a simple, robust textual\nscanner, not a framework parser (no Babel/TS-compiler-API/Vue/Astro AST).\nIgnores `node_modules`, `dist`, `build`, `coverage`, `.git`, `.angular`,\n`.next`, `.nuxt` by default.\n\n**What it can't detect — dynamic values:**\n\n```html\n<span [attr.and-icon]=\"icon\"></span>\n<!-- Angular binding -->\n<span and-icon=\"{icon}\" />\n<!-- JSX expression -->\n<span :and-icon=\"icon\"></span>\n<!-- Vue binding -->\n```\n\nFor those, list the possible names in a config file:\n\n```js\n// and-icons.config.mjs\nexport default {\n  safelist: ['home', 'search', 'user', 'settings'],\n  // include: ['src'],      // root-relative dirs to scan (default: the whole cwd)\n  // exclude: ['fixtures'], // extra dirs to ignore, merged with the defaults above\n  // outFile: './src/and-icons.generated.css',\n};\n```\n\n```bash\nand-icons scan   # reads ./and-icons.config.mjs automatically, --out/--config override it\n```\n\n**Unknown icons fail the build**, on purpose — a static `and-icon=\"homme\"`\n(typo) or a safelisted name that isn't real is reported with its file and the\nCLI exits non-zero, rather than silently generating an empty mask:\n\n```text\nUnknown icon \"homme\"\n  src/components/header.html\n```\n\nScanning and generation are also available as a programmatic, Node-only API\n(never imported by the main entry):\n\n```ts\nimport { scanIcons, buildIconsCss } from '@andersseen/icon/build';\n\nconst result = buildIconsCss({ safelist: ['home'], outFile: './out.css' });\nconsole.log(result.icons); // every icon name that ended up in out.css\n```\n\n## Runtime lazy loading\n\nFor **dynamic runtime content** where the icon names aren't knowable at build\ntime — CMS-driven markup, HTML injected by a third party, a highly dynamic CDN\npage. Opt-in only; importing the module does nothing by itself.\n\n```ts\nimport { initLazyIcons } from '@andersseen/icon/lazy';\n\nconst cleanup = initLazyIcons();\n// later, if needed: cleanup();\n```\n\n```html\n<span and-icon=\"home\" aria-hidden=\"true\"></span>\n```\n\n`initLazyIcons()` scans the DOM for existing `[and-icon]` elements, then watches\nfor new ones and for the attribute changing (via `MutationObserver`), loading\neach icon's `icons/<name>.css` over the network exactly once — deduplicated, no\nre-fetch for an icon already loaded. The shared base rule is injected once as an\ninline `<style>`, never fetched as `icons.css`/`base.css` over the network.\n`dist/lazy.js` itself never contains any SVG data — it only ever loads the\nsmall, already-generated `icons/<name>.css` files.\n\n**CDN**, no bundler, URLs resolve automatically relative to the script itself:\n\n```html\n<script\n  type=\"module\"\n  src=\"https://cdn.jsdelivr.net/npm/@andersseen/icon@<version>/dist/lazy.js\"\n></script>\n<script type=\"module\">\n  import { initLazyIcons } from 'https://cdn.jsdelivr.net/npm/@andersseen/icon@<version>/dist/lazy.js';\n  initLazyIcons();\n</script>\n```\n\n**Bundled apps:** after bundling, `import.meta.url` is not guaranteed to still\npoint at this package's own `dist/` inside `node_modules` — pass an explicit\n`baseUrl` (a path your build copies `dist/icons/` to) or a full\n`resolveIconUrl(name)` resolver:\n\n```ts\ninitLazyIcons({ baseUrl: '/assets/and-icons/' });\n// or:\ninitLazyIcons({ resolveIconUrl: name => `/icons/${name}.css` });\n```\n\nFor a bundled app, prefer the [build-time scanner](#build-time-scanner) over\nlazy loading when the icon set is knowable at build time — zero runtime JS and\nno URL-resolution configuration needed.\n\n`initLazyIcons()` validates every `and-icon` value against the same\nlowercase-kebab-case contract every bundled icon name follows before ever\nbuilding a URL from it, so a value like `and-icon=\"../../etc/passwd\"` is\nrejected outright rather than used to construct a request. A failed stylesheet\nload doesn't crash the app or retry — it logs one development warning per icon\nname (override with `onError`).\n\n## Registry + `<and-icon>` usage\n\n### Tree-shakeable (recommended)\n\nImport and register only the icons you actually use:\n\n```ts\nimport { registerIcons, CLOSE, CHEVRON_DOWN, HOME } from '@andersseen/icon';\n\nregisterIcons({ 'close': CLOSE, 'chevron-down': CHEVRON_DOWN, 'home': HOME });\n```\n\nEvery icon is also exported as a bare string constant (`CLOSE`, `CHEVRON_DOWN`,\n`ARROW_UP`, …) if you want to render it yourself without going through the\nregistry at all — the export name is the icon's `UPPER_SNAKE_CASE` form; the\nregistry key is the same name in `kebab-case`.\n\n### Everything at once (demos only)\n\n```ts\nimport { registerAllIcons } from '@andersseen/icon';\n\nregisterAllIcons();\n```\n\n`registerAllIcons()` bundles all 86 icons — fine for a demo/dev app, but it\ndefeats tree-shaking in a production bundle. Prefer `registerIcons()` with an\nexplicit map.\n\n### The set `@andersseen/web-components` needs\n\nIf you're using `and-icon` from `@andersseen/web-components`, register at least\n`COMPONENT_ICONS` — the curated subset its built-in components reference (close\nbuttons, chevrons, carousel arrows, etc.):\n\n```ts\nimport { registerIcons, COMPONENT_ICONS } from '@andersseen/icon';\n\nregisterIcons(COMPONENT_ICONS);\n```\n\n### Consuming from `<and-icon>`\n\nOnce registered, reference an icon by its registry name:\n\n```html\n<and-icon name=\"close\"></and-icon> <and-icon name=\"chevron-down\"></and-icon>\n```\n\n## Registry API\n\n| Function                   | Description                                              |\n| -------------------------- | -------------------------------------------------------- |\n| `registerIcons(icons)`     | Register a `Record<name, svgInnerMarkup>` map.           |\n| `registerAllIcons()`       | Register all 86 bundled icons. Demo/dev use only.        |\n| `getIcon(name)`            | Returns the registered SVG inner markup, or `undefined`. |\n| `hasIcon(name)`            | `boolean` — is this name registered?                     |\n| `getRegisteredIconNames()` | `string[]` of every currently registered name.           |\n| `getRegisteredIconCount()` | Number of currently registered icons.                    |\n\nThe registry is a single `Map` on `globalThis` (or `window`, when present), so\nit's shared across every consumer on the page regardless of which bundle\nregistered a given icon first.\n\n**Trust contract:** `registerIcons()` content is inserted via `innerHTML` by\n`<and-icon>` — only register SVG markup you trust, never unsanitized\nuser-generated or third-party content. In development, markup outside the\nstroke-icon contract below (a disallowed element, an event-handler attribute, a\n`javascript:` URI) triggers a one-time `console.warn` per name — a lint-level\nsignal, not a sanitizer; it never rejects or mutates what gets registered.\n\n## Design\n\n- Every icon is a plain string of inner SVG markup (`<path>`/`<g>` elements, no\n  wrapping `<svg>`) using `currentColor`-free, theme-agnostic strokes — the\n  consuming `<and-icon>`/`<svg>` wrapper controls sizing and color.\n- `ALL_ICONS` (the full map) and `COMPONENT_ICONS` (the subset used by\n  `@andersseen/web-components`) are both exported for cases where you need the\n  whole set or just the built-in-component set, respectively.\n\n## Icon conventions\n\nEvery icon in this package follows the same drawing contract. The wrapper that\nrenders it (`<and-icon>`, see\n`packages/web-components/src/components/and-icon/and-icon.tsx`) supplies:\n\n```html\n<svg\n  viewBox=\"0 0 24 24\"\n  fill=\"none\"\n  stroke=\"currentColor\"\n  stroke-width=\"2\"\n  stroke-linecap=\"round\"\n  stroke-linejoin=\"round\"\n>\n  <!-- the icon string goes here, verbatim -->\n</svg>\n```\n\nSo a contributed icon must:\n\n1. **Be based on [Lucide](https://lucide.dev)** (ISC), or drawn to match its\n   style. Copy the icon's inner markup, not the whole `<svg>`.\n2. **Fit a 24×24 grid.** No coordinate may fall outside `0`–`24`; anything\n   beyond it is clipped, and a shape that ends exactly on the edge loses half\n   its stroke.\n3. **Be stroke-only.** Never set `fill`, `stroke`, `stroke-width` or `style` on\n   a shape — that overrides `currentColor` and breaks theming. Icons designed\n   for solid fill render as the outline of their silhouette here, so they don't\n   belong in this set.\n4. **Use only** `path`, `circle`, `rect`, `line`, `polyline`, `polygon`,\n   `ellipse` and `g`.\n5. **Be the complete drawing.** This is the one the tests can't fully prove for\n   you: `lock` shipped without its shackle and `user` without its head because\n   each was a single `<path>` that parsed fine. When you copy an icon, copy\n   _every_ shape in it, then look at it rendered.\n6. **Be its own drawing.** No aliasing another constant\n   (`export const IMAGE = LAYOUT` made `<and-icon name=\"image\">` paint a layout\n   for an entire release).\n\n`src/__tests__/icon-content.test.ts` enforces 2–4 and 6 for every entry in\n`ALL_ICONS`, and snapshots each icon's shape signature so a disappearing\n`<path>` shows up as a diff in review.\n\n## Development\n\n```bash\npnpm -C packages/icon-library test    # Vitest\npnpm -C packages/icon-library lint\npnpm -C packages/icon-library build   # ESM + CJS\n```\n\nTo eyeball the whole set, render every entry of `ALL_ICONS` into the `<svg>`\nwrapper above and look at the grid. Tests confirm an icon is _valid markup_;\nonly your eyes confirm it's the _right drawing_.\n\n## License\n\nMIT\n","readmeFilename":"README.md"}