@eduardoalvarez/arrecife 0.6.0 → 0.8.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 (56) hide show
  1. package/CHANGELOG.md +112 -0
  2. package/README.md +288 -49
  3. package/dist/brand/index.cjs +2 -2
  4. package/dist/brand/index.js +3 -3
  5. package/dist/chart/index.cjs +129 -2
  6. package/dist/chart/index.d.cts +114 -4
  7. package/dist/chart/index.d.ts +114 -4
  8. package/dist/chart/index.js +129 -5
  9. package/dist/{chunk-PMN7NR3G.js → chunk-5A5GH2PF.js} +1 -1
  10. package/dist/{chunk-DKCN7BAL.js → chunk-6IGD5REB.js} +1 -1
  11. package/dist/{chunk-XKYHTOUJ.js → chunk-FAAGZG7A.js} +1 -1
  12. package/dist/{chunk-O4TAH7YJ.js → chunk-FGFNK72B.js} +29 -5
  13. package/dist/chunk-HOADZ6GS.js +72 -0
  14. package/dist/chunk-LXRGQKMG.js +145 -0
  15. package/dist/{chunk-6O3KWB6P.js → chunk-MPZBF2TZ.js} +2 -2
  16. package/dist/{chunk-JMOOFZ3B.js → chunk-TRPBID2W.js} +1 -1
  17. package/dist/{chunk-25YNFCIF.js → chunk-XXDATT3A.js} +6 -3
  18. package/dist/doctor.mjs +248 -0
  19. package/dist/form/index.cjs +2 -2
  20. package/dist/form/index.d.cts +1 -1
  21. package/dist/form/index.d.ts +1 -1
  22. package/dist/form/index.js +4 -4
  23. package/dist/icons/index.cjs +149 -0
  24. package/dist/icons/index.d.cts +94 -0
  25. package/dist/icons/index.d.ts +94 -0
  26. package/dist/icons/index.js +28 -0
  27. package/dist/index-BbRplw_B.d.cts +58 -0
  28. package/dist/index-BbRplw_B.d.ts +58 -0
  29. package/dist/index.cjs +425 -251
  30. package/dist/index.d.cts +303 -104
  31. package/dist/index.d.ts +303 -104
  32. package/dist/index.js +283 -285
  33. package/dist/{label-MgHFKnFy.d.ts → label-DJ4HuD-R.d.cts} +3 -2
  34. package/dist/{label-MgHFKnFy.d.cts → label-DJ4HuD-R.d.ts} +3 -2
  35. package/dist/og/index.cjs +3 -2
  36. package/dist/og/index.js +1 -1
  37. package/dist/shiki/index.js +1 -1
  38. package/dist/social/data.cjs +161 -0
  39. package/dist/social/data.d.cts +161 -0
  40. package/dist/social/data.d.ts +161 -0
  41. package/dist/social/data.js +2 -0
  42. package/dist/social/index.cjs +153 -0
  43. package/dist/social/index.d.cts +2 -0
  44. package/dist/social/index.d.ts +2 -0
  45. package/dist/social/index.js +3 -0
  46. package/dist/tokens/index.cjs +29 -5
  47. package/dist/tokens/index.d.cts +37 -10
  48. package/dist/tokens/index.d.ts +37 -10
  49. package/dist/tokens/index.js +2 -2
  50. package/dist/tokens/theme.css +79 -22
  51. package/dist/variants/index.cjs +6 -3
  52. package/dist/variants/index.d.cts +6 -3
  53. package/dist/variants/index.d.ts +6 -3
  54. package/dist/variants/index.js +1 -1
  55. package/llms.txt +530 -80
  56. package/package.json +29 -2
@@ -1,6 +1,7 @@
1
1
  'use client';
2
2
  'use strict';
3
3
 
4
+ var react = require('react');
4
5
  var recharts = require('recharts');
5
6
  var clsx = require('clsx');
6
7
  var tailwindMerge = require('tailwind-merge');
@@ -45,7 +46,7 @@ var typeScale = {
45
46
  * (plankton 5.57:1 over abyss), which is the part that is not negotiable.
46
47
  *
47
48
  * At 13 the three badge families grew past the size of a small button and
48
- * outweighed the title they accompany. See `docs/decisions.md`.
49
+ * outweighed the title they accompany. See `docs/decisions/`.
49
50
  */
50
51
  chip: { family: "mono", size: 11.5, lineHeight: 1.4, weight: 400 },
51
52
  /**
@@ -91,7 +92,7 @@ var control = {
91
92
  * baseline; 28 would have been a fifth height that matches nothing.
92
93
  *
93
94
  * It does not replace `icon`. A page's primary action stays at 42; this is for
94
- * a row of a table. See `docs/decisions.md` § 22.
95
+ * a row of a table. See `docs/decisions/0.6.md` § 22.
95
96
  */
96
97
  iconSm: 32
97
98
  };
