From 6ec259a0e71174651bae95d4628138bf6fd68742 Mon Sep 17 00:00:00 2001
From: kj_sh604
Date: Sun, 15 Mar 2026 16:19:35 -0400
Subject: refactor: packages/

---
 .../excalidraw/components/LibraryMenuSection.tsx   | 78 ++++++++++++++++++++++
 1 file changed, 78 insertions(+)
 create mode 100644 packages/excalidraw/components/LibraryMenuSection.tsx

(limited to 'packages/excalidraw/components/LibraryMenuSection.tsx')

diff --git a/packages/excalidraw/components/LibraryMenuSection.tsx b/packages/excalidraw/components/LibraryMenuSection.tsx
new file mode 100644
index 0000000..b07d6b1
--- /dev/null
+++ b/packages/excalidraw/components/LibraryMenuSection.tsx
@@ -0,0 +1,78 @@
+import type { ReactNode } from "react";
+import React, { memo, useEffect, useState } from "react";
+import { EmptyLibraryUnit, LibraryUnit } from "./LibraryUnit";
+import type { LibraryItem } from "../types";
+import type { ExcalidrawElement, NonDeleted } from "../element/types";
+import type { SvgCache } from "../hooks/useLibraryItemSvg";
+import { useTransition } from "../hooks/useTransition";
+
+type LibraryOrPendingItem = (
+  | LibraryItem
+  | /* pending library item */ {
+      id: null;
+      elements: readonly NonDeleted<ExcalidrawElement>[];
+    }
+)[];
+
+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;
+  itemsRenderedPerBatch: number;
+}
+
+export const LibraryMenuSectionGrid = ({
+  children,
+}: {
+  children: ReactNode;
+}) => {
+  return <div className="library-menu-items-container__grid">{children}</div>;
+};
+
+export const LibraryMenuSection = memo(
+  ({
+    items,
+    onItemSelectToggle,
+    onItemDrag,
+    isItemSelected,
+    onClick,
+    svgCache,
+    itemsRenderedPerBatch,
+  }: Props) => {
+    const [, startTransition] = useTransition();
+    const [index, setIndex] = useState(0);
+
+    useEffect(() => {
+      if (index < items.length) {
+        startTransition(() => {
+          setIndex(index + itemsRenderedPerBatch);
+        });
+      }
+    }, [index, items.length, startTransition, itemsRenderedPerBatch]);
+
+    return (
+      <>
+        {items.map((item, i) => {
+          return i < index ? (
+            <LibraryUnit
+              elements={item?.elements}
+              isPending={!item?.id && !!item?.elements}
+              onClick={onClick}
+              svgCache={svgCache}
+              id={item?.id}
+              selected={isItemSelected(item.id)}
+              onToggle={onItemSelectToggle}
+              onDrag={onItemDrag}
+              key={item?.id ?? i}
+            />
+          ) : (
+            <EmptyLibraryUnit key={i} />
+          );
+        })}
+      </>
+    );
+  },
+);
-- 
cgit v1.2.3

