UNPKG

tldraw

Version:

A tiny little drawing editor.

120 lines (119 loc) 3.35 kB
import { jsx } from "react/jsx-runtime"; import { Editor, mergeArraysAndReplaceDefaults, useShallowArrayIdentity, useTLStore } from "@tldraw/editor"; import { memo, useEffect, useLayoutEffect, useMemo, useState } from "react"; import { defaultBindingUtils } from "./defaultBindingUtils.mjs"; import { defaultShapeUtils } from "./defaultShapeUtils.mjs"; import { defaultAddFontsFromNode, tipTapDefaultExtensions } from "./utils/text/richText.mjs"; const defaultTextOptions = { tipTapConfig: { extensions: tipTapDefaultExtensions }, addFontsFromNode: defaultAddFontsFromNode }; const TldrawImage = memo(function TldrawImage2(props) { const [url, setUrl] = useState(null); const [container, setContainer] = useState(null); const _shapeUtils = useShallowArrayIdentity(props.shapeUtils ?? []); const shapeUtilsWithDefaults = useMemo( () => mergeArraysAndReplaceDefaults("type", _shapeUtils, defaultShapeUtils), [_shapeUtils] ); const _bindingUtils = useShallowArrayIdentity(props.bindingUtils ?? []); const bindingUtilsWithDefaults = useMemo( () => mergeArraysAndReplaceDefaults("type", _bindingUtils, defaultBindingUtils), [_bindingUtils] ); const store = useTLStore({ snapshot: props.snapshot, shapeUtils: shapeUtilsWithDefaults }); const { pageId, bounds, scale, pixelRatio, background, padding, darkMode, preserveAspectRatio, format = "svg", licenseKey, assetUrls, textOptions = defaultTextOptions } = props; useLayoutEffect(() => { if (!container) return; if (!store) return; let isCancelled = false; const tempElm = document.createElement("div"); container.appendChild(tempElm); container.classList.add("tl-container", "tl-theme__light"); const editor = new Editor({ store, shapeUtils: shapeUtilsWithDefaults, bindingUtils: bindingUtilsWithDefaults, tools: [], getContainer: () => tempElm, licenseKey, fontAssetUrls: assetUrls?.fonts, textOptions }); if (pageId) editor.setCurrentPage(pageId); const shapeIds = editor.getCurrentPageShapeIds(); async function setSvg() { const imageResult = await editor.toImage([...shapeIds], { bounds, scale, background, padding, darkMode, preserveAspectRatio, format }); if (!imageResult || isCancelled) return; const url2 = URL.createObjectURL(imageResult.blob); setUrl(url2); editor.dispose(); } setSvg(); return () => { isCancelled = true; }; }, [ format, container, store, shapeUtilsWithDefaults, bindingUtilsWithDefaults, pageId, bounds, scale, background, padding, darkMode, preserveAspectRatio, licenseKey, pixelRatio, assetUrls, textOptions ]); useEffect(() => { return () => { if (url) URL.revokeObjectURL(url); }; }, [url]); return /* @__PURE__ */ jsx("div", { ref: setContainer, style: { position: "relative", width: "100%", height: "100%" }, children: url && /* @__PURE__ */ jsx( "img", { src: url, referrerPolicy: "strict-origin-when-cross-origin", style: { width: "100%", height: "100%" } } ) }); }); export { TldrawImage }; //# sourceMappingURL=TldrawImage.mjs.map