@vuu-ui/vuu-chart 3.0.0 → 3.1.0-beta.1
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/package.json +15 -12
- package/src/Chart.css.js +46 -0
- package/src/Chart.mjs +81 -0
- package/src/ChartSeries.mjs +151 -0
- package/src/DataRowMovingWindow.mjs +64 -0
- package/src/chart-types.mjs +2 -0
- package/src/chartTooltip.mjs +23 -0
- package/src/index.mjs +2 -0
- package/src/useChartContextMenu.mjs +22 -0
- package/src/useChartOptions.mjs +88 -0
- package/src/useChartSelection.mjs +47 -0
- package/cjs/Chart.css.js +0 -6
- package/cjs/Chart.css.js.map +0 -1
- package/cjs/Chart.js +0 -89
- package/cjs/Chart.js.map +0 -1
- package/cjs/ChartSeries.js +0 -183
- package/cjs/ChartSeries.js.map +0 -1
- package/cjs/DataRowMovingWindow.js +0 -97
- package/cjs/DataRowMovingWindow.js.map +0 -1
- package/cjs/chart-types.js +0 -6
- package/cjs/chart-types.js.map +0 -1
- package/cjs/chartTooltip.js +0 -27
- package/cjs/chartTooltip.js.map +0 -1
- package/cjs/index.js +0 -10
- package/cjs/index.js.map +0 -1
- package/cjs/useChartContextMenu.js +0 -29
- package/cjs/useChartContextMenu.js.map +0 -1
- package/cjs/useChartOptions.js +0 -101
- package/cjs/useChartOptions.js.map +0 -1
- package/cjs/useChartSelection.js +0 -72
- package/cjs/useChartSelection.js.map +0 -1
- package/esm/Chart.css.js +0 -4
- package/esm/Chart.css.js.map +0 -1
- package/esm/Chart.js +0 -87
- package/esm/Chart.js.map +0 -1
- package/esm/ChartSeries.js +0 -181
- package/esm/ChartSeries.js.map +0 -1
- package/esm/DataRowMovingWindow.js +0 -95
- package/esm/DataRowMovingWindow.js.map +0 -1
- package/esm/chart-types.js +0 -4
- package/esm/chart-types.js.map +0 -1
- package/esm/chartTooltip.js +0 -25
- package/esm/chartTooltip.js.map +0 -1
- package/esm/index.js +0 -3
- package/esm/index.js.map +0 -1
- package/esm/useChartContextMenu.js +0 -27
- package/esm/useChartContextMenu.js.map +0 -1
- package/esm/useChartOptions.js +0 -99
- package/esm/useChartOptions.js.map +0 -1
- package/esm/useChartSelection.js +0 -70
- package/esm/useChartSelection.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "3.0.
|
|
2
|
+
"version": "3.1.0-beta.1",
|
|
3
3
|
"description": "support for apache echarts using vuu data",
|
|
4
|
+
"main": "src/index.ts",
|
|
4
5
|
"license": "Apache-2.0",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build:dev": "node ../../scripts/run-build.mjs",
|
|
8
|
+
"build": "node ../../scripts/run-build-rslib.ts",
|
|
9
|
+
"type-defs": "node ../../scripts/build-type-defs.mjs"
|
|
10
|
+
},
|
|
5
11
|
"devDependencies": {
|
|
6
|
-
"@vuu-ui/vuu-data-types": "3.0.
|
|
7
|
-
"@vuu-ui/vuu-protocol-types": "3.0.
|
|
8
|
-
"@vuu-ui/vuu-data-local": "3.0.
|
|
12
|
+
"@vuu-ui/vuu-data-types": "3.1.0-beta.1",
|
|
13
|
+
"@vuu-ui/vuu-protocol-types": "3.1.0-beta.1",
|
|
14
|
+
"@vuu-ui/vuu-data-local": "3.1.0-beta.1"
|
|
9
15
|
},
|
|
10
16
|
"dependencies": {
|
|
11
17
|
"@salt-ds/styles": "0.2.1",
|
|
12
18
|
"@salt-ds/window": "0.1.1",
|
|
13
|
-
"@vuu-ui/vuu-context-menu": "3.0.
|
|
14
|
-
"@vuu-ui/vuu-utils": "3.0.
|
|
19
|
+
"@vuu-ui/vuu-context-menu": "3.1.0-beta.1",
|
|
20
|
+
"@vuu-ui/vuu-utils": "3.1.0-beta.1",
|
|
15
21
|
"clsx": "^2.0.0"
|
|
16
22
|
},
|
|
17
23
|
"peerDependencies": {
|
|
@@ -21,19 +27,16 @@
|
|
|
21
27
|
},
|
|
22
28
|
"files": [
|
|
23
29
|
"README.md",
|
|
24
|
-
"
|
|
25
|
-
"cjs",
|
|
30
|
+
"src",
|
|
26
31
|
"/types"
|
|
27
32
|
],
|
|
28
33
|
"exports": {
|
|
29
34
|
".": {
|
|
30
|
-
"
|
|
31
|
-
"import": "./esm/index.js",
|
|
35
|
+
"import": "./src/index.js",
|
|
32
36
|
"types": "./types/index.d.ts"
|
|
33
37
|
}
|
|
34
38
|
},
|
|
35
|
-
"
|
|
36
|
-
"module": "esm/index.js",
|
|
39
|
+
"module": "index.js",
|
|
37
40
|
"name": "@vuu-ui/vuu-chart",
|
|
38
41
|
"type": "module",
|
|
39
42
|
"types": "types/index.d.ts"
|
package/src/Chart.css.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const css = `
|
|
2
|
+
.vuuChart {
|
|
3
|
+
& .vuuChartTooltip {
|
|
4
|
+
background-color: var(--salt-container-primary-background) !important;
|
|
5
|
+
border-color: var(--salt-selectable-borderColor-selected) !important;
|
|
6
|
+
font-family: var(--salt-text-fontFamily) !important;
|
|
7
|
+
border-radius: 6px !important;
|
|
8
|
+
|
|
9
|
+
& .vuuChart-tooltip-title {
|
|
10
|
+
color: var(--salt-content-primary-foreground) !important;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
& .vuuChart-tooltip-entry {
|
|
14
|
+
align-items: center;
|
|
15
|
+
gap: 6px;
|
|
16
|
+
display: flex;
|
|
17
|
+
|
|
18
|
+
& .vuuChart-tooltip-icon {
|
|
19
|
+
border-radius: 12px;
|
|
20
|
+
flex: 0 0 12px;
|
|
21
|
+
height: 12px;
|
|
22
|
+
display: block;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
& .vuuChart-tooltip-label {
|
|
26
|
+
text-transform: capitalize;
|
|
27
|
+
flex: auto;
|
|
28
|
+
min-width: 60px;
|
|
29
|
+
padding-top: 3px;
|
|
30
|
+
color: var(--salt-content-secondary-foreground) !important;
|
|
31
|
+
font-size: var(--salt-text-label-fontSize) !important;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
& .vuuChart-tooltip-value {
|
|
35
|
+
text-align: right;
|
|
36
|
+
flex: auto;
|
|
37
|
+
color: var(--salt-content-primary-foreground) !important;
|
|
38
|
+
font-size: var(--salt-text-label-fontSize) !important;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
`;
|
|
46
|
+
export default css;
|
package/src/Chart.mjs
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useComponentCssInjection } from "@salt-ds/styles";
|
|
3
|
+
import { useWindow } from "@salt-ds/window";
|
|
4
|
+
import clsx from "clsx";
|
|
5
|
+
import { getInstanceByDom, init } from "echarts";
|
|
6
|
+
import { useEffect, useRef } from "react";
|
|
7
|
+
import { useChartContextMenu } from "./useChartContextMenu.mjs";
|
|
8
|
+
import { useChartOptions } from "./useChartOptions.mjs";
|
|
9
|
+
import { useChartSelection } from "./useChartSelection.mjs";
|
|
10
|
+
import { buildColumnMap } from "@vuu-ui/vuu-utils";
|
|
11
|
+
import Chart from "./Chart.css";
|
|
12
|
+
const classBase = "vuuChart";
|
|
13
|
+
const Chart_Chart = ({ categoryColumnName, chartSettings = {
|
|
14
|
+
useCoarsePointer: true,
|
|
15
|
+
renderer: "svg"
|
|
16
|
+
}, className, config, dataExclusions, dataSource, optionSettings = {
|
|
17
|
+
notMerge: true
|
|
18
|
+
}, palette, showTooltip, style = {
|
|
19
|
+
width: "100%",
|
|
20
|
+
height: "100%"
|
|
21
|
+
}, seriesColumnNames, ...htmlAttributes })=>{
|
|
22
|
+
const targetWindow = useWindow();
|
|
23
|
+
useComponentCssInjection({
|
|
24
|
+
testId: "vuu-toast-notification",
|
|
25
|
+
css: Chart,
|
|
26
|
+
window: targetWindow
|
|
27
|
+
});
|
|
28
|
+
const chartRef = useRef(null);
|
|
29
|
+
const columnMap = buildColumnMap(dataSource.columns);
|
|
30
|
+
const onContextMenu = useChartContextMenu({
|
|
31
|
+
categoryColumnName,
|
|
32
|
+
columnMap
|
|
33
|
+
});
|
|
34
|
+
const { itemColorFunction, onClick, onMouseOut, onMouseOver, symbolSizeFunction } = useChartSelection({
|
|
35
|
+
categoryColumnName,
|
|
36
|
+
selectionModel: config?.selectionModel
|
|
37
|
+
});
|
|
38
|
+
const option = useChartOptions({
|
|
39
|
+
categoryColumnName,
|
|
40
|
+
config,
|
|
41
|
+
itemColorFunction,
|
|
42
|
+
palette,
|
|
43
|
+
dataExclusions,
|
|
44
|
+
dataSource,
|
|
45
|
+
seriesColumnNames,
|
|
46
|
+
symbolSizeFunction,
|
|
47
|
+
showTooltip
|
|
48
|
+
});
|
|
49
|
+
useEffect(()=>{
|
|
50
|
+
const chart = init(chartRef.current, null, chartSettings);
|
|
51
|
+
chart.on("contextmenu", onContextMenu);
|
|
52
|
+
chart.on("click", onClick);
|
|
53
|
+
chart.on("mouseover", onMouseOver);
|
|
54
|
+
chart.on("mouseout", onMouseOut);
|
|
55
|
+
return ()=>{
|
|
56
|
+
chart?.dispose();
|
|
57
|
+
};
|
|
58
|
+
}, [
|
|
59
|
+
chartSettings,
|
|
60
|
+
onClick,
|
|
61
|
+
onContextMenu,
|
|
62
|
+
onMouseOver,
|
|
63
|
+
onMouseOut
|
|
64
|
+
]);
|
|
65
|
+
useEffect(()=>{
|
|
66
|
+
if (chartRef.current) {
|
|
67
|
+
const chart = getInstanceByDom(chartRef.current);
|
|
68
|
+
chart?.setOption(option, optionSettings);
|
|
69
|
+
}
|
|
70
|
+
}, [
|
|
71
|
+
option,
|
|
72
|
+
optionSettings
|
|
73
|
+
]);
|
|
74
|
+
return /*#__PURE__*/ jsx("div", {
|
|
75
|
+
...htmlAttributes,
|
|
76
|
+
className: clsx(classBase, className),
|
|
77
|
+
ref: chartRef,
|
|
78
|
+
style: style
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
export { Chart_Chart as Chart };
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { EventEmitter, Range, buildColumnMap, metadataKeys } from "@vuu-ui/vuu-utils";
|
|
2
|
+
import { MovingDataRowWindow } from "./DataRowMovingWindow.mjs";
|
|
3
|
+
import { defaultItemColorFunction } from "./chart-types.mjs";
|
|
4
|
+
const { KEY: KEY } = metadataKeys;
|
|
5
|
+
function DataSourceValue(key, row, value) {
|
|
6
|
+
return {
|
|
7
|
+
key,
|
|
8
|
+
row,
|
|
9
|
+
value
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
class ChartSeries extends EventEmitter {
|
|
13
|
+
#categoryColumn = "";
|
|
14
|
+
#colorMap = new Map();
|
|
15
|
+
#columnMap = {};
|
|
16
|
+
#config;
|
|
17
|
+
#dataExclusions;
|
|
18
|
+
#dataWindow = new MovingDataRowWindow(Range(0, 1000));
|
|
19
|
+
#dates = [];
|
|
20
|
+
#palette;
|
|
21
|
+
#series = [];
|
|
22
|
+
#seriesColumns = [];
|
|
23
|
+
handleData = (message)=>{
|
|
24
|
+
if ("subscribed" === message.type) this.#columnMap = buildColumnMap(message.tableSchema.columns);
|
|
25
|
+
else if ("viewport-update" === message.type) {
|
|
26
|
+
if ("size-only" === message.mode) ;
|
|
27
|
+
else if (message.rows) {
|
|
28
|
+
for (const row of message.rows)this.#dataWindow.add(row);
|
|
29
|
+
this.buildCategoriesAndSeries();
|
|
30
|
+
}
|
|
31
|
+
} else console.warn(JSON.stringify(message));
|
|
32
|
+
};
|
|
33
|
+
buildCategoriesAndSeries() {
|
|
34
|
+
if (this.#categoryColumn && this.#seriesColumns.length > 0) {
|
|
35
|
+
const [dates, series] = this.getCategoriesAndSeries();
|
|
36
|
+
this.#dates = dates;
|
|
37
|
+
this.#series = series;
|
|
38
|
+
this.emit("update");
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
constructor({ config, dataExclusions, dataSource, palette }){
|
|
42
|
+
super();
|
|
43
|
+
this.#config = config;
|
|
44
|
+
this.#dataExclusions = dataExclusions;
|
|
45
|
+
this.#palette = palette;
|
|
46
|
+
dataSource.subscribe({
|
|
47
|
+
range: Range(0, 1000)
|
|
48
|
+
}, this.handleData);
|
|
49
|
+
}
|
|
50
|
+
get palette() {
|
|
51
|
+
return this.#seriesColumns.map((col)=>this.#colorMap.get(col));
|
|
52
|
+
}
|
|
53
|
+
get categoryColumn() {
|
|
54
|
+
return this.#categoryColumn;
|
|
55
|
+
}
|
|
56
|
+
set categoryColumn(categoryColumn) {
|
|
57
|
+
this.#categoryColumn = categoryColumn;
|
|
58
|
+
if (this.#seriesColumns.length > 0) this.buildCategoriesAndSeries();
|
|
59
|
+
}
|
|
60
|
+
get seriesColumnNames() {
|
|
61
|
+
return this.#seriesColumns;
|
|
62
|
+
}
|
|
63
|
+
set seriesColumnNames(seriesColumnNames) {
|
|
64
|
+
this.#seriesColumns = seriesColumnNames;
|
|
65
|
+
if (this.#categoryColumn) this.buildCategoriesAndSeries();
|
|
66
|
+
}
|
|
67
|
+
get categories() {
|
|
68
|
+
return this.#dates;
|
|
69
|
+
}
|
|
70
|
+
get series() {
|
|
71
|
+
return this.#series;
|
|
72
|
+
}
|
|
73
|
+
getCategoriesAndSeries() {
|
|
74
|
+
const colorMap = this.#colorMap;
|
|
75
|
+
const columnMap = this.#columnMap;
|
|
76
|
+
const data = this.#dataWindow.data;
|
|
77
|
+
const categoryColumn = this.#categoryColumn;
|
|
78
|
+
const seriesColumns = this.#seriesColumns;
|
|
79
|
+
const config = this.#config;
|
|
80
|
+
const categoryValues = [];
|
|
81
|
+
const seriesMap = new Map();
|
|
82
|
+
const { itemColorFunction = defaultItemColorFunction, symbolSize = 6 } = config;
|
|
83
|
+
data.forEach((row)=>{
|
|
84
|
+
const categoryValue = row[columnMap[categoryColumn]];
|
|
85
|
+
categoryValues.push(categoryValue);
|
|
86
|
+
for (const seriesColumn of seriesColumns){
|
|
87
|
+
let lineSeries;
|
|
88
|
+
let scatterSeries;
|
|
89
|
+
const seriesTuple = seriesMap.get(seriesColumn);
|
|
90
|
+
if (seriesTuple) [lineSeries, scatterSeries] = seriesTuple;
|
|
91
|
+
else {
|
|
92
|
+
if (!colorMap.has(seriesColumn)) colorMap.set(seriesColumn, this.#palette[this.#colorMap.size]);
|
|
93
|
+
lineSeries = {
|
|
94
|
+
id: seriesColumn,
|
|
95
|
+
name: seriesColumn,
|
|
96
|
+
label: seriesColumn,
|
|
97
|
+
connectNulls: true,
|
|
98
|
+
data: [],
|
|
99
|
+
type: "line",
|
|
100
|
+
itemStyle: {
|
|
101
|
+
color: itemColorFunction
|
|
102
|
+
},
|
|
103
|
+
lineStyle: {
|
|
104
|
+
width: 1.5
|
|
105
|
+
},
|
|
106
|
+
symbol: "circle",
|
|
107
|
+
symbolSize
|
|
108
|
+
};
|
|
109
|
+
if (this.#dataExclusions) {
|
|
110
|
+
const { symbol } = this.#dataExclusions;
|
|
111
|
+
scatterSeries = {
|
|
112
|
+
id: `${seriesColumn}-excluded`,
|
|
113
|
+
data: [],
|
|
114
|
+
itemStyle: {
|
|
115
|
+
borderColor: "#FDC82F",
|
|
116
|
+
color: "#101820",
|
|
117
|
+
borderWidth: 2
|
|
118
|
+
},
|
|
119
|
+
label: "",
|
|
120
|
+
name: seriesColumn,
|
|
121
|
+
symbol,
|
|
122
|
+
symbolSize: 20,
|
|
123
|
+
type: "scatter"
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
if (scatterSeries) seriesMap.set(seriesColumn, [
|
|
127
|
+
lineSeries,
|
|
128
|
+
scatterSeries
|
|
129
|
+
]);
|
|
130
|
+
else seriesMap.set(seriesColumn, [
|
|
131
|
+
lineSeries
|
|
132
|
+
]);
|
|
133
|
+
}
|
|
134
|
+
const key = row[KEY];
|
|
135
|
+
const value = row[columnMap[seriesColumn]];
|
|
136
|
+
if (this.#dataExclusions?.isExcludedData(row, columnMap, seriesColumn)) {
|
|
137
|
+
lineSeries.data.push(DataSourceValue(key, row, null));
|
|
138
|
+
scatterSeries?.data.push(DataSourceValue(key, row, value));
|
|
139
|
+
} else {
|
|
140
|
+
lineSeries.data.push(DataSourceValue(key, row, value));
|
|
141
|
+
scatterSeries?.data.push(DataSourceValue(key, row, null));
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
return [
|
|
146
|
+
categoryValues,
|
|
147
|
+
Array.from(seriesMap.values()).flat()
|
|
148
|
+
];
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
export { ChartSeries };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { WindowRange, metadataKeys } from "@vuu-ui/vuu-utils";
|
|
2
|
+
const { IDX: IDX, KEY: KEY } = metadataKeys;
|
|
3
|
+
class MovingDataRowWindow {
|
|
4
|
+
data;
|
|
5
|
+
rowCount = 0;
|
|
6
|
+
#range;
|
|
7
|
+
constructor({ from, to }){
|
|
8
|
+
this.#range = new WindowRange(from, to);
|
|
9
|
+
this.data = new Array(Math.max(0, to - from));
|
|
10
|
+
this.rowCount = 0;
|
|
11
|
+
}
|
|
12
|
+
setRowCount = (rowCount)=>{
|
|
13
|
+
if (rowCount < this.data.length) this.data.length = rowCount;
|
|
14
|
+
this.rowCount = rowCount;
|
|
15
|
+
};
|
|
16
|
+
add(data) {
|
|
17
|
+
const index = data[IDX];
|
|
18
|
+
if (this.isWithinRange(index)) {
|
|
19
|
+
const internalIndex = index - this.#range.from;
|
|
20
|
+
this.data[internalIndex] = data;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
getAtIndex(index) {
|
|
24
|
+
return this.#range.isWithin(index) && null != this.data[index - this.#range.from] ? this.data[index - this.#range.from] : void 0;
|
|
25
|
+
}
|
|
26
|
+
getByKey(key) {
|
|
27
|
+
return this.data.find((row)=>row[KEY] === key);
|
|
28
|
+
}
|
|
29
|
+
isWithinRange(index) {
|
|
30
|
+
return this.#range.isWithin(index);
|
|
31
|
+
}
|
|
32
|
+
setRange({ from, to }) {
|
|
33
|
+
if (from !== this.#range.from || to !== this.#range.to) {
|
|
34
|
+
const [overlapFrom, overlapTo] = this.#range.overlap(from, to);
|
|
35
|
+
const newData = new Array(Math.max(0, to - from));
|
|
36
|
+
for(let i = overlapFrom; i < overlapTo; i++){
|
|
37
|
+
const data = this.getAtIndex(i);
|
|
38
|
+
if (data) {
|
|
39
|
+
const index = i - from;
|
|
40
|
+
newData[index] = data;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
this.data = newData;
|
|
44
|
+
this.#range.from = from;
|
|
45
|
+
this.#range.to = to;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
get hasData() {
|
|
49
|
+
return this.data.some((d)=>void 0 !== d);
|
|
50
|
+
}
|
|
51
|
+
get firstRow() {
|
|
52
|
+
for(let i = 0; i < this.data.length; i++)if (this.data[i]) return this.data[i];
|
|
53
|
+
throw Error("[DataRowMovingWinddow] firstRow, no data");
|
|
54
|
+
}
|
|
55
|
+
get range() {
|
|
56
|
+
return this.#range;
|
|
57
|
+
}
|
|
58
|
+
get hasAllRowsWithinRange() {
|
|
59
|
+
const { from, to } = this.#range;
|
|
60
|
+
for(let i = from; i < to; i++)if (void 0 === this.getAtIndex(i)) return false;
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
export { MovingDataRowWindow };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const chartTooltip = (params)=>{
|
|
2
|
+
if (params.length > 0) {
|
|
3
|
+
const [{ axisValueLabel }] = params;
|
|
4
|
+
const values = [];
|
|
5
|
+
for (const { color, seriesName, seriesType, value } of params)if ('line' === seriesType) values.push({
|
|
6
|
+
color,
|
|
7
|
+
value,
|
|
8
|
+
seriesName
|
|
9
|
+
});
|
|
10
|
+
const tooltipEntries = values.map(({ color, value, seriesName })=>[
|
|
11
|
+
'<div class="vuuChart-tooltip-entry">',
|
|
12
|
+
`<span class="vuuChart-tooltip-icon" style="background:${color};"></span>`,
|
|
13
|
+
`<span class="vuuChart-tooltip-label">${seriesName}</span>`,
|
|
14
|
+
`<span class="vuuChart-tooltip-value">${value ?? 'n/a'}</span>`,
|
|
15
|
+
'</div>'
|
|
16
|
+
].join(""));
|
|
17
|
+
return [
|
|
18
|
+
`<div class="vuuChart-tooltip-title">${axisValueLabel}</div>`,
|
|
19
|
+
'<div class="vuuChart-tooltip-container">'
|
|
20
|
+
].concat(tooltipEntries).concat('</div>').join("");
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
export { chartTooltip };
|
package/src/index.mjs
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { useContextMenu } from "@vuu-ui/vuu-context-menu";
|
|
2
|
+
import { useCallback } from "react";
|
|
3
|
+
const useChartContextMenu = ({ columnMap })=>{
|
|
4
|
+
const showContextMenu = useContextMenu();
|
|
5
|
+
const onContextMenu = useCallback(({ data, event, seriesName })=>{
|
|
6
|
+
if (event && seriesName) {
|
|
7
|
+
event?.stop();
|
|
8
|
+
const { row } = data;
|
|
9
|
+
const menuOptions = {
|
|
10
|
+
column: seriesName,
|
|
11
|
+
columnMap,
|
|
12
|
+
row
|
|
13
|
+
};
|
|
14
|
+
showContextMenu(event.event, "series", menuOptions);
|
|
15
|
+
}
|
|
16
|
+
}, [
|
|
17
|
+
columnMap,
|
|
18
|
+
showContextMenu
|
|
19
|
+
]);
|
|
20
|
+
return onContextMenu;
|
|
21
|
+
};
|
|
22
|
+
export { useChartContextMenu };
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { itemsChanged } from "@vuu-ui/vuu-utils";
|
|
2
|
+
import { useMemo, useState } from "react";
|
|
3
|
+
import { ChartSeries } from "./ChartSeries.mjs";
|
|
4
|
+
import { chartTooltip } from "./chartTooltip.mjs";
|
|
5
|
+
const defaultPalette = [
|
|
6
|
+
"#4676bf",
|
|
7
|
+
"#ab6528",
|
|
8
|
+
"#9f55c2",
|
|
9
|
+
"#2a8285",
|
|
10
|
+
"#697694",
|
|
11
|
+
"#B0549d"
|
|
12
|
+
];
|
|
13
|
+
const combineConfig = (config, overrides)=>({
|
|
14
|
+
...config,
|
|
15
|
+
...overrides
|
|
16
|
+
});
|
|
17
|
+
const useChartOptions = ({ categoryColumnName, config, dataExclusions, dataSource, itemColorFunction, palette = defaultPalette, seriesColumnNames, showTooltip = true, symbolSizeFunction: symbolSize })=>{
|
|
18
|
+
const [, forceRender] = useState({});
|
|
19
|
+
const chartSeries = useMemo(()=>{
|
|
20
|
+
const cs = new ChartSeries({
|
|
21
|
+
config: combineConfig(config, {
|
|
22
|
+
itemColorFunction,
|
|
23
|
+
symbolSize
|
|
24
|
+
}),
|
|
25
|
+
dataExclusions,
|
|
26
|
+
dataSource,
|
|
27
|
+
palette
|
|
28
|
+
});
|
|
29
|
+
cs.on("update", ()=>forceRender({}));
|
|
30
|
+
return cs;
|
|
31
|
+
}, [
|
|
32
|
+
dataSource,
|
|
33
|
+
config
|
|
34
|
+
]);
|
|
35
|
+
useMemo(()=>{
|
|
36
|
+
if (categoryColumnName !== chartSeries.categoryColumn) chartSeries.categoryColumn = categoryColumnName;
|
|
37
|
+
if (itemsChanged(seriesColumnNames, chartSeries.seriesColumnNames)) chartSeries.seriesColumnNames = seriesColumnNames;
|
|
38
|
+
}, [
|
|
39
|
+
categoryColumnName,
|
|
40
|
+
chartSeries,
|
|
41
|
+
seriesColumnNames
|
|
42
|
+
]);
|
|
43
|
+
return {
|
|
44
|
+
animation: false,
|
|
45
|
+
color: chartSeries.palette,
|
|
46
|
+
dataZoom: [
|
|
47
|
+
{
|
|
48
|
+
backgroundColor: "var(--vuuChart-zoom-background, transparent)",
|
|
49
|
+
borderColor: "var(--vuuChart-zoom-borderColor, white)",
|
|
50
|
+
handleStyle: {
|
|
51
|
+
color: "var(--vuuChart-zoom-handleColor, white)"
|
|
52
|
+
},
|
|
53
|
+
moveHandleStyle: {
|
|
54
|
+
color: "var(--vuuChart-zoom-slideColor, white)"
|
|
55
|
+
},
|
|
56
|
+
type: "slider",
|
|
57
|
+
start: 0,
|
|
58
|
+
end: 100
|
|
59
|
+
}
|
|
60
|
+
],
|
|
61
|
+
grid: {
|
|
62
|
+
left: "0",
|
|
63
|
+
bottom: 0,
|
|
64
|
+
right: 5
|
|
65
|
+
},
|
|
66
|
+
series: chartSeries.series,
|
|
67
|
+
tooltip: showTooltip ? {
|
|
68
|
+
alwaysShowContent: true,
|
|
69
|
+
backgroundColor: "",
|
|
70
|
+
borderColor: "",
|
|
71
|
+
className: "vuuChartTooltip",
|
|
72
|
+
enterable: true,
|
|
73
|
+
formatter: chartTooltip,
|
|
74
|
+
trigger: "axis"
|
|
75
|
+
} : void 0,
|
|
76
|
+
xAxis: {
|
|
77
|
+
data: chartSeries.categories
|
|
78
|
+
},
|
|
79
|
+
yAxis: {
|
|
80
|
+
splitLine: {
|
|
81
|
+
lineStyle: {
|
|
82
|
+
color: "var(--salt-separable-tertiary-borderColor)"
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
export { useChartOptions };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { useCallback, useRef, useState } from "react";
|
|
2
|
+
const dataItemMatch = (dataItem, targetSeries, targetKey)=>dataItem?.column === targetSeries && dataItem?.key === targetKey;
|
|
3
|
+
const dataItemInList = (dataItems, targetColumn, targetKey)=>dataItems.some((dataItem)=>dataItemMatch(dataItem, targetColumn, targetKey));
|
|
4
|
+
const useChartSelection = (_props)=>{
|
|
5
|
+
const [selectedKeys, setSelectedKeys] = useState([]);
|
|
6
|
+
const [, setHighlightedKey] = useState();
|
|
7
|
+
const selectedKeysRef = useRef(selectedKeys);
|
|
8
|
+
const highlightedKeyRef = useRef(void 0);
|
|
9
|
+
const handleClick = useCallback(({ data, event, seriesName: column })=>{
|
|
10
|
+
if (column) {
|
|
11
|
+
event?.stop();
|
|
12
|
+
const { row } = data;
|
|
13
|
+
const key = row[6];
|
|
14
|
+
setSelectedKeys((currentSelection)=>selectedKeysRef.current = dataItemInList(currentSelection, column, key) ? [] : [
|
|
15
|
+
{
|
|
16
|
+
column,
|
|
17
|
+
key
|
|
18
|
+
}
|
|
19
|
+
]);
|
|
20
|
+
}
|
|
21
|
+
}, []);
|
|
22
|
+
const handleMouseOver = useCallback(({ data, seriesName })=>{
|
|
23
|
+
if (seriesName) {
|
|
24
|
+
const { row } = data;
|
|
25
|
+
setHighlightedKey(highlightedKeyRef.current = {
|
|
26
|
+
column: seriesName,
|
|
27
|
+
key: row[6]
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
}, []);
|
|
31
|
+
const handleMouseOut = useCallback(()=>{
|
|
32
|
+
setHighlightedKey(highlightedKeyRef.current = void 0);
|
|
33
|
+
}, []);
|
|
34
|
+
const itemColorFunction = useCallback(({ color, data, seriesName })=>dataItemInList(selectedKeysRef.current, seriesName, data.key) ? "purple" : color, []);
|
|
35
|
+
const symbolSizeFunction = useCallback((value, { data, seriesName })=>{
|
|
36
|
+
const isSelected = dataItemInList(selectedKeysRef.current, seriesName, data.key);
|
|
37
|
+
return isSelected || dataItemMatch(highlightedKeyRef.current, seriesName, data.key) ? 16 : 6;
|
|
38
|
+
}, []);
|
|
39
|
+
return {
|
|
40
|
+
onClick: handleClick,
|
|
41
|
+
onMouseOver: handleMouseOver,
|
|
42
|
+
onMouseOut: handleMouseOut,
|
|
43
|
+
itemColorFunction,
|
|
44
|
+
symbolSizeFunction
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
export { useChartSelection };
|
package/cjs/Chart.css.js
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var chartCss = "\n\n.vuuChart {\n\n .vuuChartTooltip {\n background-color: var(--salt-container-primary-background) !important;\n border-color:var(--salt-selectable-borderColor-selected) !important;\n border-radius: 6px !important;\n font-family: var(--salt-text-fontFamily) !important;\n\n .vuuChart-tooltip-title {\n color: var(--salt-content-primary-foreground) !important;\n }\n\n .vuuChart-tooltip-entry {\n align-items: center;\n display: flex;\n gap: 6px;\n\n .vuuChart-tooltip-icon {\n border-radius: 12px;\n display: block;\n flex: 0 0 12px;\n height: 12px;\n }\n .vuuChart-tooltip-label {\n color: var(--salt-content-secondary-foreground) !important;\n flex: 1 1 auto;\n font-size: var(--salt-text-label-fontSize) !important;\n min-width: 60px;\n padding-top: 3px;\n text-transform: capitalize;\n }\n .vuuChart-tooltip-value {\n flex: 1 1 auto;\n color: var(--salt-content-primary-foreground) !important;\n font-size: var(--salt-text-label-fontSize) !important;\n text-align: right;\n }\n }\n }\n}\n\n";
|
|
4
|
-
|
|
5
|
-
module.exports = chartCss;
|
|
6
|
-
//# sourceMappingURL=Chart.css.js.map
|
package/cjs/Chart.css.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Chart.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
|