@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.
- package/CHANGELOG.md +112 -0
- package/README.md +288 -49
- package/dist/brand/index.cjs +2 -2
- package/dist/brand/index.js +3 -3
- package/dist/chart/index.cjs +129 -2
- package/dist/chart/index.d.cts +114 -4
- package/dist/chart/index.d.ts +114 -4
- package/dist/chart/index.js +129 -5
- package/dist/{chunk-PMN7NR3G.js → chunk-5A5GH2PF.js} +1 -1
- package/dist/{chunk-DKCN7BAL.js → chunk-6IGD5REB.js} +1 -1
- package/dist/{chunk-XKYHTOUJ.js → chunk-FAAGZG7A.js} +1 -1
- package/dist/{chunk-O4TAH7YJ.js → chunk-FGFNK72B.js} +29 -5
- package/dist/chunk-HOADZ6GS.js +72 -0
- package/dist/chunk-LXRGQKMG.js +145 -0
- package/dist/{chunk-6O3KWB6P.js → chunk-MPZBF2TZ.js} +2 -2
- package/dist/{chunk-JMOOFZ3B.js → chunk-TRPBID2W.js} +1 -1
- package/dist/{chunk-25YNFCIF.js → chunk-XXDATT3A.js} +6 -3
- package/dist/doctor.mjs +248 -0
- package/dist/form/index.cjs +2 -2
- package/dist/form/index.d.cts +1 -1
- package/dist/form/index.d.ts +1 -1
- package/dist/form/index.js +4 -4
- package/dist/icons/index.cjs +149 -0
- package/dist/icons/index.d.cts +94 -0
- package/dist/icons/index.d.ts +94 -0
- package/dist/icons/index.js +28 -0
- package/dist/index-BbRplw_B.d.cts +58 -0
- package/dist/index-BbRplw_B.d.ts +58 -0
- package/dist/index.cjs +425 -251
- package/dist/index.d.cts +303 -104
- package/dist/index.d.ts +303 -104
- package/dist/index.js +283 -285
- package/dist/{label-MgHFKnFy.d.ts → label-DJ4HuD-R.d.cts} +3 -2
- package/dist/{label-MgHFKnFy.d.cts → label-DJ4HuD-R.d.ts} +3 -2
- package/dist/og/index.cjs +3 -2
- package/dist/og/index.js +1 -1
- package/dist/shiki/index.js +1 -1
- package/dist/social/data.cjs +161 -0
- package/dist/social/data.d.cts +161 -0
- package/dist/social/data.d.ts +161 -0
- package/dist/social/data.js +2 -0
- package/dist/social/index.cjs +153 -0
- package/dist/social/index.d.cts +2 -0
- package/dist/social/index.d.ts +2 -0
- package/dist/social/index.js +3 -0
- package/dist/tokens/index.cjs +29 -5
- package/dist/tokens/index.d.cts +37 -10
- package/dist/tokens/index.d.ts +37 -10
- package/dist/tokens/index.js +2 -2
- package/dist/tokens/theme.css +79 -22
- package/dist/variants/index.cjs +6 -3
- package/dist/variants/index.d.cts +6 -3
- package/dist/variants/index.d.ts +6 -3
- package/dist/variants/index.js +1 -1
- package/llms.txt +530 -80
- package/package.json +29 -2
package/dist/chart/index.cjs
CHANGED
|
@@ -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
|
|
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;
|
package/dist/chart/index.d.cts
CHANGED
|
@@ -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
|
-
*
|
|
26
|
-
* Recharts' API, the project already knows it, and wrapping them would
|
|
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 };
|
package/dist/chart/index.d.ts
CHANGED
|
@@ -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
|
-
*
|
|
26
|
-
* Recharts' API, the project already knows it, and wrapping them would
|
|
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 };
|
package/dist/chart/index.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { Text } from '../chunk-
|
|
2
|
+
import { Text } from '../chunk-TRPBID2W.js';
|
|
3
3
|
import '../chunk-ODBFN44D.js';
|
|
4
|
-
import { cn } from '../chunk-
|
|
5
|
-
import '../chunk-
|
|
4
|
+
import { cn } from '../chunk-FAAGZG7A.js';
|
|
5
|
+
import { radius } from '../chunk-FGFNK72B.js';
|
|
6
6
|
import '../chunk-MLKGABMK.js';
|
|
7
|
-
import {
|
|
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-
|
|
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 = {
|
|
@@ -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
|
|
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.
|
|
249
|
-
section: `linear-gradient(150deg, ${light.surface} 0%, ${light.
|
|
250
|
-
og: `linear-gradient(145deg, ${light.background} 55%, ${light.
|
|
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 = {
|