@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.
@@ -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, combineLatest } from 'rxjs';
6
- import { pie, arc, line, stack } from 'd3-shape';
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
- var Interval;
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 config of configs) {
722
- for (const series of config.series) {
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. See commit e238c2d.
764
- class TimeSeriesComponent {
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.BOTTOM_OFFSET = 24;
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.binnedData$,
825
- this.binnedDateRange$,
826
- this.binInterval$,
958
+ this.input$,
827
959
  this.width$,
828
960
  this.height$,
829
- ]).pipe(map(([binnedData, binnedDateRange, binInterval, width, height]) => {
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