aboutsummaryrefslogtreecommitdiffstats
path: root/packages/excalidraw/hooks/useLibraryItemSvg.ts
diff options
context:
space:
mode:
authorkj_sh6042026-03-15 16:19:35 -0400
committerkj_sh6042026-03-15 16:19:35 -0400
commit6ec259a0e71174651bae95d4628138bf6fd68742 (patch)
tree5e33c6a5ec091ecabfcb257fdc7b6a88ed8754ac /packages/excalidraw/hooks/useLibraryItemSvg.ts
parent16c8578b15c727f22921f8a80a56ee4d4e7f2272 (diff)
refactor: packages/
Diffstat (limited to 'packages/excalidraw/hooks/useLibraryItemSvg.ts')
-rw-r--r--packages/excalidraw/hooks/useLibraryItemSvg.ts79
1 files changed, 79 insertions, 0 deletions
diff --git a/packages/excalidraw/hooks/useLibraryItemSvg.ts b/packages/excalidraw/hooks/useLibraryItemSvg.ts
new file mode 100644
index 0000000..72b648d
--- /dev/null
+++ b/packages/excalidraw/hooks/useLibraryItemSvg.ts
@@ -0,0 +1,79 @@
+import { useEffect, useState } from "react";
+import { COLOR_PALETTE } from "../colors";
+import { atom, useAtom } from "../editor-jotai";
+import { exportToSvg } from "@excalidraw/utils/export";
+import type { LibraryItem } from "../types";
+
+export type SvgCache = Map<LibraryItem["id"], SVGSVGElement>;
+
+export const libraryItemSvgsCache = atom<SvgCache>(new Map());
+
+const exportLibraryItemToSvg = async (elements: LibraryItem["elements"]) => {
+ return await exportToSvg({
+ elements,
+ appState: {
+ exportBackground: false,
+ viewBackgroundColor: COLOR_PALETTE.white,
+ },
+ files: null,
+ renderEmbeddables: false,
+ skipInliningFonts: true,
+ });
+};
+
+export const useLibraryItemSvg = (
+ id: LibraryItem["id"] | null,
+ elements: LibraryItem["elements"] | undefined,
+ svgCache: SvgCache,
+): SVGSVGElement | undefined => {
+ const [svg, setSvg] = useState<SVGSVGElement>();
+
+ useEffect(() => {
+ if (elements) {
+ if (id) {
+ // Try to load cached svg
+ const cachedSvg = svgCache.get(id);
+
+ if (cachedSvg) {
+ setSvg(cachedSvg);
+ } else {
+ // When there is no svg in cache export it and save to cache
+ (async () => {
+ const exportedSvg = await exportLibraryItemToSvg(elements);
+ // TODO: should likely be removed for custom fonts
+ exportedSvg.querySelector(".style-fonts")?.remove();
+
+ if (exportedSvg) {
+ svgCache.set(id, exportedSvg);
+ setSvg(exportedSvg);
+ }
+ })();
+ }
+ } else {
+ // When we have no id (usualy selected items from canvas) just export the svg
+ (async () => {
+ const exportedSvg = await exportLibraryItemToSvg(elements);
+ setSvg(exportedSvg);
+ })();
+ }
+ }
+ }, [id, elements, svgCache, setSvg]);
+
+ return svg;
+};
+
+export const useLibraryCache = () => {
+ const [svgCache] = useAtom(libraryItemSvgsCache);
+
+ const clearLibraryCache = () => svgCache.clear();
+
+ const deleteItemsFromLibraryCache = (items: LibraryItem["id"][]) => {
+ items.forEach((item) => svgCache.delete(item));
+ };
+
+ return {
+ clearLibraryCache,
+ deleteItemsFromLibraryCache,
+ svgCache,
+ };
+};