@genspectrum/dashboard-components 0.5.0 → 0.5.2

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/dist/style.css CHANGED
@@ -836,7 +836,11 @@ html {
836
836
  }
837
837
 
838
838
  * {
839
- scrollbar-color: currentColor transparent;
839
+ scrollbar-color: color-mix(in oklch, currentColor 35%, transparent) transparent;
840
+ }
841
+
842
+ *:hover {
843
+ scrollbar-color: color-mix(in oklch, currentColor 60%, transparent) transparent;
840
844
  }
841
845
 
842
846
  :root {
@@ -1846,6 +1850,9 @@ input.tab:checked + .tab-content,
1846
1850
  margin-bottom: 0px;
1847
1851
  margin-inline-start: -1px;
1848
1852
  }
1853
+ .join > :where(*:not(:first-child)):is(.btn) {
1854
+ margin-inline-start: calc(var(--border-btn) * -1);
1855
+ }
1849
1856
  .loading {
1850
1857
  pointer-events: none;
1851
1858
  display: inline-block;
@@ -2596,11 +2603,17 @@ input.tab:checked + .tab-content,
2596
2603
  margin-right: 0px;
2597
2604
  margin-top: -1px;
2598
2605
  }
2606
+ .join.join-vertical > :where(*:not(:first-child)):is(.btn) {
2607
+ margin-top: calc(var(--border-btn) * -1);
2608
+ }
2599
2609
  .join.join-horizontal > :where(*:not(:first-child)) {
2600
2610
  margin-top: 0px;
2601
2611
  margin-bottom: 0px;
2602
2612
  margin-inline-start: -1px;
2603
2613
  }
2614
+ .join.join-horizontal > :where(*:not(:first-child)):is(.btn) {
2615
+ margin-inline-start: calc(var(--border-btn) * -1);
2616
+ }
2604
2617
  .modal-top :where(.modal-box) {
2605
2618
  width: 100%;
2606
2619
  max-width: none;
@@ -2854,12 +2867,12 @@ input.tab:checked + .tab-content,
2854
2867
  .w-32 {
2855
2868
  width: 8rem;
2856
2869
  }
2857
- .w-40 {
2858
- width: 10rem;
2859
- }
2860
2870
  .w-64 {
2861
2871
  width: 16rem;
2862
2872
  }
2873
+ .w-\[7\.5rem\] {
2874
+ width: 7.5rem;
2875
+ }
2863
2876
  .w-full {
2864
2877
  width: 100%;
2865
2878
  }
@@ -2867,8 +2880,8 @@ input.tab:checked + .tab-content,
2867
2880
  width: -moz-max-content;
2868
2881
  width: max-content;
2869
2882
  }
