import React, { useState, useCallback } from "react"; import Library, { distributeLibraryItemsOnSquareGrid, libraryItemsAtom, } from "../data/library"; import { t } from "../i18n"; import { randomId } from "../random"; import { LibraryItems, LibraryItem, ExcalidrawProps, UIAppState, } from "../types"; import LibraryMenuItems from "./LibraryMenuItems"; import { trackEvent } from "../analytics"; import { atom, useAtom } from "jotai"; import { jotaiScope } from "../jotai"; import Spinner from "./Spinner"; import { useApp, useAppProps, useExcalidrawElements, useExcalidrawSetAppState, } from "./App"; import { getSelectedElements } from "../scene"; import { useUIAppState } from "../context/ui-appState"; import "./LibraryMenu.scss"; import { LibraryMenuControlButtons } from "./LibraryMenuControlButtons"; export const isLibraryMenuOpenAtom = atom(false); const LibraryMenuWrapper = ({ children }: { children: React.ReactNode }) => { return
{children}
; }; export const LibraryMenuContent = ({ onInsertLibraryItems, pendingElements, onAddToLibrary, setAppState, libraryReturnUrl, library, id, appState, selectedItems, onSelectItems, }: { pendingElements: LibraryItem["elements"]; onInsertLibraryItems: (libraryItems: LibraryItems) => void; onAddToLibrary: () => void; setAppState: React.Component["setState"]; libraryReturnUrl: ExcalidrawProps["libraryReturnUrl"]; library: Library; id: string; appState: UIAppState; selectedItems: LibraryItem["id"][]; onSelectItems: (id: LibraryItem["id"][]) => void; }) => { const [libraryItemsData] = useAtom(libraryItemsAtom, jotaiScope); const addToLibrary = useCallback( async (elements: LibraryItem["elements"], libraryItems: LibraryItems) => { trackEvent("element", "addToLibrary", "ui"); if (elements.some((element) => element.type === "image")) { return setAppState({ errorMessage: "Support for adding images to the library coming soon!", }); } const nextItems: LibraryItems = [ { status: "unpublished", elements, id: randomId(), created: Date.now(), }, ...libraryItems, ]; onAddToLibrary(); library.setLibrary(nextItems).catch(() => { setAppState({ errorMessage: t("alerts.errorAddingToLibrary") }); }); }, [onAddToLibrary, library, setAppState], ); if ( libraryItemsData.status === "loading" && !libraryItemsData.isInitialized ) { return (
{t("labels.libraryLoadingMessage")}
); } const showBtn = libraryItemsData.libraryItems.length > 0 || pendingElements.length > 0; return ( addToLibrary(elements, libraryItemsData.libraryItems) } onInsertLibraryItems={onInsertLibraryItems} pendingElements={pendingElements} selectedItems={selectedItems} onSelectItems={onSelectItems} id={id} libraryReturnUrl={libraryReturnUrl} theme={appState.theme} /> {showBtn && ( )} ); }; /** * This component is meant to be rendered inside inside our * or host apps Sidebar components. */ export const LibraryMenu = () => { const { library, id, onInsertElements } = useApp(); const appProps = useAppProps(); const appState = useUIAppState(); const setAppState = useExcalidrawSetAppState(); const elements = useExcalidrawElements(); const [selectedItems, setSelectedItems] = useState([]); const deselectItems = useCallback(() => { setAppState({ selectedElementIds: {}, selectedGroupIds: {}, }); }, [setAppState]); return ( { onInsertElements(distributeLibraryItemsOnSquareGrid(libraryItems)); }} onAddToLibrary={deselectItems} setAppState={setAppState} libraryReturnUrl={appProps.libraryReturnUrl} library={library} id={id} appState={appState} selectedItems={selectedItems} onSelectItems={setSelectedItems} /> ); };