@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.
@@ -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
- </gs-text-filter>`;
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';