@tldraw/editor 5.4.0-next.ef99ab47e5ce → 5.4.1
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 +114 -47
- package/dist-cjs/index.js +4 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/TldrawEditor.js +7 -2
- package/dist-cjs/lib/TldrawEditor.js.map +2 -2
- package/dist-cjs/lib/components/MenuClickCapture.js +6 -8
- package/dist-cjs/lib/components/MenuClickCapture.js.map +2 -2
- package/dist-cjs/lib/components/default-components/CanvasOverlays.js +1 -3
- package/dist-cjs/lib/components/default-components/CanvasOverlays.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js.map +1 -1
- package/dist-cjs/lib/config/TLUserPreferences.js +6 -2
- package/dist-cjs/lib/config/TLUserPreferences.js.map +2 -2
- package/dist-cjs/lib/config/createTLStore.js +1 -1
- package/dist-cjs/lib/config/createTLStore.js.map +2 -2
- package/dist-cjs/lib/editor/Editor.js +181 -294
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/derivations/shapeIdsInCurrentPage.js +7 -3
- package/dist-cjs/lib/editor/derivations/shapeIdsInCurrentPage.js.map +2 -2
- package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js +3 -3
- package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.js +8 -8
- package/dist-cjs/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/FontManager/FontManager.js +2 -1
- package/dist-cjs/lib/editor/managers/FontManager/FontManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js +79 -6
- package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js +7 -0
- package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js +0 -2
- package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js.map +2 -2
- package/dist-cjs/lib/editor/managers/TextManager/TextManager.js +1 -2
- package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/TickManager/TickManager.js +6 -3
- package/dist-cjs/lib/editor/managers/TickManager/TickManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +12 -1
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
- package/dist-cjs/lib/editor/overlays/OverlayManager.js +3 -7
- package/dist-cjs/lib/editor/overlays/OverlayManager.js.map +2 -2
- package/dist-cjs/lib/editor/overlays/strokeShapeIndicators.js +0 -1
- package/dist-cjs/lib/editor/overlays/strokeShapeIndicators.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/BaseFrameLikeShapeUtil.js +3 -1
- package/dist-cjs/lib/editor/shapes/BaseFrameLikeShapeUtil.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/shared/getPerfectDashProps.js +1 -0
- package/dist-cjs/lib/editor/shapes/shared/getPerfectDashProps.js.map +2 -2
- package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js +1 -1
- package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js.map +2 -2
- package/dist-cjs/lib/editor/tools/StateNode.js +3 -2
- package/dist-cjs/lib/editor/tools/StateNode.js.map +2 -2
- package/dist-cjs/lib/globals/editors.js +57 -0
- package/dist-cjs/lib/globals/editors.js.map +7 -0
- package/dist-cjs/lib/globals/menus.js +9 -4
- package/dist-cjs/lib/globals/menus.js.map +2 -2
- package/dist-cjs/lib/hooks/useCanvasEvents.js +2 -0
- package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/useDocumentEvents.js +39 -9
- package/dist-cjs/lib/hooks/useDocumentEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/useLocalStore.js +10 -6
- package/dist-cjs/lib/hooks/useLocalStore.js.map +2 -2
- package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js +1 -0
- package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/usePeerIds.js +2 -1
- package/dist-cjs/lib/hooks/usePeerIds.js.map +2 -2
- package/dist-cjs/lib/license/LicenseManager.js +9 -2
- package/dist-cjs/lib/license/LicenseManager.js.map +2 -2
- package/dist-cjs/lib/license/LicenseProvider.js +16 -3
- package/dist-cjs/lib/license/LicenseProvider.js.map +2 -2
- package/dist-cjs/lib/license/useLicenseManagerState.js +5 -4
- package/dist-cjs/lib/license/useLicenseManagerState.js.map +2 -2
- package/dist-cjs/lib/primitives/Box.js +2 -1
- package/dist-cjs/lib/primitives/Box.js.map +2 -2
- package/dist-cjs/lib/primitives/Vec.js +4 -3
- package/dist-cjs/lib/primitives/Vec.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Group2d.js +63 -21
- package/dist-cjs/lib/primitives/geometry/Group2d.js.map +2 -2
- package/dist-cjs/lib/primitives/utils.js +2 -1
- package/dist-cjs/lib/primitives/utils.js.map +2 -2
- package/dist-cjs/lib/utils/deepLinks.js +5 -1
- package/dist-cjs/lib/utils/deepLinks.js.map +2 -2
- package/dist-cjs/lib/utils/normalizeWheel.js +2 -0
- package/dist-cjs/lib/utils/normalizeWheel.js.map +2 -2
- package/dist-cjs/lib/utils/rotation.js +1 -9
- package/dist-cjs/lib/utils/rotation.js.map +2 -2
- package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js +17 -0
- package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js.map +2 -2
- package/dist-cjs/lib/utils/sync/alerts.js +1 -1
- package/dist-cjs/lib/utils/sync/alerts.js.map +1 -1
- package/dist-cjs/version.js +3 -3
- package/dist-cjs/version.js.map +1 -1
- package/dist-esm/index.d.mts +114 -47
- package/dist-esm/index.mjs +9 -2
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/TldrawEditor.mjs +9 -4
- package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
- package/dist-esm/lib/components/MenuClickCapture.mjs +6 -8
- package/dist-esm/lib/components/MenuClickCapture.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/CanvasOverlays.mjs +1 -3
- package/dist-esm/lib/components/default-components/CanvasOverlays.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs.map +1 -1
- package/dist-esm/lib/config/TLUserPreferences.mjs +6 -2
- package/dist-esm/lib/config/TLUserPreferences.mjs.map +2 -2
- package/dist-esm/lib/config/createTLStore.mjs +1 -1
- package/dist-esm/lib/config/createTLStore.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +189 -295
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/derivations/shapeIdsInCurrentPage.mjs +7 -3
- package/dist-esm/lib/editor/derivations/shapeIdsInCurrentPage.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs +3 -3
- package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.mjs +9 -9
- package/dist-esm/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs +2 -1
- package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs +81 -8
- package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs +7 -0
- package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs +0 -2
- package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs +2 -3
- package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs +6 -3
- package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +12 -1
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
- package/dist-esm/lib/editor/overlays/OverlayManager.mjs +3 -7
- package/dist-esm/lib/editor/overlays/OverlayManager.mjs.map +2 -2
- package/dist-esm/lib/editor/overlays/strokeShapeIndicators.mjs +0 -1
- package/dist-esm/lib/editor/overlays/strokeShapeIndicators.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/BaseFrameLikeShapeUtil.mjs +3 -1
- package/dist-esm/lib/editor/shapes/BaseFrameLikeShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/shared/getPerfectDashProps.mjs +1 -0
- package/dist-esm/lib/editor/shapes/shared/getPerfectDashProps.mjs.map +2 -2
- package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs +1 -1
- package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs.map +2 -2
- package/dist-esm/lib/editor/tools/StateNode.mjs +3 -2
- package/dist-esm/lib/editor/tools/StateNode.mjs.map +2 -2
- package/dist-esm/lib/globals/editors.mjs +37 -0
- package/dist-esm/lib/globals/editors.mjs.map +7 -0
- package/dist-esm/lib/globals/menus.mjs +9 -4
- package/dist-esm/lib/globals/menus.mjs.map +2 -2
- package/dist-esm/lib/hooks/useCanvasEvents.mjs +2 -0
- package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useDocumentEvents.mjs +40 -10
- package/dist-esm/lib/hooks/useDocumentEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useLocalStore.mjs +11 -7
- package/dist-esm/lib/hooks/useLocalStore.mjs.map +2 -2
- package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs +1 -0
- package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/usePeerIds.mjs +2 -1
- package/dist-esm/lib/hooks/usePeerIds.mjs.map +2 -2
- package/dist-esm/lib/license/LicenseManager.mjs +9 -2
- package/dist-esm/lib/license/LicenseManager.mjs.map +2 -2
- package/dist-esm/lib/license/LicenseProvider.mjs +16 -3
- package/dist-esm/lib/license/LicenseProvider.mjs.map +2 -2
- package/dist-esm/lib/license/useLicenseManagerState.mjs +5 -4
- package/dist-esm/lib/license/useLicenseManagerState.mjs.map +2 -2
- package/dist-esm/lib/primitives/Box.mjs +2 -1
- package/dist-esm/lib/primitives/Box.mjs.map +2 -2
- package/dist-esm/lib/primitives/Vec.mjs +4 -3
- package/dist-esm/lib/primitives/Vec.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Group2d.mjs +63 -21
- package/dist-esm/lib/primitives/geometry/Group2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/utils.mjs +2 -1
- package/dist-esm/lib/primitives/utils.mjs.map +2 -2
- package/dist-esm/lib/utils/deepLinks.mjs +5 -1
- package/dist-esm/lib/utils/deepLinks.mjs.map +2 -2
- package/dist-esm/lib/utils/normalizeWheel.mjs +2 -0
- package/dist-esm/lib/utils/normalizeWheel.mjs.map +2 -2
- package/dist-esm/lib/utils/rotation.mjs +1 -9
- package/dist-esm/lib/utils/rotation.mjs.map +2 -2
- package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs +17 -0
- package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs.map +2 -2
- package/dist-esm/lib/utils/sync/alerts.mjs +1 -1
- package/dist-esm/lib/utils/sync/alerts.mjs.map +1 -1
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/package.json +13 -7
- package/src/index.ts +6 -1
- package/src/lib/TldrawEditor.tsx +16 -4
- package/src/lib/components/MenuClickCapture.tsx +19 -18
- package/src/lib/components/default-components/CanvasOverlays.tsx +1 -3
- package/src/lib/components/default-components/DefaultErrorFallback.tsx +1 -1
- package/src/lib/config/TLUserPreferences.test.ts +18 -1
- package/src/lib/config/TLUserPreferences.ts +8 -4
- package/src/lib/config/createTLStore.ts +1 -1
- package/src/lib/editor/Editor.ts +266 -383
- package/src/lib/editor/derivations/shapeIdsInCurrentPage.ts +7 -3
- package/src/lib/editor/managers/ClickManager/ClickManager.ts +5 -3
- package/src/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.ts +9 -9
- package/src/lib/editor/managers/FontManager/FontManager.ts +2 -1
- package/src/lib/editor/managers/InputsManager/InputsManager.test.ts +199 -3
- package/src/lib/editor/managers/InputsManager/InputsManager.ts +128 -9
- package/src/lib/editor/managers/ScribbleManager/ScribbleManager.ts +12 -1
- package/src/lib/editor/managers/SnapManager/BoundsSnaps.ts +0 -2
- package/src/lib/editor/managers/TextManager/TextManager.ts +2 -6
- package/src/lib/editor/managers/TickManager/TickManager.test.ts +13 -0
- package/src/lib/editor/managers/TickManager/TickManager.ts +9 -3
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +64 -3
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +18 -1
- package/src/lib/editor/overlays/OverlayManager.ts +3 -7
- package/src/lib/editor/overlays/strokeShapeIndicators.ts +0 -1
- package/src/lib/editor/shapes/BaseFrameLikeShapeUtil.tsx +5 -1
- package/src/lib/editor/shapes/shared/getPerfectDashProps.ts +3 -0
- package/src/lib/editor/tools/BaseBoxShapeTool/children/Pointing.ts +4 -1
- package/src/lib/editor/tools/StateNode.test.ts +64 -0
- package/src/lib/editor/tools/StateNode.ts +12 -2
- package/src/lib/globals/editors.test.ts +76 -0
- package/src/lib/globals/editors.ts +53 -0
- package/src/lib/globals/menus.test.ts +33 -0
- package/src/lib/globals/menus.ts +11 -4
- package/src/lib/hooks/useCanvasEvents.ts +2 -0
- package/src/lib/hooks/useDocumentEvents.ts +60 -16
- package/src/lib/hooks/useLocalStore.ts +16 -8
- package/src/lib/hooks/usePassThroughWheelEvents.ts +3 -0
- package/src/lib/hooks/usePeerIds.ts +2 -1
- package/src/lib/license/LicenseManager.test.ts +160 -0
- package/src/lib/license/LicenseManager.ts +13 -4
- package/src/lib/license/LicenseProvider.tsx +24 -3
- package/src/lib/license/useLicenseManagerState.ts +8 -6
- package/src/lib/primitives/Box.test.ts +9 -1
- package/src/lib/primitives/Box.ts +3 -1
- package/src/lib/primitives/Vec.test.ts +10 -0
- package/src/lib/primitives/Vec.ts +4 -4
- package/src/lib/primitives/geometry/Arc2d.test.ts +226 -3
- package/src/lib/primitives/geometry/CubicBezier2d.test.ts +173 -3
- package/src/lib/primitives/geometry/CubicSpline2d.test.ts +160 -3
- package/src/lib/primitives/geometry/Ellipse2d.test.ts +243 -3
- package/src/lib/primitives/geometry/Geometry2d.test.ts +553 -1
- package/src/lib/primitives/geometry/Group2d.test.ts +398 -3
- package/src/lib/primitives/geometry/Group2d.ts +63 -27
- package/src/lib/primitives/geometry/Polyline2d.test.ts +207 -0
- package/src/lib/primitives/geometry/Stadium2d.test.ts +191 -3
- package/src/lib/primitives/utils.test.ts +10 -1
- package/src/lib/primitives/utils.ts +4 -1
- package/src/lib/test/useCanvasEvents.test.tsx +74 -0
- package/src/lib/test/useDocumentEvents.test.tsx +107 -0
- package/src/lib/test/usePassThroughWheelEvents.test.tsx +25 -2
- package/src/lib/utils/deepLinks.test.ts +15 -0
- package/src/lib/utils/deepLinks.ts +7 -1
- package/src/lib/utils/normalizeWheel.test.ts +39 -0
- package/src/lib/utils/normalizeWheel.ts +6 -0
- package/src/lib/utils/rotation.ts +4 -12
- package/src/lib/utils/sync/TLLocalSyncClient.test.ts +56 -0
- package/src/lib/utils/sync/TLLocalSyncClient.ts +24 -0
- package/src/lib/utils/sync/alerts.ts +1 -1
- package/src/version.ts +3 -3
- package/src/lib/primitives/geometry/Polyline.test.ts +0 -5
|
@@ -91,6 +91,21 @@ class TLLocalSyncClient {
|
|
|
91
91
|
{ scope: "session" }
|
|
92
92
|
)
|
|
93
93
|
);
|
|
94
|
+
if (typeof window !== "undefined") {
|
|
95
|
+
const flush = () => {
|
|
96
|
+
if (!this.didLoad) return;
|
|
97
|
+
this.persistIfNeeded();
|
|
98
|
+
};
|
|
99
|
+
const onVisibilityChange = () => {
|
|
100
|
+
if (document.visibilityState === "hidden") flush();
|
|
101
|
+
};
|
|
102
|
+
window.addEventListener("pagehide", flush);
|
|
103
|
+
document.addEventListener("visibilitychange", onVisibilityChange);
|
|
104
|
+
this.disposables.add(() => {
|
|
105
|
+
window.removeEventListener("pagehide", flush);
|
|
106
|
+
document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
107
|
+
});
|
|
108
|
+
}
|
|
94
109
|
this.connect(onLoad, onLoadError);
|
|
95
110
|
this.documentTypes = new Set(
|
|
96
111
|
Object.values(this.store.schema.types).filter((t) => t.scope === "document").map((t) => t.typeName)
|
|
@@ -101,6 +116,7 @@ class TLLocalSyncClient {
|
|
|
101
116
|
disposables = /* @__PURE__ */ new Set();
|
|
102
117
|
diffQueue = [];
|
|
103
118
|
didDispose = false;
|
|
119
|
+
didLoad = false;
|
|
104
120
|
shouldDoFullDBWrite = true;
|
|
105
121
|
isReloading = false;
|
|
106
122
|
persistenceKey;
|
|
@@ -191,6 +207,7 @@ class TLLocalSyncClient {
|
|
|
191
207
|
this.disposables.add(() => {
|
|
192
208
|
this.channel.close();
|
|
193
209
|
});
|
|
210
|
+
this.didLoad = true;
|
|
194
211
|
onLoad(this);
|
|
195
212
|
} catch (e) {
|
|
196
213
|
this.debug("error loading data from store", e);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/utils/sync/TLLocalSyncClient.ts"],
|
|
4
|
-
"sourcesContent": ["import { Signal, transact } from '@tldraw/state'\nimport { RecordsDiff, SerializedSchema, UnknownRecord, squashRecordDiffs } from '@tldraw/store'\nimport { TLStore } from '@tldraw/tlschema'\nimport { assert } from '@tldraw/utils'\nimport {\n\tTAB_ID,\n\tTLSessionStateSnapshot,\n\tcreateSessionStateSnapshotSignal,\n\textractSessionStateFromLegacySnapshot,\n\tloadSessionStateSnapshotIntoStore,\n} from '../../config/TLSessionStateSnapshot'\nimport { showCantReadFromIndexDbAlert, showCantWriteToIndexDbAlert } from './alerts'\nimport { LocalIndexedDb } from './LocalIndexedDb'\n\n/** How should we debounce persists? */\nconst PERSIST_THROTTLE_MS = 350\n/** If we're in an error state, how long should we wait before retrying a write? */\nconst PERSIST_RETRY_THROTTLE_MS = 10_000\n\nconst UPDATE_INSTANCE_STATE = Symbol('UPDATE_INSTANCE_STATE')\n\n/**\n * IMPORTANT!!!\n *\n * This is just a quick-n-dirty temporary solution that will be replaced with the remote sync client\n * once it has the db integrated\n */\n\ninterface SyncMessage {\n\ttype: 'diff'\n\tstoreId: string\n\tchanges: RecordsDiff<UnknownRecord>\n\tschema: SerializedSchema\n}\n\n// Sent by new clients when they connect\n// If another client is on the channel with a newer schema version\n// It will\ninterface AnnounceMessage {\n\ttype: 'announce'\n\tschema: SerializedSchema\n}\n\ntype Message = SyncMessage | AnnounceMessage\n\ntype UnpackPromise<T> = T extends Promise<infer U> ? U : T\n\nconst msg = (msg: Message) => msg\n\n/** @internal */\nexport class BroadcastChannelMock {\n\tonmessage?: (e: MessageEvent) => void\n\tconstructor(_name: string) {\n\t\t// noop\n\t}\n\tpostMessage(_msg: Message) {\n\t\t// noop\n\t}\n\tclose() {\n\t\t// noop\n\t}\n}\n\nconst BC = typeof BroadcastChannel === 'undefined' ? BroadcastChannelMock : BroadcastChannel\n\n/** @internal */\nexport class TLLocalSyncClient {\n\tprivate disposables = new Set<() => void>()\n\tprivate diffQueue: Array<RecordsDiff<UnknownRecord> | typeof UPDATE_INSTANCE_STATE> = []\n\tprivate didDispose = false\n\tprivate shouldDoFullDBWrite = true\n\tprivate isReloading = false\n\treadonly persistenceKey: string\n\treadonly sessionId: string\n\treadonly serializedSchema: SerializedSchema\n\tprivate isDebugging = false\n\tprivate readonly documentTypes: ReadonlySet<string>\n\tprivate readonly $sessionStateSnapshot: Signal<TLSessionStateSnapshot | null>\n\t/** @internal */\n\treadonly db: LocalIndexedDb\n\n\tinitTime = Date.now()\n\tprivate debug(...args: any[]) {\n\t\tif (this.isDebugging) {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.debug(...args)\n\t\t}\n\t}\n\tconstructor(\n\t\tpublic readonly store: TLStore,\n\t\t{\n\t\t\tpersistenceKey,\n\t\t\tsessionId = TAB_ID,\n\t\t\tonLoad,\n\t\t\tonLoadError,\n\t\t}: {\n\t\t\tpersistenceKey: string\n\t\t\tsessionId?: string\n\t\t\tonLoad(self: TLLocalSyncClient): void\n\t\t\tonLoadError(error: Error): void\n\t\t},\n\t\tpublic readonly channel = new BC(`tldraw-tab-sync-${persistenceKey}`)\n\t) {\n\t\tif (typeof window !== 'undefined') {\n\t\t\t;(window as any).tlsync = this\n\t\t}\n\t\tthis.persistenceKey = persistenceKey\n\t\tthis.sessionId = sessionId\n\t\tthis.db = new LocalIndexedDb(persistenceKey)\n\t\tthis.disposables.add(() => this.db.close())\n\n\t\tthis.serializedSchema = this.store.schema.serialize()\n\t\tthis.$sessionStateSnapshot = createSessionStateSnapshotSignal(this.store)\n\n\t\tthis.disposables.add(\n\t\t\t// Set up a subscription to changes from the store: When\n\t\t\t// the store changes (and if the change was made by the user)\n\t\t\t// then immediately send the diff to other tabs via postMessage\n\t\t\t// and schedule a persist.\n\t\t\tstore.listen(\n\t\t\t\t({ changes }) => {\n\t\t\t\t\tthis.diffQueue.push(changes)\n\t\t\t\t\tthis.channel.postMessage(\n\t\t\t\t\t\tmsg({\n\t\t\t\t\t\t\ttype: 'diff',\n\t\t\t\t\t\t\tstoreId: this.store.id,\n\t\t\t\t\t\t\tchanges,\n\t\t\t\t\t\t\tschema: this.serializedSchema,\n\t\t\t\t\t\t})\n\t\t\t\t\t)\n\t\t\t\t\tthis.schedulePersist()\n\t\t\t\t},\n\t\t\t\t{ source: 'user', scope: 'document' }\n\t\t\t)\n\t\t)\n\t\tthis.disposables.add(\n\t\t\tstore.listen(\n\t\t\t\t() => {\n\t\t\t\t\tthis.diffQueue.push(UPDATE_INSTANCE_STATE)\n\t\t\t\t\tthis.schedulePersist()\n\t\t\t\t},\n\t\t\t\t{ scope: 'session' }\n\t\t\t)\n\t\t)\n\n\t\tthis.connect(onLoad, onLoadError)\n\n\t\tthis.documentTypes = new Set(\n\t\t\tObject.values(this.store.schema.types)\n\t\t\t\t.filter((t) => t.scope === 'document')\n\t\t\t\t.map((t) => t.typeName)\n\t\t)\n\t}\n\n\tprivate async connect(onLoad: (client: this) => void, onLoadError: (error: Error) => void) {\n\t\tthis.debug('connecting')\n\t\tlet data: UnpackPromise<ReturnType<LocalIndexedDb['load']>> | undefined\n\n\t\ttry {\n\t\t\tdata = await this.db.load({ sessionId: this.sessionId })\n\t\t} catch (error: any) {\n\t\t\tonLoadError(error)\n\t\t\tshowCantReadFromIndexDbAlert()\n\t\t\treturn\n\t\t}\n\n\t\tthis.debug('loaded data from store', data, 'didDispose', this.didDispose)\n\t\tif (this.didDispose) return\n\n\t\ttry {\n\t\t\tif (data) {\n\t\t\t\tconst documentSnapshot = Object.fromEntries(data.records.map((r) => [r.id, r]))\n\t\t\t\tconst sessionStateSnapshot =\n\t\t\t\t\tdata.sessionStateSnapshot ?? extractSessionStateFromLegacySnapshot(documentSnapshot)\n\t\t\t\tconst migrationResult = this.store.schema.migrateStoreSnapshot({\n\t\t\t\t\tstore: documentSnapshot,\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\t\t\t\t\tschema: data.schema ?? this.store.schema.serializeEarliestVersion(),\n\t\t\t\t})\n\n\t\t\t\tif (migrationResult.type === 'error') {\n\t\t\t\t\tconsole.error('failed to migrate store', migrationResult)\n\t\t\t\t\tonLoadError(new Error(`Failed to migrate store: ${migrationResult.reason}`))\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tconst records = Object.values(migrationResult.value).filter((r) =>\n\t\t\t\t\tthis.documentTypes.has(r.typeName)\n\t\t\t\t)\n\t\t\t\tif (records.length > 0) {\n\t\t\t\t\t// 3. Merge the changes into the REAL STORE\n\t\t\t\t\tthis.store.mergeRemoteChanges(() => {\n\t\t\t\t\t\t// Calling put will validate the records!\n\t\t\t\t\t\tthis.store.put(records, 'initialize')\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\tif (sessionStateSnapshot) {\n\t\t\t\t\tloadSessionStateSnapshotIntoStore(this.store, sessionStateSnapshot, {\n\t\t\t\t\t\tforceOverwrite: true,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.channel.onmessage = ({ data }) => {\n\t\t\t\tthis.debug('got message', data)\n\t\t\t\tconst msg = data as Message\n\t\t\t\t// if their schema is earlier than ours, we need to tell them so they can refresh\n\t\t\t\t// if their schema is later than ours, we need to refresh\n\t\t\t\tconst res = this.store.schema.getMigrationsSince(msg.schema)\n\n\t\t\t\tif (!res.ok) {\n\t\t\t\t\t// we are older, refresh\n\t\t\t\t\t// but add a safety check to make sure we don't get in an infinite loop\n\t\t\t\t\tconst timeSinceInit = Date.now() - this.initTime\n\t\t\t\t\tif (timeSinceInit < 5000) {\n\t\t\t\t\t\t// This tab was just reloaded, but is out of date compared to other tabs.\n\t\t\t\t\t\t// Not expecting this to ever happen. It should only happen if we roll back a release that incremented\n\t\t\t\t\t\t// the schema version (which we should never do)\n\t\t\t\t\t\t// Or maybe during development if you have multiple local tabs open running the app on prod mode and you\n\t\t\t\t\t\t// check out an older commit. Dev server should be fine.\n\t\t\t\t\t\tonLoadError(new Error('Schema mismatch, please close other tabs and reload the page'))\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tthis.debug('reloading')\n\t\t\t\t\tthis.isReloading = true\n\t\t\t\t\twindow?.location?.reload?.()\n\t\t\t\t\treturn\n\t\t\t\t} else if (res.value.length > 0) {\n\t\t\t\t\t// they are older, tell them to refresh and not write any more data\n\t\t\t\t\tthis.debug('telling them to reload')\n\t\t\t\t\tthis.channel.postMessage({ type: 'announce', schema: this.serializedSchema })\n\t\t\t\t\t// schedule a full db write in case they wrote data anyway\n\t\t\t\t\tthis.shouldDoFullDBWrite = true\n\t\t\t\t\tthis.persistIfNeeded()\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\t// otherwise, all good, same version :)\n\t\t\t\tif (msg.type === 'diff') {\n\t\t\t\t\tthis.debug('applying diff')\n\t\t\t\t\ttransact(() => {\n\t\t\t\t\t\tthis.store.mergeRemoteChanges(() => {\n\t\t\t\t\t\t\tthis.store.applyDiff(msg.changes as any)\n\t\t\t\t\t\t})\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.channel.postMessage({ type: 'announce', schema: this.serializedSchema })\n\t\t\tthis.disposables.add(() => {\n\t\t\t\tthis.channel.close()\n\t\t\t})\n\t\t\tonLoad(this)\n\t\t} catch (e: any) {\n\t\t\tthis.debug('error loading data from store', e)\n\t\t\tif (this.didDispose) return\n\t\t\tonLoadError(e)\n\t\t\treturn\n\t\t}\n\t}\n\n\tclose() {\n\t\tthis.debug('closing')\n\t\tthis.didDispose = true\n\t\tthis.disposables.forEach((d) => d())\n\t\tif (typeof window !== 'undefined' && (window as any).tlsync === this) {\n\t\t\tdelete (window as any).tlsync\n\t\t}\n\t}\n\n\tprivate isPersisting = false\n\tprivate didLastWriteError = false\n\t// eslint-disable-next-line no-restricted-globals\n\tprivate scheduledPersistTimeout: ReturnType<typeof setTimeout> | null = null\n\n\t/**\n\t * Schedule a persist. Persists don't happen immediately: they are throttled to avoid writing too\n\t * often, and will retry if failed.\n\t *\n\t * @internal\n\t */\n\tprivate schedulePersist() {\n\t\tthis.debug('schedulePersist', this.scheduledPersistTimeout)\n\t\tif (this.scheduledPersistTimeout) return\n\t\t// eslint-disable-next-line no-restricted-globals\n\t\tthis.scheduledPersistTimeout = setTimeout(\n\t\t\t() => {\n\t\t\t\tthis.scheduledPersistTimeout = null\n\t\t\t\tthis.persistIfNeeded()\n\t\t\t},\n\t\t\tthis.didLastWriteError ? PERSIST_RETRY_THROTTLE_MS : PERSIST_THROTTLE_MS\n\t\t)\n\t}\n\n\t/**\n\t * Persist to IndexedDB only under certain circumstances:\n\t *\n\t * - If we're not already persisting\n\t * - If we're not reloading the page\n\t * - And we have something to persist (a full db write scheduled or changes in the diff queue)\n\t *\n\t * @internal\n\t */\n\tprivate persistIfNeeded() {\n\t\tthis.debug('persistIfNeeded', {\n\t\t\tisPersisting: this.isPersisting,\n\t\t\tisReloading: this.isReloading,\n\t\t\tshouldDoFullDBWrite: this.shouldDoFullDBWrite,\n\t\t\tdiffQueueLength: this.diffQueue.length,\n\t\t\tstoreIsPossiblyCorrupt: this.store.isPossiblyCorrupted(),\n\t\t})\n\n\t\t// if we've scheduled a persist for the future, that's no longer needed\n\t\tif (this.scheduledPersistTimeout) {\n\t\t\tclearTimeout(this.scheduledPersistTimeout)\n\t\t\tthis.scheduledPersistTimeout = null\n\t\t}\n\n\t\t// if a persist is already in progress, we don't need to do anything -\n\t\t// if there are still outstanding changes once it's finished, it'll\n\t\t// schedule another persist\n\t\tif (this.isPersisting) return\n\n\t\t// if we're reloading the page, it's because there's a newer client\n\t\t// present so lets not overwrite their changes\n\t\tif (this.isReloading) return\n\n\t\t// if the store is possibly corrupted, we don't want to persist\n\t\tif (this.store.isPossiblyCorrupted()) return\n\n\t\t// if we're scheduled for a full write or if we have changes outstanding, let's persist them!\n\t\tif (this.shouldDoFullDBWrite || this.diffQueue.length > 0) {\n\t\t\tthis.doPersist()\n\t\t}\n\t}\n\n\t/**\n\t * Actually persist to IndexedDB. If the write fails, then we'll retry with a full db write after\n\t * a short delay.\n\t */\n\tprivate async doPersist() {\n\t\tassert(!this.isPersisting, 'persist already in progress')\n\t\tif (this.didDispose) return\n\t\tthis.isPersisting = true\n\n\t\tthis.debug('doPersist start')\n\n\t\t// instantly empty the diff queue, but keep our own copy of it. this way\n\t\t// diffs that come in during the persist will still get tracked\n\t\tconst diffQueue = this.diffQueue\n\t\tthis.diffQueue = []\n\n\t\ttry {\n\t\t\tif (this.shouldDoFullDBWrite) {\n\t\t\t\tthis.shouldDoFullDBWrite = false\n\t\t\t\tawait this.db.storeSnapshot({\n\t\t\t\t\tschema: this.store.schema,\n\t\t\t\t\tsnapshot: this.store.serialize(),\n\t\t\t\t\tsessionId: this.sessionId,\n\t\t\t\t\tsessionStateSnapshot: this.$sessionStateSnapshot.get(),\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\tconst diffs = squashRecordDiffs(\n\t\t\t\t\tdiffQueue.filter((d): d is RecordsDiff<UnknownRecord> => d !== UPDATE_INSTANCE_STATE)\n\t\t\t\t)\n\t\t\t\tawait this.db.storeChanges({\n\t\t\t\t\tchanges: diffs,\n\t\t\t\t\tschema: this.store.schema,\n\t\t\t\t\tsessionId: this.sessionId,\n\t\t\t\t\tsessionStateSnapshot: this.$sessionStateSnapshot.get(),\n\t\t\t\t})\n\t\t\t}\n\t\t\tthis.didLastWriteError = false\n\t\t} catch (e) {\n\t\t\t// set this.shouldDoFullDBWrite because we clear the diffQueue no matter what,\n\t\t\t// so if this is just a temporary error, we will still persist all changes\n\t\t\tthis.shouldDoFullDBWrite = true\n\t\t\tthis.didLastWriteError = true\n\t\t\tconsole.error('failed to store changes in indexed db', e)\n\n\t\t\tshowCantWriteToIndexDbAlert()\n\t\t\tif (typeof window !== 'undefined') {\n\t\t\t\t// adios\n\t\t\t\twindow.location.reload()\n\t\t\t}\n\t\t}\n\n\t\tthis.isPersisting = false\n\t\tthis.debug('doPersist end')\n\n\t\t// changes might have come in between when we started the persist and\n\t\t// now. we request another persist so any new changes can get written\n\t\tthis.schedulePersist()\n\t}\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAiC;AACjC,mBAAgF;AAEhF,mBAAuB;AACvB,oCAMO;AACP,oBAA0E;AAC1E,4BAA+B;AAG/B,MAAM,sBAAsB;AAE5B,MAAM,4BAA4B;AAElC,MAAM,wBAAwB,uBAAO,uBAAuB;AA4B5D,MAAM,MAAM,CAACA,SAAiBA;AAGvB,MAAM,qBAAqB;AAAA,EACjC;AAAA,EACA,YAAY,OAAe;AAAA,EAE3B;AAAA,EACA,YAAY,MAAe;AAAA,EAE3B;AAAA,EACA,QAAQ;AAAA,EAER;AACD;AAEA,MAAM,KAAK,OAAO,qBAAqB,cAAc,uBAAuB;AAGrE,MAAM,kBAAkB;AAAA,
|
|
4
|
+
"sourcesContent": ["import { Signal, transact } from '@tldraw/state'\nimport { RecordsDiff, SerializedSchema, UnknownRecord, squashRecordDiffs } from '@tldraw/store'\nimport { TLStore } from '@tldraw/tlschema'\nimport { assert } from '@tldraw/utils'\nimport {\n\tTAB_ID,\n\tTLSessionStateSnapshot,\n\tcreateSessionStateSnapshotSignal,\n\textractSessionStateFromLegacySnapshot,\n\tloadSessionStateSnapshotIntoStore,\n} from '../../config/TLSessionStateSnapshot'\nimport { showCantReadFromIndexDbAlert, showCantWriteToIndexDbAlert } from './alerts'\nimport { LocalIndexedDb } from './LocalIndexedDb'\n\n/** How should we debounce persists? */\nconst PERSIST_THROTTLE_MS = 350\n/** If we're in an error state, how long should we wait before retrying a write? */\nconst PERSIST_RETRY_THROTTLE_MS = 10_000\n\nconst UPDATE_INSTANCE_STATE = Symbol('UPDATE_INSTANCE_STATE')\n\n/**\n * IMPORTANT!!!\n *\n * This is just a quick-n-dirty temporary solution that will be replaced with the remote sync client\n * once it has the db integrated\n */\n\ninterface SyncMessage {\n\ttype: 'diff'\n\tstoreId: string\n\tchanges: RecordsDiff<UnknownRecord>\n\tschema: SerializedSchema\n}\n\n// Sent by new clients when they connect\n// If another client is on the channel with a newer schema version\n// It will\ninterface AnnounceMessage {\n\ttype: 'announce'\n\tschema: SerializedSchema\n}\n\ntype Message = SyncMessage | AnnounceMessage\n\ntype UnpackPromise<T> = T extends Promise<infer U> ? U : T\n\nconst msg = (msg: Message) => msg\n\n/** @internal */\nexport class BroadcastChannelMock {\n\tonmessage?: (e: MessageEvent) => void\n\tconstructor(_name: string) {\n\t\t// noop\n\t}\n\tpostMessage(_msg: Message) {\n\t\t// noop\n\t}\n\tclose() {\n\t\t// noop\n\t}\n}\n\nconst BC = typeof BroadcastChannel === 'undefined' ? BroadcastChannelMock : BroadcastChannel\n\n/** @internal */\nexport class TLLocalSyncClient {\n\tprivate disposables = new Set<() => void>()\n\tprivate diffQueue: Array<RecordsDiff<UnknownRecord> | typeof UPDATE_INSTANCE_STATE> = []\n\tprivate didDispose = false\n\tprivate didLoad = false\n\tprivate shouldDoFullDBWrite = true\n\tprivate isReloading = false\n\treadonly persistenceKey: string\n\treadonly sessionId: string\n\treadonly serializedSchema: SerializedSchema\n\tprivate isDebugging = false\n\tprivate readonly documentTypes: ReadonlySet<string>\n\tprivate readonly $sessionStateSnapshot: Signal<TLSessionStateSnapshot | null>\n\t/** @internal */\n\treadonly db: LocalIndexedDb\n\n\tinitTime = Date.now()\n\tprivate debug(...args: any[]) {\n\t\tif (this.isDebugging) {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.debug(...args)\n\t\t}\n\t}\n\tconstructor(\n\t\tpublic readonly store: TLStore,\n\t\t{\n\t\t\tpersistenceKey,\n\t\t\tsessionId = TAB_ID,\n\t\t\tonLoad,\n\t\t\tonLoadError,\n\t\t}: {\n\t\t\tpersistenceKey: string\n\t\t\tsessionId?: string\n\t\t\tonLoad(self: TLLocalSyncClient): void\n\t\t\tonLoadError(error: Error): void\n\t\t},\n\t\tpublic readonly channel = new BC(`tldraw-tab-sync-${persistenceKey}`)\n\t) {\n\t\tif (typeof window !== 'undefined') {\n\t\t\t;(window as any).tlsync = this\n\t\t}\n\t\tthis.persistenceKey = persistenceKey\n\t\tthis.sessionId = sessionId\n\t\tthis.db = new LocalIndexedDb(persistenceKey)\n\t\tthis.disposables.add(() => this.db.close())\n\n\t\tthis.serializedSchema = this.store.schema.serialize()\n\t\tthis.$sessionStateSnapshot = createSessionStateSnapshotSignal(this.store)\n\n\t\tthis.disposables.add(\n\t\t\t// Set up a subscription to changes from the store: When\n\t\t\t// the store changes (and if the change was made by the user)\n\t\t\t// then immediately send the diff to other tabs via postMessage\n\t\t\t// and schedule a persist.\n\t\t\tstore.listen(\n\t\t\t\t({ changes }) => {\n\t\t\t\t\tthis.diffQueue.push(changes)\n\t\t\t\t\tthis.channel.postMessage(\n\t\t\t\t\t\tmsg({\n\t\t\t\t\t\t\ttype: 'diff',\n\t\t\t\t\t\t\tstoreId: this.store.id,\n\t\t\t\t\t\t\tchanges,\n\t\t\t\t\t\t\tschema: this.serializedSchema,\n\t\t\t\t\t\t})\n\t\t\t\t\t)\n\t\t\t\t\tthis.schedulePersist()\n\t\t\t\t},\n\t\t\t\t{ source: 'user', scope: 'document' }\n\t\t\t)\n\t\t)\n\t\tthis.disposables.add(\n\t\t\tstore.listen(\n\t\t\t\t() => {\n\t\t\t\t\tthis.diffQueue.push(UPDATE_INSTANCE_STATE)\n\t\t\t\t\tthis.schedulePersist()\n\t\t\t\t},\n\t\t\t\t{ scope: 'session' }\n\t\t\t)\n\t\t)\n\n\t\tif (typeof window !== 'undefined') {\n\t\t\t// Persists are throttled, so without this the last PERSIST_THROTTLE_MS of edits are lost\n\t\t\t// whenever the tab is closed or reloaded. `pagehide` is the last reliable event before\n\t\t\t// unload on desktop; on mobile the page can be discarded without it firing, so we also\n\t\t\t// flush when the tab is hidden.\n\t\t\tconst flush = () => {\n\t\t\t\t// Before the initial load completes a full write would overwrite the saved\n\t\t\t\t// document with an empty store.\n\t\t\t\tif (!this.didLoad) return\n\t\t\t\tthis.persistIfNeeded()\n\t\t\t}\n\t\t\tconst onVisibilityChange = () => {\n\t\t\t\tif (document.visibilityState === 'hidden') flush()\n\t\t\t}\n\t\t\twindow.addEventListener('pagehide', flush)\n\t\t\tdocument.addEventListener('visibilitychange', onVisibilityChange)\n\t\t\tthis.disposables.add(() => {\n\t\t\t\twindow.removeEventListener('pagehide', flush)\n\t\t\t\tdocument.removeEventListener('visibilitychange', onVisibilityChange)\n\t\t\t})\n\t\t}\n\n\t\tthis.connect(onLoad, onLoadError)\n\n\t\tthis.documentTypes = new Set(\n\t\t\tObject.values(this.store.schema.types)\n\t\t\t\t.filter((t) => t.scope === 'document')\n\t\t\t\t.map((t) => t.typeName)\n\t\t)\n\t}\n\n\tprivate async connect(onLoad: (client: this) => void, onLoadError: (error: Error) => void) {\n\t\tthis.debug('connecting')\n\t\tlet data: UnpackPromise<ReturnType<LocalIndexedDb['load']>> | undefined\n\n\t\ttry {\n\t\t\tdata = await this.db.load({ sessionId: this.sessionId })\n\t\t} catch (error: any) {\n\t\t\tonLoadError(error)\n\t\t\tshowCantReadFromIndexDbAlert()\n\t\t\treturn\n\t\t}\n\n\t\tthis.debug('loaded data from store', data, 'didDispose', this.didDispose)\n\t\tif (this.didDispose) return\n\n\t\ttry {\n\t\t\tif (data) {\n\t\t\t\tconst documentSnapshot = Object.fromEntries(data.records.map((r) => [r.id, r]))\n\t\t\t\tconst sessionStateSnapshot =\n\t\t\t\t\tdata.sessionStateSnapshot ?? extractSessionStateFromLegacySnapshot(documentSnapshot)\n\t\t\t\tconst migrationResult = this.store.schema.migrateStoreSnapshot({\n\t\t\t\t\tstore: documentSnapshot,\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\t\t\t\t\tschema: data.schema ?? this.store.schema.serializeEarliestVersion(),\n\t\t\t\t})\n\n\t\t\t\tif (migrationResult.type === 'error') {\n\t\t\t\t\tconsole.error('failed to migrate store', migrationResult)\n\t\t\t\t\tonLoadError(new Error(`Failed to migrate store: ${migrationResult.reason}`))\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tconst records = Object.values(migrationResult.value).filter((r) =>\n\t\t\t\t\tthis.documentTypes.has(r.typeName)\n\t\t\t\t)\n\t\t\t\tif (records.length > 0) {\n\t\t\t\t\t// 3. Merge the changes into the REAL STORE\n\t\t\t\t\tthis.store.mergeRemoteChanges(() => {\n\t\t\t\t\t\t// Calling put will validate the records!\n\t\t\t\t\t\tthis.store.put(records, 'initialize')\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\tif (sessionStateSnapshot) {\n\t\t\t\t\tloadSessionStateSnapshotIntoStore(this.store, sessionStateSnapshot, {\n\t\t\t\t\t\tforceOverwrite: true,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.channel.onmessage = ({ data }) => {\n\t\t\t\tthis.debug('got message', data)\n\t\t\t\tconst msg = data as Message\n\t\t\t\t// if their schema is earlier than ours, we need to tell them so they can refresh\n\t\t\t\t// if their schema is later than ours, we need to refresh\n\t\t\t\tconst res = this.store.schema.getMigrationsSince(msg.schema)\n\n\t\t\t\tif (!res.ok) {\n\t\t\t\t\t// we are older, refresh\n\t\t\t\t\t// but add a safety check to make sure we don't get in an infinite loop\n\t\t\t\t\tconst timeSinceInit = Date.now() - this.initTime\n\t\t\t\t\tif (timeSinceInit < 5000) {\n\t\t\t\t\t\t// This tab was just reloaded, but is out of date compared to other tabs.\n\t\t\t\t\t\t// Not expecting this to ever happen. It should only happen if we roll back a release that incremented\n\t\t\t\t\t\t// the schema version (which we should never do)\n\t\t\t\t\t\t// Or maybe during development if you have multiple local tabs open running the app on prod mode and you\n\t\t\t\t\t\t// check out an older commit. Dev server should be fine.\n\t\t\t\t\t\tonLoadError(new Error('Schema mismatch, please close other tabs and reload the page'))\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tthis.debug('reloading')\n\t\t\t\t\tthis.isReloading = true\n\t\t\t\t\twindow?.location?.reload?.()\n\t\t\t\t\treturn\n\t\t\t\t} else if (res.value.length > 0) {\n\t\t\t\t\t// they are older, tell them to refresh and not write any more data\n\t\t\t\t\tthis.debug('telling them to reload')\n\t\t\t\t\tthis.channel.postMessage({ type: 'announce', schema: this.serializedSchema })\n\t\t\t\t\t// schedule a full db write in case they wrote data anyway\n\t\t\t\t\tthis.shouldDoFullDBWrite = true\n\t\t\t\t\tthis.persistIfNeeded()\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\t// otherwise, all good, same version :)\n\t\t\t\tif (msg.type === 'diff') {\n\t\t\t\t\tthis.debug('applying diff')\n\t\t\t\t\ttransact(() => {\n\t\t\t\t\t\tthis.store.mergeRemoteChanges(() => {\n\t\t\t\t\t\t\tthis.store.applyDiff(msg.changes as any)\n\t\t\t\t\t\t})\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.channel.postMessage({ type: 'announce', schema: this.serializedSchema })\n\t\t\tthis.disposables.add(() => {\n\t\t\t\tthis.channel.close()\n\t\t\t})\n\t\t\tthis.didLoad = true\n\t\t\tonLoad(this)\n\t\t} catch (e: any) {\n\t\t\tthis.debug('error loading data from store', e)\n\t\t\tif (this.didDispose) return\n\t\t\tonLoadError(e)\n\t\t\treturn\n\t\t}\n\t}\n\n\tclose() {\n\t\tthis.debug('closing')\n\t\tthis.didDispose = true\n\t\tthis.disposables.forEach((d) => d())\n\t\tif (typeof window !== 'undefined' && (window as any).tlsync === this) {\n\t\t\tdelete (window as any).tlsync\n\t\t}\n\t}\n\n\tprivate isPersisting = false\n\tprivate didLastWriteError = false\n\t// eslint-disable-next-line no-restricted-globals\n\tprivate scheduledPersistTimeout: ReturnType<typeof setTimeout> | null = null\n\n\t/**\n\t * Schedule a persist. Persists don't happen immediately: they are throttled to avoid writing too\n\t * often, and will retry if failed.\n\t *\n\t * @internal\n\t */\n\tprivate schedulePersist() {\n\t\tthis.debug('schedulePersist', this.scheduledPersistTimeout)\n\t\tif (this.scheduledPersistTimeout) return\n\t\t// eslint-disable-next-line no-restricted-globals\n\t\tthis.scheduledPersistTimeout = setTimeout(\n\t\t\t() => {\n\t\t\t\tthis.scheduledPersistTimeout = null\n\t\t\t\tthis.persistIfNeeded()\n\t\t\t},\n\t\t\tthis.didLastWriteError ? PERSIST_RETRY_THROTTLE_MS : PERSIST_THROTTLE_MS\n\t\t)\n\t}\n\n\t/**\n\t * Persist to IndexedDB only under certain circumstances:\n\t *\n\t * - If we're not already persisting\n\t * - If we're not reloading the page\n\t * - And we have something to persist (a full db write scheduled or changes in the diff queue)\n\t *\n\t * @internal\n\t */\n\tprivate persistIfNeeded() {\n\t\tthis.debug('persistIfNeeded', {\n\t\t\tisPersisting: this.isPersisting,\n\t\t\tisReloading: this.isReloading,\n\t\t\tshouldDoFullDBWrite: this.shouldDoFullDBWrite,\n\t\t\tdiffQueueLength: this.diffQueue.length,\n\t\t\tstoreIsPossiblyCorrupt: this.store.isPossiblyCorrupted(),\n\t\t})\n\n\t\t// if we've scheduled a persist for the future, that's no longer needed\n\t\tif (this.scheduledPersistTimeout) {\n\t\t\tclearTimeout(this.scheduledPersistTimeout)\n\t\t\tthis.scheduledPersistTimeout = null\n\t\t}\n\n\t\t// if a persist is already in progress, we don't need to do anything -\n\t\t// if there are still outstanding changes once it's finished, it'll\n\t\t// schedule another persist\n\t\tif (this.isPersisting) return\n\n\t\t// if we're reloading the page, it's because there's a newer client\n\t\t// present so lets not overwrite their changes\n\t\tif (this.isReloading) return\n\n\t\t// if the store is possibly corrupted, we don't want to persist\n\t\tif (this.store.isPossiblyCorrupted()) return\n\n\t\t// if we're scheduled for a full write or if we have changes outstanding, let's persist them!\n\t\tif (this.shouldDoFullDBWrite || this.diffQueue.length > 0) {\n\t\t\tthis.doPersist()\n\t\t}\n\t}\n\n\t/**\n\t * Actually persist to IndexedDB. If the write fails, then we'll retry with a full db write after\n\t * a short delay.\n\t */\n\tprivate async doPersist() {\n\t\tassert(!this.isPersisting, 'persist already in progress')\n\t\tif (this.didDispose) return\n\t\tthis.isPersisting = true\n\n\t\tthis.debug('doPersist start')\n\n\t\t// instantly empty the diff queue, but keep our own copy of it. this way\n\t\t// diffs that come in during the persist will still get tracked\n\t\tconst diffQueue = this.diffQueue\n\t\tthis.diffQueue = []\n\n\t\ttry {\n\t\t\tif (this.shouldDoFullDBWrite) {\n\t\t\t\tthis.shouldDoFullDBWrite = false\n\t\t\t\tawait this.db.storeSnapshot({\n\t\t\t\t\tschema: this.store.schema,\n\t\t\t\t\tsnapshot: this.store.serialize(),\n\t\t\t\t\tsessionId: this.sessionId,\n\t\t\t\t\tsessionStateSnapshot: this.$sessionStateSnapshot.get(),\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\tconst diffs = squashRecordDiffs(\n\t\t\t\t\tdiffQueue.filter((d): d is RecordsDiff<UnknownRecord> => d !== UPDATE_INSTANCE_STATE)\n\t\t\t\t)\n\t\t\t\tawait this.db.storeChanges({\n\t\t\t\t\tchanges: diffs,\n\t\t\t\t\tschema: this.store.schema,\n\t\t\t\t\tsessionId: this.sessionId,\n\t\t\t\t\tsessionStateSnapshot: this.$sessionStateSnapshot.get(),\n\t\t\t\t})\n\t\t\t}\n\t\t\tthis.didLastWriteError = false\n\t\t} catch (e) {\n\t\t\t// set this.shouldDoFullDBWrite because we clear the diffQueue no matter what,\n\t\t\t// so if this is just a temporary error, we will still persist all changes\n\t\t\tthis.shouldDoFullDBWrite = true\n\t\t\tthis.didLastWriteError = true\n\t\t\tconsole.error('failed to store changes in indexed db', e)\n\n\t\t\tshowCantWriteToIndexDbAlert()\n\t\t\tif (typeof window !== 'undefined') {\n\t\t\t\t// adios\n\t\t\t\twindow.location.reload()\n\t\t\t}\n\t\t}\n\n\t\tthis.isPersisting = false\n\t\tthis.debug('doPersist end')\n\n\t\t// changes might have come in between when we started the persist and\n\t\t// now. we request another persist so any new changes can get written\n\t\tthis.schedulePersist()\n\t}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["msg", "data"]
|
|
7
7
|
}
|
|
@@ -33,7 +33,7 @@ Keep seeing this message?
|
|
|
33
33
|
}
|
|
34
34
|
function showCantReadFromIndexDbAlert() {
|
|
35
35
|
window.alert(
|
|
36
|
-
`Oops! We could not access your browser's storage\u2014and the app won't work correctly without that.
|
|
36
|
+
`Oops! We could not access your browser's storage\u2014and the app won't work correctly without that. Reload the page to try again.
|
|
37
37
|
|
|
38
38
|
Keep seeing this message?
|
|
39
39
|
\u2022 If you're using tldraw in a private or "incognito" window, try loading tldraw in a regular window or in a different browser.`
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/utils/sync/alerts.ts"],
|
|
4
|
-
"sourcesContent": ["/** @internal */\nexport function showCantWriteToIndexDbAlert() {\n\twindow.alert(\n\t\t`Oops! We could not save changes to your browser's storage. We now need to reload the page and try again.\n\nKeep seeing this message?\n\u2022 If you're using tldraw in a private or \"incognito\" window, try loading tldraw in a regular window or in a different browser.\n\u2022 If your hard disk is full, try clearing up some space and then reload the page.`\n\t)\n}\n\n/** @internal */\nexport function showCantReadFromIndexDbAlert() {\n\twindow.alert(\n\t\t`Oops! We could not access your browser's storage\u2014and the app won't work correctly without that.
|
|
4
|
+
"sourcesContent": ["/** @internal */\nexport function showCantWriteToIndexDbAlert() {\n\twindow.alert(\n\t\t`Oops! We could not save changes to your browser's storage. We now need to reload the page and try again.\n\nKeep seeing this message?\n\u2022 If you're using tldraw in a private or \"incognito\" window, try loading tldraw in a regular window or in a different browser.\n\u2022 If your hard disk is full, try clearing up some space and then reload the page.`\n\t)\n}\n\n/** @internal */\nexport function showCantReadFromIndexDbAlert() {\n\twindow.alert(\n\t\t`Oops! We could not access your browser's storage\u2014and the app won't work correctly without that. Reload the page to try again.\n\nKeep seeing this message?\n\u2022 If you're using tldraw in a private or \"incognito\" window, try loading tldraw in a regular window or in a different browser.`\n\t)\n}\n"],
|
|
5
5
|
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACO,SAAS,8BAA8B;AAC7C,SAAO;AAAA,IACN;AAAA;AAAA;AAAA;AAAA;AAAA,EAKD;AACD;AAGO,SAAS,+BAA+B;AAC9C,SAAO;AAAA,IACN;AAAA;AAAA;AAAA;AAAA,EAID;AACD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist-cjs/version.js
CHANGED
|
@@ -22,10 +22,10 @@ __export(version_exports, {
|
|
|
22
22
|
version: () => version
|
|
23
23
|
});
|
|
24
24
|
module.exports = __toCommonJS(version_exports);
|
|
25
|
-
const version = "5.4.
|
|
25
|
+
const version = "5.4.1";
|
|
26
26
|
const publishDates = {
|
|
27
27
|
major: "2026-05-06T16:28:18.473Z",
|
|
28
|
-
minor: "2026-
|
|
29
|
-
patch: "2026-
|
|
28
|
+
minor: "2026-09-02T11:04:02.901Z",
|
|
29
|
+
patch: "2026-09-08T10:52:09.132Z"
|
|
30
30
|
};
|
|
31
31
|
//# sourceMappingURL=version.js.map
|
package/dist-cjs/version.js.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 = '5.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 = '5.4.1'\nexport const publishDates = {\n\tmajor: '2026-05-06T16:28:18.473Z',\n\tminor: '2026-09-02T11:04:02.901Z',\n\tpatch: '2026-09-08T10:52:09.132Z',\n}\n"],
|
|
5
5
|
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGO,MAAM,UAAU;AAChB,MAAM,eAAe;AAAA,EAC3B,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AACR;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist-esm/index.d.mts
CHANGED
|
@@ -18,8 +18,8 @@ import { IndexKey } from '@tldraw/utils';
|
|
|
18
18
|
import { JsonObject } from '@tldraw/utils';
|
|
19
19
|
import { JSX } from 'react/jsx-runtime';
|
|
20
20
|
import { LegacyMigrations } from '@tldraw/store';
|
|
21
|
+
import { MemoExoticComponent } from 'react';
|
|
21
22
|
import { MigrationSequence } from '@tldraw/store';
|
|
22
|
-
import { NamedExoticComponent } from 'react';
|
|
23
23
|
import { Node as Node_2 } from '@tiptap/pm/model';
|
|
24
24
|
import { PerformanceTracker } from '@tldraw/utils';
|
|
25
25
|
import * as React_2 from 'react';
|
|
@@ -68,6 +68,7 @@ import { TLImageAsset } from '@tldraw/tlschema';
|
|
|
68
68
|
import { TLInstance } from '@tldraw/tlschema';
|
|
69
69
|
import { TLInstancePageState } from '@tldraw/tlschema';
|
|
70
70
|
import { TLInstancePresence } from '@tldraw/tlschema';
|
|
71
|
+
import { TLOpacityType } from '@tldraw/tlschema';
|
|
71
72
|
import { TLPage } from '@tldraw/tlschema';
|
|
72
73
|
import { TLPageId } from '@tldraw/tlschema';
|
|
73
74
|
import { TLParentId } from '@tldraw/tlschema';
|
|
@@ -556,13 +557,13 @@ export declare class BoundsSnaps {
|
|
|
556
557
|
private getSnappablePoints;
|
|
557
558
|
private getSnappableGapNodes;
|
|
558
559
|
private getVisibleGaps;
|
|
559
|
-
snapTranslateShapes({ lockedAxis, initialSelectionPageBounds, initialSelectionSnapPoints, dragDelta }: {
|
|
560
|
+
snapTranslateShapes({ lockedAxis, initialSelectionPageBounds, initialSelectionSnapPoints, dragDelta, }: {
|
|
560
561
|
dragDelta: Vec;
|
|
561
562
|
initialSelectionPageBounds: Box;
|
|
562
563
|
initialSelectionSnapPoints: BoundsSnapPoint[];
|
|
563
564
|
lockedAxis: 'x' | 'y' | null;
|
|
564
565
|
}): SnapData;
|
|
565
|
-
snapResizeShapes({ initialSelectionPageBounds, dragDelta, handle: originalHandle, isAspectRatioLocked, isResizingFromCenter }: {
|
|
566
|
+
snapResizeShapes({ initialSelectionPageBounds, dragDelta, handle: originalHandle, isAspectRatioLocked, isResizingFromCenter, }: {
|
|
566
567
|
dragDelta: Vec;
|
|
567
568
|
handle: SelectionCorner | SelectionEdge;
|
|
568
569
|
initialSelectionPageBounds: Box;
|
|
@@ -844,7 +845,7 @@ export declare const coreShapes: readonly [typeof GroupShapeUtil];
|
|
|
844
845
|
export declare function counterClockwiseAngleDist(a0: number, a1: number): number;
|
|
845
846
|
|
|
846
847
|
/** @public */
|
|
847
|
-
export declare function createDebugValue<T>(name: string, { defaults, shouldStoreForSession }: {
|
|
848
|
+
export declare function createDebugValue<T>(name: string, { defaults, shouldStoreForSession, }: {
|
|
848
849
|
defaults: DebugFlagDefaults<T>;
|
|
849
850
|
shouldStoreForSession?: boolean;
|
|
850
851
|
}): DebugFlag<T>;
|
|
@@ -875,8 +876,8 @@ export declare function createSessionStateSnapshotSignal(store: TLStore): Signal
|
|
|
875
876
|
|
|
876
877
|
/** @public */
|
|
877
878
|
export declare function createTLCurrentUser(opts?: {
|
|
878
|
-
setUserPreferences?: (
|
|
879
|
-
userPreferences?: Signal<TLUserPreferences
|
|
879
|
+
setUserPreferences?: (userPreferences: TLUserPreferences) => void;
|
|
880
|
+
userPreferences?: Signal<TLUserPreferences>;
|
|
880
881
|
}): TLCurrentUser;
|
|
881
882
|
|
|
882
883
|
/**
|
|
@@ -991,7 +992,7 @@ export declare function DefaultCanvas({ className }: TLCanvasComponentProps): JS
|
|
|
991
992
|
*
|
|
992
993
|
* @public @react
|
|
993
994
|
*/
|
|
994
|
-
export declare const DefaultCursor:
|
|
995
|
+
export declare const DefaultCursor: MemoExoticComponent<({ className, zoom, point, color, name, chatMessage, }: TLCursorProps) => JSX.Element | null>;
|
|
995
996
|
|
|
996
997
|
/** @public @react */
|
|
997
998
|
export declare const DefaultErrorFallback: TLErrorFallbackComponent;
|
|
@@ -1010,7 +1011,7 @@ export declare function DefaultSvgDefs(): null;
|
|
|
1010
1011
|
|
|
1011
1012
|
/** @public */
|
|
1012
1013
|
export declare const defaultTldrawOptions: {
|
|
1013
|
-
readonly actionShortcutsLocation:
|
|
1014
|
+
readonly actionShortcutsLocation: 'swap';
|
|
1014
1015
|
readonly adjacentShapeMargin: 10;
|
|
1015
1016
|
readonly animationMediumMs: 320;
|
|
1016
1017
|
readonly camera: TLCameraOptions;
|
|
@@ -1182,11 +1183,12 @@ export declare class EdgeScrollManager {
|
|
|
1182
1183
|
/** @public */
|
|
1183
1184
|
export declare class Editor extends EventEmitter<TLEventMap> {
|
|
1184
1185
|
readonly id: string;
|
|
1185
|
-
constructor({ store, user, shapeUtils, bindingUtils, assetUtils: assetUtilConstructors, overlayUtils: overlayUtilConstructors, tools, getContainer, cameraOptions, initialState, autoFocus, options: _options, textOptions: _textOptions, getShapeVisibility, colorScheme, fontAssetUrls, themes, initialTheme }: TLEditorOptions);
|
|
1186
|
+
constructor({ store, user, shapeUtils, bindingUtils, assetUtils: assetUtilConstructors, overlayUtils: overlayUtilConstructors, tools, getContainer, cameraOptions, initialState, autoFocus, options: _options, textOptions: _textOptions, getShapeVisibility, colorScheme, fontAssetUrls, themes, initialTheme, }: TLEditorOptions);
|
|
1186
1187
|
private readonly _getShapeVisibility?;
|
|
1187
1188
|
private getIsShapeHiddenCache;
|
|
1188
1189
|
isShapeHidden(shapeOrId: TLShape | TLShapeId): boolean;
|
|
1189
1190
|
readonly options: TldrawOptions;
|
|
1191
|
+
/* Excluded from this release type: licenseManager */
|
|
1190
1192
|
readonly contextId: string;
|
|
1191
1193
|
/**
|
|
1192
1194
|
* The editor's store
|
|
@@ -1274,8 +1276,8 @@ export declare class Editor extends EventEmitter<TLEventMap> {
|
|
|
1274
1276
|
readonly timers: {
|
|
1275
1277
|
dispose: () => void;
|
|
1276
1278
|
requestAnimationFrame: (callback: FrameRequestCallback) => number;
|
|
1277
|
-
setInterval: (handler: TimerHandler, timeout?: number
|
|
1278
|
-
setTimeout: (handler: TimerHandler, timeout?: number
|
|
1279
|
+
setInterval: (handler: TimerHandler, timeout?: number, ...args: any[]) => number;
|
|
1280
|
+
setTimeout: (handler: TimerHandler, timeout?: number, ...args: any[]) => number;
|
|
1279
1281
|
};
|
|
1280
1282
|
/**
|
|
1281
1283
|
* A manager for remote peer collaborators connected to this editor.
|
|
@@ -1808,14 +1810,14 @@ export declare class Editor extends EventEmitter<TLEventMap> {
|
|
|
1808
1810
|
* @public
|
|
1809
1811
|
*/
|
|
1810
1812
|
getPageStates(): TLInstancePageState[];
|
|
1811
|
-
|
|
1813
|
+
/* Excluded from this release type: _getPageStatesQuery */
|
|
1812
1814
|
/**
|
|
1813
1815
|
* The current page state.
|
|
1814
1816
|
*
|
|
1815
1817
|
* @public
|
|
1816
1818
|
*/
|
|
1817
1819
|
getCurrentPageState(): TLInstancePageState;
|
|
1818
|
-
|
|
1820
|
+
/* Excluded from this release type: _getCurrentPageStateId */
|
|
1819
1821
|
/**
|
|
1820
1822
|
* Update this instance's page state.
|
|
1821
1823
|
*
|
|
@@ -2208,7 +2210,7 @@ export declare class Editor extends EventEmitter<TLEventMap> {
|
|
|
2208
2210
|
*
|
|
2209
2211
|
* @public */
|
|
2210
2212
|
getTextOptions(): TLTextOptions;
|
|
2211
|
-
|
|
2213
|
+
/* Excluded from this release type: _unsafe_getCameraId */
|
|
2212
2214
|
/**
|
|
2213
2215
|
* The current camera.
|
|
2214
2216
|
*
|
|
@@ -2276,6 +2278,7 @@ export declare class Editor extends EventEmitter<TLEventMap> {
|
|
|
2276
2278
|
*
|
|
2277
2279
|
* @public */
|
|
2278
2280
|
getBaseZoom(): number;
|
|
2281
|
+
private _getFitZoom;
|
|
2279
2282
|
private _cameraOptions;
|
|
2280
2283
|
/**
|
|
2281
2284
|
* Get the current camera options.
|
|
@@ -2464,10 +2467,10 @@ export declare class Editor extends EventEmitter<TLEventMap> {
|
|
|
2464
2467
|
*/
|
|
2465
2468
|
slideCamera(opts?: {
|
|
2466
2469
|
direction: VecLike;
|
|
2467
|
-
force?: boolean
|
|
2468
|
-
friction?: number
|
|
2470
|
+
force?: boolean;
|
|
2471
|
+
friction?: number;
|
|
2469
2472
|
speed: number;
|
|
2470
|
-
speedThreshold?: number
|
|
2473
|
+
speedThreshold?: number;
|
|
2471
2474
|
}): this;
|
|
2472
2475
|
/**
|
|
2473
2476
|
* Animate the camera to a user's cursor position. This also briefly show the user's cursor if it's not currently visible.
|
|
@@ -2826,7 +2829,7 @@ export declare class Editor extends EventEmitter<TLEventMap> {
|
|
|
2826
2829
|
* @public
|
|
2827
2830
|
*/
|
|
2828
2831
|
renamePage(page: TLPage | TLPageId, name: string): this;
|
|
2829
|
-
|
|
2832
|
+
/* Excluded from this release type: _getAllAssetsQuery */
|
|
2830
2833
|
/**
|
|
2831
2834
|
* Get all assets in the editor.
|
|
2832
2835
|
*
|
|
@@ -2915,7 +2918,7 @@ export declare class Editor extends EventEmitter<TLEventMap> {
|
|
|
2915
2918
|
* @public
|
|
2916
2919
|
*/
|
|
2917
2920
|
getShapeGeometry<T extends Geometry2d>(shape: TLShape | TLShapeId, opts?: TLGeometryOpts): T;
|
|
2918
|
-
|
|
2921
|
+
/* Excluded from this release type: _getShapeHandlesCache */
|
|
2919
2922
|
/**
|
|
2920
2923
|
* Get the handles (if any) for a shape.
|
|
2921
2924
|
*
|
|
@@ -2945,7 +2948,7 @@ export declare class Editor extends EventEmitter<TLEventMap> {
|
|
|
2945
2948
|
* @public
|
|
2946
2949
|
*/
|
|
2947
2950
|
getShapeLocalTransform(shape: TLShape | TLShapeId): Mat;
|
|
2948
|
-
|
|
2951
|
+
/* Excluded from this release type: _getShapePageTransformCache */
|
|
2949
2952
|
/**
|
|
2950
2953
|
* Get the local transform of a shape's parent as a matrix model.
|
|
2951
2954
|
*
|
|
@@ -2973,7 +2976,7 @@ export declare class Editor extends EventEmitter<TLEventMap> {
|
|
|
2973
2976
|
* @public
|
|
2974
2977
|
*/
|
|
2975
2978
|
getShapePageTransform(shape: TLShape | TLShapeId): Mat;
|
|
2976
|
-
|
|
2979
|
+
/* Excluded from this release type: _getShapePageBoundsCache */
|
|
2977
2980
|
/**
|
|
2978
2981
|
* Get the bounds of a shape in the current page space.
|
|
2979
2982
|
*
|
|
@@ -2988,7 +2991,7 @@ export declare class Editor extends EventEmitter<TLEventMap> {
|
|
|
2988
2991
|
* @public
|
|
2989
2992
|
*/
|
|
2990
2993
|
getShapePageBounds(shape: TLShape | TLShapeId): Box | undefined;
|
|
2991
|
-
|
|
2994
|
+
/* Excluded from this release type: _getShapeClipPathCache */
|
|
2992
2995
|
/**
|
|
2993
2996
|
* Get the clip path for a shape.
|
|
2994
2997
|
*
|
|
@@ -3005,7 +3008,7 @@ export declare class Editor extends EventEmitter<TLEventMap> {
|
|
|
3005
3008
|
* @public
|
|
3006
3009
|
*/
|
|
3007
3010
|
getShapeClipPath(shape: TLShape | TLShapeId): string | undefined;
|
|
3008
|
-
|
|
3011
|
+
/* Excluded from this release type: _getShapeMaskCache */
|
|
3009
3012
|
/**
|
|
3010
3013
|
* Get the mask (in the current page space) for a shape.
|
|
3011
3014
|
*
|
|
@@ -3037,7 +3040,7 @@ export declare class Editor extends EventEmitter<TLEventMap> {
|
|
|
3037
3040
|
* @public
|
|
3038
3041
|
*/
|
|
3039
3042
|
getShapeMaskedPageBounds(shape: TLShape | TLShapeId): Box | undefined;
|
|
3040
|
-
|
|
3043
|
+
/* Excluded from this release type: _getShapeMaskedPageBoundsCache */
|
|
3041
3044
|
/**
|
|
3042
3045
|
* Get the ancestors of a shape.
|
|
3043
3046
|
*
|
|
@@ -3158,8 +3161,8 @@ export declare class Editor extends EventEmitter<TLEventMap> {
|
|
|
3158
3161
|
* @public
|
|
3159
3162
|
*/
|
|
3160
3163
|
getShapesAtPoint(point: VecLike, opts?: {
|
|
3161
|
-
hitInside?: boolean
|
|
3162
|
-
margin?: number
|
|
3164
|
+
hitInside?: boolean;
|
|
3165
|
+
margin?: number;
|
|
3163
3166
|
}): TLShape[];
|
|
3164
3167
|
/**
|
|
3165
3168
|
* Get shape IDs within the given bounds.
|
|
@@ -3195,8 +3198,8 @@ export declare class Editor extends EventEmitter<TLEventMap> {
|
|
|
3195
3198
|
* @public
|
|
3196
3199
|
*/
|
|
3197
3200
|
isPointInShape(shape: TLShape | TLShapeId, point: VecLike, opts?: {
|
|
3198
|
-
hitInside?: boolean
|
|
3199
|
-
margin?: number
|
|
3201
|
+
hitInside?: boolean;
|
|
3202
|
+
margin?: number;
|
|
3200
3203
|
}): boolean;
|
|
3201
3204
|
/**
|
|
3202
3205
|
* Convert a point in the current page space to a point in the local space of a shape. For example, if a
|
|
@@ -3484,7 +3487,7 @@ export declare class Editor extends EventEmitter<TLEventMap> {
|
|
|
3484
3487
|
* Delete a binding by its ID. If the binding doesn't exist, it's ignored.
|
|
3485
3488
|
*/
|
|
3486
3489
|
deleteBinding(binding: TLBinding | TLBindingId, opts?: Parameters<this['deleteBindings']>[1]): this;
|
|
3487
|
-
canBindShapes({ fromShape, toShape, binding }: {
|
|
3490
|
+
canBindShapes({ fromShape, toShape, binding, }: {
|
|
3488
3491
|
binding: {
|
|
3489
3492
|
type: TLBinding['type'];
|
|
3490
3493
|
} | TLBinding | TLBinding['type'];
|
|
@@ -3950,8 +3953,8 @@ export declare class Editor extends EventEmitter<TLEventMap> {
|
|
|
3950
3953
|
*/
|
|
3951
3954
|
deleteShape(id: TLShapeId): this;
|
|
3952
3955
|
deleteShape(shape: TLShape): this;
|
|
3953
|
-
/* Excluded from this release type:
|
|
3954
|
-
|
|
3956
|
+
/* Excluded from this release type: _getStyleableShapes */
|
|
3957
|
+
/* Excluded from this release type: _getSelectionSharedStyles */
|
|
3955
3958
|
/**
|
|
3956
3959
|
* Get the style for the next shape.
|
|
3957
3960
|
*
|
|
@@ -4140,7 +4143,7 @@ export declare class Editor extends EventEmitter<TLEventMap> {
|
|
|
4140
4143
|
* @param opts - Options for handling external content, including force flag to bypass readonly checks.
|
|
4141
4144
|
*/
|
|
4142
4145
|
putExternalContent<E>(info: TLExternalContent<E>, opts?: {
|
|
4143
|
-
force?: boolean
|
|
4146
|
+
force?: boolean;
|
|
4144
4147
|
}): Promise<void>;
|
|
4145
4148
|
/**
|
|
4146
4149
|
* Handle replacing external content.
|
|
@@ -4149,7 +4152,7 @@ export declare class Editor extends EventEmitter<TLEventMap> {
|
|
|
4149
4152
|
* @param opts - Options for handling external content, including force flag to bypass readonly checks.
|
|
4150
4153
|
*/
|
|
4151
4154
|
replaceExternalContent<E>(info: TLExternalContent<E>, opts?: {
|
|
4152
|
-
force?: boolean
|
|
4155
|
+
force?: boolean;
|
|
4153
4156
|
}): Promise<void>;
|
|
4154
4157
|
/**
|
|
4155
4158
|
* Get content that can be exported for the given shape ids.
|
|
@@ -5040,7 +5043,7 @@ export declare class Group2d extends Geometry2d {
|
|
|
5040
5043
|
|
|
5041
5044
|
/** @public */
|
|
5042
5045
|
export declare class GroupShapeUtil extends ShapeUtil<TLGroupShape> {
|
|
5043
|
-
static type:
|
|
5046
|
+
static type: 'group';
|
|
5044
5047
|
static props: RecordProps<TLGroupShape>;
|
|
5045
5048
|
static migrations: TLPropsMigrations;
|
|
5046
5049
|
hideSelectionBoundsFg(shape: TLGroupShape): boolean;
|
|
@@ -5104,7 +5107,7 @@ export declare class HandleSnaps {
|
|
|
5104
5107
|
private iterateSnapOutlines;
|
|
5105
5108
|
private getHandleSnapPosition;
|
|
5106
5109
|
private getHandleSnapData;
|
|
5107
|
-
snapHandle({ currentShapeId, handle }: {
|
|
5110
|
+
snapHandle({ currentShapeId, handle, }: {
|
|
5108
5111
|
currentShapeId: TLShapeId;
|
|
5109
5112
|
handle: TLHandle;
|
|
5110
5113
|
}): null | SnapData;
|
|
@@ -5167,6 +5170,15 @@ export declare const inlineBase64AssetStore: TLAssetStore;
|
|
|
5167
5170
|
/** @public */
|
|
5168
5171
|
export declare class InputsManager extends EditorManager {
|
|
5169
5172
|
constructor(editor: Editor);
|
|
5173
|
+
private _detachActivityListenersFn;
|
|
5174
|
+
/**
|
|
5175
|
+
* User input anywhere in the editor's tab counts as activity for collaborator presence —
|
|
5176
|
+
* presence means "this person is here", whether or not the input lands on the editor itself
|
|
5177
|
+
* (e.g. typing in a sidebar next to the canvas). Listen in the capture phase so input that
|
|
5178
|
+
* other handlers swallow still counts.
|
|
5179
|
+
*/
|
|
5180
|
+
private _attachActivityListeners;
|
|
5181
|
+
private _detachActivityListeners;
|
|
5170
5182
|
private _onFrame;
|
|
5171
5183
|
private _originPagePoint;
|
|
5172
5184
|
/**
|
|
@@ -5385,6 +5397,26 @@ export declare class InputsManager extends EditorManager {
|
|
|
5385
5397
|
set isSpacebarPanning(isSpacebarPanning: boolean);
|
|
5386
5398
|
/* Excluded from this release type: setIsSpacebarPanning */
|
|
5387
5399
|
private _getHasCollaborators;
|
|
5400
|
+
private readonly _throttledActivityStamp;
|
|
5401
|
+
/**
|
|
5402
|
+
* Mark the current user as active for collaborator presence. User input anywhere in the
|
|
5403
|
+
* editor's tab counts as activity automatically; call this to make input that doesn't produce
|
|
5404
|
+
* DOM events count too, so peers don't classify this user as idle or inactive while they're
|
|
5405
|
+
* still interacting. Calls are throttled on the leading edge, so it's safe to call from
|
|
5406
|
+
* high-frequency input events.
|
|
5407
|
+
*
|
|
5408
|
+
* @example
|
|
5409
|
+
* ```ts
|
|
5410
|
+
* // Gamepads are polled rather than event-driven, so stamp activity from the poll
|
|
5411
|
+
* editor.timers.setInterval(() => {
|
|
5412
|
+
* const isPressed = navigator
|
|
5413
|
+
* .getGamepads()
|
|
5414
|
+
* .some((pad) => pad?.buttons.some((button) => button.pressed))
|
|
5415
|
+
* if (isPressed) editor.inputs.markActivity()
|
|
5416
|
+
* }, 50)
|
|
5417
|
+
* ```
|
|
5418
|
+
*/
|
|
5419
|
+
markActivity(): void;
|
|
5388
5420
|
/* Excluded from this release type: _velocityPrevPoint */
|
|
5389
5421
|
/* Excluded from this release type: updatePointerVelocity */
|
|
5390
5422
|
/* Excluded from this release type: updateFromEvent */
|
|
@@ -6233,11 +6265,11 @@ export declare interface RichTextFontVisitorState {
|
|
|
6233
6265
|
|
|
6234
6266
|
/** @public */
|
|
6235
6267
|
export declare const ROTATE_CORNER_TO_SELECTION_CORNER: {
|
|
6236
|
-
readonly bottom_left_rotate:
|
|
6237
|
-
readonly bottom_right_rotate:
|
|
6238
|
-
readonly mobile_rotate:
|
|
6239
|
-
readonly top_left_rotate:
|
|
6240
|
-
readonly top_right_rotate:
|
|
6268
|
+
readonly bottom_left_rotate: 'bottom_left';
|
|
6269
|
+
readonly bottom_right_rotate: 'bottom_right';
|
|
6270
|
+
readonly mobile_rotate: 'top_left';
|
|
6271
|
+
readonly top_left_rotate: 'top_left';
|
|
6272
|
+
readonly top_right_rotate: 'top_right';
|
|
6241
6273
|
};
|
|
6242
6274
|
|
|
6243
6275
|
/** @public */
|
|
@@ -7236,7 +7268,7 @@ export declare type SharedStyle<T> = {
|
|
|
7236
7268
|
export declare function shortAngleDist(a0: number, a1: number): number;
|
|
7237
7269
|
|
|
7238
7270
|
/** @public */
|
|
7239
|
-
export declare const SIDES: readonly [
|
|
7271
|
+
export declare const SIDES: readonly ['top', 'right', 'bottom', 'left'];
|
|
7240
7272
|
|
|
7241
7273
|
/** @public */
|
|
7242
7274
|
export declare const SIN: (x: number) => number;
|
|
@@ -7957,7 +7989,7 @@ export declare interface TLDragShapesOverInfo {
|
|
|
7957
7989
|
}
|
|
7958
7990
|
|
|
7959
7991
|
/** @public @react */
|
|
7960
|
-
export declare const TldrawEditor: React_3.
|
|
7992
|
+
export declare const TldrawEditor: React_3.MemoExoticComponent<({ store, components, className, user: _user, options: _options, textOptions: _textOptions, deepLinks: _deepLinks, ...rest }: TldrawEditorProps) => JSX.Element>;
|
|
7961
7993
|
|
|
7962
7994
|
/**
|
|
7963
7995
|
* Base props for the {@link tldraw#Tldraw} and {@link TldrawEditor} components.
|
|
@@ -8511,6 +8543,38 @@ export declare interface TLEditorRunOptions extends TLHistoryBatchOptions {
|
|
|
8511
8543
|
ignoreShapeLock?: boolean;
|
|
8512
8544
|
}
|
|
8513
8545
|
|
|
8546
|
+
/**
|
|
8547
|
+
* A global registry of currently mounted editor instances. Use it to discover live editors from
|
|
8548
|
+
* outside the React tree, for example from sidebar chrome, keyboard shortcuts, or multi-editor
|
|
8549
|
+
* layouts.
|
|
8550
|
+
*
|
|
8551
|
+
* @example
|
|
8552
|
+
* ```ts
|
|
8553
|
+
* tleditors.getMounted() // readonly Editor[]
|
|
8554
|
+
*
|
|
8555
|
+
* const editors = useValue('mounted editors', () => tleditors.getMounted(), [])
|
|
8556
|
+
* ```
|
|
8557
|
+
*
|
|
8558
|
+
* @public
|
|
8559
|
+
*/
|
|
8560
|
+
export declare const tleditors: {
|
|
8561
|
+
/**
|
|
8562
|
+
* A reactive list of currently mounted editor instances.
|
|
8563
|
+
*
|
|
8564
|
+
* An editor is added when it emits the `mount` event and removed when it emits `unmount`
|
|
8565
|
+
* (including when the editor is disposed while still mounted).
|
|
8566
|
+
*
|
|
8567
|
+
* @public
|
|
8568
|
+
*/
|
|
8569
|
+
mounted: Signal<readonly Editor[]>;
|
|
8570
|
+
/**
|
|
8571
|
+
* Get the currently mounted editor instances.
|
|
8572
|
+
*
|
|
8573
|
+
* @public
|
|
8574
|
+
*/
|
|
8575
|
+
getMounted(): readonly Editor[];
|
|
8576
|
+
};
|
|
8577
|
+
|
|
8514
8578
|
/** @public */
|
|
8515
8579
|
export declare interface TLEditorSnapshot {
|
|
8516
8580
|
document: TLStoreSnapshot;
|
|
@@ -9008,7 +9072,7 @@ export declare const tlmenus: {
|
|
|
9008
9072
|
*
|
|
9009
9073
|
* @public
|
|
9010
9074
|
*/
|
|
9011
|
-
clearOpenMenus(contextId?: string
|
|
9075
|
+
clearOpenMenus(contextId?: string): void;
|
|
9012
9076
|
/**
|
|
9013
9077
|
* Delete an open menu.
|
|
9014
9078
|
*
|
|
@@ -9031,7 +9095,7 @@ export declare const tlmenus: {
|
|
|
9031
9095
|
*
|
|
9032
9096
|
* @public
|
|
9033
9097
|
*/
|
|
9034
|
-
getOpenMenus(contextId?: string
|
|
9098
|
+
getOpenMenus(contextId?: string): string[];
|
|
9035
9099
|
/**
|
|
9036
9100
|
* Get whether a menu is open for a given context.
|
|
9037
9101
|
*
|
|
@@ -9045,7 +9109,7 @@ export declare const tlmenus: {
|
|
|
9045
9109
|
*
|
|
9046
9110
|
* @public
|
|
9047
9111
|
*/
|
|
9048
|
-
isMenuOpen(id: string, contextId?: string
|
|
9112
|
+
isMenuOpen(id: string, contextId?: string): boolean;
|
|
9049
9113
|
/**
|
|
9050
9114
|
* Get whether any menus are open for a given context.
|
|
9051
9115
|
*
|
|
@@ -9083,7 +9147,7 @@ export declare const tlmenus: {
|
|
|
9083
9147
|
*
|
|
9084
9148
|
* @public
|
|
9085
9149
|
*/
|
|
9086
|
-
hideOpenMenus(contextId?: string
|
|
9150
|
+
hideOpenMenus(contextId?: string): void;
|
|
9087
9151
|
/**
|
|
9088
9152
|
* Show all hidden menus.
|
|
9089
9153
|
*
|
|
@@ -9097,7 +9161,7 @@ export declare const tlmenus: {
|
|
|
9097
9161
|
*
|
|
9098
9162
|
* @public
|
|
9099
9163
|
*/
|
|
9100
|
-
showOpenMenus(contextId?: string
|
|
9164
|
+
showOpenMenus(contextId?: string): void;
|
|
9101
9165
|
forContext(contextId: string): {
|
|
9102
9166
|
addOpenMenu: (id: string) => void;
|
|
9103
9167
|
clearOpenMenus: () => void;
|
|
@@ -9876,6 +9940,8 @@ export declare function useIsEditing(shapeId: TLShapeId): boolean;
|
|
|
9876
9940
|
/** @public */
|
|
9877
9941
|
export declare function useMaybeEditor(): Editor | null;
|
|
9878
9942
|
|
|
9943
|
+
/* Excluded from this release type: useMaybeLicenseManager */
|
|
9944
|
+
|
|
9879
9945
|
/* Excluded from this release type: useOnMount */
|
|
9880
9946
|
|
|
9881
9947
|
/** @public */
|
|
@@ -9909,6 +9975,7 @@ export declare class UserPreferencesManager {
|
|
|
9909
9975
|
private readonly user;
|
|
9910
9976
|
private readonly colorScheme;
|
|
9911
9977
|
systemColorScheme: Atom<"dark" | "light", unknown>;
|
|
9978
|
+
private readonly systemPrefersReducedMotion;
|
|
9912
9979
|
disposables: Set<() => void>;
|
|
9913
9980
|
dispose(): void;
|
|
9914
9981
|
constructor(user: TLCurrentUser, colorScheme: 'dark' | 'light' | 'system');
|