@eduardoalvarez/arrecife 0.3.0 → 0.5.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/CHANGELOG.md +43 -0
- package/README.md +121 -1
- package/dist/brand/index.cjs +29 -10
- package/dist/brand/index.d.cts +9 -1
- package/dist/brand/index.d.ts +9 -1
- package/dist/brand/index.js +4 -2
- package/dist/chart/index.cjs +287 -0
- package/dist/chart/index.d.cts +127 -0
- package/dist/chart/index.d.ts +127 -0
- package/dist/chart/index.js +103 -0
- package/dist/chunk-KPZNNMV5.js +83 -0
- package/dist/chunk-MLKGABMK.js +7 -0
- package/dist/chunk-NHS7ETKJ.js +27 -0
- package/dist/{chunk-I7GYZD2A.js → chunk-TSPJOM6K.js} +5 -7
- package/dist/chunk-UOWIDFCB.js +81 -0
- package/dist/{chunk-VSMW2CT4.js → chunk-VPT32GPG.js} +2 -1
- package/dist/{chunk-ND45OQOC.js → chunk-YZ2SDOVZ.js} +29 -35
- package/dist/chunk-ZEOQKRQ7.js +19 -0
- package/dist/form/index.cjs +301 -0
- package/dist/form/index.d.cts +86 -0
- package/dist/form/index.d.ts +86 -0
- package/dist/form/index.js +84 -0
- package/dist/index.cjs +1094 -293
- package/dist/index.d.cts +452 -37
- package/dist/index.d.ts +452 -37
- package/dist/index.js +963 -373
- package/dist/label-DuTvJGxD.d.cts +14 -0
- package/dist/label-DuTvJGxD.d.ts +14 -0
- package/dist/og/index.js +2 -1
- package/dist/shiki/index.js +2 -1
- package/dist/tema/index.cjs +94 -0
- package/dist/tema/index.d.cts +110 -0
- package/dist/tema/index.d.ts +110 -0
- package/dist/tema/index.js +2 -0
- package/dist/tokens/index.cjs +6 -0
- package/dist/tokens/index.d.cts +33 -1
- package/dist/tokens/index.d.ts +33 -1
- package/dist/tokens/index.js +3 -2
- package/dist/tokens/theme.css +43 -0
- package/llms.txt +351 -44
- package/package.json +31 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,48 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.5.0](https://github.com/Proskynete/arrecife/compare/v0.4.0...v0.5.0) (2026-08-31)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### ⚠ BREAKING CHANGES
|
|
7
|
+
|
|
8
|
+
* **primitives:** `Toast`, `ToastProvider`, `ToastViewport`, `ToastTitle` y `ToastDescription` dejan de exportarse; se usa `<Toaster />` una vez y `toast()` desde donde haga falta. `ToastAction` no cambia. Migración en docs/migracion-0.5.md.
|
|
9
|
+
|
|
10
|
+
### 🚀 Novedades
|
|
11
|
+
|
|
12
|
+
* **components:** EventCalendar, la agenda con crear, editar y borrar ([6190700](https://github.com/Proskynete/arrecife/commit/61907003eeef777ba86c594791b2e95d225eda1f))
|
|
13
|
+
* **components:** la barra, el pie y las métricas como en el documento ([203b669](https://github.com/Proskynete/arrecife/commit/203b669379f63048ce4b34fce9a9411aebec3279))
|
|
14
|
+
* **primitives:** AvatarUpload, el avatar que se puede cambiar ([f888b4c](https://github.com/Proskynete/arrecife/commit/f888b4c0fadeddfb885f0b4651bf56000da7d430))
|
|
15
|
+
* **primitives:** el plegable anima la altura, como cuarta excepción ([b9dd44c](https://github.com/Proskynete/arrecife/commit/b9dd44ccb99ccb2c0f00ec99fefa17bc838cca52))
|
|
16
|
+
* **primitives:** Toaster es la única forma de mostrar un aviso ([2ec1d23](https://github.com/Proskynete/arrecife/commit/2ec1d2383ecd87c58a88c9e32543dc2112df2321))
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### 📚 Documentación
|
|
20
|
+
|
|
21
|
+
* los iconos de redes van agrupados, y por qué ([1939455](https://github.com/Proskynete/arrecife/commit/19394554185a54e4e752a86e27e60f1a60acec26))
|
|
22
|
+
|
|
23
|
+
## [0.4.0](https://github.com/Proskynete/arrecife/compare/v0.3.0...v0.4.0) (2026-08-31)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
### 🚀 Novedades
|
|
27
|
+
|
|
28
|
+
* **components:** ScrollingProgressBar y las cinco ranuras que faltaban ([52325cc](https://github.com/Proskynete/arrecife/commit/52325ccff7eedbda39d449c98386668df7a518bf))
|
|
29
|
+
* **form:** la capa de formulario y el chasis de gráficas, en su subruta ([4a40857](https://github.com/Proskynete/arrecife/commit/4a40857e9e9efc8bbe4011bf72f6313347c97541))
|
|
30
|
+
* **primitives:** Accordion, AlertDialog y el Toast imperativo ([239120d](https://github.com/Proskynete/arrecife/commit/239120d510ea395159719581ef69c26734d82441))
|
|
31
|
+
* **tema:** el modo claro y oscuro, sin parpadeo y sin React ([c99995c](https://github.com/Proskynete/arrecife/commit/c99995c8eae6313ece6ffdcf927d9120f6050866))
|
|
32
|
+
* **tokens:** la paleta de series de gráfica, cuatro colores por tono ([b660a30](https://github.com/Proskynete/arrecife/commit/b660a30376c794be82f6a11808d9de175a31d5d9))
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
### 🐛 Correcciones
|
|
36
|
+
|
|
37
|
+
* **ci:** check:exports no veía React dentro de un chunk ([3354ab1](https://github.com/Proskynete/arrecife/commit/3354ab12feb867a81480e1c3b612280c40f765ad))
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
### 📚 Documentación
|
|
41
|
+
|
|
42
|
+
* los dos requisitos de consumo que no dan ningún error ([0a3a7fd](https://github.com/Proskynete/arrecife/commit/0a3a7fd71124aa2dafa3b70df4a90f8fd080544d))
|
|
43
|
+
* main está protegida y así se trabaja con ella ([a625a49](https://github.com/Proskynete/arrecife/commit/a625a499ba871ebf7f13a8f7f0cc9f7fbfff17fc))
|
|
44
|
+
* mergear saltándose la regla se pide, no pasa solo ([c3aca08](https://github.com/Proskynete/arrecife/commit/c3aca08d3926885edea1f500200f0a7496ab13bb))
|
|
45
|
+
|
|
3
46
|
## [0.3.0](https://github.com/Proskynete/arrecife/compare/v0.2.0...v0.3.0) (2026-08-31)
|
|
4
47
|
|
|
5
48
|
|
package/README.md
CHANGED
|
@@ -64,6 +64,30 @@ mismo objeto `tokens`: la fuente no cambia.
|
|
|
64
64
|
El modo oscuro es el primario y es el default. Un proyecto en modo claro declara
|
|
65
65
|
`data-theme="light"` en `<html>`; uno oscuro no necesita declarar nada.
|
|
66
66
|
|
|
67
|
+
**Si además vas a usar componentes, falta una línea, y sin ella no falla nada.**
|
|
68
|
+
Tailwind no escanea `node_modules`, así que purga todas las clases que emiten los
|
|
69
|
+
componentes: `border-hairline`, `rounded-pill` y `p-step-lg` resuelven a la nada.
|
|
70
|
+
No hay error en consola, no hay aviso en el build, no hay clase sin definir — la
|
|
71
|
+
tarjeta simplemente sale con borde `currentColor` y la píldora, cuadrada.
|
|
72
|
+
|
|
73
|
+
```css
|
|
74
|
+
@import "tailwindcss";
|
|
75
|
+
@import "@eduardoalvarez/arrecife/tokens/theme.css";
|
|
76
|
+
|
|
77
|
+
/* Sin esto, los componentes se montan sin ningún estilo del sistema. */
|
|
78
|
+
@source "../node_modules/@eduardoalvarez/arrecife/dist";
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
La ruta es relativa al archivo CSS donde va la directiva, así que en un proyecto
|
|
82
|
+
con la hoja en `src/styles/` sube dos niveles y no uno. Lo detectaron los tests
|
|
83
|
+
E2E del blog, no el build, y hasta la 0.3.0 esto solo estaba escrito en
|
|
84
|
+
`llms.txt` — el archivo que lee un agente y no una persona.
|
|
85
|
+
|
|
86
|
+
> **Vienes de la 0.4.0 o anterior.** `Toast`, `ToastProvider`, `ToastViewport`,
|
|
87
|
+
> `ToastTitle` y `ToastDescription` dejaron de ser API pública en la 0.5.0: se
|
|
88
|
+
> usa `Toaster` y `toast()`. `ToastAction` se queda. La migración, con el porqué
|
|
89
|
+
> y los ejemplos, está en [`docs/migracion-0.5.md`](docs/migracion-0.5.md).
|
|
90
|
+
|
|
67
91
|
> **Vienes de la 0.2.0 o anterior.** Los cinco escalones de espaciado se
|
|
68
92
|
> renombraron: `p-md` es ahora `p-step-md`, `gap-sm` es `gap-step-sm`. Es un
|
|
69
93
|
> cambio incompatible, y si tu proyecto usa `max-w-sm`, `max-w-md` o `max-w-lg`,
|
|
@@ -101,6 +125,49 @@ solución es declararlo con el nombre que pide el token:
|
|
|
101
125
|
}
|
|
102
126
|
```
|
|
103
127
|
|
|
128
|
+
#### En Next, con `next/font`
|
|
129
|
+
|
|
130
|
+
Es el mismo fallo por otra puerta, y muerde a los dos proyectos Next. `next/font`
|
|
131
|
+
registra cada familia bajo un nombre GENERADO —`__Geist_a1b2c3`— y la expone como
|
|
132
|
+
una custom property; el nombre literal `"Geist"` que declaran los tokens no
|
|
133
|
+
existe en ningún `@font-face` de la página.
|
|
134
|
+
|
|
135
|
+
Importar `theme.css` sobrescribe `--font-sans` con ese literal, y las tres
|
|
136
|
+
familias caen a la fuente del sistema. En silencio: no hay 404, porque la fuente
|
|
137
|
+
sí se cargó — con otro nombre.
|
|
138
|
+
|
|
139
|
+
La solución es reafirmar las tres DESPUÉS del import, apuntando a las variables
|
|
140
|
+
que genera `next/font`:
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
// app/fuentes.ts
|
|
144
|
+
import { Geist, Bricolage_Grotesque, JetBrains_Mono } from 'next/font/google';
|
|
145
|
+
|
|
146
|
+
export const sans = Geist({ subsets: ['latin'], variable: '--fuente-sans' });
|
|
147
|
+
export const display = Bricolage_Grotesque({ subsets: ['latin'], variable: '--fuente-display' });
|
|
148
|
+
export const mono = JetBrains_Mono({ subsets: ['latin'], variable: '--fuente-mono' });
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
```css
|
|
152
|
+
@import "tailwindcss";
|
|
153
|
+
@import "@eduardoalvarez/arrecife/tokens/theme.css";
|
|
154
|
+
@source "../node_modules/@eduardoalvarez/arrecife/dist";
|
|
155
|
+
|
|
156
|
+
/* Después del import, o gana el literal que no está cargado. */
|
|
157
|
+
@theme {
|
|
158
|
+
--font-sans: var(--fuente-sans), ui-sans-serif, system-ui, sans-serif;
|
|
159
|
+
--font-display: var(--fuente-display), ui-sans-serif, system-ui, sans-serif;
|
|
160
|
+
--font-mono: var(--fuente-mono), ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Las variables se llaman `--fuente-*` y no `--font-*` a propósito: `--font-sans`
|
|
165
|
+
es el nombre que Tailwind usa para SU token, y dárselo a `next/font` deja las dos
|
|
166
|
+
capas peleando por la misma propiedad.
|
|
167
|
+
|
|
168
|
+
El `variable` de cada familia va en la clase del `<html>`, como pide Next:
|
|
169
|
+
`className={`${sans.variable} ${display.variable} ${mono.variable}`}`.
|
|
170
|
+
|
|
104
171
|
### Mapa de tokens a utilidades
|
|
105
172
|
|
|
106
173
|
| Token | Custom property | Utilidad |
|
|
@@ -191,6 +258,59 @@ Comprobado empaquetando la librería con `pnpm pack` e instalándola en un proye
|
|
|
191
258
|
aparte: los tipos resuelven desde `dist/`, `./tokens` carga sin arrastrar React y
|
|
192
259
|
`./tokens/theme.css` se resuelve por subruta.
|
|
193
260
|
|
|
261
|
+
### Los iconos de redes van agrupados
|
|
262
|
+
|
|
263
|
+
Es lo primero con lo que tropieza quien consume la librería, porque la forma
|
|
264
|
+
natural no funciona:
|
|
265
|
+
|
|
266
|
+
```tsx
|
|
267
|
+
// ❌ no existe
|
|
268
|
+
import { GitHub, LinkedIn } from '@eduardoalvarez/arrecife';
|
|
269
|
+
|
|
270
|
+
// ✅
|
|
271
|
+
import { social } from '@eduardoalvarez/arrecife';
|
|
272
|
+
|
|
273
|
+
<social.GitHub />
|
|
274
|
+
<social.LinkedIn />
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
Los ocho son `GitHub`, `LinkedIn`, `X`, `Instagram`, `Discord`, `YouTube`, `Rss`
|
|
278
|
+
y `Correo`. Van bajo un namespace por un motivo concreto: **uno se llama `X`**.
|
|
279
|
+
Un `export const X` en la raíz de una librería de componentes colisiona con
|
|
280
|
+
cualquier cosa —una variable de un genérico, un `import { X }` de otro sitio— y
|
|
281
|
+
el fallo aparece lejos de aquí.
|
|
282
|
+
|
|
283
|
+
**Los glifos internos NO se exportan.** `Close`, `ChevronDown`, `Copy`, `Sol` y
|
|
284
|
+
compañía son el juego mínimo que necesitan los primitivos y se quedan dentro.
|
|
285
|
+
Publicarlos convertiría `lib/glyphs.tsx` en la librería de iconos que el sistema
|
|
286
|
+
decidió no tener, y a partir de ahí crece sola. Un proyecto que necesite un icono
|
|
287
|
+
pasa el suyo: `Stat` recibe `icon`, `Footer` recibe el `icon` de cada red.
|
|
288
|
+
|
|
289
|
+
### Las dos subrutas que piden una dependencia
|
|
290
|
+
|
|
291
|
+
`./form` y `./chart` no cuelgan de la raíz, y es a propósito. Cada una pide una
|
|
292
|
+
dependencia de pares **opcional** —`react-hook-form` y `recharts`—, y colgarlas
|
|
293
|
+
del índice principal obligaría a los cinco proyectos a instalarlas para que su
|
|
294
|
+
bundler resolviera un import que cuatro de ellos nunca ejecutan.
|
|
295
|
+
|
|
296
|
+
Es la misma decisión que `./og` y `./shiki`, mirada desde el otro lado: allí se
|
|
297
|
+
saca React del camino de quien no lo monta; aquí se saca Recharts del camino de
|
|
298
|
+
quien no dibuja.
|
|
299
|
+
|
|
300
|
+
```tsx
|
|
301
|
+
import { Form, FormField, FormItem, FormLabel, FormControl, FormMessage }
|
|
302
|
+
from '@eduardoalvarez/arrecife/form';
|
|
303
|
+
|
|
304
|
+
import { ChartContainer, ChartTooltip, ChartTooltipContent, colorDeSerie }
|
|
305
|
+
from '@eduardoalvarez/arrecife/chart';
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
`check:exports` verifica que las cuatro portables —`./tokens`, `./tema`, `./og` y
|
|
309
|
+
`./shiki`— no traen React en el `dist/` publicado, **siguiendo los imports
|
|
310
|
+
relativos**. Sin eso el check era papel mojado: con `treeshake` activo, cada
|
|
311
|
+
entrada portable queda en dos líneas que reexportan de un `chunk-XXXX.js`, y un
|
|
312
|
+
grep sobre esas dos líneas no encuentra React ni aunque el chunk lo importe.
|
|
313
|
+
|
|
194
314
|
## Scripts
|
|
195
315
|
|
|
196
316
|
| | |
|
|
@@ -199,7 +319,7 @@ aparte: los tipos resuelven desde `dist/`, `./tokens` carga sin arrastrar React
|
|
|
199
319
|
| `pnpm typecheck` | `tsc --noEmit` |
|
|
200
320
|
| `pnpm lint` | ESLint, incluido el veto a hex literales fuera de `tokens.ts` |
|
|
201
321
|
| `pnpm check:tokens` | falla si `src/tokens/` importa algo de fuera |
|
|
202
|
-
| `pnpm test` | corre axe sobre las
|
|
322
|
+
| `pnpm test` | compila Tailwind y corre axe sobre las 206 stories, en los dos modos |
|
|
203
323
|
| `pnpm check:exports` | verifica que `dist/` tiene lo que `exports` promete |
|
|
204
324
|
| `pnpm check:release` | valida `release-please-config.json` contra el esquema oficial |
|
|
205
325
|
| `pnpm storybook` | genera los tokens y levanta Storybook en el 6006 |
|
package/dist/brand/index.cjs
CHANGED
|
@@ -116,6 +116,9 @@ var spacing = {
|
|
|
116
116
|
stepXl: 40,
|
|
117
117
|
section: 96
|
|
118
118
|
};
|
|
119
|
+
var tagline = {
|
|
120
|
+
/** Header, una línea. */
|
|
121
|
+
corto: "Ayudo a equipos a escalar con criterio"};
|
|
119
122
|
var naming = {
|
|
120
123
|
wordmark: "Eduardo \xC1lvarez"};
|
|
121
124
|
|
|
@@ -165,20 +168,36 @@ function Logo({
|
|
|
165
168
|
sobre = "oscuro",
|
|
166
169
|
basePath = RUTA_ASSETS,
|
|
167
170
|
soloIsotipo = false,
|
|
171
|
+
conLema = false,
|
|
168
172
|
className,
|
|
169
173
|
...props
|
|
170
174
|
}) {
|
|
175
|
+
const conAleta = /* @__PURE__ */ jsxRuntime.jsx(
|
|
176
|
+
Isotipo,
|
|
177
|
+
{
|
|
178
|
+
sobre,
|
|
179
|
+
basePath,
|
|
180
|
+
alt: soloIsotipo ? naming.wordmark : "",
|
|
181
|
+
className: conLema ? "h-9 w-auto" : "h-7 w-auto"
|
|
182
|
+
}
|
|
183
|
+
);
|
|
184
|
+
const wordmark = /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui font-display text-text-primary font-bold tracking-[-0.02em]", children: naming.wordmark });
|
|
185
|
+
if (soloIsotipo) {
|
|
186
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("gap-step-xs inline-flex items-center", className), ...props, children: conAleta });
|
|
187
|
+
}
|
|
188
|
+
if (conLema) {
|
|
189
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("gap-step-sm inline-flex items-center", className), ...props, children: [
|
|
190
|
+
conAleta,
|
|
191
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", className: "bg-hairline h-8 w-px shrink-0" }),
|
|
192
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 flex-col", children: [
|
|
193
|
+
wordmark,
|
|
194
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-eyebrow font-mono text-text-muted uppercase", children: tagline.corto })
|
|
195
|
+
] })
|
|
196
|
+
] });
|
|
197
|
+
}
|
|
171
198
|
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("gap-step-xs inline-flex items-center", className), ...props, children: [
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
{
|
|
175
|
-
sobre,
|
|
176
|
-
basePath,
|
|
177
|
-
alt: soloIsotipo ? naming.wordmark : "",
|
|
178
|
-
className: "h-7 w-auto"
|
|
179
|
-
}
|
|
180
|
-
),
|
|
181
|
-
soloIsotipo ? null : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui font-display text-text-primary font-bold tracking-[-0.02em]", children: naming.wordmark })
|
|
199
|
+
conAleta,
|
|
200
|
+
wordmark
|
|
182
201
|
] });
|
|
183
202
|
}
|
|
184
203
|
function Mascota({
|
package/dist/brand/index.d.cts
CHANGED
|
@@ -22,6 +22,14 @@ type LogoProps = Omit<ComponentPropsWithoutRef<'span'>, 'children'> & {
|
|
|
22
22
|
basePath?: string | undefined;
|
|
23
23
|
/** Oculta el wordmark y deja solo la aleta, para barras muy estrechas. */
|
|
24
24
|
soloIsotipo?: boolean | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Añade el lema bajo el wordmark, separado de la aleta por una divisoria.
|
|
27
|
+
*
|
|
28
|
+
* Es la forma que toma la marca en la barra del sitio. El texto sale de
|
|
29
|
+
* `tagline.corto` y no se puede pasar por prop, por lo mismo que el wordmark:
|
|
30
|
+
* un lema escrito a mano en cinco proyectos son cinco lemas en seis meses.
|
|
31
|
+
*/
|
|
32
|
+
conLema?: boolean | undefined;
|
|
25
33
|
};
|
|
26
34
|
/**
|
|
27
35
|
* El wordmark sale de `naming.wordmark`, no de una cadena escrita a mano, y
|
|
@@ -31,7 +39,7 @@ type LogoProps = Omit<ComponentPropsWithoutRef<'span'>, 'children'> & {
|
|
|
31
39
|
* Cuando se oculta el wordmark, el nombre sigue llegando al lector de pantalla
|
|
32
40
|
* por el `alt` del isotipo. Un logo sin nombre accesible es un logo invisible.
|
|
33
41
|
*/
|
|
34
|
-
declare function Logo({ sobre, basePath, soloIsotipo, className, ...props }: LogoProps): react.JSX.Element;
|
|
42
|
+
declare function Logo({ sobre, basePath, soloIsotipo, conLema, className, ...props }: LogoProps): react.JSX.Element;
|
|
35
43
|
|
|
36
44
|
type Base = Omit<ComponentPropsWithoutRef<'img'>, 'src' | 'alt'> & {
|
|
37
45
|
basePath?: string | undefined;
|
package/dist/brand/index.d.ts
CHANGED
|
@@ -22,6 +22,14 @@ type LogoProps = Omit<ComponentPropsWithoutRef<'span'>, 'children'> & {
|
|
|
22
22
|
basePath?: string | undefined;
|
|
23
23
|
/** Oculta el wordmark y deja solo la aleta, para barras muy estrechas. */
|
|
24
24
|
soloIsotipo?: boolean | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Añade el lema bajo el wordmark, separado de la aleta por una divisoria.
|
|
27
|
+
*
|
|
28
|
+
* Es la forma que toma la marca en la barra del sitio. El texto sale de
|
|
29
|
+
* `tagline.corto` y no se puede pasar por prop, por lo mismo que el wordmark:
|
|
30
|
+
* un lema escrito a mano en cinco proyectos son cinco lemas en seis meses.
|
|
31
|
+
*/
|
|
32
|
+
conLema?: boolean | undefined;
|
|
25
33
|
};
|
|
26
34
|
/**
|
|
27
35
|
* El wordmark sale de `naming.wordmark`, no de una cadena escrita a mano, y
|
|
@@ -31,7 +39,7 @@ type LogoProps = Omit<ComponentPropsWithoutRef<'span'>, 'children'> & {
|
|
|
31
39
|
* Cuando se oculta el wordmark, el nombre sigue llegando al lector de pantalla
|
|
32
40
|
* por el `alt` del isotipo. Un logo sin nombre accesible es un logo invisible.
|
|
33
41
|
*/
|
|
34
|
-
declare function Logo({ sobre, basePath, soloIsotipo, className, ...props }: LogoProps): react.JSX.Element;
|
|
42
|
+
declare function Logo({ sobre, basePath, soloIsotipo, conLema, className, ...props }: LogoProps): react.JSX.Element;
|
|
35
43
|
|
|
36
44
|
type Base = Omit<ComponentPropsWithoutRef<'img'>, 'src' | 'alt'> & {
|
|
37
45
|
basePath?: string | undefined;
|
package/dist/brand/index.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
export { CaraDeMascota, Isotipo, Logo, Mascota } from '../chunk-
|
|
1
|
+
export { CaraDeMascota, Isotipo, Logo, Mascota } from '../chunk-YZ2SDOVZ.js';
|
|
2
2
|
export { RUTA_ASSETS, aletas, caras, listaCaras, listaPoses, poses, usoDeCara } from '../chunk-E3OMP2DL.js';
|
|
3
|
-
import '../chunk-
|
|
3
|
+
import '../chunk-NHS7ETKJ.js';
|
|
4
|
+
import '../chunk-TSPJOM6K.js';
|
|
5
|
+
import '../chunk-MLKGABMK.js';
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var recharts = require('recharts');
|
|
4
|
+
var clsx = require('clsx');
|
|
5
|
+
var tailwindMerge = require('tailwind-merge');
|
|
6
|
+
var reactSlot = require('@radix-ui/react-slot');
|
|
7
|
+
var classVarianceAuthority = require('class-variance-authority');
|
|
8
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
9
|
+
|
|
10
|
+
// src/chart/index.tsx
|
|
11
|
+
var typeScale = {
|
|
12
|
+
display: { family: "display", size: 76, lineHeight: 0.96, weight: 800, tracking: "-0.035em" },
|
|
13
|
+
/** Métricas grandes. Números, no prosa: interlineado 1 y sin descendentes. */
|
|
14
|
+
stat: { family: "display", size: 46, lineHeight: 1, weight: 800, tracking: "-0.035em" },
|
|
15
|
+
h1: { family: "display", size: 44, lineHeight: 1.05, weight: 700, tracking: "-0.03em" },
|
|
16
|
+
h2: { family: "display", size: 30, lineHeight: 1.1, weight: 600, tracking: "-0.02em" },
|
|
17
|
+
h3: { family: "display", size: 25, lineHeight: 1.15, weight: 600, tracking: "-0.02em" },
|
|
18
|
+
body: { family: "sans", size: 18, lineHeight: 1.75, weight: 400 },
|
|
19
|
+
/**
|
|
20
|
+
* 17px. El botón grande y la bajada de las páginas internas.
|
|
21
|
+
*
|
|
22
|
+
* Entra como escalón propio porque el documento lo usa DOS veces y en piezas
|
|
23
|
+
* distintas: «lg 15px 30px r12» con texto de 17, y «h1 44/700 · bajada 17px ·
|
|
24
|
+
* párrafo de contexto 15px». Un solo uso no habría justificado partir la
|
|
25
|
+
* distancia entre `ui` (15) y `body` (18); dos sí.
|
|
26
|
+
*/
|
|
27
|
+
lead: { family: "sans", size: 17, lineHeight: 1.5, weight: 400 },
|
|
28
|
+
ui: { family: "sans", size: 15, lineHeight: 1.6, weight: 400 },
|
|
29
|
+
label: { family: "sans", size: 13, lineHeight: 1.5, weight: 500 },
|
|
30
|
+
/**
|
|
31
|
+
* La escala de las etiquetas de estado: sans 12.5/500, cuadrada.
|
|
32
|
+
*
|
|
33
|
+
* Es medio píxel por debajo de `label`, y esta vez el medio píxel sí importa:
|
|
34
|
+
* una etiqueta de estado va dentro de una tabla o al lado de un título, y a 13
|
|
35
|
+
* competía con el texto que acompaña. El documento la da en 12.5 y se ve.
|
|
36
|
+
*/
|
|
37
|
+
tag: { family: "sans", size: 12.5, lineHeight: 1.4, weight: 500 },
|
|
38
|
+
/**
|
|
39
|
+
* La escala de categoría y métrica: mono 11.5.
|
|
40
|
+
*
|
|
41
|
+
* Rompe el suelo de `limits.minScreenPx`, y es a propósito. Ese suelo protege
|
|
42
|
+
* al TEXTO —lo que se lee en una frase—, y una píldora de una palabra no es
|
|
43
|
+
* texto corrido: es una marca. El contraste sigue medido y pasa AA (plancton
|
|
44
|
+
* 5.57:1 sobre abismo), que es la parte que no se negocia.
|
|
45
|
+
*
|
|
46
|
+
* A 13 las tres familias de etiqueta salían del tamaño de un botón pequeño y
|
|
47
|
+
* pesaban más que el título que acompañan. Ver `docs/decisiones.md`.
|
|
48
|
+
*/
|
|
49
|
+
chip: { family: "mono", size: 11.5, lineHeight: 1.4, weight: 400 },
|
|
50
|
+
/**
|
|
51
|
+
* Mono SIN transformar: fechas, rutas, versiones, nombres de archivo, la firma
|
|
52
|
+
* del footer y las métricas de etiqueta. Es la mayoría del mono del sistema.
|
|
53
|
+
*
|
|
54
|
+
* Existe porque `eyebrow` lleva `uppercase` de fábrica y no es una preferencia
|
|
55
|
+
* que se pueda apagar: es la escala del eyebrow. Un `18 ago 2026` en versalitas
|
|
56
|
+
* o un `pose-laptop-coffee.png` en mayúsculas están mal, y sin este escalón la
|
|
57
|
+
* única salida era un `normal-case` en cada sitio de uso.
|
|
58
|
+
*
|
|
59
|
+
* El documento dice 12.5. Son 13 por la misma razón por la que `textMuted` se
|
|
60
|
+
* corrigió: `limits.minScreenPx` es 13 y plancton «nunca bajo 13px». Esta
|
|
61
|
+
* escala es justo donde se escriben las metas en muted, así que ponerla en
|
|
62
|
+
* 12.5 habría dejado ilegible su uso más común por medio píxel.
|
|
63
|
+
*/
|
|
64
|
+
meta: { family: "mono", size: 13, lineHeight: 1.6, weight: 400 },
|
|
65
|
+
eyebrow: { family: "mono", size: 12, tracking: "0.12em", transform: "uppercase" }
|
|
66
|
+
};
|
|
67
|
+
var radius = {
|
|
68
|
+
chip: 6,
|
|
69
|
+
control: 10,
|
|
70
|
+
card: 14,
|
|
71
|
+
panel: 16,
|
|
72
|
+
pill: 999
|
|
73
|
+
};
|
|
74
|
+
var control = {
|
|
75
|
+
sm: 14,
|
|
76
|
+
md: 22,
|
|
77
|
+
lg: 30,
|
|
78
|
+
/** Botón de icono: cuadrado, sin texto. */
|
|
79
|
+
icon: 42
|
|
80
|
+
};
|
|
81
|
+
var spacing = {
|
|
82
|
+
stepXs: 8,
|
|
83
|
+
stepSm: 12,
|
|
84
|
+
stepMd: 16,
|
|
85
|
+
stepLg: 26,
|
|
86
|
+
stepXl: 40,
|
|
87
|
+
section: 96
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
// src/lib/cn.ts
|
|
91
|
+
var kebab = (nombre) => nombre.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);
|
|
92
|
+
var escalas = Object.keys(typeScale);
|
|
93
|
+
var radios = Object.keys(radius);
|
|
94
|
+
var espacios = Object.keys(spacing).map(kebab);
|
|
95
|
+
var controles = Object.keys(control).map((nombre) => `control-${kebab(nombre)}`);
|
|
96
|
+
var twMerge = tailwindMerge.extendTailwindMerge({
|
|
97
|
+
extend: {
|
|
98
|
+
classGroups: {
|
|
99
|
+
"font-size": [{ text: escalas }],
|
|
100
|
+
rounded: [{ rounded: radios }],
|
|
101
|
+
p: [{ p: espacios }],
|
|
102
|
+
px: [{ px: [...espacios, ...controles] }],
|
|
103
|
+
py: [{ py: espacios }],
|
|
104
|
+
gap: [{ gap: espacios }],
|
|
105
|
+
size: [{ size: controles }]
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
function cn(...inputs) {
|
|
110
|
+
return twMerge(clsx.clsx(inputs));
|
|
111
|
+
}
|
|
112
|
+
var ETIQUETA = {
|
|
113
|
+
display: "h1",
|
|
114
|
+
stat: "p",
|
|
115
|
+
h1: "h1",
|
|
116
|
+
h2: "h2",
|
|
117
|
+
h3: "h3",
|
|
118
|
+
body: "p",
|
|
119
|
+
lead: "p",
|
|
120
|
+
ui: "p",
|
|
121
|
+
label: "span",
|
|
122
|
+
tag: "span",
|
|
123
|
+
meta: "p",
|
|
124
|
+
chip: "span",
|
|
125
|
+
eyebrow: "p"
|
|
126
|
+
};
|
|
127
|
+
var texto = classVarianceAuthority.cva("", {
|
|
128
|
+
variants: {
|
|
129
|
+
variant: {
|
|
130
|
+
display: "text-display font-display",
|
|
131
|
+
// Métricas grandes: 46px de display. Es la única escala pensada para un
|
|
132
|
+
// número, y por eso el interlineado es 1.
|
|
133
|
+
stat: "text-stat font-display",
|
|
134
|
+
h1: "text-h1 font-display",
|
|
135
|
+
h2: "text-h2 font-display",
|
|
136
|
+
h3: "text-h3 font-display",
|
|
137
|
+
body: "text-body font-sans",
|
|
138
|
+
// 17px: la bajada de las páginas internas y el botón grande.
|
|
139
|
+
lead: "text-lead font-sans",
|
|
140
|
+
ui: "text-ui font-sans",
|
|
141
|
+
label: "text-label font-sans",
|
|
142
|
+
// Las dos escalas de etiqueta. `tag` es el estado (sans 12.5/500) y `chip`
|
|
143
|
+
// la categoría y la métrica (mono 11.5). Ninguna transforma el texto.
|
|
144
|
+
tag: "text-tag font-sans",
|
|
145
|
+
chip: "text-chip font-mono",
|
|
146
|
+
// Mono SIN transformar: fechas, rutas, versiones, nombres de archivo y la
|
|
147
|
+
// firma del footer. Es el escalón que faltaba, y por el que cada sitio de
|
|
148
|
+
// uso terminaba escribiendo `variant="eyebrow" className="normal-case"`.
|
|
149
|
+
meta: "text-meta font-mono",
|
|
150
|
+
// `uppercase` no cabe en un token de tamaño: text-transform no es un
|
|
151
|
+
// modificador de --text-*. Por eso lo pone la variante y no theme.css.
|
|
152
|
+
eyebrow: "text-eyebrow font-mono uppercase"
|
|
153
|
+
},
|
|
154
|
+
tone: {
|
|
155
|
+
primary: "text-text-primary",
|
|
156
|
+
secondary: "text-text-secondary",
|
|
157
|
+
muted: "text-text-muted",
|
|
158
|
+
accent: "text-accent",
|
|
159
|
+
warm: "text-warm",
|
|
160
|
+
success: "text-success",
|
|
161
|
+
warning: "text-warning",
|
|
162
|
+
error: "text-error"
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
defaultVariants: { variant: "body", tone: "primary" }
|
|
166
|
+
});
|
|
167
|
+
function Text({
|
|
168
|
+
className,
|
|
169
|
+
variant,
|
|
170
|
+
tone,
|
|
171
|
+
as,
|
|
172
|
+
asChild = false,
|
|
173
|
+
measure,
|
|
174
|
+
children,
|
|
175
|
+
...props
|
|
176
|
+
}) {
|
|
177
|
+
const escala = variant ?? "body";
|
|
178
|
+
const limitar = measure ?? escala === "body";
|
|
179
|
+
const clases = cn(texto({ variant, tone }), limitar && "max-w-measure", className);
|
|
180
|
+
if (asChild) {
|
|
181
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactSlot.Slot, { className: clases, ...props, children });
|
|
182
|
+
}
|
|
183
|
+
const Etiqueta = as ?? ETIQUETA[escala];
|
|
184
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Etiqueta, { className: clases, ...props, children });
|
|
185
|
+
}
|
|
186
|
+
function colorDeSerie(indice) {
|
|
187
|
+
return `var(--color-serie-${Math.abs(indice) % 4 + 1})`;
|
|
188
|
+
}
|
|
189
|
+
var COLORES_DE_SERIE = [0, 1, 2, 3].map(colorDeSerie);
|
|
190
|
+
function ChartContainer({
|
|
191
|
+
label,
|
|
192
|
+
summary,
|
|
193
|
+
height = 320,
|
|
194
|
+
className,
|
|
195
|
+
children,
|
|
196
|
+
...props
|
|
197
|
+
}) {
|
|
198
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
199
|
+
"figure",
|
|
200
|
+
{
|
|
201
|
+
"aria-label": label,
|
|
202
|
+
className: cn(
|
|
203
|
+
"w-full",
|
|
204
|
+
// La rejilla y los ejes, con los tokens del sistema en vez de los grises
|
|
205
|
+
// por defecto de Recharts. Van como variantes de descendiente porque los
|
|
206
|
+
// nodos los pinta la librería y no hay dónde ponerles una clase.
|
|
207
|
+
"[&_.recharts-cartesian-grid_line]:stroke-hairline",
|
|
208
|
+
"[&_.recharts-cartesian-axis-line]:stroke-hairline",
|
|
209
|
+
"[&_.recharts-cartesian-axis-tick_text]:fill-text-muted",
|
|
210
|
+
"[&_.recharts-cartesian-axis-tick_text]:font-mono",
|
|
211
|
+
"[&_.recharts-cartesian-axis-tick_text]:text-chip",
|
|
212
|
+
"[&_.recharts-rectangle.recharts-tooltip-cursor]:fill-surface-raised",
|
|
213
|
+
"[&_.recharts-curve.recharts-tooltip-cursor]:stroke-hairline-hover",
|
|
214
|
+
"[&_.recharts-sector]:outline-none",
|
|
215
|
+
"[&_.recharts-surface]:overflow-visible",
|
|
216
|
+
className
|
|
217
|
+
),
|
|
218
|
+
...props,
|
|
219
|
+
children: [
|
|
220
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { height }, children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children }) }),
|
|
221
|
+
summary ? /* @__PURE__ */ jsxRuntime.jsx("figcaption", { className: "sr-only", children: summary }) : null
|
|
222
|
+
]
|
|
223
|
+
}
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
function ChartTooltip(props) {
|
|
227
|
+
return /* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { isAnimationActive: false, ...props });
|
|
228
|
+
}
|
|
229
|
+
function ChartLegend(props) {
|
|
230
|
+
return /* @__PURE__ */ jsxRuntime.jsx(recharts.Legend, { ...props });
|
|
231
|
+
}
|
|
232
|
+
function ChartTooltipContent({
|
|
233
|
+
active,
|
|
234
|
+
payload,
|
|
235
|
+
label,
|
|
236
|
+
formatter,
|
|
237
|
+
hideLabel = false,
|
|
238
|
+
className
|
|
239
|
+
}) {
|
|
240
|
+
if (!active || !payload || payload.length === 0) return null;
|
|
241
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
242
|
+
"div",
|
|
243
|
+
{
|
|
244
|
+
className: cn(
|
|
245
|
+
"rounded-card border-border bg-surface shadow-standard p-step-sm gap-step-xs flex flex-col border",
|
|
246
|
+
className
|
|
247
|
+
),
|
|
248
|
+
children: [
|
|
249
|
+
hideLabel || label === void 0 || label === null ? null : /* @__PURE__ */ jsxRuntime.jsx(Text, { as: "p", variant: "meta", tone: "muted", children: label }),
|
|
250
|
+
/* @__PURE__ */ jsxRuntime.jsx("ul", { className: "gap-step-xs flex flex-col", children: payload.map((item, i) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "gap-step-xs flex items-center", children: [
|
|
251
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
252
|
+
"span",
|
|
253
|
+
{
|
|
254
|
+
"aria-hidden": "true",
|
|
255
|
+
className: "rounded-chip size-2 shrink-0",
|
|
256
|
+
style: { backgroundColor: item.color ?? colorDeSerie(i) }
|
|
257
|
+
}
|
|
258
|
+
),
|
|
259
|
+
/* @__PURE__ */ jsxRuntime.jsx(Text, { as: "span", variant: "label", tone: "secondary", className: "font-normal", children: item.name }),
|
|
260
|
+
/* @__PURE__ */ jsxRuntime.jsx(Text, { as: "span", variant: "label", className: "ml-auto font-mono tabular-nums", children: formatter ? formatter(item.value, item) : String(item.value ?? "") })
|
|
261
|
+
] }, `${String(item.dataKey ?? item.name ?? i)}`)) })
|
|
262
|
+
]
|
|
263
|
+
}
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
function ChartLegendContent({ payload, className }) {
|
|
267
|
+
if (!payload || payload.length === 0) return null;
|
|
268
|
+
return /* @__PURE__ */ jsxRuntime.jsx("ul", { className: cn("gap-step-md pt-step-sm flex flex-wrap items-center justify-center", className), children: payload.map((item, i) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "gap-step-xs flex items-center", children: [
|
|
269
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
270
|
+
"span",
|
|
271
|
+
{
|
|
272
|
+
"aria-hidden": "true",
|
|
273
|
+
className: "rounded-chip size-2 shrink-0",
|
|
274
|
+
style: { backgroundColor: item.color ?? colorDeSerie(i) }
|
|
275
|
+
}
|
|
276
|
+
),
|
|
277
|
+
/* @__PURE__ */ jsxRuntime.jsx(Text, { as: "span", variant: "label", tone: "secondary", className: "font-normal", children: item.value })
|
|
278
|
+
] }, `${String(item.dataKey ?? item.value ?? i)}`)) });
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
exports.COLORES_DE_SERIE = COLORES_DE_SERIE;
|
|
282
|
+
exports.ChartContainer = ChartContainer;
|
|
283
|
+
exports.ChartLegend = ChartLegend;
|
|
284
|
+
exports.ChartLegendContent = ChartLegendContent;
|
|
285
|
+
exports.ChartTooltip = ChartTooltip;
|
|
286
|
+
exports.ChartTooltipContent = ChartTooltipContent;
|
|
287
|
+
exports.colorDeSerie = colorDeSerie;
|