@genspectrum/dashboard-components 0.17.0 → 0.18.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.
Files changed (50) hide show
  1. package/custom-elements.json +47 -16
  2. package/dist/components.d.ts +21 -17
  3. package/dist/components.js +426 -3654
  4. package/dist/components.js.map +1 -1
  5. package/dist/style.css +2 -3375
  6. package/dist/util.d.ts +15 -15
  7. package/package.json +6 -5
  8. package/src/preact/aggregatedData/aggregate.tsx +3 -3
  9. package/src/preact/components/clearable-select.tsx +1 -1
  10. package/src/preact/components/color-scale-selector-dropdown.tsx +1 -1
  11. package/src/preact/components/confidence-interval-selector.tsx +1 -1
  12. package/src/preact/components/downshift-combobox.tsx +3 -3
  13. package/src/preact/components/fullscreen.tsx +6 -2
  14. package/src/preact/components/info.tsx +1 -1
  15. package/src/preact/components/mutation-type-selector.tsx +1 -1
  16. package/src/preact/components/percent-intput.tsx +3 -3
  17. package/src/preact/components/proportion-selector-dropdown.tsx +1 -1
  18. package/src/preact/components/scaling-selector.tsx +1 -1
  19. package/src/preact/components/select.tsx +1 -1
  20. package/src/preact/components/tabs.tsx +1 -1
  21. package/src/preact/dateRangeFilter/date-picker.tsx +1 -1
  22. package/src/preact/dateRangeFilter/date-range-filter.tsx +4 -4
  23. package/src/preact/mutationComparison/mutation-comparison.tsx +1 -1
  24. package/src/preact/mutations/mutations.tsx +2 -2
  25. package/src/preact/mutationsOverTime/mutations-over-time-grid.tsx +133 -84
  26. package/src/preact/mutationsOverTime/mutations-over-time.stories.tsx +46 -16
  27. package/src/preact/mutationsOverTime/mutations-over-time.tsx +4 -1
  28. package/src/preact/numberSequencesOverTime/number-sequences-over-time.tsx +1 -1
  29. package/src/preact/prevalenceOverTime/prevalence-over-time.tsx +1 -1
  30. package/src/preact/sequencesByLocation/sequences-by-location-map.tsx +1 -1
  31. package/src/preact/sequencesByLocation/sequences-by-location.tsx +3 -7
  32. package/src/preact/shared/tanstackTable/pagination.tsx +132 -0
  33. package/src/preact/shared/tanstackTable/tanstackTable.tsx +43 -0
  34. package/src/preact/wastewater/mutationsOverTime/wastewater-mutations-over-time.stories.tsx +2 -1
  35. package/src/preact/wastewater/mutationsOverTime/wastewater-mutations-over-time.tsx +3 -5
  36. package/src/styles/tailwind.css +14 -3
  37. package/src/web-components/input/gs-date-range-filter.stories.ts +2 -2
  38. package/src/web-components/input/gs-lineage-filter.stories.ts +1 -1
  39. package/src/web-components/input/gs-location-filter.stories.ts +1 -1
  40. package/src/web-components/input/gs-mutation-filter.stories.ts +1 -1
  41. package/src/web-components/input/gs-text-filter.stories.ts +1 -1
  42. package/src/web-components/visualization/gs-mutations-over-time.spec-d.ts +39 -0
  43. package/src/web-components/visualization/gs-mutations-over-time.stories.ts +4 -0
  44. package/src/web-components/visualization/gs-mutations-over-time.tsx +8 -31
  45. package/src/web-components/wastewaterVisualization/gs-wastewater-mutations-over-time.spec-d.ts +24 -0
  46. package/src/web-components/wastewaterVisualization/gs-wastewater-mutations-over-time.stories.ts +3 -3
  47. package/src/web-components/wastewaterVisualization/gs-wastewater-mutations-over-time.tsx +5 -36
  48. package/standalone-bundle/dashboard-components.js +17318 -15507
  49. package/standalone-bundle/dashboard-components.js.map +1 -1
  50. package/standalone-bundle/style.css +1 -1
