@tldraw/editor 4.5.3 → 4.6.0-canary.00a8c03b5687
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/config/createTLUser.js.map +1 -1
- package/dist-cjs/lib/editor/Editor.js +511 -366
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js +25 -64
- package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js +22 -5
- 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/InputsManager/InputsManager.js +71 -112
- package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js +20 -55
- package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js.map +1 -1
- package/dist-cjs/lib/editor/managers/SnapManager/HandleSnaps.js +11 -52
- package/dist-cjs/lib/editor/managers/SnapManager/HandleSnaps.js.map +1 -1
- package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js +19 -56
- package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js.map +1 -1
- 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/TickManager/TickManager.js +16 -55
- package/dist-cjs/lib/editor/managers/TickManager/TickManager.js.map +1 -1
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +60 -70
- 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/ExportDelay.js +12 -53
- package/dist-cjs/lib/exports/ExportDelay.js.map +1 -1
- package/dist-cjs/lib/exports/FontEmbedder.js +23 -65
- 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/Box.js +25 -25
- package/dist-cjs/lib/primitives/Box.js.map +1 -1
- package/dist-cjs/lib/primitives/Vec.js +36 -23
- 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 +10 -1
- 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 +13 -1
- package/dist-cjs/lib/primitives/geometry/Ellipse2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Geometry2d.js +6 -6
- package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +1 -1
- package/dist-cjs/lib/primitives/geometry/Polyline2d.js +52 -13
- 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/SharedStylesMap.js +1 -1
- package/dist-cjs/lib/utils/SharedStylesMap.js.map +1 -1
- 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/lib/utils/sync/TLLocalSyncClient.js +2 -1
- package/dist-cjs/lib/utils/sync/TLLocalSyncClient.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/config/createTLUser.mjs.map +1 -1
- package/dist-esm/lib/editor/Editor.mjs +512 -368
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs +25 -64
- package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs +24 -5
- 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/InputsManager/InputsManager.mjs +71 -112
- package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs +20 -55
- package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs.map +1 -1
- package/dist-esm/lib/editor/managers/SnapManager/HandleSnaps.mjs +11 -52
- package/dist-esm/lib/editor/managers/SnapManager/HandleSnaps.mjs.map +1 -1
- package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs +19 -56
- package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs.map +1 -1
- 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/TickManager/TickManager.mjs +16 -55
- package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs.map +1 -1
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +60 -70
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
- package/dist-esm/lib/exports/ExportDelay.mjs +12 -53
- package/dist-esm/lib/exports/ExportDelay.mjs.map +1 -1
- package/dist-esm/lib/exports/FontEmbedder.mjs +23 -65
- 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/Box.mjs +25 -25
- package/dist-esm/lib/primitives/Box.mjs.map +1 -1
- package/dist-esm/lib/primitives/Vec.mjs +36 -23
- 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 +10 -1
- 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 +14 -2
- package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +6 -6
- package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +1 -1
- package/dist-esm/lib/primitives/geometry/Polyline2d.mjs +52 -13
- 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/SharedStylesMap.mjs +1 -1
- package/dist-esm/lib/utils/SharedStylesMap.mjs.map +1 -1
- 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/lib/utils/sync/TLLocalSyncClient.mjs +2 -1
- package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs.map +2 -2
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/package.json +8 -8
- package/src/index.ts +10 -6
- 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 +9 -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/config/createTLUser.ts +3 -3
- package/src/lib/editor/Editor.ts +53 -15
- package/src/lib/editor/managers/ClickManager/ClickManager.ts +1 -1
- 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/InputsManager/InputsManager.ts +30 -30
- 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/Box.ts +25 -25
- package/src/lib/primitives/Vec.ts +52 -25
- 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 +11 -1
- package/src/lib/primitives/geometry/Edge2d.ts +41 -18
- package/src/lib/primitives/geometry/Ellipse2d.ts +15 -2
- package/src/lib/primitives/geometry/Geometry2d.ts +6 -6
- package/src/lib/primitives/geometry/Polyline2d.ts +61 -13
- 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/SharedStylesMap.ts +1 -1
- package/src/lib/utils/browserCanvasMaxSize.ts +4 -2
- package/src/lib/utils/dom.ts +34 -2
- package/src/lib/utils/sync/TLLocalSyncClient.ts +1 -0
- package/src/version.ts +3 -3
|
@@ -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 }))
|
|
@@ -172,8 +172,8 @@ export class HistoryManager<R extends UnknownRecord> {
|
|
|
172
172
|
}
|
|
173
173
|
|
|
174
174
|
if (!didFindMark && toMark) {
|
|
175
|
-
//
|
|
176
|
-
|
|
175
|
+
// we didn't find the mark we were looking for — restore state and bail
|
|
176
|
+
this.pendingDiff.restore(pendingDiff)
|
|
177
177
|
return this
|
|
178
178
|
}
|
|
179
179
|
|
|
@@ -338,6 +338,11 @@ class PendingDiff<R extends UnknownRecord> {
|
|
|
338
338
|
return diff
|
|
339
339
|
}
|
|
340
340
|
|
|
341
|
+
restore(diff: RecordsDiff<R>) {
|
|
342
|
+
this.diff = diff
|
|
343
|
+
this.isEmptyAtom.set(isRecordsDiffEmpty(diff))
|
|
344
|
+
}
|
|
345
|
+
|
|
341
346
|
isEmpty() {
|
|
342
347
|
return this.isEmptyAtom.get()
|
|
343
348
|
}
|
|
@@ -21,7 +21,7 @@ export class InputsManager {
|
|
|
21
21
|
/**
|
|
22
22
|
* @deprecated Use `getOriginPagePoint()` instead.
|
|
23
23
|
*/
|
|
24
|
-
// eslint-disable-next-line no-
|
|
24
|
+
// eslint-disable-next-line tldraw/no-setter-getter
|
|
25
25
|
get originPagePoint() {
|
|
26
26
|
return this.getOriginPagePoint()
|
|
27
27
|
}
|
|
@@ -36,7 +36,7 @@ export class InputsManager {
|
|
|
36
36
|
/**
|
|
37
37
|
* @deprecated Use `getOriginScreenPoint()` instead.
|
|
38
38
|
*/
|
|
39
|
-
// eslint-disable-next-line no-
|
|
39
|
+
// eslint-disable-next-line tldraw/no-setter-getter
|
|
40
40
|
get originScreenPoint() {
|
|
41
41
|
return this.getOriginScreenPoint()
|
|
42
42
|
}
|
|
@@ -51,7 +51,7 @@ export class InputsManager {
|
|
|
51
51
|
/**
|
|
52
52
|
* @deprecated Use `getPreviousPagePoint()` instead.
|
|
53
53
|
*/
|
|
54
|
-
// eslint-disable-next-line no-
|
|
54
|
+
// eslint-disable-next-line tldraw/no-setter-getter
|
|
55
55
|
get previousPagePoint() {
|
|
56
56
|
return this.getPreviousPagePoint()
|
|
57
57
|
}
|
|
@@ -66,7 +66,7 @@ export class InputsManager {
|
|
|
66
66
|
/**
|
|
67
67
|
* @deprecated Use `getPreviousScreenPoint()` instead.
|
|
68
68
|
*/
|
|
69
|
-
// eslint-disable-next-line no-
|
|
69
|
+
// eslint-disable-next-line tldraw/no-setter-getter
|
|
70
70
|
get previousScreenPoint() {
|
|
71
71
|
return this.getPreviousScreenPoint()
|
|
72
72
|
}
|
|
@@ -81,7 +81,7 @@ export class InputsManager {
|
|
|
81
81
|
/**
|
|
82
82
|
* @deprecated Use `getCurrentPagePoint()` instead.
|
|
83
83
|
*/
|
|
84
|
-
// eslint-disable-next-line no-
|
|
84
|
+
// eslint-disable-next-line tldraw/no-setter-getter
|
|
85
85
|
get currentPagePoint() {
|
|
86
86
|
return this.getCurrentPagePoint()
|
|
87
87
|
}
|
|
@@ -96,7 +96,7 @@ export class InputsManager {
|
|
|
96
96
|
/**
|
|
97
97
|
* @deprecated Use `getCurrentScreenPoint()` instead.
|
|
98
98
|
*/
|
|
99
|
-
// eslint-disable-next-line no-
|
|
99
|
+
// eslint-disable-next-line tldraw/no-setter-getter
|
|
100
100
|
get currentScreenPoint() {
|
|
101
101
|
return this.getCurrentScreenPoint()
|
|
102
102
|
}
|
|
@@ -111,7 +111,7 @@ export class InputsManager {
|
|
|
111
111
|
/**
|
|
112
112
|
* @deprecated Use `getPointerVelocity()` instead.
|
|
113
113
|
*/
|
|
114
|
-
// eslint-disable-next-line no-
|
|
114
|
+
// eslint-disable-next-line tldraw/no-setter-getter
|
|
115
115
|
get pointerVelocity() {
|
|
116
116
|
return this.getPointerVelocity()
|
|
117
117
|
}
|
|
@@ -147,11 +147,11 @@ export class InputsManager {
|
|
|
147
147
|
/**
|
|
148
148
|
* @deprecated Use `getIsPen()` instead.
|
|
149
149
|
*/
|
|
150
|
-
// eslint-disable-next-line no-
|
|
150
|
+
// eslint-disable-next-line tldraw/no-setter-getter
|
|
151
151
|
get isPen() {
|
|
152
152
|
return this.getIsPen()
|
|
153
153
|
}
|
|
154
|
-
// eslint-disable-next-line no-
|
|
154
|
+
// eslint-disable-next-line tldraw/no-setter-getter
|
|
155
155
|
set isPen(isPen: boolean) {
|
|
156
156
|
this.setIsPen(isPen)
|
|
157
157
|
}
|
|
@@ -172,11 +172,11 @@ export class InputsManager {
|
|
|
172
172
|
/**
|
|
173
173
|
* @deprecated Use `getShiftKey()` instead.
|
|
174
174
|
*/
|
|
175
|
-
// eslint-disable-next-line no-
|
|
175
|
+
// eslint-disable-next-line tldraw/no-setter-getter
|
|
176
176
|
get shiftKey() {
|
|
177
177
|
return this.getShiftKey()
|
|
178
178
|
}
|
|
179
|
-
// eslint-disable-next-line no-
|
|
179
|
+
// eslint-disable-next-line tldraw/no-setter-getter
|
|
180
180
|
set shiftKey(shiftKey: boolean) {
|
|
181
181
|
this.setShiftKey(shiftKey)
|
|
182
182
|
}
|
|
@@ -198,11 +198,11 @@ export class InputsManager {
|
|
|
198
198
|
/**
|
|
199
199
|
* @deprecated Use `getMetaKey()` instead.
|
|
200
200
|
*/
|
|
201
|
-
// eslint-disable-next-line no-
|
|
201
|
+
// eslint-disable-next-line tldraw/no-setter-getter
|
|
202
202
|
get metaKey() {
|
|
203
203
|
return this.getMetaKey()
|
|
204
204
|
}
|
|
205
|
-
// eslint-disable-next-line no-
|
|
205
|
+
// eslint-disable-next-line tldraw/no-setter-getter
|
|
206
206
|
set metaKey(metaKey: boolean) {
|
|
207
207
|
this.setMetaKey(metaKey)
|
|
208
208
|
}
|
|
@@ -224,11 +224,11 @@ export class InputsManager {
|
|
|
224
224
|
/**
|
|
225
225
|
* @deprecated Use `getCtrlKey()` instead.
|
|
226
226
|
*/
|
|
227
|
-
// eslint-disable-next-line no-
|
|
227
|
+
// eslint-disable-next-line tldraw/no-setter-getter
|
|
228
228
|
get ctrlKey() {
|
|
229
229
|
return this.getCtrlKey()
|
|
230
230
|
}
|
|
231
|
-
// eslint-disable-next-line no-
|
|
231
|
+
// eslint-disable-next-line tldraw/no-setter-getter
|
|
232
232
|
set ctrlKey(ctrlKey: boolean) {
|
|
233
233
|
this.setCtrlKey(ctrlKey)
|
|
234
234
|
}
|
|
@@ -250,11 +250,11 @@ export class InputsManager {
|
|
|
250
250
|
/**
|
|
251
251
|
* @deprecated Use `getAltKey()` instead.
|
|
252
252
|
*/
|
|
253
|
-
// eslint-disable-next-line no-
|
|
253
|
+
// eslint-disable-next-line tldraw/no-setter-getter
|
|
254
254
|
get altKey() {
|
|
255
255
|
return this.getAltKey()
|
|
256
256
|
}
|
|
257
|
-
// eslint-disable-next-line no-
|
|
257
|
+
// eslint-disable-next-line tldraw/no-setter-getter
|
|
258
258
|
set altKey(altKey: boolean) {
|
|
259
259
|
this.setAltKey(altKey)
|
|
260
260
|
}
|
|
@@ -275,7 +275,7 @@ export class InputsManager {
|
|
|
275
275
|
/**
|
|
276
276
|
* @deprecated Use `getAccelKey()` instead.
|
|
277
277
|
*/
|
|
278
|
-
// eslint-disable-next-line no-
|
|
278
|
+
// eslint-disable-next-line tldraw/no-setter-getter
|
|
279
279
|
get accelKey() {
|
|
280
280
|
return this.getAccelKey()
|
|
281
281
|
}
|
|
@@ -290,11 +290,11 @@ export class InputsManager {
|
|
|
290
290
|
/**
|
|
291
291
|
* Soon to be deprecated, use `getIsDragging()` instead.
|
|
292
292
|
*/
|
|
293
|
-
// eslint-disable-next-line no-
|
|
293
|
+
// eslint-disable-next-line tldraw/no-setter-getter
|
|
294
294
|
get isDragging() {
|
|
295
295
|
return this.getIsDragging()
|
|
296
296
|
}
|
|
297
|
-
// eslint-disable-next-line no-
|
|
297
|
+
// eslint-disable-next-line tldraw/no-setter-getter
|
|
298
298
|
set isDragging(isDragging: boolean) {
|
|
299
299
|
this.setIsDragging(isDragging)
|
|
300
300
|
}
|
|
@@ -315,11 +315,11 @@ export class InputsManager {
|
|
|
315
315
|
/**
|
|
316
316
|
* @deprecated Use `getIsPointing()` instead.
|
|
317
317
|
*/
|
|
318
|
-
// eslint-disable-next-line no-
|
|
318
|
+
// eslint-disable-next-line tldraw/no-setter-getter
|
|
319
319
|
get isPointing() {
|
|
320
320
|
return this.getIsPointing()
|
|
321
321
|
}
|
|
322
|
-
// eslint-disable-next-line no-
|
|
322
|
+
// eslint-disable-next-line tldraw/no-setter-getter
|
|
323
323
|
set isPointing(isPointing: boolean) {
|
|
324
324
|
this.setIsPointing(isPointing)
|
|
325
325
|
}
|
|
@@ -341,11 +341,11 @@ export class InputsManager {
|
|
|
341
341
|
/**
|
|
342
342
|
* @deprecated Use `getIsPinching()` instead.
|
|
343
343
|
*/
|
|
344
|
-
// eslint-disable-next-line no-
|
|
344
|
+
// eslint-disable-next-line tldraw/no-setter-getter
|
|
345
345
|
get isPinching() {
|
|
346
346
|
return this.getIsPinching()
|
|
347
347
|
}
|
|
348
|
-
// eslint-disable-next-line no-
|
|
348
|
+
// eslint-disable-next-line tldraw/no-setter-getter
|
|
349
349
|
set isPinching(isPinching: boolean) {
|
|
350
350
|
this.setIsPinching(isPinching)
|
|
351
351
|
}
|
|
@@ -367,11 +367,11 @@ export class InputsManager {
|
|
|
367
367
|
/**
|
|
368
368
|
* @deprecated Use `getIsEditing()` instead.
|
|
369
369
|
*/
|
|
370
|
-
// eslint-disable-next-line no-
|
|
370
|
+
// eslint-disable-next-line tldraw/no-setter-getter
|
|
371
371
|
get isEditing() {
|
|
372
372
|
return this.getIsEditing()
|
|
373
373
|
}
|
|
374
|
-
// eslint-disable-next-line no-
|
|
374
|
+
// eslint-disable-next-line tldraw/no-setter-getter
|
|
375
375
|
set isEditing(isEditing: boolean) {
|
|
376
376
|
this.setIsEditing(isEditing)
|
|
377
377
|
}
|
|
@@ -392,11 +392,11 @@ export class InputsManager {
|
|
|
392
392
|
/**
|
|
393
393
|
* @deprecated Use `getIsPanning()` instead.
|
|
394
394
|
*/
|
|
395
|
-
// eslint-disable-next-line no-
|
|
395
|
+
// eslint-disable-next-line tldraw/no-setter-getter
|
|
396
396
|
get isPanning() {
|
|
397
397
|
return this.getIsPanning()
|
|
398
398
|
}
|
|
399
|
-
// eslint-disable-next-line no-
|
|
399
|
+
// eslint-disable-next-line tldraw/no-setter-getter
|
|
400
400
|
set isPanning(isPanning: boolean) {
|
|
401
401
|
this.setIsPanning(isPanning)
|
|
402
402
|
}
|
|
@@ -418,11 +418,11 @@ export class InputsManager {
|
|
|
418
418
|
/**
|
|
419
419
|
* @deprecated Use `getIsSpacebarPanning()` instead.
|
|
420
420
|
*/
|
|
421
|
-
// eslint-disable-next-line no-
|
|
421
|
+
// eslint-disable-next-line tldraw/no-setter-getter
|
|
422
422
|
get isSpacebarPanning() {
|
|
423
423
|
return this.getIsSpacebarPanning()
|
|
424
424
|
}
|
|
425
|
-
// eslint-disable-next-line no-
|
|
425
|
+
// eslint-disable-next-line tldraw/no-setter-getter
|
|
426
426
|
set isSpacebarPanning(isSpacebarPanning: boolean) {
|
|
427
427
|
this.setIsSpacebarPanning(isSpacebarPanning)
|
|
428
428
|
}
|
|
@@ -58,17 +58,16 @@ const mockCreateElement = vi.fn(() => {
|
|
|
58
58
|
})
|
|
59
59
|
|
|
60
60
|
// Mock editor
|
|
61
|
+
const mockDocument = {
|
|
62
|
+
createElement: mockCreateElement,
|
|
63
|
+
}
|
|
61
64
|
const mockEditor = {
|
|
62
65
|
getContainer: vi.fn(() => ({
|
|
63
66
|
appendChild: vi.fn(),
|
|
64
67
|
})),
|
|
68
|
+
getContainerDocument: vi.fn(() => mockDocument),
|
|
65
69
|
} as unknown as Editor
|
|
66
70
|
|
|
67
|
-
// Setup global mocks
|
|
68
|
-
global.document = {
|
|
69
|
-
createElement: mockCreateElement,
|
|
70
|
-
} as any
|
|
71
|
-
|
|
72
71
|
global.Range = vi.fn(() => ({
|
|
73
72
|
setStart: vi.fn(),
|
|
74
73
|
setEnd: vi.fn(),
|
|
@@ -75,7 +75,7 @@ export class TextManager {
|
|
|
75
75
|
private elm: HTMLDivElement
|
|
76
76
|
|
|
77
77
|
constructor(public editor: Editor) {
|
|
78
|
-
const elm =
|
|
78
|
+
const elm = editor.getContainerDocument().createElement('div')
|
|
79
79
|
elm.classList.add('tl-text')
|
|
80
80
|
elm.classList.add('tl-text-measure')
|
|
81
81
|
elm.setAttribute('dir', 'auto')
|
|
@@ -111,7 +111,7 @@ export class TextManager {
|
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
measureText(textToMeasure: string, opts: TLMeasureTextOpts): BoxModel & { scrollWidth: number } {
|
|
114
|
-
const div =
|
|
114
|
+
const div = this.editor.getContainerDocument().createElement('div')
|
|
115
115
|
div.textContent = normalizeTextForDom(textToMeasure)
|
|
116
116
|
return this.measureHtml(div.innerHTML, opts)
|
|
117
117
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { atom, computed } from '@tldraw/state'
|
|
2
2
|
import { TLUserPreferences, defaultUserPreferences } from '../../../config/TLUserPreferences'
|
|
3
3
|
import { TLUser } from '../../../config/createTLUser'
|
|
4
|
+
import { getGlobalWindow } from '../../../utils/dom'
|
|
4
5
|
|
|
5
6
|
/** @public */
|
|
6
7
|
export class UserPreferencesManager {
|
|
@@ -13,9 +14,9 @@ export class UserPreferencesManager {
|
|
|
13
14
|
private readonly user: TLUser,
|
|
14
15
|
private readonly inferDarkMode: boolean
|
|
15
16
|
) {
|
|
16
|
-
if (typeof window === 'undefined' || !
|
|
17
|
+
if (typeof window === 'undefined' || !getGlobalWindow().matchMedia) return
|
|
17
18
|
|
|
18
|
-
const darkModeMediaQuery =
|
|
19
|
+
const darkModeMediaQuery = getGlobalWindow().matchMedia('(prefers-color-scheme: dark)')
|
|
19
20
|
if (darkModeMediaQuery?.matches) {
|
|
20
21
|
this.systemColorScheme.set('dark')
|
|
21
22
|
}
|
|
@@ -40,9 +40,15 @@ export interface TLSvgExportOptions {
|
|
|
40
40
|
background?: boolean
|
|
41
41
|
|
|
42
42
|
/**
|
|
43
|
-
* How much padding to include around the bounds of exports
|
|
43
|
+
* How much padding to include around the bounds of exports.
|
|
44
|
+
*
|
|
45
|
+
* - `'auto'` (default) — trim to visual content bounds, capturing overflow (like thick
|
|
46
|
+
* strokes or arrowheads) without extra whitespace.
|
|
47
|
+
* - `number` (e.g. `32`) — fixed padding in px. No trimming; overflow beyond the padding
|
|
48
|
+
* region is clipped.
|
|
49
|
+
* - `0` — no padding, no trimming, overflow is clipped.
|
|
44
50
|
*/
|
|
45
|
-
padding?: number
|
|
51
|
+
padding?: number | 'auto'
|
|
46
52
|
|
|
47
53
|
/**
|
|
48
54
|
* Should the export be rendered in dark mode (true) or light mode (false)? Defaults to the
|
|
@@ -11,7 +11,7 @@ export const SVG_EXPORT_CLASSNAME = 'tldraw-svg-export'
|
|
|
11
11
|
* SVG.
|
|
12
12
|
*
|
|
13
13
|
* It works in three steps:
|
|
14
|
-
* 1. `
|
|
14
|
+
* 1. `startFindingDocumentFontFaces` - this traverses the given document, finding all the
|
|
15
15
|
* stylesheets in use (including those imported via `@import` rules etc) and extracting the
|
|
16
16
|
* @font-face declarations from them.
|
|
17
17
|
* 2. `onFontFamilyValue` - as `StyleEmbedder` traverses the SVG, it will call this method with the
|
|
@@ -26,9 +26,9 @@ export class FontEmbedder {
|
|
|
26
26
|
private readonly fontFacesToEmbed = new Set<ParsedFontFace>()
|
|
27
27
|
private readonly pendingPromises: Promise<void>[] = []
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
startFindingDocumentFontFaces(doc: Document) {
|
|
30
30
|
assert(!this.fontFacesPromise, 'FontEmbedder already started')
|
|
31
|
-
this.fontFacesPromise =
|
|
31
|
+
this.fontFacesPromise = getDocumentFontFaces(doc)
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
@bind onFontFamilyValue(fontFamilyValue: string) {
|
|
@@ -80,7 +80,8 @@ export class FontEmbedder {
|
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
async function
|
|
83
|
+
async function getDocumentFontFaces(doc: Document) {
|
|
84
|
+
const win = doc.defaultView ?? globalThis
|
|
84
85
|
const fontFaces: (ParsedFontFace[] | Promise<ParsedFontFace[] | null>)[] = []
|
|
85
86
|
|
|
86
87
|
// In exportToSvg we add the exported node to the DOM temporarily.
|
|
@@ -88,7 +89,7 @@ async function getCurrentDocumentFontFaces() {
|
|
|
88
89
|
// DOM, when looking at document.styleSheets the number of nodes and stylesheets
|
|
89
90
|
// can grow unbounded (especially when using "Debug svg" and moving shapes around).
|
|
90
91
|
// To avoid this, we filter out the stylesheets that are part of the SVG export.
|
|
91
|
-
const styleSheetsWithoutSvgExports = Array.from(
|
|
92
|
+
const styleSheetsWithoutSvgExports = Array.from(doc.styleSheets).filter(
|
|
92
93
|
(styleSheet) =>
|
|
93
94
|
!(styleSheet.ownerNode as HTMLElement | null)?.closest(`.${SVG_EXPORT_CLASSNAME}`)
|
|
94
95
|
)
|
|
@@ -103,10 +104,10 @@ async function getCurrentDocumentFontFaces() {
|
|
|
103
104
|
|
|
104
105
|
if (cssRules) {
|
|
105
106
|
for (const rule of styleSheet.cssRules) {
|
|
106
|
-
if (rule instanceof CSSFontFaceRule) {
|
|
107
|
-
fontFaces.push(parseCssFontFaces(rule.cssText, styleSheet.href ??
|
|
108
|
-
} else if (rule instanceof CSSImportRule) {
|
|
109
|
-
const absoluteUrl = new URL(rule.href, rule.parentStyleSheet?.href ??
|
|
107
|
+
if (rule instanceof win.CSSFontFaceRule) {
|
|
108
|
+
fontFaces.push(parseCssFontFaces(rule.cssText, styleSheet.href ?? doc.baseURI))
|
|
109
|
+
} else if (rule instanceof win.CSSImportRule) {
|
|
110
|
+
const absoluteUrl = new URL(rule.href, rule.parentStyleSheet?.href ?? doc.baseURI)
|
|
110
111
|
fontFaces.push(fetchCssFontFaces(absoluteUrl.href))
|
|
111
112
|
}
|
|
112
113
|
}
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
getComputedStyle,
|
|
7
7
|
getRenderedChildNodes,
|
|
8
8
|
getRenderedChildren,
|
|
9
|
+
isElement,
|
|
9
10
|
} from './domUtils'
|
|
10
11
|
import { resourceToDataUrl } from './fetchCache'
|
|
11
12
|
import { parseCssValueUrls, shouldIncludeCssProperty } from './parseCss'
|
|
@@ -49,7 +50,7 @@ export class StyleEmbedder {
|
|
|
49
50
|
{ shouldRespectDefaults = true, shouldSkipInheritedParentStyles = true }
|
|
50
51
|
) {
|
|
51
52
|
const defaultStyles = shouldRespectDefaults
|
|
52
|
-
? getDefaultStylesForTagName(element.tagName.toLowerCase())
|
|
53
|
+
? getDefaultStylesForTagName(element.ownerDocument, element.tagName.toLowerCase())
|
|
53
54
|
: NO_STYLES
|
|
54
55
|
|
|
55
56
|
const parentStyles = Object.assign({}, NO_STYLES) as Styles
|
|
@@ -116,14 +117,14 @@ export class StyleEmbedder {
|
|
|
116
117
|
const shadowRoot = element.shadowRoot
|
|
117
118
|
|
|
118
119
|
if (shadowRoot) {
|
|
119
|
-
const clonedCustomEl =
|
|
120
|
+
const clonedCustomEl = element.ownerDocument.createElement('div')
|
|
120
121
|
this.styles.set(clonedCustomEl, this.styles.get(element)!)
|
|
121
122
|
|
|
122
123
|
clonedCustomEl.setAttribute('data-tl-custom-element', element.tagName)
|
|
123
124
|
;(clonedParent ?? element.parentElement!).appendChild(clonedCustomEl)
|
|
124
125
|
|
|
125
126
|
for (const child of shadowRoot.childNodes) {
|
|
126
|
-
if (child
|
|
127
|
+
if (isElement(child)) {
|
|
127
128
|
visit(child, clonedCustomEl)
|
|
128
129
|
} else {
|
|
129
130
|
clonedCustomEl.appendChild(child.cloneNode(true))
|
|
@@ -144,7 +145,7 @@ export class StyleEmbedder {
|
|
|
144
145
|
clonedParent.appendChild(clonedEl)
|
|
145
146
|
|
|
146
147
|
for (const child of getRenderedChildNodes(element)) {
|
|
147
|
-
if (child
|
|
148
|
+
if (isElement(child)) {
|
|
148
149
|
visit(child, clonedEl)
|
|
149
150
|
} else {
|
|
150
151
|
clonedEl.appendChild(child.cloneNode(true))
|
|
@@ -295,36 +296,53 @@ function formatCss(style: ReadonlyStyles) {
|
|
|
295
296
|
// when we're figuring out the default values for a tag, we need read them from a separate document
|
|
296
297
|
// so they're not affected by the current document's styles
|
|
297
298
|
let defaultStyleFrame:
|
|
298
|
-
| {
|
|
299
|
+
| {
|
|
300
|
+
iframe: HTMLIFrameElement
|
|
301
|
+
foreignObject: SVGForeignObjectElement
|
|
302
|
+
document: Document
|
|
303
|
+
ownerDocument: Document
|
|
304
|
+
}
|
|
299
305
|
| undefined
|
|
300
306
|
const defaultStylesByTagName: Record<string, ReadonlyStyles> = {}
|
|
301
|
-
function getDefaultStyleFrame() {
|
|
302
|
-
if (!defaultStyleFrame) {
|
|
303
|
-
|
|
307
|
+
function getDefaultStyleFrame(ownerDoc: Document) {
|
|
308
|
+
if (!defaultStyleFrame || defaultStyleFrame.ownerDocument !== ownerDoc) {
|
|
309
|
+
destroyDefaultStyleFrame()
|
|
310
|
+
const frame = ownerDoc.createElement('iframe')
|
|
304
311
|
frame.style.display = 'none'
|
|
305
|
-
|
|
312
|
+
ownerDoc.body.appendChild(frame)
|
|
306
313
|
const frameDocument = assertExists(frame.contentDocument, 'frame must have a document')
|
|
307
|
-
const svg =
|
|
308
|
-
const foreignObject =
|
|
314
|
+
const svg = frameDocument.createElementNS('http://www.w3.org/2000/svg', 'svg')
|
|
315
|
+
const foreignObject = frameDocument.createElementNS(
|
|
316
|
+
'http://www.w3.org/2000/svg',
|
|
317
|
+
'foreignObject'
|
|
318
|
+
)
|
|
309
319
|
svg.appendChild(foreignObject)
|
|
310
320
|
frameDocument.body.appendChild(svg)
|
|
311
|
-
defaultStyleFrame = {
|
|
321
|
+
defaultStyleFrame = {
|
|
322
|
+
iframe: frame,
|
|
323
|
+
foreignObject,
|
|
324
|
+
document: frameDocument,
|
|
325
|
+
ownerDocument: ownerDoc,
|
|
326
|
+
}
|
|
312
327
|
}
|
|
313
328
|
return defaultStyleFrame
|
|
314
329
|
}
|
|
315
330
|
|
|
316
331
|
function destroyDefaultStyleFrame() {
|
|
317
332
|
if (defaultStyleFrame) {
|
|
318
|
-
|
|
333
|
+
defaultStyleFrame.iframe.remove()
|
|
319
334
|
defaultStyleFrame = undefined
|
|
320
335
|
}
|
|
336
|
+
for (const tagName in defaultStylesByTagName) {
|
|
337
|
+
delete defaultStylesByTagName[tagName]
|
|
338
|
+
}
|
|
321
339
|
}
|
|
322
340
|
|
|
323
341
|
const defaultStyleReadOptions: ReadStyleOpts = { defaultStyles: NO_STYLES, parentStyles: NO_STYLES }
|
|
324
|
-
function getDefaultStylesForTagName(tagName: string) {
|
|
342
|
+
function getDefaultStylesForTagName(ownerDoc: Document, tagName: string) {
|
|
325
343
|
let existing = defaultStylesByTagName[tagName]
|
|
326
344
|
if (!existing) {
|
|
327
|
-
const { foreignObject, document } = getDefaultStyleFrame()
|
|
345
|
+
const { foreignObject, document } = getDefaultStyleFrame(ownerDoc)
|
|
328
346
|
const element = document.createElement(tagName)
|
|
329
347
|
foreignObject.appendChild(element)
|
|
330
348
|
existing = element.computedStyleMap
|
|
@@ -22,6 +22,26 @@ export function* getRenderedChildren(node: Element) {
|
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
/** @internal */
|
|
26
|
+
export function getOwnerWindow(
|
|
27
|
+
nodeOrDocument: Node | Document | null | undefined
|
|
28
|
+
): Window & typeof globalThis {
|
|
29
|
+
if (!nodeOrDocument) return globalThis as Window & typeof globalThis
|
|
30
|
+
const doc = isDocument(nodeOrDocument) ? nodeOrDocument : nodeOrDocument.ownerDocument
|
|
31
|
+
return (doc?.defaultView ?? globalThis) as Window & typeof globalThis
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** @internal */
|
|
35
|
+
export function getOwnerDocument(nodeOrDocument: Node | Document | null | undefined): Document {
|
|
36
|
+
if (!nodeOrDocument) return globalThis.document
|
|
37
|
+
if (isDocument(nodeOrDocument)) return nodeOrDocument
|
|
38
|
+
return nodeOrDocument.ownerDocument ?? globalThis.document
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function isDocument(node: Node | Document): node is Document {
|
|
42
|
+
return node.nodeType === Node.DOCUMENT_NODE
|
|
43
|
+
}
|
|
44
|
+
|
|
25
45
|
function getWindow(node: Node) {
|
|
26
46
|
return node.ownerDocument?.defaultView ?? globalThis
|
|
27
47
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MediaHelpers } from '@tldraw/utils'
|
|
2
|
-
import { getRenderedChildren } from './domUtils'
|
|
2
|
+
import { getOwnerWindow, getRenderedChildren } from './domUtils'
|
|
3
3
|
import { resourceToDataUrl } from './fetchCache'
|
|
4
4
|
|
|
5
5
|
function copyAttrs(source: Element, target: Element) {
|
|
@@ -14,8 +14,12 @@ function replace(original: HTMLElement, replacement: HTMLElement) {
|
|
|
14
14
|
return replacement
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
async function createImage(
|
|
18
|
-
|
|
17
|
+
async function createImage(
|
|
18
|
+
doc: Document,
|
|
19
|
+
dataUrl: string | null,
|
|
20
|
+
cloneAttributesFrom?: HTMLElement
|
|
21
|
+
) {
|
|
22
|
+
const image = doc.createElement('img')
|
|
19
23
|
|
|
20
24
|
if (cloneAttributesFrom) {
|
|
21
25
|
copyAttrs(cloneAttributesFrom, image)
|
|
@@ -34,52 +38,54 @@ async function createImage(dataUrl: string | null, cloneAttributesFrom?: HTMLEle
|
|
|
34
38
|
}
|
|
35
39
|
|
|
36
40
|
async function getCanvasReplacement(canvas: HTMLCanvasElement) {
|
|
41
|
+
const doc = canvas.ownerDocument
|
|
37
42
|
try {
|
|
38
43
|
const dataURL = canvas.toDataURL()
|
|
39
|
-
return await createImage(dataURL, canvas)
|
|
44
|
+
return await createImage(doc, dataURL, canvas)
|
|
40
45
|
} catch {
|
|
41
|
-
return await createImage(null, canvas)
|
|
46
|
+
return await createImage(doc, null, canvas)
|
|
42
47
|
}
|
|
43
48
|
}
|
|
44
49
|
|
|
45
50
|
async function getVideoReplacement(video: HTMLVideoElement) {
|
|
51
|
+
const doc = video.ownerDocument
|
|
46
52
|
try {
|
|
47
53
|
const dataUrl = await MediaHelpers.getVideoFrameAsDataUrl(video)
|
|
48
|
-
return createImage(dataUrl, video)
|
|
54
|
+
return createImage(doc, dataUrl, video)
|
|
49
55
|
} catch (err) {
|
|
50
56
|
console.error('Could not get video frame', err)
|
|
51
57
|
}
|
|
52
58
|
|
|
53
59
|
if (video.poster) {
|
|
54
60
|
const dataUrl = await resourceToDataUrl(video.poster)
|
|
55
|
-
return createImage(dataUrl, video)
|
|
61
|
+
return createImage(doc, dataUrl, video)
|
|
56
62
|
}
|
|
57
63
|
|
|
58
|
-
return createImage(null, video)
|
|
64
|
+
return createImage(doc, null, video)
|
|
59
65
|
}
|
|
60
66
|
|
|
61
67
|
export async function embedMedia(node: HTMLElement) {
|
|
62
|
-
|
|
68
|
+
const win = getOwnerWindow(node)
|
|
69
|
+
if (node instanceof win.HTMLCanvasElement) {
|
|
63
70
|
return replace(node, await getCanvasReplacement(node))
|
|
64
|
-
} else if (node instanceof HTMLVideoElement) {
|
|
71
|
+
} else if (node instanceof win.HTMLVideoElement) {
|
|
65
72
|
return replace(node, await getVideoReplacement(node))
|
|
66
|
-
} else if (node instanceof HTMLImageElement) {
|
|
73
|
+
} else if (node instanceof win.HTMLImageElement) {
|
|
67
74
|
const src = node.currentSrc || node.src
|
|
68
75
|
const dataUrl = await resourceToDataUrl(src)
|
|
69
76
|
node.setAttribute('src', dataUrl ?? 'data:')
|
|
70
77
|
node.setAttribute('decoding', 'sync')
|
|
71
78
|
node.setAttribute('loading', 'eager')
|
|
72
79
|
try {
|
|
73
|
-
await node.decode()
|
|
80
|
+
await (node as HTMLImageElement).decode()
|
|
74
81
|
} catch {
|
|
75
82
|
// this is fine
|
|
76
83
|
}
|
|
77
84
|
return node
|
|
78
|
-
} else if (node instanceof HTMLInputElement) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
node.textContent = node.value
|
|
85
|
+
} else if (node instanceof win.HTMLInputElement) {
|
|
86
|
+
node.setAttribute('value', (node as HTMLInputElement).value)
|
|
87
|
+
} else if (node instanceof win.HTMLTextAreaElement) {
|
|
88
|
+
node.textContent = (node as HTMLTextAreaElement).value
|
|
83
89
|
}
|
|
84
90
|
|
|
85
91
|
await Promise.all(
|