@iconia/react 0.1.0-dev.52c1e49

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Wyesoftware
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,169 @@
1
+ # @iconia/react
2
+
3
+ CLI and React component library for [iconia.io](https://iconia.io) — manage SVG icon collections and import them as typed React components at build time.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @iconia/react
9
+ # or
10
+ bun add @iconia/react
11
+ # or
12
+ pnpm add @iconia/react
13
+ ```
14
+
15
+ ## Quick start
16
+
17
+ ```bash
18
+ npx @iconia/react init # create iconia.config.ts
19
+ npx @iconia/react add my-icons # add a collection and download icons
20
+ ```
21
+
22
+
23
+ ### Shorter commands after install
24
+
25
+ Once `@iconia/react` is installed in your project you can drop the package name and use `iconia` directly:
26
+
27
+ ```bash
28
+ iconia init
29
+ iconia add my-icons
30
+ iconia sync
31
+ iconia pull
32
+ ```
33
+
34
+ ## Configuration
35
+
36
+ `iconia.config.ts` in your project root:
37
+
38
+ ```ts
39
+ import type { IconiaConfig } from "@iconia/react";
40
+
41
+ export default {
42
+ apiKey: process.env.ICONIA_API_KEY,
43
+ collections: ["my-icons", "team-brand"],
44
+ } satisfies IconiaConfig;
45
+ ```
46
+
47
+ Set `ICONIA_API_KEY` to an API key generated in your [iconia.io dashboard](https://iconia.io/settings/api-keys).
48
+
49
+ ---
50
+
51
+ ## CLI commands
52
+
53
+ ### `iconia init`
54
+
55
+ Create a starter `iconia.config.ts` in the current directory.
56
+
57
+ ```bash
58
+ npx @iconia/react init
59
+ ```
60
+
61
+ ---
62
+
63
+ ### `iconia add <slug>`
64
+
65
+ Add a collection to your project: validates it exists on the server, updates `iconia.config.ts`, downloads icons and generates React components.
66
+
67
+ ```bash
68
+ npx @iconia/react add my-icons
69
+ npx @iconia/react add team-brand
70
+ ```
71
+
72
+ ---
73
+
74
+ ### `iconia remove <slug>`
75
+
76
+ Remove a collection: deletes generated files and removes the slug from `iconia.config.ts`.
77
+
78
+ ```bash
79
+ npx @iconia/react remove my-icons
80
+ ```
81
+
82
+ ---
83
+
84
+ ### `iconia pull`
85
+
86
+ Full re-download and regeneration of all (or one) collection. Replaces existing generated files.
87
+
88
+ ```bash
89
+ npx @iconia/react pull # all collections from config
90
+ npx @iconia/react pull --collection my-icons # one collection only
91
+ ```
92
+
93
+ ---
94
+
95
+ ### `iconia sync`
96
+
97
+ Incremental update: compares server fingerprints with the local `.iconia-lock.json` and only regenerates collections that have changes (new icons, updated icons, deleted icons).
98
+
99
+ ```bash
100
+ npx @iconia/react sync # all collections
101
+ npx @iconia/react sync --collection my-icons
102
+ ```
103
+
104
+ Output shows a diff per collection:
105
+
106
+ ```
107
+ my-icons: +3 added (arrow-right, chevron-down, x)
108
+ team-brand: ~1 updated (logo)
109
+ old-set: up to date
110
+ ```
111
+
112
+ ---
113
+
114
+ ### `iconia upload <path>`
115
+
116
+ Upload a single SVG file or an entire folder of SVGs to a collection on iconia.io.
117
+
118
+ ```bash
119
+ npx @iconia/react upload ./icons/arrow.svg --collection my-icons
120
+ npx @iconia/react upload ./icons/ --collection my-icons
121
+ npx @iconia/react upload ./icons/ --collection my-icons --tags ui,navigation
122
+ ```
123
+
124
+ Options:
125
+
126
+ - `-c, --collection <slug>` — target collection **(required)**
127
+ - `--tags <tags>` — comma-separated tags applied to all uploaded icons
128
+
129
+ ---
130
+
131
+ ## Using icons in your project
132
+
133
+ After `pull` or `sync`, import icons directly from the collection:
134
+
135
+ ```tsx
136
+ import { ArrowRight, Home, Settings } from "@iconia/react/my-icons";
137
+
138
+ export function App() {
139
+ return (
140
+ <div>
141
+ <ArrowRight className="size-5" />
142
+ <Home strokeWidth={1.5} />
143
+ <Settings color="gray" />
144
+ </div>
145
+ );
146
+ }
147
+ ```
148
+
149
+ All icons accept standard `SVGProps<SVGSVGElement>` and forward refs.
150
+
151
+ ---
152
+
153
+ ## Lockfile
154
+
155
+ `iconia sync` reads and writes `.iconia-lock.json` in your project root. It stores the fingerprint of every downloaded icon so that `sync` can detect changes without diffing SVG content.
156
+
157
+ Commit this file to version control so your team shares the same sync baseline.
158
+
159
+ ---
160
+
161
+ ## API key
162
+
163
+ Generate an API key at **iconia.io → Settings → API Keys**. The key authenticates CLI requests and scopes them to your collections.
164
+
165
+ ```bash
166
+ export ICONIA_API_KEY=ik_...
167
+ ```
168
+
169
+ Or add it to `.env` and load it via your preferred env tooling (`dotenv`, Vite, Next.js, etc.).
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env node
2
+ import{Command as eo}from"commander";import{Command as Ro}from"commander";import T from"fs";import Uo from"path";import z from"picocolors";var Lo=`import type { IconiaConfig } from 'iconia';
3
+
4
+ const config: IconiaConfig = {
5
+ apiKey: process.env.ICONIA_API_KEY ?? '',
6
+ collections: ['my-icons'],
7
+ };
8
+
9
+ export default config;
10
+ `,X=new Ro("init").description("Create an iconia.config.ts file in the current directory").action(()=>{let o=Uo.resolve(process.cwd(),"iconia.config.ts");if(T.existsSync(o)){console.log(z.yellow("iconia.config.ts already exists. Skipping."));return}T.writeFileSync(o,Lo),console.log(z.green("✓ Created iconia.config.ts")),console.log(`
11
+ Next steps:`),console.log(` 1. Set ${z.cyan("ICONIA_API_KEY")} in your environment`),console.log(` 2. Edit ${z.cyan("iconia.config.ts")} to add your collections`),console.log(` 3. Run ${z.cyan("npx iconia pull")} to fetch icons`),console.log(`
12
+ Import icons: ${z.cyan("import { MyIcon } from 'iconia/my-collection'")}`)});import{Command as qo}from"commander";import H from"picocolors";import zo from"ora";import{z as Q}from"zod";import N from"path";var Co=Q.object({apiKey:Q.string().min(1,"apiKey is required"),collections:Q.array(Q.string()).min(1,"At least one collection is required")}),Eo="https://api.iconia.io";async function E(){let o=N.resolve(process.cwd(),"iconia.config.ts"),i=N.resolve(process.cwd(),"iconia.config.js"),r;try{let c=await import(o);r=c.default??c}catch{try{let c=await import(i);r=c.default??c}catch{throw Error("Could not find iconia.config.ts or iconia.config.js\nRun `npx iconia init` to create one.")}}let n=Co.safeParse(r);if(!n.success){let c=n.error.issues.map((t)=>` - ${t.path.join(".")}: ${t.message}`).join(`
13
+ `);throw Error(`Invalid iconia config:
14
+ ${c}`)}return{...n.data,apiUrl:Eo}}function h(o){return{Authorization:`ApiKey ${o.apiKey}`,"Content-Type":"application/json"}}async function D(o){let i=await fetch(new URL("/v1/collections",o.apiUrl).toString(),{headers:h(o)});if(!i.ok){let n=await i.json().catch(()=>({}));throw Error(`API error ${i.status}: ${n.error??i.statusText}`)}return(await i.json()).collections}async function J(o,i){let r=new URL("/v1/collections/icons",o.apiUrl);r.searchParams.set("collections",i.join(","));let n=await fetch(r.toString(),{headers:h(o)});if(!n.ok){let t=await n.json().catch(()=>({}));throw Error(`API error ${n.status}: ${t.error??n.statusText}`)}return(await n.json()).icons}async function l(o,i){let r=await fetch(new URL("/v1/icons",o.apiUrl).toString(),{method:"POST",headers:h(o),body:JSON.stringify(i)});if(!r.ok){let c=await r.json().catch(()=>({}));throw Error(c.error??r.statusText)}return(await r.json()).icon}import u from"fs";import q from"path";import{fileURLToPath as Ko}from"url";import _o from"picocolors";import{optimize as so}from"svgo";function uo(o){return so(o,{plugins:["removeDoctype","removeXMLProcInst","removeComments","removeMetadata","removeTitle","removeDesc"]}).data.replace(/<svg([^>]*)>/i,(r,n)=>`<svg${n.replace(/\s+(width|height)=['"][^'"]*['"]/gi,"")}>`)}function x(o){let i={},r=/([\w:-]+)\s*=\s*(?:"([^"]*)"|'([^']*)')/g,n;while((n=r.exec(o))!==null){let c=n[1].replace(/^xlink:/,"").replace(/-([a-z])/g,(t,a)=>a.toUpperCase());i[c]=n[2]??n[3]??""}return i}function g(o){let i=[],r=0;while(r<o.length){let n=o.indexOf("<",r);if(n===-1)break;let c=o[n+1];if(c==="/"||c==="!"||c==="?"){let j=o.indexOf(">",n);r=j===-1?o.length:j+1;continue}let t=n+1,a=!1,m="";while(t<o.length){let j=o[t];if(a){if(j===m)a=!1}else if(j==='"'||j==="'")a=!0,m=j;else if(j===">")break;t++}if(t>=o.length)break;let I=o.slice(n+1,t),f=I.trimEnd().endsWith("/"),w=f?I.slice(0,I.lastIndexOf("/")).trim():I.trim(),y=w.search(/\s/),$=y===-1?w:w.slice(0,y);if(!$){r=t+1;continue}let L=y===-1?"":w.slice(y+1),O=x(L);if(r=t+1,f)i.push([$,O]);else{let j=`<${$}`,V=`</${$}>`,F=1,R=r;while(F>0&&R<o.length){let C=o.indexOf(j,R),d=o.indexOf(V,R);if(d===-1)break;if(C!==-1&&C<d)F++,R=C+j.length;else if(F--,F===0){let jo=o.slice(r,d),G=g(jo),Fo=G.length>0?[$,O,G]:[$,O];i.push(Fo),r=d+V.length}else R=d+V.length}if(F>0)i.push([$,O])}}return i}function oo(o){let i=uo(o),r=i.match(/<svg([^>]*)>/i),n=x(r?.[1]??"");delete n.xmlns,delete n.xmlnsXlink;let{viewBox:c}=n,t=c?{viewBox:c}:{},m=i.match(/<svg[^>]*>([\s\S]*)<\/svg>/i)?.[1]?.trim()??"";return{iconNode:g(m),svgAttrs:t}}function v(o){return o.replace(/[-_\s]+(.)/g,(i,r)=>r.toUpperCase()).replace(/^(.)/,(i,r)=>r.toUpperCase())}function io(o){if(o.length===0)return"";let i=["import { forwardRef, createElement } from 'react';","","const _r = (n) => n.map(([t, a, c], i) => createElement(t, { key: i, ...a }, ...(c ? _r(c) : [])));",""];for(let{name:r,iconNode:n,svgAttrs:c}of o){let t=v(r),a={viewBox:"0 0 24 24",...c},m=JSON.stringify(n),I=JSON.stringify(a);i.push(`export const ${t} = /*#__PURE__*/forwardRef(({ children, ...props }, ref) =>`,` createElement('svg', { ref, xmlns: 'http://www.w3.org/2000/svg', ...${I}, ...props },`,` ..._r(${m}),`," children"," )",");",`${t}.displayName = '${t}';`,"")}return i.join(`
15
+ `)}function ro(o){let i=["import type { ForwardRefExoticComponent, SVGProps, RefAttributes } from 'react';","","type IconComponent = ForwardRefExoticComponent<SVGProps<SVGSVGElement> & RefAttributes<SVGSVGElement>>;",""];for(let r of o)i.push(`export declare const ${v(r)}: IconComponent;`);return i.push(""),i.join(`
16
+ `)}function B(){return q.resolve(q.dirname(Ko(import.meta.url)),"..")}function Y(o,i){let r=[];for(let c of i)try{let{iconNode:t,svgAttrs:a}=oo(c.svgContent);r.push({name:c.name,iconNode:t,svgAttrs:a})}catch(t){console.warn(_o.yellow(` ⚠ Skipped ${c.name}: ${t.message}`))}if(r.length===0)return 0;let n=B();return u.writeFileSync(q.join(n,`${o}.js`),io(r),"utf-8"),u.writeFileSync(q.join(n,`${o}.d.ts`),ro(r.map((c)=>c.name)),"utf-8"),r.length}function Z(){let o=q.join(B(),"..","package.json");try{let i=JSON.parse(u.readFileSync(o,"utf-8")),r=i.exports??{};if(r["./*"]?.import?.startsWith("./dist/"))return;i.exports={".":r["."]??{types:"./dist/index.d.ts",import:"./dist/index.js",require:"./dist/index.cjs"},"./*":{import:"./dist/*.js",types:"./dist/*.d.ts"}},u.writeFileSync(o,JSON.stringify(i,null,2)+`
17
+ `,"utf-8")}catch{}}function no(o){let i=B(),r=q.join(i,`${o}.js`),n=q.join(i,`${o}.d.ts`);if(u.existsSync(r))u.unlinkSync(r);if(u.existsSync(n))u.unlinkSync(n)}import co from"fs";import Oo from"path";var Vo=".iconia-lock.json";function to(){return Oo.resolve(process.cwd(),Vo)}function K(){try{let o=co.readFileSync(to(),"utf-8");return JSON.parse(o)}catch{return{version:1,collections:{}}}}function _(o){co.writeFileSync(to(),JSON.stringify(o,null,2),"utf-8")}function A(o,i,r){return{...o,collections:{...o.collections,[i]:{icons:Object.fromEntries(r.map((n)=>[n.slug,n.fingerprint]))}}}}function fo(o,i){let{[i]:r,...n}=o.collections;return{...o,collections:n}}var mo=new qo("pull").description("Fetch icons and regenerate all collection files (replaces existing)").option("-c, --collection <slug>","Pull only this collection").action(async(o)=>{let i=zo("Loading config...").start(),r;try{r=await E()}catch(f){i.fail(H.red(f.message)),process.exit(1)}let n=o.collection?[o.collection]:r.collections;if(o.collection&&!r.collections.includes(o.collection))i.fail(H.red(`Collection '${o.collection}' is not in your config.`)),process.exit(1);i.text=`Fetching icons for ${n.join(", ")}...`;let c;try{c=await J(r,n)}catch(f){i.fail(H.red(`Failed to fetch icons: ${f.message}`)),process.exit(1)}if(c.length===0){i.warn(H.yellow("No icons found."));return}i.text=`Generating ${c.length} icon${c.length!==1?"s":""}...`;let t=new Map;for(let f of c){let w=t.get(f.collectionSlug)??[];w.push(f),t.set(f.collectionSlug,w)}let a=K(),m=0,I=[];for(let[f,w]of t){let y=Y(f,w);if(y===0)continue;m+=y,I.push(f),a=A(a,f,w.map(($)=>({slug:$.slug,fingerprint:$.fingerprint})))}if(_(a),Z(),i.succeed(H.green(`Generated ${m} icon${m!==1?"s":""} across ${I.length} collection${I.length!==1?"s":""}`)),I.length>0){let f=I[0]??"",w=v(t.get(f)?.[0]?.name??"MyIcon");console.log(`
18
+ Import icons:
19
+ ${H.cyan(`import { ${w} } from 'iconia/${f}'`)}`)}});import{Command as Jo}from"commander";import s from"picocolors";import vo from"ora";import p from"fs";import ao from"path";function e(){let o=ao.resolve(process.cwd(),"iconia.config.ts"),i=ao.resolve(process.cwd(),"iconia.config.js");if(p.existsSync(o))return o;if(p.existsSync(i))return i;return null}function S(o){let n=p.readFileSync(o,"utf-8").match(/collections:\s*\[([\s\S]*?)\]/)?.[1];if(!n)return null;let c=[],t=/['"]([^'"]+)['"]/g,a;while((a=t.exec(n))!==null){let m=a[1];if(m)c.push(m)}return c}function W(o,i){let r=p.readFileSync(o,"utf-8"),n=i.length===0?"[]":`[
20
+ ${i.map((t)=>` '${t}'`).join(`,
21
+ `)},
22
+ ]`,c=r.replace(/collections:\s*\[[\s\S]*?\]/,`collections: ${n}`);if(c===r)return!1;return p.writeFileSync(o,c,"utf-8"),!0}var yo=new Jo("add").description("Add a collection to your project (updates config and downloads icons)").argument("<slug>","Collection slug").action(async(o)=>{let i=vo("Loading config...").start(),r;try{r=await E()}catch(m){i.fail(s.red(m.message)),process.exit(1)}if(r.collections.includes(o))i.info(s.yellow(`Collection '${o}' is already in your config. Running pull...`));else{i.text="Verifying collection...";let m;try{m=await D(r)}catch(L){i.fail(s.red(`Failed to fetch collections: ${L.message}`)),process.exit(1)}if(!m.find((L)=>L.slug===o))i.fail(s.red(`Collection '${o}' not found. Available: ${m.map((L)=>L.slug).join(", ")||"none"}`)),process.exit(1);let f=e();if(!f)i.fail(s.red("Config file not found. Run `npx iconia init` first.")),process.exit(1);let y=[...S(f)??r.collections,o];if(!W(f,y))i.warn(s.yellow(`Could not update config automatically. Add '${o}' to collections in iconia.config.ts manually.`));else i.text=`Added '${o}' to config. Fetching icons...`}i.text=`Fetching icons for '${o}'...`;let n;try{n=await J(r,[o])}catch(m){i.fail(s.red(`Failed to fetch icons: ${m.message}`)),process.exit(1)}if(n.length===0){i.warn(s.yellow(`No icons in collection '${o}'.`));return}i.text=`Generating ${n.length} icon${n.length!==1?"s":""}...`;let c=Y(o,n),t=K();t=A(t,o,n.map((m)=>({slug:m.slug,fingerprint:m.fingerprint}))),_(t),i.succeed(s.green(`Added '${o}' — ${c} icon${c!==1?"s":""} generated`));let a=v(n[0]?.name??"Icon");console.log(`
23
+ Import icons:
24
+ ${s.cyan(`import { ${a} } from 'iconia/${o}'`)}`)});import{Command as Yo}from"commander";import M from"picocolors";var wo=new Yo("remove").description("Remove a collection from your project (updates config and deletes generated files)").argument("<slug>","Collection slug").action(async(o)=>{let i;try{i=await E()}catch(n){console.error(M.red(n.message)),process.exit(1)}if(!i.collections.includes(o))console.warn(M.yellow(`Collection '${o}' is not in your config.`));else{let n=e();if(n){let t=(S(n)??i.collections).filter((m)=>m!==o);if(!W(n,t))console.warn(M.yellow(`Could not update config automatically. Remove '${o}' from collections in iconia.config.ts manually.`))}}no(o);let r=K();r=fo(r,o),_(r),console.log(M.green(`✓ Removed collection '${o}'`))});import{Command as Ao}from"commander";import U from"picocolors";import Ho from"ora";var $o=new Ao("sync").description("Sync icons: add new, update changed, remove deleted — without full re-fetch").option("-c, --collection <slug>","Sync only this collection").action(async(o)=>{let i=Ho("Loading config...").start(),r;try{r=await E()}catch(y){i.fail(U.red(y.message)),process.exit(1)}let n=o.collection?[o.collection]:r.collections;if(o.collection&&!r.collections.includes(o.collection))i.fail(U.red(`Collection '${o.collection}' is not in your config.`)),process.exit(1);i.text=`Fetching icons for ${n.join(", ")}...`;let c;try{c=await J(r,n)}catch(y){i.fail(U.red(`Failed to fetch icons: ${y.message}`)),process.exit(1)}let t=new Map;for(let y of c){let $=t.get(y.collectionSlug)??[];$.push(y),t.set(y.collectionSlug,$)}let a=K(),m=0,I=0,f=0,w=0;for(let y of n){let $=t.get(y)??[],L=a.collections[y]?.icons??{},O=new Map($.map((d)=>[d.slug,d])),j=new Set(Object.keys(L)),V=new Set(O.keys()),F=[...V].filter((d)=>!j.has(d)),R=[...j].filter((d)=>!V.has(d)),C=[...V].filter((d)=>j.has(d)&&L[d]!==O.get(d).fingerprint);if(F.length===0&&R.length===0&&C.length===0){console.log(U.dim(` ${y}: up to date`));continue}if(F.length>0)console.log(U.green(` ${y}: +${F.length} added`)+U.dim(` (${F.slice(0,5).join(", ")}${F.length>5?"…":""})`));if(C.length>0)console.log(U.blue(` ${y}: ~${C.length} updated`)+U.dim(` (${C.slice(0,5).join(", ")}${C.length>5?"…":""})`));if(R.length>0)console.log(U.red(` ${y}: -${R.length} removed`)+U.dim(` (${R.slice(0,5).join(", ")}${R.length>5?"…":""})`));if($.length>0)Y(y,$);a=A(a,y,$.map((d)=>({slug:d.slug,fingerprint:d.fingerprint}))),m+=F.length,I+=C.length,f+=R.length,w++}if(_(a),w>0)Z();if(w===0)i.succeed(U.green("Everything is up to date."));else i.succeed(U.green(`Sync complete: ${m} added, ${I} updated, ${f} removed across ${w} collection${w!==1?"s":""}`))});import{Command as Po}from"commander";import k from"fs";import b from"path";import P from"picocolors";import bo from"ora";function po(o){return b.basename(o,b.extname(o)).toLowerCase().replace(/\s+/g,"-").replace(/[^a-z0-9-]/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")}function Qo(o){return o.split("-").map((i)=>i.charAt(0).toUpperCase()+i.slice(1)).join(" ")}function Zo(o){let i=k.statSync(o);if(i.isFile()){if(!o.endsWith(".svg"))throw Error(`File '${o}' is not an SVG.`);return[o]}if(i.isDirectory())return k.readdirSync(o).filter((r)=>r.endsWith(".svg")).map((r)=>b.join(o,r));throw Error(`'${o}' is not a file or directory.`)}var Io=new Po("upload").description("Upload SVG file(s) to an Iconia collection").argument("<path>","SVG file or directory of SVGs").requiredOption("-c, --collection <slug>","Target collection slug").option("--tags <tags>","Comma-separated tags to apply to all uploaded icons").action(async(o,i)=>{let r=bo("Loading config...").start(),n;try{n=await E()}catch(f){r.fail(P.red(f.message)),process.exit(1)}let c;try{c=Zo(b.resolve(process.cwd(),o))}catch(f){r.fail(P.red(f.message)),process.exit(1)}if(c.length===0){r.warn(P.yellow("No SVG files found."));return}let t=i.tags?i.tags.split(",").map((f)=>f.trim()).filter(Boolean):[];r.text=`Uploading ${c.length} file${c.length!==1?"s":""} to '${i.collection}'...`;let a=0,m=0,I=[];for(let f of c){let w=po(f);if(!w){I.push(`${b.basename(f)}: could not derive a valid slug`),m++;continue}let y=k.readFileSync(f,"utf-8");try{await l(n,{collectionSlug:i.collection,name:Qo(w),slug:w,svgContent:y,tags:t}),a++,r.text=`Uploading... (${a}/${c.length})`}catch($){I.push(`${b.basename(f)}: ${$.message}`),m++}}if(m===0)r.succeed(P.green(`Uploaded ${a} icon${a!==1?"s":""} to '${i.collection}'`));else{r.warn(P.yellow(`Uploaded ${a}, failed ${m}`));for(let f of I)console.log(P.dim(` ✗ ${f}`))}});var So=new eo("iconia").version("0.1.0").description("CLI for fetching and generating React icon components from Iconia").addCommand(X).addCommand(yo).addCommand(wo).addCommand(mo).addCommand($o).addCommand(Io);So.parse(process.argv);
package/dist/index.cjs ADDED
@@ -0,0 +1 @@
1
+ var{defineProperty:m,getOwnPropertyNames:a,getOwnPropertyDescriptor:d}=Object,y=Object.prototype.hasOwnProperty;function G(e){return this[e]}var S=(e)=>{var o=(c??=new WeakMap).get(e),t;if(o)return o;if(o=m({},"__esModule",{value:!0}),e&&typeof e==="object"||typeof e==="function"){for(var n of a(e))if(!y.call(o,n))m(o,n,{get:G.bind(e,n),enumerable:!(t=d(e,n))||t.enumerable})}return c.set(e,o),o},c;var V=(e)=>e;function I(e,o){this[e]=V.bind(null,o)}var g=(e,o)=>{for(var t in o)m(e,t,{get:o[t],enumerable:!0,configurable:!0,set:I.bind(o,t)})};var E={};g(E,{createIconiaIcon:()=>l});module.exports=S(E);var r=require("react");function i(e){return e.map(([o,t,n],p)=>r.createElement(o,{key:p,...t},...n?i(n):[]))}function l(e,o,t={}){let n=r.forwardRef(({children:p,...s},f)=>r.createElement("svg",{ref:f,xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",...t,...s},...i(o),p));return n.displayName=e,n}
@@ -0,0 +1,22 @@
1
+ // Generated by dts-bundle-generator v9.5.1
2
+
3
+ import { ForwardRefExoticComponent, RefAttributes, SVGProps } from 'react';
4
+ import { z } from 'zod';
5
+
6
+ export type IconNodeElement = [
7
+ tagName: string,
8
+ attrs: Record<string, string>,
9
+ children?: IconNodeElement[]
10
+ ];
11
+ export type IconNode = IconNodeElement[];
12
+ declare const configSchema: z.ZodObject<{
13
+ apiKey: z.ZodString;
14
+ collections: z.ZodArray<z.ZodString>;
15
+ }, z.core.$strip>;
16
+ export type IconiaConfig = z.infer<typeof configSchema> & {
17
+ apiUrl?: string;
18
+ };
19
+ export type IconComponent = ForwardRefExoticComponent<SVGProps<SVGSVGElement> & RefAttributes<SVGSVGElement>>;
20
+ export declare function createIconiaIcon(displayName: string, iconNode: IconNode, svgAttrs?: Record<string, string>): IconComponent;
21
+
22
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ import{forwardRef as s,createElement as p}from"react";function m(o){return o.map(([t,n,e],r)=>p(t,{key:r,...n},...e?m(e):[]))}function a(o,t,n={}){let e=s(({children:r,...c},i)=>p("svg",{ref:i,xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",...n,...c},...m(t),r));return e.displayName=o,e}export{a as createIconiaIcon};
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@iconia/react",
3
+ "version": "0.1.0-dev.52c1e49",
4
+ "description": "Fetch and generate React icon components from your Iconia collections",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
14
+ },
15
+ "./*": {
16
+ "import": "./dist/*.js",
17
+ "types": "./dist/*.d.ts"
18
+ }
19
+ },
20
+ "peerDependencies": {
21
+ "react": ">=18"
22
+ },
23
+ "bin": {
24
+ "iconia": "./dist/cli/index.js"
25
+ },
26
+ "scripts": {
27
+ "build": "bun build.ts",
28
+ "typecheck": "tsc --noEmit"
29
+ },
30
+ "dependencies": {
31
+ "commander": "14.0.3",
32
+ "ora": "9.3.0",
33
+ "picocolors": "1.1.1",
34
+ "prettier": "3.8.1",
35
+ "svgo": "4.0.1",
36
+ "zod": "4.3.6"
37
+ },
38
+ "devDependencies": {
39
+ "@types/bun": "1.3.11",
40
+ "@types/node": "25.5.2",
41
+ "@types/react": "19.2.14",
42
+ "bun-plugin-dts": "0.4.0",
43
+ "typescript": "6.0.2"
44
+ },
45
+ "files": [
46
+ "dist"
47
+ ],
48
+ "keywords": [
49
+ "react",
50
+ "nodejs",
51
+ "svg",
52
+ "cli",
53
+ "typescript",
54
+ "icons",
55
+ "bun"
56
+ ],
57
+ "license": "MIT",
58
+ "author": "Wyesoftware",
59
+ "repository": {
60
+ "type": "git",
61
+ "url": "git+https://github.com/Wyesoftware/iconia.git"
62
+ },
63
+ "bugs": {
64
+ "url": "https://github.com/Wyesoftware/iconia/issues"
65
+ },
66
+ "homepage": "https://github.com/Wyesoftware/iconia#readme"
67
+ }