// Shared utilities and types import { type GlossaryItem, isGlossaryItem, isGlossaryPath } from "../utils/glossaryUtils"; import ErrorBoundary from "./ErrorBoundary"; import GlossaryDocCardList from "./GlossaryDocCardList"; import styles from "./styles.module.css"; // Docusaurus core imports import type { PropSidebarItem } from "@docusaurus/plugin-content-docs"; import { filterDocCardListItems, useCurrentSidebarSiblings, } from "@docusaurus/plugin-content-docs/client"; import { useLocation } from "@docusaurus/router"; import DocCard from "@theme/DocCard"; import type { Props } from "@theme/DocCardList"; import clsx from "clsx"; import React, { ReactNode, useMemo } from "react"; // Constant empty array to avoid creating new array on each render const EMPTY_SIDEBAR_ITEMS: PropSidebarItem[] = []; // Type aliases for clarity type SidebarDocLike = Extract; /** * Type-safe property existence checker with proper typing */ function hasOwnProperty( value: T, key: K, ): value is T & Record { return Object.prototype.hasOwnProperty.call(value, key); } /** * Generates stable React keys from sidebar items, with fallback to index */ function getStableKey(item: GlossaryItem | PropSidebarItem, idx: number): string | number { if (typeof item === "object" && item !== null) { const match = ["docId", "id", "href", "label"].find( (name) => hasOwnProperty(item, name) && typeof item[name] === "string", ); return match ? ((item as Record)[match] as string) : idx; } return idx; } /** * Standard documentation card item for non-glossary content */ function DocCardListItem({ item }: { item: React.ComponentProps["item"] }) { return (
); } /** * Enhanced DocCardList component that delegates to specialized components based on content type. * Provides both standard documentation card rendering and specialized glossary functionality. */ export default function DocCardList(props: Props): ReactNode { const { items, className } = props; const pathname = useLocation()?.pathname ?? ""; const isGlossary = isGlossaryPath(pathname); const sidebarSiblings = useCurrentSidebarSiblings(); const siblings = sidebarSiblings ?? EMPTY_SIDEBAR_ITEMS; // Extract glossary terms from sidebar structure (always computed, but only used for glossary pages) const glossaryPool = useMemo(() => { const terms: SidebarDocLike[] = []; // Recursively process sidebar items to find glossary terms const processItem = (item: PropSidebarItem) => { if (isGlossaryItem(item) && item.type === "link") { terms.push(item as SidebarDocLike); } else if (item.type === "category" && item.items) { item.items.forEach(processItem); } }; siblings.forEach(processItem); return terms; }, [siblings]); // Standard documentation card items (always computed, but only used for non-glossary pages) const baseItems = useMemo(() => filterDocCardListItems(items ?? siblings), [items, siblings]); // For glossary pages, delegate to specialized GlossaryDocCardList component if (isGlossary) { return ( ); } // Standard documentation card rendering for non-glossary pages return (
{baseItems.map((item, idx) => ( ))}
); } export { DocCardList };