@genspectrum/dashboard-components 0.4.0 → 0.4.2
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 +2 -2
- package/dist/dashboard-components.js +263 -329
- package/dist/dashboard-components.js.map +1 -1
- 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/locationFilter/location-filter.tsx +9 -2
- 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/preact/textInput/text-input.tsx +2 -2
- package/src/web-components/input/gs-location-filter.stories.ts +9 -0
- package/src/web-components/input/gs-text-input.stories.ts +6 -0
- package/src/web-components/visualization/gs-prevalence-over-time.tsx +1 -1
package/dist/style.css
CHANGED
|
@@ -1016,15 +1016,6 @@ html {
|
|
|
1016
1016
|
color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));
|
|
1017
1017
|
}
|
|
1018
1018
|
|
|
1019
|
-
.menu li > *:not(ul, .menu-title, details, .btn):active,
|
|
1020
|
-
.menu li > *:not(ul, .menu-title, details, .btn).active,
|
|
1021
|
-
.menu li > details > summary:active {
|
|
1022
|
-
--tw-bg-opacity: 1;
|
|
1023
|
-
background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));
|
|
1024
|
-
--tw-text-opacity: 1;
|
|
1025
|
-
color: var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity)));
|
|
1026
|
-
}
|
|
1027
|
-
|
|
1028
1019
|
.tab:hover {
|
|
1029
1020
|
--tw-text-opacity: 1;
|
|
1030
1021
|
}
|
|
@@ -1143,39 +1134,6 @@ html {
|
|
|
1143
1134
|
transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
|
|
1144
1135
|
transition-duration: 200ms;
|
|
1145
1136
|
}
|
|
1146
|
-
.dropdown-end .dropdown-content {
|
|
1147
|
-
inset-inline-end: 0px;
|
|
1148
|
-
}
|
|
1149
|
-
.dropdown-left .dropdown-content {
|
|
1150
|
-
bottom: auto;
|
|
1151
|
-
inset-inline-end: 100%;
|
|
1152
|
-
top: 0px;
|
|
1153
|
-
transform-origin: right;
|
|
1154
|
-
}
|
|
1155
|
-
.dropdown-right .dropdown-content {
|
|
1156
|
-
bottom: auto;
|
|
1157
|
-
inset-inline-start: 100%;
|
|
1158
|
-
top: 0px;
|
|
1159
|
-
transform-origin: left;
|
|
1160
|
-
}
|
|
1161
|
-
.dropdown-bottom .dropdown-content {
|
|
1162
|
-
bottom: auto;
|
|
1163
|
-
top: 100%;
|
|
1164
|
-
transform-origin: top;
|
|
1165
|
-
}
|
|
1166
|
-
.dropdown-top .dropdown-content {
|
|
1167
|
-
bottom: 100%;
|
|
1168
|
-
top: auto;
|
|
1169
|
-
transform-origin: bottom;
|
|
1170
|
-
}
|
|
1171
|
-
.dropdown-end.dropdown-right .dropdown-content {
|
|
1172
|
-
bottom: 0px;
|
|
1173
|
-
top: auto;
|
|
1174
|
-
}
|
|
1175
|
-
.dropdown-end.dropdown-left .dropdown-content {
|
|
1176
|
-
bottom: 0px;
|
|
1177
|
-
top: auto;
|
|
1178
|
-
}
|
|
1179
1137
|
.dropdown.dropdown-open .dropdown-content,
|
|
1180
1138
|
.dropdown:not(.dropdown-hover):focus .dropdown-content,
|
|
1181
1139
|
.dropdown:focus-within .dropdown-content {
|
|
@@ -1270,19 +1228,6 @@ html {
|
|
|
1270
1228
|
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));
|
|
1271
1229
|
}
|
|
1272
1230
|
|
|
1273
|
-
:where(.menu li:not(.menu-title, .disabled) > *:not(ul, details, .menu-title)):not(.active, .btn):hover, :where(.menu li:not(.menu-title, .disabled) > details > summary:not(.menu-title)):not(.active, .btn):hover {
|
|
1274
|
-
cursor: pointer;
|
|
1275
|
-
outline: 2px solid transparent;
|
|
1276
|
-
outline-offset: 2px;
|
|
1277
|
-
}
|
|
1278
|
-
|
|
1279
|
-
@supports (color: oklch(0% 0 0)) {
|
|
1280
|
-
|
|
1281
|
-
:where(.menu li:not(.menu-title, .disabled) > *:not(ul, details, .menu-title)):not(.active, .btn):hover, :where(.menu li:not(.menu-title, .disabled) > details > summary:not(.menu-title)):not(.active, .btn):hover {
|
|
1282
|
-
background-color: var(--fallback-bc,oklch(var(--bc)/0.1));
|
|
1283
|
-
}
|
|
1284
|
-
}
|
|
1285
|
-
|
|
1286
1231
|
.tab[disabled],
|
|
1287
1232
|
.tab[disabled]:hover {
|
|
1288
1233
|
cursor: not-allowed;
|
|
@@ -1409,31 +1354,6 @@ html {
|
|
|
1409
1354
|
border-radius: inherit;
|
|
1410
1355
|
}
|
|
1411
1356
|
}
|
|
1412
|
-
.menu {
|
|
1413
|
-
display: flex;
|
|
1414
|
-
flex-direction: column;
|
|
1415
|
-
flex-wrap: wrap;
|
|
1416
|
-
font-size: 0.875rem;
|
|
1417
|
-
line-height: 1.25rem;
|
|
1418
|
-
padding: 0.5rem;
|
|
1419
|
-
}
|
|
1420
|
-
.menu :where(li ul) {
|
|
1421
|
-
position: relative;
|
|
1422
|
-
white-space: nowrap;
|
|
1423
|
-
margin-inline-start: 1rem;
|
|
1424
|
-
padding-inline-start: 0.5rem;
|
|
1425
|
-
}
|
|
1426
|
-
.menu :where(li:not(.menu-title) > *:not(ul, details, .menu-title, .btn)), .menu :where(li:not(.menu-title) > details > summary:not(.menu-title)) {
|
|
1427
|
-
display: grid;
|
|
1428
|
-
grid-auto-flow: column;
|
|
1429
|
-
align-content: flex-start;
|
|
1430
|
-
align-items: center;
|
|
1431
|
-
gap: 0.5rem;
|
|
1432
|
-
grid-auto-columns: minmax(auto, max-content) auto max-content;
|
|
1433
|
-
-webkit-user-select: none;
|
|
1434
|
-
-moz-user-select: none;
|
|
1435
|
-
user-select: none;
|
|
1436
|
-
}
|
|
1437
1357
|
.menu li.disabled {
|
|
1438
1358
|
cursor: not-allowed;
|
|
1439
1359
|
-webkit-user-select: none;
|
|
@@ -1441,20 +1361,6 @@ html {
|
|
|
1441
1361
|
user-select: none;
|
|
1442
1362
|
color: var(--fallback-bc,oklch(var(--bc)/0.3));
|
|
1443
1363
|
}
|
|
1444
|
-
.menu :where(li > .menu-dropdown:not(.menu-dropdown-show)) {
|
|
1445
|
-
display: none;
|
|
1446
|
-
}
|
|
1447
|
-
:where(.menu li) {
|
|
1448
|
-
position: relative;
|
|
1449
|
-
display: flex;
|
|
1450
|
-
flex-shrink: 0;
|
|
1451
|
-
flex-direction: column;
|
|
1452
|
-
flex-wrap: wrap;
|
|
1453
|
-
align-items: stretch;
|
|
1454
|
-
}
|
|
1455
|
-
:where(.menu li) .badge {
|
|
1456
|
-
justify-self: end;
|
|
1457
|
-
}
|
|
1458
1364
|
.modal {
|
|
1459
1365
|
pointer-events: none;
|
|
1460
1366
|
position: fixed;
|
|
@@ -1678,6 +1584,29 @@ input.tab:checked + .tab-content,
|
|
|
1678
1584
|
--tw-bg-opacity: 1;
|
|
1679
1585
|
background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)));
|
|
1680
1586
|
}
|
|
1587
|
+
.toggle {
|
|
1588
|
+
flex-shrink: 0;
|
|
1589
|
+
--tglbg: var(--fallback-b1,oklch(var(--b1)/1));
|
|
1590
|
+
--handleoffset: 1.5rem;
|
|
1591
|
+
--handleoffsetcalculator: calc(var(--handleoffset) * -1);
|
|
1592
|
+
--togglehandleborder: 0 0;
|
|
1593
|
+
height: 1.5rem;
|
|
1594
|
+
width: 3rem;
|
|
1595
|
+
cursor: pointer;
|
|
1596
|
+
-webkit-appearance: none;
|
|
1597
|
+
-moz-appearance: none;
|
|
1598
|
+
appearance: none;
|
|
1599
|
+
border-radius: var(--rounded-badge, 1.9rem);
|
|
1600
|
+
border-width: 1px;
|
|
1601
|
+
border-color: currentColor;
|
|
1602
|
+
background-color: currentColor;
|
|
1603
|
+
color: var(--fallback-bc,oklch(var(--bc)/0.5));
|
|
1604
|
+
transition: background,
|
|
1605
|
+
box-shadow var(--animation-input, 0.2s) ease-out;
|
|
1606
|
+
box-shadow: var(--handleoffsetcalculator) 0 0 2px var(--tglbg) inset,
|
|
1607
|
+
0 0 0 2px var(--tglbg) inset,
|
|
1608
|
+
var(--togglehandleborder);
|
|
1609
|
+
}
|
|
1681
1610
|
.alert-error {
|
|
1682
1611
|
border-color: var(--fallback-er,oklch(var(--er)/0.2));
|
|
1683
1612
|
--tw-text-opacity: 1;
|
|
@@ -1911,9 +1840,6 @@ input.tab:checked + .tab-content,
|
|
|
1911
1840
|
margin-bottom: 0px;
|
|
1912
1841
|
margin-inline-start: -1px;
|
|
1913
1842
|
}
|
|
1914
|
-
.join-item:focus {
|
|
1915
|
-
isolation: isolate;
|
|
1916
|
-
}
|
|
1917
1843
|
.loading {
|
|
1918
1844
|
pointer-events: none;
|
|
1919
1845
|
display: inline-block;
|
|
@@ -1936,40 +1862,6 @@ input.tab:checked + .tab-content,
|
|
|
1936
1862
|
.loading-md {
|
|
1937
1863
|
width: 1.5rem;
|
|
1938
1864
|
}
|
|
1939
|
-
:where(.menu li:empty) {
|
|
1940
|
-
--tw-bg-opacity: 1;
|
|
1941
|
-
background-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity)));
|
|
1942
|
-
opacity: 0.1;
|
|
1943
|
-
margin: 0.5rem 1rem;
|
|
1944
|
-
height: 1px;
|
|
1945
|
-
}
|
|
1946
|
-
.menu :where(li ul):before {
|
|
1947
|
-
position: absolute;
|
|
1948
|
-
bottom: 0.75rem;
|
|
1949
|
-
inset-inline-start: 0px;
|
|
1950
|
-
top: 0.75rem;
|
|
1951
|
-
width: 1px;
|
|
1952
|
-
--tw-bg-opacity: 1;
|
|
1953
|
-
background-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity)));
|
|
1954
|
-
opacity: 0.1;
|
|
1955
|
-
content: "";
|
|
1956
|
-
}
|
|
1957
|
-
.menu :where(li:not(.menu-title) > *:not(ul, details, .menu-title, .btn)),
|
|
1958
|
-
.menu :where(li:not(.menu-title) > details > summary:not(.menu-title)) {
|
|
1959
|
-
border-radius: var(--rounded-btn, 0.5rem);
|
|
1960
|
-
padding-left: 1rem;
|
|
1961
|
-
padding-right: 1rem;
|
|
1962
|
-
padding-top: 0.5rem;
|
|
1963
|
-
padding-bottom: 0.5rem;
|
|
1964
|
-
text-align: start;
|
|
1965
|
-
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
|
|
1966
|
-
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
|
|
1967
|
-
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
|
|
1968
|
-
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
1969
|
-
transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
|
|
1970
|
-
transition-duration: 200ms;
|
|
1971
|
-
text-wrap: balance;
|
|
1972
|
-
}
|
|
1973
1865
|
:where(.menu li:not(.menu-title, .disabled) > *:not(ul, details, .menu-title)):not(summary, .active, .btn).focus, :where(.menu li:not(.menu-title, .disabled) > *:not(ul, details, .menu-title)):not(summary, .active, .btn):focus, :where(.menu li:not(.menu-title, .disabled) > *:not(ul, details, .menu-title)):is(summary):not(.active, .btn):focus-visible, :where(.menu li:not(.menu-title, .disabled) > details > summary:not(.menu-title)):not(summary, .active, .btn).focus, :where(.menu li:not(.menu-title, .disabled) > details > summary:not(.menu-title)):not(summary, .active, .btn):focus, :where(.menu li:not(.menu-title, .disabled) > details > summary:not(.menu-title)):is(summary):not(.active, .btn):focus-visible {
|
|
1974
1866
|
cursor: pointer;
|
|
1975
1867
|
background-color: var(--fallback-bc,oklch(var(--bc)/0.1));
|
|
@@ -1978,38 +1870,6 @@ input.tab:checked + .tab-content,
|
|
|
1978
1870
|
outline: 2px solid transparent;
|
|
1979
1871
|
outline-offset: 2px;
|
|
1980
1872
|
}
|
|
1981
|
-
.menu li > *:not(ul, .menu-title, details, .btn):active,
|
|
1982
|
-
.menu li > *:not(ul, .menu-title, details, .btn).active,
|
|
1983
|
-
.menu li > details > summary:active {
|
|
1984
|
-
--tw-bg-opacity: 1;
|
|
1985
|
-
background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));
|
|
1986
|
-
--tw-text-opacity: 1;
|
|
1987
|
-
color: var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity)));
|
|
1988
|
-
}
|
|
1989
|
-
.menu :where(li > details > summary)::-webkit-details-marker {
|
|
1990
|
-
display: none;
|
|
1991
|
-
}
|
|
1992
|
-
.menu :where(li > details > summary):after,
|
|
1993
|
-
.menu :where(li > .menu-dropdown-toggle):after {
|
|
1994
|
-
justify-self: end;
|
|
1995
|
-
display: block;
|
|
1996
|
-
margin-top: -0.5rem;
|
|
1997
|
-
height: 0.5rem;
|
|
1998
|
-
width: 0.5rem;
|
|
1999
|
-
transform: rotate(45deg);
|
|
2000
|
-
transition-property: transform, margin-top;
|
|
2001
|
-
transition-duration: 0.3s;
|
|
2002
|
-
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
2003
|
-
content: "";
|
|
2004
|
-
transform-origin: 75% 75%;
|
|
2005
|
-
box-shadow: 2px 2px;
|
|
2006
|
-
pointer-events: none;
|
|
2007
|
-
}
|
|
2008
|
-
.menu :where(li > details[open] > summary):after,
|
|
2009
|
-
.menu :where(li > .menu-dropdown-toggle.menu-dropdown-show):after {
|
|
2010
|
-
transform: rotate(225deg);
|
|
2011
|
-
margin-top: 0;
|
|
2012
|
-
}
|
|
2013
1873
|
.mockup-phone .display {
|
|
2014
1874
|
overflow: hidden;
|
|
2015
1875
|
border-radius: 40px;
|
|
@@ -2530,6 +2390,49 @@ input.tab:checked + .tab-content,
|
|
|
2530
2390
|
opacity: 1;
|
|
2531
2391
|
}
|
|
2532
2392
|
}
|
|
2393
|
+
[dir="rtl"] .toggle {
|
|
2394
|
+
--handleoffsetcalculator: calc(var(--handleoffset) * 1);
|
|
2395
|
+
}
|
|
2396
|
+
.toggle:focus-visible {
|
|
2397
|
+
outline-style: solid;
|
|
2398
|
+
outline-width: 2px;
|
|
2399
|
+
outline-offset: 2px;
|
|
2400
|
+
outline-color: var(--fallback-bc,oklch(var(--bc)/0.2));
|
|
2401
|
+
}
|
|
2402
|
+
.toggle:hover {
|
|
2403
|
+
background-color: currentColor;
|
|
2404
|
+
}
|
|
2405
|
+
.toggle:checked,
|
|
2406
|
+
.toggle[aria-checked="true"] {
|
|
2407
|
+
background-image: none;
|
|
2408
|
+
--handleoffsetcalculator: var(--handleoffset);
|
|
2409
|
+
--tw-text-opacity: 1;
|
|
2410
|
+
color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));
|
|
2411
|
+
}
|
|
2412
|
+
[dir="rtl"] .toggle:checked, [dir="rtl"] .toggle[aria-checked="true"] {
|
|
2413
|
+
--handleoffsetcalculator: calc(var(--handleoffset) * -1);
|
|
2414
|
+
}
|
|
2415
|
+
.toggle:indeterminate {
|
|
2416
|
+
--tw-text-opacity: 1;
|
|
2417
|
+
color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));
|
|
2418
|
+
box-shadow: calc(var(--handleoffset) / 2) 0 0 2px var(--tglbg) inset,
|
|
2419
|
+
calc(var(--handleoffset) / -2) 0 0 2px var(--tglbg) inset,
|
|
2420
|
+
0 0 0 2px var(--tglbg) inset;
|
|
2421
|
+
}
|
|
2422
|
+
[dir="rtl"] .toggle:indeterminate {
|
|
2423
|
+
box-shadow: calc(var(--handleoffset) / 2) 0 0 2px var(--tglbg) inset,
|
|
2424
|
+
calc(var(--handleoffset) / -2) 0 0 2px var(--tglbg) inset,
|
|
2425
|
+
0 0 0 2px var(--tglbg) inset;
|
|
2426
|
+
}
|
|
2427
|
+
.toggle:disabled {
|
|
2428
|
+
cursor: not-allowed;
|
|
2429
|
+
--tw-border-opacity: 1;
|
|
2430
|
+
border-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity)));
|
|
2431
|
+
background-color: transparent;
|
|
2432
|
+
opacity: 0.3;
|
|
2433
|
+
--togglehandleborder: 0 0 0 3px var(--fallback-bc,oklch(var(--bc)/1)) inset,
|
|
2434
|
+
var(--handleoffsetcalculator) 0 0 3px var(--fallback-bc,oklch(var(--bc)/1)) inset;
|
|
2435
|
+
}
|
|
2533
2436
|
.btn-xs {
|
|
2534
2437
|
height: 1.5rem;
|
|
2535
2438
|
min-height: 1.5rem;
|
|
@@ -2859,18 +2762,21 @@ input.tab:checked + .tab-content,
|
|
|
2859
2762
|
.-top-3 {
|
|
2860
2763
|
top: -0.75rem;
|
|
2861
2764
|
}
|
|
2765
|
+
.left-0 {
|
|
2766
|
+
left: 0px;
|
|
2767
|
+
}
|
|
2862
2768
|
.right-2 {
|
|
2863
2769
|
right: 0.5rem;
|
|
2864
2770
|
}
|
|
2771
|
+
.top-0 {
|
|
2772
|
+
top: 0px;
|
|
2773
|
+
}
|
|
2865
2774
|
.top-2 {
|
|
2866
2775
|
top: 0.5rem;
|
|
2867
2776
|
}
|
|
2868
2777
|
.z-10 {
|
|
2869
2778
|
z-index: 10;
|
|
2870
2779
|
}
|
|
2871
|
-
.z-\[1\] {
|
|
2872
|
-
z-index: 1;
|
|
2873
|
-
}
|
|
2874
2780
|
.float-right {
|
|
2875
2781
|
float: right;
|
|
2876
2782
|
}
|
|
@@ -2895,9 +2801,6 @@ input.tab:checked + .tab-content,
|
|
|
2895
2801
|
.mb-2 {
|
|
2896
2802
|
margin-bottom: 0.5rem;
|
|
2897
2803
|
}
|
|
2898
|
-
.ml-2 {
|
|
2899
|
-
margin-left: 0.5rem;
|
|
2900
|
-
}
|
|
2901
2804
|
.mr-2 {
|
|
2902
2805
|
margin-right: 0.5rem;
|
|
2903
2806
|
}
|
|
@@ -2931,24 +2834,37 @@ input.tab:checked + .tab-content,
|
|
|
2931
2834
|
.w-32 {
|
|
2932
2835
|
width: 8rem;
|
|
2933
2836
|
}
|
|
2837
|
+
.w-40 {
|
|
2838
|
+
width: 10rem;
|
|
2839
|
+
}
|
|
2934
2840
|
.w-64 {
|
|
2935
2841
|
width: 16rem;
|
|
2936
2842
|
}
|
|
2937
|
-
.w-72 {
|
|
2938
|
-
width: 18rem;
|
|
2939
|
-
}
|
|
2940
2843
|
.w-full {
|
|
2941
2844
|
width: 100%;
|
|
2942
2845
|
}
|
|
2846
|
+
.w-max {
|
|
2847
|
+
width: -moz-max-content;
|
|
2848
|
+
width: max-content;
|
|
2849
|
+
}
|
|
2850
|
+
.min-w-40 {
|
|
2851
|
+
min-width: 10rem;
|
|
2852
|
+
}
|
|
2943
2853
|
.max-w-screen-lg {
|
|
2944
2854
|
max-width: 1024px;
|
|
2945
2855
|
}
|
|
2946
2856
|
.flex-1 {
|
|
2947
2857
|
flex: 1 1 0%;
|
|
2948
2858
|
}
|
|
2859
|
+
.flex-grow {
|
|
2860
|
+
flex-grow: 1;
|
|
2861
|
+
}
|
|
2949
2862
|
.grow {
|
|
2950
2863
|
flex-grow: 1;
|
|
2951
2864
|
}
|
|
2865
|
+
.resize {
|
|
2866
|
+
resize: both;
|
|
2867
|
+
}
|
|
2952
2868
|
.flex-row {
|
|
2953
2869
|
flex-direction: row;
|
|
2954
2870
|
}
|
|
@@ -2970,6 +2886,9 @@ input.tab:checked + .tab-content,
|
|
|
2970
2886
|
.gap-2 {
|
|
2971
2887
|
gap: 0.5rem;
|
|
2972
2888
|
}
|
|
2889
|
+
.gap-y-1 {
|
|
2890
|
+
row-gap: 0.25rem;
|
|
2891
|
+
}
|
|
2973
2892
|
.overflow-auto {
|
|
2974
2893
|
overflow: auto;
|
|
2975
2894
|
}
|
|
@@ -2979,18 +2898,9 @@ input.tab:checked + .tab-content,
|
|
|
2979
2898
|
.whitespace-nowrap {
|
|
2980
2899
|
white-space: nowrap;
|
|
2981
2900
|
}
|
|
2982
|
-
.text-nowrap {
|
|
2983
|
-
text-wrap: nowrap;
|
|
2984
|
-
}
|
|
2985
2901
|
.break-words {
|
|
2986
2902
|
overflow-wrap: break-word;
|
|
2987
2903
|
}
|
|
2988
|
-
.rounded {
|
|
2989
|
-
border-radius: 0.25rem;
|
|
2990
|
-
}
|
|
2991
|
-
.rounded-box {
|
|
2992
|
-
border-radius: var(--rounded-box, 1rem);
|
|
2993
|
-
}
|
|
2994
2904
|
.rounded-full {
|
|
2995
2905
|
border-radius: 9999px;
|
|
2996
2906
|
}
|
|
@@ -3033,6 +2943,10 @@ input.tab:checked + .tab-content,
|
|
|
3033
2943
|
--tw-border-opacity: 1;
|
|
3034
2944
|
border-color: rgb(243 244 246 / var(--tw-border-opacity));
|
|
3035
2945
|
}
|
|
2946
|
+
.border-gray-200 {
|
|
2947
|
+
--tw-border-opacity: 1;
|
|
2948
|
+
border-color: rgb(229 231 235 / var(--tw-border-opacity));
|
|
2949
|
+
}
|
|
3036
2950
|
.border-gray-300 {
|
|
3037
2951
|
--tw-border-opacity: 1;
|
|
3038
2952
|
border-color: rgb(209 213 219 / var(--tw-border-opacity));
|
|
@@ -3045,10 +2959,6 @@ input.tab:checked + .tab-content,
|
|
|
3045
2959
|
--tw-border-opacity: 1;
|
|
3046
2960
|
border-color: rgb(239 68 68 / var(--tw-border-opacity));
|
|
3047
2961
|
}
|
|
3048
|
-
.bg-base-100 {
|
|
3049
|
-
--tw-bg-opacity: 1;
|
|
3050
|
-
background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)));
|
|
3051
|
-
}
|
|
3052
2962
|
.bg-base-200 {
|
|
3053
2963
|
--tw-bg-opacity: 1;
|
|
3054
2964
|
background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)));
|
|
@@ -3063,6 +2973,9 @@ input.tab:checked + .tab-content,
|
|
|
3063
2973
|
.p-2 {
|
|
3064
2974
|
padding: 0.5rem;
|
|
3065
2975
|
}
|
|
2976
|
+
.p-4 {
|
|
2977
|
+
padding: 1rem;
|
|
2978
|
+
}
|
|
3066
2979
|
.px-2 {
|
|
3067
2980
|
padding-left: 0.5rem;
|
|
3068
2981
|
padding-right: 0.5rem;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@genspectrum/dashboard-components",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "GenSpectrum web components for building dashboards",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "AGPL-3.0-only",
|
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
],
|
|
58
58
|
"dependencies": {
|
|
59
59
|
"@floating-ui/dom": "^1.6.5",
|
|
60
|
+
"@floating-ui/utils": "^0.2.2",
|
|
60
61
|
"@lit/context": "^1.1.1",
|
|
61
62
|
"@lit/reactive-element": "^2.0.4",
|
|
62
63
|
"@lit/task": "^1.0.0",
|
|
@@ -41,7 +41,6 @@ export const SegmentSelector: FunctionComponent<SegmentSelectorProps> = ({
|
|
|
41
41
|
|
|
42
42
|
return (
|
|
43
43
|
<CheckboxSelector
|
|
44
|
-
className='mx-1'
|
|
45
44
|
items={displayedSegments}
|
|
46
45
|
label={getSegmentSelectorLabel(displayedSegments, prefix || 'Segments: ')}
|
|
47
46
|
setItems={(items) => setDisplayedSegments(items)}
|
|
@@ -1,31 +1,29 @@
|
|
|
1
|
+
import { Dropdown } from './dropdown';
|
|
2
|
+
|
|
1
3
|
export type CheckboxItem = {
|
|
2
4
|
label: string;
|
|
3
5
|
checked: boolean;
|
|
4
6
|
};
|
|
5
7
|
|
|
6
8
|
export interface CheckboxSelectorProps<Item extends CheckboxItem = CheckboxItem> {
|
|
7
|
-
className?: string;
|
|
8
9
|
items: Item[];
|
|
9
10
|
label: string;
|
|
10
11
|
setItems: (items: Item[]) => void;
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
export const CheckboxSelector = <Item extends CheckboxItem>({
|
|
14
|
-
className,
|
|
15
15
|
items,
|
|
16
16
|
label,
|
|
17
17
|
setItems,
|
|
18
18
|
}: CheckboxSelectorProps<Item>) => {
|
|
19
19
|
return (
|
|
20
|
-
<
|
|
21
|
-
<
|
|
22
|
-
{label}
|
|
23
|
-
</div>
|
|
24
|
-
<ul tabIndex={0} class='p-2 shadow menu dropdown-content z-[1] bg-base-100 rounded-box'>
|
|
20
|
+
<Dropdown buttonTitle={label} placement={'bottom-start'}>
|
|
21
|
+
<ul>
|
|
25
22
|
{items.map((item, index) => (
|
|
26
|
-
<li
|
|
23
|
+
<li className='flex flex-row items-center' key={item.label}>
|
|
27
24
|
<label>
|
|
28
25
|
<input
|
|
26
|
+
className={'mr-2'}
|
|
29
27
|
type='checkbox'
|
|
30
28
|
id={`item-${index}`}
|
|
31
29
|
checked={item.checked}
|
|
@@ -41,6 +39,6 @@ export const CheckboxSelector = <Item extends CheckboxItem>({
|
|
|
41
39
|
</li>
|
|
42
40
|
))}
|
|
43
41
|
</ul>
|
|
44
|
-
</
|
|
42
|
+
</Dropdown>
|
|
45
43
|
);
|
|
46
44
|
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { flip, offset, shift } from '@floating-ui/dom';
|
|
2
|
+
import { type Placement } from '@floating-ui/utils';
|
|
3
|
+
import { type FunctionComponent } from 'preact';
|
|
4
|
+
import { useRef, useState } from 'preact/hooks';
|
|
5
|
+
|
|
6
|
+
import { useCloseOnClickOutside, useCloseOnEsc, useFloatingUi } from '../shared/floating-ui/hooks';
|
|
7
|
+
|
|
8
|
+
interface DropdownProps {
|
|
9
|
+
buttonTitle: string;
|
|
10
|
+
placement?: Placement;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const dropdownClass =
|
|
14
|
+
'z-10 absolute w-max top-0 left-0 bg-white p-4 border border-gray-200 shadow-lg rounded-md';
|
|
15
|
+
|
|
16
|
+
export const Dropdown: FunctionComponent<DropdownProps> = ({ children, buttonTitle, placement }) => {
|
|
17
|
+
const [showContent, setShowContent] = useState(false);
|
|
18
|
+
const referenceRef = useRef<HTMLButtonElement>(null);
|
|
19
|
+
const floatingRef = useRef<HTMLDivElement>(null);
|
|
20
|
+
|
|
21
|
+
useFloatingUi(referenceRef, floatingRef, [offset(4), shift(), flip()], placement);
|
|
22
|
+
|
|
23
|
+
useCloseOnClickOutside(floatingRef, referenceRef, setShowContent);
|
|
24
|
+
useCloseOnEsc(setShowContent);
|
|
25
|
+
|
|
26
|
+
const toggle = () => {
|
|
27
|
+
setShowContent(!showContent);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<div>
|
|
32
|
+
<button type='button' className='btn btn-xs whitespace-nowrap' onClick={toggle} ref={referenceRef}>
|
|
33
|
+
{buttonTitle}
|
|
34
|
+
</button>
|
|
35
|
+
<div ref={floatingRef} className={`${dropdownClass} ${showContent ? '' : 'hidden'}`}>
|
|
36
|
+
{children}
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
);
|
|
40
|
+
};
|
|
@@ -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)}
|