diff --git a/docs/USAGE.md b/docs/USAGE.md
new file mode 100644
index 0000000..43ec592
--- /dev/null
+++ b/docs/USAGE.md
@@ -0,0 +1,356 @@
+# @armco/icon — Usage Guide
+
+## Overview
+
+`@armco/icon` is a flexible, theme-aware React Icon component. It renders icons from multiple sources: **react-icons identifiers**, SVG strings, base64-encoded SVGs, image URLs, and raw image elements. Icons fetched via identifier or URL are cached in a global registry to prevent duplicate network requests.
+
+The component is a React class component wrapped with the `withTheme` HOC from `@armco/utils`, giving it automatic access to the current theme context.
+
+## Installation
+
+```bash
+npm install @armco/icon
+```
+
+Peer dependencies: `react`, `react-dom` (^18.x)
+
+---
+
+## Quick Start
+
+```tsx
+import Icon from "@armco/icon"
+
+// Identifier-based (most common usage)
+
+
+
+```
+
+---
+
+## Icon Identifier Format
+
+The most common way to use the component is with **react-icons identifiers**:
+
+```
+.
+```
+
+- **category** — 2–3 letter prefix matching a [react-icons](https://react-icons.github.io/react-icons/) library:
+ - `ai` — Ant Design Icons
+ - `bi` — Bootstrap Icons
+ - `bs` — Bootstrap Icons (alt)
+ - `ci` — Circum Icons
+ - `cg` — css.gg
+ - `di` — Devicons
+ - `fa` — Font Awesome
+ - `fc` — Flat Color Icons
+ - `fi` — Feather Icons
+ - `gi` — Game Icons
+ - `go` — Github Octicons
+ - `gr` — Grommet Icons
+ - `hi` — Heroicons
+ - `im` — IcoMoon
+ - `io` — Ionicons
+ - `lu` — Lucide
+ - `md` — Material Design Icons
+ - `pi` — Phosphor Icons
+ - `ri` — Remix Icons
+ - `rx` — Radix Icons
+ - `si` — Simple Icons
+ - `sl` — Simple Line Icons
+ - `tb` — Tabler Icons
+ - `ti` — Typicons
+ - `vsc` — VS Code Icons
+ - `wi` — Weather Icons
+
+- **IconName** — the PascalCase icon name from that library.
+
+### Resolution
+
+When an identifier like `hi.HiViewBoards` is passed, the component:
+1. Detects it as an `identifier` type via regex: `/^[a-zA-Z0-9]{2,3}[.\/][a-zA-Z0-9]+$/`
+2. Converts dots to slashes: `hi.HiViewBoards` → `/icon/hi/HiViewBoards`
+3. Fetches the SVG from the icon server at that path
+4. Caches the result in a global `iconRegistry` (keyed by the original identifier string)
+5. Subsequent uses of the same identifier skip the network call
+
+---
+
+## Props API
+
+### `IconProps`
+
+| Prop | Type | Default | Description |
+|------|------|---------|-------------|
+| `icon` | `string \| object \| IconSource` | — | The icon source. Can be an identifier (`"hi.HiViewBoards"`), SVG string, base64 string, URL, or an `IconSource` object. |
+| `attributes` | `IconAttributes` | — | Sizing, colors, classes, and inline styles. |
+| `events` | `IconEvents` | — | Event handlers: `onClick`, `onMouseEnter`, `onMouseLeave`. |
+| `fillPath` | `boolean \| number[]` | — | Apply fill/stroke colors to specific `` elements inside the SVG. `true` = all paths, `[0, 2]` = paths at those indices. |
+| `toggled` | `boolean` | `false` | Initial toggle state. Toggles on click. Affects which colors are applied. |
+| `hoverShadow` | `boolean` | `false` | Adds a box-shadow on hover. |
+| `slot` | `ArPopoverSlots` | — | Popover slot assignment (`"popover"` or `"anchor"`). |
+| `theme` | `ArThemes` | auto | Injected by `withTheme` HOC. Can be overridden. |
+
+### `IconSource` (explicit type specification)
+
+```ts
+interface IconSource {
+ source: string | object
+ type: ArIconSourceTypes // "URL" | "identifier" | "svgString" | "b64" | "raw"
+}
+```
+
+Use this when you need to explicitly specify the source type instead of relying on auto-detection:
+
+```tsx
+
+```
+
+### `IconAttributes`
+
+```ts
+interface IconAttributes {
+ height?: string // e.g., "24px", "2rem"
+ width?: string
+ size?: string // Shorthand — sets both height and width
+ strokeWidth?: string // SVG stroke-width attribute
+ colors?: {
+ fillColor?: string
+ strokeColor?: string
+ strokeWidth?: string
+ toggleFillColor?: string
+ toggleStrokeColor?: string
+ hoverFillColor?: string
+ hoverStrokeColor?: string
+ darkFillColor?: string
+ darkStrokeColor?: string
+ darkToggleFillColor?: string
+ darkToggleStrokeColor?: string
+ darkHoverFillColor?: string
+ darkHoverStrokeColor?: string
+ }
+ styles?: CSSProperties // React inline styles applied to the SVG element
+ classes?: string // CSS class names appended to the SVG element
+}
+```
+
+### `IconEvents`
+
+```ts
+interface IconEvents {
+ onClick?: (e?: MouseEvent) => void
+ onMouseEnter?: (e?: MouseEvent) => void
+ onMouseLeave?: (e?: MouseEvent) => void
+}
+```
+
+---
+
+## Source Types
+
+The component auto-detects the icon source type. Detection order:
+
+| Type | Detection Rule | Example |
+|------|---------------|---------|
+| `identifier` | Matches regex `^[a-zA-Z0-9]{2,3}[./][a-zA-Z0-9]+$` | `"hi.HiViewBoards"` |
+| `URL` | Starts with `http://` or `https://` | `"https://cdn.example.com/icon.svg"` |
+| `b64` | Starts with `data:image/svg+xml;base64,` | Base64-encoded SVG data URI |
+| `svgString` | Starts with `
+
+
+```
+
+### Sizing
+
+```tsx
+// Using size shorthand (sets both width and height)
+
+
+// Using explicit width/height
+
+
+// Using inline styles
+
+```
+
+### Colors
+
+```tsx
+// Fill color
+
+
+// Stroke color
+
+
+// Hover colors
+
+
+// Dark theme colors (applied when theme is DARK1)
+
+```
+
+### Toggle State
+
+```tsx
+// Icon toggles fill on click
+
+```
+
+### Path-Level Coloring
+
+```tsx
+// Apply colors to all elements inside the SVG
+
+
+// Apply colors to specific paths by index
+
+```
+
+### Events
+
+```tsx
+ console.log("clicked", e),
+ onMouseEnter: () => console.log("hovered"),
+ onMouseLeave: () => console.log("left"),
+ }}
+/>
+```
+
+### CSS Classes
+
+```tsx
+
+```
+
+### Hover Shadow
+
+```tsx
+
+```
+
+### SVG String Source
+
+```tsx
+
+```
+
+### URL Source
+
+```tsx
+
+```
+
+### Explicit IconSource
+
+```tsx
+
+
+```
+
+---
+
+## Exported Utilities
+
+The package also exports helper functions and types from `index.ts`:
+
+### Helper Functions (`helper.ts`)
+
+| Function | Signature | Description |
+|----------|-----------|-------------|
+| `inferIconType` | `(source: string \| object) => ArIconSourceTypes` | Auto-detects the icon source type from the input. |
+| `parseSvgString` | `(svgString: string) => SVGSVGElement` | Parses an SVG markup string into an `SVGSVGElement`. |
+| `parseSvgB64String` | `(b64: string) => SVGSVGElement` | Decodes a base64 SVG string and parses it. |
+| `createElementFromSvg` | `(svg: SVGSVGElement) => ReactNode` | Converts an `SVGSVGElement` DOM node into a React element tree. |
+| `applyStyles` | `(milk, props, state) => SVGSVGElement` | Applies sizing, colors, classes, and styles to a cloned SVG element. |
+| `getFillColor` | `(props, state?) => string \| undefined` | Resolves the correct fill color based on theme, hover, and toggle state. |
+| `getStrokeColor` | `(props, state?) => string \| undefined` | Resolves the correct stroke color based on theme, hover, and toggle state. |
+| `placeholder` | `SVGSVGElement` | A default placeholder SVG (empty rectangle) used when icon loading fails. |
+
+### Enums (`enums.ts`)
+
+| Enum | Values | Description |
+|------|--------|-------------|
+| `ArIconSourceTypes` | `URL`, `identifier`, `svgString`, `b64`, `raw` | Icon source type classification. |
+| `ArIconTileTypes` | `COMFY`, `COMPACT`, `LIST` | Icon tile display modes. |
+| `ArValidImageMimeTypes` | `JPEG`, `PNG`, `GIF`, `WEBP`, `SVG`, `TIFF`, `BMP`, `ICON` | Valid image MIME types for content-type detection. |
+| `ArPopoverSlots` | `POPOVER`, `ANCHOR` | Slot assignment for popover usage. |
+
+### Types (`types.ts`)
+
+| Type | Description |
+|------|-------------|
+| `IconProps` | Full props interface for the Icon component. |
+| `IconSource` | Explicit `{ source, type }` icon descriptor. |
+| `IconAttributes` | Sizing, colors, classes, styles. |
+| `IconEvents` | Click, hover event handlers. |
+| `IconState` | Internal component state (hovered, toggled, milk, shake, type). |
+| `IconRegistry` | Global cache type: `{ [key]: { promise?, icon? } }`. |
+| `IconStyles` | Simplified style descriptor (fill, stroke, bg). |
+| `IconResponse` | Server API response shape for icon data. |
+
+---
+
+## Architecture
+
+1. **Icon Resolution**: The `parseIconDescriptor` method determines the source type and either fetches from the server (identifier/URL) or parses locally (SVG string, base64, raw).
+2. **Registry Caching**: A module-level `iconRegistry` object caches both the fetch promise and the resolved icon. This prevents duplicate network requests when the same icon is used multiple times.
+3. **Style Application**: On every render-relevant state change (hover, toggle, attribute change), `applyStyles` clones the SVG DOM node and applies colors, sizing, classes, and inline styles.
+4. **React Conversion**: The styled SVG DOM node is converted to a React element tree via `createElementFromSvg`, enabling React event binding.
+5. **Theme Awareness**: The `withTheme` HOC injects the current theme. Color resolution functions (`getFillColor`, `getStrokeColor`) select the appropriate color variant based on theme + hover + toggle state.
+
+---
+
+## CSS
+
+The component applies the class `ar-Icon` to all rendered SVG elements. Additional classes can be added via `attributes.classes`.
+
+```scss
+.ar-Icon {
+ transition: all 0.3s;
+
+ &:hover.hover-shadow {
+ box-shadow: 0px 4px 8px var(--ar-shadow);
+ }
+}
+```
diff --git a/package.json b/package.json
index aa31149..a601aca 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@armco/icon",
- "version": "0.0.12",
+ "version": "0.0.13",
"type": "module",
"main": "build/cjs/index.js",
"module": "build/es/index.js",
@@ -28,8 +28,8 @@
}
},
"peerDependencies": {
- "react": "^18.2.0",
- "react-dom": "^18.3.1"
+ "react": ">=18.0.0",
+ "react-dom": ">=18.0.0"
},
"prettier": "prettier-config-nick",
"repository": {
diff --git a/publish-local.sh b/publish-local.sh
index 6e75b05..8e80110 100755
--- a/publish-local.sh
+++ b/publish-local.sh
@@ -6,11 +6,22 @@ set -e
npm run build
cp package.json build/
-sed -i '' -E 's/"build"/"*"/' build/package.json
-sed -i '' 's#"build/cjs/Icon.js"#"cjs/Icon.js"#' build/package.json
-sed -i '' 's#"build/es/Icon.js"#"es/Icon.js"#' build/package.json
-sed -i '' 's#"build/types/Icon.d.ts"#"types/Icon.d.ts"#' build/package.json
+# Use Node.js for portable package.json normalization
+PKG_PATH="$(pwd)/build/package.json" node - <<'EOF'
+const fs = require('fs');
+const path = process.env.PKG_PATH;
+const pkg = JSON.parse(fs.readFileSync(path, 'utf8'));
+pkg.private = false;
+delete pkg.scripts;
+delete pkg.devDependencies;
+if (!pkg.files) pkg.files = ['*'];
+else pkg.files = pkg.files.map(x => x === 'build' ? '*' : x);
+['main','module','types'].forEach(k => {
+ if (pkg[k]) pkg[k] = pkg[k].replace(/^\.??\/build\//, '').replace(/^build\//, '');
+});
+fs.writeFileSync(path, JSON.stringify(pkg, null, 2) + '\n');
+EOF
cd build
npm pack --pack-destination ~/__Projects__/Common
\ No newline at end of file