@rivet-health/design-system 2.3.1 → 2.5.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/esm2020/lib/format/pipes/days.pipe.mjs +19 -0
- package/esm2020/lib/format/pipes/number.pipe.mjs +18 -0
- package/esm2020/lib/format/pipes/percentage.pipe.mjs +18 -0
- package/esm2020/lib/format/pipes/small-currency.pipe.mjs +35 -0
- package/esm2020/lib/modal/tooltip/tooltip.component.mjs +45 -0
- package/esm2020/lib/modal/tooltip/tooltip.directive.mjs +62 -0
- package/esm2020/lib/riv.module.mjs +39 -9
- package/esm2020/lib/visualization/donut/donut.component.mjs +7 -4
- package/esm2020/lib/visualization/legend-item/legend-item.component.mjs +6 -3
- package/esm2020/lib/visualization/time-series/time-series.component.mjs +1 -1
- package/esm2020/public-api.mjs +7 -1
- package/fesm2015/rivet-health-design-system.mjs +552 -342
- package/fesm2015/rivet-health-design-system.mjs.map +1 -1
- package/fesm2020/rivet-health-design-system.mjs +565 -359
- package/fesm2020/rivet-health-design-system.mjs.map +1 -1
- package/lib/format/pipes/days.pipe.d.ts +8 -0
- package/lib/format/pipes/number.pipe.d.ts +8 -0
- package/lib/format/pipes/percentage.pipe.d.ts +8 -0
- package/lib/format/pipes/small-currency.pipe.d.ts +8 -0
- package/lib/modal/tooltip/tooltip.component.d.ts +16 -0
- package/lib/modal/tooltip/tooltip.directive.d.ts +18 -0
- package/lib/riv.module.d.ts +16 -10
- package/lib/visualization/donut/donut.component.d.ts +2 -1
- package/lib/visualization/legend-item/legend-item.component.d.ts +2 -1
- package/package.json +1 -1
- package/public-api.d.ts +6 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Component, ChangeDetectionStrategy, Input, HostBinding, Injectable, EventEmitter, ViewChild, Output, Directive, NgModule } from '@angular/core';
|
|
2
|
+
import { Component, ChangeDetectionStrategy, Input, HostBinding, Pipe, Injectable, EventEmitter, ViewChild, Output, Directive, HostListener, ViewContainerRef, NgModule } from '@angular/core';
|
|
3
3
|
import * as i1 from '@angular/common';
|
|
4
|
-
import { DecimalPipe, CommonModule } from '@angular/common';
|
|
5
|
-
import { BehaviorSubject, map, shareReplay
|
|
6
|
-
import { pie, arc,
|
|
7
|
-
import { scaleLinear, scaleBand } from 'd3-scale';
|
|
8
|
-
import { timeYear, timeMonth, timeWeek, timeDay } from 'd3-time';
|
|
9
|
-
import { timeFormat } from 'd3-time-format';
|
|
4
|
+
import { DecimalPipe, PercentPipe, CurrencyPipe, CommonModule } from '@angular/common';
|
|
5
|
+
import { BehaviorSubject, combineLatest, map, shareReplay } from 'rxjs';
|
|
6
|
+
import { pie, arc, stack, line } from 'd3-shape';
|
|
10
7
|
import { index } from 'd3-array';
|
|
8
|
+
import { scaleBand, scaleLinear } from 'd3-scale';
|
|
9
|
+
import { timeMonth, timeYear, timeWeek, timeDay } from 'd3-time';
|
|
10
|
+
import { timeFormat } from 'd3-time-format';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* DOM cache that clones existing elements if available.
|
|
@@ -362,6 +362,84 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
|
|
|
362
362
|
type: Input
|
|
363
363
|
}] } });
|
|
364
364
|
|
|
365
|
+
class DaysPipe {
|
|
366
|
+
constructor() {
|
|
367
|
+
this.inner = new DecimalPipe('en-us');
|
|
368
|
+
}
|
|
369
|
+
transform(value, digitsInfo) {
|
|
370
|
+
const ret = this.inner.transform(value, digitsInfo ?? '1.0-2');
|
|
371
|
+
return ret ? ret + (value === 1 ? ' day' : ' days') : '-';
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
DaysPipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DaysPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
375
|
+
DaysPipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "14.3.0", ngImport: i0, type: DaysPipe, name: "rivDays" });
|
|
376
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DaysPipe, decorators: [{
|
|
377
|
+
type: Pipe,
|
|
378
|
+
args: [{ name: 'rivDays' }]
|
|
379
|
+
}] });
|
|
380
|
+
|
|
381
|
+
class NumberPipe {
|
|
382
|
+
constructor() {
|
|
383
|
+
this.inner = new DecimalPipe('en-us');
|
|
384
|
+
}
|
|
385
|
+
transform(value, digitsInfo) {
|
|
386
|
+
return this.inner.transform(value, digitsInfo ?? '1.0-0') ?? '-';
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
NumberPipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: NumberPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
390
|
+
NumberPipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "14.3.0", ngImport: i0, type: NumberPipe, name: "rivNumber" });
|
|
391
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: NumberPipe, decorators: [{
|
|
392
|
+
type: Pipe,
|
|
393
|
+
args: [{ name: 'rivNumber' }]
|
|
394
|
+
}] });
|
|
395
|
+
|
|
396
|
+
class PercentagePipe {
|
|
397
|
+
constructor() {
|
|
398
|
+
this.inner = new PercentPipe('en-us');
|
|
399
|
+
}
|
|
400
|
+
transform(value, digitsInfo) {
|
|
401
|
+
return this.inner.transform(value, digitsInfo ?? '1.1-1') ?? '-';
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
PercentagePipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PercentagePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
405
|
+
PercentagePipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "14.3.0", ngImport: i0, type: PercentagePipe, name: "rivPercentage" });
|
|
406
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PercentagePipe, decorators: [{
|
|
407
|
+
type: Pipe,
|
|
408
|
+
args: [{ name: 'rivPercentage' }]
|
|
409
|
+
}] });
|
|
410
|
+
|
|
411
|
+
class SmallCurrencyPipe {
|
|
412
|
+
constructor() {
|
|
413
|
+
this.inner = new CurrencyPipe('en-us');
|
|
414
|
+
}
|
|
415
|
+
transform(value, digitsInfo) {
|
|
416
|
+
if (value === null) {
|
|
417
|
+
return '-';
|
|
418
|
+
}
|
|
419
|
+
const num = typeof value == 'string' ? Number.parseFloat(value) : value;
|
|
420
|
+
const magnitude = Math.log10(Math.abs(num));
|
|
421
|
+
if (num === 0) {
|
|
422
|
+
return (this.inner.transform(num, undefined, undefined, digitsInfo ?? '1.0-0') ?? '-');
|
|
423
|
+
}
|
|
424
|
+
if (magnitude >= 9) {
|
|
425
|
+
return ((this.inner.transform(num / 1000000000, undefined, undefined, digitsInfo ?? num / 1000000000 >= 100 ? '1.0-0' : '1.0-2') ?? '-') + 'B');
|
|
426
|
+
}
|
|
427
|
+
if (magnitude >= 6) {
|
|
428
|
+
return ((this.inner.transform(num / 1000000, undefined, undefined, digitsInfo ?? num / 1000000 >= 100 ? '1.0-0' : '1.0-2') ?? '-') + 'M');
|
|
429
|
+
}
|
|
430
|
+
if (magnitude >= 3) {
|
|
431
|
+
return ((this.inner.transform(num / 1000, undefined, undefined, digitsInfo ?? num / 1000 >= 100 ? '1.0-0' : '1.0-2') ?? '-') + 'K');
|
|
432
|
+
}
|
|
433
|
+
return (this.inner.transform(num, undefined, undefined, digitsInfo ?? num >= 100 ? '1.0-0' : '1.0-2') ?? '-');
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
SmallCurrencyPipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: SmallCurrencyPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
437
|
+
SmallCurrencyPipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "14.3.0", ngImport: i0, type: SmallCurrencyPipe, name: "rivSmallCurrency" });
|
|
438
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: SmallCurrencyPipe, decorators: [{
|
|
439
|
+
type: Pipe,
|
|
440
|
+
args: [{ name: 'rivSmallCurrency' }]
|
|
441
|
+
}] });
|
|
442
|
+
|
|
365
443
|
class CalloutService {
|
|
366
444
|
constructor() {
|
|
367
445
|
this.calloutStack$ = new BehaviorSubject([]);
|
|
@@ -593,6 +671,160 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
|
|
|
593
671
|
}]
|
|
594
672
|
}], ctorParameters: function () { return [{ type: i0.TemplateRef }, { type: CalloutService }]; } });
|
|
595
673
|
|
|
674
|
+
class TooltipComponent {
|
|
675
|
+
constructor() {
|
|
676
|
+
this.anchor = null;
|
|
677
|
+
this.theme = 'dark';
|
|
678
|
+
this.onMouseEnter = new EventEmitter();
|
|
679
|
+
this.onMouseLeave = new EventEmitter();
|
|
680
|
+
this.isTemplate = isTemplate;
|
|
681
|
+
}
|
|
682
|
+
_onMouseLeave(evt) {
|
|
683
|
+
this.onMouseLeave.emit(evt);
|
|
684
|
+
}
|
|
685
|
+
_onMouseEnter(evt) {
|
|
686
|
+
this.onMouseEnter.emit(evt);
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
TooltipComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: TooltipComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
690
|
+
TooltipComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: TooltipComponent, selector: "riv-tooltip", inputs: { anchor: "anchor", content: "content", theme: "theme" }, outputs: { onMouseEnter: "onMouseEnter", onMouseLeave: "onMouseLeave" }, host: { listeners: { "mouseleave": "_onMouseLeave()", "mouseenter": "_onMouseEnter()" } }, ngImport: i0, template: "<riv-callout\n [anchor]=\"anchor\"\n [preferredPosition]=\"'top-center'\"\n [allowedPositions]=\"[\n 'top-center',\n 'center-right',\n 'bottom-center',\n 'center-left'\n ]\"\n [isModal]=\"false\"\n [theme]=\"theme\"\n>\n <div class=\"content\">\n <ng-container *ngIf=\"content && isTemplate(content); else stringContent\">\n <ng-container *ngTemplateOutlet=\"content\"></ng-container>\n </ng-container>\n <ng-template #stringContent>\n {{ content }}\n </ng-template>\n </div>\n</riv-callout>\n", styles: [".content{padding:var(--size-xsmall) var(--size-small)}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: CalloutComponent, selector: "riv-callout", inputs: ["anchor", "isModal", "preferredPosition", "allowedPositions", "fallbackDirection", "showCaret", "theme"], outputs: ["close"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
691
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: TooltipComponent, decorators: [{
|
|
692
|
+
type: Component,
|
|
693
|
+
args: [{ selector: 'riv-tooltip', changeDetection: ChangeDetectionStrategy.OnPush, template: "<riv-callout\n [anchor]=\"anchor\"\n [preferredPosition]=\"'top-center'\"\n [allowedPositions]=\"[\n 'top-center',\n 'center-right',\n 'bottom-center',\n 'center-left'\n ]\"\n [isModal]=\"false\"\n [theme]=\"theme\"\n>\n <div class=\"content\">\n <ng-container *ngIf=\"content && isTemplate(content); else stringContent\">\n <ng-container *ngTemplateOutlet=\"content\"></ng-container>\n </ng-container>\n <ng-template #stringContent>\n {{ content }}\n </ng-template>\n </div>\n</riv-callout>\n", styles: [".content{padding:var(--size-xsmall) var(--size-small)}\n"] }]
|
|
694
|
+
}], propDecorators: { anchor: [{
|
|
695
|
+
type: Input
|
|
696
|
+
}], content: [{
|
|
697
|
+
type: Input
|
|
698
|
+
}], theme: [{
|
|
699
|
+
type: Input
|
|
700
|
+
}], onMouseEnter: [{
|
|
701
|
+
type: Output
|
|
702
|
+
}], onMouseLeave: [{
|
|
703
|
+
type: Output
|
|
704
|
+
}], _onMouseLeave: [{
|
|
705
|
+
type: HostListener,
|
|
706
|
+
args: ['mouseleave']
|
|
707
|
+
}], _onMouseEnter: [{
|
|
708
|
+
type: HostListener,
|
|
709
|
+
args: ['mouseenter']
|
|
710
|
+
}] } });
|
|
711
|
+
function isTemplate(v) {
|
|
712
|
+
return typeof v !== 'string';
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
class TooltipDirective {
|
|
716
|
+
constructor(el, applicationRef) {
|
|
717
|
+
this.el = el;
|
|
718
|
+
this.applicationRef = applicationRef;
|
|
719
|
+
this.rivTooltipTheme = 'dark';
|
|
720
|
+
this.closeDelay = 100;
|
|
721
|
+
}
|
|
722
|
+
onMouseEnter() {
|
|
723
|
+
if (!this.rivTooltip)
|
|
724
|
+
return;
|
|
725
|
+
if (this.tooltipRef) {
|
|
726
|
+
this.cancelClose();
|
|
727
|
+
}
|
|
728
|
+
else {
|
|
729
|
+
const tooltip = this.applicationRef.components[0].injector
|
|
730
|
+
.get(ViewContainerRef)
|
|
731
|
+
.createComponent(TooltipComponent);
|
|
732
|
+
tooltip.instance.anchor = this.el.nativeElement;
|
|
733
|
+
tooltip.instance.content = this.rivTooltip;
|
|
734
|
+
tooltip.instance.theme = this.rivTooltipTheme;
|
|
735
|
+
tooltip.instance.onMouseEnter.subscribe(this.cancelClose.bind(this));
|
|
736
|
+
tooltip.instance.onMouseLeave.subscribe(this.initiateClose.bind(this));
|
|
737
|
+
this.tooltipRef = tooltip;
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
onMouseLeave() {
|
|
741
|
+
this.initiateClose();
|
|
742
|
+
}
|
|
743
|
+
initiateClose() {
|
|
744
|
+
this.closeTimeout = window.setTimeout(() => {
|
|
745
|
+
this.tooltipRef?.destroy();
|
|
746
|
+
this.tooltipRef = undefined;
|
|
747
|
+
}, this.closeDelay);
|
|
748
|
+
}
|
|
749
|
+
cancelClose() {
|
|
750
|
+
window.clearTimeout(this.closeTimeout);
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
TooltipDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: TooltipDirective, deps: [{ token: i0.ElementRef }, { token: i0.ApplicationRef }], target: i0.ɵɵFactoryTarget.Directive });
|
|
754
|
+
TooltipDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.3.0", type: TooltipDirective, selector: "[rivTooltip]", inputs: { rivTooltip: "rivTooltip", rivTooltipTheme: "rivTooltipTheme", closeDelay: "closeDelay" }, host: { listeners: { "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()" } }, ngImport: i0 });
|
|
755
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: TooltipDirective, decorators: [{
|
|
756
|
+
type: Directive,
|
|
757
|
+
args: [{
|
|
758
|
+
selector: '[rivTooltip]',
|
|
759
|
+
}]
|
|
760
|
+
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ApplicationRef }]; }, propDecorators: { rivTooltip: [{
|
|
761
|
+
type: Input
|
|
762
|
+
}], rivTooltipTheme: [{
|
|
763
|
+
type: Input
|
|
764
|
+
}], closeDelay: [{
|
|
765
|
+
type: Input
|
|
766
|
+
}], onMouseEnter: [{
|
|
767
|
+
type: HostListener,
|
|
768
|
+
args: ['mouseenter']
|
|
769
|
+
}], onMouseLeave: [{
|
|
770
|
+
type: HostListener,
|
|
771
|
+
args: ['mouseleave']
|
|
772
|
+
}] } });
|
|
773
|
+
|
|
774
|
+
class DataTableRowComponent {
|
|
775
|
+
constructor() {
|
|
776
|
+
this.subRow = false;
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
DataTableRowComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DataTableRowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
780
|
+
DataTableRowComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: DataTableRowComponent, selector: "[riv-data-table-row]", inputs: { subRow: "subRow" }, host: { properties: { "class.sub-row": "this.subRow" } }, ngImport: i0, template: '<ng-content></ng-content>', isInline: true, styles: [":host:not(.sub-row){border-top:var(--border-width) solid var(--border-light)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
781
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DataTableRowComponent, decorators: [{
|
|
782
|
+
type: Component,
|
|
783
|
+
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: '[riv-data-table-row]', template: '<ng-content></ng-content>', styles: [":host:not(.sub-row){border-top:var(--border-width) solid var(--border-light)}\n"] }]
|
|
784
|
+
}], propDecorators: { subRow: [{
|
|
785
|
+
type: Input
|
|
786
|
+
}, {
|
|
787
|
+
type: HostBinding,
|
|
788
|
+
args: ['class.sub-row']
|
|
789
|
+
}] } });
|
|
790
|
+
|
|
791
|
+
class DataTableCellComponent {
|
|
792
|
+
constructor(row) {
|
|
793
|
+
this.row = row;
|
|
794
|
+
this.subCell = false;
|
|
795
|
+
}
|
|
796
|
+
ngOnInit() {
|
|
797
|
+
this.subCell = this.row.subRow;
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
DataTableCellComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DataTableCellComponent, deps: [{ token: DataTableRowComponent }], target: i0.ɵɵFactoryTarget.Component });
|
|
801
|
+
DataTableCellComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: DataTableCellComponent, selector: "[riv-data-table-cell]", host: { properties: { "class.sub-cell": "this.subCell" } }, ngImport: i0, template: '<ng-content></ng-content>', isInline: true, styles: [":host{padding:var(--size-large) 0;text-align:right}:host.sub-cell{padding-top:0;padding-left:var(--size-xlarge)}:host:first-child{position:sticky;left:0;z-index:1;background-color:var(--surface-light-0);text-align:left}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
802
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DataTableCellComponent, decorators: [{
|
|
803
|
+
type: Component,
|
|
804
|
+
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: '[riv-data-table-cell]', template: '<ng-content></ng-content>', styles: [":host{padding:var(--size-large) 0;text-align:right}:host.sub-cell{padding-top:0;padding-left:var(--size-xlarge)}:host:first-child{position:sticky;left:0;z-index:1;background-color:var(--surface-light-0);text-align:left}\n"] }]
|
|
805
|
+
}], ctorParameters: function () { return [{ type: DataTableRowComponent }]; }, propDecorators: { subCell: [{
|
|
806
|
+
type: HostBinding,
|
|
807
|
+
args: ['class.sub-cell']
|
|
808
|
+
}] } });
|
|
809
|
+
|
|
810
|
+
class DataTableComponent {
|
|
811
|
+
}
|
|
812
|
+
DataTableComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DataTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
813
|
+
DataTableComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: DataTableComponent, selector: "riv-data-table", ngImport: i0, template: '<table><ng-content></ng-content></table>', isInline: true, styles: [":host{display:block;overflow-x:auto}table{table-layout:fixed;min-width:100%;border-collapse:collapse}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
814
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DataTableComponent, decorators: [{
|
|
815
|
+
type: Component,
|
|
816
|
+
args: [{ selector: 'riv-data-table', template: '<table><ng-content></ng-content></table>', changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block;overflow-x:auto}table{table-layout:fixed;min-width:100%;border-collapse:collapse}\n"] }]
|
|
817
|
+
}] });
|
|
818
|
+
|
|
819
|
+
class DataTableHeaderCellComponent {
|
|
820
|
+
}
|
|
821
|
+
DataTableHeaderCellComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DataTableHeaderCellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
822
|
+
DataTableHeaderCellComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: DataTableHeaderCellComponent, selector: "[riv-data-table-header-cell]", ngImport: i0, template: '<ng-content></ng-content>', isInline: true, styles: [":host{padding:var(--size-large) 0;font-weight:var(--font-weight-heavy);text-align:right}:host:first-child{position:sticky;left:0;z-index:1;background-color:var(--surface-light-0);text-align:left}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
823
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DataTableHeaderCellComponent, decorators: [{
|
|
824
|
+
type: Component,
|
|
825
|
+
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: '[riv-data-table-header-cell]', template: '<ng-content></ng-content>', styles: [":host{padding:var(--size-large) 0;font-weight:var(--font-weight-heavy);text-align:right}:host:first-child{position:sticky;left:0;z-index:1;background-color:var(--surface-light-0);text-align:left}\n"] }]
|
|
826
|
+
}] });
|
|
827
|
+
|
|
596
828
|
class ZeroStateComponent {
|
|
597
829
|
constructor() {
|
|
598
830
|
this.message = 'No data to display.';
|
|
@@ -635,16 +867,18 @@ class DonutComponent {
|
|
|
635
867
|
}
|
|
636
868
|
}
|
|
637
869
|
DonutComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DonutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
638
|
-
DonutComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: DonutComponent, selector: "riv-donut", inputs: { displayLabel: "displayLabel", displayValue: "displayValue", data: "data" }, ngImport: i0, template: "<div *ngIf=\"!empty; else zeroState\" class=\"container\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"100%\"\n [attr.height]=\"HEIGHT\"\n viewBox=\"-128 -128 256 256\"\n >\n <path\n *ngFor=\"let path of arcPaths; let i = index\"\n [attr.d]=\"path\"\n [attr.fill]=\"getFillStyle(i)\"\n ></path>\n </svg>\n <div class=\"display\">\n <div class=\"value\">{{ displayValue }}</div>\n <div class=\"label\">{{ displayLabel }}</div>\n </div>\n</div>\n\n<ng-template #zeroState>\n <riv-zero-state></riv-zero-state>\n</ng-template>\n", styles: [".container{display:grid;grid-template-rows:1fr;grid-template-columns:1fr;justify-items:center;align-items:center}svg{grid-row:1 / 1;grid-column:1 / 1}.display{grid-row:1 / 1;grid-column:1 / 1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--size-small)}.value{font-size:var(--type-6-font-size);line-height:var(--type-6-line-height-0);font-weight:var(--font-weight-heavy)}.label{font-size:var(--type-1-font-size);line-height:var(--type-1-line-height-0);color:var(--type-light-low-contrast)}.value,.label{text-shadow:0 0 var(--size-small) var(--surface-light-0),0 0 var(--size-xsmall) var(--surface-light-0)}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: ZeroStateComponent, selector: "riv-zero-state", inputs: ["message"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
870
|
+
DonutComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: DonutComponent, selector: "riv-donut", inputs: { displayLabel: "displayLabel", displayValue: "displayValue", data: "data", displayTooltip: "displayTooltip" }, ngImport: i0, template: "<div *ngIf=\"!empty; else zeroState\" class=\"container\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"100%\"\n [attr.height]=\"HEIGHT\"\n viewBox=\"-128 -128 256 256\"\n >\n <path\n *ngFor=\"let path of arcPaths; let i = index\"\n [attr.d]=\"path\"\n [attr.fill]=\"getFillStyle(i)\"\n ></path>\n </svg>\n <div class=\"display\">\n <div class=\"value\" [rivTooltip]=\"displayTooltip\">{{ displayValue }}</div>\n <div class=\"label\">{{ displayLabel }}</div>\n </div>\n</div>\n\n<ng-template #zeroState>\n <riv-zero-state></riv-zero-state>\n</ng-template>\n", styles: [".container{display:grid;grid-template-rows:1fr;grid-template-columns:1fr;justify-items:center;align-items:center}svg{grid-row:1 / 1;grid-column:1 / 1}.display{grid-row:1 / 1;grid-column:1 / 1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--size-small)}.value{font-size:var(--type-6-font-size);line-height:var(--type-6-line-height-0);font-weight:var(--font-weight-heavy)}.label{font-size:var(--type-1-font-size);line-height:var(--type-1-line-height-0);color:var(--type-light-low-contrast)}.value,.label{text-shadow:0 0 var(--size-small) var(--surface-light-0),0 0 var(--size-xsmall) var(--surface-light-0)}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: TooltipDirective, selector: "[rivTooltip]", inputs: ["rivTooltip", "rivTooltipTheme", "closeDelay"] }, { kind: "component", type: ZeroStateComponent, selector: "riv-zero-state", inputs: ["message"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
639
871
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DonutComponent, decorators: [{
|
|
640
872
|
type: Component,
|
|
641
|
-
args: [{ selector: 'riv-donut', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div *ngIf=\"!empty; else zeroState\" class=\"container\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"100%\"\n [attr.height]=\"HEIGHT\"\n viewBox=\"-128 -128 256 256\"\n >\n <path\n *ngFor=\"let path of arcPaths; let i = index\"\n [attr.d]=\"path\"\n [attr.fill]=\"getFillStyle(i)\"\n ></path>\n </svg>\n <div class=\"display\">\n <div class=\"value\">{{ displayValue }}</div>\n <div class=\"label\">{{ displayLabel }}</div>\n </div>\n</div>\n\n<ng-template #zeroState>\n <riv-zero-state></riv-zero-state>\n</ng-template>\n", styles: [".container{display:grid;grid-template-rows:1fr;grid-template-columns:1fr;justify-items:center;align-items:center}svg{grid-row:1 / 1;grid-column:1 / 1}.display{grid-row:1 / 1;grid-column:1 / 1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--size-small)}.value{font-size:var(--type-6-font-size);line-height:var(--type-6-line-height-0);font-weight:var(--font-weight-heavy)}.label{font-size:var(--type-1-font-size);line-height:var(--type-1-line-height-0);color:var(--type-light-low-contrast)}.value,.label{text-shadow:0 0 var(--size-small) var(--surface-light-0),0 0 var(--size-xsmall) var(--surface-light-0)}\n"] }]
|
|
873
|
+
args: [{ selector: 'riv-donut', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div *ngIf=\"!empty; else zeroState\" class=\"container\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"100%\"\n [attr.height]=\"HEIGHT\"\n viewBox=\"-128 -128 256 256\"\n >\n <path\n *ngFor=\"let path of arcPaths; let i = index\"\n [attr.d]=\"path\"\n [attr.fill]=\"getFillStyle(i)\"\n ></path>\n </svg>\n <div class=\"display\">\n <div class=\"value\" [rivTooltip]=\"displayTooltip\">{{ displayValue }}</div>\n <div class=\"label\">{{ displayLabel }}</div>\n </div>\n</div>\n\n<ng-template #zeroState>\n <riv-zero-state></riv-zero-state>\n</ng-template>\n", styles: [".container{display:grid;grid-template-rows:1fr;grid-template-columns:1fr;justify-items:center;align-items:center}svg{grid-row:1 / 1;grid-column:1 / 1}.display{grid-row:1 / 1;grid-column:1 / 1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--size-small)}.value{font-size:var(--type-6-font-size);line-height:var(--type-6-line-height-0);font-weight:var(--font-weight-heavy)}.label{font-size:var(--type-1-font-size);line-height:var(--type-1-line-height-0);color:var(--type-light-low-contrast)}.value,.label{text-shadow:0 0 var(--size-small) var(--surface-light-0),0 0 var(--size-xsmall) var(--surface-light-0)}\n"] }]
|
|
642
874
|
}], propDecorators: { displayLabel: [{
|
|
643
875
|
type: Input
|
|
644
876
|
}], displayValue: [{
|
|
645
877
|
type: Input
|
|
646
878
|
}], data: [{
|
|
647
879
|
type: Input
|
|
880
|
+
}], displayTooltip: [{
|
|
881
|
+
type: Input
|
|
648
882
|
}] } });
|
|
649
883
|
|
|
650
884
|
class LegendItemComponent {
|
|
@@ -660,10 +894,10 @@ class LegendItemComponent {
|
|
|
660
894
|
}
|
|
661
895
|
}
|
|
662
896
|
LegendItemComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: LegendItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
663
|
-
LegendItemComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: LegendItemComponent, selector: "riv-legend-item", inputs: { label: "label", colorToken: "colorToken", style: "style", visibility: "visibility" }, outputs: { itemClick: "itemClick" }, ngImport: i0, template: "<button (click)=\"itemClick.emit()\">\n <i\n *ngIf=\"visibility === 'visible'\"\n [class.striped]=\"style === 'striped'\"\n [style.background-color]=\"backgroundColor\"\n ></i>\n <riv-icon\n *ngIf=\"visibility === 'hidden'\"\n name=\"EyeOff\"\n [size]=\"16\"\n ></riv-icon>\n <riv-icon *ngIf=\"visibility === 'locked'\" name=\"Lock\" [size]=\"16\"></riv-icon>\n</button>\n<span [class.low-contrast]=\"visibility === 'hidden' || visibility === 'locked'\">\n {{ label }}\n</span>\n", styles: [":host{display:inline-flex;align-items:center;gap:var(--size-small)}i{width:var(--size-large);height:var(--size-large)}i.striped{background-image:repeating-linear-gradient(315deg,transparent 0px,transparent 2.5px,var(--white-100) 2.5px,var(--white-100) 3.5px,transparent 3.5px,transparent 6px)}span{color:var(--type-light-low-contrast);font-size:var(--type-1-font-size);line-height:var(--type-1-line-height-0)}button{display:inline-flex}riv-icon,span.low-contrast{color:var(--type-light-disabled)}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: IconComponent, selector: "riv-icon", inputs: ["name", "size", "customSize", "strokeWidth"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
897
|
+
LegendItemComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: LegendItemComponent, selector: "riv-legend-item", inputs: { label: "label", colorToken: "colorToken", style: "style", visibility: "visibility", iconTooltip: "iconTooltip" }, outputs: { itemClick: "itemClick" }, ngImport: i0, template: "<button (click)=\"itemClick.emit()\" [rivTooltip]=\"iconTooltip\">\n <i\n *ngIf=\"visibility === 'visible'\"\n [class.striped]=\"style === 'striped'\"\n [style.background-color]=\"backgroundColor\"\n ></i>\n <riv-icon\n *ngIf=\"visibility === 'hidden'\"\n name=\"EyeOff\"\n [size]=\"16\"\n ></riv-icon>\n <riv-icon *ngIf=\"visibility === 'locked'\" name=\"Lock\" [size]=\"16\"></riv-icon>\n</button>\n<span [class.low-contrast]=\"visibility === 'hidden' || visibility === 'locked'\">\n {{ label }}\n</span>\n", styles: [":host{display:inline-flex;align-items:center;gap:var(--size-small)}i{width:var(--size-large);height:var(--size-large)}i.striped{background-image:repeating-linear-gradient(315deg,transparent 0px,transparent 2.5px,var(--white-100) 2.5px,var(--white-100) 3.5px,transparent 3.5px,transparent 6px)}span{color:var(--type-light-low-contrast);font-size:var(--type-1-font-size);line-height:var(--type-1-line-height-0)}button{display:inline-flex}riv-icon,span.low-contrast{color:var(--type-light-disabled)}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: IconComponent, selector: "riv-icon", inputs: ["name", "size", "customSize", "strokeWidth"] }, { kind: "directive", type: TooltipDirective, selector: "[rivTooltip]", inputs: ["rivTooltip", "rivTooltipTheme", "closeDelay"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
664
898
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: LegendItemComponent, decorators: [{
|
|
665
899
|
type: Component,
|
|
666
|
-
args: [{ selector: 'riv-legend-item', changeDetection: ChangeDetectionStrategy.OnPush, template: "<button (click)=\"itemClick.emit()\">\n <i\n *ngIf=\"visibility === 'visible'\"\n [class.striped]=\"style === 'striped'\"\n [style.background-color]=\"backgroundColor\"\n ></i>\n <riv-icon\n *ngIf=\"visibility === 'hidden'\"\n name=\"EyeOff\"\n [size]=\"16\"\n ></riv-icon>\n <riv-icon *ngIf=\"visibility === 'locked'\" name=\"Lock\" [size]=\"16\"></riv-icon>\n</button>\n<span [class.low-contrast]=\"visibility === 'hidden' || visibility === 'locked'\">\n {{ label }}\n</span>\n", styles: [":host{display:inline-flex;align-items:center;gap:var(--size-small)}i{width:var(--size-large);height:var(--size-large)}i.striped{background-image:repeating-linear-gradient(315deg,transparent 0px,transparent 2.5px,var(--white-100) 2.5px,var(--white-100) 3.5px,transparent 3.5px,transparent 6px)}span{color:var(--type-light-low-contrast);font-size:var(--type-1-font-size);line-height:var(--type-1-line-height-0)}button{display:inline-flex}riv-icon,span.low-contrast{color:var(--type-light-disabled)}\n"] }]
|
|
900
|
+
args: [{ selector: 'riv-legend-item', changeDetection: ChangeDetectionStrategy.OnPush, template: "<button (click)=\"itemClick.emit()\" [rivTooltip]=\"iconTooltip\">\n <i\n *ngIf=\"visibility === 'visible'\"\n [class.striped]=\"style === 'striped'\"\n [style.background-color]=\"backgroundColor\"\n ></i>\n <riv-icon\n *ngIf=\"visibility === 'hidden'\"\n name=\"EyeOff\"\n [size]=\"16\"\n ></riv-icon>\n <riv-icon *ngIf=\"visibility === 'locked'\" name=\"Lock\" [size]=\"16\"></riv-icon>\n</button>\n<span [class.low-contrast]=\"visibility === 'hidden' || visibility === 'locked'\">\n {{ label }}\n</span>\n", styles: [":host{display:inline-flex;align-items:center;gap:var(--size-small)}i{width:var(--size-large);height:var(--size-large)}i.striped{background-image:repeating-linear-gradient(315deg,transparent 0px,transparent 2.5px,var(--white-100) 2.5px,var(--white-100) 3.5px,transparent 3.5px,transparent 6px)}span{color:var(--type-light-low-contrast);font-size:var(--type-1-font-size);line-height:var(--type-1-line-height-0)}button{display:inline-flex}riv-icon,span.low-contrast{color:var(--type-light-disabled)}\n"] }]
|
|
667
901
|
}], propDecorators: { label: [{
|
|
668
902
|
type: Input
|
|
669
903
|
}], colorToken: [{
|
|
@@ -672,6 +906,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
|
|
|
672
906
|
type: Input
|
|
673
907
|
}], visibility: [{
|
|
674
908
|
type: Input
|
|
909
|
+
}], iconTooltip: [{
|
|
910
|
+
type: Input
|
|
675
911
|
}], itemClick: [{
|
|
676
912
|
type: Output
|
|
677
913
|
}] } });
|
|
@@ -696,30 +932,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
|
|
|
696
932
|
type: Input
|
|
697
933
|
}] } });
|
|
698
934
|
|
|
699
|
-
|
|
700
|
-
(function (Interval) {
|
|
701
|
-
Interval["DAY"] = "day";
|
|
702
|
-
Interval["WEEK"] = "week";
|
|
703
|
-
Interval["MONTH"] = "month";
|
|
704
|
-
Interval["YEAR"] = "year";
|
|
705
|
-
})(Interval || (Interval = {}));
|
|
706
|
-
function getTimeInterval(interval) {
|
|
707
|
-
switch (interval) {
|
|
708
|
-
case Interval.DAY:
|
|
709
|
-
return timeDay;
|
|
710
|
-
case Interval.WEEK:
|
|
711
|
-
return timeWeek;
|
|
712
|
-
case Interval.MONTH:
|
|
713
|
-
return timeMonth;
|
|
714
|
-
case Interval.YEAR:
|
|
715
|
-
return timeYear;
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
function getDateRange$1(configs) {
|
|
935
|
+
function getDateRange$1(stacks) {
|
|
719
936
|
let min = Infinity;
|
|
720
937
|
let max = -Infinity;
|
|
721
|
-
for (const
|
|
722
|
-
for (const series of
|
|
938
|
+
for (const stack of stacks) {
|
|
939
|
+
for (const series of stack) {
|
|
723
940
|
for (const { date } of series.data) {
|
|
724
941
|
const value = date.valueOf();
|
|
725
942
|
min = Math.min(min, value);
|
|
@@ -729,340 +946,22 @@ function getDateRange$1(configs) {
|
|
|
729
946
|
}
|
|
730
947
|
return [new Date(min), new Date(max)];
|
|
731
948
|
}
|
|
732
|
-
function getMinorIntervalFormat(interval) {
|
|
733
|
-
switch (interval) {
|
|
734
|
-
case Interval.DAY:
|
|
735
|
-
case Interval.WEEK:
|
|
736
|
-
return '%-d';
|
|
737
|
-
case Interval.MONTH:
|
|
738
|
-
return '%b';
|
|
739
|
-
case Interval.YEAR:
|
|
740
|
-
return '%Y';
|
|
741
|
-
}
|
|
742
|
-
}
|
|
743
|
-
function getMajorInterval(interval) {
|
|
744
|
-
switch (interval) {
|
|
745
|
-
case Interval.DAY:
|
|
746
|
-
case Interval.WEEK:
|
|
747
|
-
return Interval.MONTH;
|
|
748
|
-
default:
|
|
749
|
-
return Interval.YEAR;
|
|
750
|
-
}
|
|
751
|
-
}
|
|
752
|
-
function getMajorIntervalFormat(interval) {
|
|
753
|
-
switch (interval) {
|
|
754
|
-
case Interval.YEAR:
|
|
755
|
-
return '%Y';
|
|
756
|
-
case Interval.MONTH:
|
|
757
|
-
return '%b %Y';
|
|
758
|
-
default:
|
|
759
|
-
return '%d';
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
949
|
// TODO: once we upgrade to Angular 16, this component can be cleaned up with
|
|
763
|
-
// signals instead of RxJS.
|
|
764
|
-
class
|
|
950
|
+
// signals instead of RxJS.
|
|
951
|
+
class StackedColumnComponent {
|
|
765
952
|
constructor() {
|
|
766
|
-
this.input$ = new BehaviorSubject([
|
|
767
|
-
{
|
|
768
|
-
pointReducer: points => points.reduce((total, { value }) => total + value, 0),
|
|
769
|
-
valueFormatter: v => new DecimalPipe('en-US').transform(v) ?? '',
|
|
770
|
-
series: [],
|
|
771
|
-
},
|
|
772
|
-
]);
|
|
953
|
+
this.input$ = new BehaviorSubject([]);
|
|
773
954
|
this.width$ = new BehaviorSubject(960);
|
|
774
955
|
this.height$ = new BehaviorSubject(256);
|
|
775
|
-
this.
|
|
776
|
-
this.LEFT_OFFSET = 48;
|
|
777
|
-
this.TOP_PADDING = 16;
|
|
778
|
-
this.LEFT_RIGHT_PADDING = 8;
|
|
779
|
-
this.BOTTOM_PADDING = 8;
|
|
780
|
-
this.Y_TICK_COUNT = 5;
|
|
781
|
-
this.X_MINOR_TICK_LIMIT = 15;
|
|
782
|
-
this.dateRange$ = this.input$.pipe(map(getDateRange$1), shareReplay({ refCount: true, bufferSize: 1 }));
|
|
783
|
-
this.binInterval$ = this.dateRange$.pipe(map(([minDate, maxDate]) => {
|
|
784
|
-
const diff = timeDay.count(new Date(minDate), new Date(maxDate));
|
|
785
|
-
if (diff >= 365 * 3) {
|
|
786
|
-
return Interval.YEAR;
|
|
787
|
-
}
|
|
788
|
-
else if (diff >= 365) {
|
|
789
|
-
return Interval.MONTH;
|
|
790
|
-
}
|
|
791
|
-
else if (diff >= 90) {
|
|
792
|
-
return Interval.WEEK;
|
|
793
|
-
}
|
|
794
|
-
else {
|
|
795
|
-
return Interval.DAY;
|
|
796
|
-
}
|
|
797
|
-
}), shareReplay({ refCount: true, bufferSize: 1 }));
|
|
798
|
-
this.binnedData$ = combineLatest([this.input$, this.binInterval$]).pipe(map(([input, binInterval]) => input.map((config) => {
|
|
799
|
-
return {
|
|
800
|
-
...config,
|
|
801
|
-
series: config.series.map(series => {
|
|
802
|
-
const binned = new Map();
|
|
803
|
-
for (const point of series.data) {
|
|
804
|
-
const bin = getTimeInterval(binInterval)
|
|
805
|
-
.floor(point.date)
|
|
806
|
-
.valueOf();
|
|
807
|
-
if (!binned.has(bin)) {
|
|
808
|
-
binned.set(bin, []);
|
|
809
|
-
}
|
|
810
|
-
binned.get(bin).push(point);
|
|
811
|
-
}
|
|
812
|
-
return {
|
|
813
|
-
...series,
|
|
814
|
-
data: [...binned.entries()].map(([dateValue, points]) => ({
|
|
815
|
-
date: new Date(dateValue),
|
|
816
|
-
value: config.pointReducer(points),
|
|
817
|
-
})),
|
|
818
|
-
};
|
|
819
|
-
}),
|
|
820
|
-
};
|
|
821
|
-
})), shareReplay({ refCount: true, bufferSize: 1 }));
|
|
822
|
-
this.binnedDateRange$ = this.binnedData$.pipe(map(getDateRange$1), shareReplay({ refCount: true, bufferSize: 1 }));
|
|
956
|
+
this.valueFormatter = v => v.toString();
|
|
823
957
|
this.drawData$ = combineLatest([
|
|
824
|
-
this.
|
|
825
|
-
this.binnedDateRange$,
|
|
826
|
-
this.binInterval$,
|
|
958
|
+
this.input$,
|
|
827
959
|
this.width$,
|
|
828
960
|
this.height$,
|
|
829
|
-
]).pipe(map(([
|
|
830
|
-
const viewBox = `0 0 ${width} ${height}`;
|
|
831
|
-
const xScale = scaleLinear()
|
|
832
|
-
.domain(binnedDateRange)
|
|
833
|
-
.range([
|
|
834
|
-
this.LEFT_OFFSET + this.LEFT_RIGHT_PADDING,
|
|
835
|
-
width - this.LEFT_RIGHT_PADDING * 2,
|
|
836
|
-
]);
|
|
837
|
-
const xMinorIntervalFormat = getMinorIntervalFormat(binInterval);
|
|
838
|
-
const [minDateValue, maxDateValue] = binnedDateRange;
|
|
839
|
-
const minorFormatter = timeFormat(xMinorIntervalFormat);
|
|
840
|
-
const xMinorTicks = getTimeInterval(binInterval)
|
|
841
|
-
.range(minDateValue, timeDay.offset(maxDateValue, 1))
|
|
842
|
-
.map(date => ({
|
|
843
|
-
value: date.valueOf(),
|
|
844
|
-
label: minorFormatter(date),
|
|
845
|
-
}))
|
|
846
|
-
.filter((_, i, arr) => arr.length > this.X_MINOR_TICK_LIMIT
|
|
847
|
-
? i % Math.round(arr.length / this.X_MINOR_TICK_LIMIT) === 0
|
|
848
|
-
: true);
|
|
849
|
-
const xMajorInterval = getMajorInterval(binInterval);
|
|
850
|
-
const xMajorIntervalFormat = getMajorIntervalFormat(xMajorInterval);
|
|
851
|
-
const timeInterval = getTimeInterval(xMajorInterval);
|
|
852
|
-
const tickFloor = timeInterval.floor(minDateValue);
|
|
853
|
-
const tickCeiling = timeInterval.ceil(timeDay.offset(maxDateValue, 1));
|
|
854
|
-
const majorFormatter = timeFormat(xMajorIntervalFormat);
|
|
855
|
-
const xMajorTicks = timeInterval
|
|
856
|
-
.range(tickFloor, tickCeiling)
|
|
857
|
-
.map(tickDate => ({
|
|
858
|
-
label: xMajorInterval === binInterval ? '' : majorFormatter(tickDate),
|
|
859
|
-
value: tickDate.valueOf(),
|
|
860
|
-
}));
|
|
861
|
-
const x = { xMax: maxDateValue, xScale, xMinorTicks, xMajorTicks };
|
|
862
|
-
const [y1, y2] = binnedData.map(config => {
|
|
863
|
-
const flattenedValues = config.series.reduce((values, series) => [
|
|
864
|
-
...values,
|
|
865
|
-
...series.data.map(({ value }) => value),
|
|
866
|
-
], []);
|
|
867
|
-
const yMax = config.max ?? Math.max(...flattenedValues);
|
|
868
|
-
const yMin = config.min ?? Math.min(...flattenedValues, 0);
|
|
869
|
-
const yScale = scaleLinear()
|
|
870
|
-
.domain([yMin, yMax])
|
|
871
|
-
.range([
|
|
872
|
-
height -
|
|
873
|
-
this.BOTTOM_OFFSET -
|
|
874
|
-
(this.BOTTOM_PADDING + this.TOP_PADDING),
|
|
875
|
-
this.TOP_PADDING,
|
|
876
|
-
]);
|
|
877
|
-
const yTicks = yScale.ticks(this.Y_TICK_COUNT);
|
|
878
|
-
const series = config.series.map(series => ({
|
|
879
|
-
...series,
|
|
880
|
-
path: line()
|
|
881
|
-
.x(d => xScale(d.date))
|
|
882
|
-
.y(d => yScale(d.value))(series.data),
|
|
883
|
-
stroke: `var(${series.colorToken})`,
|
|
884
|
-
markers: series.data.map(point => ({
|
|
885
|
-
...point,
|
|
886
|
-
x: xScale(point.date),
|
|
887
|
-
y: yScale(point.value),
|
|
888
|
-
})),
|
|
889
|
-
}));
|
|
890
|
-
return {
|
|
891
|
-
...config,
|
|
892
|
-
series,
|
|
893
|
-
yMax,
|
|
894
|
-
yMin,
|
|
895
|
-
yScale,
|
|
896
|
-
yTicks,
|
|
897
|
-
};
|
|
898
|
-
});
|
|
899
|
-
// If we have a y2, coerce y1's ticks to be visually equivalent to y2's ticks.
|
|
900
|
-
if (y2?.yTicks) {
|
|
901
|
-
const tickConversionScale = scaleLinear()
|
|
902
|
-
.range(y1.yScale.domain())
|
|
903
|
-
.domain(y2.yScale.domain());
|
|
904
|
-
y1.yTicks = y2.yTicks.map(tickConversionScale);
|
|
905
|
-
}
|
|
906
|
-
return { viewBox, x, y1, y2 };
|
|
907
|
-
}), shareReplay({ refCount: true, bufferSize: 1 }));
|
|
908
|
-
this.legend$ = this.binnedData$.pipe(map(binnedData => binnedData.reduce((items, config) => [
|
|
909
|
-
...items,
|
|
910
|
-
...config.series.map(series => ({
|
|
911
|
-
label: series.label,
|
|
912
|
-
colorToken: series.colorToken,
|
|
913
|
-
})),
|
|
914
|
-
], [])));
|
|
915
|
-
this.empty$ = this.binnedData$.pipe(map(binnedData => binnedData.every(config => config.series.every(series => series.data.length === 0))), shareReplay({ refCount: true, bufferSize: 1 }));
|
|
916
|
-
this.hoveredMarker$ = new BehaviorSubject(null);
|
|
917
|
-
this.callout$ = combineLatest([this.hoveredMarker$, this.drawData$]).pipe(map(([hoveredMarker, drawData]) => {
|
|
918
|
-
if (!hoveredMarker)
|
|
919
|
-
return null;
|
|
920
|
-
const { target } = hoveredMarker.event;
|
|
921
|
-
if (!target)
|
|
922
|
-
return null;
|
|
923
|
-
const markerRect = target.getBoundingClientRect();
|
|
924
|
-
const padding = 8;
|
|
925
|
-
const anchor = new DOMRect(markerRect.left - padding, markerRect.top - padding, markerRect.width + padding * 2, markerRect.height + padding * 2);
|
|
926
|
-
const metrics = [];
|
|
927
|
-
for (const series of drawData.y1.series) {
|
|
928
|
-
const match = series.markers.find(marker => marker.x === hoveredMarker.marker.x);
|
|
929
|
-
if (match) {
|
|
930
|
-
metrics.push({
|
|
931
|
-
label: series.label,
|
|
932
|
-
value: drawData.y1.valueFormatter(match.value),
|
|
933
|
-
});
|
|
934
|
-
}
|
|
935
|
-
}
|
|
936
|
-
if (drawData.y2) {
|
|
937
|
-
for (const series of drawData.y2.series) {
|
|
938
|
-
const match = series.markers.find(marker => marker.x === hoveredMarker.marker.x);
|
|
939
|
-
if (match) {
|
|
940
|
-
metrics.push({
|
|
941
|
-
label: series.label,
|
|
942
|
-
value: drawData.y2.valueFormatter(match.value),
|
|
943
|
-
});
|
|
944
|
-
}
|
|
945
|
-
}
|
|
946
|
-
}
|
|
947
|
-
return { anchor, metrics };
|
|
948
|
-
}));
|
|
949
|
-
}
|
|
950
|
-
set input(v) {
|
|
951
|
-
this.input$.next(v);
|
|
952
|
-
}
|
|
953
|
-
get input() {
|
|
954
|
-
return this.input$.getValue();
|
|
955
|
-
}
|
|
956
|
-
set width(v) {
|
|
957
|
-
this.width$.next(v);
|
|
958
|
-
}
|
|
959
|
-
get width() {
|
|
960
|
-
return this.width$.getValue();
|
|
961
|
-
}
|
|
962
|
-
set height(v) {
|
|
963
|
-
this.height$.next(v);
|
|
964
|
-
}
|
|
965
|
-
get height() {
|
|
966
|
-
return this.height$.getValue();
|
|
967
|
-
}
|
|
968
|
-
}
|
|
969
|
-
TimeSeriesComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: TimeSeriesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
970
|
-
TimeSeriesComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: TimeSeriesComponent, selector: "riv-time-series", inputs: { input: "input", width: "width", height: "height" }, ngImport: i0, template: "<div *ngIf=\"!(empty$ | async); else zeroState\" class=\"container\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n *ngIf=\"drawData$ | async; let d\"\n [attr.viewBox]=\"d.viewBox\"\n >\n <g *ngFor=\"let tick of d.x.xMajorTicks\">\n <rect\n class=\"tick\"\n [attr.x]=\"d.x.xScale(tick.value)\"\n y=\"0\"\n width=\"1\"\n [attr.height]=\"d.y1.yScale(d.y1.yMin)\"\n ></rect>\n <text\n class=\"x-major-tick-label\"\n [attr.x]=\"d.x.xScale(tick.value)\"\n [attr.y]=\"d.y1.yScale(d.y1.yMin)\"\n dx=\"4\"\n dy=\"-4\"\n >\n {{ tick.label }}\n </text>\n </g>\n <g *ngFor=\"let tick of d.x.xMinorTicks\">\n <text\n class=\"x-minor-tick-label\"\n [attr.x]=\"d.x.xScale(tick.value)\"\n [attr.y]=\"d.y1.yScale(d.y1.yMin)\"\n text-anchor=\"middle\"\n dominant-baseline=\"hanging\"\n dy=\"8\"\n >\n {{ tick.label }}\n <title>{{ tick.value | date }}</title>\n </text>\n </g>\n <g *ngFor=\"let tick of d.y1.yTicks\">\n <rect\n class=\"tick\"\n x=\"0\"\n [attr.y]=\"d.y1.yScale(tick)\"\n width=\"100%\"\n height=\"1\"\n ></rect>\n <text class=\"y-tick-label\" x=\"0\" [attr.y]=\"d.y1.yScale(tick)\" dy=\"-4\">\n {{ d.y1.valueFormatter(tick) }}\n </text>\n </g>\n\n <g *ngFor=\"let tick of d.y2?.yTicks\">\n <text\n class=\"y-tick-label\"\n [attr.x]=\"d.x.xScale(d.x.xMax)\"\n [attr.y]=\"d.y2?.yScale(tick)\"\n text-anchor=\"end\"\n dy=\"-4\"\n >\n {{ d.y2?.valueFormatter(tick) }}\n </text>\n </g>\n\n <g *ngIf=\"hoveredMarker$ | async; let hoveredMarker\">\n <line\n class=\"hover-rule\"\n [attr.x1]=\"hoveredMarker.marker.x\"\n [attr.y1]=\"d.y1.yScale(d.y1.yMin)\"\n [attr.x2]=\"hoveredMarker.marker.x\"\n [attr.y2]=\"d.y1.yScale(d.y1.yMax)\"\n stroke-width=\"2\"\n stroke-dasharray=\"4\"\n />\n </g>\n\n <ng-template #seriesTpl let-series=\"series\">\n <path\n class=\"data path\"\n [class.marker-hovered]=\"!!(hoveredMarker$ | async)\"\n [attr.d]=\"series.path\"\n fill=\"none\"\n stroke-width=\"2\"\n [attr.stroke]=\"series.stroke\"\n [attr.stroke-dasharray]=\"series.style === 'dashed' ? '4' : null\"\n ></path>\n <circle\n *ngFor=\"let marker of series.markers\"\n class=\"data marker\"\n [class.focused]=\"(hoveredMarker$ | async)?.marker?.x === marker.x\"\n [class.blurred]=\"\n (hoveredMarker$ | async) !== null &&\n (hoveredMarker$ | async)?.marker?.x !== marker.x\n \"\n [attr.cx]=\"marker.x\"\n [attr.cy]=\"marker.y\"\n r=\"3.5\"\n stroke-width=\"2\"\n [attr.stroke]=\"series.stroke\"\n (mouseover)=\"hoveredMarker$.next({ event: $event, marker: marker })\"\n (mouseleave)=\"hoveredMarker$.next(null)\"\n ></circle>\n </ng-template>\n <g *ngFor=\"let series of d.y1.series\">\n <ng-container\n *ngTemplateOutlet=\"seriesTpl; context: { series: series }\"\n ></ng-container>\n </g>\n <g *ngFor=\"let series of d.y2?.series\">\n <ng-container\n *ngTemplateOutlet=\"seriesTpl; context: { series: series }\"\n ></ng-container>\n </g>\n </svg>\n <legend>\n <riv-legend-item\n *ngFor=\"let item of legend$ | async\"\n [label]=\"item.label\"\n [colorToken]=\"item.colorToken\"\n ></riv-legend-item>\n </legend>\n</div>\n\n<ng-container *ngIf=\"callout$ | async; let callout\">\n <riv-callout\n *riv-callout\n [anchor]=\"callout.anchor\"\n [isModal]=\"false\"\n [preferredPosition]=\"'top-center'\"\n >\n <div class=\"callout-content\">\n <div class=\"callout-metric\" *ngFor=\"let metric of callout.metrics\">\n <div>{{ metric.label }}</div>\n <div class=\"callout-metric-value\">{{ metric.value }}</div>\n </div>\n </div>\n </riv-callout>\n</ng-container>\n\n<ng-template #zeroState>\n <riv-zero-state></riv-zero-state>\n</ng-template>\n", styles: [".container{display:flex;flex-direction:column;gap:var(--size-xlarge)}.y-tick-label,.x-major-tick-label{font-size:var(--type-0-font-size);line-height:var(--type-0-line-height-0);fill:var(--type-light-low-contrast)}.x-minor-tick-label{font-size:var(--type-1-font-size);line-height:var(--type-1-line-height-0);fill:var(--type-light-low-contrast);text-anchor:middle}.tick{fill:var(--gray-20)}.data.path{transition:stroke-opacity var(--short-transition)}.data.path.marker-hovered{stroke-opacity:.4}.data.marker{fill:var(--surface-light-0);transition:stroke-opacity var(--short-transition)}.data.marker.focused{stroke-opacity:1;filter:drop-shadow(0 1px 1px rgba(10,2,22,.15))}.data.marker.blurred{stroke-opacity:.4}.hover-rule{stroke:var(--gray-20)}legend{display:flex;flex-wrap:wrap;gap:var(--size-large);justify-content:flex-start;align-items:baseline}.callout-content{padding:var(--size-large);display:flex;gap:var(--size-medium)}.callout-metric{display:flex;flex-direction:column;gap:var(--size-xsmall);font-size:var(--type-1-font-size);line-height:var(--type-1-line-height-0)}.callout-metric-value{font-weight:var(--font-weight-heavy)}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: CalloutComponent, selector: "riv-callout", inputs: ["anchor", "isModal", "preferredPosition", "allowedPositions", "fallbackDirection", "showCaret", "theme"], outputs: ["close"] }, { kind: "directive", type: CalloutDirective, selector: "[riv-callout]" }, { kind: "component", type: LegendItemComponent, selector: "riv-legend-item", inputs: ["label", "colorToken", "style", "visibility"], outputs: ["itemClick"] }, { kind: "component", type: ZeroStateComponent, selector: "riv-zero-state", inputs: ["message"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1.DatePipe, name: "date" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
971
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: TimeSeriesComponent, decorators: [{
|
|
972
|
-
type: Component,
|
|
973
|
-
args: [{ selector: 'riv-time-series', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div *ngIf=\"!(empty$ | async); else zeroState\" class=\"container\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n *ngIf=\"drawData$ | async; let d\"\n [attr.viewBox]=\"d.viewBox\"\n >\n <g *ngFor=\"let tick of d.x.xMajorTicks\">\n <rect\n class=\"tick\"\n [attr.x]=\"d.x.xScale(tick.value)\"\n y=\"0\"\n width=\"1\"\n [attr.height]=\"d.y1.yScale(d.y1.yMin)\"\n ></rect>\n <text\n class=\"x-major-tick-label\"\n [attr.x]=\"d.x.xScale(tick.value)\"\n [attr.y]=\"d.y1.yScale(d.y1.yMin)\"\n dx=\"4\"\n dy=\"-4\"\n >\n {{ tick.label }}\n </text>\n </g>\n <g *ngFor=\"let tick of d.x.xMinorTicks\">\n <text\n class=\"x-minor-tick-label\"\n [attr.x]=\"d.x.xScale(tick.value)\"\n [attr.y]=\"d.y1.yScale(d.y1.yMin)\"\n text-anchor=\"middle\"\n dominant-baseline=\"hanging\"\n dy=\"8\"\n >\n {{ tick.label }}\n <title>{{ tick.value | date }}</title>\n </text>\n </g>\n <g *ngFor=\"let tick of d.y1.yTicks\">\n <rect\n class=\"tick\"\n x=\"0\"\n [attr.y]=\"d.y1.yScale(tick)\"\n width=\"100%\"\n height=\"1\"\n ></rect>\n <text class=\"y-tick-label\" x=\"0\" [attr.y]=\"d.y1.yScale(tick)\" dy=\"-4\">\n {{ d.y1.valueFormatter(tick) }}\n </text>\n </g>\n\n <g *ngFor=\"let tick of d.y2?.yTicks\">\n <text\n class=\"y-tick-label\"\n [attr.x]=\"d.x.xScale(d.x.xMax)\"\n [attr.y]=\"d.y2?.yScale(tick)\"\n text-anchor=\"end\"\n dy=\"-4\"\n >\n {{ d.y2?.valueFormatter(tick) }}\n </text>\n </g>\n\n <g *ngIf=\"hoveredMarker$ | async; let hoveredMarker\">\n <line\n class=\"hover-rule\"\n [attr.x1]=\"hoveredMarker.marker.x\"\n [attr.y1]=\"d.y1.yScale(d.y1.yMin)\"\n [attr.x2]=\"hoveredMarker.marker.x\"\n [attr.y2]=\"d.y1.yScale(d.y1.yMax)\"\n stroke-width=\"2\"\n stroke-dasharray=\"4\"\n />\n </g>\n\n <ng-template #seriesTpl let-series=\"series\">\n <path\n class=\"data path\"\n [class.marker-hovered]=\"!!(hoveredMarker$ | async)\"\n [attr.d]=\"series.path\"\n fill=\"none\"\n stroke-width=\"2\"\n [attr.stroke]=\"series.stroke\"\n [attr.stroke-dasharray]=\"series.style === 'dashed' ? '4' : null\"\n ></path>\n <circle\n *ngFor=\"let marker of series.markers\"\n class=\"data marker\"\n [class.focused]=\"(hoveredMarker$ | async)?.marker?.x === marker.x\"\n [class.blurred]=\"\n (hoveredMarker$ | async) !== null &&\n (hoveredMarker$ | async)?.marker?.x !== marker.x\n \"\n [attr.cx]=\"marker.x\"\n [attr.cy]=\"marker.y\"\n r=\"3.5\"\n stroke-width=\"2\"\n [attr.stroke]=\"series.stroke\"\n (mouseover)=\"hoveredMarker$.next({ event: $event, marker: marker })\"\n (mouseleave)=\"hoveredMarker$.next(null)\"\n ></circle>\n </ng-template>\n <g *ngFor=\"let series of d.y1.series\">\n <ng-container\n *ngTemplateOutlet=\"seriesTpl; context: { series: series }\"\n ></ng-container>\n </g>\n <g *ngFor=\"let series of d.y2?.series\">\n <ng-container\n *ngTemplateOutlet=\"seriesTpl; context: { series: series }\"\n ></ng-container>\n </g>\n </svg>\n <legend>\n <riv-legend-item\n *ngFor=\"let item of legend$ | async\"\n [label]=\"item.label\"\n [colorToken]=\"item.colorToken\"\n ></riv-legend-item>\n </legend>\n</div>\n\n<ng-container *ngIf=\"callout$ | async; let callout\">\n <riv-callout\n *riv-callout\n [anchor]=\"callout.anchor\"\n [isModal]=\"false\"\n [preferredPosition]=\"'top-center'\"\n >\n <div class=\"callout-content\">\n <div class=\"callout-metric\" *ngFor=\"let metric of callout.metrics\">\n <div>{{ metric.label }}</div>\n <div class=\"callout-metric-value\">{{ metric.value }}</div>\n </div>\n </div>\n </riv-callout>\n</ng-container>\n\n<ng-template #zeroState>\n <riv-zero-state></riv-zero-state>\n</ng-template>\n", styles: [".container{display:flex;flex-direction:column;gap:var(--size-xlarge)}.y-tick-label,.x-major-tick-label{font-size:var(--type-0-font-size);line-height:var(--type-0-line-height-0);fill:var(--type-light-low-contrast)}.x-minor-tick-label{font-size:var(--type-1-font-size);line-height:var(--type-1-line-height-0);fill:var(--type-light-low-contrast);text-anchor:middle}.tick{fill:var(--gray-20)}.data.path{transition:stroke-opacity var(--short-transition)}.data.path.marker-hovered{stroke-opacity:.4}.data.marker{fill:var(--surface-light-0);transition:stroke-opacity var(--short-transition)}.data.marker.focused{stroke-opacity:1;filter:drop-shadow(0 1px 1px rgba(10,2,22,.15))}.data.marker.blurred{stroke-opacity:.4}.hover-rule{stroke:var(--gray-20)}legend{display:flex;flex-wrap:wrap;gap:var(--size-large);justify-content:flex-start;align-items:baseline}.callout-content{padding:var(--size-large);display:flex;gap:var(--size-medium)}.callout-metric{display:flex;flex-direction:column;gap:var(--size-xsmall);font-size:var(--type-1-font-size);line-height:var(--type-1-line-height-0)}.callout-metric-value{font-weight:var(--font-weight-heavy)}\n"] }]
|
|
974
|
-
}], propDecorators: { input: [{
|
|
975
|
-
type: Input
|
|
976
|
-
}], width: [{
|
|
977
|
-
type: Input
|
|
978
|
-
}], height: [{
|
|
979
|
-
type: Input
|
|
980
|
-
}] } });
|
|
981
|
-
|
|
982
|
-
class DataTableComponent {
|
|
983
|
-
}
|
|
984
|
-
DataTableComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DataTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
985
|
-
DataTableComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: DataTableComponent, selector: "riv-data-table", ngImport: i0, template: '<table><ng-content></ng-content></table>', isInline: true, styles: [":host{display:block;overflow-x:auto}table{table-layout:fixed;min-width:100%;border-collapse:collapse}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
986
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DataTableComponent, decorators: [{
|
|
987
|
-
type: Component,
|
|
988
|
-
args: [{ selector: 'riv-data-table', template: '<table><ng-content></ng-content></table>', changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block;overflow-x:auto}table{table-layout:fixed;min-width:100%;border-collapse:collapse}\n"] }]
|
|
989
|
-
}] });
|
|
990
|
-
|
|
991
|
-
class DataTableRowComponent {
|
|
992
|
-
constructor() {
|
|
993
|
-
this.subRow = false;
|
|
994
|
-
}
|
|
995
|
-
}
|
|
996
|
-
DataTableRowComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DataTableRowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
997
|
-
DataTableRowComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: DataTableRowComponent, selector: "[riv-data-table-row]", inputs: { subRow: "subRow" }, host: { properties: { "class.sub-row": "this.subRow" } }, ngImport: i0, template: '<ng-content></ng-content>', isInline: true, styles: [":host:not(.sub-row){border-top:var(--border-width) solid var(--border-light)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
998
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DataTableRowComponent, decorators: [{
|
|
999
|
-
type: Component,
|
|
1000
|
-
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: '[riv-data-table-row]', template: '<ng-content></ng-content>', styles: [":host:not(.sub-row){border-top:var(--border-width) solid var(--border-light)}\n"] }]
|
|
1001
|
-
}], propDecorators: { subRow: [{
|
|
1002
|
-
type: Input
|
|
1003
|
-
}, {
|
|
1004
|
-
type: HostBinding,
|
|
1005
|
-
args: ['class.sub-row']
|
|
1006
|
-
}] } });
|
|
1007
|
-
|
|
1008
|
-
class DataTableCellComponent {
|
|
1009
|
-
constructor(row) {
|
|
1010
|
-
this.row = row;
|
|
1011
|
-
this.subCell = false;
|
|
1012
|
-
}
|
|
1013
|
-
ngOnInit() {
|
|
1014
|
-
this.subCell = this.row.subRow;
|
|
1015
|
-
}
|
|
1016
|
-
}
|
|
1017
|
-
DataTableCellComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DataTableCellComponent, deps: [{ token: DataTableRowComponent }], target: i0.ɵɵFactoryTarget.Component });
|
|
1018
|
-
DataTableCellComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: DataTableCellComponent, selector: "[riv-data-table-cell]", host: { properties: { "class.sub-cell": "this.subCell" } }, ngImport: i0, template: '<ng-content></ng-content>', isInline: true, styles: [":host{padding:var(--size-large) 0;text-align:right}:host.sub-cell{padding-top:0;padding-left:var(--size-xlarge)}:host:first-child{position:sticky;left:0;z-index:1;background-color:var(--surface-light-0);text-align:left}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1019
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DataTableCellComponent, decorators: [{
|
|
1020
|
-
type: Component,
|
|
1021
|
-
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: '[riv-data-table-cell]', template: '<ng-content></ng-content>', styles: [":host{padding:var(--size-large) 0;text-align:right}:host.sub-cell{padding-top:0;padding-left:var(--size-xlarge)}:host:first-child{position:sticky;left:0;z-index:1;background-color:var(--surface-light-0);text-align:left}\n"] }]
|
|
1022
|
-
}], ctorParameters: function () { return [{ type: DataTableRowComponent }]; }, propDecorators: { subCell: [{
|
|
1023
|
-
type: HostBinding,
|
|
1024
|
-
args: ['class.sub-cell']
|
|
1025
|
-
}] } });
|
|
1026
|
-
|
|
1027
|
-
class DataTableHeaderCellComponent {
|
|
1028
|
-
}
|
|
1029
|
-
DataTableHeaderCellComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DataTableHeaderCellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1030
|
-
DataTableHeaderCellComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: DataTableHeaderCellComponent, selector: "[riv-data-table-header-cell]", ngImport: i0, template: '<ng-content></ng-content>', isInline: true, styles: [":host{padding:var(--size-large) 0;font-weight:var(--font-weight-heavy);text-align:right}:host:first-child{position:sticky;left:0;z-index:1;background-color:var(--surface-light-0);text-align:left}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1031
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DataTableHeaderCellComponent, decorators: [{
|
|
1032
|
-
type: Component,
|
|
1033
|
-
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: '[riv-data-table-header-cell]', template: '<ng-content></ng-content>', styles: [":host{padding:var(--size-large) 0;font-weight:var(--font-weight-heavy);text-align:right}:host:first-child{position:sticky;left:0;z-index:1;background-color:var(--surface-light-0);text-align:left}\n"] }]
|
|
1034
|
-
}] });
|
|
1035
|
-
|
|
1036
|
-
function getDateRange(stacks) {
|
|
1037
|
-
let min = Infinity;
|
|
1038
|
-
let max = -Infinity;
|
|
1039
|
-
for (const stack of stacks) {
|
|
1040
|
-
for (const series of stack) {
|
|
1041
|
-
for (const { date } of series.data) {
|
|
1042
|
-
const value = date.valueOf();
|
|
1043
|
-
min = Math.min(min, value);
|
|
1044
|
-
max = Math.max(max, value);
|
|
1045
|
-
}
|
|
1046
|
-
}
|
|
1047
|
-
}
|
|
1048
|
-
return [new Date(min), new Date(max)];
|
|
1049
|
-
}
|
|
1050
|
-
// TODO: once we upgrade to Angular 16, this component can be cleaned up with
|
|
1051
|
-
// signals instead of RxJS.
|
|
1052
|
-
class StackedColumnComponent {
|
|
1053
|
-
constructor() {
|
|
1054
|
-
this.input$ = new BehaviorSubject([]);
|
|
1055
|
-
this.width$ = new BehaviorSubject(960);
|
|
1056
|
-
this.height$ = new BehaviorSubject(256);
|
|
1057
|
-
this.valueFormatter = v => v.toString();
|
|
1058
|
-
this.drawData$ = combineLatest([
|
|
1059
|
-
this.input$,
|
|
1060
|
-
this.width$,
|
|
1061
|
-
this.height$,
|
|
1062
|
-
]).pipe(map(([input, width, height]) => {
|
|
961
|
+
]).pipe(map(([input, width, height]) => {
|
|
1063
962
|
const viewBox = `0 0 ${width} ${height}`;
|
|
1064
963
|
const padding = 8;
|
|
1065
|
-
const [minDate, maxDate] = getDateRange(input);
|
|
964
|
+
const [minDate, maxDate] = getDateRange$1(input);
|
|
1066
965
|
const xSteps = timeMonth.range(timeMonth.floor(minDate), timeMonth.floor(timeMonth.offset(maxDate, 1)));
|
|
1067
966
|
const xFormatter = timeFormat('%b');
|
|
1068
967
|
const xOuterScale = scaleBand()
|
|
@@ -1204,6 +1103,289 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
|
|
|
1204
1103
|
type: Input
|
|
1205
1104
|
}] } });
|
|
1206
1105
|
|
|
1106
|
+
var Interval;
|
|
1107
|
+
(function (Interval) {
|
|
1108
|
+
Interval["DAY"] = "day";
|
|
1109
|
+
Interval["WEEK"] = "week";
|
|
1110
|
+
Interval["MONTH"] = "month";
|
|
1111
|
+
Interval["YEAR"] = "year";
|
|
1112
|
+
})(Interval || (Interval = {}));
|
|
1113
|
+
function getTimeInterval(interval) {
|
|
1114
|
+
switch (interval) {
|
|
1115
|
+
case Interval.DAY:
|
|
1116
|
+
return timeDay;
|
|
1117
|
+
case Interval.WEEK:
|
|
1118
|
+
return timeWeek;
|
|
1119
|
+
case Interval.MONTH:
|
|
1120
|
+
return timeMonth;
|
|
1121
|
+
case Interval.YEAR:
|
|
1122
|
+
return timeYear;
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
function getDateRange(configs) {
|
|
1126
|
+
let min = Infinity;
|
|
1127
|
+
let max = -Infinity;
|
|
1128
|
+
for (const config of configs) {
|
|
1129
|
+
for (const series of config.series) {
|
|
1130
|
+
for (const { date } of series.data) {
|
|
1131
|
+
const value = date.valueOf();
|
|
1132
|
+
min = Math.min(min, value);
|
|
1133
|
+
max = Math.max(max, value);
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
return [new Date(min), new Date(max)];
|
|
1138
|
+
}
|
|
1139
|
+
function getMinorIntervalFormat(interval) {
|
|
1140
|
+
switch (interval) {
|
|
1141
|
+
case Interval.DAY:
|
|
1142
|
+
case Interval.WEEK:
|
|
1143
|
+
return '%-d';
|
|
1144
|
+
case Interval.MONTH:
|
|
1145
|
+
return '%b';
|
|
1146
|
+
case Interval.YEAR:
|
|
1147
|
+
return '%Y';
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
function getMajorInterval(interval) {
|
|
1151
|
+
switch (interval) {
|
|
1152
|
+
case Interval.DAY:
|
|
1153
|
+
case Interval.WEEK:
|
|
1154
|
+
return Interval.MONTH;
|
|
1155
|
+
default:
|
|
1156
|
+
return Interval.YEAR;
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
function getMajorIntervalFormat(interval) {
|
|
1160
|
+
switch (interval) {
|
|
1161
|
+
case Interval.YEAR:
|
|
1162
|
+
return '%Y';
|
|
1163
|
+
case Interval.MONTH:
|
|
1164
|
+
return '%b %Y';
|
|
1165
|
+
default:
|
|
1166
|
+
return '%d';
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
// TODO: once we upgrade to Angular 16, this component can be cleaned up with
|
|
1170
|
+
// signals instead of RxJS. See commit e238c2d.
|
|
1171
|
+
class TimeSeriesComponent {
|
|
1172
|
+
constructor() {
|
|
1173
|
+
this.input$ = new BehaviorSubject([
|
|
1174
|
+
{
|
|
1175
|
+
pointReducer: points => points.reduce((total, { value }) => total + value, 0),
|
|
1176
|
+
valueFormatter: v => new DecimalPipe('en-US').transform(v) ?? '',
|
|
1177
|
+
series: [],
|
|
1178
|
+
},
|
|
1179
|
+
]);
|
|
1180
|
+
this.width$ = new BehaviorSubject(960);
|
|
1181
|
+
this.height$ = new BehaviorSubject(256);
|
|
1182
|
+
this.BOTTOM_OFFSET = 24;
|
|
1183
|
+
this.LEFT_OFFSET = 48;
|
|
1184
|
+
this.TOP_PADDING = 16;
|
|
1185
|
+
this.LEFT_RIGHT_PADDING = 8;
|
|
1186
|
+
this.BOTTOM_PADDING = 8;
|
|
1187
|
+
this.Y_TICK_COUNT = 5;
|
|
1188
|
+
this.X_MINOR_TICK_LIMIT = 15;
|
|
1189
|
+
this.dateRange$ = this.input$.pipe(map(getDateRange), shareReplay({ refCount: true, bufferSize: 1 }));
|
|
1190
|
+
this.binInterval$ = this.dateRange$.pipe(map(([minDate, maxDate]) => {
|
|
1191
|
+
const diff = timeDay.count(new Date(minDate), new Date(maxDate));
|
|
1192
|
+
if (diff >= 365 * 3) {
|
|
1193
|
+
return Interval.YEAR;
|
|
1194
|
+
}
|
|
1195
|
+
else if (diff >= 365) {
|
|
1196
|
+
return Interval.MONTH;
|
|
1197
|
+
}
|
|
1198
|
+
else if (diff >= 90) {
|
|
1199
|
+
return Interval.WEEK;
|
|
1200
|
+
}
|
|
1201
|
+
else {
|
|
1202
|
+
return Interval.DAY;
|
|
1203
|
+
}
|
|
1204
|
+
}), shareReplay({ refCount: true, bufferSize: 1 }));
|
|
1205
|
+
this.binnedData$ = combineLatest([this.input$, this.binInterval$]).pipe(map(([input, binInterval]) => input.map((config) => {
|
|
1206
|
+
return {
|
|
1207
|
+
...config,
|
|
1208
|
+
series: config.series.map(series => {
|
|
1209
|
+
const binned = new Map();
|
|
1210
|
+
for (const point of series.data) {
|
|
1211
|
+
const bin = getTimeInterval(binInterval)
|
|
1212
|
+
.floor(point.date)
|
|
1213
|
+
.valueOf();
|
|
1214
|
+
if (!binned.has(bin)) {
|
|
1215
|
+
binned.set(bin, []);
|
|
1216
|
+
}
|
|
1217
|
+
binned.get(bin).push(point);
|
|
1218
|
+
}
|
|
1219
|
+
return {
|
|
1220
|
+
...series,
|
|
1221
|
+
data: [...binned.entries()].map(([dateValue, points]) => ({
|
|
1222
|
+
date: new Date(dateValue),
|
|
1223
|
+
value: config.pointReducer(points),
|
|
1224
|
+
})),
|
|
1225
|
+
};
|
|
1226
|
+
}),
|
|
1227
|
+
};
|
|
1228
|
+
})), shareReplay({ refCount: true, bufferSize: 1 }));
|
|
1229
|
+
this.binnedDateRange$ = this.binnedData$.pipe(map(getDateRange), shareReplay({ refCount: true, bufferSize: 1 }));
|
|
1230
|
+
this.drawData$ = combineLatest([
|
|
1231
|
+
this.binnedData$,
|
|
1232
|
+
this.binnedDateRange$,
|
|
1233
|
+
this.binInterval$,
|
|
1234
|
+
this.width$,
|
|
1235
|
+
this.height$,
|
|
1236
|
+
]).pipe(map(([binnedData, binnedDateRange, binInterval, width, height]) => {
|
|
1237
|
+
const viewBox = `0 0 ${width} ${height}`;
|
|
1238
|
+
const xScale = scaleLinear()
|
|
1239
|
+
.domain(binnedDateRange)
|
|
1240
|
+
.range([
|
|
1241
|
+
this.LEFT_OFFSET + this.LEFT_RIGHT_PADDING,
|
|
1242
|
+
width - this.LEFT_RIGHT_PADDING * 2,
|
|
1243
|
+
]);
|
|
1244
|
+
const xMinorIntervalFormat = getMinorIntervalFormat(binInterval);
|
|
1245
|
+
const [minDateValue, maxDateValue] = binnedDateRange;
|
|
1246
|
+
const minorFormatter = timeFormat(xMinorIntervalFormat);
|
|
1247
|
+
const xMinorTicks = getTimeInterval(binInterval)
|
|
1248
|
+
.range(minDateValue, timeDay.offset(maxDateValue, 1))
|
|
1249
|
+
.map(date => ({
|
|
1250
|
+
value: date.valueOf(),
|
|
1251
|
+
label: minorFormatter(date),
|
|
1252
|
+
}))
|
|
1253
|
+
.filter((_, i, arr) => arr.length > this.X_MINOR_TICK_LIMIT
|
|
1254
|
+
? i % Math.round(arr.length / this.X_MINOR_TICK_LIMIT) === 0
|
|
1255
|
+
: true);
|
|
1256
|
+
const xMajorInterval = getMajorInterval(binInterval);
|
|
1257
|
+
const xMajorIntervalFormat = getMajorIntervalFormat(xMajorInterval);
|
|
1258
|
+
const timeInterval = getTimeInterval(xMajorInterval);
|
|
1259
|
+
const tickFloor = timeInterval.floor(minDateValue);
|
|
1260
|
+
const tickCeiling = timeInterval.ceil(timeDay.offset(maxDateValue, 1));
|
|
1261
|
+
const majorFormatter = timeFormat(xMajorIntervalFormat);
|
|
1262
|
+
const xMajorTicks = timeInterval
|
|
1263
|
+
.range(tickFloor, tickCeiling)
|
|
1264
|
+
.map(tickDate => ({
|
|
1265
|
+
label: xMajorInterval === binInterval ? '' : majorFormatter(tickDate),
|
|
1266
|
+
value: tickDate.valueOf(),
|
|
1267
|
+
}));
|
|
1268
|
+
const x = { xMax: maxDateValue, xScale, xMinorTicks, xMajorTicks };
|
|
1269
|
+
const [y1, y2] = binnedData.map(config => {
|
|
1270
|
+
const flattenedValues = config.series.reduce((values, series) => [
|
|
1271
|
+
...values,
|
|
1272
|
+
...series.data.map(({ value }) => value),
|
|
1273
|
+
], []);
|
|
1274
|
+
const yMax = config.max ?? Math.max(...flattenedValues);
|
|
1275
|
+
const yMin = config.min ?? Math.min(...flattenedValues, 0);
|
|
1276
|
+
const yScale = scaleLinear()
|
|
1277
|
+
.domain([yMin, yMax])
|
|
1278
|
+
.range([
|
|
1279
|
+
height -
|
|
1280
|
+
this.BOTTOM_OFFSET -
|
|
1281
|
+
(this.BOTTOM_PADDING + this.TOP_PADDING),
|
|
1282
|
+
this.TOP_PADDING,
|
|
1283
|
+
]);
|
|
1284
|
+
const yTicks = yScale.ticks(this.Y_TICK_COUNT);
|
|
1285
|
+
const series = config.series.map(series => ({
|
|
1286
|
+
...series,
|
|
1287
|
+
path: line()
|
|
1288
|
+
.x(d => xScale(d.date))
|
|
1289
|
+
.y(d => yScale(d.value))(series.data),
|
|
1290
|
+
stroke: `var(${series.colorToken})`,
|
|
1291
|
+
markers: series.data.map(point => ({
|
|
1292
|
+
...point,
|
|
1293
|
+
x: xScale(point.date),
|
|
1294
|
+
y: yScale(point.value),
|
|
1295
|
+
})),
|
|
1296
|
+
}));
|
|
1297
|
+
return {
|
|
1298
|
+
...config,
|
|
1299
|
+
series,
|
|
1300
|
+
yMax,
|
|
1301
|
+
yMin,
|
|
1302
|
+
yScale,
|
|
1303
|
+
yTicks,
|
|
1304
|
+
};
|
|
1305
|
+
});
|
|
1306
|
+
// If we have a y2, coerce y1's ticks to be visually equivalent to y2's ticks.
|
|
1307
|
+
if (y2?.yTicks) {
|
|
1308
|
+
const tickConversionScale = scaleLinear()
|
|
1309
|
+
.range(y1.yScale.domain())
|
|
1310
|
+
.domain(y2.yScale.domain());
|
|
1311
|
+
y1.yTicks = y2.yTicks.map(tickConversionScale);
|
|
1312
|
+
}
|
|
1313
|
+
return { viewBox, x, y1, y2 };
|
|
1314
|
+
}), shareReplay({ refCount: true, bufferSize: 1 }));
|
|
1315
|
+
this.legend$ = this.binnedData$.pipe(map(binnedData => binnedData.reduce((items, config) => [
|
|
1316
|
+
...items,
|
|
1317
|
+
...config.series.map(series => ({
|
|
1318
|
+
label: series.label,
|
|
1319
|
+
colorToken: series.colorToken,
|
|
1320
|
+
})),
|
|
1321
|
+
], [])));
|
|
1322
|
+
this.empty$ = this.binnedData$.pipe(map(binnedData => binnedData.every(config => config.series.every(series => series.data.length === 0))), shareReplay({ refCount: true, bufferSize: 1 }));
|
|
1323
|
+
this.hoveredMarker$ = new BehaviorSubject(null);
|
|
1324
|
+
this.callout$ = combineLatest([this.hoveredMarker$, this.drawData$]).pipe(map(([hoveredMarker, drawData]) => {
|
|
1325
|
+
if (!hoveredMarker)
|
|
1326
|
+
return null;
|
|
1327
|
+
const { target } = hoveredMarker.event;
|
|
1328
|
+
if (!target)
|
|
1329
|
+
return null;
|
|
1330
|
+
const markerRect = target.getBoundingClientRect();
|
|
1331
|
+
const padding = 8;
|
|
1332
|
+
const anchor = new DOMRect(markerRect.left - padding, markerRect.top - padding, markerRect.width + padding * 2, markerRect.height + padding * 2);
|
|
1333
|
+
const metrics = [];
|
|
1334
|
+
for (const series of drawData.y1.series) {
|
|
1335
|
+
const match = series.markers.find(marker => marker.x === hoveredMarker.marker.x);
|
|
1336
|
+
if (match) {
|
|
1337
|
+
metrics.push({
|
|
1338
|
+
label: series.label,
|
|
1339
|
+
value: drawData.y1.valueFormatter(match.value),
|
|
1340
|
+
});
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
if (drawData.y2) {
|
|
1344
|
+
for (const series of drawData.y2.series) {
|
|
1345
|
+
const match = series.markers.find(marker => marker.x === hoveredMarker.marker.x);
|
|
1346
|
+
if (match) {
|
|
1347
|
+
metrics.push({
|
|
1348
|
+
label: series.label,
|
|
1349
|
+
value: drawData.y2.valueFormatter(match.value),
|
|
1350
|
+
});
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
return { anchor, metrics };
|
|
1355
|
+
}));
|
|
1356
|
+
}
|
|
1357
|
+
set input(v) {
|
|
1358
|
+
this.input$.next(v);
|
|
1359
|
+
}
|
|
1360
|
+
get input() {
|
|
1361
|
+
return this.input$.getValue();
|
|
1362
|
+
}
|
|
1363
|
+
set width(v) {
|
|
1364
|
+
this.width$.next(v);
|
|
1365
|
+
}
|
|
1366
|
+
get width() {
|
|
1367
|
+
return this.width$.getValue();
|
|
1368
|
+
}
|
|
1369
|
+
set height(v) {
|
|
1370
|
+
this.height$.next(v);
|
|
1371
|
+
}
|
|
1372
|
+
get height() {
|
|
1373
|
+
return this.height$.getValue();
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
TimeSeriesComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: TimeSeriesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1377
|
+
TimeSeriesComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: TimeSeriesComponent, selector: "riv-time-series", inputs: { input: "input", width: "width", height: "height" }, ngImport: i0, template: "<div *ngIf=\"!(empty$ | async); else zeroState\" class=\"container\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n *ngIf=\"drawData$ | async; let d\"\n [attr.viewBox]=\"d.viewBox\"\n >\n <g *ngFor=\"let tick of d.x.xMajorTicks\">\n <rect\n class=\"tick\"\n [attr.x]=\"d.x.xScale(tick.value)\"\n y=\"0\"\n width=\"1\"\n [attr.height]=\"d.y1.yScale(d.y1.yMin)\"\n ></rect>\n <text\n class=\"x-major-tick-label\"\n [attr.x]=\"d.x.xScale(tick.value)\"\n [attr.y]=\"d.y1.yScale(d.y1.yMin)\"\n dx=\"4\"\n dy=\"-4\"\n >\n {{ tick.label }}\n </text>\n </g>\n <g *ngFor=\"let tick of d.x.xMinorTicks\">\n <text\n class=\"x-minor-tick-label\"\n [attr.x]=\"d.x.xScale(tick.value)\"\n [attr.y]=\"d.y1.yScale(d.y1.yMin)\"\n text-anchor=\"middle\"\n dominant-baseline=\"hanging\"\n dy=\"8\"\n >\n {{ tick.label }}\n <title>{{ tick.value | date }}</title>\n </text>\n </g>\n <g *ngFor=\"let tick of d.y1.yTicks\">\n <rect\n class=\"tick\"\n x=\"0\"\n [attr.y]=\"d.y1.yScale(tick)\"\n width=\"100%\"\n height=\"1\"\n ></rect>\n <text class=\"y-tick-label\" x=\"0\" [attr.y]=\"d.y1.yScale(tick)\" dy=\"-4\">\n {{ d.y1.valueFormatter(tick) }}\n </text>\n </g>\n\n <g *ngFor=\"let tick of d.y2?.yTicks\">\n <text\n class=\"y-tick-label\"\n [attr.x]=\"d.x.xScale(d.x.xMax)\"\n [attr.y]=\"d.y2?.yScale(tick)\"\n text-anchor=\"end\"\n dy=\"-4\"\n >\n {{ d.y2?.valueFormatter(tick) }}\n </text>\n </g>\n\n <g *ngIf=\"hoveredMarker$ | async; let hoveredMarker\">\n <line\n class=\"hover-rule\"\n [attr.x1]=\"hoveredMarker.marker.x\"\n [attr.y1]=\"d.y1.yScale(d.y1.yMin)\"\n [attr.x2]=\"hoveredMarker.marker.x\"\n [attr.y2]=\"d.y1.yScale(d.y1.yMax)\"\n stroke-width=\"2\"\n stroke-dasharray=\"4\"\n />\n </g>\n\n <ng-template #seriesTpl let-series=\"series\">\n <path\n class=\"data path\"\n [class.marker-hovered]=\"!!(hoveredMarker$ | async)\"\n [attr.d]=\"series.path\"\n fill=\"none\"\n stroke-width=\"2\"\n [attr.stroke]=\"series.stroke\"\n [attr.stroke-dasharray]=\"series.style === 'dashed' ? '4' : null\"\n ></path>\n <circle\n *ngFor=\"let marker of series.markers\"\n class=\"data marker\"\n [class.focused]=\"(hoveredMarker$ | async)?.marker?.x === marker.x\"\n [class.blurred]=\"\n (hoveredMarker$ | async) !== null &&\n (hoveredMarker$ | async)?.marker?.x !== marker.x\n \"\n [attr.cx]=\"marker.x\"\n [attr.cy]=\"marker.y\"\n r=\"3.5\"\n stroke-width=\"2\"\n [attr.stroke]=\"series.stroke\"\n (mouseover)=\"hoveredMarker$.next({ event: $event, marker: marker })\"\n (mouseleave)=\"hoveredMarker$.next(null)\"\n ></circle>\n </ng-template>\n <g *ngFor=\"let series of d.y1.series\">\n <ng-container\n *ngTemplateOutlet=\"seriesTpl; context: { series: series }\"\n ></ng-container>\n </g>\n <g *ngFor=\"let series of d.y2?.series\">\n <ng-container\n *ngTemplateOutlet=\"seriesTpl; context: { series: series }\"\n ></ng-container>\n </g>\n </svg>\n <legend>\n <riv-legend-item\n *ngFor=\"let item of legend$ | async\"\n [label]=\"item.label\"\n [colorToken]=\"item.colorToken\"\n ></riv-legend-item>\n </legend>\n</div>\n\n<ng-container *ngIf=\"callout$ | async; let callout\">\n <riv-callout\n *riv-callout\n [anchor]=\"callout.anchor\"\n [isModal]=\"false\"\n [preferredPosition]=\"'top-center'\"\n >\n <div class=\"callout-content\">\n <div class=\"callout-metric\" *ngFor=\"let metric of callout.metrics\">\n <div>{{ metric.label }}</div>\n <div class=\"callout-metric-value\">{{ metric.value }}</div>\n </div>\n </div>\n </riv-callout>\n</ng-container>\n\n<ng-template #zeroState>\n <riv-zero-state></riv-zero-state>\n</ng-template>\n", styles: [".container{display:flex;flex-direction:column;gap:var(--size-xlarge)}.y-tick-label,.x-major-tick-label{font-size:var(--type-0-font-size);line-height:var(--type-0-line-height-0);fill:var(--type-light-low-contrast)}.x-minor-tick-label{font-size:var(--type-1-font-size);line-height:var(--type-1-line-height-0);fill:var(--type-light-low-contrast);text-anchor:middle}.tick{fill:var(--gray-20)}.data.path{transition:stroke-opacity var(--short-transition)}.data.path.marker-hovered{stroke-opacity:.4}.data.marker{fill:var(--surface-light-0);transition:stroke-opacity var(--short-transition)}.data.marker.focused{stroke-opacity:1;filter:drop-shadow(0 1px 1px rgba(10,2,22,.15))}.data.marker.blurred{stroke-opacity:.4}.hover-rule{stroke:var(--gray-20)}legend{display:flex;flex-wrap:wrap;gap:var(--size-large);justify-content:flex-start;align-items:baseline}.callout-content{padding:var(--size-large);display:flex;gap:var(--size-medium)}.callout-metric{display:flex;flex-direction:column;gap:var(--size-xsmall);font-size:var(--type-1-font-size);line-height:var(--type-1-line-height-0)}.callout-metric-value{font-weight:var(--font-weight-heavy)}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: CalloutComponent, selector: "riv-callout", inputs: ["anchor", "isModal", "preferredPosition", "allowedPositions", "fallbackDirection", "showCaret", "theme"], outputs: ["close"] }, { kind: "directive", type: CalloutDirective, selector: "[riv-callout]" }, { kind: "component", type: LegendItemComponent, selector: "riv-legend-item", inputs: ["label", "colorToken", "style", "visibility", "iconTooltip"], outputs: ["itemClick"] }, { kind: "component", type: ZeroStateComponent, selector: "riv-zero-state", inputs: ["message"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1.DatePipe, name: "date" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1378
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: TimeSeriesComponent, decorators: [{
|
|
1379
|
+
type: Component,
|
|
1380
|
+
args: [{ selector: 'riv-time-series', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div *ngIf=\"!(empty$ | async); else zeroState\" class=\"container\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n *ngIf=\"drawData$ | async; let d\"\n [attr.viewBox]=\"d.viewBox\"\n >\n <g *ngFor=\"let tick of d.x.xMajorTicks\">\n <rect\n class=\"tick\"\n [attr.x]=\"d.x.xScale(tick.value)\"\n y=\"0\"\n width=\"1\"\n [attr.height]=\"d.y1.yScale(d.y1.yMin)\"\n ></rect>\n <text\n class=\"x-major-tick-label\"\n [attr.x]=\"d.x.xScale(tick.value)\"\n [attr.y]=\"d.y1.yScale(d.y1.yMin)\"\n dx=\"4\"\n dy=\"-4\"\n >\n {{ tick.label }}\n </text>\n </g>\n <g *ngFor=\"let tick of d.x.xMinorTicks\">\n <text\n class=\"x-minor-tick-label\"\n [attr.x]=\"d.x.xScale(tick.value)\"\n [attr.y]=\"d.y1.yScale(d.y1.yMin)\"\n text-anchor=\"middle\"\n dominant-baseline=\"hanging\"\n dy=\"8\"\n >\n {{ tick.label }}\n <title>{{ tick.value | date }}</title>\n </text>\n </g>\n <g *ngFor=\"let tick of d.y1.yTicks\">\n <rect\n class=\"tick\"\n x=\"0\"\n [attr.y]=\"d.y1.yScale(tick)\"\n width=\"100%\"\n height=\"1\"\n ></rect>\n <text class=\"y-tick-label\" x=\"0\" [attr.y]=\"d.y1.yScale(tick)\" dy=\"-4\">\n {{ d.y1.valueFormatter(tick) }}\n </text>\n </g>\n\n <g *ngFor=\"let tick of d.y2?.yTicks\">\n <text\n class=\"y-tick-label\"\n [attr.x]=\"d.x.xScale(d.x.xMax)\"\n [attr.y]=\"d.y2?.yScale(tick)\"\n text-anchor=\"end\"\n dy=\"-4\"\n >\n {{ d.y2?.valueFormatter(tick) }}\n </text>\n </g>\n\n <g *ngIf=\"hoveredMarker$ | async; let hoveredMarker\">\n <line\n class=\"hover-rule\"\n [attr.x1]=\"hoveredMarker.marker.x\"\n [attr.y1]=\"d.y1.yScale(d.y1.yMin)\"\n [attr.x2]=\"hoveredMarker.marker.x\"\n [attr.y2]=\"d.y1.yScale(d.y1.yMax)\"\n stroke-width=\"2\"\n stroke-dasharray=\"4\"\n />\n </g>\n\n <ng-template #seriesTpl let-series=\"series\">\n <path\n class=\"data path\"\n [class.marker-hovered]=\"!!(hoveredMarker$ | async)\"\n [attr.d]=\"series.path\"\n fill=\"none\"\n stroke-width=\"2\"\n [attr.stroke]=\"series.stroke\"\n [attr.stroke-dasharray]=\"series.style === 'dashed' ? '4' : null\"\n ></path>\n <circle\n *ngFor=\"let marker of series.markers\"\n class=\"data marker\"\n [class.focused]=\"(hoveredMarker$ | async)?.marker?.x === marker.x\"\n [class.blurred]=\"\n (hoveredMarker$ | async) !== null &&\n (hoveredMarker$ | async)?.marker?.x !== marker.x\n \"\n [attr.cx]=\"marker.x\"\n [attr.cy]=\"marker.y\"\n r=\"3.5\"\n stroke-width=\"2\"\n [attr.stroke]=\"series.stroke\"\n (mouseover)=\"hoveredMarker$.next({ event: $event, marker: marker })\"\n (mouseleave)=\"hoveredMarker$.next(null)\"\n ></circle>\n </ng-template>\n <g *ngFor=\"let series of d.y1.series\">\n <ng-container\n *ngTemplateOutlet=\"seriesTpl; context: { series: series }\"\n ></ng-container>\n </g>\n <g *ngFor=\"let series of d.y2?.series\">\n <ng-container\n *ngTemplateOutlet=\"seriesTpl; context: { series: series }\"\n ></ng-container>\n </g>\n </svg>\n <legend>\n <riv-legend-item\n *ngFor=\"let item of legend$ | async\"\n [label]=\"item.label\"\n [colorToken]=\"item.colorToken\"\n ></riv-legend-item>\n </legend>\n</div>\n\n<ng-container *ngIf=\"callout$ | async; let callout\">\n <riv-callout\n *riv-callout\n [anchor]=\"callout.anchor\"\n [isModal]=\"false\"\n [preferredPosition]=\"'top-center'\"\n >\n <div class=\"callout-content\">\n <div class=\"callout-metric\" *ngFor=\"let metric of callout.metrics\">\n <div>{{ metric.label }}</div>\n <div class=\"callout-metric-value\">{{ metric.value }}</div>\n </div>\n </div>\n </riv-callout>\n</ng-container>\n\n<ng-template #zeroState>\n <riv-zero-state></riv-zero-state>\n</ng-template>\n", styles: [".container{display:flex;flex-direction:column;gap:var(--size-xlarge)}.y-tick-label,.x-major-tick-label{font-size:var(--type-0-font-size);line-height:var(--type-0-line-height-0);fill:var(--type-light-low-contrast)}.x-minor-tick-label{font-size:var(--type-1-font-size);line-height:var(--type-1-line-height-0);fill:var(--type-light-low-contrast);text-anchor:middle}.tick{fill:var(--gray-20)}.data.path{transition:stroke-opacity var(--short-transition)}.data.path.marker-hovered{stroke-opacity:.4}.data.marker{fill:var(--surface-light-0);transition:stroke-opacity var(--short-transition)}.data.marker.focused{stroke-opacity:1;filter:drop-shadow(0 1px 1px rgba(10,2,22,.15))}.data.marker.blurred{stroke-opacity:.4}.hover-rule{stroke:var(--gray-20)}legend{display:flex;flex-wrap:wrap;gap:var(--size-large);justify-content:flex-start;align-items:baseline}.callout-content{padding:var(--size-large);display:flex;gap:var(--size-medium)}.callout-metric{display:flex;flex-direction:column;gap:var(--size-xsmall);font-size:var(--type-1-font-size);line-height:var(--type-1-line-height-0)}.callout-metric-value{font-weight:var(--font-weight-heavy)}\n"] }]
|
|
1381
|
+
}], propDecorators: { input: [{
|
|
1382
|
+
type: Input
|
|
1383
|
+
}], width: [{
|
|
1384
|
+
type: Input
|
|
1385
|
+
}], height: [{
|
|
1386
|
+
type: Input
|
|
1387
|
+
}] } });
|
|
1388
|
+
|
|
1207
1389
|
class RivModule {
|
|
1208
1390
|
}
|
|
1209
1391
|
RivModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: RivModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
@@ -1214,13 +1396,19 @@ RivModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.
|
|
|
1214
1396
|
DataTableComponent,
|
|
1215
1397
|
DataTableHeaderCellComponent,
|
|
1216
1398
|
DataTableRowComponent,
|
|
1399
|
+
DaysPipe,
|
|
1217
1400
|
DonutComponent,
|
|
1218
1401
|
IconComponent,
|
|
1219
1402
|
LegendItemComponent,
|
|
1220
1403
|
MetricComponent,
|
|
1404
|
+
NumberPipe,
|
|
1405
|
+
PercentagePipe,
|
|
1406
|
+
SmallCurrencyPipe,
|
|
1221
1407
|
StackedColumnComponent,
|
|
1222
1408
|
TextToggleComponent,
|
|
1223
1409
|
TimeSeriesComponent,
|
|
1410
|
+
TooltipComponent,
|
|
1411
|
+
TooltipDirective,
|
|
1224
1412
|
ZeroStateComponent], imports: [CommonModule], exports: [CalloutComponent,
|
|
1225
1413
|
CalloutDirective,
|
|
1226
1414
|
CalloutOutletComponent,
|
|
@@ -1228,13 +1416,19 @@ RivModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.
|
|
|
1228
1416
|
DataTableComponent,
|
|
1229
1417
|
DataTableHeaderCellComponent,
|
|
1230
1418
|
DataTableRowComponent,
|
|
1419
|
+
DaysPipe,
|
|
1231
1420
|
DonutComponent,
|
|
1232
1421
|
IconComponent,
|
|
1233
1422
|
LegendItemComponent,
|
|
1234
1423
|
MetricComponent,
|
|
1424
|
+
NumberPipe,
|
|
1425
|
+
PercentagePipe,
|
|
1426
|
+
SmallCurrencyPipe,
|
|
1235
1427
|
StackedColumnComponent,
|
|
1236
1428
|
TextToggleComponent,
|
|
1237
1429
|
TimeSeriesComponent,
|
|
1430
|
+
TooltipComponent,
|
|
1431
|
+
TooltipDirective,
|
|
1238
1432
|
ZeroStateComponent] });
|
|
1239
1433
|
RivModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: RivModule, imports: [CommonModule] });
|
|
1240
1434
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: RivModule, decorators: [{
|
|
@@ -1248,13 +1442,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
|
|
|
1248
1442
|
DataTableComponent,
|
|
1249
1443
|
DataTableHeaderCellComponent,
|
|
1250
1444
|
DataTableRowComponent,
|
|
1445
|
+
DaysPipe,
|
|
1251
1446
|
DonutComponent,
|
|
1252
1447
|
IconComponent,
|
|
1253
1448
|
LegendItemComponent,
|
|
1254
1449
|
MetricComponent,
|
|
1450
|
+
NumberPipe,
|
|
1451
|
+
PercentagePipe,
|
|
1452
|
+
SmallCurrencyPipe,
|
|
1255
1453
|
StackedColumnComponent,
|
|
1256
1454
|
TextToggleComponent,
|
|
1257
1455
|
TimeSeriesComponent,
|
|
1456
|
+
TooltipComponent,
|
|
1457
|
+
TooltipDirective,
|
|
1258
1458
|
ZeroStateComponent,
|
|
1259
1459
|
],
|
|
1260
1460
|
exports: [
|
|
@@ -1265,13 +1465,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
|
|
|
1265
1465
|
DataTableComponent,
|
|
1266
1466
|
DataTableHeaderCellComponent,
|
|
1267
1467
|
DataTableRowComponent,
|
|
1468
|
+
DaysPipe,
|
|
1268
1469
|
DonutComponent,
|
|
1269
1470
|
IconComponent,
|
|
1270
1471
|
LegendItemComponent,
|
|
1271
1472
|
MetricComponent,
|
|
1473
|
+
NumberPipe,
|
|
1474
|
+
PercentagePipe,
|
|
1475
|
+
SmallCurrencyPipe,
|
|
1272
1476
|
StackedColumnComponent,
|
|
1273
1477
|
TextToggleComponent,
|
|
1274
1478
|
TimeSeriesComponent,
|
|
1479
|
+
TooltipComponent,
|
|
1480
|
+
TooltipDirective,
|
|
1275
1481
|
ZeroStateComponent,
|
|
1276
1482
|
],
|
|
1277
1483
|
imports: [CommonModule],
|
|
@@ -1282,5 +1488,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
|
|
|
1282
1488
|
* Generated bundle index. Do not edit.
|
|
1283
1489
|
*/
|
|
1284
1490
|
|
|
1285
|
-
export { CalloutComponent, CalloutDirective, CalloutOutletComponent, DataTableCellComponent, DataTableComponent, DataTableHeaderCellComponent, DataTableRowComponent, DonutComponent, IconComponent, LegendItemComponent, MetricComponent, RivModule, StackedColumnComponent, TextToggleComponent, TimeSeriesComponent, ZeroStateComponent };
|
|
1491
|
+
export { CalloutComponent, CalloutDirective, CalloutOutletComponent, DataTableCellComponent, DataTableComponent, DataTableHeaderCellComponent, DataTableRowComponent, DaysPipe, DonutComponent, IconComponent, LegendItemComponent, MetricComponent, NumberPipe, PercentagePipe, RivModule, SmallCurrencyPipe, StackedColumnComponent, TextToggleComponent, TimeSeriesComponent, TooltipComponent, TooltipDirective, ZeroStateComponent };
|
|
1286
1492
|
//# sourceMappingURL=rivet-health-design-system.mjs.map
|