UNPKG

tldraw

Version:

A tiny little drawing editor.

138 lines (137 loc) 3.96 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 { useDefaultEditorAssetsWithOverrides } from "./utils/static-assets/assetUrls.mjs"; import { defaultAddFontsFromNode, tipTapDefaultExtensions } from "./utils/text/richText.mjs"; const defaultOptions = { text: { 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, options: _options, // eslint-disable-next-line @typescript-eslint/no-deprecated textOptions: _textOptions } = props; const options = useMemo( () => ({ ...defaultOptions, ..._options, text: { ...defaultOptions.text, ...(_options?.text ?? _textOptions) } }), [_options, _textOptions] ); const assetUrlsWithOverrides = useDefaultEditorAssetsWithOverrides(assetUrls); 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: assetUrlsWithOverrides.fonts, options }); if (pageId) editor.setCurrentPage(pageId); const shapeIds = editor.getCurrentPageShapeIds(); async function setSvg() { await editor.fonts.loadRequiredFontsForCurrentPage(editor.options.maxFontsToLoadBeforeRender); 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, assetUrlsWithOverrides, options ]); 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