@@ -294,11 +295,137 @@ function ChartLegendContent({ payload, className }) {
294
295
  /* @__PURE__ */ jsxRuntime.jsx(Text, { as: "span", variant: "label", tone: "secondary", className: "font-normal", children: item.value })
295
296
  ] }, `${String(item.dataKey ?? item.value ?? i)}`)) });
296
297
  }
298
+ var rows = (data) => data;
299
+ var color = (series2, index) => series2.color ?? seriesColor(index);
300
+ var MARGIN = { left: 0, right: 12, top: 8, bottom: 0 };
301
+ var AXIS = { tickLine: false, axisLine: false };
302
+ var legendOf = (series2, legend) => legend ?? series2.length > 1 ? /* @__PURE__ */ jsxRuntime.jsx(ChartLegend, { content: /* @__PURE__ */ jsxRuntime.jsx(ChartLegendContent, {}) }, "legend") : null;
303
+ var tooltipOf = (formatter) => /* @__PURE__ */ jsxRuntime.jsx(
304
+ ChartTooltip,
305
+ {
306
+ cursor: false,
307
+ content: /* @__PURE__ */ jsxRuntime.jsx(ChartTooltipContent, { formatter: formatter ? (value) => formatter(value) : void 0 })
308
+ },
309
+ "tooltip"
310
+ );
311
+ function AreaChart({
312
+ data,
313
+ series: series2,
314
+ xKey,
315
+ formatter,
316
+ legend,
317
+ stacked = false,
318
+ ...container
319
+ }) {
320
+ const id = react.useId();
321
+ return /* @__PURE__ */ jsxRuntime.jsx(ChartContainer, { ...container, children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.AreaChart, { data: rows(data), margin: MARGIN, children: [
322
+ /* @__PURE__ */ jsxRuntime.jsx("defs", { children: series2.map((s, i) => /* @__PURE__ */ jsxRuntime.jsxs("linearGradient", { id: `${id}-${s.key}`, x1: "0", y1: "0", x2: "0", y2: "1", children: [
323
+ /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "5%", stopColor: color(s, i), stopOpacity: 0.5 }),
324
+ /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "95%", stopColor: color(s, i), stopOpacity: 0.05 })
325
+ ] }, s.key)) }),
326
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { vertical: false }),
327
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.XAxis, { dataKey: xKey, ...AXIS, tickMargin: 8 }),
328
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.YAxis, { ...AXIS, width: 40 }),
329
+ tooltipOf(formatter),
330
+ legendOf(series2, legend),
331
+ series2.map((s, i) => /* @__PURE__ */ jsxRuntime.jsx(
332
+ recharts.Area,
333
+ {
334
+ dataKey: s.key,
335
+ name: s.label,
336
+ type: "natural",
337
+ stroke: color(s, i),
338
+ strokeWidth: 2,
339
+ fill: `url(#${id}-${s.key})`,
340
+ isAnimationActive: false,
341
+ ...stacked ? { stackId: "stack" } : {}
342
+ },
343
+ s.key
344
+ ))
345
+ ] }) });
346
+ }
347
+ function BarChart({
348
+ data,
349
+ series: series2,
350
+ xKey,
351
+ formatter,
352
+ legend,
353
+ orientation = "vertical",
354
+ stacked = false,
355
+ ...container
356
+ }) {
357
+ const lying = orientation === "horizontal";
358
+ return /* @__PURE__ */ jsxRuntime.jsx(ChartContainer, { ...container, children: /* @__PURE__ */ jsxRuntime.jsxs(
359
+ recharts.BarChart,
360
+ {
361
+ data: rows(data),
362
+ margin: MARGIN,
363
+ ...lying ? { layout: "vertical" } : {},
364
+ children: [
365
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { vertical: lying, horizontal: !lying }),
366
+ lying ? [
367
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.YAxis, { dataKey: xKey, type: "category", ...AXIS, width: 130 }, "category"),
368
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.XAxis, { type: "number", hide: true }, "value")
369
+ ] : [
370
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.XAxis, { dataKey: xKey, ...AXIS, tickMargin: 8 }, "category"),
371
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.YAxis, { ...AXIS, width: 40 }, "value")
372
+ ],
373
+ tooltipOf(formatter),
374
+ legendOf(series2, legend),
375
+ series2.map((s, i) => /* @__PURE__ */ jsxRuntime.jsx(
376
+ recharts.Bar,
377
+ {
378
+ dataKey: s.key,
379
+ name: s.label,
380
+ fill: color(s, i),
381
+ radius: lying ? [0, radius.chip, radius.chip, 0] : [radius.chip, radius.chip, 0, 0],
382
+ isAnimationActive: false,
383
+ ...stacked ? { stackId: "stack" } : {}
384
+ },
385
+ s.key
386
+ ))
387
+ ]
388
+ }
389
+ ) });
390
+ }
391
+ function LineChart({
392
+ data,
393
+ series: series2,
394
+ xKey,
395
+ formatter,
396
+ legend,
397
+ ...container
398
+ }) {
399
+ return /* @__PURE__ */ jsxRuntime.jsx(ChartContainer, { ...container, children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.LineChart, { data: rows(data), margin: MARGIN, children: [
400
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { vertical: false }),
401
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.XAxis, { dataKey: xKey, ...AXIS, tickMargin: 8 }),
402
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.YAxis, { ...AXIS, width: 40 }),
403
+ tooltipOf(formatter),
404
+ legendOf(series2, legend),
405
+ series2.map((s, i) => /* @__PURE__ */ jsxRuntime.jsx(
406
+ recharts.Line,
407
+ {
408
+ dataKey: s.key,
409
+ name: s.label,
410
+ type: "natural",
411
+ stroke: color(s, i),
412
+ strokeWidth: 2,
413
+ dot: false,
414
+ activeDot: { r: 4 },
415
+ isAnimationActive: false
416
+ },
417
+ s.key
418
+ ))
419
+ ] }) });
420
+ }
297
421
 
