@tldraw/editor 5.5.0-canary.a86abb0a5fca → 5.5.0-canary.aceb23a4d18f

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist-cjs/index.js +1 -1
  2. package/dist-cjs/lib/TldrawEditor.js +13 -10
  3. package/dist-cjs/lib/TldrawEditor.js.map +2 -2
  4. package/dist-cjs/lib/components/MenuClickCapture.js +42 -3
  5. package/dist-cjs/lib/components/MenuClickCapture.js.map +2 -2
  6. package/dist-cjs/lib/editor/Editor.js +16 -6
  7. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  8. package/dist-cjs/lib/hooks/useCanvasEvents.js +24 -0
  9. package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
  10. package/dist-cjs/lib/hooks/useIdentity.js +6 -2
  11. package/dist-cjs/lib/hooks/useIdentity.js.map +3 -3
  12. package/dist-cjs/lib/utils/deepLinks.js +2 -1
  13. package/dist-cjs/lib/utils/deepLinks.js.map +2 -2
  14. package/dist-cjs/version.js +3 -3
  15. package/dist-cjs/version.js.map +1 -1
  16. package/dist-esm/index.mjs +1 -1
  17. package/dist-esm/lib/TldrawEditor.mjs +14 -11
  18. package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
  19. package/dist-esm/lib/components/MenuClickCapture.mjs +42 -3
  20. package/dist-esm/lib/components/MenuClickCapture.mjs.map +2 -2
  21. package/dist-esm/lib/editor/Editor.mjs +16 -6
  22. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  23. package/dist-esm/lib/hooks/useCanvasEvents.mjs +24 -0
  24. package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
  25. package/dist-esm/lib/hooks/useIdentity.mjs +7 -3
  26. package/dist-esm/lib/hooks/useIdentity.mjs.map +3 -3
  27. package/dist-esm/lib/utils/deepLinks.mjs +2 -1
  28. package/dist-esm/lib/utils/deepLinks.mjs.map +2 -2
  29. package/dist-esm/version.mjs +3 -3
  30. package/dist-esm/version.mjs.map +1 -1
  31. package/editor.css +9 -1
  32. package/package.json +8 -11
  33. package/src/lib/TldrawEditor.tsx +19 -13
  34. package/src/lib/components/MenuClickCapture.tsx +55 -4
  35. package/src/lib/editor/Editor.ts +26 -7
  36. package/src/lib/hooks/useCanvasEvents.ts +42 -0
  37. package/src/lib/hooks/useIdentity.tsx +12 -1
  38. package/src/lib/utils/deepLinks.test.ts +15 -0
  39. package/src/lib/utils/deepLinks.ts +8 -3
  40. package/src/version.ts +3 -3
  41. package/dist-cjs/lib/primitives/geometry/geometry.bench.js +0 -133
  42. package/dist-cjs/lib/primitives/geometry/geometry.bench.js.map +0 -7
  43. package/dist-esm/lib/primitives/geometry/geometry.bench.mjs +0 -132
  44. package/dist-esm/lib/primitives/geometry/geometry.bench.mjs.map +0 -7
  45. package/src/lib/primitives/geometry/geometry.bench.ts +0 -179
package/dist-cjs/index.js CHANGED
@@ -392,7 +392,7 @@ var import_uniq = require("./lib/utils/uniq");
392
392
  var import_defaultThemes2 = require("./lib/editor/managers/ThemeManager/defaultThemes");
393
393
  (0, import_utils.registerTldrawLibraryVersion)(
394
394
  "@tldraw/editor",
395
- "5.5.0-canary.a86abb0a5fca",
395
+ "5.5.0-canary.aceb23a4d18f",
396
396
  "cjs"
397
397
  );
398
398
  //# sourceMappingURL=index.js.map
