@eduardoalvarez/arrecife 0.2.0 → 0.4.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.
@@ -0,0 +1,127 @@
1
+ import * as react from 'react';
2
+ import { ComponentPropsWithoutRef, ReactNode } from 'react';
3
+ import { Legend, Tooltip } from 'recharts';
4
+
5
+ /**
6
+ * El chasis de las gráficas: contenedor, tooltip y leyenda con el vocabulario
7
+ * del sistema. Recharts pinta; esto decide cómo se ve.
8
+ *
9
+ * Se publica en `@eduardoalvarez/arrecife/chart` y NO en la raíz. Recharts pesa,
10
+ * y solo uno de los cinco proyectos dibuja métricas: colgarlo del índice
11
+ * principal obligaría a los otros cuatro a instalarlo para que su bundler
12
+ * resolviera un import que nunca ejecutan. Es dependencia de pares OPCIONAL, por
13
+ * el mismo criterio con el que `./og` y `./shiki` se mantienen sin React.
14
+ *
15
+ * Lo que esta capa aporta —y lo que se perdía copiando el `chart.tsx` de shadcn
16
+ * en cada proyecto— son tres cosas que se desincronizan solas:
17
+ *
18
+ * 1. La paleta de series sale de `tokens.series` y sigue el modo. Son cuatro
19
+ * y se distinguen por tono, no por luminosidad.
20
+ * 2. La rejilla, los ejes y el cursor usan `hairline` y `textMuted`, no los
21
+ * grises por defecto de Recharts, que no son de esta identidad.
22
+ * 3. El tooltip aparece donde va a quedarse: `isAnimationActive` apagado en
23
+ * todas partes, porque el sistema no anima posición.
24
+ *
25
+ * Las piezas de datos —`BarChart`, `Line`, `XAxis`— NO se reexportan. Son la API
26
+ * de Recharts, el proyecto ya la conoce y envolverlas sería una capa de nombres
27
+ * que hay que mantener sincronizada con la versión de la librería.
28
+ */
29
+ /**
30
+ * El color de la serie `indice`, como custom property.
31
+ *
32
+ * Devuelve `var(--color-serie-N)` y no el hexadecimal: leído en JS, el hex sería
33
+ * el del modo que había cuando se montó el componente y no cambiaría al alternar
34
+ * el tema. La variable la resuelve el navegador en cada pintura.
35
+ *
36
+ * Da la vuelta pasadas las cuatro. Que dos series compartan color es un fallo
37
+ * visible, y es la señal correcta: la gráfica tiene más categorías de las que
38
+ * esta identidad sabe distinguir, y lo que toca es agrupar en «otros».
39
+ */
40
+ declare function colorDeSerie(indice: number): string;
41
+ /** Las cuatro, en orden, para pasárselas de golpe a un `Pie` con `Cell`. */
42
+ declare const COLORES_DE_SERIE: string[];
43
+ type ChartContainerProps = Omit<ComponentPropsWithoutRef<'figure'>, 'title'> & {
44
+ /**
45
+ * Qué muestra la gráfica, en una frase. Obligatorio, como el `label` de
46
+ * `Progress`: un `<svg>` de barras sin nombre accesible no es «una gráfica sin
47
+ * etiqueta», es una región vacía.
48
+ */
49
+ label: string;
50
+ /**
51
+ * Lo que la gráfica dice, en palabras. Va en un `figcaption` oculto
52
+ * visualmente.
53
+ *
54
+ * No sustituye a la gráfica: la capa de accesibilidad de Recharts ya permite
55
+ * recorrer los puntos con el teclado. Es el titular —«sube de 24 a 52 con una
56
+ * caída en mayo»— que ningún recorrido punto a punto da.
57
+ */
58
+ summary?: ReactNode;
59
+ /** Alto en píxeles. Recharts necesita uno concreto para medir. */
60
+ height?: number;
61
+ children: ReactNode;
62
+ };
63
+ /**
64
+ * Envuelve la gráfica en un `<figure>` con nombre accesible y le da a Recharts
65
+ * el alto concreto que necesita para medirse.
66
+ *
67
+ * El `<figure>` NO lleva `role`: ya tiene el suyo implícito, y ponerle `group`
68
+ * encima es un rol no permitido para el elemento —axe lo señala—. Lo que sí
69
+ * lleva es `aria-label`, que es lo que lo nombra.
70
+ *
71
+ * Y el contenido NO va `aria-hidden`. Fue lo primero que se intentó, con el
72
+ * argumento de que anunciar cada tick no cuenta lo que la gráfica cuenta, y está
73
+ * mal por dos motivos: la capa de accesibilidad de Recharts hace la gráfica
74
+ * recorrible con el teclado, y esconder un subárbol que contiene elementos
75
+ * enfocables es una violación por sí misma —el foco entra en algo que no existe
76
+ * para quien escucha—. El resumen se suma a eso, no lo reemplaza.
77
+ */
78
+ declare function ChartContainer({ label, summary, height, className, children, ...props }: ChartContainerProps): react.JSX.Element;
79
+ /**
80
+ * El `Tooltip` de Recharts con los defectos del sistema: sin animación y con el
81
+ * cursor teñido de `surfaceRaised`.
82
+ *
83
+ * Se pasa `content={<ChartTooltipContent />}` para la caja.
84
+ */
85
+ declare function ChartTooltip(props: ComponentPropsWithoutRef<typeof Tooltip>): react.JSX.Element;
86
+ declare function ChartLegend(props: ComponentPropsWithoutRef<typeof Legend>): react.JSX.Element;
87
+ /**
88
+ * Lo que Recharts le pasa a un `content`, declarado aquí en corto.
89
+ *
90
+ * Los tipos de Recharts para esto son abiertos y arrastran genéricos que no
91
+ * aportan nada al sitio de uso; `any` está prohibido en el repo, así que se
92
+ * declara lo que de verdad se lee y el valor se trata como `unknown`.
93
+ */
94
+ type ChartPayloadItem = {
95
+ name?: string | number | undefined;
96
+ value?: unknown;
97
+ color?: string | undefined;
98
+ dataKey?: string | number | undefined;
99
+ };
100
+ type ChartTooltipContentProps = {
101
+ active?: boolean | undefined;
102
+ payload?: readonly ChartPayloadItem[] | undefined;
103
+ label?: ReactNode;
104
+ /** Formatea el valor. Sin ella se imprime tal cual: la librería no impone locale. */
105
+ formatter?: ((valor: unknown, item: ChartPayloadItem) => ReactNode) | undefined;
106
+ /** Oculta el encabezado, para una gráfica de una sola categoría. */
107
+ hideLabel?: boolean;
108
+ className?: string;
109
+ };
110
+ /**
111
+ * La caja del tooltip. Es una tarjeta del sistema —`surface`, borde de control,
112
+ * sombra estándar— y no la caja blanca de Recharts, que en modo oscuro es un
113
+ * rectángulo blanco encima de un panel oscuro.
114
+ *
115
+ * El punto de color es un cuadrado de 8px, no un círculo: es la misma marca que
116
+ * usa la leyenda, y en 8 píxeles un círculo y un cuadrado se distinguen peor
117
+ * entre sí que dos colores de la paleta.
118
+ */
119
+ declare function ChartTooltipContent({ active, payload, label, formatter, hideLabel, className, }: ChartTooltipContentProps): react.JSX.Element | null;
120
+ type ChartLegendContentProps = {
121
+ payload?: readonly ChartPayloadItem[] | undefined;
122
+ className?: string;
123
+ };
124
+ /** La leyenda con la misma marca cuadrada del tooltip y la escala `label`. */
125
+ declare function ChartLegendContent({ payload, className }: ChartLegendContentProps): react.JSX.Element | null;
126
+
127
+ export { COLORES_DE_SERIE, ChartContainer, type ChartContainerProps, ChartLegend, ChartLegendContent, type ChartLegendContentProps, type ChartPayloadItem, ChartTooltip, ChartTooltipContent, type ChartTooltipContentProps, colorDeSerie };
@@ -0,0 +1,103 @@
1
+ import { Text } from '../chunk-UOWIDFCB.js';
2
+ import { cn } from '../chunk-NHS7ETKJ.js';
3
+ import '../chunk-TSPJOM6K.js';
4
+ import '../chunk-MLKGABMK.js';
5
+ import { ResponsiveContainer, Tooltip, Legend } from 'recharts';
6
+ import { jsxs, jsx } from 'react/jsx-runtime';
7
+
8
+ function colorDeSerie(indice) {
9
+ return `var(--color-serie-${Math.abs(indice) % 4 + 1})`;
10
+ }
11
+ var COLORES_DE_SERIE = [0, 1, 2, 3].map(colorDeSerie);
12
+ function ChartContainer({
13
+ label,
14
+ summary,
15
+ height = 320,
16
+ className,
17
+ children,
18
+ ...props
19
+ }) {
20
+ return /* @__PURE__ */ jsxs(
21
+ "figure",
22
+ {
23
+ "aria-label": label,
24
+ className: cn(
25
+ "w-full",
26
+ // La rejilla y los ejes, con los tokens del sistema en vez de los grises
27
+ // por defecto de Recharts. Van como variantes de descendiente porque los
28
+ // nodos los pinta la librería y no hay dónde ponerles una clase.
29
+ "[&_.recharts-cartesian-grid_line]:stroke-hairline",
30
+ "[&_.recharts-cartesian-axis-line]:stroke-hairline",
31
+ "[&_.recharts-cartesian-axis-tick_text]:fill-text-muted",
32
+ "[&_.recharts-cartesian-axis-tick_text]:font-mono",
33
+ "[&_.recharts-cartesian-axis-tick_text]:text-chip",
34
+ "[&_.recharts-rectangle.recharts-tooltip-cursor]:fill-surface-raised",
35
+ "[&_.recharts-curve.recharts-tooltip-cursor]:stroke-hairline-hover",
36
+ "[&_.recharts-sector]:outline-none",
37
+ "[&_.recharts-surface]:overflow-visible",
38
+ className
39
+ ),
40
+ ...props,
41
+ children: [
42
+ /* @__PURE__ */ jsx("div", { style: { height }, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children }) }),
43
+ summary ? /* @__PURE__ */ jsx("figcaption", { className: "sr-only", children: summary }) : null
44
+ ]
45
+ }
46
+ );
47
+ }
48
+ function ChartTooltip(props) {
49
+ return /* @__PURE__ */ jsx(Tooltip, { isAnimationActive: false, ...props });
50
+ }
51
+ function ChartLegend(props) {
52
+ return /* @__PURE__ */ jsx(Legend, { ...props });
53
+ }
54
+ function ChartTooltipContent({
55
+ active,
56
+ payload,
57
+ label,
58
+ formatter,
59
+ hideLabel = false,
60
+ className
61
+ }) {
62
+ if (!active || !payload || payload.length === 0) return null;
63
+ return /* @__PURE__ */ jsxs(
64
+ "div",
65
+ {
66
+ className: cn(
67
+ "rounded-card border-border bg-surface shadow-standard p-step-sm gap-step-xs flex flex-col border",
68
+ className
69
+ ),
70
+ children: [
71
+ hideLabel || label === void 0 || label === null ? null : /* @__PURE__ */ jsx(Text, { as: "p", variant: "meta", tone: "muted", children: label }),
72
+ /* @__PURE__ */ jsx("ul", { className: "gap-step-xs flex flex-col", children: payload.map((item, i) => /* @__PURE__ */ jsxs("li", { className: "gap-step-xs flex items-center", children: [
73
+ /* @__PURE__ */ jsx(
74
+ "span",
75
+ {
76
+ "aria-hidden": "true",
77
+ className: "rounded-chip size-2 shrink-0",
78
+ style: { backgroundColor: item.color ?? colorDeSerie(i) }
79
+ }
80
+ ),
81
+ /* @__PURE__ */ jsx(Text, { as: "span", variant: "label", tone: "secondary", className: "font-normal", children: item.name }),
82
+ /* @__PURE__ */ jsx(Text, { as: "span", variant: "label", className: "ml-auto font-mono tabular-nums", children: formatter ? formatter(item.value, item) : String(item.value ?? "") })
83
+ ] }, `${String(item.dataKey ?? item.name ?? i)}`)) })
84
+ ]
85
+ }
86
+ );
87
+ }
88
+ function ChartLegendContent({ payload, className }) {
89
+ if (!payload || payload.length === 0) return null;
90
+ return /* @__PURE__ */ jsx("ul", { className: cn("gap-step-md pt-step-sm flex flex-wrap items-center justify-center", className), children: payload.map((item, i) => /* @__PURE__ */ jsxs("li", { className: "gap-step-xs flex items-center", children: [
91
+ /* @__PURE__ */ jsx(
92
+ "span",
93
+ {
94
+ "aria-hidden": "true",
95
+ className: "rounded-chip size-2 shrink-0",
96
+ style: { backgroundColor: item.color ?? colorDeSerie(i) }
97
+ }
98
+ ),
99
+ /* @__PURE__ */ jsx(Text, { as: "span", variant: "label", tone: "secondary", className: "font-normal", children: item.value })
100
+ ] }, `${String(item.dataKey ?? item.value ?? i)}`)) });
101
+ }
102
+
103
+ export { COLORES_DE_SERIE, ChartContainer, ChartLegend, ChartLegendContent, ChartTooltip, ChartTooltipContent, colorDeSerie };
@@ -0,0 +1,83 @@
1
+ // src/tema/index.ts
2
+ var TEMA_CLAVE = "arrecife-tema";
3
+ var TEMA_ATRIBUTO = "data-theme";
4
+ var TEMA_EVENTO = "arrecife:tema";
5
+ var esTema = (valor) => valor === "dark" || valor === "light";
6
+ function temaActual() {
7
+ if (typeof document === "undefined") return "dark";
8
+ const puesto = document.documentElement.getAttribute(TEMA_ATRIBUTO);
9
+ return esTema(puesto) ? puesto : "dark";
10
+ }
11
+ function temaGuardado() {
12
+ if (typeof localStorage === "undefined") return null;
13
+ try {
14
+ const valor = localStorage.getItem(TEMA_CLAVE);
15
+ return esTema(valor) ? valor : null;
16
+ } catch {
17
+ return null;
18
+ }
19
+ }
20
+ function temaPreferido() {
21
+ const guardado = temaGuardado();
22
+ if (guardado) return guardado;
23
+ if (typeof matchMedia === "undefined") return "dark";
24
+ return matchMedia("(prefers-color-scheme: light)").matches ? "light" : "dark";
25
+ }
26
+ function aplicarTema(tema, persistir = true) {
27
+ if (typeof document === "undefined") return;
28
+ document.documentElement.setAttribute(TEMA_ATRIBUTO, tema);
29
+ document.documentElement.style.colorScheme = tema;
30
+ if (persistir) {
31
+ try {
32
+ localStorage.setItem(TEMA_CLAVE, tema);
33
+ } catch {
34
+ }
35
+ }
36
+ dispatchEvent(new CustomEvent(TEMA_EVENTO, { detail: tema }));
37
+ }
38
+ function alternarTema() {
39
+ const siguiente = temaActual() === "dark" ? "light" : "dark";
40
+ aplicarTema(siguiente);
41
+ return siguiente;
42
+ }
43
+ function escucharTema(alCambiar) {
44
+ if (typeof window === "undefined") return () => {
45
+ };
46
+ const propio = (evento) => {
47
+ const detalle = evento.detail;
48
+ if (esTema(detalle)) alCambiar(detalle);
49
+ };
50
+ const otraPestana = (evento) => {
51
+ if (evento.key !== TEMA_CLAVE) return;
52
+ const tema = esTema(evento.newValue) ? evento.newValue : temaPreferido();
53
+ aplicarTema(tema, false);
54
+ alCambiar(tema);
55
+ };
56
+ addEventListener(TEMA_EVENTO, propio);
57
+ addEventListener("storage", otraPestana);
58
+ return () => {
59
+ removeEventListener(TEMA_EVENTO, propio);
60
+ removeEventListener("storage", otraPestana);
61
+ };
62
+ }
63
+ var scriptTema = [
64
+ "(function () {",
65
+ " var CLAVE = " + JSON.stringify(TEMA_CLAVE) + ";",
66
+ " function resolver() {",
67
+ " try {",
68
+ " var guardado = localStorage.getItem(CLAVE);",
69
+ ' if (guardado === "dark" || guardado === "light") return guardado;',
70
+ " } catch (e) {}",
71
+ ' return matchMedia("(prefers-color-scheme: light)").matches ? "light" : "dark";',
72
+ " }",
73
+ " function aplicar() {",
74
+ " var tema = resolver();",
75
+ " document.documentElement.setAttribute(" + JSON.stringify(TEMA_ATRIBUTO) + ", tema);",
76
+ " document.documentElement.style.colorScheme = tema;",
77
+ " }",
78
+ " aplicar();",
79
+ ' document.addEventListener("astro:after-swap", aplicar);',
80
+ "})();"
81
+ ].join("\n");
82
+
83
+ export { TEMA_ATRIBUTO, TEMA_CLAVE, TEMA_EVENTO, alternarTema, aplicarTema, escucharTema, scriptTema, temaActual, temaGuardado, temaPreferido };
@@ -0,0 +1,7 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __export = (target, all) => {
3
+ for (var name in all)
4
+ __defProp(target, name, { get: all[name], enumerable: true });
5
+ };
6
+
7
+ export { __export };
@@ -0,0 +1,27 @@
1
+ import { spacing, control, radius, typeScale } from './chunk-TSPJOM6K.js';
2
+ import { clsx } from 'clsx';
3
+ import { extendTailwindMerge } from 'tailwind-merge';
4
+
5
+ var kebab = (nombre) => nombre.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);
6
+ var escalas = Object.keys(typeScale);
7
+ var radios = Object.keys(radius);
8
+ var espacios = Object.keys(spacing).map(kebab);
9
+ var controles = Object.keys(control).map((nombre) => `control-${kebab(nombre)}`);
10
+ var twMerge = extendTailwindMerge({
11
+ extend: {
12
+ classGroups: {
13
+ "font-size": [{ text: escalas }],
14
+ rounded: [{ rounded: radios }],
15
+ p: [{ p: espacios }],
16
+ px: [{ px: [...espacios, ...controles] }],
17
+ py: [{ py: espacios }],
18
+ gap: [{ gap: espacios }],
19
+ size: [{ size: controles }]
20
+ }
21
+ }
22
+ });
23
+ function cn(...inputs) {
24
+ return twMerge(clsx(inputs));
25
+ }
26
+
27
+ export { cn };
@@ -1,29 +1,8 @@
1
1
  import { aletas, RUTA_ASSETS, poses, caras } from './chunk-E3OMP2DL.js';
