import { FolderState } from "../ExplorerNode" type MaybeHTMLElement = HTMLElement | undefined let currentExplorerState: FolderState[] const observer = new IntersectionObserver((entries) => { // If last element is observed, remove gradient of "overflow" class so element is visible const explorerUl = document.getElementById("explorer-ul") if (!explorerUl) return for (const entry of entries) { if (entry.isIntersecting) { explorerUl.classList.add("no-background") } else { explorerUl.classList.remove("no-background") } } }) function toggleExplorer(this: HTMLElement) { this.classList.toggle("collapsed") const content = this.nextElementSibling as MaybeHTMLElement if (!content) return content.classList.toggle("collapsed") content.style.maxHeight = content.style.maxHeight === "0px" ? content.scrollHeight + "px" : "0px" } function toggleFolder(evt: MouseEvent) { evt.stopPropagation() const target = evt.target as MaybeHTMLElement if (!target) return const isSvg = target.nodeName === "svg" const childFolderContainer = ( isSvg ? target.parentElement?.nextSibling : target.parentElement?.parentElement?.nextElementSibling ) as MaybeHTMLElement const currentFolderParent = ( isSvg ? target.nextElementSibling : target.parentElement ) as MaybeHTMLElement if (!(childFolderContainer && currentFolderParent)) return childFolderContainer.classList.toggle("open") const isCollapsed = childFolderContainer.classList.contains("open") setFolderState(childFolderContainer, !isCollapsed) // Save folder state to localStorage const clickFolderPath = currentFolderParent.dataset.folderpath as string const fullFolderPath = clickFolderPath toggleCollapsedByPath(explorerState, fullFolderPath) const stringifiedFileTree = JSON.stringify(explorerState) localStorage.setItem("fileTree", stringifiedFileTree) } function setupExplorer() { const explorer = document.getElementById("explorer") if (!explorer) return if (explorer.dataset.behavior === "collapse") { for (const item of document.getElementsByClassName( "folder-button", ) as HTMLCollectionOf) { item.addEventListener("click", toggleFolder) window.addCleanup(() => item.removeEventListener("click", toggleFolder)) } } explorer.addEventListener("click", toggleExplorer) window.addCleanup(() => explorer.removeEventListener("click", toggleExplorer)) // Set up click handlers for each folder (click handler on folder "icon") for (const item of document.getElementsByClassName( "folder-icon", ) as HTMLCollectionOf) { item.addEventListener("click", toggleFolder) window.addCleanup(() => item.removeEventListener("click", toggleFolder)) } if (storageTree && useSavedFolderState) { // Get state from localStorage and set folder state explorerState = JSON.parse(storageTree) explorerState.map((folderUl) => { // grab
  • element for matching folder path const folderLi = document.querySelector(`[data-folderpath='${folderUl.path}']`) as HTMLElement // Get corresponding content
      tag and set state if (folderLi) { const folderUL = folderLi.parentElement?.nextElementSibling if (folderUL) { setFolderState(folderUL as HTMLElement, folderUl.collapsed) } } }) } else if (explorer?.dataset.tree) { // If tree is not in localStorage or config is disabled, use tree passed from Explorer as dataset explorerState = JSON.parse(explorer.dataset.tree) } currentExplorerState.map((folderState) => { const folderLi = document.querySelector( `[data-folderpath='${folderState.path}']`, ) as MaybeHTMLElement const folderUl = folderLi?.parentElement?.nextElementSibling as MaybeHTMLElement if (folderUl) { setFolderState(folderUl, folderState.collapsed) } }) } window.addEventListener("resize", setupExplorer) document.addEventListener("nav", () => { setupExplorer() observer.disconnect() observer.disconnect() // select pseudo element at end of list const lastItem = document.getElementById("explorer-end") if (lastItem) { observer.observe(lastItem) } }) /** * Toggles the state of a given folder * @param folderElement
      Element of folder (parent) * @param collapsed if folder should be set to collapsed or not */ function setFolderState(folderElement: HTMLElement, collapsed: boolean) { return collapsed ? folderElement.classList.remove("open") : folderElement.classList.add("open") } /** * Toggles visibility of a folder * @param array array of FolderState (`fileTree`, either get from local storage or data attribute) * @param path path to folder (e.g. 'advanced/more/more2') */ function toggleCollapsedByPath(array: FolderState[], path: string) { const entry = array.find((item) => item.path === path) if (entry) { entry.collapsed = !entry.collapsed } }