@robosophy/ui-vue 1.2.0 → 1.2.1

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/icon-scanner.md CHANGED
@@ -1,388 +1,388 @@
1
- # Icon Scanner — @robosophy/ui-vue
2
-
3
- ## Overview
4
-
5
- `robosophyMaterialSymbols()` es un plugin de Vite que genera un sprite SVG con solo los
6
- iconos de **Material Symbols** que tu codigo realmente usa. Sin fuentes tipograficas,
7
- sin subset fonts, sin dependencias npm.
8
-
9
- **Pipeline:**
10
-
11
- ```
12
- source code → scan (8 patterns) → merge with manifest → download SVGs → inline SVG sprite
13
- ```
14
-
15
- El scanner opera en **build time** y en **dev mode** (con file watching). Escanea archivos
16
- `.vue`, `.ts`, `.tsx`, `.js`, `.jsx`, y `.mjs` del proyecto, extrae nombres de icono,
17
- familias y pesos, y descarga los SVGs correspondientes del repositorio oficial de Google.
18
-
19
- Los iconos que usan los componentes internos de la libreria (`RsSidebar`, `RsAccountSelector`,
20
- etc.) se precargan en `dist/icon-manifest.json` durante el build del paquete y se fusionan
21
- con los detectados en el proyecto consumidor.
22
-
23
- ---
24
-
25
- ## Quick Reference
26
-
27
- | # | Pattern | Categoria | Detecta | Ejemplo |
28
- |---|---------|-----------|---------|---------|
29
- | 1 | `<RsIcon>` tag | Componente | `name` estatico + ternarias | `<RsIcon name="home" />` |
30
- | 2 | `rsPrimeIcon()` | Componente | String literal en helper | `rsPrimeIcon("home")` |
31
- | 3 | `icon:` property | Dato | Objeto con `icon:` key | `{ icon: "home" }` |
32
- | 5 | Icon arrays | Dato | Array en variable `*icon*` | `const iconNames = ["home"]` |
33
- | 5b | Icon objects | Dato | Objeto en variable `*icon*` | `const iconMap = { pc: "article" }` |
34
- | 6a | Component icon prop | Cross-file | `icon=` en tag PascalCase | `<CustomButton icon="home" />` |
35
- | 6b | Proxy components | Cross-file | Prop forwarding a `<RsIcon :name>` | `<ProxyIcon icon="home" />` |
36
- | 4 | Magic comments | Fallback | Declaracion explicita | `// @robosophy-icon: home` |
37
-
38
- ---
39
-
40
- ## Automatic Detection
41
-
42
- Estos 7 patrones se activan solos. No requieren configuracion manual, solo codigo fuente
43
- donde los nombres de icono aparezcan como **string literals**.
44
-
45
- ### Component Patterns
46
-
47
- #### Pattern 1: `<RsIcon>` tag
48
-
49
- **Regex:** `/ <RsIcon\b([\s\S]*?)>/g`
50
-
51
- Detecta usos directos del componente `<RsIcon>` con `name` estatico, ternarias en `:name`,
52
- template literals, y tags multi-linea. Soporta `family`, `:family`, `weight`, `:weight`.
53
-
54
- **Detectado:**
55
- ```vue
56
- <RsIcon name="home" />
57
- <RsIcon name="home" family="rounded" />
58
- <RsIcon :name="cond ? 'home' : 'settings'" family="rounded" weight="200" />
59
- <RsIcon
60
- name="home"
61
- family="rounded"
62
- />
63
- <RsIcon :name="`home`" />
64
- ```
65
-
66
- **No detectado** (variables en `:name`):
67
- ```vue
68
- <RsIcon :name="iconVar" />
69
- <RsIcon :name="item.icon" />
70
- <RsIcon v-for="name in list" :name="name" />
71
- ```
72
-
73
- > 💡 Si el binding tiene ternarias con string literals, ambas ramas se extraen.
74
- > Si es solo una variable (`:name="iconProp"`), usa Pattern 3 en la fuente de datos
75
- > o Magic Comments como ultimo recurso.
76
-
77
- ---
78
-
79
- #### Pattern 2: `rsPrimeIcon()` helper
80
-
81
- **Regex:** `/\brsPrimeIcon\(\s*["'`]([a-z0-9_]+)["'`](?:\s*,\s*\{([^)]*)\})?/g`
82
-
83
- Detecta el helper que PrimeVue usa como string de clases para `Button.icon`,
84
- `MenuItem.icon`, etc. Soporta `family` opcional.
85
-
86
- **Detectado:**
87
- ```ts
88
- rsPrimeIcon("home")
89
- rsPrimeIcon('settings', { family: 'rounded' })
90
- rsPrimeIcon(`home`)
91
- ```
92
-
93
- **No detectado:**
94
- ```ts
95
- rsPrimeIcon(variableName)
96
- ```
97
-
98
- ---
99
-
100
- ### Data Patterns
101
-
102
- #### Pattern 3: `icon:` property
103
-
104
- **Regex:** `/\bicon\s*:\s*["'`]([a-z0-9_]+)["'`]/g`
105
-
106
- Detecta objetos con una propiedad `icon:` y extrae `weight:` y `family:` del mismo objeto.
107
- Usa `findEnclosingObject` para encontrar los limites del objeto, ignorando comentarios,
108
- strings escapados y template literals.
109
-
110
- **Detectado:**
111
- ```ts
112
- const items = [
113
- { label: "Inbox", icon: "inbox" },
114
- { label: "Settings", icon: "settings", family: "rounded", weight: 200 },
115
- { icon: `home` },
116
- ]
117
- ```
118
-
119
- **No detectado:**
120
- ```ts
121
- { icon: dynamicVar } // variable reference
122
- { icon } // shorthand property
123
- { ["icon"]: "home" } // computed property key
124
- ```
125
-
126
- > 💡 Pattern 3 es la forma mas comun de declarar iconos en datos de navegacion.
127
- > RsSidebar recibe `items` con `icon:` — se detecta automaticamente.
128
-
129
- ---
130
-
131
- #### Pattern 5: Icon arrays
132
-
133
- **Regex:** `/(?:const|let|var)\s+(\w*[Ii]con\w*)\s*=\s*\[/g`
134
-
135
- Detecta arrays asignados a variables cuyo nombre contiene "icon" (case-insensitive).
136
- Extrae strings del nivel superior del array, incluyendo arrays anidados y template literals.
137
-
138
- **Detectado:**
139
- ```ts
140
- const iconNames = ["home", "settings", "info"]
141
- const sidebarIcons = ["home", "search"]
142
- const ICON_LIST = ["warning", "error"]
143
- ```
144
-
145
- ```ts
146
- // Arrays anidados
147
- const iconGroups = [
148
- ["home", "settings"], // ✅ detectados
149
- "search" // ✅ detectado
150
- ]
151
- ```
152
-
153
- **No detectado:**
154
- ```ts
155
- const names = ["home", "settings"] // sin "icon" en nombre
156
- const items = [{ icon: "home" }] // Pattern 3 lo cubre
157
- ```
158
-
159
- ---
160
-
161
- #### Pattern 5b: Icon objects
162
-
163
- **Regex:** `/(?:const|let|var)\s+(\w*[Ii]con\w*)[^=]*=\s*\{/g`
164
-
165
- Detecta objetos literales asignados a variables con "icon" en el nombre y extrae todos
166
- los string values que matchean el patron de nombre de icono. Soporta anotaciones de tipo
167
- TypeScript (`: Record<K, V>`) y TypeScript generics con `<>`.
168
-
169
- **Detectado:**
170
- ```ts
171
- const variantIconMap: Record<string, string> = {
172
- pc: "article",
173
- alta: "account_circle",
174
- cc: "account_balance_wallet",
175
- cyo: "nest_eco_leaf",
176
- }
177
- ```
178
-
179
- ```ts
180
- const iconConfig = {
181
- default: "home",
182
- active: "settings",
183
- }
184
- ```
185
-
186
- **No detectado:**
187
- ```ts
188
- const names = { key: "article" } // sin "icon" en nombre
189
- ```
190
-
191
- > 💡 Pattern 5b fue creado especificamente para `variantIconMap` en RsSidebar,
192
- > donde las claves son nombres de variante y los valores son iconos.
193
-
194
- ---
195
-
196
- ### Cross-file Patterns
197
-
198
- #### Pattern 6a: Component icon prop
199
-
200
- **Regex:** `/<([A-Z][a-zA-Z0-9_]*)\b([\s\S]*?)>/g`
201
-
202
- Detecta el atributo `icon`, `iconName` o `icon-name` en cualquier tag PascalCase
203
- (excepto `<RsIcon>` que usa `name`). Funciona sin analisis cross-file.
204
-
205
- **Detectado:**
206
- ```vue
207
- <CustomButton icon="home" />
208
- <AnotherComponent iconName="settings" />
209
- <ThirdThing icon-name="search" />
210
- ```
211
-
212
- **No detectado:**
213
- ```vue
214
- <RsIcon icon="home" /> <!-- RsIcon usa name, no icon -->
215
- <CustomButton :icon="var" /> <!-- dynamic binding -->
216
- ```
217
-
218
- > 💡 Este patron es util cuando un componente expone un prop `icon` y el valor
219
- > se pasa como string literal en el template del consumidor.
220
-
221
- ---
222
-
223
- #### Pattern 6b: Proxy components
224
-
225
- **Analisis en dos fases:**
226
-
227
- 1. **Fase 1** — Encuentra componentes que hacen forwarding de un prop a `<RsIcon>`:
228
- - Tienen `defineProps` con al menos un prop
229
- - Tienen `<RsIcon :name="propName">` donde `propName` es un prop
230
- - Tienen `defineOptions({ name: "ComponentName" })`
231
- 2. **Fase 2** — Escanea los consumos de esos componentes y extrae valores del prop `icon`
232
-
233
- **Detectado:**
234
-
235
- Componente (`CustomIconButton.vue`):
236
- ```vue
237
- <script setup lang="ts">
238
- defineOptions({ name: "CustomIconButton" })
239
- defineProps<{ icon: string }>()
240
- </script>
241
- <template>
242
- <RsIcon :name="icon" />
243
- </template>
244
- ```
245
-
246
- Consumo (`App.vue`):
247
- ```vue
248
- <CustomIconButton icon="home" /> <!-- ✅ detectado -->
249
- <CustomIconButton icon="settings" /> <!-- ✅ detectado -->
250
- ```
251
-
252
- **No detectado:**
253
- - Componentes sin `defineProps`
254
- - Componentes sin `defineOptions({ name: ... })`
255
- - Props que no se pasan a `<RsIcon :name="prop">`
256
- - Bindings dinamicos (`:icon="variable"`)
257
-
258
- ---
259
-
260
- ## Manual Fallbacks
261
-
262
- Cuando ningun patron automatico detecta tu icono (ej: viene de una API, de un enum,
263
- o de una variable calculada), tenes dos opciones. **Usalas solo cuando los patrones
264
- automaticos no alcancen.**
265
-
266
- ### Magic comments (Pattern 4)
267
-
268
- **Regex:** `/(?:\/\/|\/\*)\s*@robosophy-icon:\s*([a-z0-9_]+)/g`
269
-
270
- Declara el icono explicitamente en el mismo archivo donde se usa:
271
-
272
- ```ts
273
- // @robosophy-icon: manage_accounts
274
- const item = { icon: props.iconName }
275
- ```
276
-
277
- Soporta `family=` y `weight=` opcionales en la misma linea:
278
-
279
- ```ts
280
- // @robosophy-icon: settings family=rounded weight=200
281
- ```
282
-
283
- ### `include` (plugin config)
284
-
285
- Para iconos usados en muchos lugares o controlados por configuracion remota:
286
-
287
- ```ts
288
- robosophyMaterialSymbols({
289
- include: [
290
- "home",
291
- { family: "rounded", name: "settings", weight: 200 },
292
- ],
293
- })
294
- ```
295
-
296
- Si se omite `weight`, se incluyen todos los pesos validos (100-700).
297
-
298
- ---
299
-
300
- ## Plugin Options
301
-
302
- | Option | Type | Default | Description |
303
- |--------|------|---------|-------------|
304
- | `include` | `IconInput[]` | `[]` | Iconos forzados. String = nombre, objeto = `{ family?, name, weight? }` |
305
- | `scan` | `boolean` | `true` | `false` desactiva el escaneo. Todos los iconos deben ir en `include` |
306
- | `roots` | `string[]` | `["./src"]` | Directorios a escanear |
307
- | `outputDir` | `string` | `"assets"` | Directorio de salida del sprite SVG |
308
- | `fontDisplay` | `string` | — | CSS `font-display` |
309
- | `preload` | `boolean` | `false` | Precarga el sprite en el `<head>` |
310
-
311
- ---
312
-
313
- ## `icon-manifest.json`
314
-
315
- Generado por `scripts/generate-icon-manifest.mjs` durante el build del paquete.
316
- Escanea `src/components/` y produce `dist/icon-manifest.json`.
317
-
318
- ```json
319
- {
320
- "outlined": ["home", "search", "settings"],
321
- "rounded": ["settings"],
322
- "sharp": []
323
- }
324
- ```
325
-
326
- **Rol en el pipeline:**
327
- 1. Build genera el manifiesto desde los componentes de la libreria
328
- 2. Plugin de Vite carga el manifiesto como baseline
329
- 3. Plugin escanea el proyecto consumidor para iconos adicionales
330
- 4. Plugin descarga los SVGs del set combinado
331
-
332
- El manifiesto asegura que los iconos de `RsSidebar`, `RsAccountSelector`, etc. esten
333
- siempre disponibles, incluso si el proyecto consumidor no usa esos componentes.
334
-
335
- ---
336
-
337
- ## Best Practices
338
-
339
- ### Para escribir codigo que se detecta solo
340
-
341
- 1. **Usa `<RsIcon name="home" />`** — siempre detectado por Pattern 1
342
- 2. **Declara iconos en objetos con `icon:`** — Pattern 3 extrae automaticamente
343
- 3. **Nombra variables con "icon"** cuando almacenes nombres de icono — Patterns 5 y 5b se activan
344
- 4. **Pasa iconos como string literal** a componentes con prop `icon` — Pattern 6a lo detecta
345
- 5. **Usa `rsPrimeIcon("home")`** para PrimeVue — Pattern 2 lo cubre
346
-
347
- ### Para componentes que envuelven RsIcon
348
-
349
- Si creas un componente que recibe un icono por prop y lo pasa a `<RsIcon :name>`:
350
-
351
- - Usa `defineProps` con el nombre del prop tipado
352
- - Usa `defineOptions({ name: "ComponentName" })` para registrar el nombre
353
- - Pattern 6b lo detectara automaticamente
354
-
355
- Ejemplo:
356
- ```vue
357
- <script setup lang="ts">
358
- defineOptions({ name: "MyIconButton" })
359
- defineProps<{ icon: string }>()
360
- </script>
361
- <template>
362
- <button><RsIcon :name="icon" /></button>
363
- </template>
364
- ```
365
-
366
- ### Cuando nada funciona
367
-
368
- Usa magic comments o `include` — pero considera si podes reescribir el codigo para
369
- que el scanner lo detecte automaticamente. Es menos mantenimiento a futuro.
370
-
371
- ### Testing de nombres
372
-
373
- ```
374
- https://fonts.google.com/icons?icon.query=icon_name
375
- ```
376
-
377
- ---
378
-
379
- ## Changelog
380
-
381
- | Date | Change |
382
- |------|--------|
383
- | 2026-07-17 | Documentacion reestructurada: 8 patrones agrupados por categoria, automaticos primero |
384
- | 2026-07-17 | **Pattern 5b** (icon objects), **Pattern 6a** (component icon prop), **Pattern 6b** (proxy components) added |
385
- | 2026-07-13 | **Pattern 4** (magic comments) and **Pattern 5** (icon arrays) added |
386
- | 2026-07-13 | `findEnclosingObject`: ahora maneja comentarios, strings escapados y template literals |
387
- | 2026-07-13 | `resolveNames`: bindings `:name` dinamicos ya no tratan nombres de variable como iconos |
388
- | 2026-07-13 | Pattern 3: weight y family se extraen del objeto contenedor |
1
+ # Icon Scanner — @robosophy/ui-vue
2
+
3
+ ## Overview
4
+
5
+ `robosophyMaterialSymbols()` es un plugin de Vite que genera un sprite SVG con solo los
6
+ iconos de **Material Symbols** que tu codigo realmente usa. Sin fuentes tipograficas,
7
+ sin subset fonts, sin dependencias npm.
8
+
9
+ **Pipeline:**
10
+
11
+ ```
12
+ source code → scan (8 patterns) → merge with manifest → download SVGs → inline SVG sprite
13
+ ```
14
+
15
+ El scanner opera en **build time** y en **dev mode** (con file watching). Escanea archivos
16
+ `.vue`, `.ts`, `.tsx`, `.js`, `.jsx`, y `.mjs` del proyecto, extrae nombres de icono,
17
+ familias y pesos, y descarga los SVGs correspondientes del repositorio oficial de Google.
18
+
19
+ Los iconos que usan los componentes internos de la libreria (`RsSidebar`, `RsAccountSelector`,
20
+ etc.) se precargan en `dist/icon-manifest.json` durante el build del paquete y se fusionan
21
+ con los detectados en el proyecto consumidor.
22
+
23
+ ---
24
+
25
+ ## Quick Reference
26
+
27
+ | # | Pattern | Categoria | Detecta | Ejemplo |
28
+ |---|---------|-----------|---------|---------|
29
+ | 1 | `<RsIcon>` tag | Componente | `name` estatico + ternarias | `<RsIcon name="home" />` |
30
+ | 2 | `rsPrimeIcon()` | Componente | String literal en helper | `rsPrimeIcon("home")` |
31
+ | 3 | `icon:` property | Dato | Objeto con `icon:` key | `{ icon: "home" }` |
32
+ | 5 | Icon arrays | Dato | Array en variable `*icon*` | `const iconNames = ["home"]` |
33
+ | 5b | Icon objects | Dato | Objeto en variable `*icon*` | `const iconMap = { pc: "article" }` |
34
+ | 6a | Component icon prop | Cross-file | `icon=` en tag PascalCase | `<CustomButton icon="home" />` |
35
+ | 6b | Proxy components | Cross-file | Prop forwarding a `<RsIcon :name>` | `<ProxyIcon icon="home" />` |
36
+ | 4 | Magic comments | Fallback | Declaracion explicita | `// @robosophy-icon: home` |
37
+
38
+ ---
39
+
40
+ ## Automatic Detection
41
+
42
+ Estos 7 patrones se activan solos. No requieren configuracion manual, solo codigo fuente
43
+ donde los nombres de icono aparezcan como **string literals**.
44
+
45
+ ### Component Patterns
46
+
47
+ #### Pattern 1: `<RsIcon>` tag
48
+
49
+ **Regex:** `/ <RsIcon\b([\s\S]*?)>/g`
50
+
51
+ Detecta usos directos del componente `<RsIcon>` con `name` estatico, ternarias en `:name`,
52
+ template literals, y tags multi-linea. Soporta `family`, `:family`, `weight`, `:weight`.
53
+
54
+ **Detectado:**
55
+ ```vue
56
+ <RsIcon name="home" />
57
+ <RsIcon name="home" family="rounded" />
58
+ <RsIcon :name="cond ? 'home' : 'settings'" family="rounded" weight="200" />
59
+ <RsIcon
60
+ name="home"
61
+ family="rounded"
62
+ />
63
+ <RsIcon :name="`home`" />
64
+ ```
65
+
66
+ **No detectado** (variables en `:name`):
67
+ ```vue
68
+ <RsIcon :name="iconVar" />
69
+ <RsIcon :name="item.icon" />
70
+ <RsIcon v-for="name in list" :name="name" />
71
+ ```
72
+
73
+ > 💡 Si el binding tiene ternarias con string literals, ambas ramas se extraen.
74
+ > Si es solo una variable (`:name="iconProp"`), usa Pattern 3 en la fuente de datos
75
+ > o Magic Comments como ultimo recurso.
76
+
77
+ ---
78
+
79
+ #### Pattern 2: `rsPrimeIcon()` helper
80
+
81
+ **Regex:** `/\brsPrimeIcon\(\s*["'`]([a-z0-9_]+)["'`](?:\s*,\s*\{([^)]*)\})?/g`
82
+
83
+ Detecta el helper que PrimeVue usa como string de clases para `Button.icon`,
84
+ `MenuItem.icon`, etc. Soporta `family` opcional.
85
+
86
+ **Detectado:**
87
+ ```ts
88
+ rsPrimeIcon("home")
89
+ rsPrimeIcon('settings', { family: 'rounded' })
90
+ rsPrimeIcon(`home`)
91
+ ```
92
+
93
+ **No detectado:**
94
+ ```ts
95
+ rsPrimeIcon(variableName)
96
+ ```
97
+
98
+ ---
99
+
100
+ ### Data Patterns
101
+
102
+ #### Pattern 3: `icon:` property
103
+
104
+ **Regex:** `/\bicon\s*:\s*["'`]([a-z0-9_]+)["'`]/g`
105
+
106
+ Detecta objetos con una propiedad `icon:` y extrae `weight:` y `family:` del mismo objeto.
107
+ Usa `findEnclosingObject` para encontrar los limites del objeto, ignorando comentarios,
108
+ strings escapados y template literals.
109
+
110
+ **Detectado:**
111
+ ```ts
112
+ const items = [
113
+ { label: "Inbox", icon: "inbox" },
114
+ { label: "Settings", icon: "settings", family: "rounded", weight: 200 },
115
+ { icon: `home` },
116
+ ]
117
+ ```
118
+
119
+ **No detectado:**
120
+ ```ts
121
+ { icon: dynamicVar } // variable reference
122
+ { icon } // shorthand property
123
+ { ["icon"]: "home" } // computed property key
124
+ ```
125
+
126
+ > 💡 Pattern 3 es la forma mas comun de declarar iconos en datos de navegacion.
127
+ > RsSidebar recibe `items` con `icon:` — se detecta automaticamente.
128
+
129
+ ---
130
+
131
+ #### Pattern 5: Icon arrays
132
+
133
+ **Regex:** `/(?:const|let|var)\s+(\w*[Ii]con\w*)\s*=\s*\[/g`
134
+
135
+ Detecta arrays asignados a variables cuyo nombre contiene "icon" (case-insensitive).
136
+ Extrae strings del nivel superior del array, incluyendo arrays anidados y template literals.
137
+
138
+ **Detectado:**
139
+ ```ts
140
+ const iconNames = ["home", "settings", "info"]
141
+ const sidebarIcons = ["home", "search"]
142
+ const ICON_LIST = ["warning", "error"]
143
+ ```
144
+
145
+ ```ts
146
+ // Arrays anidados
147
+ const iconGroups = [
148
+ ["home", "settings"], // ✅ detectados
149
+ "search" // ✅ detectado
150
+ ]
151
+ ```
152
+
153
+ **No detectado:**
154
+ ```ts
155
+ const names = ["home", "settings"] // sin "icon" en nombre
156
+ const items = [{ icon: "home" }] // Pattern 3 lo cubre
157
+ ```
158
+
159
+ ---
160
+
161
+ #### Pattern 5b: Icon objects
162
+
163
+ **Regex:** `/(?:const|let|var)\s+(\w*[Ii]con\w*)[^=]*=\s*\{/g`
164
+
165
+ Detecta objetos literales asignados a variables con "icon" en el nombre y extrae todos
166
+ los string values que matchean el patron de nombre de icono. Soporta anotaciones de tipo
167
+ TypeScript (`: Record<K, V>`) y TypeScript generics con `<>`.
168
+
169
+ **Detectado:**
170
+ ```ts
171
+ const variantIconMap: Record<string, string> = {
172
+ pc: "article",
173
+ alta: "account_circle",
174
+ cc: "account_balance_wallet",
175
+ cyo: "nest_eco_leaf",
176
+ }
177
+ ```
178
+
179
+ ```ts
180
+ const iconConfig = {
181
+ default: "home",
182
+ active: "settings",
183
+ }
184
+ ```
185
+
186
+ **No detectado:**
187
+ ```ts
188
+ const names = { key: "article" } // sin "icon" en nombre
189
+ ```
190
+
191
+ > 💡 Pattern 5b fue creado especificamente para `variantIconMap` en RsSidebar,
192
+ > donde las claves son nombres de variante y los valores son iconos.
193
+
194
+ ---
195
+
196
+ ### Cross-file Patterns
197
+
198
+ #### Pattern 6a: Component icon prop
199
+
200
+ **Regex:** `/<([A-Z][a-zA-Z0-9_]*)\b([\s\S]*?)>/g`
201
+
202
+ Detecta el atributo `icon`, `iconName` o `icon-name` en cualquier tag PascalCase
203
+ (excepto `<RsIcon>` que usa `name`). Funciona sin analisis cross-file.
204
+
205
+ **Detectado:**
206
+ ```vue
207
+ <CustomButton icon="home" />
208
+ <AnotherComponent iconName="settings" />
209
+ <ThirdThing icon-name="search" />
210
+ ```
211
+
212
+ **No detectado:**
213
+ ```vue
214
+ <RsIcon icon="home" /> <!-- RsIcon usa name, no icon -->
215
+ <CustomButton :icon="var" /> <!-- dynamic binding -->
216
+ ```
217
+
218
+ > 💡 Este patron es util cuando un componente expone un prop `icon` y el valor
219
+ > se pasa como string literal en el template del consumidor.
220
+
221
+ ---
222
+
223
+ #### Pattern 6b: Proxy components
224
+
225
+ **Analisis en dos fases:**
226
+
227
+ 1. **Fase 1** — Encuentra componentes que hacen forwarding de un prop a `<RsIcon>`:
228
+ - Tienen `defineProps` con al menos un prop
229
+ - Tienen `<RsIcon :name="propName">` donde `propName` es un prop
230
+ - Tienen `defineOptions({ name: "ComponentName" })`
231
+ 2. **Fase 2** — Escanea los consumos de esos componentes y extrae valores del prop `icon`
232
+
233
+ **Detectado:**
234
+
235
+ Componente (`CustomIconButton.vue`):
236
+ ```vue
237
+ <script setup lang="ts">
238
+ defineOptions({ name: "CustomIconButton" })
239
+ defineProps<{ icon: string }>()
240
+ </script>
241
+ <template>
242
+ <RsIcon :name="icon" />
243
+ </template>
244
+ ```
245
+
246
+ Consumo (`App.vue`):
247
+ ```vue
248
+ <CustomIconButton icon="home" /> <!-- ✅ detectado -->
249
+ <CustomIconButton icon="settings" /> <!-- ✅ detectado -->
250
+ ```
251
+
252
+ **No detectado:**
253
+ - Componentes sin `defineProps`
254
+ - Componentes sin `defineOptions({ name: ... })`
255
+ - Props que no se pasan a `<RsIcon :name="prop">`
256
+ - Bindings dinamicos (`:icon="variable"`)
257
+
258
+ ---
259
+
260
+ ## Manual Fallbacks
261
+
262
+ Cuando ningun patron automatico detecta tu icono (ej: viene de una API, de un enum,
263
+ o de una variable calculada), tenes dos opciones. **Usalas solo cuando los patrones
264
+ automaticos no alcancen.**
265
+
266
+ ### Magic comments (Pattern 4)
267
+
268
+ **Regex:** `/(?:\/\/|\/\*)\s*@robosophy-icon:\s*([a-z0-9_]+)/g`
269
+
270
+ Declara el icono explicitamente en el mismo archivo donde se usa:
271
+
272
+ ```ts
273
+ // @robosophy-icon: manage_accounts
274
+ const item = { icon: props.iconName }
275
+ ```
276
+
277
+ Soporta `family=` y `weight=` opcionales en la misma linea:
278
+
279
+ ```ts
280
+ // @robosophy-icon: settings family=rounded weight=200
281
+ ```
282
+
283
+ ### `include` (plugin config)
284
+
285
+ Para iconos usados en muchos lugares o controlados por configuracion remota:
286
+
287
+ ```ts
288
+ robosophyMaterialSymbols({
289
+ include: [
290
+ "home",
291
+ { family: "rounded", name: "settings", weight: 200 },
292
+ ],
293
+ })
294
+ ```
295
+
296
+ Si se omite `weight`, se incluyen todos los pesos validos (100-700).
297
+
298
+ ---
299
+
300
+ ## Plugin Options
301
+
302
+ | Option | Type | Default | Description |
303
+ |--------|------|---------|-------------|
304
+ | `include` | `IconInput[]` | `[]` | Iconos forzados. String = nombre, objeto = `{ family?, name, weight? }` |
305
+ | `scan` | `boolean` | `true` | `false` desactiva el escaneo. Todos los iconos deben ir en `include` |
306
+ | `roots` | `string[]` | `["./src"]` | Directorios a escanear |
307
+ | `outputDir` | `string` | `"assets"` | Directorio de salida del sprite SVG |
308
+ | `fontDisplay` | `string` | — | CSS `font-display` |
309
+ | `preload` | `boolean` | `false` | Precarga el sprite en el `<head>` |
310
+
311
+ ---
312
+
313
+ ## `icon-manifest.json`
314
+
315
+ Generado por `scripts/generate-icon-manifest.mjs` durante el build del paquete.
316
+ Escanea `src/components/` y produce `dist/icon-manifest.json`.
317
+
318
+ ```json
319
+ {
320
+ "outlined": ["home", "search", "settings"],
321
+ "rounded": ["settings"],
322
+ "sharp": []
323
+ }
324
+ ```
325
+
326
+ **Rol en el pipeline:**
327
+ 1. Build genera el manifiesto desde los componentes de la libreria
328
+ 2. Plugin de Vite carga el manifiesto como baseline
329
+ 3. Plugin escanea el proyecto consumidor para iconos adicionales
330
+ 4. Plugin descarga los SVGs del set combinado
331
+
332
+ El manifiesto asegura que los iconos de `RsSidebar`, `RsAccountSelector`, etc. esten
333
+ siempre disponibles, incluso si el proyecto consumidor no usa esos componentes.
334
+
335
+ ---
336
+
337
+ ## Best Practices
338
+
339
+ ### Para escribir codigo que se detecta solo
340
+
341
+ 1. **Usa `<RsIcon name="home" />`** — siempre detectado por Pattern 1
342
+ 2. **Declara iconos en objetos con `icon:`** — Pattern 3 extrae automaticamente
343
+ 3. **Nombra variables con "icon"** cuando almacenes nombres de icono — Patterns 5 y 5b se activan
344
+ 4. **Pasa iconos como string literal** a componentes con prop `icon` — Pattern 6a lo detecta
345
+ 5. **Usa `rsPrimeIcon("home")`** para PrimeVue — Pattern 2 lo cubre
346
+
347
+ ### Para componentes que envuelven RsIcon
348
+
349
+ Si creas un componente que recibe un icono por prop y lo pasa a `<RsIcon :name>`:
350
+
351
+ - Usa `defineProps` con el nombre del prop tipado
352
+ - Usa `defineOptions({ name: "ComponentName" })` para registrar el nombre
353
+ - Pattern 6b lo detectara automaticamente
354
+
355
+ Ejemplo:
356
+ ```vue
357
+ <script setup lang="ts">
358
+ defineOptions({ name: "MyIconButton" })
359
+ defineProps<{ icon: string }>()
360
+ </script>
361
+ <template>
362
+ <button><RsIcon :name="icon" /></button>
363
+ </template>
364
+ ```
365
+
366
+ ### Cuando nada funciona
367
+
368
+ Usa magic comments o `include` — pero considera si podes reescribir el codigo para
369
+ que el scanner lo detecte automaticamente. Es menos mantenimiento a futuro.
370
+
371
+ ### Testing de nombres
372
+
373
+ ```
374
+ https://fonts.google.com/icons?icon.query=icon_name
375
+ ```
376
+
377
+ ---
378
+
379
+ ## Changelog
380
+
381
+ | Date | Change |
382
+ |------|--------|
383
+ | 2026-07-17 | Documentacion reestructurada: 8 patrones agrupados por categoria, automaticos primero |
384
+ | 2026-07-17 | **Pattern 5b** (icon objects), **Pattern 6a** (component icon prop), **Pattern 6b** (proxy components) added |
385
+ | 2026-07-13 | **Pattern 4** (magic comments) and **Pattern 5** (icon arrays) added |
386
+ | 2026-07-13 | `findEnclosingObject`: ahora maneja comentarios, strings escapados y template literals |
387
+ | 2026-07-13 | `resolveNames`: bindings `:name` dinamicos ya no tratan nombres de variable como iconos |
388
+ | 2026-07-13 | Pattern 3: weight y family se extraen del objeto contenedor |