package/dist/util.d.ts CHANGED
@@ -906,7 +906,7 @@ declare global {
906
906
 
907
907
  declare global {
908
908
  interface HTMLElementTagNameMap {
909
- 'gs-mutations-component': MutationsComponent;
909
+ 'gs-prevalence-over-time': PrevalenceOverTimeComponent;
910
910
  }
911
911
  }
912
912
 
@@ -914,7 +914,7 @@ declare global {
914
914
  declare global {
915
915
  namespace JSX {
916
916
  interface IntrinsicElements {
917
- 'gs-mutations-component': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
917
+ 'gs-prevalence-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
918
918
  }
919
919
  }
920
920
  }
@@ -922,7 +922,7 @@ declare global {
922
922
 
923
923
  declare global {
924
924
  interface HTMLElementTagNameMap {
925
- 'gs-prevalence-over-time': PrevalenceOverTimeComponent;
925
+ 'gs-mutations-component': MutationsComponent;
926
926
  }
927
927
  }
928
928
 
@@ -930,7 +930,7 @@ declare global {
930
930
  declare global {
931
931
  namespace JSX {
932
932
  interface IntrinsicElements {
933
- 'gs-prevalence-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
933
+ 'gs-mutations-component': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
934
934
  }
935
935
  }
936
936
  }
@@ -1034,11 +1034,7 @@ declare global {
1034
1034
 
1035
1035
  declare global {
1036
1036
  interface HTMLElementTagNameMap {
1037
- 'gs-date-range-filter': DateRangeFilterComponent;
1038
- }
1039
- interface HTMLElementEventMap {
1040
- 'gs-date-range-filter-changed': CustomEvent<Record<string, string>>;
1041
- 'gs-date-range-option-changed': DateRangeOptionChangedEvent;
1037
+ 'gs-wastewater-mutations-over-time': WastewaterMutationsOverTimeComponent;
1042
1038
  }
1043
1039
  }
1044
1040
 
@@ -1046,7 +1042,7 @@ declare global {
1046
1042
  declare global {
1047
1043
  namespace JSX {
1048
1044
  interface IntrinsicElements {
1049
- 'gs-date-range-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1045
+ 'gs-wastewater-mutations-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1050
1046
  }
1051
1047
  }
1052
1048
  }
@@ -1054,7 +1050,10 @@ declare global {
1054
1050
 
1055
1051
  declare global {
1056
1052
  interface HTMLElementTagNameMap {
1057
- 'gs-wastewater-mutations-over-time': WastewaterMutationsOverTimeComponent;
1053
+ 'gs-location-filter': LocationFilterComponent;
1054
+ }
1055
+ interface HTMLElementEventMap {
1056
+ 'gs-location-changed': LocationChangedEvent;
1058
1057
  }
1059
1058
  }
1060
1059
 
@@ -1062,7 +1061,7 @@ declare global {
1062
1061
  declare global {
1063
1062
  namespace JSX {
1064
1063
  interface IntrinsicElements {
1065
- 'gs-wastewater-mutations-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1064
+ 'gs-location-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1066
1065
  }
1067
1066
  }
1068
1067
  }
@@ -1070,10 +1069,11 @@ declare global {
1070
1069
 
1071
1070
  declare global {
1072
1071
  interface HTMLElementTagNameMap {
1073
- 'gs-location-filter': LocationFilterComponent;
1072
+ 'gs-date-range-filter': DateRangeFilterComponent;
1074
1073
  }
1075
1074
  interface HTMLElementEventMap {
1076
- 'gs-location-changed': LocationChangedEvent;
1075
+ 'gs-date-range-filter-changed': CustomEvent<Record<string, string>>;
1076
+ 'gs-date-range-option-changed': DateRangeOptionChangedEvent;
1077
1077
  }
1078
1078
  }
1079
1079
 
@@ -1081,7 +1081,7 @@ declare global {
1081
1081
  declare global {
1082
1082
  namespace JSX {
1083
1083
  interface IntrinsicElements {
1084
- 'gs-location-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1084
+ 'gs-date-range-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1085
1085
  }
1086
1086
  }
1087
1087
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@genspectrum/dashboard-components",
3
- "version": "0.17.0",
3
+ "version": "0.18.0",
4
4
  "description": "GenSpectrum web components for building dashboards",
5
5
  "type": "module",
6
6
  "license": "AGPL-3.0-only",
@@ -83,6 +83,7 @@
83
83
  "@lit/context": "^1.1.1",
84
84
  "@lit/reactive-element": "^2.0.4",
85
85
  "@lit/task": "^1.0.0",
86
+ "@tanstack/table-core": "^8.21.2",
86
87
  "chart.js": "^4.4.6",
87
88
  "chartjs-chart-error-bars": "^4.4.0",
88
89
  "chartjs-chart-venn": "^4.3.0",
@@ -101,7 +102,7 @@
101
102
  "@custom-elements-manifest/analyzer": "^0.10.2",
102
103
  "@iconify-json/mdi": "^1.1.67",
103
104
  "@iconify-json/mdi-light": "^1.1.10",
104
- "@iconify/tailwind": "^1.1.2",
105
+ "@iconify/tailwind4": "^1.0.6",
105
106
  "@playwright/test": "^1.43.1",
106
107
  "@storybook/addon-actions": "^8.0.9",
107
108
  "@storybook/addon-essentials": "^8.0.9",
@@ -115,7 +116,7 @@
115
116
  "@storybook/types": "^8.0.9",
116
117
  "@storybook/web-components": "^8.0.9",
117
118
  "@storybook/web-components-vite": "^8.0.9",
118
- "@tailwindcss/container-queries": "^0.1.1",
119
+ "@tailwindcss/postcss": "^4.0.9",
119
120
  "@testing-library/preact": "^3.2.4",
120
121
  "@types/geojson": "^7946.0.15",
121
122
  "@types/leaflet": "^1.9.15",
@@ -125,7 +126,7 @@
125
126
  "@typescript-eslint/eslint-plugin": "^8.2.0",
126
127
  "@typescript-eslint/parser": "^8.2.0",
127
128
  "autoprefixer": "^10.4.19",
128
- "daisyui": "^4.10.2",
129
+ "daisyui": "^5.0.0",
129
130
  "depcheck": "^1.4.7",
130
131
  "eslint": "^8.57.0",
131
132
  "eslint-config-preact": "^1.3.0",
@@ -141,7 +142,7 @@
141
142
  "react": "^18.3.1",
142
143
  "storybook": "^8.0.9",
143
144
  "storybook-addon-fetch-mock": "^2.0.0",
144
- "tailwindcss": "^3.4.3",
145
+ "tailwindcss": "^4.0.9",
145
146
  "typescript": "~5.7.2",
146
147
  "vite": "^6.0.3",
147
148
  "vite-plugin-dts": "^4.0.3",
@@ -119,11 +119,11 @@ type ToolbarProps = {
119
119
 
120
120
  const Toolbar: FunctionComponent<ToolbarProps> = ({ data, originalComponentProps }) => {
121
121
  return (
122
- <div class='flex flex-row'>
123
- <CsvDownloadButton className='mx-1 btn btn-xs' getData={() => data} filename='aggregate.csv' />
122
+ <>
123
+ <CsvDownloadButton className='btn btn-xs' getData={() => data} filename='aggregate.csv' />
124
124
  <AggregateInfo originalComponentProps={originalComponentProps} />
125
125
  <Fullscreen />
126
- </div>
126
+ </>
127
127
  );
128
128
  };
129
129
 
@@ -50,7 +50,7 @@ export function ClearableSelect({
50
50
  return (
51
51
  <div className={`relative inline min-w-24 ${className}`}>
52
52
  <select
53
- className={`w-full select select-bordered pr-14 ${selectClassName}`}
53
+ className={`w-full select pr-14 ${selectClassName}`}
54
54
  value={selectedOption ?? undefinedValue}
55
55
  onChange={handleChange}
56
56
  >
@@ -10,7 +10,7 @@ export const ColorScaleSelectorDropdown: FunctionComponent<ColorScaleSelectorDro
10
10
  setColorScale,
11
11
  }) => {
12
12
  return (
13
- <div className='w-20'>
13
+ <div className='w-20 inline-flex'>
14
14
  <Dropdown buttonTitle={`Color scale`} placement={'bottom-start'}>
15
15
  <ColorScaleSelector colorScale={colorScale} setColorScale={setColorScale} />
16
16
  </Dropdown>
@@ -39,7 +39,7 @@ export const ConfidenceIntervalSelector: FunctionComponent<ConfidenceIntervalSel
39
39
  const value = select.value as ConfidenceIntervalMethod;
40
40
  setConfidenceIntervalMethod(value);
41
41
  }}
42
- selectStyle={'select-xs select-bordered'}
42
+ selectStyle={'select-xs'}
43
43
  />
44
44
  );
45
45
  };
@@ -91,7 +91,7 @@ export function DownshiftCombobox<Item>({
91
91
  <div ref={divRef} className={'relative w-full'}>
92
92
  <div className='w-full flex flex-col gap-1'>
93
93
  <div
94
- className={`flex gap-0.5 input input-bordered min-w-32 ${inputClassName}`}
94
+ className={`flex gap-0.5 input min-w-32 w-full ${inputClassName}`}
95
95
  onBlur={(event) => {
96
96
  if (event.relatedTarget != buttonRef.current) {
97
97
  closeMenu();
@@ -131,7 +131,7 @@ export function DownshiftCombobox<Item>({
131
131
  {items.length > 0 ? (
132
132
  items.map((item, index) => (
133
133
  <li
134
- className={`${highlightedIndex === index ? 'bg-blue-300' : ''} ${selectedItem !== null && itemToString(selectedItem) === itemToString(item) ? 'font-bold' : ''} py-2 px-3 shadow-sm`}
134
+ className={`${highlightedIndex === index ? 'bg-blue-300' : ''} ${selectedItem !== null && itemToString(selectedItem) === itemToString(item) ? 'font-bold' : ''} py-2 px-3 shadow-xs`}
135
135
  key={itemToString(item)}
136
136
  {...getItemProps({ item, index })}
137
137
  >
@@ -139,7 +139,7 @@ export function DownshiftCombobox<Item>({
139
139
  </li>
140
140
  ))
141
141
  ) : (
142
- <li className='py-2 px-3 shadow-sm'>No elements to select.</li>
142
+ <li className='py-2 px-3 shadow-xs'>No elements to select.</li>
143
143
  )}
144
144
  </ul>
145
145
  </div>
@@ -18,9 +18,13 @@ export const Fullscreen = () => {
18
18
  }
19
19
  }
20
20
  }}
21
- className={`mt-0.5 iconify text-2xl ${isFullscreen ? 'mdi--fullscreen-exit hover:scale-90' : 'mdi--fullscreen hover:scale-110'}`}
21
+ className={`btn btn-xs`}
22
22
  title={isFullscreen ? 'Exit fullscreen' : 'Enter fullscreen'}
23
- />
23
+ >
24
+ <div
25
+ className={`iconify text-2xl ${isFullscreen ? 'mdi--fullscreen-exit hover:scale-90' : 'mdi--fullscreen hover:scale-110'}`}
26
+ />
27
+ </button>
24
28
  );
25
29
  };
26
30
 
@@ -4,7 +4,7 @@ import { Modal } from './modal';
4
4
 
5
5
  const Info: FunctionComponent = ({ children }) => {
6
6
  return (
7
- <div className='relative'>
7
+ <div className='relative inline-flex'>
8
8
  <Modal buttonClassName='btn btn-xs' modalContent={children}>
9
9
  ?
10
10
  </Modal>
@@ -17,7 +17,7 @@ export const MutationTypeSelector: FunctionComponent<MutationTypeSelectorProps>
17
17
  setDisplayedMutationTypes,
18
18
  }) => {
19
19
  return (
20
- <div className='w-[6rem]'>
20
+ <div className='w-[6rem] inline-flex'>
21
21
  <CheckboxSelector
22
22
  items={displayedMutationTypes}
23
23
  label={getMutationTypesSelectorLabel(displayedMutationTypes)}
@@ -40,7 +40,8 @@ export const PercentInput: FunctionComponent<PercentInputProps> = ({
40
40
 
41
41
  const isError = indicateError || !percentageInRange(internalPercentage);
42
42
  return (
43
- <label className={`input input-bordered flex items-center gap-2 w-32 ${isError ? 'input-error' : ''}`}>
43
+ <label className={`input flex items-center w-32 ${isError ? 'input-error' : ''}`}>
44
+ <span className='label'>%</span>
44
45
  <input
45
46
  type='number'
46
47
  step={0.1}
@@ -49,9 +50,8 @@ export const PercentInput: FunctionComponent<PercentInputProps> = ({
49
50
  value={internalPercentage}
50
51
  onInput={handleInputChange}
51
52
  lang='en'
52
- className={`grow w-16`}
53
+ className={`grow w-12`}
53
54
  />
54
- %
55
55
  </label>
56
56
  );
57
57
  };
@@ -16,7 +16,7 @@ export const ProportionSelectorDropdown: FunctionComponent<ProportionSelectorDro
16
16
  const width = 'w-[calc(1.5 * var(--tw-space-x-reverse) + 1.5 * var(--tw-space-x))]';
17
17
 
18
18
  return (
19
- <div className={width}>
19
+ <div className={`${width} inline-flex`}>
20
20
  <Dropdown buttonTitle={`${labelPrefix} ${percentLabel}`} placement={'bottom-start'}>
21
21
  <ProportionSelector
22
22
  proportionInterval={proportionInterval}
@@ -36,7 +36,7 @@ export const ScalingSelector: FunctionComponent<ScalingSelectorProps> = ({
36
36
  const value = select.value as ScaleType;
37
37
  setYAxisScaleType(value);
38
38
  }}
39
- selectStyle={`${className} select-xs select-bordered`}
39
+ selectStyle={`${className ?? ''} select-xs`}
40
40
  />
41
41
  );
42
42
  };
@@ -10,7 +10,7 @@ export interface SelectProps {
10
10
 
11
11
  export const Select: FunctionComponent<SelectProps> = ({ items, selected, onChange, selectStyle }) => {
12
12
  return (
13
- <select class={`select select-bordered ${selectStyle}`} value={selected} onChange={onChange}>
13
+ <select class={`select ${selectStyle} w-fit`} value={selected} onChange={onChange}>
14
14
  {items.map((item) => (
15
15
  <option key={item.value} value={item.value} disabled={item.disabled}>
16
16
  {item.label}
@@ -45,7 +45,7 @@ const Tabs: FunctionComponent<ComponentTabsProps> = ({ tabs, toolbar }) => {
45
45
  {tabElements}
46
46
  {toolbar && <div className='py-2 flex flex-wrap gap-y-1'>{toolbarElement}</div>}
47
47
  </div>
48
- <div className={`p-2 flex-grow overflow-scroll border-2 border-gray-100 rounded-b-md rounded-tr-md`}>
48
+ <div className={`p-2 grow overflow-scroll border-2 border-gray-100 rounded-b-md rounded-tr-md`}>
49
49
  {tabs.map((tab) => (
50
50
  <div className='h-full' key={tab.title} hidden={activeTab !== tab.title}>
51
51
  {tab.content}
@@ -55,7 +55,7 @@ export function DatePicker({
55
55
 
56
56
  return (
57
57
  <input
58
- className={`input input-bordered w-full ${className}`}
58
+ className={`input w-full ${className}`}
59
59
  type='text'
60
60
  placeholder={placeholderText}
61
61
  ref={inputRef}
@@ -193,7 +193,7 @@ export const DateRangeFilterInner = ({
193
193
  return (
194
194
  <div className={'@container'} ref={divRef}>
195
195
  <div className='flex min-w-[7.5rem] flex-col @md:flex-row'>
196
- <div className='flex-grow'>
196
+ <div className='grow'>
197
197
  <ClearableSelect
198
198
  items={options.map((item) => item.label)}
199
199
  placeholderText={placeholder}
@@ -205,9 +205,9 @@ export const DateRangeFilterInner = ({
205
205
  selectClassName={'rounded-t-md rounded-b-none @md:rounded-l-md @md:rounded-r-none'}
206
206
  />
207
207
  </div>
208
- <div className={'flex flex-grow flex-col @4xs:flex-row'}>
208
+ <div className={'flex grow flex-col @4xs:flex-row'}>
209
209
  <DatePicker
210
- className={'flex-grow min-w-[7.5rem] @4xs:rounded-bl-md @md:rounded-l-none rounded-none'}
210
+ className={'grow min-w-[7.5rem] @4xs:rounded-bl-md @md:rounded-l-none rounded-none'}
211
211
  value={state?.dateFrom}
212
212
  onChange={onChangeDateFrom}
213
213
  maxDate={state?.dateTo}
@@ -215,7 +215,7 @@ export const DateRangeFilterInner = ({
215
215
  />
216
216
  <DatePicker
217
217
  className={
218
- 'flex-grow min-w-[7.5rem] rounded-b-md rounded-t-none @4xs:rounded-tr-none @4xs:rounded-l-none @md:rounded-r-md '
218
+ 'grow min-w-[7.5rem] rounded-b-md rounded-t-none @4xs:rounded-tr-none @4xs:rounded-l-none @md:rounded-r-md '
219
219
  }
220
220
  value={state?.dateTo}
221
221
  onChange={onChangeDateTo}
@@ -178,7 +178,7 @@ const Toolbar: FunctionComponent<ToolbarProps> = ({
178
178
  setDisplayedMutationTypes={setDisplayedMutationTypes}
179
179
  />
180
180
  <CsvDownloadButton
181
- className='mx-1 btn btn-xs'
181
+ className='btn btn-xs'
182
182
  getData={() => getMutationComparisonTableData({ content: filteredData }, proportionInterval)}
183
183
  filename='mutation_comparison.csv'
184
184
  />
@@ -200,7 +200,7 @@ const Toolbar: FunctionComponent<ToolbarProps> = ({
200
200
  setMaxProportion={(max) => setProportionInterval((prev) => ({ ...prev, max }))}
201
201
  />
202
202
  <CsvDownloadButton
203
- className='mx-1 btn btn-xs'
203
+ className='btn btn-xs'
204
204
  getData={() =>
205
205
  getMutationsTableData(
206
206
  filteredData.tableData,
@@ -215,7 +215,7 @@ const Toolbar: FunctionComponent<ToolbarProps> = ({
215
215
  )}
216
216
  {activeTab === 'Insertions' && (
217
217
  <CsvDownloadButton
218
- className='mx-1 btn btn-xs'
218
+ className='btn btn-xs'
219
219
  getData={() =>
220
220
  getInsertionsTableData(filteredData.insertions).map((row) => {
221
221
  return {