@eduardoalvarez/arrecife 0.5.1 → 0.6.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.
Files changed (66) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/README.md +706 -470
  3. package/dist/brand/index.cjs +112 -95
  4. package/dist/brand/index.d.cts +40 -39
  5. package/dist/brand/index.d.ts +40 -39
  6. package/dist/brand/index.js +5 -4
  7. package/dist/catalog-D13txprv.d.cts +78 -0
  8. package/dist/catalog-D13txprv.d.ts +78 -0
  9. package/dist/chart/index.cjs +100 -83
  10. package/dist/chart/index.d.cts +66 -66
  11. package/dist/chart/index.d.ts +66 -66
  12. package/dist/chart/index.js +14 -12
  13. package/dist/chunk-25YNFCIF.js +141 -0
  14. package/dist/{chunk-YZ2SDOVZ.js → chunk-6O3KWB6P.js} +30 -30
  15. package/dist/chunk-CKRSQPTX.js +36 -0
  16. package/dist/{chunk-ZEOQKRQ7.js → chunk-DKCN7BAL.js} +1 -1
  17. package/dist/chunk-GCRII2KQ.js +86 -0
  18. package/dist/chunk-JMOOFZ3B.js +42 -0
  19. package/dist/chunk-O4TAH7YJ.js +276 -0
  20. package/dist/chunk-ODBFN44D.js +45 -0
  21. package/dist/{chunk-VPT32GPG.js → chunk-PMN7NR3G.js} +2 -2
  22. package/dist/chunk-XKYHTOUJ.js +27 -0
  23. package/dist/form/index.cjs +109 -92
  24. package/dist/form/index.d.cts +43 -42
  25. package/dist/form/index.d.ts +43 -42
  26. package/dist/form/index.js +25 -23
  27. package/dist/index.cjs +1047 -914
  28. package/dist/index.d.cts +769 -777
  29. package/dist/index.d.ts +769 -777
  30. package/dist/index.js +608 -660
  31. package/dist/{label-DuTvJGxD.d.ts → label-MgHFKnFy.d.cts} +3 -3
  32. package/dist/{label-DuTvJGxD.d.cts → label-MgHFKnFy.d.ts} +3 -3
  33. package/dist/og/index.cjs +130 -130
  34. package/dist/og/index.d.cts +93 -89
  35. package/dist/og/index.d.ts +93 -89
  36. package/dist/og/index.js +106 -106
  37. package/dist/shiki/index.cjs +28 -30
  38. package/dist/shiki/index.d.cts +4 -4
  39. package/dist/shiki/index.d.ts +4 -4
  40. package/dist/shiki/index.js +12 -12
  41. package/dist/theme/index.cjs +97 -0
  42. package/dist/theme/index.d.cts +144 -0
  43. package/dist/theme/index.d.ts +144 -0
  44. package/dist/theme/index.js +2 -0
  45. package/dist/tokens/index.cjs +133 -86
  46. package/dist/tokens/index.d.cts +246 -161
  47. package/dist/tokens/index.d.ts +246 -161
  48. package/dist/tokens/index.js +2 -2
  49. package/dist/tokens/theme.css +133 -98
  50. package/dist/variants/index.cjs +192 -0
  51. package/dist/variants/index.d.cts +192 -0
  52. package/dist/variants/index.d.ts +192 -0
  53. package/dist/variants/index.js +3 -0
  54. package/llms.txt +810 -744
  55. package/package.json +20 -11
  56. package/dist/catalogo-Du5ID-Hi.d.cts +0 -77
  57. package/dist/catalogo-Du5ID-Hi.d.ts +0 -77
  58. package/dist/chunk-E3OMP2DL.js +0 -36
  59. package/dist/chunk-KPZNNMV5.js +0 -83
  60. package/dist/chunk-NHS7ETKJ.js +0 -27
  61. package/dist/chunk-TSPJOM6K.js +0 -229
  62. package/dist/chunk-UOWIDFCB.js +0 -81
  63. package/dist/tema/index.cjs +0 -94
  64. package/dist/tema/index.d.cts +0 -110
  65. package/dist/tema/index.d.ts +0 -110
  66. package/dist/tema/index.js +0 -2
@@ -1,3 +1,4 @@
1
+ 'use client';
1
2
  'use strict';
2
3
 
3
4
  var react = require('react');
@@ -32,56 +33,56 @@ var LabelPrimitive__namespace = /*#__PURE__*/_interopNamespace(LabelPrimitive);
32
33
  // src/form/index.tsx
