@tldraw/editor 5.4.0-canary.d83d146f4cdc → 5.4.0-canary.dc9b1f2c03ff
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.
- package/dist-cjs/index.d.ts +31 -1
- package/dist-cjs/index.js +1 -1
- package/dist-cjs/lib/components/MenuClickCapture.js +6 -8
- package/dist-cjs/lib/components/MenuClickCapture.js.map +2 -2
- package/dist-cjs/lib/components/default-components/CanvasOverlays.js +1 -3
- package/dist-cjs/lib/components/default-components/CanvasOverlays.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js.map +1 -1
- package/dist-cjs/lib/config/TLUserPreferences.js +6 -2
- package/dist-cjs/lib/config/TLUserPreferences.js.map +2 -2
- package/dist-cjs/lib/config/createTLStore.js +1 -1
- package/dist-cjs/lib/config/createTLStore.js.map +2 -2
- package/dist-cjs/lib/editor/Editor.js +139 -268
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.js +8 -8
- package/dist-cjs/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/FontManager/FontManager.js +2 -1
- package/dist-cjs/lib/editor/managers/FontManager/FontManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js +79 -6
- package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js +0 -2
- package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js.map +2 -2
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +1 -0
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
- package/dist-cjs/lib/editor/overlays/OverlayManager.js +3 -7
- package/dist-cjs/lib/editor/overlays/OverlayManager.js.map +2 -2
- package/dist-cjs/lib/editor/overlays/strokeShapeIndicators.js +0 -1
- package/dist-cjs/lib/editor/overlays/strokeShapeIndicators.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/BaseFrameLikeShapeUtil.js +3 -1
- package/dist-cjs/lib/editor/shapes/BaseFrameLikeShapeUtil.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/shared/getPerfectDashProps.js +1 -0
- package/dist-cjs/lib/editor/shapes/shared/getPerfectDashProps.js.map +2 -2
- package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js +1 -1
- package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js.map +2 -2
- package/dist-cjs/lib/editor/tools/StateNode.js +3 -2
- package/dist-cjs/lib/editor/tools/StateNode.js.map +2 -2
- package/dist-cjs/lib/globals/menus.js +9 -4
- package/dist-cjs/lib/globals/menus.js.map +2 -2
- package/dist-cjs/lib/hooks/useCanvasEvents.js +2 -0
- package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/useDocumentEvents.js +9 -7
- package/dist-cjs/lib/hooks/useDocumentEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/useLocalStore.js +10 -6
- package/dist-cjs/lib/hooks/useLocalStore.js.map +2 -2
- package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js +1 -0
- package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/usePeerIds.js +2 -1
- package/dist-cjs/lib/hooks/usePeerIds.js.map +2 -2
- package/dist-cjs/lib/license/LicenseManager.js +6 -1
- package/dist-cjs/lib/license/LicenseManager.js.map +2 -2
- package/dist-cjs/lib/primitives/Box.js +2 -1
- package/dist-cjs/lib/primitives/Box.js.map +2 -2
- package/dist-cjs/lib/primitives/Vec.js +4 -3
- package/dist-cjs/lib/primitives/Vec.js.map +2 -2
- package/dist-cjs/lib/primitives/utils.js +2 -1
- package/dist-cjs/lib/primitives/utils.js.map +2 -2
- package/dist-cjs/lib/utils/rotation.js +1 -9
- package/dist-cjs/lib/utils/rotation.js.map +2 -2
- package/dist-cjs/version.js +3 -3
- package/dist-cjs/version.js.map +1 -1
- package/dist-esm/index.d.mts +31 -1
- package/dist-esm/index.mjs +1 -1
- package/dist-esm/lib/components/MenuClickCapture.mjs +6 -8
- package/dist-esm/lib/components/MenuClickCapture.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/CanvasOverlays.mjs +1 -3
- package/dist-esm/lib/components/default-components/CanvasOverlays.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs.map +1 -1
- package/dist-esm/lib/config/TLUserPreferences.mjs +6 -2
- package/dist-esm/lib/config/TLUserPreferences.mjs.map +2 -2
- package/dist-esm/lib/config/createTLStore.mjs +1 -1
- package/dist-esm/lib/config/createTLStore.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +147 -269
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.mjs +9 -9
- package/dist-esm/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs +2 -1
- package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs +81 -8
- package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs +0 -2
- package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +1 -0
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
- package/dist-esm/lib/editor/overlays/OverlayManager.mjs +3 -7
- package/dist-esm/lib/editor/overlays/OverlayManager.mjs.map +2 -2
- package/dist-esm/lib/editor/overlays/strokeShapeIndicators.mjs +0 -1
- package/dist-esm/lib/editor/overlays/strokeShapeIndicators.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/BaseFrameLikeShapeUtil.mjs +3 -1
- package/dist-esm/lib/editor/shapes/BaseFrameLikeShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/shared/getPerfectDashProps.mjs +1 -0
- package/dist-esm/lib/editor/shapes/shared/getPerfectDashProps.mjs.map +2 -2
- package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs +1 -1
- package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs.map +2 -2
- package/dist-esm/lib/editor/tools/StateNode.mjs +3 -2
- package/dist-esm/lib/editor/tools/StateNode.mjs.map +2 -2
- package/dist-esm/lib/globals/menus.mjs +9 -4
- package/dist-esm/lib/globals/menus.mjs.map +2 -2
- package/dist-esm/lib/hooks/useCanvasEvents.mjs +2 -0
- package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useDocumentEvents.mjs +9 -7
- package/dist-esm/lib/hooks/useDocumentEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useLocalStore.mjs +11 -7
- package/dist-esm/lib/hooks/useLocalStore.mjs.map +2 -2
- package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs +1 -0
- package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/usePeerIds.mjs +2 -1
- package/dist-esm/lib/hooks/usePeerIds.mjs.map +2 -2
- package/dist-esm/lib/license/LicenseManager.mjs +6 -1
- package/dist-esm/lib/license/LicenseManager.mjs.map +2 -2
- package/dist-esm/lib/primitives/Box.mjs +2 -1
- package/dist-esm/lib/primitives/Box.mjs.map +2 -2
- package/dist-esm/lib/primitives/Vec.mjs +4 -3
- package/dist-esm/lib/primitives/Vec.mjs.map +2 -2
- package/dist-esm/lib/primitives/utils.mjs +2 -1
- package/dist-esm/lib/primitives/utils.mjs.map +2 -2
- package/dist-esm/lib/utils/rotation.mjs +1 -9
- package/dist-esm/lib/utils/rotation.mjs.map +2 -2
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/package.json +7 -7
- package/src/lib/components/MenuClickCapture.tsx +19 -18
- package/src/lib/components/default-components/CanvasOverlays.tsx +1 -3
- package/src/lib/components/default-components/DefaultErrorFallback.tsx +1 -1
- package/src/lib/config/TLUserPreferences.test.ts +18 -1
- package/src/lib/config/TLUserPreferences.ts +8 -4
- package/src/lib/config/createTLStore.ts +1 -1
- package/src/lib/editor/Editor.ts +196 -341
- package/src/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.ts +9 -9
- package/src/lib/editor/managers/FontManager/FontManager.ts +2 -1
- package/src/lib/editor/managers/InputsManager/InputsManager.test.ts +199 -3
- package/src/lib/editor/managers/InputsManager/InputsManager.ts +128 -9
- package/src/lib/editor/managers/SnapManager/BoundsSnaps.ts +0 -2
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +1 -0
- package/src/lib/editor/overlays/OverlayManager.ts +3 -7
- package/src/lib/editor/overlays/strokeShapeIndicators.ts +0 -1
- package/src/lib/editor/shapes/BaseFrameLikeShapeUtil.tsx +5 -1
- package/src/lib/editor/shapes/shared/getPerfectDashProps.ts +3 -0
- package/src/lib/editor/tools/BaseBoxShapeTool/children/Pointing.ts +4 -1
- package/src/lib/editor/tools/StateNode.test.ts +64 -0
- package/src/lib/editor/tools/StateNode.ts +12 -2
- package/src/lib/globals/menus.test.ts +33 -0
- package/src/lib/globals/menus.ts +11 -4
- package/src/lib/hooks/useCanvasEvents.ts +2 -0
- package/src/lib/hooks/useDocumentEvents.ts +14 -7
- package/src/lib/hooks/useLocalStore.ts +16 -8
- package/src/lib/hooks/usePassThroughWheelEvents.ts +3 -0
- package/src/lib/hooks/usePeerIds.ts +2 -1
- package/src/lib/license/LicenseManager.test.ts +40 -7
- package/src/lib/license/LicenseManager.ts +10 -2
- package/src/lib/primitives/Box.test.ts +9 -1
- package/src/lib/primitives/Box.ts +3 -1
- package/src/lib/primitives/Vec.test.ts +10 -0
- package/src/lib/primitives/Vec.ts +4 -4
- package/src/lib/primitives/utils.test.ts +10 -1
- package/src/lib/primitives/utils.ts +4 -1
- package/src/lib/test/useCanvasEvents.test.tsx +74 -0
- package/src/lib/test/useDocumentEvents.test.tsx +31 -0
- package/src/lib/test/usePassThroughWheelEvents.test.tsx +25 -2
- package/src/lib/utils/rotation.ts +4 -12
- package/src/version.ts +3 -3
package/dist-cjs/index.d.ts
CHANGED
|
@@ -2278,6 +2278,7 @@ export declare class Editor extends EventEmitter<TLEventMap> {
|
|
|
2278
2278
|
*
|
|
2279
2279
|
* @public */
|
|
2280
2280
|
getBaseZoom(): number;
|
|
2281
|
+
private _getFitZoom;
|
|
2281
2282
|
private _cameraOptions;
|
|
2282
2283
|
/**
|
|
2283
2284
|
* Get the current camera options.
|
|
@@ -3952,7 +3953,7 @@ export declare class Editor extends EventEmitter<TLEventMap> {
|
|
|
3952
3953
|
*/
|
|
3953
3954
|
deleteShape(id: TLShapeId): this;
|
|
3954
3955
|
deleteShape(shape: TLShape): this;
|
|
3955
|
-
/* Excluded from this release type:
|
|
3956
|
+
/* Excluded from this release type: _getStyleableShapes */
|
|
3956
3957
|
/* Excluded from this release type: _getSelectionSharedStyles */
|
|
3957
3958
|
/**
|
|
3958
3959
|
* Get the style for the next shape.
|
|
@@ -5169,6 +5170,15 @@ export declare const inlineBase64AssetStore: TLAssetStore;
|
|
|
5169
5170
|
/** @public */
|
|
5170
5171
|
export declare class InputsManager extends EditorManager {
|
|
5171
5172
|
constructor(editor: Editor);
|
|
5173
|
+
private _detachActivityListenersFn;
|
|
5174
|
+
/**
|
|
5175
|
+
* User input anywhere in the editor's tab counts as activity for collaborator presence —
|
|
5176
|
+
* presence means "this person is here", whether or not the input lands on the editor itself
|
|
5177
|
+
* (e.g. typing in a sidebar next to the canvas). Listen in the capture phase so input that
|
|
5178
|
+
* other handlers swallow still counts.
|
|
5179
|
+
*/
|
|
5180
|
+
private _attachActivityListeners;
|
|
5181
|
+
private _detachActivityListeners;
|
|
5172
5182
|
private _onFrame;
|
|
5173
5183
|
private _originPagePoint;
|
|
5174
5184
|
/**
|
|
@@ -5387,6 +5397,26 @@ export declare class InputsManager extends EditorManager {
|
|
|
5387
5397
|
set isSpacebarPanning(isSpacebarPanning: boolean);
|
|
5388
5398
|
/* Excluded from this release type: setIsSpacebarPanning */
|
|
5389
5399
|
private _getHasCollaborators;
|
|
5400
|
+
private readonly _throttledActivityStamp;
|
|
5401
|
+
/**
|
|
5402
|
+
* Mark the current user as active for collaborator presence. User input anywhere in the
|
|
5403
|
+
* editor's tab counts as activity automatically; call this to make input that doesn't produce
|
|
5404
|
+
* DOM events count too, so peers don't classify this user as idle or inactive while they're
|
|
5405
|
+
* still interacting. Calls are throttled on the leading edge, so it's safe to call from
|
|
5406
|
+
* high-frequency input events.
|
|
5407
|
+
*
|
|
5408
|
+
* @example
|
|
5409
|
+
* ```ts
|
|
5410
|
+
* // Gamepads are polled rather than event-driven, so stamp activity from the poll
|
|
5411
|
+
* editor.timers.setInterval(() => {
|
|
5412
|
+
* const isPressed = navigator
|
|
5413
|
+
* .getGamepads()
|
|
5414
|
+
* .some((pad) => pad?.buttons.some((button) => button.pressed))
|
|
5415
|
+
* if (isPressed) editor.inputs.markActivity()
|
|
5416
|
+
* }, 50)
|
|
5417
|
+
* ```
|
|
5418
|
+
*/
|
|
5419
|
+
markActivity(): void;
|
|
5390
5420
|
/* Excluded from this release type: _velocityPrevPoint */
|
|
5391
5421
|
/* Excluded from this release type: updatePointerVelocity */
|
|
5392
5422
|
/* Excluded from this release type: updateFromEvent */
|
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.4.0-canary.
|
|
395
|
+
"5.4.0-canary.dc9b1f2c03ff",
|
|
396
396
|
"cjs"
|
|
397
397
|
);
|
|
398
398
|
//# sourceMappingURL=index.js.map
|
|
@@ -75,6 +75,12 @@ function MenuClickCapture() {
|
|
|
75
75
|
(e) => {
|
|
76
76
|
const button = (0, import_pointer.getPointerEventButton)(e);
|
|
77
77
|
if (button !== 0 && button !== 2) return;
|
|
78
|
+
if (button === 2 && editor.options.rightClickPanning) {
|
|
79
|
+
const canvas = editor.getContainer().querySelector(".tl-canvas") ?? e.currentTarget;
|
|
80
|
+
canvasEvents.onPointerDown?.({ ...e, currentTarget: canvas });
|
|
81
|
+
swallowNextNativeContextMenu();
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
78
84
|
(0, import_react_dom.flushSync)(() => setIsPointing(true));
|
|
79
85
|
(0, import_dom.setPointerCapture)(e.currentTarget, e);
|
|
80
86
|
rPointerState.current = {
|
|
@@ -84,15 +90,7 @@ function MenuClickCapture() {
|
|
|
84
90
|
start: new import_Vec.Vec(e.clientX, e.clientY)
|
|
85
91
|
};
|
|
86
92
|
if (button === 2) {
|
|
87
|
-
if (!editor.options.rightClickPanning) {
|
|
88
|
-
swallowNextNativeContextMenu();
|
|
89
|
-
editor.menus.clearOpenMenus();
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
const canvas = editor.getContainer().querySelector(".tl-canvas") ?? e.currentTarget;
|
|
93
|
-
canvasEvents.onPointerDown?.({ ...e, currentTarget: canvas });
|
|
94
93
|
swallowNextNativeContextMenu();
|
|
95
|
-
return;
|
|
96
94
|
}
|
|
97
95
|
editor.menus.clearOpenMenus();
|
|
98
96
|
},
|
|
@@ -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\
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
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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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -79,10 +79,8 @@ const CanvasOverlays = (0, import_react.memo)(function CanvasOverlays2() {
|
|
|
79
79
|
const shape = editor.getShape(result.id);
|
|
80
80
|
if (!shape || shape.type === "group") continue;
|
|
81
81
|
const geometry = editor.getShapeGeometry(shape);
|
|
82
|
-
const
|
|
83
|
-
if (!pageTransform) continue;
|
|
82
|
+
const m = editor.getShapePageTransform(shape);
|
|
84
83
|
ctx.save();
|
|
85
|
-
const m = pageTransform;
|
|
86
84
|
ctx.transform(m.a, m.b, m.c, m.d, m.e, m.f);
|
|
87
85
|
ctx.strokeStyle = geometry.debugColor ?? "red";
|
|
88
86
|
ctx.lineWidth = 2 / zoom;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/components/default-components/CanvasOverlays.tsx"],
|
|
4
|
-
"sourcesContent": ["import { EffectScheduler, computed } from '@tldraw/state'\nimport { memo, useEffect, useRef } from 'react'\nimport { useEditor } from '../../hooks/useEditor'\nimport { Geometry2d } from '../../primitives/geometry/Geometry2d'\nimport { Group2d } from '../../primitives/geometry/Group2d'\nimport { debugFlags } from '../../utils/debug-flags'\n\ninterface RenderInputs {\n\tdpr: number\n\tw: number\n\th: number\n\tcx: number\n\tcy: number\n\tzoom: number\n}\n\n/** @internal @react */\nexport const CanvasOverlays = memo(function CanvasOverlays() {\n\tconst editor = useEditor()\n\tconst canvasRef = useRef<HTMLCanvasElement>(null)\n\n\tuseEffect(() => {\n\t\t// Bundle the primitive scalars the renderer needs into one computed so the\n\t\t// effect only refires on actual visual change. Reading the whole instance\n\t\t// state directly would otherwise wake the renderer on every cursor move,\n\t\t// brush update, etc.\n\n\t\tconst renderInputs$ = computed<RenderInputs>(\n\t\t\t'canvas overlays render inputs',\n\t\t\t() => {\n\t\t\t\tconst instance = editor.getInstanceState()\n\t\t\t\tconst camera = editor.getCamera()\n\t\t\t\treturn {\n\t\t\t\t\tdpr: instance.devicePixelRatio,\n\t\t\t\t\tw: instance.screenBounds.w,\n\t\t\t\t\th: instance.screenBounds.h,\n\t\t\t\t\tcx: camera.x,\n\t\t\t\t\tcy: camera.y,\n\t\t\t\t\tzoom: camera.z,\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tisEqual: (a, b) =>\n\t\t\t\t\ta.dpr === b.dpr &&\n\t\t\t\t\ta.w === b.w &&\n\t\t\t\t\ta.h === b.h &&\n\t\t\t\t\ta.cx === b.cx &&\n\t\t\t\t\ta.cy === b.cy &&\n\t\t\t\t\ta.zoom === b.zoom,\n\t\t\t}\n\t\t)\n\n\t\tconst scheduler = new EffectScheduler('canvas overlays render', () => {\n\t\t\tconst canvas = canvasRef.current\n\t\t\tif (!canvas) return\n\n\t\t\tconst ctx = canvas.getContext('2d')\n\t\t\tif (!ctx) return\n\n\t\t\tconst { dpr, w, h, cx, cy, zoom } = renderInputs$.get()\n\n\t\t\tconst canvasWidth = Math.ceil(w * dpr)\n\t\t\tconst canvasHeight = Math.ceil(h * dpr)\n\n\t\t\tif (canvas.width !== canvasWidth || canvas.height !== canvasHeight) {\n\t\t\t\tcanvas.width = canvasWidth\n\t\t\t\tcanvas.height = canvasHeight\n\t\t\t\tcanvas.style.width = `${w}px`\n\t\t\t\tcanvas.style.height = `${h}px`\n\t\t\t}\n\n\t\t\tctx.setTransform(1, 0, 0, 1, 0, 0)\n\t\t\tctx.clearRect(0, 0, canvas.width, canvas.height)\n\n\t\t\t// One setTransform = DPR scale * zoom scale * camera translate, into page space.\n\t\t\tconst s = dpr * zoom\n\t\t\tctx.setTransform(s, 0, 0, s, s * cx, s * cy)\n\n\t\t\t// Render all active overlay utils in zIndex order (low to high).\n\t\t\tfor (const { util, overlays } of editor.overlays.getActiveOverlayEntries()) {\n\t\t\t\tctx.save()\n\t\t\t\tutil.render(ctx, overlays)\n\t\t\t\tctx.restore()\n\t\t\t}\n\n\t\t\t// Debug: draw all geometry\n\t\t\tif (debugFlags.debugGeometry.get()) {\n\t\t\t\tconst currentPagePoint = editor.inputs.getCurrentPagePoint()\n\n\t\t\t\t// Shape geometries\n\t\t\t\tconst renderingShapes = editor.getRenderingShapes()\n\t\t\t\tfor (const result of renderingShapes) {\n\t\t\t\t\tconst shape = editor.getShape(result.id)\n\t\t\t\t\tif (!shape || shape.type === 'group') continue\n\n\t\t\t\t\tconst geometry = editor.getShapeGeometry(shape)\n\t\t\t\t\tconst
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
4
|
+
"sourcesContent": ["import { EffectScheduler, computed } from '@tldraw/state'\nimport { memo, useEffect, useRef } from 'react'\nimport { useEditor } from '../../hooks/useEditor'\nimport { Geometry2d } from '../../primitives/geometry/Geometry2d'\nimport { Group2d } from '../../primitives/geometry/Group2d'\nimport { debugFlags } from '../../utils/debug-flags'\n\ninterface RenderInputs {\n\tdpr: number\n\tw: number\n\th: number\n\tcx: number\n\tcy: number\n\tzoom: number\n}\n\n/** @internal @react */\nexport const CanvasOverlays = memo(function CanvasOverlays() {\n\tconst editor = useEditor()\n\tconst canvasRef = useRef<HTMLCanvasElement>(null)\n\n\tuseEffect(() => {\n\t\t// Bundle the primitive scalars the renderer needs into one computed so the\n\t\t// effect only refires on actual visual change. Reading the whole instance\n\t\t// state directly would otherwise wake the renderer on every cursor move,\n\t\t// brush update, etc.\n\n\t\tconst renderInputs$ = computed<RenderInputs>(\n\t\t\t'canvas overlays render inputs',\n\t\t\t() => {\n\t\t\t\tconst instance = editor.getInstanceState()\n\t\t\t\tconst camera = editor.getCamera()\n\t\t\t\treturn {\n\t\t\t\t\tdpr: instance.devicePixelRatio,\n\t\t\t\t\tw: instance.screenBounds.w,\n\t\t\t\t\th: instance.screenBounds.h,\n\t\t\t\t\tcx: camera.x,\n\t\t\t\t\tcy: camera.y,\n\t\t\t\t\tzoom: camera.z,\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tisEqual: (a, b) =>\n\t\t\t\t\ta.dpr === b.dpr &&\n\t\t\t\t\ta.w === b.w &&\n\t\t\t\t\ta.h === b.h &&\n\t\t\t\t\ta.cx === b.cx &&\n\t\t\t\t\ta.cy === b.cy &&\n\t\t\t\t\ta.zoom === b.zoom,\n\t\t\t}\n\t\t)\n\n\t\tconst scheduler = new EffectScheduler('canvas overlays render', () => {\n\t\t\tconst canvas = canvasRef.current\n\t\t\tif (!canvas) return\n\n\t\t\tconst ctx = canvas.getContext('2d')\n\t\t\tif (!ctx) return\n\n\t\t\tconst { dpr, w, h, cx, cy, zoom } = renderInputs$.get()\n\n\t\t\tconst canvasWidth = Math.ceil(w * dpr)\n\t\t\tconst canvasHeight = Math.ceil(h * dpr)\n\n\t\t\tif (canvas.width !== canvasWidth || canvas.height !== canvasHeight) {\n\t\t\t\tcanvas.width = canvasWidth\n\t\t\t\tcanvas.height = canvasHeight\n\t\t\t\tcanvas.style.width = `${w}px`\n\t\t\t\tcanvas.style.height = `${h}px`\n\t\t\t}\n\n\t\t\tctx.setTransform(1, 0, 0, 1, 0, 0)\n\t\t\tctx.clearRect(0, 0, canvas.width, canvas.height)\n\n\t\t\t// One setTransform = DPR scale * zoom scale * camera translate, into page space.\n\t\t\tconst s = dpr * zoom\n\t\t\tctx.setTransform(s, 0, 0, s, s * cx, s * cy)\n\n\t\t\t// Render all active overlay utils in zIndex order (low to high).\n\t\t\tfor (const { util, overlays } of editor.overlays.getActiveOverlayEntries()) {\n\t\t\t\tctx.save()\n\t\t\t\tutil.render(ctx, overlays)\n\t\t\t\tctx.restore()\n\t\t\t}\n\n\t\t\t// Debug: draw all geometry\n\t\t\tif (debugFlags.debugGeometry.get()) {\n\t\t\t\tconst currentPagePoint = editor.inputs.getCurrentPagePoint()\n\n\t\t\t\t// Shape geometries\n\t\t\t\tconst renderingShapes = editor.getRenderingShapes()\n\t\t\t\tfor (const result of renderingShapes) {\n\t\t\t\t\tconst shape = editor.getShape(result.id)\n\t\t\t\t\tif (!shape || shape.type === 'group') continue\n\n\t\t\t\t\tconst geometry = editor.getShapeGeometry(shape)\n\t\t\t\t\tconst m = editor.getShapePageTransform(shape)\n\n\t\t\t\t\tctx.save()\n\t\t\t\t\tctx.transform(m.a, m.b, m.c, m.d, m.e, m.f)\n\n\t\t\t\t\t// Outline\n\t\t\t\t\tctx.strokeStyle = geometry.debugColor ?? 'red'\n\t\t\t\t\tctx.lineWidth = 2 / zoom\n\t\t\t\t\tctx.fillStyle = 'none'\n\t\t\t\t\tdrawGeometryStroke(ctx, geometry)\n\n\t\t\t\t\t// Vertices\n\t\t\t\t\tconst { vertices } = geometry\n\t\t\t\t\tfor (let i = 0; i < vertices.length; i++) {\n\t\t\t\t\t\tconst v = vertices[i]\n\t\t\t\t\t\tconst hue = vertices.length > 1 ? 120 + ((200 - 120) * i) / (vertices.length - 1) : 160\n\t\t\t\t\t\tctx.fillStyle = `hsl(${hue}, 100%, 50%)`\n\t\t\t\t\t\tctx.strokeStyle = 'black'\n\t\t\t\t\t\tctx.lineWidth = 1 / zoom\n\t\t\t\t\t\tctx.beginPath()\n\t\t\t\t\t\tctx.arc(v.x, v.y, 2 / zoom, 0, Math.PI * 2)\n\t\t\t\t\t\tctx.fill()\n\t\t\t\t\t\tctx.stroke()\n\t\t\t\t\t}\n\n\t\t\t\t\t// Nearest point line\n\t\t\t\t\tconst pointInShapeSpace = editor.getPointInShapeSpace(shape, currentPagePoint)\n\t\t\t\t\tconst dist = Math.abs(geometry.distanceToPoint(pointInShapeSpace, true)) * zoom\n\t\t\t\t\tif (dist < 150) {\n\t\t\t\t\t\tconst nearestPoint = geometry.nearestPoint(pointInShapeSpace)\n\t\t\t\t\t\tconst hitInside = geometry.distanceToPoint(pointInShapeSpace, true) < 0\n\t\t\t\t\t\tctx.strokeStyle = hitInside ? 'goldenrod' : 'dodgerblue'\n\t\t\t\t\t\tctx.lineWidth = 2 / zoom\n\t\t\t\t\t\tctx.globalAlpha = 1 - dist / 150\n\t\t\t\t\t\tctx.beginPath()\n\t\t\t\t\t\tctx.moveTo(nearestPoint.x, nearestPoint.y)\n\t\t\t\t\t\tctx.lineTo(pointInShapeSpace.x, pointInShapeSpace.y)\n\t\t\t\t\t\tctx.stroke()\n\t\t\t\t\t\tctx.globalAlpha = 1\n\t\t\t\t\t}\n\n\t\t\t\t\tctx.restore()\n\t\t\t\t}\n\n\t\t\t\t// Overlay hit-test geometries\n\t\t\t\tctx.save()\n\t\t\t\tctx.strokeStyle = 'magenta'\n\t\t\t\tctx.fillStyle = 'rgba(255, 0, 255, 0.1)'\n\t\t\t\tctx.lineWidth = 1 / zoom\n\t\t\t\tfor (const { overlays } of editor.overlays.getActiveOverlayEntries()) {\n\t\t\t\t\tfor (const overlay of overlays) {\n\t\t\t\t\t\tconst geometry = editor.overlays.getOverlayGeometry(overlay)\n\t\t\t\t\t\tif (!geometry) continue\n\t\t\t\t\t\tconst vertices = geometry.vertices\n\t\t\t\t\t\tif (vertices.length < 2) continue\n\t\t\t\t\t\tctx.beginPath()\n\t\t\t\t\t\tctx.moveTo(vertices[0].x, vertices[0].y)\n\t\t\t\t\t\tfor (let i = 1; i < vertices.length; i++) {\n\t\t\t\t\t\t\tctx.lineTo(vertices[i].x, vertices[i].y)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (geometry.isClosed) {\n\t\t\t\t\t\t\tctx.closePath()\n\t\t\t\t\t\t\tctx.fill()\n\t\t\t\t\t\t}\n\t\t\t\t\t\tctx.stroke()\n\t\t\t\t\t\tfor (const v of vertices) {\n\t\t\t\t\t\t\tctx.beginPath()\n\t\t\t\t\t\t\tctx.arc(v.x, v.y, 2 / zoom, 0, Math.PI * 2)\n\t\t\t\t\t\t\tctx.fill()\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tctx.restore()\n\t\t\t}\n\t\t})\n\n\t\tscheduler.attach()\n\t\tscheduler.execute()\n\t\treturn () => scheduler.detach()\n\t}, [editor])\n\n\treturn <canvas ref={canvasRef} className=\"tl-canvas-overlays\" />\n})\n\nfunction drawGeometryStroke(ctx: CanvasRenderingContext2D, geometry: Geometry2d) {\n\tif (geometry instanceof Group2d) {\n\t\tconst prevStroke = ctx.strokeStyle\n\t\tfor (const child of geometry.children) {\n\t\t\tif (child.debugColor) ctx.strokeStyle = child.debugColor\n\t\t\tdrawGeometryStroke(ctx, child)\n\t\t\tctx.strokeStyle = prevStroke\n\t\t}\n\t\tfor (const child of geometry.ignoredChildren) {\n\t\t\tif (child.debugColor) ctx.strokeStyle = child.debugColor\n\t\t\tdrawGeometryStroke(ctx, child)\n\t\t\tctx.strokeStyle = prevStroke\n\t\t}\n\t\treturn\n\t}\n\n\tconst vertices = geometry.vertices\n\tif (vertices.length < 2) return\n\tctx.beginPath()\n\tctx.moveTo(vertices[0].x, vertices[0].y)\n\tfor (let i = 1; i < vertices.length; i++) {\n\t\tctx.lineTo(vertices[i].x, vertices[i].y)\n\t}\n\tif (geometry.isClosed) ctx.closePath()\n\tctx.stroke()\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["CanvasOverlays"]
|
|
7
7
|
}
|
|
@@ -198,7 +198,7 @@ My browser: ${navigator.userAgent}`
|
|
|
198
198
|
children: "Reset data"
|
|
199
199
|
}
|
|
200
200
|
),
|
|
201
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: "tlui-button tl-error-boundary__refresh", onClick: refresh, children: "Refresh
|
|
201
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: "tlui-button tl-error-boundary__refresh", onClick: refresh, children: "Refresh page" })
|
|
202
202
|
] })
|
|
203
203
|
] })
|
|
204
204
|
] })
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/components/default-components/DefaultErrorFallback.tsx"],
|
|
4
|
-
"sourcesContent": ["import { useValue } from '@tldraw/state-react'\nimport { noop } from '@tldraw/utils'\nimport classNames from 'classnames'\nimport { ComponentType, useEffect, useLayoutEffect, useRef, useState } from 'react'\nimport { Editor } from '../../editor/Editor'\nimport { getOwnerDocument } from '../../exports/domUtils'\nimport { useEditorComponents } from '../../hooks/EditorComponentsContext'\nimport { EditorProvider } from '../../hooks/useEditor'\nimport { getGlobalWindow } from '../../utils/dom'\nimport { hardResetEditor, refreshPage } from '../../utils/runtime'\nimport { ErrorBoundary } from '../ErrorBoundary'\n\nconst BASE_ERROR_URL = 'https://github.com/tldraw/tldraw/issues/new'\n\n/** @public */\nexport type TLErrorFallbackComponent = ComponentType<{ error: unknown; editor?: Editor }>\n\n/** @public @react */\nexport const DefaultErrorFallback: TLErrorFallbackComponent = function DefaultErrorFallback({\n\terror,\n\teditor,\n}) {\n\tconst containerRef = useRef<HTMLDivElement>(null)\n\tconst [shouldShowError, setShouldShowError] = useState(process.env.NODE_ENV === 'development')\n\tconst [didCopy, setDidCopy] = useState(false)\n\tconst [shouldShowResetConfirmation, setShouldShowResetConfirmation] = useState(false)\n\n\tlet Canvas: React.ComponentType | null = null\n\ttry {\n\t\t// eslint-disable-next-line react-hooks/rules-of-hooks\n\t\tconst components = useEditorComponents()\n\t\tCanvas = components.Canvas ?? null\n\t} catch {\n\t\t// allow this to fail silently\n\t}\n\n\tconst errorMessage = error instanceof Error ? error.message : String(error)\n\tconst errorStack = error instanceof Error ? error.stack : null\n\n\tconst isDarkModeFromApp = useValue(\n\t\t'isDarkMode',\n\t\t() => {\n\t\t\ttry {\n\t\t\t\tif (editor) {\n\t\t\t\t\treturn editor.user.getIsDarkMode()\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// we're in a funky error state so this might not work for spooky\n\t\t\t\t// reasons. if not, we'll have another attempt later:\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\t\t[editor]\n\t)\n\tconst [isDarkMode, setIsDarkMode] = useState<null | boolean>(null)\n\tuseLayoutEffect(() => {\n\t\t// if we found a theme class from the app, we can just use that\n\t\tif (isDarkModeFromApp !== null) {\n\t\t\tsetIsDarkMode(isDarkModeFromApp)\n\t\t}\n\n\t\t// do any of our parents have a theme class? if yes then we can just\n\t\t// rely on that and don't need to set our own class\n\t\tlet parent = containerRef.current?.parentElement\n\t\tlet foundParentThemeClass = false\n\t\twhile (parent) {\n\t\t\tif (\n\t\t\t\tparent.classList.contains('tl-theme__dark') ||\n\t\t\t\tparent.classList.contains('tl-theme__light')\n\t\t\t) {\n\t\t\t\tfoundParentThemeClass = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tparent = parent.parentElement\n\t\t}\n\t\tif (foundParentThemeClass) {\n\t\t\tsetIsDarkMode(null)\n\t\t\treturn\n\t\t}\n\n\t\t// if we can't find a theme class from the app or from a parent, we have\n\t\t// to fall back on using a media query:\n\t\tif (typeof window !== 'undefined' && getGlobalWindow().matchMedia) {\n\t\t\tsetIsDarkMode(getGlobalWindow().matchMedia('(prefers-color-scheme: dark)').matches)\n\t\t}\n\t}, [isDarkModeFromApp])\n\n\tuseEffect(() => {\n\t\tif (didCopy) {\n\t\t\tconst timeout = editor?.timers.setTimeout(() => {\n\t\t\t\tsetDidCopy(false)\n\t\t\t}, 2000)\n\t\t\treturn () => clearTimeout(timeout)\n\t\t}\n\t}, [didCopy, editor])\n\n\tconst copyError = () => {\n\t\tconst doc = getOwnerDocument(containerRef.current)\n\t\tconst textarea = doc.createElement('textarea')\n\t\ttextarea.value = errorStack ?? errorMessage\n\t\tdoc.body.appendChild(textarea)\n\t\ttextarea.select()\n\t\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\t\tdoc.execCommand('copy')\n\t\ttextarea.remove()\n\t\tsetDidCopy(true)\n\t}\n\n\tconst refresh = () => {\n\t\trefreshPage()\n\t}\n\n\tconst resetLocalState = async () => {\n\t\thardResetEditor()\n\t}\n\n\tconst url = new URL(BASE_ERROR_URL)\n\turl.searchParams.set('title', errorMessage)\n\turl.searchParams.set('labels', `bug`)\n\turl.searchParams.set(\n\t\t'body',\n\t\t`Hey, I ran into an error while using tldraw:\n\n\\`\\`\\`js\n${errorStack ?? errorMessage}\n\\`\\`\\`\n\nMy browser: ${navigator.userAgent}`\n\t)\n\n\treturn (\n\t\t<div\n\t\t\tref={containerRef}\n\t\t\tclassName={classNames(\n\t\t\t\t'tl-container tl-error-boundary',\n\t\t\t\t// error-boundary is sometimes used outside of the theme\n\t\t\t\t// container, so we need to provide it with a theme for our\n\t\t\t\t// styles to work correctly\n\t\t\t\tisDarkMode === null ? '' : isDarkMode ? 'tl-theme__dark' : 'tl-theme__light'\n\t\t\t)}\n\t\t>\n\t\t\t<div className=\"tl-error-boundary__overlay\" />\n\t\t\t{editor && (\n\t\t\t\t// opportunistically attempt to render the canvas to reassure\n\t\t\t\t// the user that their document is still there. there's a good\n\t\t\t\t// chance this won't work (ie the error that we're currently\n\t\t\t\t// notifying the user about originates in the canvas) so it's\n\t\t\t\t// not a big deal if it doesn't work - in that case we just have\n\t\t\t\t// a plain grey background.\n\t\t\t\t<ErrorBoundary onError={noop} fallback={() => null}>\n\t\t\t\t\t<EditorProvider editor={editor}>\n\t\t\t\t\t\t<div className=\"tl-overlay tl-error-boundary__canvas\">{Canvas ? <Canvas /> : null}</div>\n\t\t\t\t\t</EditorProvider>\n\t\t\t\t</ErrorBoundary>\n\t\t\t)}\n\t\t\t<div\n\t\t\t\tclassName={classNames('tl-modal', 'tl-error-boundary__content', {\n\t\t\t\t\t'tl-error-boundary__content__expanded': shouldShowError && !shouldShowResetConfirmation,\n\t\t\t\t})}\n\t\t\t>\n\t\t\t\t{shouldShowResetConfirmation ? (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<h2>Are you sure?</h2>\n\t\t\t\t\t\t<p>Resetting your data will delete your drawing and cannot be undone.</p>\n\t\t\t\t\t\t<div className=\"tl-error-boundary__content__actions\">\n\t\t\t\t\t\t\t<button className=\"tlui-button\" onClick={() => setShouldShowResetConfirmation(false)}>\n\t\t\t\t\t\t\t\tCancel\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t<button className=\"tlui-button tl-error-boundary__reset\" onClick={resetLocalState}>\n\t\t\t\t\t\t\t\tReset data\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</>\n\t\t\t\t) : (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<h2>Something went wrong</h2>\n\t\t\t\t\t\t<p>Please refresh your browser.</p>\n\t\t\t\t\t\t<p>\n\t\t\t\t\t\t\tIf the issue continues after refreshing, you may need to reset the tldraw data stored\n\t\t\t\t\t\t\ton your device.\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t<p>\n\t\t\t\t\t\t\t<strong>Note:</strong> Resetting will erase your current project and any unsaved work.\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t{process.env.NODE_ENV !== 'production' && (\n\t\t\t\t\t\t\t<p>\n\t\t\t\t\t\t\t\tIf you're developing with the SDK and need help, join us on{' '}\n\t\t\t\t\t\t\t\t<a href=\"https://discord.tldraw.com/?utm_source=sdk&utm_medium=organic&utm_campaign=error-screen\">\n\t\t\t\t\t\t\t\t\tDiscord\n\t\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t\t.\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{shouldShowError && (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\tMessage:\n\t\t\t\t\t\t\t\t<h4>\n\t\t\t\t\t\t\t\t\t<code>{errorMessage}</code>\n\t\t\t\t\t\t\t\t</h4>\n\t\t\t\t\t\t\t\tStack trace:\n\t\t\t\t\t\t\t\t<div className=\"tl-error-boundary__content__error\">\n\t\t\t\t\t\t\t\t\t<pre>\n\t\t\t\t\t\t\t\t\t\t<code>{errorStack ?? errorMessage}</code>\n\t\t\t\t\t\t\t\t\t</pre>\n\t\t\t\t\t\t\t\t\t<button className=\"tlui-button\" onClick={copyError}>\n\t\t\t\t\t\t\t\t\t\t{didCopy ? 'Copied!' : 'Copy'}\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t<div className=\"tl-error-boundary__content__actions\">\n\t\t\t\t\t\t\t<button className=\"tlui-button\" onClick={() => setShouldShowError(!shouldShowError)}>\n\t\t\t\t\t\t\t\t{shouldShowError ? 'Hide details' : 'Show details'}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t<div className=\"tl-error-boundary__content__actions__group\">\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\tclassName=\"tlui-button tl-error-boundary__reset\"\n\t\t\t\t\t\t\t\t\tonClick={() => setShouldShowResetConfirmation(true)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tReset data\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t<button className=\"tlui-button tl-error-boundary__refresh\" onClick={refresh}>\n\t\t\t\t\t\t\t\t\tRefresh
|
|
4
|
+
"sourcesContent": ["import { useValue } from '@tldraw/state-react'\nimport { noop } from '@tldraw/utils'\nimport classNames from 'classnames'\nimport { ComponentType, useEffect, useLayoutEffect, useRef, useState } from 'react'\nimport { Editor } from '../../editor/Editor'\nimport { getOwnerDocument } from '../../exports/domUtils'\nimport { useEditorComponents } from '../../hooks/EditorComponentsContext'\nimport { EditorProvider } from '../../hooks/useEditor'\nimport { getGlobalWindow } from '../../utils/dom'\nimport { hardResetEditor, refreshPage } from '../../utils/runtime'\nimport { ErrorBoundary } from '../ErrorBoundary'\n\nconst BASE_ERROR_URL = 'https://github.com/tldraw/tldraw/issues/new'\n\n/** @public */\nexport type TLErrorFallbackComponent = ComponentType<{ error: unknown; editor?: Editor }>\n\n/** @public @react */\nexport const DefaultErrorFallback: TLErrorFallbackComponent = function DefaultErrorFallback({\n\terror,\n\teditor,\n}) {\n\tconst containerRef = useRef<HTMLDivElement>(null)\n\tconst [shouldShowError, setShouldShowError] = useState(process.env.NODE_ENV === 'development')\n\tconst [didCopy, setDidCopy] = useState(false)\n\tconst [shouldShowResetConfirmation, setShouldShowResetConfirmation] = useState(false)\n\n\tlet Canvas: React.ComponentType | null = null\n\ttry {\n\t\t// eslint-disable-next-line react-hooks/rules-of-hooks\n\t\tconst components = useEditorComponents()\n\t\tCanvas = components.Canvas ?? null\n\t} catch {\n\t\t// allow this to fail silently\n\t}\n\n\tconst errorMessage = error instanceof Error ? error.message : String(error)\n\tconst errorStack = error instanceof Error ? error.stack : null\n\n\tconst isDarkModeFromApp = useValue(\n\t\t'isDarkMode',\n\t\t() => {\n\t\t\ttry {\n\t\t\t\tif (editor) {\n\t\t\t\t\treturn editor.user.getIsDarkMode()\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// we're in a funky error state so this might not work for spooky\n\t\t\t\t// reasons. if not, we'll have another attempt later:\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\t\t[editor]\n\t)\n\tconst [isDarkMode, setIsDarkMode] = useState<null | boolean>(null)\n\tuseLayoutEffect(() => {\n\t\t// if we found a theme class from the app, we can just use that\n\t\tif (isDarkModeFromApp !== null) {\n\t\t\tsetIsDarkMode(isDarkModeFromApp)\n\t\t}\n\n\t\t// do any of our parents have a theme class? if yes then we can just\n\t\t// rely on that and don't need to set our own class\n\t\tlet parent = containerRef.current?.parentElement\n\t\tlet foundParentThemeClass = false\n\t\twhile (parent) {\n\t\t\tif (\n\t\t\t\tparent.classList.contains('tl-theme__dark') ||\n\t\t\t\tparent.classList.contains('tl-theme__light')\n\t\t\t) {\n\t\t\t\tfoundParentThemeClass = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tparent = parent.parentElement\n\t\t}\n\t\tif (foundParentThemeClass) {\n\t\t\tsetIsDarkMode(null)\n\t\t\treturn\n\t\t}\n\n\t\t// if we can't find a theme class from the app or from a parent, we have\n\t\t// to fall back on using a media query:\n\t\tif (typeof window !== 'undefined' && getGlobalWindow().matchMedia) {\n\t\t\tsetIsDarkMode(getGlobalWindow().matchMedia('(prefers-color-scheme: dark)').matches)\n\t\t}\n\t}, [isDarkModeFromApp])\n\n\tuseEffect(() => {\n\t\tif (didCopy) {\n\t\t\tconst timeout = editor?.timers.setTimeout(() => {\n\t\t\t\tsetDidCopy(false)\n\t\t\t}, 2000)\n\t\t\treturn () => clearTimeout(timeout)\n\t\t}\n\t}, [didCopy, editor])\n\n\tconst copyError = () => {\n\t\tconst doc = getOwnerDocument(containerRef.current)\n\t\tconst textarea = doc.createElement('textarea')\n\t\ttextarea.value = errorStack ?? errorMessage\n\t\tdoc.body.appendChild(textarea)\n\t\ttextarea.select()\n\t\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\t\tdoc.execCommand('copy')\n\t\ttextarea.remove()\n\t\tsetDidCopy(true)\n\t}\n\n\tconst refresh = () => {\n\t\trefreshPage()\n\t}\n\n\tconst resetLocalState = async () => {\n\t\thardResetEditor()\n\t}\n\n\tconst url = new URL(BASE_ERROR_URL)\n\turl.searchParams.set('title', errorMessage)\n\turl.searchParams.set('labels', `bug`)\n\turl.searchParams.set(\n\t\t'body',\n\t\t`Hey, I ran into an error while using tldraw:\n\n\\`\\`\\`js\n${errorStack ?? errorMessage}\n\\`\\`\\`\n\nMy browser: ${navigator.userAgent}`\n\t)\n\n\treturn (\n\t\t<div\n\t\t\tref={containerRef}\n\t\t\tclassName={classNames(\n\t\t\t\t'tl-container tl-error-boundary',\n\t\t\t\t// error-boundary is sometimes used outside of the theme\n\t\t\t\t// container, so we need to provide it with a theme for our\n\t\t\t\t// styles to work correctly\n\t\t\t\tisDarkMode === null ? '' : isDarkMode ? 'tl-theme__dark' : 'tl-theme__light'\n\t\t\t)}\n\t\t>\n\t\t\t<div className=\"tl-error-boundary__overlay\" />\n\t\t\t{editor && (\n\t\t\t\t// opportunistically attempt to render the canvas to reassure\n\t\t\t\t// the user that their document is still there. there's a good\n\t\t\t\t// chance this won't work (ie the error that we're currently\n\t\t\t\t// notifying the user about originates in the canvas) so it's\n\t\t\t\t// not a big deal if it doesn't work - in that case we just have\n\t\t\t\t// a plain grey background.\n\t\t\t\t<ErrorBoundary onError={noop} fallback={() => null}>\n\t\t\t\t\t<EditorProvider editor={editor}>\n\t\t\t\t\t\t<div className=\"tl-overlay tl-error-boundary__canvas\">{Canvas ? <Canvas /> : null}</div>\n\t\t\t\t\t</EditorProvider>\n\t\t\t\t</ErrorBoundary>\n\t\t\t)}\n\t\t\t<div\n\t\t\t\tclassName={classNames('tl-modal', 'tl-error-boundary__content', {\n\t\t\t\t\t'tl-error-boundary__content__expanded': shouldShowError && !shouldShowResetConfirmation,\n\t\t\t\t})}\n\t\t\t>\n\t\t\t\t{shouldShowResetConfirmation ? (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<h2>Are you sure?</h2>\n\t\t\t\t\t\t<p>Resetting your data will delete your drawing and cannot be undone.</p>\n\t\t\t\t\t\t<div className=\"tl-error-boundary__content__actions\">\n\t\t\t\t\t\t\t<button className=\"tlui-button\" onClick={() => setShouldShowResetConfirmation(false)}>\n\t\t\t\t\t\t\t\tCancel\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t<button className=\"tlui-button tl-error-boundary__reset\" onClick={resetLocalState}>\n\t\t\t\t\t\t\t\tReset data\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</>\n\t\t\t\t) : (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<h2>Something went wrong</h2>\n\t\t\t\t\t\t<p>Please refresh your browser.</p>\n\t\t\t\t\t\t<p>\n\t\t\t\t\t\t\tIf the issue continues after refreshing, you may need to reset the tldraw data stored\n\t\t\t\t\t\t\ton your device.\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t<p>\n\t\t\t\t\t\t\t<strong>Note:</strong> Resetting will erase your current project and any unsaved work.\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t{process.env.NODE_ENV !== 'production' && (\n\t\t\t\t\t\t\t<p>\n\t\t\t\t\t\t\t\tIf you're developing with the SDK and need help, join us on{' '}\n\t\t\t\t\t\t\t\t<a href=\"https://discord.tldraw.com/?utm_source=sdk&utm_medium=organic&utm_campaign=error-screen\">\n\t\t\t\t\t\t\t\t\tDiscord\n\t\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t\t.\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{shouldShowError && (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\tMessage:\n\t\t\t\t\t\t\t\t<h4>\n\t\t\t\t\t\t\t\t\t<code>{errorMessage}</code>\n\t\t\t\t\t\t\t\t</h4>\n\t\t\t\t\t\t\t\tStack trace:\n\t\t\t\t\t\t\t\t<div className=\"tl-error-boundary__content__error\">\n\t\t\t\t\t\t\t\t\t<pre>\n\t\t\t\t\t\t\t\t\t\t<code>{errorStack ?? errorMessage}</code>\n\t\t\t\t\t\t\t\t\t</pre>\n\t\t\t\t\t\t\t\t\t<button className=\"tlui-button\" onClick={copyError}>\n\t\t\t\t\t\t\t\t\t\t{didCopy ? 'Copied!' : 'Copy'}\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t<div className=\"tl-error-boundary__content__actions\">\n\t\t\t\t\t\t\t<button className=\"tlui-button\" onClick={() => setShouldShowError(!shouldShowError)}>\n\t\t\t\t\t\t\t\t{shouldShowError ? 'Hide details' : 'Show details'}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t<div className=\"tl-error-boundary__content__actions__group\">\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\tclassName=\"tlui-button tl-error-boundary__reset\"\n\t\t\t\t\t\t\t\t\tonClick={() => setShouldShowResetConfirmation(true)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tReset data\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t<button className=\"tlui-button tl-error-boundary__refresh\" onClick={refresh}>\n\t\t\t\t\t\t\t\t\tRefresh page\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": ["DefaultErrorFallback", "classNames"]
|
|
7
7
|
}
|
|
@@ -168,15 +168,19 @@ function migrateUserPreferences(userData) {
|
|
|
168
168
|
return getFreshUserPreferences();
|
|
169
169
|
}
|
|
170
170
|
const snapshot = (0, import_utils.structuredClone)(userData);
|
|
171
|
-
migrateSnapshot(snapshot);
|
|
172
171
|
try {
|
|
172
|
+
migrateSnapshot(snapshot);
|
|
173
173
|
return userTypeValidator.validate(snapshot.user);
|
|
174
174
|
} catch {
|
|
175
175
|
return getFreshUserPreferences();
|
|
176
176
|
}
|
|
177
177
|
}
|
|
178
178
|
function loadUserPreferences() {
|
|
179
|
-
|
|
179
|
+
let userData = null;
|
|
180
|
+
try {
|
|
181
|
+
userData = JSON.parse((0, import_utils.getFromLocalStorage)(USER_DATA_KEY) || "null");
|
|
182
|
+
} catch {
|
|
183
|
+
}
|
|
180
184
|
return migrateUserPreferences(userData);
|
|
181
185
|
}
|
|
182
186
|
const globalUserPreferences = (0, import_state.atom)("globalUserData", null);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/config/TLUserPreferences.ts"],
|
|
4
|
-
"sourcesContent": ["import { atom } from '@tldraw/state'\nimport { getDefaultTranslationLocale } from '@tldraw/tlschema'\nimport { getFromLocalStorage, setInLocalStorage, structuredClone, uniqueId } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { getGlobalWindow } from '../utils/dom'\n\nconst USER_DATA_KEY = 'TLDRAW_USER_DATA_v3'\n\n/**\n * A user of tldraw\n *\n * @public\n */\nexport interface TLUserPreferences {\n\tid: string\n\tname?: string | null\n\tcolor?: string | null\n\t// N.B. These are duplicated in TLdrawAppUser.\n\tlocale?: string | null\n\tanimationSpeed?: number | null\n\tareKeyboardShortcutsEnabled?: boolean | null\n\tedgeScrollSpeed?: number | null\n\tcolorScheme?: 'light' | 'dark' | 'system'\n\tisSnapMode?: boolean | null\n\tisWrapMode?: boolean | null\n\tisDynamicSizeMode?: boolean | null\n\tisPasteAtCursorMode?: boolean | null\n\tenhancedA11yMode?: boolean | null\n\tinputMode?: 'trackpad' | 'mouse' | null\n\tisZoomDirectionInverted?: boolean | null\n}\n\ninterface UserDataSnapshot {\n\tversion: number\n\tuser: TLUserPreferences\n}\n\ninterface UserChangeBroadcastMessage {\n\ttype: typeof broadcastEventKey\n\torigin: string\n\tdata: UserDataSnapshot\n}\n\n/** @public */\nexport const userTypeValidator: T.Validator<TLUserPreferences> = T.object<TLUserPreferences>({\n\tid: T.string,\n\tname: T.string.nullable().optional(),\n\tcolor: T.string.nullable().optional(),\n\t// N.B. These are duplicated in TLdrawAppUser.\n\tlocale: T.string.nullable().optional(),\n\tanimationSpeed: T.number.nullable().optional(),\n\tareKeyboardShortcutsEnabled: T.boolean.nullable().optional(),\n\tedgeScrollSpeed: T.number.nullable().optional(),\n\tcolorScheme: T.literalEnum('light', 'dark', 'system').optional(),\n\tisSnapMode: T.boolean.nullable().optional(),\n\tisWrapMode: T.boolean.nullable().optional(),\n\tisDynamicSizeMode: T.boolean.nullable().optional(),\n\tisPasteAtCursorMode: T.boolean.nullable().optional(),\n\tenhancedA11yMode: T.boolean.nullable().optional(),\n\tinputMode: T.literalEnum('trackpad', 'mouse').nullable().optional(),\n\tisZoomDirectionInverted: T.boolean.nullable().optional(),\n})\n\nconst Versions = {\n\tAddAnimationSpeed: 1,\n\tAddIsSnapMode: 2,\n\tMakeFieldsNullable: 3,\n\tAddEdgeScrollSpeed: 4,\n\tAddExcalidrawSelectMode: 5,\n\tAddDynamicSizeMode: 6,\n\tAllowSystemColorScheme: 7,\n\tAddPasteAtCursor: 8,\n\tAddKeyboardShortcuts: 9,\n\tAddShowUiLabels: 10,\n\tAddPointerPeripheral: 11,\n\tRenameShowUiLabelsToEnhancedA11yMode: 12,\n\tAddZoomDirectionInverted: 13,\n} as const\n\nconst CURRENT_VERSION = Math.max(...Object.values(Versions))\n\nfunction migrateSnapshot(data: { version: number; user: any }) {\n\tif (data.version < Versions.AddAnimationSpeed) {\n\t\tdata.user.animationSpeed = 1\n\t}\n\tif (data.version < Versions.AddIsSnapMode) {\n\t\tdata.user.isSnapMode = false\n\t}\n\tif (data.version < Versions.MakeFieldsNullable) {\n\t\t// noop\n\t}\n\tif (data.version < Versions.AddEdgeScrollSpeed) {\n\t\tdata.user.edgeScrollSpeed = 1\n\t}\n\tif (data.version < Versions.AddExcalidrawSelectMode) {\n\t\tdata.user.isWrapMode = false\n\t}\n\tif (data.version < Versions.AllowSystemColorScheme) {\n\t\tif (data.user.isDarkMode === true) {\n\t\t\tdata.user.colorScheme = 'dark'\n\t\t} else if (data.user.isDarkMode === false) {\n\t\t\tdata.user.colorScheme = 'light'\n\t\t}\n\t\tdelete data.user.isDarkMode\n\t}\n\n\tif (data.version < Versions.AddDynamicSizeMode) {\n\t\tdata.user.isDynamicSizeMode = false\n\t}\n\tif (data.version < Versions.AddPasteAtCursor) {\n\t\tdata.user.isPasteAtCursorMode = false\n\t}\n\tif (data.version < Versions.AddKeyboardShortcuts) {\n\t\tdata.user.areKeyboardShortcutsEnabled = true\n\t}\n\tif (data.version < Versions.AddShowUiLabels) {\n\t\tdata.user.showUiLabels = false\n\t}\n\tif (data.version < Versions.RenameShowUiLabelsToEnhancedA11yMode) {\n\t\tdata.user.enhancedA11yMode = data.user.showUiLabels\n\t\tdelete data.user.showUiLabels\n\t}\n\n\tif (data.version < Versions.AddPointerPeripheral) {\n\t\tdata.user.inputMode = null\n\t}\n\n\tif (data.version < Versions.AddZoomDirectionInverted) {\n\t\tdata.user.isZoomDirectionInverted = false\n\t}\n\n\t// finally\n\tdata.version = CURRENT_VERSION\n}\n\n/** @internal */\nexport const USER_COLORS = [\n\t'#FF802B',\n\t'#EC5E41',\n\t'#F2555A',\n\t'#F04F88',\n\t'#E34BA9',\n\t'#BD54C6',\n\t'#9D5BD2',\n\t'#7B66DC',\n\t'#02B1CC',\n\t'#11B3A3',\n\t'#39B178',\n\t'#55B467',\n] as const\n\nfunction getRandomColor() {\n\treturn USER_COLORS[Math.floor(Math.random() * USER_COLORS.length)]\n}\n\n/** @internal */\nexport function userPrefersReducedMotion() {\n\tif (typeof window !== 'undefined' && getGlobalWindow().matchMedia) {\n\t\treturn getGlobalWindow().matchMedia?.('(prefers-reduced-motion: reduce)')?.matches ?? false\n\t}\n\n\treturn false\n}\n\n/** @public */\nexport const defaultUserPreferences = Object.freeze({\n\tname: '',\n\tlocale: getDefaultTranslationLocale(),\n\tcolor: getRandomColor(),\n\n\t// N.B. These are duplicated in TLdrawAppUser.\n\tedgeScrollSpeed: 1,\n\tanimationSpeed: userPrefersReducedMotion() ? 0 : 1,\n\tareKeyboardShortcutsEnabled: true,\n\tisSnapMode: false,\n\tisWrapMode: false,\n\tisDynamicSizeMode: false,\n\tisPasteAtCursorMode: false,\n\tenhancedA11yMode: false,\n\tcolorScheme: 'light',\n\tinputMode: null,\n\tisZoomDirectionInverted: false,\n}) satisfies Readonly<Omit<TLUserPreferences, 'id'>>\n\n/** @public */\nexport function getFreshUserPreferences(): TLUserPreferences {\n\treturn {\n\t\tid: uniqueId(),\n\t\tcolor: getRandomColor(),\n\t}\n}\n\nfunction migrateUserPreferences(userData: unknown): TLUserPreferences {\n\tif (userData === null || typeof userData !== 'object') {\n\t\treturn getFreshUserPreferences()\n\t}\n\n\tif (!('version' in userData) || !('user' in userData) || typeof userData.version !== 'number') {\n\t\treturn getFreshUserPreferences()\n\t}\n\n\tconst snapshot = structuredClone(userData) as any\n\n\
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["import { atom } from '@tldraw/state'\nimport { getDefaultTranslationLocale } from '@tldraw/tlschema'\nimport { getFromLocalStorage, setInLocalStorage, structuredClone, uniqueId } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { getGlobalWindow } from '../utils/dom'\n\nconst USER_DATA_KEY = 'TLDRAW_USER_DATA_v3'\n\n/**\n * A user of tldraw\n *\n * @public\n */\nexport interface TLUserPreferences {\n\tid: string\n\tname?: string | null\n\tcolor?: string | null\n\t// N.B. These are duplicated in TLdrawAppUser.\n\tlocale?: string | null\n\tanimationSpeed?: number | null\n\tareKeyboardShortcutsEnabled?: boolean | null\n\tedgeScrollSpeed?: number | null\n\tcolorScheme?: 'light' | 'dark' | 'system'\n\tisSnapMode?: boolean | null\n\tisWrapMode?: boolean | null\n\tisDynamicSizeMode?: boolean | null\n\tisPasteAtCursorMode?: boolean | null\n\tenhancedA11yMode?: boolean | null\n\tinputMode?: 'trackpad' | 'mouse' | null\n\tisZoomDirectionInverted?: boolean | null\n}\n\ninterface UserDataSnapshot {\n\tversion: number\n\tuser: TLUserPreferences\n}\n\ninterface UserChangeBroadcastMessage {\n\ttype: typeof broadcastEventKey\n\torigin: string\n\tdata: UserDataSnapshot\n}\n\n/** @public */\nexport const userTypeValidator: T.Validator<TLUserPreferences> = T.object<TLUserPreferences>({\n\tid: T.string,\n\tname: T.string.nullable().optional(),\n\tcolor: T.string.nullable().optional(),\n\t// N.B. These are duplicated in TLdrawAppUser.\n\tlocale: T.string.nullable().optional(),\n\tanimationSpeed: T.number.nullable().optional(),\n\tareKeyboardShortcutsEnabled: T.boolean.nullable().optional(),\n\tedgeScrollSpeed: T.number.nullable().optional(),\n\tcolorScheme: T.literalEnum('light', 'dark', 'system').optional(),\n\tisSnapMode: T.boolean.nullable().optional(),\n\tisWrapMode: T.boolean.nullable().optional(),\n\tisDynamicSizeMode: T.boolean.nullable().optional(),\n\tisPasteAtCursorMode: T.boolean.nullable().optional(),\n\tenhancedA11yMode: T.boolean.nullable().optional(),\n\tinputMode: T.literalEnum('trackpad', 'mouse').nullable().optional(),\n\tisZoomDirectionInverted: T.boolean.nullable().optional(),\n})\n\nconst Versions = {\n\tAddAnimationSpeed: 1,\n\tAddIsSnapMode: 2,\n\tMakeFieldsNullable: 3,\n\tAddEdgeScrollSpeed: 4,\n\tAddExcalidrawSelectMode: 5,\n\tAddDynamicSizeMode: 6,\n\tAllowSystemColorScheme: 7,\n\tAddPasteAtCursor: 8,\n\tAddKeyboardShortcuts: 9,\n\tAddShowUiLabels: 10,\n\tAddPointerPeripheral: 11,\n\tRenameShowUiLabelsToEnhancedA11yMode: 12,\n\tAddZoomDirectionInverted: 13,\n} as const\n\nconst CURRENT_VERSION = Math.max(...Object.values(Versions))\n\nfunction migrateSnapshot(data: { version: number; user: any }) {\n\tif (data.version < Versions.AddAnimationSpeed) {\n\t\tdata.user.animationSpeed = 1\n\t}\n\tif (data.version < Versions.AddIsSnapMode) {\n\t\tdata.user.isSnapMode = false\n\t}\n\tif (data.version < Versions.MakeFieldsNullable) {\n\t\t// noop\n\t}\n\tif (data.version < Versions.AddEdgeScrollSpeed) {\n\t\tdata.user.edgeScrollSpeed = 1\n\t}\n\tif (data.version < Versions.AddExcalidrawSelectMode) {\n\t\tdata.user.isWrapMode = false\n\t}\n\tif (data.version < Versions.AllowSystemColorScheme) {\n\t\tif (data.user.isDarkMode === true) {\n\t\t\tdata.user.colorScheme = 'dark'\n\t\t} else if (data.user.isDarkMode === false) {\n\t\t\tdata.user.colorScheme = 'light'\n\t\t}\n\t\tdelete data.user.isDarkMode\n\t}\n\n\tif (data.version < Versions.AddDynamicSizeMode) {\n\t\tdata.user.isDynamicSizeMode = false\n\t}\n\tif (data.version < Versions.AddPasteAtCursor) {\n\t\tdata.user.isPasteAtCursorMode = false\n\t}\n\tif (data.version < Versions.AddKeyboardShortcuts) {\n\t\tdata.user.areKeyboardShortcutsEnabled = true\n\t}\n\tif (data.version < Versions.AddShowUiLabels) {\n\t\tdata.user.showUiLabels = false\n\t}\n\tif (data.version < Versions.RenameShowUiLabelsToEnhancedA11yMode) {\n\t\tdata.user.enhancedA11yMode = data.user.showUiLabels\n\t\tdelete data.user.showUiLabels\n\t}\n\n\tif (data.version < Versions.AddPointerPeripheral) {\n\t\tdata.user.inputMode = null\n\t}\n\n\tif (data.version < Versions.AddZoomDirectionInverted) {\n\t\tdata.user.isZoomDirectionInverted = false\n\t}\n\n\t// finally\n\tdata.version = CURRENT_VERSION\n}\n\n/** @internal */\nexport const USER_COLORS = [\n\t'#FF802B',\n\t'#EC5E41',\n\t'#F2555A',\n\t'#F04F88',\n\t'#E34BA9',\n\t'#BD54C6',\n\t'#9D5BD2',\n\t'#7B66DC',\n\t'#02B1CC',\n\t'#11B3A3',\n\t'#39B178',\n\t'#55B467',\n] as const\n\nfunction getRandomColor() {\n\treturn USER_COLORS[Math.floor(Math.random() * USER_COLORS.length)]\n}\n\n/** @internal */\nexport function userPrefersReducedMotion() {\n\tif (typeof window !== 'undefined' && getGlobalWindow().matchMedia) {\n\t\treturn getGlobalWindow().matchMedia?.('(prefers-reduced-motion: reduce)')?.matches ?? false\n\t}\n\n\treturn false\n}\n\n/** @public */\nexport const defaultUserPreferences = Object.freeze({\n\tname: '',\n\tlocale: getDefaultTranslationLocale(),\n\tcolor: getRandomColor(),\n\n\t// N.B. These are duplicated in TLdrawAppUser.\n\tedgeScrollSpeed: 1,\n\tanimationSpeed: userPrefersReducedMotion() ? 0 : 1,\n\tareKeyboardShortcutsEnabled: true,\n\tisSnapMode: false,\n\tisWrapMode: false,\n\tisDynamicSizeMode: false,\n\tisPasteAtCursorMode: false,\n\tenhancedA11yMode: false,\n\tcolorScheme: 'light',\n\tinputMode: null,\n\tisZoomDirectionInverted: false,\n}) satisfies Readonly<Omit<TLUserPreferences, 'id'>>\n\n/** @public */\nexport function getFreshUserPreferences(): TLUserPreferences {\n\treturn {\n\t\tid: uniqueId(),\n\t\tcolor: getRandomColor(),\n\t}\n}\n\nfunction migrateUserPreferences(userData: unknown): TLUserPreferences {\n\tif (userData === null || typeof userData !== 'object') {\n\t\treturn getFreshUserPreferences()\n\t}\n\n\tif (!('version' in userData) || !('user' in userData) || typeof userData.version !== 'number') {\n\t\treturn getFreshUserPreferences()\n\t}\n\n\tconst snapshot = structuredClone(userData) as any\n\n\ttry {\n\t\t// migration dereferences `user`, which malformed stored data may not have as an object\n\t\tmigrateSnapshot(snapshot)\n\t\treturn userTypeValidator.validate(snapshot.user)\n\t} catch {\n\t\treturn getFreshUserPreferences()\n\t}\n}\n\nfunction loadUserPreferences(): TLUserPreferences {\n\tlet userData: unknown = null\n\ttry {\n\t\tuserData = JSON.parse(getFromLocalStorage(USER_DATA_KEY) || 'null')\n\t} catch {\n\t\t// corrupt stored data is treated as absent rather than blocking the editor from mounting\n\t}\n\n\treturn migrateUserPreferences(userData)\n}\n\nconst globalUserPreferences = atom<TLUserPreferences | null>('globalUserData', null)\n\nfunction storeUserPreferences() {\n\tsetInLocalStorage(\n\t\tUSER_DATA_KEY,\n\t\tJSON.stringify({\n\t\t\tversion: CURRENT_VERSION,\n\t\t\tuser: globalUserPreferences.get(),\n\t\t})\n\t)\n}\n\n/** @public */\nexport function setUserPreferences(user: TLUserPreferences) {\n\tuserTypeValidator.validate(user)\n\tglobalUserPreferences.set(user)\n\tstoreUserPreferences()\n\tbroadcastUserPreferencesChange()\n}\n\nconst isTest = typeof process !== 'undefined' && process.env.NODE_ENV === 'test'\n\nconst channel =\n\ttypeof BroadcastChannel !== 'undefined' && !isTest\n\t\t? new BroadcastChannel('tldraw-user-sync')\n\t\t: null\n\nchannel?.addEventListener('message', (e) => {\n\tconst data = e.data as undefined | UserChangeBroadcastMessage\n\tif (data?.type === broadcastEventKey && data?.origin !== getBroadcastOrigin()) {\n\t\tglobalUserPreferences.set(migrateUserPreferences(data.data))\n\t}\n})\n\nlet _broadcastOrigin = null as null | string\nfunction getBroadcastOrigin() {\n\tif (_broadcastOrigin === null) {\n\t\t_broadcastOrigin = uniqueId()\n\t}\n\treturn _broadcastOrigin\n}\nconst broadcastEventKey = 'tldraw-user-preferences-change' as const\n\nfunction broadcastUserPreferencesChange() {\n\tchannel?.postMessage({\n\t\ttype: broadcastEventKey,\n\t\torigin: getBroadcastOrigin(),\n\t\tdata: {\n\t\t\tuser: getUserPreferences(),\n\t\t\tversion: CURRENT_VERSION,\n\t\t},\n\t} satisfies UserChangeBroadcastMessage)\n}\n\n/** @public */\nexport function getUserPreferences(): TLUserPreferences {\n\tlet prefs = globalUserPreferences.get()\n\tif (!prefs) {\n\t\tprefs = loadUserPreferences()\n\t\tsetUserPreferences(prefs)\n\t}\n\treturn prefs\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/config/createTLStore.ts"],
|
|
4
|
-
"sourcesContent": ["import { Signal, computed } from '@tldraw/state'\nimport { HistoryEntry, MigrationSequence, SerializedStore, Store, StoreSchema } from '@tldraw/store'\nimport {\n\tCustomRecordInfo,\n\tSchemaPropsInfo,\n\tTLAssetStore,\n\tTLRecord,\n\tTLStore,\n\tTLStoreProps,\n\tTLStoreSnapshot,\n\tTLThemes,\n\tTLUser,\n\tTLUserStore,\n\tUserRecordType,\n\tcreateCachedUserResolve,\n\tcreateTLSchema,\n\tcreateUserId,\n\tregisterColorsFromThemes,\n\tregisterFontsFromThemes,\n} from '@tldraw/tlschema'\nimport { FileHelpers, assert } from '@tldraw/utils'\nimport { Editor } from '../editor/Editor'\nimport { resolveThemes } from '../editor/managers/ThemeManager/ThemeManager'\nimport { TLAnyAssetUtilConstructor, checkAssets } from './defaultAssets'\nimport { TLAnyBindingUtilConstructor, checkBindings } from './defaultBindings'\nimport { TLAnyShapeUtilConstructor, checkShapesAndAddCore } from './defaultShapes'\nimport { TLEditorSnapshot, loadSnapshot } from './TLEditorSnapshot'\nimport { defaultUserPreferences, getUserPreferences } from './TLUserPreferences'\n\n/** @public */\nexport interface TLStoreBaseOptions {\n\t/** The initial data for the store. */\n\tinitialData?: SerializedStore<TLRecord>\n\n\t/** A snapshot of initial data to migrate and load into the store. */\n\tsnapshot?: Partial<TLEditorSnapshot> | TLStoreSnapshot\n\n\t/** The default name for the store. */\n\tdefaultName?: string\n\n\t/** How should this store upload & resolve assets? */\n\tassets?: TLAssetStore\n\n\t/**\n\t * Named theme definitions. When provided, custom color names are automatically\n\t * registered before the store is constructed so persisted data with those\n\t * colors passes validation on load.\n\t */\n\tthemes?: Partial<TLThemes>\n\n\t/** How should this store resolve users for attribution? */\n\tusers?: TLUserStore\n\n\t/** Called when the store is connected to an {@link @tldraw/editor#Editor}. */\n\tonMount?(editor: Editor): void | (() => void)\n}\n\n/** @public */\nexport type TLStoreSchemaOptions =\n\t| {\n\t\t\tschema?: StoreSchema<TLRecord, TLStoreProps>\n\t }\n\t| {\n\t\t\tshapeUtils?: readonly TLAnyShapeUtilConstructor[]\n\t\t\tbindingUtils?: readonly TLAnyBindingUtilConstructor[]\n\t\t\tassetUtils?: readonly TLAnyAssetUtilConstructor[]\n\t\t\tmigrations?: readonly MigrationSequence[]\n\t\t\trecords?: Record<string, CustomRecordInfo>\n\t }\n\n/** @public */\nexport type TLStoreOptions = TLStoreBaseOptions & {\n\tid?: string\n\t/** Collaboration options for the store. */\n\tcollaboration?: {\n\t\tstatus: Signal<'online' | 'offline'> | null\n\t\tmode?: Signal<'readonly' | 'readwrite'> | null\n\t}\n} & TLStoreSchemaOptions\n\n/** @public */\nexport type TLStoreEventInfo = HistoryEntry<TLRecord>\n\nconst defaultAssetResolve: NonNullable<TLAssetStore['resolve']> = (asset) => asset.props.src\n\nconst _defaultCurrentUser: Signal<TLUser | null> = computed('defaultCurrentUser', () => {\n\tconst prefs = getUserPreferences()\n\tif (!prefs.id) return null\n\treturn UserRecordType.create({\n\t\tid: createUserId(prefs.id),\n\t\tname: prefs.name ?? '',\n\t\tcolor: prefs.color ?? defaultUserPreferences.color,\n\t})\n})\n\n/** @public */\nexport const defaultUserStore: TLUserStore = {\n\tcurrentUser: _defaultCurrentUser,\n}\n\n/** @public */\nexport const inlineBase64AssetStore: TLAssetStore = {\n\tupload: async (_, file) => {\n\t\treturn { src: await FileHelpers.blobToDataUrl(file) }\n\t},\n}\n\n/**\n * A helper for creating a TLStore schema from either an object with shapeUtils, bindingUtils, and\n * migrations, or a schema.\n *\n * @param opts - Options for creating the schema.\n *\n * @public\n */\nexport function createTLSchemaFromUtils(\n\topts: TLStoreSchemaOptions\n): StoreSchema<TLRecord, TLStoreProps> {\n\tif ('schema' in opts && opts.schema) return opts.schema\n\n\treturn createTLSchema({\n\t\tshapes:\n\t\t\t'shapeUtils' in opts && opts.shapeUtils\n\t\t\t\t? utilsToMap(checkShapesAndAddCore(opts.shapeUtils))\n\t\t\t\t: undefined,\n\t\tbindings:\n\t\t\t'bindingUtils' in opts && opts.bindingUtils\n\t\t\t\t? utilsToMap(checkBindings(opts.bindingUtils))\n\t\t\t\t: undefined,\n\t\tassets:\n\t\t\t'assetUtils' in opts && opts.assetUtils\n\t\t\t\t? utilsToMap(checkAssets(opts.assetUtils))\n\t\t\t\t: undefined,\n\t\trecords: 'records' in opts ? opts.records : undefined,\n\t\tmigrations: 'migrations' in opts ? opts.migrations : undefined,\n\t})\n}\n\n/**\n * A helper for creating a TLStore.\n *\n * @param opts - Options for creating the store.\n *\n * @public\n */\nexport function createTLStore({\n\tinitialData,\n\tdefaultName = '',\n\tid,\n\tassets = inlineBase64AssetStore,\n\tusers = defaultUserStore,\n\tonMount,\n\tcollaboration,\n\tthemes,\n\t...rest\n}: TLStoreOptions = {}): TLStore {\n\tconst resolvedThemes = resolveThemes(themes)\n\tregisterColorsFromThemes(resolvedThemes)\n\tregisterFontsFromThemes(resolvedThemes)\n\tconst schema = createTLSchemaFromUtils(rest)\n\n\tconst store = new Store({\n\t\tid,\n\t\tschema,\n\t\tinitialData,\n\t\tprops: {\n\t\t\tdefaultName,\n\t\t\tassets: {\n\t\t\t\tupload: assets.upload,\n\t\t\t\tresolve: assets.resolve ?? defaultAssetResolve,\n\t\t\t\tremove: assets.remove ?? (() => Promise.resolve()),\n\t\t\t},\n\t\t\tusers: {\n\t\t\t\tcurrentUser: users.currentUser,\n\t\t\t\tresolve:\n\t\t\t\t\tusers.resolve ??\n\t\t\t\t\tcreateCachedUserResolve((userId) => {\n\t\t\t\t\t\tconst current = users.currentUser.get()\n\t\t\t\t\t\treturn current && current.id === createUserId(userId) ? current : null\n\t\t\t\t\t}),\n\t\t\t},\n\t\t\tonMount: (editor) => {\n\t\t\t\tassert(editor instanceof Editor)\n\t\t\t\
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAiC;AACjC,mBAAqF;AACrF,sBAiBO;AACP,mBAAoC;AACpC,oBAAuB;AACvB,0BAA8B;AAC9B,2BAAuD;AACvD,6BAA2D;AAC3D,2BAAiE;AACjE,8BAA+C;AAC/C,+BAA2D;AAwD3D,MAAM,sBAA4D,CAAC,UAAU,MAAM,MAAM;AAEzF,MAAM,0BAA6C,uBAAS,sBAAsB,MAAM;AACvF,QAAM,YAAQ,6CAAmB;AACjC,MAAI,CAAC,MAAM,GAAI,QAAO;AACtB,SAAO,+BAAe,OAAO;AAAA,IAC5B,QAAI,8BAAa,MAAM,EAAE;AAAA,IACzB,MAAM,MAAM,QAAQ;AAAA,IACpB,OAAO,MAAM,SAAS,gDAAuB;AAAA,EAC9C,CAAC;AACF,CAAC;AAGM,MAAM,mBAAgC;AAAA,EAC5C,aAAa;AACd;AAGO,MAAM,yBAAuC;AAAA,EACnD,QAAQ,OAAO,GAAG,SAAS;AAC1B,WAAO,EAAE,KAAK,MAAM,yBAAY,cAAc,IAAI,EAAE;AAAA,EACrD;AACD;AAUO,SAAS,wBACf,MACsC;AACtC,MAAI,YAAY,QAAQ,KAAK,OAAQ,QAAO,KAAK;AAEjD,aAAO,gCAAe;AAAA,IACrB,QACC,gBAAgB,QAAQ,KAAK,aAC1B,eAAW,4CAAsB,KAAK,UAAU,CAAC,IACjD;AAAA,IACJ,UACC,kBAAkB,QAAQ,KAAK,eAC5B,eAAW,sCAAc,KAAK,YAAY,CAAC,IAC3C;AAAA,IACJ,QACC,gBAAgB,QAAQ,KAAK,aAC1B,eAAW,kCAAY,KAAK,UAAU,CAAC,IACvC;AAAA,IACJ,SAAS,aAAa,OAAO,KAAK,UAAU;AAAA,IAC5C,YAAY,gBAAgB,OAAO,KAAK,aAAa;AAAA,EACtD,CAAC;AACF;AASO,SAAS,cAAc;AAAA,EAC7B;AAAA,EACA,cAAc;AAAA,EACd;AAAA,EACA,SAAS;AAAA,EACT,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACJ,IAAoB,CAAC,GAAY;AAChC,QAAM,qBAAiB,mCAAc,MAAM;AAC3C,gDAAyB,cAAc;AACvC,+CAAwB,cAAc;AACtC,QAAM,SAAS,wBAAwB,IAAI;AAE3C,QAAM,QAAQ,IAAI,mBAAM;AAAA,IACvB;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO;AAAA,MACN;AAAA,MACA,QAAQ;AAAA,QACP,QAAQ,OAAO;AAAA,QACf,SAAS,OAAO,WAAW;AAAA,QAC3B,QAAQ,OAAO,WAAW,MAAM,QAAQ,QAAQ;AAAA,MACjD;AAAA,MACA,OAAO;AAAA,QACN,aAAa,MAAM;AAAA,QACnB,SACC,MAAM,eACN,yCAAwB,CAAC,WAAW;AACnC,gBAAM,UAAU,MAAM,YAAY,IAAI;AACtC,iBAAO,WAAW,QAAQ,WAAO,8BAAa,MAAM,IAAI,UAAU;AAAA,QACnE,CAAC;AAAA,MACH;AAAA,MACA,SAAS,CAAC,WAAW;AACpB,iCAAO,kBAAkB,oBAAM;AAC/B,
|
|
4
|
+
"sourcesContent": ["import { Signal, computed } from '@tldraw/state'\nimport { HistoryEntry, MigrationSequence, SerializedStore, Store, StoreSchema } from '@tldraw/store'\nimport {\n\tCustomRecordInfo,\n\tSchemaPropsInfo,\n\tTLAssetStore,\n\tTLRecord,\n\tTLStore,\n\tTLStoreProps,\n\tTLStoreSnapshot,\n\tTLThemes,\n\tTLUser,\n\tTLUserStore,\n\tUserRecordType,\n\tcreateCachedUserResolve,\n\tcreateTLSchema,\n\tcreateUserId,\n\tregisterColorsFromThemes,\n\tregisterFontsFromThemes,\n} from '@tldraw/tlschema'\nimport { FileHelpers, assert } from '@tldraw/utils'\nimport { Editor } from '../editor/Editor'\nimport { resolveThemes } from '../editor/managers/ThemeManager/ThemeManager'\nimport { TLAnyAssetUtilConstructor, checkAssets } from './defaultAssets'\nimport { TLAnyBindingUtilConstructor, checkBindings } from './defaultBindings'\nimport { TLAnyShapeUtilConstructor, checkShapesAndAddCore } from './defaultShapes'\nimport { TLEditorSnapshot, loadSnapshot } from './TLEditorSnapshot'\nimport { defaultUserPreferences, getUserPreferences } from './TLUserPreferences'\n\n/** @public */\nexport interface TLStoreBaseOptions {\n\t/** The initial data for the store. */\n\tinitialData?: SerializedStore<TLRecord>\n\n\t/** A snapshot of initial data to migrate and load into the store. */\n\tsnapshot?: Partial<TLEditorSnapshot> | TLStoreSnapshot\n\n\t/** The default name for the store. */\n\tdefaultName?: string\n\n\t/** How should this store upload & resolve assets? */\n\tassets?: TLAssetStore\n\n\t/**\n\t * Named theme definitions. When provided, custom color names are automatically\n\t * registered before the store is constructed so persisted data with those\n\t * colors passes validation on load.\n\t */\n\tthemes?: Partial<TLThemes>\n\n\t/** How should this store resolve users for attribution? */\n\tusers?: TLUserStore\n\n\t/** Called when the store is connected to an {@link @tldraw/editor#Editor}. */\n\tonMount?(editor: Editor): void | (() => void)\n}\n\n/** @public */\nexport type TLStoreSchemaOptions =\n\t| {\n\t\t\tschema?: StoreSchema<TLRecord, TLStoreProps>\n\t }\n\t| {\n\t\t\tshapeUtils?: readonly TLAnyShapeUtilConstructor[]\n\t\t\tbindingUtils?: readonly TLAnyBindingUtilConstructor[]\n\t\t\tassetUtils?: readonly TLAnyAssetUtilConstructor[]\n\t\t\tmigrations?: readonly MigrationSequence[]\n\t\t\trecords?: Record<string, CustomRecordInfo>\n\t }\n\n/** @public */\nexport type TLStoreOptions = TLStoreBaseOptions & {\n\tid?: string\n\t/** Collaboration options for the store. */\n\tcollaboration?: {\n\t\tstatus: Signal<'online' | 'offline'> | null\n\t\tmode?: Signal<'readonly' | 'readwrite'> | null\n\t}\n} & TLStoreSchemaOptions\n\n/** @public */\nexport type TLStoreEventInfo = HistoryEntry<TLRecord>\n\nconst defaultAssetResolve: NonNullable<TLAssetStore['resolve']> = (asset) => asset.props.src\n\nconst _defaultCurrentUser: Signal<TLUser | null> = computed('defaultCurrentUser', () => {\n\tconst prefs = getUserPreferences()\n\tif (!prefs.id) return null\n\treturn UserRecordType.create({\n\t\tid: createUserId(prefs.id),\n\t\tname: prefs.name ?? '',\n\t\tcolor: prefs.color ?? defaultUserPreferences.color,\n\t})\n})\n\n/** @public */\nexport const defaultUserStore: TLUserStore = {\n\tcurrentUser: _defaultCurrentUser,\n}\n\n/** @public */\nexport const inlineBase64AssetStore: TLAssetStore = {\n\tupload: async (_, file) => {\n\t\treturn { src: await FileHelpers.blobToDataUrl(file) }\n\t},\n}\n\n/**\n * A helper for creating a TLStore schema from either an object with shapeUtils, bindingUtils, and\n * migrations, or a schema.\n *\n * @param opts - Options for creating the schema.\n *\n * @public\n */\nexport function createTLSchemaFromUtils(\n\topts: TLStoreSchemaOptions\n): StoreSchema<TLRecord, TLStoreProps> {\n\tif ('schema' in opts && opts.schema) return opts.schema\n\n\treturn createTLSchema({\n\t\tshapes:\n\t\t\t'shapeUtils' in opts && opts.shapeUtils\n\t\t\t\t? utilsToMap(checkShapesAndAddCore(opts.shapeUtils))\n\t\t\t\t: undefined,\n\t\tbindings:\n\t\t\t'bindingUtils' in opts && opts.bindingUtils\n\t\t\t\t? utilsToMap(checkBindings(opts.bindingUtils))\n\t\t\t\t: undefined,\n\t\tassets:\n\t\t\t'assetUtils' in opts && opts.assetUtils\n\t\t\t\t? utilsToMap(checkAssets(opts.assetUtils))\n\t\t\t\t: undefined,\n\t\trecords: 'records' in opts ? opts.records : undefined,\n\t\tmigrations: 'migrations' in opts ? opts.migrations : undefined,\n\t})\n}\n\n/**\n * A helper for creating a TLStore.\n *\n * @param opts - Options for creating the store.\n *\n * @public\n */\nexport function createTLStore({\n\tinitialData,\n\tdefaultName = '',\n\tid,\n\tassets = inlineBase64AssetStore,\n\tusers = defaultUserStore,\n\tonMount,\n\tcollaboration,\n\tthemes,\n\t...rest\n}: TLStoreOptions = {}): TLStore {\n\tconst resolvedThemes = resolveThemes(themes)\n\tregisterColorsFromThemes(resolvedThemes)\n\tregisterFontsFromThemes(resolvedThemes)\n\tconst schema = createTLSchemaFromUtils(rest)\n\n\tconst store = new Store({\n\t\tid,\n\t\tschema,\n\t\tinitialData,\n\t\tprops: {\n\t\t\tdefaultName,\n\t\t\tassets: {\n\t\t\t\tupload: assets.upload,\n\t\t\t\tresolve: assets.resolve ?? defaultAssetResolve,\n\t\t\t\tremove: assets.remove ?? (() => Promise.resolve()),\n\t\t\t},\n\t\t\tusers: {\n\t\t\t\tcurrentUser: users.currentUser,\n\t\t\t\tresolve:\n\t\t\t\t\tusers.resolve ??\n\t\t\t\t\tcreateCachedUserResolve((userId) => {\n\t\t\t\t\t\tconst current = users.currentUser.get()\n\t\t\t\t\t\treturn current && current.id === createUserId(userId) ? current : null\n\t\t\t\t\t}),\n\t\t\t},\n\t\t\tonMount: (editor) => {\n\t\t\t\tassert(editor instanceof Editor)\n\t\t\t\treturn onMount?.(editor)\n\t\t\t},\n\t\t\tcollaboration,\n\t\t},\n\t})\n\n\tif (rest.snapshot) {\n\t\tif (initialData) throw new Error('Cannot provide both initialData and snapshot')\n\t\tloadSnapshot(store, rest.snapshot, { forceOverwriteSessionState: true })\n\t}\n\n\treturn store\n}\n\nfunction utilsToMap<T extends SchemaPropsInfo & { type: string }>(utils: T[]) {\n\treturn Object.fromEntries(\n\t\tutils.map((s): [string, SchemaPropsInfo] => [\n\t\t\ts.type,\n\t\t\t{\n\t\t\t\tprops: s.props,\n\t\t\t\tmigrations: s.migrations,\n\t\t\t},\n\t\t])\n\t)\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|