import React, { type ComponentProps, type ReactNode, useEffect, useMemo, } from 'react'; import clsx from 'clsx'; import { ThemeClassNames, useThemeConfig, usePrevious, Collapsible, useCollapsible, } from '@docusaurus/theme-common'; import {isSamePath} from '@docusaurus/theme-common/internal'; import { isActiveSidebarItem, findFirstSidebarItemLink, useDocSidebarItemsExpandedState, } from '@docusaurus/plugin-content-docs/client'; import Link from '@docusaurus/Link'; import {translate} from '@docusaurus/Translate'; import useIsBrowser from '@docusaurus/useIsBrowser'; import DocSidebarItems from '@theme/DocSidebarItems'; import type {Props} from '@theme/DocSidebarItem/Category'; import { Rocket, Package, Settings, BookOpen, Plug, Wrench, Users, Code, type LucideIcon, } from 'lucide-react'; // Map category labels to Lucide icons const categoryIcons: Record = { 'Getting Started': Rocket, 'Installation': Package, 'Configuration': Settings, 'Using Karakeep': BookOpen, 'Integrations': Plug, 'Administration': Wrench, 'Community': Users, 'Development': Code, 'API': Code, }; // If we navigate to a category and it becomes active, it should automatically // expand itself function useAutoExpandActiveCategory({ isActive, collapsed, updateCollapsed, }: { isActive: boolean; collapsed: boolean; updateCollapsed: (b: boolean) => void; }) { const wasActive = usePrevious(isActive); useEffect(() => { const justBecameActive = isActive && !wasActive; if (justBecameActive && collapsed) { updateCollapsed(false); } }, [isActive, wasActive, collapsed, updateCollapsed]); } /** * When a collapsible category has no link, we still link it to its first child * during SSR as a temporary fallback. This allows to be able to navigate inside * the category even when JS fails to load, is delayed or simply disabled * React hydration becomes an optional progressive enhancement * see https://github.com/facebookincubator/infima/issues/36#issuecomment-772543188 * see https://github.com/facebook/docusaurus/issues/3030 */ function useCategoryHrefWithSSRFallback( item: Props['item'], ): string | undefined { const isBrowser = useIsBrowser(); return useMemo(() => { if (item.href && !item.linkUnlisted) { return item.href; } // In these cases, it's not necessary to render a fallback // We skip the "findFirstCategoryLink" computation if (isBrowser || !item.collapsible) { return undefined; } return findFirstSidebarItemLink(item); }, [item, isBrowser]); } function CollapseButton({ collapsed, categoryLabel, onClick, }: { collapsed: boolean; categoryLabel: string; onClick: ComponentProps<'button'>['onClick']; }) { return (