idicon 0.0.0-stage → 0.1.0

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/README.md CHANGED
@@ -1,3 +1,331 @@
1
- # Temporary Holding Version
1
+ # IDicon
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Avatares SVG únicos y deterministas a partir de un id. Dado el identificador de un cliente o usuario, `idicon` devuelve siempre el mismo avatar: una persona, un personaje, un objeto o una forma geométrica, con cara, sobre un fondo con patrón y una paleta de hasta 6 colores. No necesita base de datos ni servidor: el avatar se calcula, no se almacena.
4
+
5
+ El repositorio contiene dos cosas:
6
+
7
+ - **El paquete npm** `idicon`: la librería que genera los avatares (sin dependencias) y un componente opcional para React.
8
+ - **Una web de demostración** para probar ids, opciones y paletas, y copiar o descargar el resultado.
9
+
10
+ Índice:
11
+
12
+ 1. [Guía de implementación en otro proyecto](#1-guía-de-implementación-en-otro-proyecto)
13
+ 2. [Referencia de la API](#2-referencia-de-la-api)
14
+ 3. [Garantías del generador](#3-garantías-del-generador)
15
+ 4. [Estabilidad del diseño y versionado](#4-estabilidad-del-diseño-y-versionado)
16
+ 5. [Web de demostración](#5-web-de-demostración)
17
+ 6. [Mantenimiento del paquete](#6-mantenimiento-del-paquete)
18
+
19
+ ---
20
+
21
+
22
+
23
+ ## 1. Guía de implementación en otro proyecto
24
+
25
+ Pasos para usar IDicon en una aplicación real, con clientes. Síguelos en orden.
26
+
27
+ ### Paso 0: decisiones previas (5 minutos)
28
+
29
+ Antes de escribir código, acuerda con el equipo:
30
+
31
+ - **Qué versión se instala.** Siempre una versión concreta (etiqueta `vX.Y.Z` o número en el registro), nunca "lo último de `main`". Ver [sección 4](#4-estabilidad-del-diseño-y-versionado).
32
+ - **Si los avatares llevan la paleta de la empresa.** Si sí, elige los 5 colores (`#rrggbb`) una sola vez. Si no, el generador asigna una paleta distinta a cada id.
33
+ - **Qué id se usa.** Debe ser el identificador **estable** del cliente (el id de la base de datos, el email, un UUID). No uses el nombre si puede cambiar: cambiar el id cambia el avatar.
34
+
35
+
36
+
37
+ ### Paso 1: instalar el paquete
38
+
39
+ Requisitos: Node.js 18 o superior (o cualquier navegador moderno). El paquete es solo módulos ES (`import`). React es opcional y solo hace falta para `idicon/react`.
40
+
41
+ El paquete está publicado en npm ([npmjs.com/package/idicon](https://www.npmjs.com/package/idicon)). Instala una versión concreta:
42
+
43
+ ```bash
44
+ npm install idicon@0.1.0
45
+ ```
46
+
47
+ Alternativas, por si en algún entorno no hay acceso al registro de npm:
48
+
49
+ ```bash
50
+ # Desde el repositorio Git, fijando una etiqueta de versión
51
+ npm install git+https://github.com/AI-Digital-Solutions-Blue/IDicon-generator.git#v0.1.0
52
+
53
+ # Desde un fichero generado con npm pack
54
+ npm install ./idicon-0.1.0.tgz
55
+ ```
56
+
57
+ Comprueba en tu `package.json` que la versión queda **fijada sin `^` ni `~`**, por ejemplo `"idicon": "0.1.0"`. Así una actualización del paquete nunca cambia tus avatares sin que tú lo decidas.
58
+
59
+ ### Paso 2: centralizar la configuración
60
+
61
+ Crea un único módulo en tu aplicación que envuelva al paquete. Todas las pantallas lo usan a él, no a `idicon` directamente, para que las opciones (paleta, contenido) sean las mismas en toda la app y vivan en un solo sitio.
62
+
63
+ ```ts
64
+ // src/lib/avatares.ts
65
+ import { generateAvatarSvg, avatarDataUri, type AvatarOptions } from "idicon";
66
+
67
+ // Opciones comunes a toda la aplicación. Cambiarlas cambia TODOS los avatares.
68
+ const OPCIONES: AvatarOptions = {
69
+ // Paleta de marca (5 colores #rrggbb). Quita esta línea para paletas automáticas.
70
+ palette: ["#12263F", "#2E5E8C", "#7FB2E5", "#F2C14E", "#F7F4EA"],
71
+ // subject: "person", // si solo quieres personas
72
+ // pattern: "plain", // si prefieres fondos lisos
73
+ };
74
+
75
+ /** Id estable del cliente → SVG. */
76
+ export function avatarSvg(clienteId: string, size = 96): string {
77
+ return generateAvatarSvg(clienteId, { ...OPCIONES, size });
78
+ }
79
+
80
+ /** Igual, como URL para <img src>. */
81
+ export function avatarUrl(clienteId: string, size = 96): string {
82
+ return avatarDataUri(clienteId, { ...OPCIONES, size });
83
+ }
84
+ ```
85
+
86
+
87
+
88
+ ### Paso 3: usarlo en la interfaz
89
+
90
+ **React** (con el componente del paquete y las opciones centralizadas):
91
+
92
+ ```tsx
93
+ // src/components/AvatarCliente.tsx
94
+ import { Avatar } from "idicon/react";
95
+
96
+ const OPCIONES = { palette: ["#12263F", "#2E5E8C", "#7FB2E5", "#F2C14E", "#F7F4EA"] } as const;
97
+
98
+ export function AvatarCliente({ id, size = 40 }: { id: string; size?: number }) {
99
+ return <Avatar id={id} size={size} {...OPCIONES} title={id} />;
100
+ }
101
+ ```
102
+
103
+ ```tsx
104
+ <AvatarCliente id={cliente.id} />
105
+ <AvatarCliente id={cliente.id} size={96} />
106
+ ```
107
+
108
+ **HTML o cualquier otro framework** (Vue, Angular, plantillas de servidor):
109
+
110
+ ```ts
111
+ import { avatarUrl } from "./lib/avatares";
112
+
113
+ img.src = avatarUrl(cliente.id, 48);
114
+ // o en una plantilla: <img src="${avatarUrl(id)}" width="48" height="48" alt="">
115
+ ```
116
+
117
+ **Como fondo CSS**:
118
+
119
+ ```ts
120
+ el.style.backgroundImage = `url("${avatarUrl(cliente.id)}")`;
121
+ ```
122
+
123
+
124
+
125
+ ### Paso 4: (opcional) servirlo desde el backend
126
+
127
+ Si varias aplicaciones, o apps que no son JavaScript, deben mostrar el mismo avatar, expón una URL en tu servidor. Ejemplo con Express:
128
+
129
+ ```ts
130
+ import express from "express";
131
+ import { avatarSvg } from "./lib/avatares";
132
+
133
+ const app = express();
134
+
135
+ app.get("/avatar/:id.svg", (req, res) => {
136
+ res.type("image/svg+xml");
137
+ res.set("Cache-Control", "public, max-age=31536000, immutable"); // el avatar no cambia
138
+ res.send(avatarSvg(req.params.id, 256));
139
+ });
140
+ ```
141
+
142
+ Entonces cualquier cliente usa `<img src="https://tu-servidor/avatar/cliente-1042.svg">`. La cabecera de caché es segura porque el mismo id siempre devuelve el mismo SVG (mientras no cambie la versión del paquete; ver sección 4).
143
+
144
+ ### Paso 5: comprobar la integración
145
+
146
+ - [ ] El mismo cliente muestra el mismo avatar en todas las pantallas y tras recargar.
147
+ - [ ] Dos clientes distintos muestran avatares distintos.
148
+ - [ ] Con paleta de marca: todos los avatares usan solo esos colores (más tinta oscura o blanca en la cara).
149
+ - [ ] En TypeScript, `subject="cualquiercosa"` da error de compilación (los tipos llegan bien).
150
+ - [ ] El `package.json` fija la versión exacta.
151
+ - [ ] Si usas un endpoint: la respuesta tiene `Content-Type: image/svg+xml`.
152
+
153
+
154
+
155
+ ### Paso 6: política de actualización
156
+
157
+ - Lee el [CHANGELOG](CHANGELOG.md) antes de subir de versión. Si la entrada dice que **altera avatares existentes**, tus clientes verán avatares nuevos. Decide si lo aceptas y, si procede, avísales.
158
+ - Las versiones **menores y de parche** (`0.1.0` → `0.1.1`, `0.2.0`) no cambian ningún avatar existente; son seguras.
159
+ - Las versiones **mayores** (`0.x` → `1.0`, `1.x` → `2.0`) pueden cambiar el dibujo.
160
+ - Cada SVG lleva el atributo `data-idicon-design="N"` con la versión de diseño que lo generó. Sirve para comprobar, en un test o en soporte, con qué versión se dibujó un avatar.
161
+ - Si necesitas que convivan dos diseños (por ejemplo, clientes antiguos conservan el suyo y los nuevos usan el nuevo), incluye la versión en el id: `generateAvatarSvg("v1:" + cliente.id)` con el paquete antiguo y `"v2:" + cliente.id` con el nuevo. Como el id forma parte de la semilla, cada prefijo da su propio avatar estable.
162
+
163
+ ---
164
+
165
+
166
+
167
+ ## 2. Referencia de la API
168
+
169
+ ```ts
170
+ import { generateAvatarSvg, avatarDataUri, SUBJECTS, PATTERNS, PATTERN_CHOICES, PALETTES, DESIGN_VERSION } from "idicon";
171
+ import type { AvatarOptions, Subject, Pattern, PatternChoice } from "idicon";
172
+ import { Avatar, type AvatarProps } from "idicon/react";
173
+ ```
174
+
175
+
176
+
177
+ ### `generateAvatarSvg(id, options?) → string`
178
+
179
+ Devuelve el avatar de `id` como documento SVG completo (texto). El id se recorta (espacios al principio y al final) y se normaliza (`NFC`), así que `"ana"` y `" ana "` dan el mismo avatar. Cualquier texto vale como id: nunca se escribe dentro del SVG.
180
+
181
+ ### `avatarDataUri(id, options?) → string`
182
+
183
+ El mismo avatar como URL `data:image/svg+xml;charset=utf-8,...`, lista para `src` de una imagen o `background-image` en CSS.
184
+
185
+ ### Opciones (`AvatarOptions`)
186
+
187
+
188
+ | Opción | Valores | Por defecto | Qué hace |
189
+ | --------- | ------------------------------------------------------------------------------- | ----------- | -------------------------------------------------------------------------------------------------------------- |
190
+ | `subject` | `"random"`, `"person"`, `"character"`, `"object"`, `"shape"`, `"none"` | `"random"` | Qué se dibuja. `random` deja que el id elija entre todos; `none` dibuja solo el fondo. |
191
+ | `pattern` | `"random"`, `"plain"`, `"rings"`, `"stripes"`, `"blobs"`, `"dots"`, `"horizon"` | `"random"` | Patrón del fondo. `plain` es un color liso. |
192
+ | `palette` | 5 colores `#rrggbb` | automática | Paleta manual. Si no se indica, o no es válida, el id elige una de las 12 paletas incluidas. |
193
+ | `size` | número | `256` | Ancho y alto en píxeles escritos en el `<svg>`. El dibujo escala por su `viewBox`, así que no cambia nada más. |
194
+
195
+
196
+ - `"character"`: robot, gato, búho, fantasma o monstruo.
197
+ - `"object"`: caja, nube, bombilla, cohete, maceta o taza.
198
+ - `"shape"`: hexágono, triángulo, rombo, cuadrado, estrella, corazón, gota o píldora.
199
+
200
+
201
+
202
+ ### Constantes
203
+
204
+ - `SUBJECTS`: valores válidos de `subject`. `PATTERN_CHOICES`: valores válidos de `pattern`. `PATTERNS`: solo los patrones dibujables. Útiles para construir selectores.
205
+ - `PALETTES`: las 12 paletas incluidas (5 colores cada una), como punto de partida para una paleta manual.
206
+ - `DESIGN_VERSION`: versión del dibujo. Es el valor que aparece en `data-idicon-design` de cada SVG.
207
+
208
+
209
+
210
+ ### `Avatar` (`idicon/react`)
211
+
212
+ Props: `id` (obligatorio), `subject`, `pattern`, `palette`, `size`, `className`, `title`. Dibuja el SVG en línea dentro de un `<span>`. Requiere React 18 o superior.
213
+
214
+ ---
215
+
216
+
217
+
218
+ ## 3. Garantías del generador
219
+
220
+ - **Determinista.** El mismo id con las mismas opciones produce siempre el mismo SVG, en cualquier máquina, navegador o versión de Node. No usa `Math.random()`.
221
+ - **Las opciones no se mezclan.** Paleta, patrón, personaje y pose se deciden con secuencias independientes derivadas del id. Cambiar el patrón o los colores nunca cambia el personaje, la pose ni la cara, y viceversa.
222
+ - **Máximo 6 colores.** Los 5 de la paleta más la tinta de la cara, que se elige oscura o blanca según el contraste con el color sobre el que se dibuja.
223
+ - **Contraste.** Los colores de la paleta se reparten entre fondo, cuerpo, cara y acento comprobando que se distingan entre sí. Con una paleta manual, cada id reparte esos colores de forma distinta; si los 5 colores son muy parecidos, la cara puede perder contraste.
224
+ - **Formato.** Cuadrado de esquinas rectas, `viewBox="0 0 120 120"`, unos 3-4 KB por avatar. El personaje queda recortado dentro del cuadrado aunque esté inclinado.
225
+ - **Seguro.** El id nunca aparece en el SVG generado. Hay un test que lo comprueba.
226
+ - **Rápido.** Generar un avatar cuesta microsegundos; se puede hacer en cada render sin cachear.
227
+
228
+ ---
229
+
230
+
231
+
232
+ ## 4. Estabilidad del diseño y versionado
233
+
234
+ El avatar de un id es el resultado de un dibujo concreto. **Cualquier cambio en el dibujo (añadir un personaje, una paleta o un patrón, o reordenar decisiones aleatorias dentro de una capa) cambia los avatares de ids ya existentes.** Para un cliente que ya conoce su avatar, eso parece un error. El proyecto tiene tres mecanismos para que nunca ocurra por accidente:
235
+
236
+ ### Candado de diseño (test automático)
237
+
238
+ `src/lib/design-lock.test.ts` genera 494 avatares (38 ids × 13 combinaciones de opciones), calcula una huella de cada uno y la compara con `src/lib/__snapshots__/design-lock.json`. **Si cualquier avatar cambia en lo más mínimo,** `npm test` **falla** y muestra qué ids y opciones se vieron afectados.
239
+
240
+ Un cambio de dibujo solo puede entrar si alguien lo acepta a propósito:
241
+
242
+ ```bash
243
+ # 1. Subir DESIGN_VERSION en src/lib/avatar.ts (1 → 2)
244
+ # 2. Regenerar el candado
245
+ npm run design:accept
246
+ # 3. Anotarlo en CHANGELOG.md como cambio que altera avatares existentes
247
+ # 4. Publicar como versión MAYOR
248
+ ```
249
+
250
+ Si el test falla y **no** querías cambiar el dibujo, el cambio tiene un efecto secundario: revísalo antes de aceptarlo.
251
+
252
+ ### Versión de diseño
253
+
254
+ `DESIGN_VERSION` (exportada y escrita en cada SVG como `data-idicon-design`) identifica el dibujo. Sube con cada cambio visual aceptado; las apps pueden usarla para saber con qué diseño se generó un avatar.
255
+
256
+ ### Integración continua
257
+
258
+ `.github/workflows/ci.yml` ejecuta lint, tests (con el candado) y ambos builds en cada push y pull request. Un check rojo en GitHub significa que el cambio no es seguro para publicar.
259
+
260
+ ### Reglas de versión (semver)
261
+
262
+
263
+ | Cambio | Versión | Ejemplo |
264
+ | ------------------------------------------------- | --------- | ----------------- |
265
+ | Altera algún avatar existente | **Mayor** | `1.4.2` → `2.0.0` |
266
+ | Opción nueva que por defecto no cambia nada | Menor | `1.4.2` → `1.5.0` |
267
+ | Corrección sin efecto visual, documentación, demo | Parche | `1.4.2` → `1.4.3` |
268
+
269
+
270
+ Mientras la versión sea `0.x`, el dibujo todavía puede cambiar; **antes de usarlo con clientes reales, publica** `1.0.0` como compromiso de estabilidad.
271
+
272
+ ---
273
+
274
+
275
+
276
+ ## 5. Web de demostración
277
+
278
+ ```bash
279
+ npm install
280
+ npm run dev # http://localhost:5173
281
+ npm run build:demo # versión estática en dist-demo/
282
+ ```
283
+
284
+ La demo permite escribir un id o generar uno aleatorio, elegir contenido, patrón y paleta (automática, predefinida, manual con selector de color y cuentagotas, o guardada con nombre), copiar la imagen al portapapeles como PNG, copiar el SVG, descargar en SVG o PNG, y guardar avatares en el navegador para volver a ellos.
285
+
286
+ ---
287
+
288
+
289
+
290
+ ## 6. Mantenimiento del paquete
291
+
292
+ ```bash
293
+ npm run build # compila la librería a dist/ (JS + .d.ts)
294
+ npm test # tests del generador y candado de diseño
295
+ npm run lint # oxlint
296
+ npm run design:accept # acepta un cambio de dibujo (ver sección 4)
297
+ ```
298
+
299
+ Estructura:
300
+
301
+ ```
302
+ src/
303
+ index.ts Entrada pública del paquete
304
+ react.tsx Entrada idicon/react
305
+ lib/
306
+ avatar.ts Composición del avatar: fondo, personajes, cara, pose
307
+ palettes.ts Paletas, contraste y reparto de colores
308
+ random.ts Generador aleatorio con semilla (sfc32 + xmur3)
309
+ avatar.test.ts Tests de reglas (determinismo, colores, opciones...)
310
+ design-lock.test.ts Candado de diseño
311
+ __snapshots__/ Huellas del candado
312
+ App.tsx, components/, lib/*.ts restantes Solo para la demo
313
+ scripts/fix-dts.mjs Ajusta las rutas de import en los .d.ts tras compilar
314
+ .github/workflows/ci.yml Integración continua
315
+ CHANGELOG.md Historial de versiones
316
+ ```
317
+
318
+ Solo lo exportado desde `src/index.ts` y `src/react.tsx` forma parte de la API pública. El resto es interno y puede cambiar.
319
+
320
+ ### Publicar una versión
321
+
322
+ 1. `npm test`, `npm run lint` y `npm run build` pasan (y el CI está en verde).
323
+ 2. Añade la entrada al `CHANGELOG.md`, indicando si altera avatares existentes.
324
+ 3. Sube la versión según la tabla de la sección 4. Esto actualiza `package.json` y crea la etiqueta Git `vX.Y.Z`:
325
+ ```bash
326
+ npm version patch # o minor, o major
327
+ git push --follow-tags
328
+ ```
329
+ 4. Si se publica en un registro: `npm pack --dry-run` para revisar el contenido (solo `dist/`, `README.md` y `package.json`) y después `npm publish`. Para un registro privado con ámbito (por ejemplo `@empresa/idicon` en GitHub Packages), cambia `name` en `package.json` y configura `publishConfig.registry` antes.
330
+
331
+ `npm publish` ejecuta `npm run build` automáticamente (`prepack`), así que `dist/` siempre se genera a partir del código actual. Las apps que instalan desde Git con `#vX.Y.Z` también compilan `dist/` al instalar.
@@ -0,0 +1,3 @@
1
+ export { generateAvatarSvg, avatarDataUri, SUBJECTS, PATTERNS, PATTERN_CHOICES, DESIGN_VERSION, type AvatarOptions, type Subject, type Pattern, type PatternChoice, } from "./lib/avatar.js";
2
+ export { PALETTES } from "./lib/palettes.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,eAAe,EACf,cAAc,EACd,KAAK,aAAa,EAClB,KAAK,OAAO,EACZ,KAAK,OAAO,EACZ,KAAK,aAAa,GACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ // Public entry of the npm package. Anything not re-exported here is internal
2
+ // and may change without notice.
3
+ export { generateAvatarSvg, avatarDataUri, SUBJECTS, PATTERNS, PATTERN_CHOICES, DESIGN_VERSION, } from "./lib/avatar.js";
4
+ export { PALETTES } from "./lib/palettes.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,iCAAiC;AACjC,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,eAAe,EACf,cAAc,GAKf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,35 @@
1
+ export type Pattern = "rings" | "stripes" | "blobs" | "dots" | "horizon";
2
+ export declare const PATTERNS: readonly Pattern[];
3
+ /** "random" lets the id decide, "plain" is a flat color with no pattern. */
4
+ export type PatternChoice = "random" | "plain" | Pattern;
5
+ /** What the avatar shows: "random" lets the id decide, "none" is background only. */
6
+ export type Subject = "random" | "person" | "character" | "object" | "shape" | "none";
7
+ export declare const SUBJECTS: readonly Subject[];
8
+ export declare const PATTERN_CHOICES: readonly PatternChoice[];
9
+ export interface AvatarOptions {
10
+ subject?: Subject;
11
+ pattern?: PatternChoice;
12
+ /** Exactly 5 #rrggbb colors; anything else falls back to the automatic palette. */
13
+ palette?: readonly string[];
14
+ /**
15
+ * Pixel width and height written on the <svg> element (default 256). The
16
+ * drawing scales through its viewBox, so this never changes what is drawn.
17
+ */
18
+ size?: number;
19
+ }
20
+ /**
21
+ * Version of the drawing itself. Bump it (together with the package's major
22
+ * version) whenever any change makes an existing id render differently:
23
+ * a new character, palette or pattern, or a reordered rng call. The design
24
+ * lock test (design-lock.test.ts) fails on such a change until it is
25
+ * accepted on purpose.
26
+ */
27
+ export declare const DESIGN_VERSION = 1;
28
+ /** The avatar for `id`, as a standalone SVG document string. */
29
+ export declare function generateAvatarSvg(id: string, options?: AvatarOptions): string;
30
+ /**
31
+ * The same avatar as a `data:` URL, ready for an <img src> or a CSS
32
+ * background-image, for pages that cannot inline SVG markup.
33
+ */
34
+ export declare function avatarDataUri(id: string, options?: AvatarOptions): string;
35
+ //# sourceMappingURL=avatar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"avatar.d.ts","sourceRoot":"","sources":["../../src/lib/avatar.ts"],"names":[],"mappings":"AA0MA,MAAM,MAAM,OAAO,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;AACzE,eAAO,MAAM,QAAQ,EAAE,SAAS,OAAO,EAAqD,CAAC;AAC7F,4EAA4E;AAC5E,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC;AAiWzD,qFAAqF;AACrF,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AACtF,eAAO,MAAM,QAAQ,EAAE,SAAS,OAAO,EAAiE,CAAC;AACzG,eAAO,MAAM,eAAe,EAAE,SAAS,aAAa,EAAqC,CAAC;AAS1F,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,mFAAmF;IACnF,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAID;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,IAAI,CAAC;AAEhC,gEAAgE;AAChE,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,MAAM,CAoCjF;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,MAAM,CAE7E"}