|
|
|
@ -118,70 +118,83 @@ const LibraryMenuItems = ({
|
|
|
|
|
let addedPendingElements = false;
|
|
|
|
|
|
|
|
|
|
rows.push(
|
|
|
|
|
<Stack.Row
|
|
|
|
|
align="center"
|
|
|
|
|
gap={1}
|
|
|
|
|
key={"actions"}
|
|
|
|
|
style={{ padding: "2px 0" }}
|
|
|
|
|
>
|
|
|
|
|
<ToolButton
|
|
|
|
|
key="import"
|
|
|
|
|
type="button"
|
|
|
|
|
title={t("buttons.load")}
|
|
|
|
|
aria-label={t("buttons.load")}
|
|
|
|
|
icon={load}
|
|
|
|
|
<>
|
|
|
|
|
<a
|
|
|
|
|
className="browse-libraries"
|
|
|
|
|
href="https://libraries.excalidraw.com"
|
|
|
|
|
target="_excalidraw_libraries"
|
|
|
|
|
onClick={() => {
|
|
|
|
|
importLibraryFromJSON()
|
|
|
|
|
.then(() => {
|
|
|
|
|
// Maybe we should close and open the menu so that the items get updated.
|
|
|
|
|
// But for now we just close the menu.
|
|
|
|
|
setAppState({ isLibraryOpen: false });
|
|
|
|
|
})
|
|
|
|
|
.catch(muteFSAbortError)
|
|
|
|
|
.catch((error) => {
|
|
|
|
|
setAppState({ errorMessage: error.message });
|
|
|
|
|
});
|
|
|
|
|
trackEvent(EVENT_EXIT, "libraries");
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
<ToolButton
|
|
|
|
|
key="export"
|
|
|
|
|
type="button"
|
|
|
|
|
title={t("buttons.export")}
|
|
|
|
|
aria-label={t("buttons.export")}
|
|
|
|
|
icon={exportFile}
|
|
|
|
|
onClick={() => {
|
|
|
|
|
saveLibraryAsJSON()
|
|
|
|
|
.catch(muteFSAbortError)
|
|
|
|
|
.catch((error) => {
|
|
|
|
|
setAppState({ errorMessage: error.message });
|
|
|
|
|
});
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
</Stack.Row>,
|
|
|
|
|
>
|
|
|
|
|
{t("labels.libraries")}
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
<Stack.Row
|
|
|
|
|
align="center"
|
|
|
|
|
gap={1}
|
|
|
|
|
key={"actions"}
|
|
|
|
|
style={{ padding: "2px 0" }}
|
|
|
|
|
>
|
|
|
|
|
<ToolButton
|
|
|
|
|
key="import"
|
|
|
|
|
type="button"
|
|
|
|
|
title={t("buttons.load")}
|
|
|
|
|
aria-label={t("buttons.load")}
|
|
|
|
|
icon={load}
|
|
|
|
|
onClick={() => {
|
|
|
|
|
importLibraryFromJSON()
|
|
|
|
|
.then(() => {
|
|
|
|
|
// Maybe we should close and open the menu so that the items get updated.
|
|
|
|
|
// But for now we just close the menu.
|
|
|
|
|
setAppState({ isLibraryOpen: false });
|
|
|
|
|
})
|
|
|
|
|
.catch(muteFSAbortError)
|
|
|
|
|
.catch((error) => {
|
|
|
|
|
setAppState({ errorMessage: error.message });
|
|
|
|
|
});
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
<ToolButton
|
|
|
|
|
key="export"
|
|
|
|
|
type="button"
|
|
|
|
|
title={t("buttons.export")}
|
|
|
|
|
aria-label={t("buttons.export")}
|
|
|
|
|
icon={exportFile}
|
|
|
|
|
onClick={() => {
|
|
|
|
|
saveLibraryAsJSON()
|
|
|
|
|
.catch(muteFSAbortError)
|
|
|
|
|
.catch((error) => {
|
|
|
|
|
setAppState({ errorMessage: error.message });
|
|
|
|
|
});
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
</Stack.Row>
|
|
|
|
|
</>,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
for (let row = 0; row < numRows; row++) {
|
|
|
|
|
const i = CELLS_PER_ROW * row;
|
|
|
|
|
const y = CELLS_PER_ROW * row;
|
|
|
|
|
const children = [];
|
|
|
|
|
for (let j = 0; j < CELLS_PER_ROW; j++) {
|
|
|
|
|
for (let x = 0; x < CELLS_PER_ROW; x++) {
|
|
|
|
|
const shouldAddPendingElements: boolean =
|
|
|
|
|
pendingElements.length > 0 &&
|
|
|
|
|
!addedPendingElements &&
|
|
|
|
|
i + j >= library.length;
|
|
|
|
|
y + x >= library.length;
|
|
|
|
|
addedPendingElements = addedPendingElements || shouldAddPendingElements;
|
|
|
|
|
|
|
|
|
|
children.push(
|
|
|
|
|
<Stack.Col key={j}>
|
|
|
|
|
<Stack.Col key={x}>
|
|
|
|
|
<LibraryUnit
|
|
|
|
|
elements={library[i + j]}
|
|
|
|
|
elements={library[y + x]}
|
|
|
|
|
pendingElements={
|
|
|
|
|
shouldAddPendingElements ? pendingElements : undefined
|
|
|
|
|
}
|
|
|
|
|
onRemoveFromLibrary={onRemoveFromLibrary.bind(null, i + j)}
|
|
|
|
|
onRemoveFromLibrary={onRemoveFromLibrary.bind(null, y + x)}
|
|
|
|
|
onClick={
|
|
|
|
|
shouldAddPendingElements
|
|
|
|
|
? onAddToLibrary.bind(null, pendingElements)
|
|
|
|
|
: onInsertShape.bind(null, library[i + j])
|
|
|
|
|
: onInsertShape.bind(null, library[y + x])
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
</Stack.Col>,
|
|
|
|
|