422
+ exports.AreaChart = AreaChart;
423
+ exports.BarChart = BarChart;
298
424
  exports.ChartContainer = ChartContainer;
299
425
  exports.ChartLegend = ChartLegend;
300
426
  exports.ChartLegendContent = ChartLegendContent;
301
427
  exports.ChartTooltip = ChartTooltip;
302
428
  exports.ChartTooltipContent = ChartTooltipContent;
429
+ exports.LineChart = LineChart;
303
430
  exports.SERIES_COLORS = SERIES_COLORS;
304
431
  exports.seriesColor = seriesColor;
@@ -22,9 +22,15 @@ import { Legend, Tooltip } from 'recharts';
22
22
  * 3. The tooltip appears where it will stay: `isAnimationActive` is off
23
23
  * everywhere, because the system does not animate position.
24
24
  *
25
- * The data pieces — `BarChart`, `Line`, `XAxis` — are NOT re-exported. They are
26
- * Recharts' API, the project already knows it, and wrapping them would be a
27
- * layer of names to keep in sync with the library's version.
25
+ * Recharts' data pieces — `Area`, `Line`, `XAxis` — are still NOT re-exported.
26
+ * They are Recharts' API, the project already knows it, and wrapping them would
27
+ * be a layer of names to keep in sync with the library's version.
28
+ *
29
+ * What IS published, since this version, are three CHART TYPES on top of that
30
+ * chassis: `AreaChart`, `BarChart` and `LineChart`. They are not wrappers over
31
+ * Recharts' components of the same name — they take `data`, `series` and `xKey`
32
+ * and draw the whole thing. See `docs/decisions/0.8.md` § 43 for why the names
33
+ * collide on purpose.
28
34
  */
29
35
  /**
30
36
  * The color of series `index`, as a custom property.
@@ -123,5 +129,109 @@ type ChartLegendContentProps = {
123
129
  };
124
130
  /** The legend, with the tooltip's same square swatch and the `label` scale. */
125
131
  declare function ChartLegendContent({ payload, className }: ChartLegendContentProps): react.JSX.Element | null;
