UNPKG

tldraw

Version:

A tiny little drawing editor.

8 lines (7 loc) • 7.84 kB
{ "version": 3, "sources": ["../../src/lib/TldrawImage.tsx"], "sourcesContent": ["import {\n\tDefaultSpinner,\n\tEditor,\n\tErrorScreen,\n\tLoadingScreen,\n\tTLAnyBindingUtilConstructor,\n\tTLAnyShapeUtilConstructor,\n\tTLEditorSnapshot,\n\tTLImageExportOptions,\n\tTLPageId,\n\tTLStoreSnapshot,\n\tuseShallowArrayIdentity,\n\tuseTLStore,\n} from '@tldraw/editor'\nimport { memo, useLayoutEffect, useMemo, useState } from 'react'\nimport { defaultBindingUtils } from './defaultBindingUtils'\nimport { defaultShapeUtils } from './defaultShapeUtils'\nimport { TLUiAssetUrlOverrides } from './ui/assetUrls'\nimport { usePreloadAssets } from './ui/hooks/usePreloadAssets'\nimport { getSvgAsImage } from './utils/export/export'\nimport { useDefaultEditorAssetsWithOverrides } from './utils/static-assets/assetUrls'\n\n/** @public */\nexport interface TldrawImageProps extends TLImageExportOptions {\n\t/**\n\t * The snapshot to display.\n\t */\n\tsnapshot: Partial<TLEditorSnapshot> | TLStoreSnapshot\n\n\t/**\n\t * The image format to use. Defaults to 'svg'.\n\t */\n\tformat?: 'svg' | 'png'\n\n\t/**\n\t * The page to display. Defaults to the first page.\n\t */\n\tpageId?: TLPageId\n\n\t/**\n\t * Additional shape utils to use.\n\t */\n\tshapeUtils?: readonly TLAnyShapeUtilConstructor[]\n\t/**\n\t * Additional binding utils to use.\n\t */\n\tbindingUtils?: readonly TLAnyBindingUtilConstructor[]\n\t/**\n\t * The license key.\n\t */\n\tlicenseKey?: string\n\t/**\n\t * Asset URL overrides.\n\t */\n\tassetUrls?: TLUiAssetUrlOverrides\n}\n\n/**\n * A renderered SVG image of a Tldraw snapshot.\n *\n * @example\n * ```tsx\n * <TldrawImage\n * \tsnapshot={snapshot}\n * \tpageId={pageId}\n * \tbackground={false}\n * darkMode={true}\n * bounds={new Box(0,0,600,400)}\n * scale={1}\n * />\n * ```\n *\n * @public\n * @react\n */\nexport const TldrawImage = memo(function TldrawImage(props: TldrawImageProps) {\n\tconst [url, setUrl] = useState<string | null>(null)\n\tconst [container, setContainer] = useState<HTMLDivElement | null>(null)\n\n\tconst shapeUtils = useShallowArrayIdentity(props.shapeUtils ?? [])\n\tconst shapeUtilsWithDefaults = useMemo(() => [...defaultShapeUtils, ...shapeUtils], [shapeUtils])\n\tconst bindingUtils = useShallowArrayIdentity(props.bindingUtils ?? [])\n\tconst bindingUtilsWithDefaults = useMemo(\n\t\t() => [...defaultBindingUtils, ...bindingUtils],\n\t\t[bindingUtils]\n\t)\n\tconst store = useTLStore({ snapshot: props.snapshot, shapeUtils: shapeUtilsWithDefaults })\n\n\tconst assets = useDefaultEditorAssetsWithOverrides(props.assetUrls)\n\tconst { done: preloadingComplete, error: preloadingError } = usePreloadAssets(assets)\n\n\tconst {\n\t\tpageId,\n\t\tbounds,\n\t\tscale,\n\t\tpixelRatio,\n\t\tbackground,\n\t\tpadding,\n\t\tdarkMode,\n\t\tpreserveAspectRatio,\n\t\tformat = 'svg',\n\t\tlicenseKey,\n\t} = props\n\n\tuseLayoutEffect(() => {\n\t\tif (!container) return\n\t\tif (!store) return\n\t\tif (!preloadingComplete) return\n\n\t\tlet isCancelled = false\n\n\t\tconst tempElm = document.createElement('div')\n\t\tcontainer.appendChild(tempElm)\n\t\tcontainer.classList.add('tl-container', 'tl-theme__light')\n\n\t\tconst editor = new Editor({\n\t\t\tstore,\n\t\t\tshapeUtils: shapeUtilsWithDefaults,\n\t\t\tbindingUtils: bindingUtilsWithDefaults,\n\t\t\ttools: [],\n\t\t\tgetContainer: () => tempElm,\n\t\t\tlicenseKey,\n\t\t})\n\n\t\tif (pageId) editor.setCurrentPage(pageId)\n\n\t\tconst shapeIds = editor.getCurrentPageShapeIds()\n\n\t\tasync function setSvg() {\n\t\t\tconst svgResult = await editor.getSvgString([...shapeIds], {\n\t\t\t\tbounds,\n\t\t\t\tscale,\n\t\t\t\tbackground,\n\t\t\t\tpadding,\n\t\t\t\tdarkMode,\n\t\t\t\tpreserveAspectRatio,\n\t\t\t})\n\n\t\t\tif (svgResult && !isCancelled) {\n\t\t\t\tif (format === 'svg') {\n\t\t\t\t\tif (!isCancelled) {\n\t\t\t\t\t\tconst blob = new Blob([svgResult.svg], { type: 'image/svg+xml' })\n\t\t\t\t\t\tconst url = URL.createObjectURL(blob)\n\t\t\t\t\t\tsetUrl(url)\n\t\t\t\t\t}\n\t\t\t\t} else if (format === 'png') {\n\t\t\t\t\tconst blob = await getSvgAsImage(editor, svgResult.svg, {\n\t\t\t\t\t\ttype: format,\n\t\t\t\t\t\twidth: svgResult.width,\n\t\t\t\t\t\theight: svgResult.height,\n\t\t\t\t\t\tpixelRatio,\n\t\t\t\t\t})\n\t\t\t\t\tif (blob && !isCancelled) {\n\t\t\t\t\t\tconst url = URL.createObjectURL(blob)\n\t\t\t\t\t\tsetUrl(url)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\teditor.dispose()\n\t\t}\n\n\t\tsetSvg()\n\n\t\treturn () => {\n\t\t\tisCancelled = true\n\t\t}\n\t}, [\n\t\tformat,\n\t\tcontainer,\n\t\tstore,\n\t\tshapeUtilsWithDefaults,\n\t\tbindingUtilsWithDefaults,\n\t\tpageId,\n\t\tbounds,\n\t\tscale,\n\t\tbackground,\n\t\tpadding,\n\t\tdarkMode,\n\t\tpreserveAspectRatio,\n\t\tpreloadingComplete,\n\t\tpreloadingError,\n\t\tlicenseKey,\n\t\tpixelRatio,\n\t])\n\n\tif (preloadingError) {\n\t\treturn <ErrorScreen>Could not load assets.</ErrorScreen>\n\t}\n\n\tif (!preloadingComplete) {\n\t\treturn (\n\t\t\t<LoadingScreen>\n\t\t\t\t<DefaultSpinner />\n\t\t\t</LoadingScreen>\n\t\t)\n\t}\n\n\treturn (\n\t\t<div ref={setContainer} style={{ position: 'relative', width: '100%', height: '100%' }}>\n\t\t\t{url && (\n\t\t\t\t<img\n\t\t\t\t\tsrc={url}\n\t\t\t\t\treferrerPolicy=\"strict-origin-when-cross-origin\"\n\t\t\t\t\tstyle={{ width: '100%', height: '100%' }}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</div>\n\t)\n})\n"], "mappings": "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", "names": ["TldrawImage", "url"] }