@tldraw/editor 4.5.3 → 4.6.0-canary.0bcbb3ed5bcb
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 +37 -6
- package/dist-cjs/index.js +6 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/TldrawEditor.js +7 -5
- package/dist-cjs/lib/TldrawEditor.js.map +3 -3
- package/dist-cjs/lib/components/default-components/CanvasShapeIndicators.js +3 -2
- package/dist-cjs/lib/components/default-components/CanvasShapeIndicators.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js +8 -5
- package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js.map +2 -2
- package/dist-cjs/lib/config/TLSessionStateSnapshot.js +8 -5
- package/dist-cjs/lib/config/TLSessionStateSnapshot.js.map +2 -2
- package/dist-cjs/lib/config/TLUserPreferences.js +3 -2
- package/dist-cjs/lib/config/TLUserPreferences.js.map +2 -2
- package/dist-cjs/lib/config/createTLStore.js +1 -0
- package/dist-cjs/lib/config/createTLStore.js.map +2 -2
- package/dist-cjs/lib/editor/Editor.js +52 -16
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js +62 -6
- package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/FontManager/FontManager.js +4 -3
- package/dist-cjs/lib/editor/managers/FontManager/FontManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js +5 -0
- package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/TextManager/TextManager.js +2 -2
- package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +3 -2
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
- package/dist-cjs/lib/editor/types/misc-types.js.map +1 -1
- package/dist-cjs/lib/exports/FontEmbedder.js +9 -8
- package/dist-cjs/lib/exports/FontEmbedder.js.map +2 -2
- package/dist-cjs/lib/exports/StyleEmbedder.js +27 -15
- package/dist-cjs/lib/exports/StyleEmbedder.js.map +3 -3
- package/dist-cjs/lib/exports/domUtils.js +15 -0
- package/dist-cjs/lib/exports/domUtils.js.map +2 -2
- package/dist-cjs/lib/exports/embedMedia.js +15 -12
- package/dist-cjs/lib/exports/embedMedia.js.map +2 -2
- package/dist-cjs/lib/exports/exportToSvg.js +8 -7
- package/dist-cjs/lib/exports/exportToSvg.js.map +2 -2
- package/dist-cjs/lib/exports/getSvgAsImage.js +181 -29
- package/dist-cjs/lib/exports/getSvgAsImage.js.map +3 -3
- package/dist-cjs/lib/exports/getSvgJsx.js +21 -9
- package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
- package/dist-cjs/lib/globals/environment.js +4 -3
- package/dist-cjs/lib/globals/environment.js.map +2 -2
- package/dist-cjs/lib/hooks/useCanvasEvents.js +2 -2
- package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/useDocumentEvents.js +13 -11
- package/dist-cjs/lib/hooks/useDocumentEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.js +3 -2
- package/dist-cjs/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/useScreenBounds.js +10 -6
- package/dist-cjs/lib/hooks/useScreenBounds.js.map +2 -2
- package/dist-cjs/lib/hooks/useViewportHeight.js +13 -11
- package/dist-cjs/lib/hooks/useViewportHeight.js.map +3 -3
- package/dist-cjs/lib/license/Watermark.js +10 -0
- package/dist-cjs/lib/license/Watermark.js.map +2 -2
- package/dist-cjs/lib/primitives/Vec.js +35 -22
- package/dist-cjs/lib/primitives/Vec.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Arc2d.js +6 -13
- package/dist-cjs/lib/primitives/geometry/Arc2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Circle2d.js +31 -2
- package/dist-cjs/lib/primitives/geometry/Circle2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js +9 -0
- package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/CubicSpline2d.js +9 -0
- package/dist-cjs/lib/primitives/geometry/CubicSpline2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Edge2d.js +32 -18
- package/dist-cjs/lib/primitives/geometry/Edge2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Ellipse2d.js +12 -0
- package/dist-cjs/lib/primitives/geometry/Ellipse2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Polyline2d.js +51 -12
- package/dist-cjs/lib/primitives/geometry/Polyline2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Stadium2d.js +12 -0
- package/dist-cjs/lib/primitives/geometry/Stadium2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/geometry.bench.js +133 -0
- package/dist-cjs/lib/primitives/geometry/geometry.bench.js.map +7 -0
- package/dist-cjs/lib/primitives/intersect.js +16 -15
- package/dist-cjs/lib/primitives/intersect.js.map +2 -2
- package/dist-cjs/lib/primitives/utils.js +0 -1
- package/dist-cjs/lib/primitives/utils.js.map +2 -2
- package/dist-cjs/lib/utils/browserCanvasMaxSize.js +3 -2
- package/dist-cjs/lib/utils/browserCanvasMaxSize.js.map +2 -2
- package/dist-cjs/lib/utils/dom.js +15 -2
- package/dist-cjs/lib/utils/dom.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 +37 -6
- package/dist-esm/index.mjs +8 -1
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/TldrawEditor.mjs +7 -5
- package/dist-esm/lib/TldrawEditor.mjs.map +3 -3
- package/dist-esm/lib/components/default-components/CanvasShapeIndicators.mjs +2 -1
- package/dist-esm/lib/components/default-components/CanvasShapeIndicators.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs +8 -5
- package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs.map +2 -2
- package/dist-esm/lib/config/TLSessionStateSnapshot.mjs +8 -5
- package/dist-esm/lib/config/TLSessionStateSnapshot.mjs.map +2 -2
- package/dist-esm/lib/config/TLUserPreferences.mjs +3 -2
- package/dist-esm/lib/config/TLUserPreferences.mjs.map +2 -2
- package/dist-esm/lib/config/createTLStore.mjs +1 -0
- package/dist-esm/lib/config/createTLStore.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +53 -17
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs +64 -6
- package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs +4 -3
- package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs +5 -0
- package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs +2 -2
- package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +3 -2
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
- package/dist-esm/lib/exports/FontEmbedder.mjs +9 -8
- package/dist-esm/lib/exports/FontEmbedder.mjs.map +2 -2
- package/dist-esm/lib/exports/StyleEmbedder.mjs +29 -16
- package/dist-esm/lib/exports/StyleEmbedder.mjs.map +3 -3
- package/dist-esm/lib/exports/domUtils.mjs +15 -0
- package/dist-esm/lib/exports/domUtils.mjs.map +2 -2
- package/dist-esm/lib/exports/embedMedia.mjs +16 -13
- package/dist-esm/lib/exports/embedMedia.mjs.map +2 -2
- package/dist-esm/lib/exports/exportToSvg.mjs +8 -7
- package/dist-esm/lib/exports/exportToSvg.mjs.map +2 -2
- package/dist-esm/lib/exports/getSvgAsImage.mjs +181 -29
- package/dist-esm/lib/exports/getSvgAsImage.mjs.map +3 -3
- package/dist-esm/lib/exports/getSvgJsx.mjs +21 -9
- package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
- package/dist-esm/lib/globals/environment.mjs +4 -3
- package/dist-esm/lib/globals/environment.mjs.map +2 -2
- package/dist-esm/lib/hooks/useCanvasEvents.mjs +2 -2
- package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useDocumentEvents.mjs +13 -11
- package/dist-esm/lib/hooks/useDocumentEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.mjs +3 -2
- package/dist-esm/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useScreenBounds.mjs +10 -6
- package/dist-esm/lib/hooks/useScreenBounds.mjs.map +2 -2
- package/dist-esm/lib/hooks/useViewportHeight.mjs +13 -11
- package/dist-esm/lib/hooks/useViewportHeight.mjs.map +3 -3
- package/dist-esm/lib/license/Watermark.mjs +10 -0
- package/dist-esm/lib/license/Watermark.mjs.map +2 -2
- package/dist-esm/lib/primitives/Vec.mjs +35 -22
- package/dist-esm/lib/primitives/Vec.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Arc2d.mjs +6 -13
- package/dist-esm/lib/primitives/geometry/Arc2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Circle2d.mjs +31 -2
- package/dist-esm/lib/primitives/geometry/Circle2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs +9 -0
- package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/CubicSpline2d.mjs +9 -0
- package/dist-esm/lib/primitives/geometry/CubicSpline2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Edge2d.mjs +32 -18
- package/dist-esm/lib/primitives/geometry/Edge2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs +13 -1
- package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Polyline2d.mjs +51 -12
- package/dist-esm/lib/primitives/geometry/Polyline2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Stadium2d.mjs +13 -1
- package/dist-esm/lib/primitives/geometry/Stadium2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/geometry.bench.mjs +132 -0
- package/dist-esm/lib/primitives/geometry/geometry.bench.mjs.map +7 -0
- package/dist-esm/lib/primitives/intersect.mjs +17 -16
- package/dist-esm/lib/primitives/intersect.mjs.map +2 -2
- package/dist-esm/lib/primitives/utils.mjs +0 -1
- package/dist-esm/lib/primitives/utils.mjs.map +2 -2
- package/dist-esm/lib/utils/browserCanvasMaxSize.mjs +3 -2
- package/dist-esm/lib/utils/browserCanvasMaxSize.mjs.map +2 -2
- package/dist-esm/lib/utils/dom.mjs +15 -2
- package/dist-esm/lib/utils/dom.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/index.ts +3 -0
- package/src/lib/TldrawEditor.tsx +7 -5
- package/src/lib/components/default-components/CanvasShapeIndicators.tsx +2 -1
- package/src/lib/components/default-components/DefaultCanvas.tsx +1 -1
- package/src/lib/components/default-components/DefaultErrorFallback.tsx +8 -5
- package/src/lib/config/TLSessionStateSnapshot.ts +8 -5
- package/src/lib/config/TLUserPreferences.ts +3 -2
- package/src/lib/config/createTLStore.ts +3 -0
- package/src/lib/editor/Editor.ts +53 -15
- package/src/lib/editor/managers/FocusManager/FocusManager.test.ts +7 -6
- package/src/lib/editor/managers/FocusManager/FocusManager.ts +10 -7
- package/src/lib/editor/managers/FontManager/FontManager.test.ts +1 -0
- package/src/lib/editor/managers/FontManager/FontManager.ts +4 -3
- package/src/lib/editor/managers/HistoryManager/HistoryManager.test.ts +16 -0
- package/src/lib/editor/managers/HistoryManager/HistoryManager.ts +7 -2
- package/src/lib/editor/managers/TextManager/TextManager.test.ts +4 -5
- package/src/lib/editor/managers/TextManager/TextManager.ts +2 -2
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +3 -2
- package/src/lib/editor/types/misc-types.ts +8 -2
- package/src/lib/exports/FontEmbedder.ts +10 -9
- package/src/lib/exports/StyleEmbedder.ts +33 -15
- package/src/lib/exports/domUtils.ts +20 -0
- package/src/lib/exports/embedMedia.ts +23 -17
- package/src/lib/exports/exportToSvg.tsx +8 -7
- package/src/lib/exports/getSvgAsImage.ts +292 -32
- package/src/lib/exports/getSvgJsx.test.ts +103 -101
- package/src/lib/exports/getSvgJsx.tsx +33 -10
- package/src/lib/globals/environment.ts +4 -3
- package/src/lib/hooks/useCanvasEvents.ts +2 -3
- package/src/lib/hooks/useDocumentEvents.ts +16 -11
- package/src/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.ts +3 -3
- package/src/lib/hooks/useScreenBounds.ts +10 -6
- package/src/lib/hooks/useViewportHeight.ts +13 -11
- package/src/lib/license/Watermark.tsx +10 -0
- package/src/lib/primitives/Vec.ts +51 -24
- package/src/lib/primitives/geometry/Arc2d.ts +10 -15
- package/src/lib/primitives/geometry/Circle2d.ts +40 -2
- package/src/lib/primitives/geometry/CubicBezier2d.ts +10 -0
- package/src/lib/primitives/geometry/CubicSpline2d.ts +10 -0
- package/src/lib/primitives/geometry/Edge2d.ts +41 -18
- package/src/lib/primitives/geometry/Ellipse2d.ts +14 -1
- package/src/lib/primitives/geometry/Polyline2d.ts +60 -12
- package/src/lib/primitives/geometry/Stadium2d.ts +14 -1
- package/src/lib/primitives/geometry/geometry.bench.ts +179 -0
- package/src/lib/primitives/intersect.ts +27 -27
- package/src/lib/primitives/utils.ts +4 -4
- package/src/lib/test/TestEditor.ts +1 -0
- package/src/lib/utils/browserCanvasMaxSize.ts +4 -2
- package/src/lib/utils/dom.ts +34 -2
- package/src/version.ts +3 -3
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/utils/browserCanvasMaxSize.ts"],
|
|
4
|
-
"sourcesContent": ["/** @internal */\nexport interface CanvasMaxSize {\n\tmaxWidth: number\n\tmaxHeight: number\n\tmaxArea: number\n}\n\n// Cache this, only want to do this once per browser session\nlet maxCanvasSizes: CanvasMaxSize | null = null\n\nfunction getBrowserCanvasMaxSize(): CanvasMaxSize {\n\tif (!maxCanvasSizes) {\n\t\tmaxCanvasSizes = {\n\t\t\tmaxWidth: getCanvasSize('width'), // test very wide but 1 pixel tall canvases\n\t\t\tmaxHeight: getCanvasSize('height'), // test very tall but 1 pixel wide canvases\n\t\t\tmaxArea: getCanvasSize('area'), // test square canvases\n\t\t}\n\t}\n\treturn maxCanvasSizes\n}\n\n/*!\n * Extracted from https://github.com/jhildenbiddle/canvas-size\n * MIT License: https://github.com/jhildenbiddle/canvas-size/blob/master/LICENSE\n * Copyright (c) John Hildenbiddle\n */\n\nconst MAX_SAFE_CANVAS_DIMENSION = 8192\nconst MAX_SAFE_CANVAS_AREA = 4096 * 4096\n\nconst TEST_SIZES = {\n\tarea: [\n\t\t// Chrome 70 (Mac, Win)\n\t\t// Chrome 68 (Android 4.4)\n\t\t// Edge 17 (Win)\n\t\t// Safari 7-12 (Mac)\n\t\t16384,\n\t\t// Chrome 68 (Android 7.1-9)\n\t\t14188,\n\t\t// Chrome 68 (Android 5)\n\t\t11402,\n\t\t// Firefox 63 (Mac, Win)\n\t\t11180,\n\t\t// Chrome 68 (Android 6)\n\t\t10836,\n\t\t// IE 9-11 (Win)\n\t\t8192,\n\t\t// IE Mobile (Windows Phone 8.x)\n\t\t// Safari (iOS 9 - 12)\n\t\t4096,\n\t],\n\theight: [\n\t\t// Safari 7-12 (Mac)\n\t\t// Safari (iOS 9-12)\n\t\t8388607,\n\t\t// Chrome 83 (Mac, Win)\n\t\t65535,\n\t\t// Chrome 70 (Mac, Win)\n\t\t// Chrome 68 (Android 4.4-9)\n\t\t// Firefox 63 (Mac, Win)\n\t\t32767,\n\t\t// Edge 17 (Win)\n\t\t// IE11 (Win)\n\t\t16384,\n\t\t// IE 9-10 (Win)\n\t\t8192,\n\t\t// IE Mobile (Windows Phone 8.x)\n\t\t4096,\n\t],\n\twidth: [\n\t\t// Safari 7-12 (Mac)\n\t\t// Safari (iOS 9-12)\n\t\t4194303,\n\t\t// Chrome 83 (Mac, Win)\n\t\t65535,\n\t\t// Chrome 70 (Mac, Win)\n\t\t// Chrome 68 (Android 4.4-9)\n\t\t// Firefox 63 (Mac, Win)\n\t\t32767,\n\t\t// Edge 17 (Win)\n\t\t// IE11 (Win)\n\t\t16384,\n\t\t// IE 9-10 (Win)\n\t\t8192,\n\t\t// IE Mobile (Windows Phone 8.x)\n\t\t4096,\n\t],\n} as const\n\n/**\n * Tests ability to read pixel data from canvas elements of various dimensions\n * by decreasing canvas height and/or width until a test succeeds.\n * @param dimension - The dimension to test.\n * @returns The maximum size of the canvas for the given dimension.\n */\nfunction getCanvasSize(dimension: 'width' | 'height' | 'area'): number {\n\tconst cropCvs =
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["import { getGlobalDocument } from './dom'\n\n/** @internal */\nexport interface CanvasMaxSize {\n\tmaxWidth: number\n\tmaxHeight: number\n\tmaxArea: number\n}\n\n// Cache this, only want to do this once per browser session\nlet maxCanvasSizes: CanvasMaxSize | null = null\n\nfunction getBrowserCanvasMaxSize(): CanvasMaxSize {\n\tif (!maxCanvasSizes) {\n\t\tmaxCanvasSizes = {\n\t\t\tmaxWidth: getCanvasSize('width'), // test very wide but 1 pixel tall canvases\n\t\t\tmaxHeight: getCanvasSize('height'), // test very tall but 1 pixel wide canvases\n\t\t\tmaxArea: getCanvasSize('area'), // test square canvases\n\t\t}\n\t}\n\treturn maxCanvasSizes\n}\n\n/*!\n * Extracted from https://github.com/jhildenbiddle/canvas-size\n * MIT License: https://github.com/jhildenbiddle/canvas-size/blob/master/LICENSE\n * Copyright (c) John Hildenbiddle\n */\n\nconst MAX_SAFE_CANVAS_DIMENSION = 8192\nconst MAX_SAFE_CANVAS_AREA = 4096 * 4096\n\nconst TEST_SIZES = {\n\tarea: [\n\t\t// Chrome 70 (Mac, Win)\n\t\t// Chrome 68 (Android 4.4)\n\t\t// Edge 17 (Win)\n\t\t// Safari 7-12 (Mac)\n\t\t16384,\n\t\t// Chrome 68 (Android 7.1-9)\n\t\t14188,\n\t\t// Chrome 68 (Android 5)\n\t\t11402,\n\t\t// Firefox 63 (Mac, Win)\n\t\t11180,\n\t\t// Chrome 68 (Android 6)\n\t\t10836,\n\t\t// IE 9-11 (Win)\n\t\t8192,\n\t\t// IE Mobile (Windows Phone 8.x)\n\t\t// Safari (iOS 9 - 12)\n\t\t4096,\n\t],\n\theight: [\n\t\t// Safari 7-12 (Mac)\n\t\t// Safari (iOS 9-12)\n\t\t8388607,\n\t\t// Chrome 83 (Mac, Win)\n\t\t65535,\n\t\t// Chrome 70 (Mac, Win)\n\t\t// Chrome 68 (Android 4.4-9)\n\t\t// Firefox 63 (Mac, Win)\n\t\t32767,\n\t\t// Edge 17 (Win)\n\t\t// IE11 (Win)\n\t\t16384,\n\t\t// IE 9-10 (Win)\n\t\t8192,\n\t\t// IE Mobile (Windows Phone 8.x)\n\t\t4096,\n\t],\n\twidth: [\n\t\t// Safari 7-12 (Mac)\n\t\t// Safari (iOS 9-12)\n\t\t4194303,\n\t\t// Chrome 83 (Mac, Win)\n\t\t65535,\n\t\t// Chrome 70 (Mac, Win)\n\t\t// Chrome 68 (Android 4.4-9)\n\t\t// Firefox 63 (Mac, Win)\n\t\t32767,\n\t\t// Edge 17 (Win)\n\t\t// IE11 (Win)\n\t\t16384,\n\t\t// IE 9-10 (Win)\n\t\t8192,\n\t\t// IE Mobile (Windows Phone 8.x)\n\t\t4096,\n\t],\n} as const\n\n/**\n * Tests ability to read pixel data from canvas elements of various dimensions\n * by decreasing canvas height and/or width until a test succeeds.\n * @param dimension - The dimension to test.\n * @returns The maximum size of the canvas for the given dimension.\n */\nfunction getCanvasSize(dimension: 'width' | 'height' | 'area'): number {\n\tconst cropCvs = getGlobalDocument().createElement('canvas')\n\tcropCvs.width = 1\n\tcropCvs.height = 1\n\tconst cropCtx = cropCvs.getContext('2d')!\n\n\tfor (const size of TEST_SIZES[dimension]) {\n\t\tconst w = dimension === 'height' ? 1 : size\n\t\tconst h = dimension === 'width' ? 1 : size\n\n\t\tconst testCvs = getGlobalDocument().createElement('canvas')\n\t\ttestCvs.width = w\n\t\ttestCvs.height = h\n\t\tconst testCtx = testCvs.getContext('2d')!\n\n\t\ttestCtx.fillRect(w - 1, h - 1, 1, 1)\n\t\tcropCtx.drawImage(testCvs, w - 1, h - 1, 1, 1, 0, 0, 1, 1)\n\n\t\tconst isTestPassed = cropCtx.getImageData(0, 0, 1, 1).data[3] !== 0\n\t\t// release memory\n\t\ttestCvs.width = 0\n\t\ttestCvs.height = 0\n\n\t\tif (isTestPassed) {\n\t\t\t// release memory\n\t\t\tcropCvs.width = 0\n\t\t\tcropCvs.height = 0\n\n\t\t\tif (dimension === 'area') {\n\t\t\t\treturn size * size\n\t\t\t} else {\n\t\t\t\treturn size\n\t\t\t}\n\t\t}\n\t}\n\n\t// didn't find a good size, release memory and error\n\tcropCvs.width = 0\n\tcropCvs.height = 0\n\n\tthrow Error('Failed to determine maximum canvas dimension')\n}\n\n/** @internal */\nexport function clampToBrowserMaxCanvasSize(width: number, height: number): [number, number] {\n\tif (\n\t\twidth <= MAX_SAFE_CANVAS_DIMENSION &&\n\t\theight <= MAX_SAFE_CANVAS_DIMENSION &&\n\t\twidth * height <= MAX_SAFE_CANVAS_AREA\n\t) {\n\t\treturn [width, height]\n\t}\n\n\tconst { maxWidth, maxHeight, maxArea } = getBrowserCanvasMaxSize()\n\tconst aspectRatio = width / height\n\n\tif (width > maxWidth) {\n\t\twidth = maxWidth\n\t\theight = width / aspectRatio\n\t}\n\n\tif (height > maxHeight) {\n\t\theight = maxHeight\n\t\twidth = height * aspectRatio\n\t}\n\n\tif (width * height > maxArea) {\n\t\tconst ratio = Math.sqrt(maxArea / (width * height))\n\t\twidth *= ratio\n\t\theight *= ratio\n\t}\n\n\treturn [width, height]\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,yBAAyB;AAUlC,IAAI,iBAAuC;AAE3C,SAAS,0BAAyC;AACjD,MAAI,CAAC,gBAAgB;AACpB,qBAAiB;AAAA,MAChB,UAAU,cAAc,OAAO;AAAA;AAAA,MAC/B,WAAW,cAAc,QAAQ;AAAA;AAAA,MACjC,SAAS,cAAc,MAAM;AAAA;AAAA,IAC9B;AAAA,EACD;AACA,SAAO;AACR;AAEA;AAAA;AAAA;AAAA;AAAA;AAMA,MAAM,4BAA4B;AAClC,MAAM,uBAAuB,OAAO;AAEpC,MAAM,aAAa;AAAA,EAClB,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA,IAKL;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA;AAAA;AAAA,IAGA;AAAA,EACD;AAAA,EACA,QAAQ;AAAA;AAAA;AAAA,IAGP;AAAA;AAAA,IAEA;AAAA;AAAA;AAAA;AAAA,IAIA;AAAA;AAAA;AAAA,IAGA;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA,EACD;AAAA,EACA,OAAO;AAAA;AAAA;AAAA,IAGN;AAAA;AAAA,IAEA;AAAA;AAAA;AAAA;AAAA,IAIA;AAAA;AAAA;AAAA,IAGA;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA,EACD;AACD;AAQA,SAAS,cAAc,WAAgD;AACtE,QAAM,UAAU,kBAAkB,EAAE,cAAc,QAAQ;AAC1D,UAAQ,QAAQ;AAChB,UAAQ,SAAS;AACjB,QAAM,UAAU,QAAQ,WAAW,IAAI;AAEvC,aAAW,QAAQ,WAAW,SAAS,GAAG;AACzC,UAAM,IAAI,cAAc,WAAW,IAAI;AACvC,UAAM,IAAI,cAAc,UAAU,IAAI;AAEtC,UAAM,UAAU,kBAAkB,EAAE,cAAc,QAAQ;AAC1D,YAAQ,QAAQ;AAChB,YAAQ,SAAS;AACjB,UAAM,UAAU,QAAQ,WAAW,IAAI;AAEvC,YAAQ,SAAS,IAAI,GAAG,IAAI,GAAG,GAAG,CAAC;AACnC,YAAQ,UAAU,SAAS,IAAI,GAAG,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAEzD,UAAM,eAAe,QAAQ,aAAa,GAAG,GAAG,GAAG,CAAC,EAAE,KAAK,CAAC,MAAM;AAElE,YAAQ,QAAQ;AAChB,YAAQ,SAAS;AAEjB,QAAI,cAAc;AAEjB,cAAQ,QAAQ;AAChB,cAAQ,SAAS;AAEjB,UAAI,cAAc,QAAQ;AACzB,eAAO,OAAO;AAAA,MACf,OAAO;AACN,eAAO;AAAA,MACR;AAAA,IACD;AAAA,EACD;AAGA,UAAQ,QAAQ;AAChB,UAAQ,SAAS;AAEjB,QAAM,MAAM,8CAA8C;AAC3D;AAGO,SAAS,4BAA4B,OAAe,QAAkC;AAC5F,MACC,SAAS,6BACT,UAAU,6BACV,QAAQ,UAAU,sBACjB;AACD,WAAO,CAAC,OAAO,MAAM;AAAA,EACtB;AAEA,QAAM,EAAE,UAAU,WAAW,QAAQ,IAAI,wBAAwB;AACjE,QAAM,cAAc,QAAQ;AAE5B,MAAI,QAAQ,UAAU;AACrB,YAAQ;AACR,aAAS,QAAQ;AAAA,EAClB;AAEA,MAAI,SAAS,WAAW;AACvB,aAAS;AACT,YAAQ,SAAS;AAAA,EAClB;AAEA,MAAI,QAAQ,SAAS,SAAS;AAC7B,UAAM,QAAQ,KAAK,KAAK,WAAW,QAAQ,OAAO;AAClD,aAAS;AACT,cAAU;AAAA,EACX;AAEA,SAAO,CAAC,OAAO,MAAM;AACtB;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -45,12 +45,25 @@ function elementShouldCaptureKeys(el, includeButtonsAndMenus = true) {
|
|
|
45
45
|
const tagName = el.tagName.toLowerCase();
|
|
46
46
|
return el.isContentEditable || tagName === "input" || tagName === "textarea" || includeButtonsAndMenus && tagName === "select" || includeButtonsAndMenus && tagName === "button" || el.classList.contains("tlui-slider__thumb");
|
|
47
47
|
}
|
|
48
|
-
function
|
|
49
|
-
|
|
48
|
+
function getGlobalDocument() {
|
|
49
|
+
if (typeof document !== "undefined") return document;
|
|
50
|
+
return globalThis.document;
|
|
51
|
+
}
|
|
52
|
+
function getGlobalWindow() {
|
|
53
|
+
if (typeof window !== "undefined") return window;
|
|
54
|
+
return globalThis;
|
|
55
|
+
}
|
|
56
|
+
function activeElementShouldCaptureKeys(includeButtonsAndMenus = true, doc) {
|
|
57
|
+
return elementShouldCaptureKeys(
|
|
58
|
+
(doc ?? getGlobalDocument()).activeElement,
|
|
59
|
+
includeButtonsAndMenus
|
|
60
|
+
);
|
|
50
61
|
}
|
|
51
62
|
export {
|
|
52
63
|
activeElementShouldCaptureKeys,
|
|
53
64
|
elementShouldCaptureKeys,
|
|
65
|
+
getGlobalDocument,
|
|
66
|
+
getGlobalWindow,
|
|
54
67
|
loopToHtmlElement,
|
|
55
68
|
preventDefault,
|
|
56
69
|
releasePointerCapture,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/utils/dom.ts"],
|
|
4
|
-
"sourcesContent": ["/*\nThis is used to facilitate double clicking and pointer capture on elements.\n\nThe events in this file are possibly set on individual SVG elements, \nsuch as handles or corner handles, rather than on HTML elements or \nSVGSVGElements. Raw SVG elements do not support pointerCapture in\nmost cases, meaning that in order for pointer capture to work, we \nneed to crawl up the DOM tree to find the nearest HTML element. Then,\nin order for that element to also call the `onPointerUp` event from\nthis file, we need to manually set that event on that element and\nlater remove it when the pointerup occurs. This is a potential leak\nif the user clicks on a handle but the pointerup does not fire for\nwhatever reason.\n*/\n\nimport { debugFlags, pointerCaptureTrackingObject } from './debug-flags'\n\n/** @public */\nexport function loopToHtmlElement(elm: Element): HTMLElement {\n\tif (elm.nodeType === Node.ELEMENT_NODE) return elm as HTMLElement\n\tif (elm.parentElement) return loopToHtmlElement(elm.parentElement)\n\telse throw Error('Could not find a parent element of an HTML type!')\n}\n\n/**\n * This function calls `event.preventDefault()` for you. Why is that useful?\n *\n * Because if you enable `window.preventDefaultLogging = true` it'll log out a message when it\n * happens. Because we use console.warn rather than (log) you'll get a stack trace in the inspector\n * telling you exactly where it happened. This is important because `e.preventDefault()` is the\n * source of many bugs, but unfortunately it can't be avoided because it also stops a lot of default\n * behaviour which doesn't make sense in our UI\n *\n * @param event - To prevent default on\n * @public\n */\nexport function preventDefault(event: React.BaseSyntheticEvent | Event) {\n\tevent.preventDefault()\n\tif (debugFlags.logPreventDefaults.get()) {\n\t\tconsole.warn('preventDefault called on event:', event)\n\t}\n}\n\n/** @public */\nexport function setPointerCapture(\n\telement: Element,\n\tevent: React.PointerEvent<Element> | PointerEvent\n) {\n\telement.setPointerCapture(event.pointerId)\n\tif (debugFlags.logPointerCaptures.get()) {\n\t\tconst trackingObj = pointerCaptureTrackingObject.get()\n\t\ttrackingObj.set(element, (trackingObj.get(element) ?? 0) + 1)\n\t\tconsole.warn('setPointerCapture called on element:', element, event)\n\t}\n}\n\n/** @public */\nexport function releasePointerCapture(\n\telement: Element,\n\tevent: React.PointerEvent<Element> | PointerEvent\n) {\n\tif (!element.hasPointerCapture(event.pointerId)) {\n\t\treturn\n\t}\n\n\telement.releasePointerCapture(event.pointerId)\n\tif (debugFlags.logPointerCaptures.get()) {\n\t\tconst trackingObj = pointerCaptureTrackingObject.get()\n\t\tif (trackingObj.get(element) === 1) {\n\t\t\ttrackingObj.delete(element)\n\t\t} else if (trackingObj.has(element)) {\n\t\t\ttrackingObj.set(element, trackingObj.get(element)! - 1)\n\t\t} else {\n\t\t\tconsole.warn('Release without capture')\n\t\t}\n\t\tconsole.warn('releasePointerCapture called on element:', element, event)\n\t}\n}\n\n/**\n * Calls `event.stopPropagation()`.\n *\n * @deprecated Use {@link Editor.markEventAsHandled} instead, or manually call `event.stopPropagation()` if\n * that's what you really want.\n *\n * @public\n */\nexport const stopEventPropagation = (e: any) => e.stopPropagation()\n\n/** @internal */\nexport const setStyleProperty = (\n\telm: HTMLElement | null,\n\tproperty: string,\n\tvalue: string | number\n) => {\n\tif (!elm) return\n\telm.style.setProperty(property, String(value))\n}\n\n/** @internal */\nexport function elementShouldCaptureKeys(el: Element | null, includeButtonsAndMenus = true) {\n\tif (!el) return false\n\n\tconst tagName = el.tagName.toLowerCase()\n\treturn (\n\t\t(el as HTMLElement).isContentEditable ||\n\t\ttagName === 'input' ||\n\t\ttagName === 'textarea' ||\n\t\t(includeButtonsAndMenus && tagName === 'select') ||\n\t\t(includeButtonsAndMenus && tagName === 'button') ||\n\t\tel.classList.contains('tlui-slider__thumb')\n\t)\n}\n\n/** @internal */\nexport function activeElementShouldCaptureKeys(includeButtonsAndMenus = true) {\n\treturn elementShouldCaptureKeys(
|
|
5
|
-
"mappings": "AAeA,SAAS,YAAY,oCAAoC;AAGlD,SAAS,kBAAkB,KAA2B;AAC5D,MAAI,IAAI,aAAa,KAAK,aAAc,QAAO;AAC/C,MAAI,IAAI,cAAe,QAAO,kBAAkB,IAAI,aAAa;AAAA,MAC5D,OAAM,MAAM,kDAAkD;AACpE;AAcO,SAAS,eAAe,OAAyC;AACvE,QAAM,eAAe;AACrB,MAAI,WAAW,mBAAmB,IAAI,GAAG;AACxC,YAAQ,KAAK,mCAAmC,KAAK;AAAA,EACtD;AACD;AAGO,SAAS,kBACf,SACA,OACC;AACD,UAAQ,kBAAkB,MAAM,SAAS;AACzC,MAAI,WAAW,mBAAmB,IAAI,GAAG;AACxC,UAAM,cAAc,6BAA6B,IAAI;AACrD,gBAAY,IAAI,UAAU,YAAY,IAAI,OAAO,KAAK,KAAK,CAAC;AAC5D,YAAQ,KAAK,wCAAwC,SAAS,KAAK;AAAA,EACpE;AACD;AAGO,SAAS,sBACf,SACA,OACC;AACD,MAAI,CAAC,QAAQ,kBAAkB,MAAM,SAAS,GAAG;AAChD;AAAA,EACD;AAEA,UAAQ,sBAAsB,MAAM,SAAS;AAC7C,MAAI,WAAW,mBAAmB,IAAI,GAAG;AACxC,UAAM,cAAc,6BAA6B,IAAI;AACrD,QAAI,YAAY,IAAI,OAAO,MAAM,GAAG;AACnC,kBAAY,OAAO,OAAO;AAAA,IAC3B,WAAW,YAAY,IAAI,OAAO,GAAG;AACpC,kBAAY,IAAI,SAAS,YAAY,IAAI,OAAO,IAAK,CAAC;AAAA,IACvD,OAAO;AACN,cAAQ,KAAK,yBAAyB;AAAA,IACvC;AACA,YAAQ,KAAK,4CAA4C,SAAS,KAAK;AAAA,EACxE;AACD;AAUO,MAAM,uBAAuB,CAAC,MAAW,EAAE,gBAAgB;AAG3D,MAAM,mBAAmB,CAC/B,KACA,UACA,UACI;AACJ,MAAI,CAAC,IAAK;AACV,MAAI,MAAM,YAAY,UAAU,OAAO,KAAK,CAAC;AAC9C;AAGO,SAAS,yBAAyB,IAAoB,yBAAyB,MAAM;AAC3F,MAAI,CAAC,GAAI,QAAO;AAEhB,QAAM,UAAU,GAAG,QAAQ,YAAY;AACvC,SACE,GAAmB,qBACpB,YAAY,WACZ,YAAY,cACX,0BAA0B,YAAY,YACtC,0BAA0B,YAAY,YACvC,GAAG,UAAU,SAAS,oBAAoB;AAE5C;AAGO,SAAS,+BAA+B,yBAAyB,MAAM;
|
|
4
|
+
"sourcesContent": ["/*\nThis is used to facilitate double clicking and pointer capture on elements.\n\nThe events in this file are possibly set on individual SVG elements, \nsuch as handles or corner handles, rather than on HTML elements or \nSVGSVGElements. Raw SVG elements do not support pointerCapture in\nmost cases, meaning that in order for pointer capture to work, we \nneed to crawl up the DOM tree to find the nearest HTML element. Then,\nin order for that element to also call the `onPointerUp` event from\nthis file, we need to manually set that event on that element and\nlater remove it when the pointerup occurs. This is a potential leak\nif the user clicks on a handle but the pointerup does not fire for\nwhatever reason.\n*/\n\nimport { debugFlags, pointerCaptureTrackingObject } from './debug-flags'\n\n/** @public */\nexport function loopToHtmlElement(elm: Element): HTMLElement {\n\tif (elm.nodeType === Node.ELEMENT_NODE) return elm as HTMLElement\n\tif (elm.parentElement) return loopToHtmlElement(elm.parentElement)\n\telse throw Error('Could not find a parent element of an HTML type!')\n}\n\n/**\n * This function calls `event.preventDefault()` for you. Why is that useful?\n *\n * Because if you enable `window.preventDefaultLogging = true` it'll log out a message when it\n * happens. Because we use console.warn rather than (log) you'll get a stack trace in the inspector\n * telling you exactly where it happened. This is important because `e.preventDefault()` is the\n * source of many bugs, but unfortunately it can't be avoided because it also stops a lot of default\n * behaviour which doesn't make sense in our UI\n *\n * @param event - To prevent default on\n * @public\n */\nexport function preventDefault(event: React.BaseSyntheticEvent | Event) {\n\tevent.preventDefault()\n\tif (debugFlags.logPreventDefaults.get()) {\n\t\tconsole.warn('preventDefault called on event:', event)\n\t}\n}\n\n/** @public */\nexport function setPointerCapture(\n\telement: Element,\n\tevent: React.PointerEvent<Element> | PointerEvent\n) {\n\telement.setPointerCapture(event.pointerId)\n\tif (debugFlags.logPointerCaptures.get()) {\n\t\tconst trackingObj = pointerCaptureTrackingObject.get()\n\t\ttrackingObj.set(element, (trackingObj.get(element) ?? 0) + 1)\n\t\tconsole.warn('setPointerCapture called on element:', element, event)\n\t}\n}\n\n/** @public */\nexport function releasePointerCapture(\n\telement: Element,\n\tevent: React.PointerEvent<Element> | PointerEvent\n) {\n\tif (!element.hasPointerCapture(event.pointerId)) {\n\t\treturn\n\t}\n\n\telement.releasePointerCapture(event.pointerId)\n\tif (debugFlags.logPointerCaptures.get()) {\n\t\tconst trackingObj = pointerCaptureTrackingObject.get()\n\t\tif (trackingObj.get(element) === 1) {\n\t\t\ttrackingObj.delete(element)\n\t\t} else if (trackingObj.has(element)) {\n\t\t\ttrackingObj.set(element, trackingObj.get(element)! - 1)\n\t\t} else {\n\t\t\tconsole.warn('Release without capture')\n\t\t}\n\t\tconsole.warn('releasePointerCapture called on element:', element, event)\n\t}\n}\n\n/**\n * Calls `event.stopPropagation()`.\n *\n * @deprecated Use {@link Editor.markEventAsHandled} instead, or manually call `event.stopPropagation()` if\n * that's what you really want.\n *\n * @public\n */\nexport const stopEventPropagation = (e: any) => e.stopPropagation()\n\n/** @internal */\nexport const setStyleProperty = (\n\telm: HTMLElement | null,\n\tproperty: string,\n\tvalue: string | number\n) => {\n\tif (!elm) return\n\telm.style.setProperty(property, String(value))\n}\n\n/** @internal */\nexport function elementShouldCaptureKeys(el: Element | null, includeButtonsAndMenus = true) {\n\tif (!el) return false\n\n\tconst tagName = el.tagName.toLowerCase()\n\treturn (\n\t\t(el as HTMLElement).isContentEditable ||\n\t\ttagName === 'input' ||\n\t\ttagName === 'textarea' ||\n\t\t(includeButtonsAndMenus && tagName === 'select') ||\n\t\t(includeButtonsAndMenus && tagName === 'button') ||\n\t\tel.classList.contains('tlui-slider__thumb')\n\t)\n}\n\n/**\n * Returns the global `document`. Use this instead of bare `document` to satisfy lint rules.\n *\n * When you have a DOM node or editor instance, prefer the scoped versions instead:\n * - `getOwnerDocument(node)` \u2013 the document that owns a specific DOM node\n * - `editor.getContainerDocument()` \u2013 the document where the editor is mounted\n *\n * @internal\n */\nexport function getGlobalDocument(): Document {\n\t// eslint-disable-next-line no-restricted-globals\n\tif (typeof document !== 'undefined') return document\n\treturn globalThis.document\n}\n\n/**\n * Returns the global `window`. Use this instead of bare `window` to satisfy lint rules.\n *\n * When you have a DOM node or editor instance, prefer the scoped versions instead:\n * - `getOwnerWindow(node)` \u2013 the window that owns a specific DOM node\n * - `editor.getContainerWindow()` \u2013 the window where the editor is mounted\n *\n * @internal\n */\nexport function getGlobalWindow(): Window & typeof globalThis {\n\tif (typeof window !== 'undefined') return window as Window & typeof globalThis\n\treturn globalThis as Window & typeof globalThis\n}\n\n/** @internal */\nexport function activeElementShouldCaptureKeys(includeButtonsAndMenus = true, doc?: Document) {\n\treturn elementShouldCaptureKeys(\n\t\t(doc ?? getGlobalDocument()).activeElement,\n\t\tincludeButtonsAndMenus\n\t)\n}\n"],
|
|
5
|
+
"mappings": "AAeA,SAAS,YAAY,oCAAoC;AAGlD,SAAS,kBAAkB,KAA2B;AAC5D,MAAI,IAAI,aAAa,KAAK,aAAc,QAAO;AAC/C,MAAI,IAAI,cAAe,QAAO,kBAAkB,IAAI,aAAa;AAAA,MAC5D,OAAM,MAAM,kDAAkD;AACpE;AAcO,SAAS,eAAe,OAAyC;AACvE,QAAM,eAAe;AACrB,MAAI,WAAW,mBAAmB,IAAI,GAAG;AACxC,YAAQ,KAAK,mCAAmC,KAAK;AAAA,EACtD;AACD;AAGO,SAAS,kBACf,SACA,OACC;AACD,UAAQ,kBAAkB,MAAM,SAAS;AACzC,MAAI,WAAW,mBAAmB,IAAI,GAAG;AACxC,UAAM,cAAc,6BAA6B,IAAI;AACrD,gBAAY,IAAI,UAAU,YAAY,IAAI,OAAO,KAAK,KAAK,CAAC;AAC5D,YAAQ,KAAK,wCAAwC,SAAS,KAAK;AAAA,EACpE;AACD;AAGO,SAAS,sBACf,SACA,OACC;AACD,MAAI,CAAC,QAAQ,kBAAkB,MAAM,SAAS,GAAG;AAChD;AAAA,EACD;AAEA,UAAQ,sBAAsB,MAAM,SAAS;AAC7C,MAAI,WAAW,mBAAmB,IAAI,GAAG;AACxC,UAAM,cAAc,6BAA6B,IAAI;AACrD,QAAI,YAAY,IAAI,OAAO,MAAM,GAAG;AACnC,kBAAY,OAAO,OAAO;AAAA,IAC3B,WAAW,YAAY,IAAI,OAAO,GAAG;AACpC,kBAAY,IAAI,SAAS,YAAY,IAAI,OAAO,IAAK,CAAC;AAAA,IACvD,OAAO;AACN,cAAQ,KAAK,yBAAyB;AAAA,IACvC;AACA,YAAQ,KAAK,4CAA4C,SAAS,KAAK;AAAA,EACxE;AACD;AAUO,MAAM,uBAAuB,CAAC,MAAW,EAAE,gBAAgB;AAG3D,MAAM,mBAAmB,CAC/B,KACA,UACA,UACI;AACJ,MAAI,CAAC,IAAK;AACV,MAAI,MAAM,YAAY,UAAU,OAAO,KAAK,CAAC;AAC9C;AAGO,SAAS,yBAAyB,IAAoB,yBAAyB,MAAM;AAC3F,MAAI,CAAC,GAAI,QAAO;AAEhB,QAAM,UAAU,GAAG,QAAQ,YAAY;AACvC,SACE,GAAmB,qBACpB,YAAY,WACZ,YAAY,cACX,0BAA0B,YAAY,YACtC,0BAA0B,YAAY,YACvC,GAAG,UAAU,SAAS,oBAAoB;AAE5C;AAWO,SAAS,oBAA8B;AAE7C,MAAI,OAAO,aAAa,YAAa,QAAO;AAC5C,SAAO,WAAW;AACnB;AAWO,SAAS,kBAA8C;AAC7D,MAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,SAAO;AACR;AAGO,SAAS,+BAA+B,yBAAyB,MAAM,KAAgB;AAC7F,SAAO;AAAA,KACL,OAAO,kBAAkB,GAAG;AAAA,IAC7B;AAAA,EACD;AACD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist-esm/version.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
const version = "4.
|
|
1
|
+
const version = "4.6.0-canary.0bcbb3ed5bcb";
|
|
2
2
|
const publishDates = {
|
|
3
3
|
major: "2025-09-18T14:39:22.803Z",
|
|
4
|
-
minor: "2026-03-
|
|
5
|
-
patch: "2026-03-
|
|
4
|
+
minor: "2026-03-18T17:26:38.671Z",
|
|
5
|
+
patch: "2026-03-18T17:26:38.671Z"
|
|
6
6
|
};
|
|
7
7
|
export {
|
|
8
8
|
publishDates,
|
package/dist-esm/version.mjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/version.ts"],
|
|
4
|
-
"sourcesContent": ["// This file is automatically generated by internal/scripts/refresh-assets.ts.\n// Do not edit manually. Or do, I'm a comment, not a cop.\n\nexport const version = '4.
|
|
4
|
+
"sourcesContent": ["// This file is automatically generated by internal/scripts/refresh-assets.ts.\n// Do not edit manually. Or do, I'm a comment, not a cop.\n\nexport const version = '4.6.0-canary.0bcbb3ed5bcb'\nexport const publishDates = {\n\tmajor: '2025-09-18T14:39:22.803Z',\n\tminor: '2026-03-18T17:26:38.671Z',\n\tpatch: '2026-03-18T17:26:38.671Z',\n}\n"],
|
|
5
5
|
"mappings": "AAGO,MAAM,UAAU;AAChB,MAAM,eAAe;AAAA,EAC3B,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AACR;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tldraw/editor",
|
|
3
3
|
"description": "tldraw infinite canvas SDK (editor).",
|
|
4
|
-
"version": "4.
|
|
4
|
+
"version": "4.6.0-canary.0bcbb3ed5bcb",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "tldraw Inc.",
|
|
7
7
|
"email": "hello@tldraw.com"
|
|
@@ -49,12 +49,12 @@
|
|
|
49
49
|
"@tiptap/core": "^3.12.1",
|
|
50
50
|
"@tiptap/pm": "^3.12.1",
|
|
51
51
|
"@tiptap/react": "^3.12.1",
|
|
52
|
-
"@tldraw/state": "4.
|
|
53
|
-
"@tldraw/state-react": "4.
|
|
54
|
-
"@tldraw/store": "4.
|
|
55
|
-
"@tldraw/tlschema": "4.
|
|
56
|
-
"@tldraw/utils": "4.
|
|
57
|
-
"@tldraw/validate": "4.
|
|
52
|
+
"@tldraw/state": "4.6.0-canary.0bcbb3ed5bcb",
|
|
53
|
+
"@tldraw/state-react": "4.6.0-canary.0bcbb3ed5bcb",
|
|
54
|
+
"@tldraw/store": "4.6.0-canary.0bcbb3ed5bcb",
|
|
55
|
+
"@tldraw/tlschema": "4.6.0-canary.0bcbb3ed5bcb",
|
|
56
|
+
"@tldraw/utils": "4.6.0-canary.0bcbb3ed5bcb",
|
|
57
|
+
"@tldraw/validate": "4.6.0-canary.0bcbb3ed5bcb",
|
|
58
58
|
"@use-gesture/react": "^10.3.1",
|
|
59
59
|
"classnames": "^2.5.1",
|
|
60
60
|
"eventemitter3": "^4.0.7",
|
package/src/index.ts
CHANGED
|
@@ -282,6 +282,7 @@ export {
|
|
|
282
282
|
type SvgExportContext,
|
|
283
283
|
type SvgExportDef,
|
|
284
284
|
} from './lib/editor/types/SvgExportContext'
|
|
285
|
+
export { getOwnerDocument, getOwnerWindow } from './lib/exports/domUtils'
|
|
285
286
|
export { getSvgAsImage } from './lib/exports/getSvgAsImage'
|
|
286
287
|
export { tlenv, tlenvReactive } from './lib/globals/environment'
|
|
287
288
|
export { tlmenus } from './lib/globals/menus'
|
|
@@ -448,6 +449,8 @@ export {
|
|
|
448
449
|
export {
|
|
449
450
|
activeElementShouldCaptureKeys,
|
|
450
451
|
elementShouldCaptureKeys,
|
|
452
|
+
getGlobalDocument,
|
|
453
|
+
getGlobalWindow,
|
|
451
454
|
loopToHtmlElement,
|
|
452
455
|
preventDefault,
|
|
453
456
|
releasePointerCapture,
|
package/src/lib/TldrawEditor.tsx
CHANGED
|
@@ -42,6 +42,7 @@ import { LicenseProvider } from './license/LicenseProvider'
|
|
|
42
42
|
import { Watermark } from './license/Watermark'
|
|
43
43
|
import { TldrawOptions } from './options'
|
|
44
44
|
import { TLDeepLinkOptions } from './utils/deepLinks'
|
|
45
|
+
import { getGlobalDocument } from './utils/dom'
|
|
45
46
|
import { TLTextOptions } from './utils/richText'
|
|
46
47
|
import { TLStoreWithStatus } from './utils/sync/StoreWithStatus'
|
|
47
48
|
|
|
@@ -405,7 +406,7 @@ const TldrawEditorWithLoadingStore = memo(function TldrawEditorBeforeLoading({
|
|
|
405
406
|
return <TldrawEditorWithReadyStore {...rest} store={store.store} user={user} />
|
|
406
407
|
})
|
|
407
408
|
|
|
408
|
-
const noAutoFocus = () =>
|
|
409
|
+
const noAutoFocus = () => getGlobalDocument().location.search.includes('tldraw_preserve_focus')
|
|
409
410
|
|
|
410
411
|
function TldrawEditorWithReadyStore({
|
|
411
412
|
onMount,
|
|
@@ -572,12 +573,13 @@ function TldrawEditorWithReadyStore({
|
|
|
572
573
|
}
|
|
573
574
|
|
|
574
575
|
if (autoFocus && noAutoFocus()) {
|
|
575
|
-
editor.getContainer()
|
|
576
|
-
|
|
576
|
+
const container = editor.getContainer()
|
|
577
|
+
container.addEventListener('pointerdown', handleFocusOnPointerDown)
|
|
578
|
+
container.ownerDocument.body.addEventListener('pointerdown', handleBlurOnPointerDown)
|
|
577
579
|
|
|
578
580
|
return () => {
|
|
579
|
-
|
|
580
|
-
|
|
581
|
+
container.removeEventListener('pointerdown', handleFocusOnPointerDown)
|
|
582
|
+
container.ownerDocument.body.removeEventListener('pointerdown', handleBlurOnPointerDown)
|
|
581
583
|
}
|
|
582
584
|
}
|
|
583
585
|
},
|
|
@@ -5,6 +5,7 @@ import { dedupe } from '@tldraw/utils'
|
|
|
5
5
|
import { memo, useEffect, useRef } from 'react'
|
|
6
6
|
import { Editor } from '../../editor/Editor'
|
|
7
7
|
import { TLIndicatorPath } from '../../editor/shapes/ShapeUtil'
|
|
8
|
+
import { getComputedStyle } from '../../exports/domUtils'
|
|
8
9
|
import { useEditor } from '../../hooks/useEditor'
|
|
9
10
|
import { useIsDarkMode } from '../../hooks/useIsDarkMode'
|
|
10
11
|
import { useActivePeerIds$ } from '../../hooks/usePeerIds'
|
|
@@ -223,7 +224,7 @@ export const CanvasShapeIndicators = memo(function CanvasShapeIndicators() {
|
|
|
223
224
|
$renderData.get()
|
|
224
225
|
|
|
225
226
|
const { w, h } = editor.getViewportScreenBounds()
|
|
226
|
-
const dpr =
|
|
227
|
+
const dpr = editor.getInstanceState().devicePixelRatio
|
|
227
228
|
const { x: cx, y: cy, z: zoom } = editor.getCamera()
|
|
228
229
|
|
|
229
230
|
const canvasWidth = Math.ceil(w * dpr)
|
|
@@ -427,7 +427,7 @@ function ReflowIfNeeded() {
|
|
|
427
427
|
if (culledShapesRef.current === culledShapes) return
|
|
428
428
|
|
|
429
429
|
culledShapesRef.current = culledShapes
|
|
430
|
-
const canvas =
|
|
430
|
+
const canvas = editor.getContainerDocument().getElementsByClassName('tl-canvas')
|
|
431
431
|
if (canvas.length === 0) return
|
|
432
432
|
// This causes a reflow
|
|
433
433
|
// https://gist.github.com/paulirish/5d52fb081b3570c81e3a
|
|
@@ -3,8 +3,10 @@ import { noop } from '@tldraw/utils'
|
|
|
3
3
|
import classNames from 'classnames'
|
|
4
4
|
import { ComponentType, useEffect, useLayoutEffect, useRef, useState } from 'react'
|
|
5
5
|
import { Editor } from '../../editor/Editor'
|
|
6
|
+
import { getOwnerDocument } from '../../exports/domUtils'
|
|
6
7
|
import { useEditorComponents } from '../../hooks/EditorComponentsContext'
|
|
7
8
|
import { EditorProvider } from '../../hooks/useEditor'
|
|
9
|
+
import { getGlobalWindow } from '../../utils/dom'
|
|
8
10
|
import { hardResetEditor, refreshPage } from '../../utils/runtime'
|
|
9
11
|
import { ErrorBoundary } from '../ErrorBoundary'
|
|
10
12
|
|
|
@@ -74,8 +76,8 @@ export const DefaultErrorFallback: TLErrorFallbackComponent = ({ error, editor }
|
|
|
74
76
|
|
|
75
77
|
// if we can't find a theme class from the app or from a parent, we have
|
|
76
78
|
// to fall back on using a media query:
|
|
77
|
-
if (typeof window !== 'undefined' &&
|
|
78
|
-
setIsDarkMode(
|
|
79
|
+
if (typeof window !== 'undefined' && getGlobalWindow().matchMedia) {
|
|
80
|
+
setIsDarkMode(getGlobalWindow().matchMedia('(prefers-color-scheme: dark)').matches)
|
|
79
81
|
}
|
|
80
82
|
}, [isDarkModeFromApp])
|
|
81
83
|
|
|
@@ -89,12 +91,13 @@ export const DefaultErrorFallback: TLErrorFallbackComponent = ({ error, editor }
|
|
|
89
91
|
}, [didCopy, editor])
|
|
90
92
|
|
|
91
93
|
const copyError = () => {
|
|
92
|
-
const
|
|
94
|
+
const doc = getOwnerDocument(containerRef.current)
|
|
95
|
+
const textarea = doc.createElement('textarea')
|
|
93
96
|
textarea.value = errorStack ?? errorMessage
|
|
94
|
-
|
|
97
|
+
doc.body.appendChild(textarea)
|
|
95
98
|
textarea.select()
|
|
96
99
|
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
97
|
-
|
|
100
|
+
doc.execCommand('copy')
|
|
98
101
|
textarea.remove()
|
|
99
102
|
setDidCopy(true)
|
|
100
103
|
}
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
} from '@tldraw/utils'
|
|
22
22
|
import { T } from '@tldraw/validate'
|
|
23
23
|
import { tlenv } from '../globals/environment'
|
|
24
|
+
import { getGlobalDocument, getGlobalWindow } from '../utils/dom'
|
|
24
25
|
|
|
25
26
|
const tabIdKey = 'TLDRAW_TAB_ID_v2' as const
|
|
26
27
|
|
|
@@ -38,10 +39,10 @@ function iOS() {
|
|
|
38
39
|
return (
|
|
39
40
|
['iPad Simulator', 'iPhone Simulator', 'iPod Simulator', 'iPad', 'iPhone', 'iPod'].includes(
|
|
40
41
|
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
41
|
-
|
|
42
|
+
getGlobalWindow().navigator.platform
|
|
42
43
|
) ||
|
|
43
44
|
// iPad on iOS 13 detection
|
|
44
|
-
(tlenv.isDarwin && 'ontouchend' in
|
|
45
|
+
(tlenv.isDarwin && 'ontouchend' in getGlobalDocument())
|
|
45
46
|
)
|
|
46
47
|
}
|
|
47
48
|
|
|
@@ -69,9 +70,11 @@ if (window) {
|
|
|
69
70
|
}
|
|
70
71
|
}
|
|
71
72
|
|
|
72
|
-
window
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
if (typeof window !== 'undefined') {
|
|
74
|
+
getGlobalWindow().addEventListener('beforeunload', () => {
|
|
75
|
+
setInSessionStorage(tabIdKey, TAB_ID)
|
|
76
|
+
})
|
|
77
|
+
}
|
|
75
78
|
|
|
76
79
|
const Versions = {
|
|
77
80
|
Initial: 0,
|
|
@@ -2,6 +2,7 @@ import { atom } from '@tldraw/state'
|
|
|
2
2
|
import { getDefaultTranslationLocale } from '@tldraw/tlschema'
|
|
3
3
|
import { getFromLocalStorage, setInLocalStorage, structuredClone, uniqueId } from '@tldraw/utils'
|
|
4
4
|
import { T } from '@tldraw/validate'
|
|
5
|
+
import { getGlobalWindow } from '../utils/dom'
|
|
5
6
|
|
|
6
7
|
const USER_DATA_KEY = 'TLDRAW_USER_DATA_v3'
|
|
7
8
|
|
|
@@ -154,8 +155,8 @@ function getRandomColor() {
|
|
|
154
155
|
|
|
155
156
|
/** @internal */
|
|
156
157
|
export function userPrefersReducedMotion() {
|
|
157
|
-
if (typeof window !== 'undefined' &&
|
|
158
|
-
return
|
|
158
|
+
if (typeof window !== 'undefined' && getGlobalWindow().matchMedia) {
|
|
159
|
+
return getGlobalWindow().matchMedia?.('(prefers-reduced-motion: reduce)')?.matches ?? false
|
|
159
160
|
}
|
|
160
161
|
|
|
161
162
|
return false
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Signal } from '@tldraw/state'
|
|
2
2
|
import { HistoryEntry, MigrationSequence, SerializedStore, Store, StoreSchema } from '@tldraw/store'
|
|
3
3
|
import {
|
|
4
|
+
CustomRecordInfo,
|
|
4
5
|
SchemaPropsInfo,
|
|
5
6
|
TLAssetStore,
|
|
6
7
|
TLRecord,
|
|
@@ -42,6 +43,7 @@ export type TLStoreSchemaOptions =
|
|
|
42
43
|
shapeUtils?: readonly TLAnyShapeUtilConstructor[]
|
|
43
44
|
migrations?: readonly MigrationSequence[]
|
|
44
45
|
bindingUtils?: readonly TLAnyBindingUtilConstructor[]
|
|
46
|
+
records?: Record<string, CustomRecordInfo>
|
|
45
47
|
}
|
|
46
48
|
|
|
47
49
|
/** @public */
|
|
@@ -88,6 +90,7 @@ export function createTLSchemaFromUtils(
|
|
|
88
90
|
'bindingUtils' in opts && opts.bindingUtils
|
|
89
91
|
? utilsToMap(checkBindings(opts.bindingUtils))
|
|
90
92
|
: undefined,
|
|
93
|
+
records: 'records' in opts ? opts.records : undefined,
|
|
91
94
|
migrations: 'migrations' in opts ? opts.migrations : undefined,
|
|
92
95
|
})
|
|
93
96
|
}
|
package/src/lib/editor/Editor.ts
CHANGED
|
@@ -108,8 +108,9 @@ import {
|
|
|
108
108
|
RIGHT_MOUSE_BUTTON,
|
|
109
109
|
STYLUS_ERASER_BUTTON,
|
|
110
110
|
} from '../constants'
|
|
111
|
+
import { getOwnerWindow } from '../exports/domUtils'
|
|
111
112
|
import { exportToSvg } from '../exports/exportToSvg'
|
|
112
|
-
import {
|
|
113
|
+
import { getSvgAsImageWithOptions, trimSvgToContent } from '../exports/getSvgAsImage'
|
|
113
114
|
import { tlmenus } from '../globals/menus'
|
|
114
115
|
import { tltime } from '../globals/time'
|
|
115
116
|
import { TldrawOptions, defaultTldrawOptions } from '../options'
|
|
@@ -999,6 +1000,26 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
999
1000
|
*/
|
|
1000
1001
|
getContainer: () => HTMLElement
|
|
1001
1002
|
|
|
1003
|
+
/**
|
|
1004
|
+
* The document that the editor's container element belongs to.
|
|
1005
|
+
* Use this instead of the global `document` to support cross-window embedding.
|
|
1006
|
+
*
|
|
1007
|
+
* @internal
|
|
1008
|
+
*/
|
|
1009
|
+
getContainerDocument(): Document {
|
|
1010
|
+
return this.getContainer().ownerDocument
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
/**
|
|
1014
|
+
* The window that the editor's container element belongs to.
|
|
1015
|
+
* Use this instead of the global `window` to support cross-window embedding.
|
|
1016
|
+
*
|
|
1017
|
+
* @internal
|
|
1018
|
+
*/
|
|
1019
|
+
getContainerWindow(): Window & typeof globalThis {
|
|
1020
|
+
return getOwnerWindow(this.getContainer())
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1002
1023
|
/**
|
|
1003
1024
|
* Dispose the editor.
|
|
1004
1025
|
*
|
|
@@ -3774,13 +3795,14 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
3774
3795
|
screenBounds.height = Math.max(screenBounds.height, 1)
|
|
3775
3796
|
}
|
|
3776
3797
|
|
|
3798
|
+
const doc = this.getContainerDocument()
|
|
3777
3799
|
const insets = [
|
|
3778
3800
|
// top
|
|
3779
3801
|
screenBounds.minY !== 0,
|
|
3780
3802
|
// right
|
|
3781
|
-
!approximately(
|
|
3803
|
+
!approximately(doc.body.scrollWidth, screenBounds.maxX, 1),
|
|
3782
3804
|
// bottom
|
|
3783
|
-
!approximately(
|
|
3805
|
+
!approximately(doc.body.scrollHeight, screenBounds.maxY, 1),
|
|
3784
3806
|
// left
|
|
3785
3807
|
screenBounds.minX !== 0,
|
|
3786
3808
|
]
|
|
@@ -9593,6 +9615,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
9593
9615
|
svg: serializer.serializeToString(result.svg),
|
|
9594
9616
|
width: result.width,
|
|
9595
9617
|
height: result.height,
|
|
9618
|
+
trimPadding: result.trimPadding,
|
|
9596
9619
|
}
|
|
9597
9620
|
}
|
|
9598
9621
|
|
|
@@ -9616,30 +9639,45 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
9616
9639
|
if (!result) throw new Error('Could not create SVG')
|
|
9617
9640
|
|
|
9618
9641
|
switch (withDefaults.format) {
|
|
9619
|
-
case 'svg':
|
|
9642
|
+
case 'svg': {
|
|
9643
|
+
let svg = result.svg
|
|
9644
|
+
let w = result.width
|
|
9645
|
+
let h = result.height
|
|
9646
|
+
if (result.trimPadding > 0) {
|
|
9647
|
+
const trimmed = await trimSvgToContent(svg, {
|
|
9648
|
+
width: w,
|
|
9649
|
+
height: h,
|
|
9650
|
+
trimPadding: result.trimPadding,
|
|
9651
|
+
scale: withDefaults.scale,
|
|
9652
|
+
})
|
|
9653
|
+
if (trimmed) {
|
|
9654
|
+
svg = trimmed.svg
|
|
9655
|
+
w = trimmed.width
|
|
9656
|
+
h = trimmed.height
|
|
9657
|
+
}
|
|
9658
|
+
}
|
|
9620
9659
|
return {
|
|
9621
|
-
blob: new Blob([
|
|
9622
|
-
width:
|
|
9623
|
-
height:
|
|
9660
|
+
blob: new Blob([svg], { type: 'image/svg+xml' }),
|
|
9661
|
+
width: w,
|
|
9662
|
+
height: h,
|
|
9624
9663
|
}
|
|
9664
|
+
}
|
|
9625
9665
|
case 'jpeg':
|
|
9626
9666
|
case 'png':
|
|
9627
9667
|
case 'webp': {
|
|
9628
|
-
const
|
|
9668
|
+
const imageResult = await getSvgAsImageWithOptions(result.svg, {
|
|
9629
9669
|
type: withDefaults.format,
|
|
9630
9670
|
quality: withDefaults.quality,
|
|
9631
9671
|
pixelRatio: withDefaults.pixelRatio,
|
|
9632
9672
|
width: result.width,
|
|
9633
9673
|
height: result.height,
|
|
9674
|
+
trimPadding: result.trimPadding,
|
|
9675
|
+
scale: withDefaults.scale,
|
|
9634
9676
|
})
|
|
9635
|
-
if (!
|
|
9677
|
+
if (!imageResult) {
|
|
9636
9678
|
throw new Error('Could not construct image.')
|
|
9637
9679
|
}
|
|
9638
|
-
return
|
|
9639
|
-
blob,
|
|
9640
|
-
width: result.width,
|
|
9641
|
-
height: result.height,
|
|
9642
|
-
}
|
|
9680
|
+
return imageResult
|
|
9643
9681
|
}
|
|
9644
9682
|
default: {
|
|
9645
9683
|
exhaustiveSwitchError(withDefaults.format)
|
|
@@ -10078,7 +10116,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
10078
10116
|
to: opts?.getTarget?.(this),
|
|
10079
10117
|
})
|
|
10080
10118
|
|
|
10081
|
-
window.history.replaceState({},
|
|
10119
|
+
window.history.replaceState({}, this.getContainerDocument().title, url.toString())
|
|
10082
10120
|
})
|
|
10083
10121
|
|
|
10084
10122
|
const scheduleEffect = debounce((execute: () => void) => execute(), opts?.debounceMs ?? 500)
|
|
@@ -36,6 +36,12 @@ describe('FocusManager', () => {
|
|
|
36
36
|
// Create mock dispose function
|
|
37
37
|
mockDispose = vi.fn()
|
|
38
38
|
|
|
39
|
+
// Mock document.body event listeners
|
|
40
|
+
originalAddEventListener = document.body.addEventListener
|
|
41
|
+
originalRemoveEventListener = document.body.removeEventListener
|
|
42
|
+
document.body.addEventListener = vi.fn()
|
|
43
|
+
document.body.removeEventListener = vi.fn()
|
|
44
|
+
|
|
39
45
|
// Mock editor
|
|
40
46
|
editor = {
|
|
41
47
|
sideEffects: {
|
|
@@ -44,16 +50,11 @@ describe('FocusManager', () => {
|
|
|
44
50
|
getInstanceState: vi.fn(() => ({ isFocused: false })),
|
|
45
51
|
updateInstanceState: vi.fn(),
|
|
46
52
|
getContainer: vi.fn(() => mockContainer),
|
|
53
|
+
getContainerDocument: vi.fn(() => document),
|
|
47
54
|
isIn: vi.fn(() => false),
|
|
48
55
|
getSelectedShapeIds: vi.fn(() => []),
|
|
49
56
|
complete: vi.fn(),
|
|
50
57
|
} as any
|
|
51
|
-
|
|
52
|
-
// Mock document.body event listeners
|
|
53
|
-
originalAddEventListener = document.body.addEventListener
|
|
54
|
-
originalRemoveEventListener = document.body.removeEventListener
|
|
55
|
-
document.body.addEventListener = vi.fn()
|
|
56
|
-
document.body.removeEventListener = vi.fn()
|
|
57
58
|
})
|
|
58
59
|
|
|
59
60
|
afterEach(() => {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { bind } from '@tldraw/utils'
|
|
1
2
|
import type { Editor } from '../../Editor'
|
|
2
3
|
|
|
3
4
|
/**
|
|
@@ -31,8 +32,9 @@ export class FocusManager {
|
|
|
31
32
|
}
|
|
32
33
|
this.updateContainerClass()
|
|
33
34
|
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
const body = editor.getContainerDocument().body
|
|
36
|
+
body.addEventListener('keydown', this.handleKeyDown)
|
|
37
|
+
body.addEventListener('mousedown', this.handleMouseDown)
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
/**
|
|
@@ -56,9 +58,9 @@ export class FocusManager {
|
|
|
56
58
|
container.classList.add('tl-container__no-focus-ring')
|
|
57
59
|
}
|
|
58
60
|
|
|
59
|
-
private handleKeyDown(keyEvent: KeyboardEvent) {
|
|
61
|
+
@bind private handleKeyDown(keyEvent: KeyboardEvent) {
|
|
60
62
|
const container = this.editor.getContainer()
|
|
61
|
-
const activeEl =
|
|
63
|
+
const activeEl = container.ownerDocument.activeElement
|
|
62
64
|
// Edit mode should remove the focus ring, however if the active element's
|
|
63
65
|
// parent is the contextual toolbar, then allow it.
|
|
64
66
|
if (this.editor.isIn('select.editing_shape') && !activeEl?.closest('.tlui-contextual-toolbar'))
|
|
@@ -69,7 +71,7 @@ export class FocusManager {
|
|
|
69
71
|
}
|
|
70
72
|
}
|
|
71
73
|
|
|
72
|
-
private handleMouseDown() {
|
|
74
|
+
@bind private handleMouseDown() {
|
|
73
75
|
const container = this.editor.getContainer()
|
|
74
76
|
container.classList.add('tl-container__no-focus-ring')
|
|
75
77
|
}
|
|
@@ -84,8 +86,9 @@ export class FocusManager {
|
|
|
84
86
|
}
|
|
85
87
|
|
|
86
88
|
dispose() {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
+
const body = this.editor.getContainerDocument().body
|
|
90
|
+
body.removeEventListener('keydown', this.handleKeyDown)
|
|
91
|
+
body.removeEventListener('mousedown', this.handleMouseDown)
|
|
89
92
|
this.disposeSideEffectListener?.()
|
|
90
93
|
}
|
|
91
94
|
}
|
|
@@ -160,7 +160,7 @@ export class FontManager {
|
|
|
160
160
|
loadingPromise: instance
|
|
161
161
|
.load()
|
|
162
162
|
.then(() => {
|
|
163
|
-
|
|
163
|
+
this.editor.getContainerDocument().fonts.add(instance)
|
|
164
164
|
this.fontStates.update(font, (s) => ({ ...s, state: 'ready' }))
|
|
165
165
|
})
|
|
166
166
|
.catch((err) => {
|
|
@@ -193,7 +193,8 @@ export class FontManager {
|
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
private findOrCreateFontFace(font: TLFontFace) {
|
|
196
|
-
|
|
196
|
+
const fonts = this.editor.getContainerDocument().fonts
|
|
197
|
+
for (const existing of fonts) {
|
|
197
198
|
if (
|
|
198
199
|
existing.family === font.family &&
|
|
199
200
|
objectMapEntries(defaultFontFaceDescriptors).every(
|
|
@@ -210,7 +211,7 @@ export class FontManager {
|
|
|
210
211
|
display: 'swap',
|
|
211
212
|
})
|
|
212
213
|
|
|
213
|
-
|
|
214
|
+
fonts.add(instance)
|
|
214
215
|
|
|
215
216
|
return instance
|
|
216
217
|
}
|
|
@@ -736,6 +736,22 @@ describe('HistoryManager error scenarios and edge cases', () => {
|
|
|
736
736
|
expect(store.get(ids.a)!.value).toBe(originalValue)
|
|
737
737
|
})
|
|
738
738
|
|
|
739
|
+
it('should preserve pending diff when mark is not found', () => {
|
|
740
|
+
manager._mark('real-mark')
|
|
741
|
+
store.update(ids.a, (s) => ({ ...s, value: 1 }))
|
|
742
|
+
|
|
743
|
+
// bail to a mark that doesn't exist
|
|
744
|
+
manager.bailToMark('non-existent-mark')
|
|
745
|
+
|
|
746
|
+
// the pending diff should still be intact
|
|
747
|
+
expect(store.get(ids.a)!.value).toBe(1)
|
|
748
|
+
expect(manager.getNumUndos()).toBeGreaterThan(0)
|
|
749
|
+
|
|
750
|
+
// a subsequent bail to the real mark should still work
|
|
751
|
+
manager.bailToMark('real-mark')
|
|
752
|
+
expect(store.get(ids.a)!.value).toBe(0)
|
|
753
|
+
})
|
|
754
|
+
|
|
739
755
|
it('should find mark correctly when it exists', () => {
|
|
740
756
|
manager._mark('existing-mark')
|
|
741
757
|
store.update(ids.a, (s) => ({ ...s, value: 1 }))
|