import addProjectIcon from "./assets/figma/navigation/add-project.svg"; import bookBookmarkIcon from "./assets/figma/navigation/book-bookmark.svg"; import boxArchiveIcon from "./assets/figma/navigation/box-archive.svg"; import chopinIcon from "./assets/figma/navigation/chopin.svg"; import collapseIcon from "./assets/figma/navigation/collapse.svg"; import documentActionsIcon from "./assets/figma/navigation/document-actions.svg"; import newDocumentIcon from "./assets/figma/navigation/new-document.svg"; import searchIcon from "./assets/figma/navigation/search.svg"; import { DocumentActionsMenu } from "./document-actions-menu"; import { motionContract } from "./motion-contract"; import { motionImmediately } from "./motion-input"; import { canManageProject } from "./navigation-model"; import { MotionDisclosure } from "@chopin/editor"; import { documentPath, researchWorkspacePath } from "@chopin/protocol/document-url"; import { useId, useRef, useState } from "react"; import type * as Api from "./api"; import type { DocumentAction } from "./document-actions-menu"; import type { ProjectDocuments } from "./document-actions"; import type { ReactNode } from "react"; import type { ResearchChannelGroup } from "./research-navigation"; export function NavigationIcon( { alt = "", className, src }: { alt?: string; className?: string; src: string }, ) { return {alt}; } export function toggleCollapsedProjectIds( ids: ReadonlySet, repositoryId: string, ): Set { let next = new Set(ids); if (next.has(repositoryId)) next.delete(repositoryId); else next.add(repositoryId); return next; } export function newestResearchFirst( workspaces: ResearchChannelGroup["workspaces"], ): ResearchChannelGroup["workspaces"] { return [...workspaces].sort((first, second) => second.createdAt.localeCompare(first.createdAt) || second.id.localeCompare(first.id) ); } function Project( { archiveMode, creatingProjectIds, currentDocumentId, currentResearchWorkspaceId, entry, expanded, onCreateDocument, onDocumentAction, onLoadMore, onNewResearch, research, onToggle, }: { archiveMode: boolean; creatingProjectIds: ReadonlySet; currentDocumentId?: string; currentResearchWorkspaceId?: string; entry: ProjectDocuments; expanded: boolean; onCreateDocument: (project: Api.NavigationProject) => void; onDocumentAction: (channel: Api.Channel, action: DocumentAction) => void; onLoadMore: (entry: ProjectDocuments) => void; onNewResearch?: (channel: Api.Channel) => void; research: ReadonlyMap; onToggle: () => void; }, ) { let { documents, project } = entry; let channels = documents.channels.filter(channel => archiveMode ? channel.archivedAt !== undefined : channel.archivedAt === undefined ); let label = project.repository?.name ?? project.repositoryName; let canManage = canManageProject(project); let creating = creatingProjectIds.has(project.repositoryId); let contentId = useId(); let collapseMotion = motionContract("collapse"); let projectContent = ( <> {documents.status === "unavailable" && (

Access unavailable

)} {documents.status === "error" && (

{documents.message}

)} {documents.status === "loading" && channels.length === 0 && (

Loading documents…

)} {channels.length > 0 && (
    {channels.map(channel => { let children = newestResearchFirst(research.get(channel.id)?.workspaces ?? []); let parentCurrent = currentDocumentId === channel.id; let researchCurrent = parentCurrent && currentResearchWorkspaceId !== undefined; let parentHref = documentPath( channel.repositoryOwner, channel.repositoryName, channel.slug, ); return (
  • {channel.title} {channel.description && ( {channel.description} )} {canManage && (
    {onNewResearch && !channel.archivedAt && ( )} onDocumentAction(channel, action)} trigger={ } />
    )}
    {children.length > 0 && ( )}
  • ); })}
)} {documents.status === "loading" && channels.length > 0 && (

Loading more…

)} {documents.status === "ready" && documents.nextCursor && ( )} ); return (
  • {!archiveMode && project.available && canManage && ( )}
    {projectContent}
  • ); } export function ProjectSidebar( { accountMenu, accountMenuOpen, canCreateDocument, creatingNewDocument, creatingProjectIds, currentDocumentId, currentResearchWorkspaceId, onAccount, onAddProject, onCollapse, onCreateDocument, onDocumentAction, onLoadMore, onNewResearch, onNewDocument, onSearch, onCatalogueModeChange, projects, research = new Map(), catalogueMode, user, }: { accountMenu?: ReactNode; accountMenuOpen?: boolean; canCreateDocument: boolean; catalogueMode: "active" | "archived"; creatingNewDocument: boolean; creatingProjectIds: ReadonlySet; currentDocumentId?: string; currentResearchWorkspaceId?: string; onAccount: () => void; onAddProject: () => void; onCollapse: () => void; onCreateDocument: (project: Api.NavigationProject) => void; onDocumentAction: (channel: Api.Channel, action: DocumentAction) => void; onLoadMore: (entry: ProjectDocuments) => void; onNewResearch?: (channel: Api.Channel) => void; onNewDocument: () => void; onSearch: () => void; onCatalogueModeChange: (mode: "active" | "archived") => void; projects: ProjectDocuments[]; research?: ReadonlyMap; user: Api.User; }, ) { let [collapsedProjectIds, setCollapsedProjectIds] = useState>( () => new Set(), ); let archivedChats = useRef(null); let backToActiveDocs = useRef(null); let archiveMode = catalogueMode === "archived"; let primaryActions = (
    {archiveMode ? ( ) : ( <> )}
    ); let archiveFooter = !archiveMode ? (
    ) : null; return ( ); }