@@ -88,16 +88,19 @@ const TldrawEditor = (0, import_react.memo)(function TldrawEditor2({
88
88
  const [portalHost, setPortalHost] = (0, import_react.useState)(null);
89
89
  const user = (0, import_react.useMemo)(() => _user ?? (0, import_createTLCurrentUser.createTLCurrentUser)(), [_user]);
90
90
  const ErrorFallback = components?.ErrorFallback === void 0 ? import_DefaultErrorFallback.DefaultErrorFallback : components?.ErrorFallback;
91
- const mergedOptions = (0, import_react.useMemo)(() => {
92
- let result = _options;
93
- if (_textOptions) {
94
- result = { ...result, text: result?.text ?? _textOptions };
95
- }
96
- if (_deepLinks !== void 0) {
97
- result = { ...result, deepLinks: result?.deepLinks ?? _deepLinks };
98
- }
99
- return result;
100
- }, [_options, _textOptions, _deepLinks]);
91
+ const camera = (0, import_useIdentity.useDeepObjectIdentity)(_options?.camera);
92
+ const gridSteps = (0, import_useIdentity.useDeepObjectIdentity)(_options?.gridSteps);
93
+ const text = (0, import_useIdentity.useDeepObjectIdentity)(_options?.text ?? _textOptions);
94
+ const mergedDeepLinks = _options?.deepLinks ?? _deepLinks;
95
+ const deepLinkOptions = (0, import_useIdentity.useDeepObjectIdentity)(
96
+ mergedDeepLinks === true ? void 0 : mergedDeepLinks
97
+ );
98
+ const deepLinks = mergedDeepLinks === true ? true : deepLinkOptions;
99
+ let mergedOptions = _options;
100
+ if (camera !== void 0) mergedOptions = { ...mergedOptions, camera };
101
+ if (gridSteps !== void 0) mergedOptions = { ...mergedOptions, gridSteps };
102
+ if (text !== void 0) mergedOptions = { ...mergedOptions, text };
103
+ if (deepLinks !== void 0) mergedOptions = { ...mergedOptions, deepLinks };
101
104
  const withDefaults = {
102
105
  ...rest,
103
106
  shapeUtils: rest.shapeUtils ?? EMPTY_SHAPE_UTILS_ARRAY,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/lib/TldrawEditor.tsx"],
4
- "sourcesContent": ["import { MigrationSequence, Store } from '@tldraw/store'\nimport {\n\tTLShape,\n\tTLStore,\n\tTLStoreSnapshot,\n\tTLTheme,\n\tTLThemeId,\n\tTLThemes,\n\tregisterColorsFromThemes,\n\tregisterFontsFromThemes,\n} from '@tldraw/tlschema'\nimport { annotateError, Required } from '@tldraw/utils'\nimport classNames from 'classnames'\nimport React, {\n\tmemo,\n\tReactNode,\n\tuseCallback,\n\tuseEffect,\n\tuseLayoutEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n\tuseSyncExternalStore,\n} from 'react'\nimport { version } from '../version'\nimport { DefaultErrorFallback } from './components/default-components/DefaultErrorFallback'\nimport { EditorPortalProvider } from './components/EditorPortal'\nimport { OptionalErrorBoundary } from './components/ErrorBoundary'\nimport { createTLCurrentUser, TLCurrentUser } from './config/createTLCurrentUser'\nimport { TLStoreBaseOptions } from './config/createTLStore'\nimport { TLAnyAssetUtilConstructor } from './config/defaultAssets'\nimport { TLAnyBindingUtilConstructor } from './config/defaultBindings'\nimport { TLAnyShapeUtilConstructor } from './config/defaultShapes'\nimport { TLEditorSnapshot } from './config/TLEditorSnapshot'\nimport { Editor } from './editor/Editor'\nimport { resolveThemes } from './editor/managers/ThemeManager/ThemeManager'\nimport { TLAnyOverlayUtilConstructor } from './editor/overlays/OverlayUtil'\nimport { TLStateNodeConstructor } from './editor/tools/StateNode'\nimport { TLCameraOptions } from './editor/types/misc-types'\nimport { useEditorComponents } from './hooks/EditorComponentsContext'\nimport type { TLEditorComponents } from './hooks/EditorComponentsContext'\nimport { ContainerProvider, useContainer } from './hooks/useContainer'\nimport { useCursor } from './hooks/useCursor'\nimport { useDarkMode } from './hooks/useDarkMode'\nimport { EditorProvider, useEditor } from './hooks/useEditor'\nimport { EditorComponentsProvider } from './hooks/useEditorComponents'\nimport { useEvent } from './hooks/useEvent'\nimport { useForceUpdate } from './hooks/useForceUpdate'\nimport { useShallowObjectIdentity } from './hooks/useIdentity'\nimport { useLocalStore } from './hooks/useLocalStore'\nimport { useRefState } from './hooks/useRefState'\nimport { useStateAttribute } from './hooks/useStateAttribute'\nimport { useZoomCss } from './hooks/useZoomCss'\nimport { LicenseProvider, useLicenseContext } from './license/LicenseProvider'\nimport { Watermark } from './license/Watermark'\nimport { TldrawOptions } from './options'\nimport { TLDeepLinkOptions } from './utils/deepLinks'\nimport { getGlobalDocument, getGlobalWindow } from './utils/dom'\nimport { TLTextOptions } from './utils/richText'\nimport { TLStoreWithStatus } from './utils/sync/StoreWithStatus'\n\n/**\n * Props for the {@link tldraw#Tldraw} and {@link TldrawEditor} components, when passing in a\n * `TLStore` directly. If you would like tldraw to create a store for you, use\n * {@link TldrawEditorWithoutStoreProps}.\n *\n * @public\n */\nexport interface TldrawEditorWithStoreProps {\n\t/**\n\t * The store to use in the editor.\n\t */\n\tstore: TLStore | TLStoreWithStatus\n}\n\n/**\n * Props for the {@link tldraw#Tldraw} and {@link TldrawEditor} components, when not passing in a\n * `TLStore` directly. If you would like to pass in a store directly, use\n * {@link TldrawEditorWithStoreProps}.\n *\n * @public\n */\nexport interface TldrawEditorWithoutStoreProps extends TLStoreBaseOptions {\n\tstore?: undefined\n\n\t/**\n\t * Additional migrations to use in the store\n\t */\n\tmigrations?: readonly MigrationSequence[]\n\n\t/**\n\t * A starting snapshot of data to pre-populate the store. Do not supply both this and\n\t * `initialData`.\n\t */\n\tsnapshot?: TLEditorSnapshot | TLStoreSnapshot\n\n\t/**\n\t * If you would like to persist the store to the browser's local IndexedDB storage and sync it\n\t * across tabs, provide a key here. Each key represents a single tldraw document.\n\t */\n\tpersistenceKey?: string\n\n\tsessionId?: string\n}\n\n/** @public */\nexport type TldrawEditorStoreProps = TldrawEditorWithStoreProps | TldrawEditorWithoutStoreProps\n\n/**\n * Props for the {@link tldraw#Tldraw} and {@link TldrawEditor} components.\n *\n * @public\n **/\nexport type TldrawEditorProps = TldrawEditorBaseProps & TldrawEditorStoreProps\n\n/**\n * Base props for the {@link tldraw#Tldraw} and {@link TldrawEditor} components.\n *\n * @public\n */\nexport interface TldrawEditorBaseProps {\n\t/**\n\t * The component's children.\n\t */\n\tchildren?: ReactNode\n\n\t/**\n\t * An array of shape utils to use in the editor.\n\t */\n\tshapeUtils?: readonly TLAnyShapeUtilConstructor[]\n\n\t/**\n\t * An array of binding utils to use in the editor.\n\t */\n\tbindingUtils?: readonly TLAnyBindingUtilConstructor[]\n\n\t/**\n\t * An array of asset utils to use in the editor.\n\t */\n\tassetUtils?: readonly TLAnyAssetUtilConstructor[]\n\n\t/**\n\t * An array of overlay utils to use in the editor for canvas overlay UI elements.\n\t */\n\toverlayUtils?: readonly TLAnyOverlayUtilConstructor[]\n\n\t/**\n\t * An array of tools to add to the editor's state chart.\n\t */\n\ttools?: readonly TLStateNodeConstructor[]\n\n\t/**\n\t * Whether to automatically focus the editor when it mounts.\n\t */\n\tautoFocus?: boolean\n\n\t/**\n\t * Overrides for the editor's components, such as handles, collaborator cursors, etc.\n\t */\n\tcomponents?: TLEditorComponents\n\n\t/**\n\t * Called when the editor has mounted.\n\t */\n\tonMount?: TLOnMountHandler\n\n\t/**\n\t * The editor's initial state (usually the id of the first active tool).\n\t */\n\tinitialState?: string\n\n\t/**\n\t * A classname to pass to the editor's container.\n\t */\n\tclassName?: string\n\n\t/**\n\t * The user interacting with the editor.\n\t */\n\tuser?: TLCurrentUser\n\n\t/**\n\t * The editor's color scheme. Defaults to `'light'`.\n\t *\n\t * - `'light'` - Always use light mode.\n\t * - `'dark'` - Always use dark mode.\n\t * - `'system'` - Follow the OS color scheme preference.\n\t */\n\tcolorScheme?: 'light' | 'dark' | 'system'\n\n\t/**\n\t * Named themes for the editor.\n\t */\n\tthemes?: Partial<TLThemes>\n\n\t/**\n\t * The id of the initially active theme. Defaults to `'default'`.\n\t */\n\tinitialTheme?: TLThemeId\n\n\t/**\n\t * Camera options for the editor.\n\t *\n\t * @deprecated Use `options.cameraOptions` instead. This will be removed in a future release.\n\t */\n\tcameraOptions?: Partial<TLCameraOptions>\n\n\t/**\n\t * Options for the editor.\n\t */\n\toptions?: Partial<TldrawOptions>\n\n\t/**\n\t * Text options for the editor.\n\t *\n\t * @deprecated Use `options.text` instead. This prop will be removed in a future release.\n\t */\n\ttextOptions?: TLTextOptions\n\n\t/**\n\t * The license key.\n\t */\n\tlicenseKey?: string\n\n\t/**\n\t * Options for syncing the editor's camera state with the URL.\n\t *\n\t * @deprecated Use `options.deepLinks` instead. This prop will be removed in a future release.\n\t */\n\tdeepLinks?: true | TLDeepLinkOptions\n\n\t/**\n\t * Provides a way to hide shapes.\n\t *\n\t * Hidden shapes will not render in the editor, and they will not be eligible for hit test via\n\t * {@link @tldraw/editor#Editor.getShapeAtPoint} and {@link @tldraw/editor#Editor.getShapesAtPoint}. But otherwise they will\n\t * remain in the store and participate in all other operations.\n\t *\n\t * @example\n\t * ```ts\n\t * getShapeVisibility={(shape, editor) => shape.meta.hidden ? 'hidden' : 'inherit'}\n\t * ```\n\t *\n\t * - `'inherit' | undefined` - (default) The shape will be visible unless its parent is hidden.\n\t * - `'hidden'` - The shape will be hidden.\n\t * - `'visible'` - The shape will be visible.\n\t *\n\t * @param shape - The shape to check.\n\t * @param editor - The editor instance.\n\t */\n\tgetShapeVisibility?(\n\t\tshape: TLShape,\n\t\teditor: Editor\n\t): 'visible' | 'hidden' | 'inherit' | null | undefined\n\n\t/**\n\t * The URLs for the fonts to use in the editor.\n\t */\n\tassetUrls?: { fonts?: { [key: string]: string | undefined } }\n}\n\n/**\n * Called when the editor has mounted.\n * @example\n * ```ts\n * <Tldraw onMount={(editor) => editor.selectAll()} />\n * ```\n * @param editor - The editor instance.\n *\n * @public\n */\nexport type TLOnMountHandler = (editor: Editor) => (() => void | undefined) | undefined | void\n\ndeclare global {\n\tinterface Window {\n\t\ttldrawReady: boolean\n\t}\n}\n\nconst EMPTY_SHAPE_UTILS_ARRAY = [] as const\nconst EMPTY_BINDING_UTILS_ARRAY = [] as const\nconst EMPTY_ASSET_UTILS_ARRAY = [] as const\nconst EMPTY_TOOLS_ARRAY = [] as const\n/** @internal */\nexport const TL_CONTAINER_CLASS = 'tl-container'\n\n/** @public @react */\nexport const TldrawEditor = memo(function TldrawEditor({\n\tstore,\n\tcomponents,\n\tclassName,\n\tuser: _user,\n\toptions: _options,\n\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\ttextOptions: _textOptions,\n\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\tdeepLinks: _deepLinks,\n\t...rest\n}: TldrawEditorProps) {\n\t// Register custom colors and fonts before effects run. For external stores,\n\t// users should also pass themes to createTLStore so they are\n\t// registered before data is loaded into the store.\n\tconst resolvedThemes = resolveThemes(rest.themes)\n\tregisterColorsFromThemes(resolvedThemes)\n\tregisterFontsFromThemes(resolvedThemes)\n\n\tconst [container, setContainer] = useState<HTMLElement | null>(null)\n\tconst [portalHost, setPortalHost] = useState<HTMLElement | null>(null)\n\tconst user = useMemo(() => _user ?? createTLCurrentUser(), [_user])\n\n\tconst ErrorFallback =\n\t\tcomponents?.ErrorFallback === undefined ? DefaultErrorFallback : components?.ErrorFallback\n\n\t// Merge deprecated props with options\n\t// options values take precedence over the deprecated props\n\tconst mergedOptions = useMemo(() => {\n\t\tlet result = _options\n\t\tif (_textOptions) {\n\t\t\tresult = { ...result, text: result?.text ?? _textOptions }\n\t\t}\n\t\tif (_deepLinks !== undefined) {\n\t\t\tresult = { ...result, deepLinks: result?.deepLinks ?? _deepLinks }\n\t\t}\n\t\treturn result\n\t}, [_options, _textOptions, _deepLinks])\n\n\t// apply defaults. if you're using the bare @tldraw/editor package, we\n\t// default these to the \"tldraw zero\" configuration. We have different\n\t// defaults applied in tldraw.\n\tconst withDefaults = {\n\t\t...rest,\n\t\tshapeUtils: rest.shapeUtils ?? EMPTY_SHAPE_UTILS_ARRAY,\n\t\tbindingUtils: rest.bindingUtils ?? EMPTY_BINDING_UTILS_ARRAY,\n\t\tassetUtils: rest.assetUtils ?? EMPTY_ASSET_UTILS_ARRAY,\n\t\ttools: rest.tools ?? EMPTY_TOOLS_ARRAY,\n\t\tcomponents,\n\t\toptions: useShallowObjectIdentity(mergedOptions),\n\t}\n\n\treturn (\n\t\t<div\n\t\t\tref={setContainer}\n\t\t\tdata-tldraw={version}\n\t\t\tdraggable={false}\n\t\t\tclassName={classNames(`${TL_CONTAINER_CLASS} tl-theme__light`, className)}\n\t\t\ttabIndex={-1}\n\t\t\trole=\"application\"\n\t\t\taria-label={_options?.branding ?? 'tldraw'}\n\t\t>\n\t\t\t<OptionalErrorBoundary\n\t\t\t\tfallback={ErrorFallback}\n\t\t\t\tonError={(error) => annotateError(error, { tags: { origin: 'react.tldraw-before-app' } })}\n\t\t\t>\n\t\t\t\t{container && (\n\t\t\t\t\t<LicenseProvider licenseKey={rest.licenseKey}>\n\t\t\t\t\t\t<ContainerProvider container={container}>\n\t\t\t\t\t\t\t<EditorPortalProvider host={portalHost}>\n\t\t\t\t\t\t\t\t<EditorComponentsProvider overrides={components}>\n\t\t\t\t\t\t\t\t\t{store ? (\n\t\t\t\t\t\t\t\t\t\tstore instanceof Store ? (\n\t\t\t\t\t\t\t\t\t\t\t// Store is ready to go, whether externally synced or not\n\t\t\t\t\t\t\t\t\t\t\t<TldrawEditorWithReadyStore {...withDefaults} store={store} user={user} />\n\t\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t\t// Store is a synced store, so handle syncing stages internally\n\t\t\t\t\t\t\t\t\t\t\t<TldrawEditorWithLoadingStore {...withDefaults} store={store} user={user} />\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t// We have no store (it's undefined) so create one and possibly sync it\n\t\t\t\t\t\t\t\t\t\t<TldrawEditorWithOwnStore {...withDefaults} store={store} user={user} />\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</EditorComponentsProvider>\n\t\t\t\t\t\t\t</EditorPortalProvider>\n\t\t\t\t\t\t</ContainerProvider>\n\t\t\t\t\t</LicenseProvider>\n\t\t\t\t)}\n\t\t\t</OptionalErrorBoundary>\n\t\t\t{/* The host for <EditorPortal>, last among the container's children so that anything\n\t\t\t portaled through it lands after the canvas and the UI \u2014 behind the UI's \"skip to main\n\t\t\t content\" link in the tab order, which only works while nothing precedes it. */}\n\t\t\t<div className=\"tl-portal-host\" ref={setPortalHost} />\n\t\t</div>\n\t)\n})\n\nfunction TldrawEditorWithOwnStore(\n\tprops: Required<\n\t\tTldrawEditorProps & { store: undefined; user: TLCurrentUser },\n\t\t'shapeUtils' | 'bindingUtils' | 'assetUtils' | 'tools'\n\t>\n) {\n\tconst {\n\t\tdefaultName,\n\t\tsnapshot,\n\t\tinitialData,\n\t\tshapeUtils,\n\t\tbindingUtils,\n\t\tassetUtils,\n\t\tpersistenceKey,\n\t\tsessionId,\n\t\tuser,\n\t\tassets,\n\t\tusers,\n\t\tmigrations,\n\t\tthemes,\n\t} = props\n\n\tconst syncedStore = useLocalStore({\n\t\tshapeUtils,\n\t\tbindingUtils,\n\t\tassetUtils,\n\t\tinitialData,\n\t\tpersistenceKey,\n\t\tsessionId,\n\t\tdefaultName,\n\t\tsnapshot,\n\t\tassets,\n\t\tusers,\n\t\tmigrations,\n\t\tthemes,\n\t})\n\n\treturn <TldrawEditorWithLoadingStore {...props} store={syncedStore} user={user} />\n}\n\nconst TldrawEditorWithLoadingStore = memo(function TldrawEditorBeforeLoading({\n\tstore,\n\tuser,\n\t...rest\n}: Required<\n\tTldrawEditorProps & { store: TLStoreWithStatus; user: TLCurrentUser },\n\t'shapeUtils' | 'bindingUtils' | 'assetUtils' | 'tools'\n>) {\n\tconst container = useContainer()\n\n\tuseLayoutEffect(() => {\n\t\t// Resolve the scheme the same way UserPreferencesManager.getIsDarkMode will once the\n\t\t// editor mounts, so a 'system' user on a dark OS doesn't get a light loading screen that\n\t\t// flips dark on mount.\n\t\tconst scheme = user.userPreferences.get().colorScheme ?? rest.colorScheme ?? 'light'\n\t\tconst isDark =\n\t\t\tscheme === 'dark' ||\n\t\t\t(scheme === 'system' &&\n\t\t\t\ttypeof window !== 'undefined' &&\n\t\t\t\t!!getGlobalWindow().matchMedia?.('(prefers-color-scheme: dark)').matches)\n\t\tif (isDark) {\n\t\t\tcontainer.classList.remove('tl-theme__light')\n\t\t\tcontainer.classList.add('tl-theme__dark')\n\t\t}\n\t}, [container, user, rest.colorScheme])\n\n\tconst { LoadingScreen } = useEditorComponents()\n\n\tswitch (store.status) {\n\t\tcase 'error': {\n\t\t\t// for error handling, we fall back to the default error boundary.\n\t\t\t// if users want to handle this error differently, they can render\n\t\t\t// their own error screen before the TldrawEditor component\n\t\t\tthrow store.error\n\t\t}\n\t\tcase 'loading': {\n\t\t\treturn LoadingScreen ? <LoadingScreen /> : null\n\t\t}\n\t\tcase 'not-synced': {\n\t\t\tbreak\n\t\t}\n\t\tcase 'synced-local': {\n\t\t\tbreak\n\t\t}\n\t\tcase 'synced-remote': {\n\t\t\tbreak\n\t\t}\n\t}\n\n\treturn <TldrawEditorWithReadyStore {...rest} store={store.store} user={user} />\n})\n\nconst noAutoFocus = () => getGlobalDocument().location.search.includes('tldraw_preserve_focus')\n\nfunction TldrawEditorWithReadyStore({\n\tonMount,\n\tchildren,\n\tstore,\n\ttools,\n\tshapeUtils,\n\tbindingUtils,\n\tassetUtils,\n\toverlayUtils,\n\tuser,\n\tinitialState,\n\tautoFocus = true,\n\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\tcameraOptions,\n\toptions,\n\tlicenseKey,\n\tgetShapeVisibility,\n\tcolorScheme,\n\tassetUrls,\n\tthemes,\n\tinitialTheme,\n}: Required<\n\tTldrawEditorProps & {\n\t\tstore: TLStore\n\t\tuser: TLCurrentUser\n\t},\n\t'shapeUtils' | 'bindingUtils' | 'assetUtils' | 'tools'\n>) {\n\tconst { ErrorFallback } = useEditorComponents()\n\tconst container = useContainer()\n\tconst licenseManager = useLicenseContext()\n\n\tconst [editor, setEditor] = useRefState<Editor | null>(null)\n\n\tconst canvasRef = useRef<HTMLDivElement | null>(null)\n\n\tconst _deepLinks = options?.deepLinks\n\tconst deepLinks = useShallowObjectIdentity(_deepLinks === true ? {} : _deepLinks)\n\n\t// props in this ref can be changed without causing the editor to be recreated.\n\tconst editorOptionsRef = useRef({\n\t\t// for these, it's because they're only used when the editor first mounts:\n\t\tautoFocus: autoFocus && !noAutoFocus(),\n\t\tinitialState,\n\t\tcolorScheme,\n\n\t\t// for these, it's because we keep them up to date in a separate effect:\n\t\tcameraOptions,\n\t\tdeepLinks,\n\t\tthemes,\n\t\tinitialTheme,\n\t})\n\n\tuseLayoutEffect(() => {\n\t\teditorOptionsRef.current = {\n\t\t\tautoFocus: autoFocus && !noAutoFocus(),\n\t\t\tinitialState,\n\t\t\tcolorScheme,\n\t\t\tcameraOptions,\n\t\t\tdeepLinks,\n\t\t\tthemes,\n\t\t\tinitialTheme,\n\t\t}\n\t}, [autoFocus, initialState, colorScheme, cameraOptions, deepLinks, themes, initialTheme])\n\n\tuseLayoutEffect(\n\t\t() => {\n\t\t\tconst {\n\t\t\t\tautoFocus,\n\t\t\t\tinitialState,\n\t\t\t\tcolorScheme: initColorScheme,\n\t\t\t\tcameraOptions,\n\t\t\t\tdeepLinks,\n\t\t\t\tthemes,\n\t\t\t\tinitialTheme,\n\t\t\t} = editorOptionsRef.current\n\t\t\tconst editor = new Editor({\n\t\t\t\tstore,\n\t\t\t\tshapeUtils,\n\t\t\t\tbindingUtils,\n\t\t\t\tassetUtils,\n\t\t\t\toverlayUtils,\n\t\t\t\ttools,\n\t\t\t\tgetContainer: () => container,\n\t\t\t\tuser,\n\t\t\t\tinitialState,\n\t\t\t\t// we should check for some kind of query parameter that turns off autofocus\n\t\t\t\tautoFocus,\n\t\t\t\tcameraOptions,\n\t\t\t\toptions,\n\t\t\t\tlicenseKey,\n\t\t\t\tgetShapeVisibility,\n\t\t\t\tcolorScheme: initColorScheme,\n\t\t\t\tfontAssetUrls: assetUrls?.fonts,\n\t\t\t\tthemes: themes,\n\t\t\t\tinitialTheme: initialTheme,\n\t\t\t})\n\t\t\teditor.licenseManager = licenseManager\n\n\t\t\teditor.updateViewportScreenBounds(canvasRef.current ?? container)\n\n\t\t\t// Use the ref here because we only want to do this once when the editor is created.\n\t\t\t// We don't want changes to the urlStateSync prop to trigger creating new editors.\n\t\t\tif (deepLinks) {\n\t\t\t\tif (!deepLinks?.getUrl) {\n\t\t\t\t\t// load the state from window.location\n\t\t\t\t\teditor.navigateToDeepLink(deepLinks)\n\t\t\t\t} else {\n\t\t\t\t\t// load the state from the provided URL\n\t\t\t\t\teditor.navigateToDeepLink({ ...deepLinks, url: deepLinks.getUrl(editor) })\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tsetEditor(editor)\n\n\t\t\treturn () => {\n\t\t\t\teditor.dispose()\n\t\t\t}\n\t\t},\n\t\t// if any of these change, we need to recreate the editor.\n\t\t[\n\t\t\tassetUtils,\n\t\t\tbindingUtils,\n\t\t\tcolorScheme,\n\t\t\tcontainer,\n\t\t\toptions,\n\t\t\toverlayUtils,\n\t\t\tshapeUtils,\n\t\t\tstore,\n\t\t\ttools,\n\t\t\tuser,\n\t\t\tsetEditor,\n\t\t\tlicenseKey,\n\t\t\tlicenseManager,\n\t\t\tgetShapeVisibility,\n\t\t\tassetUrls,\n\t\t]\n\t)\n\n\tuseLayoutEffect(() => {\n\t\tif (!editor) return\n\t\tif (deepLinks) {\n\t\t\treturn editor.registerDeepLinkListener(deepLinks)\n\t\t}\n\t}, [editor, deepLinks])\n\n\t// keep the editor up to date with the latest camera options\n\t// options.cameraOptions takes precedence over the deprecated cameraOptions prop\n\tuseLayoutEffect(() => {\n\t\tif (editor && (cameraOptions || options?.camera)) {\n\t\t\teditor.setCameraOptions({ ...cameraOptions, ...options?.camera })\n\t\t}\n\t}, [editor, cameraOptions, options?.camera])\n\n\t// keep the editor up to date with the latest theme definitions\n\tuseLayoutEffect(() => {\n\t\tif (editor && themes) {\n\t\t\tfor (const def of Object.values(themes) as TLTheme[]) {\n\t\t\t\teditor.updateTheme(def)\n\t\t\t}\n\t\t}\n\t}, [editor, themes])\n\n\tuseLayoutEffect(() => {\n\t\tif (editor && initialTheme) {\n\t\t\teditor.setCurrentTheme(initialTheme)\n\t\t}\n\t}, [editor, initialTheme])\n\n\tconst crashingError = useSyncExternalStore(\n\t\tuseCallback(\n\t\t\t(onStoreChange) => {\n\t\t\t\tif (editor) {\n\t\t\t\t\teditor.on('crash', onStoreChange)\n\t\t\t\t\treturn () => editor.off('crash', onStoreChange)\n\t\t\t\t}\n\t\t\t\treturn () => {\n\t\t\t\t\t// noop\n\t\t\t\t}\n\t\t\t},\n\t\t\t[editor]\n\t\t),\n\t\t() => editor?.getCrashingError() ?? null\n\t)\n\n\t// For our examples site, we want autoFocus to be true on the examples site, but not\n\t// when embedded in our docs site. If present, the `tldraw_preserve_focus` search param\n\t// overrides the `autoFocus` prop and prevents the editor from focusing immediately,\n\t// however here we also add some logic to focus the editor when the user clicks\n\t// on it and unfocus it when the user clicks away from it.\n\tuseEffect(\n\t\tfunction handleFocusOnPointerDownForPreserveFocusMode() {\n\t\t\tif (!editor) return\n\t\t\tconst container = editor.getContainer()\n\n\t\t\tfunction handleFocusOnPointerDown() {\n\t\t\t\tif (!editor) return\n\t\t\t\teditor.focus()\n\t\t\t}\n\n\t\t\tfunction handleBlurOnPointerDown(e: PointerEvent) {\n\t\t\t\tif (!editor) return\n\t\t\t\t// The same pointerdown bubbles from the container to the body; blurring here would\n\t\t\t\t// cancel the interaction the container listener just focused for. Check the composed\n\t\t\t\t// path rather than `e.target`: when the editor lives in an open shadow root the target\n\t\t\t\t// is retargeted to the shadow host by the time the event reaches the body. (A closed\n\t\t\t\t// shadow root truncates the path at the host, so those still blur.)\n\t\t\t\tif (e.composedPath().includes(container)) return\n\t\t\t\teditor.blur()\n\t\t\t}\n\n\t\t\tif (autoFocus && noAutoFocus()) {\n\t\t\t\tcontainer.addEventListener('pointerdown', handleFocusOnPointerDown)\n\t\t\t\tcontainer.ownerDocument.body.addEventListener('pointerdown', handleBlurOnPointerDown)\n\n\t\t\t\treturn () => {\n\t\t\t\t\tcontainer.removeEventListener('pointerdown', handleFocusOnPointerDown)\n\t\t\t\t\tcontainer.ownerDocument.body.removeEventListener('pointerdown', handleBlurOnPointerDown)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[editor, autoFocus]\n\t)\n\n\tconst [_fontLoadingState, setFontLoadingState] = useState<{\n\t\teditor: Editor\n\t\tisLoaded: boolean\n\t} | null>(null)\n\tlet fontLoadingState = _fontLoadingState\n\tif (editor !== fontLoadingState?.editor) {\n\t\tfontLoadingState = null\n\t}\n\tuseLayoutEffect(() => {\n\t\tif (!editor) return\n\t\tif (editor.options.maxFontsToLoadBeforeRender === 0) {\n\t\t\tsetFontLoadingState({ editor, isLoaded: true })\n\t\t\treturn\n\t\t}\n\n\t\tlet isCancelled = false\n\n\t\tsetFontLoadingState({ editor, isLoaded: false })\n\n\t\teditor.fonts\n\t\t\t.loadRequiredFontsForCurrentPage(editor.options.maxFontsToLoadBeforeRender)\n\t\t\t.finally(() => {\n\t\t\t\tif (isCancelled) return\n\t\t\t\tsetFontLoadingState({ editor, isLoaded: true })\n\t\t\t})\n\n\t\treturn () => {\n\t\t\tisCancelled = true\n\t\t}\n\t}, [editor])\n\n\tconst { Canvas, LoadingScreen } = useEditorComponents()\n\n\tif (!editor || !fontLoadingState?.isLoaded) {\n\t\treturn (\n\t\t\t<>\n\t\t\t\t{LoadingScreen && <LoadingScreen />}\n\t\t\t\t<div className=\"tl-canvas\" ref={canvasRef} />\n\t\t\t</>\n\t\t)\n\t}\n\n\treturn (\n\t\t// the top-level tldraw component also renders an error boundary almost\n\t\t// identical to this one. the reason we have two is because this one has\n\t\t// access to `App`, which means that here we can enrich errors with data\n\t\t// from app for reporting, and also still attempt to render the user's\n\t\t// document in the event of an error to reassure them that their work is\n\t\t// not lost.\n\t\t<OptionalErrorBoundary\n\t\t\tfallback={ErrorFallback as any}\n\t\t\tonError={(error) =>\n\t\t\t\teditor.annotateError(error, { origin: 'react.tldraw', willCrashApp: true })\n\t\t\t}\n\t\t>\n\t\t\t{crashingError ? (\n\t\t\t\t<Crash crashingError={crashingError} />\n\t\t\t) : (\n\t\t\t\t<EditorProvider editor={editor}>\n\t\t\t\t\t<Layout onMount={onMount}>\n\t\t\t\t\t\t{children ?? (Canvas ? <Canvas key={editor.contextId} /> : null)}\n\t\t\t\t\t\t<Watermark />\n\t\t\t\t\t</Layout>\n\t\t\t\t</EditorProvider>\n\t\t\t)}\n\t\t</OptionalErrorBoundary>\n\t)\n}\n\nfunction Layout({ children, onMount }: { children: ReactNode; onMount?: TLOnMountHandler }) {\n\tuseZoomCss()\n\tuseCursor()\n\tuseDarkMode()\n\tuseForceUpdate()\n\tuseStateAttribute()\n\tuseOnMount((editor) => {\n\t\tconst teardownStore = editor.store.props.onMount(editor)\n\t\tconst teardownCallback = onMount?.(editor)\n\n\t\treturn () => {\n\t\t\tteardownStore?.()\n\t\t\tteardownCallback?.()\n\t\t}\n\t})\n\n\treturn children\n}\n\nfunction Crash({ crashingError }: { crashingError: unknown }): null {\n\tthrow crashingError\n}\n\n/** @public */\nexport interface LoadingScreenProps {\n\tchildren: ReactNode\n}\n\n/** @public @react */\nexport function LoadingScreen({ children }: LoadingScreenProps) {\n\treturn (\n\t\t<div className=\"tl-loading\" aria-busy=\"true\" tabIndex={0}>\n\t\t\t{children}\n\t\t</div>\n\t)\n}\n\n/** @public @react */\nexport function ErrorScreen({ children }: LoadingScreenProps) {\n\treturn <div className=\"tl-loading\">{children}</div>\n}\n\n/** @internal */\nexport function useOnMount(onMount?: TLOnMountHandler) {\n\tconst editor = useEditor()\n\n\tconst onMountEvent = useEvent((editor: Editor) => {\n\t\tlet teardown: (() => void) | void = undefined\n\t\t// If the user wants to do something when the editor mounts, we make sure it doesn't effect the history.\n\t\t// todo: is this reeeeally what we want to do, or should we leave it up to the caller?\n\t\teditor.run(\n\t\t\t() => {\n\t\t\t\tteardown = onMount?.(editor)\n\t\t\t\teditor.emit('mount')\n\t\t\t},\n\t\t\t{ history: 'ignore' }\n\t\t)\n\t\twindow.tldrawReady = true\n\t\treturn () => {\n\t\t\tteardown?.()\n\t\t\t// The editor's component can unmount without the editor being disposed (for example when\n\t\t\t// the canvas is swapped for an error fallback), so emit `unmount` here rather than relying\n\t\t\t// on disposal. If the editor is being disposed, `dispose()` emits `unmount` itself, so we\n\t\t\t// only emit here when it's still mounted and alive.\n\t\t\tif (editor.getIsMounted() && !editor.isDisposed) {\n\t\t\t\teditor.run(() => editor.emit('unmount'), { history: 'ignore' })\n\t\t\t}\n\t\t}\n\t})\n\n\tReact.useLayoutEffect(() => {\n\t\tif (editor) return onMountEvent?.(editor)\n\t}, [editor, onMountEvent])\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { MigrationSequence, Store } from '@tldraw/store'\nimport {\n\tTLShape,\n\tTLStore,\n\tTLStoreSnapshot,\n\tTLTheme,\n\tTLThemeId,\n\tTLThemes,\n\tregisterColorsFromThemes,\n\tregisterFontsFromThemes,\n} from '@tldraw/tlschema'\nimport { annotateError, Required } from '@tldraw/utils'\nimport classNames from 'classnames'\nimport React, {\n\tmemo,\n\tReactNode,\n\tuseCallback,\n\tuseEffect,\n\tuseLayoutEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n\tuseSyncExternalStore,\n} from 'react'\nimport { version } from '../version'\nimport { DefaultErrorFallback } from './components/default-components/DefaultErrorFallback'\nimport { EditorPortalProvider } from './components/EditorPortal'\nimport { OptionalErrorBoundary } from './components/ErrorBoundary'\nimport { createTLCurrentUser, TLCurrentUser } from './config/createTLCurrentUser'\nimport { TLStoreBaseOptions } from './config/createTLStore'\nimport { TLAnyAssetUtilConstructor } from './config/defaultAssets'\nimport { TLAnyBindingUtilConstructor } from './config/defaultBindings'\nimport { TLAnyShapeUtilConstructor } from './config/defaultShapes'\nimport { TLEditorSnapshot } from './config/TLEditorSnapshot'\nimport { Editor } from './editor/Editor'\nimport { resolveThemes } from './editor/managers/ThemeManager/ThemeManager'\nimport { TLAnyOverlayUtilConstructor } from './editor/overlays/OverlayUtil'\nimport { TLStateNodeConstructor } from './editor/tools/StateNode'\nimport { TLCameraOptions } from './editor/types/misc-types'\nimport { useEditorComponents } from './hooks/EditorComponentsContext'\nimport type { TLEditorComponents } from './hooks/EditorComponentsContext'\nimport { ContainerProvider, useContainer } from './hooks/useContainer'\nimport { useCursor } from './hooks/useCursor'\nimport { useDarkMode } from './hooks/useDarkMode'\nimport { EditorProvider, useEditor } from './hooks/useEditor'\nimport { EditorComponentsProvider } from './hooks/useEditorComponents'\nimport { useEvent } from './hooks/useEvent'\nimport { useForceUpdate } from './hooks/useForceUpdate'\nimport { useDeepObjectIdentity, useShallowObjectIdentity } from './hooks/useIdentity'\nimport { useLocalStore } from './hooks/useLocalStore'\nimport { useRefState } from './hooks/useRefState'\nimport { useStateAttribute } from './hooks/useStateAttribute'\nimport { useZoomCss } from './hooks/useZoomCss'\nimport { LicenseProvider, useLicenseContext } from './license/LicenseProvider'\nimport { Watermark } from './license/Watermark'\nimport { TldrawOptions } from './options'\nimport { TLDeepLinkOptions } from './utils/deepLinks'\nimport { getGlobalDocument, getGlobalWindow } from './utils/dom'\nimport { TLTextOptions } from './utils/richText'\nimport { TLStoreWithStatus } from './utils/sync/StoreWithStatus'\n\n/**\n * Props for the {@link tldraw#Tldraw} and {@link TldrawEditor} components, when passing in a\n * `TLStore` directly. If you would like tldraw to create a store for you, use\n * {@link TldrawEditorWithoutStoreProps}.\n *\n * @public\n */\nexport interface TldrawEditorWithStoreProps {\n\t/**\n\t * The store to use in the editor.\n\t */\n\tstore: TLStore | TLStoreWithStatus\n}\n\n/**\n * Props for the {@link tldraw#Tldraw} and {@link TldrawEditor} components, when not passing in a\n * `TLStore` directly. If you would like to pass in a store directly, use\n * {@link TldrawEditorWithStoreProps}.\n *\n * @public\n */\nexport interface TldrawEditorWithoutStoreProps extends TLStoreBaseOptions {\n\tstore?: undefined\n\n\t/**\n\t * Additional migrations to use in the store\n\t */\n\tmigrations?: readonly MigrationSequence[]\n\n\t/**\n\t * A starting snapshot of data to pre-populate the store. Do not supply both this and\n\t * `initialData`.\n\t */\n\tsnapshot?: TLEditorSnapshot | TLStoreSnapshot\n\n\t/**\n\t * If you would like to persist the store to the browser's local IndexedDB storage and sync it\n\t * across tabs, provide a key here. Each key represents a single tldraw document.\n\t */\n\tpersistenceKey?: string\n\n\tsessionId?: string\n}\n\n/** @public */\nexport type TldrawEditorStoreProps = TldrawEditorWithStoreProps | TldrawEditorWithoutStoreProps\n\n/**\n * Props for the {@link tldraw#Tldraw} and {@link TldrawEditor} components.\n *\n * @public\n **/\nexport type TldrawEditorProps = TldrawEditorBaseProps & TldrawEditorStoreProps\n\n/**\n * Base props for the {@link tldraw#Tldraw} and {@link TldrawEditor} components.\n *\n * @public\n */\nexport interface TldrawEditorBaseProps {\n\t/**\n\t * The component's children.\n\t */\n\tchildren?: ReactNode\n\n\t/**\n\t * An array of shape utils to use in the editor.\n\t */\n\tshapeUtils?: readonly TLAnyShapeUtilConstructor[]\n\n\t/**\n\t * An array of binding utils to use in the editor.\n\t */\n\tbindingUtils?: readonly TLAnyBindingUtilConstructor[]\n\n\t/**\n\t * An array of asset utils to use in the editor.\n\t */\n\tassetUtils?: readonly TLAnyAssetUtilConstructor[]\n\n\t/**\n\t * An array of overlay utils to use in the editor for canvas overlay UI elements.\n\t */\n\toverlayUtils?: readonly TLAnyOverlayUtilConstructor[]\n\n\t/**\n\t * An array of tools to add to the editor's state chart.\n\t */\n\ttools?: readonly TLStateNodeConstructor[]\n\n\t/**\n\t * Whether to automatically focus the editor when it mounts.\n\t */\n\tautoFocus?: boolean\n\n\t/**\n\t * Overrides for the editor's components, such as handles, collaborator cursors, etc.\n\t */\n\tcomponents?: TLEditorComponents\n\n\t/**\n\t * Called when the editor has mounted.\n\t */\n\tonMount?: TLOnMountHandler\n\n\t/**\n\t * The editor's initial state (usually the id of the first active tool).\n\t */\n\tinitialState?: string\n\n\t/**\n\t * A classname to pass to the editor's container.\n\t */\n\tclassName?: string\n\n\t/**\n\t * The user interacting with the editor.\n\t */\n\tuser?: TLCurrentUser\n\n\t/**\n\t * The editor's color scheme. Defaults to `'light'`.\n\t *\n\t * - `'light'` - Always use light mode.\n\t * - `'dark'` - Always use dark mode.\n\t * - `'system'` - Follow the OS color scheme preference.\n\t */\n\tcolorScheme?: 'light' | 'dark' | 'system'\n\n\t/**\n\t * Named themes for the editor.\n\t */\n\tthemes?: Partial<TLThemes>\n\n\t/**\n\t * The id of the initially active theme. Defaults to `'default'`.\n\t */\n\tinitialTheme?: TLThemeId\n\n\t/**\n\t * Camera options for the editor.\n\t *\n\t * @deprecated Use `options.cameraOptions` instead. This will be removed in a future release.\n\t */\n\tcameraOptions?: Partial<TLCameraOptions>\n\n\t/**\n\t * Options for the editor.\n\t */\n\toptions?: Partial<TldrawOptions>\n\n\t/**\n\t * Text options for the editor.\n\t *\n\t * @deprecated Use `options.text` instead. This prop will be removed in a future release.\n\t */\n\ttextOptions?: TLTextOptions\n\n\t/**\n\t * The license key.\n\t */\n\tlicenseKey?: string\n\n\t/**\n\t * Options for syncing the editor's camera state with the URL.\n\t *\n\t * @deprecated Use `options.deepLinks` instead. This prop will be removed in a future release.\n\t */\n\tdeepLinks?: true | TLDeepLinkOptions\n\n\t/**\n\t * Provides a way to hide shapes.\n\t *\n\t * Hidden shapes will not render in the editor, and they will not be eligible for hit test via\n\t * {@link @tldraw/editor#Editor.getShapeAtPoint} and {@link @tldraw/editor#Editor.getShapesAtPoint}. But otherwise they will\n\t * remain in the store and participate in all other operations.\n\t *\n\t * @example\n\t * ```ts\n\t * getShapeVisibility={(shape, editor) => shape.meta.hidden ? 'hidden' : 'inherit'}\n\t * ```\n\t *\n\t * - `'inherit' | undefined` - (default) The shape will be visible unless its parent is hidden.\n\t * - `'hidden'` - The shape will be hidden.\n\t * - `'visible'` - The shape will be visible.\n\t *\n\t * @param shape - The shape to check.\n\t * @param editor - The editor instance.\n\t */\n\tgetShapeVisibility?(\n\t\tshape: TLShape,\n\t\teditor: Editor\n\t): 'visible' | 'hidden' | 'inherit' | null | undefined\n\n\t/**\n\t * The URLs for the fonts to use in the editor.\n\t */\n\tassetUrls?: { fonts?: { [key: string]: string | undefined } }\n}\n\n/**\n * Called when the editor has mounted.\n * @example\n * ```ts\n * <Tldraw onMount={(editor) => editor.selectAll()} />\n * ```\n * @param editor - The editor instance.\n *\n * @public\n */\nexport type TLOnMountHandler = (editor: Editor) => (() => void | undefined) | undefined | void\n\ndeclare global {\n\tinterface Window {\n\t\ttldrawReady: boolean\n\t}\n}\n\nconst EMPTY_SHAPE_UTILS_ARRAY = [] as const\nconst EMPTY_BINDING_UTILS_ARRAY = [] as const\nconst EMPTY_ASSET_UTILS_ARRAY = [] as const\nconst EMPTY_TOOLS_ARRAY = [] as const\n/** @internal */\nexport const TL_CONTAINER_CLASS = 'tl-container'\n\n/** @public @react */\nexport const TldrawEditor = memo(function TldrawEditor({\n\tstore,\n\tcomponents,\n\tclassName,\n\tuser: _user,\n\toptions: _options,\n\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\ttextOptions: _textOptions,\n\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\tdeepLinks: _deepLinks,\n\t...rest\n}: TldrawEditorProps) {\n\t// Register custom colors and fonts before effects run. For external stores,\n\t// users should also pass themes to createTLStore so they are\n\t// registered before data is loaded into the store.\n\tconst resolvedThemes = resolveThemes(rest.themes)\n\tregisterColorsFromThemes(resolvedThemes)\n\tregisterFontsFromThemes(resolvedThemes)\n\n\tconst [container, setContainer] = useState<HTMLElement | null>(null)\n\tconst [portalHost, setPortalHost] = useState<HTMLElement | null>(null)\n\tconst user = useMemo(() => _user ?? createTLCurrentUser(), [_user])\n\n\tconst ErrorFallback =\n\t\tcomponents?.ErrorFallback === undefined ? DefaultErrorFallback : components?.ErrorFallback\n\n\t// Merge deprecated props with options (options win). `options` is a dependency of the\n\t// editor-creating effect, so it's shallow-stabilised below; the nested objects are\n\t// deep-stabilised here first, or an inline `options={{ camera: { ... } }}` would still\n\t// recreate the editor on every render. `text` needs the deep comparison as well: `<Tldraw>`\n\t// builds a fresh `tipTapConfig` inside it whenever its own `options.text` is a new identity.\n\tconst camera = useDeepObjectIdentity(_options?.camera)\n\tconst gridSteps = useDeepObjectIdentity(_options?.gridSteps)\n\tconst text = useDeepObjectIdentity(_options?.text ?? _textOptions)\n\tconst mergedDeepLinks = _options?.deepLinks ?? _deepLinks\n\tconst deepLinkOptions = useDeepObjectIdentity(\n\t\tmergedDeepLinks === true ? undefined : mergedDeepLinks\n\t)\n\tconst deepLinks = mergedDeepLinks === true ? true : deepLinkOptions\n\tlet mergedOptions = _options\n\tif (camera !== undefined) mergedOptions = { ...mergedOptions, camera }\n\tif (gridSteps !== undefined) mergedOptions = { ...mergedOptions, gridSteps }\n\tif (text !== undefined) mergedOptions = { ...mergedOptions, text }\n\tif (deepLinks !== undefined) mergedOptions = { ...mergedOptions, deepLinks }\n\n\t// apply defaults. if you're using the bare @tldraw/editor package, we\n\t// default these to the \"tldraw zero\" configuration. We have different\n\t// defaults applied in tldraw.\n\tconst withDefaults = {\n\t\t...rest,\n\t\tshapeUtils: rest.shapeUtils ?? EMPTY_SHAPE_UTILS_ARRAY,\n\t\tbindingUtils: rest.bindingUtils ?? EMPTY_BINDING_UTILS_ARRAY,\n\t\tassetUtils: rest.assetUtils ?? EMPTY_ASSET_UTILS_ARRAY,\n\t\ttools: rest.tools ?? EMPTY_TOOLS_ARRAY,\n\t\tcomponents,\n\t\toptions: useShallowObjectIdentity(mergedOptions),\n\t}\n\n\treturn (\n\t\t<div\n\t\t\tref={setContainer}\n\t\t\tdata-tldraw={version}\n\t\t\tdraggable={false}\n\t\t\tclassName={classNames(`${TL_CONTAINER_CLASS} tl-theme__light`, className)}\n\t\t\ttabIndex={-1}\n\t\t\trole=\"application\"\n\t\t\taria-label={_options?.branding ?? 'tldraw'}\n\t\t>\n\t\t\t<OptionalErrorBoundary\n\t\t\t\tfallback={ErrorFallback}\n\t\t\t\tonError={(error) => annotateError(error, { tags: { origin: 'react.tldraw-before-app' } })}\n\t\t\t>\n\t\t\t\t{container && (\n\t\t\t\t\t<LicenseProvider licenseKey={rest.licenseKey}>\n\t\t\t\t\t\t<ContainerProvider container={container}>\n\t\t\t\t\t\t\t<EditorPortalProvider host={portalHost}>\n\t\t\t\t\t\t\t\t<EditorComponentsProvider overrides={components}>\n\t\t\t\t\t\t\t\t\t{store ? (\n\t\t\t\t\t\t\t\t\t\tstore instanceof Store ? (\n\t\t\t\t\t\t\t\t\t\t\t// Store is ready to go, whether externally synced or not\n\t\t\t\t\t\t\t\t\t\t\t<TldrawEditorWithReadyStore {...withDefaults} store={store} user={user} />\n\t\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t\t// Store is a synced store, so handle syncing stages internally\n\t\t\t\t\t\t\t\t\t\t\t<TldrawEditorWithLoadingStore {...withDefaults} store={store} user={user} />\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t// We have no store (it's undefined) so create one and possibly sync it\n\t\t\t\t\t\t\t\t\t\t<TldrawEditorWithOwnStore {...withDefaults} store={store} user={user} />\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</EditorComponentsProvider>\n\t\t\t\t\t\t\t</EditorPortalProvider>\n\t\t\t\t\t\t</ContainerProvider>\n\t\t\t\t\t</LicenseProvider>\n\t\t\t\t)}\n\t\t\t</OptionalErrorBoundary>\n\t\t\t{/* The host for <EditorPortal>, last among the container's children so that anything\n\t\t\t portaled through it lands after the canvas and the UI \u2014 behind the UI's \"skip to main\n\t\t\t content\" link in the tab order, which only works while nothing precedes it. */}\n\t\t\t<div className=\"tl-portal-host\" ref={setPortalHost} />\n\t\t</div>\n\t)\n})\n\nfunction TldrawEditorWithOwnStore(\n\tprops: Required<\n\t\tTldrawEditorProps & { store: undefined; user: TLCurrentUser },\n\t\t'shapeUtils' | 'bindingUtils' | 'assetUtils' | 'tools'\n\t>\n) {\n\tconst {\n\t\tdefaultName,\n\t\tsnapshot,\n\t\tinitialData,\n\t\tshapeUtils,\n\t\tbindingUtils,\n\t\tassetUtils,\n\t\tpersistenceKey,\n\t\tsessionId,\n\t\tuser,\n\t\tassets,\n\t\tusers,\n\t\tmigrations,\n\t\tthemes,\n\t} = props\n\n\tconst syncedStore = useLocalStore({\n\t\tshapeUtils,\n\t\tbindingUtils,\n\t\tassetUtils,\n\t\tinitialData,\n\t\tpersistenceKey,\n\t\tsessionId,\n\t\tdefaultName,\n\t\tsnapshot,\n\t\tassets,\n\t\tusers,\n\t\tmigrations,\n\t\tthemes,\n\t})\n\n\treturn <TldrawEditorWithLoadingStore {...props} store={syncedStore} user={user} />\n}\n\nconst TldrawEditorWithLoadingStore = memo(function TldrawEditorBeforeLoading({\n\tstore,\n\tuser,\n\t...rest\n}: Required<\n\tTldrawEditorProps & { store: TLStoreWithStatus; user: TLCurrentUser },\n\t'shapeUtils' | 'bindingUtils' | 'assetUtils' | 'tools'\n>) {\n\tconst container = useContainer()\n\n\tuseLayoutEffect(() => {\n\t\t// Resolve the scheme the same way UserPreferencesManager.getIsDarkMode will once the\n\t\t// editor mounts, so a 'system' user on a dark OS doesn't get a light loading screen that\n\t\t// flips dark on mount.\n\t\tconst scheme = user.userPreferences.get().colorScheme ?? rest.colorScheme ?? 'light'\n\t\tconst isDark =\n\t\t\tscheme === 'dark' ||\n\t\t\t(scheme === 'system' &&\n\t\t\t\ttypeof window !== 'undefined' &&\n\t\t\t\t!!getGlobalWindow().matchMedia?.('(prefers-color-scheme: dark)').matches)\n\t\tif (isDark) {\n\t\t\tcontainer.classList.remove('tl-theme__light')\n\t\t\tcontainer.classList.add('tl-theme__dark')\n\t\t}\n\t}, [container, user, rest.colorScheme])\n\n\tconst { LoadingScreen } = useEditorComponents()\n\n\tswitch (store.status) {\n\t\tcase 'error': {\n\t\t\t// for error handling, we fall back to the default error boundary.\n\t\t\t// if users want to handle this error differently, they can render\n\t\t\t// their own error screen before the TldrawEditor component\n\t\t\tthrow store.error\n\t\t}\n\t\tcase 'loading': {\n\t\t\treturn LoadingScreen ? <LoadingScreen /> : null\n\t\t}\n\t\tcase 'not-synced': {\n\t\t\tbreak\n\t\t}\n\t\tcase 'synced-local': {\n\t\t\tbreak\n\t\t}\n\t\tcase 'synced-remote': {\n\t\t\tbreak\n\t\t}\n\t}\n\n\treturn <TldrawEditorWithReadyStore {...rest} store={store.store} user={user} />\n})\n\nconst noAutoFocus = () => getGlobalDocument().location.search.includes('tldraw_preserve_focus')\n\nfunction TldrawEditorWithReadyStore({\n\tonMount,\n\tchildren,\n\tstore,\n\ttools,\n\tshapeUtils,\n\tbindingUtils,\n\tassetUtils,\n\toverlayUtils,\n\tuser,\n\tinitialState,\n\tautoFocus = true,\n\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\tcameraOptions,\n\toptions,\n\tlicenseKey,\n\tgetShapeVisibility,\n\tcolorScheme,\n\tassetUrls,\n\tthemes,\n\tinitialTheme,\n}: Required<\n\tTldrawEditorProps & {\n\t\tstore: TLStore\n\t\tuser: TLCurrentUser\n\t},\n\t'shapeUtils' | 'bindingUtils' | 'assetUtils' | 'tools'\n>) {\n\tconst { ErrorFallback } = useEditorComponents()\n\tconst container = useContainer()\n\tconst licenseManager = useLicenseContext()\n\n\tconst [editor, setEditor] = useRefState<Editor | null>(null)\n\n\tconst canvasRef = useRef<HTMLDivElement | null>(null)\n\n\tconst _deepLinks = options?.deepLinks\n\tconst deepLinks = useShallowObjectIdentity(_deepLinks === true ? {} : _deepLinks)\n\n\t// props in this ref can be changed without causing the editor to be recreated.\n\tconst editorOptionsRef = useRef({\n\t\t// for these, it's because they're only used when the editor first mounts:\n\t\tautoFocus: autoFocus && !noAutoFocus(),\n\t\tinitialState,\n\t\tcolorScheme,\n\n\t\t// for these, it's because we keep them up to date in a separate effect:\n\t\tcameraOptions,\n\t\tdeepLinks,\n\t\tthemes,\n\t\tinitialTheme,\n\t})\n\n\tuseLayoutEffect(() => {\n\t\teditorOptionsRef.current = {\n\t\t\tautoFocus: autoFocus && !noAutoFocus(),\n\t\t\tinitialState,\n\t\t\tcolorScheme,\n\t\t\tcameraOptions,\n\t\t\tdeepLinks,\n\t\t\tthemes,\n\t\t\tinitialTheme,\n\t\t}\n\t}, [autoFocus, initialState, colorScheme, cameraOptions, deepLinks, themes, initialTheme])\n\n\tuseLayoutEffect(\n\t\t() => {\n\t\t\tconst {\n\t\t\t\tautoFocus,\n\t\t\t\tinitialState,\n\t\t\t\tcolorScheme: initColorScheme,\n\t\t\t\tcameraOptions,\n\t\t\t\tdeepLinks,\n\t\t\t\tthemes,\n\t\t\t\tinitialTheme,\n\t\t\t} = editorOptionsRef.current\n\t\t\tconst editor = new Editor({\n\t\t\t\tstore,\n\t\t\t\tshapeUtils,\n\t\t\t\tbindingUtils,\n\t\t\t\tassetUtils,\n\t\t\t\toverlayUtils,\n\t\t\t\ttools,\n\t\t\t\tgetContainer: () => container,\n\t\t\t\tuser,\n\t\t\t\tinitialState,\n\t\t\t\t// we should check for some kind of query parameter that turns off autofocus\n\t\t\t\tautoFocus,\n\t\t\t\tcameraOptions,\n\t\t\t\toptions,\n\t\t\t\tlicenseKey,\n\t\t\t\tgetShapeVisibility,\n\t\t\t\tcolorScheme: initColorScheme,\n\t\t\t\tfontAssetUrls: assetUrls?.fonts,\n\t\t\t\tthemes: themes,\n\t\t\t\tinitialTheme: initialTheme,\n\t\t\t})\n\t\t\teditor.licenseManager = licenseManager\n\n\t\t\teditor.updateViewportScreenBounds(canvasRef.current ?? container)\n\n\t\t\t// Use the ref here because we only want to do this once when the editor is created.\n\t\t\t// We don't want changes to the urlStateSync prop to trigger creating new editors.\n\t\t\tif (deepLinks) {\n\t\t\t\tif (!deepLinks?.getUrl) {\n\t\t\t\t\t// load the state from window.location\n\t\t\t\t\teditor.navigateToDeepLink(deepLinks)\n\t\t\t\t} else {\n\t\t\t\t\t// load the state from the provided URL\n\t\t\t\t\teditor.navigateToDeepLink({ ...deepLinks, url: deepLinks.getUrl(editor) })\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tsetEditor(editor)\n\n\t\t\treturn () => {\n\t\t\t\teditor.dispose()\n\t\t\t}\n\t\t},\n\t\t// if any of these change, we need to recreate the editor.\n\t\t[\n\t\t\tassetUtils,\n\t\t\tbindingUtils,\n\t\t\tcolorScheme,\n\t\t\tcontainer,\n\t\t\toptions,\n\t\t\toverlayUtils,\n\t\t\tshapeUtils,\n\t\t\tstore,\n\t\t\ttools,\n\t\t\tuser,\n\t\t\tsetEditor,\n\t\t\tlicenseKey,\n\t\t\tlicenseManager,\n\t\t\tgetShapeVisibility,\n\t\t\tassetUrls,\n\t\t]\n\t)\n\n\tuseLayoutEffect(() => {\n\t\tif (!editor) return\n\t\tif (deepLinks) {\n\t\t\treturn editor.registerDeepLinkListener(deepLinks)\n\t\t}\n\t}, [editor, deepLinks])\n\n\t// keep the editor up to date with the latest camera options\n\t// options.cameraOptions takes precedence over the deprecated cameraOptions prop\n\tuseLayoutEffect(() => {\n\t\tif (editor && (cameraOptions || options?.camera)) {\n\t\t\teditor.setCameraOptions({ ...cameraOptions, ...options?.camera })\n\t\t}\n\t}, [editor, cameraOptions, options?.camera])\n\n\t// keep the editor up to date with the latest theme definitions\n\tuseLayoutEffect(() => {\n\t\tif (editor && themes) {\n\t\t\tfor (const def of Object.values(themes) as TLTheme[]) {\n\t\t\t\teditor.updateTheme(def)\n\t\t\t}\n\t\t}\n\t}, [editor, themes])\n\n\tuseLayoutEffect(() => {\n\t\tif (editor && initialTheme) {\n\t\t\teditor.setCurrentTheme(initialTheme)\n\t\t}\n\t}, [editor, initialTheme])\n\n\tconst crashingError = useSyncExternalStore(\n\t\tuseCallback(\n\t\t\t(onStoreChange) => {\n\t\t\t\tif (editor) {\n\t\t\t\t\teditor.on('crash', onStoreChange)\n\t\t\t\t\treturn () => editor.off('crash', onStoreChange)\n\t\t\t\t}\n\t\t\t\treturn () => {\n\t\t\t\t\t// noop\n\t\t\t\t}\n\t\t\t},\n\t\t\t[editor]\n\t\t),\n\t\t() => editor?.getCrashingError() ?? null\n\t)\n\n\t// For our examples site, we want autoFocus to be true on the examples site, but not\n\t// when embedded in our docs site. If present, the `tldraw_preserve_focus` search param\n\t// overrides the `autoFocus` prop and prevents the editor from focusing immediately,\n\t// however here we also add some logic to focus the editor when the user clicks\n\t// on it and unfocus it when the user clicks away from it.\n\tuseEffect(\n\t\tfunction handleFocusOnPointerDownForPreserveFocusMode() {\n\t\t\tif (!editor) return\n\t\t\tconst container = editor.getContainer()\n\n\t\t\tfunction handleFocusOnPointerDown() {\n\t\t\t\tif (!editor) return\n\t\t\t\teditor.focus()\n\t\t\t}\n\n\t\t\tfunction handleBlurOnPointerDown(e: PointerEvent) {\n\t\t\t\tif (!editor) return\n\t\t\t\t// The same pointerdown bubbles from the container to the body; blurring here would\n\t\t\t\t// cancel the interaction the container listener just focused for. Check the composed\n\t\t\t\t// path rather than `e.target`: when the editor lives in an open shadow root the target\n\t\t\t\t// is retargeted to the shadow host by the time the event reaches the body. (A closed\n\t\t\t\t// shadow root truncates the path at the host, so those still blur.)\n\t\t\t\tif (e.composedPath().includes(container)) return\n\t\t\t\teditor.blur()\n\t\t\t}\n\n\t\t\tif (autoFocus && noAutoFocus()) {\n\t\t\t\tcontainer.addEventListener('pointerdown', handleFocusOnPointerDown)\n\t\t\t\tcontainer.ownerDocument.body.addEventListener('pointerdown', handleBlurOnPointerDown)\n\n\t\t\t\treturn () => {\n\t\t\t\t\tcontainer.removeEventListener('pointerdown', handleFocusOnPointerDown)\n\t\t\t\t\tcontainer.ownerDocument.body.removeEventListener('pointerdown', handleBlurOnPointerDown)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[editor, autoFocus]\n\t)\n\n\tconst [_fontLoadingState, setFontLoadingState] = useState<{\n\t\teditor: Editor\n\t\tisLoaded: boolean\n\t} | null>(null)\n\tlet fontLoadingState = _fontLoadingState\n\tif (editor !== fontLoadingState?.editor) {\n\t\tfontLoadingState = null\n\t}\n\tuseLayoutEffect(() => {\n\t\tif (!editor) return\n\t\tif (editor.options.maxFontsToLoadBeforeRender === 0) {\n\t\t\tsetFontLoadingState({ editor, isLoaded: true })\n\t\t\treturn\n\t\t}\n\n\t\tlet isCancelled = false\n\n\t\tsetFontLoadingState({ editor, isLoaded: false })\n\n\t\teditor.fonts\n\t\t\t.loadRequiredFontsForCurrentPage(editor.options.maxFontsToLoadBeforeRender)\n\t\t\t.finally(() => {\n\t\t\t\tif (isCancelled) return\n\t\t\t\tsetFontLoadingState({ editor, isLoaded: true })\n\t\t\t})\n\n\t\treturn () => {\n\t\t\tisCancelled = true\n\t\t}\n\t}, [editor])\n\n\tconst { Canvas, LoadingScreen } = useEditorComponents()\n\n\tif (!editor || !fontLoadingState?.isLoaded) {\n\t\treturn (\n\t\t\t<>\n\t\t\t\t{LoadingScreen && <LoadingScreen />}\n\t\t\t\t<div className=\"tl-canvas\" ref={canvasRef} />\n\t\t\t</>\n\t\t)\n\t}\n\n\treturn (\n\t\t// the top-level tldraw component also renders an error boundary almost\n\t\t// identical to this one. the reason we have two is because this one has\n\t\t// access to `App`, which means that here we can enrich errors with data\n\t\t// from app for reporting, and also still attempt to render the user's\n\t\t// document in the event of an error to reassure them that their work is\n\t\t// not lost.\n\t\t<OptionalErrorBoundary\n\t\t\tfallback={ErrorFallback as any}\n\t\t\tonError={(error) =>\n\t\t\t\teditor.annotateError(error, { origin: 'react.tldraw', willCrashApp: true })\n\t\t\t}\n\t\t>\n\t\t\t{crashingError ? (\n\t\t\t\t<Crash crashingError={crashingError} />\n\t\t\t) : (\n\t\t\t\t<EditorProvider editor={editor}>\n\t\t\t\t\t<Layout onMount={onMount}>\n\t\t\t\t\t\t{children ?? (Canvas ? <Canvas key={editor.contextId} /> : null)}\n\t\t\t\t\t\t<Watermark />\n\t\t\t\t\t</Layout>\n\t\t\t\t</EditorProvider>\n\t\t\t)}\n\t\t</OptionalErrorBoundary>\n\t)\n}\n\nfunction Layout({ children, onMount }: { children: ReactNode; onMount?: TLOnMountHandler }) {\n\tuseZoomCss()\n\tuseCursor()\n\tuseDarkMode()\n\tuseForceUpdate()\n\tuseStateAttribute()\n\tuseOnMount((editor) => {\n\t\tconst teardownStore = editor.store.props.onMount(editor)\n\t\tconst teardownCallback = onMount?.(editor)\n\n\t\treturn () => {\n\t\t\tteardownStore?.()\n\t\t\tteardownCallback?.()\n\t\t}\n\t})\n\n\treturn children\n}\n\nfunction Crash({ crashingError }: { crashingError: unknown }): null {\n\tthrow crashingError\n}\n\n/** @public */\nexport interface LoadingScreenProps {\n\tchildren: ReactNode\n}\n\n/** @public @react */\nexport function LoadingScreen({ children }: LoadingScreenProps) {\n\treturn (\n\t\t<div className=\"tl-loading\" aria-busy=\"true\" tabIndex={0}>\n\t\t\t{children}\n\t\t</div>\n\t)\n}\n\n/** @public @react */\nexport function ErrorScreen({ children }: LoadingScreenProps) {\n\treturn <div className=\"tl-loading\">{children}</div>\n}\n\n/** @internal */\nexport function useOnMount(onMount?: TLOnMountHandler) {\n\tconst editor = useEditor()\n\n\tconst onMountEvent = useEvent((editor: Editor) => {\n\t\tlet teardown: (() => void) | void = undefined\n\t\t// If the user wants to do something when the editor mounts, we make sure it doesn't effect the history.\n\t\t// todo: is this reeeeally what we want to do, or should we leave it up to the caller?\n\t\teditor.run(\n\t\t\t() => {\n\t\t\t\tteardown = onMount?.(editor)\n\t\t\t\teditor.emit('mount')\n\t\t\t},\n\t\t\t{ history: 'ignore' }\n\t\t)\n\t\twindow.tldrawReady = true\n\t\treturn () => {\n\t\t\tteardown?.()\n\t\t\t// The editor's component can unmount without the editor being disposed (for example when\n\t\t\t// the canvas is swapped for an error fallback), so emit `unmount` here rather than relying\n\t\t\t// on disposal. If the editor is being disposed, `dispose()` emits `unmount` itself, so we\n\t\t\t// only emit here when it's still mounted and alive.\n\t\t\tif (editor.getIsMounted() && !editor.isDisposed) {\n\t\t\t\teditor.run(() => editor.emit('unmount'), { history: 'ignore' })\n\t\t\t}\n\t\t}\n\t})\n\n\tReact.useLayoutEffect(() => {\n\t\tif (editor) return onMountEvent?.(editor)\n\t}, [editor, onMountEvent])\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["TldrawEditor", "classNames", "LoadingScreen", "autoFocus", "initialState", "cameraOptions", "deepLinks", "themes", "initialTheme", "editor", "container", "React"]
7
7
  }
@@ -41,6 +41,7 @@ function MenuClickCapture() {
41
41
  isDown: false,
42
42
  isDragging: false,
43
43
  button: 0,
44
+ pointerId: -1,
44
45
  start: new import_Vec.Vec()
45
46
  });
46
47
  const rCancelContextMenuSwallow = (0, import_react.useRef)(null);
@@ -73,6 +74,7 @@ function MenuClickCapture() {
73
74
  }, [editor]);
74
75
  const handlePointerDown = (0, import_react.useCallback)(
75
76
  (e) => {
77
+ if (rPointerState.current.isDown) return;
76
78
  const button = (0, import_pointer.getPointerEventButton)(e);
77
79
  if (button !== 0 && button !== 2) return;
78
80
  if (button === 2 && editor.options.rightClickPanning) {
@@ -87,6 +89,7 @@ function MenuClickCapture() {
87
89
  isDown: true,
88
90
  isDragging: false,
89
91
  button,
92
+ pointerId: e.pointerId,
90
93
  start: new import_Vec.Vec(e.clientX, e.clientY)
91
94
  };
92
95
  if (button === 2) {
@@ -99,7 +102,7 @@ function MenuClickCapture() {
99
102
  const handlePointerMove = (0, import_react.useCallback)(
100
103
  (e) => {
101
104
  const state = rPointerState.current;
102
- if (!state.isDown) return;
105
+ if (!state.isDown || state.pointerId !== e.pointerId) return;
103
106
  if (state.button !== 2 && !state.isDragging) {
104
107
  if (import_Vec.Vec.Dist2(state.start, new import_Vec.Vec(e.clientX, e.clientY)) <= editor.options.dragDistanceSquared) {
105
108
  return;
@@ -123,13 +126,15 @@ function MenuClickCapture() {
123
126
  );
124
127
  const handlePointerUp = (0, import_react.useCallback)(
125
128
  (e) => {
126
- const isStaticRightClick = rPointerState.current.button === 2 && !rPointerState.current.isDragging;
129
+ const state = rPointerState.current;
130
+ if (!state.isDown || state.pointerId !== e.pointerId) return;
131
+ const isStaticRightClick = state.button === 2 && !state.isDragging;
127
132
  editor.dispatch({
128
133
  type: "pointer",
129
134
  target: "canvas",
130
135
  name: "pointer_up",
131
136
  ...(0, import_getPointerInfo.getPointerInfo)(editor, e),
132
- button: rPointerState.current.button === 2 ? 2 : (0, import_pointer.getPointerEventButton)(e)
137
+ button: state.button === 2 ? 2 : (0, import_pointer.getPointerEventButton)(e)
133
138
  });
134
139
  if (isStaticRightClick && editor.options.rightClickPanning) {
135
140
  const canvas = editor.getContainer().querySelector(".tl-canvas");
@@ -155,11 +160,44 @@ function MenuClickCapture() {
155
160
  isDown: false,
156
161
  isDragging: false,
157
162
  button: 0,
163
+ pointerId: -1,
158
164
  start: new import_Vec.Vec(e.clientX, e.clientY)
159
165
  };
160
166
  },
161
167
  [editor]
162
168
  );
169
+ const handlePointerCancel = (0, import_react.useCallback)(
170
+ (e) => {
171
+ const state = rPointerState.current;
172
+ if (!state.isDown || state.pointerId !== e.pointerId) {
173
+ canvasEvents.onPointerCancel?.(e);
174
+ return;
175
+ }
176
+ if (editor.inputs.getIsPointing()) {
177
+ editor.interrupt();
178
+ editor.dispatch({
179
+ type: "pointer",
180
+ target: "canvas",
181
+ name: "pointer_up",
182
+ ...(0, import_getPointerInfo.getPointerInfo)(editor, e),
183
+ // pointercancel reports button -1
184
+ button: state.button
185
+ });
186
+ } else {
187
+ editor.markEventAsHandled(e);
188
+ }
189
+ (0, import_dom.releasePointerCapture)(e.currentTarget, e);
190
+ setIsPointing(false);
191
+ rPointerState.current = {
192
+ isDown: false,
193
+ isDragging: false,
194
+ button: 0,
195
+ pointerId: -1,
196
+ start: new import_Vec.Vec(e.clientX, e.clientY)
197
+ };
198
+ },
199
+ [canvasEvents, editor]
200
+ );
163
201
  return showElement && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
164
202
  "div",
165
203
  {
@@ -169,6 +207,7 @@ function MenuClickCapture() {
169
207
  onPointerDown: handlePointerDown,
170
208
  onPointerMove: handlePointerMove,
171
209
  onPointerUp: handlePointerUp,
210
+ onPointerCancel: handlePointerCancel,
172
211
  onContextMenu: (e) => {
173
212
  e.preventDefault();
174
213
  e.stopPropagation();
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/components/MenuClickCapture.tsx"],
4
- "sourcesContent": ["import { useValue } from '@tldraw/state-react'\nimport { type PointerEvent, useCallback, useEffect, useRef, useState } from 'react'\nimport { flushSync } from 'react-dom'\nimport { useCanvasEvents } from '../hooks/useCanvasEvents'\nimport { useEditor } from '../hooks/useEditor'\nimport { Vec } from '../primitives/Vec'\nimport { releasePointerCapture, setPointerCapture } from '../utils/dom'\nimport { getPointerInfo } from '../utils/getPointerInfo'\nimport { getPointerEventButton } from '../utils/pointer'\n\n/**\n * When a menu is open, this component prevents the user from interacting with the canvas.\n *\n * @public @react\n */\nexport function MenuClickCapture() {\n\tconst editor = useEditor()\n\n\tconst isMenuOpen = useValue('is menu open', () => editor.menus.hasAnyOpenMenus(), [editor])\n\n\t// Keep this component mounted while the pointer is down so pointerup/move still\n\t// land here after a synchronous clearOpenMenus() flips isMenuOpen to false.\n\tconst [isPointing, setIsPointing] = useState(false)\n\tconst showElement = isMenuOpen || isPointing\n\n\tconst canvasEvents = useCanvasEvents()\n\n\tconst rPointerState = useRef({\n\t\tisDown: false,\n\t\tisDragging: false,\n\t\tbutton: 0,\n\t\tstart: new Vec(),\n\t})\n\n\t// Swallow the native contextmenu that follows a right-click pointerdown. Without\n\t// this, Radix's trigger catches the native event and opens a menu at the pointer-\n\t// DOWN position \u2014 then our own synthetic contextmenu (fired on pointerup) opens it\n\t// again at the release position, producing a visible flash.\n\tconst rCancelContextMenuSwallow = useRef<null | (() => void)>(null)\n\tuseEffect(\n\t\t() => () => {\n\t\t\trCancelContextMenuSwallow.current?.()\n\t\t\trCancelContextMenuSwallow.current = null\n\t\t},\n\t\t[]\n\t)\n\tconst swallowNextNativeContextMenu = useCallback(() => {\n\t\trCancelContextMenuSwallow.current?.()\n\t\tconst doc = editor.getContainerDocument()\n\t\tconst onContextMenu = (event: MouseEvent) => {\n\t\t\t// Skip our own synthetic contextmenu \u2014 only swallow the real browser one\n\t\t\tif (!event.isTrusted) return\n\t\t\trCancelContextMenuSwallow.current?.()\n\t\t\trCancelContextMenuSwallow.current = null\n\t\t\tevent.preventDefault()\n\t\t\tevent.stopImmediatePropagation()\n\t\t}\n\t\tconst cancel = () => doc.removeEventListener('contextmenu', onContextMenu, true)\n\t\trCancelContextMenuSwallow.current = cancel\n\t\tdoc.addEventListener('contextmenu', onContextMenu, true)\n\t\t// Drop the listener on the next tick if it never fires (e.g. pointer moved off-screen)\n\t\tdoc.defaultView?.setTimeout(() => {\n\t\t\tif (rCancelContextMenuSwallow.current === cancel) {\n\t\t\t\tcancel()\n\t\t\t\trCancelContextMenuSwallow.current = null\n\t\t\t}\n\t\t}, 0)\n\t}, [editor])\n\n\tconst handlePointerDown = useCallback(\n\t\t(e: PointerEvent) => {\n\t\t\tconst button = getPointerEventButton(e)\n\t\t\tif (button !== 0 && button !== 2) return\n\n\t\t\tif (button === 2 && editor.options.rightClickPanning) {\n\t\t\t\t// Forward right-click pointerdown through the canvas's own handler so\n\t\t\t\t// pointer capture is set on the canvas (load-bearing: without this\n\t\t\t\t// the context menu briefly flashes closed during consecutive right-clicks).\n\t\t\t\t// The canvas owns the rest of the gesture, so don't capture or mark\n\t\t\t\t// pointing here: this element's pointerup would never fire, leaving it\n\t\t\t\t// mounted over the canvas after the menu closes.\n\t\t\t\t// We don't clearOpenMenus() \u2014 Radix's DismissableLayer closes the menu\n\t\t\t\t// via outside-click detection, keeping its internal state in sync.\n\t\t\t\tconst canvas =\n\t\t\t\t\teditor.getContainer().querySelector<HTMLDivElement>('.tl-canvas') ?? e.currentTarget\n\t\t\t\tcanvasEvents.onPointerDown?.({ ...e, currentTarget: canvas })\n\t\t\t\tswallowNextNativeContextMenu()\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tflushSync(() => setIsPointing(true))\n\t\t\tsetPointerCapture(e.currentTarget, e)\n\t\t\trPointerState.current = {\n\t\t\t\tisDown: true,\n\t\t\t\tisDragging: false,\n\t\t\t\tbutton,\n\t\t\t\tstart: new Vec(e.clientX, e.clientY),\n\t\t\t}\n\n\t\t\tif (button === 2) {\n\t\t\t\t// Right-click panning off: swallow the native contextmenu that would otherwise\n\t\t\t\t// briefly open a new menu (causing a flash) once the open one closes below.\n\t\t\t\tswallowNextNativeContextMenu()\n\t\t\t}\n\n\t\t\teditor.menus.clearOpenMenus()\n\t\t},\n\t\t[canvasEvents, editor, swallowNextNativeContextMenu]\n\t)\n\n\tconst handlePointerMove = useCallback(\n\t\t(e: PointerEvent) => {\n\t\t\tconst state = rPointerState.current\n\t\t\tif (!state.isDown) return\n\n\t\t\t// Left-click: wait for the drag threshold before forwarding anything, then\n\t\t\t// replay pointerdown at the original start so the editor records the\n\t\t\t// correct drag origin. Right-click forwards moves immediately.\n\t\t\tif (state.button !== 2 && !state.isDragging) {\n\t\t\t\tif (\n\t\t\t\t\tVec.Dist2(state.start, new Vec(e.clientX, e.clientY)) <=\n\t\t\t\t\teditor.options.dragDistanceSquared\n\t\t\t\t) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tstate.isDragging = true\n\t\t\t\teditor.dispatch({\n\t\t\t\t\ttype: 'pointer',\n\t\t\t\t\ttarget: 'canvas',\n\t\t\t\t\tname: 'pointer_down',\n\t\t\t\t\t...getPointerInfo(editor, { ...e, clientX: state.start.x, clientY: state.start.y }),\n\t\t\t\t})\n\t\t\t}\n\n\t\t\teditor.dispatch({\n\t\t\t\ttype: 'pointer',\n\t\t\t\ttarget: 'canvas',\n\t\t\t\tname: 'pointer_move',\n\t\t\t\t...getPointerInfo(editor, e),\n\t\t\t})\n\t\t},\n\t\t[editor]\n\t)\n\n\tconst handlePointerUp = useCallback(\n\t\t(e: PointerEvent) => {\n\t\t\tconst isStaticRightClick =\n\t\t\t\trPointerState.current.button === 2 && !rPointerState.current.isDragging\n\n\t\t\teditor.dispatch({\n\t\t\t\ttype: 'pointer',\n\t\t\t\ttarget: 'canvas',\n\t\t\t\tname: 'pointer_up',\n\t\t\t\t...getPointerInfo(editor, e),\n\t\t\t\tbutton: rPointerState.current.button === 2 ? 2 : getPointerEventButton(e),\n\t\t\t})\n\n\t\t\tif (isStaticRightClick && editor.options.rightClickPanning) {\n\t\t\t\t// Dispatch contextmenu on the canvas's parent (Radix's trigger) so the\n\t\t\t\t// menu opens at the release position. Bypassing the canvas avoids its\n\t\t\t\t// own onContextMenu handler, which preventDefaults non-synthesized events.\n\t\t\t\tconst canvas = editor.getContainer().querySelector<HTMLDivElement>('.tl-canvas')\n\t\t\t\tconst trigger = canvas?.parentElement ?? e.currentTarget\n\t\t\t\teditor.timers.requestAnimationFrame(() => {\n\t\t\t\t\ttrigger.dispatchEvent(\n\t\t\t\t\t\tnew PointerEvent('contextmenu', {\n\t\t\t\t\t\t\tbubbles: true,\n\t\t\t\t\t\t\tclientX: e.clientX,\n\t\t\t\t\t\t\tclientY: e.clientY,\n\t\t\t\t\t\t\tbutton: 2,\n\t\t\t\t\t\t\tbuttons: 0,\n\t\t\t\t\t\t\tpointerId: e.pointerId,\n\t\t\t\t\t\t\tpointerType: e.pointerType,\n\t\t\t\t\t\t\tisPrimary: e.isPrimary,\n\t\t\t\t\t\t})\n\t\t\t\t\t)\n\t\t\t\t})\n\t\t\t}\n\n\t\t\treleasePointerCapture(e.currentTarget, e)\n\t\t\tsetIsPointing(false)\n\t\t\trPointerState.current = {\n\t\t\t\tisDown: false,\n\t\t\t\tisDragging: false,\n\t\t\t\tbutton: 0,\n\t\t\t\tstart: new Vec(e.clientX, e.clientY),\n\t\t\t}\n\t\t},\n\t\t[editor]\n\t)\n\n\treturn (\n\t\tshowElement && (\n\t\t\t<div\n\t\t\t\tclassName=\"tlui-menu-click-capture\"\n\t\t\t\tdata-testid=\"menu-click-capture.content\"\n\t\t\t\t{...canvasEvents}\n\t\t\t\tonPointerDown={handlePointerDown}\n\t\t\t\tonPointerMove={handlePointerMove}\n\t\t\t\tonPointerUp={handlePointerUp}\n\t\t\t\tonContextMenu={(e) => {\n\t\t\t\t\te.preventDefault()\n\t\t\t\t\te.stopPropagation()\n\t\t\t\t}}\n\t\t\t/>\n\t\t)\n\t)\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { useValue } from '@tldraw/state-react'\nimport { type PointerEvent, useCallback, useEffect, useRef, useState } from 'react'\nimport { flushSync } from 'react-dom'\nimport { useCanvasEvents } from '../hooks/useCanvasEvents'\nimport { useEditor } from '../hooks/useEditor'\nimport { Vec } from '../primitives/Vec'\nimport { releasePointerCapture, setPointerCapture } from '../utils/dom'\nimport { getPointerInfo } from '../utils/getPointerInfo'\nimport { getPointerEventButton } from '../utils/pointer'\n\n/**\n * When a menu is open, this component prevents the user from interacting with the canvas.\n *\n * @public @react\n */\nexport function MenuClickCapture() {\n\tconst editor = useEditor()\n\n\tconst isMenuOpen = useValue('is menu open', () => editor.menus.hasAnyOpenMenus(), [editor])\n\n\t// Keep this component mounted while the pointer is down so pointerup/move still\n\t// land here after a synchronous clearOpenMenus() flips isMenuOpen to false.\n\tconst [isPointing, setIsPointing] = useState(false)\n\tconst showElement = isMenuOpen || isPointing\n\n\tconst canvasEvents = useCanvasEvents()\n\n\tconst rPointerState = useRef({\n\t\tisDown: false,\n\t\tisDragging: false,\n\t\tbutton: 0,\n\t\tpointerId: -1,\n\t\tstart: new Vec(),\n\t})\n\n\t// Swallow the native contextmenu that follows a right-click pointerdown. Without\n\t// this, Radix's trigger catches the native event and opens a menu at the pointer-\n\t// DOWN position \u2014 then our own synthetic contextmenu (fired on pointerup) opens it\n\t// again at the release position, producing a visible flash.\n\tconst rCancelContextMenuSwallow = useRef<null | (() => void)>(null)\n\tuseEffect(\n\t\t() => () => {\n\t\t\trCancelContextMenuSwallow.current?.()\n\t\t\trCancelContextMenuSwallow.current = null\n\t\t},\n\t\t[]\n\t)\n\tconst swallowNextNativeContextMenu = useCallback(() => {\n\t\trCancelContextMenuSwallow.current?.()\n\t\tconst doc = editor.getContainerDocument()\n\t\tconst onContextMenu = (event: MouseEvent) => {\n\t\t\t// Skip our own synthetic contextmenu \u2014 only swallow the real browser one\n\t\t\tif (!event.isTrusted) return\n\t\t\trCancelContextMenuSwallow.current?.()\n\t\t\trCancelContextMenuSwallow.current = null\n\t\t\tevent.preventDefault()\n\t\t\tevent.stopImmediatePropagation()\n\t\t}\n\t\tconst cancel = () => doc.removeEventListener('contextmenu', onContextMenu, true)\n\t\trCancelContextMenuSwallow.current = cancel\n\t\tdoc.addEventListener('contextmenu', onContextMenu, true)\n\t\t// Drop the listener on the next tick if it never fires (e.g. pointer moved off-screen)\n\t\tdoc.defaultView?.setTimeout(() => {\n\t\t\tif (rCancelContextMenuSwallow.current === cancel) {\n\t\t\t\tcancel()\n\t\t\t\trCancelContextMenuSwallow.current = null\n\t\t\t}\n\t\t}, 0)\n\t}, [editor])\n\n\tconst handlePointerDown = useCallback(\n\t\t(e: PointerEvent) => {\n\t\t\t// This overlay tracks a single press. A second pointer landing while one is active \u2014\n\t\t\t// a palm resting on the glass beside a pen \u2014 must not take over the gesture, or its\n\t\t\t// own cancel would end the press it stole.\n\t\t\tif (rPointerState.current.isDown) return\n\n\t\t\tconst button = getPointerEventButton(e)\n\t\t\tif (button !== 0 && button !== 2) return\n\n\t\t\tif (button === 2 && editor.options.rightClickPanning) {\n\t\t\t\t// Forward right-click pointerdown through the canvas's own handler so\n\t\t\t\t// pointer capture is set on the canvas (load-bearing: without this\n\t\t\t\t// the context menu briefly flashes closed during consecutive right-clicks).\n\t\t\t\t// The canvas owns the rest of the gesture, so don't capture or mark\n\t\t\t\t// pointing here: this element's pointerup would never fire, leaving it\n\t\t\t\t// mounted over the canvas after the menu closes.\n\t\t\t\t// We don't clearOpenMenus() \u2014 Radix's DismissableLayer closes the menu\n\t\t\t\t// via outside-click detection, keeping its internal state in sync.\n\t\t\t\tconst canvas =\n\t\t\t\t\teditor.getContainer().querySelector<HTMLDivElement>('.tl-canvas') ?? e.currentTarget\n\t\t\t\tcanvasEvents.onPointerDown?.({ ...e, currentTarget: canvas })\n\t\t\t\tswallowNextNativeContextMenu()\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tflushSync(() => setIsPointing(true))\n\t\t\tsetPointerCapture(e.currentTarget, e)\n\t\t\trPointerState.current = {\n\t\t\t\tisDown: true,\n\t\t\t\tisDragging: false,\n\t\t\t\tbutton,\n\t\t\t\tpointerId: e.pointerId,\n\t\t\t\tstart: new Vec(e.clientX, e.clientY),\n\t\t\t}\n\n\t\t\tif (button === 2) {\n\t\t\t\t// Right-click panning off: swallow the native contextmenu that would otherwise\n\t\t\t\t// briefly open a new menu (causing a flash) once the open one closes below.\n\t\t\t\tswallowNextNativeContextMenu()\n\t\t\t}\n\n\t\t\teditor.menus.clearOpenMenus()\n\t\t},\n\t\t[canvasEvents, editor, swallowNextNativeContextMenu]\n\t)\n\n\tconst handlePointerMove = useCallback(\n\t\t(e: PointerEvent) => {\n\t\t\tconst state = rPointerState.current\n\t\t\tif (!state.isDown || state.pointerId !== e.pointerId) return\n\n\t\t\t// Left-click: wait for the drag threshold before forwarding anything, then\n\t\t\t// replay pointerdown at the original start so the editor records the\n\t\t\t// correct drag origin. Right-click forwards moves immediately.\n\t\t\tif (state.button !== 2 && !state.isDragging) {\n\t\t\t\tif (\n\t\t\t\t\tVec.Dist2(state.start, new Vec(e.clientX, e.clientY)) <=\n\t\t\t\t\teditor.options.dragDistanceSquared\n\t\t\t\t) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tstate.isDragging = true\n\t\t\t\teditor.dispatch({\n\t\t\t\t\ttype: 'pointer',\n\t\t\t\t\ttarget: 'canvas',\n\t\t\t\t\tname: 'pointer_down',\n\t\t\t\t\t...getPointerInfo(editor, { ...e, clientX: state.start.x, clientY: state.start.y }),\n\t\t\t\t})\n\t\t\t}\n\n\t\t\teditor.dispatch({\n\t\t\t\ttype: 'pointer',\n\t\t\t\ttarget: 'canvas',\n\t\t\t\tname: 'pointer_move',\n\t\t\t\t...getPointerInfo(editor, e),\n\t\t\t})\n\t\t},\n\t\t[editor]\n\t)\n\n\tconst handlePointerUp = useCallback(\n\t\t(e: PointerEvent) => {\n\t\t\tconst state = rPointerState.current\n\t\t\tif (!state.isDown || state.pointerId !== e.pointerId) return\n\n\t\t\tconst isStaticRightClick = state.button === 2 && !state.isDragging\n\n\t\t\teditor.dispatch({\n\t\t\t\ttype: 'pointer',\n\t\t\t\ttarget: 'canvas',\n\t\t\t\tname: 'pointer_up',\n\t\t\t\t...getPointerInfo(editor, e),\n\t\t\t\tbutton: state.button === 2 ? 2 : getPointerEventButton(e),\n\t\t\t})\n\n\t\t\tif (isStaticRightClick && editor.options.rightClickPanning) {\n\t\t\t\t// Dispatch contextmenu on the canvas's parent (Radix's trigger) so the\n\t\t\t\t// menu opens at the release position. Bypassing the canvas avoids its\n\t\t\t\t// own onContextMenu handler, which preventDefaults non-synthesized events.\n\t\t\t\tconst canvas = editor.getContainer().querySelector<HTMLDivElement>('.tl-canvas')\n\t\t\t\tconst trigger = canvas?.parentElement ?? e.currentTarget\n\t\t\t\teditor.timers.requestAnimationFrame(() => {\n\t\t\t\t\ttrigger.dispatchEvent(\n\t\t\t\t\t\tnew PointerEvent('contextmenu', {\n\t\t\t\t\t\t\tbubbles: true,\n\t\t\t\t\t\t\tclientX: e.clientX,\n\t\t\t\t\t\t\tclientY: e.clientY,\n\t\t\t\t\t\t\tbutton: 2,\n\t\t\t\t\t\t\tbuttons: 0,\n\t\t\t\t\t\t\tpointerId: e.pointerId,\n\t\t\t\t\t\t\tpointerType: e.pointerType,\n\t\t\t\t\t\t\tisPrimary: e.isPrimary,\n\t\t\t\t\t\t})\n\t\t\t\t\t)\n\t\t\t\t})\n\t\t\t}\n\n\t\t\treleasePointerCapture(e.currentTarget, e)\n\t\t\tsetIsPointing(false)\n\t\t\trPointerState.current = {\n\t\t\t\tisDown: false,\n\t\t\t\tisDragging: false,\n\t\t\t\tbutton: 0,\n\t\t\t\tpointerId: -1,\n\t\t\t\tstart: new Vec(e.clientX, e.clientY),\n\t\t\t}\n\t\t},\n\t\t[editor]\n\t)\n\n\tconst handlePointerCancel = useCallback(\n\t\t(e: PointerEvent) => {\n\t\t\tconst state = rPointerState.current\n\t\t\tif (!state.isDown || state.pointerId !== e.pointerId) {\n\t\t\t\t// Either a right-click press that was forwarded to the canvas, or a pointer this\n\t\t\t\t// overlay never tracked. Neither is ours to end, so let the canvas handler decide.\n\t\t\t\tcanvasEvents.onPointerCancel?.(e)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// The canvas's own cancel handler doesn't know about this element's pointer\n\t\t\t// state, so without this the overlay stays mounted over the canvas and\n\t\t\t// swallows the next interaction after the browser cancels a press.\n\t\t\tif (editor.inputs.getIsPointing()) {\n\t\t\t\teditor.interrupt()\n\t\t\t\teditor.dispatch({\n\t\t\t\t\ttype: 'pointer',\n\t\t\t\t\ttarget: 'canvas',\n\t\t\t\t\tname: 'pointer_up',\n\t\t\t\t\t...getPointerInfo(editor, e),\n\t\t\t\t\t// pointercancel reports button -1\n\t\t\t\t\tbutton: state.button,\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\teditor.markEventAsHandled(e)\n\t\t\t}\n\n\t\t\treleasePointerCapture(e.currentTarget, e)\n\t\t\tsetIsPointing(false)\n\t\t\trPointerState.current = {\n\t\t\t\tisDown: false,\n\t\t\t\tisDragging: false,\n\t\t\t\tbutton: 0,\n\t\t\t\tpointerId: -1,\n\t\t\t\tstart: new Vec(e.clientX, e.clientY),\n\t\t\t}\n\t\t},\n\t\t[canvasEvents, editor]\n\t)\n\n\treturn (\n\t\tshowElement && (\n\t\t\t<div\n\t\t\t\tclassName=\"tlui-menu-click-capture\"\n\t\t\t\tdata-testid=\"menu-click-capture.content\"\n\t\t\t\t{...canvasEvents}\n\t\t\t\tonPointerDown={handlePointerDown}\n\t\t\t\tonPointerMove={handlePointerMove}\n\t\t\t\tonPointerUp={handlePointerUp}\n\t\t\t\tonPointerCancel={handlePointerCancel}\n\t\t\t\tonContextMenu={(e) => {\n\t\t\t\t\te.preventDefault()\n\t\t\t\t\te.stopPropagation()\n\t\t\t\t}}\n\t\t\t/>\n\t\t)\n\t)\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -2801,11 +2801,14 @@ class Editor extends import_eventemitter3.default {
2801
2801
  _animateViewport(ms) {
2802
2802
  if (!this._viewportAnimation) return;
2803
2803
  this._viewportAnimation.elapsed += ms;
2804
- const { elapsed, easing, duration, start, end } = this._viewportAnimation;
2804
+ const { elapsed, easing, duration, start, end, opts } = this._viewportAnimation;
2805
2805
  if (elapsed > duration) {
2806
2806
  this.off("tick", this._animateViewport);
2807
2807
  this._viewportAnimation = null;
2808
- this._setCamera(new import_Vec.Vec(-end.x, -end.y, this.getViewportScreenBounds().width / end.width));
2808
+ this._setCamera(
2809
+ new import_Vec.Vec(-end.x, -end.y, this.getViewportScreenBounds().width / end.width),
2810
+ opts
2811
+ );
2809
2812
  return;
2810
2813
  }
2811
2814
  const remaining = duration - elapsed;
@@ -2843,7 +2846,8 @@ class Editor extends import_eventemitter3.default {
2843
2846
  duration: duration / animationSpeed,
2844
2847
  easing,
2845
2848
  start: viewportPageBounds.clone(),
2846
- end: targetViewportPage.clone()
2849
+ end: targetViewportPage.clone(),
2850
+ opts: rest
2847
2851
  };
2848
2852
  this.once("stop-camera-animation", () => {
2849
2853
  this.off("tick", this._animateViewport);
@@ -4242,12 +4246,14 @@ class Editor extends import_eventemitter3.default {
4242
4246
  */
4243
4247
  getSelectedShapeAtPoint(point) {
4244
4248
  const selectedShapeIds = this.getSelectedShapeIds();
4245
- const margin = this.options.hitTestMargin / this.getZoomLevel();
4249
+ if (selectedShapeIds.length === 0) return void 0;
4250
+ const selectedShapeIdSet = new Set(selectedShapeIds);
4251
+ const margin = this.getHitTestMargin();
4246
4252
  const sortedShapes = this.getCurrentPageShapesSorted();
4247
4253
  for (let i = sortedShapes.length - 1; i >= 0; i--) {
4248
4254
  const shape = sortedShapes[i];
4249
4255
  if (shape.type === "group") continue;
4250
- if (!selectedShapeIds.includes(shape.id)) continue;
4256
+ if (!selectedShapeIdSet.has(shape.id)) continue;
4251
4257
  if (this.getShapeGeometry(shape).hitTestPoint(
4252
4258
  this.getPointInShapeSpace(shape, point),
4253
4259
  margin,
@@ -4345,7 +4351,6 @@ class Editor extends import_eventemitter3.default {
4345
4351
  }
4346
4352
  return inMarginClosestToEdgeHit || shape;
4347
4353
  } else {
4348
- if (this.getShapePageBounds(shape).contains(viewportPageBounds)) continue;
4349
4354
  if (hitInside ? (
4350
4355
  // On hitInside, the distance will be negative for hits inside
4351
4356
  // If the distance is positive, check against the outer margin
@@ -4362,6 +4367,7 @@ class Editor extends import_eventemitter3.default {
4362
4367
  inMarginClosestToEdgeHit = shape;
4363
4368
  }
4364
4369
  } else if (!inMarginClosestToEdgeHit) {
4370
+ if (this.getShapePageBounds(shape).contains(viewportPageBounds)) continue;
4365
4371
  const { area } = geometry;
4366
4372
  if (area < inHollowSmallestArea) {
4367
4373
  inHollowSmallestArea = area;
@@ -4372,6 +4378,9 @@ class Editor extends import_eventemitter3.default {
4372
4378
  }
4373
4379
  } else {
4374
4380
  if (distance < this.getHitTestMargin()) {
4381
+ if (inMarginClosestToEdgeHit && inMarginClosestToEdgeDistance <= distance) {
4382
+ return inMarginClosestToEdgeHit;
4383
+ }
4375
4384
  return shape;
4376
4385
  }
4377
4386
  }
@@ -8135,6 +8144,7 @@ class Editor extends import_eventemitter3.default {
8135
8144
  inputs.buttons.add(info.button);
8136
8145
  inputs.setIsPointing(true);
8137
8146
  inputs.setIsDragging(false);
8147
+ this.stopCameraAnimation();
8138
8148
  if (!isPenMode && info.isPenDirect) {
8139
8149
  this.updateInstanceState({ isPenMode: true });
8140
8150
  this.interrupt();