33
34
  var typeScale = {
34
35
  display: { family: "display", size: 76, lineHeight: 0.96, weight: 800, tracking: "-0.035em" },
35
- /** Métricas grandes. Números, no prosa: interlineado 1 y sin descendentes. */
36
+ /** Large metrics. Numbers, not prose: line height 1 and no descenders. */
36
37
  stat: { family: "display", size: 46, lineHeight: 1, weight: 800, tracking: "-0.035em" },
37
38
  h1: { family: "display", size: 44, lineHeight: 1.05, weight: 700, tracking: "-0.03em" },
38
39
  h2: { family: "display", size: 30, lineHeight: 1.1, weight: 600, tracking: "-0.02em" },
39
40
  h3: { family: "display", size: 25, lineHeight: 1.15, weight: 600, tracking: "-0.02em" },
40
41
  body: { family: "sans", size: 18, lineHeight: 1.75, weight: 400 },
41
42
  /**
42
- * 17px. El botón grande y la bajada de las páginas internas.
43
+ * 17px. The large button, and the deck on interior pages.
43
44
  *
44
- * Entra como escalón propio porque el documento lo usa DOS veces y en piezas
45
- * distintas: «lg 15px 30px r12» con texto de 17, y «h1 44/700 · bajada 17px ·
46
- * párrafo de contexto 15px». Un solo uso no habría justificado partir la
47
- * distancia entre `ui` (15) y `body` (18); dos sí.
45
+ * It earns its own step because the identity document uses it TWICE, in two
46
+ * different pieces: «lg 15/30 r12» with 17px text, and «h1 44/700 · deck 17px
47
+ * · context paragraph 15px». One use would not have justified splitting the
48
+ * gap between `ui` (15) and `body` (18); two did.
48
49
  */
49
50
  lead: { family: "sans", size: 17, lineHeight: 1.5, weight: 400 },
50
51
  ui: { family: "sans", size: 15, lineHeight: 1.6, weight: 400 },
51
52
  label: { family: "sans", size: 13, lineHeight: 1.5, weight: 500 },
52
53
  /**
53
- * La escala de las etiquetas de estado: sans 12.5/500, cuadrada.
54
+ * The status-badge scale: sans 12.5/500, squared off.
54
55
  *
55
- * Es medio píxel por debajo de `label`, y esta vez el medio píxel sí importa:
56
- * una etiqueta de estado va dentro de una tabla o al lado de un título, y a 13
57
- * competía con el texto que acompaña. El documento la da en 12.5 y se ve.
56
+ * That is half a pixel below `label`, and this time the half pixel matters: a
57
+ * status badge sits inside a table or next to a title, and at 13 it competed
58
+ * with the text it accompanies. The document specifies 12.5 and it shows.
58
59
  */
59
60
  tag: { family: "sans", size: 12.5, lineHeight: 1.4, weight: 500 },
60
61
  /**
61
- * La escala de categoría y métrica: mono 11.5.
62
+ * The category and metric scale: mono 11.5.
62
63
  *
63
- * Rompe el suelo de `limits.minScreenPx`, y es a propósito. Ese suelo protege
64
- * al TEXTO —lo que se lee en una frase—, y una píldora de una palabra no es
65
- * texto corrido: es una marca. El contraste sigue medido y pasa AA (plancton
66
- * 5.57:1 sobre abismo), que es la parte que no se negocia.
64
+ * It breaks the floor set by `limits.minScreenPx`, deliberately. That floor
65
+ * protects TEXT — what you read in a sentence — and a one-word pill is not
66
+ * running text: it is a mark. Contrast is still measured and still passes AA
67
+ * (plankton 5.57:1 over abyss), which is the part that is not negotiable.
67
68
  *
68
- * A 13 las tres familias de etiqueta salían del tamaño de un botón pequeño y
69
- * pesaban más que el título que acompañan. Ver `docs/decisiones.md`.
69
+ * At 13 the three badge families grew past the size of a small button and
70
+ * outweighed the title they accompany. See `docs/decisions.md`.
70
71
  */
71
72
  chip: { family: "mono", size: 11.5, lineHeight: 1.4, weight: 400 },
72
73
  /**
73
- * Mono SIN transformar: fechas, rutas, versiones, nombres de archivo, la firma
74
- * del footer y las métricas de etiqueta. Es la mayoría del mono del sistema.
74
+ * Mono with NO transform: dates, paths, versions, file names, the footer
75
+ * signature and metric labels. It is most of the mono in the system.
75
76
  *
76
- * Existe porque `eyebrow` lleva `uppercase` de fábrica y no es una preferencia
77
- * que se pueda apagar: es la escala del eyebrow. Un `18 ago 2026` en versalitas
78
- * o un `pose-laptop-coffee.png` en mayúsculas están mal, y sin este escalón la
79
- * única salida era un `normal-case` en cada sitio de uso.
77
+ * It exists because `eyebrow` ships `uppercase` and that is not a preference
78
+ * you can switch off: it IS the eyebrow scale. An `18 Aug 2026` in small caps
79
+ * or a `pose-laptop-coffee.png` in all caps are wrong, and without this step
80
+ * the only way out was a `normal-case` at every call site.
80
81
  *
81
- * El documento dice 12.5. Son 13 por la misma razón por la que `textMuted` se
82
- * corrigió: `limits.minScreenPx` es 13 y plancton «nunca bajo 13px». Esta
83
- * escala es justo donde se escriben las metas en muted, así que ponerla en
84
- * 12.5 habría dejado ilegible su uso más común por medio píxel.
82
+ * The document says 12.5. This is 13 for the same reason `textMuted` was
83
+ * corrected: `limits.minScreenPx` is 13 and plankton is «never under 13px».
84
+ * This scale is exactly where muted metadata gets written, so putting it at
85
+ * 12.5 would have made its most common use illegible by half a pixel.
85
86
  */
86
87
  meta: { family: "mono", size: 13, lineHeight: 1.6, weight: 400 },
87
88
  eyebrow: { family: "mono", size: 12, tracking: "0.12em", transform: "uppercase" }
@@ -97,8 +98,24 @@ var control = {
97
98
  sm: 14,
98
99
  md: 22,
99
100
  lg: 30,
100
- /** Botón de icono: cuadrado, sin texto. */
101
- icon: 42
101
+ /** Icon button: square, no text. */
102
+ icon: 42,
103
+ /**
104
+ * The dense icon button, 32×32.
105
+ *
106
+ * 42 is the right measure for a control you hit with a thumb, and the four
107
+ * reading sites are where that fits. `cursos` is the odd one out: it is the
108
+ * only admin app of the set, with three actions per table row, and at 42 the
109
+ * row grows with them — the original used 24 and 28.
110
+ *
111
+ * It is 32 and not 28 because 32 is `sm`'s height. A dense icon button lines
112
+ * up with a small text button, so a toolbar mixing the two stays on one
113
+ * baseline; 28 would have been a fifth height that matches nothing.
114
+ *
115
+ * It does not replace `icon`. A page's primary action stays at 42; this is for
116
+ * a row of a table. See `docs/decisions.md` § 22.
117
+ */
118
+ iconSm: 32
102
119
  };
103
120
  var spacing = {
104
121
  stepXs: 8,
@@ -110,21 +127,21 @@ var spacing = {
110
127
  };
111
128
 
112
129
  // src/lib/cn.ts
113
- var kebab = (nombre) => nombre.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);
114
- var escalas = Object.keys(typeScale);
115
- var radios = Object.keys(radius);
116
- var espacios = Object.keys(spacing).map(kebab);
117
- var controles = Object.keys(control).map((nombre) => `control-${kebab(nombre)}`);
130
+ var kebab = (name) => name.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);
131
+ var scales = Object.keys(typeScale);
132
+ var radii = Object.keys(radius);
133
+ var namespaces = Object.keys(spacing).map(kebab);
134
+ var controls = Object.keys(control).map((name) => `control-${kebab(name)}`);
118
135
  var twMerge = tailwindMerge.extendTailwindMerge({
119
136
  extend: {
120
137
  classGroups: {
121
- "font-size": [{ text: escalas }],
122
- rounded: [{ rounded: radios }],
123
- p: [{ p: espacios }],
124
- px: [{ px: [...espacios, ...controles] }],
125
- py: [{ py: espacios }],
126
- gap: [{ gap: espacios }],
127
- size: [{ size: controles }]
138
+ "font-size": [{ text: scales }],
139
+ rounded: [{ rounded: radii }],
140
+ p: [{ p: namespaces }],
141
+ px: [{ px: [...namespaces, ...controls] }],
142
+ py: [{ py: namespaces }],
143
+ gap: [{ gap: namespaces }],
144
+ size: [{ size: controls }]
128
145
  }
129
146
  }
130
147
  });
