minerva-design 1.2.0 → 1.3.0
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/CHANGELOG.md +7 -0
- package/dist/charts/canvas.d.cts +4 -1
- package/dist/charts/canvas.d.ts +4 -1
- package/dist/charts/core.cjs +1 -1
- package/dist/charts/core.d.cts +5 -2
- package/dist/charts/core.d.ts +5 -2
- package/dist/charts/core.js +6 -4
- package/dist/charts/engine/canvas.cjs +1 -1
- package/dist/charts/engine/canvas.cjs.map +1 -1
- package/dist/charts/engine/canvas.js +65 -53
- package/dist/charts/engine/canvas.js.map +1 -1
- package/dist/charts/engine/chart.cjs +1 -2
- package/dist/charts/engine/chart.cjs.map +1 -1
- package/dist/charts/engine/chart.js +342 -323
- package/dist/charts/engine/chart.js.map +1 -1
- package/dist/charts/engine/color.cjs +1 -1
- package/dist/charts/engine/color.cjs.map +1 -1
- package/dist/charts/engine/color.d.cts +17 -0
- package/dist/charts/engine/color.d.ts +17 -0
- package/dist/charts/engine/color.js +27 -3
- package/dist/charts/engine/color.js.map +1 -1
- package/dist/charts/engine/controller.cjs +2 -2
- package/dist/charts/engine/controller.cjs.map +1 -1
- package/dist/charts/engine/controller.d.cts +6 -0
- package/dist/charts/engine/controller.d.ts +6 -0
- package/dist/charts/engine/controller.js +317 -253
- package/dist/charts/engine/controller.js.map +1 -1
- package/dist/charts/engine/curve.cjs +2 -0
- package/dist/charts/engine/curve.cjs.map +1 -0
- package/dist/charts/engine/curve.d.cts +15 -0
- package/dist/charts/engine/curve.d.ts +15 -0
- package/dist/charts/engine/curve.js +56 -0
- package/dist/charts/engine/curve.js.map +1 -0
- package/dist/charts/engine/data.cjs +1 -1
- package/dist/charts/engine/data.cjs.map +1 -1
- package/dist/charts/engine/data.d.cts +15 -2
- package/dist/charts/engine/data.d.ts +15 -2
- package/dist/charts/engine/data.js +98 -38
- package/dist/charts/engine/data.js.map +1 -1
- package/dist/charts/engine/dom.cjs +1 -1
- package/dist/charts/engine/dom.cjs.map +1 -1
- package/dist/charts/engine/dom.d.cts +5 -3
- package/dist/charts/engine/dom.d.ts +5 -3
- package/dist/charts/engine/dom.js +27 -22
- package/dist/charts/engine/dom.js.map +1 -1
- package/dist/charts/engine/items.cjs +1 -1
- package/dist/charts/engine/items.cjs.map +1 -1
- package/dist/charts/engine/items.js +132 -61
- package/dist/charts/engine/items.js.map +1 -1
- package/dist/charts/engine/model.cjs +1 -1
- package/dist/charts/engine/model.cjs.map +1 -1
- package/dist/charts/engine/model.d.cts +30 -3
- package/dist/charts/engine/model.d.ts +30 -3
- package/dist/charts/engine/model.js +225 -108
- package/dist/charts/engine/model.js.map +1 -1
- package/dist/charts/engine/overlay.cjs +1 -1
- package/dist/charts/engine/overlay.cjs.map +1 -1
- package/dist/charts/engine/overlay.d.cts +2 -0
- package/dist/charts/engine/overlay.d.ts +2 -0
- package/dist/charts/engine/overlay.js +16 -16
- package/dist/charts/engine/overlay.js.map +1 -1
- package/dist/charts/engine/presets.cjs +2 -2
- package/dist/charts/engine/presets.cjs.map +1 -1
- package/dist/charts/engine/presets.d.cts +71 -5
- package/dist/charts/engine/presets.d.ts +71 -5
- package/dist/charts/engine/presets.js +120 -33
- package/dist/charts/engine/presets.js.map +1 -1
- package/dist/charts/engine/renderers/canvas2d.cjs +1 -1
- package/dist/charts/engine/renderers/canvas2d.cjs.map +1 -1
- package/dist/charts/engine/renderers/canvas2d.js +149 -111
- package/dist/charts/engine/renderers/canvas2d.js.map +1 -1
- package/dist/charts/engine/renderers/range.cjs +1 -1
- package/dist/charts/engine/renderers/range.cjs.map +1 -1
- package/dist/charts/engine/renderers/range.js +4 -4
- package/dist/charts/engine/renderers/range.js.map +1 -1
- package/dist/charts/engine/renderers/shaders.cjs +37 -19
- package/dist/charts/engine/renderers/shaders.cjs.map +1 -1
- package/dist/charts/engine/renderers/shaders.d.cts +2 -2
- package/dist/charts/engine/renderers/shaders.d.ts +2 -2
- package/dist/charts/engine/renderers/shaders.js +37 -19
- package/dist/charts/engine/renderers/shaders.js.map +1 -1
- package/dist/charts/engine/renderers/types.cjs.map +1 -1
- package/dist/charts/engine/renderers/types.d.cts +11 -4
- package/dist/charts/engine/renderers/types.d.ts +11 -4
- package/dist/charts/engine/renderers/types.js.map +1 -1
- package/dist/charts/engine/renderers/webgl2.cjs +1 -1
- package/dist/charts/engine/renderers/webgl2.cjs.map +1 -1
- package/dist/charts/engine/renderers/webgl2.js +33 -12
- package/dist/charts/engine/renderers/webgl2.js.map +1 -1
- package/dist/charts/engine/renderers/webgpu.cjs +1 -1
- package/dist/charts/engine/renderers/webgpu.cjs.map +1 -1
- package/dist/charts/engine/renderers/webgpu.js +18 -15
- package/dist/charts/engine/renderers/webgpu.js.map +1 -1
- package/dist/charts/engine/scene.cjs +1 -1
- package/dist/charts/engine/scene.cjs.map +1 -1
- package/dist/charts/engine/scene.d.cts +19 -6
- package/dist/charts/engine/scene.d.ts +19 -6
- package/dist/charts/engine/scene.js +201 -89
- package/dist/charts/engine/scene.js.map +1 -1
- package/dist/charts/engine/shapes/canvas.cjs +2 -0
- package/dist/charts/engine/shapes/canvas.cjs.map +1 -0
- package/dist/charts/engine/shapes/canvas.d.cts +58 -0
- package/dist/charts/engine/shapes/canvas.d.ts +58 -0
- package/dist/charts/engine/shapes/canvas.js +159 -0
- package/dist/charts/engine/shapes/canvas.js.map +1 -0
- package/dist/charts/engine/shapes/chart.cjs +2 -0
- package/dist/charts/engine/shapes/chart.cjs.map +1 -0
- package/dist/charts/engine/shapes/chart.d.cts +6 -0
- package/dist/charts/engine/shapes/chart.d.ts +6 -0
- package/dist/charts/engine/shapes/chart.js +273 -0
- package/dist/charts/engine/shapes/chart.js.map +1 -0
- package/dist/charts/engine/shapes/draw.cjs +2 -0
- package/dist/charts/engine/shapes/draw.cjs.map +1 -0
- package/dist/charts/engine/shapes/draw.d.cts +20 -0
- package/dist/charts/engine/shapes/draw.d.ts +20 -0
- package/dist/charts/engine/shapes/draw.js +152 -0
- package/dist/charts/engine/shapes/draw.js.map +1 -0
- package/dist/charts/engine/shapes/funnel.cjs +2 -0
- package/dist/charts/engine/shapes/funnel.cjs.map +1 -0
- package/dist/charts/engine/shapes/funnel.d.cts +6 -0
- package/dist/charts/engine/shapes/funnel.d.ts +6 -0
- package/dist/charts/engine/shapes/funnel.js +149 -0
- package/dist/charts/engine/shapes/funnel.js.map +1 -0
- package/dist/charts/engine/shapes/gauge.cjs +2 -0
- package/dist/charts/engine/shapes/gauge.cjs.map +1 -0
- package/dist/charts/engine/shapes/gauge.d.cts +7 -0
- package/dist/charts/engine/shapes/gauge.d.ts +7 -0
- package/dist/charts/engine/shapes/gauge.js +173 -0
- package/dist/charts/engine/shapes/gauge.js.map +1 -0
- package/dist/charts/engine/shapes/hit.cjs +2 -0
- package/dist/charts/engine/shapes/hit.cjs.map +1 -0
- package/dist/charts/engine/shapes/hit.d.cts +28 -0
- package/dist/charts/engine/shapes/hit.d.ts +28 -0
- package/dist/charts/engine/shapes/hit.js +124 -0
- package/dist/charts/engine/shapes/hit.js.map +1 -0
- package/dist/charts/engine/shapes/index.d.cts +9 -0
- package/dist/charts/engine/shapes/index.d.ts +9 -0
- package/dist/charts/engine/shapes/layout.cjs +3 -0
- package/dist/charts/engine/shapes/layout.cjs.map +1 -0
- package/dist/charts/engine/shapes/layout.d.cts +88 -0
- package/dist/charts/engine/shapes/layout.d.ts +88 -0
- package/dist/charts/engine/shapes/layout.js +266 -0
- package/dist/charts/engine/shapes/layout.js.map +1 -0
- package/dist/charts/engine/shapes/pie.cjs +2 -0
- package/dist/charts/engine/shapes/pie.cjs.map +1 -0
- package/dist/charts/engine/shapes/pie.d.cts +20 -0
- package/dist/charts/engine/shapes/pie.d.ts +20 -0
- package/dist/charts/engine/shapes/pie.js +302 -0
- package/dist/charts/engine/shapes/pie.js.map +1 -0
- package/dist/charts/engine/shapes/radar.cjs +2 -0
- package/dist/charts/engine/shapes/radar.cjs.map +1 -0
- package/dist/charts/engine/shapes/radar.d.cts +8 -0
- package/dist/charts/engine/shapes/radar.d.ts +8 -0
- package/dist/charts/engine/shapes/radar.js +197 -0
- package/dist/charts/engine/shapes/radar.js.map +1 -0
- package/dist/charts/engine/shapes/runtime.cjs +2 -0
- package/dist/charts/engine/shapes/runtime.cjs.map +1 -0
- package/dist/charts/engine/shapes/runtime.d.cts +29 -0
- package/dist/charts/engine/shapes/runtime.d.ts +29 -0
- package/dist/charts/engine/shapes/runtime.js +97 -0
- package/dist/charts/engine/shapes/runtime.js.map +1 -0
- package/dist/charts/engine/shapes/scene.cjs +2 -0
- package/dist/charts/engine/shapes/scene.cjs.map +1 -0
- package/dist/charts/engine/shapes/scene.d.cts +257 -0
- package/dist/charts/engine/shapes/scene.d.ts +257 -0
- package/dist/charts/engine/shapes/scene.js +123 -0
- package/dist/charts/engine/shapes/scene.js.map +1 -0
- package/dist/charts/engine/shapes/treemap.cjs +2 -0
- package/dist/charts/engine/shapes/treemap.cjs.map +1 -0
- package/dist/charts/engine/shapes/treemap.d.cts +14 -0
- package/dist/charts/engine/shapes/treemap.d.ts +14 -0
- package/dist/charts/engine/shapes/treemap.js +213 -0
- package/dist/charts/engine/shapes/treemap.js.map +1 -0
- package/dist/charts/engine/shapes/types.d.cts +292 -0
- package/dist/charts/engine/shapes/types.d.ts +292 -0
- package/dist/charts/engine/signature.cjs +2 -0
- package/dist/charts/engine/signature.cjs.map +1 -0
- package/dist/charts/engine/signature.d.cts +9 -0
- package/dist/charts/engine/signature.d.ts +9 -0
- package/dist/charts/engine/signature.js +13 -0
- package/dist/charts/engine/signature.js.map +1 -0
- package/dist/charts/engine/theme.cjs +1 -1
- package/dist/charts/engine/theme.cjs.map +1 -1
- package/dist/charts/engine/theme.d.cts +10 -1
- package/dist/charts/engine/theme.d.ts +10 -1
- package/dist/charts/engine/theme.js +40 -16
- package/dist/charts/engine/theme.js.map +1 -1
- package/dist/charts/engine/types.d.cts +70 -9
- package/dist/charts/engine/types.d.ts +70 -9
- package/dist/charts/index.cjs +1 -1
- package/dist/charts/index.d.cts +4 -2
- package/dist/charts/index.d.ts +4 -2
- package/dist/charts/index.js +8 -5
- package/dist/charts/react/Chart.cjs +1 -1
- package/dist/charts/react/Chart.cjs.map +1 -1
- package/dist/charts/react/Chart.d.cts +8 -1
- package/dist/charts/react/Chart.d.ts +8 -1
- package/dist/charts/react/Chart.js +66 -47
- package/dist/charts/react/Chart.js.map +1 -1
- package/dist/charts/react/charts.cjs +1 -1
- package/dist/charts/react/charts.cjs.map +1 -1
- package/dist/charts/react/charts.d.cts +10 -2
- package/dist/charts/react/charts.d.ts +10 -2
- package/dist/charts/react/charts.js +174 -51
- package/dist/charts/react/charts.js.map +1 -1
- package/dist/charts/react/shapes.cjs +2 -0
- package/dist/charts/react/shapes.cjs.map +1 -0
- package/dist/charts/react/shapes.d.cts +255 -0
- package/dist/charts/react/shapes.d.ts +255 -0
- package/dist/charts/react/shapes.js +242 -0
- package/dist/charts/react/shapes.js.map +1 -0
- package/dist/charts/react/types.d.cts +73 -4
- package/dist/charts/react/types.d.ts +73 -4
- package/dist/native/charts/src/engine/color.cjs +1 -1
- package/dist/native/charts/src/engine/color.cjs.map +1 -1
- package/dist/native/charts/src/engine/color.js +12 -3
- package/dist/native/charts/src/engine/color.js.map +1 -1
- package/dist/native/charts/src/engine/controller.cjs +2 -2
- package/dist/native/charts/src/engine/controller.cjs.map +1 -1
- package/dist/native/charts/src/engine/controller.js +334 -270
- package/dist/native/charts/src/engine/controller.js.map +1 -1
- package/dist/native/charts/src/engine/curve.cjs +2 -0
- package/dist/native/charts/src/engine/curve.cjs.map +1 -0
- package/dist/native/charts/src/engine/curve.js +56 -0
- package/dist/native/charts/src/engine/curve.js.map +1 -0
- package/dist/native/charts/src/engine/data.cjs +1 -1
- package/dist/native/charts/src/engine/data.cjs.map +1 -1
- package/dist/native/charts/src/engine/data.js +98 -38
- package/dist/native/charts/src/engine/data.js.map +1 -1
- package/dist/native/charts/src/engine/model.cjs +1 -1
- package/dist/native/charts/src/engine/model.cjs.map +1 -1
- package/dist/native/charts/src/engine/model.js +229 -112
- package/dist/native/charts/src/engine/model.js.map +1 -1
- package/dist/native/charts/src/engine/overlay.cjs +1 -1
- package/dist/native/charts/src/engine/overlay.cjs.map +1 -1
- package/dist/native/charts/src/engine/overlay.js +16 -16
- package/dist/native/charts/src/engine/overlay.js.map +1 -1
- package/dist/native/charts/src/engine/presets.cjs +1 -1
- package/dist/native/charts/src/engine/presets.cjs.map +1 -1
- package/dist/native/charts/src/engine/presets.js +11 -4
- package/dist/native/charts/src/engine/presets.js.map +1 -1
- package/dist/native/charts/src/engine/scene.cjs +1 -1
- package/dist/native/charts/src/engine/scene.cjs.map +1 -1
- package/dist/native/charts/src/engine/scene.js +209 -97
- package/dist/native/charts/src/engine/scene.js.map +1 -1
- package/dist/native/charts/src/engine/theme.cjs.map +1 -1
- package/dist/native/charts/src/engine/theme.js.map +1 -1
- package/dist/native/components/Chart/scene.cjs +1 -1
- package/dist/native/components/Chart/scene.cjs.map +1 -1
- package/dist/native/components/Chart/scene.js +31 -19
- package/dist/native/components/Chart/scene.js.map +1 -1
- package/dist/native/source/components/Chart/scene.tsx +54 -20
- package/dist/taro/index.js +1059 -579
- package/dist/uni/charts-canvas.js +3 -1
- package/dist/weapp/controls.js +966 -225
- package/package.json +1 -1
package/dist/weapp/controls.js
CHANGED
|
@@ -6364,6 +6364,118 @@ var mix = (a, b, t) => [
|
|
|
6364
6364
|
a[2] + (b[2] - a[2]) * t,
|
|
6365
6365
|
a[3] + (b[3] - a[3]) * t
|
|
6366
6366
|
];
|
|
6367
|
+
/** Inverse of `packColor` */
|
|
6368
|
+
var unpackColor = (packed) => [
|
|
6369
|
+
(packed & 255) / 255,
|
|
6370
|
+
(packed >>> 8 & 255) / 255,
|
|
6371
|
+
(packed >>> 16 & 255) / 255,
|
|
6372
|
+
(packed >>> 24 & 255) / 255
|
|
6373
|
+
];
|
|
6374
|
+
/** Color at `t` (0-1) of a ramp through `stops` */
|
|
6375
|
+
var rampColor = (stops, t) => {
|
|
6376
|
+
if (stops.length === 1) return stops[0];
|
|
6377
|
+
const p = clamp01(t) * (stops.length - 1);
|
|
6378
|
+
const i = Math.min(stops.length - 2, Math.floor(p));
|
|
6379
|
+
return mix(stops[i], stops[i + 1], p - i);
|
|
6380
|
+
};
|
|
6381
|
+
/**
|
|
6382
|
+
* Points of the curve through `x[i], y[i]` (`i` in `[start, end)`), as
|
|
6383
|
+
* interleaved x, y, plus the index of the source point each output point
|
|
6384
|
+
* belongs to. Gaps (non-finite y) are kept.
|
|
6385
|
+
*/
|
|
6386
|
+
var curvePoints = (x, y, start, end, curve) => {
|
|
6387
|
+
const n = Math.max(0, end - start);
|
|
6388
|
+
if (curve === "step") {
|
|
6389
|
+
const points = new Float64Array(n * 4);
|
|
6390
|
+
const source = new Uint32Array(n * 2);
|
|
6391
|
+
let length = 0;
|
|
6392
|
+
for (let i = start; i < end; i++) {
|
|
6393
|
+
if (i > start && Number.isFinite(y[i - 1]) && Number.isFinite(y[i])) {
|
|
6394
|
+
points[length * 2] = x[i];
|
|
6395
|
+
points[length * 2 + 1] = y[i - 1];
|
|
6396
|
+
source[length++] = i - 1;
|
|
6397
|
+
}
|
|
6398
|
+
points[length * 2] = x[i];
|
|
6399
|
+
points[length * 2 + 1] = y[i];
|
|
6400
|
+
source[length++] = i;
|
|
6401
|
+
}
|
|
6402
|
+
return {
|
|
6403
|
+
points,
|
|
6404
|
+
source,
|
|
6405
|
+
length
|
|
6406
|
+
};
|
|
6407
|
+
}
|
|
6408
|
+
if (curve !== "smooth" || n < 3 || n > 5e4) {
|
|
6409
|
+
const points = new Float64Array(n * 2);
|
|
6410
|
+
const source = new Uint32Array(n);
|
|
6411
|
+
for (let i = start; i < end; i++) {
|
|
6412
|
+
points[(i - start) * 2] = x[i];
|
|
6413
|
+
points[(i - start) * 2 + 1] = y[i];
|
|
6414
|
+
source[i - start] = i;
|
|
6415
|
+
}
|
|
6416
|
+
return {
|
|
6417
|
+
points,
|
|
6418
|
+
source,
|
|
6419
|
+
length: n
|
|
6420
|
+
};
|
|
6421
|
+
}
|
|
6422
|
+
const tangents = new Float64Array(n);
|
|
6423
|
+
const valid = (i) => i >= start && i < end && Number.isFinite(y[i]) && Number.isFinite(x[i]);
|
|
6424
|
+
const slope = (i) => {
|
|
6425
|
+
const dx = x[i + 1] - x[i];
|
|
6426
|
+
return dx !== 0 ? (y[i + 1] - y[i]) / dx : 0;
|
|
6427
|
+
};
|
|
6428
|
+
for (let i = start; i < end; i++) {
|
|
6429
|
+
if (!valid(i)) continue;
|
|
6430
|
+
const hasPrev = valid(i - 1);
|
|
6431
|
+
const hasNext = valid(i + 1);
|
|
6432
|
+
let m;
|
|
6433
|
+
if (hasPrev && hasNext) {
|
|
6434
|
+
const a = slope(i - 1);
|
|
6435
|
+
const b = slope(i);
|
|
6436
|
+
if (a * b <= 0) m = 0;
|
|
6437
|
+
else {
|
|
6438
|
+
const ha = x[i] - x[i - 1];
|
|
6439
|
+
const hb = x[i + 1] - x[i];
|
|
6440
|
+
const w1 = 2 * hb + ha;
|
|
6441
|
+
const w2 = hb + 2 * ha;
|
|
6442
|
+
m = (w1 + w2) / (w1 / a + w2 / b);
|
|
6443
|
+
}
|
|
6444
|
+
} else if (hasNext) m = slope(i);
|
|
6445
|
+
else if (hasPrev) m = slope(i - 1);
|
|
6446
|
+
else m = 0;
|
|
6447
|
+
tangents[i - start] = m;
|
|
6448
|
+
}
|
|
6449
|
+
const points = new Float64Array((n - 1) * 10 * 2 + 2);
|
|
6450
|
+
const source = new Uint32Array((n - 1) * 10 + 1);
|
|
6451
|
+
let length = 0;
|
|
6452
|
+
for (let i = start; i < end; i++) {
|
|
6453
|
+
points[length * 2] = x[i];
|
|
6454
|
+
points[length * 2 + 1] = y[i];
|
|
6455
|
+
source[length++] = i;
|
|
6456
|
+
if (!valid(i) || !valid(i + 1)) continue;
|
|
6457
|
+
const x0 = x[i];
|
|
6458
|
+
const y0 = y[i];
|
|
6459
|
+
const h = x[i + 1] - x0;
|
|
6460
|
+
const m0 = tangents[i - start] * h;
|
|
6461
|
+
const m1 = tangents[i + 1 - start] * h;
|
|
6462
|
+
const y1 = y[i + 1];
|
|
6463
|
+
for (let k = 1; k < 10; k++) {
|
|
6464
|
+
const t = k / 10;
|
|
6465
|
+
const t2 = t * t;
|
|
6466
|
+
const t3 = t2 * t;
|
|
6467
|
+
const v = (2 * t3 - 3 * t2 + 1) * y0 + (t3 - 2 * t2 + t) * m0 + (-2 * t3 + 3 * t2) * y1 + (t3 - t2) * m1;
|
|
6468
|
+
points[length * 2] = x0 + h * t;
|
|
6469
|
+
points[length * 2 + 1] = v;
|
|
6470
|
+
source[length++] = i;
|
|
6471
|
+
}
|
|
6472
|
+
}
|
|
6473
|
+
return {
|
|
6474
|
+
points,
|
|
6475
|
+
source,
|
|
6476
|
+
length
|
|
6477
|
+
};
|
|
6478
|
+
};
|
|
6367
6479
|
//#endregion
|
|
6368
6480
|
//#region ../charts/src/engine/data.ts
|
|
6369
6481
|
var isColumns = (data) => typeof data === "object" && data !== null && !("length" in data) && "y" in data;
|
|
@@ -6382,6 +6494,27 @@ var xResolver = (type, categoryIndex) => {
|
|
|
6382
6494
|
};
|
|
6383
6495
|
};
|
|
6384
6496
|
var toNumber = (v) => typeof v === "number" ? v : v === null || v === void 0 ? NaN : Number(v);
|
|
6497
|
+
/** Category names used by string y values (heatmap rows), in order of appearance */
|
|
6498
|
+
var collectYCategories = (datas) => {
|
|
6499
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6500
|
+
for (const data of datas) {
|
|
6501
|
+
if (isColumns(data)) {
|
|
6502
|
+
const ys = data.y;
|
|
6503
|
+
if (!ArrayBuffer.isView(ys)) for (let i = 0; i < ys.length; i++) {
|
|
6504
|
+
const v = ys[i];
|
|
6505
|
+
if (typeof v === "string") seen.add(v);
|
|
6506
|
+
}
|
|
6507
|
+
continue;
|
|
6508
|
+
}
|
|
6509
|
+
const list = data;
|
|
6510
|
+
for (let i = 0; i < list.length; i++) {
|
|
6511
|
+
const item = list[i];
|
|
6512
|
+
const v = Array.isArray(item) ? item[1] : item && typeof item === "object" ? item.y : void 0;
|
|
6513
|
+
if (typeof v === "string") seen.add(v);
|
|
6514
|
+
}
|
|
6515
|
+
}
|
|
6516
|
+
return [...seen];
|
|
6517
|
+
};
|
|
6385
6518
|
/** Category names used by string x values, in order of appearance */
|
|
6386
6519
|
var collectCategories = (datas) => {
|
|
6387
6520
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -6410,6 +6543,7 @@ var finalize = (x, y, count, extra) => {
|
|
|
6410
6543
|
let yMax = -Infinity;
|
|
6411
6544
|
let sorted = true;
|
|
6412
6545
|
let prev = -Infinity;
|
|
6546
|
+
const { high, low, value } = extra;
|
|
6413
6547
|
for (let i = 0; i < count; i++) {
|
|
6414
6548
|
const xi = x[i];
|
|
6415
6549
|
if (!Number.isFinite(xi)) {
|
|
@@ -6424,6 +6558,24 @@ var finalize = (x, y, count, extra) => {
|
|
|
6424
6558
|
if (xi > xMax) xMax = xi;
|
|
6425
6559
|
if (yi < yMin) yMin = yi;
|
|
6426
6560
|
if (yi > yMax) yMax = yi;
|
|
6561
|
+
if (high) {
|
|
6562
|
+
const h = high[i];
|
|
6563
|
+
if (h > yMax) yMax = h;
|
|
6564
|
+
if (h < yMin) yMin = h;
|
|
6565
|
+
}
|
|
6566
|
+
if (low) {
|
|
6567
|
+
const l = low[i];
|
|
6568
|
+
if (l < yMin) yMin = l;
|
|
6569
|
+
if (l > yMax) yMax = l;
|
|
6570
|
+
}
|
|
6571
|
+
}
|
|
6572
|
+
let valueMin = Infinity;
|
|
6573
|
+
let valueMax = -Infinity;
|
|
6574
|
+
if (value) for (let i = 0; i < count; i++) {
|
|
6575
|
+
const v = value[i];
|
|
6576
|
+
if (!Number.isFinite(v)) continue;
|
|
6577
|
+
if (v < valueMin) valueMin = v;
|
|
6578
|
+
if (v > valueMax) valueMax = v;
|
|
6427
6579
|
}
|
|
6428
6580
|
const empty = xMin > xMax;
|
|
6429
6581
|
return {
|
|
@@ -6435,24 +6587,44 @@ var finalize = (x, y, count, extra) => {
|
|
|
6435
6587
|
xMax: empty ? NaN : xMax,
|
|
6436
6588
|
yMin: empty ? NaN : yMin,
|
|
6437
6589
|
yMax: empty ? NaN : yMax,
|
|
6590
|
+
valueMin: valueMin > valueMax ? NaN : valueMin,
|
|
6591
|
+
valueMax: valueMin > valueMax ? NaN : valueMax,
|
|
6438
6592
|
...extra
|
|
6439
6593
|
};
|
|
6440
6594
|
};
|
|
6595
|
+
var column = (values, count) => {
|
|
6596
|
+
if (!values) return null;
|
|
6597
|
+
if (values instanceof Float64Array && values.length >= count) return values.length === count ? values : values.subarray(0, count);
|
|
6598
|
+
const out = new Float64Array(count);
|
|
6599
|
+
for (let i = 0; i < count; i++) out[i] = toNumber(values[i]);
|
|
6600
|
+
return out;
|
|
6601
|
+
};
|
|
6441
6602
|
/** Turns any supported data form into columns */
|
|
6442
|
-
var normalizeData = (data, resolveX) => {
|
|
6603
|
+
var normalizeData = (data, resolveX, resolveY = toNumber) => {
|
|
6443
6604
|
const none = {
|
|
6444
6605
|
size: null,
|
|
6445
6606
|
colors: null,
|
|
6446
|
-
labels: null
|
|
6607
|
+
labels: null,
|
|
6608
|
+
open: null,
|
|
6609
|
+
high: null,
|
|
6610
|
+
low: null,
|
|
6611
|
+
value: null
|
|
6447
6612
|
};
|
|
6448
6613
|
if (isColumns(data)) {
|
|
6449
6614
|
const count = data.y.length;
|
|
6450
6615
|
const x = new Float64Array(count);
|
|
6451
|
-
const y = new Float64Array(count);
|
|
6452
6616
|
const xs = data.x;
|
|
6453
|
-
for (let i = 0; i < count; i++)
|
|
6454
|
-
|
|
6455
|
-
|
|
6617
|
+
if (!xs) for (let i = 0; i < count; i++) x[i] = i;
|
|
6618
|
+
else if (ArrayBuffer.isView(xs) && xs.length >= count) x.set(xs.length === count ? xs : xs.subarray(0, count));
|
|
6619
|
+
else for (let i = 0; i < count; i++) x[i] = resolveX(xs[i], i);
|
|
6620
|
+
const ys = data.y;
|
|
6621
|
+
let y;
|
|
6622
|
+
if (ArrayBuffer.isView(ys)) {
|
|
6623
|
+
y = new Float64Array(count);
|
|
6624
|
+
y.set(ys);
|
|
6625
|
+
} else {
|
|
6626
|
+
y = new Float64Array(count);
|
|
6627
|
+
for (let i = 0; i < count; i++) y[i] = resolveY(ys[i]);
|
|
6456
6628
|
}
|
|
6457
6629
|
let size = null;
|
|
6458
6630
|
if (data.size) {
|
|
@@ -6461,7 +6633,11 @@ var normalizeData = (data, resolveX) => {
|
|
|
6461
6633
|
}
|
|
6462
6634
|
return finalize(x, y, count, {
|
|
6463
6635
|
...none,
|
|
6464
|
-
size
|
|
6636
|
+
size,
|
|
6637
|
+
open: column(data.open, count),
|
|
6638
|
+
high: column(data.high, count),
|
|
6639
|
+
low: column(data.low, count),
|
|
6640
|
+
value: column(data.value, count)
|
|
6465
6641
|
});
|
|
6466
6642
|
}
|
|
6467
6643
|
const list = data;
|
|
@@ -6471,6 +6647,11 @@ var normalizeData = (data, resolveX) => {
|
|
|
6471
6647
|
let size = null;
|
|
6472
6648
|
let colors = null;
|
|
6473
6649
|
let labels = null;
|
|
6650
|
+
let open = null;
|
|
6651
|
+
let high = null;
|
|
6652
|
+
let low = null;
|
|
6653
|
+
let value = null;
|
|
6654
|
+
const nanColumn = () => new Float64Array(count).fill(NaN);
|
|
6474
6655
|
for (let i = 0; i < count; i++) {
|
|
6475
6656
|
const item = list[i];
|
|
6476
6657
|
if (item === null || item === void 0 || typeof item === "number") {
|
|
@@ -6478,11 +6659,11 @@ var normalizeData = (data, resolveX) => {
|
|
|
6478
6659
|
y[i] = toNumber(item);
|
|
6479
6660
|
} else if (Array.isArray(item)) {
|
|
6480
6661
|
x[i] = resolveX(item[0], i);
|
|
6481
|
-
y[i] =
|
|
6662
|
+
y[i] = resolveY(item[1]);
|
|
6482
6663
|
} else if (typeof item === "object") {
|
|
6483
6664
|
const d = item;
|
|
6484
6665
|
x[i] = d.x === void 0 ? i : resolveX(d.x, i);
|
|
6485
|
-
y[i] =
|
|
6666
|
+
y[i] = resolveY(d.y);
|
|
6486
6667
|
if (d.size !== void 0) {
|
|
6487
6668
|
size ??= new Float32Array(count).fill(NaN);
|
|
6488
6669
|
size[i] = d.size;
|
|
@@ -6495,6 +6676,10 @@ var normalizeData = (data, resolveX) => {
|
|
|
6495
6676
|
labels ??= new Array(count);
|
|
6496
6677
|
labels[i] = d.label;
|
|
6497
6678
|
}
|
|
6679
|
+
if (d.open !== void 0) (open ??= nanColumn())[i] = toNumber(d.open);
|
|
6680
|
+
if (d.high !== void 0) (high ??= nanColumn())[i] = toNumber(d.high);
|
|
6681
|
+
if (d.low !== void 0) (low ??= nanColumn())[i] = toNumber(d.low);
|
|
6682
|
+
if (d.value !== void 0) (value ??= nanColumn())[i] = toNumber(d.value);
|
|
6498
6683
|
} else {
|
|
6499
6684
|
x[i] = i;
|
|
6500
6685
|
y[i] = NaN;
|
|
@@ -6503,7 +6688,11 @@ var normalizeData = (data, resolveX) => {
|
|
|
6503
6688
|
return finalize(x, y, count, {
|
|
6504
6689
|
size,
|
|
6505
6690
|
colors,
|
|
6506
|
-
labels
|
|
6691
|
+
labels,
|
|
6692
|
+
open,
|
|
6693
|
+
high,
|
|
6694
|
+
low,
|
|
6695
|
+
value
|
|
6507
6696
|
});
|
|
6508
6697
|
};
|
|
6509
6698
|
/** First index whose x is >= value (sorted x) */
|
|
@@ -6802,18 +6991,94 @@ var extent = (values) => {
|
|
|
6802
6991
|
}
|
|
6803
6992
|
return [min, max];
|
|
6804
6993
|
};
|
|
6805
|
-
/** Smallest positive gap between consecutive
|
|
6806
|
-
var smallestStep = (
|
|
6994
|
+
/** Smallest positive gap between consecutive values (bar width on numeric axes) */
|
|
6995
|
+
var smallestStep = (columns, sorted) => {
|
|
6807
6996
|
let step = Infinity;
|
|
6808
|
-
|
|
6809
|
-
const xs =
|
|
6810
|
-
for (let i = 1; i <
|
|
6997
|
+
columns.forEach((values, k) => {
|
|
6998
|
+
const xs = sorted[k] ? values : Float64Array.from(values).sort();
|
|
6999
|
+
for (let i = 1; i < xs.length; i++) {
|
|
6811
7000
|
const d = xs[i] - xs[i - 1];
|
|
6812
7001
|
if (d > 0 && d < step) step = d;
|
|
6813
7002
|
}
|
|
6814
|
-
}
|
|
7003
|
+
});
|
|
6815
7004
|
return step;
|
|
6816
7005
|
};
|
|
7006
|
+
var bandOf = (list, axis, category) => {
|
|
7007
|
+
if (category) return 1;
|
|
7008
|
+
const step = smallestStep(list.map((s) => axis === "x" ? s.cols.x : s.cols.y), list.map((s) => axis === "x" && s.cols.sorted));
|
|
7009
|
+
return Number.isFinite(step) ? step : 1;
|
|
7010
|
+
};
|
|
7011
|
+
/**
|
|
7012
|
+
* Stacks the y values of series sharing a stack id (positive and negative
|
|
7013
|
+
* values separately); `percent` scales every stack to 100 at each x
|
|
7014
|
+
*/
|
|
7015
|
+
var stackValues = (list, percent) => {
|
|
7016
|
+
const totals = /* @__PURE__ */ new Map();
|
|
7017
|
+
if (percent) for (const { s, stack } of list) {
|
|
7018
|
+
let byX = totals.get(stack);
|
|
7019
|
+
if (!byX) totals.set(stack, byX = /* @__PURE__ */ new Map());
|
|
7020
|
+
const { x, y, count } = s.cols;
|
|
7021
|
+
for (let i = 0; i < count; i++) {
|
|
7022
|
+
const v = y[i];
|
|
7023
|
+
if (!Number.isFinite(v)) continue;
|
|
7024
|
+
const t = byX.get(x[i]) ?? [0, 0];
|
|
7025
|
+
if (v >= 0) t[0] += v;
|
|
7026
|
+
else t[1] -= v;
|
|
7027
|
+
byX.set(x[i], t);
|
|
7028
|
+
}
|
|
7029
|
+
}
|
|
7030
|
+
const running = /* @__PURE__ */ new Map();
|
|
7031
|
+
const members = /* @__PURE__ */ new Map();
|
|
7032
|
+
for (const { stack } of list) members.set(stack, (members.get(stack) ?? 0) + 1);
|
|
7033
|
+
return list.map(({ s, stack }) => {
|
|
7034
|
+
const { x, y, count } = s.cols;
|
|
7035
|
+
if (!percent && members.get(stack) === 1) {
|
|
7036
|
+
const base = new Float64Array(count);
|
|
7037
|
+
const top = new Float64Array(count);
|
|
7038
|
+
for (let i = 0; i < count; i++) {
|
|
7039
|
+
const v = y[i];
|
|
7040
|
+
const valid = Number.isFinite(v);
|
|
7041
|
+
base[i] = valid ? 0 : NaN;
|
|
7042
|
+
top[i] = valid ? v : NaN;
|
|
7043
|
+
}
|
|
7044
|
+
return {
|
|
7045
|
+
base,
|
|
7046
|
+
top
|
|
7047
|
+
};
|
|
7048
|
+
}
|
|
7049
|
+
let byX = running.get(stack);
|
|
7050
|
+
if (!byX) running.set(stack, byX = /* @__PURE__ */ new Map());
|
|
7051
|
+
const sums = totals.get(stack);
|
|
7052
|
+
const base = new Float64Array(count);
|
|
7053
|
+
const top = new Float64Array(count);
|
|
7054
|
+
for (let i = 0; i < count; i++) {
|
|
7055
|
+
let v = y[i];
|
|
7056
|
+
if (!Number.isFinite(v)) {
|
|
7057
|
+
base[i] = NaN;
|
|
7058
|
+
top[i] = NaN;
|
|
7059
|
+
continue;
|
|
7060
|
+
}
|
|
7061
|
+
if (sums) {
|
|
7062
|
+
const t = sums.get(x[i]);
|
|
7063
|
+
const total = t ? v >= 0 ? t[0] : t[1] : 0;
|
|
7064
|
+
v = total > 0 ? v / total * 100 : 0;
|
|
7065
|
+
}
|
|
7066
|
+
const t = byX.get(x[i]) ?? [0, 0];
|
|
7067
|
+
const b = v >= 0 ? t[0] : t[1];
|
|
7068
|
+
base[i] = b;
|
|
7069
|
+
top[i] = b + v;
|
|
7070
|
+
if (v >= 0) t[0] += v;
|
|
7071
|
+
else t[1] += v;
|
|
7072
|
+
byX.set(x[i], t);
|
|
7073
|
+
}
|
|
7074
|
+
return {
|
|
7075
|
+
base,
|
|
7076
|
+
top
|
|
7077
|
+
};
|
|
7078
|
+
});
|
|
7079
|
+
};
|
|
7080
|
+
var DEFAULT_UP = "var(--success-color, #16a34a)";
|
|
7081
|
+
var DEFAULT_DOWN = "var(--danger-color, #dc2626)";
|
|
6817
7082
|
var buildModel = (options, theme, hidden, cache, resolver = null) => {
|
|
6818
7083
|
const resolve = resolver ?? theme.resolve ?? ((value, fallback) => resolveStaticColor(value, {}, fallback));
|
|
6819
7084
|
const input = options.series;
|
|
@@ -6822,7 +7087,14 @@ var buildModel = (options, theme, hidden, cache, resolver = null) => {
|
|
|
6822
7087
|
const categories = xType === "category" ? [...options.xAxis?.categories ?? collectCategories(datas)] : [];
|
|
6823
7088
|
const categoryMap = new Map(categories.map((c, i) => [c, i]));
|
|
6824
7089
|
const resolveX = xResolver(xType, (name) => categoryMap.get(name) ?? NaN);
|
|
6825
|
-
const
|
|
7090
|
+
const yOpts = options.yAxis;
|
|
7091
|
+
const heatmapData = input.filter((s) => s.type === "heatmap").map((s) => s.data);
|
|
7092
|
+
const yCategories = yOpts?.type === "category" || !yOpts?.type && heatmapData.length ? [...yOpts?.categories ?? collectYCategories(heatmapData)] : [];
|
|
7093
|
+
const yType = yOpts?.type === "category" || yCategories.length ? "category" : yOpts?.type === "time" ? "time" : "linear";
|
|
7094
|
+
const yCategoryMap = new Map(yCategories.map((c, i) => [c, i]));
|
|
7095
|
+
const resolveY = (v) => typeof v === "number" ? v : typeof v === "string" ? yType === "category" ? yCategoryMap.get(v) ?? NaN : Number(v) : NaN;
|
|
7096
|
+
const resolverKey = `${xType}|${categories.join("")}|${yType}|${yCategories.join("")}`;
|
|
7097
|
+
const percent = options.stackMode === "percent";
|
|
6826
7098
|
const usedKeys = /* @__PURE__ */ new Set();
|
|
6827
7099
|
const series = input.map((s, index) => {
|
|
6828
7100
|
let key = s.id ?? `#${index}`;
|
|
@@ -6833,15 +7105,16 @@ var buildModel = (options, theme, hidden, cache, resolver = null) => {
|
|
|
6833
7105
|
entry = {
|
|
6834
7106
|
data: s.data,
|
|
6835
7107
|
resolverKey,
|
|
6836
|
-
cols: normalizeData(s.data, resolveX)
|
|
7108
|
+
cols: normalizeData(s.data, resolveX, resolveY)
|
|
6837
7109
|
};
|
|
6838
7110
|
cache.set(key, entry);
|
|
6839
7111
|
}
|
|
6840
7112
|
const type = s.type ?? "line";
|
|
6841
|
-
const
|
|
7113
|
+
const paletteColor = theme.palette[index % theme.palette.length];
|
|
7114
|
+
const color = s.color ? resolve(s.color, paletteColor) : paletteColor;
|
|
6842
7115
|
const cols = entry.cols;
|
|
6843
7116
|
let pointColors = null;
|
|
6844
|
-
if (type === "scatter" && cols.colors) {
|
|
7117
|
+
if ((type === "scatter" || type === "bar") && cols.colors) {
|
|
6845
7118
|
const resolved = /* @__PURE__ */ new Map();
|
|
6846
7119
|
pointColors = cols.colors.map((c) => {
|
|
6847
7120
|
if (c === void 0) return void 0;
|
|
@@ -6850,6 +7123,23 @@ var buildModel = (options, theme, hidden, cache, resolver = null) => {
|
|
|
6850
7123
|
return rgba;
|
|
6851
7124
|
});
|
|
6852
7125
|
}
|
|
7126
|
+
let colorScale = [];
|
|
7127
|
+
let valueRange = [0, 1];
|
|
7128
|
+
let cellColors = null;
|
|
7129
|
+
if (type === "heatmap") {
|
|
7130
|
+
colorScale = s.colorScale && s.colorScale.length ? s.colorScale.map((c) => resolve(c, color)) : [mix(theme.background, color, .08), color];
|
|
7131
|
+
valueRange = s.valueRange ? [s.valueRange[0], s.valueRange[1]] : [cols.valueMin, cols.valueMax];
|
|
7132
|
+
if (!Number.isFinite(valueRange[0])) valueRange = [0, 1];
|
|
7133
|
+
const values = cols.value ?? cols.y;
|
|
7134
|
+
const [lo, hi] = valueRange;
|
|
7135
|
+
const span = hi - lo || 1;
|
|
7136
|
+
cellColors = new Uint32Array(cols.count);
|
|
7137
|
+
for (let i = 0; i < cols.count; i++) {
|
|
7138
|
+
const v = values[i];
|
|
7139
|
+
if (!Number.isFinite(v) || !Number.isFinite(cols.y[i])) continue;
|
|
7140
|
+
cellColors[i] = packColor(rampColor(colorScale, (v - lo) / span));
|
|
7141
|
+
}
|
|
7142
|
+
}
|
|
6853
7143
|
const id = s.id ?? String(index);
|
|
6854
7144
|
return {
|
|
6855
7145
|
index,
|
|
@@ -6859,61 +7149,93 @@ var buildModel = (options, theme, hidden, cache, resolver = null) => {
|
|
|
6859
7149
|
type,
|
|
6860
7150
|
color,
|
|
6861
7151
|
colorCss: toCss(color),
|
|
6862
|
-
lineWidth: s.lineWidth ?? 2,
|
|
7152
|
+
lineWidth: s.lineWidth ?? (type === "candlestick" ? 1 : 2),
|
|
6863
7153
|
pointSize: s.pointSize ?? 8,
|
|
6864
7154
|
opacity: s.opacity ?? (type === "area" ? .28 : type === "scatter" ? .78 : 1),
|
|
6865
7155
|
hidden: !!s.hidden || hidden.has(id),
|
|
6866
7156
|
showLabels: !!s.showLabels,
|
|
7157
|
+
curve: s.curve ?? "linear",
|
|
6867
7158
|
cols,
|
|
6868
7159
|
barOffset: 0,
|
|
6869
7160
|
barHalfWidth: 0,
|
|
6870
7161
|
barBase: null,
|
|
6871
7162
|
barTop: null,
|
|
6872
|
-
|
|
7163
|
+
stackBase: null,
|
|
7164
|
+
stackTop: null,
|
|
7165
|
+
pointColors,
|
|
7166
|
+
upColor: type === "candlestick" ? resolve(s.upColor ?? DEFAULT_UP, [
|
|
7167
|
+
.09,
|
|
7168
|
+
.64,
|
|
7169
|
+
.29,
|
|
7170
|
+
1
|
|
7171
|
+
]) : color,
|
|
7172
|
+
downColor: type === "candlestick" ? resolve(s.downColor ?? DEFAULT_DOWN, [
|
|
7173
|
+
.86,
|
|
7174
|
+
.15,
|
|
7175
|
+
.15,
|
|
7176
|
+
1
|
|
7177
|
+
]) : color,
|
|
7178
|
+
cellColors,
|
|
7179
|
+
cellHalf: {
|
|
7180
|
+
x: .5,
|
|
7181
|
+
y: .5
|
|
7182
|
+
},
|
|
7183
|
+
colorScale,
|
|
7184
|
+
valueRange,
|
|
7185
|
+
radius: s.radius ?? (type === "heatmap" ? 2 : 3),
|
|
7186
|
+
format: s.format
|
|
6873
7187
|
};
|
|
6874
7188
|
});
|
|
6875
7189
|
const visible = series.filter((s) => !s.hidden);
|
|
6876
|
-
const allScatter = series.length > 0 && series.every((s) => s.type === "scatter");
|
|
7190
|
+
const allScatter = series.length > 0 && series.every((s) => s.type === "scatter" || s.type === "heatmap");
|
|
6877
7191
|
const bars = visible.filter((s) => s.type === "bar");
|
|
6878
|
-
const band = xType === "category"
|
|
6879
|
-
const step = smallestStep(bars.map((s) => s.cols));
|
|
6880
|
-
return Number.isFinite(step) ? step : 1;
|
|
6881
|
-
})();
|
|
7192
|
+
const band = bandOf(bars, "x", xType === "category");
|
|
6882
7193
|
if (bars.length) {
|
|
6883
7194
|
const slots = /* @__PURE__ */ new Map();
|
|
6884
|
-
|
|
6885
|
-
|
|
6886
|
-
if (!slots.has(stack)) slots.set(stack, slots.size);
|
|
6887
|
-
}
|
|
7195
|
+
const stackId = (s) => input[s.index].stack ?? `\u0000${s.key}`;
|
|
7196
|
+
for (const s of bars) if (!slots.has(stackId(s))) slots.set(stackId(s), slots.size);
|
|
6888
7197
|
const group = band * (slots.size > 1 ? .78 : .62);
|
|
6889
7198
|
const slotWidth = group / slots.size;
|
|
6890
|
-
const
|
|
6891
|
-
|
|
6892
|
-
|
|
6893
|
-
|
|
7199
|
+
const stacked = stackValues(bars.map((s) => ({
|
|
7200
|
+
s,
|
|
7201
|
+
stack: stackId(s)
|
|
7202
|
+
})), false);
|
|
7203
|
+
const percentStacked = percent ? stackValues(bars.filter((s) => input[s.index].stack !== void 0).map((s) => ({
|
|
7204
|
+
s,
|
|
7205
|
+
stack: stackId(s)
|
|
7206
|
+
})), true) : [];
|
|
7207
|
+
let p = 0;
|
|
7208
|
+
bars.forEach((s, k) => {
|
|
7209
|
+
const slot = slots.get(stackId(s)) ?? 0;
|
|
6894
7210
|
s.barOffset = -group / 2 + slotWidth * (slot + .5);
|
|
6895
7211
|
s.barHalfWidth = slotWidth / 2 * (slots.size > 1 ? .86 : 1);
|
|
6896
|
-
|
|
6897
|
-
|
|
6898
|
-
|
|
6899
|
-
|
|
6900
|
-
|
|
6901
|
-
|
|
6902
|
-
|
|
6903
|
-
|
|
6904
|
-
|
|
6905
|
-
|
|
6906
|
-
|
|
6907
|
-
|
|
6908
|
-
|
|
6909
|
-
|
|
6910
|
-
|
|
6911
|
-
|
|
6912
|
-
|
|
6913
|
-
|
|
6914
|
-
|
|
6915
|
-
|
|
6916
|
-
|
|
7212
|
+
const values = percent && input[s.index].stack !== void 0 ? percentStacked[p++] : stacked[k];
|
|
7213
|
+
s.barBase = values.base;
|
|
7214
|
+
s.barTop = values.top;
|
|
7215
|
+
});
|
|
7216
|
+
}
|
|
7217
|
+
const stackedLines = visible.filter((s) => (s.type === "line" || s.type === "area") && input[s.index].stack !== void 0);
|
|
7218
|
+
if (stackedLines.length) {
|
|
7219
|
+
const values = stackValues(stackedLines.map((s) => ({
|
|
7220
|
+
s,
|
|
7221
|
+
stack: input[s.index].stack ?? ""
|
|
7222
|
+
})), percent);
|
|
7223
|
+
stackedLines.forEach((s, k) => {
|
|
7224
|
+
s.stackBase = values[k].base;
|
|
7225
|
+
s.stackTop = values[k].top;
|
|
7226
|
+
});
|
|
7227
|
+
}
|
|
7228
|
+
const candles = visible.filter((s) => s.type === "candlestick");
|
|
7229
|
+
const candleBand = bandOf(candles, "x", xType === "category");
|
|
7230
|
+
for (const s of candles) s.barHalfWidth = candleBand * .3;
|
|
7231
|
+
const heatmaps = visible.filter((s) => s.type === "heatmap");
|
|
7232
|
+
if (heatmaps.length) {
|
|
7233
|
+
const cx = bandOf(heatmaps, "x", xType === "category") / 2;
|
|
7234
|
+
const cy = bandOf(heatmaps, "y", yType === "category") / 2;
|
|
7235
|
+
for (const s of heatmaps) s.cellHalf = {
|
|
7236
|
+
x: cx,
|
|
7237
|
+
y: cy
|
|
7238
|
+
};
|
|
6917
7239
|
}
|
|
6918
7240
|
const xOpts = options.xAxis;
|
|
6919
7241
|
let xRange;
|
|
@@ -6922,31 +7244,48 @@ var buildModel = (options, theme, hidden, cache, resolver = null) => {
|
|
|
6922
7244
|
const values = [];
|
|
6923
7245
|
for (const s of visible) {
|
|
6924
7246
|
values.push(s.cols.xMin, s.cols.xMax);
|
|
6925
|
-
|
|
7247
|
+
const pad = s.type === "bar" ? band / 2 : s.type === "candlestick" ? candleBand / 2 : s.type === "heatmap" ? s.cellHalf.x : 0;
|
|
7248
|
+
if (pad) values.push(s.cols.xMin - pad, s.cols.xMax + pad);
|
|
6926
7249
|
}
|
|
6927
7250
|
xRange = ensureSpan(...extent(values), xType === "time" ? [Date.now() - 864e5, Date.now()] : [0, 1]);
|
|
6928
|
-
|
|
7251
|
+
const pointsOnly = series.every((s) => s.type === "scatter");
|
|
7252
|
+
if (pointsOnly) {
|
|
6929
7253
|
const pad = (xRange[1] - xRange[0]) * .04;
|
|
6930
7254
|
xRange = [xRange[0] - pad, xRange[1] + pad];
|
|
6931
7255
|
}
|
|
6932
|
-
if ((xOpts?.nice ?? (
|
|
7256
|
+
if ((xOpts?.nice ?? (pointsOnly && xType === "linear")) && xType === "linear") xRange = niceDomain(xRange[0], xRange[1], xOpts?.tickCount ?? 6);
|
|
6933
7257
|
}
|
|
6934
7258
|
if (xOpts?.min !== void 0) xRange[0] = xOpts.min;
|
|
6935
7259
|
if (xOpts?.max !== void 0) xRange[1] = xOpts.max;
|
|
6936
7260
|
xRange = ensureSpan(xRange[0], xRange[1]);
|
|
6937
|
-
|
|
6938
|
-
|
|
6939
|
-
|
|
6940
|
-
|
|
6941
|
-
|
|
6942
|
-
|
|
6943
|
-
|
|
6944
|
-
|
|
6945
|
-
|
|
6946
|
-
|
|
6947
|
-
|
|
6948
|
-
|
|
6949
|
-
|
|
7261
|
+
let yRange;
|
|
7262
|
+
if (yType === "category") yRange = [-.5, Math.max(1, yCategories.length) - .5];
|
|
7263
|
+
else {
|
|
7264
|
+
const yValues = [];
|
|
7265
|
+
for (const s of visible) if (s.type === "bar" && s.barBase && s.barTop) yValues.push(...extent(s.barBase), ...extent(s.barTop));
|
|
7266
|
+
else if (s.stackBase && s.stackTop) yValues.push(...extent(s.stackBase), ...extent(s.stackTop));
|
|
7267
|
+
else if (s.type === "heatmap") yValues.push(s.cols.yMin - s.cellHalf.y, s.cols.yMax + s.cellHalf.y);
|
|
7268
|
+
else yValues.push(s.cols.yMin, s.cols.yMax);
|
|
7269
|
+
const filled = bars.length > 0 || visible.some((s) => s.type === "area");
|
|
7270
|
+
if (bars.length || yOpts?.zero) yValues.push(0);
|
|
7271
|
+
if (bars.some((s) => s.showLabels)) {
|
|
7272
|
+
const [lo, hi] = extent(yValues);
|
|
7273
|
+
if (hi > 0) yValues.push(hi + (hi - Math.min(0, lo)) * .1);
|
|
7274
|
+
if (lo < 0) yValues.push(lo - (Math.max(0, hi) - lo) * .1);
|
|
7275
|
+
}
|
|
7276
|
+
yRange = ensureSpan(...extent(yValues));
|
|
7277
|
+
if (series.every((s) => s.type === "scatter")) {
|
|
7278
|
+
const pad = (yRange[1] - yRange[0]) * .06;
|
|
7279
|
+
yRange = [yRange[0] - pad, yRange[1] + pad];
|
|
7280
|
+
} else if (candles.length && !bars.length) {
|
|
7281
|
+
const pad = (yRange[1] - yRange[0]) * .04;
|
|
7282
|
+
yRange = [yRange[0] - pad, yRange[1] + pad];
|
|
7283
|
+
}
|
|
7284
|
+
if ((yOpts?.nice ?? !heatmaps.length) && yType === "linear") yRange = niceDomain(yRange[0], yRange[1], yOpts?.tickCount ?? 5);
|
|
7285
|
+
if (percent && (bars.length || stackedLines.length)) yRange = [extent(yValues)[0] < 0 ? -100 : 0, 100];
|
|
7286
|
+
if (filled && !yOpts?.zero) {
|
|
7287
|
+
if (yRange[0] < 0 && extent(yValues)[0] >= 0) yRange[0] = 0;
|
|
7288
|
+
}
|
|
6950
7289
|
}
|
|
6951
7290
|
if (yOpts?.min !== void 0) yRange[0] = yOpts.min;
|
|
6952
7291
|
if (yOpts?.max !== void 0) yRange[1] = yOpts.max;
|
|
@@ -6963,10 +7302,14 @@ var buildModel = (options, theme, hidden, cache, resolver = null) => {
|
|
|
6963
7302
|
y: zoomOption.includes("y")
|
|
6964
7303
|
};
|
|
6965
7304
|
const tooltip = typeof options.tooltip === "object" ? options.tooltip : void 0;
|
|
7305
|
+
const yFormat = yOpts?.format ?? (percent && (bars.length || stackedLines.length) ? (v) => `${+v.toFixed(1)}%` : void 0);
|
|
6966
7306
|
return {
|
|
6967
7307
|
series,
|
|
6968
7308
|
x: axisModel(xOpts, xType, categories, false),
|
|
6969
|
-
y:
|
|
7309
|
+
y: {
|
|
7310
|
+
...axisModel(yOpts, yType, yCategories, yType !== "category"),
|
|
7311
|
+
format: yFormat
|
|
7312
|
+
},
|
|
6970
7313
|
base: {
|
|
6971
7314
|
x: xRange,
|
|
6972
7315
|
y: yRange
|
|
@@ -6977,10 +7320,14 @@ var buildModel = (options, theme, hidden, cache, resolver = null) => {
|
|
|
6977
7320
|
baseline: Math.min(Math.max(0, yRange[0]), yRange[1]),
|
|
6978
7321
|
minSpan: {
|
|
6979
7322
|
x: xType === "category" ? 1 : (xRange[1] - xRange[0]) * 1e-7,
|
|
6980
|
-
y: (yRange[1] - yRange[0]) * 1e-7
|
|
6981
|
-
}
|
|
7323
|
+
y: yType === "category" ? 1 : (yRange[1] - yRange[0]) * 1e-7
|
|
7324
|
+
},
|
|
7325
|
+
percent,
|
|
7326
|
+
stacks: input.map((s) => s.stack !== void 0 && (s.type === "bar" || s.type === "line" || s.type === "area" || !s.type) ? `${s.type === "bar" ? "bar" : "line"}:${s.stack}` : null)
|
|
6982
7327
|
};
|
|
6983
7328
|
};
|
|
7329
|
+
/** Y value drawn for a point: its stacked top for stacks, the close for candles */
|
|
7330
|
+
var plottedY = (s, i) => s.barTop ? s.barTop[i] : s.stackTop ? s.stackTop[i] : s.cols.y[i];
|
|
6984
7331
|
var grids = /* @__PURE__ */ new WeakMap();
|
|
6985
7332
|
/** Spatial index of a scatter series, built on first use and kept with its data */
|
|
6986
7333
|
var gridOf = (s) => {
|
|
@@ -7135,7 +7482,19 @@ var placeLabels = (labels, plot, measure, height, occupied = []) => {
|
|
|
7135
7482
|
for (const label of labels) {
|
|
7136
7483
|
const w = measure(label.text);
|
|
7137
7484
|
const gap = label.r + 4;
|
|
7138
|
-
const
|
|
7485
|
+
const above = {
|
|
7486
|
+
x: label.x - w / 2,
|
|
7487
|
+
y: label.y - gap - height,
|
|
7488
|
+
width: w,
|
|
7489
|
+
height
|
|
7490
|
+
};
|
|
7491
|
+
const below = {
|
|
7492
|
+
x: label.x - w / 2,
|
|
7493
|
+
y: label.y + gap,
|
|
7494
|
+
width: w,
|
|
7495
|
+
height
|
|
7496
|
+
};
|
|
7497
|
+
const box = (label.placement === "above" ? [above] : label.placement === "below" ? [below] : [
|
|
7139
7498
|
{
|
|
7140
7499
|
x: label.x + gap,
|
|
7141
7500
|
y: label.y - height / 2,
|
|
@@ -7148,19 +7507,9 @@ var placeLabels = (labels, plot, measure, height, occupied = []) => {
|
|
|
7148
7507
|
width: w,
|
|
7149
7508
|
height
|
|
7150
7509
|
},
|
|
7151
|
-
|
|
7152
|
-
|
|
7153
|
-
|
|
7154
|
-
width: w,
|
|
7155
|
-
height
|
|
7156
|
-
},
|
|
7157
|
-
{
|
|
7158
|
-
x: label.x - w / 2,
|
|
7159
|
-
y: label.y + gap,
|
|
7160
|
-
width: w,
|
|
7161
|
-
height
|
|
7162
|
-
}
|
|
7163
|
-
].find((c) => inside(c, plot) && !occupied.some((o) => overlaps(o, c)));
|
|
7510
|
+
above,
|
|
7511
|
+
below
|
|
7512
|
+
]).find((c) => inside(c, plot) && !occupied.some((o) => overlaps(o, c)));
|
|
7164
7513
|
if (!box) continue;
|
|
7165
7514
|
occupied.push(box);
|
|
7166
7515
|
placed.push({
|
|
@@ -7610,7 +7959,7 @@ var resolveAnnotations = (annotations, theme) => {
|
|
|
7610
7959
|
/** Ticks, room for the axes and the plot rectangle */
|
|
7611
7960
|
var layoutChart = (input) => {
|
|
7612
7961
|
const { model, view, theme, width, height, measure } = input;
|
|
7613
|
-
const yCount = model.y.tickCount ?? (height >= 220 ? 5 : Math.max(2, Math.round((height - 48) / 52)));
|
|
7962
|
+
const yCount = model.y.tickCount ?? (model.y.type === "category" ? Math.max(1, Math.floor((height - 40) / (theme.fontSize + 5))) : height >= 220 ? 5 : Math.max(2, Math.round((height - 48) / 52)));
|
|
7614
7963
|
const yTicks = axisTicks(model.y, view.y, yCount);
|
|
7615
7964
|
let yLabelWidth = 0;
|
|
7616
7965
|
if (model.y.visible) for (const label of yTicks.labels) yLabelWidth = Math.max(yLabelWidth, measure(label));
|
|
@@ -7634,7 +7983,7 @@ var layoutChart = (input) => {
|
|
|
7634
7983
|
fontSize: theme.fontSize
|
|
7635
7984
|
});
|
|
7636
7985
|
if (input.top) plot.y += input.top;
|
|
7637
|
-
const xCount = model.x.type === "category" ? Math.max(1, Math.floor(plot.width / (categoryWidth + 14))) : model.x.tickCount ?? Math.max(
|
|
7986
|
+
const xCount = model.x.type === "category" ? Math.max(1, Math.floor(plot.width / (categoryWidth + 14))) : model.x.tickCount ?? Math.max(3, Math.floor(plot.width / 88));
|
|
7638
7987
|
const xTicks = axisTicks(model.x, view.x, xCount);
|
|
7639
7988
|
return {
|
|
7640
7989
|
plot,
|
|
@@ -7643,11 +7992,32 @@ var layoutChart = (input) => {
|
|
|
7643
7992
|
yTicks
|
|
7644
7993
|
};
|
|
7645
7994
|
};
|
|
7646
|
-
/** Labels of the visible scatter points (`showLabels`) */
|
|
7647
|
-
var collectPointLabels = (model, view, s) => {
|
|
7995
|
+
/** Labels of the visible scatter points and bar values (`showLabels`) */
|
|
7996
|
+
var collectPointLabels = (model, view, s, yTicks) => {
|
|
7648
7997
|
const labels = [];
|
|
7998
|
+
const axisFormat = model.percent ? formatValue : yTicks?.formatValue ?? formatValue;
|
|
7649
7999
|
for (const series of model.series) {
|
|
7650
|
-
if (series.hidden ||
|
|
8000
|
+
if (series.hidden || !series.showLabels) continue;
|
|
8001
|
+
if (series.type === "bar" && series.barTop) {
|
|
8002
|
+
const format = series.format ?? axisFormat;
|
|
8003
|
+
const { x, y, count } = series.cols;
|
|
8004
|
+
const top = series.barTop;
|
|
8005
|
+
const [x0, x1] = view.x[0] <= view.x[1] ? view.x : [view.x[1], view.x[0]];
|
|
8006
|
+
for (let i = 0; i < count && labels.length < 300; i++) {
|
|
8007
|
+
const xv = x[i] + series.barOffset;
|
|
8008
|
+
if (!Number.isFinite(y[i]) || xv < x0 || xv > x1) continue;
|
|
8009
|
+
const negative = top[i] < (series.barBase?.[i] ?? 0);
|
|
8010
|
+
labels.push({
|
|
8011
|
+
x: s.xToPx(xv),
|
|
8012
|
+
y: s.yToPx(top[i]),
|
|
8013
|
+
r: 0,
|
|
8014
|
+
text: format(y[i]),
|
|
8015
|
+
placement: negative ? "below" : "above"
|
|
8016
|
+
});
|
|
8017
|
+
}
|
|
8018
|
+
continue;
|
|
8019
|
+
}
|
|
8020
|
+
if (series.type !== "scatter") continue;
|
|
7651
8021
|
const { x, y, count, labels: texts, size } = series.cols;
|
|
7652
8022
|
if (!texts) continue;
|
|
7653
8023
|
for (let i = 0; i < count && labels.length < 300; i++) {
|
|
@@ -7667,13 +8037,12 @@ var collectPointLabels = (model, view, s) => {
|
|
|
7667
8037
|
}
|
|
7668
8038
|
return labels;
|
|
7669
8039
|
};
|
|
7670
|
-
/** Pixel position of a point (the top of a bar) */
|
|
8040
|
+
/** Pixel position of a point (the top of a bar or stack, the close of a candle) */
|
|
7671
8041
|
var pointOf = (s, i, sc) => {
|
|
7672
8042
|
const xv = s.cols.x[i] + (s.type === "bar" ? s.barOffset : 0);
|
|
7673
|
-
const yv = s.type === "bar" && s.barTop ? s.barTop[i] : s.cols.y[i];
|
|
7674
8043
|
return {
|
|
7675
8044
|
px: sc.xToPx(xv),
|
|
7676
|
-
py: sc.yToPx(
|
|
8045
|
+
py: sc.yToPx(plottedY(s, i))
|
|
7677
8046
|
};
|
|
7678
8047
|
};
|
|
7679
8048
|
var candidateOf = (s, i, px, py, sc) => {
|
|
@@ -7683,6 +8052,12 @@ var candidateOf = (s, i, px, py, sc) => {
|
|
|
7683
8052
|
const half = s.barHalfWidth / sc.xPerPx;
|
|
7684
8053
|
const base = sc.yToPx(s.barBase[i]);
|
|
7685
8054
|
inside = Math.abs(px - p.px) <= half && py >= Math.min(base, p.py) - 2 && py <= Math.max(base, p.py) + 2;
|
|
8055
|
+
} else if (s.type === "candlestick") {
|
|
8056
|
+
const { high, low, y } = s.cols;
|
|
8057
|
+
const half = Math.max(s.barHalfWidth / sc.xPerPx, 3);
|
|
8058
|
+
const a = sc.yToPx(high ? high[i] : y[i]);
|
|
8059
|
+
const b = sc.yToPx(low ? low[i] : y[i]);
|
|
8060
|
+
inside = Math.abs(px - p.px) <= half && py >= Math.min(a, b) - 2 && py <= Math.max(a, b) + 2;
|
|
7686
8061
|
}
|
|
7687
8062
|
return {
|
|
7688
8063
|
series: s,
|
|
@@ -7714,6 +8089,16 @@ var nearestScatter = (s, px, py, sc, slop) => {
|
|
|
7714
8089
|
});
|
|
7715
8090
|
return best;
|
|
7716
8091
|
};
|
|
8092
|
+
/** Heatmap cell containing a data position, -1 if none */
|
|
8093
|
+
var cellAt = (s, xv, yv) => {
|
|
8094
|
+
const { x: hx, y: hy } = s.cellHalf;
|
|
8095
|
+
const { x, y } = s.cols;
|
|
8096
|
+
let found = -1;
|
|
8097
|
+
gridOf(s).query(xv - hx, xv + hx, yv - hy, yv + hy, (i) => {
|
|
8098
|
+
if (s.cellColors?.[i] && Math.abs(x[i] - xv) <= hx && Math.abs(y[i] - yv) <= hy) found = i;
|
|
8099
|
+
});
|
|
8100
|
+
return found;
|
|
8101
|
+
};
|
|
7717
8102
|
var nearestX = (s, xv) => {
|
|
7718
8103
|
const { x, y, count, sorted } = s.cols;
|
|
7719
8104
|
if (sorted) return nearestIndex(x, y, count, xv);
|
|
@@ -7733,6 +8118,21 @@ var nearestX = (s, xv) => {
|
|
|
7733
8118
|
var hoverItemOf = (s, index) => {
|
|
7734
8119
|
const pc = s.pointColors?.[index];
|
|
7735
8120
|
const label = s.cols.labels?.[index];
|
|
8121
|
+
const { open, high, low, value } = s.cols;
|
|
8122
|
+
let color = pc ? toCss(pc) : s.colorCss;
|
|
8123
|
+
const extra = {};
|
|
8124
|
+
if (s.type === "candlestick") {
|
|
8125
|
+
const o = open ? open[index] : NaN;
|
|
8126
|
+
if (Number.isFinite(o)) extra.open = o;
|
|
8127
|
+
if (high && Number.isFinite(high[index])) extra.high = high[index];
|
|
8128
|
+
if (low && Number.isFinite(low[index])) extra.low = low[index];
|
|
8129
|
+
color = toCss(s.cols.y[index] < o ? s.downColor : s.upColor);
|
|
8130
|
+
} else if (s.type === "heatmap") {
|
|
8131
|
+
const v = value ? value[index] : s.cols.y[index];
|
|
8132
|
+
if (Number.isFinite(v)) extra.value = v;
|
|
8133
|
+
const packed = s.cellColors?.[index];
|
|
8134
|
+
if (packed) color = toCss(unpackColor(packed));
|
|
8135
|
+
}
|
|
7736
8136
|
return {
|
|
7737
8137
|
seriesIndex: s.index,
|
|
7738
8138
|
seriesId: s.id,
|
|
@@ -7740,8 +8140,9 @@ var hoverItemOf = (s, index) => {
|
|
|
7740
8140
|
index,
|
|
7741
8141
|
x: s.cols.x[index],
|
|
7742
8142
|
y: s.cols.y[index],
|
|
7743
|
-
color
|
|
7744
|
-
...label !== void 0 ? { label } : {}
|
|
8143
|
+
color,
|
|
8144
|
+
...label !== void 0 ? { label } : {},
|
|
8145
|
+
...extra
|
|
7745
8146
|
};
|
|
7746
8147
|
};
|
|
7747
8148
|
var eventOf = (candidates, xTicks) => {
|
|
@@ -7772,6 +8173,14 @@ var hitTest = (model, sc, xTicks, px, py, slop = 0) => {
|
|
|
7772
8173
|
if (s.type === "scatter") {
|
|
7773
8174
|
const i = nearestScatter(s, px, py, sc, slop);
|
|
7774
8175
|
if (i >= 0) scatter.push(candidateOf(s, i, px, py, sc));
|
|
8176
|
+
} else if (s.type === "heatmap") {
|
|
8177
|
+
const i = cellAt(s, sc.pxToX(px), sc.pxToY(py));
|
|
8178
|
+
if (i >= 0) {
|
|
8179
|
+
const c = candidateOf(s, i, px, py, sc);
|
|
8180
|
+
c.inside = true;
|
|
8181
|
+
c.dist = 0;
|
|
8182
|
+
scatter.push(c);
|
|
8183
|
+
}
|
|
7775
8184
|
} else {
|
|
7776
8185
|
const i = nearestX(s, xv);
|
|
7777
8186
|
if (i >= 0) others.push(candidateOf(s, i, px, py, sc));
|
|
@@ -7806,6 +8215,20 @@ var sameHover = (a, b) => a === b || !!a && !!b && a.items.length === b.items.le
|
|
|
7806
8215
|
/** Default tooltip content of a hover payload */
|
|
7807
8216
|
var tooltipContent = (model, event, yTicks) => {
|
|
7808
8217
|
const yFormat = yTicks?.formatValue ?? String;
|
|
8218
|
+
const first = event.items[0];
|
|
8219
|
+
const firstSeries = first ? model.series[first.seriesIndex] : null;
|
|
8220
|
+
if (event.items.length === 1 && firstSeries?.type === "heatmap") {
|
|
8221
|
+
const yName = model.y.type === "category" ? model.y.categories[Math.round(first.y)] ?? yFormat(first.y) : yFormat(first.y);
|
|
8222
|
+
return {
|
|
8223
|
+
title: `${event.xLabel} · ${yName}`,
|
|
8224
|
+
titleColor: null,
|
|
8225
|
+
rows: [{
|
|
8226
|
+
color: first.color,
|
|
8227
|
+
name: first.label ?? firstSeries.name,
|
|
8228
|
+
value: first.value === void 0 ? "–" : (firstSeries.format ?? formatValue)(first.value)
|
|
8229
|
+
}]
|
|
8230
|
+
};
|
|
8231
|
+
}
|
|
7809
8232
|
if (event.items.every((it) => model.series[it.seriesIndex].type === "scatter") && event.items.length === 1) {
|
|
7810
8233
|
const it = event.items[0];
|
|
7811
8234
|
const rows = [{
|
|
@@ -7828,52 +8251,125 @@ var tooltipContent = (model, event, yTicks) => {
|
|
|
7828
8251
|
rows
|
|
7829
8252
|
};
|
|
7830
8253
|
}
|
|
8254
|
+
const rows = [];
|
|
8255
|
+
/** Row of every item */
|
|
8256
|
+
const rowOf = [];
|
|
8257
|
+
for (const it of event.items) {
|
|
8258
|
+
const s = model.series[it.seriesIndex];
|
|
8259
|
+
rowOf.push(rows.length);
|
|
8260
|
+
if (s.type === "candlestick") {
|
|
8261
|
+
const change = it.open !== void 0 && it.open !== 0 ? (it.y - it.open) / Math.abs(it.open) * 100 : NaN;
|
|
8262
|
+
rows.push({
|
|
8263
|
+
color: it.color,
|
|
8264
|
+
name: s.name,
|
|
8265
|
+
value: Number.isFinite(change) ? `${change >= 0 ? "+" : ""}${change.toFixed(2)}%` : ""
|
|
8266
|
+
});
|
|
8267
|
+
const ohlc = [
|
|
8268
|
+
["Open", it.open],
|
|
8269
|
+
["High", it.high],
|
|
8270
|
+
["Low", it.low],
|
|
8271
|
+
["Close", it.y]
|
|
8272
|
+
];
|
|
8273
|
+
for (const [name, v] of ohlc) if (v !== void 0 && Number.isFinite(v)) rows.push({
|
|
8274
|
+
color: null,
|
|
8275
|
+
name,
|
|
8276
|
+
value: (s.format ?? yFormat)(v)
|
|
8277
|
+
});
|
|
8278
|
+
continue;
|
|
8279
|
+
}
|
|
8280
|
+
rows.push({
|
|
8281
|
+
color: it.color,
|
|
8282
|
+
name: it.label ? `${it.seriesName} · ${it.label}` : it.seriesName,
|
|
8283
|
+
value: (s.format ?? yFormat)(it.y)
|
|
8284
|
+
});
|
|
8285
|
+
}
|
|
8286
|
+
if (model.percent) {
|
|
8287
|
+
const totals = /* @__PURE__ */ new Map();
|
|
8288
|
+
for (const it of event.items) {
|
|
8289
|
+
const stack = stackIdOf(model, it.seriesIndex);
|
|
8290
|
+
if (stack !== null && Number.isFinite(it.y)) totals.set(stack, (totals.get(stack) ?? 0) + Math.abs(it.y));
|
|
8291
|
+
}
|
|
8292
|
+
event.items.forEach((it, k) => {
|
|
8293
|
+
const stack = stackIdOf(model, it.seriesIndex);
|
|
8294
|
+
const total = stack !== null ? totals.get(stack) : void 0;
|
|
8295
|
+
const row = rows[rowOf[k]];
|
|
8296
|
+
if (total && row && Number.isFinite(it.y)) row.value = `${(model.series[it.seriesIndex].format ?? formatValue)(it.y)} · ${(Math.abs(it.y) / total * 100).toFixed(1)}%`;
|
|
8297
|
+
});
|
|
8298
|
+
}
|
|
7831
8299
|
return {
|
|
7832
8300
|
title: event.xLabel,
|
|
7833
8301
|
titleColor: null,
|
|
7834
|
-
rows
|
|
7835
|
-
color: it.color,
|
|
7836
|
-
name: it.label ? `${it.seriesName} · ${it.label}` : it.seriesName,
|
|
7837
|
-
value: yFormat(it.y)
|
|
7838
|
-
}))
|
|
8302
|
+
rows
|
|
7839
8303
|
};
|
|
7840
8304
|
};
|
|
7841
|
-
/**
|
|
8305
|
+
/** Stack of a series in a 100% chart (`null` when it is not stacked) */
|
|
8306
|
+
var stackIdOf = (model, seriesIndex) => model.series[seriesIndex].hidden ? null : model.stacks[seriesIndex];
|
|
8307
|
+
/** Markers of the hovered points (pixels of the stage); bands come first */
|
|
7842
8308
|
var hoverMarks = (model, sc, event) => {
|
|
7843
8309
|
const marks = [];
|
|
7844
8310
|
const { plot } = sc;
|
|
8311
|
+
let bandLo = Infinity;
|
|
8312
|
+
let bandHi = -Infinity;
|
|
7845
8313
|
for (const it of event.items) {
|
|
7846
8314
|
const s = model.series[it.seriesIndex];
|
|
7847
|
-
if (s.type === "bar"
|
|
8315
|
+
if (s.type === "bar" || s.type === "candlestick") {
|
|
7848
8316
|
const cx = sc.xToPx(it.x + s.barOffset);
|
|
7849
8317
|
const half = Math.max(s.barHalfWidth / sc.xPerPx, 1);
|
|
7850
|
-
|
|
7851
|
-
|
|
8318
|
+
bandLo = Math.min(bandLo, cx - half);
|
|
8319
|
+
bandHi = Math.max(bandHi, cx + half);
|
|
8320
|
+
continue;
|
|
8321
|
+
}
|
|
8322
|
+
if (s.type === "heatmap") {
|
|
8323
|
+
const cx = sc.xToPx(it.x);
|
|
8324
|
+
const cy = sc.yToPx(it.y);
|
|
8325
|
+
const hw = Math.abs(s.cellHalf.x / sc.xPerPx);
|
|
8326
|
+
const hh = Math.abs(s.cellHalf.y / sc.yPerPx);
|
|
7852
8327
|
marks.push({
|
|
7853
|
-
kind: "
|
|
7854
|
-
x: cx -
|
|
7855
|
-
y:
|
|
7856
|
-
width:
|
|
7857
|
-
height:
|
|
8328
|
+
kind: "cell",
|
|
8329
|
+
x: cx - hw,
|
|
8330
|
+
y: cy - hh,
|
|
8331
|
+
width: hw * 2,
|
|
8332
|
+
height: hh * 2
|
|
7858
8333
|
});
|
|
7859
8334
|
continue;
|
|
7860
8335
|
}
|
|
7861
|
-
const px =
|
|
7862
|
-
const py = sc.yToPx(it.y);
|
|
8336
|
+
const { px, py } = pointOf(s, it.index, sc);
|
|
7863
8337
|
if (px < plot.x - 1 || px > plot.x + plot.width + 1 || py < plot.y - 1 || py > plot.y + plot.height + 1) continue;
|
|
7864
|
-
const size = s.type === "scatter" ? dotSize(s, it.index) +
|
|
8338
|
+
const size = s.type === "scatter" ? dotSize(s, it.index) + 4 : Math.max(9, s.lineWidth * 2 + 5);
|
|
8339
|
+
const rgba = s.pointColors?.[it.index] ?? s.color;
|
|
7865
8340
|
marks.push({
|
|
7866
8341
|
kind: "dot",
|
|
7867
8342
|
x: px,
|
|
7868
8343
|
y: py,
|
|
7869
8344
|
size,
|
|
7870
|
-
color: it.color
|
|
8345
|
+
color: it.color,
|
|
8346
|
+
halo: toCss(rgba, .2)
|
|
8347
|
+
});
|
|
8348
|
+
}
|
|
8349
|
+
if (bandHi > bandLo) {
|
|
8350
|
+
const pad = Math.max(4, (bandHi - bandLo) * .14);
|
|
8351
|
+
const x0 = Math.max(plot.x, bandLo - pad);
|
|
8352
|
+
const x1 = Math.min(plot.x + plot.width, bandHi + pad);
|
|
8353
|
+
if (x1 > x0) marks.unshift({
|
|
8354
|
+
kind: "band",
|
|
8355
|
+
x: x0,
|
|
8356
|
+
y: plot.y,
|
|
8357
|
+
width: x1 - x0,
|
|
8358
|
+
height: plot.height
|
|
7871
8359
|
});
|
|
7872
8360
|
}
|
|
7873
8361
|
return marks;
|
|
7874
8362
|
};
|
|
8363
|
+
/** Swatch of a series in the legend */
|
|
8364
|
+
var legendShape = (type) => type === "scatter" ? "dot" : type === "line" ? "line" : "square";
|
|
7875
8365
|
/** Whether the guide line follows the pointer */
|
|
7876
|
-
var showsCrosshair = (model, event, crosshair) => crosshair ?? (model.tooltipMode === "axis" && event.items.some((it) =>
|
|
8366
|
+
var showsCrosshair = (model, event, crosshair) => crosshair ?? (model.tooltipMode === "axis" && event.items.some((it) => {
|
|
8367
|
+
const type = model.series[it.seriesIndex].type;
|
|
8368
|
+
return type === "line" || type === "area";
|
|
8369
|
+
}) && !event.items.some((it) => {
|
|
8370
|
+
const type = model.series[it.seriesIndex].type;
|
|
8371
|
+
return type === "bar" || type === "candlestick";
|
|
8372
|
+
}));
|
|
7877
8373
|
//#endregion
|
|
7878
8374
|
//#region ../charts/src/engine/theme.ts
|
|
7879
8375
|
/** Used when no CSS variable is defined (e.g. without the Minerva stylesheet) */
|
|
@@ -8065,7 +8561,7 @@ var createChartController = (config) => {
|
|
|
8065
8561
|
id: s.id,
|
|
8066
8562
|
name: s.name,
|
|
8067
8563
|
color: s.colorCss,
|
|
8068
|
-
shape: s.type
|
|
8564
|
+
shape: legendShape(s.type),
|
|
8069
8565
|
hidden: s.hidden,
|
|
8070
8566
|
box: {
|
|
8071
8567
|
x,
|
|
@@ -8141,7 +8637,7 @@ var createChartController = (config) => {
|
|
|
8141
8637
|
top: legendTop,
|
|
8142
8638
|
measure: (text) => measure(text)
|
|
8143
8639
|
});
|
|
8144
|
-
const labels = collectPointLabels(model, view, layout.scales);
|
|
8640
|
+
const labels = collectPointLabels(model, view, layout.scales, layout.yTicks);
|
|
8145
8641
|
const occupied = [];
|
|
8146
8642
|
const labelHeight = theme.fontSize + 4;
|
|
8147
8643
|
for (const a of annotations) {
|
|
@@ -8567,19 +9063,49 @@ var GAP = 3e38;
|
|
|
8567
9063
|
//#endregion
|
|
8568
9064
|
//#region ../charts/src/engine/items.ts
|
|
8569
9065
|
var rel = (value, origin) => Number.isFinite(value) ? value - origin : GAP;
|
|
8570
|
-
var points = (x, y, count, o) => {
|
|
8571
|
-
const out = new Float32Array(count * 2);
|
|
8572
|
-
for (let i = 0; i < count; i++) {
|
|
8573
|
-
out[i * 2] = rel(x[i], o.x);
|
|
8574
|
-
out[i * 2 + 1] = Number.isFinite(y[i]) ? y[i] - o.y : GAP;
|
|
8575
|
-
}
|
|
8576
|
-
return out;
|
|
8577
|
-
};
|
|
8578
9066
|
var DRAW_ORDER = {
|
|
8579
|
-
|
|
8580
|
-
|
|
8581
|
-
|
|
8582
|
-
|
|
9067
|
+
heatmap: 0,
|
|
9068
|
+
area: 1,
|
|
9069
|
+
bar: 2,
|
|
9070
|
+
candlestick: 3,
|
|
9071
|
+
line: 4,
|
|
9072
|
+
scatter: 5
|
|
9073
|
+
};
|
|
9074
|
+
/** Line (and area) points of a series: stacked, curved; interleaved x, y */
|
|
9075
|
+
var linePoints = (s) => {
|
|
9076
|
+
const { x, count } = s.cols;
|
|
9077
|
+
const top = s.stackTop ?? s.cols.y;
|
|
9078
|
+
const stackBase = s.stackBase;
|
|
9079
|
+
if (s.curve === "linear") return {
|
|
9080
|
+
n: count,
|
|
9081
|
+
xAt: (i) => x[i],
|
|
9082
|
+
yAt: (i) => top[i],
|
|
9083
|
+
baseAt: stackBase ? (i) => stackBase[i] : null
|
|
9084
|
+
};
|
|
9085
|
+
const curved = curvePoints(x, top, 0, count, s.curve);
|
|
9086
|
+
const base = stackBase ? curvePoints(x, stackBase, 0, count, s.curve).points : null;
|
|
9087
|
+
const points = curved.points;
|
|
9088
|
+
return {
|
|
9089
|
+
n: curved.length,
|
|
9090
|
+
xAt: (i) => points[i * 2],
|
|
9091
|
+
yAt: (i) => points[i * 2 + 1],
|
|
9092
|
+
baseAt: base ? (i) => base[i * 2 + 1] : null
|
|
9093
|
+
};
|
|
9094
|
+
};
|
|
9095
|
+
var barItem = (key, version, s, count, write, extra) => {
|
|
9096
|
+
const instances = /* @__PURE__ */ new ArrayBuffer(count * 16);
|
|
9097
|
+
const f = new Float32Array(instances);
|
|
9098
|
+
const u = new Uint32Array(instances);
|
|
9099
|
+
for (let i = 0; i < count; i++) write(i, f, u);
|
|
9100
|
+
return {
|
|
9101
|
+
kind: "bar",
|
|
9102
|
+
key,
|
|
9103
|
+
version,
|
|
9104
|
+
color: s.color,
|
|
9105
|
+
instances,
|
|
9106
|
+
count,
|
|
9107
|
+
...extra
|
|
9108
|
+
};
|
|
8583
9109
|
};
|
|
8584
9110
|
/** Render items of the visible series, back to front */
|
|
8585
9111
|
var buildItems = (model, origin, version) => {
|
|
@@ -8593,25 +9119,48 @@ var buildItems = (model, origin, version) => {
|
|
|
8593
9119
|
switch (s.type) {
|
|
8594
9120
|
case "line":
|
|
8595
9121
|
case "area": {
|
|
8596
|
-
const
|
|
8597
|
-
|
|
8598
|
-
|
|
8599
|
-
|
|
8600
|
-
|
|
8601
|
-
|
|
8602
|
-
|
|
8603
|
-
|
|
8604
|
-
|
|
8605
|
-
|
|
8606
|
-
|
|
8607
|
-
|
|
9122
|
+
const { n, xAt, yAt, baseAt } = linePoints(s);
|
|
9123
|
+
const pts = new Float32Array(n * 2);
|
|
9124
|
+
if (s.curve === "linear") {
|
|
9125
|
+
const top = s.stackTop ?? y;
|
|
9126
|
+
const ox = origin.x;
|
|
9127
|
+
const oy = origin.y;
|
|
9128
|
+
for (let i = 0; i < n; i++) {
|
|
9129
|
+
const xv = x[i];
|
|
9130
|
+
const yv = top[i];
|
|
9131
|
+
pts[i * 2] = Number.isFinite(xv) ? xv - ox : GAP;
|
|
9132
|
+
pts[i * 2 + 1] = Number.isFinite(yv) ? yv - oy : GAP;
|
|
9133
|
+
}
|
|
9134
|
+
} else for (let i = 0; i < n; i++) {
|
|
9135
|
+
pts[i * 2] = rel(xAt(i), origin.x);
|
|
9136
|
+
pts[i * 2 + 1] = rel(yAt(i), origin.y);
|
|
9137
|
+
}
|
|
9138
|
+
if (s.type === "area") {
|
|
9139
|
+
const area = new Float32Array(n * 3);
|
|
9140
|
+
const baseline = model.baseline - origin.y;
|
|
9141
|
+
for (let i = 0; i < n; i++) {
|
|
9142
|
+
area[i * 3] = pts[i * 2];
|
|
9143
|
+
area[i * 3 + 1] = pts[i * 2 + 1];
|
|
9144
|
+
area[i * 3 + 2] = baseAt ? rel(baseAt(i), origin.y) : baseline;
|
|
9145
|
+
}
|
|
9146
|
+
items.push({
|
|
9147
|
+
kind: "area",
|
|
9148
|
+
key: `${s.key}:area`,
|
|
9149
|
+
version,
|
|
9150
|
+
color: s.color,
|
|
9151
|
+
points: area,
|
|
9152
|
+
count: n,
|
|
9153
|
+
opacity: s.opacity,
|
|
9154
|
+
sorted
|
|
9155
|
+
});
|
|
9156
|
+
}
|
|
8608
9157
|
(s.type === "area" ? outlines : items).push({
|
|
8609
9158
|
kind: "line",
|
|
8610
9159
|
key: `${s.key}:line`,
|
|
8611
9160
|
version,
|
|
8612
9161
|
color: s.color,
|
|
8613
9162
|
points: pts,
|
|
8614
|
-
count,
|
|
9163
|
+
count: n,
|
|
8615
9164
|
width: s.lineWidth,
|
|
8616
9165
|
sorted
|
|
8617
9166
|
});
|
|
@@ -8620,24 +9169,76 @@ var buildItems = (model, origin, version) => {
|
|
|
8620
9169
|
case "bar": {
|
|
8621
9170
|
const base = s.barBase ?? new Float64Array(count);
|
|
8622
9171
|
const top = s.barTop ?? y;
|
|
8623
|
-
const
|
|
8624
|
-
|
|
9172
|
+
const seriesColor = packColor(s.color);
|
|
9173
|
+
const shared = model.series.some((o) => o !== s && !o.hidden && o.type === "bar" && o.barOffset === s.barOffset);
|
|
9174
|
+
items.push(barItem(`${s.key}:bar`, version, s, count, (i, f, u) => {
|
|
8625
9175
|
const valid = Number.isFinite(top[i]) && Number.isFinite(base[i]);
|
|
8626
|
-
|
|
8627
|
-
|
|
8628
|
-
|
|
8629
|
-
|
|
8630
|
-
|
|
8631
|
-
|
|
8632
|
-
key: `${s.key}:bar`,
|
|
8633
|
-
version,
|
|
8634
|
-
color: s.color,
|
|
8635
|
-
instances,
|
|
8636
|
-
count,
|
|
9176
|
+
f[i * 4] = rel(x[i] + s.barOffset, origin.x);
|
|
9177
|
+
f[i * 4 + 1] = valid ? base[i] - origin.y : GAP;
|
|
9178
|
+
f[i * 4 + 2] = valid ? top[i] - origin.y : GAP;
|
|
9179
|
+
const pc = s.pointColors?.[i];
|
|
9180
|
+
u[i * 4 + 3] = pc ? packColor(pc) : seriesColor;
|
|
9181
|
+
}, {
|
|
8637
9182
|
halfWidth: s.barHalfWidth,
|
|
8638
|
-
|
|
8639
|
-
|
|
8640
|
-
|
|
9183
|
+
radius: shared ? 0 : s.radius,
|
|
9184
|
+
inset: 0,
|
|
9185
|
+
minHalf: 0,
|
|
9186
|
+
sorted
|
|
9187
|
+
}));
|
|
9188
|
+
break;
|
|
9189
|
+
}
|
|
9190
|
+
case "candlestick": {
|
|
9191
|
+
const { open, high, low } = s.cols;
|
|
9192
|
+
const up = packColor(s.upColor);
|
|
9193
|
+
const down = packColor(s.downColor);
|
|
9194
|
+
const colorAt = (i) => open && Number.isFinite(open[i]) && y[i] < open[i] ? down : up;
|
|
9195
|
+
items.push(barItem(`${s.key}:wick`, version, s, count, (i, f, u) => {
|
|
9196
|
+
const hi = high ? high[i] : y[i];
|
|
9197
|
+
const lo = low ? low[i] : y[i];
|
|
9198
|
+
const valid = Number.isFinite(hi) && Number.isFinite(lo) && Number.isFinite(y[i]);
|
|
9199
|
+
f[i * 4] = rel(x[i], origin.x);
|
|
9200
|
+
f[i * 4 + 1] = valid ? lo - origin.y : GAP;
|
|
9201
|
+
f[i * 4 + 2] = valid ? hi - origin.y : GAP;
|
|
9202
|
+
u[i * 4 + 3] = colorAt(i);
|
|
9203
|
+
}, {
|
|
9204
|
+
halfWidth: 0,
|
|
9205
|
+
radius: 0,
|
|
9206
|
+
inset: 0,
|
|
9207
|
+
minHalf: s.lineWidth / 2,
|
|
9208
|
+
sorted
|
|
9209
|
+
}), barItem(`${s.key}:body`, version, s, count, (i, f, u) => {
|
|
9210
|
+
const o = open ? open[i] : y[i];
|
|
9211
|
+
const valid = Number.isFinite(o) && Number.isFinite(y[i]);
|
|
9212
|
+
f[i * 4] = rel(x[i], origin.x);
|
|
9213
|
+
f[i * 4 + 1] = valid ? o - origin.y : GAP;
|
|
9214
|
+
f[i * 4 + 2] = valid ? y[i] - origin.y : GAP;
|
|
9215
|
+
u[i * 4 + 3] = colorAt(i);
|
|
9216
|
+
}, {
|
|
9217
|
+
halfWidth: s.barHalfWidth,
|
|
9218
|
+
radius: Math.min(s.radius, 1.5),
|
|
9219
|
+
inset: 0,
|
|
9220
|
+
minHalf: .5,
|
|
9221
|
+
sorted
|
|
9222
|
+
}));
|
|
9223
|
+
break;
|
|
9224
|
+
}
|
|
9225
|
+
case "heatmap": {
|
|
9226
|
+
const colors = s.cellColors;
|
|
9227
|
+
const hy = s.cellHalf.y;
|
|
9228
|
+
items.push(barItem(`${s.key}:cells`, version, s, count, (i, f, u) => {
|
|
9229
|
+
const c = colors ? colors[i] : 0;
|
|
9230
|
+
const valid = c !== 0 && Number.isFinite(x[i]);
|
|
9231
|
+
f[i * 4] = rel(x[i], origin.x);
|
|
9232
|
+
f[i * 4 + 1] = valid ? y[i] - hy - origin.y : GAP;
|
|
9233
|
+
f[i * 4 + 2] = valid ? y[i] + hy - origin.y : GAP;
|
|
9234
|
+
u[i * 4 + 3] = c;
|
|
9235
|
+
}, {
|
|
9236
|
+
halfWidth: s.cellHalf.x,
|
|
9237
|
+
radius: s.radius,
|
|
9238
|
+
inset: 1,
|
|
9239
|
+
minHalf: 0,
|
|
9240
|
+
sorted
|
|
9241
|
+
}));
|
|
8641
9242
|
break;
|
|
8642
9243
|
}
|
|
8643
9244
|
default: {
|
|
@@ -8673,25 +9274,77 @@ var buildItems = (model, origin, version) => {
|
|
|
8673
9274
|
return items;
|
|
8674
9275
|
};
|
|
8675
9276
|
var rgba = (c, alpha) => `rgba(${Math.round(c[0] * 255)},${Math.round(c[1] * 255)},${Math.round(c[2] * 255)},${c[3] * alpha})`;
|
|
8676
|
-
var unpack = (packed) => [
|
|
8677
|
-
(packed & 255) / 255,
|
|
8678
|
-
(packed >>> 8 & 255) / 255,
|
|
8679
|
-
(packed >>> 16 & 255) / 255,
|
|
8680
|
-
(packed >>> 24 & 255) / 255
|
|
8681
|
-
];
|
|
8682
9277
|
var isGap = (v) => !Number.isFinite(v) || Math.abs(v) >= 15e37;
|
|
8683
9278
|
/** First point index whose relative x is >= value (sorted, interleaved) */
|
|
8684
|
-
var lowerBoundX = (points, count, value) => {
|
|
9279
|
+
var lowerBoundX = (points, count, value, stride = 2) => {
|
|
8685
9280
|
let lo = 0;
|
|
8686
9281
|
let hi = count;
|
|
8687
9282
|
while (lo < hi) {
|
|
8688
9283
|
const mid = lo + hi >>> 1;
|
|
8689
|
-
if (points[mid *
|
|
9284
|
+
if (points[mid * stride] < value) lo = mid + 1;
|
|
8690
9285
|
else hi = mid;
|
|
8691
9286
|
}
|
|
8692
9287
|
return lo;
|
|
8693
9288
|
};
|
|
8694
9289
|
/**
|
|
9290
|
+
* Min-max decimation of area points (x, top, bottom): per pixel column the
|
|
9291
|
+
* first, lowest, highest and last tops are kept with their bottoms
|
|
9292
|
+
*/
|
|
9293
|
+
var decimateArea = (points, start, end, column) => {
|
|
9294
|
+
const out = new Float64Array(Math.max(0, end - start) * 3);
|
|
9295
|
+
let length = 0;
|
|
9296
|
+
const push = (i) => {
|
|
9297
|
+
out[length * 3] = points[i * 3];
|
|
9298
|
+
out[length * 3 + 1] = points[i * 3 + 1];
|
|
9299
|
+
out[length * 3 + 2] = points[i * 3 + 2];
|
|
9300
|
+
length++;
|
|
9301
|
+
};
|
|
9302
|
+
let col = NaN;
|
|
9303
|
+
let first = -1;
|
|
9304
|
+
let min = -1;
|
|
9305
|
+
let max = -1;
|
|
9306
|
+
let last = -1;
|
|
9307
|
+
const flush = () => {
|
|
9308
|
+
if (first < 0) return;
|
|
9309
|
+
const picks = [
|
|
9310
|
+
first,
|
|
9311
|
+
min,
|
|
9312
|
+
max,
|
|
9313
|
+
last
|
|
9314
|
+
].sort((a, b) => a - b);
|
|
9315
|
+
let prev = -1;
|
|
9316
|
+
for (const i of picks) {
|
|
9317
|
+
if (i !== prev) push(i);
|
|
9318
|
+
prev = i;
|
|
9319
|
+
}
|
|
9320
|
+
first = -1;
|
|
9321
|
+
};
|
|
9322
|
+
for (let i = start; i < end; i++) {
|
|
9323
|
+
const y = points[i * 3 + 1];
|
|
9324
|
+
if (isGap(points[i * 3]) || isGap(y) || isGap(points[i * 3 + 2])) {
|
|
9325
|
+
flush();
|
|
9326
|
+
col = NaN;
|
|
9327
|
+
push(i);
|
|
9328
|
+
continue;
|
|
9329
|
+
}
|
|
9330
|
+
const c = Math.floor(column(points[i * 3]));
|
|
9331
|
+
if (c !== col || first < 0) {
|
|
9332
|
+
flush();
|
|
9333
|
+
col = c;
|
|
9334
|
+
first = min = max = last = i;
|
|
9335
|
+
} else {
|
|
9336
|
+
if (y < points[min * 3 + 1]) min = i;
|
|
9337
|
+
if (y > points[max * 3 + 1]) max = i;
|
|
9338
|
+
last = i;
|
|
9339
|
+
}
|
|
9340
|
+
}
|
|
9341
|
+
flush();
|
|
9342
|
+
return {
|
|
9343
|
+
points: out,
|
|
9344
|
+
length
|
|
9345
|
+
};
|
|
9346
|
+
};
|
|
9347
|
+
/**
|
|
8695
9348
|
* Data layer drawn with any 2D context (browser canvases, mini-program
|
|
8696
9349
|
* canvases, OffscreenCanvas). `scratchCanvas` creates the canvas used to
|
|
8697
9350
|
* rasterize very large scatter sets; without it they are drawn as one
|
|
@@ -8754,61 +9407,82 @@ var createCanvas2dPainter = (ctx, scratchCanvas) => {
|
|
|
8754
9407
|
};
|
|
8755
9408
|
const drawArea = (item, frame) => {
|
|
8756
9409
|
const m = mapper(frame);
|
|
8757
|
-
|
|
8758
|
-
|
|
8759
|
-
|
|
9410
|
+
let points = item.points;
|
|
9411
|
+
let length = item.count;
|
|
9412
|
+
if (item.sorted && item.count > frame.width * 2) {
|
|
9413
|
+
const [x0, x1] = m.xRange();
|
|
9414
|
+
const start = Math.max(0, lowerBoundX(item.points, item.count, x0, 3) - 1);
|
|
9415
|
+
const end = Math.min(item.count, lowerBoundX(item.points, item.count, x1, 3) + 1);
|
|
9416
|
+
({points, length} = decimateArea(item.points, start, end, m.px));
|
|
9417
|
+
}
|
|
9418
|
+
const gradient = ctx.createLinearGradient(0, 0, 0, frame.height);
|
|
8760
9419
|
gradient.addColorStop(0, rgba(item.color, item.opacity));
|
|
8761
|
-
gradient.addColorStop(1, rgba(item.color, item.opacity * .
|
|
9420
|
+
gradient.addColorStop(1, rgba(item.color, item.opacity * .25));
|
|
8762
9421
|
ctx.fillStyle = gradient;
|
|
8763
9422
|
ctx.beginPath();
|
|
8764
9423
|
let runStart = -1;
|
|
8765
|
-
|
|
8766
|
-
const close = () => {
|
|
9424
|
+
const close = (end) => {
|
|
8767
9425
|
if (runStart < 0) return;
|
|
8768
|
-
ctx.lineTo(
|
|
9426
|
+
for (let k = end - 1; k >= runStart; k--) ctx.lineTo(m.px(points[k * 3]), m.py(points[k * 3 + 2]));
|
|
8769
9427
|
ctx.closePath();
|
|
8770
9428
|
runStart = -1;
|
|
8771
9429
|
};
|
|
8772
9430
|
for (let i = 0; i < length; i++) {
|
|
8773
|
-
const x = points[i *
|
|
8774
|
-
const y = points[i *
|
|
8775
|
-
if (isGap(x) || isGap(y)) {
|
|
8776
|
-
close();
|
|
9431
|
+
const x = points[i * 3];
|
|
9432
|
+
const y = points[i * 3 + 1];
|
|
9433
|
+
if (isGap(x) || isGap(y) || isGap(points[i * 3 + 2])) {
|
|
9434
|
+
close(i);
|
|
8777
9435
|
continue;
|
|
8778
9436
|
}
|
|
8779
|
-
const px = m.px(x);
|
|
8780
9437
|
if (runStart < 0) {
|
|
8781
9438
|
runStart = i;
|
|
8782
|
-
ctx.moveTo(px,
|
|
8783
|
-
}
|
|
8784
|
-
ctx.lineTo(px, m.py(y));
|
|
8785
|
-
lastX = px;
|
|
9439
|
+
ctx.moveTo(m.px(x), m.py(y));
|
|
9440
|
+
} else ctx.lineTo(m.px(x), m.py(y));
|
|
8786
9441
|
}
|
|
8787
|
-
close();
|
|
9442
|
+
close(length);
|
|
8788
9443
|
ctx.fill();
|
|
8789
9444
|
};
|
|
8790
9445
|
const drawBars = (item, frame) => {
|
|
8791
9446
|
const m = mapper(frame);
|
|
8792
|
-
const
|
|
8793
|
-
const
|
|
8794
|
-
|
|
8795
|
-
|
|
8796
|
-
const
|
|
9447
|
+
const dpr = frame.dpr;
|
|
9448
|
+
const minHalf = item.minHalf * dpr;
|
|
9449
|
+
const rawHalf = Math.abs(item.halfWidth * frame.transform.xScale) * .5 * frame.width;
|
|
9450
|
+
const r = item.radius * dpr;
|
|
9451
|
+
const f = new Float32Array(item.instances, 0, item.count * 4);
|
|
9452
|
+
const u = new Uint32Array(item.instances, 0, item.count * 4);
|
|
9453
|
+
const [x0, x1] = m.xRange();
|
|
9454
|
+
const pad = Math.abs(item.halfWidth);
|
|
9455
|
+
const groups = /* @__PURE__ */ new Map();
|
|
8797
9456
|
for (let i = 0; i < item.count; i++) {
|
|
8798
|
-
const x =
|
|
8799
|
-
|
|
8800
|
-
|
|
8801
|
-
|
|
8802
|
-
|
|
8803
|
-
|
|
8804
|
-
|
|
8805
|
-
|
|
8806
|
-
|
|
8807
|
-
|
|
8808
|
-
|
|
8809
|
-
|
|
9457
|
+
const x = f[i * 4];
|
|
9458
|
+
if (isGap(x) || isGap(f[i * 4 + 1]) || isGap(f[i * 4 + 2])) continue;
|
|
9459
|
+
if (x < x0 - pad || x > x1 + pad) continue;
|
|
9460
|
+
const packed = u[i * 4 + 3];
|
|
9461
|
+
let list = groups.get(packed);
|
|
9462
|
+
if (!list) groups.set(packed, list = []);
|
|
9463
|
+
list.push(i);
|
|
9464
|
+
}
|
|
9465
|
+
const rounded = typeof ctx.roundRect === "function";
|
|
9466
|
+
for (const [packed, list] of groups) {
|
|
9467
|
+
ctx.fillStyle = rgba(unpackColor(packed), 1);
|
|
9468
|
+
ctx.beginPath();
|
|
9469
|
+
for (const i of list) {
|
|
9470
|
+
const cx = m.px(f[i * 4]);
|
|
9471
|
+
const a = m.py(f[i * 4 + 1]);
|
|
9472
|
+
const b = m.py(f[i * 4 + 2]);
|
|
9473
|
+
const rawHh = Math.abs(a - b) / 2;
|
|
9474
|
+
const fade = Math.min(1, Math.max(0, (Math.min(rawHalf, rawHh) - 3 * dpr) / (2 * dpr)));
|
|
9475
|
+
const inset = item.inset * dpr * fade - (item.inset > 0 ? .5 * (1 - fade) : 0);
|
|
9476
|
+
const half = Math.max(rawHalf - inset, .5, minHalf);
|
|
9477
|
+
const hh = Math.max(rawHh - inset, minHalf);
|
|
9478
|
+
if (hh <= 0) continue;
|
|
9479
|
+
const cy = (a + b) / 2;
|
|
9480
|
+
const radius = Math.min(r, half, hh);
|
|
9481
|
+
if (radius > .5 && rounded) ctx.roundRect(cx - half, cy - hh, half * 2, hh * 2, radius);
|
|
9482
|
+
else ctx.rect(cx - half, cy - hh, half * 2, hh * 2);
|
|
9483
|
+
}
|
|
9484
|
+
ctx.fill();
|
|
8810
9485
|
}
|
|
8811
|
-
ctx.fill();
|
|
8812
9486
|
};
|
|
8813
9487
|
/** One square per occupied cell (the last point of a cell wins, like the GPU) */
|
|
8814
9488
|
const drawScatterCells = (item, frame) => {
|
|
@@ -8842,7 +9516,7 @@ var createCanvas2dPainter = (ctx, scratchCanvas) => {
|
|
|
8842
9516
|
list.push(c);
|
|
8843
9517
|
}
|
|
8844
9518
|
for (const [packed, cells] of groups) {
|
|
8845
|
-
ctx.fillStyle = rgba(
|
|
9519
|
+
ctx.fillStyle = rgba(unpackColor(packed), Math.max(item.opacity, .6));
|
|
8846
9520
|
for (const c of cells) ctx.fillRect(c % cols * cell, Math.floor(c / cols) * cell, cell, cell);
|
|
8847
9521
|
}
|
|
8848
9522
|
};
|
|
@@ -8908,7 +9582,7 @@ var createCanvas2dPainter = (ctx, scratchCanvas) => {
|
|
|
8908
9582
|
}
|
|
8909
9583
|
const stroke = item.stroke * frame.dpr;
|
|
8910
9584
|
for (const [packed, list] of groups) {
|
|
8911
|
-
const color =
|
|
9585
|
+
const color = unpackColor(packed);
|
|
8912
9586
|
ctx.beginPath();
|
|
8913
9587
|
for (const i of list) {
|
|
8914
9588
|
const x = f[i * 4];
|
|
@@ -8969,6 +9643,33 @@ var createCanvas2dPainter = (ctx, scratchCanvas) => {
|
|
|
8969
9643
|
};
|
|
8970
9644
|
};
|
|
8971
9645
|
//#endregion
|
|
9646
|
+
//#region ../charts/src/engine/signature.ts
|
|
9647
|
+
var ids = /* @__PURE__ */ new WeakMap();
|
|
9648
|
+
var counter = 0;
|
|
9649
|
+
/** Stable id of an object (data columns compare by identity) */
|
|
9650
|
+
var idOf = (value) => {
|
|
9651
|
+
let id = ids.get(value);
|
|
9652
|
+
if (id === void 0) ids.set(value, id = ++counter);
|
|
9653
|
+
return id;
|
|
9654
|
+
};
|
|
9655
|
+
/**
|
|
9656
|
+
* Every input of `buildItems` (and of the origin of its positions): data
|
|
9657
|
+
* identity, types, colors, visibility, widths, bar layout, stacks, curves,
|
|
9658
|
+
* radii, candlestick and heatmap colors. `themeKey` covers the colors resolved
|
|
9659
|
+
* from the theme that the model doesn't spell out (per-point colors);
|
|
9660
|
+
* `stackOf` gives the `stack` option of a series.
|
|
9661
|
+
*/
|
|
9662
|
+
var itemsSignature = (model, themeKey, stackOf) => {
|
|
9663
|
+
const { base } = model;
|
|
9664
|
+
let signature = `${themeKey}|${model.baseline}|${model.percent}|${base.x[0]},${base.x[1]}|${base.y[0]},${base.y[1]}`;
|
|
9665
|
+
for (const s of model.series) {
|
|
9666
|
+
signature += `\n${s.key}|${s.type}|${idOf(s.cols)}|${s.colorCss}|${s.hidden}|${s.lineWidth}|${s.pointSize}|${s.opacity}|${s.barOffset}|${s.barHalfWidth}|${stackOf(s.index) ?? ""}|${s.curve}|${s.radius}`;
|
|
9667
|
+
if (s.type === "candlestick") signature += `|${s.upColor}/${s.downColor}`;
|
|
9668
|
+
else if (s.type === "heatmap") signature += `|${s.colorScale.join(";")}/${s.valueRange[0]},${s.valueRange[1]}/${s.cellHalf.x},${s.cellHalf.y}`;
|
|
9669
|
+
}
|
|
9670
|
+
return signature;
|
|
9671
|
+
};
|
|
9672
|
+
//#endregion
|
|
8972
9673
|
//#region ../charts/src/engine/canvas.ts
|
|
8973
9674
|
var mid = (r) => (r[0] + r[1]) / 2;
|
|
8974
9675
|
var roundedRect = (ctx, x, y, w, h, r) => {
|
|
@@ -9026,6 +9727,12 @@ var drawScene = (ctx, scene, items, origin, pixelRatio, painter = createCanvas2d
|
|
|
9026
9727
|
}
|
|
9027
9728
|
ctx.globalAlpha = 1;
|
|
9028
9729
|
}
|
|
9730
|
+
for (const mark of scene.hover?.marks ?? []) {
|
|
9731
|
+
if (mark.kind !== "band") continue;
|
|
9732
|
+
roundedRect(ctx, mark.x, mark.y, mark.width, mark.height, 6);
|
|
9733
|
+
ctx.fillStyle = toCss(theme.text, .06);
|
|
9734
|
+
ctx.fill();
|
|
9735
|
+
}
|
|
9029
9736
|
const scale = (range, o, reverse) => {
|
|
9030
9737
|
const s = 2 / (range[1] - range[0]);
|
|
9031
9738
|
const offset = (o - range[0]) * s - 1;
|
|
@@ -9084,13 +9791,23 @@ var drawScene = (ctx, scene, items, origin, pixelRatio, painter = createCanvas2d
|
|
|
9084
9791
|
ctx.restore();
|
|
9085
9792
|
}
|
|
9086
9793
|
for (const mark of hover.marks) {
|
|
9087
|
-
if (mark.kind === "
|
|
9088
|
-
|
|
9089
|
-
ctx
|
|
9794
|
+
if (mark.kind === "band") continue;
|
|
9795
|
+
if (mark.kind === "cell") {
|
|
9796
|
+
roundedRect(ctx, mark.x, mark.y, mark.width, mark.height, 3);
|
|
9797
|
+
ctx.lineWidth = 3;
|
|
9798
|
+
ctx.strokeStyle = toCss(theme.background);
|
|
9799
|
+
ctx.stroke();
|
|
9800
|
+
ctx.lineWidth = 1.5;
|
|
9801
|
+
ctx.strokeStyle = toCss(theme.text, .55);
|
|
9802
|
+
ctx.stroke();
|
|
9090
9803
|
continue;
|
|
9091
9804
|
}
|
|
9092
9805
|
ctx.beginPath();
|
|
9093
|
-
ctx.arc(mark.x, mark.y, mark.size / 2, 0, Math.PI * 2);
|
|
9806
|
+
ctx.arc(mark.x, mark.y, mark.size / 2 + 4, 0, Math.PI * 2);
|
|
9807
|
+
ctx.fillStyle = mark.halo;
|
|
9808
|
+
ctx.fill();
|
|
9809
|
+
ctx.beginPath();
|
|
9810
|
+
ctx.arc(mark.x, mark.y, mark.size / 2 - 1, 0, Math.PI * 2);
|
|
9094
9811
|
ctx.fillStyle = mark.color;
|
|
9095
9812
|
ctx.fill();
|
|
9096
9813
|
ctx.lineWidth = 2;
|
|
@@ -9122,7 +9839,7 @@ var drawScene = (ctx, scene, items, origin, pixelRatio, painter = createCanvas2d
|
|
|
9122
9839
|
ctx.fill();
|
|
9123
9840
|
ctx.restore();
|
|
9124
9841
|
roundedRect(ctx, box.x + .5, box.y + .5, box.width - 1, box.height - 1, 8);
|
|
9125
|
-
ctx.strokeStyle = toCss(theme.axis);
|
|
9842
|
+
ctx.strokeStyle = toCss(theme.axis, .6);
|
|
9126
9843
|
ctx.lineWidth = 1;
|
|
9127
9844
|
ctx.stroke();
|
|
9128
9845
|
ctx.textBaseline = "middle";
|
|
@@ -9190,6 +9907,16 @@ var createCanvasChart = (config) => {
|
|
|
9190
9907
|
let frameId = null;
|
|
9191
9908
|
let items = [];
|
|
9192
9909
|
let itemsModel = null;
|
|
9910
|
+
let itemsKey = "";
|
|
9911
|
+
let options = config.options;
|
|
9912
|
+
/** Ids of the themes seen (the controller replaces its theme on changes) */
|
|
9913
|
+
const themeIds = /* @__PURE__ */ new WeakMap();
|
|
9914
|
+
let themeCount = 0;
|
|
9915
|
+
const themeId = (theme) => {
|
|
9916
|
+
let id = themeIds.get(theme);
|
|
9917
|
+
if (id === void 0) themeIds.set(theme, id = ++themeCount);
|
|
9918
|
+
return id;
|
|
9919
|
+
};
|
|
9193
9920
|
let origin = {
|
|
9194
9921
|
x: 0,
|
|
9195
9922
|
y: 0
|
|
@@ -9218,11 +9945,15 @@ var createCanvasChart = (config) => {
|
|
|
9218
9945
|
fontSet = "";
|
|
9219
9946
|
if (itemsModel !== scene.model) {
|
|
9220
9947
|
itemsModel = scene.model;
|
|
9221
|
-
|
|
9222
|
-
|
|
9223
|
-
|
|
9224
|
-
|
|
9225
|
-
|
|
9948
|
+
const key = itemsSignature(scene.model, themeId(scene.theme), (index) => options.series[index]?.stack);
|
|
9949
|
+
if (key !== itemsKey) {
|
|
9950
|
+
itemsKey = key;
|
|
9951
|
+
origin = {
|
|
9952
|
+
x: mid(scene.model.base.x),
|
|
9953
|
+
y: mid(scene.model.base.y)
|
|
9954
|
+
};
|
|
9955
|
+
items = buildItems(scene.model, origin, ++version);
|
|
9956
|
+
}
|
|
9226
9957
|
}
|
|
9227
9958
|
drawScene(ctx, scene, items, origin, dpr, painter);
|
|
9228
9959
|
fontSet = "";
|
|
@@ -9245,7 +9976,10 @@ var createCanvasChart = (config) => {
|
|
|
9245
9976
|
touch: true
|
|
9246
9977
|
});
|
|
9247
9978
|
return {
|
|
9248
|
-
setOptions: (o) =>
|
|
9979
|
+
setOptions: (o) => {
|
|
9980
|
+
options = o;
|
|
9981
|
+
controller.setOptions(o);
|
|
9982
|
+
},
|
|
9249
9983
|
setTheme: (t) => controller.setTheme(t),
|
|
9250
9984
|
resize(w, h, ratio) {
|
|
9251
9985
|
width = w;
|
|
@@ -9308,15 +10042,22 @@ var createCanvasChart = (config) => {
|
|
|
9308
10042
|
//#endregion
|
|
9309
10043
|
//#region ../charts/src/engine/presets.ts
|
|
9310
10044
|
/** Gives the series without a `type` the type of the component */
|
|
9311
|
-
var withSeriesType = (series, type, stack) => series.map((s) =>
|
|
9312
|
-
|
|
9313
|
-
|
|
9314
|
-
|
|
9315
|
-
|
|
10045
|
+
var withSeriesType = (series, type, stack, curve) => series.map((s) => {
|
|
10046
|
+
const t = s.type ?? type;
|
|
10047
|
+
return {
|
|
10048
|
+
...s,
|
|
10049
|
+
type: t,
|
|
10050
|
+
...stack !== void 0 && t === type ? { stack: s.stack ?? stack } : {},
|
|
10051
|
+
...curve !== void 0 && (t === "line" || t === "area") ? { curve: s.curve ?? curve } : {}
|
|
10052
|
+
};
|
|
10053
|
+
});
|
|
9316
10054
|
/** Series of a LineChart (`area` fills them) */
|
|
9317
|
-
var lineSeries = (series, area = false) => withSeriesType(series, area ? "area" : "line");
|
|
9318
|
-
/** Series of a BarChart (`stacked` stacks them) */
|
|
9319
|
-
var barSeries = (series, stacked = false) => withSeriesType(series, "bar", stacked ? "stack" : void 0)
|
|
10055
|
+
var lineSeries = (series, area = false, extra = {}) => withSeriesType(series, area ? "area" : "line", extra.stacked ? "stack" : void 0, extra.curve);
|
|
10056
|
+
/** Series of a BarChart (`stacked` stacks them, `labels` shows the values) */
|
|
10057
|
+
var barSeries = (series, stacked = false, labels = false) => withSeriesType(series, "bar", stacked ? "stack" : void 0).map((s) => labels && s.type === "bar" ? {
|
|
10058
|
+
...s,
|
|
10059
|
+
showLabels: s.showLabels ?? true
|
|
10060
|
+
} : s);
|
|
9320
10061
|
/** Series of a ScatterChart */
|
|
9321
10062
|
var scatterSeries = (series) => withSeriesType(series, "scatter");
|
|
9322
10063
|
var DEFAULT_QUADRANT_COLORS = {
|