@eduardoalvarez/arrecife 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/CHANGELOG.md +55 -0
- package/LICENSE +21 -0
- package/README.md +520 -0
- package/assets/brand/face-annoyed.png +0 -0
- package/assets/brand/face-confused.png +0 -0
- package/assets/brand/face-hearts.png +0 -0
- package/assets/brand/face-laughing.png +0 -0
- package/assets/brand/face-shades.png +0 -0
- package/assets/brand/face-waiting.png +0 -0
- package/assets/brand/face-wink.png +0 -0
- package/assets/brand/fin-foam.png +0 -0
- package/assets/brand/fin.png +0 -0
- package/assets/brand/pose-desk.png +0 -0
- package/assets/brand/pose-laptop-coffee.png +0 -0
- package/assets/brand/pose-peek.png +0 -0
- package/assets/brand/pose-surf.png +0 -0
- package/dist/brand/index.cjs +228 -0
- package/dist/brand/index.d.cts +63 -0
- package/dist/brand/index.d.ts +63 -0
- package/dist/brand/index.js +3 -0
- package/dist/catalogo-Du5ID-Hi.d.cts +77 -0
- package/dist/catalogo-Du5ID-Hi.d.ts +77 -0
- package/dist/chunk-22OXRTAL.js +22 -0
- package/dist/chunk-DHF63QNM.js +231 -0
- package/dist/chunk-E3OMP2DL.js +36 -0
- package/dist/chunk-ZL5X6XO7.js +102 -0
- package/dist/index.cjs +3191 -0
- package/dist/index.d.cts +1024 -0
- package/dist/index.d.ts +1024 -0
- package/dist/index.js +2624 -0
- package/dist/og/index.cjs +322 -0
- package/dist/og/index.d.cts +164 -0
- package/dist/og/index.d.ts +164 -0
- package/dist/og/index.js +242 -0
- package/dist/shiki/index.cjs +127 -0
- package/dist/shiki/index.d.cts +16 -0
- package/dist/shiki/index.d.ts +16 -0
- package/dist/shiki/index.js +95 -0
- package/dist/tokens/index.cjs +263 -0
- package/dist/tokens/index.d.cts +623 -0
- package/dist/tokens/index.d.ts +623 -0
- package/dist/tokens/index.js +2 -0
- package/dist/tokens/theme.css +266 -0
- package/package.json +128 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,1024 @@
|
|
|
1
|
+
export { BrandToken, ColorMode, ColorToken, ControlToken, FontToken, GradientToken, RadiusToken, SintaxisToken, SizeToken, SpacingToken, Tokens, TypeScaleToken, brand, colors, control, dark, fonts, gradient, light, limits, motion, naming, radius, shadow, sintaxis, size, spacing, tagline, tokens, typeScale } from './tokens/index.js';
|
|
2
|
+
import * as react from 'react';
|
|
3
|
+
import { ComponentPropsWithoutRef, ReactNode, ComponentProps, SVGProps } from 'react';
|
|
4
|
+
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
5
|
+
import { VariantProps } from 'class-variance-authority';
|
|
6
|
+
import * as AvatarPrimitive from '@radix-ui/react-avatar';
|
|
7
|
+
import { DayPicker } from 'react-day-picker';
|
|
8
|
+
import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
|
|
9
|
+
import * as DialogPrimitive from '@radix-ui/react-dialog';
|
|
10
|
+
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
|
|
11
|
+
import * as LabelPrimitive from '@radix-ui/react-label';
|
|
12
|
+
import * as PopoverPrimitive from '@radix-ui/react-popover';
|
|
13
|
+
import * as ProgressPrimitive from '@radix-ui/react-progress';
|
|
14
|
+
import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
|
|
15
|
+
import * as SelectPrimitive from '@radix-ui/react-select';
|
|
16
|
+
import * as SeparatorPrimitive from '@radix-ui/react-separator';
|
|
17
|
+
import * as SwitchPrimitive from '@radix-ui/react-switch';
|
|
18
|
+
import * as TabsPrimitive from '@radix-ui/react-tabs';
|
|
19
|
+
import * as ToastPrimitive from '@radix-ui/react-toast';
|
|
20
|
+
import * as TooltipPrimitive from '@radix-ui/react-tooltip';
|
|
21
|
+
import { C as Cara, P as Pose } from './catalogo-Du5ID-Hi.js';
|
|
22
|
+
export { A as Aleta, F as Fondo, R as RUTA_ASSETS, a as aletas, c as caras, l as listaCaras, b as listaPoses, p as poses, u as usoDeCara } from './catalogo-Du5ID-Hi.js';
|
|
23
|
+
export { CaraDeMascota, CaraDeMascotaProps, Isotipo, IsotipoProps, Logo, LogoProps, Mascota, MascotaProps } from './brand/index.js';
|
|
24
|
+
import { ClassValue } from 'clsx';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* El aviso lleva el color en el fondo, no solo en el borde.
|
|
28
|
+
*
|
|
29
|
+
* La receta del sistema es fondo al 8 % del color semántico y borde al 22 %.
|
|
30
|
+
* Este archivo daba `bg-surface` a las cuatro variantes, así que el tono vivía
|
|
31
|
+
* entero en un borde de 1px: cuatro avisos que se distinguían entre sí por una
|
|
32
|
+
* línea.
|
|
33
|
+
*
|
|
34
|
+
* Los cuatro tonos empiezan en ACENTO, que es el informativo del sistema (✦).
|
|
35
|
+
* No hay `neutral`: un aviso sin color es un párrafo.
|
|
36
|
+
*
|
|
37
|
+
* MEDIDO en los dos modos, porque el 8 % del documento está calculado sobre
|
|
38
|
+
* abismo y había que comprobar que sobrevive sobre papel. Contraste del tinte
|
|
39
|
+
* contra el fondo de página:
|
|
40
|
+
*
|
|
41
|
+
* 8 % oscuro 8 % claro
|
|
42
|
+
* accent 1.149 1.106
|
|
43
|
+
* success 1.116 1.121
|
|
44
|
+
* warning 1.126 1.109
|
|
45
|
+
* error 1.067 1.120
|
|
46
|
+
*
|
|
47
|
+
* El modo claro NO necesita una segunda tabla: aguanta igual o mejor que el
|
|
48
|
+
* oscuro. El único punto flojo del sistema es `error` sobre abismo, 1.067, que
|
|
49
|
+
* es el tinte más tenue de los ocho y se apoya entero en el borde al 22 %.
|
|
50
|
+
*
|
|
51
|
+
* Hay una SEGUNDA receta, a propósito: el aviso bajo el formulario de
|
|
52
|
+
* newsletter va al 10 % con el borde sólido para leerse bajo el campo. Es
|
|
53
|
+
* `enfasis="fuerte"`, y no se unifica con la sutil porque la diferencia está
|
|
54
|
+
* documentada.
|
|
55
|
+
*
|
|
56
|
+
* TERCERA corrección de contraste, en la línea de las tres que ya tenía
|
|
57
|
+
* `tokens.ts`. El título iba en el color semántico, y en modo claro eso no puede
|
|
58
|
+
* pasar AA: los semánticos claros están calibrados para pasar JUSTO sobre papel
|
|
59
|
+
* (4.54–4.88), así que sobre su propio tinte al 8 % caen a 4.11–4.40. No hay
|
|
60
|
+
* alfa que lo arregle — el problema es poner el color encima de sí mismo.
|
|
61
|
+
*
|
|
62
|
+
* El tinte es una SUPERFICIE, así que el texto que lleva encima es un token de
|
|
63
|
+
* texto: `textPrimary` da 14.6–14.9 sobre los cuatro tintes. El color semántico
|
|
64
|
+
* se queda donde no es texto — el borde y el glifo —, que es lo único que el
|
|
65
|
+
* documento pedía de él. El glifo es decorativo y va `aria-hidden`, así que le
|
|
66
|
+
* aplica el umbral de 3:1 y no el de 4.5: su peor caso claro es 4.11.
|
|
67
|
+
*
|
|
68
|
+
* El radio: el documento dice 12, que no es ninguno de los cinco radios del
|
|
69
|
+
* sistema. Usa el de tarjeta antes que estrenar un sexto — ver
|
|
70
|
+
* `docs/decisiones.md`.
|
|
71
|
+
*/
|
|
72
|
+
declare const alert: (props?: ({
|
|
73
|
+
variant?: "accent" | "success" | "warning" | "error" | null | undefined;
|
|
74
|
+
enfasis?: "sutil" | "fuerte" | null | undefined;
|
|
75
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
76
|
+
type AlertProps = Omit<ComponentPropsWithoutRef<'div'>, 'title'> & VariantProps<typeof alert> & {
|
|
77
|
+
title?: ReactNode;
|
|
78
|
+
/**
|
|
79
|
+
* Sustituye el glifo mono de la variante. Nunca un emoji: si necesitas otra
|
|
80
|
+
* cosa, es un SVG de `glyphs`.
|
|
81
|
+
*/
|
|
82
|
+
icon?: ReactNode;
|
|
83
|
+
};
|
|
84
|
+
declare function Alert({ className, variant, enfasis, title, icon, children, ...props }: AlertProps): react.JSX.Element;
|
|
85
|
+
|
|
86
|
+
declare const avatar: (props?: ({
|
|
87
|
+
size?: "sm" | "md" | "lg" | "xl" | null | undefined;
|
|
88
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
89
|
+
type AvatarProps = ComponentPropsWithoutRef<typeof AvatarPrimitive.Root> & VariantProps<typeof avatar>;
|
|
90
|
+
/**
|
|
91
|
+
* Uno solo para todo: la foto del autor y la de cualquier persona del sistema.
|
|
92
|
+
* No hay un `brand/Avatar` aparte — una foto de perfil con la piel de la marca
|
|
93
|
+
* es exactamente esto con un `src` distinto.
|
|
94
|
+
*/
|
|
95
|
+
declare function Avatar({ className, size, ...props }: AvatarProps): react.JSX.Element;
|
|
96
|
+
declare function AvatarImage({ className, ...props }: ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>): react.JSX.Element;
|
|
97
|
+
/** Iniciales mientras la imagen carga, o cuando no hay imagen. */
|
|
98
|
+
declare function AvatarFallback({ className, ...props }: ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>): react.JSX.Element;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* TRES familias de etiqueta, no una.
|
|
102
|
+
*
|
|
103
|
+
* El sistema define tres formas distintas y este archivo las servía todas como
|
|
104
|
+
* píldora mono en versalitas. Cada una tiene su forma porque cada una dice otra
|
|
105
|
+
* cosa:
|
|
106
|
+
*
|
|
107
|
+
* categoría · píldora r999, mono 11.5, arena → un slug: `engineering-culture`
|
|
108
|
+
* estado · cuadrada r6, sans 12.5/500, tinte → un semáforo: publicado, borrador
|
|
109
|
+
* métrica · píldora, mono 11.5 muted → un dato: `8 min de lectura`
|
|
110
|
+
*
|
|
111
|
+
* NINGUNA va en versalitas. El `uppercase tracking-[0.12em]` que tenían las tres
|
|
112
|
+
* venía de `text-eyebrow`, que es la escala del eyebrow y no la de las
|
|
113
|
+
* etiquetas: convertía `engineering-culture` en `ENGINEERING-CULTURE` y
|
|
114
|
+
* `pose-laptop-coffee.png` en un nombre de archivo que no existe.
|
|
115
|
+
*/
|
|
116
|
+
/**
|
|
117
|
+
* Semáforo. Cuadrada r6, sans 12.5/500 y fondo al 8 % del semántico — la receta
|
|
118
|
+
* del aviso en tamaño de palabra: un estado es un aviso de una sola palabra.
|
|
119
|
+
*
|
|
120
|
+
* SIN borde. Lo llevó un tiempo, puesto para reforzar el tono, y pesaba: una
|
|
121
|
+
* caja con borde al lado de un título se lee como un control y no como un dato.
|
|
122
|
+
* El tinte solo es lo que pide el documento y es lo que se ve más limpio.
|
|
123
|
+
*
|
|
124
|
+
* El texto va en `textPrimary`, no en el color del tono. En modo claro los
|
|
125
|
+
* semánticos están calibrados para pasar JUSTO sobre papel, así que sobre su
|
|
126
|
+
* propio tinte caen a 4.10–4.40 y no pasan AA. El tinte es una superficie;
|
|
127
|
+
* encima va un token de texto. Medido en `alert.tsx`.
|
|
128
|
+
*
|
|
129
|
+
* El tono nunca es el único portador del significado: la etiqueta dice
|
|
130
|
+
* «Publicado» o «Borrador» con todas sus letras.
|
|
131
|
+
*/
|
|
132
|
+
declare const badge: (props?: ({
|
|
133
|
+
variant?: "accent" | "success" | "warning" | "error" | "neutral" | "warm" | null | undefined;
|
|
134
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
135
|
+
type BadgeProps = ComponentPropsWithoutRef<'span'> & VariantProps<typeof badge>;
|
|
136
|
+
declare function Badge({ className, variant, ...props }: BadgeProps): react.JSX.Element;
|
|
137
|
+
/**
|
|
138
|
+
* Un slug, en arena. Sin transformar: los slugs ya vienen en minúscula y
|
|
139
|
+
* forzarla sería el mismo error que forzaba el `uppercase`.
|
|
140
|
+
*
|
|
141
|
+
* El borde del documento es `#4A3A25`, que es arena al 28 % sobre abismo: sale
|
|
142
|
+
* de la paleta, así que no entra como token nuevo. En modo claro la misma regla
|
|
143
|
+
* da arena oscura al 28 % sobre papel, que es lo que se quiere.
|
|
144
|
+
*
|
|
145
|
+
* La variante rellena NO es decorativa: es el único indicador de filtro activo
|
|
146
|
+
* del listado de artículos. Por eso `active` es una prop y no un `className`.
|
|
147
|
+
*/
|
|
148
|
+
declare const categoria: (props?: ({
|
|
149
|
+
active?: boolean | null | undefined;
|
|
150
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
151
|
+
type CategoryBadgeProps = ComponentPropsWithoutRef<'span'> & {
|
|
152
|
+
/** Filtro seleccionado: arena sólido con tinta encima. */
|
|
153
|
+
active?: boolean | undefined;
|
|
154
|
+
};
|
|
155
|
+
declare function CategoryBadge({ className, active, ...props }: CategoryBadgeProps): react.JSX.Element;
|
|
156
|
+
type MetricBadgeProps = ComponentPropsWithoutRef<'span'> & {
|
|
157
|
+
/** Añade el aro de hairline. Por defecto la métrica va sin caja. */
|
|
158
|
+
boxed?: boolean | undefined;
|
|
159
|
+
};
|
|
160
|
+
declare function MetricBadge({ className, boxed, ...props }: MetricBadgeProps): react.JSX.Element;
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Las CUATRO variantes del sistema, y solo esas cuatro.
|
|
164
|
+
*
|
|
165
|
+
* Regla de marca 2, como código y no como documentación: en modo claro el botón
|
|
166
|
+
* primario no puede ser bioluz ni arena, así que pasa a casco sólido. No hay un
|
|
167
|
+
* hex literal en ningún lado — `brand.hull` es un token, y el hover reusa
|
|
168
|
+
* `textSecondary` en vez de inventar un `hullHover`.
|
|
169
|
+
*
|
|
170
|
+
* Regla de marca 3: `conversion` va UNA sola vez por pantalla. Está documentado
|
|
171
|
+
* en la story y no se fuerza en runtime: dos botones de conversión en una misma
|
|
172
|
+
* página son un problema de diseño, no un error que deba tirar el render.
|
|
173
|
+
*
|
|
174
|
+
* `secondary` NUNCA se rellena el fondo. Es borde y texto: en reposo, hairline
|
|
175
|
+
* de hover y espuma; en hover, los dos pasan a bioluz. Un secundario relleno es
|
|
176
|
+
* un primario mal teñido, y era lo que hacía este archivo.
|
|
177
|
+
*
|
|
178
|
+
* `tertiary` es la estética CLI del sistema: mono, formato `./acción →`, sin
|
|
179
|
+
* caja. Aparece en cada tarjeta, así que no es un `ghost` genérico con otro
|
|
180
|
+
* nombre — el formato del texto es parte de la variante.
|
|
181
|
+
*
|
|
182
|
+
* No hay variante de peligro. El error del sistema vive en los avisos y en la
|
|
183
|
+
* validación de campo, no en un botón rojo. Si alguna vez hace falta uno de
|
|
184
|
+
* verdad, entra primero en el documento y luego aquí.
|
|
185
|
+
*/
|
|
186
|
+
declare const button: (props?: ({
|
|
187
|
+
variant?: "primary" | "conversion" | "secondary" | "tertiary" | null | undefined;
|
|
188
|
+
size?: "icon" | "sm" | "md" | "lg" | null | undefined;
|
|
189
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
190
|
+
type ButtonProps = ComponentPropsWithoutRef<'button'> & VariantProps<typeof button> & {
|
|
191
|
+
/** Renderiza el hijo en vez de un `<button>`, para envolver un enlace. */
|
|
192
|
+
asChild?: boolean;
|
|
193
|
+
/** Deshabilita y anuncia `aria-busy`. Incompatible con `asChild`. */
|
|
194
|
+
loading?: boolean;
|
|
195
|
+
/** Glifo SVG antes del texto. Se oculta mientras carga. */
|
|
196
|
+
icon?: ReactNode;
|
|
197
|
+
};
|
|
198
|
+
declare function Button({ className, variant, size, asChild, loading, icon, children, disabled, ...props }: ButtonProps): react.JSX.Element;
|
|
199
|
+
|
|
200
|
+
type CalendarProps = ComponentProps<typeof DayPicker> & {
|
|
201
|
+
/**
|
|
202
|
+
* Estira el calendario hasta ocupar todo el ancho de su contenedor, con las
|
|
203
|
+
* celdas repartiéndoselo a partes iguales.
|
|
204
|
+
*
|
|
205
|
+
* Apagado, el calendario mide lo que miden sus celdas —36 px cada una— y es lo
|
|
206
|
+
* que quieres dentro de un `Popover`, donde estirarlo dejaría un globo enorme.
|
|
207
|
+
* Encendido, es la vista de mes de un planificador, que ocupa la página.
|
|
208
|
+
*
|
|
209
|
+
* Con varios meses, cada uno se lleva una fracción igual del ancho.
|
|
210
|
+
*/
|
|
211
|
+
fullWidth?: boolean | undefined;
|
|
212
|
+
};
|
|
213
|
+
/**
|
|
214
|
+
* Calendario mensual navegable, sobre `react-day-picker`.
|
|
215
|
+
*
|
|
216
|
+
* Es la única dependencia pesada de la librería y entró a sabiendas: el
|
|
217
|
+
* calendario del planificador de contenido no se puede resolver con el control
|
|
218
|
+
* nativo. Para elegir una fecha dentro de un formulario existe `DateField`, que
|
|
219
|
+
* no arrastra nada.
|
|
220
|
+
*
|
|
221
|
+
* `animate` se queda apagado —es su valor por defecto— así que el cambio de mes
|
|
222
|
+
* no se desliza. Los días se marcan con color y borde, como todo lo demás.
|
|
223
|
+
*
|
|
224
|
+
* El idioma va en español por defecto porque los cinco proyectos lo están; se
|
|
225
|
+
* cambia pasando otro `locale` de date-fns.
|
|
226
|
+
*
|
|
227
|
+
* No trae el `style.css` de la librería: todas las clases salen de aquí, así que
|
|
228
|
+
* el consumidor no tiene que importar CSS de terceros ni pelearse con su
|
|
229
|
+
* especificidad.
|
|
230
|
+
*/
|
|
231
|
+
declare function Calendar({ className, classNames, showOutsideDays, fullWidth, ...props }: CalendarProps): react.JSX.Element;
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* El contenedor de superficie del sistema, y la única definición de lo que es
|
|
235
|
+
* una tarjeta: `surface`, borde `hairline`, radio de tarjeta.
|
|
236
|
+
*
|
|
237
|
+
* Las tarjetas con dominio — `ArticleCard`, `TalkCard`, `CourseCard`,
|
|
238
|
+
* `LinkRow` — reutilizan estas mismas clases, así que si el radio o el borde
|
|
239
|
+
* cambian, cambian en todas a la vez.
|
|
240
|
+
*
|
|
241
|
+
* El documento daba a la tarjeta un fondo propio, `#0B1620`, un cuarto nivel de
|
|
242
|
+
* superficie entre abismo y fosa. No entra: no tiene par en modo claro, y una
|
|
243
|
+
* superficie sin par es un token que miente en la mitad de los proyectos. La
|
|
244
|
+
* tarjeta es `surface`, y el documento se corrige — ver `docs/decisiones.md`.
|
|
245
|
+
*
|
|
246
|
+
* El padding sí estaba mal: el documento pide 26 (`lg`) y aquí había 16 (`md`).
|
|
247
|
+
*/
|
|
248
|
+
declare const SUPERFICIE_TARJETA = "rounded-card border-hairline bg-surface border";
|
|
249
|
+
/** El hover de la regla 6: solo el borde. Se aplica donde la tarjeta es pulsable. */
|
|
250
|
+
declare const HOVER_TARJETA = "transition-standard hover:border-hairline-hover";
|
|
251
|
+
declare function Card({ className, ...props }: ComponentPropsWithoutRef<'div'>): react.JSX.Element;
|
|
252
|
+
declare function CardHeader({ className, ...props }: ComponentPropsWithoutRef<'div'>): react.JSX.Element;
|
|
253
|
+
declare function CardTitle({ className, ...props }: ComponentPropsWithoutRef<'h3'>): react.JSX.Element;
|
|
254
|
+
declare function CardDescription({ className, ...props }: ComponentPropsWithoutRef<'p'>): react.JSX.Element;
|
|
255
|
+
declare function CardContent({ className, ...props }: ComponentPropsWithoutRef<'div'>): react.JSX.Element;
|
|
256
|
+
declare function CardFooter({ className, ...props }: ComponentPropsWithoutRef<'div'>): react.JSX.Element;
|
|
257
|
+
|
|
258
|
+
type CheckboxProps = ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>;
|
|
259
|
+
declare function Checkbox({ className, ...props }: CheckboxProps): react.JSX.Element;
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Código en línea, dentro de prosa.
|
|
263
|
+
*
|
|
264
|
+
* Existe porque no existía: cada consumidor escribía `<code className="font-mono">`
|
|
265
|
+
* a mano, y la story de marca lo hacía cuatro veces en un solo párrafo. Un
|
|
266
|
+
* `<code>` suelto hereda el tamaño del párrafo, así que dentro de `body` (18px)
|
|
267
|
+
* se veía un mono de 18px que el documento no tiene en ninguna parte.
|
|
268
|
+
*
|
|
269
|
+
* No es `CodeBlock`. El bloque es una isla de tema oscuro sobre casco con barra
|
|
270
|
+
* y botón de copiar; esto es una palabra dentro de una frase, y por eso se queda
|
|
271
|
+
* en la superficie de la página en vez de invertir el tema.
|
|
272
|
+
*/
|
|
273
|
+
type CodeProps = ComponentPropsWithoutRef<'code'>;
|
|
274
|
+
declare function Code({ className, ...props }: CodeProps): react.JSX.Element;
|
|
275
|
+
|
|
276
|
+
type DateFieldProps = Omit<ComponentPropsWithoutRef<'input'>, 'type'> & {
|
|
277
|
+
invalid?: boolean | undefined;
|
|
278
|
+
/** Añade la hora al campo. Es el `datetime-local` nativo. */
|
|
279
|
+
withTime?: boolean | undefined;
|
|
280
|
+
};
|
|
281
|
+
/**
|
|
282
|
+
* Un campo de fecha sobre el control nativo, no sobre un calendario propio.
|
|
283
|
+
*
|
|
284
|
+
* Es una decisión deliberada: `react-day-picker` habría sido la primera
|
|
285
|
+
* dependencia pesada de la librería, con su propio CSS y su propia animación de
|
|
286
|
+
* cambio de mes — que el sistema no permite. El control nativo trae gratis el
|
|
287
|
+
* teclado del sistema operativo, el formato según el idioma del usuario y el
|
|
288
|
+
* soporte de lector de pantalla, que es más de lo que un calendario a medida da
|
|
289
|
+
* sin trabajo.
|
|
290
|
+
*
|
|
291
|
+
* Cubre elegir una fecha dentro de un formulario. Un calendario mensual
|
|
292
|
+
* navegable es otra cosa y vive en el proyecto que lo necesita.
|
|
293
|
+
*
|
|
294
|
+
* El icono nativo del selector se tiñe con `color-scheme`, que es lo único que
|
|
295
|
+
* el navegador deja controlar: se ata al modo activo para que no aparezca un
|
|
296
|
+
* cuadradito blanco sobre fondo abismo.
|
|
297
|
+
*/
|
|
298
|
+
declare function DateField({ className, invalid, withTime, ...props }: DateFieldProps): react.JSX.Element;
|
|
299
|
+
|
|
300
|
+
declare const Dialog: react.FC<DialogPrimitive.DialogProps>;
|
|
301
|
+
declare const DialogTrigger: react.ForwardRefExoticComponent<DialogPrimitive.DialogTriggerProps & react.RefAttributes<HTMLButtonElement>>;
|
|
302
|
+
declare const DialogClose: react.ForwardRefExoticComponent<DialogPrimitive.DialogCloseProps & react.RefAttributes<HTMLButtonElement>>;
|
|
303
|
+
declare function DialogOverlay({ className, ...props }: ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>): react.JSX.Element;
|
|
304
|
+
/** Sin entrada animada: no hay escala ni desplazamiento en el sistema. */
|
|
305
|
+
declare function DialogContent({ className, children, ...props }: ComponentPropsWithoutRef<typeof DialogPrimitive.Content>): react.JSX.Element;
|
|
306
|
+
declare function DialogHeader({ className, ...props }: ComponentPropsWithoutRef<'div'>): react.JSX.Element;
|
|
307
|
+
declare function DialogFooter({ className, ...props }: ComponentPropsWithoutRef<'div'>): react.JSX.Element;
|
|
308
|
+
declare function DialogTitle({ className, ...props }: ComponentPropsWithoutRef<typeof DialogPrimitive.Title>): react.JSX.Element;
|
|
309
|
+
declare function DialogDescription({ className, ...props }: ComponentPropsWithoutRef<typeof DialogPrimitive.Description>): react.JSX.Element;
|
|
310
|
+
|
|
311
|
+
declare const DropdownMenu: react.FC<DropdownMenuPrimitive.DropdownMenuProps>;
|
|
312
|
+
declare const DropdownMenuTrigger: react.ForwardRefExoticComponent<DropdownMenuPrimitive.DropdownMenuTriggerProps & react.RefAttributes<HTMLButtonElement>>;
|
|
313
|
+
declare const DropdownMenuGroup: react.ForwardRefExoticComponent<DropdownMenuPrimitive.DropdownMenuGroupProps & react.RefAttributes<HTMLDivElement>>;
|
|
314
|
+
declare const DropdownMenuRadioGroup: react.ForwardRefExoticComponent<DropdownMenuPrimitive.DropdownMenuRadioGroupProps & react.RefAttributes<HTMLDivElement>>;
|
|
315
|
+
declare const DropdownMenuSub: react.FC<DropdownMenuPrimitive.DropdownMenuSubProps>;
|
|
316
|
+
/** Sin animación de entrada: el menú aparece, no se despliega. */
|
|
317
|
+
declare function DropdownMenuContent({ className, sideOffset, ...props }: ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>): react.JSX.Element;
|
|
318
|
+
declare function DropdownMenuItem({ className, ...props }: ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item>): react.JSX.Element;
|
|
319
|
+
declare function DropdownMenuCheckboxItem({ className, children, ...props }: ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>): react.JSX.Element;
|
|
320
|
+
declare function DropdownMenuRadioItem({ className, children, ...props }: ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>): react.JSX.Element;
|
|
321
|
+
declare function DropdownMenuLabel({ className, ...props }: ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label>): react.JSX.Element;
|
|
322
|
+
declare function DropdownMenuSeparator({ className, ...props }: ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>): react.JSX.Element;
|
|
323
|
+
declare function DropdownMenuSubTrigger({ className, children, ...props }: ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger>): react.JSX.Element;
|
|
324
|
+
declare function DropdownMenuSubContent({ className, ...props }: ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>): react.JSX.Element;
|
|
325
|
+
|
|
326
|
+
type InputProps = ComponentPropsWithoutRef<'input'> & {
|
|
327
|
+
/** Marca el control como inválido y tiñe el borde. */
|
|
328
|
+
invalid?: boolean;
|
|
329
|
+
};
|
|
330
|
+
declare function Input({ className, invalid, ...props }: InputProps): react.JSX.Element;
|
|
331
|
+
|
|
332
|
+
type LabelProps = ComponentPropsWithoutRef<typeof LabelPrimitive.Root>;
|
|
333
|
+
/**
|
|
334
|
+
* La escala `label`: 13px, que es el mínimo absoluto en pantalla del sistema.
|
|
335
|
+
*
|
|
336
|
+
* Se atenúa junto al control cuando este está deshabilitado, para que la
|
|
337
|
+
* pareja etiqueta-control se lea siempre como una sola unidad.
|
|
338
|
+
*/
|
|
339
|
+
declare function Label({ className, ...props }: LabelProps): react.JSX.Element;
|
|
340
|
+
|
|
341
|
+
declare function Pagination({ className, ...props }: ComponentPropsWithoutRef<'nav'>): react.JSX.Element;
|
|
342
|
+
declare function PaginationContent({ className, ...props }: ComponentPropsWithoutRef<'ul'>): react.JSX.Element;
|
|
343
|
+
declare function PaginationItem(props: ComponentPropsWithoutRef<'li'>): react.JSX.Element;
|
|
344
|
+
type PaginationLinkProps = ComponentPropsWithoutRef<'a'> & {
|
|
345
|
+
isActive?: boolean;
|
|
346
|
+
};
|
|
347
|
+
declare function PaginationLink({ className, isActive, ...props }: PaginationLinkProps): react.JSX.Element;
|
|
348
|
+
declare function PaginationPrevious({ className, ...props }: PaginationLinkProps): react.JSX.Element;
|
|
349
|
+
declare function PaginationNext({ className, ...props }: PaginationLinkProps): react.JSX.Element;
|
|
350
|
+
declare function PaginationEllipsis({ className, ...props }: ComponentPropsWithoutRef<'span'>): react.JSX.Element;
|
|
351
|
+
|
|
352
|
+
declare const Popover: react.FC<PopoverPrimitive.PopoverProps>;
|
|
353
|
+
declare const PopoverTrigger: react.ForwardRefExoticComponent<PopoverPrimitive.PopoverTriggerProps & react.RefAttributes<HTMLButtonElement>>;
|
|
354
|
+
declare const PopoverAnchor: react.ForwardRefExoticComponent<PopoverPrimitive.PopoverAnchorProps & react.RefAttributes<HTMLDivElement>>;
|
|
355
|
+
/**
|
|
356
|
+
* Radix le pone `role="dialog"` al contenido, y un diálogo sin nombre accesible
|
|
357
|
+
* no le dice nada a quien navega con lector de pantalla. Por eso el tipo exige
|
|
358
|
+
* uno de los dos: `aria-label` con el texto, o `aria-labelledby` apuntando al
|
|
359
|
+
* título que ya se ve en pantalla. No se puede olvidar porque no compila.
|
|
360
|
+
*/
|
|
361
|
+
type Etiquetado = {
|
|
362
|
+
'aria-label': string;
|
|
363
|
+
'aria-labelledby'?: never;
|
|
364
|
+
} | {
|
|
365
|
+
'aria-labelledby': string;
|
|
366
|
+
'aria-label'?: never;
|
|
367
|
+
};
|
|
368
|
+
type PopoverContentProps = ComponentPropsWithoutRef<typeof PopoverPrimitive.Content> & Etiquetado;
|
|
369
|
+
/** Sin animación de entrada: aparece donde va a quedarse, como el resto. */
|
|
370
|
+
declare function PopoverContent({ className, align, sideOffset, ...props }: PopoverContentProps): react.JSX.Element;
|
|
371
|
+
|
|
372
|
+
type ProgressProps = ComponentPropsWithoutRef<typeof ProgressPrimitive.Root> & {
|
|
373
|
+
/**
|
|
374
|
+
* Nombre accesible de la barra. Es obligatorio a propósito: una barra de
|
|
375
|
+
* progreso sin nombre no dice de qué es el progreso, y ninguna otra parte del
|
|
376
|
+
* componente puede deducirlo.
|
|
377
|
+
*/
|
|
378
|
+
label: string;
|
|
379
|
+
/** Arena en vez de bioluz, para progreso de curso. */
|
|
380
|
+
tone?: 'accent' | 'warm';
|
|
381
|
+
};
|
|
382
|
+
/**
|
|
383
|
+
* El ancho del indicador cambia, no se anima: el sistema no anima escala ni
|
|
384
|
+
* desplazamiento. `transition-standard` solo cubre color y borde, así que el
|
|
385
|
+
* salto de ancho es inmediato aunque la clase esté puesta.
|
|
386
|
+
*/
|
|
387
|
+
declare function Progress({ className, value, label, tone, ...props }: ProgressProps): react.JSX.Element;
|
|
388
|
+
|
|
389
|
+
type RadioGroupProps = ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>;
|
|
390
|
+
type RadioGroupItemProps = ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>;
|
|
391
|
+
declare function RadioGroup({ className, ...props }: RadioGroupProps): react.JSX.Element;
|
|
392
|
+
declare function RadioGroupItem({ className, ...props }: RadioGroupItemProps): react.JSX.Element;
|
|
393
|
+
|
|
394
|
+
declare const Select: react.FC<SelectPrimitive.SelectProps>;
|
|
395
|
+
declare const SelectGroup: react.ForwardRefExoticComponent<SelectPrimitive.SelectGroupProps & react.RefAttributes<HTMLDivElement>>;
|
|
396
|
+
declare const SelectValue: react.ForwardRefExoticComponent<SelectPrimitive.SelectValueProps & react.RefAttributes<HTMLSpanElement>>;
|
|
397
|
+
declare function SelectTrigger({ className, children, ...props }: ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>): react.JSX.Element;
|
|
398
|
+
/** Sin animación de entrada: el menú aparece, no se despliega. */
|
|
399
|
+
declare function SelectContent({ className, children, position, ...props }: ComponentPropsWithoutRef<typeof SelectPrimitive.Content>): react.JSX.Element;
|
|
400
|
+
declare function SelectLabel({ className, ...props }: ComponentPropsWithoutRef<typeof SelectPrimitive.Label>): react.JSX.Element;
|
|
401
|
+
declare function SelectItem({ className, children, ...props }: ComponentPropsWithoutRef<typeof SelectPrimitive.Item>): react.JSX.Element;
|
|
402
|
+
declare function SelectSeparator({ className, ...props }: ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>): react.JSX.Element;
|
|
403
|
+
|
|
404
|
+
type SeparatorProps = ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>;
|
|
405
|
+
/**
|
|
406
|
+
* `hairline`, no `border`: una división entre contenidos es sutil por
|
|
407
|
+
* definición. Para delimitar un control existe `border`, que es otro token.
|
|
408
|
+
*/
|
|
409
|
+
declare function Separator({ className, orientation, decorative, ...props }: SeparatorProps): react.JSX.Element;
|
|
410
|
+
|
|
411
|
+
declare const Sheet: react.FC<DialogPrimitive.DialogProps>;
|
|
412
|
+
declare const SheetTrigger: react.ForwardRefExoticComponent<DialogPrimitive.DialogTriggerProps & react.RefAttributes<HTMLButtonElement>>;
|
|
413
|
+
declare const SheetClose: react.ForwardRefExoticComponent<DialogPrimitive.DialogCloseProps & react.RefAttributes<HTMLButtonElement>>;
|
|
414
|
+
/**
|
|
415
|
+
* La segunda y última excepción a «nada de desplazamiento», aprobada a
|
|
416
|
+
* sabiendas: un panel que entra desde un borde se desliza por definición, y
|
|
417
|
+
* quieto sería un modal descentrado.
|
|
418
|
+
*
|
|
419
|
+
* Dura `--duration-standard` con `--ease-standard`, o sea lo mismo y con la
|
|
420
|
+
* misma curva que cualquier cambio de color del sistema, así que no introduce
|
|
421
|
+
* un tiempo nuevo. Va detrás de `motion-safe`: quien pidió menos movimiento lo
|
|
422
|
+
* ve aparecer sin deslizarse.
|
|
423
|
+
*/
|
|
424
|
+
declare const panel: (props?: ({
|
|
425
|
+
side?: "bottom" | "left" | "right" | "top" | null | undefined;
|
|
426
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
427
|
+
type SheetContentProps = ComponentPropsWithoutRef<typeof DialogPrimitive.Content> & VariantProps<typeof panel>;
|
|
428
|
+
declare function SheetContent({ className, side, children, ...props }: SheetContentProps): react.JSX.Element;
|
|
429
|
+
declare function SheetHeader({ className, ...props }: ComponentPropsWithoutRef<'div'>): react.JSX.Element;
|
|
430
|
+
declare function SheetBody({ className, ...props }: ComponentPropsWithoutRef<'div'>): react.JSX.Element;
|
|
431
|
+
declare function SheetFooter({ className, ...props }: ComponentPropsWithoutRef<'div'>): react.JSX.Element;
|
|
432
|
+
declare function SheetTitle({ className, ...props }: ComponentPropsWithoutRef<typeof DialogPrimitive.Title>): react.JSX.Element;
|
|
433
|
+
declare function SheetDescription({ className, ...props }: ComponentPropsWithoutRef<typeof DialogPrimitive.Description>): react.JSX.Element;
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Barrido de 1.4s lineal, del documento.
|
|
437
|
+
*
|
|
438
|
+
* Es la TERCERA y última excepción a «el sistema no anima», junto al spinner del
|
|
439
|
+
* botón y el panel lateral. Las tres son realimentación de PROGRESO y no de
|
|
440
|
+
* estado, que es el criterio: un bloque quieto y un bloque que nunca va a cargar
|
|
441
|
+
* se ven exactamente igual, y el skeleton existe para decir «esto viene en
|
|
442
|
+
* camino», no «esto está vacío».
|
|
443
|
+
*
|
|
444
|
+
* Va detrás de `motion-safe`, así que se apaga solo para quien pidió menos
|
|
445
|
+
* movimiento — y ahí queda el bloque en `surfaceRaised`, que sigue comunicando
|
|
446
|
+
* la forma de lo que va a llegar.
|
|
447
|
+
*
|
|
448
|
+
* `still` lo apaga a mano, para las tablas largas: veinte filas barriendo a la
|
|
449
|
+
* vez es un estroboscopio, no una carga.
|
|
450
|
+
*/
|
|
451
|
+
type SkeletonProps = ComponentPropsWithoutRef<'div'> & {
|
|
452
|
+
/** Apaga el barrido. Para listas largas, donde muchas a la vez marean. */
|
|
453
|
+
still?: boolean | undefined;
|
|
454
|
+
};
|
|
455
|
+
declare function Skeleton({ className, still, ...props }: SkeletonProps): react.JSX.Element;
|
|
456
|
+
|
|
457
|
+
type SwitchProps = ComponentPropsWithoutRef<typeof SwitchPrimitive.Root>;
|
|
458
|
+
/**
|
|
459
|
+
* La perilla cambia de posición, pero no se anima al hacerlo: la posición es el
|
|
460
|
+
* estado, no una transición. Lo único que transiciona es el color de la vía.
|
|
461
|
+
*/
|
|
462
|
+
declare function Switch({ className, ...props }: SwitchProps): react.JSX.Element;
|
|
463
|
+
|
|
464
|
+
/** El contenedor scrollea en horizontal: la página nunca lo hace. */
|
|
465
|
+
declare function Table({ className, ...props }: ComponentPropsWithoutRef<'table'>): react.JSX.Element;
|
|
466
|
+
declare function TableHeader({ className, ...props }: ComponentPropsWithoutRef<'thead'>): react.JSX.Element;
|
|
467
|
+
declare function TableBody({ className, ...props }: ComponentPropsWithoutRef<'tbody'>): react.JSX.Element;
|
|
468
|
+
declare function TableFooter({ className, ...props }: ComponentPropsWithoutRef<'tfoot'>): react.JSX.Element;
|
|
469
|
+
declare function TableRow({ className, ...props }: ComponentPropsWithoutRef<'tr'>): react.JSX.Element;
|
|
470
|
+
declare function TableHead({ className, ...props }: ComponentPropsWithoutRef<'th'>): react.JSX.Element;
|
|
471
|
+
declare function TableCell({ className, ...props }: ComponentPropsWithoutRef<'td'>): react.JSX.Element;
|
|
472
|
+
declare function TableCaption({ className, ...props }: ComponentPropsWithoutRef<'caption'>): react.JSX.Element;
|
|
473
|
+
|
|
474
|
+
type TabsProps = ComponentPropsWithoutRef<typeof TabsPrimitive.Root>;
|
|
475
|
+
declare function Tabs({ className, ...props }: TabsProps): react.JSX.Element;
|
|
476
|
+
declare function TabsList({ className, ...props }: ComponentPropsWithoutRef<typeof TabsPrimitive.List>): react.JSX.Element;
|
|
477
|
+
declare function TabsTrigger({ className, ...props }: ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>): react.JSX.Element;
|
|
478
|
+
declare function TabsContent({ className, ...props }: ComponentPropsWithoutRef<typeof TabsPrimitive.Content>): react.JSX.Element;
|
|
479
|
+
|
|
480
|
+
type TextareaProps = ComponentPropsWithoutRef<'textarea'> & {
|
|
481
|
+
invalid?: boolean;
|
|
482
|
+
};
|
|
483
|
+
declare function Textarea({ className, invalid, ...props }: TextareaProps): react.JSX.Element;
|
|
484
|
+
|
|
485
|
+
declare const ToastProvider: react.FC<ToastPrimitive.ToastProviderProps>;
|
|
486
|
+
declare const ToastAction: react.ForwardRefExoticComponent<ToastPrimitive.ToastActionProps & react.RefAttributes<HTMLButtonElement>>;
|
|
487
|
+
declare function ToastViewport({ className, ...props }: ComponentPropsWithoutRef<typeof ToastPrimitive.Viewport>): react.JSX.Element;
|
|
488
|
+
declare const toast: (props?: ({
|
|
489
|
+
variant?: "success" | "error" | "neutral" | null | undefined;
|
|
490
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
491
|
+
type ToastProps = ComponentPropsWithoutRef<typeof ToastPrimitive.Root> & VariantProps<typeof toast>;
|
|
492
|
+
/** Sin deslizamiento de entrada: el aviso aparece donde va a quedarse. */
|
|
493
|
+
declare function Toast({ className, variant, children, ...props }: ToastProps): react.JSX.Element;
|
|
494
|
+
declare function ToastTitle({ className, ...props }: ComponentPropsWithoutRef<typeof ToastPrimitive.Title>): react.JSX.Element;
|
|
495
|
+
declare function ToastDescription({ className, ...props }: ComponentPropsWithoutRef<typeof ToastPrimitive.Description>): react.JSX.Element;
|
|
496
|
+
|
|
497
|
+
declare const TooltipProvider: react.FC<TooltipPrimitive.TooltipProviderProps>;
|
|
498
|
+
declare const Tooltip: react.FC<TooltipPrimitive.TooltipProps>;
|
|
499
|
+
declare const TooltipTrigger: react.ForwardRefExoticComponent<TooltipPrimitive.TooltipTriggerProps & react.RefAttributes<HTMLButtonElement>>;
|
|
500
|
+
declare function TooltipContent({ className, sideOffset, ...props }: ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>): react.JSX.Element;
|
|
501
|
+
|
|
502
|
+
declare const texto: (props?: ({
|
|
503
|
+
variant?: "display" | "body" | "h1" | "h2" | "h3" | "label" | "meta" | "stat" | "lead" | "ui" | "tag" | "chip" | "eyebrow" | null | undefined;
|
|
504
|
+
tone?: "accent" | "success" | "warning" | "error" | "warm" | "primary" | "secondary" | "muted" | null | undefined;
|
|
505
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
506
|
+
/** Etiquetas admitidas. La lista es corta a propósito: no es un `div` con estilo. */
|
|
507
|
+
type Etiqueta = 'h1' | 'h2' | 'h3' | 'h4' | 'p' | 'span' | 'strong' | 'em' | 'figcaption' | 'caption' | 'legend' | 'dt' | 'dd' | 'li';
|
|
508
|
+
type TextProps = Omit<ComponentPropsWithoutRef<'p'>, 'color'> & VariantProps<typeof texto> & {
|
|
509
|
+
/** Etiqueta HTML. Por defecto, la que corresponde a la escala. */
|
|
510
|
+
as?: Etiqueta;
|
|
511
|
+
/** Renderiza el hijo en vez de crear un elemento, para envolver un enlace. */
|
|
512
|
+
asChild?: boolean;
|
|
513
|
+
/**
|
|
514
|
+
* Corta la línea a 68ch. Activo por defecto en `body`, que es la única
|
|
515
|
+
* escala pensada para leerse en párrafos largos.
|
|
516
|
+
*/
|
|
517
|
+
measure?: boolean;
|
|
518
|
+
};
|
|
519
|
+
declare function Text({ className, variant, tone, as, asChild, measure, children, ...props }: TextProps): react.JSX.Element;
|
|
520
|
+
|
|
521
|
+
type TarjetaProps = ComponentPropsWithoutRef<'a'> & {
|
|
522
|
+
/**
|
|
523
|
+
* Renderiza el hijo en vez de un `<a>`. Es como se enchufa el `Link` de Next
|
|
524
|
+
* o de Astro sin que la librería dependa de ningún enrutador.
|
|
525
|
+
*/
|
|
526
|
+
asChild?: boolean | undefined;
|
|
527
|
+
children: ReactNode;
|
|
528
|
+
};
|
|
529
|
+
|
|
530
|
+
type ArticleCardProps = Omit<TarjetaProps, 'children' | 'title'> & {
|
|
531
|
+
title: ReactNode;
|
|
532
|
+
/** Entradilla. Se corta a dos líneas para que la rejilla no se desalinee. */
|
|
533
|
+
excerpt?: ReactNode;
|
|
534
|
+
/** Fecha ya formateada por el proyecto: la librería no impone locale. */
|
|
535
|
+
date?: ReactNode;
|
|
536
|
+
/** Valor de `datetime` del `<time>`, en ISO. */
|
|
537
|
+
dateTime?: string | undefined;
|
|
538
|
+
readingMinutes?: number | undefined;
|
|
539
|
+
tags?: readonly string[] | undefined;
|
|
540
|
+
};
|
|
541
|
+
/**
|
|
542
|
+
* La línea de metadatos va en `meta` y no en `eyebrow`: `18 ago 2026 · 8 min de
|
|
543
|
+
* lectura` es un dato, no un antetítulo, y en versalitas no era ninguna de las
|
|
544
|
+
* dos cosas.
|
|
545
|
+
*
|
|
546
|
+
* Los tags son la familia CATEGORÍA — píldora de arena en minúscula —, no la de
|
|
547
|
+
* estado. Un slug es lo que se lee `engineering-culture`.
|
|
548
|
+
*/
|
|
549
|
+
declare function ArticleCard({ title, excerpt, date, dateTime, readingMinutes, tags, className, ...props }: ArticleCardProps): react.JSX.Element;
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* La firma al pie del artículo: avatar 52px, nombre 15/500 y el rol en mono
|
|
553
|
+
* muted. Tres datos, ni uno más.
|
|
554
|
+
*
|
|
555
|
+
* NO recibe cara de mascota, y no es un descuido: es la misma regla que
|
|
556
|
+
* `PageHeader`. Una cara aquí sería humor en el sitio donde el lector está
|
|
557
|
+
* decidiendo si el autor sabe de lo que habla — justo lo que el contrato del
|
|
558
|
+
* manual excluye.
|
|
559
|
+
*
|
|
560
|
+
* El avatar del manual es la cabeza dentro de un círculo azul tiburón sólido,
|
|
561
|
+
* nunca la cara expresiva suelta.
|
|
562
|
+
*/
|
|
563
|
+
type AuthorCardProps = Omit<ComponentPropsWithoutRef<'div'>, 'role'> & {
|
|
564
|
+
name: string;
|
|
565
|
+
/** El rol. Va en mono: es un dato, no una frase. */
|
|
566
|
+
role?: ReactNode;
|
|
567
|
+
/** URL del avatar. Sin ella se muestran las iniciales. */
|
|
568
|
+
src?: string | undefined;
|
|
569
|
+
/** Una o dos frases. Se corta a 68ch sola. */
|
|
570
|
+
bio?: ReactNode;
|
|
571
|
+
/** Enlaces o botón de contacto. */
|
|
572
|
+
action?: ReactNode;
|
|
573
|
+
};
|
|
574
|
+
declare function AuthorCard({ name, role, src, bio, action, className, ...props }: AuthorCardProps): react.JSX.Element;
|
|
575
|
+
|
|
576
|
+
/**
|
|
577
|
+
* Migrado desde `eduardoalvarez.dev/src/components/audio-player/index.tsx`.
|
|
578
|
+
*
|
|
579
|
+
* La lógica no se reescribió: los tres modos, el reproductor flotante, los
|
|
580
|
+
* saltos de ±15s, el ciclo de velocidad 1 → 1.25 → 1.5 → 1.75 → 2 y el volumen
|
|
581
|
+
* con mute son los mismos. Lo que cambió es la piel y las dos dependencias que
|
|
582
|
+
* un paquete no puede tener:
|
|
583
|
+
*
|
|
584
|
+
* - `Icon` del portafolio → los glifos viven ahora en `src/lib/glyphs.tsx`,
|
|
585
|
+
* con los mismos trazados.
|
|
586
|
+
* - `trackEvent` de analítica → la prop `onFirstPlay`, que el consumidor
|
|
587
|
+
* conecta a lo que use. Sigue disparándose una sola vez por carga.
|
|
588
|
+
*
|
|
589
|
+
* Y tres cosas que el sistema no permite:
|
|
590
|
+
*
|
|
591
|
+
* - La onda ya no anima `scaleY`. Las barras siguen ahí y siguen distinguiendo
|
|
592
|
+
* reproducción de pausa por opacidad, pero no escalan.
|
|
593
|
+
* - El reproductor flotante aparece y desaparece en vez de deslizarse.
|
|
594
|
+
* - La barra de progreso ya no interpola el ancho.
|
|
595
|
+
*
|
|
596
|
+
* El giro del spinner de carga se queda, con la misma justificación que en
|
|
597
|
+
* `Button`: es realimentación de progreso, no de estado, y va en `motion-safe`.
|
|
598
|
+
*/
|
|
599
|
+
type AudioPlayerMode = 'full' | 'compact' | 'banner';
|
|
600
|
+
type AudioPlayerProps = {
|
|
601
|
+
src: string;
|
|
602
|
+
title?: string;
|
|
603
|
+
/**
|
|
604
|
+
* `full` para páginas de podcast, `compact` para barras laterales y `banner`
|
|
605
|
+
* para artículos con narración. `compact` y `banner` traen además el
|
|
606
|
+
* reproductor flotante cuando el estático sale de vista.
|
|
607
|
+
*/
|
|
608
|
+
mode?: AudioPlayerMode | undefined;
|
|
609
|
+
/**
|
|
610
|
+
* Se llama una sola vez por carga, la primera vez que el audio arranca.
|
|
611
|
+
* Aquí es donde el proyecto engancha su analítica; la librería no la trae.
|
|
612
|
+
*/
|
|
613
|
+
onFirstPlay?: ((title?: string) => void) | undefined;
|
|
614
|
+
};
|
|
615
|
+
declare function AudioPlayer({ src, title, mode, onFirstPlay }: AudioPlayerProps): react.JSX.Element;
|
|
616
|
+
|
|
617
|
+
type BlockquoteProps = Omit<ComponentPropsWithoutRef<'blockquote'>, 'cite'> & {
|
|
618
|
+
children: ReactNode;
|
|
619
|
+
/** Quién lo dijo. Se marca como `<cite>`. */
|
|
620
|
+
author?: ReactNode;
|
|
621
|
+
/** Dónde lo dijo: charla, artículo, conversación. */
|
|
622
|
+
source?: ReactNode;
|
|
623
|
+
};
|
|
624
|
+
/**
|
|
625
|
+
* La barra lateral es `accent`, que es el color interactivo, porque una cita es
|
|
626
|
+
* la voz de otro entrando en el texto. No lleva comillas decorativas: los
|
|
627
|
+
* glifos del sistema son SVG y una comilla de adorno no aporta nada que el
|
|
628
|
+
* borde y la sangría no digan ya.
|
|
629
|
+
*/
|
|
630
|
+
declare function Blockquote({ children, author, source, className, ...props }: BlockquoteProps): react.JSX.Element;
|
|
631
|
+
|
|
632
|
+
/**
|
|
633
|
+
* La ruta como una ruta: `~ / artículos / cómo-escalar-un-equipo`.
|
|
634
|
+
*
|
|
635
|
+
* El `~` no es decoración ni un icono de casa: es el home del sistema de
|
|
636
|
+
* archivos, y por eso el breadcrumb es mono y no sans. Los separadores van en
|
|
637
|
+
* `border` (#22414F), que es el token más tenue que sigue leyéndose como línea.
|
|
638
|
+
*
|
|
639
|
+
* El último tramo es la página actual, así que no es un enlace y lleva
|
|
640
|
+
* `aria-current="page"`. Es la diferencia entre una miga de pan accesible y
|
|
641
|
+
* cuatro enlaces seguidos, uno de los cuales no va a ninguna parte.
|
|
642
|
+
*/
|
|
643
|
+
type Migaja = {
|
|
644
|
+
label: ReactNode;
|
|
645
|
+
/** Sin `href`, el tramo es texto. El último nunca debería llevarlo. */
|
|
646
|
+
href?: string | undefined;
|
|
647
|
+
};
|
|
648
|
+
type BreadcrumbProps = Omit<ComponentPropsWithoutRef<'nav'>, 'children'> & {
|
|
649
|
+
items: readonly Migaja[];
|
|
650
|
+
/** Destino del `~`. Por defecto, la raíz del sitio. */
|
|
651
|
+
homeHref?: string;
|
|
652
|
+
/** Etiqueta accesible del `~`, que si no se lee como una tilde suelta. */
|
|
653
|
+
homeLabel?: string;
|
|
654
|
+
/**
|
|
655
|
+
* Renderiza los enlaces con el hijo, para enchufar el `Link` de Next o Astro.
|
|
656
|
+
* Recibe cada `href` en el `props` del Slot.
|
|
657
|
+
*/
|
|
658
|
+
linkAsChild?: ((props: {
|
|
659
|
+
href: string;
|
|
660
|
+
children: ReactNode;
|
|
661
|
+
}) => ReactNode) | undefined;
|
|
662
|
+
};
|
|
663
|
+
declare function Breadcrumb({ items, homeHref, homeLabel, linkAsChild, className, ...props }: BreadcrumbProps): react.JSX.Element;
|
|
664
|
+
|
|
665
|
+
/**
|
|
666
|
+
* `brand.hull` es «casco · contorno y fondo de bloques de código», así que un
|
|
667
|
+
* bloque de código es oscuro también en modo claro. Por eso la raíz declara
|
|
668
|
+
* `data-theme="dark"`: todo lo de dentro — tinta, hairline, acento — pasa a la
|
|
669
|
+
* paleta oscura sin importar el tema de la página. Es la única isla de tema
|
|
670
|
+
* invertido del sistema, y es deliberada.
|
|
671
|
+
*/
|
|
672
|
+
type CodeBlockProps = Omit<ComponentPropsWithoutRef<'div'>, 'children'> & {
|
|
673
|
+
/** El código ya resaltado, o texto plano. */
|
|
674
|
+
children: ReactNode;
|
|
675
|
+
/** Etiqueta del lenguaje. Se muestra en la barra superior. */
|
|
676
|
+
language?: string | undefined;
|
|
677
|
+
/** Texto que se copia al portapapeles. Sin esto, no se muestra el botón. */
|
|
678
|
+
copyText?: string | undefined;
|
|
679
|
+
};
|
|
680
|
+
declare function CodeBlock({ children, language, copyText, className, ...props }: CodeBlockProps): react.JSX.Element;
|
|
681
|
+
|
|
682
|
+
type CourseCardProps = Omit<TarjetaProps, 'children' | 'title'> & {
|
|
683
|
+
title: ReactNode;
|
|
684
|
+
summary?: ReactNode;
|
|
685
|
+
/** Nivel, duración, número de lecciones: lo que el proyecto quiera listar. */
|
|
686
|
+
meta?: readonly ReactNode[] | undefined;
|
|
687
|
+
/** Etiqueta de estado: «próximamente», «gratis», «nuevo». */
|
|
688
|
+
status?: ReactNode;
|
|
689
|
+
/**
|
|
690
|
+
* Porcentaje cursado. Solo tiene sentido para quien ya está inscrito; cuando
|
|
691
|
+
* se pasa, la barra va en arena, que es el color del progreso de curso.
|
|
692
|
+
*/
|
|
693
|
+
progress?: number | undefined;
|
|
694
|
+
};
|
|
695
|
+
declare function CourseCard({ title, summary, meta, status, progress, className, ...props }: CourseCardProps): react.JSX.Element;
|
|
696
|
+
|
|
697
|
+
/**
|
|
698
|
+
* La regla más importante de la mascota, por fin como código.
|
|
699
|
+
*
|
|
700
|
+
* `catalogo.ts` y `page-header/index.tsx` la citaban los dos —«por eso
|
|
701
|
+
* `EmptyState` recibe una cara y `PageHeader` no»— y el componente no existía,
|
|
702
|
+
* así que la regla vivía en un comentario sobre un componente fantasma. Desde
|
|
703
|
+
* que la story de marca repite la frase, además, era una promesa publicada.
|
|
704
|
+
*
|
|
705
|
+
* `expresion` es OBLIGATORIA y no opcional: un estado vacío sin cara es la mitad
|
|
706
|
+
* del componente. Es el único sitio, junto con el 404, el error de servidor, el
|
|
707
|
+
* progreso de curso, la celebración, el toast y el «sin spam» del newsletter,
|
|
708
|
+
* donde una cara puede aparecer.
|
|
709
|
+
*/
|
|
710
|
+
type EmptyStateProps = Omit<ComponentPropsWithoutRef<'div'>, 'title'> & {
|
|
711
|
+
/** La cara. Obligatoria: sin ella esto es un párrafo centrado. */
|
|
712
|
+
expresion: Cara;
|
|
713
|
+
title: ReactNode;
|
|
714
|
+
/** Una línea explicando qué falta o qué hacer. */
|
|
715
|
+
description?: ReactNode;
|
|
716
|
+
/** La acción que saca del estado vacío. Normalmente un botón terciario. */
|
|
717
|
+
action?: ReactNode;
|
|
718
|
+
/** Dónde se sirven los PNG de la marca. */
|
|
719
|
+
basePath?: string | undefined;
|
|
720
|
+
};
|
|
721
|
+
declare function EmptyState({ expresion, title, description, action, basePath, className, ...props }: EmptyStateProps): react.JSX.Element;
|
|
722
|
+
|
|
723
|
+
/**
|
|
724
|
+
* El pie, y la firma CLI del sitio: `$ cd ~/eduardoalvarez.dev/2026`.
|
|
725
|
+
*
|
|
726
|
+
* El dominio sale de `naming.domain` y no de una cadena escrita a mano, por la
|
|
727
|
+
* misma razón que el wordmark: si cambia, cambia en los cinco proyectos a la
|
|
728
|
+
* vez.
|
|
729
|
+
*
|
|
730
|
+
* Los enlaces de redes son iconos SIN texto visible, así que `aria-label` no es
|
|
731
|
+
* una mejora: es lo único que los hace legibles. Por eso es obligatorio en el
|
|
732
|
+
* tipo y no una prop opcional que se olvide.
|
|
733
|
+
*/
|
|
734
|
+
type Red = {
|
|
735
|
+
/** Lo que reemplaza al texto visible. Obligatorio. */
|
|
736
|
+
label: string;
|
|
737
|
+
href: string;
|
|
738
|
+
/**
|
|
739
|
+
* El glifo, a 19px. Las marcas van en SÓLIDO (`fill`) y los iconos
|
|
740
|
+
* funcionales en trazo de 1.6. Nunca un emoji.
|
|
741
|
+
*/
|
|
742
|
+
icon: ReactNode;
|
|
743
|
+
};
|
|
744
|
+
type FooterProps = ComponentPropsWithoutRef<'footer'> & {
|
|
745
|
+
social?: readonly Red[];
|
|
746
|
+
/** Año de la firma. */
|
|
747
|
+
year?: number;
|
|
748
|
+
/** Enlaces de texto: aviso legal, RSS, mapa del sitio. */
|
|
749
|
+
children?: ReactNode;
|
|
750
|
+
};
|
|
751
|
+
declare function Footer({ social, year, children, className, ...props }: FooterProps): react.JSX.Element;
|
|
752
|
+
type FooterLinkProps = ComponentPropsWithoutRef<'a'> & {
|
|
753
|
+
asChild?: boolean | undefined;
|
|
754
|
+
};
|
|
755
|
+
declare function FooterLink({ asChild, className, ...props }: FooterLinkProps): react.JSX.Element;
|
|
756
|
+
|
|
757
|
+
/**
|
|
758
|
+
* UNO por sitio. Es la única pieza del sistema que se gasta como el botón de
|
|
759
|
+
* conversión, y por la misma razón: si hay dos, no hay ninguno.
|
|
760
|
+
*
|
|
761
|
+
* Degradado, radio de panel, texto al 62 % del ancho y la pose sangrando por el
|
|
762
|
+
* borde inferior derecho. NUNCA centrada: una mascota centrada bajo un titular
|
|
763
|
+
* es una ilustración de portada, y esto es una cabecera.
|
|
764
|
+
*
|
|
765
|
+
* En móvil no hay borde por el que sangrar, así que la pose baja al flujo, bajo
|
|
766
|
+
* los botones. No es un `hidden` en pantalla pequeña: la pose es el 40 % de la
|
|
767
|
+
* personalidad del hero.
|
|
768
|
+
*
|
|
769
|
+
* El degradado viene de `--gradient-hero`, así que sigue el modo. No hay ángulo
|
|
770
|
+
* escrito a mano en ningún proyecto.
|
|
771
|
+
*/
|
|
772
|
+
type HeroProps = Omit<ComponentPropsWithoutRef<'section'>, 'title'> & {
|
|
773
|
+
title: ReactNode;
|
|
774
|
+
/** Mono, versalitas, en acento. */
|
|
775
|
+
eyebrow?: ReactNode;
|
|
776
|
+
description?: ReactNode;
|
|
777
|
+
/** Los botones. Aquí va el único `conversion` de la pantalla. */
|
|
778
|
+
action?: ReactNode;
|
|
779
|
+
/** La pose de Tiburoncín. Sin ella el hero es un panel con texto. */
|
|
780
|
+
pose?: Pose | undefined;
|
|
781
|
+
basePath?: string | undefined;
|
|
782
|
+
};
|
|
783
|
+
declare function Hero({ title, eyebrow, description, action, pose, basePath, className, ...props }: HeroProps): react.JSX.Element;
|
|
784
|
+
|
|
785
|
+
type LinkRowProps = Omit<TarjetaProps, 'children'> & {
|
|
786
|
+
name: ReactNode;
|
|
787
|
+
description?: ReactNode;
|
|
788
|
+
/** Glifo SVG del destino. Nunca un emoji. */
|
|
789
|
+
icon?: ReactNode;
|
|
790
|
+
/** Marca el enlace como externo: añade la flecha y el `rel` seguro. */
|
|
791
|
+
external?: boolean | undefined;
|
|
792
|
+
};
|
|
793
|
+
/**
|
|
794
|
+
* Migrado desde `links/src/components/Card.astro`. El original escalaba la
|
|
795
|
+
* tarjeta al 102 %, subía el título un píxel y giraba y agrandaba el icono en
|
|
796
|
+
* hover — cuatro movimientos que el sistema no permite. Aquí el hover cambia el
|
|
797
|
+
* borde y el color del icono, y nada más.
|
|
798
|
+
*/
|
|
799
|
+
declare function LinkRow({ name, description, icon, external, className, ...props }: LinkRowProps): react.JSX.Element;
|
|
800
|
+
|
|
801
|
+
/**
|
|
802
|
+
* La barra del sitio: 64px, abismo al 86 % y desenfoque de 14px detrás.
|
|
803
|
+
*
|
|
804
|
+
* Es composición de página y no un primitivo, pero vive en la librería por una
|
|
805
|
+
* razón concreta: la estética CLI de los items —mono, formato `./sección`— es lo
|
|
806
|
+
* primero que se desincroniza cuando cinco proyectos la reescriben cada uno por
|
|
807
|
+
* su cuenta.
|
|
808
|
+
*
|
|
809
|
+
* Renderiza `<header>` colgando directamente del `body`, así que ES el landmark
|
|
810
|
+
* `banner` del sitio. Por eso `PageHeader` va dentro de `<main>` y no es
|
|
811
|
+
* landmark: dos banners en una página son un fallo de accesibilidad.
|
|
812
|
+
*/
|
|
813
|
+
type NavProps = ComponentPropsWithoutRef<'header'> & {
|
|
814
|
+
/** El logo, a la izquierda. */
|
|
815
|
+
brand?: ReactNode;
|
|
816
|
+
/** Los items de sección, en el centro. */
|
|
817
|
+
children?: ReactNode;
|
|
818
|
+
/** Acciones a la derecha: conversión, cambio de tema, buscar. */
|
|
819
|
+
actions?: ReactNode;
|
|
820
|
+
};
|
|
821
|
+
declare function Nav({ brand, children, actions, className, ...props }: NavProps): react.JSX.Element;
|
|
822
|
+
type NavItemProps = ComponentPropsWithoutRef<'a'> & {
|
|
823
|
+
/** Sección actual: bioluz con subrayado de 1px. */
|
|
824
|
+
active?: boolean | undefined;
|
|
825
|
+
/** Renderiza el hijo en vez de un `<a>`, para el `Link` del enrutador. */
|
|
826
|
+
asChild?: boolean | undefined;
|
|
827
|
+
};
|
|
828
|
+
/**
|
|
829
|
+
* El `./` lo pone el componente, no quien lo usa.
|
|
830
|
+
*
|
|
831
|
+
* Es la misma decisión que el botón terciario: el formato es parte de la pieza,
|
|
832
|
+
* no una convención que haya que recordar en cinco proyectos. Va `aria-hidden`,
|
|
833
|
+
* así que un lector de pantalla anuncia «artículos» y no «punto barra
|
|
834
|
+
* artículos».
|
|
835
|
+
*/
|
|
836
|
+
declare function NavItem({ active, asChild, className, children, ...props }: NavItemProps): react.JSX.Element;
|
|
837
|
+
|
|
838
|
+
/**
|
|
839
|
+
* Cuatro estados, y el aviso va DEBAJO del formulario.
|
|
840
|
+
*
|
|
841
|
+
* Reemplazar el formulario por el mensaje de éxito es lo que hace casi todo el
|
|
842
|
+
* mundo y es lo que rompe el caso real: alguien se suscribe con el correo
|
|
843
|
+
* equivocado y ya no tiene dónde volver a escribirlo. El campo se queda.
|
|
844
|
+
*
|
|
845
|
+
* El componente es presentacional: recibe `state` y emite `onSubmitEmail`. La
|
|
846
|
+
* llamada de red la hace el proyecto, porque cada uno tiene su proveedor y la
|
|
847
|
+
* librería no va a elegirlo por ellos.
|
|
848
|
+
*
|
|
849
|
+
* El aviso usa la SEGUNDA receta del sistema —`enfasis="fuerte"`, fondo al 10 %
|
|
850
|
+
* y borde sólido— porque va pegado bajo un campo que ya tiene borde: con la
|
|
851
|
+
* receta sutil, las dos líneas se leen como una sola caja.
|
|
852
|
+
*
|
|
853
|
+
* Es uno de los sitios donde la mascota puede aparecer: el «sin spam».
|
|
854
|
+
*/
|
|
855
|
+
type NewsletterState = 'reposo' | 'enviando' | 'exito' | 'error';
|
|
856
|
+
type NewsletterFormProps = Omit<ComponentPropsWithoutRef<'section'>, 'title' | 'onSubmit'> & {
|
|
857
|
+
title: ReactNode;
|
|
858
|
+
description?: ReactNode;
|
|
859
|
+
state?: NewsletterState;
|
|
860
|
+
/** Se dispara con el correo ya leído del campo. */
|
|
861
|
+
onSubmitEmail?: ((email: string) => void) | undefined;
|
|
862
|
+
successMessage?: ReactNode;
|
|
863
|
+
errorMessage?: ReactNode;
|
|
864
|
+
/** La letra pequeña. Es el «sin spam», y por eso admite cara. */
|
|
865
|
+
disclaimer?: ReactNode;
|
|
866
|
+
expresion?: Cara | undefined;
|
|
867
|
+
basePath?: string | undefined;
|
|
868
|
+
submitLabel?: string;
|
|
869
|
+
placeholder?: string;
|
|
870
|
+
fieldLabel?: string;
|
|
871
|
+
};
|
|
872
|
+
declare function NewsletterForm({ title, description, state, onSubmitEmail, successMessage, errorMessage, disclaimer, expresion, basePath, submitLabel, placeholder, fieldLabel, className, ...props }: NewsletterFormProps): react.JSX.Element;
|
|
873
|
+
|
|
874
|
+
/**
|
|
875
|
+
* Una sola cabecera en dos escalas, no dos componentes.
|
|
876
|
+
*
|
|
877
|
+
* El hero del portafolio y el de cursos resultaron ser el mismo esqueleto —
|
|
878
|
+
* eyebrow en acento, titular, párrafo acotado — con distinto tamaño. Separarlos
|
|
879
|
+
* en `Hero` y `PageHeader` habría duplicado la misma regla en dos sitios y
|
|
880
|
+
* habría dejado la puerta abierta a que se separaran con el tiempo.
|
|
881
|
+
*
|
|
882
|
+
* `display` para portadas, `page` para cabeceras de sección.
|
|
883
|
+
*
|
|
884
|
+
* No recibe cara de la mascota, ni en una escala ni en la otra: las caras van en
|
|
885
|
+
* estados vacíos, confirmaciones, errores, progreso de curso y celebración.
|
|
886
|
+
*
|
|
887
|
+
* Renderiza un `<header>`, y va DENTRO de `<main>`. Un `<header>` que cuelga
|
|
888
|
+
* directamente del `<body>` se convierte en landmark `banner`, y entonces
|
|
889
|
+
* compite con la cabecera del sitio: dos banners en una página es un fallo de
|
|
890
|
+
* accesibilidad. Dentro de `<main>` no es landmark y sí es la cabecera del
|
|
891
|
+
* contenido, que es lo que este componente es.
|
|
892
|
+
*/
|
|
893
|
+
declare const cabecera: (props?: ({
|
|
894
|
+
size?: "display" | "page" | null | undefined;
|
|
895
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
896
|
+
type PageHeaderProps = Omit<ComponentPropsWithoutRef<'header'>, 'title'> & VariantProps<typeof cabecera> & {
|
|
897
|
+
title: ReactNode;
|
|
898
|
+
/** Mono, versalitas, en acento. Es la sección a la que pertenece la página. */
|
|
899
|
+
eyebrow?: ReactNode | undefined;
|
|
900
|
+
description?: ReactNode | undefined;
|
|
901
|
+
/**
|
|
902
|
+
* Ranura para las llamadas a la acción. Si aquí va un botón de conversión,
|
|
903
|
+
* es el único de la pantalla.
|
|
904
|
+
*/
|
|
905
|
+
action?: ReactNode | undefined;
|
|
906
|
+
/** Nivel del titular. `h1` salvo que la página ya tenga uno. */
|
|
907
|
+
as?: 'h1' | 'h2' | undefined;
|
|
908
|
+
};
|
|
909
|
+
declare function PageHeader({ title, eyebrow, description, action, size, as, className, ...props }: PageHeaderProps): react.JSX.Element;
|
|
910
|
+
|
|
911
|
+
/**
|
|
912
|
+
* La barra lateral del admin del blog.
|
|
913
|
+
*
|
|
914
|
+
* El `▸` lo pone el componente, igual que el `./` de `NavItem` y el `~` del
|
|
915
|
+
* breadcrumb: es la misma estética CLI y la misma decisión — el formato es parte
|
|
916
|
+
* de la pieza, no una convención que haya que recordar. Va `aria-hidden`.
|
|
917
|
+
*
|
|
918
|
+
* El pie lleva la versión y la rama (`v5.0.1 · main`) en la escala `meta`. No es
|
|
919
|
+
* decoración: en un admin es lo primero que se pregunta cuando algo se ve raro.
|
|
920
|
+
*/
|
|
921
|
+
type SidebarItemProps = ComponentPropsWithoutRef<'a'> & {
|
|
922
|
+
active?: boolean | undefined;
|
|
923
|
+
asChild?: boolean | undefined;
|
|
924
|
+
/** Contador a la derecha: borradores pendientes, media sin usar. */
|
|
925
|
+
badge?: ReactNode;
|
|
926
|
+
};
|
|
927
|
+
declare function SidebarItem({ active, asChild, badge, className, children, ...props }: SidebarItemProps): react.JSX.Element;
|
|
928
|
+
type SidebarNavProps = ComponentPropsWithoutRef<'nav'> & {
|
|
929
|
+
/** Encabezado del panel. */
|
|
930
|
+
title?: ReactNode;
|
|
931
|
+
/** Versión y rama, al pie. */
|
|
932
|
+
version?: ReactNode;
|
|
933
|
+
branch?: ReactNode;
|
|
934
|
+
};
|
|
935
|
+
declare function SidebarNav({ title, version, branch, children, className, ...props }: SidebarNavProps): react.JSX.Element;
|
|
936
|
+
|
|
937
|
+
/**
|
|
938
|
+
* Una métrica grande: el número en la escala `stat` y su nombre debajo.
|
|
939
|
+
*
|
|
940
|
+
* La regla del documento no es de estilo, es de semántica: «bioluz para lo
|
|
941
|
+
* neutro y arena SOLO cuando el número es el problema». Un 12 de aplicaciones
|
|
942
|
+
* es un dato; un 0 de design systems es el problema del que trata la charla.
|
|
943
|
+
* Por eso `tone` no es una paleta abierta — son dos valores y significan cosas
|
|
944
|
+
* distintas.
|
|
945
|
+
*/
|
|
946
|
+
type StatProps = Omit<ComponentPropsWithoutRef<'div'>, 'title'> & {
|
|
947
|
+
/** El número, ya formateado. La librería no impone locale. */
|
|
948
|
+
value: ReactNode;
|
|
949
|
+
/** Qué se está contando. Va en mono versalitas. */
|
|
950
|
+
label: ReactNode;
|
|
951
|
+
/** `alerta` solo cuando el número ES el problema. */
|
|
952
|
+
tone?: 'neutral' | 'alerta';
|
|
953
|
+
/** Con `progress`, la métrica se lee como avance y añade la barra. */
|
|
954
|
+
progress?: number | undefined;
|
|
955
|
+
};
|
|
956
|
+
declare function Stat({ value, label, tone, progress, className, ...props }: StatProps): react.JSX.Element;
|
|
957
|
+
|
|
958
|
+
type TalkCardProps = Omit<TarjetaProps, 'children' | 'title'> & {
|
|
959
|
+
title: ReactNode;
|
|
960
|
+
/** Dónde se dio: la conferencia, el meetup, el equipo. */
|
|
961
|
+
event: ReactNode;
|
|
962
|
+
date?: ReactNode;
|
|
963
|
+
dateTime?: string | undefined;
|
|
964
|
+
location?: ReactNode;
|
|
965
|
+
/** Etiqueta corta de estado: «con vídeo», «próxima», «solo audio». */
|
|
966
|
+
status?: ReactNode;
|
|
967
|
+
};
|
|
968
|
+
declare function TalkCard({ title, event, date, dateTime, location, status, className, ...props }: TalkCardProps): react.JSX.Element;
|
|
969
|
+
|
|
970
|
+
/**
|
|
971
|
+
* «En esta página». El índice del artículo largo.
|
|
972
|
+
*
|
|
973
|
+
* Es un `<nav>` con nombre accesible propio, no una lista suelta: en una página
|
|
974
|
+
* que ya tiene la barra del sitio y las migas, un tercer grupo de enlaces sin
|
|
975
|
+
* nombre es indistinguible de los otros dos para quien navega por landmarks.
|
|
976
|
+
*
|
|
977
|
+
* El activo se marca con `aria-current`, no solo con color — la sección en la
|
|
978
|
+
* que estás no puede comunicarse únicamente con bioluz.
|
|
979
|
+
*/
|
|
980
|
+
type Entrada = {
|
|
981
|
+
/** El ancla, con `#`. */
|
|
982
|
+
href: string;
|
|
983
|
+
label: ReactNode;
|
|
984
|
+
/** Sangra la entrada. Solo dos niveles: h2 y h3. */
|
|
985
|
+
nested?: boolean | undefined;
|
|
986
|
+
};
|
|
987
|
+
type TableOfContentsProps = Omit<ComponentPropsWithoutRef<'nav'>, 'children'> & {
|
|
988
|
+
items: readonly Entrada[];
|
|
989
|
+
/** El título del bloque. */
|
|
990
|
+
title?: ReactNode;
|
|
991
|
+
/** Ancla de la sección visible. */
|
|
992
|
+
activeHref?: string | undefined;
|
|
993
|
+
linkAsChild?: ((props: {
|
|
994
|
+
href: string;
|
|
995
|
+
children: ReactNode;
|
|
996
|
+
}) => ReactNode) | undefined;
|
|
997
|
+
};
|
|
998
|
+
declare function TableOfContents({ items, title, activeHref, linkAsChild, className, ...props }: TableOfContentsProps): react.JSX.Element;
|
|
999
|
+
|
|
1000
|
+
declare function cn(...inputs: ClassValue[]): string;
|
|
1001
|
+
|
|
1002
|
+
type IconProps = SVGProps<SVGSVGElement>;
|
|
1003
|
+
declare const GitHub: (props: IconProps) => react.JSX.Element;
|
|
1004
|
+
declare const LinkedIn: (props: IconProps) => react.JSX.Element;
|
|
1005
|
+
declare const X: (props: IconProps) => react.JSX.Element;
|
|
1006
|
+
declare const Instagram: (props: IconProps) => react.JSX.Element;
|
|
1007
|
+
declare const Discord: (props: IconProps) => react.JSX.Element;
|
|
1008
|
+
declare const YouTube: (props: IconProps) => react.JSX.Element;
|
|
1009
|
+
declare const Rss: (props: IconProps) => react.JSX.Element;
|
|
1010
|
+
declare const Correo: (props: IconProps) => react.JSX.Element;
|
|
1011
|
+
|
|
1012
|
+
declare const social_Correo: typeof Correo;
|
|
1013
|
+
declare const social_Discord: typeof Discord;
|
|
1014
|
+
declare const social_GitHub: typeof GitHub;
|
|
1015
|
+
declare const social_Instagram: typeof Instagram;
|
|
1016
|
+
declare const social_LinkedIn: typeof LinkedIn;
|
|
1017
|
+
declare const social_Rss: typeof Rss;
|
|
1018
|
+
declare const social_X: typeof X;
|
|
1019
|
+
declare const social_YouTube: typeof YouTube;
|
|
1020
|
+
declare namespace social {
|
|
1021
|
+
export { social_Correo as Correo, social_Discord as Discord, social_GitHub as GitHub, social_Instagram as Instagram, social_LinkedIn as LinkedIn, social_Rss as Rss, social_X as X, social_YouTube as YouTube };
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
export { Alert, type AlertProps, ArticleCard, type ArticleCardProps, AudioPlayer, type AudioPlayerMode, type AudioPlayerProps, AuthorCard, type AuthorCardProps, Avatar, AvatarFallback, AvatarImage, type AvatarProps, Badge, type BadgeProps, Blockquote, type BlockquoteProps, Breadcrumb, type BreadcrumbProps, Button, type ButtonProps, Calendar, type CalendarProps, Cara, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CategoryBadge, type CategoryBadgeProps, Checkbox, type CheckboxProps, Code, CodeBlock, type CodeBlockProps, type CodeProps, CourseCard, type CourseCardProps, DateField, type DateFieldProps, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, type EmptyStateProps, type Entrada, Footer, FooterLink, type FooterLinkProps, type FooterProps, HOVER_TARJETA, Hero, type HeroProps, Input, type InputProps, Label, type LabelProps, LinkRow, type LinkRowProps, MetricBadge, type MetricBadgeProps, type Migaja, Nav, NavItem, type NavItemProps, type NavProps, NewsletterForm, type NewsletterFormProps, type NewsletterState, PageHeader, type PageHeaderProps, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, type PaginationLinkProps, PaginationNext, PaginationPrevious, Popover, PopoverAnchor, PopoverContent, type PopoverContentProps, PopoverTrigger, Pose, Progress, type ProgressProps, RadioGroup, RadioGroupItem, type RadioGroupItemProps, type RadioGroupProps, type Red, SUPERFICIE_TARJETA, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue, Separator, type SeparatorProps, Sheet, SheetBody, SheetClose, SheetContent, type SheetContentProps, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, SidebarItem, type SidebarItemProps, SidebarNav, type SidebarNavProps, Skeleton, type SkeletonProps, Stat, type StatProps, Switch, type SwitchProps, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableOfContents, type TableOfContentsProps, TableRow, Tabs, TabsContent, TabsList, type TabsProps, TabsTrigger, TalkCard, type TalkCardProps, Text, type TextProps, Textarea, type TextareaProps, Toast, ToastAction, ToastDescription, type ToastProps, ToastProvider, ToastTitle, ToastViewport, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, alert as alertVariants, avatar as avatarVariants, badge as badgeVariants, button as buttonVariants, categoria as categoryBadgeVariants, cn, social, texto as textVariants };
|