@genspectrum/dashboard-components 0.8.2 → 0.8.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 +3 -3
- package/dist/dashboard-components.js +207 -214
- package/dist/dashboard-components.js.map +1 -1
- package/dist/genspectrum-components.d.ts +13 -12
- package/dist/style.css +47 -49
- package/package.json +7 -1
- package/src/preact/components/chart.tsx +7 -13
- package/src/preact/mutationFilter/mutation-filter.stories.tsx +95 -11
- package/src/preact/mutationFilter/mutation-filter.tsx +178 -175
- package/src/preact/mutationFilter/parseAndValidateMutation.ts +1 -1
- package/src/preact/mutationsOverTime/mutations-over-time-grid.tsx +5 -35
- package/src/web-components/input/gs-mutation-filter.stories.ts +12 -2
- package/src/web-components/input/gs-mutation-filter.tsx +3 -2
- package/standalone-bundle/dashboard-components.js +9843 -9856
- package/standalone-bundle/dashboard-components.js.map +1 -1
|
@@ -411,8 +411,9 @@ export declare class MutationComparisonComponent extends PreactLitAdapterWithGri
|
|
|
411
411
|
* ## Context
|
|
412
412
|
* This component provides an input field to specify filters for nucleotide and amino acid mutations and insertions.
|
|
413
413
|
*
|
|
414
|
-
* Input values have to be provided one at a time and submitted by pressing the Enter key or by
|
|
415
|
-
*
|
|
414
|
+
* Input values have to be provided one at a time and submitted by pressing the Enter key or by selecting an option from the dropdown.
|
|
415
|
+
* Alternatively, they can be provided as a string of comma-separated values, which will be directly parsed and validated.
|
|
416
|
+
* After submission (after pressing Enter or pasting a comma-separated string) an event is fired with the selected mutations.
|
|
416
417
|
* All previously selected mutations are displayed at the input field and added to the event.
|
|
417
418
|
* Users can remove a mutation by clicking the 'x' button next to the mutation.
|
|
418
419
|
*
|
|
@@ -1093,7 +1094,7 @@ declare global {
|
|
|
1093
1094
|
|
|
1094
1095
|
declare global {
|
|
1095
1096
|
interface HTMLElementTagNameMap {
|
|
1096
|
-
'gs-
|
|
1097
|
+
'gs-number-sequences-over-time': NumberSequencesOverTimeComponent;
|
|
1097
1098
|
}
|
|
1098
1099
|
}
|
|
1099
1100
|
|
|
@@ -1101,7 +1102,7 @@ declare global {
|
|
|
1101
1102
|
declare global {
|
|
1102
1103
|
namespace JSX {
|
|
1103
1104
|
interface IntrinsicElements {
|
|
1104
|
-
'gs-
|
|
1105
|
+
'gs-number-sequences-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1105
1106
|
}
|
|
1106
1107
|
}
|
|
1107
1108
|
}
|
|
@@ -1109,7 +1110,7 @@ declare global {
|
|
|
1109
1110
|
|
|
1110
1111
|
declare global {
|
|
1111
1112
|
interface HTMLElementTagNameMap {
|
|
1112
|
-
'gs-
|
|
1113
|
+
'gs-aggregate-component': AggregateComponent;
|
|
1113
1114
|
}
|
|
1114
1115
|
}
|
|
1115
1116
|
|
|
@@ -1117,7 +1118,7 @@ declare global {
|
|
|
1117
1118
|
declare global {
|
|
1118
1119
|
namespace JSX {
|
|
1119
1120
|
interface IntrinsicElements {
|
|
1120
|
-
'gs-
|
|
1121
|
+
'gs-aggregate-component': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1121
1122
|
}
|
|
1122
1123
|
}
|
|
1123
1124
|
}
|
|
@@ -1198,10 +1199,10 @@ declare global {
|
|
|
1198
1199
|
|
|
1199
1200
|
declare global {
|
|
1200
1201
|
interface HTMLElementTagNameMap {
|
|
1201
|
-
'gs-
|
|
1202
|
+
'gs-lineage-filter': LineageFilterComponent;
|
|
1202
1203
|
}
|
|
1203
1204
|
interface HTMLElementEventMap {
|
|
1204
|
-
'gs-
|
|
1205
|
+
'gs-lineage-filter-changed': CustomEvent<Record<string, string>>;
|
|
1205
1206
|
}
|
|
1206
1207
|
}
|
|
1207
1208
|
|
|
@@ -1209,7 +1210,7 @@ declare global {
|
|
|
1209
1210
|
declare global {
|
|
1210
1211
|
namespace JSX {
|
|
1211
1212
|
interface IntrinsicElements {
|
|
1212
|
-
'gs-
|
|
1213
|
+
'gs-lineage-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1213
1214
|
}
|
|
1214
1215
|
}
|
|
1215
1216
|
}
|
|
@@ -1217,10 +1218,10 @@ declare global {
|
|
|
1217
1218
|
|
|
1218
1219
|
declare global {
|
|
1219
1220
|
interface HTMLElementTagNameMap {
|
|
1220
|
-
'gs-
|
|
1221
|
+
'gs-mutation-filter': MutationFilterComponent;
|
|
1221
1222
|
}
|
|
1222
1223
|
interface HTMLElementEventMap {
|
|
1223
|
-
'gs-
|
|
1224
|
+
'gs-mutation-filter-changed': CustomEvent<SelectedMutationFilterStrings>;
|
|
1224
1225
|
}
|
|
1225
1226
|
}
|
|
1226
1227
|
|
|
@@ -1228,7 +1229,7 @@ declare global {
|
|
|
1228
1229
|
declare global {
|
|
1229
1230
|
namespace JSX {
|
|
1230
1231
|
interface IntrinsicElements {
|
|
1231
|
-
'gs-
|
|
1232
|
+
'gs-mutation-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1232
1233
|
}
|
|
1233
1234
|
}
|
|
1234
1235
|
}
|
package/dist/style.css
CHANGED
|
@@ -482,7 +482,7 @@ input[type="range"] {
|
|
|
482
482
|
--tw-contain-paint: ;
|
|
483
483
|
--tw-contain-style: ;
|
|
484
484
|
}/*
|
|
485
|
-
! tailwindcss v3.4.
|
|
485
|
+
! tailwindcss v3.4.15 | MIT License | https://tailwindcss.com
|
|
486
486
|
*//*
|
|
487
487
|
1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
|
|
488
488
|
2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
|
|
@@ -3029,15 +3029,15 @@ input.tab:checked + .tab-content,
|
|
|
3029
3029
|
.mt-4 {
|
|
3030
3030
|
margin-top: 1rem;
|
|
3031
3031
|
}
|
|
3032
|
-
.inline-block {
|
|
3033
|
-
display: inline-block;
|
|
3034
|
-
}
|
|
3035
3032
|
.inline {
|
|
3036
3033
|
display: inline;
|
|
3037
3034
|
}
|
|
3038
3035
|
.flex {
|
|
3039
3036
|
display: flex;
|
|
3040
3037
|
}
|
|
3038
|
+
.inline-flex {
|
|
3039
|
+
display: inline-flex;
|
|
3040
|
+
}
|
|
3041
3041
|
.table {
|
|
3042
3042
|
display: table;
|
|
3043
3043
|
}
|
|
@@ -3107,6 +3107,9 @@ input.tab:checked + .tab-content,
|
|
|
3107
3107
|
--tw-translate-y: -50%;
|
|
3108
3108
|
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
|
3109
3109
|
}
|
|
3110
|
+
.cursor-pointer {
|
|
3111
|
+
cursor: pointer;
|
|
3112
|
+
}
|
|
3110
3113
|
.resize {
|
|
3111
3114
|
resize: both;
|
|
3112
3115
|
}
|
|
@@ -3155,9 +3158,6 @@ input.tab:checked + .tab-content,
|
|
|
3155
3158
|
.break-words {
|
|
3156
3159
|
overflow-wrap: break-word;
|
|
3157
3160
|
}
|
|
3158
|
-
.rounded-full {
|
|
3159
|
-
border-radius: 9999px;
|
|
3160
|
-
}
|
|
3161
3161
|
.rounded-lg {
|
|
3162
3162
|
border-radius: 0.5rem;
|
|
3163
3163
|
}
|
|
@@ -3186,43 +3186,41 @@ input.tab:checked + .tab-content,
|
|
|
3186
3186
|
.border-b-2 {
|
|
3187
3187
|
border-bottom-width: 2px;
|
|
3188
3188
|
}
|
|
3189
|
-
.border-solid {
|
|
3190
|
-
border-style: solid;
|
|
3191
|
-
}
|
|
3192
|
-
.border-none {
|
|
3193
|
-
border-style: none;
|
|
3194
|
-
}
|
|
3195
3189
|
.border-error {
|
|
3196
3190
|
--tw-border-opacity: 1;
|
|
3197
|
-
border-color: var(--fallback-er,oklch(var(--er)/var(--tw-border-opacity)));
|
|
3191
|
+
border-color: var(--fallback-er,oklch(var(--er)/var(--tw-border-opacity, 1)));
|
|
3198
3192
|
}
|
|
3199
3193
|
.border-gray-100 {
|
|
3200
3194
|
--tw-border-opacity: 1;
|
|
3201
|
-
border-color: rgb(243 244 246 / var(--tw-border-opacity));
|
|
3195
|
+
border-color: rgb(243 244 246 / var(--tw-border-opacity, 1));
|
|
3202
3196
|
}
|
|
3203
3197
|
.border-gray-200 {
|
|
3204
3198
|
--tw-border-opacity: 1;
|
|
3205
|
-
border-color: rgb(229 231 235 / var(--tw-border-opacity));
|
|
3199
|
+
border-color: rgb(229 231 235 / var(--tw-border-opacity, 1));
|
|
3206
3200
|
}
|
|
3207
3201
|
.border-gray-300 {
|
|
3208
3202
|
--tw-border-opacity: 1;
|
|
3209
|
-
border-color: rgb(209 213 219 / var(--tw-border-opacity));
|
|
3203
|
+
border-color: rgb(209 213 219 / var(--tw-border-opacity, 1));
|
|
3210
3204
|
}
|
|
3211
3205
|
.border-gray-400 {
|
|
3212
3206
|
--tw-border-opacity: 1;
|
|
3213
|
-
border-color: rgb(156 163 175 / var(--tw-border-opacity));
|
|
3207
|
+
border-color: rgb(156 163 175 / var(--tw-border-opacity, 1));
|
|
3214
3208
|
}
|
|
3215
|
-
.border-
|
|
3209
|
+
.border-slate-500 {
|
|
3216
3210
|
--tw-border-opacity: 1;
|
|
3217
|
-
border-color: rgb(
|
|
3211
|
+
border-color: rgb(100 116 139 / var(--tw-border-opacity, 1));
|
|
3218
3212
|
}
|
|
3219
3213
|
.bg-red-200 {
|
|
3220
3214
|
--tw-bg-opacity: 1;
|
|
3221
|
-
background-color: rgb(254 202 202 / var(--tw-bg-opacity));
|
|
3215
|
+
background-color: rgb(254 202 202 / var(--tw-bg-opacity, 1));
|
|
3216
|
+
}
|
|
3217
|
+
.bg-slate-200 {
|
|
3218
|
+
--tw-bg-opacity: 1;
|
|
3219
|
+
background-color: rgb(226 232 240 / var(--tw-bg-opacity, 1));
|
|
3222
3220
|
}
|
|
3223
3221
|
.bg-white {
|
|
3224
3222
|
--tw-bg-opacity: 1;
|
|
3225
|
-
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
|
3223
|
+
background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
|
|
3226
3224
|
}
|
|
3227
3225
|
.p-1 {
|
|
3228
3226
|
padding: 0.25rem;
|
|
@@ -3233,10 +3231,6 @@ input.tab:checked + .tab-content,
|
|
|
3233
3231
|
.p-4 {
|
|
3234
3232
|
padding: 1rem;
|
|
3235
3233
|
}
|
|
3236
|
-
.px-2 {
|
|
3237
|
-
padding-left: 0.5rem;
|
|
3238
|
-
padding-right: 0.5rem;
|
|
3239
|
-
}
|
|
3240
3234
|
.px-4 {
|
|
3241
3235
|
padding-left: 1rem;
|
|
3242
3236
|
padding-right: 1rem;
|
|
@@ -3301,23 +3295,27 @@ input.tab:checked + .tab-content,
|
|
|
3301
3295
|
}
|
|
3302
3296
|
.text-\[\#606060\] {
|
|
3303
3297
|
--tw-text-opacity: 1;
|
|
3304
|
-
color: rgb(96 96 96 / var(--tw-text-opacity));
|
|
3298
|
+
color: rgb(96 96 96 / var(--tw-text-opacity, 1));
|
|
3299
|
+
}
|
|
3300
|
+
.text-black {
|
|
3301
|
+
--tw-text-opacity: 1;
|
|
3302
|
+
color: rgb(0 0 0 / var(--tw-text-opacity, 1));
|
|
3305
3303
|
}
|
|
3306
3304
|
.text-blue-600 {
|
|
3307
3305
|
--tw-text-opacity: 1;
|
|
3308
|
-
color: rgb(37 99 235 / var(--tw-text-opacity));
|
|
3306
|
+
color: rgb(37 99 235 / var(--tw-text-opacity, 1));
|
|
3309
3307
|
}
|
|
3310
3308
|
.text-gray-600 {
|
|
3311
3309
|
--tw-text-opacity: 1;
|
|
3312
|
-
color: rgb(75 85 99 / var(--tw-text-opacity));
|
|
3310
|
+
color: rgb(75 85 99 / var(--tw-text-opacity, 1));
|
|
3313
3311
|
}
|
|
3314
3312
|
.text-neutral-500 {
|
|
3315
3313
|
--tw-text-opacity: 1;
|
|
3316
|
-
color: rgb(115 115 115 / var(--tw-text-opacity));
|
|
3314
|
+
color: rgb(115 115 115 / var(--tw-text-opacity, 1));
|
|
3317
3315
|
}
|
|
3318
3316
|
.text-red-700 {
|
|
3319
3317
|
--tw-text-opacity: 1;
|
|
3320
|
-
color: rgb(185 28 28 / var(--tw-text-opacity));
|
|
3318
|
+
color: rgb(185 28 28 / var(--tw-text-opacity, 1));
|
|
3321
3319
|
}
|
|
3322
3320
|
.underline {
|
|
3323
3321
|
text-decoration-line: underline;
|
|
@@ -3347,6 +3345,9 @@ input.tab:checked + .tab-content,
|
|
|
3347
3345
|
.duration-150 {
|
|
3348
3346
|
transition-duration: 150ms;
|
|
3349
3347
|
}
|
|
3348
|
+
.\@container {
|
|
3349
|
+
container-type: inline-size;
|
|
3350
|
+
}
|
|
3350
3351
|
.mdi--fullscreen {
|
|
3351
3352
|
--svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='24' height='24'%3E%3Cpath fill='black' d='M5 5h5v2H7v3H5zm9 0h5v5h-2V7h-3zm3 9h2v5h-5v-2h3zm-7 3v2H5v-5h2v3z'/%3E%3C/svg%3E");
|
|
3352
3353
|
}
|
|
@@ -3375,10 +3376,6 @@ input.tab:checked + .tab-content,
|
|
|
3375
3376
|
border-bottom-left-radius: var(--rounded-box, 1rem);
|
|
3376
3377
|
}
|
|
3377
3378
|
}
|
|
3378
|
-
.focus-within\:border-gray-400:focus-within {
|
|
3379
|
-
--tw-border-opacity: 1;
|
|
3380
|
-
border-color: rgb(156 163 175 / var(--tw-border-opacity));
|
|
3381
|
-
}
|
|
3382
3379
|
.hover\:scale-110:hover {
|
|
3383
3380
|
--tw-scale-x: 1.1;
|
|
3384
3381
|
--tw-scale-y: 1.1;
|
|
@@ -3391,39 +3388,40 @@ input.tab:checked + .tab-content,
|
|
|
3391
3388
|
}
|
|
3392
3389
|
.hover\:bg-gray-100:hover {
|
|
3393
3390
|
--tw-bg-opacity: 1;
|
|
3394
|
-
background-color: rgb(243 244 246 / var(--tw-bg-opacity));
|
|
3391
|
+
background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));
|
|
3392
|
+
}
|
|
3393
|
+
.hover\:bg-gray-300:hover {
|
|
3394
|
+
--tw-bg-opacity: 1;
|
|
3395
|
+
background-color: rgb(209 213 219 / var(--tw-bg-opacity, 1));
|
|
3395
3396
|
}
|
|
3396
3397
|
.hover\:font-bold:hover {
|
|
3397
3398
|
font-weight: 700;
|
|
3398
3399
|
}
|
|
3399
3400
|
.hover\:text-blue-700:hover {
|
|
3400
3401
|
--tw-text-opacity: 1;
|
|
3401
|
-
color: rgb(29 78 216 / var(--tw-text-opacity));
|
|
3402
|
+
color: rgb(29 78 216 / var(--tw-text-opacity, 1));
|
|
3402
3403
|
}
|
|
3403
3404
|
.hover\:text-blue-800:hover {
|
|
3404
3405
|
--tw-text-opacity: 1;
|
|
3405
|
-
color: rgb(30 64 175 / var(--tw-text-opacity));
|
|
3406
|
+
color: rgb(30 64 175 / var(--tw-text-opacity, 1));
|
|
3406
3407
|
}
|
|
3407
3408
|
.hover\:text-gray-400:hover {
|
|
3408
3409
|
--tw-text-opacity: 1;
|
|
3409
|
-
color: rgb(156 163 175 / var(--tw-text-opacity));
|
|
3410
|
+
color: rgb(156 163 175 / var(--tw-text-opacity, 1));
|
|
3410
3411
|
}
|
|
3411
3412
|
.hover\:text-gray-700:hover {
|
|
3412
3413
|
--tw-text-opacity: 1;
|
|
3413
|
-
color: rgb(55 65 81 / var(--tw-text-opacity));
|
|
3414
|
-
}
|
|
3415
|
-
.focus\:outline-none:focus {
|
|
3416
|
-
outline: 2px solid transparent;
|
|
3417
|
-
outline-offset: 2px;
|
|
3418
|
-
}
|
|
3419
|
-
.focus\:ring-0:focus {
|
|
3420
|
-
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
|
3421
|
-
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
|
3422
|
-
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
|
3414
|
+
color: rgb(55 65 81 / var(--tw-text-opacity, 1));
|
|
3423
3415
|
}
|
|
3424
3416
|
.peer:hover ~ .peer-hover\:visible {
|
|
3425
3417
|
visibility: visible;
|
|
3426
3418
|
}
|
|
3419
|
+
@container (min-width: 30rem) {
|
|
3420
|
+
|
|
3421
|
+
.\@\[30rem\]\:visible {
|
|
3422
|
+
visibility: visible;
|
|
3423
|
+
}
|
|
3424
|
+
}
|
|
3427
3425
|
@media (min-width: 640px) {
|
|
3428
3426
|
|
|
3429
3427
|
.sm\:max-w-5xl {
|
package/package.json
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@genspectrum/dashboard-components",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.4",
|
|
4
4
|
"description": "GenSpectrum web components for building dashboards",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "AGPL-3.0-only",
|
|
7
7
|
"main": "dist/genspectrum-components.js",
|
|
8
8
|
"module": "dist/genspectrum-components.js",
|
|
9
9
|
"types": "dist/genspectrum-components.d.ts",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/GenSpectrum/dashboard-components.git",
|
|
13
|
+
"directory": "components"
|
|
14
|
+
},
|
|
10
15
|
"publishConfig": {
|
|
11
16
|
"access": "public"
|
|
12
17
|
},
|
|
@@ -101,6 +106,7 @@
|
|
|
101
106
|
"@storybook/types": "^8.0.9",
|
|
102
107
|
"@storybook/web-components": "^8.0.9",
|
|
103
108
|
"@storybook/web-components-vite": "^8.0.9",
|
|
109
|
+
"@tailwindcss/container-queries": "^0.1.1",
|
|
104
110
|
"@types/node": "^22.0.0",
|
|
105
111
|
"@typescript-eslint/eslint-plugin": "^8.2.0",
|
|
106
112
|
"@typescript-eslint/parser": "^8.2.0",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Chart, type ChartConfiguration } from 'chart.js';
|
|
2
|
-
import {
|
|
2
|
+
import { useEffect, useRef } from 'preact/hooks';
|
|
3
3
|
|
|
4
4
|
export interface GsChartProps {
|
|
5
5
|
configuration: ChartConfiguration;
|
|
@@ -21,9 +21,14 @@ const GsChart = ({ configuration }: GsChartProps) => {
|
|
|
21
21
|
|
|
22
22
|
chartRef.current = new Chart(ctx, configuration);
|
|
23
23
|
|
|
24
|
-
resizeChartAfterFullscreenChange(
|
|
24
|
+
const resizeChartAfterFullscreenChange = () => {
|
|
25
|
+
chartRef.current?.destroy();
|
|
26
|
+
chartRef.current = new Chart(ctx, configuration);
|
|
27
|
+
};
|
|
28
|
+
document.addEventListener('fullscreenchange', resizeChartAfterFullscreenChange);
|
|
25
29
|
|
|
26
30
|
return () => {
|
|
31
|
+
document.removeEventListener('fullscreenchange', resizeChartAfterFullscreenChange);
|
|
27
32
|
chartRef.current?.destroy();
|
|
28
33
|
};
|
|
29
34
|
}, [canvasRef, configuration]);
|
|
@@ -32,14 +37,3 @@ const GsChart = ({ configuration }: GsChartProps) => {
|
|
|
32
37
|
};
|
|
33
38
|
|
|
34
39
|
export default GsChart;
|
|
35
|
-
|
|
36
|
-
const resizeChartAfterFullscreenChange = (
|
|
37
|
-
chartRef: MutableRef<Chart | null>,
|
|
38
|
-
ctx: CanvasRenderingContext2D,
|
|
39
|
-
configuration: ChartConfiguration,
|
|
40
|
-
) => {
|
|
41
|
-
document.addEventListener('fullscreenchange', () => {
|
|
42
|
-
chartRef.current?.destroy();
|
|
43
|
-
chartRef.current = new Chart(ctx, configuration);
|
|
44
|
-
});
|
|
45
|
-
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type PreactRenderer, type Meta, type StoryObj } from '@storybook/preact';
|
|
2
2
|
import { expect, fireEvent, fn, userEvent, waitFor, within } from '@storybook/test';
|
|
3
3
|
import { type StepFunction } from '@storybook/types';
|
|
4
4
|
|
|
@@ -43,13 +43,75 @@ export const Default: StoryObj<MutationFilterProps> = {
|
|
|
43
43
|
},
|
|
44
44
|
};
|
|
45
45
|
|
|
46
|
+
export const FiresFilterMultipleCommaSeparatedQueries: StoryObj<MutationFilterProps> = {
|
|
47
|
+
...Default,
|
|
48
|
+
play: async ({ canvasElement, step }) => {
|
|
49
|
+
const { canvas, changedListenerMock } = await prepare(canvasElement, step);
|
|
50
|
+
|
|
51
|
+
await step('Enter a valid mutation', async () => {
|
|
52
|
+
await submitMutation(canvas, 'A123T');
|
|
53
|
+
|
|
54
|
+
await waitFor(() =>
|
|
55
|
+
expect(changedListenerMock).toHaveBeenCalledWith(
|
|
56
|
+
expect.objectContaining({
|
|
57
|
+
detail: {
|
|
58
|
+
nucleotideMutations: ['A123T'],
|
|
59
|
+
aminoAcidMutations: [],
|
|
60
|
+
nucleotideInsertions: [],
|
|
61
|
+
aminoAcidInsertions: [],
|
|
62
|
+
},
|
|
63
|
+
}),
|
|
64
|
+
),
|
|
65
|
+
);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
await step('Enter a comma separated list of valid and invalid mutations', async () => {
|
|
69
|
+
await pasteMutations(canvas, 'A123T, error_insX, A234T, ins_123:AA');
|
|
70
|
+
|
|
71
|
+
await waitFor(() =>
|
|
72
|
+
expect(changedListenerMock).toHaveBeenCalledWith(
|
|
73
|
+
expect.objectContaining({
|
|
74
|
+
detail: {
|
|
75
|
+
nucleotideMutations: ['A123T', 'A234T'],
|
|
76
|
+
aminoAcidMutations: [],
|
|
77
|
+
nucleotideInsertions: ['ins_123:AA'],
|
|
78
|
+
aminoAcidInsertions: [],
|
|
79
|
+
},
|
|
80
|
+
}),
|
|
81
|
+
),
|
|
82
|
+
);
|
|
83
|
+
await expect(canvas.queryByText('A123T')).toBeVisible();
|
|
84
|
+
await expect(canvas.queryByText('A234T')).toBeVisible();
|
|
85
|
+
await expect(inputField(canvas)).toHaveValue('error_insX');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
await step('Remove the first mutation', async () => {
|
|
89
|
+
const mutationItem = within(canvas.getByText('A234T'));
|
|
90
|
+
await fireEvent.click(mutationItem.getByRole('button', { name: '×' }));
|
|
91
|
+
|
|
92
|
+
await waitFor(() =>
|
|
93
|
+
expect(changedListenerMock).toHaveBeenCalledWith(
|
|
94
|
+
expect.objectContaining({
|
|
95
|
+
detail: {
|
|
96
|
+
nucleotideMutations: ['A123T'],
|
|
97
|
+
aminoAcidMutations: [],
|
|
98
|
+
nucleotideInsertions: ['ins_123:AA'],
|
|
99
|
+
aminoAcidInsertions: [],
|
|
100
|
+
},
|
|
101
|
+
}),
|
|
102
|
+
),
|
|
103
|
+
);
|
|
104
|
+
});
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
|
|
46
108
|
export const FiresFilterChangedEvents: StoryObj<MutationFilterProps> = {
|
|
47
109
|
...Default,
|
|
48
110
|
play: async ({ canvasElement, step }) => {
|
|
49
111
|
const { canvas, changedListenerMock } = await prepare(canvasElement, step);
|
|
50
112
|
|
|
51
113
|
await step('Enters an invalid mutation', async () => {
|
|
52
|
-
await
|
|
114
|
+
await testNoOptionsExist(canvas, 'notAMutation');
|
|
53
115
|
await expect(changedListenerMock).not.toHaveBeenCalled();
|
|
54
116
|
|
|
55
117
|
await userEvent.type(inputField(canvas), '{backspace>12/}');
|
|
@@ -88,7 +150,7 @@ export const FiresFilterChangedEvents: StoryObj<MutationFilterProps> = {
|
|
|
88
150
|
});
|
|
89
151
|
|
|
90
152
|
await step('Enter another valid mutation', async () => {
|
|
91
|
-
await submitMutation(canvas, 'ins_123:AA');
|
|
153
|
+
await submitMutation(canvas, 'ins_123:AA', 'enter');
|
|
92
154
|
|
|
93
155
|
await expect(changedListenerMock).toHaveBeenCalledWith(
|
|
94
156
|
expect.objectContaining({
|
|
@@ -103,13 +165,13 @@ export const FiresFilterChangedEvents: StoryObj<MutationFilterProps> = {
|
|
|
103
165
|
});
|
|
104
166
|
|
|
105
167
|
await step('Remove the first mutation', async () => {
|
|
106
|
-
const
|
|
107
|
-
await
|
|
168
|
+
const mutationItem = within(canvas.getByText('A234-'));
|
|
169
|
+
await fireEvent.click(mutationItem.getByRole('button', { name: '×' }));
|
|
108
170
|
|
|
109
171
|
await expect(changedListenerMock).toHaveBeenCalledWith(
|
|
110
172
|
expect.objectContaining({
|
|
111
173
|
detail: {
|
|
112
|
-
nucleotideMutations: ['
|
|
174
|
+
nucleotideMutations: ['A123T'],
|
|
113
175
|
aminoAcidMutations: [],
|
|
114
176
|
nucleotideInsertions: ['ins_123:AA'],
|
|
115
177
|
aminoAcidInsertions: [],
|
|
@@ -140,7 +202,7 @@ export const WithInitialValue: StoryObj<MutationFilterProps> = {
|
|
|
140
202
|
play: async ({ canvasElement, step }) => {
|
|
141
203
|
const { canvas, changedListenerMock } = await prepare(canvasElement, step);
|
|
142
204
|
|
|
143
|
-
await step('
|
|
205
|
+
await step('Add input to initial value', async () => {
|
|
144
206
|
await submitMutation(canvas, 'G500T');
|
|
145
207
|
|
|
146
208
|
await expect(changedListenerMock).toHaveBeenCalledWith(
|
|
@@ -174,12 +236,34 @@ async function prepare(canvasElement: HTMLElement, step: StepFunction<PreactRend
|
|
|
174
236
|
return { canvas, changedListenerMock };
|
|
175
237
|
}
|
|
176
238
|
|
|
177
|
-
|
|
239
|
+
export type SubmissionMethod = 'click' | 'enter';
|
|
240
|
+
|
|
241
|
+
const submitMutation = async (
|
|
242
|
+
canvas: ReturnType<typeof within>,
|
|
243
|
+
mutation: string,
|
|
244
|
+
submissionMethod: SubmissionMethod = 'click',
|
|
245
|
+
) => {
|
|
178
246
|
await userEvent.type(inputField(canvas), mutation);
|
|
179
|
-
|
|
247
|
+
const firstOption = await canvas.findByRole('option', { name: mutation });
|
|
248
|
+
if (submissionMethod === 'click') {
|
|
249
|
+
await userEvent.click(firstOption);
|
|
250
|
+
}
|
|
251
|
+
if (submissionMethod === 'enter') {
|
|
252
|
+
await userEvent.keyboard('{enter}');
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
const pasteMutations = async (canvas: ReturnType<typeof within>, mutation: string) => {
|
|
257
|
+
await userEvent.click(inputField(canvas));
|
|
258
|
+
await userEvent.paste(mutation);
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
const testNoOptionsExist = async (canvas: ReturnType<typeof within>, mutation: string) => {
|
|
262
|
+
await userEvent.type(inputField(canvas), mutation);
|
|
263
|
+
const options = canvas.queryAllByRole('option');
|
|
264
|
+
|
|
265
|
+
await expect(options).toHaveLength(0);
|
|
180
266
|
};
|
|
181
267
|
|
|
182
268
|
const inputField = (canvas: ReturnType<typeof within>) =>
|
|
183
269
|
canvas.getByPlaceholderText('Enter a mutation', { exact: false });
|
|
184
|
-
|
|
185
|
-
const submitButton = (canvas: ReturnType<typeof within>) => canvas.getByRole('button', { name: '+' });
|