@tldraw/editor
Version:
tldraw infinite canvas SDK (editor).
223 lines (222 loc) • 8.77 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var TLSessionStateSnapshot_exports = {};
__export(TLSessionStateSnapshot_exports, {
TAB_ID: () => TAB_ID,
createSessionStateSnapshotSignal: () => createSessionStateSnapshotSignal,
extractSessionStateFromLegacySnapshot: () => extractSessionStateFromLegacySnapshot,
loadSessionStateSnapshotIntoStore: () => loadSessionStateSnapshotIntoStore
});
module.exports = __toCommonJS(TLSessionStateSnapshot_exports);
var import_state = require("@tldraw/state");
var import_tlschema = require("@tldraw/tlschema");
var import_utils = require("@tldraw/utils");
var import_validate = require("@tldraw/validate");
var import_environment = require("../globals/environment");
const tabIdKey = "TLDRAW_TAB_ID_v2";
const window = globalThis.window;
function iOS() {
if (!window) return false;
return ["iPad Simulator", "iPhone Simulator", "iPod Simulator", "iPad", "iPhone", "iPod"].includes(
// eslint-disable-next-line @typescript-eslint/no-deprecated
window.navigator.platform
) || // iPad on iOS 13 detection
import_environment.tlenv.isDarwin && "ontouchend" in document;
}
const TAB_ID = window ? window[tabIdKey] ?? (0, import_utils.getFromSessionStorage)(tabIdKey) ?? `TLDRAW_INSTANCE_STATE_V1_` + (0, import_utils.uniqueId)() : "<error>";
if (window) {
window[tabIdKey] = TAB_ID;
if (iOS()) {
(0, import_utils.setInSessionStorage)(tabIdKey, TAB_ID);
} else {
(0, import_utils.deleteFromSessionStorage)(tabIdKey);
}
}
window?.addEventListener("beforeunload", () => {
(0, import_utils.setInSessionStorage)(tabIdKey, TAB_ID);
});
const Versions = {
Initial: 0
};
const CURRENT_SESSION_STATE_SNAPSHOT_VERSION = Math.max(...Object.values(Versions));
function migrate(snapshot) {
if (snapshot.version < Versions.Initial) {
}
snapshot.version = CURRENT_SESSION_STATE_SNAPSHOT_VERSION;
}
const sessionStateSnapshotValidator = import_validate.T.object({
version: import_validate.T.number,
currentPageId: import_tlschema.pageIdValidator.optional(),
isFocusMode: import_validate.T.boolean.optional(),
exportBackground: import_validate.T.boolean.optional(),
isDebugMode: import_validate.T.boolean.optional(),
isToolLocked: import_validate.T.boolean.optional(),
isGridMode: import_validate.T.boolean.optional(),
pageStates: import_validate.T.arrayOf(
import_validate.T.object({
pageId: import_tlschema.pageIdValidator,
camera: import_validate.T.object({
x: import_validate.T.number,
y: import_validate.T.number,
z: import_validate.T.number
}).optional(),
selectedShapeIds: import_validate.T.arrayOf(import_tlschema.shapeIdValidator).optional(),
focusedGroupId: import_tlschema.shapeIdValidator.nullable().optional()
})
).optional()
});
function migrateAndValidateSessionStateSnapshot(state) {
if (!state || typeof state !== "object") {
console.warn("Invalid instance state");
return null;
}
if (!("version" in state) || typeof state.version !== "number") {
console.warn("No version in instance state");
return null;
}
if (state.version !== CURRENT_SESSION_STATE_SNAPSHOT_VERSION) {
state = (0, import_utils.structuredClone)(state);
migrate(state);
}
try {
return sessionStateSnapshotValidator.validate(state);
} catch (e) {
console.warn(e);
return null;
}
}
function createSessionStateSnapshotSignal(store) {
const $allPageIds = store.query.ids("page");
return (0, import_state.computed)(
"sessionStateSnapshot",
() => {
const instanceState = store.get(import_tlschema.TLINSTANCE_ID);
if (!instanceState) return null;
const allPageIds = [...$allPageIds.get()];
return {
version: CURRENT_SESSION_STATE_SNAPSHOT_VERSION,
currentPageId: instanceState.currentPageId,
exportBackground: instanceState.exportBackground,
isFocusMode: instanceState.isFocusMode,
isDebugMode: instanceState.isDebugMode,
isToolLocked: instanceState.isToolLocked,
isGridMode: instanceState.isGridMode,
pageStates: allPageIds.map((id) => {
const ps = store.get(import_tlschema.InstancePageStateRecordType.createId(id));
const camera = store.get(import_tlschema.CameraRecordType.createId(id));
return {
pageId: id,
camera: {
x: camera?.x ?? 0,
y: camera?.y ?? 0,
z: camera?.z ?? 1
},
selectedShapeIds: ps?.selectedShapeIds ?? [],
focusedGroupId: ps?.focusedGroupId ?? null
};
})
};
},
{ isEqual: import_utils.isEqual }
);
}
function loadSessionStateSnapshotIntoStore(store, snapshot, opts) {
const res = migrateAndValidateSessionStateSnapshot(snapshot);
if (!res) return;
const preserved = (0, import_tlschema.pluckPreservingValues)(store.get(import_tlschema.TLINSTANCE_ID));
const primary = opts?.forceOverwrite ? res : preserved;
const secondary = opts?.forceOverwrite ? preserved : res;
const instanceState = store.schema.types.instance.create({
id: import_tlschema.TLINSTANCE_ID,
...preserved,
// the integrity checker will ensure that the currentPageId is valid
currentPageId: res.currentPageId,
isDebugMode: primary?.isDebugMode ?? secondary?.isDebugMode,
isFocusMode: primary?.isFocusMode ?? secondary?.isFocusMode,
isToolLocked: primary?.isToolLocked ?? secondary?.isToolLocked,
isGridMode: primary?.isGridMode ?? secondary?.isGridMode,
exportBackground: primary?.exportBackground ?? secondary?.exportBackground
});
store.atomic(() => {
for (const ps of res.pageStates ?? []) {
if (!store.has(ps.pageId)) continue;
const cameraId = import_tlschema.CameraRecordType.createId(ps.pageId);
const instancePageState = import_tlschema.InstancePageStateRecordType.createId(ps.pageId);
const previousCamera = store.get(cameraId);
const previousInstanceState = store.get(instancePageState);
store.put([
import_tlschema.CameraRecordType.create({
id: cameraId,
x: ps.camera?.x ?? previousCamera?.x,
y: ps.camera?.y ?? previousCamera?.y,
z: ps.camera?.z ?? previousCamera?.z
}),
import_tlschema.InstancePageStateRecordType.create({
id: instancePageState,
pageId: ps.pageId,
selectedShapeIds: ps.selectedShapeIds ?? previousInstanceState?.selectedShapeIds,
focusedGroupId: ps.focusedGroupId ?? previousInstanceState?.focusedGroupId
})
]);
}
store.put([instanceState]);
store.ensureStoreIsUsable();
});
}
function extractSessionStateFromLegacySnapshot(store) {
const instanceRecords = [];
for (const record of Object.values(store)) {
if (record.typeName?.match(/^(instance.*|pointer|camera)$/)) {
instanceRecords.push(record);
}
}
const oldInstance = instanceRecords.filter(
(r) => r.typeName === "instance" && r.id !== import_tlschema.TLINSTANCE_ID
)[0];
if (!oldInstance) return null;
const result = {
version: CURRENT_SESSION_STATE_SNAPSHOT_VERSION,
currentPageId: oldInstance.currentPageId,
exportBackground: !!oldInstance.exportBackground,
isFocusMode: !!oldInstance.isFocusMode,
isDebugMode: !!oldInstance.isDebugMode,
isToolLocked: !!oldInstance.isToolLocked,
isGridMode: false,
pageStates: instanceRecords.filter((r) => r.typeName === "instance_page_state" && r.instanceId === oldInstance.id).map((ps) => {
const camera = store[ps.cameraId] ?? { x: 0, y: 0, z: 1 };
return {
pageId: ps.pageId,
camera: {
x: camera.x,
y: camera.y,
z: camera.z
},
selectedShapeIds: ps.selectedShapeIds,
focusedGroupId: ps.focusedGroupId
};
})
};
try {
sessionStateSnapshotValidator.validate(result);
return result;
} catch {
return null;
}
}
//# sourceMappingURL=TLSessionStateSnapshot.js.map