132
+ /**
133
+ * One series: which key of the datum it reads, what it is called, and — only if
134
+ * you insist — what color it is.
135
+ *
136
+ * `color` is there for the case the palette cannot serve: a status series where
137
+ * «pagado» has to be `success` and not «the first of the four». Leaving it out
138
+ * is the normal case and the right one — `seriesColor(i)` follows the mode, and
139
+ * a hard-coded hex does not. See the note on `seriesColor` above.
140
+ */
141
+ type ChartSeries = {
142
+ /** The key this series reads in each datum. */
143
+ key: string;
144
+ /** What the legend and the tooltip call it. User-facing, so Spanish. */
145
+ label: string;
146
+ /** Overrides the palette. Defaults to `seriesColor(index)`. */
147
+ color?: string | undefined;
148
+ };
149
+ /** A row of the chart: the category key plus one value per series. */
150
+ type ChartDatum = Record<string, unknown>;
151
+ /**
152
+ * What all three types take, and it is deliberately short: `data`, `series` and
153
+ * `xKey`, plus the container's own `label`.
154
+ *
155
+ * Everything that is NOT here is the part that was being copied — the gradient,
156
+ * the grid with no vertical lines, the axes with no line and no tick, the
157
+ * tooltip with no cursor. `cursos` wrote all of it four times, once per chart,
158
+ * and the fourth one would have had a different `strokeWidth` from the first.
159
+ * The drawing is the system's; the data is the project's.
160
+ */
161
+ type SeriesChartProps = Omit<ChartContainerProps, 'children'> & {
162
+ data: readonly ChartDatum[];
163
+ series: readonly ChartSeries[];
164
+ /** The key on the category axis: the day, the month, the course. */
165
+ xKey: string;
166
+ /** Formats the value in the tooltip. The library imposes no locale. */
167
+ formatter?: ((value: unknown) => ReactNode) | undefined;
168
+ /**
169
+ * Shows the legend. It defaults to «only when there is more than one series»:
170
+ * a legend naming the one line already named by the chart's own heading is a
171
+ * row of pixels that says nothing.
172
+ */
173
+ legend?: boolean | undefined;
174
+ };
175
+ /**
176
+ * A series over time, with the fill fading out underneath it.
177
+ *
178
+ * The gradient is the whole reason this is a component and not three lines at
179
+ * the call site: it needs a `<linearGradient>` with an id, the id has to be
180
+ * unique on the page, and the two projects that wrote it by hand both hardcoded
181
+ * one — a second chart on the same screen would have taken the first one's fill.
182
+ * `useId` settles it.
183
+ *
184
+ * 0.5 down to 0.05 is the ramp `cursos` arrived at, and `type="natural"` is its
185
+ * curve: a monotone spline reads as a measurement and a straight segment reads
186
+ * as a schedule. The stroke is 2, which is the one weight in the system that is
187
+ * neither a hairline nor a border.
188
+ *
189
+ * With more than one series the areas OVERLAP rather than stack, because a
190
+ * stacked area answers «how much in total» and this library has no way to know
191
+ * that is the question. When it is, pass `stacked`. When you want to compare
192
+ * rather than add up, the answer is `LineChart`.
193
+ */
194
+ type AreaChartProps = SeriesChartProps & {
195
+ /** Adds the series up instead of overlaying them. */
196
+ stacked?: boolean | undefined;
197
+ };
198
+ declare function AreaChart({ data, series, xKey, formatter, legend, stacked, ...container }: AreaChartProps): react.JSX.Element;
199
+ /**
200
+ * Bars, upright or lying down.
201
+ *
202
+ * `orientation` is named for what you SEE and not for what Recharts calls it,
203
+ * and the two are opposites: Recharts' `layout="vertical"` draws horizontal
204
+ * bars. That inversion is a coin flip every time somebody writes it, so it is
205
+ * settled here once — `vertical` means the bars grow upwards.
206
+ *
207
+ * `horizontal` is the shape for a ranking, which is what `cursos` uses it for:
208
+ * course names on the left, one bar each. It reserves 130px for the category
209
+ * axis and hides the value axis, because a ranking is read by comparing lengths
210
+ * and not by reading a number off a scale — the number is in the tooltip.
211
+ *
212
+ * The corner radius is `radius.chip`, the system's smallest. A bar is a chip
213
+ * lying down, and picking a number that is not a token is how a fifth radius
214
+ * gets into the system without anybody deciding it should.
215
+ */
216
+ type BarChartProps = SeriesChartProps & {
217
+ /** `vertical` grows the bars upwards, which is the default. `horizontal` is a ranking. */
218
+ orientation?: 'vertical' | 'horizontal' | undefined;
219
+ /** Stacks the series instead of putting them side by side. */
220
+ stacked?: boolean | undefined;
221
+ };
222
+ declare function BarChart({ data, series, xKey, formatter, legend, orientation, stacked, ...container }: BarChartProps): react.JSX.Element;
223
+ /**
224
+ * Lines, for comparing series against each other.
225
+ *
226
+ * It is the type that does NOT add anything up, which is the whole reason it
227
+ * exists next to `AreaChart`: four filled areas on top of each other are a
228
+ * total, and four lines are four things you can tell apart.
229
+ *
230
+ * No dots at rest. A point per datum on a 90-day series is a dotted line, and
231
+ * the value is in the tooltip; the dot comes back on hover because that is
232
+ * where it means «this one».
233
+ */
234
+ type LineChartProps = SeriesChartProps;
235
+ declare function LineChart({ data, series, xKey, formatter, legend, ...container }: LineChartProps): react.JSX.Element;
126
236
 
127
- export { ChartContainer, type ChartContainerProps, ChartLegend, ChartLegendContent, type ChartLegendContentProps, type ChartPayloadItem, ChartTooltip, ChartTooltipContent, type ChartTooltipContentProps, SERIES_COLORS, seriesColor };
237
+ export { AreaChart, type AreaChartProps, BarChart, type BarChartProps, ChartContainer, type ChartContainerProps, type ChartDatum, ChartLegend, ChartLegendContent, type ChartLegendContentProps, type ChartPayloadItem, type ChartSeries, ChartTooltip, ChartTooltipContent, type ChartTooltipContentProps, LineChart, type LineChartProps, SERIES_COLORS, type SeriesChartProps, seriesColor };
@@ -22,9 +22,15 @@ import { Legend, Tooltip } from 'recharts';
22
22
  * 3. The tooltip appears where it will stay: `isAnimationActive` is off
23
23
  * everywhere, because the system does not animate position.
24
24
  *