@@ -144,46 +161,31 @@ function Label({ className, ...props }) {
144
161
  }
145
162
  );
146
163
  }
147
- var ETIQUETA = {
148
- display: "h1",
149
- stat: "p",
150
- h1: "h1",
151
- h2: "h2",
152
- h3: "h3",
153
- body: "p",
154
- lead: "p",
155
- ui: "p",
156
- label: "span",
157
- tag: "span",
158
- meta: "p",
159
- chip: "span",
160
- eyebrow: "p"
161
- };
162
- var texto = classVarianceAuthority.cva("", {
164
+ var text = classVarianceAuthority.cva("", {
163
165
  variants: {
164
166
  variant: {
165
167
  display: "text-display font-display",
166
- // Métricas grandes: 46px de display. Es la única escala pensada para un
167
- // número, y por eso el interlineado es 1.
168
+ // Large metrics: 46px of display. It is the only scale designed for a
169
+ // number, which is why its line height is 1.
168
170
  stat: "text-stat font-display",
169
171
  h1: "text-h1 font-display",
170
172
  h2: "text-h2 font-display",
171
173
  h3: "text-h3 font-display",
172
174
  body: "text-body font-sans",
173
- // 17px: la bajada de las páginas internas y el botón grande.
175
+ // 17px: the deck on interior pages and the large button.
174
176
  lead: "text-lead font-sans",
175
177
  ui: "text-ui font-sans",
176
178
  label: "text-label font-sans",
177
- // Las dos escalas de etiqueta. `tag` es el estado (sans 12.5/500) y `chip`
178
- // la categoría y la métrica (mono 11.5). Ninguna transforma el texto.
179
+ // The two badge scales. `tag` is status (sans 12.5/500) and `chip` is
180
+ // category and metric (mono 11.5). Neither transforms the text.
179
181
  tag: "text-tag font-sans",
180
182
  chip: "text-chip font-mono",
181
- // Mono SIN transformar: fechas, rutas, versiones, nombres de archivo y la
182
- // firma del footer. Es el escalón que faltaba, y por el que cada sitio de
183
- // uso terminaba escribiendo `variant="eyebrow" className="normal-case"`.
183
+ // Mono with NO transform: dates, paths, versions, file names and the
184
+ // footer signature. It is the step that was missing, and the reason every
185
+ // call site ended up writing `variant="eyebrow" className="normal-case"`.
184
186
  meta: "text-meta font-mono",
185
- // `uppercase` no cabe en un token de tamaño: text-transform no es un
186
- // modificador de --text-*. Por eso lo pone la variante y no theme.css.
187
+ // `uppercase` does not fit in a size token: text-transform is not a
188
+ // modifier of --text-*. Which is why the variant sets it, not theme.css.
187
189
  eyebrow: "text-eyebrow font-mono uppercase"
188
190
  },
189
191
  tone: {
@@ -199,6 +201,21 @@ var texto = classVarianceAuthority.cva("", {
199
201
  },
200
202
  defaultVariants: { variant: "body", tone: "primary" }
201
203
  });
204
+ var LABEL = {
205
+ display: "h1",
206
+ stat: "p",
207
+ h1: "h1",
208
+ h2: "h2",
209
+ h3: "h3",
210
+ body: "p",
211
+ lead: "p",
212
+ ui: "p",
213
+ label: "span",
214
+ tag: "span",
215
+ meta: "p",
216
+ chip: "span",
217
+ eyebrow: "p"
218
+ };
202
219
  function Text({
203
220
  className,
204
221
  variant,
@@ -209,34 +226,34 @@ function Text({
209
226
  children,
210
227
  ...props
211
228
  }) {
212
- const escala = variant ?? "body";
213
- const limitar = measure ?? escala === "body";
214
- const clases = cn(texto({ variant, tone }), limitar && "max-w-measure", className);
229
+ const scale = variant ?? "body";
230
+ const clamp = measure ?? scale === "body";
231
+ const classes = cn(text({ variant, tone }), clamp && "max-w-measure", className);
215
232
  if (asChild) {
216
- return /* @__PURE__ */ jsxRuntime.jsx(reactSlot.Slot, { className: clases, ...props, children });
233
+ return /* @__PURE__ */ jsxRuntime.jsx(reactSlot.Slot, { className: classes, ...props, children });
217
234
  }
218
- const Etiqueta = as ?? ETIQUETA[escala];
219
- return /* @__PURE__ */ jsxRuntime.jsx(Etiqueta, { className: clases, ...props, children });
235
+ const Label2 = as ?? LABEL[scale];
236
+ return /* @__PURE__ */ jsxRuntime.jsx(Label2, { className: classes, ...props, children });
220
237
  }
221
238
  var Form = reactHookForm.FormProvider;
222
- var Campo = react.createContext(null);
239
+ var Field = react.createContext(null);
223
240
  var Item = react.createContext(null);
224
241
  function FormField(props) {
225
- return /* @__PURE__ */ jsxRuntime.jsx(Campo.Provider, { value: { name: props.name }, children: /* @__PURE__ */ jsxRuntime.jsx(reactHookForm.Controller, { ...props }) });
242
+ return /* @__PURE__ */ jsxRuntime.jsx(Field.Provider, { value: { name: props.name }, children: /* @__PURE__ */ jsxRuntime.jsx(reactHookForm.Controller, { ...props }) });
226
243
  }
227
244
  function useFormField() {
228
- const campo = react.useContext(Campo);
245
+ const field = react.useContext(Field);
229
246
  const item = react.useContext(Item);
230
247
  const { getFieldState } = reactHookForm.useFormContext();
231
- const estado = reactHookForm.useFormState({ name: campo?.name ?? "" });
232
- if (!campo) throw new Error("useFormField se usa dentro de un <FormField>.");
233
- if (!item) throw new Error("useFormField se usa dentro de un <FormItem>.");
248
+ const state = reactHookForm.useFormState({ name: field?.name ?? "" });
249
+ if (!field) throw new Error("useFormField must be used inside a <FormField>.");
250
+ if (!item) throw new Error("useFormField must be used inside a <FormItem>.");
234
251
  return {
235
- name: campo.name,
252
+ name: field.name,
236
253
  id: item.id,
237
- idDescripcion: `${item.id}-descripcion`,
238
- idMensaje: `${item.id}-mensaje`,
239
- ...getFieldState(campo.name, estado)
254
+ descriptionId: `${item.id}-descripcion`,
255
+ messageId: `${item.id}-mensaje`,
256
+ ...getFieldState(field.name, state)
240
257
  };
241
258
  }
242
259
  function FormItem({ className, ...props }) {
@@ -248,45 +265,45 @@ function FormLabel({ className, ...props }) {
248
265
  return /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: id, className, ...props });
249
266
  }
250
267
  function FormControl({ ...props }) {
251
- const { error, id, idDescripcion, idMensaje } = useFormField();
268
+ const { error, id, descriptionId, messageId } = useFormField();
252
269
  return /* @__PURE__ */ jsxRuntime.jsx(
253
270
  reactSlot.Slot,
254
271
  {
255
272
  id,
256
- "aria-describedby": error ? `${idDescripcion} ${idMensaje}` : idDescripcion,
273
+ "aria-describedby": error ? `${descriptionId} ${messageId}` : descriptionId,
257
274
  "aria-invalid": error ? true : void 0,
258
275
  ...props
259
276
  }
260
277
  );
261
278
  }
262
279
  function FormDescription({ className, ...props }) {
263
- const { idDescripcion } = useFormField();
280
+ const { descriptionId } = useFormField();
264
281
  return /* @__PURE__ */ jsxRuntime.jsx(
265
282
  Text,
266
283
  {
267
284
  as: "p",
268
285
  variant: "label",
269
286
  tone: "muted",
270
- id: idDescripcion,
287
+ id: descriptionId,
271
288
  className: cn("font-normal", className),
272
289
  ...props
273
290
  }
274
291
  );
275
292
  }
276
293
  function FormMessage({ className, children, ...props }) {
277
- const { error, idMensaje } = useFormField();
278
- const cuerpo = error?.message ? String(error.message) : children;
279
- if (!cuerpo) return null;
294
+ const { error, messageId } = useFormField();
295
+ const body = error?.message ? String(error.message) : children;
296
+ if (!body) return null;
280
297
  return /* @__PURE__ */ jsxRuntime.jsx(
281
298
  Text,
282
299
  {
283
300
  as: "p",
284
301
  variant: "label",
285
302
  tone: "error",
286
- id: idMensaje,
303
+ id: messageId,
287
304
  className,
288
305
  ...props,
289
- children: cuerpo
306
+ children: body
290
307
  }
291
308
  );
292
309
  }
@@ -3,44 +3,45 @@ import { ComponentPropsWithoutRef } from 'react';
3
3
  import * as react_hook_form from 'react-hook-form';
4
4
  import { FieldValues, FieldPath, ControllerProps } from 'react-hook-form';
5
5
  import { Slot } from '@radix-ui/react-slot';
6
- import { L as Label } from '../label-DuTvJGxD.cjs';
6
+ import { L as Label } from '../label-MgHFKnFy.cjs';
7
7
  import '@radix-ui/react-label';
8
8
 
9
9
  /**
10
- * La capa que ata los controles a un formulario con validación y mensajes.
10
+ * The layer that ties the controls to a form with validation and messages.
11
11
  *
12
- * La librería ya traía `Input`, `Label`, `Checkbox`, `RadioGroup`, `Select` y
13
- * `Textarea`, y ninguno sabía nada del otro: el `htmlFor`, el `aria-describedby`
14
- * del mensaje de error y el `aria-invalid` había que cablearlos a mano en cada
15
- * campo de cada proyecto. Eso se olvida, y cuando se olvida el fallo es que un
16
- * lector de pantalla no anuncia por qué el campo está en rojo.
12
+ * The library already had `Input`, `Label`, `Checkbox`, `RadioGroup`, `Select`
13
+ * and `Textarea`, and none of them knew anything about the others: the
14
+ * `htmlFor`, the error message's `aria-describedby` and the `aria-invalid` had
15
+ * to be wired by hand on every field of every project. That gets forgotten, and
16
+ * when it does the failure is that a screen reader never announces why the field
17
+ * is red.
17
18
  *
18
- * Se publica en `@eduardoalvarez/arrecife/form`, NO en la raíz, y eso es
19
- * deliberado. React Hook Form es una dependencia de pares opcional: solo uno de
20
- * los cinco proyectos la usa, y si esto colgara del índice principal, los otros
21
- * cuatro tendrían que instalarla para que su bundler resolviera un import que
22
- * nunca ejecutan. Es la misma razón por la que `./og` y `./shiki` viven aparte,
23
- * mirada desde el otro lado: allí se saca React del camino, aquí se saca RHF.
19
+ * It is published at `@eduardoalvarez/arrecife/form`, NOT at the root, and that
20
+ * is deliberate. React Hook Form is an optional peer dependency: only one of the
21
+ * five projects uses it, and if this hung off the main index the other four
22
+ * would have to install it just so their bundler could resolve an import they
23
+ * never execute. It is the same reason `./og` and `./shiki` live apart, seen
24
+ * from the other side: there React is kept out of the way, here RHF is.
24
25
  *
25
- * La forma es la de shadcn —`FormField` sobre `Controller`, contexto de campo y
26
- * contexto de item— porque el proyecto que la consume ya está escrito contra
27
- * ella y reinventarla solo le costaría una migración. Lo que cambia es el
28
- * vocabulario visual: los ids, la escala y el tono salen del sistema.
26
+ * The shape is shadcn's — `FormField` on `Controller`, field context and item
27
+ * context — because the project consuming it is already written against it and
28
+ * reinventing it would only cost them a migration. What changes is the visual
29
+ * vocabulary: the ids, the scale and the tone come from the system.
29
30
  */
30
31
  declare const Form: <TFieldValues extends FieldValues, TContext = any, TTransformedValues = TFieldValues>({ children, watch, getValues, getErrors, getFieldState, setError, clearErrors, setValue, setValues, trigger, formState, resetField, reset, resetDefaultValues, handleSubmit, unregister, control, register, setFocus, subscribe, }: react_hook_form.FormProviderProps<TFieldValues, TContext, TTransformedValues>) => React.JSX.Element;
31
32
  /**
32
- * Un campo controlado. Envuelve el `Controller` de RHF y además publica el
33
- * nombre en contexto, que es de donde lo leen la etiqueta y el mensaje sin que
34
- * haya que repetirlo tres veces.
33
+ * A controlled field. It wraps RHF's `Controller` and also publishes the name
34
+ * into context, which is where the label and the message read it from without
35
+ * having to repeat it three times.
35
36
  */
36
37
  declare function FormField<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>(props: ControllerProps<TFieldValues, TName>): react.JSX.Element;
37
38
  /**
38
- * Lo que necesita cualquier pieza del campo: el nombre, los tres ids y el estado
39
- * de validación.
39
+ * What any piece of the field needs: the name, the three ids and the validation
40
+ * state.
40
41
  *
41
- * Tira si se usa fuera de un `FormField` o de un `FormItem`, con el mensaje que
42
- * dice cuál de los dos falta. Devolver algo a medias sería peor: el campo se
43
- * renderizaría sin `aria-describedby` y nada avisaría.
42
+ * It throws if used outside a `FormField` or a `FormItem`, with a message saying
43
+ * which of the two is missing. Returning something half-formed would be worse:
44
+ * the field would render with no `aria-describedby` and nothing would warn.
44
45
  */
45
46
  declare function useFormField(): {
46
47
  invalid: boolean;
@@ -50,36 +51,36 @@ declare function useFormField(): {
50
51
  error?: react_hook_form.FieldError;
51
52
  name: string;
52
53
  id: string;
53
- idDescripcion: string;
54
- idMensaje: string;
54
+ descriptionId: string;
55
+ messageId: string;
55
56
  };
56
- /** La caja del campo: etiqueta, control, ayuda y mensaje, en columna. */
57
+ /** The field's box: label, control, help and message, in a column. */
57
58
  declare function FormItem({ className, ...props }: ComponentPropsWithoutRef<'div'>): react.JSX.Element;
58
59
  /**
59
- * La etiqueta NO se tiñe de rojo cuando el campo falla.
60
+ * The label is NOT tinted red when the field fails.
60
61
  *
61
- * El sistema deja el color semántico en el borde y en el glifo, y el texto en un
62
- * token de texto: el borde del control ya está en `error` y el mensaje de abajo
63
- * también, así que teñir además la etiqueta son tres rojos para un solo fallo.
62
+ * The system keeps the semantic color on the border and on the glyph, and the
63
+ * text on a text token: the control's border is already in `error` and so is the
64
+ * message below it, so tinting the label as well is three reds for one failure.
64
65
  */
65
66
  declare function FormLabel({ className, ...props }: ComponentPropsWithoutRef<typeof Label>): react.JSX.Element;
66
67
  /**
67
- * Envuelve al control y le cablea los atributos: el `id` que la etiqueta apunta,
68
- * el `aria-describedby` con la ayuda y el mensaje, y el `aria-invalid`.
68
+ * Wraps the control and wires its attributes: the `id` the label points at, the
69
+ * `aria-describedby` with the help and the message, and the `aria-invalid`.
69
70
  *
70
- * Es un `Slot`, así que el hijo puede ser cualquiera de los controles del
71
- * sistema —`Input`, `Textarea`, `SelectTrigger`— sin que esto sepa cuál.
71
+ * It is a `Slot`, so the child can be any of the system's controls — `Input`,
72
+ * `Textarea`, `SelectTrigger` — without this knowing which.
72
73
  */
73
74
  declare function FormControl({ ...props }: ComponentPropsWithoutRef<typeof Slot>): react.JSX.Element;
74
- /** La ayuda del campo. Se anuncia siempre, haya error o no. */
75
+ /** The field's help text. It is always announced, error or not. */
75
76
  declare function FormDescription({ className, ...props }: ComponentPropsWithoutRef<'p'>): react.JSX.Element;
76
77
  /**
77
- * El mensaje de validación. Sin error no renderiza nada: un hueco reservado
78
- * para el fallo desplaza el resto del formulario cada vez que aparece.
78
+ * The validation message. With no error it renders nothing: a gap reserved for
79
+ * the failure shifts the rest of the form every time it appears.
79
80
  *
80
- * Toma el texto del error de RHF; `children` sirve para un mensaje que no venga
81
- * del esquema —el 409 que devuelve el servidor y que ningún validador de
82
- * cliente puede anticipar—.
81
+ * It takes its text from RHF's error; `children` is for a message that does not
82
+ * come from the schema — the 409 the server returns and that no client-side
83
+ * validator can anticipate.
83
84
  */
84
85
  declare function FormMessage({ className, children, ...props }: ComponentPropsWithoutRef<'p'>): react.JSX.Element | null;
85
86
 
@@ -3,44 +3,45 @@ import { ComponentPropsWithoutRef } from 'react';
3
3
  import * as react_hook_form from 'react-hook-form';
4
4
  import { FieldValues, FieldPath, ControllerProps } from 'react-hook-form';
5
5
  import { Slot } from '@radix-ui/react-slot';
6
- import { L as Label } from '../label-DuTvJGxD.js';
6
+ import { L as Label } from '../label-MgHFKnFy.js';
7
7
  import '@radix-ui/react-label';
8
8
 
9
9
  /**
10
- * La capa que ata los controles a un formulario con validación y mensajes.
10
+ * The layer that ties the controls to a form with validation and messages.
11
11
  *
12
- * La librería ya traía `Input`, `Label`, `Checkbox`, `RadioGroup`, `Select` y
13
- * `Textarea`, y ninguno sabía nada del otro: el `htmlFor`, el `aria-describedby`
14
- * del mensaje de error y el `aria-invalid` había que cablearlos a mano en cada
15
- * campo de cada proyecto. Eso se olvida, y cuando se olvida el fallo es que un
16
- * lector de pantalla no anuncia por qué el campo está en rojo.
12
+ * The library already had `Input`, `Label`, `Checkbox`, `RadioGroup`, `Select`
13
+ * and `Textarea`, and none of them knew anything about the others: the
14
+ * `htmlFor`, the error message's `aria-describedby` and the `aria-invalid` had
15
+ * to be wired by hand on every field of every project. That gets forgotten, and
16
+ * when it does the failure is that a screen reader never announces why the field
17
+ * is red.
17
18
  *
18
- * Se publica en `@eduardoalvarez/arrecife/form`, NO en la raíz, y eso es
19
- * deliberado. React Hook Form es una dependencia de pares opcional: solo uno de
20
- * los cinco proyectos la usa, y si esto colgara del índice principal, los otros
21
- * cuatro tendrían que instalarla para que su bundler resolviera un import que
22
- * nunca ejecutan. Es la misma razón por la que `./og` y `./shiki` viven aparte,
23
- * mirada desde el otro lado: allí se saca React del camino, aquí se saca RHF.
19
+ * It is published at `@eduardoalvarez/arrecife/form`, NOT at the root, and that
20
+ * is deliberate. React Hook Form is an optional peer dependency: only one of the
21
+ * five projects uses it, and if this hung off the main index the other four
22
+ * would have to install it just so their bundler could resolve an import they
23
+ * never execute. It is the same reason `./og` and `./shiki` live apart, seen
24
+ * from the other side: there React is kept out of the way, here RHF is.
24
25
  *
25
- * La forma es la de shadcn —`FormField` sobre `Controller`, contexto de campo y
26
- * contexto de item— porque el proyecto que la consume ya está escrito contra
27
- * ella y reinventarla solo le costaría una migración. Lo que cambia es el
28
- * vocabulario visual: los ids, la escala y el tono salen del sistema.
26
+ * The shape is shadcn's — `FormField` on `Controller`, field context and item
27
+ * context — because the project consuming it is already written against it and
28
+ * reinventing it would only cost them a migration. What changes is the visual
29
+ * vocabulary: the ids, the scale and the tone come from the system.
29
30
  */
30
31
  declare const Form: <TFieldValues extends FieldValues, TContext = any, TTransformedValues = TFieldValues>({ children, watch, getValues, getErrors, getFieldState, setError, clearErrors, setValue, setValues, trigger, formState, resetField, reset, resetDefaultValues, handleSubmit, unregister, control, register, setFocus, subscribe, }: react_hook_form.FormProviderProps<TFieldValues, TContext, TTransformedValues>) => React.JSX.Element;
31
32
  /**
32
- * Un campo controlado. Envuelve el `Controller` de RHF y además publica el
33
- * nombre en contexto, que es de donde lo leen la etiqueta y el mensaje sin que
34
- * haya que repetirlo tres veces.
33
+ * A controlled field. It wraps RHF's `Controller` and also publishes the name
34
+ * into context, which is where the label and the message read it from without
35
+ * having to repeat it three times.
35
36
  */
36
37
  declare function FormField<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>(props: ControllerProps<TFieldValues, TName>): react.JSX.Element;
37
38
  /**
38
- * Lo que necesita cualquier pieza del campo: el nombre, los tres ids y el estado
39
- * de validación.
39
+ * What any piece of the field needs: the name, the three ids and the validation
40
+ * state.
40
41
  *
41
- * Tira si se usa fuera de un `FormField` o de un `FormItem`, con el mensaje que
42
- * dice cuál de los dos falta. Devolver algo a medias sería peor: el campo se
43
- * renderizaría sin `aria-describedby` y nada avisaría.
42
+ * It throws if used outside a `FormField` or a `FormItem`, with a message saying
43
+ * which of the two is missing. Returning something half-formed would be worse:
44
+ * the field would render with no `aria-describedby` and nothing would warn.
44
45
  */
45
46
  declare function useFormField(): {
46
47
  invalid: boolean;
@@ -50,36 +51,36 @@ declare function useFormField(): {
50
51
  error?: react_hook_form.FieldError;
51
52
  name: string;
52
53
  id: string;
53
- idDescripcion: string;
54
- idMensaje: string;
54
+ descriptionId: string;
55
+ messageId: string;
55
56
  };
56
- /** La caja del campo: etiqueta, control, ayuda y mensaje, en columna. */
57
+ /** The field's box: label, control, help and message, in a column. */
57
58
  declare function FormItem({ className, ...props }: ComponentPropsWithoutRef<'div'>): react.JSX.Element;
58
59
  /**
59
- * La etiqueta NO se tiñe de rojo cuando el campo falla.
60
+ * The label is NOT tinted red when the field fails.
60
61
  *
61
- * El sistema deja el color semántico en el borde y en el glifo, y el texto en un
62
- * token de texto: el borde del control ya está en `error` y el mensaje de abajo
63
- * también, así que teñir además la etiqueta son tres rojos para un solo fallo.
62
+ * The system keeps the semantic color on the border and on the glyph, and the
63
+ * text on a text token: the control's border is already in `error` and so is the
64
+ * message below it, so tinting the label as well is three reds for one failure.
64
65
  */
65
66
  declare function FormLabel({ className, ...props }: ComponentPropsWithoutRef<typeof Label>): react.JSX.Element;
66
67
  /**
67
- * Envuelve al control y le cablea los atributos: el `id` que la etiqueta apunta,
68
- * el `aria-describedby` con la ayuda y el mensaje, y el `aria-invalid`.
68
+ * Wraps the control and wires its attributes: the `id` the label points at, the
69
+ * `aria-describedby` with the help and the message, and the `aria-invalid`.
69
70
  *
70
- * Es un `Slot`, así que el hijo puede ser cualquiera de los controles del
71
- * sistema —`Input`, `Textarea`, `SelectTrigger`— sin que esto sepa cuál.
71
+ * It is a `Slot`, so the child can be any of the system's controls — `Input`,
72
+ * `Textarea`, `SelectTrigger` — without this knowing which.
72
73
  */
73
74
  declare function FormControl({ ...props }: ComponentPropsWithoutRef<typeof Slot>): react.JSX.Element;
74
- /** La ayuda del campo. Se anuncia siempre, haya error o no. */
75
+ /** The field's help text. It is always announced, error or not. */
75
76
  declare function FormDescription({ className, ...props }: ComponentPropsWithoutRef<'p'>): react.JSX.Element;
76
77
  /**
77
- * El mensaje de validación. Sin error no renderiza nada: un hueco reservado
78
- * para el fallo desplaza el resto del formulario cada vez que aparece.
78
+ * The validation message. With no error it renders nothing: a gap reserved for
79
+ * the failure shifts the rest of the form every time it appears.
79
80
  *
80
- * Toma el texto del error de RHF; `children` sirve para un mensaje que no venga
81
- * del esquema —el 409 que devuelve el servidor y que ningún validador de
82
- * cliente puede anticipar—.
81
+ * It takes its text from RHF's error; `children` is for a message that does not
82
+ * come from the schema — the 409 the server returns and that no client-side
83
+ * validator can anticipate.
83
84
  */
84
85
  declare function FormMessage({ className, children, ...props }: ComponentPropsWithoutRef<'p'>): react.JSX.Element | null;
85
86