Repository navigation
Iconos
English · Español
Todos los iconos de la app son iconos de Iconify que pinta un único componente, <Icono icon="prefijo:nombre">. Hay dos clases: los que el código escribe tal cual (van dentro de la app desde la compilación, se pintan al momento y sin red) y los que elige la persona con el selector de iconos (por ahora, el icono de una etiqueta de la biblioteca), que Rust baja una vez de la API de Iconify y guarda en disco para que se vean sin red.
La única excepción es src/components/ui/: las primitivas de shadcn/judlex son de solo lectura y siguen importando lucide-react (las flechas de los selectores y los menús, la cruz de cerrar de los diálogos, la marca de las casillas). Todo lo que está fuera de esa carpeta usa <Icono>.
| Fichero | Responsabilidad |
|---|---|
src/components/icono.tsx |
Icono({ icon, size, ... }): un <svg> con el viewBox y el cuerpo del icono. Los incluidos salen de INCLUIDOS; cualquier otro id se pide con useIconos().pedir(id) y su hueco (24 px de fábrica, o la clase size-*) se guarda vacío hasta que llega, así nada salta. Un id vacío no pinta nada. |
src/lib/iconos/incluidos.ts |
Generado por scripts/iconos.mjs (no se edita a mano, fuera de Biome): INCLUIDOS: Record<id, { body, vb }>, los datos de cada id de icono escrito tal cual en src/. |
scripts/iconos.mjs |
Recorre src/**/*.{ts,tsx} (sin node_modules, bindings, assets, __tests__ ni los ficheros de test), encuentra cada prefijo:nombre entre comillas, lo busca en las colecciones de @iconify/json (con los alias resueltos por getIconData/iconToSVG de @iconify/utils) y escribe incluidos.ts. Las cadenas entre comillas que no son iconos (16:9, pbimg:…) se caen solas porque su prefijo no es una colección; un id cuya colección existe pero cuyo nombre no, es un error. --check falla si el fichero no está al día. |
src/components/selector-icono.tsx |
SelectorIcono({ valor, onChange, quitable }): el selector de iconos. |
src/stores/iconos-store.ts |
useIconos: datos (los iconos que Rust ya devolvió en esta sesión), pedir(id) (junta los ids pedidos en un mismo pintado, 16 ms, en un único iconos_datos; si falla, se pueden volver a pedir) y recibir. |
src-tauri/src/iconos.rs |
El cliente de Iconify: catálogo, búsqueda, datos de iconos, iconos elegidos, limpieza del SVG. |
src-tauri/src/commands/iconos.rs |
Los cinco comandos de abajo. |
Dependencias: @iconify/utils (dependencia de ejecución, la usa el script) y @iconify/json (dependencia de desarrollo con todas las colecciones; en ignoreDependencies de knip.json porque solo la lee el script desde node_modules).
flowchart LR
SRC["src/**/*.tsx<br/>"game-icons:crown""] -->|pnpm iconos| GEN["src/lib/iconos/incluidos.ts"]
JSON["@iconify/json"] --> GEN
GEN --> ICONO["<Icono>"]
ICONO -->|id no incluido| STORE["useIconos.pedir"] -->|iconos_datos| RUST["iconos.rs"]
Tras añadir o cambiar un id de icono en el código, pnpm iconos. pnpm check ejecuta pnpm check:iconos (node scripts/iconos.mjs --check), así que olvidarse de regenerarlo falla en local y en el CI. Por qué generarlo en vez de importar icono a icono: un solo componente para las dos clases de icono (escritos y elegidos), sin red para los iconos propios de la app, y en el paquete solo entran los iconos que se usan.
Un id montado con una plantilla (`lucide:${x}`) no lo ve el script: hay que escribir los ids enteros en algún sitio del código (una tabla) para que entren. No incluido quiere decir bajado de la red al usarlo, y los iconos propios de la app nunca deben necesitarla.
Qué colección: lucide:* para los iconos generales de la interfaz (la misma familia que usaba la app antes), game-icons:* para los conceptos de juego de las pantallas de «Jugar» y del registro de la partida: veneno (frasco), monarca (corona), iniciativa (puerta de mazmorra), bendición de la ciudad (castillo), cementerio (lápida), el sol y la luna del día/noche, «no se endereza» (candado), fuera de fase (portal), notas temporales (reloj de arena), etc. Deducido: otras colecciones valen cuando encajan, siempre que el id se escriba tal cual.
SelectorIcono es un botón con el icono actual (o un hueco) que abre un popover, como el IconPicker de la web del proyecto, pero cada petición pasa por Rust porque la vista web nunca sale a internet:
-
Elegir colección: todas las colecciones visibles de Iconify (
iconos_colecciones, por categoría y nombre, con cuántos iconos tiene cada una) más «Todas las colecciones», que busca por nombre en todas (iconos_buscar). Se abre en la colección del icono actual, o engame-iconssi no hay. -
Filtro: dentro de una colección, un filtro local sobre sus nombres (
iconos_nombres); en «todas las colecciones», el texto de búsqueda («Buscar en todas (2 letras o más)…»: dos letras como mínimo). -
Páginas: 240 iconos cada vez (
PAGINA) y un botón «Mostrar más» para los siguientes; los que se ven se piden juntos poruseIconos. -
Elegir llama a
iconos_elegir(id), que guarda los datos del icono para verlo sin red, y devuelve el id entero (game-icons:crown) aonChange. Conquitable, «Sin icono» lo quita.
Las colecciones, nombres y búsquedas ya cargados se guardan además en variables del módulo durante el resto de la sesión.
| Comando | Hace |
|---|---|
iconos_colecciones() |
GET api.iconify.design/collections → Vec<ColeccionIconos { prefijo, nombre, total, categoria }>, sin las colecciones ocultas ni los prefijos raros. |
iconos_nombres(prefijo) |
GET /collection?prefix=… → todos los nombres (con y sin categoría), ordenados. |
iconos_buscar(texto) |
GET /search?query=…&limit=999 (el máximo de la API); el texto va en minúsculas, cortado a 40 caracteres, solo letras, cifras, espacios y guiones. Los resultados se guardan en memoria por búsqueda. |
iconos_datos(ids) |
BTreeMap<id, DatosIcono { body, vb }>, de memoria, de los elegidos en disco o de GET /<prefijo>.json?icons=a,b,… (120 por petición, como mucho 2.000 ids por llamada). |
iconos_elegir(id) |
Como iconos_datos con un id, y luego lo escribe en el fichero de elegidos. NotFound si el icono no existe. |
-
Red: por
fuentes::Externocon la entrada nueva de la lista de permitidos("api.iconify.design", "/"), así cada redirección se vuelve a comprobar y las respuestas tienen tope de tamaño (8 MiB de JSON,MAX_JSON). Véase Fuentes externas. -
Ids:
partirsolo aceptaprefijo:nombrecon letras ASCII minúsculas, cifras,-y_, hasta 64 caracteres cada parte; a una URL nunca llega nada más (los_ids_raros_no_llegan_a_la_url).id_validolo usa la biblioteca para rechazar un icono de etiqueta malo. -
Alias:
resolversigue hasta 6 saltos de alias, hereda la medida y suma giros y volteos;a_svghace lo mismo queiconToSVGde@iconify/utils(las transformaciones en un<g>, ancho y alto cambiados a 90°/270°), así los incluidos y los bajados se ven igual. -
Limpieza (
seguro): el cuerpo se mete en la página tal cual (dangerouslySetInnerHTML), así que se descarta cualquier cuerpo con<script,foreignObject,javascript:,<image,<iframe,<!entity, un manejadoron…=o unhref/url(que no sea un#idlocal (el_svg_peligroso_se_rechaza). Los incluidos salen de@iconify/jsonal compilar y son de fiar. -
Dónde se guarda: el catálogo (la lista de colecciones y los nombres de cada una) en la caché,
app_cache_dir/iconos/(colecciones.json,<prefijo>.json), renovado a los 7 días (RENOVAR); se puede borrar. Los datos de los iconos vistos en el selector, solo en memoria. Los elegidos, a los que apunta algo guardado, van aapp_data_dir/iconos/elegidos.json(escrito de forma atómica), así el icono de una etiqueta se ve sin red o tras borrar la caché. Véase Almacenamiento y blobs.
-
Etiquetas de la biblioteca:
tags.icon(migración0007_icono_etiqueta.sql),Tag.icon,tag_icon_set, y viajan en el.pbdeck. Véanse Biblioteca de mazos y Formato del paquete de mazo.
- Rust:
iconos::tests(se rechazan los ids que podrían romper una URL, se rechaza el SVG peligroso y nourl(#a)ni los nombres que contienen «on», un alias hereda de su padre y se voltea). -
pnpm check:iconosmantieneincluidos.tsal día con el código.
Use and build · Uso y desarrollo
- User-Guide · Guía de usuario
- Development-Setup · Preparación del entorno de desarrollo
- Testing-and-CI · Tests y CI
- Releases-and-Auto-Updates · Versiones y actualizaciones automáticas
- Conventions · Convenciones
Architecture · Arquitectura
- Architecture · Arquitectura
- IPC-and-Error-Handling · IPC y manejo de errores
- Rust-App-Layer · Capa de aplicación Rust
Data · Datos
- Deck-Model · Modelo del mazo
- Storage-and-Blobs · Almacenamiento y blobs
- Deck-Package-Format · Formato del paquete de mazo
- Deck-Library · Biblioteca de mazos
Getting cards · Conseguir cartas
- Decklist-Parsing · Parseo de la lista del mazo
- Scryfall-Integration · Integración con Scryfall
- External-Sources · Fuentes externas
- Card-Identification-and-OCR · Identificación de cartas y OCR
Layout, images, PDF · Maquetación, imagen y PDF
- Layout-Engine · Motor de maquetación
- Imaging-and-PDF · Imagen y PDF
- Export · Exportación
- Live-Preview · Vista previa en vivo
- Statistics · Estadísticas
Card designer · Diseñador de cartas
- Designer-Overview · Visión general del diseñador
- Designer-Engine · Motor del diseñador
- Designer-Composition · Composición del diseñador
- Frame-Packs · Packs de marcos
- Designer-App-Layer · Capa de aplicación del diseñador
- Designer-UI · Interfaz del diseñador
- Card-Editor-Dialog · Diálogo Editar carta
Game table · Mesa de juego
Frontend · Frontend
- Frontend-Architecture · Arquitectura del frontend
- State-Stores · Stores de estado
- Internationalization · Internacionalización
- Themes-and-Skins · Temas y skins
- Icons · Iconos
- Settings-and-Shell · Ajustes y shell
- Tutorials · Tutoriales
- Decklist-Panel · Panel de la lista del mazo
- Add-Card-and-Variants · Añadir carta y variantes
- Set-Browser · Explorador de sets
Reference · Referencia