25
- * The data pieces — `BarChart`, `Line`, `XAxis` — are NOT re-exported. They are
26
- * Recharts' API, the project already knows it, and wrapping them would be a
27
- * layer of names to keep in sync with the library's version.
25
+ * Recharts' data pieces — `Area`, `Line`, `XAxis` — are still NOT re-exported.
26
+ * They are Recharts' API, the project already knows it, and wrapping them would
27
+ * be a layer of names to keep in sync with the library's version.
28
+ *
29
+ * What IS published, since this version, are three CHART TYPES on top of that
30
+ * chassis: `AreaChart`, `BarChart` and `LineChart`. They are not wrappers over
31
+ * Recharts' components of the same name — they take `data`, `series` and `xKey`
32
+ * and draw the whole thing. See `docs/decisions/0.8.md` § 43 for why the names
33
+ * collide on purpose.
28
34
  */
29
35
  /**
30
36
  * The color of series `index`, as a custom property.
@@ -123,5 +129,109 @@ type ChartLegendContentProps = {
123
129
  };
124
130
  /** The legend, with the tooltip's same square swatch and the `label` scale. */
125
131
  declare function ChartLegendContent({ payload, className }: ChartLegendContentProps): react.JSX.Element | null;
132
+ /**
133
+ * One series: which key of the datum it reads, what it is called, and — only if
134
+ * you insist — what color it is.
135
+ *
136
+ * `color` is there for the case the palette cannot serve: a status series where
137
+ * «pagado» has to be `success` and not «the first of the four». Leaving it out
138
+ * is the normal case and the right one — `seriesColor(i)` follows the mode, and
139
+ * a hard-coded hex does not. See the note on `seriesColor` above.
140
+ */
141
+ type ChartSeries = {
142
+ /** The key this series reads in each datum. */
143
+ key: string;
144
+ /** What the legend and the tooltip call it. User-facing, so Spanish. */
145
+ label: string;
146
+ /** Overrides the palette. Defaults to `seriesColor(index)`. */
147
+ color?: string | undefined;
148
+ };
149
+ /** A row of the chart: the category key plus one value per series. */
150
+ type ChartDatum = Record<string, unknown>;
151
+ /**
152
+ * What all three types take, and it is deliberately short: `data`, `series` and
153
+ * `xKey`, plus the container's own `label`.
154
+ *
155
+ * Everything that is NOT here is the part that was being copied — the gradient,
156
+ * the grid with no vertical lines, the axes with no line and no tick, the
157
+ * tooltip with no cursor. `cursos` wrote all of it four times, once per chart,
158
+ * and the fourth one would have had a different `strokeWidth` from the first.
159
+ * The drawing is the system's; the data is the project's.
160
+ */
161
+ type SeriesChartProps = Omit<ChartContainerProps, 'children'> & {
162
+ data: readonly ChartDatum[];
163
+ series: readonly ChartSeries[];
164
+ /** The key on the category axis: the day, the month, the course. */
165
+ xKey: string;
166
+ /** Formats the value in the tooltip. The library imposes no locale. */
167
+ formatter?: ((value: unknown) => ReactNode) | undefined;
168
+ /**
169
+ * Shows the legend. It defaults to «only when there is more than one series»:
170
+ * a legend naming the one line already named by the chart's own heading is a
171
+ * row of pixels that says nothing.
172
+ */
173
+ legend?: boolean | undefined;
174
+ };
175
+ /**
176
+ * A series over time, with the fill fading out underneath it.
177
+ *
178
+ * The gradient is the whole reason this is a component and not three lines at
179
+ * the call site: it needs a `<linearGradient>` with an id, the id has to be
180
+ * unique on the page, and the two projects that wrote it by hand both hardcoded
181
+ * one — a second chart on the same screen would have taken the first one's fill.
182
+ * `useId` settles it.
183
+ *
184
+ * 0.5 down to 0.05 is the ramp `cursos` arrived at, and `type="natural"` is its
185
+ * curve: a monotone spline reads as a measurement and a straight segment reads
186
+ * as a schedule. The stroke is 2, which is the one weight in the system that is
187
+ * neither a hairline nor a border.
188
+ *
189
+ * With more than one series the areas OVERLAP rather than stack, because a
190
+ * stacked area answers «how much in total» and this library has no way to know
191
+ * that is the question. When it is, pass `stacked`. When you want to compare
192
+ * rather than add up, the answer is `LineChart`.
193
+ */
194
+ type AreaChartProps = SeriesChartProps & {
195
+ /** Adds the series up instead of overlaying them. */
196
+ stacked?: boolean | undefined;
197
+ };
198
+ declare function AreaChart({ data, series, xKey, formatter, legend, stacked, ...container }: AreaChartProps): react.JSX.Element;
199
+ /**
200
+ * Bars, upright or lying down.
201
+ *
202
+ * `orientation` is named for what you SEE and not for what Recharts calls it,
203
+ * and the two are opposites: Recharts' `layout="vertical"` draws horizontal
204
+ * bars. That inversion is a coin flip every time somebody writes it, so it is
205
+ * settled here once — `vertical` means the bars grow upwards.
206
+ *
207
+ * `horizontal` is the shape for a ranking, which is what `cursos` uses it for:
208
+ * course names on the left, one bar each. It reserves 130px for the category
209
+ * axis and hides the value axis, because a ranking is read by comparing lengths
210
+ * and not by reading a number off a scale — the number is in the tooltip.
211
+ *
212
+ * The corner radius is `radius.chip`, the system's smallest. A bar is a chip
213
+ * lying down, and picking a number that is not a token is how a fifth radius
214
+ * gets into the system without anybody deciding it should.
215
+ */
216
+ type BarChartProps = SeriesChartProps & {
217
+ /** `vertical` grows the bars upwards, which is the default. `horizontal` is a ranking. */
218
+ orientation?: 'vertical' | 'horizontal' | undefined;
219
+ /** Stacks the series instead of putting them side by side. */
220
+ stacked?: boolean | undefined;
221
+ };
222
+ declare function BarChart({ data, series, xKey, formatter, legend, orientation, stacked, ...container }: BarChartProps): react.JSX.Element;
223
+ /**
224
+ * Lines, for comparing series against each other.
225
+ *
226
+ * It is the type that does NOT add anything up, which is the whole reason it
227
+ * exists next to `AreaChart`: four filled areas on top of each other are a
228
+ * total, and four lines are four things you can tell apart.
229
+ *
230
+ * No dots at rest. A point per datum on a 90-day series is a dotted line, and
231
+ * the value is in the tooltip; the dot comes back on hover because that is
232
+ * where it means «this one».
233
+ */
234
+ type LineChartProps = SeriesChartProps;
235
+ declare function LineChart({ data, series, xKey, formatter, legend, ...container }: LineChartProps): react.JSX.Element;
126
236
 
