UNPKG

tldraw

Version:

A tiny little drawing editor.

226 lines (225 loc) • 8.3 kB
import { Fragment, jsx, jsxs } from "react/jsx-runtime"; import { DEFAULT_SUPPORTED_IMAGE_TYPES, DEFAULT_SUPPORT_VIDEO_TYPES, TldrawEditor, defaultUserPreferences, mergeArraysAndReplaceDefaults, useEditor, useEditorComponents, useOnMount, useShallowArrayIdentity, useShallowObjectIdentity } from "@tldraw/editor"; import { useMemo } from "react"; import { TldrawHandles } from "./canvas/TldrawHandles.mjs"; import { TldrawOverlays } from "./canvas/TldrawOverlays.mjs"; import { TldrawScribble } from "./canvas/TldrawScribble.mjs"; import { TldrawSelectionForeground } from "./canvas/TldrawSelectionForeground.mjs"; import { TldrawShapeIndicators } from "./canvas/TldrawShapeIndicators.mjs"; import { defaultBindingUtils } from "./defaultBindingUtils.mjs"; import { registerDefaultExternalContentHandlers } from "./defaultExternalContentHandlers.mjs"; import { defaultShapeTools } from "./defaultShapeTools.mjs"; import { defaultShapeUtils } from "./defaultShapeUtils.mjs"; import { registerDefaultSideEffects } from "./defaultSideEffects.mjs"; import { defaultTools } from "./defaultTools.mjs"; import { EmbedShapeUtil } from "./shapes/embed/EmbedShapeUtil.mjs"; import { allDefaultFontFaces } from "./shapes/shared/defaultFonts.mjs"; import { TldrawUi, TldrawUiInFrontOfTheCanvas } from "./ui/TldrawUi.mjs"; import { useDefaultUiAssetUrlsWithOverrides } from "./ui/assetUrls.mjs"; import { LoadingScreen } from "./ui/components/LoadingScreen.mjs"; import { Spinner } from "./ui/components/Spinner.mjs"; import { AssetUrlsProvider } from "./ui/context/asset-urls.mjs"; import { useTldrawUiComponents } from "./ui/context/components.mjs"; import { useUiEvents } from "./ui/context/events.mjs"; import { useToasts } from "./ui/context/toasts.mjs"; import { TldrawUiTranslationProvider, useTranslation } from "./ui/hooks/useTranslation/useTranslation.mjs"; import { useMergedTranslationOverrides } from "./ui/overrides.mjs"; import { useDefaultEditorAssetsWithOverrides } from "./utils/static-assets/assetUrls.mjs"; import { defaultAddFontsFromNode, tipTapDefaultExtensions } from "./utils/text/richText.mjs"; const allDefaultTools = [...defaultTools, ...defaultShapeTools]; function Tldraw(props) { const { children, maxImageDimension, maxAssetSize, acceptedImageMimeTypes, acceptedVideoMimeTypes, onMount, components = {}, shapeUtils = [], bindingUtils = [], tools = [], // needs to be here for backwards compatibility // eslint-disable-next-line @typescript-eslint/no-deprecated embeds, options, // needs to be here for backwards compatibility with TldrawEditor // eslint-disable-next-line @typescript-eslint/no-deprecated textOptions: _textOptions, ...rest } = props; const _components = useShallowObjectIdentity(components); const CustomInFrontOfTheCanvas = components?.InFrontOfTheCanvas; const InFrontOfTheCanvas = useMemo(() => { if (rest.hideUi) return CustomInFrontOfTheCanvas ?? null; if (!CustomInFrontOfTheCanvas) return TldrawUiInFrontOfTheCanvas; return () => /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx(TldrawUiInFrontOfTheCanvas, {}), /* @__PURE__ */ jsx(CustomInFrontOfTheCanvas, {}) ] }); }, [rest.hideUi, CustomInFrontOfTheCanvas]); const componentsWithDefault = useMemo( () => ({ Scribble: TldrawScribble, ShapeIndicators: TldrawShapeIndicators, CollaboratorScribble: TldrawScribble, SelectionForeground: TldrawSelectionForeground, Handles: TldrawHandles, Overlays: TldrawOverlays, Spinner, LoadingScreen, ..._components, InFrontOfTheCanvas }), [_components, InFrontOfTheCanvas] ); const _shapeUtils = useShallowArrayIdentity(shapeUtils); const shapeUtilsWithDefaults = useMemo( () => mergeArraysAndReplaceDefaults("type", _shapeUtils, defaultShapeUtils), [_shapeUtils] ); const _bindingUtils = useShallowArrayIdentity(bindingUtils); const bindingUtilsWithDefaults = useMemo( () => mergeArraysAndReplaceDefaults("type", _bindingUtils, defaultBindingUtils), [_bindingUtils] ); const _tools = useShallowArrayIdentity(tools); const toolsWithDefaults = useMemo( () => mergeArraysAndReplaceDefaults("id", _tools, allDefaultTools), [_tools] ); const _imageMimeTypes = useShallowArrayIdentity( acceptedImageMimeTypes ?? DEFAULT_SUPPORTED_IMAGE_TYPES ); const _videoMimeTypes = useShallowArrayIdentity( acceptedVideoMimeTypes ?? DEFAULT_SUPPORT_VIDEO_TYPES ); const _mergedTextOptions = options?.text ?? _textOptions; const textOptionsWithDefaults = useMemo(() => { return { addFontsFromNode: defaultAddFontsFromNode, ..._mergedTextOptions, tipTapConfig: { extensions: tipTapDefaultExtensions, ..._mergedTextOptions?.tipTapConfig } }; }, [_mergedTextOptions]); const optionsWithDefaults = useMemo( () => ({ ...options, text: textOptionsWithDefaults }), [options, textOptionsWithDefaults] ); const mediaMimeTypes = useMemo( () => [..._imageMimeTypes, ..._videoMimeTypes], [_imageMimeTypes, _videoMimeTypes] ); const assets = useDefaultEditorAssetsWithOverrides(rest.assetUrls); const embedShapeUtil = shapeUtilsWithDefaults.find((util) => util.type === "embed"); if (embedShapeUtil && embeds) { EmbedShapeUtil.setEmbedDefinitions(embeds); } return ( // We provide an extra higher layer of asset+translations providers here so that // loading UI (which is rendered outside of TldrawUi) may be translated. // Ideally we would refactor to hoist all the UI context providers we can up here. Maybe later. /* @__PURE__ */ (jsx( AssetUrlsProvider, { assetUrls: useDefaultUiAssetUrlsWithOverrides(rest.assetUrls), children: /* @__PURE__ */ jsx( TldrawUiTranslationProvider, { overrides: useMergedTranslationOverrides(rest.overrides), locale: rest.user?.userPreferences.get().locale ?? defaultUserPreferences.locale, children: /* @__PURE__ */ jsx( TldrawEditor, { initialState: "select", ...rest, components: componentsWithDefault, shapeUtils: shapeUtilsWithDefaults, bindingUtils: bindingUtilsWithDefaults, tools: toolsWithDefaults, options: optionsWithDefaults, assetUrls: assets, children: /* @__PURE__ */ jsxs(TldrawUi, { ...rest, components: componentsWithDefault, mediaMimeTypes, children: [ /* @__PURE__ */ jsx( InsideOfEditorAndUiContext, { maxImageDimension, maxAssetSize, acceptedImageMimeTypes: _imageMimeTypes, acceptedVideoMimeTypes: _videoMimeTypes, onMount } ), children ] }) } ) } ) } )) ); } function InsideOfEditorAndUiContext({ maxImageDimension, maxAssetSize, acceptedImageMimeTypes, acceptedVideoMimeTypes, onMount }) { const editor = useEditor(); const toasts = useToasts(); const msg = useTranslation(); const trackEvent = useUiEvents(); useOnMount(() => { const unsubs = []; unsubs.push(registerDefaultSideEffects(editor)); editor.fonts.requestFonts(allDefaultFontFaces); editor.once("edit", () => trackEvent("edit", { source: "unknown" })); registerDefaultExternalContentHandlers(editor, { maxImageDimension, maxAssetSize, acceptedImageMimeTypes, acceptedVideoMimeTypes, toasts, msg }); unsubs.push(editor.store.props.onMount(editor)); unsubs.push(onMount?.(editor)); return () => { unsubs.forEach((fn) => fn?.()); }; }); const { Canvas } = useEditorComponents(); const { ContextMenu } = useTldrawUiComponents(); if (ContextMenu) { return /* @__PURE__ */ jsx(ContextMenu, {}); } if (Canvas) { return /* @__PURE__ */ jsx(Canvas, {}); } return null; } export { Tldraw }; //# sourceMappingURL=Tldraw.mjs.map