@genspectrum/dashboard-components 0.4.0 → 0.4.1
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/dashboard-components.js +253 -323
- package/dist/dashboard-components.js.map +1 -1
- package/dist/genspectrum-components.d.ts +4 -4
- package/dist/style.css +98 -185
- package/package.json +2 -1
- package/src/preact/components/SegmentSelector.tsx +0 -1
- package/src/preact/components/checkbox-selector.tsx +7 -9
- package/src/preact/components/dropdown.tsx +40 -0
- package/src/preact/components/info.tsx +20 -94
- package/src/preact/components/mutation-type-selector.tsx +0 -1
- package/src/preact/components/proportion-selector-dropdown.tsx +9 -18
- package/src/preact/components/tabs.tsx +12 -3
- package/src/preact/dateRangeSelector/date-range-selector.tsx +22 -18
- package/src/preact/mutationComparison/mutation-comparison.tsx +2 -2
- package/src/preact/mutations/mutations.tsx +2 -3
- package/src/preact/prevalenceOverTime/prevalence-over-time.tsx +3 -5
- package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.tsx +2 -2
- package/src/preact/shared/floating-ui/hooks.ts +83 -0
- package/src/web-components/visualization/gs-prevalence-over-time.tsx +1 -1
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { offset, shift, size } from '@floating-ui/dom';
|
|
2
2
|
import { type FunctionComponent } from 'preact';
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import { useRef, useState } from 'preact/hooks';
|
|
4
|
+
|
|
5
|
+
import { dropdownClass } from './dropdown';
|
|
6
|
+
import { useCloseOnClickOutside, useCloseOnEsc, useFloatingUi } from '../shared/floating-ui/hooks';
|
|
5
7
|
|
|
6
8
|
export interface InfoProps {
|
|
7
9
|
height?: string;
|
|
@@ -12,7 +14,19 @@ const Info: FunctionComponent<InfoProps> = ({ children, height }) => {
|
|
|
12
14
|
const referenceRef = useRef<HTMLButtonElement>(null);
|
|
13
15
|
const floatingRef = useRef<HTMLDivElement>(null);
|
|
14
16
|
|
|
15
|
-
useFloatingUi(referenceRef, floatingRef,
|
|
17
|
+
useFloatingUi(referenceRef, floatingRef, [
|
|
18
|
+
offset(10),
|
|
19
|
+
shift(),
|
|
20
|
+
size({
|
|
21
|
+
apply() {
|
|
22
|
+
if (!floatingRef.current) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
floatingRef.current.style.width = '100vw';
|
|
26
|
+
floatingRef.current.style.height = height ? height : '50vh';
|
|
27
|
+
},
|
|
28
|
+
}),
|
|
29
|
+
]);
|
|
16
30
|
|
|
17
31
|
const toggleHelp = () => {
|
|
18
32
|
setShowHelp(!showHelp);
|
|
@@ -22,14 +36,13 @@ const Info: FunctionComponent<InfoProps> = ({ children, height }) => {
|
|
|
22
36
|
useCloseOnClickOutside(floatingRef, referenceRef, setShowHelp);
|
|
23
37
|
|
|
24
38
|
return (
|
|
25
|
-
<div className='relative
|
|
39
|
+
<div className='relative'>
|
|
26
40
|
<button type='button' className='btn btn-xs' onClick={toggleHelp} ref={referenceRef}>
|
|
27
41
|
?
|
|
28
42
|
</button>
|
|
29
43
|
<div
|
|
30
44
|
ref={floatingRef}
|
|
31
|
-
className=
|
|
32
|
-
style={{ position: 'absolute', zIndex: 10, display: showHelp ? '' : 'none' }}
|
|
45
|
+
className={`${dropdownClass} overflow-y-auto opacity-90 ${showHelp ? '' : 'hidden'}`}
|
|
33
46
|
>
|
|
34
47
|
<div className={'flex flex-col'}>{children}</div>
|
|
35
48
|
<button
|
|
@@ -43,93 +56,6 @@ const Info: FunctionComponent<InfoProps> = ({ children, height }) => {
|
|
|
43
56
|
);
|
|
44
57
|
};
|
|
45
58
|
|
|
46
|
-
function useFloatingUi(
|
|
47
|
-
referenceRef: MutableRefObject<HTMLButtonElement | null>,
|
|
48
|
-
floatingRef: MutableRefObject<HTMLDivElement | null>,
|
|
49
|
-
height: string | undefined,
|
|
50
|
-
showHelp: boolean,
|
|
51
|
-
) {
|
|
52
|
-
const cleanupRef = useRef<Function | null>(null);
|
|
53
|
-
|
|
54
|
-
useEffect(() => {
|
|
55
|
-
if (!referenceRef.current || !floatingRef.current) {
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const { current: reference } = referenceRef;
|
|
60
|
-
const { current: floating } = floatingRef;
|
|
61
|
-
|
|
62
|
-
const update = () => {
|
|
63
|
-
computePosition(reference, floating, {
|
|
64
|
-
middleware: [
|
|
65
|
-
offset(10),
|
|
66
|
-
shift(),
|
|
67
|
-
size({
|
|
68
|
-
apply({}) {
|
|
69
|
-
floating.style.width = '100vw';
|
|
70
|
-
floating.style.height = height ? height : '50vh';
|
|
71
|
-
},
|
|
72
|
-
}),
|
|
73
|
-
],
|
|
74
|
-
}).then(({ x, y }) => {
|
|
75
|
-
floating.style.left = `${x}px`;
|
|
76
|
-
floating.style.top = `${y}px`;
|
|
77
|
-
});
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
update();
|
|
81
|
-
cleanupRef.current = autoUpdate(reference, floating, update);
|
|
82
|
-
|
|
83
|
-
return () => {
|
|
84
|
-
if (cleanupRef.current) {
|
|
85
|
-
cleanupRef.current();
|
|
86
|
-
}
|
|
87
|
-
};
|
|
88
|
-
}, [showHelp, height, referenceRef, floatingRef]);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function useCloseOnClickOutside(
|
|
92
|
-
floatingRef: MutableRefObject<HTMLDivElement | null>,
|
|
93
|
-
referenceRef: MutableRefObject<HTMLButtonElement | null>,
|
|
94
|
-
setShowHelp: (value: ((prevState: boolean) => boolean) | boolean) => void,
|
|
95
|
-
) {
|
|
96
|
-
useEffect(() => {
|
|
97
|
-
const handleClickOutside = (event: MouseEvent) => {
|
|
98
|
-
const path = event.composedPath();
|
|
99
|
-
if (
|
|
100
|
-
floatingRef.current &&
|
|
101
|
-
!path.includes(floatingRef.current) &&
|
|
102
|
-
referenceRef.current &&
|
|
103
|
-
!path.includes(referenceRef.current)
|
|
104
|
-
) {
|
|
105
|
-
setShowHelp(false);
|
|
106
|
-
}
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
document.addEventListener('mousedown', handleClickOutside);
|
|
110
|
-
|
|
111
|
-
return () => {
|
|
112
|
-
document.removeEventListener('mousedown', handleClickOutside);
|
|
113
|
-
};
|
|
114
|
-
}, [floatingRef, referenceRef, setShowHelp]);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
function useCloseOnEsc(setShowHelp: (value: ((prevState: boolean) => boolean) | boolean) => void) {
|
|
118
|
-
useEffect(() => {
|
|
119
|
-
const handleKeyDown = (event: KeyboardEvent) => {
|
|
120
|
-
if (event.key === 'Escape') {
|
|
121
|
-
setShowHelp(false);
|
|
122
|
-
}
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
document.addEventListener('keydown', handleKeyDown);
|
|
126
|
-
|
|
127
|
-
return () => {
|
|
128
|
-
document.removeEventListener('keydown', handleKeyDown);
|
|
129
|
-
};
|
|
130
|
-
}, [setShowHelp]);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
59
|
export const InfoHeadline1: FunctionComponent = ({ children }) => {
|
|
134
60
|
return <h1 className='text-lg font-bold'>{children}</h1>;
|
|
135
61
|
};
|
|
@@ -21,7 +21,6 @@ export const MutationTypeSelector: FunctionComponent<MutationTypeSelectorProps>
|
|
|
21
21
|
|
|
22
22
|
return (
|
|
23
23
|
<CheckboxSelector
|
|
24
|
-
className='mx-1'
|
|
25
24
|
items={displayedMutationTypes}
|
|
26
25
|
label={mutationTypesSelectorLabel}
|
|
27
26
|
setItems={(items) => setDisplayedMutationTypes(items)}
|
|
@@ -1,33 +1,24 @@
|
|
|
1
1
|
import { type FunctionComponent } from 'preact';
|
|
2
2
|
|
|
3
|
+
import { Dropdown } from './dropdown';
|
|
3
4
|
import { ProportionSelector, type ProportionSelectorProps } from './proportion-selector';
|
|
4
5
|
|
|
5
|
-
export
|
|
6
|
-
openDirection?: 'left' | 'right';
|
|
7
|
-
}
|
|
6
|
+
export type ProportionSelectorDropdownProps = ProportionSelectorProps;
|
|
8
7
|
|
|
9
8
|
export const ProportionSelectorDropdown: FunctionComponent<ProportionSelectorDropdownProps> = ({
|
|
10
9
|
proportionInterval,
|
|
11
10
|
setMinProportion,
|
|
12
11
|
setMaxProportion,
|
|
13
|
-
openDirection = 'right',
|
|
14
12
|
}) => {
|
|
15
13
|
const label = `${(proportionInterval.min * 100).toFixed(1)}% - ${(proportionInterval.max * 100).toFixed(1)}%`;
|
|
16
14
|
|
|
17
15
|
return (
|
|
18
|
-
<
|
|
19
|
-
<
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
proportionInterval={proportionInterval}
|
|
26
|
-
setMinProportion={setMinProportion}
|
|
27
|
-
setMaxProportion={setMaxProportion}
|
|
28
|
-
/>
|
|
29
|
-
</div>
|
|
30
|
-
</ul>
|
|
31
|
-
</div>
|
|
16
|
+
<Dropdown buttonTitle={`Proportion ${label}`} placement={'bottom-start'}>
|
|
17
|
+
<ProportionSelector
|
|
18
|
+
proportionInterval={proportionInterval}
|
|
19
|
+
setMinProportion={setMinProportion}
|
|
20
|
+
setMaxProportion={setMaxProportion}
|
|
21
|
+
/>
|
|
22
|
+
</Dropdown>
|
|
32
23
|
);
|
|
33
24
|
};
|
|
@@ -17,11 +17,20 @@ const Tabs: FunctionComponent<ComponentTabsProps> = ({ tabs, toolbar }) => {
|
|
|
17
17
|
const [heightOfTabs, setHeightOfTabs] = useState('3rem');
|
|
18
18
|
const tabRef = useRef<HTMLDivElement>(null);
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
const updateHeightOfTabs = () => {
|
|
21
21
|
if (tabRef.current) {
|
|
22
22
|
const heightOfTabs = tabRef.current.getBoundingClientRect().height;
|
|
23
23
|
setHeightOfTabs(`${heightOfTabs}px`);
|
|
24
24
|
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
updateHeightOfTabs();
|
|
29
|
+
|
|
30
|
+
window.addEventListener('resize', updateHeightOfTabs);
|
|
31
|
+
return () => {
|
|
32
|
+
window.removeEventListener('resize', updateHeightOfTabs);
|
|
33
|
+
};
|
|
25
34
|
}, []);
|
|
26
35
|
|
|
27
36
|
const tabElements = (
|
|
@@ -51,9 +60,9 @@ const Tabs: FunctionComponent<ComponentTabsProps> = ({ tabs, toolbar }) => {
|
|
|
51
60
|
|
|
52
61
|
return (
|
|
53
62
|
<div className='h-full w-full'>
|
|
54
|
-
<div ref={tabRef} className='flex flex-row justify-between'>
|
|
63
|
+
<div ref={tabRef} className='flex flex-row justify-between flex-wrap'>
|
|
55
64
|
{tabElements}
|
|
56
|
-
{toolbar && <div className='py-2'>{toolbarElement}</div>}
|
|
65
|
+
{toolbar && <div className='py-2 flex flex-wrap gap-y-1'>{toolbarElement}</div>}
|
|
57
66
|
</div>
|
|
58
67
|
<div
|
|
59
68
|
className={`p-2 border-2 border-gray-100 rounded-b-md rounded-tr-md ${activeTab === tabs[0].title ? '' : 'rounded-tl-md'}`}
|
|
@@ -179,11 +179,11 @@ export const DateRangeSelectorInner = <CustomLabel extends string>({
|
|
|
179
179
|
};
|
|
180
180
|
|
|
181
181
|
return (
|
|
182
|
-
<div class='
|
|
182
|
+
<div class='flex flex-wrap' ref={divRef}>
|
|
183
183
|
<Select
|
|
184
184
|
items={getSelectableOptions(customSelectOptions)}
|
|
185
185
|
selected={selectedDateRange}
|
|
186
|
-
selectStyle='select-bordered rounded-none
|
|
186
|
+
selectStyle='select-bordered rounded-none flex-grow w-40'
|
|
187
187
|
onChange={(event: Event) => {
|
|
188
188
|
event.preventDefault();
|
|
189
189
|
const select = event.target as HTMLSelectElement;
|
|
@@ -191,22 +191,26 @@ export const DateRangeSelectorInner = <CustomLabel extends string>({
|
|
|
191
191
|
onSelectChange(value as CustomLabel | PresetOptionValues);
|
|
192
192
|
}}
|
|
193
193
|
/>
|
|
194
|
-
<
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
194
|
+
<div className={'flex flex-wrap flex-grow'}>
|
|
195
|
+
<input
|
|
196
|
+
class='input input-bordered rounded-none flex-grow min-w-40'
|
|
197
|
+
type='text'
|
|
198
|
+
size={10}
|
|
199
|
+
placeholder='Date from'
|
|
200
|
+
ref={fromDatePickerRef}
|
|
201
|
+
onChange={onChangeDateFrom}
|
|
202
|
+
onBlur={onChangeDateFrom}
|
|
203
|
+
/>
|
|
204
|
+
<input
|
|
205
|
+
class='input input-bordered rounded-none flex-grow min-w-40'
|
|
206
|
+
type='text'
|
|
207
|
+
size={10}
|
|
208
|
+
placeholder='Date to'
|
|
209
|
+
ref={toDatePickerRef}
|
|
210
|
+
onChange={onChangeDateTo}
|
|
211
|
+
onBlur={onChangeDateTo}
|
|
212
|
+
/>
|
|
213
|
+
</div>
|
|
210
214
|
</div>
|
|
211
215
|
);
|
|
212
216
|
};
|
|
@@ -167,7 +167,7 @@ const Toolbar: FunctionComponent<ToolbarProps> = ({
|
|
|
167
167
|
setProportionInterval,
|
|
168
168
|
}) => {
|
|
169
169
|
return (
|
|
170
|
-
|
|
170
|
+
<>
|
|
171
171
|
<ProportionSelectorDropdown
|
|
172
172
|
proportionInterval={proportionInterval}
|
|
173
173
|
setMinProportion={(min) => setProportionInterval((prev) => ({ ...prev, min }))}
|
|
@@ -184,6 +184,6 @@ const Toolbar: FunctionComponent<ToolbarProps> = ({
|
|
|
184
184
|
filename='mutation_comparison.csv'
|
|
185
185
|
/>
|
|
186
186
|
<Info height={'100px'}>Info for mutation comparison</Info>
|
|
187
|
-
|
|
187
|
+
</>
|
|
188
188
|
);
|
|
189
189
|
};
|
|
@@ -168,7 +168,7 @@ const Toolbar: FunctionComponent<ToolbarProps> = ({
|
|
|
168
168
|
setProportionInterval,
|
|
169
169
|
}) => {
|
|
170
170
|
return (
|
|
171
|
-
|
|
171
|
+
<>
|
|
172
172
|
<SegmentSelector displayedSegments={displayedSegments} setDisplayedSegments={setDisplayedSegments} />
|
|
173
173
|
{activeTab === 'Table' && (
|
|
174
174
|
<MutationTypeSelector
|
|
@@ -182,7 +182,6 @@ const Toolbar: FunctionComponent<ToolbarProps> = ({
|
|
|
182
182
|
proportionInterval={proportionInterval}
|
|
183
183
|
setMinProportion={(min) => setProportionInterval((prev) => ({ ...prev, min }))}
|
|
184
184
|
setMaxProportion={(max) => setProportionInterval((prev) => ({ ...prev, max }))}
|
|
185
|
-
openDirection={'left'}
|
|
186
185
|
/>
|
|
187
186
|
<CsvDownloadButton
|
|
188
187
|
className='mx-1 btn btn-xs'
|
|
@@ -206,6 +205,6 @@ const Toolbar: FunctionComponent<ToolbarProps> = ({
|
|
|
206
205
|
/>
|
|
207
206
|
)}
|
|
208
207
|
<Info height={'100px'}>Info for mutations</Info>
|
|
209
|
-
|
|
208
|
+
</>
|
|
210
209
|
);
|
|
211
210
|
};
|
|
@@ -208,7 +208,7 @@ const Toolbar: FunctionComponent<ToolbarProps> = ({
|
|
|
208
208
|
granularity,
|
|
209
209
|
}) => {
|
|
210
210
|
return (
|
|
211
|
-
|
|
211
|
+
<>
|
|
212
212
|
{activeTab !== 'Table' && (
|
|
213
213
|
<ScalingSelector yAxisScaleType={yAxisScaleType} setYAxisScaleType={setYAxisScaleType} />
|
|
214
214
|
)}
|
|
@@ -226,11 +226,11 @@ const Toolbar: FunctionComponent<ToolbarProps> = ({
|
|
|
226
226
|
/>
|
|
227
227
|
|
|
228
228
|
<PrevalenceOverTimeInfo />
|
|
229
|
-
|
|
229
|
+
</>
|
|
230
230
|
);
|
|
231
231
|
};
|
|
232
232
|
|
|
233
|
-
const PrevalenceOverTimeInfo: FunctionComponent = (
|
|
233
|
+
const PrevalenceOverTimeInfo: FunctionComponent = () => {
|
|
234
234
|
return (
|
|
235
235
|
<Info height={'100px'}>
|
|
236
236
|
<InfoHeadline1>Prevalence over time</InfoHeadline1>
|
|
@@ -238,5 +238,3 @@ const PrevalenceOverTimeInfo: FunctionComponent = ({}) => {
|
|
|
238
238
|
</Info>
|
|
239
239
|
);
|
|
240
240
|
};
|
|
241
|
-
|
|
242
|
-
export default PrevalenceOverTime;
|
|
@@ -161,10 +161,10 @@ const RelativeGrowthAdvantageToolbar: FunctionComponent<RelativeGrowthAdvantageT
|
|
|
161
161
|
generationTime,
|
|
162
162
|
}) => {
|
|
163
163
|
return (
|
|
164
|
-
|
|
164
|
+
<>
|
|
165
165
|
<ScalingSelector yAxisScaleType={yAxisScaleType} setYAxisScaleType={setYAxisScaleType} />
|
|
166
166
|
<RelativeGrowthAdvantageInfo generationTime={generationTime} />
|
|
167
|
-
|
|
167
|
+
</>
|
|
168
168
|
);
|
|
169
169
|
};
|
|
170
170
|
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { autoUpdate, computePosition, type Middleware } from '@floating-ui/dom';
|
|
2
|
+
import type { Placement } from '@floating-ui/utils';
|
|
3
|
+
import { useEffect, useRef } from 'preact/hooks';
|
|
4
|
+
import type { MutableRefObject } from 'react';
|
|
5
|
+
|
|
6
|
+
export function useFloatingUi(
|
|
7
|
+
referenceRef: MutableRefObject<HTMLElement | null>,
|
|
8
|
+
floatingRef: MutableRefObject<HTMLElement | null>,
|
|
9
|
+
middleware?: Array<Middleware | null | undefined | false>,
|
|
10
|
+
placement?: Placement,
|
|
11
|
+
) {
|
|
12
|
+
const cleanupRef = useRef<Function | null>(null);
|
|
13
|
+
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
if (!referenceRef.current || !floatingRef.current) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const { current: reference } = referenceRef;
|
|
20
|
+
const { current: floating } = floatingRef;
|
|
21
|
+
|
|
22
|
+
const update = () => {
|
|
23
|
+
computePosition(reference, floating, {
|
|
24
|
+
placement,
|
|
25
|
+
middleware,
|
|
26
|
+
}).then(({ x, y }) => {
|
|
27
|
+
floating.style.left = `${x}px`;
|
|
28
|
+
floating.style.top = `${y}px`;
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
update();
|
|
33
|
+
cleanupRef.current = autoUpdate(reference, floating, update);
|
|
34
|
+
|
|
35
|
+
return () => {
|
|
36
|
+
if (cleanupRef.current) {
|
|
37
|
+
cleanupRef.current();
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
}, [placement, middleware, referenceRef, floatingRef]);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function useCloseOnClickOutside(
|
|
44
|
+
floatingRef: MutableRefObject<HTMLElement | null>,
|
|
45
|
+
referenceRef: MutableRefObject<HTMLElement | null>,
|
|
46
|
+
setShowContent: (value: ((prevState: boolean) => boolean) | boolean) => void,
|
|
47
|
+
) {
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
const handleClickOutside = (event: MouseEvent) => {
|
|
50
|
+
const path = event.composedPath();
|
|
51
|
+
if (
|
|
52
|
+
floatingRef.current &&
|
|
53
|
+
!path.includes(floatingRef.current) &&
|
|
54
|
+
referenceRef.current &&
|
|
55
|
+
!path.includes(referenceRef.current)
|
|
56
|
+
) {
|
|
57
|
+
setShowContent(false);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
document.addEventListener('mousedown', handleClickOutside);
|
|
62
|
+
|
|
63
|
+
return () => {
|
|
64
|
+
document.removeEventListener('mousedown', handleClickOutside);
|
|
65
|
+
};
|
|
66
|
+
}, [floatingRef, referenceRef, setShowContent]);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function useCloseOnEsc(setShowHelp: (value: ((prevState: boolean) => boolean) | boolean) => void) {
|
|
70
|
+
useEffect(() => {
|
|
71
|
+
const handleKeyDown = (event: KeyboardEvent) => {
|
|
72
|
+
if (event.key === 'Escape') {
|
|
73
|
+
setShowHelp(false);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
document.addEventListener('keydown', handleKeyDown);
|
|
78
|
+
|
|
79
|
+
return () => {
|
|
80
|
+
document.removeEventListener('keydown', handleKeyDown);
|
|
81
|
+
};
|
|
82
|
+
}, [setShowHelp]);
|
|
83
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { customElement, property } from 'lit/decorators.js';
|
|
2
2
|
|
|
3
|
-
import PrevalenceOverTime,
|
|
3
|
+
import { PrevalenceOverTime, type PrevalenceOverTimeProps } from '../../preact/prevalenceOverTime/prevalence-over-time';
|
|
4
4
|
import { type Equals, type Expect } from '../../utils/typeAssertions';
|
|
5
5
|
import { PreactLitAdapterWithGridJsStyles } from '../PreactLitAdapterWithGridJsStyles';
|
|
6
6
|
|