@ixfx/components 0.1.5 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundle/index.d.ts +105 -37
- package/bundle/index.d.ts.map +1 -1
- package/bundle/index.js +477 -156
- package/bundle/index.js.map +1 -1
- package/dist/charts/plot.d.ts +104 -36
- package/dist/charts/plot.d.ts.map +1 -1
- package/dist/charts/plot.js +628 -175
- package/dist/charts/plot.js.map +1 -1
- package/package.json +13 -13
package/bundle/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { Circles, degreeToRadian, radianArc, radianToDegree, radiansSum } from "ixfx/geometry.js";
|
|
1
|
+
import { Circles, Rects, degreeToRadian, radianArc, radianToDegree, radiansSum } from "ixfx/geometry.js";
|
|
2
2
|
import * as Numbers from "ixfx/numbers.js";
|
|
3
3
|
import { clamp } from "ixfx/numbers.js";
|
|
4
4
|
import { getCssVariable, getCssVariablesWithFallback } from "ixfx/dom.js";
|
|
5
5
|
import { Trees } from "ixfx/collections.js";
|
|
6
6
|
import { CanvasHelper, Colour, Drawing } from "ixfx/visual.js";
|
|
7
|
+
import * as Arrays from "ixfx/arrays.js";
|
|
7
8
|
import { Pathed } from "ixfx";
|
|
8
9
|
|
|
9
10
|
//#region node_modules/@lit/reactive-element/css-tag.js
|
|
@@ -2227,31 +2228,139 @@ SplitLayoutElement = __decorate([t("ixfx-split-layout")], SplitLayoutElement);
|
|
|
2227
2228
|
|
|
2228
2229
|
//#endregion
|
|
2229
2230
|
//#region src/charts/plot.ts
|
|
2231
|
+
const rangeIsEqual = (a$2, b$2) => {
|
|
2232
|
+
if (a$2 === void 0 || b$2 === void 0) return false;
|
|
2233
|
+
return a$2.max === b$2.max && a$2.min === b$2.min;
|
|
2234
|
+
};
|
|
2235
|
+
var PlotAxis = class {
|
|
2236
|
+
bounds = `auto`;
|
|
2237
|
+
#currentScalerRange;
|
|
2238
|
+
#persistentScale = Numbers.rangeInit();
|
|
2239
|
+
#currentScaler = (v$2) => v$2;
|
|
2240
|
+
constructor(name) {
|
|
2241
|
+
this.name = name;
|
|
2242
|
+
}
|
|
2243
|
+
humanFormatValue(value) {
|
|
2244
|
+
if (value.length === 0) return ``;
|
|
2245
|
+
const v$2 = value[0];
|
|
2246
|
+
if (v$2 < 2) return v$2.toFixed(2);
|
|
2247
|
+
return v$2.toString();
|
|
2248
|
+
}
|
|
2249
|
+
getRange(series) {
|
|
2250
|
+
if (this.bounds === `auto`) return this.computeActualRange(series);
|
|
2251
|
+
if (this.bounds === `auto-persistent`) {
|
|
2252
|
+
const r$6 = this.computeActualRange(series);
|
|
2253
|
+
this.#persistentScale = Numbers.rangeMergeRange(r$6, this.#persistentScale);
|
|
2254
|
+
return this.#persistentScale;
|
|
2255
|
+
}
|
|
2256
|
+
return this.bounds;
|
|
2257
|
+
}
|
|
2258
|
+
getCurrentRange() {
|
|
2259
|
+
return this.#currentScalerRange;
|
|
2260
|
+
}
|
|
2261
|
+
getValueScaler(series) {
|
|
2262
|
+
const r$6 = this.getRange(series);
|
|
2263
|
+
if (!rangeIsEqual(r$6, this.#currentScalerRange)) {
|
|
2264
|
+
this.#currentScalerRange = r$6;
|
|
2265
|
+
this.#currentScaler = Numbers.scaler(r$6.min, r$6.max, 0, 1);
|
|
2266
|
+
}
|
|
2267
|
+
return this.#currentScaler;
|
|
2268
|
+
}
|
|
2269
|
+
computeActualRange(seriesOnAxis, column = 0) {
|
|
2270
|
+
let min = Number.MAX_SAFE_INTEGER;
|
|
2271
|
+
let max = Number.MIN_SAFE_INTEGER;
|
|
2272
|
+
let count = 0;
|
|
2273
|
+
for (const s$5 of seriesOnAxis) {
|
|
2274
|
+
for (const [v$2, _index] of s$5.getValuesForColumn(column)) {
|
|
2275
|
+
if (typeof v$2 !== `number`) continue;
|
|
2276
|
+
if (Number.isNaN(v$2)) continue;
|
|
2277
|
+
if (v$2 < min) min = v$2;
|
|
2278
|
+
if (v$2 > max) max = v$2;
|
|
2279
|
+
}
|
|
2280
|
+
count++;
|
|
2281
|
+
}
|
|
2282
|
+
return {
|
|
2283
|
+
min,
|
|
2284
|
+
max
|
|
2285
|
+
};
|
|
2286
|
+
}
|
|
2287
|
+
};
|
|
2230
2288
|
let PlotElement = class PlotElement$1 extends i {
|
|
2231
|
-
streaming = true;
|
|
2232
2289
|
hideLegend = false;
|
|
2233
|
-
maxLength = 500;
|
|
2234
|
-
dataWidth = 5;
|
|
2235
|
-
fixedMax = NaN;
|
|
2236
|
-
fixedMin = NaN;
|
|
2237
|
-
lineWidth = 2;
|
|
2238
2290
|
renderStyle = `dot`;
|
|
2239
|
-
manualDraw = false;
|
|
2240
2291
|
padding = 5;
|
|
2292
|
+
primaryAxis = new PlotAxis(`primary`);
|
|
2293
|
+
secondaryAxis = new PlotAxis(`secondary`);
|
|
2241
2294
|
paused = false;
|
|
2295
|
+
plotAreaFormat = {
|
|
2296
|
+
fill: { type: `none` },
|
|
2297
|
+
outline: { type: `none` }
|
|
2298
|
+
};
|
|
2299
|
+
/**
|
|
2300
|
+
* Settings used for automatically generating series colour
|
|
2301
|
+
*/
|
|
2302
|
+
automaticSeriesColour = {
|
|
2303
|
+
saturation: 1,
|
|
2304
|
+
lightness: .5,
|
|
2305
|
+
alpha: 1
|
|
2306
|
+
};
|
|
2307
|
+
seriesDefault = {};
|
|
2242
2308
|
#series = /* @__PURE__ */ new Map();
|
|
2243
2309
|
#canvas;
|
|
2244
2310
|
#drawing;
|
|
2245
2311
|
#legendColour = ``;
|
|
2246
|
-
#
|
|
2312
|
+
#autoSeriesColour = 0;
|
|
2313
|
+
#hitboxes = [];
|
|
2314
|
+
#seriesFormatting = /* @__PURE__ */ new Map();
|
|
2315
|
+
#swatchSize = 10;
|
|
2247
2316
|
canvasEl = e$1();
|
|
2248
|
-
|
|
2317
|
+
tooltipEl = e$1();
|
|
2318
|
+
seriesColourGenerate = (_seriesName) => {
|
|
2319
|
+
const c$6 = Colour.goldenAngleColour(this.#autoSeriesColour, this.automaticSeriesColour.saturation, this.automaticSeriesColour.lightness, this.automaticSeriesColour.alpha);
|
|
2320
|
+
this.#autoSeriesColour++;
|
|
2321
|
+
return c$6;
|
|
2322
|
+
};
|
|
2249
2323
|
get series() {
|
|
2250
2324
|
return [...this.#series.values()];
|
|
2251
2325
|
}
|
|
2252
2326
|
get seriesCount() {
|
|
2253
2327
|
return this.#series.size;
|
|
2254
2328
|
}
|
|
2329
|
+
getSeriesFormatting(seriesName, createIfNeeded) {
|
|
2330
|
+
let f$4 = this.#seriesFormatting.get(seriesName);
|
|
2331
|
+
if (!f$4 && createIfNeeded) {
|
|
2332
|
+
f$4 = {
|
|
2333
|
+
axis: `primary`,
|
|
2334
|
+
fill: {
|
|
2335
|
+
colour: this.seriesColourGenerate(seriesName),
|
|
2336
|
+
type: `solid`
|
|
2337
|
+
},
|
|
2338
|
+
outline: { type: `none` },
|
|
2339
|
+
bar: { gapWidth: 10 },
|
|
2340
|
+
dot: {
|
|
2341
|
+
gapWidth: 0,
|
|
2342
|
+
radius: `automatic`
|
|
2343
|
+
},
|
|
2344
|
+
line: {
|
|
2345
|
+
width: 2,
|
|
2346
|
+
cap: `round`,
|
|
2347
|
+
join: `round`
|
|
2348
|
+
}
|
|
2349
|
+
};
|
|
2350
|
+
this.#seriesFormatting.set(seriesName, f$4);
|
|
2351
|
+
}
|
|
2352
|
+
return f$4;
|
|
2353
|
+
}
|
|
2354
|
+
setSeriesFormatting(seriesName, formatting) {
|
|
2355
|
+
let existing = this.getSeriesFormatting(seriesName, true);
|
|
2356
|
+
const combined = {
|
|
2357
|
+
...existing,
|
|
2358
|
+
...formatting
|
|
2359
|
+
};
|
|
2360
|
+
combined.fill = resolveFillDrawStyle(combined.fill);
|
|
2361
|
+
combined.outline = resolveOutlineDrawStyle(combined.outline);
|
|
2362
|
+
this.#seriesFormatting.set(seriesName, combined);
|
|
2363
|
+
}
|
|
2255
2364
|
/**
|
|
2256
2365
|
* Returns a `PlotElement` instance based on a query
|
|
2257
2366
|
* ```js
|
|
@@ -2298,6 +2407,7 @@ let PlotElement = class PlotElement$1 extends i {
|
|
|
2298
2407
|
*/
|
|
2299
2408
|
clear() {
|
|
2300
2409
|
this.#series.clear();
|
|
2410
|
+
this.#autoSeriesColour = 0;
|
|
2301
2411
|
}
|
|
2302
2412
|
/**
|
|
2303
2413
|
* Keeps all series, but deletes their data
|
|
@@ -2305,8 +2415,45 @@ let PlotElement = class PlotElement$1 extends i {
|
|
|
2305
2415
|
clearData() {
|
|
2306
2416
|
for (const s$5 of this.#series.values()) s$5.clear();
|
|
2307
2417
|
}
|
|
2308
|
-
|
|
2309
|
-
|
|
2418
|
+
#lastPointerPosition;
|
|
2419
|
+
#onPointerLeave() {
|
|
2420
|
+
this.#lastPointerPosition = void 0;
|
|
2421
|
+
this.#hideTooltip();
|
|
2422
|
+
}
|
|
2423
|
+
#onPointerMove(event) {
|
|
2424
|
+
this.#lastPointerPosition = {
|
|
2425
|
+
x: event.offsetX,
|
|
2426
|
+
screenX: event.x,
|
|
2427
|
+
y: event.offsetY,
|
|
2428
|
+
screenY: event.y
|
|
2429
|
+
};
|
|
2430
|
+
this.#updateToolTip();
|
|
2431
|
+
}
|
|
2432
|
+
#updateToolTip() {
|
|
2433
|
+
if (!this.#lastPointerPosition) return;
|
|
2434
|
+
for (const hb of this.#hitboxes) if (Rects.intersectsPoint(hb, this.#lastPointerPosition)) {
|
|
2435
|
+
if (hb.value) this.#setTooltip(hb.series.humanFormatValue(hb.value));
|
|
2436
|
+
else this.#setTooltip(``);
|
|
2437
|
+
return;
|
|
2438
|
+
}
|
|
2439
|
+
this.#hideTooltip();
|
|
2440
|
+
}
|
|
2441
|
+
#hideTooltip() {
|
|
2442
|
+
const v$2 = this.tooltipEl.value;
|
|
2443
|
+
if (!v$2) return;
|
|
2444
|
+
v$2.classList.add(`hidden`);
|
|
2445
|
+
}
|
|
2446
|
+
#setTooltip(innerHtml) {
|
|
2447
|
+
const v$2 = this.tooltipEl.value;
|
|
2448
|
+
if (!v$2) return;
|
|
2449
|
+
const pos = this.#lastPointerPosition;
|
|
2450
|
+
v$2.classList.remove(`hidden`);
|
|
2451
|
+
const offset = 10;
|
|
2452
|
+
v$2.innerHTML = innerHtml;
|
|
2453
|
+
if (pos) {
|
|
2454
|
+
v$2.style.left = `${pos.screenX + offset}px`;
|
|
2455
|
+
v$2.style.top = `${pos.screenY + offset}px`;
|
|
2456
|
+
}
|
|
2310
2457
|
}
|
|
2311
2458
|
#setupCanvas() {
|
|
2312
2459
|
if (this.#canvas !== void 0) return this.#canvas;
|
|
@@ -2326,48 +2473,46 @@ let PlotElement = class PlotElement$1 extends i {
|
|
|
2326
2473
|
if (!c$6) return;
|
|
2327
2474
|
const entry = event[0];
|
|
2328
2475
|
c$6.setLogicalSize(entry.contentRect);
|
|
2476
|
+
if (this.#hasDirty()) this.draw();
|
|
2329
2477
|
});
|
|
2330
2478
|
ro.observe(this);
|
|
2331
2479
|
this.updateColours();
|
|
2332
2480
|
}
|
|
2481
|
+
#hasDirty() {
|
|
2482
|
+
for (const s$5 of this.series.values()) if (s$5.isDirty) return true;
|
|
2483
|
+
return false;
|
|
2484
|
+
}
|
|
2333
2485
|
updateColours() {
|
|
2334
2486
|
this.#legendColour = getCssVariable(`legend-fg`, `black`);
|
|
2335
2487
|
}
|
|
2336
|
-
|
|
2337
|
-
if (typeof value !== "number") throw new TypeError(`Can only add numbers. Got: ${typeof value}`);
|
|
2338
|
-
let s$5 = this.#series.get(seriesName.toLowerCase());
|
|
2339
|
-
if (s$5 === void 0) {
|
|
2340
|
-
s$5 = new PlotSeries(seriesName, this.colourGenerator(seriesName), this);
|
|
2341
|
-
this.#series.set(seriesName.toLowerCase(), s$5);
|
|
2342
|
-
}
|
|
2343
|
-
s$5.push(value);
|
|
2344
|
-
if (!this.manualDraw && !skipDrawing) this.draw();
|
|
2345
|
-
return s$5;
|
|
2346
|
-
}
|
|
2347
|
-
plotSeries(values, seriesName = ``, skipDrawing = false) {
|
|
2488
|
+
setRawValues(values, seriesName, automaticallyDraw) {
|
|
2348
2489
|
if (!Array.isArray(values)) throw new TypeError(`Param 'values' is not an array`);
|
|
2349
|
-
let s$5 = this
|
|
2350
|
-
|
|
2351
|
-
s$5 = new PlotSeries(seriesName, this.colourGenerator(seriesName), this);
|
|
2352
|
-
this.#series.set(seriesName.toLowerCase(), s$5);
|
|
2353
|
-
}
|
|
2354
|
-
s$5.setValues(values);
|
|
2355
|
-
if (!this.manualDraw && !skipDrawing) this.draw();
|
|
2490
|
+
let s$5 = this.getOrCreateSeries(seriesName);
|
|
2491
|
+
s$5.setRawValues(values, automaticallyDraw);
|
|
2356
2492
|
return s$5;
|
|
2357
2493
|
}
|
|
2358
2494
|
/**
|
|
2359
|
-
*
|
|
2495
|
+
* Treats each property of an object as the series name
|
|
2360
2496
|
* @param value
|
|
2497
|
+
* @param automaticallyDraw
|
|
2361
2498
|
*/
|
|
2362
|
-
|
|
2363
|
-
for (const p$3 of Pathed.getPathsAndData(value, true))
|
|
2364
|
-
|
|
2499
|
+
appendObjectBySeries(value, automaticallyDraw) {
|
|
2500
|
+
for (const p$3 of Pathed.getPathsAndData(value, true)) {
|
|
2501
|
+
const v$2 = p$3.value;
|
|
2502
|
+
if (typeof v$2 === `number`) this.appendRawValues(v$2, p$3.path, false);
|
|
2503
|
+
}
|
|
2504
|
+
if (automaticallyDraw) this.draw();
|
|
2365
2505
|
}
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2506
|
+
appendRawValues(values, seriesName, automaticallyDraw) {
|
|
2507
|
+
if (!Array.isArray(values)) values = [values];
|
|
2508
|
+
let s$5 = this.getOrCreateSeries(seriesName);
|
|
2509
|
+
for (const v$2 of values) s$5.pushValue(v$2, false);
|
|
2510
|
+
if (automaticallyDraw) this.draw();
|
|
2370
2511
|
}
|
|
2512
|
+
/**
|
|
2513
|
+
* Draw a set of key-value pairs as a batch.
|
|
2514
|
+
* @param value
|
|
2515
|
+
*/
|
|
2371
2516
|
draw() {
|
|
2372
2517
|
if (this.paused) return;
|
|
2373
2518
|
const c$6 = this.#canvas;
|
|
@@ -2384,14 +2529,12 @@ let PlotElement = class PlotElement$1 extends i {
|
|
|
2384
2529
|
width: axisYwidth,
|
|
2385
2530
|
height: plotHeight
|
|
2386
2531
|
};
|
|
2387
|
-
const
|
|
2532
|
+
const plotDataArea = this.calculatePlotDataArea(c$6, plotHeight, cy.width, padding);
|
|
2388
2533
|
const cl = {
|
|
2389
2534
|
...clLegend.bounds,
|
|
2390
2535
|
x: cy.width,
|
|
2391
|
-
y:
|
|
2536
|
+
y: plotDataArea.y + plotDataArea.height + padding
|
|
2392
2537
|
};
|
|
2393
|
-
let globalScaler;
|
|
2394
|
-
if (!Number.isNaN(this.fixedMax) && !Number.isNaN(this.fixedMin)) globalScaler = Numbers.scaler(this.fixedMin, this.fixedMax);
|
|
2395
2538
|
if (!this.hideLegend) {
|
|
2396
2539
|
ctx.save();
|
|
2397
2540
|
ctx.translate(cl.x + padding, cl.y + padding);
|
|
@@ -2399,19 +2542,41 @@ let PlotElement = class PlotElement$1 extends i {
|
|
|
2399
2542
|
ctx.restore();
|
|
2400
2543
|
}
|
|
2401
2544
|
ctx.save();
|
|
2402
|
-
ctx.translate(
|
|
2545
|
+
ctx.translate(plotDataArea.x + padding, plotDataArea.y + padding);
|
|
2546
|
+
if (this.plotAreaFormat.fill.type === `solid`) {
|
|
2547
|
+
ctx.fillStyle = Colour.resolveCss(this.plotAreaFormat.fill.colour);
|
|
2548
|
+
ctx.fillRect(0, 0, plotDataArea.width, plotDataArea.height);
|
|
2549
|
+
}
|
|
2550
|
+
if (this.plotAreaFormat.outline.type === `solid`) {
|
|
2551
|
+
ctx.strokeStyle = Colour.resolveCss(this.plotAreaFormat.outline.colour);
|
|
2552
|
+
ctx.strokeRect(0, 0, plotDataArea.width, plotDataArea.height);
|
|
2553
|
+
}
|
|
2554
|
+
const primaryAxisS = this.primaryAxis.getValueScaler(this.#series.values().filter((s$5) => s$5.onPrimaryAxis));
|
|
2555
|
+
const secondaryAxisAxisS = this.secondaryAxis.getValueScaler(this.#series.values().filter((s$5) => !s$5.onPrimaryAxis));
|
|
2556
|
+
this.#hitboxes = [];
|
|
2403
2557
|
for (const series of this.#series.values()) {
|
|
2404
|
-
const seriesScale = this.seriesRanges.get(series.name);
|
|
2405
|
-
const data = seriesScale === void 0 ? globalScaler === void 0 ? series.getScaled() : series.getScaledBy(globalScaler) : series.getScaledBy(Numbers.scaler(seriesScale[0], seriesScale[1]));
|
|
2406
|
-
const colour = Colour.toCssColour(series.colour);
|
|
2407
2558
|
switch (this.renderStyle) {
|
|
2408
2559
|
case `line`:
|
|
2409
|
-
this
|
|
2560
|
+
this.#drawLineSeries(series, d$3, series.onPrimaryAxis ? primaryAxisS : secondaryAxisAxisS, plotDataArea, {
|
|
2561
|
+
x: padding,
|
|
2562
|
+
y: padding
|
|
2563
|
+
});
|
|
2410
2564
|
break;
|
|
2411
|
-
|
|
2565
|
+
case `bar`:
|
|
2566
|
+
this.#drawBarSeries(series, d$3, series.onPrimaryAxis ? primaryAxisS : secondaryAxisAxisS, plotDataArea, {
|
|
2567
|
+
x: padding,
|
|
2568
|
+
y: padding
|
|
2569
|
+
});
|
|
2570
|
+
break;
|
|
2571
|
+
default: this.#drawDotSeries(series, d$3, series.onPrimaryAxis ? primaryAxisS : secondaryAxisAxisS, plotDataArea, {
|
|
2572
|
+
x: padding,
|
|
2573
|
+
y: padding
|
|
2574
|
+
});
|
|
2412
2575
|
}
|
|
2576
|
+
series.isDirty = false;
|
|
2413
2577
|
}
|
|
2414
2578
|
ctx.restore();
|
|
2579
|
+
this.#updateToolTip();
|
|
2415
2580
|
}
|
|
2416
2581
|
drawLegend(cl, d$3) {
|
|
2417
2582
|
const textColour = this.#legendColour;
|
|
@@ -2421,7 +2586,9 @@ let PlotElement = class PlotElement$1 extends i {
|
|
|
2421
2586
|
const swatchSize = 10;
|
|
2422
2587
|
const ctx = d$3.ctx;
|
|
2423
2588
|
for (const series of this.#series.values()) {
|
|
2424
|
-
|
|
2589
|
+
const f$4 = series.getFormatting();
|
|
2590
|
+
const colour = f$4.fill.type === `solid` ? f$4.fill.colour : `transparent`;
|
|
2591
|
+
ctx.fillStyle = Colour.toCssColour(colour);
|
|
2425
2592
|
ctx.fillRect(x$1, y$2, swatchSize, swatchSize);
|
|
2426
2593
|
ctx.fillStyle = textColour;
|
|
2427
2594
|
x$1 += swatchSize + padding;
|
|
@@ -2435,60 +2602,161 @@ let PlotElement = class PlotElement$1 extends i {
|
|
|
2435
2602
|
}
|
|
2436
2603
|
}
|
|
2437
2604
|
}
|
|
2438
|
-
drawLineSeries(
|
|
2439
|
-
const
|
|
2605
|
+
#drawLineSeries(series, d$3, scaler, plotDataArea, plotDataAreaOffset) {
|
|
2606
|
+
const formatting = series.getFormatting();
|
|
2607
|
+
const lineFormatting = formatting.line;
|
|
2608
|
+
const widthPerValue = plotDataArea.width / series.length;
|
|
2609
|
+
const xOffset = widthPerValue / 2;
|
|
2610
|
+
const lineThickness = lineFormatting.width;
|
|
2611
|
+
const lineThicknessHalf = lineThickness / 2;
|
|
2612
|
+
const h$5 = plotDataArea.height;
|
|
2440
2613
|
let x$1 = 0;
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
x$1 +=
|
|
2614
|
+
const dotsToDraw = [...series.getValuesForColumn(0)].map((d$4) => {
|
|
2615
|
+
const [value, index] = d$4;
|
|
2616
|
+
x$1 += widthPerValue;
|
|
2617
|
+
const scaledValue = scaler(value);
|
|
2618
|
+
if (Number.isNaN(value)) return void 0;
|
|
2444
2619
|
return {
|
|
2445
|
-
x: x$1,
|
|
2446
|
-
y: (1 -
|
|
2447
|
-
|
|
2620
|
+
x: x$1 - xOffset,
|
|
2621
|
+
y: (1 - scaledValue) * h$5,
|
|
2622
|
+
value,
|
|
2623
|
+
index
|
|
2448
2624
|
};
|
|
2449
2625
|
});
|
|
2450
|
-
const
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2626
|
+
const filtered = dotsToDraw.filter((f$4) => f$4 !== void 0);
|
|
2627
|
+
const hitboxes = filtered.map((d$4) => ({
|
|
2628
|
+
height: lineThickness,
|
|
2629
|
+
width: widthPerValue,
|
|
2630
|
+
x: plotDataAreaOffset.x + d$4.x - lineThicknessHalf,
|
|
2631
|
+
y: plotDataAreaOffset.y + d$4.y - lineThicknessHalf,
|
|
2632
|
+
series,
|
|
2633
|
+
index: d$4.index,
|
|
2634
|
+
value: series.getValue(d$4.index)
|
|
2635
|
+
}));
|
|
2636
|
+
this.#hitboxes.push(...hitboxes);
|
|
2637
|
+
const drawOpts = {
|
|
2638
|
+
filled: false,
|
|
2639
|
+
fillStyle: `transparent`,
|
|
2640
|
+
stroked: true,
|
|
2641
|
+
strokeStyle: `black`,
|
|
2642
|
+
strokeWidth: lineFormatting.width
|
|
2643
|
+
};
|
|
2644
|
+
if (formatting.outline.type === `solid`) drawOpts.strokeStyle = formatting.outline.colour;
|
|
2645
|
+
else if (formatting.fill.type === `solid`) drawOpts.strokeStyle = formatting.fill.colour;
|
|
2646
|
+
d$3.ctx.lineWidth = lineFormatting.width;
|
|
2647
|
+
d$3.ctx.lineCap = lineFormatting.cap;
|
|
2648
|
+
d$3.ctx.lineJoin = lineFormatting.join;
|
|
2649
|
+
d$3.connectedPoints(filtered, drawOpts);
|
|
2650
|
+
}
|
|
2651
|
+
#drawDotSeries(series, d$3, scaler, plotDataArea, plotDataAreaOffset) {
|
|
2652
|
+
const formatting = series.getFormatting();
|
|
2653
|
+
const dotFormatting = formatting.dot;
|
|
2654
|
+
const widthPerValue = plotDataArea.width / series.length;
|
|
2655
|
+
const radius = dotFormatting.radius === `automatic` ? widthPerValue * .3 : dotFormatting.radius;
|
|
2656
|
+
const xOffset = widthPerValue / 2;
|
|
2657
|
+
const h$5 = plotDataArea.height;
|
|
2461
2658
|
let x$1 = 0;
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
x$1 +=
|
|
2659
|
+
const dotsToDraw = [...series.getValuesForColumn(0)].map((d$4) => {
|
|
2660
|
+
const [value, index] = d$4;
|
|
2661
|
+
x$1 += widthPerValue;
|
|
2662
|
+
const scaledValue = scaler(value);
|
|
2663
|
+
if (Number.isNaN(value)) return void 0;
|
|
2465
2664
|
return {
|
|
2466
|
-
x: x$1,
|
|
2467
|
-
y: (1 -
|
|
2468
|
-
radius
|
|
2665
|
+
x: x$1 - xOffset,
|
|
2666
|
+
y: (1 - scaledValue) * h$5,
|
|
2667
|
+
radius,
|
|
2668
|
+
value,
|
|
2669
|
+
index
|
|
2469
2670
|
};
|
|
2470
2671
|
});
|
|
2471
|
-
const
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2672
|
+
const filtered = dotsToDraw.filter((f$4) => f$4 !== void 0);
|
|
2673
|
+
const hitboxes = filtered.map((d$4) => ({
|
|
2674
|
+
height: d$4.radius * 2,
|
|
2675
|
+
width: d$4.radius * 2,
|
|
2676
|
+
x: plotDataAreaOffset.x + d$4.x - d$4.radius,
|
|
2677
|
+
y: plotDataAreaOffset.y + d$4.y - d$4.radius,
|
|
2678
|
+
series,
|
|
2679
|
+
index: d$4.index,
|
|
2680
|
+
value: series.getValue(d$4.index)
|
|
2681
|
+
}));
|
|
2682
|
+
this.#hitboxes.push(...hitboxes);
|
|
2683
|
+
const drawOpts = {
|
|
2684
|
+
filled: false,
|
|
2685
|
+
fillStyle: `transparent`,
|
|
2686
|
+
stroked: false,
|
|
2687
|
+
strokeStyle: `transparent`
|
|
2688
|
+
};
|
|
2689
|
+
if (formatting.fill.type === `solid`) {
|
|
2690
|
+
drawOpts.filled = true;
|
|
2691
|
+
drawOpts.fillStyle = formatting.fill.colour;
|
|
2692
|
+
}
|
|
2693
|
+
if (formatting.outline.type === `solid`) {
|
|
2694
|
+
drawOpts.stroked = true;
|
|
2695
|
+
drawOpts.strokeStyle = formatting.outline.colour;
|
|
2696
|
+
}
|
|
2697
|
+
d$3.dot(filtered, drawOpts);
|
|
2698
|
+
}
|
|
2699
|
+
#drawBarSeries(series, d$3, scaler, plotDataArea, plotDataAreaOffset) {
|
|
2700
|
+
const formatting = series.getFormatting();
|
|
2701
|
+
const barFormatting = formatting.bar;
|
|
2702
|
+
const widthPerValue = plotDataArea.width / series.length;
|
|
2703
|
+
const rectWidth = widthPerValue - barFormatting.gapWidth / 2;
|
|
2704
|
+
const xOffset = widthPerValue / 2;
|
|
2705
|
+
const h$5 = plotDataArea.height;
|
|
2706
|
+
let x$1 = 0;
|
|
2707
|
+
const rectsToDraw = [...series.getValuesForColumn(0)].map((d$4) => {
|
|
2708
|
+
const [value, index] = d$4;
|
|
2709
|
+
x$1 += widthPerValue;
|
|
2710
|
+
const scaledValue = scaler(value);
|
|
2711
|
+
if (Number.isNaN(value)) return void 0;
|
|
2712
|
+
const barHeight = scaledValue * h$5;
|
|
2713
|
+
return {
|
|
2714
|
+
x: x$1 - xOffset,
|
|
2715
|
+
y: h$5 - barHeight,
|
|
2716
|
+
width: rectWidth,
|
|
2717
|
+
height: barHeight,
|
|
2718
|
+
value,
|
|
2719
|
+
index
|
|
2720
|
+
};
|
|
2478
2721
|
});
|
|
2722
|
+
const filtered = rectsToDraw.filter((f$4) => f$4 !== void 0);
|
|
2723
|
+
const hitboxes = filtered.map((d$4) => ({
|
|
2724
|
+
height: Math.max(5, d$4.height),
|
|
2725
|
+
width: d$4.width,
|
|
2726
|
+
x: plotDataAreaOffset.x + d$4.x,
|
|
2727
|
+
y: plotDataAreaOffset.y + d$4.y,
|
|
2728
|
+
series,
|
|
2729
|
+
index: d$4.index,
|
|
2730
|
+
value: series.getValue(d$4.index)
|
|
2731
|
+
}));
|
|
2732
|
+
this.#hitboxes.push(...hitboxes);
|
|
2733
|
+
const drawOpts = {
|
|
2734
|
+
filled: false,
|
|
2735
|
+
fillStyle: `transparent`,
|
|
2736
|
+
stroked: false,
|
|
2737
|
+
strokeStyle: `transparent`
|
|
2738
|
+
};
|
|
2739
|
+
if (formatting.fill.type === `solid`) {
|
|
2740
|
+
drawOpts.filled = true;
|
|
2741
|
+
drawOpts.fillStyle = formatting.fill.colour;
|
|
2742
|
+
}
|
|
2743
|
+
if (formatting.outline.type === `solid`) {
|
|
2744
|
+
drawOpts.stroked = true;
|
|
2745
|
+
drawOpts.strokeStyle = formatting.outline.colour;
|
|
2746
|
+
}
|
|
2747
|
+
d$3.rect(filtered, drawOpts);
|
|
2479
2748
|
}
|
|
2480
|
-
|
|
2749
|
+
calculatePlotDataArea(c$6, plotHeight, axisYwidth, padding) {
|
|
2481
2750
|
return {
|
|
2482
2751
|
x: axisYwidth,
|
|
2483
2752
|
y: 0,
|
|
2484
|
-
width: c$6.width - axisYwidth - padding,
|
|
2485
|
-
height: plotHeight - padding
|
|
2753
|
+
width: c$6.width - axisYwidth - padding - padding,
|
|
2754
|
+
height: plotHeight - padding
|
|
2486
2755
|
};
|
|
2487
2756
|
}
|
|
2488
2757
|
computeAxisYWidth(_c) {
|
|
2489
2758
|
return 0;
|
|
2490
2759
|
}
|
|
2491
|
-
#swatchSize = 10;
|
|
2492
2760
|
computeLegend(c$6, maxWidth, padding) {
|
|
2493
2761
|
if (this.hideLegend) return {
|
|
2494
2762
|
bounds: {
|
|
@@ -2537,105 +2805,158 @@ let PlotElement = class PlotElement$1 extends i {
|
|
|
2537
2805
|
parts
|
|
2538
2806
|
};
|
|
2539
2807
|
}
|
|
2808
|
+
getOrCreateSeries(name) {
|
|
2809
|
+
let s$5 = this.#series.get(name.toLowerCase());
|
|
2810
|
+
if (s$5) return s$5;
|
|
2811
|
+
s$5 = new PlotSeries(name, this);
|
|
2812
|
+
const seriesDefault = {
|
|
2813
|
+
limit: NaN,
|
|
2814
|
+
...this.seriesDefault
|
|
2815
|
+
};
|
|
2816
|
+
if (!Number.isNaN(seriesDefault.limit)) s$5.setCapacityLimit(seriesDefault.limit);
|
|
2817
|
+
this.#series.set(name.toLowerCase(), s$5);
|
|
2818
|
+
return s$5;
|
|
2819
|
+
}
|
|
2540
2820
|
getSeries(name) {
|
|
2541
2821
|
return this.#series.get(name);
|
|
2542
2822
|
}
|
|
2823
|
+
render() {
|
|
2824
|
+
return x`<canvas @pointerleave="${this.#onPointerLeave}" @pointermove="${this.#onPointerMove}" ${n$1(this.canvasEl)}></canvas><div class="hidden" ${n$1(this.tooltipEl)} id="tooltip">Tooltip!</div>`;
|
|
2825
|
+
}
|
|
2543
2826
|
static styles = i$1`
|
|
2544
2827
|
:host {
|
|
2545
2828
|
width: 100%;
|
|
2546
2829
|
height: 100%;
|
|
2547
2830
|
display: block;
|
|
2548
2831
|
}
|
|
2832
|
+
|
|
2833
|
+
#tooltip {
|
|
2834
|
+
border: 1px solid black;
|
|
2835
|
+
background: white;
|
|
2836
|
+
color: black;
|
|
2837
|
+
padding: 0.3em;
|
|
2838
|
+
font-size: 10px;
|
|
2839
|
+
display: inline-block;
|
|
2840
|
+
position: absolute;
|
|
2841
|
+
left: 0px;
|
|
2842
|
+
top: 0px;
|
|
2843
|
+
opacity:1;
|
|
2844
|
+
pointer-events: none;
|
|
2845
|
+
}
|
|
2846
|
+
|
|
2847
|
+
.hidden {
|
|
2848
|
+
opacity:0 !important;
|
|
2849
|
+
}
|
|
2549
2850
|
`;
|
|
2550
2851
|
};
|
|
2551
|
-
__decorate([n({
|
|
2552
|
-
attribute: `streaming`,
|
|
2553
|
-
type: Boolean
|
|
2554
|
-
})], PlotElement.prototype, "streaming", void 0);
|
|
2555
2852
|
__decorate([n({
|
|
2556
2853
|
attribute: `hide-legend`,
|
|
2557
2854
|
type: Boolean
|
|
2558
2855
|
})], PlotElement.prototype, "hideLegend", void 0);
|
|
2559
|
-
__decorate([n({
|
|
2560
|
-
attribute: `max-length`,
|
|
2561
|
-
type: Number
|
|
2562
|
-
})], PlotElement.prototype, "maxLength", void 0);
|
|
2563
|
-
__decorate([n({
|
|
2564
|
-
attribute: `data-width`,
|
|
2565
|
-
type: Number
|
|
2566
|
-
})], PlotElement.prototype, "dataWidth", void 0);
|
|
2567
|
-
__decorate([n({
|
|
2568
|
-
attribute: `fixed-max`,
|
|
2569
|
-
type: Number
|
|
2570
|
-
})], PlotElement.prototype, "fixedMax", void 0);
|
|
2571
|
-
__decorate([n({
|
|
2572
|
-
attribute: `fixed-min`,
|
|
2573
|
-
type: Number
|
|
2574
|
-
})], PlotElement.prototype, "fixedMin", void 0);
|
|
2575
|
-
__decorate([n({
|
|
2576
|
-
attribute: `line-width`,
|
|
2577
|
-
type: Number
|
|
2578
|
-
})], PlotElement.prototype, "lineWidth", void 0);
|
|
2579
2856
|
__decorate([n({
|
|
2580
2857
|
attribute: `render`,
|
|
2581
2858
|
type: String
|
|
2582
2859
|
})], PlotElement.prototype, "renderStyle", void 0);
|
|
2583
2860
|
__decorate([n({
|
|
2584
|
-
attribute: `
|
|
2585
|
-
type:
|
|
2586
|
-
})], PlotElement.prototype, "
|
|
2861
|
+
attribute: `padding`,
|
|
2862
|
+
type: Number
|
|
2863
|
+
})], PlotElement.prototype, "padding", void 0);
|
|
2587
2864
|
PlotElement = __decorate([t(`ixfx-plot-element`)], PlotElement);
|
|
2865
|
+
const resolveFillDrawStyle = (s$5) => {
|
|
2866
|
+
if (s$5.type === `none`) return s$5;
|
|
2867
|
+
const c$6 = Colour.resolveCss(s$5.colour);
|
|
2868
|
+
return {
|
|
2869
|
+
type: `solid`,
|
|
2870
|
+
colour: c$6
|
|
2871
|
+
};
|
|
2872
|
+
};
|
|
2873
|
+
const resolveOutlineDrawStyle = (s$5) => {
|
|
2874
|
+
if (s$5.type === `none`) return s$5;
|
|
2875
|
+
const c$6 = Colour.resolveCss(s$5.colour);
|
|
2876
|
+
return {
|
|
2877
|
+
...s$5,
|
|
2878
|
+
colour: c$6
|
|
2879
|
+
};
|
|
2880
|
+
};
|
|
2588
2881
|
var PlotSeries = class {
|
|
2589
|
-
data = [];
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2882
|
+
#data = [];
|
|
2883
|
+
#capacityLimit = NaN;
|
|
2884
|
+
#dirty = false;
|
|
2885
|
+
#onPrimaryAxis = true;
|
|
2886
|
+
constructor(name, plot) {
|
|
2593
2887
|
this.name = name;
|
|
2594
|
-
this.colour = colour;
|
|
2595
2888
|
this.plot = plot;
|
|
2596
2889
|
}
|
|
2597
|
-
|
|
2598
|
-
this.
|
|
2599
|
-
this.resetScale();
|
|
2890
|
+
get length() {
|
|
2891
|
+
return this.#data.length;
|
|
2600
2892
|
}
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
let max = this.maxSeen;
|
|
2609
|
-
if (Number.isNaN(min)) min = 0;
|
|
2610
|
-
if (Number.isNaN(max)) max = 1;
|
|
2611
|
-
const s$5 = Numbers.scaler(min, max);
|
|
2612
|
-
return this.getScaledBy(s$5);
|
|
2613
|
-
}
|
|
2614
|
-
getScaledBy(scaler) {
|
|
2615
|
-
return this.data.map((v$2) => {
|
|
2616
|
-
if (typeof v$2 !== `number`) throw new Error(`Data should just be numbers. Got: ${typeof v$2}`);
|
|
2617
|
-
if (Number.isNaN(v$2)) throw new Error(`data contains NaN`);
|
|
2618
|
-
const scaled = scaler(v$2);
|
|
2619
|
-
if (Number.isNaN(scaled)) throw new Error(`NaN. v: ${v$2} scaled: ${scaled}`);
|
|
2620
|
-
return Numbers.clamp(scaled);
|
|
2621
|
-
});
|
|
2893
|
+
*getValuesForColumn(column) {
|
|
2894
|
+
let index = 0;
|
|
2895
|
+
for (const dv of this.#data) {
|
|
2896
|
+
if (dv && column in dv) yield [dv[column], index];
|
|
2897
|
+
else yield [NaN, index];
|
|
2898
|
+
index++;
|
|
2899
|
+
}
|
|
2622
2900
|
}
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
this.data.push(value);
|
|
2626
|
-
if (this.data.length > this.plot.maxLength && this.plot.streaming) this.data = this.data.slice(1);
|
|
2627
|
-
this.minSeen = Math.min(this.minSeen, value);
|
|
2628
|
-
this.maxSeen = Math.max(this.maxSeen, value);
|
|
2901
|
+
getValue(index) {
|
|
2902
|
+
return this.#data[index];
|
|
2629
2903
|
}
|
|
2630
|
-
|
|
2904
|
+
pushValue(value, automaticallyDraw) {
|
|
2905
|
+
if (!Array.isArray(value)) value = [value];
|
|
2906
|
+
if (value.length === 0) throw new Error(`Param 'value' is empty. Expected a value or array of value components`);
|
|
2907
|
+
this.#data.push(value);
|
|
2908
|
+
if (!Number.isNaN(this.#capacityLimit)) this.#data = Arrays.ensureLength(this.#data, this.#capacityLimit, `undefined`, `from-start`);
|
|
2909
|
+
this.#dirty = true;
|
|
2910
|
+
if (automaticallyDraw) this.plot.draw();
|
|
2911
|
+
}
|
|
2912
|
+
setValues(values, automaticallyDraw) {
|
|
2631
2913
|
if (!Array.isArray(values)) throw new TypeError(`Param 'values' is not an array`);
|
|
2632
|
-
this
|
|
2633
|
-
this
|
|
2634
|
-
|
|
2914
|
+
this.#data = Arrays.ensureLength(values, this.#capacityLimit, `undefined`);
|
|
2915
|
+
this.#dirty = true;
|
|
2916
|
+
if (automaticallyDraw) this.plot.draw();
|
|
2917
|
+
}
|
|
2918
|
+
humanFormatValue(value) {
|
|
2919
|
+
let v$2 = `${this.name} `;
|
|
2920
|
+
if (this.onPrimaryAxis) v$2 += this.plot.primaryAxis.humanFormatValue(value);
|
|
2921
|
+
else v$2 += this.plot.secondaryAxis.humanFormatValue(value);
|
|
2922
|
+
return v$2;
|
|
2923
|
+
}
|
|
2924
|
+
setRawValues(values, automaticallyDraw) {
|
|
2925
|
+
this.setValues(values.map((v$2) => [v$2]), automaticallyDraw);
|
|
2926
|
+
}
|
|
2927
|
+
setCapacityLimit(v$2) {
|
|
2928
|
+
if (typeof v$2 !== `number`) throw new TypeError(`Expect type number. Got: ${typeof v$2}`);
|
|
2929
|
+
if (!Number.isFinite(v$2)) throw new TypeError(`Param 'v' is not finite`);
|
|
2930
|
+
if (Number.isNaN(v$2)) throw new TypeError(`Param 'v' is NaN`);
|
|
2931
|
+
this.#capacityLimit = v$2;
|
|
2932
|
+
this.#data = Arrays.ensureLength(this.#data, this.#capacityLimit, `undefined`);
|
|
2933
|
+
}
|
|
2934
|
+
unsetCapacityLimit() {
|
|
2935
|
+
this.#capacityLimit = NaN;
|
|
2635
2936
|
}
|
|
2636
|
-
|
|
2637
|
-
this.
|
|
2638
|
-
|
|
2937
|
+
setFormatting(formatting) {
|
|
2938
|
+
this.plot.setSeriesFormatting(this.name, formatting);
|
|
2939
|
+
}
|
|
2940
|
+
getFormatting() {
|
|
2941
|
+
return this.plot.getSeriesFormatting(this.name, true);
|
|
2942
|
+
}
|
|
2943
|
+
get isDirty() {
|
|
2944
|
+
return this.#dirty;
|
|
2945
|
+
}
|
|
2946
|
+
set isDirty(value) {
|
|
2947
|
+
this.#dirty = value;
|
|
2948
|
+
}
|
|
2949
|
+
get onPrimaryAxis() {
|
|
2950
|
+
return this.#onPrimaryAxis;
|
|
2951
|
+
}
|
|
2952
|
+
set onPrimaryAxis(value) {
|
|
2953
|
+
if (value === this.#onPrimaryAxis) return;
|
|
2954
|
+
this.#onPrimaryAxis = value;
|
|
2955
|
+
this.#dirty = true;
|
|
2956
|
+
}
|
|
2957
|
+
clear() {
|
|
2958
|
+
this.#data = [];
|
|
2959
|
+
this.#dirty = true;
|
|
2639
2960
|
}
|
|
2640
2961
|
};
|
|
2641
2962
|
|
|
@@ -3013,5 +3334,5 @@ const init = () => {
|
|
|
3013
3334
|
};
|
|
3014
3335
|
|
|
3015
3336
|
//#endregion
|
|
3016
|
-
export { CrumbNavElement, CrumbNavigationElement, DialElement, FrequencyHistogramPlot, HistogramVis, PlotElement, PlotSeries, SelectHorizontalElement, SplitLayoutElement, TabListElement, TabListItemElement, TabPanelElement, TabPanelsElement, init };
|
|
3337
|
+
export { CrumbNavElement, CrumbNavigationElement, DialElement, FrequencyHistogramPlot, HistogramVis, PlotAxis, PlotElement, PlotSeries, SelectHorizontalElement, SplitLayoutElement, TabListElement, TabListItemElement, TabPanelElement, TabPanelsElement, init };
|
|
3017
3338
|
//# sourceMappingURL=index.js.map
|