diff --git a/src/components/GensploreView.js b/src/components/GensploreView.js
index 994c4a6..64ea228 100644
--- a/src/components/GensploreView.js
+++ b/src/components/GensploreView.js
@@ -7,6 +7,9 @@ import React, {
useCallback,
} from "react";
+
+import Offcanvas from './Offcanvas'; // Import the new offcanvas component
+
import Tooltip from "./Tooltip";
import { getReverseComplement, filterFeatures } from "../utils";
import SingleRow from "./SingleRow";
@@ -18,7 +21,7 @@ import { useWindowVirtualizer } from "@tanstack/react-virtual";
import { ToastContainer, toast } from "react-toastify";
import SearchPanel from "../SearchPanel";
import { GiDna1 } from "react-icons/gi";
-import { MdSettings } from "react-icons/md";
+
function GensploreView({ genbankString, searchInput, setSearchInput }) {
const [searchPanelOpen, setSearchPanelOpen] = useState(false);
@@ -292,6 +295,37 @@ function GensploreView({ genbankString, searchInput, setSearchInput }) {
setLastSearch(sequenceSearchInput);
}, [sequenceSearchInput, curSeqHitIndex,includeRC]);
+ const [featureOffcanvasOpen, setFeatureOffcanvasOpen] = useState(false);
+ const [featureVisibility, setFeatureVisibility] = useState({});
+ const visibleFeatures = useMemo(() => {
+ if (!genbankData) return [];
+ const visibleFeatures = [];
+ genbankData.parsedSequence.features.forEach((feature, i) => {
+ if (featureVisibility[i]) {
+ visibleFeatures.push(feature);
+ }
+ });
+ return visibleFeatures;
+ }, [featureVisibility, genbankData]);
+
+
+
+ useEffect(() => {
+ if (!genbankData) return;
+ const newFeatureVisibility = {};
+ /*
+ feature.type !== "source" &&
+ feature.type !== "gene" &&
+ feature.type !== "mRNA" &&
+ */
+ genbankData.parsedSequence.features.forEach((feature, i) => {
+ newFeatureVisibility[i] = feature.type !== "source" && feature.type !== "gene" && feature.type !== "mRNA"
+ }
+ );
+ setFeatureVisibility(newFeatureVisibility);
+ }, [genbankData]);
+
+
//console.log("virtualItems", virtualItems);
@@ -374,7 +408,8 @@ function GensploreView({ genbankString, searchInput, setSearchInput }) {
)}
-
+
@@ -436,6 +471,7 @@ function GensploreView({ genbankString, searchInput, setSearchInput }) {
+
+
+
+ setFeatureOffcanvasOpen(false)}>
+
+
>
);
}
diff --git a/src/components/Offcanvas.js b/src/components/Offcanvas.js
new file mode 100644
index 0000000..657fb15
--- /dev/null
+++ b/src/components/Offcanvas.js
@@ -0,0 +1,35 @@
+import React from 'react';
+
+const Offcanvas = ({ isOpen, onClose, children }) => {
+ return (
+
+
+ {/* Background overlay */}
+
+
+ {/* Offcanvas Panel from Bottom */}
+
+ {/* Offcanvas Panel */}
+
+
+
+
+ {/* Place your content here */}
+ {children}
+
+
+
+
+
+
+ );
+};
+
+export default Offcanvas;
diff --git a/src/components/SettingsPanel.js b/src/components/SettingsPanel.js
index d0789b9..ca826a6 100644
--- a/src/components/SettingsPanel.js
+++ b/src/components/SettingsPanel.js
@@ -3,11 +3,15 @@ import Slider from 'rc-slider';
import "rc-slider/assets/index.css";
import { AiOutlineZoomIn, AiOutlineZoomOut } from 'react-icons/ai';
import { MdSettings } from 'react-icons/md';
+import { PiTagChevronFill } from "react-icons/pi";
-const SettingsPanel = ({ zoomLevel, setZoomLevel, configModalOpen, setConfigModalOpen }) => {
+const SettingsPanel = ({ zoomLevel, setZoomLevel, configModalOpen, setConfigModalOpen, setFeatureOffcanvasOpen }) => {
return (
<>
-