@astryxdesign/lab 0.1.4-canary.37c19d3 → 0.1.4-canary.39ffd21
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/ChartV2/Chart.d.ts +32 -0
- package/dist/ChartV2/Chart.d.ts.map +1 -0
- package/dist/ChartV2/Chart.js +281 -0
- package/dist/ChartV2/ChartAxis.d.ts +36 -0
- package/dist/ChartV2/ChartAxis.d.ts.map +1 -0
- package/dist/ChartV2/ChartAxis.js +161 -0
- package/dist/ChartV2/ChartGrid.d.ts +20 -0
- package/dist/ChartV2/ChartGrid.d.ts.map +1 -0
- package/dist/ChartV2/ChartGrid.js +76 -0
- package/dist/ChartV2/ChartLegend.d.ts +14 -0
- package/dist/ChartV2/ChartLegend.d.ts.map +1 -0
- package/dist/ChartV2/ChartLegend.js +54 -0
- package/dist/ChartV2/ChartSwatch.d.ts +36 -0
- package/dist/ChartV2/ChartSwatch.d.ts.map +1 -0
- package/dist/ChartV2/ChartSwatch.js +82 -0
- package/dist/ChartV2/ChartTooltip.d.ts +46 -0
- package/dist/ChartV2/ChartTooltip.d.ts.map +1 -0
- package/dist/ChartV2/ChartTooltip.js +267 -0
- package/dist/ChartV2/ChartV2Context.d.ts +4 -0
- package/dist/ChartV2/ChartV2Context.d.ts.map +1 -0
- package/dist/ChartV2/ChartV2Context.js +12 -0
- package/dist/ChartV2/index.d.ts +13 -0
- package/dist/ChartV2/index.d.ts.map +1 -0
- package/dist/ChartV2/index.js +10 -0
- package/dist/ChartV2/layout.d.ts +25 -0
- package/dist/ChartV2/layout.d.ts.map +1 -0
- package/dist/ChartV2/layout.js +195 -0
- package/dist/ChartV2/legend.d.ts +18 -0
- package/dist/ChartV2/legend.d.ts.map +1 -0
- package/dist/ChartV2/legend.js +24 -0
- package/dist/ChartV2/marks/area.d.ts +19 -0
- package/dist/ChartV2/marks/area.d.ts.map +1 -0
- package/dist/ChartV2/marks/area.js +109 -0
- package/dist/ChartV2/marks/band.d.ts +9 -0
- package/dist/ChartV2/marks/band.d.ts.map +1 -0
- package/dist/ChartV2/marks/band.js +59 -0
- package/dist/ChartV2/marks/bar.d.ts +17 -0
- package/dist/ChartV2/marks/bar.d.ts.map +1 -0
- package/dist/ChartV2/marks/bar.js +120 -0
- package/dist/ChartV2/marks/candlestick.d.ts +15 -0
- package/dist/ChartV2/marks/candlestick.d.ts.map +1 -0
- package/dist/ChartV2/marks/candlestick.js +83 -0
- package/dist/ChartV2/marks/dot.d.ts +15 -0
- package/dist/ChartV2/marks/dot.d.ts.map +1 -0
- package/dist/ChartV2/marks/dot.js +65 -0
- package/dist/ChartV2/marks/dotGL.d.ts +16 -0
- package/dist/ChartV2/marks/dotGL.d.ts.map +1 -0
- package/dist/ChartV2/marks/dotGL.js +178 -0
- package/dist/ChartV2/marks/dotGLInteractive.d.ts +30 -0
- package/dist/ChartV2/marks/dotGLInteractive.d.ts.map +1 -0
- package/dist/ChartV2/marks/dotGLInteractive.js +464 -0
- package/dist/ChartV2/marks/errorBar.d.ts +27 -0
- package/dist/ChartV2/marks/errorBar.d.ts.map +1 -0
- package/dist/ChartV2/marks/errorBar.js +87 -0
- package/dist/ChartV2/marks/heatmapGL.d.ts +23 -0
- package/dist/ChartV2/marks/heatmapGL.d.ts.map +1 -0
- package/dist/ChartV2/marks/heatmapGL.js +242 -0
- package/dist/ChartV2/marks/index.d.ts +13 -0
- package/dist/ChartV2/marks/index.d.ts.map +1 -0
- package/dist/ChartV2/marks/index.js +14 -0
- package/dist/ChartV2/marks/line.d.ts +18 -0
- package/dist/ChartV2/marks/line.d.ts.map +1 -0
- package/dist/ChartV2/marks/line.js +76 -0
- package/dist/ChartV2/marks/referenceLine.d.ts +35 -0
- package/dist/ChartV2/marks/referenceLine.d.ts.map +1 -0
- package/dist/ChartV2/marks/referenceLine.js +186 -0
- package/dist/ChartV2/marks/streamGL.d.ts +36 -0
- package/dist/ChartV2/marks/streamGL.d.ts.map +1 -0
- package/dist/ChartV2/marks/streamGL.js +204 -0
- package/dist/ChartV2/tooltip.d.ts +38 -0
- package/dist/ChartV2/tooltip.d.ts.map +1 -0
- package/dist/ChartV2/tooltip.js +54 -0
- package/dist/ChartV2/types.d.ts +115 -0
- package/dist/ChartV2/types.d.ts.map +1 -0
- package/dist/ChartV2/types.js +35 -0
- package/dist/CodeEditor/CodeEditor.d.ts +1 -4
- package/dist/CodeEditor/CodeEditor.d.ts.map +1 -1
- package/dist/CodeEditor/CodeEditor.js +0 -3
- package/dist/Sankey/SankeyChart.d.ts.map +1 -1
- package/dist/Sankey/SankeyChart.js +0 -3
- package/dist/Schedule/ListView.d.ts.map +1 -1
- package/dist/Schedule/ListView.js +4 -7
- package/dist/Schedule/MonthlyView.js +2 -3
- package/dist/Schedule/Schedule.d.ts +1 -3
- package/dist/Schedule/Schedule.d.ts.map +1 -1
- package/dist/Schedule/Schedule.js +4 -9
- package/dist/Schedule/TimeGridView.js +2 -3
- package/dist/Schedule/context.d.ts +0 -2
- package/dist/Schedule/context.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -5
- package/dist/lab.css +15 -6
- package/package.json +2 -2
- package/src/ChartV2/Chart.tsx +348 -0
- package/src/ChartV2/ChartAxis.tsx +209 -0
- package/src/ChartV2/ChartGrid.tsx +99 -0
- package/src/ChartV2/ChartLegend.tsx +69 -0
- package/src/ChartV2/ChartSwatch.doc.mjs +17 -0
- package/src/ChartV2/ChartSwatch.tsx +86 -0
- package/src/ChartV2/ChartTooltip.tsx +382 -0
- package/src/ChartV2/ChartV2.doc.mjs +16 -0
- package/src/ChartV2/ChartV2Context.ts +15 -0
- package/src/ChartV2/index.ts +62 -0
- package/src/ChartV2/layout.ts +223 -0
- package/src/ChartV2/legend.ts +32 -0
- package/src/ChartV2/marks/area.tsx +122 -0
- package/src/ChartV2/marks/band.tsx +70 -0
- package/src/ChartV2/marks/bar.tsx +159 -0
- package/src/ChartV2/marks/candlestick.tsx +106 -0
- package/src/ChartV2/marks/dot.tsx +64 -0
- package/src/ChartV2/marks/dotGL.tsx +202 -0
- package/src/ChartV2/marks/dotGLInteractive.tsx +546 -0
- package/src/ChartV2/marks/errorBar.tsx +89 -0
- package/src/ChartV2/marks/heatmapGL.tsx +299 -0
- package/src/ChartV2/marks/index.ts +14 -0
- package/src/ChartV2/marks/line.tsx +94 -0
- package/src/ChartV2/marks/referenceLine.tsx +224 -0
- package/src/ChartV2/marks/streamGL.tsx +251 -0
- package/src/ChartV2/tooltip.ts +70 -0
- package/src/ChartV2/types.ts +129 -0
- package/src/CodeEditor/CodeEditor.tsx +0 -5
- package/src/Sankey/SankeyChart.tsx +0 -3
- package/src/Schedule/ListView.tsx +2 -5
- package/src/Schedule/MonthlyView.tsx +2 -2
- package/src/Schedule/Schedule.test.tsx +0 -39
- package/src/Schedule/Schedule.tsx +0 -8
- package/src/Schedule/TimeGridView.tsx +2 -2
- package/src/Schedule/context.tsx +0 -2
- package/src/index.ts +46 -5
- package/dist/InfoTip/InfoTip.d.ts +0 -58
- package/dist/InfoTip/InfoTip.d.ts.map +0 -1
- package/dist/InfoTip/InfoTip.js +0 -91
- package/dist/InfoTip/index.d.ts +0 -6
- package/dist/InfoTip/index.d.ts.map +0 -1
- package/dist/InfoTip/index.js +0 -8
- package/src/CodeEditor/CodeEditor.test.tsx +0 -21
- package/src/InfoTip/InfoTip.doc.mjs +0 -97
- package/src/InfoTip/InfoTip.test.tsx +0 -169
- package/src/InfoTip/InfoTip.tsx +0 -155
- package/src/InfoTip/index.ts +0 -10
- package/src/Sankey/SankeyChart.test.tsx +0 -77
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file marks/heatmapGL.tsx
|
|
5
|
+
* @output WebGL heatmap — 2D grid of colored cells on canvas
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { useRef, useEffect, useMemo } from 'react';
|
|
9
|
+
import { scaleBand } from 'd3-scale';
|
|
10
|
+
import { hexToGL, getWebGLContext, setupGLState, sizeCanvas, mountCanvasOverSVG, createProgram } from "../../Chart/webgl.js";
|
|
11
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
12
|
+
const VERT = `
|
|
13
|
+
attribute vec2 a_position;
|
|
14
|
+
attribute vec3 a_color;
|
|
15
|
+
uniform vec2 u_resolution;
|
|
16
|
+
varying vec3 v_color;
|
|
17
|
+
void main() {
|
|
18
|
+
vec2 clip = (a_position / u_resolution) * 2.0 - 1.0;
|
|
19
|
+
gl_Position = vec4(clip.x, -clip.y, 0.0, 1.0);
|
|
20
|
+
v_color = a_color;
|
|
21
|
+
}
|
|
22
|
+
`;
|
|
23
|
+
const FRAG = `
|
|
24
|
+
precision mediump float;
|
|
25
|
+
varying vec3 v_color;
|
|
26
|
+
void main() {
|
|
27
|
+
gl_FragColor = vec4(v_color, 1.0);
|
|
28
|
+
}
|
|
29
|
+
`;
|
|
30
|
+
function sampleRamp(ramp, t) {
|
|
31
|
+
const c = Math.max(0, Math.min(1, t));
|
|
32
|
+
if (ramp.length === 1) {
|
|
33
|
+
return ramp[0];
|
|
34
|
+
}
|
|
35
|
+
const s = c * (ramp.length - 1);
|
|
36
|
+
const lo = Math.floor(s);
|
|
37
|
+
const hi = Math.min(lo + 1, ramp.length - 1);
|
|
38
|
+
const f = s - lo;
|
|
39
|
+
return [ramp[lo][0] + f * (ramp[hi][0] - ramp[lo][0]), ramp[lo][1] + f * (ramp[hi][1] - ramp[lo][1]), ramp[lo][2] + f * (ramp[hi][2] - ramp[lo][2])];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Inline component — manages the heatmap WebGL canvas and its own y band scale.
|
|
44
|
+
*/
|
|
45
|
+
function HeatmapGLCanvas({
|
|
46
|
+
data,
|
|
47
|
+
xKey,
|
|
48
|
+
yKey,
|
|
49
|
+
valueKey,
|
|
50
|
+
xScale,
|
|
51
|
+
colorRange,
|
|
52
|
+
domain: domainProp,
|
|
53
|
+
cellGap,
|
|
54
|
+
width,
|
|
55
|
+
height
|
|
56
|
+
}) {
|
|
57
|
+
const canvasRef = useRef(null);
|
|
58
|
+
const glRef = useRef(null);
|
|
59
|
+
const programRef = useRef(null);
|
|
60
|
+
const markerRef = useRef(null);
|
|
61
|
+
const ramp = useMemo(() => colorRange.map(hexToGL), [colorRange]);
|
|
62
|
+
const yBandScale = useMemo(() => {
|
|
63
|
+
const cats = [...new Set(data.map(d => String(d[yKey])))];
|
|
64
|
+
return scaleBand().domain(cats).range([0, height]).padding(0.05);
|
|
65
|
+
}, [data, yKey, height]);
|
|
66
|
+
const domain = useMemo(() => {
|
|
67
|
+
if (domainProp) {
|
|
68
|
+
return domainProp;
|
|
69
|
+
}
|
|
70
|
+
let min = Infinity,
|
|
71
|
+
max = -Infinity;
|
|
72
|
+
for (const d of data) {
|
|
73
|
+
const v = d[valueKey];
|
|
74
|
+
if (typeof v === 'number') {
|
|
75
|
+
if (v < min) {
|
|
76
|
+
min = v;
|
|
77
|
+
}
|
|
78
|
+
if (v > max) {
|
|
79
|
+
max = v;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return [min, max];
|
|
84
|
+
}, [data, valueKey, domainProp]);
|
|
85
|
+
|
|
86
|
+
// Mount canvas outside SVG
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
const marker = markerRef.current;
|
|
89
|
+
if (!marker) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (!canvasRef.current) {
|
|
93
|
+
canvasRef.current = document.createElement('canvas');
|
|
94
|
+
}
|
|
95
|
+
return mountCanvasOverSVG(marker, canvasRef.current, width, height);
|
|
96
|
+
}, [width, height]);
|
|
97
|
+
|
|
98
|
+
// Draw
|
|
99
|
+
useEffect(() => {
|
|
100
|
+
const canvas = canvasRef.current;
|
|
101
|
+
if (!canvas || width <= 0 || height <= 0) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
sizeCanvas(canvas, width, height);
|
|
105
|
+
if (!glRef.current) {
|
|
106
|
+
glRef.current = getWebGLContext(canvas);
|
|
107
|
+
}
|
|
108
|
+
const gl = glRef.current;
|
|
109
|
+
if (!gl) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
if (!programRef.current) {
|
|
113
|
+
programRef.current = createProgram(gl, VERT, FRAG);
|
|
114
|
+
}
|
|
115
|
+
const program = programRef.current;
|
|
116
|
+
if (!program) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
gl.viewport(0, 0, canvas.width, canvas.height);
|
|
120
|
+
setupGLState(gl);
|
|
121
|
+
gl.useProgram(program);
|
|
122
|
+
const positions = [];
|
|
123
|
+
const colors = [];
|
|
124
|
+
const [dMin, dMax] = domain;
|
|
125
|
+
const range = dMax - dMin || 1;
|
|
126
|
+
const gap = cellGap;
|
|
127
|
+
const xBW = xScale.bandwidth();
|
|
128
|
+
const yBW = yBandScale.bandwidth();
|
|
129
|
+
for (const d of data) {
|
|
130
|
+
const xVal = xScale(String(d[xKey]));
|
|
131
|
+
const yVal = yBandScale(String(d[yKey]));
|
|
132
|
+
if (xVal == null || yVal == null) {
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
const v = typeof d[valueKey] === 'number' ? d[valueKey] : 0;
|
|
136
|
+
const t = (v - dMin) / range;
|
|
137
|
+
const [r, g, b] = sampleRamp(ramp, t);
|
|
138
|
+
const x0 = xVal + gap / 2;
|
|
139
|
+
const x1 = xVal + xBW - gap / 2;
|
|
140
|
+
const y0 = yVal + gap / 2;
|
|
141
|
+
const y1 = yVal + yBW - gap / 2;
|
|
142
|
+
|
|
143
|
+
// Two triangles per cell
|
|
144
|
+
positions.push(x0, y0, x1, y0, x0, y1, x1, y0, x1, y1, x0, y1);
|
|
145
|
+
for (let i = 0; i < 6; i++) {
|
|
146
|
+
colors.push(r, g, b);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
const posBuf = gl.createBuffer();
|
|
150
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, posBuf);
|
|
151
|
+
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
|
|
152
|
+
const aPos = gl.getAttribLocation(program, 'a_position');
|
|
153
|
+
gl.enableVertexAttribArray(aPos);
|
|
154
|
+
gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 0, 0);
|
|
155
|
+
const colBuf = gl.createBuffer();
|
|
156
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, colBuf);
|
|
157
|
+
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
|
|
158
|
+
const aCol = gl.getAttribLocation(program, 'a_color');
|
|
159
|
+
gl.enableVertexAttribArray(aCol);
|
|
160
|
+
gl.vertexAttribPointer(aCol, 3, gl.FLOAT, false, 0, 0);
|
|
161
|
+
gl.uniform2f(gl.getUniformLocation(program, 'u_resolution'), width, height);
|
|
162
|
+
gl.drawArrays(gl.TRIANGLES, 0, positions.length / 2);
|
|
163
|
+
gl.deleteBuffer(posBuf);
|
|
164
|
+
gl.deleteBuffer(colBuf);
|
|
165
|
+
}, [data, xKey, yKey, valueKey, xScale, yBandScale, width, height, domain, ramp, cellGap]);
|
|
166
|
+
if (width <= 0 || height <= 0) {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
return /*#__PURE__*/_jsx("g", {
|
|
170
|
+
ref: markerRef
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* WebGL heatmap. Renders a 2D grid of colored cells using triangles.
|
|
176
|
+
* Manages its own y band scale for rows; uses the chart's x band scale for columns.
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```
|
|
180
|
+
* series={[heatmapGL({
|
|
181
|
+
* xKey: 'hour', yKey: 'day', valueKey: 'count',
|
|
182
|
+
* colorRange: ['#f0f9ff', '#1e40af'],
|
|
183
|
+
* })]}
|
|
184
|
+
* ```
|
|
185
|
+
*/
|
|
186
|
+
export function heatmapGL(options) {
|
|
187
|
+
const {
|
|
188
|
+
xKey,
|
|
189
|
+
yKey,
|
|
190
|
+
valueKey,
|
|
191
|
+
colorRange
|
|
192
|
+
} = options;
|
|
193
|
+
const cellGap = options.cellGap ?? 1;
|
|
194
|
+
return {
|
|
195
|
+
type: 'heatmapGL',
|
|
196
|
+
key: `heatmap-${valueKey}`,
|
|
197
|
+
dataKeys: [valueKey],
|
|
198
|
+
layout: {},
|
|
199
|
+
resolve(ctx) {
|
|
200
|
+
// Heatmap doesn't resolve per-point positions the standard way —
|
|
201
|
+
// the canvas component handles its own cell layout.
|
|
202
|
+
const {
|
|
203
|
+
data,
|
|
204
|
+
xScale,
|
|
205
|
+
yScale
|
|
206
|
+
} = ctx;
|
|
207
|
+
const points = [];
|
|
208
|
+
if (!('bandwidth' in xScale)) {
|
|
209
|
+
return points;
|
|
210
|
+
}
|
|
211
|
+
for (let i = 0; i < data.length; i++) {
|
|
212
|
+
const d = data[i];
|
|
213
|
+
const px = (xScale(String(d[xKey])) ?? 0) + xScale.bandwidth() / 2;
|
|
214
|
+
const v = typeof d[valueKey] === 'number' ? d[valueKey] : 0;
|
|
215
|
+
points.push({
|
|
216
|
+
px,
|
|
217
|
+
py: yScale(v),
|
|
218
|
+
py0: yScale(0),
|
|
219
|
+
dataIndex: i
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
return points;
|
|
223
|
+
},
|
|
224
|
+
render(_resolved, ctx) {
|
|
225
|
+
if (!('bandwidth' in ctx.xScale)) {
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
return /*#__PURE__*/_jsx(HeatmapGLCanvas, {
|
|
229
|
+
data: ctx.data,
|
|
230
|
+
xKey: xKey,
|
|
231
|
+
yKey: yKey,
|
|
232
|
+
valueKey: valueKey,
|
|
233
|
+
xScale: ctx.xScale,
|
|
234
|
+
colorRange: colorRange,
|
|
235
|
+
domain: options.domain,
|
|
236
|
+
cellGap: cellGap,
|
|
237
|
+
width: ctx.width,
|
|
238
|
+
height: ctx.height
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { bar, type BarOptions } from './bar';
|
|
2
|
+
export { line, type LineOptions } from './line';
|
|
3
|
+
export { dot, type DotOptions } from './dot';
|
|
4
|
+
export { area, type AreaOptions } from './area';
|
|
5
|
+
export { band, type BandOptions } from './band';
|
|
6
|
+
export { candlestick, type CandlestickOptions } from './candlestick';
|
|
7
|
+
export { errorBar, type ErrorBarOptions } from './errorBar';
|
|
8
|
+
export { referenceLine, type ReferenceLineOptions } from './referenceLine';
|
|
9
|
+
export { dotGL, type DotGLOptions } from './dotGL';
|
|
10
|
+
export { dotGLInteractive, type DotGLInteractiveOptions } from './dotGLInteractive';
|
|
11
|
+
export { heatmapGL, type HeatmapGLOptions } from './heatmapGL';
|
|
12
|
+
export { streamGL, type StreamGLOptions, type StreamGLHandle } from './streamGL';
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ChartV2/marks/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,GAAG,EAAE,KAAK,UAAU,EAAC,MAAM,OAAO,CAAC;AAC3C,OAAO,EAAC,IAAI,EAAE,KAAK,WAAW,EAAC,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAC,GAAG,EAAE,KAAK,UAAU,EAAC,MAAM,OAAO,CAAC;AAC3C,OAAO,EAAC,IAAI,EAAE,KAAK,WAAW,EAAC,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAC,IAAI,EAAE,KAAK,WAAW,EAAC,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAC,WAAW,EAAE,KAAK,kBAAkB,EAAC,MAAM,eAAe,CAAC;AACnE,OAAO,EAAC,QAAQ,EAAE,KAAK,eAAe,EAAC,MAAM,YAAY,CAAC;AAC1D,OAAO,EAAC,aAAa,EAAE,KAAK,oBAAoB,EAAC,MAAM,iBAAiB,CAAC;AACzE,OAAO,EAAC,KAAK,EAAE,KAAK,YAAY,EAAC,MAAM,SAAS,CAAC;AACjD,OAAO,EAAC,gBAAgB,EAAE,KAAK,uBAAuB,EAAC,MAAM,oBAAoB,CAAC;AAClF,OAAO,EAAC,SAAS,EAAE,KAAK,gBAAgB,EAAC,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAC,QAAQ,EAAE,KAAK,eAAe,EAAE,KAAK,cAAc,EAAC,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
export { bar } from "./bar.js";
|
|
4
|
+
export { line } from "./line.js";
|
|
5
|
+
export { dot } from "./dot.js";
|
|
6
|
+
export { area } from "./area.js";
|
|
7
|
+
export { band } from "./band.js";
|
|
8
|
+
export { candlestick } from "./candlestick.js";
|
|
9
|
+
export { errorBar } from "./errorBar.js";
|
|
10
|
+
export { referenceLine } from "./referenceLine.js";
|
|
11
|
+
export { dotGL } from "./dotGL.js";
|
|
12
|
+
export { dotGLInteractive } from "./dotGLInteractive.js";
|
|
13
|
+
export { heatmapGL } from "./heatmapGL.js";
|
|
14
|
+
export { streamGL } from "./streamGL.js";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { SeriesDef } from '../types';
|
|
2
|
+
declare const CURVES: {
|
|
3
|
+
readonly linear: import("d3-shape").CurveFactory;
|
|
4
|
+
readonly monotone: import("d3-shape").CurveFactory;
|
|
5
|
+
readonly natural: import("d3-shape").CurveFactory;
|
|
6
|
+
readonly step: import("d3-shape").CurveFactory;
|
|
7
|
+
};
|
|
8
|
+
export type CurveType = keyof typeof CURVES;
|
|
9
|
+
export interface LineOptions {
|
|
10
|
+
color?: string;
|
|
11
|
+
curve?: CurveType;
|
|
12
|
+
strokeWidth?: number;
|
|
13
|
+
dots?: boolean;
|
|
14
|
+
label?: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function line(dataKey: string, options?: LineOptions): SeriesDef;
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=line.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"line.d.ts","sourceRoot":"","sources":["../../../src/ChartV2/marks/line.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAC,SAAS,EAAgB,MAAM,UAAU,CAAC;AAGvD,QAAA,MAAM,MAAM;;;;;CAKF,CAAC;AACX,MAAM,MAAM,SAAS,GAAG,MAAM,OAAO,MAAM,CAAC;AAE5C,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,SAAS,CA4D1E"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file marks/line.tsx
|
|
5
|
+
* @output Line series — self-contained resolve + render
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { line as d3Line, curveLinear, curveMonotoneX, curveNatural, curveStep } from 'd3-shape';
|
|
9
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
10
|
+
const CURVES = {
|
|
11
|
+
linear: curveLinear,
|
|
12
|
+
monotone: curveMonotoneX,
|
|
13
|
+
natural: curveNatural,
|
|
14
|
+
step: curveStep
|
|
15
|
+
};
|
|
16
|
+
export function line(dataKey, options = {}) {
|
|
17
|
+
const color = options.color ?? 'var(--color-chart-1)';
|
|
18
|
+
const curve = options.curve ?? 'monotone';
|
|
19
|
+
const strokeWidth = options.strokeWidth ?? 2;
|
|
20
|
+
const dots = options.dots ?? false;
|
|
21
|
+
return {
|
|
22
|
+
type: 'line',
|
|
23
|
+
key: dataKey,
|
|
24
|
+
dataKeys: [dataKey],
|
|
25
|
+
color,
|
|
26
|
+
label: options.label ?? dataKey,
|
|
27
|
+
layout: {},
|
|
28
|
+
resolve(ctx) {
|
|
29
|
+
const {
|
|
30
|
+
data,
|
|
31
|
+
xKey,
|
|
32
|
+
xScale,
|
|
33
|
+
yScale
|
|
34
|
+
} = ctx;
|
|
35
|
+
const points = [];
|
|
36
|
+
for (let i = 0; i < data.length; i++) {
|
|
37
|
+
const d = data[i];
|
|
38
|
+
let px;
|
|
39
|
+
if ('bandwidth' in xScale) {
|
|
40
|
+
px = (xScale(String(d[xKey])) ?? 0) + xScale.bandwidth() / 2;
|
|
41
|
+
} else {
|
|
42
|
+
px = xScale(d[xKey]);
|
|
43
|
+
}
|
|
44
|
+
const v = typeof d[dataKey] === 'number' ? d[dataKey] : 0;
|
|
45
|
+
points.push({
|
|
46
|
+
px,
|
|
47
|
+
py: yScale(v),
|
|
48
|
+
py0: yScale(0),
|
|
49
|
+
dataIndex: i
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
return points;
|
|
53
|
+
},
|
|
54
|
+
render(resolved) {
|
|
55
|
+
if (resolved.length === 0) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
const curveFactory = CURVES[curve];
|
|
59
|
+
const pathGen = d3Line().x(d => d.px).y(d => d.py).curve(curveFactory);
|
|
60
|
+
const pathD = pathGen(resolved) ?? '';
|
|
61
|
+
return /*#__PURE__*/_jsxs("g", {
|
|
62
|
+
children: [/*#__PURE__*/_jsx("path", {
|
|
63
|
+
d: pathD,
|
|
64
|
+
fill: "none",
|
|
65
|
+
stroke: color,
|
|
66
|
+
strokeWidth: strokeWidth
|
|
67
|
+
}), dots && resolved.map((p, i) => /*#__PURE__*/_jsx("circle", {
|
|
68
|
+
cx: p.px,
|
|
69
|
+
cy: p.py,
|
|
70
|
+
r: 3,
|
|
71
|
+
fill: color
|
|
72
|
+
}, i))]
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file marks/referenceLine.tsx
|
|
3
|
+
* @output Horizontal or vertical reference line/band annotation
|
|
4
|
+
*/
|
|
5
|
+
import type { SeriesDef } from '../types';
|
|
6
|
+
export interface ReferenceLineOptions {
|
|
7
|
+
/** Horizontal reference at this y value */
|
|
8
|
+
y?: number;
|
|
9
|
+
/** Second y value — draws a shaded band between y and y2 */
|
|
10
|
+
y2?: number;
|
|
11
|
+
/** Vertical reference at this x value */
|
|
12
|
+
x?: number;
|
|
13
|
+
/** Line/band color */
|
|
14
|
+
color?: string;
|
|
15
|
+
/** Stroke width (for lines) */
|
|
16
|
+
strokeWidth?: number;
|
|
17
|
+
/** Dash pattern */
|
|
18
|
+
strokeDasharray?: string;
|
|
19
|
+
/** Text label */
|
|
20
|
+
label?: string;
|
|
21
|
+
/** Label position */
|
|
22
|
+
labelPosition?: 'start' | 'end';
|
|
23
|
+
/** Band fill opacity (when y2 is set) */
|
|
24
|
+
bandOpacity?: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Reference line or band annotation. Not a data series — renders at fixed values.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```
|
|
31
|
+
* series={[line('revenue'), referenceLine({y: 100, label: 'Target'})]}
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export declare function referenceLine(options: ReferenceLineOptions): SeriesDef;
|
|
35
|
+
//# sourceMappingURL=referenceLine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"referenceLine.d.ts","sourceRoot":"","sources":["../../../src/ChartV2/marks/referenceLine.tsx"],"names":[],"mappings":"AAEA;;;GAGG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,UAAU,CAAC;AAGxC,MAAM,WAAW,oBAAoB;IACnC,2CAA2C;IAC3C,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,4DAA4D;IAC5D,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,yCAAyC;IACzC,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,sBAAsB;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mBAAmB;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qBAAqB;IACrB,aAAa,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC;IAChC,yCAAyC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,SAAS,CAwLtE"}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @file marks/referenceLine.tsx
|
|
6
|
+
* @output Horizontal or vertical reference line/band annotation
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Reference line or band annotation. Not a data series — renders at fixed values.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```
|
|
14
|
+
* series={[line('revenue'), referenceLine({y: 100, label: 'Target'})]}
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export function referenceLine(options) {
|
|
18
|
+
const color = options.color ?? 'var(--color-border-emphasized)';
|
|
19
|
+
const strokeWidth = options.strokeWidth ?? 1;
|
|
20
|
+
const strokeDasharray = options.strokeDasharray ?? '6 3';
|
|
21
|
+
const label = options.label;
|
|
22
|
+
const labelPosition = options.labelPosition ?? 'end';
|
|
23
|
+
const bandOpacity = options.bandOpacity ?? 0.1;
|
|
24
|
+
|
|
25
|
+
// Badge dimensions — matches crosshair label style
|
|
26
|
+
const badgeH = 14;
|
|
27
|
+
const badgeRx = 3;
|
|
28
|
+
const fontSize = 10;
|
|
29
|
+
return {
|
|
30
|
+
type: 'referenceLine',
|
|
31
|
+
key: `ref-${options.y ?? options.x ?? 'none'}`,
|
|
32
|
+
dataKeys: [],
|
|
33
|
+
layout: {},
|
|
34
|
+
// No data points to resolve — this is a fixed annotation
|
|
35
|
+
resolve() {
|
|
36
|
+
return [];
|
|
37
|
+
},
|
|
38
|
+
render(_resolved, ctx) {
|
|
39
|
+
const {
|
|
40
|
+
width,
|
|
41
|
+
height,
|
|
42
|
+
xScale,
|
|
43
|
+
yScale
|
|
44
|
+
} = ctx;
|
|
45
|
+
|
|
46
|
+
// Horizontal reference line or band
|
|
47
|
+
if (options.y != null) {
|
|
48
|
+
const py = yScale(options.y);
|
|
49
|
+
const textW = label ? label.length * 5.5 + 8 : 0;
|
|
50
|
+
const bx = labelPosition === 'end' ? width - textW - 2 : 2;
|
|
51
|
+
|
|
52
|
+
// Band mode: shaded region between y and y2
|
|
53
|
+
if (options.y2 != null) {
|
|
54
|
+
const py2 = yScale(options.y2);
|
|
55
|
+
const top = Math.min(py, py2);
|
|
56
|
+
const bandHeight = Math.abs(py2 - py);
|
|
57
|
+
return /*#__PURE__*/_jsxs("g", {
|
|
58
|
+
children: [/*#__PURE__*/_jsx("rect", {
|
|
59
|
+
x: 0,
|
|
60
|
+
y: top,
|
|
61
|
+
width: width,
|
|
62
|
+
height: bandHeight,
|
|
63
|
+
fill: color,
|
|
64
|
+
opacity: bandOpacity
|
|
65
|
+
}), /*#__PURE__*/_jsx("line", {
|
|
66
|
+
x1: 0,
|
|
67
|
+
x2: width,
|
|
68
|
+
y1: py,
|
|
69
|
+
y2: py,
|
|
70
|
+
stroke: color,
|
|
71
|
+
strokeWidth: strokeWidth,
|
|
72
|
+
strokeDasharray: strokeDasharray
|
|
73
|
+
}), /*#__PURE__*/_jsx("line", {
|
|
74
|
+
x1: 0,
|
|
75
|
+
x2: width,
|
|
76
|
+
y1: py2,
|
|
77
|
+
y2: py2,
|
|
78
|
+
stroke: color,
|
|
79
|
+
strokeWidth: strokeWidth,
|
|
80
|
+
strokeDasharray: strokeDasharray
|
|
81
|
+
}), label && /*#__PURE__*/_jsxs("g", {
|
|
82
|
+
transform: `translate(${bx},${py})`,
|
|
83
|
+
pointerEvents: "none",
|
|
84
|
+
children: [/*#__PURE__*/_jsx("rect", {
|
|
85
|
+
x: 0,
|
|
86
|
+
y: -badgeH / 2,
|
|
87
|
+
width: textW,
|
|
88
|
+
height: badgeH,
|
|
89
|
+
rx: badgeRx,
|
|
90
|
+
fill: "var(--color-background-popover)",
|
|
91
|
+
fillOpacity: 0.85,
|
|
92
|
+
stroke: color,
|
|
93
|
+
strokeWidth: 0.5
|
|
94
|
+
}), /*#__PURE__*/_jsx("text", {
|
|
95
|
+
x: textW / 2,
|
|
96
|
+
dy: "0.35em",
|
|
97
|
+
textAnchor: "middle",
|
|
98
|
+
fontSize: fontSize,
|
|
99
|
+
fontWeight: 500,
|
|
100
|
+
fill: color,
|
|
101
|
+
children: label
|
|
102
|
+
})]
|
|
103
|
+
})]
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Single horizontal line
|
|
108
|
+
return /*#__PURE__*/_jsxs("g", {
|
|
109
|
+
children: [/*#__PURE__*/_jsx("line", {
|
|
110
|
+
x1: 0,
|
|
111
|
+
x2: width,
|
|
112
|
+
y1: py,
|
|
113
|
+
y2: py,
|
|
114
|
+
stroke: color,
|
|
115
|
+
strokeWidth: strokeWidth,
|
|
116
|
+
strokeDasharray: strokeDasharray
|
|
117
|
+
}), label && /*#__PURE__*/_jsxs("g", {
|
|
118
|
+
transform: `translate(${bx},${py})`,
|
|
119
|
+
pointerEvents: "none",
|
|
120
|
+
children: [/*#__PURE__*/_jsx("rect", {
|
|
121
|
+
x: 0,
|
|
122
|
+
y: -badgeH / 2,
|
|
123
|
+
width: textW,
|
|
124
|
+
height: badgeH,
|
|
125
|
+
rx: badgeRx,
|
|
126
|
+
fill: "var(--color-background-popover)",
|
|
127
|
+
fillOpacity: 0.85,
|
|
128
|
+
stroke: color,
|
|
129
|
+
strokeWidth: 0.5
|
|
130
|
+
}), /*#__PURE__*/_jsx("text", {
|
|
131
|
+
x: textW / 2,
|
|
132
|
+
dy: "0.35em",
|
|
133
|
+
textAnchor: "middle",
|
|
134
|
+
fontSize: fontSize,
|
|
135
|
+
fontWeight: 500,
|
|
136
|
+
fill: color,
|
|
137
|
+
children: label
|
|
138
|
+
})]
|
|
139
|
+
})]
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Vertical reference line
|
|
144
|
+
if (options.x != null && !('bandwidth' in xScale)) {
|
|
145
|
+
const px = xScale(options.x);
|
|
146
|
+
const textW = label ? label.length * 5.5 + 8 : 0;
|
|
147
|
+
const by = labelPosition === 'end' ? 4 : height - badgeH - 4;
|
|
148
|
+
return /*#__PURE__*/_jsxs("g", {
|
|
149
|
+
children: [/*#__PURE__*/_jsx("line", {
|
|
150
|
+
x1: px,
|
|
151
|
+
x2: px,
|
|
152
|
+
y1: 0,
|
|
153
|
+
y2: height,
|
|
154
|
+
stroke: color,
|
|
155
|
+
strokeWidth: strokeWidth,
|
|
156
|
+
strokeDasharray: strokeDasharray
|
|
157
|
+
}), label && /*#__PURE__*/_jsxs("g", {
|
|
158
|
+
transform: `translate(${px - textW / 2},${by})`,
|
|
159
|
+
pointerEvents: "none",
|
|
160
|
+
children: [/*#__PURE__*/_jsx("rect", {
|
|
161
|
+
x: 0,
|
|
162
|
+
y: 0,
|
|
163
|
+
width: textW,
|
|
164
|
+
height: badgeH,
|
|
165
|
+
rx: badgeRx,
|
|
166
|
+
fill: "var(--color-background-popover)",
|
|
167
|
+
fillOpacity: 0.85,
|
|
168
|
+
stroke: color,
|
|
169
|
+
strokeWidth: 0.5
|
|
170
|
+
}), /*#__PURE__*/_jsx("text", {
|
|
171
|
+
x: textW / 2,
|
|
172
|
+
y: badgeH / 2,
|
|
173
|
+
dy: "0.35em",
|
|
174
|
+
textAnchor: "middle",
|
|
175
|
+
fontSize: fontSize,
|
|
176
|
+
fontWeight: 500,
|
|
177
|
+
fill: color,
|
|
178
|
+
children: label
|
|
179
|
+
})]
|
|
180
|
+
})]
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file marks/streamGL.tsx
|
|
3
|
+
* @output WebGL streaming time-series line — ring buffer, canvas outside SVG
|
|
4
|
+
*
|
|
5
|
+
* Data is pushed imperatively via the returned handle, not from the static dataset.
|
|
6
|
+
* The chart's xScale/yScale map pushed values to pixel coordinates.
|
|
7
|
+
*/
|
|
8
|
+
import { type MutableRefObject } from 'react';
|
|
9
|
+
import type { SeriesDef } from '../types';
|
|
10
|
+
export interface StreamGLHandle {
|
|
11
|
+
push(x: number, y: number): void;
|
|
12
|
+
clear(): void;
|
|
13
|
+
}
|
|
14
|
+
export interface StreamGLOptions {
|
|
15
|
+
color: string;
|
|
16
|
+
bufferSize?: number;
|
|
17
|
+
lineWidth?: number;
|
|
18
|
+
opacity?: number;
|
|
19
|
+
/** Ref to receive the push/clear handle */
|
|
20
|
+
handleRef?: MutableRefObject<StreamGLHandle | null>;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* WebGL streaming line. Data is pushed imperatively via handleRef,
|
|
24
|
+
* not from the chart's static dataset. Internally uses a ring buffer.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```
|
|
28
|
+
* const streamRef = useRef<StreamGLHandle>(null);
|
|
29
|
+
* // Push data points in a rAF loop or event handler:
|
|
30
|
+
* streamRef.current?.push(Date.now(), value);
|
|
31
|
+
*
|
|
32
|
+
* <Chart series={[streamGL({color: '#10b981', handleRef: streamRef})]} />
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare function streamGL(options: StreamGLOptions): SeriesDef;
|
|
36
|
+
//# sourceMappingURL=streamGL.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streamGL.d.ts","sourceRoot":"","sources":["../../../src/ChartV2/marks/streamGL.tsx"],"names":[],"mappings":"AAEA;;;;;;GAMG;AAEH,OAAO,EAKL,KAAK,gBAAgB,EACtB,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,UAAU,CAAC;AAWxC,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,KAAK,IAAI,IAAI,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2CAA2C;IAC3C,SAAS,CAAC,EAAE,gBAAgB,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;CACrD;AAqKD;;;;;;;;;;;;GAYG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,SAAS,CAgC5D"}
|