tldraw
Version:
A tiny little drawing editor.
178 lines (177 loc) • 5.86 kB
JavaScript
import { jsx, jsxs } from "react/jsx-runtime";
import {
DEFAULT_SUPPORTED_IMAGE_TYPES,
DEFAULT_SUPPORT_VIDEO_TYPES,
TldrawEditor,
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 } from "./ui/TldrawUi.mjs";
import { LoadingScreen } from "./ui/components/LoadingScreen.mjs";
import { Spinner } from "./ui/components/Spinner.mjs";
import { useTldrawUiComponents } from "./ui/context/components.mjs";
import { useToasts } from "./ui/context/toasts.mjs";
import { useTranslation } from "./ui/hooks/useTranslation/useTranslation.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 = [],
embeds,
textOptions,
...rest
} = props;
const _components = useShallowObjectIdentity(components);
const componentsWithDefault = useMemo(
() => ({
Scribble: TldrawScribble,
ShapeIndicators: TldrawShapeIndicators,
CollaboratorScribble: TldrawScribble,
SelectionForeground: TldrawSelectionForeground,
Handles: TldrawHandles,
Overlays: TldrawOverlays,
Spinner,
LoadingScreen,
..._components
}),
[_components]
);
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", allDefaultTools, _tools),
[_tools]
);
const _imageMimeTypes = useShallowArrayIdentity(
acceptedImageMimeTypes ?? DEFAULT_SUPPORTED_IMAGE_TYPES
);
const _videoMimeTypes = useShallowArrayIdentity(
acceptedVideoMimeTypes ?? DEFAULT_SUPPORT_VIDEO_TYPES
);
const textOptionsWithDefaults = useMemo(() => {
return {
addFontsFromNode: defaultAddFontsFromNode,
...textOptions,
tipTapConfig: {
extensions: tipTapDefaultExtensions,
...textOptions?.tipTapConfig
}
};
}, [textOptions]);
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 /* @__PURE__ */ jsx(
TldrawEditor,
{
initialState: "select",
...rest,
components: componentsWithDefault,
shapeUtils: shapeUtilsWithDefaults,
bindingUtils: bindingUtilsWithDefaults,
tools: toolsWithDefaults,
textOptions: textOptionsWithDefaults,
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();
useOnMount(() => {
const unsubs = [];
unsubs.push(registerDefaultSideEffects(editor));
editor.fonts.requestFonts(allDefaultFontFaces);
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