@rivet-health/design-system 2.3.1 → 2.4.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/riv.module.mjs +29 -9
- package/esm2020/public-api.mjs +5 -1
- package/fesm2015/rivet-health-design-system.mjs +337 -240
- package/fesm2015/rivet-health-design-system.mjs.map +1 -1
- package/fesm2020/rivet-health-design-system.mjs +330 -236
- 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/riv.module.d.ts +14 -10
- package/package.json +1 -1
- package/public-api.d.ts +4 -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, 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,60 @@ 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 DataTableRowComponent {
|
|
675
|
+
constructor() {
|
|
676
|
+
this.subRow = false;
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
DataTableRowComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DataTableRowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
680
|
+
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 });
|
|
681
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DataTableRowComponent, decorators: [{
|
|
682
|
+
type: Component,
|
|
683
|
+
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"] }]
|
|
684
|
+
}], propDecorators: { subRow: [{
|
|
685
|
+
type: Input
|
|
686
|
+
}, {
|
|
687
|
+
type: HostBinding,
|
|
688
|
+
args: ['class.sub-row']
|
|
689
|
+
}] } });
|
|
690
|
+
|
|
691
|
+
class DataTableCellComponent {
|
|
692
|
+
constructor(row) {
|
|
693
|
+
this.row = row;
|
|
694
|
+
this.subCell = false;
|
|
695
|
+
}
|
|
696
|
+
ngOnInit() {
|
|
697
|
+
this.subCell = this.row.subRow;
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
DataTableCellComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DataTableCellComponent, deps: [{ token: DataTableRowComponent }], target: i0.ɵɵFactoryTarget.Component });
|
|
701
|
+
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 });
|
|
702
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DataTableCellComponent, decorators: [{
|
|
703
|
+
type: Component,
|
|
704
|
+
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"] }]
|
|
705
|
+
}], ctorParameters: function () { return [{ type: DataTableRowComponent }]; }, propDecorators: { subCell: [{
|
|
706
|
+
type: HostBinding,
|
|
707
|
+
args: ['class.sub-cell']
|
|
708
|
+
}] } });
|
|
709
|
+
|
|
710
|
+
class DataTableComponent {
|
|
711
|
+
}
|
|
712
|
+
DataTableComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DataTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
713
|
+
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 });
|
|
714
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DataTableComponent, decorators: [{
|
|
715
|
+
type: Component,
|
|
716
|
+
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"] }]
|
|
717
|
+
}] });
|
|
718
|
+
|
|
719
|
+
class DataTableHeaderCellComponent {
|
|
720
|
+
}
|
|
721
|
+
DataTableHeaderCellComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DataTableHeaderCellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
722
|
+
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 });
|
|
723
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DataTableHeaderCellComponent, decorators: [{
|
|
724
|
+
type: Component,
|
|
725
|
+
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"] }]
|
|
726
|
+
}] });
|
|
727
|
+
|
|
596
728
|
class ZeroStateComponent {
|
|
597
729
|
constructor() {
|
|
598
730
|
this.message = 'No data to display.';
|
|
@@ -696,6 +828,177 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
|
|
|
696
828
|
type: Input
|
|
697
829
|
}] } });
|
|
698
830
|
|
|
831
|
+
function getDateRange$1(stacks) {
|
|
832
|
+
let min = Infinity;
|
|
833
|
+
let max = -Infinity;
|
|
834
|
+
for (const stack of stacks) {
|
|
835
|
+
for (const series of stack) {
|
|
836
|
+
for (const { date } of series.data) {
|
|
837
|
+
const value = date.valueOf();
|
|
838
|
+
min = Math.min(min, value);
|
|
839
|
+
max = Math.max(max, value);
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
return [new Date(min), new Date(max)];
|
|
844
|
+
}
|
|
845
|
+
// TODO: once we upgrade to Angular 16, this component can be cleaned up with
|
|
846
|
+
// signals instead of RxJS.
|
|
847
|
+
class StackedColumnComponent {
|
|
848
|
+
constructor() {
|
|
849
|
+
this.input$ = new BehaviorSubject([]);
|
|
850
|
+
this.width$ = new BehaviorSubject(960);
|
|
851
|
+
this.height$ = new BehaviorSubject(256);
|
|
852
|
+
this.valueFormatter = v => v.toString();
|
|
853
|
+
this.drawData$ = combineLatest([
|
|
854
|
+
this.input$,
|
|
855
|
+
this.width$,
|
|
856
|
+
this.height$,
|
|
857
|
+
]).pipe(map(([input, width, height]) => {
|
|
858
|
+
const viewBox = `0 0 ${width} ${height}`;
|
|
859
|
+
const padding = 8;
|
|
860
|
+
const [minDate, maxDate] = getDateRange$1(input);
|
|
861
|
+
const xSteps = timeMonth.range(timeMonth.floor(minDate), timeMonth.floor(timeMonth.offset(maxDate, 1)));
|
|
862
|
+
const xFormatter = timeFormat('%b');
|
|
863
|
+
const xOuterScale = scaleBand()
|
|
864
|
+
.domain(xSteps.map(date => xFormatter(date)))
|
|
865
|
+
.range([0, width]);
|
|
866
|
+
const columnWidth = 6;
|
|
867
|
+
const columnPadding = 4;
|
|
868
|
+
const outerPadding = (xOuterScale.bandwidth() -
|
|
869
|
+
(columnPadding * (input.length - 1) + columnWidth * input.length)) /
|
|
870
|
+
2;
|
|
871
|
+
const renderInformation = input.map(stackData => {
|
|
872
|
+
const stackedTable = stackData.reduce((table, s) => [
|
|
873
|
+
...table,
|
|
874
|
+
...s.data.map(point => ({
|
|
875
|
+
...point,
|
|
876
|
+
series: s,
|
|
877
|
+
})),
|
|
878
|
+
], []);
|
|
879
|
+
const indexedTable = index(stackedTable, d => d.date, d => d.series.label);
|
|
880
|
+
const stacked = stack()
|
|
881
|
+
.keys(stackData.map(v => v.label))
|
|
882
|
+
.value(([_, group], key) => {
|
|
883
|
+
return group.get(key).value;
|
|
884
|
+
})(indexedTable);
|
|
885
|
+
return { indexedTable, stacked };
|
|
886
|
+
});
|
|
887
|
+
let domainMax = 0;
|
|
888
|
+
renderInformation.forEach(({ stacked, indexedTable }) => {
|
|
889
|
+
[...indexedTable.values()].forEach((pointMap, i) => {
|
|
890
|
+
[...pointMap.values()].forEach((_, j) => {
|
|
891
|
+
domainMax = Math.max(domainMax, ...stacked[j][i]);
|
|
892
|
+
});
|
|
893
|
+
});
|
|
894
|
+
});
|
|
895
|
+
const yScale = scaleLinear()
|
|
896
|
+
.domain([0, domainMax])
|
|
897
|
+
.range([height - padding * 2, padding]);
|
|
898
|
+
const rects = [];
|
|
899
|
+
renderInformation.forEach(({ stacked, indexedTable }, index) => {
|
|
900
|
+
[...indexedTable.entries()].forEach(([date, pointMap], i) => {
|
|
901
|
+
[...pointMap.entries()].forEach(([_, seriesPoint], j) => {
|
|
902
|
+
const [baseline, topline] = stacked[j][i];
|
|
903
|
+
const width = columnWidth;
|
|
904
|
+
const height = yScale(baseline) - yScale(topline);
|
|
905
|
+
const x = (xOuterScale(xFormatter(date)) ?? 0) +
|
|
906
|
+
outerPadding +
|
|
907
|
+
columnWidth * index +
|
|
908
|
+
columnPadding * index;
|
|
909
|
+
const y = yScale(baseline) - height;
|
|
910
|
+
const fill = `var(${seriesPoint.series.colorToken})`;
|
|
911
|
+
rects.push({
|
|
912
|
+
dateValue: date.valueOf(),
|
|
913
|
+
x,
|
|
914
|
+
y,
|
|
915
|
+
width,
|
|
916
|
+
height,
|
|
917
|
+
fill,
|
|
918
|
+
striped: seriesPoint.series.style === 'striped',
|
|
919
|
+
seriesPoint,
|
|
920
|
+
});
|
|
921
|
+
});
|
|
922
|
+
});
|
|
923
|
+
});
|
|
924
|
+
const xTicks = xSteps.map(date => ({
|
|
925
|
+
dateValue: date.valueOf(),
|
|
926
|
+
label: xFormatter(date),
|
|
927
|
+
x: (xOuterScale(xFormatter(date)) ?? 0) + xOuterScale.bandwidth() / 2,
|
|
928
|
+
}));
|
|
929
|
+
const yTicks = yScale.ticks(5);
|
|
930
|
+
const hoverBandWidth = renderInformation.length * columnWidth +
|
|
931
|
+
(renderInformation.length + 1) * columnPadding;
|
|
932
|
+
const hoverBands = xSteps.map(date => ({
|
|
933
|
+
dateValue: date.valueOf(),
|
|
934
|
+
x: (xOuterScale(xFormatter(date)) ?? 0) +
|
|
935
|
+
(xOuterScale.bandwidth() - hoverBandWidth) / 2,
|
|
936
|
+
y: yScale(domainMax),
|
|
937
|
+
width: hoverBandWidth,
|
|
938
|
+
height: yScale(0) - yScale(domainMax),
|
|
939
|
+
}));
|
|
940
|
+
return {
|
|
941
|
+
columnWidth,
|
|
942
|
+
hoverBands,
|
|
943
|
+
rects,
|
|
944
|
+
viewBox,
|
|
945
|
+
xTicks,
|
|
946
|
+
yScale,
|
|
947
|
+
yTicks,
|
|
948
|
+
};
|
|
949
|
+
}), shareReplay({ refCount: true, bufferSize: 1 }));
|
|
950
|
+
this.empty$ = this.input$.pipe(map(input => input.every(stack => stack.every(series => series.data.length === 0))), shareReplay({ refCount: true, bufferSize: 1 }));
|
|
951
|
+
this.hoveredBand$ = new BehaviorSubject(null);
|
|
952
|
+
this.callout$ = combineLatest([this.hoveredBand$, this.drawData$]).pipe(map(([hoveredBand, drawData]) => {
|
|
953
|
+
if (!hoveredBand)
|
|
954
|
+
return null;
|
|
955
|
+
const { target } = hoveredBand.event;
|
|
956
|
+
if (!target)
|
|
957
|
+
return null;
|
|
958
|
+
const anchor = target.getBoundingClientRect();
|
|
959
|
+
const metrics = drawData.rects
|
|
960
|
+
.filter(rect => rect.dateValue === hoveredBand.dateValue)
|
|
961
|
+
.map(rect => ({
|
|
962
|
+
label: rect.seriesPoint.series.label,
|
|
963
|
+
value: this.valueFormatter(rect.seriesPoint.value),
|
|
964
|
+
}));
|
|
965
|
+
return { anchor, metrics };
|
|
966
|
+
}), shareReplay({ refCount: true, bufferSize: 1 }));
|
|
967
|
+
}
|
|
968
|
+
set input(v) {
|
|
969
|
+
this.input$.next(v);
|
|
970
|
+
}
|
|
971
|
+
get input() {
|
|
972
|
+
return this.input$.getValue();
|
|
973
|
+
}
|
|
974
|
+
set width(v) {
|
|
975
|
+
this.width$.next(v);
|
|
976
|
+
}
|
|
977
|
+
get width() {
|
|
978
|
+
return this.width$.getValue();
|
|
979
|
+
}
|
|
980
|
+
set height(v) {
|
|
981
|
+
this.height$.next(v);
|
|
982
|
+
}
|
|
983
|
+
get height() {
|
|
984
|
+
return this.height$.getValue();
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
StackedColumnComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: StackedColumnComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
988
|
+
StackedColumnComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: StackedColumnComponent, selector: "riv-stacked-column", inputs: { input: "input", width: "width", height: "height", valueFormatter: "valueFormatter" }, 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 <defs>\n <pattern\n id=\"stripes\"\n x=\"0\"\n y=\"0\"\n [attr.width]=\"d.columnWidth\"\n [attr.height]=\"d.columnWidth\"\n patternUnits=\"userSpaceOnUse\"\n >\n <line\n x1=\"0\"\n [attr.y1]=\"d.columnWidth\"\n [attr.x2]=\"d.columnWidth\"\n y2=\"0\"\n stroke=\"var(--white-100)\"\n stroke-width=\"1\"\n ></line>\n </pattern>\n </defs>\n <g *ngFor=\"let tick of d.xTicks\">\n <rect\n class=\"tick-background\"\n [class.focused]=\"(hoveredBand$ | async)?.dateValue === tick.dateValue\"\n [attr.x]=\"tick.x - 20\"\n [attr.y]=\"d.yScale(0) + 3\"\n width=\"40\"\n height=\"12\"\n rx=\"2\"\n ></rect>\n <text\n class=\"tick-label\"\n [attr.x]=\"tick.x\"\n [attr.y]=\"d.yScale(0) + 12\"\n text-anchor=\"middle\"\n >\n {{ tick.label }}\n </text>\n </g>\n <g *ngFor=\"let tick of d.yTicks\">\n <rect\n class=\"tick\"\n x=\"0\"\n [attr.y]=\"d.yScale(tick)\"\n width=\"100%\"\n height=\"1\"\n ></rect>\n <text class=\"tick-label\" x=\"0\" [attr.y]=\"d.yScale(tick)\" dy=\"-4\">\n {{ valueFormatter(tick) }}\n </text>\n </g>\n <g *ngFor=\"let rect of d.rects\">\n <rect\n class=\"column\"\n [attr.x]=\"rect.x\"\n [attr.y]=\"rect.y\"\n [attr.width]=\"rect.width\"\n [attr.height]=\"rect.height\"\n [attr.fill]=\"rect.fill\"\n [class.blurred]=\"\n (hoveredBand$ | async) !== null &&\n (hoveredBand$ | async)?.dateValue !== rect.dateValue\n \"\n ></rect>\n <rect\n *ngIf=\"rect.striped\"\n [attr.x]=\"rect.x\"\n [attr.y]=\"rect.y\"\n [attr.width]=\"rect.width\"\n [attr.height]=\"rect.height\"\n fill=\"url(#stripes)\"\n ></rect>\n </g>\n <rect\n *ngFor=\"let rect of d.hoverBands\"\n [attr.x]=\"rect.x\"\n [attr.y]=\"rect.y\"\n [attr.width]=\"rect.width\"\n [attr.height]=\"rect.height\"\n fill=\"transparent\"\n (mouseenter)=\"\n hoveredBand$.next({ dateValue: rect.dateValue, event: $event })\n \"\n (mouseleave)=\"hoveredBand$.next(null)\"\n ></rect>\n </svg>\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]=\"'center-right'\"\n [allowedPositions]=\"[\n 'center-right',\n 'center-left',\n 'top-center',\n 'bottom-center'\n ]\"\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: [".tick{fill:var(--gray-20)}.tick-label{font-size:var(--type-0-font-size);line-height:var(--type-0-line-height-0);fill:var(--type-light-low-contrast)}.tick-background{transition:fill var(--short-transition);fill:transparent}.tick-background.focused{fill:var(--baloo-10)}.column{transition:opacity var(--short-transition)}.column.blurred{opacity:.4}.callout-content{padding:var(--size-large);display:grid;gap:var(--size-medium);grid-template-columns:1fr 1fr}.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: "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: ZeroStateComponent, selector: "riv-zero-state", inputs: ["message"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
989
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: StackedColumnComponent, decorators: [{
|
|
990
|
+
type: Component,
|
|
991
|
+
args: [{ selector: 'riv-stacked-column', 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 <defs>\n <pattern\n id=\"stripes\"\n x=\"0\"\n y=\"0\"\n [attr.width]=\"d.columnWidth\"\n [attr.height]=\"d.columnWidth\"\n patternUnits=\"userSpaceOnUse\"\n >\n <line\n x1=\"0\"\n [attr.y1]=\"d.columnWidth\"\n [attr.x2]=\"d.columnWidth\"\n y2=\"0\"\n stroke=\"var(--white-100)\"\n stroke-width=\"1\"\n ></line>\n </pattern>\n </defs>\n <g *ngFor=\"let tick of d.xTicks\">\n <rect\n class=\"tick-background\"\n [class.focused]=\"(hoveredBand$ | async)?.dateValue === tick.dateValue\"\n [attr.x]=\"tick.x - 20\"\n [attr.y]=\"d.yScale(0) + 3\"\n width=\"40\"\n height=\"12\"\n rx=\"2\"\n ></rect>\n <text\n class=\"tick-label\"\n [attr.x]=\"tick.x\"\n [attr.y]=\"d.yScale(0) + 12\"\n text-anchor=\"middle\"\n >\n {{ tick.label }}\n </text>\n </g>\n <g *ngFor=\"let tick of d.yTicks\">\n <rect\n class=\"tick\"\n x=\"0\"\n [attr.y]=\"d.yScale(tick)\"\n width=\"100%\"\n height=\"1\"\n ></rect>\n <text class=\"tick-label\" x=\"0\" [attr.y]=\"d.yScale(tick)\" dy=\"-4\">\n {{ valueFormatter(tick) }}\n </text>\n </g>\n <g *ngFor=\"let rect of d.rects\">\n <rect\n class=\"column\"\n [attr.x]=\"rect.x\"\n [attr.y]=\"rect.y\"\n [attr.width]=\"rect.width\"\n [attr.height]=\"rect.height\"\n [attr.fill]=\"rect.fill\"\n [class.blurred]=\"\n (hoveredBand$ | async) !== null &&\n (hoveredBand$ | async)?.dateValue !== rect.dateValue\n \"\n ></rect>\n <rect\n *ngIf=\"rect.striped\"\n [attr.x]=\"rect.x\"\n [attr.y]=\"rect.y\"\n [attr.width]=\"rect.width\"\n [attr.height]=\"rect.height\"\n fill=\"url(#stripes)\"\n ></rect>\n </g>\n <rect\n *ngFor=\"let rect of d.hoverBands\"\n [attr.x]=\"rect.x\"\n [attr.y]=\"rect.y\"\n [attr.width]=\"rect.width\"\n [attr.height]=\"rect.height\"\n fill=\"transparent\"\n (mouseenter)=\"\n hoveredBand$.next({ dateValue: rect.dateValue, event: $event })\n \"\n (mouseleave)=\"hoveredBand$.next(null)\"\n ></rect>\n </svg>\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]=\"'center-right'\"\n [allowedPositions]=\"[\n 'center-right',\n 'center-left',\n 'top-center',\n 'bottom-center'\n ]\"\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: [".tick{fill:var(--gray-20)}.tick-label{font-size:var(--type-0-font-size);line-height:var(--type-0-line-height-0);fill:var(--type-light-low-contrast)}.tick-background{transition:fill var(--short-transition);fill:transparent}.tick-background.focused{fill:var(--baloo-10)}.column{transition:opacity var(--short-transition)}.column.blurred{opacity:.4}.callout-content{padding:var(--size-large);display:grid;gap:var(--size-medium);grid-template-columns:1fr 1fr}.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"] }]
|
|
992
|
+
}], propDecorators: { input: [{
|
|
993
|
+
type: Input
|
|
994
|
+
}], width: [{
|
|
995
|
+
type: Input
|
|
996
|
+
}], height: [{
|
|
997
|
+
type: Input
|
|
998
|
+
}], valueFormatter: [{
|
|
999
|
+
type: Input
|
|
1000
|
+
}] } });
|
|
1001
|
+
|
|
699
1002
|
var Interval;
|
|
700
1003
|
(function (Interval) {
|
|
701
1004
|
Interval["DAY"] = "day";
|
|
@@ -715,7 +1018,7 @@ function getTimeInterval(interval) {
|
|
|
715
1018
|
return timeYear;
|
|
716
1019
|
}
|
|
717
1020
|
}
|
|
718
|
-
function getDateRange
|
|
1021
|
+
function getDateRange(configs) {
|
|
719
1022
|
let min = Infinity;
|
|
720
1023
|
let max = -Infinity;
|
|
721
1024
|
for (const config of configs) {
|
|
@@ -779,7 +1082,7 @@ class TimeSeriesComponent {
|
|
|
779
1082
|
this.BOTTOM_PADDING = 8;
|
|
780
1083
|
this.Y_TICK_COUNT = 5;
|
|
781
1084
|
this.X_MINOR_TICK_LIMIT = 15;
|
|
782
|
-
this.dateRange$ = this.input$.pipe(map(getDateRange
|
|
1085
|
+
this.dateRange$ = this.input$.pipe(map(getDateRange), shareReplay({ refCount: true, bufferSize: 1 }));
|
|
783
1086
|
this.binInterval$ = this.dateRange$.pipe(map(([minDate, maxDate]) => {
|
|
784
1087
|
const diff = timeDay.count(new Date(minDate), new Date(maxDate));
|
|
785
1088
|
if (diff >= 365 * 3) {
|
|
@@ -819,7 +1122,7 @@ class TimeSeriesComponent {
|
|
|
819
1122
|
}),
|
|
820
1123
|
};
|
|
821
1124
|
})), shareReplay({ refCount: true, bufferSize: 1 }));
|
|
822
|
-
this.binnedDateRange$ = this.binnedData$.pipe(map(getDateRange
|
|
1125
|
+
this.binnedDateRange$ = this.binnedData$.pipe(map(getDateRange), shareReplay({ refCount: true, bufferSize: 1 }));
|
|
823
1126
|
this.drawData$ = combineLatest([
|
|
824
1127
|
this.binnedData$,
|
|
825
1128
|
this.binnedDateRange$,
|
|
@@ -979,231 +1282,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
|
|
|
979
1282
|
type: Input
|
|
980
1283
|
}] } });
|
|
981
1284
|
|
|
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]) => {
|
|
1063
|
-
const viewBox = `0 0 ${width} ${height}`;
|
|
1064
|
-
const padding = 8;
|
|
1065
|
-
const [minDate, maxDate] = getDateRange(input);
|
|
1066
|
-
const xSteps = timeMonth.range(timeMonth.floor(minDate), timeMonth.floor(timeMonth.offset(maxDate, 1)));
|
|
1067
|
-
const xFormatter = timeFormat('%b');
|
|
1068
|
-
const xOuterScale = scaleBand()
|
|
1069
|
-
.domain(xSteps.map(date => xFormatter(date)))
|
|
1070
|
-
.range([0, width]);
|
|
1071
|
-
const columnWidth = 6;
|
|
1072
|
-
const columnPadding = 4;
|
|
1073
|
-
const outerPadding = (xOuterScale.bandwidth() -
|
|
1074
|
-
(columnPadding * (input.length - 1) + columnWidth * input.length)) /
|
|
1075
|
-
2;
|
|
1076
|
-
const renderInformation = input.map(stackData => {
|
|
1077
|
-
const stackedTable = stackData.reduce((table, s) => [
|
|
1078
|
-
...table,
|
|
1079
|
-
...s.data.map(point => ({
|
|
1080
|
-
...point,
|
|
1081
|
-
series: s,
|
|
1082
|
-
})),
|
|
1083
|
-
], []);
|
|
1084
|
-
const indexedTable = index(stackedTable, d => d.date, d => d.series.label);
|
|
1085
|
-
const stacked = stack()
|
|
1086
|
-
.keys(stackData.map(v => v.label))
|
|
1087
|
-
.value(([_, group], key) => {
|
|
1088
|
-
return group.get(key).value;
|
|
1089
|
-
})(indexedTable);
|
|
1090
|
-
return { indexedTable, stacked };
|
|
1091
|
-
});
|
|
1092
|
-
let domainMax = 0;
|
|
1093
|
-
renderInformation.forEach(({ stacked, indexedTable }) => {
|
|
1094
|
-
[...indexedTable.values()].forEach((pointMap, i) => {
|
|
1095
|
-
[...pointMap.values()].forEach((_, j) => {
|
|
1096
|
-
domainMax = Math.max(domainMax, ...stacked[j][i]);
|
|
1097
|
-
});
|
|
1098
|
-
});
|
|
1099
|
-
});
|
|
1100
|
-
const yScale = scaleLinear()
|
|
1101
|
-
.domain([0, domainMax])
|
|
1102
|
-
.range([height - padding * 2, padding]);
|
|
1103
|
-
const rects = [];
|
|
1104
|
-
renderInformation.forEach(({ stacked, indexedTable }, index) => {
|
|
1105
|
-
[...indexedTable.entries()].forEach(([date, pointMap], i) => {
|
|
1106
|
-
[...pointMap.entries()].forEach(([_, seriesPoint], j) => {
|
|
1107
|
-
const [baseline, topline] = stacked[j][i];
|
|
1108
|
-
const width = columnWidth;
|
|
1109
|
-
const height = yScale(baseline) - yScale(topline);
|
|
1110
|
-
const x = (xOuterScale(xFormatter(date)) ?? 0) +
|
|
1111
|
-
outerPadding +
|
|
1112
|
-
columnWidth * index +
|
|
1113
|
-
columnPadding * index;
|
|
1114
|
-
const y = yScale(baseline) - height;
|
|
1115
|
-
const fill = `var(${seriesPoint.series.colorToken})`;
|
|
1116
|
-
rects.push({
|
|
1117
|
-
dateValue: date.valueOf(),
|
|
1118
|
-
x,
|
|
1119
|
-
y,
|
|
1120
|
-
width,
|
|
1121
|
-
height,
|
|
1122
|
-
fill,
|
|
1123
|
-
striped: seriesPoint.series.style === 'striped',
|
|
1124
|
-
seriesPoint,
|
|
1125
|
-
});
|
|
1126
|
-
});
|
|
1127
|
-
});
|
|
1128
|
-
});
|
|
1129
|
-
const xTicks = xSteps.map(date => ({
|
|
1130
|
-
dateValue: date.valueOf(),
|
|
1131
|
-
label: xFormatter(date),
|
|
1132
|
-
x: (xOuterScale(xFormatter(date)) ?? 0) + xOuterScale.bandwidth() / 2,
|
|
1133
|
-
}));
|
|
1134
|
-
const yTicks = yScale.ticks(5);
|
|
1135
|
-
const hoverBandWidth = renderInformation.length * columnWidth +
|
|
1136
|
-
(renderInformation.length + 1) * columnPadding;
|
|
1137
|
-
const hoverBands = xSteps.map(date => ({
|
|
1138
|
-
dateValue: date.valueOf(),
|
|
1139
|
-
x: (xOuterScale(xFormatter(date)) ?? 0) +
|
|
1140
|
-
(xOuterScale.bandwidth() - hoverBandWidth) / 2,
|
|
1141
|
-
y: yScale(domainMax),
|
|
1142
|
-
width: hoverBandWidth,
|
|
1143
|
-
height: yScale(0) - yScale(domainMax),
|
|
1144
|
-
}));
|
|
1145
|
-
return {
|
|
1146
|
-
columnWidth,
|
|
1147
|
-
hoverBands,
|
|
1148
|
-
rects,
|
|
1149
|
-
viewBox,
|
|
1150
|
-
xTicks,
|
|
1151
|
-
yScale,
|
|
1152
|
-
yTicks,
|
|
1153
|
-
};
|
|
1154
|
-
}), shareReplay({ refCount: true, bufferSize: 1 }));
|
|
1155
|
-
this.empty$ = this.input$.pipe(map(input => input.every(stack => stack.every(series => series.data.length === 0))), shareReplay({ refCount: true, bufferSize: 1 }));
|
|
1156
|
-
this.hoveredBand$ = new BehaviorSubject(null);
|
|
1157
|
-
this.callout$ = combineLatest([this.hoveredBand$, this.drawData$]).pipe(map(([hoveredBand, drawData]) => {
|
|
1158
|
-
if (!hoveredBand)
|
|
1159
|
-
return null;
|
|
1160
|
-
const { target } = hoveredBand.event;
|
|
1161
|
-
if (!target)
|
|
1162
|
-
return null;
|
|
1163
|
-
const anchor = target.getBoundingClientRect();
|
|
1164
|
-
const metrics = drawData.rects
|
|
1165
|
-
.filter(rect => rect.dateValue === hoveredBand.dateValue)
|
|
1166
|
-
.map(rect => ({
|
|
1167
|
-
label: rect.seriesPoint.series.label,
|
|
1168
|
-
value: this.valueFormatter(rect.seriesPoint.value),
|
|
1169
|
-
}));
|
|
1170
|
-
return { anchor, metrics };
|
|
1171
|
-
}), shareReplay({ refCount: true, bufferSize: 1 }));
|
|
1172
|
-
}
|
|
1173
|
-
set input(v) {
|
|
1174
|
-
this.input$.next(v);
|
|
1175
|
-
}
|
|
1176
|
-
get input() {
|
|
1177
|
-
return this.input$.getValue();
|
|
1178
|
-
}
|
|
1179
|
-
set width(v) {
|
|
1180
|
-
this.width$.next(v);
|
|
1181
|
-
}
|
|
1182
|
-
get width() {
|
|
1183
|
-
return this.width$.getValue();
|
|
1184
|
-
}
|
|
1185
|
-
set height(v) {
|
|
1186
|
-
this.height$.next(v);
|
|
1187
|
-
}
|
|
1188
|
-
get height() {
|
|
1189
|
-
return this.height$.getValue();
|
|
1190
|
-
}
|
|
1191
|
-
}
|
|
1192
|
-
StackedColumnComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: StackedColumnComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1193
|
-
StackedColumnComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: StackedColumnComponent, selector: "riv-stacked-column", inputs: { input: "input", width: "width", height: "height", valueFormatter: "valueFormatter" }, 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 <defs>\n <pattern\n id=\"stripes\"\n x=\"0\"\n y=\"0\"\n [attr.width]=\"d.columnWidth\"\n [attr.height]=\"d.columnWidth\"\n patternUnits=\"userSpaceOnUse\"\n >\n <line\n x1=\"0\"\n [attr.y1]=\"d.columnWidth\"\n [attr.x2]=\"d.columnWidth\"\n y2=\"0\"\n stroke=\"var(--white-100)\"\n stroke-width=\"1\"\n ></line>\n </pattern>\n </defs>\n <g *ngFor=\"let tick of d.xTicks\">\n <rect\n class=\"tick-background\"\n [class.focused]=\"(hoveredBand$ | async)?.dateValue === tick.dateValue\"\n [attr.x]=\"tick.x - 20\"\n [attr.y]=\"d.yScale(0) + 3\"\n width=\"40\"\n height=\"12\"\n rx=\"2\"\n ></rect>\n <text\n class=\"tick-label\"\n [attr.x]=\"tick.x\"\n [attr.y]=\"d.yScale(0) + 12\"\n text-anchor=\"middle\"\n >\n {{ tick.label }}\n </text>\n </g>\n <g *ngFor=\"let tick of d.yTicks\">\n <rect\n class=\"tick\"\n x=\"0\"\n [attr.y]=\"d.yScale(tick)\"\n width=\"100%\"\n height=\"1\"\n ></rect>\n <text class=\"tick-label\" x=\"0\" [attr.y]=\"d.yScale(tick)\" dy=\"-4\">\n {{ valueFormatter(tick) }}\n </text>\n </g>\n <g *ngFor=\"let rect of d.rects\">\n <rect\n class=\"column\"\n [attr.x]=\"rect.x\"\n [attr.y]=\"rect.y\"\n [attr.width]=\"rect.width\"\n [attr.height]=\"rect.height\"\n [attr.fill]=\"rect.fill\"\n [class.blurred]=\"\n (hoveredBand$ | async) !== null &&\n (hoveredBand$ | async)?.dateValue !== rect.dateValue\n \"\n ></rect>\n <rect\n *ngIf=\"rect.striped\"\n [attr.x]=\"rect.x\"\n [attr.y]=\"rect.y\"\n [attr.width]=\"rect.width\"\n [attr.height]=\"rect.height\"\n fill=\"url(#stripes)\"\n ></rect>\n </g>\n <rect\n *ngFor=\"let rect of d.hoverBands\"\n [attr.x]=\"rect.x\"\n [attr.y]=\"rect.y\"\n [attr.width]=\"rect.width\"\n [attr.height]=\"rect.height\"\n fill=\"transparent\"\n (mouseenter)=\"\n hoveredBand$.next({ dateValue: rect.dateValue, event: $event })\n \"\n (mouseleave)=\"hoveredBand$.next(null)\"\n ></rect>\n </svg>\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]=\"'center-right'\"\n [allowedPositions]=\"[\n 'center-right',\n 'center-left',\n 'top-center',\n 'bottom-center'\n ]\"\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: [".tick{fill:var(--gray-20)}.tick-label{font-size:var(--type-0-font-size);line-height:var(--type-0-line-height-0);fill:var(--type-light-low-contrast)}.tick-background{transition:fill var(--short-transition);fill:transparent}.tick-background.focused{fill:var(--baloo-10)}.column{transition:opacity var(--short-transition)}.column.blurred{opacity:.4}.callout-content{padding:var(--size-large);display:grid;gap:var(--size-medium);grid-template-columns:1fr 1fr}.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: "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: ZeroStateComponent, selector: "riv-zero-state", inputs: ["message"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1194
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: StackedColumnComponent, decorators: [{
|
|
1195
|
-
type: Component,
|
|
1196
|
-
args: [{ selector: 'riv-stacked-column', 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 <defs>\n <pattern\n id=\"stripes\"\n x=\"0\"\n y=\"0\"\n [attr.width]=\"d.columnWidth\"\n [attr.height]=\"d.columnWidth\"\n patternUnits=\"userSpaceOnUse\"\n >\n <line\n x1=\"0\"\n [attr.y1]=\"d.columnWidth\"\n [attr.x2]=\"d.columnWidth\"\n y2=\"0\"\n stroke=\"var(--white-100)\"\n stroke-width=\"1\"\n ></line>\n </pattern>\n </defs>\n <g *ngFor=\"let tick of d.xTicks\">\n <rect\n class=\"tick-background\"\n [class.focused]=\"(hoveredBand$ | async)?.dateValue === tick.dateValue\"\n [attr.x]=\"tick.x - 20\"\n [attr.y]=\"d.yScale(0) + 3\"\n width=\"40\"\n height=\"12\"\n rx=\"2\"\n ></rect>\n <text\n class=\"tick-label\"\n [attr.x]=\"tick.x\"\n [attr.y]=\"d.yScale(0) + 12\"\n text-anchor=\"middle\"\n >\n {{ tick.label }}\n </text>\n </g>\n <g *ngFor=\"let tick of d.yTicks\">\n <rect\n class=\"tick\"\n x=\"0\"\n [attr.y]=\"d.yScale(tick)\"\n width=\"100%\"\n height=\"1\"\n ></rect>\n <text class=\"tick-label\" x=\"0\" [attr.y]=\"d.yScale(tick)\" dy=\"-4\">\n {{ valueFormatter(tick) }}\n </text>\n </g>\n <g *ngFor=\"let rect of d.rects\">\n <rect\n class=\"column\"\n [attr.x]=\"rect.x\"\n [attr.y]=\"rect.y\"\n [attr.width]=\"rect.width\"\n [attr.height]=\"rect.height\"\n [attr.fill]=\"rect.fill\"\n [class.blurred]=\"\n (hoveredBand$ | async) !== null &&\n (hoveredBand$ | async)?.dateValue !== rect.dateValue\n \"\n ></rect>\n <rect\n *ngIf=\"rect.striped\"\n [attr.x]=\"rect.x\"\n [attr.y]=\"rect.y\"\n [attr.width]=\"rect.width\"\n [attr.height]=\"rect.height\"\n fill=\"url(#stripes)\"\n ></rect>\n </g>\n <rect\n *ngFor=\"let rect of d.hoverBands\"\n [attr.x]=\"rect.x\"\n [attr.y]=\"rect.y\"\n [attr.width]=\"rect.width\"\n [attr.height]=\"rect.height\"\n fill=\"transparent\"\n (mouseenter)=\"\n hoveredBand$.next({ dateValue: rect.dateValue, event: $event })\n \"\n (mouseleave)=\"hoveredBand$.next(null)\"\n ></rect>\n </svg>\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]=\"'center-right'\"\n [allowedPositions]=\"[\n 'center-right',\n 'center-left',\n 'top-center',\n 'bottom-center'\n ]\"\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: [".tick{fill:var(--gray-20)}.tick-label{font-size:var(--type-0-font-size);line-height:var(--type-0-line-height-0);fill:var(--type-light-low-contrast)}.tick-background{transition:fill var(--short-transition);fill:transparent}.tick-background.focused{fill:var(--baloo-10)}.column{transition:opacity var(--short-transition)}.column.blurred{opacity:.4}.callout-content{padding:var(--size-large);display:grid;gap:var(--size-medium);grid-template-columns:1fr 1fr}.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"] }]
|
|
1197
|
-
}], propDecorators: { input: [{
|
|
1198
|
-
type: Input
|
|
1199
|
-
}], width: [{
|
|
1200
|
-
type: Input
|
|
1201
|
-
}], height: [{
|
|
1202
|
-
type: Input
|
|
1203
|
-
}], valueFormatter: [{
|
|
1204
|
-
type: Input
|
|
1205
|
-
}] } });
|
|
1206
|
-
|
|
1207
1285
|
class RivModule {
|
|
1208
1286
|
}
|
|
1209
1287
|
RivModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: RivModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
@@ -1214,10 +1292,14 @@ RivModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.
|
|
|
1214
1292
|
DataTableComponent,
|
|
1215
1293
|
DataTableHeaderCellComponent,
|
|
1216
1294
|
DataTableRowComponent,
|
|
1295
|
+
DaysPipe,
|
|
1217
1296
|
DonutComponent,
|
|
1218
1297
|
IconComponent,
|
|
1219
1298
|
LegendItemComponent,
|
|
1220
1299
|
MetricComponent,
|
|
1300
|
+
NumberPipe,
|
|
1301
|
+
PercentagePipe,
|
|
1302
|
+
SmallCurrencyPipe,
|
|
1221
1303
|
StackedColumnComponent,
|
|
1222
1304
|
TextToggleComponent,
|
|
1223
1305
|
TimeSeriesComponent,
|
|
@@ -1228,10 +1310,14 @@ RivModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.
|
|
|
1228
1310
|
DataTableComponent,
|
|
1229
1311
|
DataTableHeaderCellComponent,
|
|
1230
1312
|
DataTableRowComponent,
|
|
1313
|
+
DaysPipe,
|
|
1231
1314
|
DonutComponent,
|
|
1232
1315
|
IconComponent,
|
|
1233
1316
|
LegendItemComponent,
|
|
1234
1317
|
MetricComponent,
|
|
1318
|
+
NumberPipe,
|
|
1319
|
+
PercentagePipe,
|
|
1320
|
+
SmallCurrencyPipe,
|
|
1235
1321
|
StackedColumnComponent,
|
|
1236
1322
|
TextToggleComponent,
|
|
1237
1323
|
TimeSeriesComponent,
|
|
@@ -1248,10 +1334,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
|
|
|
1248
1334
|
DataTableComponent,
|
|
1249
1335
|
DataTableHeaderCellComponent,
|
|
1250
1336
|
DataTableRowComponent,
|
|
1337
|
+
DaysPipe,
|
|
1251
1338
|
DonutComponent,
|
|
1252
1339
|
IconComponent,
|
|
1253
1340
|
LegendItemComponent,
|
|
1254
1341
|
MetricComponent,
|
|
1342
|
+
NumberPipe,
|
|
1343
|
+
PercentagePipe,
|
|
1344
|
+
SmallCurrencyPipe,
|
|
1255
1345
|
StackedColumnComponent,
|
|
1256
1346
|
TextToggleComponent,
|
|
1257
1347
|
TimeSeriesComponent,
|
|
@@ -1265,10 +1355,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
|
|
|
1265
1355
|
DataTableComponent,
|
|
1266
1356
|
DataTableHeaderCellComponent,
|
|
1267
1357
|
DataTableRowComponent,
|
|
1358
|
+
DaysPipe,
|
|
1268
1359
|
DonutComponent,
|
|
1269
1360
|
IconComponent,
|
|
1270
1361
|
LegendItemComponent,
|
|
1271
1362
|
MetricComponent,
|
|
1363
|
+
NumberPipe,
|
|
1364
|
+
PercentagePipe,
|
|
1365
|
+
SmallCurrencyPipe,
|
|
1272
1366
|
StackedColumnComponent,
|
|
1273
1367
|
TextToggleComponent,
|
|
1274
1368
|
TimeSeriesComponent,
|
|
@@ -1282,5 +1376,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
|
|
|
1282
1376
|
* Generated bundle index. Do not edit.
|
|
1283
1377
|
*/
|
|
1284
1378
|
|
|
1285
|
-
export { CalloutComponent, CalloutDirective, CalloutOutletComponent, DataTableCellComponent, DataTableComponent, DataTableHeaderCellComponent, DataTableRowComponent, DonutComponent, IconComponent, LegendItemComponent, MetricComponent, RivModule, StackedColumnComponent, TextToggleComponent, TimeSeriesComponent, ZeroStateComponent };
|
|
1379
|
+
export { CalloutComponent, CalloutDirective, CalloutOutletComponent, DataTableCellComponent, DataTableComponent, DataTableHeaderCellComponent, DataTableRowComponent, DaysPipe, DonutComponent, IconComponent, LegendItemComponent, MetricComponent, NumberPipe, PercentagePipe, RivModule, SmallCurrencyPipe, StackedColumnComponent, TextToggleComponent, TimeSeriesComponent, ZeroStateComponent };
|
|
1286
1380
|
//# sourceMappingURL=rivet-health-design-system.mjs.map
|