@genspectrum/dashboard-components 0.6.11 → 0.6.12
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 +1072 -853
- package/dist/dashboard-components.js.map +1 -1
- package/dist/genspectrum-components.d.ts +7 -7
- package/dist/style.css +113 -0
- package/package.json +2 -2
- package/src/preact/components/checkbox-selector.stories.tsx +93 -11
- package/src/preact/components/checkbox-selector.tsx +19 -0
- package/src/preact/components/color-scale-selector-dropdown.tsx +5 -3
- package/src/preact/components/dropdown.tsx +3 -3
- package/src/preact/components/mutation-type-selector.stories.tsx +115 -0
- package/src/preact/components/mutation-type-selector.tsx +33 -8
- package/src/preact/components/percent-input.stories.tsx +93 -0
- package/src/preact/components/percent-intput.tsx +4 -0
- package/src/preact/components/proportion-selector-dropdown.stories.tsx +2 -2
- package/src/preact/components/proportion-selector-dropdown.tsx +9 -7
- package/src/preact/components/proportion-selector.stories.tsx +4 -4
- package/src/preact/components/proportion-selector.tsx +46 -12
- package/src/preact/components/segment-selector.stories.tsx +151 -0
- package/src/preact/components/{SegmentSelector.tsx → segment-selector.tsx} +29 -20
- package/src/preact/mutationComparison/mutation-comparison.stories.tsx +1 -1
- package/src/preact/mutationComparison/mutation-comparison.tsx +1 -1
- package/src/preact/mutationComparison/queryMutationData.ts +1 -1
- package/src/preact/mutations/mutations-grid.tsx +5 -1
- package/src/preact/mutations/mutations.tsx +1 -1
- package/src/preact/mutations/queryMutations.ts +1 -1
- package/src/preact/mutationsOverTime/getFilteredMutationsOverTime.spec.ts +4 -4
- package/src/preact/mutationsOverTime/getFilteredMutationsOverTimeData.ts +3 -2
- package/src/preact/mutationsOverTime/mutations-over-time.tsx +1 -1
- package/src/preact/numberSequencesOverTime/number-sequences-over-time.tsx +3 -2
- package/src/preact/useQuery.ts +1 -1
- package/src/query/queryMutationsOverTime.ts +3 -3
- package/src/utils/map2d.spec.ts +83 -22
- package/src/utils/map2d.ts +158 -0
- package/src/utils/Map2d.ts +0 -75
|
@@ -25877,6 +25877,242 @@ function filterBySegmentAndMutationType(data, displayedSegments, displayedMutati
|
|
|
25877
25877
|
return data.filter(byDisplayedSegments).filter(byDisplayedMutationTypes);
|
|
25878
25878
|
}
|
|
25879
25879
|
const LapisUrlContext = G$1("");
|
|
25880
|
+
const CsvDownloadButton = ({
|
|
25881
|
+
label = "Download",
|
|
25882
|
+
filename = "data.csv",
|
|
25883
|
+
getData,
|
|
25884
|
+
className
|
|
25885
|
+
}) => {
|
|
25886
|
+
const download = () => {
|
|
25887
|
+
const content = getDownloadContent();
|
|
25888
|
+
const blob = new Blob([content], { type: "text/csv" });
|
|
25889
|
+
const url = URL.createObjectURL(blob);
|
|
25890
|
+
const a2 = document.createElement("a");
|
|
25891
|
+
a2.href = url;
|
|
25892
|
+
a2.download = filename;
|
|
25893
|
+
a2.click();
|
|
25894
|
+
URL.revokeObjectURL(url);
|
|
25895
|
+
};
|
|
25896
|
+
const getDownloadContent = () => {
|
|
25897
|
+
const data = getData();
|
|
25898
|
+
const keys = getDataKeys(data);
|
|
25899
|
+
const header = `${keys.join(",")}
|
|
25900
|
+
`;
|
|
25901
|
+
const rows = data.map((row) => keys.map((key) => row[key]).join(",")).join("\n");
|
|
25902
|
+
return header + rows;
|
|
25903
|
+
};
|
|
25904
|
+
const getDataKeys = (data) => {
|
|
25905
|
+
const keysSet = data.map((row) => Object.keys(row)).reduce((accumulatedKeys, keys) => {
|
|
25906
|
+
keys.forEach((key) => accumulatedKeys.add(key));
|
|
25907
|
+
return accumulatedKeys;
|
|
25908
|
+
}, /* @__PURE__ */ new Set());
|
|
25909
|
+
return [...keysSet];
|
|
25910
|
+
};
|
|
25911
|
+
return /* @__PURE__ */ u$2("button", { className, onClick: download, children: label });
|
|
25912
|
+
};
|
|
25913
|
+
class UserFacingError extends Error {
|
|
25914
|
+
constructor(headline, message) {
|
|
25915
|
+
super(message);
|
|
25916
|
+
this.headline = headline;
|
|
25917
|
+
this.name = "UserFacingError";
|
|
25918
|
+
}
|
|
25919
|
+
}
|
|
25920
|
+
const ErrorDisplay = ({ error }) => {
|
|
25921
|
+
console.error(error);
|
|
25922
|
+
const ref = A$1(null);
|
|
25923
|
+
return /* @__PURE__ */ u$2("div", { className: "h-full w-full rounded-md border-2 border-gray-100 p-2 flex items-center justify-center flex-col", children: [
|
|
25924
|
+
/* @__PURE__ */ u$2("div", { className: "text-red-700 font-bold", children: "Error" }),
|
|
25925
|
+
/* @__PURE__ */ u$2("div", { children: [
|
|
25926
|
+
"Oops! Something went wrong.",
|
|
25927
|
+
error instanceof UserFacingError && /* @__PURE__ */ u$2(k$1, { children: [
|
|
25928
|
+
" ",
|
|
25929
|
+
/* @__PURE__ */ u$2(
|
|
25930
|
+
"button",
|
|
25931
|
+
{
|
|
25932
|
+
className: "text-sm text-gray-600 hover:text-gray-300",
|
|
25933
|
+
onClick: () => {
|
|
25934
|
+
var _a2;
|
|
25935
|
+
return (_a2 = ref.current) == null ? void 0 : _a2.showModal();
|
|
25936
|
+
},
|
|
25937
|
+
children: "Show details."
|
|
25938
|
+
}
|
|
25939
|
+
),
|
|
25940
|
+
/* @__PURE__ */ u$2("dialog", { ref, class: "modal", children: [
|
|
25941
|
+
/* @__PURE__ */ u$2("div", { class: "modal-box", children: [
|
|
25942
|
+
/* @__PURE__ */ u$2("form", { method: "dialog", children: /* @__PURE__ */ u$2("button", { className: "btn btn-sm btn-circle btn-ghost absolute right-2 top-2", children: "✕" }) }),
|
|
25943
|
+
/* @__PURE__ */ u$2("h1", { class: "text-lg", children: error.headline }),
|
|
25944
|
+
/* @__PURE__ */ u$2("p", { class: "py-4", children: error.message })
|
|
25945
|
+
] }),
|
|
25946
|
+
/* @__PURE__ */ u$2("form", { method: "dialog", class: "modal-backdrop", children: /* @__PURE__ */ u$2("button", { children: "close" }) })
|
|
25947
|
+
] })
|
|
25948
|
+
] })
|
|
25949
|
+
] })
|
|
25950
|
+
] });
|
|
25951
|
+
};
|
|
25952
|
+
const ResizeContainer = ({ children, size }) => {
|
|
25953
|
+
return /* @__PURE__ */ u$2("div", { style: size, className: "bg-white", children });
|
|
25954
|
+
};
|
|
25955
|
+
const ErrorBoundary = ({ size, children }) => {
|
|
25956
|
+
const [internalError] = b$1();
|
|
25957
|
+
if (internalError) {
|
|
25958
|
+
return /* @__PURE__ */ u$2(ResizeContainer, { size, children: /* @__PURE__ */ u$2(ErrorDisplay, { error: internalError }) });
|
|
25959
|
+
}
|
|
25960
|
+
return /* @__PURE__ */ u$2(k$1, { children });
|
|
25961
|
+
};
|
|
25962
|
+
const Fullscreen = () => {
|
|
25963
|
+
const element = A$1(null);
|
|
25964
|
+
const isFullscreen = useFullscreenStatus();
|
|
25965
|
+
return /* @__PURE__ */ u$2(
|
|
25966
|
+
"button",
|
|
25967
|
+
{
|
|
25968
|
+
ref: element,
|
|
25969
|
+
onClick: async () => {
|
|
25970
|
+
if (element.current) {
|
|
25971
|
+
if (isFullscreen) {
|
|
25972
|
+
await document.exitFullscreen();
|
|
25973
|
+
} else {
|
|
25974
|
+
const componentRoot = findComponentRoot(element.current);
|
|
25975
|
+
if (componentRoot) {
|
|
25976
|
+
await componentRoot.requestFullscreen();
|
|
25977
|
+
}
|
|
25978
|
+
}
|
|
25979
|
+
}
|
|
25980
|
+
},
|
|
25981
|
+
className: `mt-0.5 iconify text-2xl ${isFullscreen ? "mdi--fullscreen-exit hover:scale-90" : "mdi--fullscreen hover:scale-110"}`,
|
|
25982
|
+
title: isFullscreen ? "Exit fullscreen" : "Enter fullscreen"
|
|
25983
|
+
}
|
|
25984
|
+
);
|
|
25985
|
+
};
|
|
25986
|
+
function findComponentRoot(element) {
|
|
25987
|
+
var _a2;
|
|
25988
|
+
return (_a2 = findShadowRoot(element)) == null ? void 0 : _a2.children[0];
|
|
25989
|
+
}
|
|
25990
|
+
function findShadowRoot(element) {
|
|
25991
|
+
let current = element;
|
|
25992
|
+
while (current) {
|
|
25993
|
+
if (current instanceof ShadowRoot) {
|
|
25994
|
+
return current;
|
|
25995
|
+
}
|
|
25996
|
+
if (current.parentNode === null) {
|
|
25997
|
+
return null;
|
|
25998
|
+
}
|
|
25999
|
+
current = current.parentNode;
|
|
26000
|
+
}
|
|
26001
|
+
return null;
|
|
26002
|
+
}
|
|
26003
|
+
function useFullscreenStatus() {
|
|
26004
|
+
const [isFullscreen, setIsFullscreen] = h$1(document.fullscreenElement !== null);
|
|
26005
|
+
y$1(() => {
|
|
26006
|
+
const handleFullscreenChange = () => {
|
|
26007
|
+
setIsFullscreen(document.fullscreenElement !== null);
|
|
26008
|
+
};
|
|
26009
|
+
document.addEventListener("fullscreenchange", handleFullscreenChange);
|
|
26010
|
+
return () => {
|
|
26011
|
+
document.removeEventListener("fullscreenchange", handleFullscreenChange);
|
|
26012
|
+
};
|
|
26013
|
+
}, []);
|
|
26014
|
+
return isFullscreen;
|
|
26015
|
+
}
|
|
26016
|
+
const Info = ({ children }) => {
|
|
26017
|
+
const dialogRef = A$1(null);
|
|
26018
|
+
const toggleHelp = () => {
|
|
26019
|
+
var _a2;
|
|
26020
|
+
(_a2 = dialogRef.current) == null ? void 0 : _a2.showModal();
|
|
26021
|
+
};
|
|
26022
|
+
return /* @__PURE__ */ u$2("div", { className: "relative", children: [
|
|
26023
|
+
/* @__PURE__ */ u$2("button", { type: "button", className: "btn btn-xs", onClick: toggleHelp, children: "?" }),
|
|
26024
|
+
/* @__PURE__ */ u$2("dialog", { ref: dialogRef, className: "modal modal-bottom sm:modal-middle", children: [
|
|
26025
|
+
/* @__PURE__ */ u$2("div", { className: "modal-box sm:max-w-5xl", children: [
|
|
26026
|
+
/* @__PURE__ */ u$2("form", { method: "dialog", children: /* @__PURE__ */ u$2("button", { className: "btn btn-sm btn-circle btn-ghost absolute right-2 top-2", children: "✕" }) }),
|
|
26027
|
+
/* @__PURE__ */ u$2("div", { className: "flex flex-col", children }),
|
|
26028
|
+
/* @__PURE__ */ u$2("div", { className: "modal-action", children: /* @__PURE__ */ u$2("form", { method: "dialog", children: /* @__PURE__ */ u$2("button", { className: "float-right underline text-sm hover:text-blue-700 mr-2", children: "Close" }) }) })
|
|
26029
|
+
] }),
|
|
26030
|
+
/* @__PURE__ */ u$2("form", { method: "dialog", className: "modal-backdrop", children: /* @__PURE__ */ u$2("button", { children: "Helper to close when clicked outside" }) })
|
|
26031
|
+
] })
|
|
26032
|
+
] });
|
|
26033
|
+
};
|
|
26034
|
+
const InfoHeadline1 = ({ children }) => {
|
|
26035
|
+
return /* @__PURE__ */ u$2("h1", { className: "text-lg font-bold", children });
|
|
26036
|
+
};
|
|
26037
|
+
const InfoHeadline2 = ({ children }) => {
|
|
26038
|
+
return /* @__PURE__ */ u$2("h2", { className: "text-base font-bold mt-4", children });
|
|
26039
|
+
};
|
|
26040
|
+
const InfoParagraph = ({ children }) => {
|
|
26041
|
+
return /* @__PURE__ */ u$2("p", { className: "text-justify my-1", children });
|
|
26042
|
+
};
|
|
26043
|
+
const InfoLink = ({ children, href }) => {
|
|
26044
|
+
return /* @__PURE__ */ u$2("a", { className: "text-blue-600 hover:text-blue-800", href, target: "_blank", rel: "noopener noreferrer", children });
|
|
26045
|
+
};
|
|
26046
|
+
const InfoComponentCode = ({ componentName, params, lapisUrl }) => {
|
|
26047
|
+
const componentCode = componentParametersToCode(componentName, params, lapisUrl);
|
|
26048
|
+
const codePenData = {
|
|
26049
|
+
title: "GenSpectrum dashboard component",
|
|
26050
|
+
html: generateFullExampleCode(componentCode, componentName),
|
|
26051
|
+
layout: "left",
|
|
26052
|
+
editors: "100"
|
|
26053
|
+
};
|
|
26054
|
+
return /* @__PURE__ */ u$2(k$1, { children: [
|
|
26055
|
+
/* @__PURE__ */ u$2(InfoHeadline2, { children: "Use this component yourself" }),
|
|
26056
|
+
/* @__PURE__ */ u$2(InfoParagraph, { children: [
|
|
26057
|
+
"This component was created using the following parameters:",
|
|
26058
|
+
/* @__PURE__ */ u$2("div", { className: "p-4 border border-gray-200 rounded-lg overflow-x-auto", children: /* @__PURE__ */ u$2("pre", { children: /* @__PURE__ */ u$2("code", { children: componentCode }) }) })
|
|
26059
|
+
] }),
|
|
26060
|
+
/* @__PURE__ */ u$2(InfoParagraph, { children: [
|
|
26061
|
+
"You can add this component to your own website using the",
|
|
26062
|
+
" ",
|
|
26063
|
+
/* @__PURE__ */ u$2(InfoLink, { href: "https://github.com/GenSpectrum/dashboard-components", children: "GenSpectrum dashboard components library" }),
|
|
26064
|
+
" ",
|
|
26065
|
+
"and the code from above."
|
|
26066
|
+
] }),
|
|
26067
|
+
/* @__PURE__ */ u$2(InfoParagraph, { children: /* @__PURE__ */ u$2("form", { action: "https://codepen.io/pen/define", method: "POST", target: "_blank", children: [
|
|
26068
|
+
/* @__PURE__ */ u$2(
|
|
26069
|
+
"input",
|
|
26070
|
+
{
|
|
26071
|
+
type: "hidden",
|
|
26072
|
+
name: "data",
|
|
26073
|
+
value: JSON.stringify(codePenData).replace(/"/g, """).replace(/'/g, "'")
|
|
26074
|
+
}
|
|
26075
|
+
),
|
|
26076
|
+
/* @__PURE__ */ u$2("button", { className: "text-blue-600 hover:text-blue-800", type: "submit", children: "Click here to try it out on CodePen." })
|
|
26077
|
+
] }) })
|
|
26078
|
+
] });
|
|
26079
|
+
};
|
|
26080
|
+
function componentParametersToCode(componentName, params, lapisUrl) {
|
|
26081
|
+
const stringifyIfNeeded = (value) => {
|
|
26082
|
+
return typeof value === "object" ? JSON.stringify(value) : value;
|
|
26083
|
+
};
|
|
26084
|
+
const attributes = indentLines(
|
|
26085
|
+
Object.entries(params).map(([key, value]) => `${key}='${stringifyIfNeeded(value)}'`).join("\n"),
|
|
26086
|
+
4
|
|
26087
|
+
);
|
|
26088
|
+
return `<gs-app lapis="${lapisUrl}">
|
|
26089
|
+
<gs-${componentName}
|
|
26090
|
+
${attributes}
|
|
26091
|
+
/>
|
|
26092
|
+
</gs-app>`;
|
|
26093
|
+
}
|
|
26094
|
+
function generateFullExampleCode(componentCode, componentName) {
|
|
26095
|
+
const storyBookPath = `/docs/visualization-${componentName}--docs`;
|
|
26096
|
+
return `<html>
|
|
26097
|
+
<head>
|
|
26098
|
+
<script type="module" src="https://unpkg.com/@genspectrum/dashboard-components@latest/dist/dashboard-components.js"><\/script>
|
|
26099
|
+
<link rel="stylesheet" href="https://unpkg.com/@genspectrum/dashboard-components@latest/dist/style.css" />
|
|
26100
|
+
</head>
|
|
26101
|
+
|
|
26102
|
+
<body>
|
|
26103
|
+
<!-- Component documentation: https://genspectrum.github.io/dashboard-components/?path=${storyBookPath} -->
|
|
26104
|
+
${indentLines(componentCode, 2)}
|
|
26105
|
+
</body>
|
|
26106
|
+
</html>
|
|
26107
|
+
`;
|
|
26108
|
+
}
|
|
26109
|
+
function indentLines(text, numberSpaces) {
|
|
26110
|
+
const spaces = " ".repeat(numberSpaces);
|
|
26111
|
+
return text.split("\n").map((line) => spaces + line).join("\n");
|
|
26112
|
+
}
|
|
26113
|
+
const LoadingDisplay = () => {
|
|
26114
|
+
return /* @__PURE__ */ u$2("div", { "aria-label": "Loading", className: "h-full w-full skeleton" });
|
|
26115
|
+
};
|
|
25880
26116
|
const min = Math.min;
|
|
25881
26117
|
const max = Math.max;
|
|
25882
26118
|
const round = Math.round;
|
|
@@ -27188,8 +27424,8 @@ const Dropdown = ({ children, buttonTitle, placement }) => {
|
|
|
27188
27424
|
const toggle = () => {
|
|
27189
27425
|
setShowContent(!showContent);
|
|
27190
27426
|
};
|
|
27191
|
-
return /* @__PURE__ */ u$2(
|
|
27192
|
-
/* @__PURE__ */ u$2("button", { type: "button", className: "btn btn-xs whitespace-nowrap", onClick: toggle, ref: referenceRef, children: buttonTitle }),
|
|
27427
|
+
return /* @__PURE__ */ u$2(k$1, { children: [
|
|
27428
|
+
/* @__PURE__ */ u$2("button", { type: "button", className: "btn btn-xs whitespace-nowrap w-full", onClick: toggle, ref: referenceRef, children: buttonTitle }),
|
|
27193
27429
|
/* @__PURE__ */ u$2("div", { ref: floatingRef, className: `${dropdownClass} ${showContent ? "" : "hidden"}`, children })
|
|
27194
27430
|
] });
|
|
27195
27431
|
};
|
|
@@ -27198,52 +27434,294 @@ const CheckboxSelector = ({
|
|
|
27198
27434
|
label,
|
|
27199
27435
|
setItems
|
|
27200
27436
|
}) => {
|
|
27201
|
-
return /* @__PURE__ */ u$2(Dropdown, { buttonTitle: label, placement: "bottom-start", children:
|
|
27437
|
+
return /* @__PURE__ */ u$2(Dropdown, { buttonTitle: label, placement: "bottom-start", children: [
|
|
27202
27438
|
/* @__PURE__ */ u$2(
|
|
27203
|
-
"
|
|
27439
|
+
"button",
|
|
27204
27440
|
{
|
|
27205
|
-
className: "
|
|
27206
|
-
|
|
27207
|
-
|
|
27208
|
-
checked: item.checked,
|
|
27209
|
-
onChange: () => {
|
|
27210
|
-
const newItems = items.map(
|
|
27211
|
-
(item2, i3) => i3 === index2 ? { ...item2, checked: !item2.checked } : item2
|
|
27212
|
-
);
|
|
27441
|
+
className: "btn btn-xs btn-ghost",
|
|
27442
|
+
onClick: () => {
|
|
27443
|
+
const newItems = items.map((item) => ({ ...item, checked: true }));
|
|
27213
27444
|
setItems(newItems);
|
|
27214
|
-
}
|
|
27445
|
+
},
|
|
27446
|
+
children: "Select all"
|
|
27215
27447
|
}
|
|
27216
27448
|
),
|
|
27217
|
-
|
|
27218
|
-
|
|
27219
|
-
|
|
27220
|
-
|
|
27221
|
-
|
|
27222
|
-
|
|
27223
|
-
|
|
27224
|
-
|
|
27225
|
-
|
|
27226
|
-
|
|
27227
|
-
|
|
27228
|
-
|
|
27229
|
-
|
|
27230
|
-
|
|
27231
|
-
|
|
27232
|
-
|
|
27233
|
-
|
|
27234
|
-
|
|
27235
|
-
|
|
27236
|
-
|
|
27449
|
+
/* @__PURE__ */ u$2(
|
|
27450
|
+
"button",
|
|
27451
|
+
{
|
|
27452
|
+
className: "btn btn-xs btn-ghost",
|
|
27453
|
+
onClick: () => {
|
|
27454
|
+
const newItems = items.map((item) => ({ ...item, checked: false }));
|
|
27455
|
+
setItems(newItems);
|
|
27456
|
+
},
|
|
27457
|
+
children: "Select none"
|
|
27458
|
+
}
|
|
27459
|
+
),
|
|
27460
|
+
/* @__PURE__ */ u$2("div", { className: "divider mt-0 mb-0" }),
|
|
27461
|
+
/* @__PURE__ */ u$2("ul", { children: items.map((item, index2) => /* @__PURE__ */ u$2("li", { className: "flex flex-row items-center", children: /* @__PURE__ */ u$2("label", { children: [
|
|
27462
|
+
/* @__PURE__ */ u$2(
|
|
27463
|
+
"input",
|
|
27464
|
+
{
|
|
27465
|
+
className: "mr-2",
|
|
27466
|
+
type: "checkbox",
|
|
27467
|
+
id: `item-${index2}`,
|
|
27468
|
+
checked: item.checked,
|
|
27469
|
+
onChange: () => {
|
|
27470
|
+
const newItems = items.map(
|
|
27471
|
+
(item2, i3) => i3 === index2 ? { ...item2, checked: !item2.checked } : item2
|
|
27472
|
+
);
|
|
27473
|
+
setItems(newItems);
|
|
27474
|
+
}
|
|
27475
|
+
}
|
|
27476
|
+
),
|
|
27477
|
+
item.label
|
|
27478
|
+
] }) }, item.label)) })
|
|
27479
|
+
] });
|
|
27480
|
+
};
|
|
27481
|
+
const MutationTypeSelector = ({
|
|
27482
|
+
displayedMutationTypes,
|
|
27483
|
+
setDisplayedMutationTypes
|
|
27484
|
+
}) => {
|
|
27485
|
+
return /* @__PURE__ */ u$2("div", { className: "w-[6rem]", children: /* @__PURE__ */ u$2(
|
|
27486
|
+
CheckboxSelector,
|
|
27487
|
+
{
|
|
27488
|
+
items: displayedMutationTypes,
|
|
27489
|
+
label: getMutationTypesSelectorLabel(displayedMutationTypes),
|
|
27490
|
+
setItems: (items) => setDisplayedMutationTypes(items)
|
|
27491
|
+
}
|
|
27492
|
+
) });
|
|
27493
|
+
};
|
|
27494
|
+
const getMutationTypesSelectorLabel = (displayedMutationTypes) => {
|
|
27495
|
+
const checkedLabels = displayedMutationTypes.filter((displayedMutationType) => displayedMutationType.checked);
|
|
27496
|
+
if (checkedLabels.length === 0) {
|
|
27497
|
+
return `No types`;
|
|
27498
|
+
}
|
|
27499
|
+
if (displayedMutationTypes.length === checkedLabels.length) {
|
|
27500
|
+
return displayedMutationTypes.map((type) => {
|
|
27501
|
+
switch (type.type) {
|
|
27502
|
+
case "substitution":
|
|
27503
|
+
return "Subst.";
|
|
27504
|
+
case "deletion":
|
|
27505
|
+
return "Del.";
|
|
27506
|
+
}
|
|
27507
|
+
}).join(", ");
|
|
27508
|
+
}
|
|
27509
|
+
return checkedLabels.map((type) => {
|
|
27510
|
+
return type.label;
|
|
27511
|
+
}).join(", ");
|
|
27512
|
+
};
|
|
27513
|
+
const NoDataDisplay = () => {
|
|
27514
|
+
return /* @__PURE__ */ u$2("div", { className: "h-full w-full rounded-md border-2 border-gray-100 p-2 flex items-center justify-center", children: /* @__PURE__ */ u$2("div", { children: "No data available." }) });
|
|
27515
|
+
};
|
|
27516
|
+
const MinMaxRangeSlider = ({
|
|
27517
|
+
min: min2,
|
|
27518
|
+
max: max2,
|
|
27519
|
+
setMin,
|
|
27520
|
+
setMax,
|
|
27521
|
+
rangeMin = 0,
|
|
27522
|
+
rangeMax = 100,
|
|
27523
|
+
step = 0.1
|
|
27524
|
+
}) => {
|
|
27525
|
+
const sliderColor = "#C6C6C6";
|
|
27526
|
+
const rangeColor = "#387bbe";
|
|
27527
|
+
const [zIndexTo, setZIndexTo] = h$1(0);
|
|
27528
|
+
const onMinChange = (event) => {
|
|
27529
|
+
const input = event.target;
|
|
27530
|
+
const minValue = Number(input.value);
|
|
27531
|
+
if (minValue > max2) {
|
|
27532
|
+
setMax(minValue);
|
|
27533
|
+
setMin(minValue);
|
|
27534
|
+
} else {
|
|
27535
|
+
setMin(minValue);
|
|
27536
|
+
}
|
|
27537
|
+
};
|
|
27538
|
+
const onMaxChange = (event) => {
|
|
27539
|
+
const input = event.target;
|
|
27540
|
+
const maxValue = Number(input.value);
|
|
27541
|
+
if (maxValue <= 0) {
|
|
27542
|
+
setZIndexTo(2);
|
|
27543
|
+
} else {
|
|
27544
|
+
setZIndexTo(0);
|
|
27545
|
+
}
|
|
27546
|
+
if (maxValue < min2) {
|
|
27547
|
+
setMin(maxValue);
|
|
27548
|
+
setMax(maxValue);
|
|
27549
|
+
} else {
|
|
27550
|
+
setMax(maxValue);
|
|
27551
|
+
}
|
|
27552
|
+
};
|
|
27553
|
+
const background = `
|
|
27554
|
+
linear-gradient(
|
|
27555
|
+
to right,
|
|
27556
|
+
${sliderColor} 0%,
|
|
27557
|
+
${sliderColor} ${min2}%,
|
|
27558
|
+
${rangeColor} ${min2}%,
|
|
27559
|
+
${rangeColor} ${max2}%,
|
|
27560
|
+
${sliderColor} ${max2}%,
|
|
27561
|
+
${sliderColor} 100%)
|
|
27562
|
+
`;
|
|
27563
|
+
return /* @__PURE__ */ u$2("div", { class: "my-4 relative w-full h-full", children: [
|
|
27564
|
+
/* @__PURE__ */ u$2(
|
|
27565
|
+
"input",
|
|
27566
|
+
{
|
|
27567
|
+
id: "fromSlider",
|
|
27568
|
+
type: "range",
|
|
27569
|
+
value: min2,
|
|
27570
|
+
onInput: onMinChange,
|
|
27571
|
+
min: rangeMin,
|
|
27572
|
+
max: rangeMax,
|
|
27573
|
+
step,
|
|
27574
|
+
style: { background, zIndex: 1, height: 0 }
|
|
27575
|
+
}
|
|
27576
|
+
),
|
|
27577
|
+
/* @__PURE__ */ u$2(
|
|
27578
|
+
"input",
|
|
27579
|
+
{
|
|
27580
|
+
id: "toSlider",
|
|
27581
|
+
type: "range",
|
|
27582
|
+
value: max2,
|
|
27583
|
+
min: rangeMin,
|
|
27584
|
+
max: rangeMax,
|
|
27585
|
+
step,
|
|
27586
|
+
onInput: onMaxChange,
|
|
27587
|
+
style: { background, zIndex: zIndexTo }
|
|
27588
|
+
}
|
|
27589
|
+
)
|
|
27590
|
+
] });
|
|
27591
|
+
};
|
|
27592
|
+
const percentageInRange = (percentage) => {
|
|
27593
|
+
return percentage <= 100 && percentage >= 0;
|
|
27594
|
+
};
|
|
27595
|
+
const PercentInput = ({ percentage, setPercentage }) => {
|
|
27596
|
+
const [internalPercentage, setInternalPercentage] = h$1(percentage);
|
|
27597
|
+
y$1(() => {
|
|
27598
|
+
setInternalPercentage(percentage);
|
|
27599
|
+
}, [percentage]);
|
|
27600
|
+
const handleInputChange = (event) => {
|
|
27601
|
+
const input = event.target;
|
|
27602
|
+
const value = Number(input.value);
|
|
27603
|
+
if (value === internalPercentage || input.value === "") {
|
|
27604
|
+
return;
|
|
27605
|
+
}
|
|
27606
|
+
const inRange2 = percentageInRange(value);
|
|
27607
|
+
if (inRange2) {
|
|
27608
|
+
setPercentage(value);
|
|
27609
|
+
}
|
|
27610
|
+
setInternalPercentage(value);
|
|
27611
|
+
};
|
|
27612
|
+
const isError = !percentageInRange(internalPercentage);
|
|
27613
|
+
return /* @__PURE__ */ u$2("label", { className: `input input-bordered flex items-center gap-2 w-32 ${isError ? "input-error" : ""}`, children: [
|
|
27614
|
+
/* @__PURE__ */ u$2(
|
|
27615
|
+
"input",
|
|
27616
|
+
{
|
|
27617
|
+
type: "number",
|
|
27618
|
+
step: 0.1,
|
|
27619
|
+
min: 0,
|
|
27620
|
+
max: 100,
|
|
27621
|
+
value: internalPercentage,
|
|
27622
|
+
onInput: handleInputChange,
|
|
27623
|
+
lang: "en",
|
|
27624
|
+
className: `grow w-16`
|
|
27625
|
+
}
|
|
27626
|
+
),
|
|
27627
|
+
"%"
|
|
27628
|
+
] });
|
|
27629
|
+
};
|
|
27630
|
+
function useUpdateExternalValueInIntervals(setExternalValue, updateIntervalInMs, internalValue) {
|
|
27631
|
+
const hasMounted = A$1(false);
|
|
27632
|
+
y$1(() => {
|
|
27633
|
+
if (!hasMounted.current) {
|
|
27634
|
+
hasMounted.current = true;
|
|
27635
|
+
return;
|
|
27636
|
+
}
|
|
27637
|
+
const minTimeout = setTimeout(() => {
|
|
27638
|
+
setExternalValue(internalValue);
|
|
27639
|
+
}, updateIntervalInMs);
|
|
27640
|
+
return () => clearTimeout(minTimeout);
|
|
27641
|
+
}, [internalValue]);
|
|
27642
|
+
}
|
|
27643
|
+
const ProportionSelector = ({
|
|
27644
|
+
proportionInterval,
|
|
27645
|
+
setMinProportion,
|
|
27646
|
+
setMaxProportion
|
|
27647
|
+
}) => {
|
|
27648
|
+
const updateIntervalInMs = 300;
|
|
27649
|
+
const { min: minProportion, max: maxProportion } = proportionInterval;
|
|
27650
|
+
const [internalMinProportion, setInternalMinProportion] = h$1(minProportion);
|
|
27651
|
+
const [internalMaxProportion, setInternalMaxProportion] = h$1(maxProportion);
|
|
27652
|
+
useUpdateExternalValueInIntervals(setMinProportion, updateIntervalInMs, internalMinProportion);
|
|
27653
|
+
const updateMinPercentage = (minPercentage) => {
|
|
27654
|
+
const newMinProportion = minPercentage / 100;
|
|
27655
|
+
setInternalMinProportion(newMinProportion);
|
|
27656
|
+
};
|
|
27657
|
+
useUpdateExternalValueInIntervals(setMaxProportion, updateIntervalInMs, internalMaxProportion);
|
|
27658
|
+
const updateMaxPercentage = (maxPercentage) => {
|
|
27659
|
+
const newMaxProportion = maxPercentage / 100;
|
|
27660
|
+
setInternalMaxProportion(newMaxProportion);
|
|
27661
|
+
};
|
|
27662
|
+
return /* @__PURE__ */ u$2("div", { class: "flex flex-col w-64 mb-2", children: [
|
|
27663
|
+
/* @__PURE__ */ u$2("div", { class: "flex items-center ", children: [
|
|
27664
|
+
/* @__PURE__ */ u$2(PercentInput, { percentage: internalMinProportion * 100, setPercentage: updateMinPercentage }),
|
|
27665
|
+
/* @__PURE__ */ u$2("div", { class: "m-2", children: "-" }),
|
|
27666
|
+
/* @__PURE__ */ u$2(PercentInput, { percentage: internalMaxProportion * 100, setPercentage: updateMaxPercentage })
|
|
27667
|
+
] }),
|
|
27668
|
+
/* @__PURE__ */ u$2("div", { class: "my-1", children: /* @__PURE__ */ u$2(
|
|
27669
|
+
MinMaxRangeSlider,
|
|
27670
|
+
{
|
|
27671
|
+
min: internalMinProportion * 100,
|
|
27672
|
+
max: internalMaxProportion * 100,
|
|
27673
|
+
setMin: updateMinPercentage,
|
|
27674
|
+
setMax: updateMaxPercentage
|
|
27675
|
+
}
|
|
27676
|
+
) })
|
|
27677
|
+
] });
|
|
27678
|
+
};
|
|
27679
|
+
const ProportionSelectorDropdown = ({
|
|
27680
|
+
proportionInterval,
|
|
27681
|
+
setMinProportion,
|
|
27682
|
+
setMaxProportion
|
|
27683
|
+
}) => {
|
|
27684
|
+
const label = `${(proportionInterval.min * 100).toFixed(1)}% - ${(proportionInterval.max * 100).toFixed(1)}%`;
|
|
27685
|
+
return /* @__PURE__ */ u$2("div", { className: "w-44", children: /* @__PURE__ */ u$2(Dropdown, { buttonTitle: `Proportion ${label}`, placement: "bottom-start", children: /* @__PURE__ */ u$2(
|
|
27686
|
+
ProportionSelector,
|
|
27687
|
+
{
|
|
27688
|
+
proportionInterval,
|
|
27689
|
+
setMinProportion,
|
|
27690
|
+
setMaxProportion
|
|
27691
|
+
}
|
|
27692
|
+
) }) });
|
|
27693
|
+
};
|
|
27694
|
+
const ReferenceGenomeContext = G$1({ nucleotideSequences: [], genes: [] });
|
|
27695
|
+
const SegmentSelector = ({
|
|
27696
|
+
displayedSegments,
|
|
27697
|
+
setDisplayedSegments
|
|
27698
|
+
}) => {
|
|
27699
|
+
if (displayedSegments.length <= 1) {
|
|
27237
27700
|
return null;
|
|
27238
27701
|
}
|
|
27239
|
-
return /* @__PURE__ */ u$2(
|
|
27702
|
+
return /* @__PURE__ */ u$2("div", { className: "w-24", children: /* @__PURE__ */ u$2(
|
|
27240
27703
|
CheckboxSelector,
|
|
27241
27704
|
{
|
|
27242
27705
|
items: displayedSegments,
|
|
27243
|
-
label: getSegmentSelectorLabel(displayedSegments
|
|
27706
|
+
label: getSegmentSelectorLabel(displayedSegments),
|
|
27244
27707
|
setItems: (items) => setDisplayedSegments(items)
|
|
27245
27708
|
}
|
|
27246
|
-
);
|
|
27709
|
+
) });
|
|
27710
|
+
};
|
|
27711
|
+
const getSegmentSelectorLabel = (displayedSegments) => {
|
|
27712
|
+
const allSelectedSelected = displayedSegments.filter((segment) => segment.checked).map((segment) => segment.segment);
|
|
27713
|
+
if (allSelectedSelected.length === 0) {
|
|
27714
|
+
return `No segments`;
|
|
27715
|
+
}
|
|
27716
|
+
if (displayedSegments.length === allSelectedSelected.length) {
|
|
27717
|
+
return `All segments`;
|
|
27718
|
+
}
|
|
27719
|
+
const longestDisplayString = `All segments`;
|
|
27720
|
+
const allSelectedSelectedString = allSelectedSelected.join(", ");
|
|
27721
|
+
if (longestDisplayString.length >= allSelectedSelectedString.length) {
|
|
27722
|
+
return allSelectedSelectedString;
|
|
27723
|
+
}
|
|
27724
|
+
return `${allSelectedSelected.length} ${allSelectedSelected.length === 1 ? "segment" : "segments"}`;
|
|
27247
27725
|
};
|
|
27248
27726
|
function useDisplayedSegments(sequenceType) {
|
|
27249
27727
|
const referenceGenome = x$1(ReferenceGenomeContext);
|
|
@@ -27254,512 +27732,97 @@ function useDisplayedSegments(sequenceType) {
|
|
|
27254
27732
|
}));
|
|
27255
27733
|
return h$1(displayedSegments);
|
|
27256
27734
|
}
|
|
27257
|
-
const
|
|
27258
|
-
|
|
27259
|
-
|
|
27260
|
-
|
|
27261
|
-
|
|
27262
|
-
|
|
27263
|
-
|
|
27264
|
-
|
|
27265
|
-
|
|
27266
|
-
const url = URL.createObjectURL(blob);
|
|
27267
|
-
const a2 = document.createElement("a");
|
|
27268
|
-
a2.href = url;
|
|
27269
|
-
a2.download = filename;
|
|
27270
|
-
a2.click();
|
|
27271
|
-
URL.revokeObjectURL(url);
|
|
27272
|
-
};
|
|
27273
|
-
const getDownloadContent = () => {
|
|
27274
|
-
const data = getData();
|
|
27275
|
-
const keys = getDataKeys(data);
|
|
27276
|
-
const header = `${keys.join(",")}
|
|
27277
|
-
`;
|
|
27278
|
-
const rows = data.map((row) => keys.map((key) => row[key]).join(",")).join("\n");
|
|
27279
|
-
return header + rows;
|
|
27280
|
-
};
|
|
27281
|
-
const getDataKeys = (data) => {
|
|
27282
|
-
const keysSet = data.map((row) => Object.keys(row)).reduce((accumulatedKeys, keys) => {
|
|
27283
|
-
keys.forEach((key) => accumulatedKeys.add(key));
|
|
27284
|
-
return accumulatedKeys;
|
|
27285
|
-
}, /* @__PURE__ */ new Set());
|
|
27286
|
-
return [...keysSet];
|
|
27735
|
+
const Tabs = ({ tabs, toolbar }) => {
|
|
27736
|
+
const [activeTab, setActiveTab] = h$1(tabs[0].title);
|
|
27737
|
+
const [heightOfTabs, setHeightOfTabs] = h$1("3rem");
|
|
27738
|
+
const tabRef = A$1(null);
|
|
27739
|
+
const updateHeightOfTabs = () => {
|
|
27740
|
+
if (tabRef.current) {
|
|
27741
|
+
const heightOfTabs2 = tabRef.current.getBoundingClientRect().height;
|
|
27742
|
+
setHeightOfTabs(`${heightOfTabs2}px`);
|
|
27743
|
+
}
|
|
27287
27744
|
};
|
|
27288
|
-
return /* @__PURE__ */ u$2("button", { className, onClick: download, children: label });
|
|
27289
|
-
};
|
|
27290
|
-
class UserFacingError extends Error {
|
|
27291
|
-
constructor(headline, message) {
|
|
27292
|
-
super(message);
|
|
27293
|
-
this.headline = headline;
|
|
27294
|
-
this.name = "UserFacingError";
|
|
27295
|
-
}
|
|
27296
|
-
}
|
|
27297
|
-
const ErrorDisplay = ({ error }) => {
|
|
27298
|
-
console.error(error);
|
|
27299
|
-
const ref = A$1(null);
|
|
27300
|
-
return /* @__PURE__ */ u$2("div", { className: "h-full w-full rounded-md border-2 border-gray-100 p-2 flex items-center justify-center flex-col", children: [
|
|
27301
|
-
/* @__PURE__ */ u$2("div", { className: "text-red-700 font-bold", children: "Error" }),
|
|
27302
|
-
/* @__PURE__ */ u$2("div", { children: [
|
|
27303
|
-
"Oops! Something went wrong.",
|
|
27304
|
-
error instanceof UserFacingError && /* @__PURE__ */ u$2(k$1, { children: [
|
|
27305
|
-
" ",
|
|
27306
|
-
/* @__PURE__ */ u$2(
|
|
27307
|
-
"button",
|
|
27308
|
-
{
|
|
27309
|
-
className: "text-sm text-gray-600 hover:text-gray-300",
|
|
27310
|
-
onClick: () => {
|
|
27311
|
-
var _a2;
|
|
27312
|
-
return (_a2 = ref.current) == null ? void 0 : _a2.showModal();
|
|
27313
|
-
},
|
|
27314
|
-
children: "Show details."
|
|
27315
|
-
}
|
|
27316
|
-
),
|
|
27317
|
-
/* @__PURE__ */ u$2("dialog", { ref, class: "modal", children: [
|
|
27318
|
-
/* @__PURE__ */ u$2("div", { class: "modal-box", children: [
|
|
27319
|
-
/* @__PURE__ */ u$2("form", { method: "dialog", children: /* @__PURE__ */ u$2("button", { className: "btn btn-sm btn-circle btn-ghost absolute right-2 top-2", children: "✕" }) }),
|
|
27320
|
-
/* @__PURE__ */ u$2("h1", { class: "text-lg", children: error.headline }),
|
|
27321
|
-
/* @__PURE__ */ u$2("p", { class: "py-4", children: error.message })
|
|
27322
|
-
] }),
|
|
27323
|
-
/* @__PURE__ */ u$2("form", { method: "dialog", class: "modal-backdrop", children: /* @__PURE__ */ u$2("button", { children: "close" }) })
|
|
27324
|
-
] })
|
|
27325
|
-
] })
|
|
27326
|
-
] })
|
|
27327
|
-
] });
|
|
27328
|
-
};
|
|
27329
|
-
const ResizeContainer = ({ children, size }) => {
|
|
27330
|
-
return /* @__PURE__ */ u$2("div", { style: size, className: "bg-white", children });
|
|
27331
|
-
};
|
|
27332
|
-
const ErrorBoundary = ({ size, children }) => {
|
|
27333
|
-
const [internalError] = b$1();
|
|
27334
|
-
if (internalError) {
|
|
27335
|
-
return /* @__PURE__ */ u$2(ResizeContainer, { size, children: /* @__PURE__ */ u$2(ErrorDisplay, { error: internalError }) });
|
|
27336
|
-
}
|
|
27337
|
-
return /* @__PURE__ */ u$2(k$1, { children });
|
|
27338
|
-
};
|
|
27339
|
-
const Fullscreen = () => {
|
|
27340
|
-
const element = A$1(null);
|
|
27341
|
-
const isFullscreen = useFullscreenStatus();
|
|
27342
|
-
return /* @__PURE__ */ u$2(
|
|
27343
|
-
"button",
|
|
27344
|
-
{
|
|
27345
|
-
ref: element,
|
|
27346
|
-
onClick: async () => {
|
|
27347
|
-
if (element.current) {
|
|
27348
|
-
if (isFullscreen) {
|
|
27349
|
-
await document.exitFullscreen();
|
|
27350
|
-
} else {
|
|
27351
|
-
const componentRoot = findComponentRoot(element.current);
|
|
27352
|
-
if (componentRoot) {
|
|
27353
|
-
await componentRoot.requestFullscreen();
|
|
27354
|
-
}
|
|
27355
|
-
}
|
|
27356
|
-
}
|
|
27357
|
-
},
|
|
27358
|
-
className: `mt-0.5 iconify text-2xl ${isFullscreen ? "mdi--fullscreen-exit hover:scale-90" : "mdi--fullscreen hover:scale-110"}`,
|
|
27359
|
-
title: isFullscreen ? "Exit fullscreen" : "Enter fullscreen"
|
|
27360
|
-
}
|
|
27361
|
-
);
|
|
27362
|
-
};
|
|
27363
|
-
function findComponentRoot(element) {
|
|
27364
|
-
var _a2;
|
|
27365
|
-
return (_a2 = findShadowRoot(element)) == null ? void 0 : _a2.children[0];
|
|
27366
|
-
}
|
|
27367
|
-
function findShadowRoot(element) {
|
|
27368
|
-
let current = element;
|
|
27369
|
-
while (current) {
|
|
27370
|
-
if (current instanceof ShadowRoot) {
|
|
27371
|
-
return current;
|
|
27372
|
-
}
|
|
27373
|
-
if (current.parentNode === null) {
|
|
27374
|
-
return null;
|
|
27375
|
-
}
|
|
27376
|
-
current = current.parentNode;
|
|
27377
|
-
}
|
|
27378
|
-
return null;
|
|
27379
|
-
}
|
|
27380
|
-
function useFullscreenStatus() {
|
|
27381
|
-
const [isFullscreen, setIsFullscreen] = h$1(document.fullscreenElement !== null);
|
|
27382
27745
|
y$1(() => {
|
|
27383
|
-
|
|
27384
|
-
|
|
27385
|
-
};
|
|
27386
|
-
document.addEventListener("fullscreenchange", handleFullscreenChange);
|
|
27746
|
+
updateHeightOfTabs();
|
|
27747
|
+
window.addEventListener("resize", updateHeightOfTabs);
|
|
27387
27748
|
return () => {
|
|
27388
|
-
|
|
27749
|
+
window.removeEventListener("resize", updateHeightOfTabs);
|
|
27389
27750
|
};
|
|
27390
27751
|
}, []);
|
|
27391
|
-
|
|
27392
|
-
|
|
27393
|
-
|
|
27394
|
-
|
|
27395
|
-
|
|
27396
|
-
|
|
27397
|
-
|
|
27398
|
-
|
|
27399
|
-
|
|
27400
|
-
|
|
27401
|
-
|
|
27402
|
-
|
|
27403
|
-
|
|
27404
|
-
|
|
27405
|
-
|
|
27406
|
-
|
|
27407
|
-
/* @__PURE__ */ u$2("
|
|
27408
|
-
] })
|
|
27409
|
-
] });
|
|
27410
|
-
};
|
|
27411
|
-
const InfoHeadline1 = ({ children }) => {
|
|
27412
|
-
return /* @__PURE__ */ u$2("h1", { className: "text-lg font-bold", children });
|
|
27413
|
-
};
|
|
27414
|
-
const InfoHeadline2 = ({ children }) => {
|
|
27415
|
-
return /* @__PURE__ */ u$2("h2", { className: "text-base font-bold mt-4", children });
|
|
27416
|
-
};
|
|
27417
|
-
const InfoParagraph = ({ children }) => {
|
|
27418
|
-
return /* @__PURE__ */ u$2("p", { className: "text-justify my-1", children });
|
|
27419
|
-
};
|
|
27420
|
-
const InfoLink = ({ children, href }) => {
|
|
27421
|
-
return /* @__PURE__ */ u$2("a", { className: "text-blue-600 hover:text-blue-800", href, target: "_blank", rel: "noopener noreferrer", children });
|
|
27422
|
-
};
|
|
27423
|
-
const InfoComponentCode = ({ componentName, params, lapisUrl }) => {
|
|
27424
|
-
const componentCode = componentParametersToCode(componentName, params, lapisUrl);
|
|
27425
|
-
const codePenData = {
|
|
27426
|
-
title: "GenSpectrum dashboard component",
|
|
27427
|
-
html: generateFullExampleCode(componentCode, componentName),
|
|
27428
|
-
layout: "left",
|
|
27429
|
-
editors: "100"
|
|
27430
|
-
};
|
|
27431
|
-
return /* @__PURE__ */ u$2(k$1, { children: [
|
|
27432
|
-
/* @__PURE__ */ u$2(InfoHeadline2, { children: "Use this component yourself" }),
|
|
27433
|
-
/* @__PURE__ */ u$2(InfoParagraph, { children: [
|
|
27434
|
-
"This component was created using the following parameters:",
|
|
27435
|
-
/* @__PURE__ */ u$2("div", { className: "p-4 border border-gray-200 rounded-lg overflow-x-auto", children: /* @__PURE__ */ u$2("pre", { children: /* @__PURE__ */ u$2("code", { children: componentCode }) }) })
|
|
27436
|
-
] }),
|
|
27437
|
-
/* @__PURE__ */ u$2(InfoParagraph, { children: [
|
|
27438
|
-
"You can add this component to your own website using the",
|
|
27439
|
-
" ",
|
|
27440
|
-
/* @__PURE__ */ u$2(InfoLink, { href: "https://github.com/GenSpectrum/dashboard-components", children: "GenSpectrum dashboard components library" }),
|
|
27441
|
-
" ",
|
|
27442
|
-
"and the code from above."
|
|
27752
|
+
const tabElements = /* @__PURE__ */ u$2("div", { className: "flex flex-row", children: tabs.map((tab) => {
|
|
27753
|
+
return /* @__PURE__ */ u$2(k$1, { children: /* @__PURE__ */ u$2(
|
|
27754
|
+
"button",
|
|
27755
|
+
{
|
|
27756
|
+
className: `px-4 py-2 text-sm font-medium leading-5 transition-colors duration-150 ${activeTab === tab.title ? "border-b-2 border-gray-400" : "text-gray-600 hover:bg-gray-100 hover:text-gray-700"}`,
|
|
27757
|
+
onClick: () => {
|
|
27758
|
+
setActiveTab(tab.title);
|
|
27759
|
+
},
|
|
27760
|
+
children: tab.title
|
|
27761
|
+
}
|
|
27762
|
+
) }, tab.title);
|
|
27763
|
+
}) });
|
|
27764
|
+
const toolbarElement = typeof toolbar === "function" ? toolbar(activeTab) : toolbar;
|
|
27765
|
+
return /* @__PURE__ */ u$2("div", { className: "h-full w-full", children: [
|
|
27766
|
+
/* @__PURE__ */ u$2("div", { ref: tabRef, className: "flex flex-row justify-between flex-wrap", children: [
|
|
27767
|
+
tabElements,
|
|
27768
|
+
toolbar && /* @__PURE__ */ u$2("div", { className: "py-2 flex flex-wrap gap-y-1", children: toolbarElement })
|
|
27443
27769
|
] }),
|
|
27444
|
-
/* @__PURE__ */ u$2(
|
|
27445
|
-
|
|
27446
|
-
|
|
27447
|
-
{
|
|
27448
|
-
|
|
27449
|
-
|
|
27450
|
-
|
|
27451
|
-
|
|
27452
|
-
),
|
|
27453
|
-
/* @__PURE__ */ u$2("button", { className: "text-blue-600 hover:text-blue-800", type: "submit", children: "Click here to try it out on CodePen." })
|
|
27454
|
-
] }) })
|
|
27770
|
+
/* @__PURE__ */ u$2(
|
|
27771
|
+
"div",
|
|
27772
|
+
{
|
|
27773
|
+
className: `p-2 border-2 border-gray-100 rounded-b-md rounded-tr-md ${activeTab === tabs[0].title ? "" : "rounded-tl-md"}`,
|
|
27774
|
+
style: { height: `calc(100% - ${heightOfTabs})` },
|
|
27775
|
+
children: tabs.map((tab) => /* @__PURE__ */ u$2("div", { className: "h-full overflow-auto", hidden: activeTab !== tab.title, children: tab.content }, tab.title))
|
|
27776
|
+
}
|
|
27777
|
+
)
|
|
27455
27778
|
] });
|
|
27456
27779
|
};
|
|
27457
|
-
function
|
|
27458
|
-
const
|
|
27459
|
-
|
|
27460
|
-
|
|
27461
|
-
|
|
27462
|
-
|
|
27463
|
-
|
|
27464
|
-
|
|
27465
|
-
|
|
27466
|
-
|
|
27467
|
-
|
|
27468
|
-
|
|
27469
|
-
|
|
27470
|
-
}
|
|
27471
|
-
|
|
27472
|
-
|
|
27473
|
-
|
|
27474
|
-
|
|
27475
|
-
|
|
27476
|
-
|
|
27477
|
-
</head>
|
|
27478
|
-
|
|
27479
|
-
<body>
|
|
27480
|
-
<!-- Component documentation: https://genspectrum.github.io/dashboard-components/?path=${storyBookPath} -->
|
|
27481
|
-
${indentLines(componentCode, 2)}
|
|
27482
|
-
</body>
|
|
27483
|
-
</html>
|
|
27484
|
-
`;
|
|
27485
|
-
}
|
|
27486
|
-
function indentLines(text, numberSpaces) {
|
|
27487
|
-
const spaces = " ".repeat(numberSpaces);
|
|
27488
|
-
return text.split("\n").map((line) => spaces + line).join("\n");
|
|
27780
|
+
function useQuery(fetchDataCallback, dependencies) {
|
|
27781
|
+
const [data, setData] = h$1(null);
|
|
27782
|
+
const [error, setError] = h$1(null);
|
|
27783
|
+
const [isLoading, setIsLoading] = h$1(true);
|
|
27784
|
+
y$1(() => {
|
|
27785
|
+
const fetchData = async () => {
|
|
27786
|
+
setIsLoading(true);
|
|
27787
|
+
try {
|
|
27788
|
+
const result = await fetchDataCallback();
|
|
27789
|
+
setData(result);
|
|
27790
|
+
setError(null);
|
|
27791
|
+
} catch (error2) {
|
|
27792
|
+
setError(error2);
|
|
27793
|
+
} finally {
|
|
27794
|
+
setIsLoading(false);
|
|
27795
|
+
}
|
|
27796
|
+
};
|
|
27797
|
+
fetchData();
|
|
27798
|
+
}, [JSON.stringify(dependencies)]);
|
|
27799
|
+
return { data, error, isLoading };
|
|
27489
27800
|
}
|
|
27490
|
-
const
|
|
27491
|
-
|
|
27801
|
+
const MutationComparison = ({ width, height, ...innerProps }) => {
|
|
27802
|
+
const size = { height, width };
|
|
27803
|
+
return /* @__PURE__ */ u$2(ErrorBoundary, { size, children: /* @__PURE__ */ u$2(ResizeContainer, { size, children: /* @__PURE__ */ u$2(MutationComparisonInner, { ...innerProps }) }) });
|
|
27492
27804
|
};
|
|
27493
|
-
const
|
|
27494
|
-
|
|
27495
|
-
|
|
27805
|
+
const MutationComparisonInner = ({
|
|
27806
|
+
lapisFilters,
|
|
27807
|
+
sequenceType,
|
|
27808
|
+
views,
|
|
27809
|
+
pageSize
|
|
27496
27810
|
}) => {
|
|
27497
|
-
const
|
|
27498
|
-
const
|
|
27811
|
+
const lapis = x$1(LapisUrlContext);
|
|
27812
|
+
const { data, error, isLoading } = useQuery(async () => {
|
|
27813
|
+
return queryMutationData(lapisFilters, sequenceType, lapis);
|
|
27814
|
+
}, [lapisFilters, sequenceType, lapis]);
|
|
27815
|
+
if (isLoading) {
|
|
27816
|
+
return /* @__PURE__ */ u$2(LoadingDisplay, {});
|
|
27817
|
+
}
|
|
27818
|
+
if (error !== null) {
|
|
27819
|
+
return /* @__PURE__ */ u$2(ErrorDisplay, { error });
|
|
27820
|
+
}
|
|
27821
|
+
if (data === null) {
|
|
27822
|
+
return /* @__PURE__ */ u$2(NoDataDisplay, {});
|
|
27823
|
+
}
|
|
27499
27824
|
return /* @__PURE__ */ u$2(
|
|
27500
|
-
|
|
27501
|
-
{
|
|
27502
|
-
items: displayedMutationTypes,
|
|
27503
|
-
label: mutationTypesSelectorLabel,
|
|
27504
|
-
setItems: (items) => setDisplayedMutationTypes(items)
|
|
27505
|
-
}
|
|
27506
|
-
);
|
|
27507
|
-
};
|
|
27508
|
-
const NoDataDisplay = () => {
|
|
27509
|
-
return /* @__PURE__ */ u$2("div", { className: "h-full w-full rounded-md border-2 border-gray-100 p-2 flex items-center justify-center", children: /* @__PURE__ */ u$2("div", { children: "No data available." }) });
|
|
27510
|
-
};
|
|
27511
|
-
const MinMaxRangeSlider = ({
|
|
27512
|
-
min: min2,
|
|
27513
|
-
max: max2,
|
|
27514
|
-
setMin,
|
|
27515
|
-
setMax,
|
|
27516
|
-
rangeMin = 0,
|
|
27517
|
-
rangeMax = 100,
|
|
27518
|
-
step = 0.1
|
|
27519
|
-
}) => {
|
|
27520
|
-
const sliderColor = "#C6C6C6";
|
|
27521
|
-
const rangeColor = "#387bbe";
|
|
27522
|
-
const [zIndexTo, setZIndexTo] = h$1(0);
|
|
27523
|
-
const onMinChange = (event) => {
|
|
27524
|
-
const input = event.target;
|
|
27525
|
-
const minValue = Number(input.value);
|
|
27526
|
-
if (minValue > max2) {
|
|
27527
|
-
setMax(minValue);
|
|
27528
|
-
setMin(minValue);
|
|
27529
|
-
} else {
|
|
27530
|
-
setMin(minValue);
|
|
27531
|
-
}
|
|
27532
|
-
};
|
|
27533
|
-
const onMaxChange = (event) => {
|
|
27534
|
-
const input = event.target;
|
|
27535
|
-
const maxValue = Number(input.value);
|
|
27536
|
-
if (maxValue <= 0) {
|
|
27537
|
-
setZIndexTo(2);
|
|
27538
|
-
} else {
|
|
27539
|
-
setZIndexTo(0);
|
|
27540
|
-
}
|
|
27541
|
-
if (maxValue < min2) {
|
|
27542
|
-
setMin(maxValue);
|
|
27543
|
-
setMax(maxValue);
|
|
27544
|
-
} else {
|
|
27545
|
-
setMax(maxValue);
|
|
27546
|
-
}
|
|
27547
|
-
};
|
|
27548
|
-
const background = `
|
|
27549
|
-
linear-gradient(
|
|
27550
|
-
to right,
|
|
27551
|
-
${sliderColor} 0%,
|
|
27552
|
-
${sliderColor} ${min2}%,
|
|
27553
|
-
${rangeColor} ${min2}%,
|
|
27554
|
-
${rangeColor} ${max2}%,
|
|
27555
|
-
${sliderColor} ${max2}%,
|
|
27556
|
-
${sliderColor} 100%)
|
|
27557
|
-
`;
|
|
27558
|
-
return /* @__PURE__ */ u$2("div", { class: "my-4 relative w-full h-full", children: [
|
|
27559
|
-
/* @__PURE__ */ u$2(
|
|
27560
|
-
"input",
|
|
27561
|
-
{
|
|
27562
|
-
id: "fromSlider",
|
|
27563
|
-
type: "range",
|
|
27564
|
-
value: min2,
|
|
27565
|
-
onInput: onMinChange,
|
|
27566
|
-
min: rangeMin,
|
|
27567
|
-
max: rangeMax,
|
|
27568
|
-
step,
|
|
27569
|
-
style: { background, zIndex: 1, height: 0 }
|
|
27570
|
-
}
|
|
27571
|
-
),
|
|
27572
|
-
/* @__PURE__ */ u$2(
|
|
27573
|
-
"input",
|
|
27574
|
-
{
|
|
27575
|
-
id: "toSlider",
|
|
27576
|
-
type: "range",
|
|
27577
|
-
value: max2,
|
|
27578
|
-
min: rangeMin,
|
|
27579
|
-
max: rangeMax,
|
|
27580
|
-
step,
|
|
27581
|
-
onInput: onMaxChange,
|
|
27582
|
-
style: { background, zIndex: zIndexTo }
|
|
27583
|
-
}
|
|
27584
|
-
)
|
|
27585
|
-
] });
|
|
27586
|
-
};
|
|
27587
|
-
const percentageInRange = (percentage) => {
|
|
27588
|
-
return percentage <= 100 && percentage >= 0;
|
|
27589
|
-
};
|
|
27590
|
-
const PercentInput = ({ percentage, setPercentage }) => {
|
|
27591
|
-
const [internalPercentage, setInternalPercentage] = h$1(percentage);
|
|
27592
|
-
y$1(() => {
|
|
27593
|
-
setInternalPercentage(percentage);
|
|
27594
|
-
}, [percentage]);
|
|
27595
|
-
const handleInputChange = (event) => {
|
|
27596
|
-
const input = event.target;
|
|
27597
|
-
const value = Number(input.value);
|
|
27598
|
-
const inRange2 = percentageInRange(value);
|
|
27599
|
-
if (inRange2) {
|
|
27600
|
-
setPercentage(value);
|
|
27601
|
-
}
|
|
27602
|
-
setInternalPercentage(value);
|
|
27603
|
-
};
|
|
27604
|
-
const isError = !percentageInRange(internalPercentage);
|
|
27605
|
-
return /* @__PURE__ */ u$2("label", { className: `input input-bordered flex items-center gap-2 w-32 ${isError ? "input-error" : ""}`, children: [
|
|
27606
|
-
/* @__PURE__ */ u$2(
|
|
27607
|
-
"input",
|
|
27608
|
-
{
|
|
27609
|
-
type: "number",
|
|
27610
|
-
step: 0.1,
|
|
27611
|
-
min: 0,
|
|
27612
|
-
max: 100,
|
|
27613
|
-
value: internalPercentage,
|
|
27614
|
-
onInput: handleInputChange,
|
|
27615
|
-
lang: "en",
|
|
27616
|
-
className: `grow w-16`
|
|
27617
|
-
}
|
|
27618
|
-
),
|
|
27619
|
-
"%"
|
|
27620
|
-
] });
|
|
27621
|
-
};
|
|
27622
|
-
const ProportionSelector = ({
|
|
27623
|
-
proportionInterval,
|
|
27624
|
-
setMinProportion,
|
|
27625
|
-
setMaxProportion
|
|
27626
|
-
}) => {
|
|
27627
|
-
const { min: minProportion, max: maxProportion } = proportionInterval;
|
|
27628
|
-
return /* @__PURE__ */ u$2("div", { class: "flex flex-col w-64 mb-2", children: [
|
|
27629
|
-
/* @__PURE__ */ u$2("div", { class: "flex items-center ", children: [
|
|
27630
|
-
/* @__PURE__ */ u$2(
|
|
27631
|
-
PercentInput,
|
|
27632
|
-
{
|
|
27633
|
-
percentage: minProportion * 100,
|
|
27634
|
-
setPercentage: (percentage) => setMinProportion(percentage / 100)
|
|
27635
|
-
}
|
|
27636
|
-
),
|
|
27637
|
-
/* @__PURE__ */ u$2("div", { class: "m-2", children: "-" }),
|
|
27638
|
-
/* @__PURE__ */ u$2(
|
|
27639
|
-
PercentInput,
|
|
27640
|
-
{
|
|
27641
|
-
percentage: maxProportion * 100,
|
|
27642
|
-
setPercentage: (percentage) => setMaxProportion(percentage / 100)
|
|
27643
|
-
}
|
|
27644
|
-
)
|
|
27645
|
-
] }),
|
|
27646
|
-
/* @__PURE__ */ u$2("div", { class: "my-1", children: /* @__PURE__ */ u$2(
|
|
27647
|
-
MinMaxRangeSlider,
|
|
27648
|
-
{
|
|
27649
|
-
min: minProportion * 100,
|
|
27650
|
-
max: maxProportion * 100,
|
|
27651
|
-
setMin: (percentage) => setMinProportion(percentage / 100),
|
|
27652
|
-
setMax: (percentage) => setMaxProportion(percentage / 100)
|
|
27653
|
-
}
|
|
27654
|
-
) })
|
|
27655
|
-
] });
|
|
27656
|
-
};
|
|
27657
|
-
const ProportionSelectorDropdown = ({
|
|
27658
|
-
proportionInterval,
|
|
27659
|
-
setMinProportion,
|
|
27660
|
-
setMaxProportion
|
|
27661
|
-
}) => {
|
|
27662
|
-
const label = `${(proportionInterval.min * 100).toFixed(1)}% - ${(proportionInterval.max * 100).toFixed(1)}%`;
|
|
27663
|
-
return /* @__PURE__ */ u$2(Dropdown, { buttonTitle: `Proportion ${label}`, placement: "bottom-start", children: /* @__PURE__ */ u$2(
|
|
27664
|
-
ProportionSelector,
|
|
27665
|
-
{
|
|
27666
|
-
proportionInterval,
|
|
27667
|
-
setMinProportion,
|
|
27668
|
-
setMaxProportion
|
|
27669
|
-
}
|
|
27670
|
-
) });
|
|
27671
|
-
};
|
|
27672
|
-
const Tabs = ({ tabs, toolbar }) => {
|
|
27673
|
-
const [activeTab, setActiveTab] = h$1(tabs[0].title);
|
|
27674
|
-
const [heightOfTabs, setHeightOfTabs] = h$1("3rem");
|
|
27675
|
-
const tabRef = A$1(null);
|
|
27676
|
-
const updateHeightOfTabs = () => {
|
|
27677
|
-
if (tabRef.current) {
|
|
27678
|
-
const heightOfTabs2 = tabRef.current.getBoundingClientRect().height;
|
|
27679
|
-
setHeightOfTabs(`${heightOfTabs2}px`);
|
|
27680
|
-
}
|
|
27681
|
-
};
|
|
27682
|
-
y$1(() => {
|
|
27683
|
-
updateHeightOfTabs();
|
|
27684
|
-
window.addEventListener("resize", updateHeightOfTabs);
|
|
27685
|
-
return () => {
|
|
27686
|
-
window.removeEventListener("resize", updateHeightOfTabs);
|
|
27687
|
-
};
|
|
27688
|
-
}, []);
|
|
27689
|
-
const tabElements = /* @__PURE__ */ u$2("div", { className: "flex flex-row", children: tabs.map((tab) => {
|
|
27690
|
-
return /* @__PURE__ */ u$2(k$1, { children: /* @__PURE__ */ u$2(
|
|
27691
|
-
"button",
|
|
27692
|
-
{
|
|
27693
|
-
className: `px-4 py-2 text-sm font-medium leading-5 transition-colors duration-150 ${activeTab === tab.title ? "border-b-2 border-gray-400" : "text-gray-600 hover:bg-gray-100 hover:text-gray-700"}`,
|
|
27694
|
-
onClick: () => {
|
|
27695
|
-
setActiveTab(tab.title);
|
|
27696
|
-
},
|
|
27697
|
-
children: tab.title
|
|
27698
|
-
}
|
|
27699
|
-
) }, tab.title);
|
|
27700
|
-
}) });
|
|
27701
|
-
const toolbarElement = typeof toolbar === "function" ? toolbar(activeTab) : toolbar;
|
|
27702
|
-
return /* @__PURE__ */ u$2("div", { className: "h-full w-full", children: [
|
|
27703
|
-
/* @__PURE__ */ u$2("div", { ref: tabRef, className: "flex flex-row justify-between flex-wrap", children: [
|
|
27704
|
-
tabElements,
|
|
27705
|
-
toolbar && /* @__PURE__ */ u$2("div", { className: "py-2 flex flex-wrap gap-y-1", children: toolbarElement })
|
|
27706
|
-
] }),
|
|
27707
|
-
/* @__PURE__ */ u$2(
|
|
27708
|
-
"div",
|
|
27709
|
-
{
|
|
27710
|
-
className: `p-2 border-2 border-gray-100 rounded-b-md rounded-tr-md ${activeTab === tabs[0].title ? "" : "rounded-tl-md"}`,
|
|
27711
|
-
style: { height: `calc(100% - ${heightOfTabs})` },
|
|
27712
|
-
children: tabs.map((tab) => /* @__PURE__ */ u$2("div", { className: "h-full overflow-auto", hidden: activeTab !== tab.title, children: tab.content }, tab.title))
|
|
27713
|
-
}
|
|
27714
|
-
)
|
|
27715
|
-
] });
|
|
27716
|
-
};
|
|
27717
|
-
function useQuery(fetchDataCallback, dependencies = []) {
|
|
27718
|
-
const [data, setData] = h$1(null);
|
|
27719
|
-
const [error, setError] = h$1(null);
|
|
27720
|
-
const [isLoading, setIsLoading] = h$1(true);
|
|
27721
|
-
y$1(() => {
|
|
27722
|
-
const fetchData = async () => {
|
|
27723
|
-
setIsLoading(true);
|
|
27724
|
-
try {
|
|
27725
|
-
const result = await fetchDataCallback();
|
|
27726
|
-
setData(result);
|
|
27727
|
-
setError(null);
|
|
27728
|
-
} catch (error2) {
|
|
27729
|
-
setError(error2);
|
|
27730
|
-
} finally {
|
|
27731
|
-
setIsLoading(false);
|
|
27732
|
-
}
|
|
27733
|
-
};
|
|
27734
|
-
fetchData();
|
|
27735
|
-
}, [JSON.stringify(dependencies)]);
|
|
27736
|
-
return { data, error, isLoading };
|
|
27737
|
-
}
|
|
27738
|
-
const MutationComparison = ({ width, height, ...innerProps }) => {
|
|
27739
|
-
const size = { height, width };
|
|
27740
|
-
return /* @__PURE__ */ u$2(ErrorBoundary, { size, children: /* @__PURE__ */ u$2(ResizeContainer, { size, children: /* @__PURE__ */ u$2(MutationComparisonInner, { ...innerProps }) }) });
|
|
27741
|
-
};
|
|
27742
|
-
const MutationComparisonInner = ({
|
|
27743
|
-
lapisFilters,
|
|
27744
|
-
sequenceType,
|
|
27745
|
-
views,
|
|
27746
|
-
pageSize
|
|
27747
|
-
}) => {
|
|
27748
|
-
const lapis = x$1(LapisUrlContext);
|
|
27749
|
-
const { data, error, isLoading } = useQuery(async () => {
|
|
27750
|
-
return queryMutationData(lapisFilters, sequenceType, lapis);
|
|
27751
|
-
}, [lapisFilters, sequenceType, lapis]);
|
|
27752
|
-
if (isLoading) {
|
|
27753
|
-
return /* @__PURE__ */ u$2(LoadingDisplay, {});
|
|
27754
|
-
}
|
|
27755
|
-
if (error !== null) {
|
|
27756
|
-
return /* @__PURE__ */ u$2(ErrorDisplay, { error });
|
|
27757
|
-
}
|
|
27758
|
-
if (data === null) {
|
|
27759
|
-
return /* @__PURE__ */ u$2(NoDataDisplay, {});
|
|
27760
|
-
}
|
|
27761
|
-
return /* @__PURE__ */ u$2(
|
|
27762
|
-
MutationComparisonTabs,
|
|
27825
|
+
MutationComparisonTabs,
|
|
27763
27826
|
{
|
|
27764
27827
|
data: data.mutationData,
|
|
27765
27828
|
sequenceType,
|
|
@@ -28479,19 +28542,52 @@ html {
|
|
|
28479
28542
|
--tw-contain-paint: ;
|
|
28480
28543
|
--tw-contain-style: ;
|
|
28481
28544
|
}
|
|
28482
|
-
.
|
|
28483
|
-
display: grid;
|
|
28545
|
+
.container {
|
|
28484
28546
|
width: 100%;
|
|
28485
|
-
|
|
28486
|
-
|
|
28487
|
-
|
|
28488
|
-
|
|
28489
|
-
|
|
28490
|
-
|
|
28491
|
-
|
|
28492
|
-
|
|
28493
|
-
|
|
28494
|
-
|
|
28547
|
+
}
|
|
28548
|
+
@media (min-width: 640px) {
|
|
28549
|
+
|
|
28550
|
+
.container {
|
|
28551
|
+
max-width: 640px;
|
|
28552
|
+
}
|
|
28553
|
+
}
|
|
28554
|
+
@media (min-width: 768px) {
|
|
28555
|
+
|
|
28556
|
+
.container {
|
|
28557
|
+
max-width: 768px;
|
|
28558
|
+
}
|
|
28559
|
+
}
|
|
28560
|
+
@media (min-width: 1024px) {
|
|
28561
|
+
|
|
28562
|
+
.container {
|
|
28563
|
+
max-width: 1024px;
|
|
28564
|
+
}
|
|
28565
|
+
}
|
|
28566
|
+
@media (min-width: 1280px) {
|
|
28567
|
+
|
|
28568
|
+
.container {
|
|
28569
|
+
max-width: 1280px;
|
|
28570
|
+
}
|
|
28571
|
+
}
|
|
28572
|
+
@media (min-width: 1536px) {
|
|
28573
|
+
|
|
28574
|
+
.container {
|
|
28575
|
+
max-width: 1536px;
|
|
28576
|
+
}
|
|
28577
|
+
}
|
|
28578
|
+
.alert {
|
|
28579
|
+
display: grid;
|
|
28580
|
+
width: 100%;
|
|
28581
|
+
grid-auto-flow: row;
|
|
28582
|
+
align-content: flex-start;
|
|
28583
|
+
align-items: center;
|
|
28584
|
+
justify-items: center;
|
|
28585
|
+
gap: 1rem;
|
|
28586
|
+
text-align: center;
|
|
28587
|
+
border-radius: var(--rounded-box, 1rem);
|
|
28588
|
+
border-width: 1px;
|
|
28589
|
+
--tw-border-opacity: 1;
|
|
28590
|
+
border-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity)));
|
|
28495
28591
|
padding: 1rem;
|
|
28496
28592
|
--tw-text-opacity: 1;
|
|
28497
28593
|
color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));
|
|
@@ -28520,6 +28616,15 @@ html {
|
|
|
28520
28616
|
color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));
|
|
28521
28617
|
}
|
|
28522
28618
|
|
|
28619
|
+
.menu li > *:not(ul, .menu-title, details, .btn):active,
|
|
28620
|
+
.menu li > *:not(ul, .menu-title, details, .btn).active,
|
|
28621
|
+
.menu li > details > summary:active {
|
|
28622
|
+
--tw-bg-opacity: 1;
|
|
28623
|
+
background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));
|
|
28624
|
+
--tw-text-opacity: 1;
|
|
28625
|
+
color: var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity)));
|
|
28626
|
+
}
|
|
28627
|
+
|
|
28523
28628
|
.tab:hover {
|
|
28524
28629
|
--tw-text-opacity: 1;
|
|
28525
28630
|
}
|
|
@@ -28613,6 +28718,25 @@ html {
|
|
|
28613
28718
|
container-type: inline-size;
|
|
28614
28719
|
grid-template-columns: auto 1fr;
|
|
28615
28720
|
}
|
|
28721
|
+
.divider {
|
|
28722
|
+
display: flex;
|
|
28723
|
+
flex-direction: row;
|
|
28724
|
+
align-items: center;
|
|
28725
|
+
align-self: stretch;
|
|
28726
|
+
margin-top: 1rem;
|
|
28727
|
+
margin-bottom: 1rem;
|
|
28728
|
+
height: 1rem;
|
|
28729
|
+
white-space: nowrap;
|
|
28730
|
+
}
|
|
28731
|
+
.divider:before,
|
|
28732
|
+
.divider:after {
|
|
28733
|
+
height: 0.125rem;
|
|
28734
|
+
width: 100%;
|
|
28735
|
+
flex-grow: 1;
|
|
28736
|
+
--tw-content: '';
|
|
28737
|
+
content: var(--tw-content);
|
|
28738
|
+
background-color: var(--fallback-bc,oklch(var(--bc)/0.1));
|
|
28739
|
+
}
|
|
28616
28740
|
.dropdown {
|
|
28617
28741
|
position: relative;
|
|
28618
28742
|
display: inline-block;
|
|
@@ -29129,6 +29253,11 @@ input.tab:checked + .tab-content,
|
|
|
29129
29253
|
--alert-bg: var(--fallback-er,oklch(var(--er)/1));
|
|
29130
29254
|
--alert-bg-mix: var(--fallback-b1,oklch(var(--b1)/1));
|
|
29131
29255
|
}
|
|
29256
|
+
.btm-nav > *:where(.active) {
|
|
29257
|
+
border-top-width: 2px;
|
|
29258
|
+
--tw-bg-opacity: 1;
|
|
29259
|
+
background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)));
|
|
29260
|
+
}
|
|
29132
29261
|
.btm-nav > *.disabled,
|
|
29133
29262
|
.btm-nav > *[disabled] {
|
|
29134
29263
|
pointer-events: none;
|
|
@@ -29281,6 +29410,9 @@ input.tab:checked + .tab-content,
|
|
|
29281
29410
|
background-position-y: 0;
|
|
29282
29411
|
}
|
|
29283
29412
|
}
|
|
29413
|
+
.divider:not(:empty) {
|
|
29414
|
+
gap: 1rem;
|
|
29415
|
+
}
|
|
29284
29416
|
.dropdown.dropdown-open .dropdown-content,
|
|
29285
29417
|
.dropdown:focus .dropdown-content,
|
|
29286
29418
|
.dropdown:focus-within .dropdown-content {
|
|
@@ -29396,6 +29528,14 @@ input.tab:checked + .tab-content,
|
|
|
29396
29528
|
outline: 2px solid transparent;
|
|
29397
29529
|
outline-offset: 2px;
|
|
29398
29530
|
}
|
|
29531
|
+
.menu li > *:not(ul, .menu-title, details, .btn):active,
|
|
29532
|
+
.menu li > *:not(ul, .menu-title, details, .btn).active,
|
|
29533
|
+
.menu li > details > summary:active {
|
|
29534
|
+
--tw-bg-opacity: 1;
|
|
29535
|
+
background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));
|
|
29536
|
+
--tw-text-opacity: 1;
|
|
29537
|
+
color: var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity)));
|
|
29538
|
+
}
|
|
29399
29539
|
.mockup-phone .display {
|
|
29400
29540
|
overflow: hidden;
|
|
29401
29541
|
border-radius: 40px;
|
|
@@ -29892,6 +30032,12 @@ input.tab:checked + .tab-content,
|
|
|
29892
30032
|
--tw-bg-opacity: 1;
|
|
29893
30033
|
background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)));
|
|
29894
30034
|
}
|
|
30035
|
+
.table-zebra tr.active,
|
|
30036
|
+
.table-zebra tr.active:nth-child(even),
|
|
30037
|
+
.table-zebra-zebra tbody tr:nth-child(even) {
|
|
30038
|
+
--tw-bg-opacity: 1;
|
|
30039
|
+
background-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity)));
|
|
30040
|
+
}
|
|
29895
30041
|
.table :where(thead tr, tbody tr:not(:last-child), tbody tr:first-child:last-child) {
|
|
29896
30042
|
border-bottom-width: 1px;
|
|
29897
30043
|
--tw-border-opacity: 1;
|
|
@@ -29964,6 +30110,18 @@ input.tab:checked + .tab-content,
|
|
|
29964
30110
|
--togglehandleborder: 0 0 0 3px var(--fallback-bc,oklch(var(--bc)/1)) inset,
|
|
29965
30111
|
var(--handleoffsetcalculator) 0 0 3px var(--fallback-bc,oklch(var(--bc)/1)) inset;
|
|
29966
30112
|
}
|
|
30113
|
+
.btm-nav-xs > *:where(.active) {
|
|
30114
|
+
border-top-width: 1px;
|
|
30115
|
+
}
|
|
30116
|
+
.btm-nav-sm > *:where(.active) {
|
|
30117
|
+
border-top-width: 2px;
|
|
30118
|
+
}
|
|
30119
|
+
.btm-nav-md > *:where(.active) {
|
|
30120
|
+
border-top-width: 2px;
|
|
30121
|
+
}
|
|
30122
|
+
.btm-nav-lg > *:where(.active) {
|
|
30123
|
+
border-top-width: 4px;
|
|
30124
|
+
}
|
|
29967
30125
|
.btn-xs {
|
|
29968
30126
|
height: 1.5rem;
|
|
29969
30127
|
min-height: 1.5rem;
|
|
@@ -30383,6 +30541,9 @@ input.tab:checked + .tab-content,
|
|
|
30383
30541
|
margin-top: 1rem;
|
|
30384
30542
|
margin-bottom: 1rem;
|
|
30385
30543
|
}
|
|
30544
|
+
.mb-0 {
|
|
30545
|
+
margin-bottom: 0px;
|
|
30546
|
+
}
|
|
30386
30547
|
.mb-1 {
|
|
30387
30548
|
margin-bottom: 0.25rem;
|
|
30388
30549
|
}
|
|
@@ -30407,6 +30568,9 @@ input.tab:checked + .tab-content,
|
|
|
30407
30568
|
.mr-2 {
|
|
30408
30569
|
margin-right: 0.5rem;
|
|
30409
30570
|
}
|
|
30571
|
+
.mt-0 {
|
|
30572
|
+
margin-top: 0px;
|
|
30573
|
+
}
|
|
30410
30574
|
.mt-0\\.5 {
|
|
30411
30575
|
margin-top: 0.125rem;
|
|
30412
30576
|
}
|
|
@@ -30446,12 +30610,24 @@ input.tab:checked + .tab-content,
|
|
|
30446
30610
|
.w-16 {
|
|
30447
30611
|
width: 4rem;
|
|
30448
30612
|
}
|
|
30613
|
+
.w-20 {
|
|
30614
|
+
width: 5rem;
|
|
30615
|
+
}
|
|
30616
|
+
.w-24 {
|
|
30617
|
+
width: 6rem;
|
|
30618
|
+
}
|
|
30449
30619
|
.w-32 {
|
|
30450
30620
|
width: 8rem;
|
|
30451
30621
|
}
|
|
30622
|
+
.w-44 {
|
|
30623
|
+
width: 11rem;
|
|
30624
|
+
}
|
|
30452
30625
|
.w-64 {
|
|
30453
30626
|
width: 16rem;
|
|
30454
30627
|
}
|
|
30628
|
+
.w-\\[6rem\\] {
|
|
30629
|
+
width: 6rem;
|
|
30630
|
+
}
|
|
30455
30631
|
.w-\\[7\\.5rem\\] {
|
|
30456
30632
|
width: 7.5rem;
|
|
30457
30633
|
}
|
|
@@ -31041,7 +31217,10 @@ const MutationsGrid = ({
|
|
|
31041
31217
|
}
|
|
31042
31218
|
return {};
|
|
31043
31219
|
};
|
|
31044
|
-
const tableData =
|
|
31220
|
+
const tableData = T$1(
|
|
31221
|
+
() => getMutationsGridData(data, sequenceType, proportionInterval).map((row) => Object.values(row)),
|
|
31222
|
+
[data, proportionInterval, sequenceType]
|
|
31223
|
+
);
|
|
31045
31224
|
return /* @__PURE__ */ u$2(Table, { data: tableData, columns: getHeaders(), pageSize });
|
|
31046
31225
|
};
|
|
31047
31226
|
const sortInsertions = (a2, b3) => {
|
|
@@ -34650,7 +34829,8 @@ const NumberSequencesOverTimeInner = ({
|
|
|
34650
34829
|
}) => {
|
|
34651
34830
|
const lapis = x$1(LapisUrlContext);
|
|
34652
34831
|
const { data, error, isLoading } = useQuery(
|
|
34653
|
-
() => queryNumberOfSequencesOverTime(lapis, lapisFilter, lapisDateField, granularity, smoothingWindow)
|
|
34832
|
+
() => queryNumberOfSequencesOverTime(lapis, lapisFilter, lapisDateField, granularity, smoothingWindow),
|
|
34833
|
+
[lapis, lapisFilter, lapisDateField, granularity, smoothingWindow]
|
|
34654
34834
|
);
|
|
34655
34835
|
if (isLoading) {
|
|
34656
34836
|
return /* @__PURE__ */ u$2(LoadingDisplay, {});
|
|
@@ -34825,308 +35005,43 @@ __decorateClass$6([
|
|
|
34825
35005
|
NumberSequencesOverTimeComponent = __decorateClass$6([
|
|
34826
35006
|
t$2("gs-number-sequences-over-time")
|
|
34827
35007
|
], NumberSequencesOverTimeComponent);
|
|
34828
|
-
function
|
|
34829
|
-
|
|
34830
|
-
filterDisplayedSegments(displayedSegments, filteredData);
|
|
34831
|
-
filterMutationTypes(displayedMutationTypes, filteredData);
|
|
34832
|
-
filterProportion(filteredData, overallMutationData, proportionInterval);
|
|
34833
|
-
return filteredData;
|
|
35008
|
+
function getDefaultExportFromCjs(x2) {
|
|
35009
|
+
return x2 && x2.__esModule && Object.prototype.hasOwnProperty.call(x2, "default") ? x2["default"] : x2;
|
|
34834
35010
|
}
|
|
34835
|
-
function
|
|
34836
|
-
|
|
34837
|
-
if (!segment.checked) {
|
|
34838
|
-
data.getFirstAxisKeys().forEach((mutation) => {
|
|
34839
|
-
if (mutation.segment === segment.segment) {
|
|
34840
|
-
data.deleteRow(mutation);
|
|
34841
|
-
}
|
|
34842
|
-
});
|
|
34843
|
-
}
|
|
34844
|
-
});
|
|
35011
|
+
function commonjsRequire(path) {
|
|
35012
|
+
throw new Error('Could not dynamically require "' + path + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.');
|
|
34845
35013
|
}
|
|
34846
|
-
|
|
34847
|
-
|
|
34848
|
-
|
|
34849
|
-
|
|
34850
|
-
|
|
34851
|
-
|
|
35014
|
+
var object_hash = { exports: {} };
|
|
35015
|
+
(function(module, exports) {
|
|
35016
|
+
!function(e3) {
|
|
35017
|
+
module.exports = e3();
|
|
35018
|
+
}(function() {
|
|
35019
|
+
return function r2(o2, i3, u2) {
|
|
35020
|
+
function s6(n3, e4) {
|
|
35021
|
+
if (!i3[n3]) {
|
|
35022
|
+
if (!o2[n3]) {
|
|
35023
|
+
var t2 = "function" == typeof commonjsRequire && commonjsRequire;
|
|
35024
|
+
if (!e4 && t2) return t2(n3, true);
|
|
35025
|
+
if (a2) return a2(n3, true);
|
|
35026
|
+
throw new Error("Cannot find module '" + n3 + "'");
|
|
35027
|
+
}
|
|
35028
|
+
e4 = i3[n3] = { exports: {} };
|
|
35029
|
+
o2[n3][0].call(e4.exports, function(e5) {
|
|
35030
|
+
var t3 = o2[n3][1][e5];
|
|
35031
|
+
return s6(t3 || e5);
|
|
35032
|
+
}, e4, e4.exports, r2, o2, i3, u2);
|
|
34852
35033
|
}
|
|
34853
|
-
|
|
34854
|
-
}
|
|
34855
|
-
});
|
|
34856
|
-
}
|
|
34857
|
-
function filterProportion(data, overallMutationData, proportionInterval) {
|
|
34858
|
-
const overallProportionsByMutation = overallMutationData.content.reduce(
|
|
34859
|
-
(acc, { mutation, proportion }) => ({
|
|
34860
|
-
...acc,
|
|
34861
|
-
[mutation.toString()]: proportion
|
|
34862
|
-
}),
|
|
34863
|
-
{}
|
|
34864
|
-
);
|
|
34865
|
-
data.getFirstAxisKeys().forEach((mutation) => {
|
|
34866
|
-
const overallProportion = overallProportionsByMutation[mutation.toString()] || -1;
|
|
34867
|
-
if (overallProportion < proportionInterval.min || overallProportion > proportionInterval.max) {
|
|
34868
|
-
data.deleteRow(mutation);
|
|
34869
|
-
}
|
|
34870
|
-
});
|
|
34871
|
-
}
|
|
34872
|
-
const ColorScaleSelector = ({ colorScale, setColorScale }) => {
|
|
34873
|
-
const colorDisplayCss = `w-10 h-8 border border-gray-200 mx-2 text-xs flex items-center justify-center`;
|
|
34874
|
-
return /* @__PURE__ */ u$2("div", { className: "flex items-center", children: [
|
|
34875
|
-
/* @__PURE__ */ u$2(
|
|
34876
|
-
"div",
|
|
34877
|
-
{
|
|
34878
|
-
style: {
|
|
34879
|
-
backgroundColor: singleGraphColorRGBByName(colorScale.color, 0),
|
|
34880
|
-
color: "black"
|
|
34881
|
-
},
|
|
34882
|
-
className: colorDisplayCss,
|
|
34883
|
-
children: formatProportion(colorScale.min, 0)
|
|
35034
|
+
return i3[n3].exports;
|
|
34884
35035
|
}
|
|
34885
|
-
|
|
34886
|
-
|
|
34887
|
-
|
|
34888
|
-
{
|
|
34889
|
-
|
|
34890
|
-
|
|
34891
|
-
|
|
34892
|
-
|
|
34893
|
-
|
|
34894
|
-
setMax: (percentage) => {
|
|
34895
|
-
setColorScale({ ...colorScale, max: percentage / 100 });
|
|
34896
|
-
}
|
|
34897
|
-
}
|
|
34898
|
-
) }),
|
|
34899
|
-
/* @__PURE__ */ u$2(
|
|
34900
|
-
"div",
|
|
34901
|
-
{
|
|
34902
|
-
style: {
|
|
34903
|
-
backgroundColor: singleGraphColorRGBByName(colorScale.color, 1),
|
|
34904
|
-
color: "white"
|
|
34905
|
-
},
|
|
34906
|
-
className: colorDisplayCss,
|
|
34907
|
-
children: formatProportion(colorScale.max, 0)
|
|
34908
|
-
}
|
|
34909
|
-
)
|
|
34910
|
-
] });
|
|
34911
|
-
};
|
|
34912
|
-
const getColorWithingScale = (value, colorScale) => {
|
|
34913
|
-
if (colorScale.min === colorScale.max) {
|
|
34914
|
-
return singleGraphColorRGBByName(colorScale.color, 0);
|
|
34915
|
-
}
|
|
34916
|
-
const colorRange = colorScale.max - colorScale.min;
|
|
34917
|
-
const alpha2 = (value - colorScale.min) / colorRange;
|
|
34918
|
-
return singleGraphColorRGBByName(colorScale.color, alpha2);
|
|
34919
|
-
};
|
|
34920
|
-
const getTextColorForScale = (value, colorScale) => {
|
|
34921
|
-
if (colorScale.min === colorScale.max) {
|
|
34922
|
-
return "black";
|
|
34923
|
-
}
|
|
34924
|
-
const colorRange = colorScale.max - colorScale.min;
|
|
34925
|
-
const alpha2 = (value - colorScale.min) / colorRange;
|
|
34926
|
-
return alpha2 <= 0.5 ? "black" : "white";
|
|
34927
|
-
};
|
|
34928
|
-
function getPositionCss(position) {
|
|
34929
|
-
switch (position) {
|
|
34930
|
-
case "top":
|
|
34931
|
-
return "bottom-full translate-x-[-50%] left-1/2 mb-1";
|
|
34932
|
-
case "top-start":
|
|
34933
|
-
return "bottom-full mr-1 mb-1";
|
|
34934
|
-
case "top-end":
|
|
34935
|
-
return "bottom-full right-0 ml-1 mb-1";
|
|
34936
|
-
case "bottom":
|
|
34937
|
-
return "top-full translate-x-[-50%] left-1/2 mt-1";
|
|
34938
|
-
case "bottom-start":
|
|
34939
|
-
return "mr-1 mt-1";
|
|
34940
|
-
case "bottom-end":
|
|
34941
|
-
return "right-0 ml-1 mt-1";
|
|
34942
|
-
case "left":
|
|
34943
|
-
return "right-full translate-y-[-50%] top-1/2 mr-1";
|
|
34944
|
-
case "right":
|
|
34945
|
-
return "left-full translate-y-[-50%] top-1/2 ml-1";
|
|
34946
|
-
case void 0:
|
|
34947
|
-
return "";
|
|
34948
|
-
}
|
|
34949
|
-
}
|
|
34950
|
-
const Tooltip = ({ children, content, position = "bottom" }) => {
|
|
34951
|
-
return /* @__PURE__ */ u$2("div", { className: "relative w-full h-full", children: [
|
|
34952
|
-
/* @__PURE__ */ u$2("div", { className: "peer w-full h-full", children }),
|
|
34953
|
-
/* @__PURE__ */ u$2(
|
|
34954
|
-
"div",
|
|
34955
|
-
{
|
|
34956
|
-
className: `absolute z-10 w-max bg-white p-4 border border-gray-200 rounded-md invisible peer-hover:visible ${getPositionCss(position)}`,
|
|
34957
|
-
children: content
|
|
34958
|
-
}
|
|
34959
|
-
)
|
|
34960
|
-
] });
|
|
34961
|
-
};
|
|
34962
|
-
const MAX_NUMBER_OF_GRID_ROWS = 100;
|
|
34963
|
-
const MUTATION_CELL_WIDTH_REM = 8;
|
|
34964
|
-
const MutationsOverTimeGrid = ({ data, colorScale }) => {
|
|
34965
|
-
const allMutations = data.getFirstAxisKeys().sort(sortSubstitutionsAndDeletions);
|
|
34966
|
-
const shownMutations = allMutations.slice(0, MAX_NUMBER_OF_GRID_ROWS);
|
|
34967
|
-
const dates = data.getSecondAxisKeys().sort((a2, b3) => compareTemporal(a2, b3));
|
|
34968
|
-
const [showProportionText, setShowProportionText] = h$1(false);
|
|
34969
|
-
const gridRef = A$1(null);
|
|
34970
|
-
useShowProportion(gridRef, dates.length, setShowProportionText);
|
|
34971
|
-
return /* @__PURE__ */ u$2(k$1, { children: [
|
|
34972
|
-
allMutations.length > MAX_NUMBER_OF_GRID_ROWS && /* @__PURE__ */ u$2("div", { className: "pl-2", children: [
|
|
34973
|
-
"Showing ",
|
|
34974
|
-
MAX_NUMBER_OF_GRID_ROWS,
|
|
34975
|
-
" of ",
|
|
34976
|
-
allMutations.length,
|
|
34977
|
-
" mutations. You can narrow the filter to reduce the number of mutations."
|
|
34978
|
-
] }),
|
|
34979
|
-
/* @__PURE__ */ u$2(
|
|
34980
|
-
"div",
|
|
34981
|
-
{
|
|
34982
|
-
ref: gridRef,
|
|
34983
|
-
style: {
|
|
34984
|
-
display: "grid",
|
|
34985
|
-
gridTemplateRows: `repeat(${shownMutations.length}, 24px)`,
|
|
34986
|
-
gridTemplateColumns: `${MUTATION_CELL_WIDTH_REM}rem repeat(${dates.length}, minmax(0.05rem, 1fr))`
|
|
34987
|
-
},
|
|
34988
|
-
children: shownMutations.map((mutation, rowIndex) => {
|
|
34989
|
-
return /* @__PURE__ */ u$2(k$1, { children: [
|
|
34990
|
-
/* @__PURE__ */ u$2(
|
|
34991
|
-
"div",
|
|
34992
|
-
{
|
|
34993
|
-
style: { gridRowStart: rowIndex + 1, gridColumnStart: 1 },
|
|
34994
|
-
children: /* @__PURE__ */ u$2(MutationCell, { mutation })
|
|
34995
|
-
},
|
|
34996
|
-
`mutation-${mutation.toString()}`
|
|
34997
|
-
),
|
|
34998
|
-
dates.map((date, columnIndex) => {
|
|
34999
|
-
const value = data.get(mutation, date) ?? { proportion: 0, count: 0 };
|
|
35000
|
-
const tooltipPosition = getTooltipPosition(
|
|
35001
|
-
rowIndex,
|
|
35002
|
-
shownMutations.length,
|
|
35003
|
-
columnIndex,
|
|
35004
|
-
dates.length
|
|
35005
|
-
);
|
|
35006
|
-
return /* @__PURE__ */ u$2(
|
|
35007
|
-
"div",
|
|
35008
|
-
{
|
|
35009
|
-
style: { gridRowStart: rowIndex + 1, gridColumnStart: columnIndex + 2 },
|
|
35010
|
-
children: /* @__PURE__ */ u$2(
|
|
35011
|
-
ProportionCell,
|
|
35012
|
-
{
|
|
35013
|
-
value,
|
|
35014
|
-
date,
|
|
35015
|
-
mutation,
|
|
35016
|
-
tooltipPosition,
|
|
35017
|
-
showProportionText,
|
|
35018
|
-
colorScale
|
|
35019
|
-
}
|
|
35020
|
-
)
|
|
35021
|
-
},
|
|
35022
|
-
`${mutation.toString()}-${date.toString()}`
|
|
35023
|
-
);
|
|
35024
|
-
})
|
|
35025
|
-
] }, `fragment-${mutation.toString()}`);
|
|
35026
|
-
})
|
|
35027
|
-
}
|
|
35028
|
-
)
|
|
35029
|
-
] });
|
|
35030
|
-
};
|
|
35031
|
-
function useShowProportion(gridRef, girdColumns, setShowProportionText) {
|
|
35032
|
-
y$1(() => {
|
|
35033
|
-
const checkWidth = () => {
|
|
35034
|
-
if (gridRef.current) {
|
|
35035
|
-
const width = gridRef.current.getBoundingClientRect().width;
|
|
35036
|
-
const widthPerDate = (width - remToPx(MUTATION_CELL_WIDTH_REM)) / girdColumns;
|
|
35037
|
-
const maxWidthProportionText = 28;
|
|
35038
|
-
setShowProportionText(widthPerDate > maxWidthProportionText);
|
|
35039
|
-
}
|
|
35040
|
-
};
|
|
35041
|
-
checkWidth();
|
|
35042
|
-
window.addEventListener("resize", checkWidth);
|
|
35043
|
-
return () => {
|
|
35044
|
-
window.removeEventListener("resize", checkWidth);
|
|
35045
|
-
};
|
|
35046
|
-
}, [girdColumns, gridRef, setShowProportionText]);
|
|
35047
|
-
}
|
|
35048
|
-
const remToPx = (rem) => rem * parseFloat(getComputedStyle(document.documentElement).fontSize);
|
|
35049
|
-
function getTooltipPosition(rowIndex, rows, columnIndex, columns) {
|
|
35050
|
-
const tooltipX = rowIndex < rows / 2 ? "bottom" : "top";
|
|
35051
|
-
const tooltipY = columnIndex < columns / 2 ? "start" : "end";
|
|
35052
|
-
return `${tooltipX}-${tooltipY}`;
|
|
35053
|
-
}
|
|
35054
|
-
const ProportionCell = ({ value, mutation, date, tooltipPosition, showProportionText, colorScale }) => {
|
|
35055
|
-
const tooltipContent = /* @__PURE__ */ u$2("div", { children: [
|
|
35056
|
-
/* @__PURE__ */ u$2("p", { children: /* @__PURE__ */ u$2("span", { className: "font-bold", children: date.englishName() }) }),
|
|
35057
|
-
/* @__PURE__ */ u$2("p", { children: [
|
|
35058
|
-
"(",
|
|
35059
|
-
timeIntervalDisplay(date),
|
|
35060
|
-
")"
|
|
35061
|
-
] }),
|
|
35062
|
-
/* @__PURE__ */ u$2("p", { children: mutation.code }),
|
|
35063
|
-
/* @__PURE__ */ u$2("p", { children: [
|
|
35064
|
-
"Proportion: ",
|
|
35065
|
-
formatProportion(value.proportion)
|
|
35066
|
-
] }),
|
|
35067
|
-
/* @__PURE__ */ u$2("p", { children: [
|
|
35068
|
-
"Count: ",
|
|
35069
|
-
value.count
|
|
35070
|
-
] })
|
|
35071
|
-
] });
|
|
35072
|
-
return /* @__PURE__ */ u$2("div", { className: "py-1 w-full h-full", children: /* @__PURE__ */ u$2(Tooltip, { content: tooltipContent, position: tooltipPosition, children: /* @__PURE__ */ u$2(
|
|
35073
|
-
"div",
|
|
35074
|
-
{
|
|
35075
|
-
style: {
|
|
35076
|
-
backgroundColor: getColorWithingScale(value.proportion, colorScale),
|
|
35077
|
-
color: getTextColorForScale(value.proportion, colorScale)
|
|
35078
|
-
},
|
|
35079
|
-
className: `w-full h-full text-center hover:font-bold text-xs group`,
|
|
35080
|
-
children: showProportionText ? formatProportion(value.proportion, 0) : void 0
|
|
35081
|
-
}
|
|
35082
|
-
) }) });
|
|
35083
|
-
};
|
|
35084
|
-
const timeIntervalDisplay = (date) => {
|
|
35085
|
-
if (date instanceof YearMonthDay) {
|
|
35086
|
-
return date.toString();
|
|
35087
|
-
}
|
|
35088
|
-
return `${date.firstDay.toString()} - ${date.lastDay.toString()}`;
|
|
35089
|
-
};
|
|
35090
|
-
const MutationCell = ({ mutation }) => {
|
|
35091
|
-
return /* @__PURE__ */ u$2("div", { className: "text-center", children: mutation.toString() });
|
|
35092
|
-
};
|
|
35093
|
-
function getDefaultExportFromCjs(x2) {
|
|
35094
|
-
return x2 && x2.__esModule && Object.prototype.hasOwnProperty.call(x2, "default") ? x2["default"] : x2;
|
|
35095
|
-
}
|
|
35096
|
-
function commonjsRequire(path) {
|
|
35097
|
-
throw new Error('Could not dynamically require "' + path + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.');
|
|
35098
|
-
}
|
|
35099
|
-
var object_hash = { exports: {} };
|
|
35100
|
-
(function(module, exports) {
|
|
35101
|
-
!function(e3) {
|
|
35102
|
-
module.exports = e3();
|
|
35103
|
-
}(function() {
|
|
35104
|
-
return function r2(o2, i3, u2) {
|
|
35105
|
-
function s6(n3, e4) {
|
|
35106
|
-
if (!i3[n3]) {
|
|
35107
|
-
if (!o2[n3]) {
|
|
35108
|
-
var t2 = "function" == typeof commonjsRequire && commonjsRequire;
|
|
35109
|
-
if (!e4 && t2) return t2(n3, true);
|
|
35110
|
-
if (a2) return a2(n3, true);
|
|
35111
|
-
throw new Error("Cannot find module '" + n3 + "'");
|
|
35112
|
-
}
|
|
35113
|
-
e4 = i3[n3] = { exports: {} };
|
|
35114
|
-
o2[n3][0].call(e4.exports, function(e5) {
|
|
35115
|
-
var t3 = o2[n3][1][e5];
|
|
35116
|
-
return s6(t3 || e5);
|
|
35117
|
-
}, e4, e4.exports, r2, o2, i3, u2);
|
|
35118
|
-
}
|
|
35119
|
-
return i3[n3].exports;
|
|
35120
|
-
}
|
|
35121
|
-
for (var a2 = "function" == typeof commonjsRequire && commonjsRequire, e3 = 0; e3 < u2.length; e3++) s6(u2[e3]);
|
|
35122
|
-
return s6;
|
|
35123
|
-
}({ 1: [function(w2, b3, m2) {
|
|
35124
|
-
!(function(e3, n3, s6, c2, d2, h3, p2, g2, y2) {
|
|
35125
|
-
var r2 = w2("crypto");
|
|
35126
|
-
function t2(e4, t3) {
|
|
35127
|
-
t3 = u2(e4, t3);
|
|
35128
|
-
var n4;
|
|
35129
|
-
return void 0 === (n4 = "passthrough" !== t3.algorithm ? r2.createHash(t3.algorithm) : new l2()).write && (n4.write = n4.update, n4.end = n4.update), f2(t3, n4).dispatch(e4), n4.update || n4.end(""), n4.digest ? n4.digest("buffer" === t3.encoding ? void 0 : t3.encoding) : (e4 = n4.read(), "buffer" !== t3.encoding ? e4.toString(t3.encoding) : e4);
|
|
35036
|
+
for (var a2 = "function" == typeof commonjsRequire && commonjsRequire, e3 = 0; e3 < u2.length; e3++) s6(u2[e3]);
|
|
35037
|
+
return s6;
|
|
35038
|
+
}({ 1: [function(w2, b3, m2) {
|
|
35039
|
+
!(function(e3, n3, s6, c2, d2, h3, p2, g2, y2) {
|
|
35040
|
+
var r2 = w2("crypto");
|
|
35041
|
+
function t2(e4, t3) {
|
|
35042
|
+
t3 = u2(e4, t3);
|
|
35043
|
+
var n4;
|
|
35044
|
+
return void 0 === (n4 = "passthrough" !== t3.algorithm ? r2.createHash(t3.algorithm) : new l2()).write && (n4.write = n4.update, n4.end = n4.update), f2(t3, n4).dispatch(e4), n4.update || n4.end(""), n4.digest ? n4.digest("buffer" === t3.encoding ? void 0 : t3.encoding) : (e4 = n4.read(), "buffer" !== t3.encoding ? e4.toString(t3.encoding) : e4);
|
|
35130
35045
|
}
|
|
35131
35046
|
(m2 = b3.exports = t2).sha1 = function(e4) {
|
|
35132
35047
|
return t2(e4);
|
|
@@ -35881,7 +35796,7 @@ var object_hash = { exports: {} };
|
|
|
35881
35796
|
})(object_hash);
|
|
35882
35797
|
var object_hashExports = object_hash.exports;
|
|
35883
35798
|
const hash = /* @__PURE__ */ getDefaultExportFromCjs(object_hashExports);
|
|
35884
|
-
class
|
|
35799
|
+
class Map2dBase {
|
|
35885
35800
|
constructor(serializeFirstAxis = (key) => typeof key === "string" ? key : hash(key), serializeSecondAxis = (key) => typeof key === "string" ? key : hash(key)) {
|
|
35886
35801
|
this.serializeFirstAxis = serializeFirstAxis;
|
|
35887
35802
|
this.serializeSecondAxis = serializeSecondAxis;
|
|
@@ -35931,18 +35846,322 @@ class Map2d {
|
|
|
35931
35846
|
});
|
|
35932
35847
|
});
|
|
35933
35848
|
}
|
|
35934
|
-
|
|
35935
|
-
|
|
35936
|
-
|
|
35937
|
-
|
|
35938
|
-
|
|
35939
|
-
|
|
35940
|
-
|
|
35849
|
+
}
|
|
35850
|
+
class Map2dView {
|
|
35851
|
+
constructor(map2) {
|
|
35852
|
+
this.keysFirstAxis = new Map(map2.keysFirstAxis);
|
|
35853
|
+
this.keysSecondAxis = new Map(map2.keysSecondAxis);
|
|
35854
|
+
if (map2 instanceof Map2dView) {
|
|
35855
|
+
this.baseMap = map2.baseMap;
|
|
35856
|
+
}
|
|
35857
|
+
this.baseMap = map2;
|
|
35858
|
+
}
|
|
35859
|
+
serializeFirstAxis(key) {
|
|
35860
|
+
return this.baseMap.serializeFirstAxis(key);
|
|
35861
|
+
}
|
|
35862
|
+
serializeSecondAxis(key) {
|
|
35863
|
+
return this.baseMap.serializeSecondAxis(key);
|
|
35864
|
+
}
|
|
35865
|
+
deleteRow(key) {
|
|
35866
|
+
this.keysFirstAxis.delete(this.serializeFirstAxis(key));
|
|
35867
|
+
}
|
|
35868
|
+
get(keyFirstAxis, keySecondAxis) {
|
|
35869
|
+
const firstAxisKey = this.serializeFirstAxis(keyFirstAxis);
|
|
35870
|
+
const secondAxisKey = this.serializeSecondAxis(keySecondAxis);
|
|
35871
|
+
if (!this.keysFirstAxis.has(firstAxisKey) || !this.keysSecondAxis.has(secondAxisKey)) {
|
|
35872
|
+
return void 0;
|
|
35873
|
+
}
|
|
35874
|
+
return this.baseMap.get(keyFirstAxis, keySecondAxis);
|
|
35875
|
+
}
|
|
35876
|
+
set() {
|
|
35877
|
+
throw new Error("Cannot set value on a Map2dView");
|
|
35878
|
+
}
|
|
35879
|
+
getFirstAxisKeys() {
|
|
35880
|
+
return Array.from(this.keysFirstAxis.values());
|
|
35881
|
+
}
|
|
35882
|
+
getSecondAxisKeys() {
|
|
35883
|
+
return Array.from(this.keysSecondAxis.values());
|
|
35884
|
+
}
|
|
35885
|
+
getAsArray(fillEmptyWith) {
|
|
35886
|
+
return this.getFirstAxisKeys().map((firstAxisKey) => {
|
|
35887
|
+
return this.getSecondAxisKeys().map((secondAxisKey) => {
|
|
35888
|
+
return this.baseMap.get(firstAxisKey, secondAxisKey) ?? fillEmptyWith;
|
|
35941
35889
|
});
|
|
35942
35890
|
});
|
|
35943
|
-
return copy;
|
|
35944
35891
|
}
|
|
35892
|
+
getRow(key, fillEmptyWith) {
|
|
35893
|
+
const serializedKeyFirstAxis = this.serializeFirstAxis(key);
|
|
35894
|
+
if (!this.keysFirstAxis.has(serializedKeyFirstAxis)) {
|
|
35895
|
+
return [];
|
|
35896
|
+
}
|
|
35897
|
+
return this.baseMap.getRow(key, fillEmptyWith);
|
|
35898
|
+
}
|
|
35899
|
+
}
|
|
35900
|
+
function getFilteredMutationOverTimeData(data, overallMutationData, displayedSegments, displayedMutationTypes, proportionInterval) {
|
|
35901
|
+
const filteredData = new Map2dView(data);
|
|
35902
|
+
filterDisplayedSegments(displayedSegments, filteredData);
|
|
35903
|
+
filterMutationTypes(displayedMutationTypes, filteredData);
|
|
35904
|
+
filterProportion(filteredData, overallMutationData, proportionInterval);
|
|
35905
|
+
return filteredData;
|
|
35906
|
+
}
|
|
35907
|
+
function filterDisplayedSegments(displayedSegments, data) {
|
|
35908
|
+
displayedSegments.forEach((segment) => {
|
|
35909
|
+
if (!segment.checked) {
|
|
35910
|
+
data.getFirstAxisKeys().forEach((mutation) => {
|
|
35911
|
+
if (mutation.segment === segment.segment) {
|
|
35912
|
+
data.deleteRow(mutation);
|
|
35913
|
+
}
|
|
35914
|
+
});
|
|
35915
|
+
}
|
|
35916
|
+
});
|
|
35917
|
+
}
|
|
35918
|
+
function filterMutationTypes(displayedMutationTypes, data) {
|
|
35919
|
+
displayedMutationTypes.forEach((mutationType) => {
|
|
35920
|
+
if (!mutationType.checked) {
|
|
35921
|
+
data.getFirstAxisKeys().forEach((mutation) => {
|
|
35922
|
+
if (mutationType.type === mutation.type) {
|
|
35923
|
+
data.deleteRow(mutation);
|
|
35924
|
+
}
|
|
35925
|
+
});
|
|
35926
|
+
}
|
|
35927
|
+
});
|
|
35928
|
+
}
|
|
35929
|
+
function filterProportion(data, overallMutationData, proportionInterval) {
|
|
35930
|
+
const overallProportionsByMutation = overallMutationData.content.reduce(
|
|
35931
|
+
(acc, { mutation, proportion }) => ({
|
|
35932
|
+
...acc,
|
|
35933
|
+
[mutation.toString()]: proportion
|
|
35934
|
+
}),
|
|
35935
|
+
{}
|
|
35936
|
+
);
|
|
35937
|
+
data.getFirstAxisKeys().forEach((mutation) => {
|
|
35938
|
+
const overallProportion = overallProportionsByMutation[mutation.toString()] || -1;
|
|
35939
|
+
if (overallProportion < proportionInterval.min || overallProportion > proportionInterval.max) {
|
|
35940
|
+
data.deleteRow(mutation);
|
|
35941
|
+
}
|
|
35942
|
+
});
|
|
35943
|
+
}
|
|
35944
|
+
const ColorScaleSelector = ({ colorScale, setColorScale }) => {
|
|
35945
|
+
const colorDisplayCss = `w-10 h-8 border border-gray-200 mx-2 text-xs flex items-center justify-center`;
|
|
35946
|
+
return /* @__PURE__ */ u$2("div", { className: "flex items-center", children: [
|
|
35947
|
+
/* @__PURE__ */ u$2(
|
|
35948
|
+
"div",
|
|
35949
|
+
{
|
|
35950
|
+
style: {
|
|
35951
|
+
backgroundColor: singleGraphColorRGBByName(colorScale.color, 0),
|
|
35952
|
+
color: "black"
|
|
35953
|
+
},
|
|
35954
|
+
className: colorDisplayCss,
|
|
35955
|
+
children: formatProportion(colorScale.min, 0)
|
|
35956
|
+
}
|
|
35957
|
+
),
|
|
35958
|
+
/* @__PURE__ */ u$2("div", { className: "w-64", children: /* @__PURE__ */ u$2(
|
|
35959
|
+
MinMaxRangeSlider,
|
|
35960
|
+
{
|
|
35961
|
+
min: colorScale.min * 100,
|
|
35962
|
+
max: colorScale.max * 100,
|
|
35963
|
+
setMin: (percentage) => {
|
|
35964
|
+
setColorScale({ ...colorScale, min: percentage / 100 });
|
|
35965
|
+
},
|
|
35966
|
+
setMax: (percentage) => {
|
|
35967
|
+
setColorScale({ ...colorScale, max: percentage / 100 });
|
|
35968
|
+
}
|
|
35969
|
+
}
|
|
35970
|
+
) }),
|
|
35971
|
+
/* @__PURE__ */ u$2(
|
|
35972
|
+
"div",
|
|
35973
|
+
{
|
|
35974
|
+
style: {
|
|
35975
|
+
backgroundColor: singleGraphColorRGBByName(colorScale.color, 1),
|
|
35976
|
+
color: "white"
|
|
35977
|
+
},
|
|
35978
|
+
className: colorDisplayCss,
|
|
35979
|
+
children: formatProportion(colorScale.max, 0)
|
|
35980
|
+
}
|
|
35981
|
+
)
|
|
35982
|
+
] });
|
|
35983
|
+
};
|
|
35984
|
+
const getColorWithingScale = (value, colorScale) => {
|
|
35985
|
+
if (colorScale.min === colorScale.max) {
|
|
35986
|
+
return singleGraphColorRGBByName(colorScale.color, 0);
|
|
35987
|
+
}
|
|
35988
|
+
const colorRange = colorScale.max - colorScale.min;
|
|
35989
|
+
const alpha2 = (value - colorScale.min) / colorRange;
|
|
35990
|
+
return singleGraphColorRGBByName(colorScale.color, alpha2);
|
|
35991
|
+
};
|
|
35992
|
+
const getTextColorForScale = (value, colorScale) => {
|
|
35993
|
+
if (colorScale.min === colorScale.max) {
|
|
35994
|
+
return "black";
|
|
35995
|
+
}
|
|
35996
|
+
const colorRange = colorScale.max - colorScale.min;
|
|
35997
|
+
const alpha2 = (value - colorScale.min) / colorRange;
|
|
35998
|
+
return alpha2 <= 0.5 ? "black" : "white";
|
|
35999
|
+
};
|
|
36000
|
+
function getPositionCss(position) {
|
|
36001
|
+
switch (position) {
|
|
36002
|
+
case "top":
|
|
36003
|
+
return "bottom-full translate-x-[-50%] left-1/2 mb-1";
|
|
36004
|
+
case "top-start":
|
|
36005
|
+
return "bottom-full mr-1 mb-1";
|
|
36006
|
+
case "top-end":
|
|
36007
|
+
return "bottom-full right-0 ml-1 mb-1";
|
|
36008
|
+
case "bottom":
|
|
36009
|
+
return "top-full translate-x-[-50%] left-1/2 mt-1";
|
|
36010
|
+
case "bottom-start":
|
|
36011
|
+
return "mr-1 mt-1";
|
|
36012
|
+
case "bottom-end":
|
|
36013
|
+
return "right-0 ml-1 mt-1";
|
|
36014
|
+
case "left":
|
|
36015
|
+
return "right-full translate-y-[-50%] top-1/2 mr-1";
|
|
36016
|
+
case "right":
|
|
36017
|
+
return "left-full translate-y-[-50%] top-1/2 ml-1";
|
|
36018
|
+
case void 0:
|
|
36019
|
+
return "";
|
|
36020
|
+
}
|
|
36021
|
+
}
|
|
36022
|
+
const Tooltip = ({ children, content, position = "bottom" }) => {
|
|
36023
|
+
return /* @__PURE__ */ u$2("div", { className: "relative w-full h-full", children: [
|
|
36024
|
+
/* @__PURE__ */ u$2("div", { className: "peer w-full h-full", children }),
|
|
36025
|
+
/* @__PURE__ */ u$2(
|
|
36026
|
+
"div",
|
|
36027
|
+
{
|
|
36028
|
+
className: `absolute z-10 w-max bg-white p-4 border border-gray-200 rounded-md invisible peer-hover:visible ${getPositionCss(position)}`,
|
|
36029
|
+
children: content
|
|
36030
|
+
}
|
|
36031
|
+
)
|
|
36032
|
+
] });
|
|
36033
|
+
};
|
|
36034
|
+
const MAX_NUMBER_OF_GRID_ROWS = 100;
|
|
36035
|
+
const MUTATION_CELL_WIDTH_REM = 8;
|
|
36036
|
+
const MutationsOverTimeGrid = ({ data, colorScale }) => {
|
|
36037
|
+
const allMutations = data.getFirstAxisKeys().sort(sortSubstitutionsAndDeletions);
|
|
36038
|
+
const shownMutations = allMutations.slice(0, MAX_NUMBER_OF_GRID_ROWS);
|
|
36039
|
+
const dates = data.getSecondAxisKeys().sort((a2, b3) => compareTemporal(a2, b3));
|
|
36040
|
+
const [showProportionText, setShowProportionText] = h$1(false);
|
|
36041
|
+
const gridRef = A$1(null);
|
|
36042
|
+
useShowProportion(gridRef, dates.length, setShowProportionText);
|
|
36043
|
+
return /* @__PURE__ */ u$2(k$1, { children: [
|
|
36044
|
+
allMutations.length > MAX_NUMBER_OF_GRID_ROWS && /* @__PURE__ */ u$2("div", { className: "pl-2", children: [
|
|
36045
|
+
"Showing ",
|
|
36046
|
+
MAX_NUMBER_OF_GRID_ROWS,
|
|
36047
|
+
" of ",
|
|
36048
|
+
allMutations.length,
|
|
36049
|
+
" mutations. You can narrow the filter to reduce the number of mutations."
|
|
36050
|
+
] }),
|
|
36051
|
+
/* @__PURE__ */ u$2(
|
|
36052
|
+
"div",
|
|
36053
|
+
{
|
|
36054
|
+
ref: gridRef,
|
|
36055
|
+
style: {
|
|
36056
|
+
display: "grid",
|
|
36057
|
+
gridTemplateRows: `repeat(${shownMutations.length}, 24px)`,
|
|
36058
|
+
gridTemplateColumns: `${MUTATION_CELL_WIDTH_REM}rem repeat(${dates.length}, minmax(0.05rem, 1fr))`
|
|
36059
|
+
},
|
|
36060
|
+
children: shownMutations.map((mutation, rowIndex) => {
|
|
36061
|
+
return /* @__PURE__ */ u$2(k$1, { children: [
|
|
36062
|
+
/* @__PURE__ */ u$2(
|
|
36063
|
+
"div",
|
|
36064
|
+
{
|
|
36065
|
+
style: { gridRowStart: rowIndex + 1, gridColumnStart: 1 },
|
|
36066
|
+
children: /* @__PURE__ */ u$2(MutationCell, { mutation })
|
|
36067
|
+
},
|
|
36068
|
+
`mutation-${mutation.toString()}`
|
|
36069
|
+
),
|
|
36070
|
+
dates.map((date, columnIndex) => {
|
|
36071
|
+
const value = data.get(mutation, date) ?? { proportion: 0, count: 0 };
|
|
36072
|
+
const tooltipPosition = getTooltipPosition(
|
|
36073
|
+
rowIndex,
|
|
36074
|
+
shownMutations.length,
|
|
36075
|
+
columnIndex,
|
|
36076
|
+
dates.length
|
|
36077
|
+
);
|
|
36078
|
+
return /* @__PURE__ */ u$2(
|
|
36079
|
+
"div",
|
|
36080
|
+
{
|
|
36081
|
+
style: { gridRowStart: rowIndex + 1, gridColumnStart: columnIndex + 2 },
|
|
36082
|
+
children: /* @__PURE__ */ u$2(
|
|
36083
|
+
ProportionCell,
|
|
36084
|
+
{
|
|
36085
|
+
value,
|
|
36086
|
+
date,
|
|
36087
|
+
mutation,
|
|
36088
|
+
tooltipPosition,
|
|
36089
|
+
showProportionText,
|
|
36090
|
+
colorScale
|
|
36091
|
+
}
|
|
36092
|
+
)
|
|
36093
|
+
},
|
|
36094
|
+
`${mutation.toString()}-${date.toString()}`
|
|
36095
|
+
);
|
|
36096
|
+
})
|
|
36097
|
+
] }, `fragment-${mutation.toString()}`);
|
|
36098
|
+
})
|
|
36099
|
+
}
|
|
36100
|
+
)
|
|
36101
|
+
] });
|
|
36102
|
+
};
|
|
36103
|
+
function useShowProportion(gridRef, girdColumns, setShowProportionText) {
|
|
36104
|
+
y$1(() => {
|
|
36105
|
+
const checkWidth = () => {
|
|
36106
|
+
if (gridRef.current) {
|
|
36107
|
+
const width = gridRef.current.getBoundingClientRect().width;
|
|
36108
|
+
const widthPerDate = (width - remToPx(MUTATION_CELL_WIDTH_REM)) / girdColumns;
|
|
36109
|
+
const maxWidthProportionText = 28;
|
|
36110
|
+
setShowProportionText(widthPerDate > maxWidthProportionText);
|
|
36111
|
+
}
|
|
36112
|
+
};
|
|
36113
|
+
checkWidth();
|
|
36114
|
+
window.addEventListener("resize", checkWidth);
|
|
36115
|
+
return () => {
|
|
36116
|
+
window.removeEventListener("resize", checkWidth);
|
|
36117
|
+
};
|
|
36118
|
+
}, [girdColumns, gridRef, setShowProportionText]);
|
|
36119
|
+
}
|
|
36120
|
+
const remToPx = (rem) => rem * parseFloat(getComputedStyle(document.documentElement).fontSize);
|
|
36121
|
+
function getTooltipPosition(rowIndex, rows, columnIndex, columns) {
|
|
36122
|
+
const tooltipX = rowIndex < rows / 2 ? "bottom" : "top";
|
|
36123
|
+
const tooltipY = columnIndex < columns / 2 ? "start" : "end";
|
|
36124
|
+
return `${tooltipX}-${tooltipY}`;
|
|
35945
36125
|
}
|
|
36126
|
+
const ProportionCell = ({ value, mutation, date, tooltipPosition, showProportionText, colorScale }) => {
|
|
36127
|
+
const tooltipContent = /* @__PURE__ */ u$2("div", { children: [
|
|
36128
|
+
/* @__PURE__ */ u$2("p", { children: /* @__PURE__ */ u$2("span", { className: "font-bold", children: date.englishName() }) }),
|
|
36129
|
+
/* @__PURE__ */ u$2("p", { children: [
|
|
36130
|
+
"(",
|
|
36131
|
+
timeIntervalDisplay(date),
|
|
36132
|
+
")"
|
|
36133
|
+
] }),
|
|
36134
|
+
/* @__PURE__ */ u$2("p", { children: mutation.code }),
|
|
36135
|
+
/* @__PURE__ */ u$2("p", { children: [
|
|
36136
|
+
"Proportion: ",
|
|
36137
|
+
formatProportion(value.proportion)
|
|
36138
|
+
] }),
|
|
36139
|
+
/* @__PURE__ */ u$2("p", { children: [
|
|
36140
|
+
"Count: ",
|
|
36141
|
+
value.count
|
|
36142
|
+
] })
|
|
36143
|
+
] });
|
|
36144
|
+
return /* @__PURE__ */ u$2("div", { className: "py-1 w-full h-full", children: /* @__PURE__ */ u$2(Tooltip, { content: tooltipContent, position: tooltipPosition, children: /* @__PURE__ */ u$2(
|
|
36145
|
+
"div",
|
|
36146
|
+
{
|
|
36147
|
+
style: {
|
|
36148
|
+
backgroundColor: getColorWithingScale(value.proportion, colorScale),
|
|
36149
|
+
color: getTextColorForScale(value.proportion, colorScale)
|
|
36150
|
+
},
|
|
36151
|
+
className: `w-full h-full text-center hover:font-bold text-xs group`,
|
|
36152
|
+
children: showProportionText ? formatProportion(value.proportion, 0) : void 0
|
|
36153
|
+
}
|
|
36154
|
+
) }) });
|
|
36155
|
+
};
|
|
36156
|
+
const timeIntervalDisplay = (date) => {
|
|
36157
|
+
if (date instanceof YearMonthDay) {
|
|
36158
|
+
return date.toString();
|
|
36159
|
+
}
|
|
36160
|
+
return `${date.firstDay.toString()} - ${date.lastDay.toString()}`;
|
|
36161
|
+
};
|
|
36162
|
+
const MutationCell = ({ mutation }) => {
|
|
36163
|
+
return /* @__PURE__ */ u$2("div", { className: "text-center", children: mutation.toString() });
|
|
36164
|
+
};
|
|
35946
36165
|
const MAX_NUMBER_OF_GRID_COLUMNS = 200;
|
|
35947
36166
|
async function queryOverallMutationData(lapisFilter, sequenceType, lapis, signal) {
|
|
35948
36167
|
return fetchAndPrepareSubstitutionsOrDeletions(lapisFilter, sequenceType).evaluate(lapis, signal);
|
|
@@ -36014,7 +36233,7 @@ function fetchAndPrepareSubstitutionsOrDeletions(filter, sequenceType) {
|
|
|
36014
36233
|
return new FetchSubstitutionsOrDeletionsOperator(filter, sequenceType, 1e-3);
|
|
36015
36234
|
}
|
|
36016
36235
|
function groupByMutation(data) {
|
|
36017
|
-
const dataArray = new
|
|
36236
|
+
const dataArray = new Map2dBase(
|
|
36018
36237
|
(mutation) => mutation.code,
|
|
36019
36238
|
(date) => date.toString()
|
|
36020
36239
|
);
|
|
@@ -36043,7 +36262,7 @@ const ColorScaleSelectorDropdown = ({
|
|
|
36043
36262
|
colorScale,
|
|
36044
36263
|
setColorScale
|
|
36045
36264
|
}) => {
|
|
36046
|
-
return /* @__PURE__ */ u$2(Dropdown, { buttonTitle: `Color scale`, placement: "bottom-start", children: /* @__PURE__ */ u$2(ColorScaleSelector, { colorScale, setColorScale }) });
|
|
36265
|
+
return /* @__PURE__ */ u$2("div", { className: "w-20", children: /* @__PURE__ */ u$2(Dropdown, { buttonTitle: `Color scale`, placement: "bottom-start", children: /* @__PURE__ */ u$2(ColorScaleSelector, { colorScale, setColorScale }) }) });
|
|
36047
36266
|
};
|
|
36048
36267
|
const MutationsOverTime = ({ width, height, ...innerProps }) => {
|
|
36049
36268
|
const size = { height, width };
|