127
- export { ChartContainer, type ChartContainerProps, ChartLegend, ChartLegendContent, type ChartLegendContentProps, type ChartPayloadItem, ChartTooltip, ChartTooltipContent, type ChartTooltipContentProps, SERIES_COLORS, seriesColor };
237
+ export { AreaChart, type AreaChartProps, BarChart, type BarChartProps, ChartContainer, type ChartContainerProps, type ChartDatum, ChartLegend, ChartLegendContent, type ChartLegendContentProps, type ChartPayloadItem, type ChartSeries, ChartTooltip, ChartTooltipContent, type ChartTooltipContentProps, LineChart, type LineChartProps, SERIES_COLORS, type SeriesChartProps, seriesColor };
@@ -1,10 +1,11 @@
1
1
  'use client';
2
- import { Text } from '../chunk-JMOOFZ3B.js';
2
+ import { Text } from '../chunk-TRPBID2W.js';
3
3
  import '../chunk-ODBFN44D.js';
4
- import { cn } from '../chunk-XKYHTOUJ.js';
5
- import '../chunk-O4TAH7YJ.js';
4
+ import { cn } from '../chunk-FAAGZG7A.js';
5
+ import { radius } from '../chunk-FGFNK72B.js';
6
6
  import '../chunk-MLKGABMK.js';
7
- import { ResponsiveContainer, Tooltip, Legend } from 'recharts';
7
+ import { useId } from 'react';
8
+ import { ResponsiveContainer, Tooltip, Legend, AreaChart as AreaChart$1, CartesianGrid, XAxis, YAxis, Area, BarChart as BarChart$1, Bar, LineChart as LineChart$1, Line } from 'recharts';
8
9
  import { jsxs, jsx } from 'react/jsx-runtime';
9
10
 
10
11
  function seriesColor(index) {
@@ -101,5 +102,128 @@ function ChartLegendContent({ payload, className }) {
101
102
  /* @__PURE__ */ jsx(Text, { as: "span", variant: "label", tone: "secondary", className: "font-normal", children: item.value })
102
103
  ] }, `${String(item.dataKey ?? item.value ?? i)}`)) });
103
104
  }
