import React, { useEffect, useMemo, useState } from "react"; import { LibraryUnit } from "./LibraryUnit"; import { LibraryItem } from "../types"; import Stack from "./Stack"; import clsx from "clsx"; import { ExcalidrawElement, NonDeleted } from "../element/types"; import { SvgCache } from "../hooks/useLibraryItemSvg"; import { useTransition } from "../hooks/useTransition"; const ITEMS_PER_ROW = 4; const ROWS_RENDERED_PER_BATCH = 6; const CACHED_ROWS_RENDERED_PER_BATCH = 16; type LibraryOrPendingItem = ( | LibraryItem | /* pending library item */ { id: null; elements: readonly NonDeleted[]; } )[]; interface Props { items: LibraryOrPendingItem; onClick: (id: LibraryItem["id"] | null) => void; onItemSelectToggle: (id: LibraryItem["id"], event: React.MouseEvent) => void; onItemDrag: (id: LibraryItem["id"], event: React.DragEvent) => void; isItemSelected: (id: LibraryItem["id"] | null) => boolean; svgCache: SvgCache; } function LibraryRow({ items, onItemSelectToggle, onItemDrag, isItemSelected, onClick, svgCache, }: Props) { return ( {items.map((item) => ( ))} ); } const EmptyLibraryRow = () => ( {Array.from({ length: ITEMS_PER_ROW }).map((_, index) => (
))} ); function LibraryMenuSection({ items, onItemSelectToggle, onItemDrag, isItemSelected, onClick, svgCache, }: Props) { const rows = Math.ceil(items.length / ITEMS_PER_ROW); const [, startTransition] = useTransition(); const [index, setIndex] = useState(0); const rowsRenderedPerBatch = useMemo(() => { return svgCache.size === 0 ? ROWS_RENDERED_PER_BATCH : CACHED_ROWS_RENDERED_PER_BATCH; }, [svgCache]); useEffect(() => { if (index < rows) { startTransition(() => { setIndex(index + rowsRenderedPerBatch); }); } }, [index, rows, startTransition, rowsRenderedPerBatch]); return ( <> {Array.from({ length: rows }).map((_, i) => i < index ? ( ) : ( ), )} ); } export default LibraryMenuSection;