2
- import { control, spacing, radius, typeScale, naming } from './chunk-DHF63QNM.js';
3
- import { clsx } from 'clsx';
4
- import { extendTailwindMerge } from 'tailwind-merge';
2
+ import { cn } from './chunk-NHS7ETKJ.js';
3
+ import { naming } from './chunk-TSPJOM6K.js';
5
4
  import { jsx, jsxs } from 'react/jsx-runtime';
6
5
 
7
- var escalas = Object.keys(typeScale);
8
- var radios = Object.keys(radius);
9
- var espacios = Object.keys(spacing);
10
- var controles = Object.keys(control).map((nombre) => `control-${nombre}`);
11
- var twMerge = extendTailwindMerge({
12
- extend: {
13
- classGroups: {
14
- "font-size": [{ text: escalas }],
15
- rounded: [{ rounded: radios }],
16
- p: [{ p: espacios }],
17
- px: [{ px: [...espacios, ...controles] }],
18
- py: [{ py: espacios }],
19
- gap: [{ gap: espacios }],
20
- size: [{ size: controles }]
21
- }
22
- }
23
- });
24
- function cn(...inputs) {
25
- return twMerge(clsx(inputs));
26
- }
27
6
  function Isotipo({
28
7
  sobre = "oscuro",
29
8
  basePath = RUTA_ASSETS,
@@ -51,7 +30,7 @@ function Logo({
51
30
  className,
52
31
  ...props
53
32
  }) {
54
- return /* @__PURE__ */ jsxs("span", { className: cn("gap-xs inline-flex items-center", className), ...props, children: [
33
+ return /* @__PURE__ */ jsxs("span", { className: cn("gap-step-xs inline-flex items-center", className), ...props, children: [
55
34
  /* @__PURE__ */ jsx(
56
35
  Isotipo,
57
36
  {
@@ -99,4 +78,4 @@ function CaraDeMascota({
99
78
  );
100
79
  }
101
80
 
102
- export { CaraDeMascota, Isotipo, Logo, Mascota, cn };
81
+ export { CaraDeMascota, Isotipo, Logo, Mascota };
@@ -1,9 +1,3 @@
1
- var __defProp = Object.defineProperty;
2
- var __export = (target, all) => {
3
- for (var name in all)
4
- __defProp(target, name, { get: all[name], enumerable: true });
5
- };
6
-
7
1
  // src/tokens/tokens.ts
8
2
  var dark = {
9
3
  background: "#091319",
@@ -162,11 +156,11 @@ var control = {
162
156
  icon: 42
163
157
  };
164
158
  var spacing = {
165
- xs: 8,
166
- sm: 12,
167
- md: 16,
168
- lg: 26,
169
- xl: 40,
159
+ stepXs: 8,
160
+ stepSm: 12,
161
+ stepMd: 16,
162
+ stepLg: 26,
163
+ stepXl: 40,
170
164
  section: 96
171
165
  };
172
166
  var size = {
@@ -191,6 +185,10 @@ var sintaxis = {
191
185
  /** `markup.deleted`, `invalid`. */
192
186
  invalido: dark.error
193
187
  };
188
+ var series = {
189
+ dark: [dark.accent, dark.warm, brand.body, dark.textMuted],
190
+ light: [light.accent, light.warm, brand.body, light.textMuted]
191
+ };
194
192
  var profundo = "#0D2129";
195
193
  var gradient = {
196
194
  dark: {
@@ -228,4 +226,4 @@ var naming = {
228
226
  domain: "eduardoalvarez.dev"
229
227
  };
230
228
 
231
- export { __export, brand, colors, control, dark, fonts, gradient, light, limits, motion, naming, radius, shadow, sintaxis, size, spacing, tagline, typeScale };
229
+ export { brand, colors, control, dark, fonts, gradient, light, limits, motion, naming, radius, series, shadow, sintaxis, size, spacing, tagline, typeScale };
@@ -0,0 +1,81 @@
1
+ import { cn } from './chunk-NHS7ETKJ.js';
2
+ import { Slot } from '@radix-ui/react-slot';
3
+ import { cva } from 'class-variance-authority';
4
+ import { jsx } from 'react/jsx-runtime';
5
+
6
+ var ETIQUETA = {
7
+ display: "h1",
8
+ stat: "p",
9
+ h1: "h1",
10
+ h2: "h2",
11
+ h3: "h3",
12
+ body: "p",
13
+ lead: "p",
14
+ ui: "p",
15
+ label: "span",
16
+ tag: "span",
17
+ meta: "p",
18
+ chip: "span",
19
+ eyebrow: "p"
20
+ };
21
+ var texto = cva("", {
22
+ variants: {
23
+ variant: {
24
+ display: "text-display font-display",
25
+ // Métricas grandes: 46px de display. Es la única escala pensada para un
26
+ // número, y por eso el interlineado es 1.
27
+ stat: "text-stat font-display",
28
+ h1: "text-h1 font-display",
29
+ h2: "text-h2 font-display",
30
+ h3: "text-h3 font-display",
31
+ body: "text-body font-sans",
32
+ // 17px: la bajada de las páginas internas y el botón grande.
33
+ lead: "text-lead font-sans",
34
+ ui: "text-ui font-sans",
35
+ label: "text-label font-sans",
36
+ // Las dos escalas de etiqueta. `tag` es el estado (sans 12.5/500) y `chip`
37
+ // la categoría y la métrica (mono 11.5). Ninguna transforma el texto.
38
+ tag: "text-tag font-sans",
39
+ chip: "text-chip font-mono",
40
+ // Mono SIN transformar: fechas, rutas, versiones, nombres de archivo y la
41
+ // firma del footer. Es el escalón que faltaba, y por el que cada sitio de
42
+ // uso terminaba escribiendo `variant="eyebrow" className="normal-case"`.
43
+ meta: "text-meta font-mono",
44
+ // `uppercase` no cabe en un token de tamaño: text-transform no es un
45
+ // modificador de --text-*. Por eso lo pone la variante y no theme.css.
46
+ eyebrow: "text-eyebrow font-mono uppercase"
47
+ },
48
+ tone: {
49
+ primary: "text-text-primary",
50
+ secondary: "text-text-secondary",
51
+ muted: "text-text-muted",
52
+ accent: "text-accent",
53
+ warm: "text-warm",
54
+ success: "text-success",
55
+ warning: "text-warning",
56
+ error: "text-error"
57
+ }
58
+ },
59
+ defaultVariants: { variant: "body", tone: "primary" }
60
+ });
61
+ function Text({
62
+ className,
63
+ variant,
64
+ tone,
65
+ as,
66
+ asChild = false,
67
+ measure,
68
+ children,
69
+ ...props
70
+ }) {
71
+ const escala = variant ?? "body";
72
+ const limitar = measure ?? escala === "body";
73
+ const clases = cn(texto({ variant, tone }), limitar && "max-w-measure", className);
74
+ if (asChild) {
75
+ return /* @__PURE__ */ jsx(Slot, { className: clases, ...props, children });
76
+ }
77
+ const Etiqueta = as ?? ETIQUETA[escala];
78
+ return /* @__PURE__ */ jsx(Etiqueta, { className: clases, ...props, children });
79
+ }
80
+
81
+ export { Text, texto };
@@ -1,4 +1,4 @@
1
- import { naming, tagline, motion, shadow, sintaxis, gradient, size, spacing, control, radius, limits, typeScale, fonts, brand, colors } from './chunk-DHF63QNM.js';
1
+ import { naming, tagline, motion, shadow, series, sintaxis, gradient, size, spacing, control, radius, limits, typeScale, fonts, brand, colors } from './chunk-TSPJOM6K.js';
2
2
 
3
3
  // src/tokens/index.ts
4
4
  var tokens = {
@@ -13,6 +13,7 @@ var tokens = {
13
13
  size,
14
14
  gradient,
15
15
  sintaxis,
16
+ series,
16
17
  shadow,
17
18
  motion,
18
19
  tagline,
@@ -0,0 +1,19 @@
1
+ import { cn } from './chunk-NHS7ETKJ.js';
2
+ import * as LabelPrimitive from '@radix-ui/react-label';
3
+ import { jsx } from 'react/jsx-runtime';
4
+
5
+ function Label({ className, ...props }) {
6
+ return /* @__PURE__ */ jsx(
7
+ LabelPrimitive.Root,
8
+ {
9
+ className: cn(
10
+ "text-label font-sans text-text-secondary select-none",
11
+ "peer-disabled:opacity-50 group-data-[disabled]:opacity-50",
12
+ className
13
+ ),
14
+ ...props
15
+ }
16
+ );
17
+ }
18
+
19
+ export { Label };