105
+ var rows = (data) => data;
106
+ var color = (series, index) => series.color ?? seriesColor(index);
107
+ var MARGIN = { left: 0, right: 12, top: 8, bottom: 0 };
108
+ var AXIS = { tickLine: false, axisLine: false };
109
+ var legendOf = (series, legend) => legend ?? series.length > 1 ? /* @__PURE__ */ jsx(ChartLegend, { content: /* @__PURE__ */ jsx(ChartLegendContent, {}) }, "legend") : null;
110
+ var tooltipOf = (formatter) => /* @__PURE__ */ jsx(
111
+ ChartTooltip,
112
+ {
113
+ cursor: false,
114
+ content: /* @__PURE__ */ jsx(ChartTooltipContent, { formatter: formatter ? (value) => formatter(value) : void 0 })
115
+ },
116
+ "tooltip"
117
+ );
118
+ function AreaChart({
119
+ data,
120
+ series,
121
+ xKey,
122
+ formatter,
123
+ legend,
124
+ stacked = false,
125
+ ...container
126
+ }) {
127
+ const id = useId();
128
+ return /* @__PURE__ */ jsx(ChartContainer, { ...container, children: /* @__PURE__ */ jsxs(AreaChart$1, { data: rows(data), margin: MARGIN, children: [
129
+ /* @__PURE__ */ jsx("defs", { children: series.map((s, i) => /* @__PURE__ */ jsxs("linearGradient", { id: `${id}-${s.key}`, x1: "0", y1: "0", x2: "0", y2: "1", children: [
130
+ /* @__PURE__ */ jsx("stop", { offset: "5%", stopColor: color(s, i), stopOpacity: 0.5 }),
131
+ /* @__PURE__ */ jsx("stop", { offset: "95%", stopColor: color(s, i), stopOpacity: 0.05 })
132
+ ] }, s.key)) }),
133
+ /* @__PURE__ */ jsx(CartesianGrid, { vertical: false }),
134
+ /* @__PURE__ */ jsx(XAxis, { dataKey: xKey, ...AXIS, tickMargin: 8 }),
135
+ /* @__PURE__ */ jsx(YAxis, { ...AXIS, width: 40 }),
136
+ tooltipOf(formatter),
137
+ legendOf(series, legend),
138
+ series.map((s, i) => /* @__PURE__ */ jsx(
139
+ Area,
140
+ {
141
+ dataKey: s.key,
142
+ name: s.label,
143
+ type: "natural",
144
+ stroke: color(s, i),
145
+ strokeWidth: 2,
146
+ fill: `url(#${id}-${s.key})`,
147
+ isAnimationActive: false,
148
+ ...stacked ? { stackId: "stack" } : {}
149
+ },
150
+ s.key
151
+ ))
152
+ ] }) });
153
+ }
154
+ function BarChart({
155
+ data,
156
+ series,
157
+ xKey,
158
+ formatter,
159
+ legend,
160
+ orientation = "vertical",
161
+ stacked = false,
162
+ ...container
163
+ }) {
164
+ const lying = orientation === "horizontal";
165
+ return /* @__PURE__ */ jsx(ChartContainer, { ...container, children: /* @__PURE__ */ jsxs(
166
+ BarChart$1,
167
+ {
168
+ data: rows(data),
169
+ margin: MARGIN,
170
+ ...lying ? { layout: "vertical" } : {},
171
+ children: [
172
+ /* @__PURE__ */ jsx(CartesianGrid, { vertical: lying, horizontal: !lying }),
173
+ lying ? [
174
+ /* @__PURE__ */ jsx(YAxis, { dataKey: xKey, type: "category", ...AXIS, width: 130 }, "category"),
175
+ /* @__PURE__ */ jsx(XAxis, { type: "number", hide: true }, "value")
176
+ ] : [
177
+ /* @__PURE__ */ jsx(XAxis, { dataKey: xKey, ...AXIS, tickMargin: 8 }, "category"),
178
+ /* @__PURE__ */ jsx(YAxis, { ...AXIS, width: 40 }, "value")
179
+ ],
180
+ tooltipOf(formatter),
181
+ legendOf(series, legend),
182
+ series.map((s, i) => /* @__PURE__ */ jsx(
183
+ Bar,
184
+ {
185
+ dataKey: s.key,
186
+ name: s.label,
187
+ fill: color(s, i),
188
+ radius: lying ? [0, radius.chip, radius.chip, 0] : [radius.chip, radius.chip, 0, 0],
189
+ isAnimationActive: false,
190
+ ...stacked ? { stackId: "stack" } : {}
191
+ },
192
+ s.key
193
+ ))
194
+ ]
195
+ }
196
+ ) });
197
+ }
198
+ function LineChart({
199
+ data,
200
+ series,
201
+ xKey,
202
+ formatter,
203
+ legend,
204
+ ...container
205
+ }) {
206
+ return /* @__PURE__ */ jsx(ChartContainer, { ...container, children: /* @__PURE__ */ jsxs(LineChart$1, { data: rows(data), margin: MARGIN, children: [
207
+ /* @__PURE__ */ jsx(CartesianGrid, { vertical: false }),
208
+ /* @__PURE__ */ jsx(XAxis, { dataKey: xKey, ...AXIS, tickMargin: 8 }),
209
+ /* @__PURE__ */ jsx(YAxis, { ...AXIS, width: 40 }),
210
+ tooltipOf(formatter),
211
+ legendOf(series, legend),
212
+ series.map((s, i) => /* @__PURE__ */ jsx(
213
+ Line,
214
+ {
215
+ dataKey: s.key,
216
+ name: s.label,
217
+ type: "natural",
218
+ stroke: color(s, i),
219
+ strokeWidth: 2,
220
+ dot: false,
221
+ activeDot: { r: 4 },
222
+ isAnimationActive: false
223
+ },
224
+ s.key
225
+ ))
226
+ ] }) });
227
+ }
104
228
 