2870
- .min-w-40 {
2871
- min-width: 10rem;
2883
+ .min-w-\[7\.5rem\] {
2884
+ min-width: 7.5rem;
2872
2885
  }
2873
2886
  .max-w-screen-lg {
2874
2887
  max-width: 1024px;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@genspectrum/dashboard-components",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "GenSpectrum web components for building dashboards",
5
5
  "type": "module",
6
6
  "license": "AGPL-3.0-only",
@@ -1,6 +1,6 @@
1
1
  import { type FunctionComponent } from 'preact';
2
2
 
3
- import { type AggregateData } from '../../query/queryAggregateData';
3
+ import { type AggregateData, compareAscending } from '../../query/queryAggregateData';
4
4
  import { Table } from '../components/table';
5
5
  import { formatProportion } from '../shared/table/formatProportion';
6
6
 
@@ -15,7 +15,9 @@ export const AggregateTable: FunctionComponent<AggregateTableProps> = ({ data, f
15
15
  ...fields.map((field) => {
16
16
  return {
17
17
  name: field,
18
- sort: true,
18
+ sort: {
19
+ compare: compareAscending,
20
+ },
19
21
  };
20
22
  }),
21
23
  {
@@ -182,7 +182,7 @@ export const DateRangeSelectorInner = <CustomLabel extends string>({
182
182
  <Select
183
183
  items={getSelectableOptions(customSelectOptions)}
184
184
  selected={selectedDateRange}
185
- selectStyle='select-bordered rounded-none flex-grow w-40'
185
+ selectStyle='select-bordered rounded-none flex-grow min-w-[7.5rem]'
186
186
  onChange={(event: Event) => {
187
187
  event.preventDefault();
188
188
  const select = event.target as HTMLSelectElement;
@@ -192,18 +192,16 @@ export const DateRangeSelectorInner = <CustomLabel extends string>({
192
192
  />
193
193
  <div className={'flex flex-wrap flex-grow'}>
194
194
  <input
195
- class='input input-bordered rounded-none flex-grow min-w-40'
195
+ class='input input-bordered rounded-none flex-grow w-[7.5rem]'
196
196
  type='text'
197
- size={10}
198
197
  placeholder='Date from'
199
198
  ref={fromDatePickerRef}
200
199
  onChange={onChangeDateFrom}
201
200
  onBlur={onChangeDateFrom}
202
201
  />
203
202
  <input
204
- class='input input-bordered rounded-none flex-grow min-w-40'
203
+ class='input input-bordered rounded-none flex-grow w-[7.5rem]'
205
204
  type='text'
206
- size={10}
207
205
  placeholder='Date to'
208
206
  ref={toDatePickerRef}
209
207
  onChange={onChangeDateTo}
@@ -2,7 +2,11 @@ import { Chart, type ChartConfiguration, registerables, type TooltipItem } from
2
2
  import { BarWithErrorBar, BarWithErrorBarsController } from 'chartjs-chart-error-bars';
3
3
 
4
4
  import { maxInData } from './prevalence-over-time';
5
- import { type PrevalenceOverTimeData, type PrevalenceOverTimeVariantData } from '../../query/queryPrevalenceOverTime';
5
+ import {
6
+ type PrevalenceOverTimeData,
7
+ type PrevalenceOverTimeVariantData,
8
+ type PrevalenceOverTimeVariantDataPoint,
9
+ } from '../../query/queryPrevalenceOverTime';
6
10
  import type { Temporal } from '../../utils/temporal';
7
11
  import GsChart from '../components/chart';
8
12
  import { LogitScale } from '../shared/charts/LogitScale';
@@ -84,32 +88,37 @@ const getDataset = (
84
88
  index: number,
85
89
  confidenceIntervalMethod: ConfidenceIntervalMethod,
86
90
  ) => {
87
- const generalConfig = {
91
+ return {
88
92
  borderWidth: 1,
89
93
  pointRadius: 0,
90
94
  label: prevalenceOverTimeVariant.displayName,
91
95
  backgroundColor: singleGraphColorRGBAById(index, 0.3),
92
96
  borderColor: singleGraphColorRGBAById(index),
97
+ data: prevalenceOverTimeVariant.content.map(mapDataPoint(confidenceIntervalMethod)),
98
+ };
99
+ };
100
+
101
+ const mapDataPoint = (confidenceIntervalMethod: ConfidenceIntervalMethod) => {
102
+ return (dataPoint: PrevalenceOverTimeVariantDataPoint) => {
103
+ const confidenceInterval = getConfidenceInterval(dataPoint, confidenceIntervalMethod);
104
+ return {
105
+ y: dataPoint.prevalence,
106
+ yMin: confidenceInterval.lowerLimit,
107
+ yMax: confidenceInterval.upperLimit,
108
+ x: dataPoint.dateRange?.toString() ?? 'Unknown',
109
+ };
93
110
  };
111
+ };
94
112
 
113
+ const getConfidenceInterval = (
114
+ dataPoint: PrevalenceOverTimeVariantDataPoint,
115
+ confidenceIntervalMethod: ConfidenceIntervalMethod,
116
+ ) => {
95
117
  switch (confidenceIntervalMethod) {
96
118
  case 'wilson':
97
- return {
98
- ...generalConfig,
99
- data: prevalenceOverTimeVariant.content.map((dataPoint) => ({
100
- y: dataPoint.prevalence,
101
- yMin: wilson95PercentConfidenceInterval(dataPoint.count, dataPoint.total).lowerLimit,
102
- yMax: wilson95PercentConfidenceInterval(dataPoint.count, dataPoint.total).upperLimit,
103
- x: dataPoint.dateRange?.toString() ?? 'Unknown',
104
- })),
105
- };
119
+ return wilson95PercentConfidenceInterval(dataPoint.count, dataPoint.total);
106
120
  default:
107
- return {
108
- ...generalConfig,
109
- data: prevalenceOverTimeVariant.content.map((dataPoint) => {
110
- return { y: dataPoint.prevalence, x: dataPoint.dateRange };
111
- }),
112
- };
121
+ return { lowerLimit: undefined, upperLimit: undefined };
113
122
  }
114
123
  };
115
124
 
@@ -8,7 +8,7 @@ export type AggregateData = (Record<string, string | null | number | boolean> &
8
8
  proportion: number;
9
9
  })[];
10
10
 
11
- const compareAscending = (a: string | null | number, b: string | null | number) => {
11
+ export const compareAscending = (a: string | null | number, b: string | null | number) => {
12
12
  if (typeof a === 'number' && typeof b === 'number') {
13
13
  return a - b;
14
14
  }
@@ -19,7 +19,14 @@ export type PrevalenceOverTimeData = PrevalenceOverTimeVariantData[];
19
19
 
20
20
  export type PrevalenceOverTimeVariantData = {
21
21
  displayName: string;
22
- content: { count: number; prevalence: number; total: number; dateRange: Temporal | null }[];
22
+ content: PrevalenceOverTimeVariantDataPoint[];
23
+ };
24
+
25
+ export type PrevalenceOverTimeVariantDataPoint = {
26
+ count: number;
27
+ prevalence: number;
28
+ total: number;
29
+ dateRange: Temporal | null;
23
30
  };
24
31
 
25
32
  export function queryPrevalenceOverTime(