@antv/gpt-vis 1.0.1 → 1.0.2
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 +87 -33
- package/README.zh-CN.md +87 -33
- package/dist/cjs/util/crosshair-axis-labels.d.ts +7 -1
- package/dist/cjs/util/crosshair-axis-labels.js +127 -30
- package/dist/cjs/util/html.d.ts +1 -0
- package/dist/cjs/util/html.js +29 -0
- package/dist/cjs/util/theme.js +3 -3
- package/dist/cjs/util/tokens.js +4 -4
- package/dist/cjs/vis/dual-axes/index.js +18 -0
- package/dist/cjs/vis/funnel/index.d.ts +0 -1
- package/dist/cjs/vis/funnel/index.js +21 -23
- package/dist/cjs/vis/table/index.js +13 -5
- package/dist/esm/util/crosshair-axis-labels.d.ts +7 -1
- package/dist/esm/util/crosshair-axis-labels.js +138 -35
- package/dist/esm/util/html.d.ts +1 -0
- package/dist/esm/util/html.js +3 -0
- package/dist/esm/util/theme.js +3 -3
- package/dist/esm/util/tokens.js +4 -4
- package/dist/esm/vis/dual-axes/index.js +31 -1
- package/dist/esm/vis/funnel/index.d.ts +0 -1
- package/dist/esm/vis/funnel/index.js +15 -14
- package/dist/esm/vis/table/index.js +9 -9
- package/dist/umd/index.min.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -57,19 +57,14 @@ const gptVis = new GPTVis({
|
|
|
57
57
|
height: 400,
|
|
58
58
|
});
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
value
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
- time 2022
|
|
69
|
-
value 150
|
|
70
|
-
`;
|
|
71
|
-
|
|
72
|
-
gptVis.render(visSyntax);
|
|
60
|
+
gptVis.render({
|
|
61
|
+
type: 'line',
|
|
62
|
+
data: [
|
|
63
|
+
{ time: '2020', value: 100 },
|
|
64
|
+
{ time: '2021', value: 120 },
|
|
65
|
+
{ time: '2022', value: 150 },
|
|
66
|
+
],
|
|
67
|
+
});
|
|
73
68
|
```
|
|
74
69
|
|
|
75
70
|
### Streaming Rendering
|
|
@@ -94,9 +89,73 @@ function onToken(token) {
|
|
|
94
89
|
|
|
95
90
|
## 📚 Syntax Guide
|
|
96
91
|
|
|
97
|
-
`render()` supports two input formats:
|
|
92
|
+
`render()` supports two input formats: JSON objects (ideal for programmatic use) and DSL syntax (ideal for LLM streaming).
|
|
93
|
+
|
|
94
|
+
### Object Config
|
|
95
|
+
|
|
96
|
+
Pass JSON objects directly for programmatic chart creation:
|
|
97
|
+
|
|
98
|
+
**Line chart:**
|
|
99
|
+
|
|
100
|
+
```javascript
|
|
101
|
+
gptVis.render({
|
|
102
|
+
type: 'line',
|
|
103
|
+
data: [
|
|
104
|
+
{ time: '2020', value: 100 },
|
|
105
|
+
{ time: '2021', value: 120 },
|
|
106
|
+
{ time: '2022', value: 150 },
|
|
107
|
+
],
|
|
108
|
+
});
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**Pie chart:**
|
|
112
|
+
|
|
113
|
+
```javascript
|
|
114
|
+
gptVis.render({
|
|
115
|
+
type: 'pie',
|
|
116
|
+
data: [
|
|
117
|
+
{ category: 'Android', value: 72 },
|
|
118
|
+
{ category: 'iOS', value: 28 },
|
|
119
|
+
],
|
|
120
|
+
innerRadius: 0.6,
|
|
121
|
+
});
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**Themes:**
|
|
125
|
+
|
|
126
|
+
Three built-in themes, switchable via the `theme` property:
|
|
127
|
+
|
|
128
|
+
| Theme | Identifier | Background | Palette |
|
|
129
|
+
| --------------- | ---------- | ---------- | ----------------------------------------------------- |
|
|
130
|
+
| Default (Light) | `default` | `#FFF` | `#1783FF` `#F08F56` `#D580FF` `#00C9C9` `#7863FF` ... |
|
|
131
|
+
| Dark | `dark` | `#000` | `#1783FF` `#F08F56` `#D580FF` `#00C9C9` `#7863FF` ... |
|
|
132
|
+
| Academy | `academy` | `#FFF` | `#4e79a7` `#f28e2c` `#e15759` `#76b7b2` `#59a14f` ... |
|
|
133
|
+
|
|
134
|
+
```javascript
|
|
135
|
+
gptVis.render({
|
|
136
|
+
type: 'line',
|
|
137
|
+
data: [
|
|
138
|
+
{ time: '2020', value: 100 },
|
|
139
|
+
{ time: '2021', value: 120 },
|
|
140
|
+
],
|
|
141
|
+
theme: 'dark',
|
|
142
|
+
});
|
|
143
|
+
```
|
|
98
144
|
|
|
99
|
-
|
|
145
|
+
**Custom Styles:**
|
|
146
|
+
|
|
147
|
+
```javascript
|
|
148
|
+
gptVis.render({
|
|
149
|
+
type: 'line',
|
|
150
|
+
data: [
|
|
151
|
+
{ time: '2020', value: 100 },
|
|
152
|
+
{ time: '2021', value: 120 },
|
|
153
|
+
],
|
|
154
|
+
style: { lineWidth: 3, palette: ['#5B8FF9', '#5AD8A6'] },
|
|
155
|
+
});
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### DSL Syntax
|
|
100
159
|
|
|
101
160
|
Declarative markdown-like syntax that LLMs can generate without learning complex APIs:
|
|
102
161
|
|
|
@@ -121,14 +180,6 @@ innerRadius 0.6
|
|
|
121
180
|
|
|
122
181
|
**Themes:**
|
|
123
182
|
|
|
124
|
-
Three built-in themes, switchable via the `theme` property:
|
|
125
|
-
|
|
126
|
-
| Theme | Identifier | Background | Palette |
|
|
127
|
-
| --------------- | ---------- | ---------- | ----------------------------------------------------- |
|
|
128
|
-
| Default (Light) | `default` | `#FFF` | `#1783FF` `#F08F56` `#D580FF` `#00C9C9` `#7863FF` ... |
|
|
129
|
-
| Dark | `dark` | `#000` | `#1783FF` `#F08F56` `#D580FF` `#00C9C9` `#7863FF` ... |
|
|
130
|
-
| Academy | `academy` | `#FFF` | `#4e79a7` `#f28e2c` `#e15759` `#76b7b2` `#59a14f` ... |
|
|
131
|
-
|
|
132
183
|
```
|
|
133
184
|
vis line
|
|
134
185
|
data
|
|
@@ -179,18 +230,21 @@ data
|
|
|
179
230
|
- name Phase 2
|
|
180
231
|
```
|
|
181
232
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
Also supports passing JSON objects directly, ideal for programmatic use:
|
|
233
|
+
**Render DSL syntax:**
|
|
185
234
|
|
|
186
235
|
```javascript
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
236
|
+
const visSyntax = `
|
|
237
|
+
vis line
|
|
238
|
+
data
|
|
239
|
+
- time 2020
|
|
240
|
+
value 100
|
|
241
|
+
- time 2021
|
|
242
|
+
value 120
|
|
243
|
+
- time 2022
|
|
244
|
+
value 150
|
|
245
|
+
`;
|
|
246
|
+
|
|
247
|
+
gptVis.render(visSyntax);
|
|
194
248
|
```
|
|
195
249
|
|
|
196
250
|
## 📊 Chart Types
|
package/README.zh-CN.md
CHANGED
|
@@ -57,19 +57,14 @@ const gptVis = new GPTVis({
|
|
|
57
57
|
height: 400,
|
|
58
58
|
});
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
value
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
- time 2022
|
|
69
|
-
value 150
|
|
70
|
-
`;
|
|
71
|
-
|
|
72
|
-
gptVis.render(visSyntax);
|
|
60
|
+
gptVis.render({
|
|
61
|
+
type: 'line',
|
|
62
|
+
data: [
|
|
63
|
+
{ time: '2020', value: 100 },
|
|
64
|
+
{ time: '2021', value: 120 },
|
|
65
|
+
{ time: '2022', value: 150 },
|
|
66
|
+
],
|
|
67
|
+
});
|
|
73
68
|
```
|
|
74
69
|
|
|
75
70
|
### 流式渲染
|
|
@@ -94,9 +89,73 @@ function onToken(token) {
|
|
|
94
89
|
|
|
95
90
|
## 📚 语法指南
|
|
96
91
|
|
|
97
|
-
`render()`
|
|
92
|
+
`render()` 支持两种输入格式:对象配置(适合程序化调用)和 DSL 语法(适合 LLM 流式生成)。
|
|
93
|
+
|
|
94
|
+
### 对象配置
|
|
95
|
+
|
|
96
|
+
直接传入 JSON 对象,适合程序化图表创建:
|
|
97
|
+
|
|
98
|
+
**折线图:**
|
|
99
|
+
|
|
100
|
+
```javascript
|
|
101
|
+
gptVis.render({
|
|
102
|
+
type: 'line',
|
|
103
|
+
data: [
|
|
104
|
+
{ time: '2020', value: 100 },
|
|
105
|
+
{ time: '2021', value: 120 },
|
|
106
|
+
{ time: '2022', value: 150 },
|
|
107
|
+
],
|
|
108
|
+
});
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**饼图:**
|
|
112
|
+
|
|
113
|
+
```javascript
|
|
114
|
+
gptVis.render({
|
|
115
|
+
type: 'pie',
|
|
116
|
+
data: [
|
|
117
|
+
{ category: 'Android', value: 72 },
|
|
118
|
+
{ category: 'iOS', value: 28 },
|
|
119
|
+
],
|
|
120
|
+
innerRadius: 0.6,
|
|
121
|
+
});
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**主题:**
|
|
125
|
+
|
|
126
|
+
内置三套主题,通过 `theme` 属性切换:
|
|
127
|
+
|
|
128
|
+
| 主题 | 标识 | 背景色 | 色板 |
|
|
129
|
+
| ------------ | --------- | ------ | ----------------------------------------------------- |
|
|
130
|
+
| 默认(亮色) | `default` | `#FFF` | `#1783FF` `#F08F56` `#D580FF` `#00C9C9` `#7863FF` ... |
|
|
131
|
+
| 暗色 | `dark` | `#000` | `#1783FF` `#F08F56` `#D580FF` `#00C9C9` `#7863FF` ... |
|
|
132
|
+
| 学术 | `academy` | `#FFF` | `#4e79a7` `#f28e2c` `#e15759` `#76b7b2` `#59a14f` ... |
|
|
133
|
+
|
|
134
|
+
```javascript
|
|
135
|
+
gptVis.render({
|
|
136
|
+
type: 'line',
|
|
137
|
+
data: [
|
|
138
|
+
{ time: '2020', value: 100 },
|
|
139
|
+
{ time: '2021', value: 120 },
|
|
140
|
+
],
|
|
141
|
+
theme: 'dark',
|
|
142
|
+
});
|
|
143
|
+
```
|
|
98
144
|
|
|
99
|
-
|
|
145
|
+
**自定义样式:**
|
|
146
|
+
|
|
147
|
+
```javascript
|
|
148
|
+
gptVis.render({
|
|
149
|
+
type: 'line',
|
|
150
|
+
data: [
|
|
151
|
+
{ time: '2020', value: 100 },
|
|
152
|
+
{ time: '2021', value: 120 },
|
|
153
|
+
],
|
|
154
|
+
style: { lineWidth: 3, palette: ['#5B8FF9', '#5AD8A6'] },
|
|
155
|
+
});
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### DSL 语法
|
|
100
159
|
|
|
101
160
|
类 Markdown 的声明式语法,LLM 无需学习复杂 API 即可生成:
|
|
102
161
|
|
|
@@ -121,14 +180,6 @@ innerRadius 0.6
|
|
|
121
180
|
|
|
122
181
|
**主题:**
|
|
123
182
|
|
|
124
|
-
内置三套主题,通过 `theme` 属性切换:
|
|
125
|
-
|
|
126
|
-
| 主题 | 标识 | 背景色 | 色板 |
|
|
127
|
-
| ------------ | --------- | ------ | ----------------------------------------------------- |
|
|
128
|
-
| 默认(亮色) | `default` | `#FFF` | `#1783FF` `#F08F56` `#D580FF` `#00C9C9` `#7863FF` ... |
|
|
129
|
-
| 暗色 | `dark` | `#000` | `#1783FF` `#F08F56` `#D580FF` `#00C9C9` `#7863FF` ... |
|
|
130
|
-
| 学术 | `academy` | `#FFF` | `#4e79a7` `#f28e2c` `#e15759` `#76b7b2` `#59a14f` ... |
|
|
131
|
-
|
|
132
183
|
```
|
|
133
184
|
vis line
|
|
134
185
|
data
|
|
@@ -179,18 +230,21 @@ data
|
|
|
179
230
|
- name 第二阶段
|
|
180
231
|
```
|
|
181
232
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
也支持直接传入 JSON 对象,适合程序化调用:
|
|
233
|
+
**使用 DSL 语法渲染:**
|
|
185
234
|
|
|
186
235
|
```javascript
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
236
|
+
const visSyntax = `
|
|
237
|
+
vis line
|
|
238
|
+
data
|
|
239
|
+
- time 2020
|
|
240
|
+
value 100
|
|
241
|
+
- time 2021
|
|
242
|
+
value 120
|
|
243
|
+
- time 2022
|
|
244
|
+
value 150
|
|
245
|
+
`;
|
|
246
|
+
|
|
247
|
+
gptVis.render(visSyntax);
|
|
194
248
|
```
|
|
195
249
|
|
|
196
250
|
## 📊 图表类型
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import { type Chart } from '@antv/g2';
|
|
2
2
|
import type { VisualizationTheme } from '../types';
|
|
3
|
+
export type CrosshairAxisLabelsOptions = {
|
|
4
|
+
showXLabel?: boolean;
|
|
5
|
+
useStandaloneYLabel?: boolean;
|
|
6
|
+
yAxisPosition?: 'left' | 'right';
|
|
7
|
+
yField?: string;
|
|
8
|
+
};
|
|
3
9
|
/**
|
|
4
10
|
* Bridges G2 tooltip crosshairs to axis value tags.
|
|
5
11
|
*
|
|
6
12
|
* G2 does not currently expose axis tags for tooltip crosshairs, so this adapter
|
|
7
13
|
* reads the rule geometry created by G2 5.4 and renders labels with LineCrosshair.
|
|
8
14
|
*/
|
|
9
|
-
export declare const bindCrosshairAxisLabels: (chart: Chart, theme: VisualizationTheme) => (() => void);
|
|
15
|
+
export declare const bindCrosshairAxisLabels: (chart: Chart, theme: VisualizationTheme, { showXLabel, useStandaloneYLabel, yAxisPosition, yField, }?: CrosshairAxisLabelsOptions) => (() => void);
|
|
@@ -25,27 +25,41 @@ module.exports = __toCommonJS(crosshair_axis_labels_exports);
|
|
|
25
25
|
var import_component = require("@antv/component");
|
|
26
26
|
var import_g2 = require("@antv/g2");
|
|
27
27
|
var import_tokens = require("./tokens");
|
|
28
|
+
var MAX_CROSSHAIR_DECIMAL_PLACES = 6;
|
|
28
29
|
var formatCrosshairAxisValue = (value, formatter, precision) => {
|
|
29
30
|
if (value === void 0 || value === null || value === "")
|
|
30
31
|
return "";
|
|
32
|
+
let displayValue = value;
|
|
31
33
|
try {
|
|
32
34
|
const formatted = formatter == null ? void 0 : formatter(value);
|
|
33
|
-
if (formatted !== void 0 && formatted !== null)
|
|
34
|
-
|
|
35
|
+
if (formatted !== void 0 && formatted !== null) {
|
|
36
|
+
const numericFormatted = typeof formatted === "number" || typeof formatted === "string" && formatted.trim() !== "" && Number.isFinite(Number(formatted)) ? Number(formatted) : void 0;
|
|
37
|
+
if (numericFormatted === void 0)
|
|
38
|
+
return String(formatted);
|
|
39
|
+
displayValue = numericFormatted;
|
|
40
|
+
}
|
|
35
41
|
} catch {
|
|
36
42
|
}
|
|
37
|
-
if (
|
|
38
|
-
return
|
|
39
|
-
if (typeof
|
|
40
|
-
|
|
43
|
+
if (displayValue instanceof Date)
|
|
44
|
+
return displayValue.toLocaleString();
|
|
45
|
+
if (typeof displayValue === "number" && Number.isFinite(displayValue)) {
|
|
46
|
+
if (displayValue !== 0 && Math.abs(displayValue) < 10 ** -MAX_CROSSHAIR_DECIMAL_PLACES) {
|
|
47
|
+
return Number(displayValue.toPrecision(4)).toString();
|
|
48
|
+
}
|
|
49
|
+
const decimalPlaces = Math.min(
|
|
50
|
+
Math.max(precision ?? MAX_CROSSHAIR_DECIMAL_PLACES, 0),
|
|
51
|
+
MAX_CROSSHAIR_DECIMAL_PLACES
|
|
52
|
+
);
|
|
53
|
+
return Number(displayValue.toFixed(decimalPlaces)).toString();
|
|
41
54
|
}
|
|
42
|
-
return String(
|
|
55
|
+
return String(displayValue);
|
|
43
56
|
};
|
|
44
57
|
var getNumberPrecision = (value) => {
|
|
45
58
|
var _a;
|
|
46
59
|
if (!Number.isFinite(value) || value === 0)
|
|
47
60
|
return 0;
|
|
48
|
-
const
|
|
61
|
+
const normalizedValue = Number(value.toPrecision(12));
|
|
62
|
+
const [coefficient, exponentText = "0"] = Math.abs(normalizedValue).toExponential().split("e");
|
|
49
63
|
const coefficientPrecision = ((_a = coefficient.split(".")[1]) == null ? void 0 : _a.length) || 0;
|
|
50
64
|
return Math.max(0, coefficientPrecision - Number(exponentText));
|
|
51
65
|
};
|
|
@@ -64,7 +78,7 @@ var getCrosshairScalePrecision = (scale) => {
|
|
|
64
78
|
}
|
|
65
79
|
if (!Number.isFinite(interval))
|
|
66
80
|
return void 0;
|
|
67
|
-
return Math.min(getNumberPrecision(interval) + 2,
|
|
81
|
+
return Math.min(getNumberPrecision(interval) + 2, MAX_CROSSHAIR_DECIMAL_PLACES);
|
|
68
82
|
};
|
|
69
83
|
var getCrosshairTagStyle = (theme, tokens) => ({
|
|
70
84
|
lineLineWidth: 0,
|
|
@@ -86,6 +100,25 @@ var getCrosshairTagStyle = (theme, tokens) => ({
|
|
|
86
100
|
tagLabelLineWidth: 0,
|
|
87
101
|
tagPointerEvents: "none"
|
|
88
102
|
});
|
|
103
|
+
var getStandaloneTagStyle = (theme, tokens) => ({
|
|
104
|
+
align: "start",
|
|
105
|
+
verticalAlign: "middle",
|
|
106
|
+
padding: [4, 7],
|
|
107
|
+
radius: 6,
|
|
108
|
+
backgroundFill: tokens.textPrimary,
|
|
109
|
+
backgroundStroke: "transparent",
|
|
110
|
+
backgroundLineWidth: 0,
|
|
111
|
+
backgroundShadowColor: theme === "dark" ? "rgba(0, 0, 0, 0.38)" : "rgba(15, 23, 42, 0.18)",
|
|
112
|
+
backgroundShadowBlur: 8,
|
|
113
|
+
backgroundShadowOffsetY: 2,
|
|
114
|
+
labelFill: tokens.background,
|
|
115
|
+
labelFillOpacity: 1,
|
|
116
|
+
labelFontFamily: import_tokens.CHART_FONT_FAMILY,
|
|
117
|
+
labelFontSize: 11,
|
|
118
|
+
labelFontWeight: 500,
|
|
119
|
+
labelLineWidth: 0,
|
|
120
|
+
pointerEvents: "none"
|
|
121
|
+
});
|
|
89
122
|
var clamp = (value, min, max) => Math.min(Math.max(value, Math.min(min, max)), Math.max(min, max));
|
|
90
123
|
var invertCrosshairValue = (scale, value) => {
|
|
91
124
|
var _a, _b, _c;
|
|
@@ -122,12 +155,41 @@ var getTooltipPlot = (context) => {
|
|
|
122
155
|
return void 0;
|
|
123
156
|
return (0, import_g2.selectPlotArea)(root);
|
|
124
157
|
};
|
|
125
|
-
var
|
|
158
|
+
var getScaleField = (scale) => {
|
|
159
|
+
var _a, _b;
|
|
160
|
+
return (_b = (_a = scale == null ? void 0 : scale.getOptions) == null ? void 0 : _a.call(scale)) == null ? void 0 : _b.field;
|
|
161
|
+
};
|
|
162
|
+
var findYScaleByField = (view, yField) => {
|
|
163
|
+
var _a;
|
|
164
|
+
return (_a = Object.entries(view.scale).find(
|
|
165
|
+
([scaleName, scale]) => /^y\d*$/.test(scaleName) && getScaleField(scale) === yField
|
|
166
|
+
)) == null ? void 0 : _a[1];
|
|
167
|
+
};
|
|
168
|
+
var getYScale = (view, yField) => yField ? findYScaleByField(view, yField) : view.scale.y;
|
|
169
|
+
var getCartesianView = (context, yField) => {
|
|
126
170
|
var _a;
|
|
127
171
|
return (_a = context.views) == null ? void 0 : _a.find(
|
|
128
|
-
(
|
|
172
|
+
(view) => {
|
|
173
|
+
var _a2, _b;
|
|
174
|
+
return Boolean(((_a2 = view.scale) == null ? void 0 : _a2.x) && getYScale(view, yField)) && typeof ((_b = view.coordinate) == null ? void 0 : _b.invert) === "function";
|
|
175
|
+
}
|
|
129
176
|
);
|
|
130
177
|
};
|
|
178
|
+
var hasAxisField = (field, yField) => Array.isArray(field) ? field.includes(yField) : field === yField;
|
|
179
|
+
var getYAxisLinePosition = (view, yField, position, fallback, plotX) => {
|
|
180
|
+
var _a;
|
|
181
|
+
if (!yField)
|
|
182
|
+
return fallback;
|
|
183
|
+
const axis = (_a = view.components) == null ? void 0 : _a.find(
|
|
184
|
+
({ bbox, position: axisPosition, scales, type }) => type === "axisY" && axisPosition === position && Number.isFinite(Number(bbox == null ? void 0 : bbox.x)) && (scales == null ? void 0 : scales.some((scale) => hasAxisField(scale.field, yField)))
|
|
185
|
+
);
|
|
186
|
+
if (!(axis == null ? void 0 : axis.bbox))
|
|
187
|
+
return fallback;
|
|
188
|
+
const x = Number(axis.bbox.x);
|
|
189
|
+
const width = Number(axis.bbox.width);
|
|
190
|
+
const axisX = position === "right" || !Number.isFinite(width) ? x : x + width;
|
|
191
|
+
return axisX - plotX;
|
|
192
|
+
};
|
|
131
193
|
var getRuleLine = (rule) => {
|
|
132
194
|
var _a, _b, _c, _d;
|
|
133
195
|
const x1 = Number((_a = rule == null ? void 0 : rule.style) == null ? void 0 : _a.x1);
|
|
@@ -155,24 +217,33 @@ var invertCoordinate = (view, point) => {
|
|
|
155
217
|
return void 0;
|
|
156
218
|
}
|
|
157
219
|
};
|
|
158
|
-
var bindCrosshairAxisLabels = (chart, theme
|
|
220
|
+
var bindCrosshairAxisLabels = (chart, theme, {
|
|
221
|
+
showXLabel = true,
|
|
222
|
+
useStandaloneYLabel = false,
|
|
223
|
+
yAxisPosition = "left",
|
|
224
|
+
yField
|
|
225
|
+
} = {}) => {
|
|
159
226
|
if (!chart || typeof chart.on !== "function")
|
|
160
227
|
return () => void 0;
|
|
161
228
|
const tagStyle = getCrosshairTagStyle(theme, (0, import_tokens.getChartVisualTokens)(theme));
|
|
229
|
+
const standaloneTagStyle = getStandaloneTagStyle(theme, (0, import_tokens.getChartVisualTokens)(theme));
|
|
162
230
|
let boundPlot = null;
|
|
163
231
|
let xCrosshair = null;
|
|
164
232
|
let yCrosshair = null;
|
|
233
|
+
let standaloneYTag = null;
|
|
165
234
|
let latestPointerY = null;
|
|
166
235
|
let latestXValue;
|
|
167
236
|
const destroyCrosshairs = () => {
|
|
168
237
|
xCrosshair == null ? void 0 : xCrosshair.destroy();
|
|
169
238
|
yCrosshair == null ? void 0 : yCrosshair.destroy();
|
|
239
|
+
standaloneYTag == null ? void 0 : standaloneYTag.destroy();
|
|
170
240
|
xCrosshair = null;
|
|
171
241
|
yCrosshair = null;
|
|
242
|
+
standaloneYTag = null;
|
|
172
243
|
boundPlot = null;
|
|
173
244
|
};
|
|
174
245
|
const hideCrosshairs = () => {
|
|
175
|
-
for (const crosshair of [xCrosshair, yCrosshair]) {
|
|
246
|
+
for (const crosshair of [xCrosshair, yCrosshair, standaloneYTag]) {
|
|
176
247
|
if (crosshair)
|
|
177
248
|
crosshair.style.visibility = "hidden";
|
|
178
249
|
}
|
|
@@ -193,7 +264,7 @@ var bindCrosshairAxisLabels = (chart, theme) => {
|
|
|
193
264
|
const xEnd = [xLine.x2 + plotX, xLine.y2 + plotY];
|
|
194
265
|
const yStart = [yLine.x1 + plotX, yLine.y1 + plotY];
|
|
195
266
|
const yEnd = [yLine.x2 + plotX, yLine.y2 + plotY];
|
|
196
|
-
if (!xCrosshair) {
|
|
267
|
+
if (showXLabel && !xCrosshair) {
|
|
197
268
|
xCrosshair = new import_component.LineCrosshair({
|
|
198
269
|
style: { ...tagStyle, startPos: xStart, endPos: xEnd, tagText: xText, tagPosition: "end" }
|
|
199
270
|
});
|
|
@@ -201,31 +272,38 @@ var bindCrosshairAxisLabels = (chart, theme) => {
|
|
|
201
272
|
xCrosshair.style.pointerEvents = "none";
|
|
202
273
|
layer.appendChild(xCrosshair);
|
|
203
274
|
}
|
|
204
|
-
if (!yCrosshair) {
|
|
275
|
+
if (showXLabel && !useStandaloneYLabel && !yCrosshair) {
|
|
205
276
|
yCrosshair = new import_component.LineCrosshair({
|
|
206
277
|
style: {
|
|
207
278
|
...tagStyle,
|
|
208
279
|
startPos: yStart,
|
|
209
280
|
endPos: yEnd,
|
|
210
281
|
tagText: yText,
|
|
211
|
-
tagPosition: "start"
|
|
282
|
+
tagPosition: yAxisPosition === "right" ? "end" : "start"
|
|
212
283
|
}
|
|
213
284
|
});
|
|
214
285
|
yCrosshair.style.zIndex = 7;
|
|
215
286
|
yCrosshair.style.pointerEvents = "none";
|
|
216
287
|
layer.appendChild(yCrosshair);
|
|
217
288
|
}
|
|
289
|
+
if ((useStandaloneYLabel || !showXLabel) && !standaloneYTag) {
|
|
290
|
+
standaloneYTag = new import_component.Tag({ style: { ...standaloneTagStyle, text: yText } });
|
|
291
|
+
standaloneYTag.style.zIndex = 7;
|
|
292
|
+
standaloneYTag.style.pointerEvents = "none";
|
|
293
|
+
layer.appendChild(standaloneYTag);
|
|
294
|
+
}
|
|
218
295
|
boundPlot = plot;
|
|
219
296
|
};
|
|
220
297
|
const updateCrosshairs = (event) => {
|
|
221
|
-
var _a, _b, _c, _d, _e, _f, _g, _h
|
|
298
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
222
299
|
const context = chart.getContext();
|
|
223
300
|
const plot = getTooltipPlot(context);
|
|
224
|
-
const view = getCartesianView(context);
|
|
301
|
+
const view = getCartesianView(context, yField);
|
|
225
302
|
if (!plot || !view) {
|
|
226
303
|
hideCrosshairs();
|
|
227
304
|
return;
|
|
228
305
|
}
|
|
306
|
+
const yScale = getYScale(view, yField);
|
|
229
307
|
const verticalRule = getRuleLine(plot.ruleY);
|
|
230
308
|
const horizontalRule = getRuleLine(plot.ruleX);
|
|
231
309
|
if (!verticalRule || !horizontalRule) {
|
|
@@ -240,36 +318,55 @@ var bindCrosshairAxisLabels = (chart, theme) => {
|
|
|
240
318
|
const y = clamp(pointerY, verticalRule.y1, verticalRule.y2);
|
|
241
319
|
const invertedPosition = invertCoordinate(view, [x, y]);
|
|
242
320
|
const xValue = latestXValue ?? invertCrosshairValue(view.scale.x, invertedPosition == null ? void 0 : invertedPosition[0]);
|
|
243
|
-
const yValue = invertCrosshairValue(
|
|
321
|
+
const yValue = invertCrosshairValue(yScale, invertedPosition == null ? void 0 : invertedPosition[1]) ?? ((_c = (_b = (_a = event.data) == null ? void 0 : _a.items) == null ? void 0 : _b[0]) == null ? void 0 : _c.value);
|
|
244
322
|
const xText = formatCrosshairAxisValue(xValue, (_e = (_d = view.scale.x).getFormatter) == null ? void 0 : _e.call(_d));
|
|
245
323
|
const yText = formatCrosshairAxisValue(
|
|
246
324
|
yValue,
|
|
247
|
-
(
|
|
248
|
-
getCrosshairScalePrecision(
|
|
325
|
+
(_f = yScale == null ? void 0 : yScale.getFormatter) == null ? void 0 : _f.call(yScale),
|
|
326
|
+
getCrosshairScalePrecision(yScale)
|
|
249
327
|
);
|
|
250
328
|
if (!xText || !yText) {
|
|
251
329
|
hideCrosshairs();
|
|
252
330
|
return;
|
|
253
331
|
}
|
|
254
|
-
if ((
|
|
332
|
+
if ((_g = plot.ruleY) == null ? void 0 : _g.style) {
|
|
255
333
|
plot.ruleY.style.x1 = x;
|
|
256
334
|
plot.ruleY.style.x2 = x;
|
|
257
335
|
}
|
|
258
|
-
if ((
|
|
336
|
+
if ((_h = plot.ruleX) == null ? void 0 : _h.style) {
|
|
259
337
|
plot.ruleX.style.y1 = y;
|
|
260
338
|
plot.ruleX.style.y2 = y;
|
|
261
339
|
}
|
|
262
340
|
const displayVerticalRule = { ...verticalRule, x1: x, x2: x };
|
|
263
341
|
const displayHorizontalRule = { ...horizontalRule, y1: y, y2: y };
|
|
264
342
|
ensureCrosshairs(plot, displayVerticalRule, displayHorizontalRule, xText, yText);
|
|
265
|
-
if (!xCrosshair || !yCrosshair)
|
|
343
|
+
if (showXLabel && !xCrosshair || (useStandaloneYLabel ? !standaloneYTag : !yCrosshair && !standaloneYTag))
|
|
266
344
|
return;
|
|
267
|
-
xCrosshair
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
yCrosshair
|
|
345
|
+
if (xCrosshair) {
|
|
346
|
+
xCrosshair.setText(xText);
|
|
347
|
+
xCrosshair.setPointer([x + plotX, verticalRule.y2 + plotY]);
|
|
348
|
+
xCrosshair.style.visibility = "visible";
|
|
349
|
+
}
|
|
350
|
+
if (yCrosshair) {
|
|
351
|
+
yCrosshair.setText(yText);
|
|
352
|
+
yCrosshair.setPointer([
|
|
353
|
+
(yAxisPosition === "right" ? horizontalRule.x2 : horizontalRule.x1) + plotX,
|
|
354
|
+
y + plotY
|
|
355
|
+
]);
|
|
356
|
+
yCrosshair.style.visibility = "visible";
|
|
357
|
+
}
|
|
358
|
+
if (standaloneYTag) {
|
|
359
|
+
const yAxisX = getYAxisLinePosition(
|
|
360
|
+
view,
|
|
361
|
+
yField,
|
|
362
|
+
yAxisPosition,
|
|
363
|
+
yAxisPosition === "right" ? horizontalRule.x2 : horizontalRule.x1,
|
|
364
|
+
plotX
|
|
365
|
+
);
|
|
366
|
+
standaloneYTag.update({ text: yText });
|
|
367
|
+
standaloneYTag.setLocalPosition([yAxisX + plotX, y + plotY]);
|
|
368
|
+
standaloneYTag.style.visibility = "visible";
|
|
369
|
+
}
|
|
273
370
|
};
|
|
274
371
|
const onPointerMove = (event) => {
|
|
275
372
|
const y = Number(event.offsetY ?? event.canvasY);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const escapeHtml: (value: unknown) => string;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
|
|
19
|
+
// src/util/html.ts
|
|
20
|
+
var html_exports = {};
|
|
21
|
+
__export(html_exports, {
|
|
22
|
+
escapeHtml: () => escapeHtml
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(html_exports);
|
|
25
|
+
var escapeHtml = (value) => (value == null ? "" : String(value)).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
26
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
27
|
+
0 && (module.exports = {
|
|
28
|
+
escapeHtml
|
|
29
|
+
});
|
package/dist/cjs/util/theme.js
CHANGED
|
@@ -156,12 +156,12 @@ var createTheme = (type) => {
|
|
|
156
156
|
} : {}
|
|
157
157
|
},
|
|
158
158
|
axisY: {
|
|
159
|
-
lineLineWidth:
|
|
159
|
+
lineLineWidth: 1,
|
|
160
160
|
grid: true,
|
|
161
161
|
gridStroke: tokens.axisGrid,
|
|
162
162
|
gridStrokeOpacity: 1,
|
|
163
|
-
gridLineWidth: isAcademy ? 1 : 0.
|
|
164
|
-
gridLineDash: isAcademy ? [0, 0] : [
|
|
163
|
+
gridLineWidth: isAcademy ? 1 : 0.75,
|
|
164
|
+
gridLineDash: isAcademy ? [0, 0] : [3, 3],
|
|
165
165
|
gridFilter: filterBaselineGrid
|
|
166
166
|
},
|
|
167
167
|
axisRadar: {
|
package/dist/cjs/util/tokens.js
CHANGED
|
@@ -43,8 +43,8 @@ var LIGHT_TOKENS = {
|
|
|
43
43
|
textPrimary: "#1F2937",
|
|
44
44
|
textSecondary: "#667085",
|
|
45
45
|
grid: "#E7EAF0",
|
|
46
|
-
axisGrid: "#
|
|
47
|
-
axisLine: "#
|
|
46
|
+
axisGrid: "#D0D5DD",
|
|
47
|
+
axisLine: "#98A2B3",
|
|
48
48
|
axisTick: "#98A2B3",
|
|
49
49
|
separator: "#FFFFFF",
|
|
50
50
|
tooltipBackground: "rgba(255, 255, 255, 0.96)",
|
|
@@ -58,8 +58,8 @@ var DARK_TOKENS = {
|
|
|
58
58
|
textPrimary: "#F3F4F6",
|
|
59
59
|
textSecondary: "#A7AFBE",
|
|
60
60
|
grid: "#343841",
|
|
61
|
-
axisGrid: "#
|
|
62
|
-
axisLine: "#
|
|
61
|
+
axisGrid: "#475467",
|
|
62
|
+
axisLine: "#667085",
|
|
63
63
|
axisTick: "#596170",
|
|
64
64
|
separator: "#141414",
|
|
65
65
|
tooltipBackground: "rgba(26, 27, 31, 0.96)",
|