105
- export { ChartContainer, ChartLegend, ChartLegendContent, ChartTooltip, ChartTooltipContent, SERIES_COLORS, seriesColor };
229
+ export { AreaChart, BarChart, ChartContainer, ChartLegend, ChartLegendContent, ChartTooltip, ChartTooltipContent, LineChart, SERIES_COLORS, seriesColor };
@@ -1,4 +1,4 @@
1
- import { naming, tagline, motion, shadow, series, syntax, gradient, size, spacing, control, radius, limits, typeScale, fonts, brand, colors } from './chunk-O4TAH7YJ.js';
1
+ import { naming, tagline, motion, shadow, series, syntax, gradient, size, spacing, control, radius, limits, typeScale, fonts, brand, colors } from './chunk-FGFNK72B.js';
2
2
 
3
3
  // src/tokens/index.ts
4
4
  var tokens = {
@@ -1,4 +1,4 @@
1
- import { cn } from './chunk-XKYHTOUJ.js';
1
+ import { cn } from './chunk-FAAGZG7A.js';
2
2
  import * as LabelPrimitive from '@radix-ui/react-label';
3
3
  import { jsx } from 'react/jsx-runtime';
4
4
 
@@ -1,4 +1,4 @@
1
- import { spacing, control, radius, typeScale } from './chunk-O4TAH7YJ.js';
1
+ import { spacing, control, radius, typeScale } from './chunk-FGFNK72B.js';
2
2
  import { clsx } from 'clsx';
3
3
  import { extendTailwindMerge } from 'tailwind-merge';
4
4
 
@@ -144,7 +144,7 @@ var typeScale = {
144
144
  * (plankton 5.57:1 over abyss), which is the part that is not negotiable.
145
145
  *
146
146
  * At 13 the three badge families grew past the size of a small button and
147
- * outweighed the title they accompany. See `docs/decisions.md`.
147
+ * outweighed the title they accompany. See `docs/decisions/`.
148
148
  */
149
149
  chip: { family: "mono", size: 11.5, lineHeight: 1.4, weight: 400 },
150
150
  /**
@@ -198,7 +198,7 @@ var control = {
198
198
  * baseline; 28 would have been a fifth height that matches nothing.
199
199
  *
200
200
  * It does not replace `icon`. A page's primary action stays at 42; this is for
201
- * a row of a table. See `docs/decisions.md` § 22.
201
+ * a row of a table. See `docs/decisions/0.6.md` § 22.
202
202
  */
203
203
  iconSm: 32
204
204
  };
@@ -213,6 +213,30 @@ var spacing = {
213
213
  var size = {
214
214
  /** Navigation bar height. */
215
215
  nav: 64,
216
+ /**
217
+ * The bar when it shares the screen with a sidebar.
218
+ *
219
+ * It is not «a smaller bar because it looks better». At 64 the header of an
220
+ * app shell competes with the rail beside it for the same corner, and the two
221
+ * together eat the top of the content area. 56 is what `cursos` had arrived at
222
+ * on its own, and it is the same reasoning as `control.iconSm`: the one admin
223
+ * app of the five is denser than the four reading sites. See
224
+ * `docs/decisions/0.7.md` § 30.
225
+ */
226
+ navCompact: 56,
227
+ /**
228
+ * The admin sidebar, and the rail it collapses to.
229
+ *
230
+ * They are tokens and not the consumer's `w-*` because a collapsible sidebar
231
+ * has to know BOTH: the layout beside it reserves one of the two, and two
232
+ * numbers written by hand in two files drift the first time one of them moves.
233
+ * A sidebar that never collapses is still just a box the layout sizes.
234
+ *
235
+ * 56 is the rail: `navCompact`'s height, so a panel's bar and its rail meet in
236
+ * a square corner instead of a step.
237
+ */
238
+ sidebar: 256,
239
+ sidebarRail: 56,
216
240
  /** Reading column width. */
217
241
  content: 760,
218
242
  /** Maximum page width. */
@@ -245,9 +269,9 @@ var gradient = {
245
269
  og: `linear-gradient(145deg, ${dark.background} 55%, ${deep} 100%)`
246
270
  },
247
271
  light: {
248
- hero: `linear-gradient(160deg, ${light.background} 60%, ${light.surfaceRaised} 100%)`,
249
- section: `linear-gradient(150deg, ${light.surface} 0%, ${light.surfaceRaised} 100%)`,
250
- og: `linear-gradient(145deg, ${light.background} 55%, ${light.surfaceRaised} 100%)`
272
+ hero: `linear-gradient(160deg, ${light.background} 60%, ${light.surface} 100%)`,
273
+ section: `linear-gradient(150deg, ${light.surface} 0%, ${light.background} 100%)`,
274
+ og: `linear-gradient(145deg, ${light.background} 55%, ${light.surface} 100%)`
251
275
  }
252
276
  };
253
277
  var shadow = {