@techsio/ui-kit 0.37.1 → 0.39.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/dist/molecules/chart.js +393 -0
- package/dist/organisms/data-table.fields.js +720 -0
- package/dist/organisms/data-table.helpers.js +168 -0
- package/dist/organisms/data-table.js +1736 -0
- package/dist/organisms/table.js +7 -3
- package/dist/src/molecules/chart.d.ts +64 -0
- package/dist/src/molecules/chart.d.ts.map +1 -0
- package/dist/src/molecules/switch.d.ts +3 -3
- package/dist/src/molecules/toast.d.ts +3 -3
- package/dist/src/organisms/data-table.d.ts +357 -0
- package/dist/src/organisms/data-table.d.ts.map +1 -0
- package/dist/src/organisms/data-table.fields.d.ts +119 -0
- package/dist/src/organisms/data-table.fields.d.ts.map +1 -0
- package/dist/src/organisms/data-table.helpers.d.ts +240 -0
- package/dist/src/organisms/data-table.helpers.d.ts.map +1 -0
- package/dist/src/organisms/table.d.ts +15 -7
- package/dist/src/organisms/table.d.ts.map +1 -1
- package/dist/stories/changelog/changelog.stories.d.ts.map +1 -1
- package/dist/stories/molecules/chart.stories.d.ts +24 -0
- package/dist/stories/molecules/chart.stories.d.ts.map +1 -0
- package/dist/stories/organisms/data-table.stories.d.ts +145 -0
- package/dist/stories/organisms/data-table.stories.d.ts.map +1 -0
- package/dist/stories/organisms/table.stories.d.ts +7 -0
- package/dist/stories/organisms/table.stories.d.ts.map +1 -1
- package/package.json +14 -1
- package/src/tokens/components/components.css +2 -0
- package/src/tokens/components/molecules/_chart.css +98 -0
- package/src/tokens/components/organisms/_data-table.css +51 -0
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { areaY, barX, barY, colorLegend, d3Curve, defineChart, dot, group, lineY, stack } from "@tanstack/charts";
|
|
3
|
+
import { polar, radialArc } from "@tanstack/charts/polar";
|
|
4
|
+
import { tooltip as tooltip_tooltip } from "@tanstack/charts/tooltip";
|
|
5
|
+
import { scaleBand } from "@tanstack/charts-scales/band";
|
|
6
|
+
import { scaleLinear } from "@tanstack/charts-scales/linear";
|
|
7
|
+
import { scalePoint } from "@tanstack/charts-scales/point";
|
|
8
|
+
import { Chart } from "@tanstack/react-charts";
|
|
9
|
+
import { scaleUtc } from "d3-scale";
|
|
10
|
+
import { curveMonotoneX, pie } from "d3-shape";
|
|
11
|
+
import { useMemo } from "react";
|
|
12
|
+
import { tv } from "../utils.js";
|
|
13
|
+
const chartVariants = tv({
|
|
14
|
+
slots: {
|
|
15
|
+
root: "chart-base block w-full text-chart-fg",
|
|
16
|
+
tooltip: "chart-tooltip"
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
const SERIES_1_PAINT = "var(--color-chart-series-1)";
|
|
20
|
+
const SERIES_STROKE_FROM_COLOR = null;
|
|
21
|
+
const DONUT_INNER_RADIUS_RATIO = 0.6;
|
|
22
|
+
const POLAR_INSET = 8;
|
|
23
|
+
function toAccessor(accessor) {
|
|
24
|
+
if ("function" == typeof accessor) return accessor;
|
|
25
|
+
return (datum)=>datum[accessor];
|
|
26
|
+
}
|
|
27
|
+
const defineChartSpec = defineChart;
|
|
28
|
+
const MAX_SERIES = 6;
|
|
29
|
+
function resolveXAxis(data, getX, xLabel) {
|
|
30
|
+
const values = data.map(getX);
|
|
31
|
+
if (values.length > 0 && values.every((value)=>value instanceof Date)) return {
|
|
32
|
+
scale: ()=>scaleUtc(),
|
|
33
|
+
nice: true,
|
|
34
|
+
axis: {
|
|
35
|
+
label: xLabel
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
if (values.length > 0 && values.every((value)=>"number" == typeof value)) return {
|
|
39
|
+
scale: scaleLinear,
|
|
40
|
+
nice: true,
|
|
41
|
+
axis: {
|
|
42
|
+
label: xLabel
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
return {
|
|
46
|
+
scale: ()=>scalePoint().padding(0.1),
|
|
47
|
+
axis: {
|
|
48
|
+
label: xLabel
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function resolveBuild(config) {
|
|
53
|
+
const getX = toAccessor(config.x);
|
|
54
|
+
const getY = toAccessor(config.y);
|
|
55
|
+
const getSeries = null == config.series ? void 0 : toAccessor(config.series);
|
|
56
|
+
const isPolar = "pie" === config.type || "donut" === config.type;
|
|
57
|
+
const showLegend = config.legend ?? (null != config.series || isPolar);
|
|
58
|
+
const { formatValue } = config;
|
|
59
|
+
const valueTicks = formatValue ? {
|
|
60
|
+
format: formatValue
|
|
61
|
+
} : void 0;
|
|
62
|
+
warnOnSeriesOverflow(config.data, isPolar ? getX : getSeries);
|
|
63
|
+
const tooltipBase = {
|
|
64
|
+
use: tooltip_tooltip,
|
|
65
|
+
className: config.tooltipClassName
|
|
66
|
+
};
|
|
67
|
+
const channelName = (accessor, label)=>label ?? ("string" == typeof accessor ? accessor : void 0);
|
|
68
|
+
const xName = channelName(config.x, config.xLabel);
|
|
69
|
+
const yName = channelName(config.y, config.yLabel);
|
|
70
|
+
const formatChannel = (point, channel)=>{
|
|
71
|
+
const value = "x" === channel ? point.xValue : point.yValue;
|
|
72
|
+
if ("number" == typeof value && formatValue) return formatValue(value);
|
|
73
|
+
return String(value ?? "");
|
|
74
|
+
};
|
|
75
|
+
const tooltipFor = (valueChannel, swapped = false)=>{
|
|
76
|
+
if (!config.showTooltip) return false;
|
|
77
|
+
const dataValueChannel = swapped ? "y" : valueChannel;
|
|
78
|
+
const valueName = "x" === dataValueChannel ? xName : yName;
|
|
79
|
+
const categoryName = "x" === dataValueChannel ? yName : xName;
|
|
80
|
+
const valueItem = {
|
|
81
|
+
channel: valueChannel,
|
|
82
|
+
label: valueName,
|
|
83
|
+
text: formatValue ? (point)=>formatChannel(point, valueChannel) : void 0
|
|
84
|
+
};
|
|
85
|
+
const categoryChannel = "x" === valueChannel ? "y" : "x";
|
|
86
|
+
const categoryItem = {
|
|
87
|
+
channel: categoryChannel,
|
|
88
|
+
label: categoryName
|
|
89
|
+
};
|
|
90
|
+
return {
|
|
91
|
+
...tooltipBase,
|
|
92
|
+
items: "x" === valueChannel ? [
|
|
93
|
+
valueItem,
|
|
94
|
+
categoryItem
|
|
95
|
+
] : [
|
|
96
|
+
categoryItem,
|
|
97
|
+
valueItem
|
|
98
|
+
]
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
const polarTooltip = ()=>{
|
|
102
|
+
if (!config.showTooltip) return false;
|
|
103
|
+
return {
|
|
104
|
+
...tooltipBase,
|
|
105
|
+
items: [
|
|
106
|
+
{
|
|
107
|
+
id: "value",
|
|
108
|
+
label: yName,
|
|
109
|
+
text: (point)=>{
|
|
110
|
+
const row = point.datum.data;
|
|
111
|
+
const value = getY(row);
|
|
112
|
+
return formatValue ? formatValue(value) : String(value);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
]
|
|
116
|
+
};
|
|
117
|
+
};
|
|
118
|
+
const valueAxis = {
|
|
119
|
+
scale: scaleLinear,
|
|
120
|
+
nice: true,
|
|
121
|
+
grid: config.grid,
|
|
122
|
+
axis: {
|
|
123
|
+
label: config.yLabel,
|
|
124
|
+
ticks: valueTicks
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
const xAxis = resolveXAxis(config.data, getX, config.xLabel);
|
|
128
|
+
return {
|
|
129
|
+
data: config.data,
|
|
130
|
+
getX,
|
|
131
|
+
getY,
|
|
132
|
+
getSeries,
|
|
133
|
+
stacked: config.stacked,
|
|
134
|
+
points: config.points,
|
|
135
|
+
curve: config.smooth ? d3Curve(curveMonotoneX) : void 0,
|
|
136
|
+
grid: config.grid,
|
|
137
|
+
xLabel: config.xLabel,
|
|
138
|
+
yLabel: config.yLabel,
|
|
139
|
+
valueTicks,
|
|
140
|
+
valueAxis,
|
|
141
|
+
xAxis,
|
|
142
|
+
bandAxis: {
|
|
143
|
+
scale: ()=>scaleBand().padding(0.3),
|
|
144
|
+
axis: {
|
|
145
|
+
label: config.xLabel
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
tooltipFor,
|
|
149
|
+
polarTooltip,
|
|
150
|
+
shared: {
|
|
151
|
+
color: showLegend ? {
|
|
152
|
+
legend: colorLegend({
|
|
153
|
+
label: config.legendLabel
|
|
154
|
+
})
|
|
155
|
+
} : void 0,
|
|
156
|
+
animate: config.animate
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
function warnOnSeriesOverflow(data, getColorIdentity) {
|
|
161
|
+
const isProduction = "undefined" != typeof process && process.env?.NODE_ENV === "production";
|
|
162
|
+
if (null == getColorIdentity || isProduction) return;
|
|
163
|
+
const distinct = new Set(data.map((datum)=>String(getColorIdentity(datum))));
|
|
164
|
+
if (distinct.size > MAX_SERIES) console.warn(`Chart: ${distinct.size} distinct colors exceeds the ${MAX_SERIES}-color palette; everything beyond the sixth reuses an earlier color and cannot be told apart. Group the long tail into an “Other” bucket, or split into small multiples.`);
|
|
165
|
+
}
|
|
166
|
+
function buildLine(build) {
|
|
167
|
+
const { data, getX, getY, getSeries } = build;
|
|
168
|
+
return defineChartSpec({
|
|
169
|
+
marks: [
|
|
170
|
+
lineY(data, {
|
|
171
|
+
x: getX,
|
|
172
|
+
y: getY,
|
|
173
|
+
z: getSeries,
|
|
174
|
+
color: getSeries,
|
|
175
|
+
points: build.points,
|
|
176
|
+
curve: build.curve,
|
|
177
|
+
stroke: null == getSeries ? SERIES_1_PAINT : void 0
|
|
178
|
+
})
|
|
179
|
+
],
|
|
180
|
+
x: build.xAxis,
|
|
181
|
+
y: build.valueAxis,
|
|
182
|
+
...build.shared,
|
|
183
|
+
tooltip: build.tooltipFor("y")
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
function buildArea(build) {
|
|
187
|
+
const { data, getX, getY, getSeries } = build;
|
|
188
|
+
const isStacked = build.stacked ?? true;
|
|
189
|
+
return defineChartSpec({
|
|
190
|
+
marks: [
|
|
191
|
+
areaY(data, {
|
|
192
|
+
x: getX,
|
|
193
|
+
...null != getSeries && isStacked ? {
|
|
194
|
+
y: getY
|
|
195
|
+
} : {
|
|
196
|
+
y1: 0,
|
|
197
|
+
y2: getY
|
|
198
|
+
},
|
|
199
|
+
z: getSeries,
|
|
200
|
+
color: getSeries,
|
|
201
|
+
curve: build.curve,
|
|
202
|
+
fill: null == getSeries ? SERIES_1_PAINT : void 0,
|
|
203
|
+
fillOpacity: null != getSeries && isStacked ? 0.85 : 0.25,
|
|
204
|
+
stroke: null == getSeries ? SERIES_1_PAINT : SERIES_STROKE_FROM_COLOR,
|
|
205
|
+
strokeWidth: 2
|
|
206
|
+
})
|
|
207
|
+
],
|
|
208
|
+
x: build.xAxis,
|
|
209
|
+
y: build.valueAxis,
|
|
210
|
+
...build.shared,
|
|
211
|
+
tooltip: build.tooltipFor("y")
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
function barLayout(hasSeries, isStacked) {
|
|
215
|
+
if (!hasSeries) return;
|
|
216
|
+
return isStacked ? stack() : group({
|
|
217
|
+
padding: 0.15
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
function buildBars(build, horizontal) {
|
|
221
|
+
const { data, getX, getY, getSeries } = build;
|
|
222
|
+
const isStacked = build.stacked ?? false;
|
|
223
|
+
const barOptions = {
|
|
224
|
+
z: getSeries,
|
|
225
|
+
color: getSeries,
|
|
226
|
+
fill: null == getSeries ? SERIES_1_PAINT : void 0,
|
|
227
|
+
layout: barLayout(null != getSeries, isStacked),
|
|
228
|
+
radius: null != getSeries && isStacked ? 0 : 4
|
|
229
|
+
};
|
|
230
|
+
if (horizontal) return defineChartSpec({
|
|
231
|
+
marks: [
|
|
232
|
+
barX(data, {
|
|
233
|
+
x: getY,
|
|
234
|
+
y: getX,
|
|
235
|
+
...barOptions
|
|
236
|
+
})
|
|
237
|
+
],
|
|
238
|
+
x: {
|
|
239
|
+
scale: scaleLinear,
|
|
240
|
+
nice: true,
|
|
241
|
+
grid: build.grid,
|
|
242
|
+
axis: {
|
|
243
|
+
label: build.yLabel,
|
|
244
|
+
ticks: build.valueTicks
|
|
245
|
+
}
|
|
246
|
+
},
|
|
247
|
+
y: build.bandAxis,
|
|
248
|
+
...build.shared,
|
|
249
|
+
tooltip: build.tooltipFor("x", true)
|
|
250
|
+
});
|
|
251
|
+
return defineChartSpec({
|
|
252
|
+
marks: [
|
|
253
|
+
barY(data, {
|
|
254
|
+
x: getX,
|
|
255
|
+
y: getY,
|
|
256
|
+
...barOptions
|
|
257
|
+
})
|
|
258
|
+
],
|
|
259
|
+
x: build.bandAxis,
|
|
260
|
+
y: build.valueAxis,
|
|
261
|
+
...build.shared,
|
|
262
|
+
tooltip: build.tooltipFor("y")
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
function buildScatter(build) {
|
|
266
|
+
const { data, getX, getY, getSeries } = build;
|
|
267
|
+
return defineChartSpec({
|
|
268
|
+
marks: [
|
|
269
|
+
dot(data, {
|
|
270
|
+
x: getX,
|
|
271
|
+
y: getY,
|
|
272
|
+
z: getSeries,
|
|
273
|
+
color: getSeries,
|
|
274
|
+
r: 4,
|
|
275
|
+
fill: null == getSeries ? SERIES_1_PAINT : void 0
|
|
276
|
+
})
|
|
277
|
+
],
|
|
278
|
+
x: {
|
|
279
|
+
...build.xAxis,
|
|
280
|
+
grid: build.grid
|
|
281
|
+
},
|
|
282
|
+
y: build.valueAxis,
|
|
283
|
+
...build.shared,
|
|
284
|
+
tooltip: build.tooltipFor("y")
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
function buildPolar(build, donut) {
|
|
288
|
+
const { data, getX, getY } = build;
|
|
289
|
+
const sliceLabel = (slice)=>String(getX(slice.data));
|
|
290
|
+
const slices = pie().sort(null).padAngle(0.02).value((datum)=>getY(datum))([
|
|
291
|
+
...data
|
|
292
|
+
]);
|
|
293
|
+
return defineChartSpec({
|
|
294
|
+
x: null,
|
|
295
|
+
y: null,
|
|
296
|
+
marks: [
|
|
297
|
+
polar({
|
|
298
|
+
inset: POLAR_INSET,
|
|
299
|
+
marks: [
|
|
300
|
+
radialArc(slices, {
|
|
301
|
+
startAngle: "startAngle",
|
|
302
|
+
endAngle: "endAngle",
|
|
303
|
+
padAngle: "padAngle",
|
|
304
|
+
innerRadius: donut ? ({ radius })=>radius * DONUT_INNER_RADIUS_RATIO : 0,
|
|
305
|
+
cornerRadius: 2,
|
|
306
|
+
z: sliceLabel,
|
|
307
|
+
color: sliceLabel
|
|
308
|
+
})
|
|
309
|
+
]
|
|
310
|
+
})
|
|
311
|
+
],
|
|
312
|
+
...build.shared,
|
|
313
|
+
tooltip: build.polarTooltip()
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
function buildChartDefinition(config) {
|
|
317
|
+
const build = resolveBuild(config);
|
|
318
|
+
switch(config.type){
|
|
319
|
+
case "area":
|
|
320
|
+
return buildArea(build);
|
|
321
|
+
case "bar":
|
|
322
|
+
return buildBars(build, false);
|
|
323
|
+
case "bar-horizontal":
|
|
324
|
+
return buildBars(build, true);
|
|
325
|
+
case "scatter":
|
|
326
|
+
return buildScatter(build);
|
|
327
|
+
case "pie":
|
|
328
|
+
return buildPolar(build, false);
|
|
329
|
+
case "donut":
|
|
330
|
+
return buildPolar(build, true);
|
|
331
|
+
default:
|
|
332
|
+
return buildLine(build);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
function chart_Chart({ type = "line", data, x, y, series, stacked, points = false, smooth = false, grid = true, legend, legendLabel, xLabel, yLabel, formatValue, height, aspectRatio, initialWidth = 640, animate = true, tooltip = true, ariaLabel, ariaDescription, className, onSelect }) {
|
|
336
|
+
const { root, tooltip: tooltipSlot } = chartVariants();
|
|
337
|
+
const tooltipClassName = tooltipSlot();
|
|
338
|
+
const definition = useMemo(()=>buildChartDefinition({
|
|
339
|
+
type,
|
|
340
|
+
data,
|
|
341
|
+
x,
|
|
342
|
+
y,
|
|
343
|
+
series,
|
|
344
|
+
stacked,
|
|
345
|
+
points,
|
|
346
|
+
smooth,
|
|
347
|
+
grid,
|
|
348
|
+
legend,
|
|
349
|
+
legendLabel,
|
|
350
|
+
xLabel,
|
|
351
|
+
yLabel,
|
|
352
|
+
formatValue,
|
|
353
|
+
animate,
|
|
354
|
+
showTooltip: tooltip,
|
|
355
|
+
tooltipClassName
|
|
356
|
+
}), [
|
|
357
|
+
type,
|
|
358
|
+
data,
|
|
359
|
+
x,
|
|
360
|
+
y,
|
|
361
|
+
series,
|
|
362
|
+
stacked,
|
|
363
|
+
points,
|
|
364
|
+
smooth,
|
|
365
|
+
grid,
|
|
366
|
+
legend,
|
|
367
|
+
legendLabel,
|
|
368
|
+
xLabel,
|
|
369
|
+
yLabel,
|
|
370
|
+
formatValue,
|
|
371
|
+
animate,
|
|
372
|
+
tooltip,
|
|
373
|
+
tooltipClassName
|
|
374
|
+
]);
|
|
375
|
+
const isPolar = "pie" === type || "donut" === type;
|
|
376
|
+
const handleSelect = onSelect ? (point)=>{
|
|
377
|
+
if (null == point) return void onSelect(null);
|
|
378
|
+
onSelect(isPolar ? point.datum.data : point.datum);
|
|
379
|
+
} : void 0;
|
|
380
|
+
return /*#__PURE__*/ jsx(Chart, {
|
|
381
|
+
ariaDescription: ariaDescription,
|
|
382
|
+
ariaLabel: ariaLabel,
|
|
383
|
+
aspectRatio: null == height ? aspectRatio ?? 16 / 9 : void 0,
|
|
384
|
+
className: root({
|
|
385
|
+
className
|
|
386
|
+
}),
|
|
387
|
+
definition: definition,
|
|
388
|
+
height: height,
|
|
389
|
+
initialWidth: initialWidth,
|
|
390
|
+
onSelect: handleSelect
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
export { chart_Chart as Chart };
|