@quantumwake/terminal-ux-dashboard-components 0.1.18 → 0.1.19
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/README.md +10 -11
- package/dist/index.cjs +419 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +75 -8
- package/dist/index.d.ts +75 -8
- package/dist/index.js +416 -13
- package/dist/index.js.map +1 -1
- package/package.json +4 -2
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createContext, useContext, useMemo, useState, useEffect, useRef, useCallback, Suspense } from 'react';
|
|
2
2
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
|
+
import { interpolateRdYlGn } from 'd3-scale-chromatic';
|
|
3
4
|
import { ResponsiveBar } from '@nivo/bar';
|
|
4
5
|
import { ResponsivePie } from '@nivo/pie';
|
|
5
6
|
import { ResponsiveLine } from '@nivo/line';
|
|
@@ -8,7 +9,7 @@ import { ResponsiveHeatMap } from '@nivo/heatmap';
|
|
|
8
9
|
import PivotTableUI from 'react-pivottable/PivotTableUI';
|
|
9
10
|
import 'react-pivottable/pivottable.css';
|
|
10
11
|
import { TerminalSlider, TerminalInput, TerminalToggle, TerminalSelect } from '@quantumwake/terminal-ux-components';
|
|
11
|
-
import { Loader2, Play, ChevronDown, AlertCircle, Rows3, BarChart3, PieChart, TrendingUp, ScatterChart, LayoutGrid, Code, Sparkles, Terminal, RefreshCw, Minimize2, Maximize2, Plus, Save, FolderOpen, Trash2, X, Filter, Database, Send, GripVertical } from 'lucide-react';
|
|
12
|
+
import { Loader2, Play, ChevronDown, AlertCircle, Rows3, BarChart3, PieChart, TrendingUp, ScatterChart, LayoutGrid, Grid3x3, Code, Sparkles, Terminal, RefreshCw, Minimize2, Maximize2, Plus, Save, FolderOpen, Trash2, X, Filter, Database, Send, GripVertical } from 'lucide-react';
|
|
12
13
|
import CodeMirror, { EditorView, Prec, keymap } from '@uiw/react-codemirror';
|
|
13
14
|
import { sql, PostgreSQL, schemaCompletionSource, keywordCompletionSource } from '@codemirror/lang-sql';
|
|
14
15
|
import { snippetCompletion, completeFromList, autocompletion, acceptCompletion } from '@codemirror/autocomplete';
|
|
@@ -75,6 +76,8 @@ var aggExpr = (agg, col) => {
|
|
|
75
76
|
return `MIN(${qNum(col)})`;
|
|
76
77
|
case "max":
|
|
77
78
|
return `MAX(${qNum(col)})`;
|
|
79
|
+
case "median":
|
|
80
|
+
return `MEDIAN(${qNum(col)})`;
|
|
78
81
|
default:
|
|
79
82
|
return "COUNT(*)";
|
|
80
83
|
}
|
|
@@ -112,7 +115,10 @@ var buildChartSQL = ({
|
|
|
112
115
|
xFields = [],
|
|
113
116
|
yFields = [],
|
|
114
117
|
valueField = null,
|
|
115
|
-
filters = []
|
|
118
|
+
filters = [],
|
|
119
|
+
labelStat,
|
|
120
|
+
colorStat,
|
|
121
|
+
blockField
|
|
116
122
|
}) => {
|
|
117
123
|
const where = compileWhere(filters);
|
|
118
124
|
const x = xFields[0]?.name;
|
|
@@ -149,6 +155,14 @@ var buildChartSQL = ({
|
|
|
149
155
|
const metric = valueField ? aggExpr(valueField.agg || "count", valueField.name) : "COUNT(*)";
|
|
150
156
|
return `SELECT ${qIdent(x)} AS r, ${qIdent(y)} AS c, ${metric} AS v FROM ${TABLE}${where} GROUP BY 1, 2`;
|
|
151
157
|
}
|
|
158
|
+
case "heatmap-plus": {
|
|
159
|
+
if (!x || !y) return null;
|
|
160
|
+
const col = valueField?.name;
|
|
161
|
+
const lv = col ? aggExpr(labelStat || valueField?.agg || "count", col) : "COUNT(*)";
|
|
162
|
+
const cv = col ? aggExpr(colorStat || labelStat || valueField?.agg || "count", col) : "COUNT(*)";
|
|
163
|
+
const blockSel = blockField ? `, ANY_VALUE(${qIdent(blockField)}) AS block` : "";
|
|
164
|
+
return `SELECT ${qIdent(x)} AS r, ${qIdent(y)} AS c, ${lv} AS lv, ${cv} AS cv${blockSel}, GROUPING(${qIdent(x)}) AS gr, GROUPING(${qIdent(y)}) AS gc FROM ${TABLE}${where} GROUP BY GROUPING SETS ((${qIdent(x)}, ${qIdent(y)}), (${qIdent(x)}), (${qIdent(y)}), ())`;
|
|
165
|
+
}
|
|
152
166
|
default:
|
|
153
167
|
return null;
|
|
154
168
|
}
|
|
@@ -197,6 +211,17 @@ var shapeChartData = (chartType, rows, { yFields = [] } = {}) => {
|
|
|
197
211
|
data: colKeys.map((ck) => ({ x: ck, y: cell[rk][ck] || 0 }))
|
|
198
212
|
}));
|
|
199
213
|
}
|
|
214
|
+
case "heatmap-plus": {
|
|
215
|
+
return rows.map((r) => ({
|
|
216
|
+
r: r.r == null ? null : String(r.r),
|
|
217
|
+
c: r.c == null ? null : String(r.c),
|
|
218
|
+
lv: Number(r.lv) || 0,
|
|
219
|
+
cv: Number(r.cv) || 0,
|
|
220
|
+
gr: Number(r.gr) || 0,
|
|
221
|
+
gc: Number(r.gc) || 0,
|
|
222
|
+
...r.block != null ? { block: String(r.block) } : {}
|
|
223
|
+
}));
|
|
224
|
+
}
|
|
200
225
|
default:
|
|
201
226
|
return [];
|
|
202
227
|
}
|
|
@@ -342,10 +367,73 @@ var aggregate = (records, column, fn) => {
|
|
|
342
367
|
return Math.min(...values.map(Number));
|
|
343
368
|
case "max":
|
|
344
369
|
return Math.max(...values.map(Number));
|
|
370
|
+
case "median": {
|
|
371
|
+
const nums = values.map(Number).filter((v) => !Number.isNaN(v)).sort((a, b) => a - b);
|
|
372
|
+
if (!nums.length) return 0;
|
|
373
|
+
const mid = Math.floor(nums.length / 2);
|
|
374
|
+
return nums.length % 2 ? nums[mid] : (nums[mid - 1] + nums[mid]) / 2;
|
|
375
|
+
}
|
|
345
376
|
default:
|
|
346
377
|
return records.length;
|
|
347
378
|
}
|
|
348
379
|
};
|
|
380
|
+
var HEAT_STATS = ["count", "sum", "avg", "min", "max", "median"];
|
|
381
|
+
var cellKey = (row, col) => `${row}\0${col}`;
|
|
382
|
+
var normalizePartition = (cells, method, vmin, vmax) => {
|
|
383
|
+
const out = /* @__PURE__ */ new Map();
|
|
384
|
+
const values = cells.map((c) => c.colorValue).filter((v) => Number.isFinite(v));
|
|
385
|
+
if (!values.length) return out;
|
|
386
|
+
if (method === "rank") {
|
|
387
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
388
|
+
for (const c of cells) {
|
|
389
|
+
const below = sorted.findIndex((v) => v >= c.colorValue);
|
|
390
|
+
const ties = sorted.filter((v) => v === c.colorValue).length;
|
|
391
|
+
out.set(cellKey(c.row, c.col), (below + 0.5 * ties) / sorted.length);
|
|
392
|
+
}
|
|
393
|
+
return out;
|
|
394
|
+
}
|
|
395
|
+
const lo = vmin ?? Math.min(...values);
|
|
396
|
+
const hi = vmax ?? Math.max(...values);
|
|
397
|
+
for (const c of cells) {
|
|
398
|
+
const t = hi === lo ? 0.5 : (c.colorValue - lo) / (hi - lo);
|
|
399
|
+
out.set(cellKey(c.row, c.col), Math.max(0, Math.min(1, t)));
|
|
400
|
+
}
|
|
401
|
+
return out;
|
|
402
|
+
};
|
|
403
|
+
var normalizeCells = (cells, { scope = "global", method = "linear", vmin, vmax } = {}) => {
|
|
404
|
+
const partitions = /* @__PURE__ */ new Map();
|
|
405
|
+
const partOf = (c) => {
|
|
406
|
+
switch (scope) {
|
|
407
|
+
case "row":
|
|
408
|
+
return `r:${c.row}`;
|
|
409
|
+
case "column":
|
|
410
|
+
return `c:${c.col}`;
|
|
411
|
+
case "block":
|
|
412
|
+
return c.block != null ? `b:${c.block}` : "global";
|
|
413
|
+
default:
|
|
414
|
+
return "global";
|
|
415
|
+
}
|
|
416
|
+
};
|
|
417
|
+
for (const c of cells) {
|
|
418
|
+
const k = partOf(c);
|
|
419
|
+
const part = partitions.get(k);
|
|
420
|
+
if (part) part.push(c);
|
|
421
|
+
else partitions.set(k, [c]);
|
|
422
|
+
}
|
|
423
|
+
const out = /* @__PURE__ */ new Map();
|
|
424
|
+
for (const part of partitions.values()) {
|
|
425
|
+
for (const [k, t] of normalizePartition(part, method, vmin, vmax)) out.set(k, t);
|
|
426
|
+
}
|
|
427
|
+
return out;
|
|
428
|
+
};
|
|
429
|
+
var heatColor = (t) => interpolateRdYlGn(Math.max(0, Math.min(1, t)));
|
|
430
|
+
var heatLabelColor = (t) => {
|
|
431
|
+
const m = heatColor(t).match(/\d+/g);
|
|
432
|
+
if (!m) return "#0f172a";
|
|
433
|
+
const [r, g, b] = m.map(Number);
|
|
434
|
+
const lum = 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
|
435
|
+
return lum > 140 ? "#0f172a" : "#f8fafc";
|
|
436
|
+
};
|
|
349
437
|
function MetricView({ records, config, value: presetValue }) {
|
|
350
438
|
const value = useMemo(() => {
|
|
351
439
|
if (presetValue != null) return presetValue;
|
|
@@ -661,6 +749,159 @@ function HeatmapView({
|
|
|
661
749
|
}
|
|
662
750
|
) });
|
|
663
751
|
}
|
|
752
|
+
var MAX_AXIS2 = 30;
|
|
753
|
+
var TOTAL_ID = "\u03A3";
|
|
754
|
+
var NULL = "(null)";
|
|
755
|
+
var fmtNum2 = (n) => {
|
|
756
|
+
if (typeof n !== "number" || Number.isNaN(n)) return "";
|
|
757
|
+
return Number.isInteger(n) ? n.toLocaleString() : n.toLocaleString(void 0, { maximumFractionDigits: 2 });
|
|
758
|
+
};
|
|
759
|
+
var orderIds2 = (ids, margin, order) => {
|
|
760
|
+
const sorted = [...ids];
|
|
761
|
+
if (order.endsWith("-desc")) sorted.sort((a, b) => (margin[b]?.lv ?? 0) - (margin[a]?.lv ?? 0));
|
|
762
|
+
else if (order.endsWith("-asc")) sorted.sort((a, b) => (margin[a]?.lv ?? 0) - (margin[b]?.lv ?? 0));
|
|
763
|
+
else sorted.sort();
|
|
764
|
+
return sorted;
|
|
765
|
+
};
|
|
766
|
+
function fromRecords(records, rowCol, colCol, valueCol, labelStat, colorStat, blockField) {
|
|
767
|
+
const col = valueCol || rowCol;
|
|
768
|
+
const statOf = (rs, s) => valueCol ? aggregate(rs, col, s) : rs.length;
|
|
769
|
+
const both = (rs) => ({ lv: statOf(rs, labelStat), cv: statOf(rs, colorStat) });
|
|
770
|
+
const byRow = groupBy(records, rowCol);
|
|
771
|
+
const rowIds = Object.keys(byRow);
|
|
772
|
+
const colIds = [...new Set(records.map((r) => String(r[colCol] ?? NULL)))];
|
|
773
|
+
const cells = {};
|
|
774
|
+
for (const rid of rowIds) {
|
|
775
|
+
cells[rid] = {};
|
|
776
|
+
const byCol2 = groupBy(byRow[rid], colCol);
|
|
777
|
+
for (const cid of colIds) {
|
|
778
|
+
const cellRows = byCol2[cid] || [];
|
|
779
|
+
const stat = both(cellRows);
|
|
780
|
+
if (blockField && cellRows.length) stat.block = String(cellRows[0][blockField] ?? NULL);
|
|
781
|
+
cells[rid][cid] = stat;
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
const rowMargin = {};
|
|
785
|
+
for (const rid of rowIds) rowMargin[rid] = both(byRow[rid]);
|
|
786
|
+
const colMargin = {};
|
|
787
|
+
const byCol = groupBy(records, colCol);
|
|
788
|
+
for (const cid of colIds) colMargin[cid] = both(byCol[cid] || []);
|
|
789
|
+
return { rowIds, colIds, cells, rowMargin, colMargin, grand: both(records) };
|
|
790
|
+
}
|
|
791
|
+
function fromData(data) {
|
|
792
|
+
const cells = {};
|
|
793
|
+
const rowMargin = {};
|
|
794
|
+
const colMargin = {};
|
|
795
|
+
let grand = { lv: 0, cv: 0 };
|
|
796
|
+
const rowIds = [];
|
|
797
|
+
const colIds = [];
|
|
798
|
+
for (const d of data) {
|
|
799
|
+
const stat = { lv: d.lv, cv: d.cv, ...d.block != null ? { block: d.block } : {} };
|
|
800
|
+
if (d.gr && d.gc) {
|
|
801
|
+
grand = stat;
|
|
802
|
+
continue;
|
|
803
|
+
}
|
|
804
|
+
if (d.gr) {
|
|
805
|
+
if (d.c != null) colMargin[d.c] = stat;
|
|
806
|
+
continue;
|
|
807
|
+
}
|
|
808
|
+
if (d.gc) {
|
|
809
|
+
if (d.r != null) rowMargin[d.r] = stat;
|
|
810
|
+
continue;
|
|
811
|
+
}
|
|
812
|
+
const r = d.r ?? NULL, c = d.c ?? NULL;
|
|
813
|
+
if (!cells[r]) {
|
|
814
|
+
cells[r] = {};
|
|
815
|
+
rowIds.push(r);
|
|
816
|
+
}
|
|
817
|
+
if (!colIds.includes(c)) colIds.push(c);
|
|
818
|
+
cells[r][c] = stat;
|
|
819
|
+
}
|
|
820
|
+
return { rowIds, colIds, cells, rowMargin, colMargin, grand };
|
|
821
|
+
}
|
|
822
|
+
function HeatmapPlusView({
|
|
823
|
+
records,
|
|
824
|
+
rowColumn,
|
|
825
|
+
colColumn,
|
|
826
|
+
valueColumn,
|
|
827
|
+
labelStat = "count",
|
|
828
|
+
colorStat = "count",
|
|
829
|
+
blockField,
|
|
830
|
+
data: presetData,
|
|
831
|
+
scope = "global",
|
|
832
|
+
method = "linear",
|
|
833
|
+
vmin,
|
|
834
|
+
vmax,
|
|
835
|
+
rowOrder = "alpha",
|
|
836
|
+
colOrder = "alpha",
|
|
837
|
+
showMargins = false,
|
|
838
|
+
style
|
|
839
|
+
}) {
|
|
840
|
+
const s = withStyleDefaults(style);
|
|
841
|
+
const model = useMemo(() => {
|
|
842
|
+
if (presetData) return fromData(presetData);
|
|
843
|
+
if (records) return fromRecords(records, rowColumn, colColumn, valueColumn, labelStat, colorStat, blockField);
|
|
844
|
+
return null;
|
|
845
|
+
}, [presetData, records, rowColumn, colColumn, valueColumn, labelStat, colorStat, blockField]);
|
|
846
|
+
const built = useMemo(() => {
|
|
847
|
+
if (!model || !model.rowIds.length || !model.colIds.length) return null;
|
|
848
|
+
const { cells, rowMargin, colMargin, grand } = model;
|
|
849
|
+
const rows = orderIds2(model.rowIds, rowMargin, rowOrder).slice(0, MAX_AXIS2);
|
|
850
|
+
const cols = orderIds2(model.colIds, colMargin, colOrder).slice(0, MAX_AXIS2);
|
|
851
|
+
const bodyCells = [];
|
|
852
|
+
for (const rid of rows) for (const cid of cols) {
|
|
853
|
+
bodyCells.push({ row: rid, col: cid, colorValue: cells[rid]?.[cid]?.cv ?? NaN, block: cells[rid]?.[cid]?.block });
|
|
854
|
+
}
|
|
855
|
+
const t2 = new Map(normalizeCells(bodyCells, { scope, method, vmin, vmax }));
|
|
856
|
+
if (showMargins) {
|
|
857
|
+
const rowMc = rows.map((rid) => ({ row: rid, col: TOTAL_ID, colorValue: rowMargin[rid]?.cv ?? NaN }));
|
|
858
|
+
const colMc = cols.map((cid) => ({ row: TOTAL_ID, col: cid, colorValue: colMargin[cid]?.cv ?? NaN }));
|
|
859
|
+
for (const [k, v] of normalizeCells(rowMc, { scope: "global", method })) t2.set(k, v);
|
|
860
|
+
for (const [k, v] of normalizeCells(colMc, { scope: "global", method })) t2.set(k, v);
|
|
861
|
+
t2.set(cellKey(TOTAL_ID, TOTAL_ID), 0.5);
|
|
862
|
+
}
|
|
863
|
+
const colKeys = showMargins ? [...cols, TOTAL_ID] : cols;
|
|
864
|
+
const nivoData2 = rows.map((rid) => ({
|
|
865
|
+
id: rid,
|
|
866
|
+
data: colKeys.map((cid) => ({
|
|
867
|
+
x: cid,
|
|
868
|
+
y: cid === TOTAL_ID ? rowMargin[rid]?.lv ?? 0 : cells[rid]?.[cid]?.lv ?? 0
|
|
869
|
+
}))
|
|
870
|
+
}));
|
|
871
|
+
if (showMargins) {
|
|
872
|
+
nivoData2.push({
|
|
873
|
+
id: TOTAL_ID,
|
|
874
|
+
data: colKeys.map((cid) => ({
|
|
875
|
+
x: cid,
|
|
876
|
+
y: cid === TOTAL_ID ? grand.lv : colMargin[cid]?.lv ?? 0
|
|
877
|
+
}))
|
|
878
|
+
});
|
|
879
|
+
}
|
|
880
|
+
return { nivoData: nivoData2, t: t2 };
|
|
881
|
+
}, [model, rowOrder, colOrder, scope, method, vmin, vmax, showMargins]);
|
|
882
|
+
if (!built) {
|
|
883
|
+
return /* @__PURE__ */ jsx("div", { className: "p-8 text-center text-midnight-text-muted", children: "Not enough distinct values for a heatmap" });
|
|
884
|
+
}
|
|
885
|
+
const { nivoData, t } = built;
|
|
886
|
+
const tAt = (serieId, x) => t.get(cellKey(serieId, x)) ?? 0;
|
|
887
|
+
return /* @__PURE__ */ jsx("div", { className: "h-full w-full min-h-[160px]", children: /* @__PURE__ */ jsx(
|
|
888
|
+
ResponsiveHeatMap,
|
|
889
|
+
{
|
|
890
|
+
data: nivoData,
|
|
891
|
+
margin: { top: 60, right: 20, bottom: showMargins ? 60 : 20, left: 100 },
|
|
892
|
+
valueFormat: ((v) => fmtNum2(v)),
|
|
893
|
+
axisTop: { tickSize: 5, tickPadding: 5, tickRotation: s.xTickRotation, legend: s.showXLegend ? s.xAxisLabel || colColumn : "", legendPosition: s.xLegendPosition, legendOffset: -50 },
|
|
894
|
+
axisLeft: { tickSize: 5, tickPadding: 5, legend: s.showYLegend ? s.yAxisLabel || rowColumn : "", legendPosition: s.yLegendPosition, legendOffset: -80 },
|
|
895
|
+
colors: ((cell) => heatColor(tAt(cell.serieId, cell.data.x))),
|
|
896
|
+
emptyColor: "#1e293b",
|
|
897
|
+
borderWidth: 1,
|
|
898
|
+
borderColor: "#334155",
|
|
899
|
+
labelTextColor: ((cell) => heatLabelColor(tAt(cell.serieId, cell.data.x))),
|
|
900
|
+
hoverTarget: "cell",
|
|
901
|
+
theme: buildNivoTheme(style)
|
|
902
|
+
}
|
|
903
|
+
) });
|
|
904
|
+
}
|
|
664
905
|
function PivotView({ records }) {
|
|
665
906
|
const [pivotState, setPivotState] = useState({});
|
|
666
907
|
if (!records?.length) {
|
|
@@ -1197,6 +1438,7 @@ var CHART_TYPES = [
|
|
|
1197
1438
|
{ id: "line", icon: TrendingUp, label: "Line" },
|
|
1198
1439
|
{ id: "scatter", icon: ScatterChart, label: "Scatter" },
|
|
1199
1440
|
{ id: "heatmap", icon: LayoutGrid, label: "Heatmap" },
|
|
1441
|
+
{ id: "heatmap-plus", icon: Grid3x3, label: "Heatmap+" },
|
|
1200
1442
|
{ id: "grouped-bar", icon: BarChart3, label: "Grouped Bar" }
|
|
1201
1443
|
];
|
|
1202
1444
|
var AGG_OPTIONS = ["count", "distinct", "sum", "avg", "min", "max"];
|
|
@@ -1217,6 +1459,17 @@ var ORDER_OPTIONS = [
|
|
|
1217
1459
|
{ id: "total-asc", label: "Total \u2191" }
|
|
1218
1460
|
];
|
|
1219
1461
|
var MARGIN_AGGS = ["sum", "avg", "min", "max", "count"].map((a) => ({ id: a, label: a }));
|
|
1462
|
+
var HEAT_STAT_OPTIONS = HEAT_STATS.map((a) => ({ id: a, label: a }));
|
|
1463
|
+
var SCOPE_OPTIONS = [
|
|
1464
|
+
{ id: "global", label: "Global" },
|
|
1465
|
+
{ id: "row", label: "Per row" },
|
|
1466
|
+
{ id: "column", label: "Per column" },
|
|
1467
|
+
{ id: "block", label: "Per block" }
|
|
1468
|
+
];
|
|
1469
|
+
var METHOD_OPTIONS = [
|
|
1470
|
+
{ id: "linear", label: "Linear" },
|
|
1471
|
+
{ id: "rank", label: "Rank" }
|
|
1472
|
+
];
|
|
1220
1473
|
var FILTER_OP_OPTIONS = FILTER_OPS.map((o) => ({ id: o, label: o }));
|
|
1221
1474
|
var FieldPill = ({ name, type, onRemove, onChangeAgg, agg, showAgg }) => {
|
|
1222
1475
|
const typeColor = {
|
|
@@ -1405,6 +1658,7 @@ var ChartPreview = ({
|
|
|
1405
1658
|
sqlLoading,
|
|
1406
1659
|
sqlError,
|
|
1407
1660
|
heatmapOpts = {},
|
|
1661
|
+
heatPlusOpts = {},
|
|
1408
1662
|
style
|
|
1409
1663
|
}) => {
|
|
1410
1664
|
const xCol = xFields[0]?.name;
|
|
@@ -1443,6 +1697,8 @@ var ChartPreview = ({
|
|
|
1443
1697
|
return /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(ScatterView, { data: shaped, xColumn: xCol, yColumn: yCol, style }) });
|
|
1444
1698
|
case "heatmap":
|
|
1445
1699
|
return shaped.length ? /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(HeatmapView, { data: shaped, rowColumn: xCol, colColumn: yCol, ...heatmapOpts, style }) }) : /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center h-full text-sm text-midnight-text-muted", children: "No data" });
|
|
1700
|
+
case "heatmap-plus":
|
|
1701
|
+
return shaped.length ? /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(HeatmapPlusView, { data: shaped, rowColumn: xCol, colColumn: yCol, ...heatPlusOpts, style }) }) : /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center h-full text-sm text-midnight-text-muted", children: "No data" });
|
|
1446
1702
|
default:
|
|
1447
1703
|
return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center h-full text-sm text-midnight-text-muted", children: "Select a chart type" });
|
|
1448
1704
|
}
|
|
@@ -1464,6 +1720,8 @@ var ChartPreview = ({
|
|
|
1464
1720
|
return xCol && yCol ? /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(ScatterView, { records, xColumn: xCol, yColumn: yCol, style }) }) : null;
|
|
1465
1721
|
case "heatmap":
|
|
1466
1722
|
return xCol && yCol ? /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(HeatmapView, { records, rowColumn: xCol, colColumn: yCol, valueColumn: valueField?.name, aggFn: valueField?.agg || "count", ...heatmapOpts, style }) }) : null;
|
|
1723
|
+
case "heatmap-plus":
|
|
1724
|
+
return xCol && yCol ? /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(HeatmapPlusView, { records, rowColumn: xCol, colColumn: yCol, valueColumn: valueField?.name, ...heatPlusOpts, style }) }) : null;
|
|
1467
1725
|
default:
|
|
1468
1726
|
return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center h-full text-sm text-midnight-text-muted", children: "Select a chart type" });
|
|
1469
1727
|
}
|
|
@@ -1487,6 +1745,13 @@ function ChartBuilder({ records, columns, stateId, onSave }) {
|
|
|
1487
1745
|
const [colOrder, setColOrder] = useState("alpha");
|
|
1488
1746
|
const [marginAgg, setMarginAgg] = useState("sum");
|
|
1489
1747
|
const [showTotals, setShowTotals] = useState(false);
|
|
1748
|
+
const [labelStat, setLabelStat] = useState("count");
|
|
1749
|
+
const [colorStat, setColorStat] = useState("count");
|
|
1750
|
+
const [scope, setScope] = useState("global");
|
|
1751
|
+
const [method, setMethod] = useState("linear");
|
|
1752
|
+
const [vmin, setVmin] = useState("");
|
|
1753
|
+
const [vmax, setVmax] = useState("");
|
|
1754
|
+
const [showMargins, setShowMargins] = useState(false);
|
|
1490
1755
|
const [style, setStyle] = useState(DEFAULT_CHART_STYLE);
|
|
1491
1756
|
const [showStyle, setShowStyle] = useState(false);
|
|
1492
1757
|
const [showFields, setShowFields] = useState(false);
|
|
@@ -1495,8 +1760,17 @@ function ChartBuilder({ records, columns, stateId, onSave }) {
|
|
|
1495
1760
|
const [sqlLoading, setSqlLoading] = useState(false);
|
|
1496
1761
|
const [sqlError, setSqlError] = useState(null);
|
|
1497
1762
|
const generatedSql = useMemo(
|
|
1498
|
-
() => buildChartSQL({
|
|
1499
|
-
|
|
1763
|
+
() => buildChartSQL({
|
|
1764
|
+
chartType,
|
|
1765
|
+
xFields,
|
|
1766
|
+
yFields,
|
|
1767
|
+
valueField,
|
|
1768
|
+
filters,
|
|
1769
|
+
labelStat,
|
|
1770
|
+
colorStat,
|
|
1771
|
+
blockField: colorField?.name
|
|
1772
|
+
}),
|
|
1773
|
+
[chartType, xFields, yFields, valueField, filters, labelStat, colorStat, colorField]
|
|
1500
1774
|
);
|
|
1501
1775
|
useEffect(() => {
|
|
1502
1776
|
if (engineMode !== "sql") return void 0;
|
|
@@ -1594,6 +1868,26 @@ function ChartBuilder({ records, columns, stateId, onSave }) {
|
|
|
1594
1868
|
config.marginAgg = marginAgg;
|
|
1595
1869
|
config.showTotals = showTotals;
|
|
1596
1870
|
}
|
|
1871
|
+
if (chartType === "heatmap-plus") {
|
|
1872
|
+
config.row = xFields[0]?.name;
|
|
1873
|
+
config.col = yFields[0]?.name;
|
|
1874
|
+
if (valueField) config.value = valueField.name;
|
|
1875
|
+
else delete config.value;
|
|
1876
|
+
config.labelStat = labelStat;
|
|
1877
|
+
config.colorStat = colorStat;
|
|
1878
|
+
if (colorField) config.blockField = colorField.name;
|
|
1879
|
+
else delete config.blockField;
|
|
1880
|
+
config.scope = scope;
|
|
1881
|
+
config.method = method;
|
|
1882
|
+
const nMin = parseFloat(vmin), nMax = parseFloat(vmax);
|
|
1883
|
+
if (Number.isFinite(nMin)) config.vmin = nMin;
|
|
1884
|
+
else delete config.vmin;
|
|
1885
|
+
if (Number.isFinite(nMax)) config.vmax = nMax;
|
|
1886
|
+
else delete config.vmax;
|
|
1887
|
+
config.rowOrder = rowOrder;
|
|
1888
|
+
config.colOrder = colOrder;
|
|
1889
|
+
config.showMargins = showMargins;
|
|
1890
|
+
}
|
|
1597
1891
|
if (engineMode === "sql" && generatedSql) {
|
|
1598
1892
|
config.sql = generatedSql;
|
|
1599
1893
|
config.chartType = chartType;
|
|
@@ -1614,6 +1908,7 @@ function ChartBuilder({ records, columns, stateId, onSave }) {
|
|
|
1614
1908
|
height: fillContainer ? 8 : 2
|
|
1615
1909
|
});
|
|
1616
1910
|
};
|
|
1911
|
+
const isHeat = chartType === "heatmap" || chartType === "heatmap-plus";
|
|
1617
1912
|
return /* @__PURE__ */ jsxs("div", { className: "flex h-full", children: [
|
|
1618
1913
|
/* @__PURE__ */ jsxs("div", { className: `w-[280px] shrink-0 border-r ${theme.border} bg-midnight-elevated overflow-y-auto p-3 space-y-4`, children: [
|
|
1619
1914
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
@@ -1649,30 +1944,30 @@ function ChartBuilder({ records, columns, stateId, onSave }) {
|
|
|
1649
1944
|
/* @__PURE__ */ jsx(
|
|
1650
1945
|
DropZone,
|
|
1651
1946
|
{
|
|
1652
|
-
label:
|
|
1947
|
+
label: isHeat ? "Rows" : "X Axis / Group By",
|
|
1653
1948
|
fields: xFields,
|
|
1654
1949
|
columns,
|
|
1655
1950
|
onAdd: (f) => addField("x", f),
|
|
1656
1951
|
onRemove: (i) => removeField("x", i),
|
|
1657
1952
|
onChangeAgg: () => {
|
|
1658
1953
|
},
|
|
1659
|
-
maxFields: chartType === "pie" ||
|
|
1954
|
+
maxFields: chartType === "pie" || isHeat ? 1 : 3
|
|
1660
1955
|
}
|
|
1661
1956
|
),
|
|
1662
1957
|
/* @__PURE__ */ jsx(
|
|
1663
1958
|
DropZone,
|
|
1664
1959
|
{
|
|
1665
|
-
label:
|
|
1960
|
+
label: isHeat ? "Columns" : "Y Axis / Values",
|
|
1666
1961
|
fields: yFields,
|
|
1667
1962
|
columns,
|
|
1668
1963
|
onAdd: (f) => addField("y", f),
|
|
1669
1964
|
onRemove: (i) => removeField("y", i),
|
|
1670
1965
|
onChangeAgg: (i, agg) => changeAgg("y", i, agg),
|
|
1671
|
-
showAgg:
|
|
1672
|
-
maxFields:
|
|
1966
|
+
showAgg: !isHeat,
|
|
1967
|
+
maxFields: isHeat ? 1 : 5
|
|
1673
1968
|
}
|
|
1674
1969
|
),
|
|
1675
|
-
|
|
1970
|
+
isHeat && /* @__PURE__ */ jsx(
|
|
1676
1971
|
DropZone,
|
|
1677
1972
|
{
|
|
1678
1973
|
label: "Cell Value (optional \u2014 defaults to count)",
|
|
@@ -1681,10 +1976,93 @@ function ChartBuilder({ records, columns, stateId, onSave }) {
|
|
|
1681
1976
|
onAdd: (f) => addField("value", f),
|
|
1682
1977
|
onRemove: () => removeField("value"),
|
|
1683
1978
|
onChangeAgg: (i, agg) => changeAgg("value", i, agg),
|
|
1684
|
-
showAgg:
|
|
1979
|
+
showAgg: chartType === "heatmap",
|
|
1685
1980
|
maxFields: 1
|
|
1686
1981
|
}
|
|
1687
1982
|
),
|
|
1983
|
+
chartType === "heatmap-plus" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1984
|
+
/* @__PURE__ */ jsx(
|
|
1985
|
+
DropZone,
|
|
1986
|
+
{
|
|
1987
|
+
label: "Block (optional \u2014 color-scope grouping)",
|
|
1988
|
+
fields: colorField ? [colorField] : [],
|
|
1989
|
+
columns,
|
|
1990
|
+
onAdd: (f) => addField("color", f),
|
|
1991
|
+
onRemove: () => removeField("color"),
|
|
1992
|
+
onChangeAgg: () => {
|
|
1993
|
+
},
|
|
1994
|
+
maxFields: 1
|
|
1995
|
+
}
|
|
1996
|
+
),
|
|
1997
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
1998
|
+
/* @__PURE__ */ jsx("div", { className: "text-xs uppercase text-midnight-text-muted mb-2 font-mono", children: "Cell Stats" }),
|
|
1999
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
2000
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3 min-h-[28px]", children: [
|
|
2001
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-mono text-midnight-text-muted", children: "Label stat" }),
|
|
2002
|
+
/* @__PURE__ */ jsx(SelectControl, { value: labelStat, options: HEAT_STAT_OPTIONS, onChange: (v) => setLabelStat(v) })
|
|
2003
|
+
] }),
|
|
2004
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3 min-h-[28px]", children: [
|
|
2005
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-mono text-midnight-text-muted", children: "Color stat" }),
|
|
2006
|
+
/* @__PURE__ */ jsx(SelectControl, { value: colorStat, options: HEAT_STAT_OPTIONS, onChange: (v) => setColorStat(v) })
|
|
2007
|
+
] })
|
|
2008
|
+
] })
|
|
2009
|
+
] }),
|
|
2010
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
2011
|
+
/* @__PURE__ */ jsx("div", { className: "text-xs uppercase text-midnight-text-muted mb-2 font-mono", children: "Color Engine" }),
|
|
2012
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
2013
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3 min-h-[28px]", children: [
|
|
2014
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-mono text-midnight-text-muted", children: "Scale scope" }),
|
|
2015
|
+
/* @__PURE__ */ jsx(SelectControl, { value: scope, options: SCOPE_OPTIONS, onChange: (v) => setScope(v) })
|
|
2016
|
+
] }),
|
|
2017
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3 min-h-[28px]", children: [
|
|
2018
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-mono text-midnight-text-muted", children: "Scale method" }),
|
|
2019
|
+
/* @__PURE__ */ jsx(SelectControl, { value: method, options: METHOD_OPTIONS, onChange: (v) => setMethod(v) })
|
|
2020
|
+
] }),
|
|
2021
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3 min-h-[28px]", children: [
|
|
2022
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-mono text-midnight-text-muted", children: "Fixed min / max" }),
|
|
2023
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-1", children: [
|
|
2024
|
+
/* @__PURE__ */ jsx(
|
|
2025
|
+
"input",
|
|
2026
|
+
{
|
|
2027
|
+
value: vmin,
|
|
2028
|
+
onChange: (e) => setVmin(e.target.value),
|
|
2029
|
+
placeholder: "auto",
|
|
2030
|
+
inputMode: "decimal",
|
|
2031
|
+
className: "w-14 px-2 py-1 text-xs font-mono bg-midnight-surface border border-midnight-border text-midnight-text-body outline-none focus:border-midnight-accent"
|
|
2032
|
+
}
|
|
2033
|
+
),
|
|
2034
|
+
/* @__PURE__ */ jsx(
|
|
2035
|
+
"input",
|
|
2036
|
+
{
|
|
2037
|
+
value: vmax,
|
|
2038
|
+
onChange: (e) => setVmax(e.target.value),
|
|
2039
|
+
placeholder: "auto",
|
|
2040
|
+
inputMode: "decimal",
|
|
2041
|
+
className: "w-14 px-2 py-1 text-xs font-mono bg-midnight-surface border border-midnight-border text-midnight-text-body outline-none focus:border-midnight-accent"
|
|
2042
|
+
}
|
|
2043
|
+
)
|
|
2044
|
+
] })
|
|
2045
|
+
] })
|
|
2046
|
+
] })
|
|
2047
|
+
] }),
|
|
2048
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
2049
|
+
/* @__PURE__ */ jsx("div", { className: "text-xs uppercase text-midnight-text-muted mb-2 font-mono", children: "Order & Margins" }),
|
|
2050
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
2051
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3 min-h-[28px]", children: [
|
|
2052
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-mono text-midnight-text-muted", children: "Order rows" }),
|
|
2053
|
+
/* @__PURE__ */ jsx(SelectControl, { value: rowOrder, options: ORDER_OPTIONS, onChange: (v) => setRowOrder(v) })
|
|
2054
|
+
] }),
|
|
2055
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3 min-h-[28px]", children: [
|
|
2056
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-mono text-midnight-text-muted", children: "Order columns" }),
|
|
2057
|
+
/* @__PURE__ */ jsx(SelectControl, { value: colOrder, options: ORDER_OPTIONS, onChange: (v) => setColOrder(v) })
|
|
2058
|
+
] }),
|
|
2059
|
+
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 cursor-pointer", children: [
|
|
2060
|
+
/* @__PURE__ */ jsx("input", { type: "checkbox", checked: showMargins, onChange: (e) => setShowMargins(e.target.checked), className: "accent-midnight-accent" }),
|
|
2061
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-mono text-midnight-text-muted", children: "Show margins (row / col / grand)" })
|
|
2062
|
+
] })
|
|
2063
|
+
] })
|
|
2064
|
+
] })
|
|
2065
|
+
] }),
|
|
1688
2066
|
chartType === "heatmap" && /* @__PURE__ */ jsxs("div", { children: [
|
|
1689
2067
|
/* @__PURE__ */ jsx("div", { className: "text-xs uppercase text-midnight-text-muted mb-2 font-mono", children: "Order & Totals" }),
|
|
1690
2068
|
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
@@ -1818,6 +2196,18 @@ function ChartBuilder({ records, columns, stateId, onSave }) {
|
|
|
1818
2196
|
sqlLoading,
|
|
1819
2197
|
sqlError,
|
|
1820
2198
|
heatmapOpts: { rowOrder, colOrder, marginAgg, showTotals },
|
|
2199
|
+
heatPlusOpts: {
|
|
2200
|
+
labelStat,
|
|
2201
|
+
colorStat,
|
|
2202
|
+
blockField: colorField?.name,
|
|
2203
|
+
scope,
|
|
2204
|
+
method,
|
|
2205
|
+
vmin: Number.isFinite(parseFloat(vmin)) ? parseFloat(vmin) : void 0,
|
|
2206
|
+
vmax: Number.isFinite(parseFloat(vmax)) ? parseFloat(vmax) : void 0,
|
|
2207
|
+
rowOrder,
|
|
2208
|
+
colOrder,
|
|
2209
|
+
showMargins
|
|
2210
|
+
},
|
|
1821
2211
|
style
|
|
1822
2212
|
}
|
|
1823
2213
|
) })
|
|
@@ -1826,7 +2216,7 @@ function ChartBuilder({ records, columns, stateId, onSave }) {
|
|
|
1826
2216
|
function ViewLoading() {
|
|
1827
2217
|
return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center h-full text-xs text-midnight-text-muted", children: "Loading..." });
|
|
1828
2218
|
}
|
|
1829
|
-
var SQL_CHART_TYPES = /* @__PURE__ */ new Set(["bar", "grouped-bar", "pie", "line", "scatter", "heatmap"]);
|
|
2219
|
+
var SQL_CHART_TYPES = /* @__PURE__ */ new Set(["bar", "grouped-bar", "pie", "line", "scatter", "heatmap", "heatmap-plus"]);
|
|
1830
2220
|
var SQL_DATA_TYPES = /* @__PURE__ */ new Set(["table", "metric"]);
|
|
1831
2221
|
var TABLE_PREVIEW_ROWS = 200;
|
|
1832
2222
|
function tableSql(config) {
|
|
@@ -1857,6 +2247,14 @@ function panelToChartConfig(chartType, config) {
|
|
|
1857
2247
|
if (config.col) cfg.yFields = [{ name: config.col }];
|
|
1858
2248
|
if (config.value) cfg.valueField = { name: config.value, agg: config.agg };
|
|
1859
2249
|
break;
|
|
2250
|
+
case "heatmap-plus":
|
|
2251
|
+
if (config.row) cfg.xFields = [{ name: config.row }];
|
|
2252
|
+
if (config.col) cfg.yFields = [{ name: config.col }];
|
|
2253
|
+
if (config.value) cfg.valueField = { name: config.value, agg: config.labelStat };
|
|
2254
|
+
cfg.labelStat = config.labelStat;
|
|
2255
|
+
cfg.colorStat = config.colorStat;
|
|
2256
|
+
cfg.blockField = config.blockField;
|
|
2257
|
+
break;
|
|
1860
2258
|
}
|
|
1861
2259
|
return cfg;
|
|
1862
2260
|
}
|
|
@@ -2005,6 +2403,9 @@ function SqlPanel({ panel }) {
|
|
|
2005
2403
|
case "heatmap":
|
|
2006
2404
|
chart = shaped.length ? /* @__PURE__ */ jsx(HeatmapView, { data: shaped, rowColumn: config.row || "", colColumn: config.col || "", rowOrder: config.rowOrder, colOrder: config.colOrder, marginAgg: config.marginAgg, showTotals: config.showTotals, style: config.style }) : /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center h-full text-xs text-midnight-text-muted", children: "No data" });
|
|
2007
2405
|
break;
|
|
2406
|
+
case "heatmap-plus":
|
|
2407
|
+
chart = shaped.length ? /* @__PURE__ */ jsx(HeatmapPlusView, { data: shaped, rowColumn: config.row || "", colColumn: config.col || "", scope: config.scope, method: config.method, vmin: config.vmin, vmax: config.vmax, rowOrder: config.rowOrder, colOrder: config.colOrder, showMargins: config.showMargins, style: config.style }) : /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center h-full text-xs text-midnight-text-muted", children: "No data" });
|
|
2408
|
+
break;
|
|
2008
2409
|
default:
|
|
2009
2410
|
chart = /* @__PURE__ */ jsxs("div", { className: "p-4 text-xs text-midnight-text-muted", children: [
|
|
2010
2411
|
"Unsupported SQL chart: ",
|
|
@@ -2038,6 +2439,8 @@ function PanelContent({ panel, records, columns }) {
|
|
|
2038
2439
|
return config.x && config.y ? /* @__PURE__ */ jsx(ScatterView, { records, xColumn: config.x, yColumn: config.y, style: config.style }) : null;
|
|
2039
2440
|
case "heatmap":
|
|
2040
2441
|
return config.row && config.col ? /* @__PURE__ */ jsx(HeatmapView, { records, rowColumn: config.row, colColumn: config.col, valueColumn: config.value, aggFn: config.agg || "count", rowOrder: config.rowOrder, colOrder: config.colOrder, marginAgg: config.marginAgg, showTotals: config.showTotals, style: config.style }) : null;
|
|
2442
|
+
case "heatmap-plus":
|
|
2443
|
+
return config.row && config.col ? /* @__PURE__ */ jsx(HeatmapPlusView, { records, rowColumn: config.row, colColumn: config.col, valueColumn: config.value, labelStat: config.labelStat, colorStat: config.colorStat, blockField: config.blockField, scope: config.scope, method: config.method, vmin: config.vmin, vmax: config.vmax, rowOrder: config.rowOrder, colOrder: config.colOrder, showMargins: config.showMargins, style: config.style }) : null;
|
|
2041
2444
|
case "pivot":
|
|
2042
2445
|
return /* @__PURE__ */ jsx(PivotView, { records });
|
|
2043
2446
|
case "metric":
|
|
@@ -2497,6 +2900,6 @@ function DataExplorer({
|
|
|
2497
2900
|
] });
|
|
2498
2901
|
}
|
|
2499
2902
|
|
|
2500
|
-
export { BarView, ChartBuilder, ChartStyleControls, DEFAULT_CHART_STYLE, DashboardProvider, DashboardRenderer, DataExplorer, HeatmapView, InsightView, LEGEND_ANCHORS, LineView, MetricView, PanelChart, PieView, PivotView, ScatterView, SqlConsole, aggExpr, aggregate, axisLegend, buildChartSQL, buildNivoTheme, compileWhere, groupBy, legendConfig, qIdent, qLit, shapeChartData, useCapabilities, useDashboard, withStyleDefaults };
|
|
2903
|
+
export { BarView, ChartBuilder, ChartStyleControls, DEFAULT_CHART_STYLE, DashboardProvider, DashboardRenderer, DataExplorer, HEAT_STATS, HeatmapPlusView, HeatmapView, InsightView, LEGEND_ANCHORS, LineView, MetricView, PanelChart, PieView, PivotView, ScatterView, SqlConsole, aggExpr, aggregate, axisLegend, buildChartSQL, buildNivoTheme, compileWhere, groupBy, heatColor, heatLabelColor, legendConfig, normalizeCells, qIdent, qLit, shapeChartData, useCapabilities, useDashboard, withStyleDefaults };
|
|
2501
2904
|
//# sourceMappingURL=index.js.map
|
|
2502
2905
|
//# sourceMappingURL=index.js.map
|