@quantumwake/terminal-ux-dashboard-components 0.1.19 → 0.1.21
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/index.cjs +141 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +43 -3
- package/dist/index.d.ts +43 -3
- package/dist/index.js +137 -28
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -276,8 +276,57 @@ var DEFAULT_CHART_STYLE = {
|
|
|
276
276
|
titleAlign: "left",
|
|
277
277
|
titleBold: false,
|
|
278
278
|
titleBackground: "",
|
|
279
|
-
titleColor: ""
|
|
279
|
+
titleColor: "",
|
|
280
|
+
// Chart frame + series color model.
|
|
281
|
+
height: 0,
|
|
282
|
+
margin: null,
|
|
283
|
+
maxXTicks: 0,
|
|
284
|
+
maxYTicks: 0,
|
|
285
|
+
areaOpacity: 0.15,
|
|
286
|
+
barLabels: true,
|
|
287
|
+
seriesColors: []
|
|
280
288
|
};
|
|
289
|
+
var DEFAULT_SERIES_COLORS = [
|
|
290
|
+
"#3987e5",
|
|
291
|
+
// blue
|
|
292
|
+
"#d95926",
|
|
293
|
+
// orange
|
|
294
|
+
"#199e70",
|
|
295
|
+
// aqua
|
|
296
|
+
"#c98500",
|
|
297
|
+
// yellow
|
|
298
|
+
"#d55181",
|
|
299
|
+
// magenta
|
|
300
|
+
"#008300",
|
|
301
|
+
// green
|
|
302
|
+
"#9085e9",
|
|
303
|
+
// violet
|
|
304
|
+
"#e66767"
|
|
305
|
+
// red
|
|
306
|
+
];
|
|
307
|
+
var SERIES_OVERFLOW_COLOR = "#707078";
|
|
308
|
+
var seriesColor = (i, style) => {
|
|
309
|
+
const s = withStyleDefaults(style);
|
|
310
|
+
const palette = s.seriesColors.length ? s.seriesColors : DEFAULT_SERIES_COLORS;
|
|
311
|
+
return i < palette.length ? palette[i] : SERIES_OVERFLOW_COLOR;
|
|
312
|
+
};
|
|
313
|
+
var chartSizing = (style, defaultMargin) => {
|
|
314
|
+
const s = withStyleDefaults(style);
|
|
315
|
+
return {
|
|
316
|
+
frameClass: s.height > 0 ? "w-full" : "h-full w-full min-h-[160px]",
|
|
317
|
+
frameStyle: s.height > 0 ? { height: s.height } : {},
|
|
318
|
+
margin: { ...defaultMargin, ...s.margin || {} }
|
|
319
|
+
};
|
|
320
|
+
};
|
|
321
|
+
function thinTicks(values, max) {
|
|
322
|
+
if (max <= 0 || values.length <= max) return void 0;
|
|
323
|
+
if (max === 1) return [values[values.length - 1]];
|
|
324
|
+
const picked = [];
|
|
325
|
+
for (let i = 0; i < max; i++) {
|
|
326
|
+
picked.push(values[Math.round(i * (values.length - 1) / (max - 1))]);
|
|
327
|
+
}
|
|
328
|
+
return [...new Set(picked)];
|
|
329
|
+
}
|
|
281
330
|
var LEGEND_ANCHORS = ["right", "top-left", "top-right", "bottom-left", "bottom-right", "none"];
|
|
282
331
|
var withStyleDefaults = (style) => ({
|
|
283
332
|
...DEFAULT_CHART_STYLE,
|
|
@@ -527,27 +576,37 @@ function makeAxis(style, axis, columnName, opts2 = {}) {
|
|
|
527
576
|
out.tickRotation = rotate;
|
|
528
577
|
out.format = (v) => formatVal(v, s, numeric);
|
|
529
578
|
}
|
|
579
|
+
const maxTicks = isX ? s.maxXTicks : s.maxYTicks;
|
|
580
|
+
if (numeric && maxTicks > 0) out.tickValues = maxTicks;
|
|
530
581
|
return out;
|
|
531
582
|
}
|
|
532
|
-
function BarView({ records, groupColumn, valueColumn, aggFn = "count", data: presetData, style }) {
|
|
583
|
+
function BarView({ records, groupColumn, valueColumn, aggFn = "count", data: presetData, layout = "vertical", style }) {
|
|
533
584
|
const computed = react.useMemo(() => {
|
|
534
585
|
if (presetData || !records) return [];
|
|
535
586
|
const groups = groupBy(records, groupColumn);
|
|
536
587
|
return Object.entries(groups).map(([key, recs]) => ({ group: key, value: aggregate(recs, valueColumn, aggFn) })).sort((a, b) => b.value - a.value).slice(0, 50);
|
|
537
588
|
}, [records, groupColumn, valueColumn, aggFn, presetData]);
|
|
538
589
|
const data = presetData || computed;
|
|
539
|
-
|
|
590
|
+
const s = withStyleDefaults(style);
|
|
591
|
+
const { frameClass, frameStyle, margin } = chartSizing(style, { top: 20, right: 20, bottom: 60, left: 60 });
|
|
592
|
+
const horizontal = layout === "horizontal";
|
|
593
|
+
const plotted = horizontal ? [...data].reverse() : data;
|
|
594
|
+
const axisBottom = horizontal ? makeAxis(style, "x", valueColumn, { numeric: true }) : makeAxis(style, "x", groupColumn);
|
|
595
|
+
const axisLeft = horizontal ? makeAxis(style, "y", groupColumn) : makeAxis(style, "y", valueColumn, { numeric: true });
|
|
596
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: frameClass, style: frameStyle, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
540
597
|
bar.ResponsiveBar,
|
|
541
598
|
{
|
|
542
|
-
data,
|
|
599
|
+
data: plotted,
|
|
543
600
|
keys: ["value"],
|
|
544
601
|
indexBy: "group",
|
|
545
|
-
|
|
602
|
+
layout,
|
|
603
|
+
margin,
|
|
546
604
|
padding: 0.3,
|
|
547
|
-
colors: ["rgba(74, 222, 128, 0.8)"],
|
|
605
|
+
colors: [s.seriesColors[0] || "rgba(74, 222, 128, 0.8)"],
|
|
548
606
|
borderColor: { from: "color", modifiers: [["darker", 1.6]] },
|
|
549
|
-
axisBottom
|
|
550
|
-
axisLeft
|
|
607
|
+
axisBottom,
|
|
608
|
+
axisLeft,
|
|
609
|
+
enableLabel: s.barLabels,
|
|
551
610
|
labelSkipWidth: 12,
|
|
552
611
|
labelSkipHeight: 12,
|
|
553
612
|
labelTextColor: { from: "color", modifiers: [["darker", 3]] },
|
|
@@ -568,16 +627,19 @@ function PieView({ records, groupColumn, data: presetData, style }) {
|
|
|
568
627
|
}, [records, groupColumn, presetData]);
|
|
569
628
|
const data = presetData || computed;
|
|
570
629
|
const legend = legendConfig(style);
|
|
571
|
-
|
|
630
|
+
const s = withStyleDefaults(style);
|
|
631
|
+
const { frameClass, frameStyle, margin } = chartSizing(style, { top: 20, right: 120, bottom: 20, left: 20 });
|
|
632
|
+
const colorById = new Map(data.map((d, i) => [d.id, seriesColor(i, s)]));
|
|
633
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: frameClass, style: frameStyle, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
572
634
|
pie.ResponsivePie,
|
|
573
635
|
{
|
|
574
636
|
data,
|
|
575
|
-
margin
|
|
637
|
+
margin,
|
|
576
638
|
innerRadius: 0.4,
|
|
577
639
|
padAngle: 1,
|
|
578
640
|
cornerRadius: 3,
|
|
579
641
|
activeOuterRadiusOffset: 8,
|
|
580
|
-
colors:
|
|
642
|
+
colors: ((d) => colorById.get(d.id)),
|
|
581
643
|
borderWidth: 1,
|
|
582
644
|
borderColor: { from: "color", modifiers: [["darker", 0.2]] },
|
|
583
645
|
arcLinkLabelsSkipAngle: 10,
|
|
@@ -590,7 +652,7 @@ function PieView({ records, groupColumn, data: presetData, style }) {
|
|
|
590
652
|
}
|
|
591
653
|
) });
|
|
592
654
|
}
|
|
593
|
-
function LineView({ records, xColumn, yColumn, data: presetData, style }) {
|
|
655
|
+
function LineView({ records, xColumn, yColumn, data: presetData, dashedIds, style }) {
|
|
594
656
|
const computed = react.useMemo(() => {
|
|
595
657
|
if (presetData || !records) return [];
|
|
596
658
|
const sorted = [...records].filter((r) => r[xColumn] != null && r[yColumn] != null).sort((a, b) => {
|
|
@@ -604,29 +666,69 @@ function LineView({ records, xColumn, yColumn, data: presetData, style }) {
|
|
|
604
666
|
}];
|
|
605
667
|
}, [records, xColumn, yColumn, presetData]);
|
|
606
668
|
const data = presetData || computed;
|
|
607
|
-
|
|
669
|
+
const s = withStyleDefaults(style);
|
|
670
|
+
const { frameClass, frameStyle, margin } = chartSizing(style, { top: 20, right: 20, bottom: 60, left: 60 });
|
|
671
|
+
const colorById = new Map(data.map((serie, i) => [
|
|
672
|
+
serie.id,
|
|
673
|
+
s.seriesColors.length || data.length > 1 ? seriesColor(i, s) : "rgba(96, 165, 250, 0.9)"
|
|
674
|
+
]));
|
|
675
|
+
const longest = data.reduce((a, b) => b.data.length > a.data.length ? b : a, { id: "", data: [] });
|
|
676
|
+
const tickValues = thinTicks(longest.data.map((d) => d.x), s.maxXTicks);
|
|
677
|
+
const dashed = new Set(dashedIds || []);
|
|
678
|
+
const linesLayer = ({ series, lineGenerator }) => /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: series.map((serie) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
679
|
+
"path",
|
|
680
|
+
{
|
|
681
|
+
d: lineGenerator(serie.data.map((d) => d.position)),
|
|
682
|
+
fill: "none",
|
|
683
|
+
stroke: serie.color,
|
|
684
|
+
strokeWidth: 2,
|
|
685
|
+
strokeLinecap: "round",
|
|
686
|
+
strokeDasharray: dashed.has(String(serie.id)) ? "1 5" : void 0
|
|
687
|
+
},
|
|
688
|
+
serie.id
|
|
689
|
+
)) });
|
|
690
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: frameClass, style: frameStyle, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
608
691
|
line.ResponsiveLine,
|
|
609
692
|
{
|
|
610
693
|
data,
|
|
611
|
-
margin
|
|
694
|
+
margin,
|
|
612
695
|
xScale: { type: "point" },
|
|
613
696
|
yScale: { type: "linear", min: "auto", max: "auto" },
|
|
614
697
|
curve: "monotoneX",
|
|
615
|
-
enableArea:
|
|
616
|
-
areaOpacity:
|
|
617
|
-
colors:
|
|
618
|
-
pointSize:
|
|
698
|
+
enableArea: s.areaOpacity > 0,
|
|
699
|
+
areaOpacity: s.areaOpacity,
|
|
700
|
+
colors: ((serie) => colorById.get(serie.id)),
|
|
701
|
+
pointSize: 0,
|
|
619
702
|
pointColor: { theme: "background" },
|
|
620
703
|
pointBorderWidth: 2,
|
|
621
704
|
pointBorderColor: { from: "serieColor" },
|
|
622
705
|
enableGridX: false,
|
|
623
|
-
axisBottom: makeAxis(style, "x", xColumn),
|
|
706
|
+
axisBottom: { ...makeAxis(style, "x", xColumn), ...tickValues ? { tickValues } : {} },
|
|
624
707
|
axisLeft: makeAxis(style, "y", yColumn, { numeric: true }),
|
|
625
708
|
useMesh: true,
|
|
709
|
+
layers: ["grid", "markers", "axes", "areas", linesLayer, "crosshair", "slices", "mesh", "legends"],
|
|
626
710
|
theme: buildNivoTheme(style)
|
|
627
711
|
}
|
|
628
712
|
) });
|
|
629
713
|
}
|
|
714
|
+
function SparklineView({ data, height = 56, color = "#3987e5" }) {
|
|
715
|
+
const gradientId = react.useId();
|
|
716
|
+
const width = 260;
|
|
717
|
+
const pts = data && data.length ? data : [0];
|
|
718
|
+
const max = Math.max(...pts, 1);
|
|
719
|
+
const dx = pts.length > 1 ? width / (pts.length - 1) : width;
|
|
720
|
+
const xy = (v, i) => [i * dx, height - v / max * (height - 4) - 2];
|
|
721
|
+
const line = pts.map((v, i) => `${i === 0 ? "M" : "L"} ${xy(v, i)[0].toFixed(1)} ${xy(v, i)[1].toFixed(1)}`).join(" ");
|
|
722
|
+
const area = `${line} L ${width} ${height} L 0 ${height} Z`;
|
|
723
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: `0 0 ${width} ${height}`, height, className: "w-full", preserveAspectRatio: "none", children: [
|
|
724
|
+
/* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsxs("linearGradient", { id: gradientId, x1: "0", y1: "0", x2: "0", y2: "1", children: [
|
|
725
|
+
/* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "0%", stopColor: color, stopOpacity: "0.25" }),
|
|
726
|
+
/* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "100%", stopColor: color, stopOpacity: "0" })
|
|
727
|
+
] }) }),
|
|
728
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: area, fill: `url(#${gradientId})` }),
|
|
729
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: line, fill: "none", stroke: color, strokeWidth: "2", vectorEffect: "non-scaling-stroke" })
|
|
730
|
+
] });
|
|
731
|
+
}
|
|
630
732
|
function ScatterView({ records, xColumn, yColumn, data: presetData, style }) {
|
|
631
733
|
const computed = react.useMemo(() => {
|
|
632
734
|
if (presetData || !records) return [];
|
|
@@ -634,14 +736,20 @@ function ScatterView({ records, xColumn, yColumn, data: presetData, style }) {
|
|
|
634
736
|
return [{ id: `${xColumn} vs ${yColumn}`, data: points }];
|
|
635
737
|
}, [records, xColumn, yColumn, presetData]);
|
|
636
738
|
const data = presetData || computed;
|
|
637
|
-
|
|
739
|
+
const s = withStyleDefaults(style);
|
|
740
|
+
const { frameClass, frameStyle, margin } = chartSizing(style, { top: 20, right: 20, bottom: 60, left: 60 });
|
|
741
|
+
const colorById = new Map(data.map((serie, i) => [
|
|
742
|
+
serie.id,
|
|
743
|
+
s.seriesColors.length || data.length > 1 ? seriesColor(i, s) : "rgba(167, 139, 250, 0.7)"
|
|
744
|
+
]));
|
|
745
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: frameClass, style: frameStyle, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
638
746
|
scatterplot.ResponsiveScatterPlot,
|
|
639
747
|
{
|
|
640
748
|
data,
|
|
641
|
-
margin
|
|
749
|
+
margin,
|
|
642
750
|
xScale: { type: "linear", min: "auto", max: "auto" },
|
|
643
751
|
yScale: { type: "linear", min: "auto", max: "auto" },
|
|
644
|
-
colors:
|
|
752
|
+
colors: ((serie) => colorById.get(serie.serieId ?? serie.id ?? "")),
|
|
645
753
|
nodeSize: 6,
|
|
646
754
|
axisBottom: makeAxis(style, "x", xColumn, { numeric: true }),
|
|
647
755
|
axisLeft: makeAxis(style, "y", yColumn, { numeric: true }),
|
|
@@ -737,8 +845,8 @@ function HeatmapView({
|
|
|
737
845
|
if (!data.length || !data[0].data.length) {
|
|
738
846
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-8 text-center text-midnight-text-muted", children: "Not enough distinct values for a heatmap" });
|
|
739
847
|
}
|
|
740
|
-
const margin = showTotals ? { top: 60, right: 70, bottom: 60, left: 100 } : { top: 60, right: 20, bottom: 20, left: 100 };
|
|
741
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className:
|
|
848
|
+
const { frameClass, frameStyle, margin } = chartSizing(style, showTotals ? { top: 60, right: 70, bottom: 60, left: 100 } : { top: 60, right: 20, bottom: 20, left: 100 });
|
|
849
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: frameClass, style: frameStyle, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
742
850
|
heatmap.ResponsiveHeatMap,
|
|
743
851
|
{
|
|
744
852
|
data,
|
|
@@ -892,11 +1000,12 @@ function HeatmapPlusView({
|
|
|
892
1000
|
}
|
|
893
1001
|
const { nivoData, t } = built;
|
|
894
1002
|
const tAt = (serieId, x) => t.get(cellKey(serieId, x)) ?? 0;
|
|
895
|
-
|
|
1003
|
+
const { frameClass, frameStyle, margin } = chartSizing(style, { top: 60, right: 20, bottom: showMargins ? 60 : 20, left: 100 });
|
|
1004
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: frameClass, style: frameStyle, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
896
1005
|
heatmap.ResponsiveHeatMap,
|
|
897
1006
|
{
|
|
898
1007
|
data: nivoData,
|
|
899
|
-
margin
|
|
1008
|
+
margin,
|
|
900
1009
|
valueFormat: ((v) => fmtNum2(v)),
|
|
901
1010
|
axisTop: { tickSize: 5, tickPadding: 5, tickRotation: s.xTickRotation, legend: s.showXLegend ? s.xAxisLabel || colColumn : "", legendPosition: s.xLegendPosition, legendOffset: -50 },
|
|
902
1011
|
axisLeft: { tickSize: 5, tickPadding: 5, legend: s.showYLegend ? s.yAxisLabel || rowColumn : "", legendPosition: s.yLegendPosition, legendOffset: -80 },
|
|
@@ -2912,6 +3021,7 @@ exports.BarView = BarView;
|
|
|
2912
3021
|
exports.ChartBuilder = ChartBuilder;
|
|
2913
3022
|
exports.ChartStyleControls = ChartStyleControls;
|
|
2914
3023
|
exports.DEFAULT_CHART_STYLE = DEFAULT_CHART_STYLE;
|
|
3024
|
+
exports.DEFAULT_SERIES_COLORS = DEFAULT_SERIES_COLORS;
|
|
2915
3025
|
exports.DashboardProvider = DashboardProvider;
|
|
2916
3026
|
exports.DashboardRenderer = DashboardRenderer;
|
|
2917
3027
|
exports.DataExplorer = DataExplorer;
|
|
@@ -2925,13 +3035,16 @@ exports.MetricView = MetricView;
|
|
|
2925
3035
|
exports.PanelChart = PanelChart;
|
|
2926
3036
|
exports.PieView = PieView;
|
|
2927
3037
|
exports.PivotView = PivotView;
|
|
3038
|
+
exports.SERIES_OVERFLOW_COLOR = SERIES_OVERFLOW_COLOR;
|
|
2928
3039
|
exports.ScatterView = ScatterView;
|
|
3040
|
+
exports.SparklineView = SparklineView;
|
|
2929
3041
|
exports.SqlConsole = SqlConsole;
|
|
2930
3042
|
exports.aggExpr = aggExpr;
|
|
2931
3043
|
exports.aggregate = aggregate;
|
|
2932
3044
|
exports.axisLegend = axisLegend;
|
|
2933
3045
|
exports.buildChartSQL = buildChartSQL;
|
|
2934
3046
|
exports.buildNivoTheme = buildNivoTheme;
|
|
3047
|
+
exports.chartSizing = chartSizing;
|
|
2935
3048
|
exports.compileWhere = compileWhere;
|
|
2936
3049
|
exports.groupBy = groupBy;
|
|
2937
3050
|
exports.heatColor = heatColor;
|
|
@@ -2940,7 +3053,9 @@ exports.legendConfig = legendConfig;
|
|
|
2940
3053
|
exports.normalizeCells = normalizeCells;
|
|
2941
3054
|
exports.qIdent = qIdent;
|
|
2942
3055
|
exports.qLit = qLit;
|
|
3056
|
+
exports.seriesColor = seriesColor;
|
|
2943
3057
|
exports.shapeChartData = shapeChartData;
|
|
3058
|
+
exports.thinTicks = thinTicks;
|
|
2944
3059
|
exports.useCapabilities = useCapabilities;
|
|
2945
3060
|
exports.useDashboard = useDashboard;
|
|
2946
3061
|
exports.withStyleDefaults = withStyleDefaults;
|