import includes from "lodash/includes"; import { observer } from "mobx-react"; import * as React from "react"; import { useTranslation } from "react-i18next"; import { NavigationNode } from "@shared/types"; import Collection from "~/models/Collection"; import Document from "~/models/Document"; import useStores from "~/hooks/useStores"; import { sharedDocumentPath } from "~/utils/routeHelpers"; import { descendants } from "~/utils/tree"; import SidebarLink from "./SidebarLink"; type Props = { node: NavigationNode; collection?: Collection; activeDocumentId?: string; activeDocument?: Document; isDraft?: boolean; depth: number; index: number; shareId: string; parentId?: string; }; function DocumentLink( { node, collection, activeDocument, activeDocumentId, isDraft, depth, shareId, }: Props, ref: React.RefObject ) { const { documents } = useStores(); const { t } = useTranslation(); const isActiveDocument = activeDocumentId === node.id; const hasChildDocuments = !!node.children.length || activeDocument?.parentDocumentId === node.id; const document = documents.get(node.id); const showChildren = React.useMemo( () => !!( hasChildDocuments && ((activeDocumentId && includes( descendants(node).map((n) => n.id), activeDocumentId )) || isActiveDocument || depth <= 1) ), [hasChildDocuments, activeDocumentId, isActiveDocument, depth, node] ); const [expanded, setExpanded] = React.useState(showChildren); React.useEffect(() => { if (showChildren) { setExpanded(showChildren); } }, [showChildren]); const handleDisclosureClick = React.useCallback( (ev: React.SyntheticEvent) => { ev.preventDefault(); ev.stopPropagation(); setExpanded(!expanded); }, [expanded] ); // since we don't have access to the collection sort here, we just put any // drafts at the front of the list. this is slightly inconsistent with the // logged-in behavior, but it's probably better to emphasize the draft state // of the document in a shared context const nodeChildren = React.useMemo(() => { if ( activeDocument?.isDraft && activeDocument?.isActive && activeDocument?.parentDocumentId === node.id ) { return [activeDocument?.asNavigationNode, ...node.children]; } return node.children; }, [ activeDocument?.isActive, activeDocument?.isDraft, activeDocument?.parentDocumentId, activeDocument?.asNavigationNode, node, ]); const title = (activeDocument?.id === node.id ? activeDocument.title : node.title) || t("Untitled"); return ( <> !!isActiveDocument} /> {expanded && nodeChildren.map((childNode, index) => ( ))} ); } const ObservedDocumentLink = observer(React.forwardRef(DocumentLink)); export default ObservedDocumentLink;