tmw-icons
v0.1.3
Published
Componente icona SVG standalone, self-contained — nessuna dipendenza da Angular Material/CDK. Artwork vendorizzato da Tabler Icons (MIT).
Readme
tmw-icons
Libreria Angular con un unico componente icona SVG (<tmw-icon>), standalone e
self-contained: nessuna dipendenza da Angular Material/CDK né da font esterni
(niente ligature font-icon). Ogni icona è renderizzata inline (path SVG diretti nel
DOM) a partire da un registry di dati vettoriali interno al pacchetto — sostituisce
<mat-icon> per il set fisso di icone usato dalle librerie tmw-*.
Il registry attuale (tmw-icons.registry.ts) contiene 232 icone, un sottoinsieme
curato — non l'intero set Tabler (~6000 icone). Vedi Perché un sottoinsieme e non
l'intero set Tabler.
Installazione / import
Nel workspace tmw-suite la libreria si importa come le altre librerie tmw-*:
import { TmwIconComponent } from 'tmw-icons'; // pacchetto buildato (dist/tmw-icons)
// oppure, nell'app demo dentro questo stesso repo, direttamente da sorgente:
import { TmwIconComponent } from 'projects/tmw-icons/src/public-api';TmwIconComponent è standalone: si importa direttamente nell'array imports del
componente/modulo che lo usa, senza NgModule dedicato.
Uso base
<tmw-icon name="settings"></tmw-icon>
<tmw-icon name="chevron-right" size="16" ariaLabel="Espandi"></tmw-icon>
<tmw-icon name="heart" variant="filled" [style.color]="'#c0392b'"></tmw-icon>Il colore segue il color CSS ereditato dal contesto (stroke/fill currentColor),
esattamente come <mat-icon>.
API del componente (@Input)
| Input | Tipo | Default | Descrizione |
|---|---|---|---|
| name | TmwIconName \| (string & {}) | (obbligatorio) | Nome icona nel registry. Il tipo unisce l'autocomplete su TmwIconName con string generica, per i binding dinamici alimentati da valori arbitrari (es. ConfigAction.icon letto da skin/config DB) che a compile-time non possono essere ristretti al literal union. |
| size | string \| number \| null | null | Lato del quadrato icona: numero (px) o stringa CSS (es. '1.5em'). Se null, la dimensione la decide il CSS del contesto (default 24px da :host, sovrascrivibile con tmw-icon { width/height: ... }). Impostato esplicitamente, vince sempre sul CSS esterno (stile inline). |
| ariaLabel | string \| undefined | undefined | Etichetta accessibile. Se assente l'icona è aria-hidden="true" (decorativa) — coerente con l'uso tipico accanto a un testo o dentro un bottone già etichettato. Se valorizzata, l'icona diventa role="img" con l'aria-label indicata. |
| variant | 'outline' \| 'filled' \| undefined | segue il default globale | Stile di disegno, rispecchia le due varianti Tabler: outline (stroke, storicamente il default) e filled (fill pieno). Se non impostato esplicitamente, segue TmwIconDefaultsService — vedi Default globali. |
| strokeWidth | string \| number \| undefined | segue il default globale | Spessore del tratto in variante outline (es. 1.5); ignorato in filled. Stessa logica di fallback di variant. |
Non tutte le icone hanno una controparte filled (Tabler la offre solo per un
sottoinsieme del set outline): se si richiede una variante assente per una data icona,
TmwIconComponent ricade sull'altra variante disponibile, con un console.warn.
Se name non è presente nel registry (es. un vecchio nome Material/FontAwesome non
ancora migrato), il componente non renderizza nulla e stampa un console.warn — non fa
crashare l'host, anche quando il nome arriva da un consumer esterno.
Default globali (TmwIconDefaultsService)
TmwIconDefaultsService (providedIn: 'root') espone i default di variant e
strokeWidth per tutte le <tmw-icon> dell'app che non impostano esplicitamente il
proprio [variant]/[strokeWidth]:
constructor(private readonly iconDefaults: TmwIconDefaultsService) {}
applyBrandStyle(): void {
this.iconDefaults.setDefaults({ variant: 'filled', strokeWidth: 1.5 });
}Una singola chiamata a setDefaults(...) si propaga a ogni <tmw-icon> già montata
nell'app, senza reload — pensato per essere pilotato dallo Skin Editor di TMED
(sezione "Icone"). Le icone con un [variant]/[strokeWidth] esplicito non vengono
toccate: l'@Input esplicito ha sempre precedenza sul default globale.
setDefaults accetta un oggetto parziale (Partial<TmwIconDefaults>): si può
aggiornare solo variant o solo strokeWidth in una chiamata.
Superficie pubblica (public-api.ts)
export * from './lib/components/tmw-icon/tmw-icon.component'; // TmwIconComponent, TmwIconNameInput, TmwIconVariant
export * from './lib/registry/tmw-icons.registry'; // TMW_ICONS, TmwIconDefinition, TmwIconName
export * from './lib/services/tmw-icon-defaults.service'; // TmwIconDefaultsService, TmwIconDefaultsTmwIconName è il literal union generato dalle chiavi del registry — usarlo per
tipizzare variabili/@Input che devono restare allineati all'elenco reale delle icone
disponibili (l'elenco completo si ottiene anche a runtime con
Object.keys(TMW_ICONS) as TmwIconName[], senza dover mantenere una lista a mano — vedi
l'esempio nel playground demo, test-tmw-icons.component.ts).
Origine dell'artwork e licenza
I path SVG sono estratti da Tabler Icons
(repo), licenza MIT. Il nome originale
dell'icona in Tabler è conservato nel campo source di ogni voce del registry (per
tracciabilità/aggiornamento). Vedi THIRD-PARTY-LICENSES.md
per la nota di copyright completa.
Perché un sottoinsieme e non l'intero set Tabler?
TmwIconComponent risolve l'icona con TMW_ICONS[name], dove name è una stringa
a runtime (necessario per i valori dinamici alimentati da skin/config DB — vedi
TmwIconNameInput sopra). Questo impedisce a qualunque bundler di fare tree-shaking del
registry: includere l'intero set Tabler (~6000 icone) gonfierebbe il bundle di ~18× in
ogni app consumer, anche quella che ne usa 20. Per questo si importa una nuova icona
solo quando serve davvero, con il flusso descritto sotto.
Aggiungere una nuova icona da Tabler
Per aggiungere un'icona al registry, buildare, bumpare la versione e pubblicare su npm in un solo passaggio, usare lo slash command Claude Code:
/import-icon-from-tabler <nome-icona-tabler>Il nome deve essere quello canonico usato su https://tabler.io/icons (minuscolo,
lettere/numeri/trattini — es. trash-off, brand-github, mood-confuzed). Si possono
importare più icone in un colpo solo, separandole con la virgola:
/import-icon-from-tabler trash-off,brand-github,mood-confuzedIl comando è disponibile sia in questo repo sia in TMED (stesso file in
.claude/commands/import-icon-from-tabler.md, entrambi con path assoluti verso questo
repo — l'unico posto dove vive davvero il registry).
Cosa fa in automatico:
- Esegue
scripts/import-tabler-icon.js <nome>, che:- scarica da GitHub entrambe le varianti SVG dell'icona,
outlineefilled(quest'ultima solo se Tabler la offre per quel nome — non è un errore se manca, v. sopra); - estrae i
<path d="...">da ciascun SVG; - inserisce una nuova voce nel registry (
tmw-icons.registry.ts), prima del marcatore finale} as const;.
- scarica da GitHub entrambe le varianti SVG dell'icona,
- Verifica che la libreria compili (
ng build tmw-icons --configuration=production) — se fallisce, si ferma senza pubblicare. - Bump di versione patch (
npm version patchdentroprojects/tmw-icons). - Rebuild con la versione aggiornata.
- Pubblica su npm (
npm publishdadist/tmw-icons) — azione reale e visibile sul registro pubblico, eseguita senza ulteriore conferma perché è esplicitamente lo scopo del comando quando invocato con un nome icona valido. - Riporta il numero di path outline/filled trovati e la nuova versione pubblicata.
Esiti possibili dello script (il comando si ferma e non tocca altro se l'esito non è un semplice successo):
- icona già presente nel registry → nessuna azione, nessuna build/publish;
- nome inesistente su Tabler (slug sbagliato) → verificare il nome esatto su tabler.io/icons;
- errore di parsing/formato del registry → da leggere e capire prima di correggere a mano, non un caso da "riprovare alla cieca".
tmw-suite stesso e TMED consumano tmw-icons via file: (symlink verso
tmw-suite/dist/tmw-icons): vedono la nuova icona immediatamente, senza
reinstallare nulla. Un consumer esterno reale andrebbe invece aggiornato con
npm update tmw-icons.
Import manuale (senza build/publish)
Per il solo inserimento nel registry, senza i passi successivi di build/versioning/
pubblicazione (utile per iterare rapidamente durante lo sviluppo), lo script è
invocabile anche a mano da dentro tmw-suite/:
npm run import-icon -- <nome-icona>[,<nome-icona>...]Build
ng build tmw-icons --configuration=production # output in tmw-suite/dist/tmw-icons