@genspectrum/dashboard-components 0.18.3 → 0.18.5
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/components.d.ts +279 -0
- package/dist/components.js +63 -30
- package/dist/components.js.map +1 -1
- package/dist/style.css +1 -1
- package/dist/util.d.ts +279 -0
- package/package.json +2 -2
- package/src/preact/components/segment-selector.stories.tsx +12 -5
- package/src/preact/components/segment-selector.tsx +11 -7
- package/src/preact/mutationComparison/mutation-comparison.tsx +5 -1
- package/src/preact/mutations/mutations.tsx +5 -1
- package/src/preact/mutationsOverTime/mutations-over-time-grid.tsx +1 -1
- package/src/preact/mutationsOverTime/mutations-over-time.tsx +5 -1
- package/src/preact/sequencesByLocation/__mockData__/worldAtlas.json +1 -1
- package/src/preact/shared/tanstackTable/pagination.tsx +24 -17
- package/src/preact/wastewater/mutationsOverTime/wastewater-mutations-over-time.stories.tsx +3 -3
- package/src/preact/wastewater/mutationsOverTime/wastewater-mutations-over-time.tsx +5 -1
- package/standalone-bundle/dashboard-components.js +1999 -1967
- package/standalone-bundle/dashboard-components.js.map +1 -1
- package/standalone-bundle/style.css +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@genspectrum/dashboard-components",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.5",
|
|
4
4
|
"description": "GenSpectrum web components for building dashboards",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "AGPL-3.0-only",
|
|
@@ -145,7 +145,7 @@
|
|
|
145
145
|
"tailwindcss": "^4.0.9",
|
|
146
146
|
"typescript": "^5.8.2",
|
|
147
147
|
"vite": "^6.0.3",
|
|
148
|
-
"vite-plugin-dts": "
|
|
148
|
+
"vite-plugin-dts": "4.5.0",
|
|
149
149
|
"vitest": "^3.0.2"
|
|
150
150
|
}
|
|
151
151
|
}
|
|
@@ -4,6 +4,7 @@ import { type FunctionComponent } from 'preact';
|
|
|
4
4
|
import { useState } from 'preact/hooks';
|
|
5
5
|
|
|
6
6
|
import { type DisplayedSegment, SegmentSelector, type SegmentSelectorProps } from './segment-selector';
|
|
7
|
+
import type { SequenceType } from '../../types';
|
|
7
8
|
|
|
8
9
|
const meta: Meta<SegmentSelectorProps> = {
|
|
9
10
|
title: 'Component/Segment selector',
|
|
@@ -15,7 +16,8 @@ export default meta;
|
|
|
15
16
|
|
|
16
17
|
const WrapperWithState: FunctionComponent<{
|
|
17
18
|
displayedSegments: DisplayedSegment[];
|
|
18
|
-
|
|
19
|
+
sequenceType: SequenceType;
|
|
20
|
+
}> = ({ displayedSegments: initialDisplayedSegments, sequenceType }) => {
|
|
19
21
|
const [displayedSegments, setDisplayedSegments] = useState<DisplayedSegment[]>(initialDisplayedSegments);
|
|
20
22
|
|
|
21
23
|
return (
|
|
@@ -24,6 +26,7 @@ const WrapperWithState: FunctionComponent<{
|
|
|
24
26
|
setDisplayedSegments={(items: DisplayedSegment[]) => {
|
|
25
27
|
setDisplayedSegments(items);
|
|
26
28
|
}}
|
|
29
|
+
sequenceType={sequenceType}
|
|
27
30
|
/>
|
|
28
31
|
);
|
|
29
32
|
};
|
|
@@ -50,12 +53,13 @@ export const AllSegmentsSelected: StoryObj<SegmentSelectorProps> = {
|
|
|
50
53
|
checked: true,
|
|
51
54
|
},
|
|
52
55
|
],
|
|
56
|
+
sequenceType: 'amino acid',
|
|
53
57
|
},
|
|
54
58
|
play: async ({ canvasElement, step }) => {
|
|
55
59
|
const canvas = within(canvasElement);
|
|
56
60
|
|
|
57
|
-
await step("Show 'All
|
|
58
|
-
await expect(canvas.getByText('All
|
|
61
|
+
await step("Show 'All genes' as label", async () => {
|
|
62
|
+
await expect(canvas.getByText('All genes')).toBeInTheDocument();
|
|
59
63
|
});
|
|
60
64
|
},
|
|
61
65
|
};
|
|
@@ -80,6 +84,7 @@ export const NoSegmentsSelected: StoryObj<SegmentSelectorProps> = {
|
|
|
80
84
|
checked: false,
|
|
81
85
|
},
|
|
82
86
|
],
|
|
87
|
+
sequenceType: 'nucleotide',
|
|
83
88
|
},
|
|
84
89
|
play: async ({ canvasElement, step }) => {
|
|
85
90
|
const canvas = within(canvasElement);
|
|
@@ -110,12 +115,13 @@ export const LongSegmentsSelected: StoryObj<SegmentSelectorProps> = {
|
|
|
110
115
|
checked: true,
|
|
111
116
|
},
|
|
112
117
|
],
|
|
118
|
+
sequenceType: 'amino acid',
|
|
113
119
|
},
|
|
114
120
|
play: async ({ canvasElement, step }) => {
|
|
115
121
|
const canvas = within(canvasElement);
|
|
116
122
|
|
|
117
|
-
await step('Show number of active
|
|
118
|
-
await expect(canvas.getByText('2
|
|
123
|
+
await step('Show number of active genes as label', async () => {
|
|
124
|
+
await expect(canvas.getByText('2 genes')).toBeInTheDocument();
|
|
119
125
|
});
|
|
120
126
|
},
|
|
121
127
|
};
|
|
@@ -140,6 +146,7 @@ export const ShortSegmentsSelected: StoryObj<SegmentSelectorProps> = {
|
|
|
140
146
|
checked: false,
|
|
141
147
|
},
|
|
142
148
|
],
|
|
149
|
+
sequenceType: 'amino acid',
|
|
143
150
|
},
|
|
144
151
|
play: async ({ canvasElement, step }) => {
|
|
145
152
|
const canvas = within(canvasElement);
|
|
@@ -13,40 +13,44 @@ export type DisplayedSegment = CheckboxItem & {
|
|
|
13
13
|
export type SegmentSelectorProps = {
|
|
14
14
|
displayedSegments: DisplayedSegment[];
|
|
15
15
|
setDisplayedSegments: (items: DisplayedSegment[]) => void;
|
|
16
|
+
sequenceType: SequenceType;
|
|
16
17
|
};
|
|
17
18
|
|
|
18
19
|
export const SegmentSelector: FunctionComponent<SegmentSelectorProps> = ({
|
|
19
20
|
displayedSegments,
|
|
20
21
|
setDisplayedSegments,
|
|
22
|
+
sequenceType,
|
|
21
23
|
}) => {
|
|
22
24
|
if (displayedSegments.length <= 1) {
|
|
23
25
|
return null;
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
return (
|
|
27
|
-
<div className='w-
|
|
29
|
+
<div className='w-20 inline-flex'>
|
|
28
30
|
<CheckboxSelector
|
|
29
31
|
items={displayedSegments}
|
|
30
|
-
label={getSegmentSelectorLabel(displayedSegments)}
|
|
32
|
+
label={getSegmentSelectorLabel(displayedSegments, sequenceType)}
|
|
31
33
|
setItems={(items) => setDisplayedSegments(items)}
|
|
32
34
|
/>
|
|
33
35
|
</div>
|
|
34
36
|
);
|
|
35
37
|
};
|
|
36
38
|
|
|
37
|
-
const getSegmentSelectorLabel = (displayedSegments: DisplayedSegment[]) => {
|
|
39
|
+
const getSegmentSelectorLabel = (displayedSegments: DisplayedSegment[], sequenceType: SequenceType) => {
|
|
38
40
|
const allSelectedSelected = displayedSegments
|
|
39
41
|
.filter((segment) => segment.checked)
|
|
40
42
|
.map((segment) => segment.segment);
|
|
41
43
|
|
|
44
|
+
const label = sequenceType === 'amino acid' ? 'gene' : 'segment';
|
|
45
|
+
|
|
42
46
|
if (allSelectedSelected.length === 0) {
|
|
43
|
-
return `No
|
|
47
|
+
return `No ${label}s`;
|
|
44
48
|
}
|
|
45
49
|
if (displayedSegments.length === allSelectedSelected.length) {
|
|
46
|
-
return `All
|
|
50
|
+
return `All ${label}s`;
|
|
47
51
|
}
|
|
48
52
|
|
|
49
|
-
const longestDisplayString = `All
|
|
53
|
+
const longestDisplayString = `All ${label}s`;
|
|
50
54
|
|
|
51
55
|
const allSelectedSelectedString = allSelectedSelected.join(', ');
|
|
52
56
|
|
|
@@ -54,7 +58,7 @@ const getSegmentSelectorLabel = (displayedSegments: DisplayedSegment[]) => {
|
|
|
54
58
|
return allSelectedSelectedString;
|
|
55
59
|
}
|
|
56
60
|
|
|
57
|
-
return `${allSelectedSelected.length} ${allSelectedSelected.length === 1 ?
|
|
61
|
+
return `${allSelectedSelected.length} ${allSelectedSelected.length === 1 ? label : `${label}s`}`;
|
|
58
62
|
};
|
|
59
63
|
|
|
60
64
|
export function useDisplayedSegments(sequenceType: SequenceType) {
|
|
@@ -172,7 +172,11 @@ const Toolbar: FunctionComponent<ToolbarProps> = ({
|
|
|
172
172
|
setMinProportion={(min) => setProportionInterval((prev) => ({ ...prev, min }))}
|
|
173
173
|
setMaxProportion={(max) => setProportionInterval((prev) => ({ ...prev, max }))}
|
|
174
174
|
/>
|
|
175
|
-
<SegmentSelector
|
|
175
|
+
<SegmentSelector
|
|
176
|
+
displayedSegments={displayedSegments}
|
|
177
|
+
setDisplayedSegments={setDisplayedSegments}
|
|
178
|
+
sequenceType={originalComponentProps.sequenceType}
|
|
179
|
+
/>
|
|
176
180
|
<MutationTypeSelector
|
|
177
181
|
displayedMutationTypes={displayedMutationTypes}
|
|
178
182
|
setDisplayedMutationTypes={setDisplayedMutationTypes}
|
|
@@ -185,7 +185,11 @@ const Toolbar: FunctionComponent<ToolbarProps> = ({
|
|
|
185
185
|
}) => {
|
|
186
186
|
return (
|
|
187
187
|
<>
|
|
188
|
-
<SegmentSelector
|
|
188
|
+
<SegmentSelector
|
|
189
|
+
displayedSegments={displayedSegments}
|
|
190
|
+
setDisplayedSegments={setDisplayedSegments}
|
|
191
|
+
sequenceType={originalComponentProps.sequenceType}
|
|
192
|
+
/>
|
|
189
193
|
{activeTab === 'Table' && (
|
|
190
194
|
<MutationTypeSelector
|
|
191
195
|
setDisplayedMutationTypes={setDisplayedMutationTypes}
|
|
@@ -192,7 +192,7 @@ const ProportionCell: FunctionComponent<{
|
|
|
192
192
|
backgroundColor: getColorWithinScale(proportion, colorScale),
|
|
193
193
|
color: getTextColorForScale(proportion, colorScale),
|
|
194
194
|
}}
|
|
195
|
-
className={`w-full h-full hover:font-bold text-xs group @container`}
|
|
195
|
+
className={`w-full h-full hover:font-bold text-xs group @container text-nowrap`}
|
|
196
196
|
>
|
|
197
197
|
{value === null ? (
|
|
198
198
|
<span className='invisible'>No data</span>
|
|
@@ -228,7 +228,11 @@ const Toolbar: FunctionComponent<ToolbarProps> = ({
|
|
|
228
228
|
{activeTab === 'Grid' && (
|
|
229
229
|
<ColorScaleSelectorDropdown colorScale={colorScale} setColorScale={setColorScale} />
|
|
230
230
|
)}
|
|
231
|
-
<SegmentSelector
|
|
231
|
+
<SegmentSelector
|
|
232
|
+
displayedSegments={displayedSegments}
|
|
233
|
+
setDisplayedSegments={setDisplayedSegments}
|
|
234
|
+
sequenceType={originalComponentProps.sequenceType}
|
|
235
|
+
/>
|
|
232
236
|
<MutationTypeSelector
|
|
233
237
|
setDisplayedMutationTypes={setDisplayedMutationTypes}
|
|
234
238
|
displayedMutationTypes={displayedMutationTypes}
|