@genspectrum/dashboard-components 0.19.3 → 0.19.4
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/custom-elements.json +223 -0
- package/dist/{LineageFilterChangedEvent-b0iuroUL.js → LineageFilterChangedEvent-GgkxoF3X.js} +4 -2
- package/dist/{LineageFilterChangedEvent-b0iuroUL.js.map → LineageFilterChangedEvent-GgkxoF3X.js.map} +1 -1
- package/dist/components.d.ts +146 -29
- package/dist/components.js +555 -234
- package/dist/components.js.map +1 -1
- package/dist/util.d.ts +51 -29
- package/dist/util.js +1 -1
- package/package.json +1 -1
- package/src/preact/components/min-max-range-slider.tsx +19 -4
- package/src/preact/dateRangeFilter/date-range-filter.stories.tsx +4 -1
- package/src/preact/genomeViewer/loadGff3.spec.ts +1 -1
- package/src/preact/genomeViewer/loadGff3.ts +12 -6
- package/src/preact/numberRangeFilter/NumberRangeFilterChangedEvent.ts +31 -0
- package/src/preact/numberRangeFilter/number-range-filter.stories.tsx +383 -0
- package/src/preact/numberRangeFilter/number-range-filter.tsx +159 -0
- package/src/preact/numberRangeFilter/useSelectedRangeReducer.ts +137 -0
- package/src/utils/gsEventNames.ts +2 -0
- package/src/web-components/input/gs-number-range-filter.spec.ts +27 -0
- package/src/web-components/input/gs-number-range-filter.stories.ts +96 -0
- package/src/web-components/input/gs-number-range-filter.tsx +148 -0
- package/src/web-components/input/gs-text-filter.stories.ts +2 -2
- package/src/web-components/input/index.ts +1 -0
- package/standalone-bundle/dashboard-components.js +6921 -6640
- package/standalone-bundle/dashboard-components.js.map +1 -1
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { describe, expectTypeOf, test } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { NumberRangeFilterComponent } from './gs-number-range-filter';
|
|
4
|
+
import { type NumberRangeFilterProps } from '../../preact/numberRangeFilter/number-range-filter';
|
|
5
|
+
|
|
6
|
+
describe('gs-number-range-filter types', () => {
|
|
7
|
+
test('should match', ({}) => {
|
|
8
|
+
expectTypeOf(NumberRangeFilterComponent.prototype)
|
|
9
|
+
.toHaveProperty('value')
|
|
10
|
+
.toEqualTypeOf<NumberRangeFilterProps['value']>();
|
|
11
|
+
expectTypeOf(NumberRangeFilterComponent.prototype)
|
|
12
|
+
.toHaveProperty('lapisField')
|
|
13
|
+
.toEqualTypeOf<NumberRangeFilterProps['lapisField']>();
|
|
14
|
+
expectTypeOf(NumberRangeFilterComponent.prototype)
|
|
15
|
+
.toHaveProperty('sliderMin')
|
|
16
|
+
.toEqualTypeOf<NumberRangeFilterProps['sliderMin']>();
|
|
17
|
+
expectTypeOf(NumberRangeFilterComponent.prototype)
|
|
18
|
+
.toHaveProperty('sliderMax')
|
|
19
|
+
.toEqualTypeOf<NumberRangeFilterProps['sliderMax']>();
|
|
20
|
+
expectTypeOf(NumberRangeFilterComponent.prototype)
|
|
21
|
+
.toHaveProperty('sliderStep')
|
|
22
|
+
.toEqualTypeOf<NumberRangeFilterProps['sliderStep']>();
|
|
23
|
+
expectTypeOf(NumberRangeFilterComponent.prototype)
|
|
24
|
+
.toHaveProperty('width')
|
|
25
|
+
.toEqualTypeOf<NumberRangeFilterProps['width']>();
|
|
26
|
+
});
|
|
27
|
+
});
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import '../gs-app';
|
|
2
|
+
import './gs-number-range-filter';
|
|
3
|
+
|
|
4
|
+
import { type Meta, type StoryObj } from '@storybook/web-components';
|
|
5
|
+
import { html } from 'lit';
|
|
6
|
+
|
|
7
|
+
import { withComponentDocs } from '../../../.storybook/ComponentDocsBlock';
|
|
8
|
+
import { LAPIS_URL } from '../../constants';
|
|
9
|
+
import { type NumberRangeFilterProps } from '../../preact/numberRangeFilter/number-range-filter';
|
|
10
|
+
import { gsEventNames } from '../../utils/gsEventNames';
|
|
11
|
+
|
|
12
|
+
const codeExample = String.raw`
|
|
13
|
+
<gs-number-range-filter
|
|
14
|
+
value='{"ageFrom": 10, "ageTo": 90}'
|
|
15
|
+
lapisField="age"
|
|
16
|
+
sliderMin="0"
|
|
17
|
+
sliderMax="100"
|
|
18
|
+
sliderStep="1"
|
|
19
|
+
width="50%"
|
|
20
|
+
></gs-number-range-filter>`;
|
|
21
|
+
|
|
22
|
+
const meta: Meta<NumberRangeFilterProps> = {
|
|
23
|
+
title: 'Input/Number range filter',
|
|
24
|
+
component: 'gs-number-range-filter',
|
|
25
|
+
parameters: withComponentDocs({
|
|
26
|
+
actions: {
|
|
27
|
+
handles: [gsEventNames.numberRangeFilterChanged, gsEventNames.numberRangeValueChanged],
|
|
28
|
+
},
|
|
29
|
+
componentDocs: {
|
|
30
|
+
opensShadowDom: true,
|
|
31
|
+
expectsChildren: false,
|
|
32
|
+
codeExample,
|
|
33
|
+
},
|
|
34
|
+
}),
|
|
35
|
+
tags: ['autodocs'],
|
|
36
|
+
argTypes: {
|
|
37
|
+
value: {
|
|
38
|
+
control: {
|
|
39
|
+
type: 'object',
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
lapisField: {
|
|
43
|
+
control: {
|
|
44
|
+
type: 'text',
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
sliderMin: {
|
|
48
|
+
control: {
|
|
49
|
+
type: 'number',
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
sliderMax: {
|
|
53
|
+
control: {
|
|
54
|
+
type: 'number',
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
sliderStep: {
|
|
58
|
+
control: {
|
|
59
|
+
type: 'number',
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
width: {
|
|
63
|
+
control: {
|
|
64
|
+
type: 'text',
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export default meta;
|
|
71
|
+
|
|
72
|
+
export const Default: StoryObj<NumberRangeFilterProps> = {
|
|
73
|
+
render: (args) => {
|
|
74
|
+
return html`
|
|
75
|
+
<gs-app lapis="${LAPIS_URL}">
|
|
76
|
+
<gs-number-range-filter
|
|
77
|
+
.value=${args.value}
|
|
78
|
+
.lapisField=${args.lapisField}
|
|
79
|
+
.sliderMin=${args.sliderMin}
|
|
80
|
+
.sliderMax=${args.sliderMax}
|
|
81
|
+
.sliderStep=${args.sliderStep}
|
|
82
|
+
.width=${args.width}
|
|
83
|
+
>
|
|
84
|
+
</gs-number-range-filter>
|
|
85
|
+
</gs-app>
|
|
86
|
+
`;
|
|
87
|
+
},
|
|
88
|
+
args: {
|
|
89
|
+
lapisField: 'age',
|
|
90
|
+
value: { min: 10, max: 90 },
|
|
91
|
+
sliderMin: 0,
|
|
92
|
+
sliderMax: 100,
|
|
93
|
+
sliderStep: 0.1,
|
|
94
|
+
width: '100%',
|
|
95
|
+
},
|
|
96
|
+
};
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { customElement, property } from 'lit/decorators.js';
|
|
2
|
+
import type { DetailedHTMLProps, HTMLAttributes } from 'react';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
type NumberRangeFilterChangedEvent,
|
|
6
|
+
type NumberRangeValueChangedEvent,
|
|
7
|
+
} from '../../preact/numberRangeFilter/NumberRangeFilterChangedEvent';
|
|
8
|
+
import { NumberRangeFilter } from '../../preact/numberRangeFilter/number-range-filter';
|
|
9
|
+
import { type gsEventNames } from '../../utils/gsEventNames';
|
|
10
|
+
import { PreactLitAdapter } from '../PreactLitAdapter';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
*
|
|
14
|
+
* ## Context
|
|
15
|
+
*
|
|
16
|
+
* This component lets the user specify filters for a `float` or `int` field in LAPIS.
|
|
17
|
+
* It consists of two text input fields and a slider.
|
|
18
|
+
*
|
|
19
|
+
* The slider must be restricted to a certain range.
|
|
20
|
+
* Users can however still enter values outside of this range in the text input fields.
|
|
21
|
+
*
|
|
22
|
+
* @fires {CustomEvent<Record<string, string | undefined>>} gs-number-range-filter-changed
|
|
23
|
+
* Fired when the slider is released,
|
|
24
|
+
* `onBlur` on the input fields after the user has typed a valid range in the input fields,
|
|
25
|
+
* or when one of the input fields is cleared.
|
|
26
|
+
* The `details` of this event contain an object with `${lapisField}From` and `${lapisField}To` as keys.
|
|
27
|
+
* The values are the numbers from the input fields or `undefined` if the input field is empty:
|
|
28
|
+
* ```
|
|
29
|
+
* {
|
|
30
|
+
* [`${lapisField}From`]: number | undefined
|
|
31
|
+
* [`${lapisField}To`]: number | undefined
|
|
32
|
+
* }
|
|
33
|
+
* ```
|
|
34
|
+
* Example:
|
|
35
|
+
* ```
|
|
36
|
+
* {
|
|
37
|
+
* ageFrom: 18,
|
|
38
|
+
* ageTo: undefined
|
|
39
|
+
* }
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* @fires {CustomEvent<Record<string, string | undefined>>} gs-number-range-value-changed
|
|
43
|
+
* Similar to the `gs-number-range-filter-changed` event,
|
|
44
|
+
* but contains an `event.detail` that has a fixed format:
|
|
45
|
+
* ```
|
|
46
|
+
* {
|
|
47
|
+
* min: number | undefined
|
|
48
|
+
* max: number | undefined
|
|
49
|
+
* }
|
|
50
|
+
* ```
|
|
51
|
+
* This event should be used when you want to control this component externally.
|
|
52
|
+
* The `event.detail` can be used as the value of the component.
|
|
53
|
+
* Example:
|
|
54
|
+
* ```
|
|
55
|
+
* {
|
|
56
|
+
* min: 18,
|
|
57
|
+
* max: undefined
|
|
58
|
+
* }
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
@customElement('gs-number-range-filter')
|
|
62
|
+
export class NumberRangeFilterComponent extends PreactLitAdapter {
|
|
63
|
+
/**
|
|
64
|
+
* The value to use for this number filter.
|
|
65
|
+
*
|
|
66
|
+
* Must be of the form:
|
|
67
|
+
* ```
|
|
68
|
+
* {
|
|
69
|
+
* [`${lapisField}From`]: number | undefined
|
|
70
|
+
* [`${lapisField}To`]: number | undefined
|
|
71
|
+
* }
|
|
72
|
+
* ```
|
|
73
|
+
*
|
|
74
|
+
* This is the same format that the `gs-number-value-changed` event will emit.
|
|
75
|
+
*/
|
|
76
|
+
@property({ type: Object })
|
|
77
|
+
value: { min?: number; max?: number } = {};
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Required.
|
|
81
|
+
*
|
|
82
|
+
* The LAPIS field name to use for this text filter.
|
|
83
|
+
* The field must exist on this LAPIS instance.
|
|
84
|
+
*/
|
|
85
|
+
@property()
|
|
86
|
+
lapisField = '';
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* The `min` value to use for the slider.
|
|
90
|
+
*/
|
|
91
|
+
@property({ type: Number })
|
|
92
|
+
sliderMin = 0;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* The `max` value to use for the slider.
|
|
96
|
+
*/
|
|
97
|
+
@property({ type: Number })
|
|
98
|
+
sliderMax = 100;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* The `step` value to use for the slider.
|
|
102
|
+
*
|
|
103
|
+
* This attribute has no effect on the text input.
|
|
104
|
+
*/
|
|
105
|
+
@property({ type: Number })
|
|
106
|
+
sliderStep = 1;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* The width of the component.
|
|
110
|
+
*
|
|
111
|
+
* Visit https://genspectrum.github.io/dashboard-components/?path=/docs/concepts-size-of-components--docs for more information.
|
|
112
|
+
*/
|
|
113
|
+
@property({ type: String })
|
|
114
|
+
width: string = '100%';
|
|
115
|
+
|
|
116
|
+
override render() {
|
|
117
|
+
return (
|
|
118
|
+
<NumberRangeFilter
|
|
119
|
+
value={this.value}
|
|
120
|
+
lapisField={this.lapisField}
|
|
121
|
+
sliderMin={this.sliderMin}
|
|
122
|
+
sliderMax={this.sliderMax}
|
|
123
|
+
sliderStep={this.sliderStep}
|
|
124
|
+
width={this.width}
|
|
125
|
+
/>
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
declare global {
|
|
131
|
+
interface HTMLElementTagNameMap {
|
|
132
|
+
'gs-number-range-filter': NumberRangeFilterComponent;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
interface HTMLElementEventMap {
|
|
136
|
+
[gsEventNames.numberRangeFilterChanged]: NumberRangeFilterChangedEvent;
|
|
137
|
+
[gsEventNames.numberRangeValueChanged]: NumberRangeValueChangedEvent;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
declare global {
|
|
142
|
+
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
143
|
+
namespace JSX {
|
|
144
|
+
interface IntrinsicElements {
|
|
145
|
+
'gs-number-range-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -18,8 +18,8 @@ const codeExample = String.raw`
|
|
|
18
18
|
lapisFilter='{"country": "Germany"}'
|
|
19
19
|
placeholderText="Enter host name"
|
|
20
20
|
value="Homo sapiens"
|
|
21
|
-
width="50%"
|
|
22
|
-
|
|
21
|
+
width="50%"
|
|
22
|
+
></gs-text-filter>`;
|
|
23
23
|
|
|
24
24
|
const meta: Meta<Required<TextFilterProps>> = {
|
|
25
25
|
title: 'Input/Text filter',
|
|
@@ -3,3 +3,4 @@ export { LocationFilterComponent } from './gs-location-filter';
|
|
|
3
3
|
export { TextFilterComponent } from './gs-text-filter';
|
|
4
4
|
export { MutationFilterComponent } from './gs-mutation-filter';
|
|
5
5
|
export { LineageFilterComponent } from './gs-lineage-filter';
|
|
6
|
+
export { NumberRangeFilterComponent } from './gs-number-range-filter';
|