@akcelik/strct 0.26.0 → 0.29.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/fesm2022/akcelik-strct.mjs +585 -100
- package/fesm2022/akcelik-strct.mjs.map +1 -1
- package/package.json +1 -1
- package/types/akcelik-strct.d.ts +119 -15
|
@@ -641,7 +641,7 @@ class StrctIcon {
|
|
|
641
641
|
</svg>
|
|
642
642
|
}
|
|
643
643
|
</span>
|
|
644
|
-
}`, isInline: true, styles: [".strct-icon{position:relative;display:inline-flex;align-items:center;justify-content:center;line-height:0}.strct-icon__raw{display:inline-flex}.strct-icon__raw>svg{width:100%;height:100%;display:block}.strct-icon__badge{position:absolute;right:-3px;bottom:-3px;width:50%;height:50%;min-width:8px;min-height:8px;max-width:12px;max-height:12px;border-radius:50%;box-shadow:0 0 0 1.5px var(--bg-1)}.strct-icon__badge--success,.strct-icon__badge--critical,.strct-icon__badge--info,.strct-icon__badge--off{display:flex;align-items:center;justify-content:center;font-size:clamp(6px,68%,10px);font-weight:800;line-height:1;color:var(--inv)}.strct-icon__badge--success{background:var(--success)}.strct-icon__badge--success:before{content:\"\\2713\"}.strct-icon__badge--warning{background:var(--warning);border-radius:1px;clip-path:polygon(50% 10%,92% 90%,8% 90%);box-shadow:none;filter:drop-shadow(0 0 1.5px var(--bg-1));right:-2px;bottom:-2px;width:60%;height:60%;min-width:11px;min-height:11px;max-width:18px;max-height:18px;display:flex;align-items:center;justify-content:center;font-size:clamp(6px,70%,10px);font-weight:800;color:var(--inv);line-height:1}.strct-icon__badge--warning:before{content:\"!\"}.strct-icon__badge--critical{background:var(--critical)}.strct-icon__badge--critical:before{content:\"\\d7\"}.strct-icon__badge--off{background:var(--t3)}.strct-icon__badge--off:before{content:\"
|
|
644
|
+
}`, isInline: true, styles: [".strct-icon{position:relative;display:inline-flex;align-items:center;justify-content:center;line-height:0}.strct-icon__raw{display:inline-flex}.strct-icon__raw>svg{width:100%;height:100%;display:block}.strct-icon__badge{position:absolute;right:-3px;bottom:-3px;width:50%;height:50%;min-width:8px;min-height:8px;max-width:12px;max-height:12px;border-radius:50%;box-shadow:0 0 0 1.5px var(--bg-1)}.strct-icon__badge--success,.strct-icon__badge--critical,.strct-icon__badge--info,.strct-icon__badge--off,.strct-icon__badge--paused,.strct-icon__badge--running{display:flex;align-items:center;justify-content:center;font-size:clamp(6px,68%,10px);font-weight:800;line-height:1;color:var(--inv)}.strct-icon__badge--success{background:var(--success)}.strct-icon__badge--success:before{content:\"\\2713\"}.strct-icon__badge--warning{background:var(--warning);border-radius:1px;clip-path:polygon(50% 10%,92% 90%,8% 90%);box-shadow:none;filter:drop-shadow(0 0 1.5px var(--bg-1));right:-2px;bottom:-2px;width:60%;height:60%;min-width:11px;min-height:11px;max-width:18px;max-height:18px;display:flex;align-items:center;justify-content:center;font-size:clamp(6px,70%,10px);font-weight:800;color:var(--inv);line-height:1}.strct-icon__badge--warning:before{content:\"!\"}.strct-icon__badge--critical{background:var(--critical);border-radius:1px;clip-path:polygon(50% 0%,100% 50%,50% 100%,0% 50%);box-shadow:none;filter:drop-shadow(0 0 1.5px var(--bg-1));width:58%;height:58%;min-width:10px;min-height:10px;max-width:15px;max-height:15px;font-size:clamp(6px,56%,9px)}.strct-icon__badge--critical:before{content:\"\\d7\"}.strct-icon__badge--running{background:var(--success)}.strct-icon__badge--running:before{content:\"\";width:46%;height:46%;min-width:4px;min-height:4px;background:var(--inv);clip-path:polygon(15% 2%,100% 50%,15% 98%);transform:translate(9%)}.strct-icon__badge--paused{background:var(--warning)}.strct-icon__badge--paused:before{content:\"\";width:1.6px;height:42%;min-height:4px;background:var(--inv);box-shadow:2.6px 0 0 var(--inv);transform:translate(-1.3px)}.strct-icon__badge--off{background:var(--t3)}.strct-icon__badge--off:before{content:\"\";width:40%;height:40%;min-width:3.5px;min-height:3.5px;background:var(--inv);border-radius:1px}.strct-icon__badge--info{background:var(--acc)}.strct-icon__badge--info:before{content:\"i\"}.strct-icon__badge--maintenance{background:var(--warning);right:-2px;bottom:-2px;width:58%;height:58%;min-width:10px;min-height:10px;max-width:16px;max-height:16px;display:flex;align-items:center;justify-content:center;padding:1px;box-shadow:0 0 0 1.5px var(--bg-1)}.strct-icon__badge--maintenance svg{width:84%;height:84%;color:var(--inv)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
645
645
|
}
|
|
646
646
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctIcon, decorators: [{
|
|
647
647
|
type: Component,
|
|
@@ -685,7 +685,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
685
685
|
</svg>
|
|
686
686
|
}
|
|
687
687
|
</span>
|
|
688
|
-
}`, host: { class: 'strct-icon' }, styles: [".strct-icon{position:relative;display:inline-flex;align-items:center;justify-content:center;line-height:0}.strct-icon__raw{display:inline-flex}.strct-icon__raw>svg{width:100%;height:100%;display:block}.strct-icon__badge{position:absolute;right:-3px;bottom:-3px;width:50%;height:50%;min-width:8px;min-height:8px;max-width:12px;max-height:12px;border-radius:50%;box-shadow:0 0 0 1.5px var(--bg-1)}.strct-icon__badge--success,.strct-icon__badge--critical,.strct-icon__badge--info,.strct-icon__badge--off{display:flex;align-items:center;justify-content:center;font-size:clamp(6px,68%,10px);font-weight:800;line-height:1;color:var(--inv)}.strct-icon__badge--success{background:var(--success)}.strct-icon__badge--success:before{content:\"\\2713\"}.strct-icon__badge--warning{background:var(--warning);border-radius:1px;clip-path:polygon(50% 10%,92% 90%,8% 90%);box-shadow:none;filter:drop-shadow(0 0 1.5px var(--bg-1));right:-2px;bottom:-2px;width:60%;height:60%;min-width:11px;min-height:11px;max-width:18px;max-height:18px;display:flex;align-items:center;justify-content:center;font-size:clamp(6px,70%,10px);font-weight:800;color:var(--inv);line-height:1}.strct-icon__badge--warning:before{content:\"!\"}.strct-icon__badge--critical{background:var(--critical)}.strct-icon__badge--critical:before{content:\"\\d7\"}.strct-icon__badge--off{background:var(--t3)}.strct-icon__badge--off:before{content:\"
|
|
688
|
+
}`, host: { class: 'strct-icon' }, styles: [".strct-icon{position:relative;display:inline-flex;align-items:center;justify-content:center;line-height:0}.strct-icon__raw{display:inline-flex}.strct-icon__raw>svg{width:100%;height:100%;display:block}.strct-icon__badge{position:absolute;right:-3px;bottom:-3px;width:50%;height:50%;min-width:8px;min-height:8px;max-width:12px;max-height:12px;border-radius:50%;box-shadow:0 0 0 1.5px var(--bg-1)}.strct-icon__badge--success,.strct-icon__badge--critical,.strct-icon__badge--info,.strct-icon__badge--off,.strct-icon__badge--paused,.strct-icon__badge--running{display:flex;align-items:center;justify-content:center;font-size:clamp(6px,68%,10px);font-weight:800;line-height:1;color:var(--inv)}.strct-icon__badge--success{background:var(--success)}.strct-icon__badge--success:before{content:\"\\2713\"}.strct-icon__badge--warning{background:var(--warning);border-radius:1px;clip-path:polygon(50% 10%,92% 90%,8% 90%);box-shadow:none;filter:drop-shadow(0 0 1.5px var(--bg-1));right:-2px;bottom:-2px;width:60%;height:60%;min-width:11px;min-height:11px;max-width:18px;max-height:18px;display:flex;align-items:center;justify-content:center;font-size:clamp(6px,70%,10px);font-weight:800;color:var(--inv);line-height:1}.strct-icon__badge--warning:before{content:\"!\"}.strct-icon__badge--critical{background:var(--critical);border-radius:1px;clip-path:polygon(50% 0%,100% 50%,50% 100%,0% 50%);box-shadow:none;filter:drop-shadow(0 0 1.5px var(--bg-1));width:58%;height:58%;min-width:10px;min-height:10px;max-width:15px;max-height:15px;font-size:clamp(6px,56%,9px)}.strct-icon__badge--critical:before{content:\"\\d7\"}.strct-icon__badge--running{background:var(--success)}.strct-icon__badge--running:before{content:\"\";width:46%;height:46%;min-width:4px;min-height:4px;background:var(--inv);clip-path:polygon(15% 2%,100% 50%,15% 98%);transform:translate(9%)}.strct-icon__badge--paused{background:var(--warning)}.strct-icon__badge--paused:before{content:\"\";width:1.6px;height:42%;min-height:4px;background:var(--inv);box-shadow:2.6px 0 0 var(--inv);transform:translate(-1.3px)}.strct-icon__badge--off{background:var(--t3)}.strct-icon__badge--off:before{content:\"\";width:40%;height:40%;min-width:3.5px;min-height:3.5px;background:var(--inv);border-radius:1px}.strct-icon__badge--info{background:var(--acc)}.strct-icon__badge--info:before{content:\"i\"}.strct-icon__badge--maintenance{background:var(--warning);right:-2px;bottom:-2px;width:58%;height:58%;min-width:10px;min-height:10px;max-width:16px;max-height:16px;display:flex;align-items:center;justify-content:center;padding:1px;box-shadow:0 0 0 1.5px var(--bg-1)}.strct-icon__badge--maintenance svg{width:84%;height:84%;color:var(--inv)}\n"] }]
|
|
689
689
|
}], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: true }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], strokeWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "strokeWidth", required: false }] }], badge: [{ type: i0.Input, args: [{ isSignal: true, alias: "badge", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }] } });
|
|
690
690
|
|
|
691
691
|
/** Palette dots + light/dark pill, wired to {@link StrctThemeService}. */
|
|
@@ -8330,6 +8330,64 @@ function smoothPath(p) {
|
|
|
8330
8330
|
function pathFor(pts, curve) {
|
|
8331
8331
|
return curve === 'linear' ? linearPath(pts) : curve === 'step' ? stepPath(pts) : smoothPath(pts);
|
|
8332
8332
|
}
|
|
8333
|
+
/** A real value — `null` and `NaN` both mark a data gap. */
|
|
8334
|
+
function isVal(v) {
|
|
8335
|
+
return v != null && !Number.isNaN(v);
|
|
8336
|
+
}
|
|
8337
|
+
/** Split a nullable point array into contiguous non-gap segments. */
|
|
8338
|
+
function segs(pts) {
|
|
8339
|
+
const out = [];
|
|
8340
|
+
let cur = [];
|
|
8341
|
+
for (const p of pts) {
|
|
8342
|
+
if (p)
|
|
8343
|
+
cur.push(p);
|
|
8344
|
+
else if (cur.length) {
|
|
8345
|
+
out.push(cur);
|
|
8346
|
+
cur = [];
|
|
8347
|
+
}
|
|
8348
|
+
}
|
|
8349
|
+
if (cur.length)
|
|
8350
|
+
out.push(cur);
|
|
8351
|
+
return out;
|
|
8352
|
+
}
|
|
8353
|
+
/** Line path that breaks at gaps (one sub-path per segment). */
|
|
8354
|
+
function pathForSegs(pts, curve) {
|
|
8355
|
+
return segs(pts)
|
|
8356
|
+
.map((s) => pathFor(s, curve))
|
|
8357
|
+
.join('');
|
|
8358
|
+
}
|
|
8359
|
+
/** Area path per segment — the fill drops to the baseline at gap edges, never across. */
|
|
8360
|
+
function areaForSegs(pts, curve, base) {
|
|
8361
|
+
return segs(pts)
|
|
8362
|
+
.map((s) => `${pathFor(s, curve)}L${round$1(s[s.length - 1].x)},${round$1(base)}L${round$1(s[0].x)},${round$1(base)}Z`)
|
|
8363
|
+
.join('');
|
|
8364
|
+
}
|
|
8365
|
+
/** Closed band between per-point upper and lower bounds (gap-aware). */
|
|
8366
|
+
function bandPath(upper, lower, curve) {
|
|
8367
|
+
let out = '';
|
|
8368
|
+
let u = [];
|
|
8369
|
+
let l = [];
|
|
8370
|
+
const flush = () => {
|
|
8371
|
+
if (u.length > 1) {
|
|
8372
|
+
const back = pathFor([...l].reverse(), curve).replace(/^M/, 'L');
|
|
8373
|
+
out += pathFor(u, curve) + back + 'Z';
|
|
8374
|
+
}
|
|
8375
|
+
u = [];
|
|
8376
|
+
l = [];
|
|
8377
|
+
};
|
|
8378
|
+
for (let i = 0; i < upper.length; i++) {
|
|
8379
|
+
const up = upper[i];
|
|
8380
|
+
const lo = lower[i];
|
|
8381
|
+
if (up && lo) {
|
|
8382
|
+
u.push(up);
|
|
8383
|
+
l.push(lo);
|
|
8384
|
+
}
|
|
8385
|
+
else
|
|
8386
|
+
flush();
|
|
8387
|
+
}
|
|
8388
|
+
flush();
|
|
8389
|
+
return out;
|
|
8390
|
+
}
|
|
8333
8391
|
/**
|
|
8334
8392
|
* Single- or multi-series chart (line / area / bar). Dependency-free SVG,
|
|
8335
8393
|
* token-coloured.
|
|
@@ -8346,7 +8404,7 @@ function pathFor(pts, curve) {
|
|
|
8346
8404
|
* <strct-chart [series]="[{data:inArr,label:'In'},{data:outArr,label:'Out'}]" legend />
|
|
8347
8405
|
*/
|
|
8348
8406
|
class StrctChart {
|
|
8349
|
-
/** Single-series data (or use `series`). */
|
|
8407
|
+
/** Single-series data (or use `series`). `null` / `NaN` marks a gap — the line breaks. */
|
|
8350
8408
|
data = input([], ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
|
|
8351
8409
|
/** Multiple series; when set it takes precedence over `data`. */
|
|
8352
8410
|
series = input(null, ...(ngDevMode ? [{ debugName: "series" }] : /* istanbul ignore next */ []));
|
|
@@ -8404,6 +8462,28 @@ class StrctChart {
|
|
|
8404
8462
|
* `[valueFormat]="v => v.toFixed(3) + ' %'"`. When null, the raw value is shown.
|
|
8405
8463
|
*/
|
|
8406
8464
|
valueFormat = input(null, ...(ngDevMode ? [{ debugName: "valueFormat" }] : /* istanbul ignore next */ []));
|
|
8465
|
+
/** Vertical event / annotation markers ("alarm raised", "deploy", …). */
|
|
8466
|
+
annotations = input([], ...(ngDevMode ? [{ debugName: "annotations" }] : /* istanbul ignore next */ []));
|
|
8467
|
+
/**
|
|
8468
|
+
* Drive the crosshair externally (e.g. mirror a sibling chart's hover for a
|
|
8469
|
+
* vCenter-style synced dashboard). A local pointer wins while over this chart.
|
|
8470
|
+
*/
|
|
8471
|
+
activeIndex = input(null, ...(ngDevMode ? [{ debugName: "activeIndex" }] : /* istanbul ignore next */ []));
|
|
8472
|
+
/** Drag-select a range; the selection is emitted through `brushChange`. */
|
|
8473
|
+
brush = input(false, { ...(ngDevMode ? { debugName: "brush" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
8474
|
+
/**
|
|
8475
|
+
* Drag-select **zooms into** the selected range (implies `brush`).
|
|
8476
|
+
* Double-click, Escape or the reset chip zooms back out.
|
|
8477
|
+
*/
|
|
8478
|
+
zoom = input(false, { ...(ngDevMode ? { debugName: "zoom" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
8479
|
+
/** Tooltip text for a gap (null) point. */
|
|
8480
|
+
gapText = input('no data', ...(ngDevMode ? [{ debugName: "gapText" }] : /* istanbul ignore next */ []));
|
|
8481
|
+
/** Accessible label of the reset-zoom chip (localizable). */
|
|
8482
|
+
resetLabel = input('Reset zoom', ...(ngDevMode ? [{ debugName: "resetLabel" }] : /* istanbul ignore next */ []));
|
|
8483
|
+
/** Emits the hovered point index (or null on leave) — wire cross-chart sync with it. */
|
|
8484
|
+
hoverIndex = output();
|
|
8485
|
+
/** Emits the brushed [startIndex, endIndex] (inclusive), or null when cleared. */
|
|
8486
|
+
brushChange = output();
|
|
8407
8487
|
pad = PAD;
|
|
8408
8488
|
color = computed(() => COLOR$1[this.status()], ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
|
|
8409
8489
|
showArea = computed(() => this.area() || this.type() === 'area', ...(ngDevMode ? [{ debugName: "showArea" }] : /* istanbul ignore next */ []));
|
|
@@ -8420,8 +8500,22 @@ class StrctChart {
|
|
|
8420
8500
|
firstData = true;
|
|
8421
8501
|
/** Reactive OS motion preference (tracks live changes, not just first load). */
|
|
8422
8502
|
reduceMotion = signal(typeof matchMedia !== 'undefined' && matchMedia('(prefers-reduced-motion: reduce)').matches, ...(ngDevMode ? [{ debugName: "reduceMotion" }] : /* istanbul ignore next */ []));
|
|
8423
|
-
// Hover state.
|
|
8503
|
+
// Hover state. `hoverIdx` is the local pointer/keyboard index; `dispIdx` is
|
|
8504
|
+
// what actually renders — local wins, else the externally driven activeIndex.
|
|
8424
8505
|
hoverIdx = signal(null, ...(ngDevMode ? [{ debugName: "hoverIdx" }] : /* istanbul ignore next */ []));
|
|
8506
|
+
dispIdx = computed(() => {
|
|
8507
|
+
const local = this.hoverIdx();
|
|
8508
|
+
const i = local ?? this.activeIndex();
|
|
8509
|
+
if (i == null)
|
|
8510
|
+
return null;
|
|
8511
|
+
const [s, e] = this.domain();
|
|
8512
|
+
return i >= s && i <= e ? i : null;
|
|
8513
|
+
}, ...(ngDevMode ? [{ debugName: "dispIdx" }] : /* istanbul ignore next */ []));
|
|
8514
|
+
// Zoom / brush state (indices are always in the full-data domain).
|
|
8515
|
+
viewRange = signal(null, ...(ngDevMode ? [{ debugName: "viewRange" }] : /* istanbul ignore next */ []));
|
|
8516
|
+
brushDrag = signal(null, ...(ngDevMode ? [{ debugName: "brushDrag" }] : /* istanbul ignore next */ []));
|
|
8517
|
+
brushEnabled = computed(() => this.brush() || this.zoom(), ...(ngDevMode ? [{ debugName: "brushEnabled" }] : /* istanbul ignore next */ []));
|
|
8518
|
+
zoomed = computed(() => this.viewRange() !== null, ...(ngDevMode ? [{ debugName: "zoomed" }] : /* istanbul ignore next */ []));
|
|
8425
8519
|
constructor() {
|
|
8426
8520
|
const destroyRef = inject(DestroyRef);
|
|
8427
8521
|
if (typeof matchMedia !== 'undefined') {
|
|
@@ -8481,6 +8575,16 @@ class StrctChart {
|
|
|
8481
8575
|
isEmpty = computed(() => this.allData().every((d) => d.length === 0), ...(ngDevMode ? [{ debugName: "isEmpty" }] : /* istanbul ignore next */ []));
|
|
8482
8576
|
/** Number of x slots. */
|
|
8483
8577
|
nx = computed(() => Math.max(1, ...this.allData().map((d) => d.length)), ...(ngDevMode ? [{ debugName: "nx" }] : /* istanbul ignore next */ []));
|
|
8578
|
+
/** Visible index window: the brush-zoom range, or the full data. */
|
|
8579
|
+
domain = computed(() => {
|
|
8580
|
+
const n = this.nx();
|
|
8581
|
+
const vr = this.viewRange();
|
|
8582
|
+
if (!vr)
|
|
8583
|
+
return [0, n - 1];
|
|
8584
|
+
const s = Math.max(0, Math.min(vr[0], n - 1));
|
|
8585
|
+
const e = Math.max(s, Math.min(vr[1], n - 1));
|
|
8586
|
+
return e > s ? [s, e] : [0, n - 1];
|
|
8587
|
+
}, ...(ngDevMode ? [{ debugName: "domain" }] : /* istanbul ignore next */ []));
|
|
8484
8588
|
/** Left padding: wider when the y-axis labels are shown. */
|
|
8485
8589
|
pl = computed(() => (this.yAxis() ? Y_AXIS_GUTTER : PAD.l), ...(ngDevMode ? [{ debugName: "pl" }] : /* istanbul ignore next */ []));
|
|
8486
8590
|
chartW() {
|
|
@@ -8489,16 +8593,46 @@ class StrctChart {
|
|
|
8489
8593
|
chartH() {
|
|
8490
8594
|
return this.height() - PAD.t - PAD.b;
|
|
8491
8595
|
}
|
|
8492
|
-
/** Horizontal gap between two data points, in px. */
|
|
8596
|
+
/** Horizontal gap between two data points, in px (of the visible window). */
|
|
8493
8597
|
stepX() {
|
|
8494
|
-
const
|
|
8495
|
-
return
|
|
8598
|
+
const [s, e] = this.domain();
|
|
8599
|
+
return e > s ? this.chartW() / (e - s) : 0;
|
|
8496
8600
|
}
|
|
8601
|
+
/** Real values inside the visible window (multi-aware; bands included). */
|
|
8602
|
+
visibleValues = computed(() => {
|
|
8603
|
+
const [s, e] = this.domain();
|
|
8604
|
+
const out = [];
|
|
8605
|
+
const push = (v) => {
|
|
8606
|
+
if (isVal(v))
|
|
8607
|
+
out.push(v);
|
|
8608
|
+
};
|
|
8609
|
+
const ser = this.seriesResolved();
|
|
8610
|
+
if (ser) {
|
|
8611
|
+
const N = this.nx();
|
|
8612
|
+
for (const x of ser) {
|
|
8613
|
+
const data = x.data ?? [];
|
|
8614
|
+
const offset = N - data.length;
|
|
8615
|
+
for (let gi = Math.max(s, offset); gi <= e; gi++) {
|
|
8616
|
+
const li = gi - offset;
|
|
8617
|
+
if (li < 0 || li >= data.length)
|
|
8618
|
+
continue;
|
|
8619
|
+
push(data[li]);
|
|
8620
|
+
push(x.upper?.[li]);
|
|
8621
|
+
}
|
|
8622
|
+
}
|
|
8623
|
+
}
|
|
8624
|
+
else {
|
|
8625
|
+
const d = this.data();
|
|
8626
|
+
for (let i = s; i <= Math.min(e, d.length - 1); i++)
|
|
8627
|
+
push(d[i]);
|
|
8628
|
+
}
|
|
8629
|
+
return out;
|
|
8630
|
+
}, ...(ngDevMode ? [{ debugName: "visibleValues" }] : /* istanbul ignore next */ []));
|
|
8497
8631
|
yMax = computed(() => {
|
|
8498
8632
|
const explicit = this.max();
|
|
8499
8633
|
if (explicit != null)
|
|
8500
8634
|
return explicit || 1;
|
|
8501
|
-
const m = Math.max(0, ...this.
|
|
8635
|
+
const m = Math.max(0, ...this.visibleValues());
|
|
8502
8636
|
return m === 0 ? 1 : m * 1.1;
|
|
8503
8637
|
}, ...(ngDevMode ? [{ debugName: "yMax" }] : /* istanbul ignore next */ []));
|
|
8504
8638
|
yMin = computed(() => this.min() ?? 0, ...(ngDevMode ? [{ debugName: "yMin" }] : /* istanbul ignore next */ []));
|
|
@@ -8509,50 +8643,46 @@ class StrctChart {
|
|
|
8509
8643
|
const c = Math.max(lo, Math.min(hi, v));
|
|
8510
8644
|
return PAD.t + (1 - (c - lo) / range) * this.chartH();
|
|
8511
8645
|
}
|
|
8512
|
-
// ── Single-series geometry (
|
|
8646
|
+
// ── Single-series geometry (gap-aware; null keeps its x-slot) ──
|
|
8513
8647
|
points = computed(() => {
|
|
8514
8648
|
const d = this.data();
|
|
8515
|
-
|
|
8516
|
-
const pl = this.pl();
|
|
8517
|
-
return d.map((v, i) => ({ x: pl + i * step, y: this.yOf(v) }));
|
|
8649
|
+
return d.map((v, i) => (isVal(v) ? { x: this.xOf(i), y: this.yOf(v) } : null));
|
|
8518
8650
|
}, ...(ngDevMode ? [{ debugName: "points" }] : /* istanbul ignore next */ []));
|
|
8651
|
+
/** Non-gap points only (dot rendering). */
|
|
8652
|
+
dotPts = computed(() => this.points().filter((p) => p !== null), ...(ngDevMode ? [{ debugName: "dotPts" }] : /* istanbul ignore next */ []));
|
|
8519
8653
|
head = computed(() => {
|
|
8520
8654
|
const p = this.points();
|
|
8521
|
-
|
|
8655
|
+
for (let i = p.length - 1; i >= 0; i--)
|
|
8656
|
+
if (p[i])
|
|
8657
|
+
return p[i];
|
|
8658
|
+
return null;
|
|
8522
8659
|
}, ...(ngDevMode ? [{ debugName: "head" }] : /* istanbul ignore next */ []));
|
|
8523
8660
|
plotPoints = computed(() => {
|
|
8524
8661
|
const p = this.points();
|
|
8525
|
-
if (!this.live() || p.length < 2)
|
|
8662
|
+
if (!this.live() || p.length < 2 || !p[0])
|
|
8526
8663
|
return p;
|
|
8527
8664
|
return [{ x: p[0].x - this.stepX(), y: p[0].y }, ...p];
|
|
8528
8665
|
}, ...(ngDevMode ? [{ debugName: "plotPoints" }] : /* istanbul ignore next */ []));
|
|
8529
|
-
linePath = computed(() =>
|
|
8530
|
-
areaPath = computed(() => {
|
|
8531
|
-
const line = this.linePath();
|
|
8532
|
-
const p = this.plotPoints();
|
|
8533
|
-
if (!line || !p.length)
|
|
8534
|
-
return '';
|
|
8535
|
-
const base = this.height() - PAD.b;
|
|
8536
|
-
return `${line}L${round$1(p[p.length - 1].x)},${round$1(base)}L${round$1(p[0].x)},${round$1(base)}Z`;
|
|
8537
|
-
}, ...(ngDevMode ? [{ debugName: "areaPath" }] : /* istanbul ignore next */ []));
|
|
8666
|
+
linePath = computed(() => pathForSegs(this.plotPoints(), this.curve()), ...(ngDevMode ? [{ debugName: "linePath" }] : /* istanbul ignore next */ []));
|
|
8667
|
+
areaPath = computed(() => areaForSegs(this.plotPoints(), this.curve(), this.height() - PAD.b), ...(ngDevMode ? [{ debugName: "areaPath" }] : /* istanbul ignore next */ []));
|
|
8538
8668
|
// ── Multi-series geometry ─────────────────────────────────────
|
|
8539
8669
|
multiSeries = computed(() => {
|
|
8540
8670
|
const s = this.seriesResolved();
|
|
8541
8671
|
if (!s)
|
|
8542
8672
|
return [];
|
|
8543
8673
|
const N = this.nx();
|
|
8544
|
-
const step = this.stepX();
|
|
8545
|
-
const pl = this.pl();
|
|
8546
8674
|
const base = this.height() - PAD.b;
|
|
8547
8675
|
return s.map((x) => {
|
|
8548
8676
|
const data = x.data ?? [];
|
|
8549
8677
|
const offset = N - data.length; // right-align shorter series
|
|
8550
|
-
const
|
|
8678
|
+
const ptOf = (v, i) => isVal(v) ? { x: this.xOf(offset + i), y: this.yOf(v) } : null;
|
|
8679
|
+
const pts = data.map((v, i) => ptOf(v, i));
|
|
8551
8680
|
const curve = x.curve ?? this.curve();
|
|
8552
|
-
const path =
|
|
8681
|
+
const path = pathForSegs(pts, curve);
|
|
8553
8682
|
const area = x.area ?? false;
|
|
8554
|
-
const areaPath = area
|
|
8555
|
-
|
|
8683
|
+
const areaPath = area ? areaForSegs(pts, curve, base) : '';
|
|
8684
|
+
const band = x.lower && x.upper
|
|
8685
|
+
? bandPath(x.upper.map((v, i) => ptOf(v, i)), x.lower.map((v, i) => ptOf(v, i)), curve)
|
|
8556
8686
|
: '';
|
|
8557
8687
|
return {
|
|
8558
8688
|
color: COLOR$1[x.status ?? this.status()],
|
|
@@ -8562,26 +8692,42 @@ class StrctChart {
|
|
|
8562
8692
|
pts,
|
|
8563
8693
|
path,
|
|
8564
8694
|
areaPath,
|
|
8695
|
+
bandPath: band,
|
|
8565
8696
|
offset,
|
|
8566
8697
|
data,
|
|
8698
|
+
lower: x.lower,
|
|
8699
|
+
upper: x.upper,
|
|
8567
8700
|
};
|
|
8568
8701
|
});
|
|
8569
8702
|
}, ...(ngDevMode ? [{ debugName: "multiSeries" }] : /* istanbul ignore next */ []));
|
|
8570
8703
|
legendItems = computed(() => this.multiSeries()
|
|
8571
8704
|
.filter((s) => s.label)
|
|
8572
8705
|
.map((s) => ({ label: s.label, color: s.color, dash: s.dash })), ...(ngDevMode ? [{ debugName: "legendItems" }] : /* istanbul ignore next */ []));
|
|
8573
|
-
// ── Bars (single-series only)
|
|
8706
|
+
// ── Bars (single-series only; gaps render no bar, keep their slot) ──
|
|
8574
8707
|
bars = computed(() => {
|
|
8575
8708
|
const d = this.data();
|
|
8709
|
+
const [s, e] = this.domain();
|
|
8576
8710
|
const chartW = this.chartW();
|
|
8577
8711
|
const base = this.height() - PAD.b;
|
|
8578
|
-
const
|
|
8712
|
+
const last = Math.min(e, d.length - 1);
|
|
8713
|
+
const count = Math.max(1, last - s + 1);
|
|
8714
|
+
const slot = chartW / count;
|
|
8579
8715
|
const w = slot * 0.6;
|
|
8580
8716
|
const pl = this.pl();
|
|
8581
|
-
|
|
8717
|
+
const out = [];
|
|
8718
|
+
for (let i = s; i <= last; i++) {
|
|
8719
|
+
const v = d[i];
|
|
8720
|
+
if (!isVal(v))
|
|
8721
|
+
continue;
|
|
8582
8722
|
const h = ((Math.max(0, v) - this.yMin()) / (this.yMax() - this.yMin() || 1)) * this.chartH();
|
|
8583
|
-
|
|
8584
|
-
|
|
8723
|
+
out.push({
|
|
8724
|
+
x: pl + (i - s) * slot + (slot - w) / 2,
|
|
8725
|
+
y: base - Math.max(0, h),
|
|
8726
|
+
w,
|
|
8727
|
+
h: Math.max(0, h),
|
|
8728
|
+
});
|
|
8729
|
+
}
|
|
8730
|
+
return out;
|
|
8585
8731
|
}, ...(ngDevMode ? [{ debugName: "bars" }] : /* istanbul ignore next */ []));
|
|
8586
8732
|
// ── Axes ───────────────────────────────────────────────────────
|
|
8587
8733
|
gridY = computed(() => {
|
|
@@ -8616,34 +8762,49 @@ class StrctChart {
|
|
|
8616
8762
|
const ls = this.labels();
|
|
8617
8763
|
const fmt = this.xFormat();
|
|
8618
8764
|
const xt = this.xTicks();
|
|
8619
|
-
|
|
8620
|
-
|
|
8621
|
-
|
|
8622
|
-
|
|
8623
|
-
|
|
8765
|
+
const [s, e] = this.domain();
|
|
8766
|
+
const last = Math.min(e, ls.length - 1);
|
|
8767
|
+
let idxs;
|
|
8768
|
+
if (xt && xt > 1 && last - s + 1 > xt) {
|
|
8769
|
+
const stepI = (last - s) / (xt - 1);
|
|
8770
|
+
idxs = Array.from(new Set(Array.from({ length: xt }, (_, k) => s + Math.round(k * stepI))));
|
|
8624
8771
|
}
|
|
8625
8772
|
else {
|
|
8626
|
-
|
|
8627
|
-
}
|
|
8628
|
-
return
|
|
8773
|
+
idxs = Array.from({ length: Math.max(0, last - s + 1) }, (_, k) => s + k);
|
|
8774
|
+
}
|
|
8775
|
+
return idxs
|
|
8776
|
+
.filter((i) => i >= 0 && i < ls.length)
|
|
8777
|
+
.map((i) => ({
|
|
8778
|
+
text: fmt ? fmt(ls[i], i) : ls[i],
|
|
8779
|
+
i,
|
|
8780
|
+
}));
|
|
8629
8781
|
}, ...(ngDevMode ? [{ debugName: "displayLabels" }] : /* istanbul ignore next */ []));
|
|
8630
|
-
// ── Hover
|
|
8782
|
+
// ── Hover (driven by dispIdx: local pointer, else external activeIndex) ──
|
|
8631
8783
|
hoverX = computed(() => {
|
|
8632
|
-
const i = this.
|
|
8784
|
+
const i = this.dispIdx();
|
|
8633
8785
|
if (i == null)
|
|
8634
8786
|
return null;
|
|
8635
|
-
return this.
|
|
8787
|
+
return this.xOf(i);
|
|
8636
8788
|
}, ...(ngDevMode ? [{ debugName: "hoverX" }] : /* istanbul ignore next */ []));
|
|
8637
8789
|
hoverPt = computed(() => {
|
|
8638
|
-
const i = this.
|
|
8790
|
+
const i = this.dispIdx();
|
|
8639
8791
|
const p = this.points();
|
|
8640
8792
|
return i != null && i >= 0 && i < p.length ? p[i] : null;
|
|
8641
8793
|
}, ...(ngDevMode ? [{ debugName: "hoverPt" }] : /* istanbul ignore next */ []));
|
|
8642
8794
|
hoverValue = computed(() => {
|
|
8643
|
-
const i = this.
|
|
8795
|
+
const i = this.dispIdx();
|
|
8644
8796
|
const d = this.data();
|
|
8645
|
-
|
|
8797
|
+
const v = i != null && i >= 0 && i < d.length ? d[i] : null;
|
|
8798
|
+
return isVal(v) ? v : '';
|
|
8646
8799
|
}, ...(ngDevMode ? [{ debugName: "hoverValue" }] : /* istanbul ignore next */ []));
|
|
8800
|
+
/** The hovered slot exists but holds a gap (single-series). */
|
|
8801
|
+
hoverGap = computed(() => {
|
|
8802
|
+
const i = this.dispIdx();
|
|
8803
|
+
if (i == null || this.isMulti())
|
|
8804
|
+
return false;
|
|
8805
|
+
const d = this.data();
|
|
8806
|
+
return i >= 0 && i < d.length && !isVal(d[i]);
|
|
8807
|
+
}, ...(ngDevMode ? [{ debugName: "hoverGap" }] : /* istanbul ignore next */ []));
|
|
8647
8808
|
/** hoverValue run through valueFormat (unit / precision), else the raw value. */
|
|
8648
8809
|
hoverValueText = computed(() => {
|
|
8649
8810
|
const v = this.hoverValue();
|
|
@@ -8658,20 +8819,24 @@ class StrctChart {
|
|
|
8658
8819
|
return f ? f(this.absDelta()) : String(this.absDelta());
|
|
8659
8820
|
}, ...(ngDevMode ? [{ debugName: "absDeltaText" }] : /* istanbul ignore next */ []));
|
|
8660
8821
|
hoverLabel = computed(() => {
|
|
8661
|
-
const i = this.
|
|
8822
|
+
const i = this.dispIdx();
|
|
8662
8823
|
const l = this.labels();
|
|
8663
8824
|
return i != null && i >= 0 && i < l.length ? l[i] : '';
|
|
8664
8825
|
}, ...(ngDevMode ? [{ debugName: "hoverLabel" }] : /* istanbul ignore next */ []));
|
|
8665
|
-
/** Change from the previous point (single-series; null at the first point). */
|
|
8826
|
+
/** Change from the previous point (single-series; null at the first point or across a gap). */
|
|
8666
8827
|
hoverDelta = computed(() => {
|
|
8667
|
-
const i = this.
|
|
8828
|
+
const i = this.dispIdx();
|
|
8668
8829
|
const d = this.data();
|
|
8669
|
-
|
|
8830
|
+
if (i == null || i <= 0 || i >= d.length)
|
|
8831
|
+
return null;
|
|
8832
|
+
const cur = d[i];
|
|
8833
|
+
const prev = d[i - 1];
|
|
8834
|
+
return isVal(cur) && isVal(prev) ? cur - prev : null;
|
|
8670
8835
|
}, ...(ngDevMode ? [{ debugName: "hoverDelta" }] : /* istanbul ignore next */ []));
|
|
8671
8836
|
absDelta = computed(() => Math.abs(this.hoverDelta() ?? 0), ...(ngDevMode ? [{ debugName: "absDelta" }] : /* istanbul ignore next */ []));
|
|
8672
8837
|
/** Second tooltip line: "Xs ago" while live, else the x label. */
|
|
8673
8838
|
hoverMeta = computed(() => {
|
|
8674
|
-
const i = this.
|
|
8839
|
+
const i = this.dispIdx();
|
|
8675
8840
|
if (i == null)
|
|
8676
8841
|
return '';
|
|
8677
8842
|
if (this.live()) {
|
|
@@ -8684,59 +8849,102 @@ class StrctChart {
|
|
|
8684
8849
|
const l = this.labels();
|
|
8685
8850
|
return i >= 0 && i < l.length ? l[i] : '';
|
|
8686
8851
|
}, ...(ngDevMode ? [{ debugName: "hoverMeta" }] : /* istanbul ignore next */ []));
|
|
8687
|
-
/** Per-series value at the hovered index (multi-series tooltip). */
|
|
8852
|
+
/** Per-series value at the hovered index (multi-series tooltip; bands as `avg (min–max)`). */
|
|
8688
8853
|
hoverRows = computed(() => {
|
|
8689
|
-
const i = this.
|
|
8854
|
+
const i = this.dispIdx();
|
|
8690
8855
|
const s = this.multiSeries();
|
|
8691
8856
|
if (i == null || !s.length)
|
|
8692
8857
|
return [];
|
|
8693
8858
|
const f = this.valueFormat();
|
|
8859
|
+
const fmt = (v) => (f ? f(v) : String(v));
|
|
8694
8860
|
return s
|
|
8695
8861
|
.map((x) => {
|
|
8696
8862
|
const li = i - x.offset;
|
|
8697
|
-
const
|
|
8863
|
+
const raw = li >= 0 && li < x.data.length ? x.data[li] : null;
|
|
8864
|
+
const v = isVal(raw) ? raw : null;
|
|
8865
|
+
const lo = x.lower?.[li];
|
|
8866
|
+
const hi = x.upper?.[li];
|
|
8867
|
+
const band = isVal(lo) && isVal(hi) ? ` (${fmt(lo)}–${fmt(hi)})` : '';
|
|
8698
8868
|
return {
|
|
8699
8869
|
label: x.label,
|
|
8700
8870
|
color: x.color,
|
|
8701
8871
|
value: v,
|
|
8702
|
-
text: v == null ? '' :
|
|
8872
|
+
text: v == null ? '' : fmt(v) + band,
|
|
8703
8873
|
};
|
|
8704
8874
|
})
|
|
8705
8875
|
.filter((r) => r.value !== null);
|
|
8706
8876
|
}, ...(ngDevMode ? [{ debugName: "hoverRows" }] : /* istanbul ignore next */ []));
|
|
8707
8877
|
/** Per-series hover dots (multi-series). */
|
|
8708
8878
|
hoverDots = computed(() => {
|
|
8709
|
-
const i = this.
|
|
8879
|
+
const i = this.dispIdx();
|
|
8710
8880
|
const s = this.multiSeries();
|
|
8711
8881
|
if (i == null || !s.length)
|
|
8712
8882
|
return [];
|
|
8713
8883
|
return s
|
|
8714
8884
|
.map((x) => {
|
|
8715
8885
|
const li = i - x.offset;
|
|
8716
|
-
|
|
8717
|
-
|
|
8718
|
-
: null;
|
|
8886
|
+
const p = li >= 0 && li < x.pts.length ? x.pts[li] : null;
|
|
8887
|
+
return p ? { x: p.x, y: p.y, color: x.color } : null;
|
|
8719
8888
|
})
|
|
8720
8889
|
.filter((d) => d !== null);
|
|
8721
8890
|
}, ...(ngDevMode ? [{ debugName: "hoverDots" }] : /* istanbul ignore next */ []));
|
|
8891
|
+
// ── Annotations ────────────────────────────────────────────────
|
|
8892
|
+
annotationLines = computed(() => {
|
|
8893
|
+
const [s, e] = this.domain();
|
|
8894
|
+
return this.annotations()
|
|
8895
|
+
.filter((a) => a.index >= s && a.index <= e)
|
|
8896
|
+
.map((a) => ({
|
|
8897
|
+
x: this.xOf(a.index),
|
|
8898
|
+
color: COLOR$1[a.status ?? 'accent'],
|
|
8899
|
+
dashed: a.dashed ?? true,
|
|
8900
|
+
label: a.label ?? '',
|
|
8901
|
+
index: a.index,
|
|
8902
|
+
}));
|
|
8903
|
+
}, ...(ngDevMode ? [{ debugName: "annotationLines" }] : /* istanbul ignore next */ []));
|
|
8904
|
+
/** The annotation sitting exactly under the crosshair, if any. */
|
|
8905
|
+
annAt = computed(() => {
|
|
8906
|
+
const i = this.dispIdx();
|
|
8907
|
+
if (i == null)
|
|
8908
|
+
return null;
|
|
8909
|
+
return this.annotationLines().find((a) => a.index === i && a.label) ?? null;
|
|
8910
|
+
}, ...(ngDevMode ? [{ debugName: "annAt" }] : /* istanbul ignore next */ []));
|
|
8911
|
+
// ── Brush / zoom ───────────────────────────────────────────────
|
|
8912
|
+
brushRect = computed(() => {
|
|
8913
|
+
const d = this.brushDrag();
|
|
8914
|
+
if (!d)
|
|
8915
|
+
return null;
|
|
8916
|
+
const x1 = this.xOf(Math.min(d.a, d.b));
|
|
8917
|
+
const x2 = this.xOf(Math.max(d.a, d.b));
|
|
8918
|
+
return { x: round$1(x1), w: round$1(Math.max(1, x2 - x1)) };
|
|
8919
|
+
}, ...(ngDevMode ? [{ debugName: "brushRect" }] : /* istanbul ignore next */ []));
|
|
8920
|
+
/** Zoom back out to the full data window (also emits `brushChange` null). */
|
|
8921
|
+
resetZoom() {
|
|
8922
|
+
this.brushDrag.set(null);
|
|
8923
|
+
if (this.viewRange() !== null) {
|
|
8924
|
+
this.viewRange.set(null);
|
|
8925
|
+
this.brushChange.emit(null);
|
|
8926
|
+
}
|
|
8927
|
+
}
|
|
8722
8928
|
/** Screen-reader summary of the whole chart (role="img" name). */
|
|
8723
8929
|
chartAria = computed(() => {
|
|
8724
8930
|
const f = this.valueFormat() ?? ((v) => String(Math.round(v * 100) / 100));
|
|
8725
8931
|
if (this.isMulti()) {
|
|
8726
8932
|
const parts = this.multiSeries().map((s) => {
|
|
8727
|
-
const
|
|
8933
|
+
const reals = s.data.filter(isVal);
|
|
8934
|
+
const last = reals.length ? f(reals[reals.length - 1]) : '';
|
|
8728
8935
|
return `${s.label || 'series'} latest ${last}`;
|
|
8729
8936
|
});
|
|
8730
8937
|
return `Chart, ${this.multiSeries().length} series: ${parts.join('; ')}`;
|
|
8731
8938
|
}
|
|
8732
8939
|
const d = this.data();
|
|
8733
|
-
|
|
8940
|
+
const reals = d.filter(isVal);
|
|
8941
|
+
if (!reals.length)
|
|
8734
8942
|
return this.emptyText();
|
|
8735
|
-
return `Chart, ${d.length} points. Min ${f(Math.min(...
|
|
8943
|
+
return `Chart, ${d.length} points. Min ${f(Math.min(...reals))}, max ${f(Math.max(...reals))}, latest ${f(reals[reals.length - 1])}`;
|
|
8736
8944
|
}, ...(ngDevMode ? [{ debugName: "chartAria" }] : /* istanbul ignore next */ []));
|
|
8737
8945
|
/** aria-live text announcing the hovered / keyboard-selected point. */
|
|
8738
8946
|
srText = computed(() => {
|
|
8739
|
-
const i = this.
|
|
8947
|
+
const i = this.dispIdx();
|
|
8740
8948
|
if (i == null)
|
|
8741
8949
|
return '';
|
|
8742
8950
|
if (this.isMulti()) {
|
|
@@ -8746,61 +8954,221 @@ class StrctChart {
|
|
|
8746
8954
|
return `${this.hoverMeta() || 'point ' + (i + 1)}: ${rows}`;
|
|
8747
8955
|
}
|
|
8748
8956
|
const meta = this.hoverMeta();
|
|
8749
|
-
|
|
8957
|
+
const value = this.hoverGap() ? this.gapText() : this.hoverValueText();
|
|
8958
|
+
return `${meta ? meta + ': ' : ''}${value}`;
|
|
8750
8959
|
}, ...(ngDevMode ? [{ debugName: "srText" }] : /* istanbul ignore next */ []));
|
|
8751
|
-
/** Pixel x of a data index (shared by the plot and
|
|
8960
|
+
/** Pixel x of a data index (shared by the plot, labels and annotations). */
|
|
8752
8961
|
xOf(i) {
|
|
8753
|
-
|
|
8962
|
+
const [s] = this.domain();
|
|
8963
|
+
return this.pl() + (i - s) * this.stepX();
|
|
8964
|
+
}
|
|
8965
|
+
/** Set the local hover index, emitting `hoverIndex` on change. */
|
|
8966
|
+
setHover(i) {
|
|
8967
|
+
if (i === this.hoverIdx())
|
|
8968
|
+
return;
|
|
8969
|
+
this.hoverIdx.set(i);
|
|
8970
|
+
this.hoverIndex.emit(i);
|
|
8971
|
+
}
|
|
8972
|
+
onLeave() {
|
|
8973
|
+
this.setHover(null);
|
|
8754
8974
|
}
|
|
8755
|
-
/** Keyboard access
|
|
8975
|
+
/** Keyboard access: arrows walk the points; Escape unwinds brush → zoom → crosshair. */
|
|
8756
8976
|
onKey(event) {
|
|
8757
|
-
if (
|
|
8977
|
+
if (event.key === 'Escape') {
|
|
8978
|
+
if (this.brushDrag()) {
|
|
8979
|
+
this.brushDrag.set(null);
|
|
8980
|
+
}
|
|
8981
|
+
else if (this.zoomed()) {
|
|
8982
|
+
this.resetZoom();
|
|
8983
|
+
}
|
|
8984
|
+
else {
|
|
8985
|
+
this.setHover(null);
|
|
8986
|
+
}
|
|
8758
8987
|
return;
|
|
8759
|
-
|
|
8760
|
-
if (!
|
|
8988
|
+
}
|
|
8989
|
+
if (!this.interactive() || this.type() === 'bar')
|
|
8761
8990
|
return;
|
|
8991
|
+
const [s, e] = this.domain();
|
|
8762
8992
|
const cur = this.hoverIdx();
|
|
8763
8993
|
let next = null;
|
|
8764
8994
|
switch (event.key) {
|
|
8765
8995
|
case 'ArrowRight':
|
|
8766
|
-
next = cur == null ?
|
|
8996
|
+
next = cur == null ? s : Math.min(e, cur + 1);
|
|
8767
8997
|
break;
|
|
8768
8998
|
case 'ArrowLeft':
|
|
8769
|
-
next = cur == null ?
|
|
8999
|
+
next = cur == null ? e : Math.max(s, cur - 1);
|
|
8770
9000
|
break;
|
|
8771
9001
|
case 'Home':
|
|
8772
|
-
next =
|
|
9002
|
+
next = s;
|
|
8773
9003
|
break;
|
|
8774
9004
|
case 'End':
|
|
8775
|
-
next =
|
|
9005
|
+
next = e;
|
|
8776
9006
|
break;
|
|
8777
|
-
case 'Escape':
|
|
8778
|
-
this.hoverIdx.set(null);
|
|
8779
|
-
return;
|
|
8780
9007
|
default:
|
|
8781
9008
|
return;
|
|
8782
9009
|
}
|
|
8783
9010
|
event.preventDefault();
|
|
8784
|
-
this.
|
|
9011
|
+
this.setHover(next);
|
|
8785
9012
|
}
|
|
8786
|
-
|
|
8787
|
-
|
|
8788
|
-
return;
|
|
9013
|
+
/** Data index under the pointer, clamped to the visible window. */
|
|
9014
|
+
idxAt(event) {
|
|
8789
9015
|
const el = this.svgRef()?.nativeElement;
|
|
8790
|
-
const n = this.nx();
|
|
8791
9016
|
if (!el || this.isEmpty())
|
|
8792
|
-
return;
|
|
9017
|
+
return null;
|
|
8793
9018
|
const rect = el.getBoundingClientRect();
|
|
8794
9019
|
if (!rect.width)
|
|
8795
|
-
return;
|
|
9020
|
+
return null;
|
|
8796
9021
|
const plFrac = this.pl() / this.width();
|
|
8797
9022
|
const rFrac = PAD.r / this.width();
|
|
8798
9023
|
const fx = ((event.clientX - rect.left) / rect.width - plFrac) / (1 - plFrac - rFrac);
|
|
8799
|
-
const
|
|
8800
|
-
|
|
9024
|
+
const [s, e] = this.domain();
|
|
9025
|
+
return Math.max(s, Math.min(e, s + Math.round(fx * (e - s))));
|
|
9026
|
+
}
|
|
9027
|
+
onDown(event) {
|
|
9028
|
+
if (!this.brushEnabled() || this.isEmpty())
|
|
9029
|
+
return;
|
|
9030
|
+
const i = this.idxAt(event);
|
|
9031
|
+
if (i == null)
|
|
9032
|
+
return;
|
|
9033
|
+
event.currentTarget?.setPointerCapture?.(event.pointerId);
|
|
9034
|
+
this.brushDrag.set({ a: i, b: i });
|
|
9035
|
+
this.setHover(null);
|
|
9036
|
+
event.preventDefault();
|
|
9037
|
+
}
|
|
9038
|
+
onMove(event) {
|
|
9039
|
+
const drag = this.brushDrag();
|
|
9040
|
+
if (drag) {
|
|
9041
|
+
const i = this.idxAt(event);
|
|
9042
|
+
if (i != null && i !== drag.b)
|
|
9043
|
+
this.brushDrag.set({ a: drag.a, b: i });
|
|
9044
|
+
return;
|
|
9045
|
+
}
|
|
9046
|
+
if (!this.interactive() || (this.type() === 'bar' && !this.isMulti()))
|
|
9047
|
+
return;
|
|
9048
|
+
const i = this.idxAt(event);
|
|
9049
|
+
if (i != null)
|
|
9050
|
+
this.setHover(i);
|
|
9051
|
+
}
|
|
9052
|
+
onUp() {
|
|
9053
|
+
const d = this.brushDrag();
|
|
9054
|
+
if (!d)
|
|
9055
|
+
return;
|
|
9056
|
+
this.brushDrag.set(null);
|
|
9057
|
+
const lo = Math.min(d.a, d.b);
|
|
9058
|
+
const hi = Math.max(d.a, d.b);
|
|
9059
|
+
if (hi - lo < 1)
|
|
9060
|
+
return; // a click, not a selection
|
|
9061
|
+
if (this.zoom())
|
|
9062
|
+
this.viewRange.set([lo, hi]);
|
|
9063
|
+
this.brushChange.emit([lo, hi]);
|
|
9064
|
+
}
|
|
9065
|
+
onDblClick() {
|
|
9066
|
+
if (this.brushEnabled())
|
|
9067
|
+
this.resetZoom();
|
|
9068
|
+
}
|
|
9069
|
+
// ── Export (FR-CHART-13) ───────────────────────────────────────
|
|
9070
|
+
/**
|
|
9071
|
+
* The rendered chart as a standalone SVG string — theme colors resolved to
|
|
9072
|
+
* literals, background baked in, y-tick / x-label text included.
|
|
9073
|
+
*/
|
|
9074
|
+
toSVG() {
|
|
9075
|
+
const svg = this.svgRef()?.nativeElement;
|
|
9076
|
+
if (!svg || typeof getComputedStyle === 'undefined')
|
|
9077
|
+
return '';
|
|
9078
|
+
const doc = svg.ownerDocument;
|
|
9079
|
+
const NS = 'http://www.w3.org/2000/svg';
|
|
9080
|
+
const clone = svg.cloneNode(true);
|
|
9081
|
+
clone.setAttribute('xmlns', NS);
|
|
9082
|
+
clone.removeAttribute('class');
|
|
9083
|
+
clone.removeAttribute('style');
|
|
9084
|
+
clone.removeAttribute('tabindex');
|
|
9085
|
+
const PROPS = [
|
|
9086
|
+
'stroke',
|
|
9087
|
+
'fill',
|
|
9088
|
+
'stroke-width',
|
|
9089
|
+
'stroke-dasharray',
|
|
9090
|
+
'stroke-linecap',
|
|
9091
|
+
'stroke-linejoin',
|
|
9092
|
+
'opacity',
|
|
9093
|
+
'fill-opacity',
|
|
9094
|
+
'stroke-opacity',
|
|
9095
|
+
];
|
|
9096
|
+
const src = Array.from(svg.querySelectorAll('*'));
|
|
9097
|
+
const dst = Array.from(clone.querySelectorAll('*'));
|
|
9098
|
+
src.forEach((el, i) => {
|
|
9099
|
+
const cs = getComputedStyle(el);
|
|
9100
|
+
for (const p of PROPS) {
|
|
9101
|
+
const v = cs.getPropertyValue(p);
|
|
9102
|
+
if (v)
|
|
9103
|
+
dst[i].setAttribute(p, v);
|
|
9104
|
+
}
|
|
9105
|
+
dst[i].removeAttribute('class');
|
|
9106
|
+
});
|
|
9107
|
+
const rootCs = getComputedStyle(svg);
|
|
9108
|
+
const bg = rootCs.getPropertyValue('--bg-1').trim();
|
|
9109
|
+
const fg = rootCs.getPropertyValue('--t3').trim() || '#888';
|
|
9110
|
+
const hasLabels = this.displayLabels().length > 0;
|
|
9111
|
+
const w = this.width();
|
|
9112
|
+
const h = this.height() + (hasLabels ? 18 : 0);
|
|
9113
|
+
clone.setAttribute('viewBox', `0 0 ${w} ${h}`);
|
|
9114
|
+
clone.setAttribute('width', String(w));
|
|
9115
|
+
clone.setAttribute('height', String(h));
|
|
9116
|
+
if (bg) {
|
|
9117
|
+
const rect = doc.createElementNS(NS, 'rect');
|
|
9118
|
+
rect.setAttribute('width', String(w));
|
|
9119
|
+
rect.setAttribute('height', String(h));
|
|
9120
|
+
rect.setAttribute('fill', bg);
|
|
9121
|
+
clone.insertBefore(rect, clone.firstChild);
|
|
9122
|
+
}
|
|
9123
|
+
const text = (x, y, content, anchor) => {
|
|
9124
|
+
const t = doc.createElementNS(NS, 'text');
|
|
9125
|
+
t.setAttribute('x', String(round$1(x)));
|
|
9126
|
+
t.setAttribute('y', String(round$1(y)));
|
|
9127
|
+
t.setAttribute('fill', fg);
|
|
9128
|
+
t.setAttribute('font-size', '10');
|
|
9129
|
+
t.setAttribute('font-family', 'monospace');
|
|
9130
|
+
t.setAttribute('text-anchor', anchor);
|
|
9131
|
+
t.textContent = content;
|
|
9132
|
+
clone.appendChild(t);
|
|
9133
|
+
};
|
|
9134
|
+
for (const tick of this.yAxisTicks())
|
|
9135
|
+
text(this.pl() - 6, tick.y + 3.5, tick.text, 'end');
|
|
9136
|
+
if (hasLabels) {
|
|
9137
|
+
for (const l of this.displayLabels())
|
|
9138
|
+
text(this.xOf(l.i), this.height() + 12, l.text, 'middle');
|
|
9139
|
+
}
|
|
9140
|
+
return new XMLSerializer().serializeToString(clone);
|
|
9141
|
+
}
|
|
9142
|
+
/** The chart as a PNG data URL at the given scale (default 2×). */
|
|
9143
|
+
toPNG(scale = 2) {
|
|
9144
|
+
const s = this.toSVG();
|
|
9145
|
+
const w = this.width();
|
|
9146
|
+
const h = this.height() + (this.displayLabels().length ? 18 : 0);
|
|
9147
|
+
return new Promise((resolve, reject) => {
|
|
9148
|
+
if (!s) {
|
|
9149
|
+
reject(new Error('chart is not rendered'));
|
|
9150
|
+
return;
|
|
9151
|
+
}
|
|
9152
|
+
const img = new Image();
|
|
9153
|
+
img.onload = () => {
|
|
9154
|
+
const canvas = document.createElement('canvas');
|
|
9155
|
+
canvas.width = Math.round(w * scale);
|
|
9156
|
+
canvas.height = Math.round(h * scale);
|
|
9157
|
+
const ctx = canvas.getContext('2d');
|
|
9158
|
+
if (!ctx) {
|
|
9159
|
+
reject(new Error('no 2d canvas context'));
|
|
9160
|
+
return;
|
|
9161
|
+
}
|
|
9162
|
+
ctx.scale(scale, scale);
|
|
9163
|
+
ctx.drawImage(img, 0, 0);
|
|
9164
|
+
resolve(canvas.toDataURL('image/png'));
|
|
9165
|
+
};
|
|
9166
|
+
img.onerror = () => reject(new Error('SVG rasterization failed'));
|
|
9167
|
+
img.src = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(s);
|
|
9168
|
+
});
|
|
8801
9169
|
}
|
|
8802
9170
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctChart, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
8803
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctChart, isStandalone: true, selector: "strct-chart", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, series: { classPropertyName: "series", publicName: "series", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, curve: { classPropertyName: "curve", publicName: "curve", isSignal: true, isRequired: false, transformFunction: null }, area: { classPropertyName: "area", publicName: "area", isSignal: true, isRequired: false, transformFunction: null }, glow: { classPropertyName: "glow", publicName: "glow", isSignal: true, isRequired: false, transformFunction: null }, live: { classPropertyName: "live", publicName: "live", isSignal: true, isRequired: false, transformFunction: null }, interval: { classPropertyName: "interval", publicName: "interval", isSignal: true, isRequired: false, transformFunction: null }, interactive: { classPropertyName: "interactive", publicName: "interactive", isSignal: true, isRequired: false, transformFunction: null }, strokeWidth: { classPropertyName: "strokeWidth", publicName: "strokeWidth", isSignal: true, isRequired: false, transformFunction: null }, grid: { classPropertyName: "grid", publicName: "grid", isSignal: true, isRequired: false, transformFunction: null }, dots: { classPropertyName: "dots", publicName: "dots", isSignal: true, isRequired: false, transformFunction: null }, legend: { classPropertyName: "legend", publicName: "legend", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: false, transformFunction: null }, xTicks: { classPropertyName: "xTicks", publicName: "xTicks", isSignal: true, isRequired: false, transformFunction: null }, xFormat: { classPropertyName: "xFormat", publicName: "xFormat", isSignal: true, isRequired: false, transformFunction: null }, status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, yAxis: { classPropertyName: "yAxis", publicName: "yAxis", isSignal: true, isRequired: false, transformFunction: null }, yTicks: { classPropertyName: "yTicks", publicName: "yTicks", isSignal: true, isRequired: false, transformFunction: null }, axisFormat: { classPropertyName: "axisFormat", publicName: "axisFormat", isSignal: true, isRequired: false, transformFunction: null }, thresholds: { classPropertyName: "thresholds", publicName: "thresholds", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, agoFormat: { classPropertyName: "agoFormat", publicName: "agoFormat", isSignal: true, isRequired: false, transformFunction: null }, valueFormat: { classPropertyName: "valueFormat", publicName: "valueFormat", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.strct-chart--glow": "glow()", "style.--strct-chart-c": "color()" }, classAttribute: "strct-chart" }, viewQueries: [{ propertyName: "svgRef", first: true, predicate: ["svg"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
9171
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: StrctChart, isStandalone: true, selector: "strct-chart", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, series: { classPropertyName: "series", publicName: "series", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, curve: { classPropertyName: "curve", publicName: "curve", isSignal: true, isRequired: false, transformFunction: null }, area: { classPropertyName: "area", publicName: "area", isSignal: true, isRequired: false, transformFunction: null }, glow: { classPropertyName: "glow", publicName: "glow", isSignal: true, isRequired: false, transformFunction: null }, live: { classPropertyName: "live", publicName: "live", isSignal: true, isRequired: false, transformFunction: null }, interval: { classPropertyName: "interval", publicName: "interval", isSignal: true, isRequired: false, transformFunction: null }, interactive: { classPropertyName: "interactive", publicName: "interactive", isSignal: true, isRequired: false, transformFunction: null }, strokeWidth: { classPropertyName: "strokeWidth", publicName: "strokeWidth", isSignal: true, isRequired: false, transformFunction: null }, grid: { classPropertyName: "grid", publicName: "grid", isSignal: true, isRequired: false, transformFunction: null }, dots: { classPropertyName: "dots", publicName: "dots", isSignal: true, isRequired: false, transformFunction: null }, legend: { classPropertyName: "legend", publicName: "legend", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: false, transformFunction: null }, xTicks: { classPropertyName: "xTicks", publicName: "xTicks", isSignal: true, isRequired: false, transformFunction: null }, xFormat: { classPropertyName: "xFormat", publicName: "xFormat", isSignal: true, isRequired: false, transformFunction: null }, status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, yAxis: { classPropertyName: "yAxis", publicName: "yAxis", isSignal: true, isRequired: false, transformFunction: null }, yTicks: { classPropertyName: "yTicks", publicName: "yTicks", isSignal: true, isRequired: false, transformFunction: null }, axisFormat: { classPropertyName: "axisFormat", publicName: "axisFormat", isSignal: true, isRequired: false, transformFunction: null }, thresholds: { classPropertyName: "thresholds", publicName: "thresholds", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, agoFormat: { classPropertyName: "agoFormat", publicName: "agoFormat", isSignal: true, isRequired: false, transformFunction: null }, valueFormat: { classPropertyName: "valueFormat", publicName: "valueFormat", isSignal: true, isRequired: false, transformFunction: null }, annotations: { classPropertyName: "annotations", publicName: "annotations", isSignal: true, isRequired: false, transformFunction: null }, activeIndex: { classPropertyName: "activeIndex", publicName: "activeIndex", isSignal: true, isRequired: false, transformFunction: null }, brush: { classPropertyName: "brush", publicName: "brush", isSignal: true, isRequired: false, transformFunction: null }, zoom: { classPropertyName: "zoom", publicName: "zoom", isSignal: true, isRequired: false, transformFunction: null }, gapText: { classPropertyName: "gapText", publicName: "gapText", isSignal: true, isRequired: false, transformFunction: null }, resetLabel: { classPropertyName: "resetLabel", publicName: "resetLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { hoverIndex: "hoverIndex", brushChange: "brushChange" }, host: { properties: { "class.strct-chart--glow": "glow()", "class.strct-chart--brush": "brush() || zoom()", "style.--strct-chart-c": "color()" }, classAttribute: "strct-chart" }, viewQueries: [{ propertyName: "svgRef", first: true, predicate: ["svg"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
8804
9172
|
@if (isEmpty()) {
|
|
8805
9173
|
<div class="strct-chart__empty" [style.height.px]="height()">{{ emptyText() }}</div>
|
|
8806
9174
|
} @else {
|
|
@@ -8835,10 +9203,14 @@ class StrctChart {
|
|
|
8835
9203
|
[attr.width]="width()"
|
|
8836
9204
|
[attr.height]="height()"
|
|
8837
9205
|
[style.height.px]="height()"
|
|
9206
|
+
(pointerdown)="onDown($event)"
|
|
8838
9207
|
(pointermove)="onMove($event)"
|
|
8839
|
-
(
|
|
9208
|
+
(pointerup)="onUp()"
|
|
9209
|
+
(lostpointercapture)="onUp()"
|
|
9210
|
+
(pointerleave)="onLeave()"
|
|
9211
|
+
(dblclick)="onDblClick()"
|
|
8840
9212
|
(keydown)="onKey($event)"
|
|
8841
|
-
(blur)="
|
|
9213
|
+
(blur)="onLeave()"
|
|
8842
9214
|
>
|
|
8843
9215
|
<defs>
|
|
8844
9216
|
<linearGradient [attr.id]="gradId" x1="0" y1="0" x2="0" y2="1">
|
|
@@ -8862,6 +9234,19 @@ class StrctChart {
|
|
|
8862
9234
|
}
|
|
8863
9235
|
}
|
|
8864
9236
|
|
|
9237
|
+
<!-- Event / annotation markers: behind the data, above the grid. -->
|
|
9238
|
+
@for (a of annotationLines(); track $index) {
|
|
9239
|
+
<line
|
|
9240
|
+
class="strct-chart__ann"
|
|
9241
|
+
[class.strct-chart__ann--dashed]="a.dashed"
|
|
9242
|
+
[attr.x1]="a.x"
|
|
9243
|
+
[attr.x2]="a.x"
|
|
9244
|
+
[attr.y1]="pad.t"
|
|
9245
|
+
[attr.y2]="height() - pad.b"
|
|
9246
|
+
[attr.stroke]="a.color"
|
|
9247
|
+
/>
|
|
9248
|
+
}
|
|
9249
|
+
|
|
8865
9250
|
@if (type() === 'bar' && !isMulti()) {
|
|
8866
9251
|
@for (b of bars(); track $index) {
|
|
8867
9252
|
<rect
|
|
@@ -8882,6 +9267,9 @@ class StrctChart {
|
|
|
8882
9267
|
>
|
|
8883
9268
|
@if (isMulti()) {
|
|
8884
9269
|
@for (s of multiSeries(); track $index) {
|
|
9270
|
+
@if (s.bandPath) {
|
|
9271
|
+
<path class="strct-chart__band" [attr.d]="s.bandPath" [attr.fill]="s.color" />
|
|
9272
|
+
}
|
|
8885
9273
|
@if (s.area && s.areaPath) {
|
|
8886
9274
|
<path
|
|
8887
9275
|
class="strct-chart__area strct-chart__area--flat"
|
|
@@ -8916,7 +9304,7 @@ class StrctChart {
|
|
|
8916
9304
|
[attr.stroke]="color()"
|
|
8917
9305
|
/>
|
|
8918
9306
|
@if (dots()) {
|
|
8919
|
-
@for (p of
|
|
9307
|
+
@for (p of dotPts(); track $index) {
|
|
8920
9308
|
<circle
|
|
8921
9309
|
class="strct-chart__dot"
|
|
8922
9310
|
[attr.cx]="p.x"
|
|
@@ -8942,6 +9330,16 @@ class StrctChart {
|
|
|
8942
9330
|
/>
|
|
8943
9331
|
}
|
|
8944
9332
|
|
|
9333
|
+
@if (brushRect(); as br) {
|
|
9334
|
+
<rect
|
|
9335
|
+
class="strct-chart__brush"
|
|
9336
|
+
[attr.x]="br.x"
|
|
9337
|
+
[attr.y]="pad.t"
|
|
9338
|
+
[attr.width]="br.w"
|
|
9339
|
+
[attr.height]="height() - pad.t - pad.b"
|
|
9340
|
+
/>
|
|
9341
|
+
}
|
|
9342
|
+
|
|
8945
9343
|
@if (interactive() && hoverX() !== null) {
|
|
8946
9344
|
<line
|
|
8947
9345
|
class="strct-chart__cross"
|
|
@@ -9002,12 +9400,29 @@ class StrctChart {
|
|
|
9002
9400
|
}
|
|
9003
9401
|
}
|
|
9004
9402
|
|
|
9403
|
+
@for (a of annotationLines(); track $index) {
|
|
9404
|
+
@if (a.label) {
|
|
9405
|
+
<div class="strct-chart__ann-label" [style.left.px]="a.x" [style.color]="a.color">
|
|
9406
|
+
{{ a.label }}
|
|
9407
|
+
</div>
|
|
9408
|
+
}
|
|
9409
|
+
}
|
|
9410
|
+
|
|
9411
|
+
@if (zoomed()) {
|
|
9412
|
+
<button type="button" class="strct-chart__reset" (click)="resetZoom()">
|
|
9413
|
+
⟲ {{ resetLabel() }}
|
|
9414
|
+
</button>
|
|
9415
|
+
}
|
|
9416
|
+
|
|
9005
9417
|
@if (interactive() && hoverX() !== null) {
|
|
9006
9418
|
@if (isMulti()) {
|
|
9007
9419
|
<div class="strct-chart__tip strct-chart__tip--multi" [style.left.px]="hoverX()">
|
|
9008
9420
|
@if (hoverMeta()) {
|
|
9009
9421
|
<span class="strct-chart__tip-l">{{ hoverMeta() }}</span>
|
|
9010
9422
|
}
|
|
9423
|
+
@if (annAt(); as ann) {
|
|
9424
|
+
<span class="strct-chart__tip-ann" [style.color]="ann.color">{{ ann.label }}</span>
|
|
9425
|
+
}
|
|
9011
9426
|
@for (r of hoverRows(); track r.label) {
|
|
9012
9427
|
<span class="strct-chart__tip-row">
|
|
9013
9428
|
<span class="strct-chart__tip-sw" [style.background]="r.color"></span>
|
|
@@ -9039,6 +9454,17 @@ class StrctChart {
|
|
|
9039
9454
|
}
|
|
9040
9455
|
</span>
|
|
9041
9456
|
}
|
|
9457
|
+
@if (annAt(); as ann) {
|
|
9458
|
+
<span class="strct-chart__tip-ann" [style.color]="ann.color">{{ ann.label }}</span>
|
|
9459
|
+
}
|
|
9460
|
+
</div>
|
|
9461
|
+
} @else if (hoverGap()) {
|
|
9462
|
+
<!-- A gap point: keep the time slot, say "no data" instead of a value. -->
|
|
9463
|
+
<div class="strct-chart__tip strct-chart__tip--gap" [style.left.px]="hoverX()">
|
|
9464
|
+
<span class="strct-chart__tip-v">{{ gapText() }}</span>
|
|
9465
|
+
@if (hoverMeta()) {
|
|
9466
|
+
<span class="strct-chart__tip-l">{{ hoverMeta() }}</span>
|
|
9467
|
+
}
|
|
9042
9468
|
</div>
|
|
9043
9469
|
}
|
|
9044
9470
|
}
|
|
@@ -9053,7 +9479,7 @@ class StrctChart {
|
|
|
9053
9479
|
<div class="strct-chart__labels">
|
|
9054
9480
|
@for (l of displayLabels(); track $index) {
|
|
9055
9481
|
<span
|
|
9056
|
-
[class.strct-chart__label--active]="interactive() &&
|
|
9482
|
+
[class.strct-chart__label--active]="interactive() && dispIdx() === l.i"
|
|
9057
9483
|
[style.left.px]="xOf(l.i)"
|
|
9058
9484
|
>{{ l.text }}</span
|
|
9059
9485
|
>
|
|
@@ -9061,7 +9487,7 @@ class StrctChart {
|
|
|
9061
9487
|
</div>
|
|
9062
9488
|
}
|
|
9063
9489
|
}
|
|
9064
|
-
`, isInline: true, styles: [".strct-chart{display:block;position:relative}.strct-chart__plot{position:relative}.strct-chart__svg{width:100%;display:block;touch-action:none}.strct-chart__svg:focus-visible{outline:2px solid var(--acc50);outline-offset:2px;border-radius:var(--radius-sm)}.strct-chart__sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.strct-chart__empty{display:flex;align-items:center;justify-content:center;font-size:12px;color:var(--t3)}.strct-chart__grid{stroke:var(--b1);stroke-width:1;vector-effect:non-scaling-stroke}.strct-chart__line{vector-effect:non-scaling-stroke;stroke-linejoin:round;stroke-linecap:round}.strct-chart__area{stroke:none}.strct-chart__area--flat{opacity:.14}.strct-chart__dot,.strct-chart__hoverdot,.strct-chart__head-dot{stroke:var(--bg-1);stroke-width:1.5}.strct-chart__cross{stroke:var(--strct-chart-c);stroke-width:1;opacity:.4;stroke-dasharray:3 3;vector-effect:non-scaling-stroke}.strct-chart__threshold{stroke-width:1;opacity:.85;vector-effect:non-scaling-stroke}.strct-chart__threshold--dashed{stroke-dasharray:4 3}.strct-chart__bar{rx:1.5}.strct-chart--glow .strct-chart__line{filter:drop-shadow(0 0 1.5px var(--strct-chart-c)) drop-shadow(0 0 5px var(--strct-chart-c))}.strct-chart--glow .strct-chart__head-dot{filter:drop-shadow(0 0 2px var(--strct-chart-c)) drop-shadow(0 0 6px var(--strct-chart-c))}.strct-chart--glow .strct-chart__hoverdot{filter:drop-shadow(0 0 4px var(--strct-chart-c))}.strct-chart__ytick{position:absolute;left:0;width:34px;text-align:end;transform:translateY(-50%);pointer-events:none;font-family:var(--mono);font-size:12px;color:var(--t3);font-variant-numeric:tabular-nums}.strct-chart__thr{position:absolute;right:2px;transform:translateY(-50%);pointer-events:none;font-size:12px;font-weight:600;font-variant-numeric:tabular-nums;background:var(--bg-1);padding:0 3px;border-radius:3px}.strct-chart__axis-y{position:absolute;left:0;transform:translateY(-50%);pointer-events:none;padding:1px 5px;border-radius:var(--radius-sm);background:var(--bg-a);border:1px solid var(--b2);font-family:var(--mono);font-size:12px;font-weight:600;color:var(--t2);font-variant-numeric:tabular-nums;z-index:2}.strct-chart__label--active{color:var(--t1);font-weight:700}.strct-chart__legend{display:flex;flex-wrap:wrap;gap:6px 14px;margin-bottom:8px;font-size:12px;color:var(--t2)}.strct-chart__leg{display:inline-flex;align-items:center;gap:6px}.strct-chart__leg-sw{width:9px;height:3px;border-radius:2px;flex-shrink:0}.strct-chart__tip{position:absolute;transform:translate(-50%,calc(-100% - 10px));pointer-events:none;display:flex;flex-direction:column;align-items:center;gap:1px;padding:4px 8px;border-radius:var(--radius-sm);background:var(--bg-a);border:1px solid var(--b2);box-shadow:var(--shadow-elevated);white-space:nowrap;z-index:2}.strct-chart__tip--multi{top:6px;transform:translate(-50%);align-items:stretch;gap:3px}.strct-chart__tip-v{font-size:12px;font-weight:700;color:var(--t1);font-variant-numeric:tabular-nums}.strct-chart__tip-meta{display:inline-flex;align-items:center;gap:5px}.strct-chart__tip-delta{font-size:12px;font-weight:600;color:var(--t3);font-variant-numeric:tabular-nums}.strct-chart__tip-delta--up{color:var(--success)}.strct-chart__tip-delta--down{color:var(--critical)}.strct-chart__tip-l{font-size:12px;color:var(--t3)}.strct-chart__tip-row{display:inline-flex;align-items:center;gap:6px;font-size:12px}.strct-chart__tip-sw{width:8px;height:3px;border-radius:2px;flex-shrink:0}.strct-chart__tip-rl{color:var(--t3);margin-inline-end:auto}.strct-chart__tip-rv{color:var(--t1);font-weight:700;font-variant-numeric:tabular-nums}.strct-chart__labels{position:relative;height:15px;margin-top:6px;font-size:12px;color:var(--t3)}.strct-chart__labels span{position:absolute;transform:translate(-50%);white-space:nowrap}@media(prefers-reduced-motion:no-preference){.strct-chart__line--draw{stroke-dasharray:1;stroke-dashoffset:1;animation:strct-chart-draw .9s ease forwards}.strct-chart__pulse{transform-box:fill-box;transform-origin:center;animation:strct-chart-pulse 2.4s ease-out infinite}}@keyframes strct-chart-draw{to{stroke-dashoffset:0}}@keyframes strct-chart-pulse{0%{transform:scale(1);opacity:.45}70%{opacity:0}to{transform:scale(2.5);opacity:0}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
9490
|
+
`, isInline: true, styles: [".strct-chart{display:block;position:relative}.strct-chart__plot{position:relative}.strct-chart__svg{width:100%;display:block;touch-action:none}.strct-chart__svg:focus-visible{outline:2px solid var(--acc50);outline-offset:2px;border-radius:var(--radius-sm)}.strct-chart__sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.strct-chart__empty{display:flex;align-items:center;justify-content:center;font-size:12px;color:var(--t3)}.strct-chart__grid{stroke:var(--b1);stroke-width:1;vector-effect:non-scaling-stroke}.strct-chart__line{vector-effect:non-scaling-stroke;stroke-linejoin:round;stroke-linecap:round}.strct-chart__area{stroke:none}.strct-chart__area--flat{opacity:.14}.strct-chart__dot,.strct-chart__hoverdot,.strct-chart__head-dot{stroke:var(--bg-1);stroke-width:1.5}.strct-chart__cross{stroke:var(--strct-chart-c);stroke-width:1;opacity:.4;stroke-dasharray:3 3;vector-effect:non-scaling-stroke}.strct-chart__threshold{stroke-width:1;opacity:.85;vector-effect:non-scaling-stroke}.strct-chart__threshold--dashed{stroke-dasharray:4 3}.strct-chart__bar{rx:1.5}.strct-chart__band{opacity:.13;stroke:none}.strct-chart__ann{stroke-width:1;opacity:.8;vector-effect:non-scaling-stroke}.strct-chart__ann--dashed{stroke-dasharray:4 3}.strct-chart__ann-label{position:absolute;top:0;transform:translate(-50%);pointer-events:none;font-size:12px;font-weight:600;background:var(--bg-1);padding:0 3px;border-radius:3px;white-space:nowrap}.strct-chart--brush .strct-chart__svg{cursor:crosshair}.strct-chart__brush{fill:var(--acc);opacity:.16;stroke:var(--acc50);stroke-width:1;vector-effect:non-scaling-stroke}.strct-chart__reset{position:absolute;top:6px;right:8px;z-index:3;display:inline-flex;align-items:center;gap:5px;padding:2px 9px;border:1px solid var(--b2);border-radius:99px;background:var(--bg-a);color:var(--t2);font-family:var(--font);font-size:12px;font-weight:600;cursor:pointer}.strct-chart__reset:hover{color:var(--t1);border-color:var(--acc50)}.strct-chart__reset:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-chart__tip--gap{top:6px;transform:translate(-50%)}.strct-chart__tip-ann{font-size:12px;font-weight:600}.strct-chart--glow .strct-chart__line{filter:drop-shadow(0 0 1.5px var(--strct-chart-c)) drop-shadow(0 0 5px var(--strct-chart-c))}.strct-chart--glow .strct-chart__head-dot{filter:drop-shadow(0 0 2px var(--strct-chart-c)) drop-shadow(0 0 6px var(--strct-chart-c))}.strct-chart--glow .strct-chart__hoverdot{filter:drop-shadow(0 0 4px var(--strct-chart-c))}.strct-chart__ytick{position:absolute;left:0;width:34px;text-align:end;transform:translateY(-50%);pointer-events:none;font-family:var(--mono);font-size:12px;color:var(--t3);font-variant-numeric:tabular-nums}.strct-chart__thr{position:absolute;right:2px;transform:translateY(-50%);pointer-events:none;font-size:12px;font-weight:600;font-variant-numeric:tabular-nums;background:var(--bg-1);padding:0 3px;border-radius:3px}.strct-chart__axis-y{position:absolute;left:0;transform:translateY(-50%);pointer-events:none;padding:1px 5px;border-radius:var(--radius-sm);background:var(--bg-a);border:1px solid var(--b2);font-family:var(--mono);font-size:12px;font-weight:600;color:var(--t2);font-variant-numeric:tabular-nums;z-index:2}.strct-chart__label--active{color:var(--t1);font-weight:700}.strct-chart__legend{display:flex;flex-wrap:wrap;gap:6px 14px;margin-bottom:8px;font-size:12px;color:var(--t2)}.strct-chart__leg{display:inline-flex;align-items:center;gap:6px}.strct-chart__leg-sw{width:9px;height:3px;border-radius:2px;flex-shrink:0}.strct-chart__tip{position:absolute;transform:translate(-50%,calc(-100% - 10px));pointer-events:none;display:flex;flex-direction:column;align-items:center;gap:1px;padding:4px 8px;border-radius:var(--radius-sm);background:var(--bg-a);border:1px solid var(--b2);box-shadow:var(--shadow-elevated);white-space:nowrap;z-index:2}.strct-chart__tip--multi{top:6px;transform:translate(-50%);align-items:stretch;gap:3px}.strct-chart__tip-v{font-size:12px;font-weight:700;color:var(--t1);font-variant-numeric:tabular-nums}.strct-chart__tip-meta{display:inline-flex;align-items:center;gap:5px}.strct-chart__tip-delta{font-size:12px;font-weight:600;color:var(--t3);font-variant-numeric:tabular-nums}.strct-chart__tip-delta--up{color:var(--success)}.strct-chart__tip-delta--down{color:var(--critical)}.strct-chart__tip-l{font-size:12px;color:var(--t3)}.strct-chart__tip-row{display:inline-flex;align-items:center;gap:6px;font-size:12px}.strct-chart__tip-sw{width:8px;height:3px;border-radius:2px;flex-shrink:0}.strct-chart__tip-rl{color:var(--t3);margin-inline-end:auto}.strct-chart__tip-rv{color:var(--t1);font-weight:700;font-variant-numeric:tabular-nums}.strct-chart__labels{position:relative;height:15px;margin-top:6px;font-size:12px;color:var(--t3)}.strct-chart__labels span{position:absolute;transform:translate(-50%);white-space:nowrap}@media(prefers-reduced-motion:no-preference){.strct-chart__line--draw{stroke-dasharray:1;stroke-dashoffset:1;animation:strct-chart-draw .9s ease forwards}.strct-chart__pulse{transform-box:fill-box;transform-origin:center;animation:strct-chart-pulse 2.4s ease-out infinite}}@keyframes strct-chart-draw{to{stroke-dashoffset:0}}@keyframes strct-chart-pulse{0%{transform:scale(1);opacity:.45}70%{opacity:0}to{transform:scale(2.5);opacity:0}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
9065
9491
|
}
|
|
9066
9492
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: StrctChart, decorators: [{
|
|
9067
9493
|
type: Component,
|
|
@@ -9100,10 +9526,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
9100
9526
|
[attr.width]="width()"
|
|
9101
9527
|
[attr.height]="height()"
|
|
9102
9528
|
[style.height.px]="height()"
|
|
9529
|
+
(pointerdown)="onDown($event)"
|
|
9103
9530
|
(pointermove)="onMove($event)"
|
|
9104
|
-
(
|
|
9531
|
+
(pointerup)="onUp()"
|
|
9532
|
+
(lostpointercapture)="onUp()"
|
|
9533
|
+
(pointerleave)="onLeave()"
|
|
9534
|
+
(dblclick)="onDblClick()"
|
|
9105
9535
|
(keydown)="onKey($event)"
|
|
9106
|
-
(blur)="
|
|
9536
|
+
(blur)="onLeave()"
|
|
9107
9537
|
>
|
|
9108
9538
|
<defs>
|
|
9109
9539
|
<linearGradient [attr.id]="gradId" x1="0" y1="0" x2="0" y2="1">
|
|
@@ -9127,6 +9557,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
9127
9557
|
}
|
|
9128
9558
|
}
|
|
9129
9559
|
|
|
9560
|
+
<!-- Event / annotation markers: behind the data, above the grid. -->
|
|
9561
|
+
@for (a of annotationLines(); track $index) {
|
|
9562
|
+
<line
|
|
9563
|
+
class="strct-chart__ann"
|
|
9564
|
+
[class.strct-chart__ann--dashed]="a.dashed"
|
|
9565
|
+
[attr.x1]="a.x"
|
|
9566
|
+
[attr.x2]="a.x"
|
|
9567
|
+
[attr.y1]="pad.t"
|
|
9568
|
+
[attr.y2]="height() - pad.b"
|
|
9569
|
+
[attr.stroke]="a.color"
|
|
9570
|
+
/>
|
|
9571
|
+
}
|
|
9572
|
+
|
|
9130
9573
|
@if (type() === 'bar' && !isMulti()) {
|
|
9131
9574
|
@for (b of bars(); track $index) {
|
|
9132
9575
|
<rect
|
|
@@ -9147,6 +9590,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
9147
9590
|
>
|
|
9148
9591
|
@if (isMulti()) {
|
|
9149
9592
|
@for (s of multiSeries(); track $index) {
|
|
9593
|
+
@if (s.bandPath) {
|
|
9594
|
+
<path class="strct-chart__band" [attr.d]="s.bandPath" [attr.fill]="s.color" />
|
|
9595
|
+
}
|
|
9150
9596
|
@if (s.area && s.areaPath) {
|
|
9151
9597
|
<path
|
|
9152
9598
|
class="strct-chart__area strct-chart__area--flat"
|
|
@@ -9181,7 +9627,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
9181
9627
|
[attr.stroke]="color()"
|
|
9182
9628
|
/>
|
|
9183
9629
|
@if (dots()) {
|
|
9184
|
-
@for (p of
|
|
9630
|
+
@for (p of dotPts(); track $index) {
|
|
9185
9631
|
<circle
|
|
9186
9632
|
class="strct-chart__dot"
|
|
9187
9633
|
[attr.cx]="p.x"
|
|
@@ -9207,6 +9653,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
9207
9653
|
/>
|
|
9208
9654
|
}
|
|
9209
9655
|
|
|
9656
|
+
@if (brushRect(); as br) {
|
|
9657
|
+
<rect
|
|
9658
|
+
class="strct-chart__brush"
|
|
9659
|
+
[attr.x]="br.x"
|
|
9660
|
+
[attr.y]="pad.t"
|
|
9661
|
+
[attr.width]="br.w"
|
|
9662
|
+
[attr.height]="height() - pad.t - pad.b"
|
|
9663
|
+
/>
|
|
9664
|
+
}
|
|
9665
|
+
|
|
9210
9666
|
@if (interactive() && hoverX() !== null) {
|
|
9211
9667
|
<line
|
|
9212
9668
|
class="strct-chart__cross"
|
|
@@ -9267,12 +9723,29 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
9267
9723
|
}
|
|
9268
9724
|
}
|
|
9269
9725
|
|
|
9726
|
+
@for (a of annotationLines(); track $index) {
|
|
9727
|
+
@if (a.label) {
|
|
9728
|
+
<div class="strct-chart__ann-label" [style.left.px]="a.x" [style.color]="a.color">
|
|
9729
|
+
{{ a.label }}
|
|
9730
|
+
</div>
|
|
9731
|
+
}
|
|
9732
|
+
}
|
|
9733
|
+
|
|
9734
|
+
@if (zoomed()) {
|
|
9735
|
+
<button type="button" class="strct-chart__reset" (click)="resetZoom()">
|
|
9736
|
+
⟲ {{ resetLabel() }}
|
|
9737
|
+
</button>
|
|
9738
|
+
}
|
|
9739
|
+
|
|
9270
9740
|
@if (interactive() && hoverX() !== null) {
|
|
9271
9741
|
@if (isMulti()) {
|
|
9272
9742
|
<div class="strct-chart__tip strct-chart__tip--multi" [style.left.px]="hoverX()">
|
|
9273
9743
|
@if (hoverMeta()) {
|
|
9274
9744
|
<span class="strct-chart__tip-l">{{ hoverMeta() }}</span>
|
|
9275
9745
|
}
|
|
9746
|
+
@if (annAt(); as ann) {
|
|
9747
|
+
<span class="strct-chart__tip-ann" [style.color]="ann.color">{{ ann.label }}</span>
|
|
9748
|
+
}
|
|
9276
9749
|
@for (r of hoverRows(); track r.label) {
|
|
9277
9750
|
<span class="strct-chart__tip-row">
|
|
9278
9751
|
<span class="strct-chart__tip-sw" [style.background]="r.color"></span>
|
|
@@ -9304,6 +9777,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
9304
9777
|
}
|
|
9305
9778
|
</span>
|
|
9306
9779
|
}
|
|
9780
|
+
@if (annAt(); as ann) {
|
|
9781
|
+
<span class="strct-chart__tip-ann" [style.color]="ann.color">{{ ann.label }}</span>
|
|
9782
|
+
}
|
|
9783
|
+
</div>
|
|
9784
|
+
} @else if (hoverGap()) {
|
|
9785
|
+
<!-- A gap point: keep the time slot, say "no data" instead of a value. -->
|
|
9786
|
+
<div class="strct-chart__tip strct-chart__tip--gap" [style.left.px]="hoverX()">
|
|
9787
|
+
<span class="strct-chart__tip-v">{{ gapText() }}</span>
|
|
9788
|
+
@if (hoverMeta()) {
|
|
9789
|
+
<span class="strct-chart__tip-l">{{ hoverMeta() }}</span>
|
|
9790
|
+
}
|
|
9307
9791
|
</div>
|
|
9308
9792
|
}
|
|
9309
9793
|
}
|
|
@@ -9318,7 +9802,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
9318
9802
|
<div class="strct-chart__labels">
|
|
9319
9803
|
@for (l of displayLabels(); track $index) {
|
|
9320
9804
|
<span
|
|
9321
|
-
[class.strct-chart__label--active]="interactive() &&
|
|
9805
|
+
[class.strct-chart__label--active]="interactive() && dispIdx() === l.i"
|
|
9322
9806
|
[style.left.px]="xOf(l.i)"
|
|
9323
9807
|
>{{ l.text }}</span
|
|
9324
9808
|
>
|
|
@@ -9329,9 +9813,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
9329
9813
|
`, host: {
|
|
9330
9814
|
class: 'strct-chart',
|
|
9331
9815
|
'[class.strct-chart--glow]': 'glow()',
|
|
9816
|
+
'[class.strct-chart--brush]': 'brush() || zoom()',
|
|
9332
9817
|
'[style.--strct-chart-c]': 'color()',
|
|
9333
|
-
}, styles: [".strct-chart{display:block;position:relative}.strct-chart__plot{position:relative}.strct-chart__svg{width:100%;display:block;touch-action:none}.strct-chart__svg:focus-visible{outline:2px solid var(--acc50);outline-offset:2px;border-radius:var(--radius-sm)}.strct-chart__sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.strct-chart__empty{display:flex;align-items:center;justify-content:center;font-size:12px;color:var(--t3)}.strct-chart__grid{stroke:var(--b1);stroke-width:1;vector-effect:non-scaling-stroke}.strct-chart__line{vector-effect:non-scaling-stroke;stroke-linejoin:round;stroke-linecap:round}.strct-chart__area{stroke:none}.strct-chart__area--flat{opacity:.14}.strct-chart__dot,.strct-chart__hoverdot,.strct-chart__head-dot{stroke:var(--bg-1);stroke-width:1.5}.strct-chart__cross{stroke:var(--strct-chart-c);stroke-width:1;opacity:.4;stroke-dasharray:3 3;vector-effect:non-scaling-stroke}.strct-chart__threshold{stroke-width:1;opacity:.85;vector-effect:non-scaling-stroke}.strct-chart__threshold--dashed{stroke-dasharray:4 3}.strct-chart__bar{rx:1.5}.strct-chart--glow .strct-chart__line{filter:drop-shadow(0 0 1.5px var(--strct-chart-c)) drop-shadow(0 0 5px var(--strct-chart-c))}.strct-chart--glow .strct-chart__head-dot{filter:drop-shadow(0 0 2px var(--strct-chart-c)) drop-shadow(0 0 6px var(--strct-chart-c))}.strct-chart--glow .strct-chart__hoverdot{filter:drop-shadow(0 0 4px var(--strct-chart-c))}.strct-chart__ytick{position:absolute;left:0;width:34px;text-align:end;transform:translateY(-50%);pointer-events:none;font-family:var(--mono);font-size:12px;color:var(--t3);font-variant-numeric:tabular-nums}.strct-chart__thr{position:absolute;right:2px;transform:translateY(-50%);pointer-events:none;font-size:12px;font-weight:600;font-variant-numeric:tabular-nums;background:var(--bg-1);padding:0 3px;border-radius:3px}.strct-chart__axis-y{position:absolute;left:0;transform:translateY(-50%);pointer-events:none;padding:1px 5px;border-radius:var(--radius-sm);background:var(--bg-a);border:1px solid var(--b2);font-family:var(--mono);font-size:12px;font-weight:600;color:var(--t2);font-variant-numeric:tabular-nums;z-index:2}.strct-chart__label--active{color:var(--t1);font-weight:700}.strct-chart__legend{display:flex;flex-wrap:wrap;gap:6px 14px;margin-bottom:8px;font-size:12px;color:var(--t2)}.strct-chart__leg{display:inline-flex;align-items:center;gap:6px}.strct-chart__leg-sw{width:9px;height:3px;border-radius:2px;flex-shrink:0}.strct-chart__tip{position:absolute;transform:translate(-50%,calc(-100% - 10px));pointer-events:none;display:flex;flex-direction:column;align-items:center;gap:1px;padding:4px 8px;border-radius:var(--radius-sm);background:var(--bg-a);border:1px solid var(--b2);box-shadow:var(--shadow-elevated);white-space:nowrap;z-index:2}.strct-chart__tip--multi{top:6px;transform:translate(-50%);align-items:stretch;gap:3px}.strct-chart__tip-v{font-size:12px;font-weight:700;color:var(--t1);font-variant-numeric:tabular-nums}.strct-chart__tip-meta{display:inline-flex;align-items:center;gap:5px}.strct-chart__tip-delta{font-size:12px;font-weight:600;color:var(--t3);font-variant-numeric:tabular-nums}.strct-chart__tip-delta--up{color:var(--success)}.strct-chart__tip-delta--down{color:var(--critical)}.strct-chart__tip-l{font-size:12px;color:var(--t3)}.strct-chart__tip-row{display:inline-flex;align-items:center;gap:6px;font-size:12px}.strct-chart__tip-sw{width:8px;height:3px;border-radius:2px;flex-shrink:0}.strct-chart__tip-rl{color:var(--t3);margin-inline-end:auto}.strct-chart__tip-rv{color:var(--t1);font-weight:700;font-variant-numeric:tabular-nums}.strct-chart__labels{position:relative;height:15px;margin-top:6px;font-size:12px;color:var(--t3)}.strct-chart__labels span{position:absolute;transform:translate(-50%);white-space:nowrap}@media(prefers-reduced-motion:no-preference){.strct-chart__line--draw{stroke-dasharray:1;stroke-dashoffset:1;animation:strct-chart-draw .9s ease forwards}.strct-chart__pulse{transform-box:fill-box;transform-origin:center;animation:strct-chart-pulse 2.4s ease-out infinite}}@keyframes strct-chart-draw{to{stroke-dashoffset:0}}@keyframes strct-chart-pulse{0%{transform:scale(1);opacity:.45}70%{opacity:0}to{transform:scale(2.5);opacity:0}}\n"] }]
|
|
9334
|
-
}], ctorParameters: () => [], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], series: [{ type: i0.Input, args: [{ isSignal: true, alias: "series", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], curve: [{ type: i0.Input, args: [{ isSignal: true, alias: "curve", required: false }] }], area: [{ type: i0.Input, args: [{ isSignal: true, alias: "area", required: false }] }], glow: [{ type: i0.Input, args: [{ isSignal: true, alias: "glow", required: false }] }], live: [{ type: i0.Input, args: [{ isSignal: true, alias: "live", required: false }] }], interval: [{ type: i0.Input, args: [{ isSignal: true, alias: "interval", required: false }] }], interactive: [{ type: i0.Input, args: [{ isSignal: true, alias: "interactive", required: false }] }], strokeWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "strokeWidth", required: false }] }], grid: [{ type: i0.Input, args: [{ isSignal: true, alias: "grid", required: false }] }], dots: [{ type: i0.Input, args: [{ isSignal: true, alias: "dots", required: false }] }], legend: [{ type: i0.Input, args: [{ isSignal: true, alias: "legend", required: false }] }], labels: [{ type: i0.Input, args: [{ isSignal: true, alias: "labels", required: false }] }], xTicks: [{ type: i0.Input, args: [{ isSignal: true, alias: "xTicks", required: false }] }], xFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "xFormat", required: false }] }], status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], yAxis: [{ type: i0.Input, args: [{ isSignal: true, alias: "yAxis", required: false }] }], yTicks: [{ type: i0.Input, args: [{ isSignal: true, alias: "yTicks", required: false }] }], axisFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "axisFormat", required: false }] }], thresholds: [{ type: i0.Input, args: [{ isSignal: true, alias: "thresholds", required: false }] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], agoFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "agoFormat", required: false }] }], valueFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueFormat", required: false }] }], svgRef: [{ type: i0.ViewChild, args: ['svg', { isSignal: true }] }] } });
|
|
9818
|
+
}, styles: [".strct-chart{display:block;position:relative}.strct-chart__plot{position:relative}.strct-chart__svg{width:100%;display:block;touch-action:none}.strct-chart__svg:focus-visible{outline:2px solid var(--acc50);outline-offset:2px;border-radius:var(--radius-sm)}.strct-chart__sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.strct-chart__empty{display:flex;align-items:center;justify-content:center;font-size:12px;color:var(--t3)}.strct-chart__grid{stroke:var(--b1);stroke-width:1;vector-effect:non-scaling-stroke}.strct-chart__line{vector-effect:non-scaling-stroke;stroke-linejoin:round;stroke-linecap:round}.strct-chart__area{stroke:none}.strct-chart__area--flat{opacity:.14}.strct-chart__dot,.strct-chart__hoverdot,.strct-chart__head-dot{stroke:var(--bg-1);stroke-width:1.5}.strct-chart__cross{stroke:var(--strct-chart-c);stroke-width:1;opacity:.4;stroke-dasharray:3 3;vector-effect:non-scaling-stroke}.strct-chart__threshold{stroke-width:1;opacity:.85;vector-effect:non-scaling-stroke}.strct-chart__threshold--dashed{stroke-dasharray:4 3}.strct-chart__bar{rx:1.5}.strct-chart__band{opacity:.13;stroke:none}.strct-chart__ann{stroke-width:1;opacity:.8;vector-effect:non-scaling-stroke}.strct-chart__ann--dashed{stroke-dasharray:4 3}.strct-chart__ann-label{position:absolute;top:0;transform:translate(-50%);pointer-events:none;font-size:12px;font-weight:600;background:var(--bg-1);padding:0 3px;border-radius:3px;white-space:nowrap}.strct-chart--brush .strct-chart__svg{cursor:crosshair}.strct-chart__brush{fill:var(--acc);opacity:.16;stroke:var(--acc50);stroke-width:1;vector-effect:non-scaling-stroke}.strct-chart__reset{position:absolute;top:6px;right:8px;z-index:3;display:inline-flex;align-items:center;gap:5px;padding:2px 9px;border:1px solid var(--b2);border-radius:99px;background:var(--bg-a);color:var(--t2);font-family:var(--font);font-size:12px;font-weight:600;cursor:pointer}.strct-chart__reset:hover{color:var(--t1);border-color:var(--acc50)}.strct-chart__reset:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-chart__tip--gap{top:6px;transform:translate(-50%)}.strct-chart__tip-ann{font-size:12px;font-weight:600}.strct-chart--glow .strct-chart__line{filter:drop-shadow(0 0 1.5px var(--strct-chart-c)) drop-shadow(0 0 5px var(--strct-chart-c))}.strct-chart--glow .strct-chart__head-dot{filter:drop-shadow(0 0 2px var(--strct-chart-c)) drop-shadow(0 0 6px var(--strct-chart-c))}.strct-chart--glow .strct-chart__hoverdot{filter:drop-shadow(0 0 4px var(--strct-chart-c))}.strct-chart__ytick{position:absolute;left:0;width:34px;text-align:end;transform:translateY(-50%);pointer-events:none;font-family:var(--mono);font-size:12px;color:var(--t3);font-variant-numeric:tabular-nums}.strct-chart__thr{position:absolute;right:2px;transform:translateY(-50%);pointer-events:none;font-size:12px;font-weight:600;font-variant-numeric:tabular-nums;background:var(--bg-1);padding:0 3px;border-radius:3px}.strct-chart__axis-y{position:absolute;left:0;transform:translateY(-50%);pointer-events:none;padding:1px 5px;border-radius:var(--radius-sm);background:var(--bg-a);border:1px solid var(--b2);font-family:var(--mono);font-size:12px;font-weight:600;color:var(--t2);font-variant-numeric:tabular-nums;z-index:2}.strct-chart__label--active{color:var(--t1);font-weight:700}.strct-chart__legend{display:flex;flex-wrap:wrap;gap:6px 14px;margin-bottom:8px;font-size:12px;color:var(--t2)}.strct-chart__leg{display:inline-flex;align-items:center;gap:6px}.strct-chart__leg-sw{width:9px;height:3px;border-radius:2px;flex-shrink:0}.strct-chart__tip{position:absolute;transform:translate(-50%,calc(-100% - 10px));pointer-events:none;display:flex;flex-direction:column;align-items:center;gap:1px;padding:4px 8px;border-radius:var(--radius-sm);background:var(--bg-a);border:1px solid var(--b2);box-shadow:var(--shadow-elevated);white-space:nowrap;z-index:2}.strct-chart__tip--multi{top:6px;transform:translate(-50%);align-items:stretch;gap:3px}.strct-chart__tip-v{font-size:12px;font-weight:700;color:var(--t1);font-variant-numeric:tabular-nums}.strct-chart__tip-meta{display:inline-flex;align-items:center;gap:5px}.strct-chart__tip-delta{font-size:12px;font-weight:600;color:var(--t3);font-variant-numeric:tabular-nums}.strct-chart__tip-delta--up{color:var(--success)}.strct-chart__tip-delta--down{color:var(--critical)}.strct-chart__tip-l{font-size:12px;color:var(--t3)}.strct-chart__tip-row{display:inline-flex;align-items:center;gap:6px;font-size:12px}.strct-chart__tip-sw{width:8px;height:3px;border-radius:2px;flex-shrink:0}.strct-chart__tip-rl{color:var(--t3);margin-inline-end:auto}.strct-chart__tip-rv{color:var(--t1);font-weight:700;font-variant-numeric:tabular-nums}.strct-chart__labels{position:relative;height:15px;margin-top:6px;font-size:12px;color:var(--t3)}.strct-chart__labels span{position:absolute;transform:translate(-50%);white-space:nowrap}@media(prefers-reduced-motion:no-preference){.strct-chart__line--draw{stroke-dasharray:1;stroke-dashoffset:1;animation:strct-chart-draw .9s ease forwards}.strct-chart__pulse{transform-box:fill-box;transform-origin:center;animation:strct-chart-pulse 2.4s ease-out infinite}}@keyframes strct-chart-draw{to{stroke-dashoffset:0}}@keyframes strct-chart-pulse{0%{transform:scale(1);opacity:.45}70%{opacity:0}to{transform:scale(2.5);opacity:0}}\n"] }]
|
|
9819
|
+
}], ctorParameters: () => [], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], series: [{ type: i0.Input, args: [{ isSignal: true, alias: "series", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], curve: [{ type: i0.Input, args: [{ isSignal: true, alias: "curve", required: false }] }], area: [{ type: i0.Input, args: [{ isSignal: true, alias: "area", required: false }] }], glow: [{ type: i0.Input, args: [{ isSignal: true, alias: "glow", required: false }] }], live: [{ type: i0.Input, args: [{ isSignal: true, alias: "live", required: false }] }], interval: [{ type: i0.Input, args: [{ isSignal: true, alias: "interval", required: false }] }], interactive: [{ type: i0.Input, args: [{ isSignal: true, alias: "interactive", required: false }] }], strokeWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "strokeWidth", required: false }] }], grid: [{ type: i0.Input, args: [{ isSignal: true, alias: "grid", required: false }] }], dots: [{ type: i0.Input, args: [{ isSignal: true, alias: "dots", required: false }] }], legend: [{ type: i0.Input, args: [{ isSignal: true, alias: "legend", required: false }] }], labels: [{ type: i0.Input, args: [{ isSignal: true, alias: "labels", required: false }] }], xTicks: [{ type: i0.Input, args: [{ isSignal: true, alias: "xTicks", required: false }] }], xFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "xFormat", required: false }] }], status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], yAxis: [{ type: i0.Input, args: [{ isSignal: true, alias: "yAxis", required: false }] }], yTicks: [{ type: i0.Input, args: [{ isSignal: true, alias: "yTicks", required: false }] }], axisFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "axisFormat", required: false }] }], thresholds: [{ type: i0.Input, args: [{ isSignal: true, alias: "thresholds", required: false }] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], agoFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "agoFormat", required: false }] }], valueFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueFormat", required: false }] }], annotations: [{ type: i0.Input, args: [{ isSignal: true, alias: "annotations", required: false }] }], activeIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeIndex", required: false }] }], brush: [{ type: i0.Input, args: [{ isSignal: true, alias: "brush", required: false }] }], zoom: [{ type: i0.Input, args: [{ isSignal: true, alias: "zoom", required: false }] }], gapText: [{ type: i0.Input, args: [{ isSignal: true, alias: "gapText", required: false }] }], resetLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "resetLabel", required: false }] }], hoverIndex: [{ type: i0.Output, args: ["hoverIndex"] }], brushChange: [{ type: i0.Output, args: ["brushChange"] }], svgRef: [{ type: i0.ViewChild, args: ['svg', { isSignal: true }] }] } });
|
|
9335
9820
|
|
|
9336
9821
|
const PALETTE = [
|
|
9337
9822
|
'var(--acc)',
|