@tldraw/editor 5.4.0-canary.403aa122ec3e → 5.4.0-canary.40b2bd5a6b96

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.
Files changed (56) hide show
  1. package/dist-cjs/index.js +1 -1
  2. package/dist-cjs/lib/config/createTLStore.js +1 -1
  3. package/dist-cjs/lib/config/createTLStore.js.map +2 -2
  4. package/dist-cjs/lib/editor/Editor.js +58 -73
  5. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  6. package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js +3 -3
  7. package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js.map +2 -2
  8. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js +1 -1
  9. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js.map +2 -2
  10. package/dist-cjs/lib/hooks/useCanvasEvents.js +2 -0
  11. package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
  12. package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js +1 -0
  13. package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js.map +2 -2
  14. package/dist-cjs/lib/hooks/usePeerIds.js +2 -1
  15. package/dist-cjs/lib/hooks/usePeerIds.js.map +2 -2
  16. package/dist-cjs/lib/utils/deepLinks.js +5 -1
  17. package/dist-cjs/lib/utils/deepLinks.js.map +2 -2
  18. package/dist-cjs/lib/utils/sync/alerts.js +1 -1
  19. package/dist-cjs/lib/utils/sync/alerts.js.map +1 -1
  20. package/dist-cjs/version.js +3 -3
  21. package/dist-cjs/version.js.map +1 -1
  22. package/dist-esm/index.mjs +1 -1
  23. package/dist-esm/lib/config/createTLStore.mjs +1 -1
  24. package/dist-esm/lib/config/createTLStore.mjs.map +2 -2
  25. package/dist-esm/lib/editor/Editor.mjs +59 -73
  26. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  27. package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs +3 -3
  28. package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs.map +2 -2
  29. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs +1 -1
  30. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs.map +2 -2
  31. package/dist-esm/lib/hooks/useCanvasEvents.mjs +2 -0
  32. package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
  33. package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs +1 -0
  34. package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs.map +2 -2
  35. package/dist-esm/lib/hooks/usePeerIds.mjs +2 -1
  36. package/dist-esm/lib/hooks/usePeerIds.mjs.map +2 -2
  37. package/dist-esm/lib/utils/deepLinks.mjs +5 -1
  38. package/dist-esm/lib/utils/deepLinks.mjs.map +2 -2
  39. package/dist-esm/lib/utils/sync/alerts.mjs +1 -1
  40. package/dist-esm/lib/utils/sync/alerts.mjs.map +1 -1
  41. package/dist-esm/version.mjs +3 -3
  42. package/dist-esm/version.mjs.map +1 -1
  43. package/package.json +7 -7
  44. package/src/lib/config/createTLStore.ts +1 -1
  45. package/src/lib/editor/Editor.ts +99 -101
  46. package/src/lib/editor/managers/ClickManager/ClickManager.ts +5 -3
  47. package/src/lib/editor/tools/BaseBoxShapeTool/children/Pointing.ts +4 -1
  48. package/src/lib/hooks/useCanvasEvents.ts +2 -0
  49. package/src/lib/hooks/usePassThroughWheelEvents.ts +3 -0
  50. package/src/lib/hooks/usePeerIds.ts +2 -1
  51. package/src/lib/test/useCanvasEvents.test.tsx +74 -0
  52. package/src/lib/test/usePassThroughWheelEvents.test.tsx +25 -2
  53. package/src/lib/utils/deepLinks.test.ts +15 -0
  54. package/src/lib/utils/deepLinks.ts +7 -1
  55. package/src/lib/utils/sync/alerts.ts +1 -1
  56. package/src/version.ts +3 -3
package/dist-cjs/index.js CHANGED
@@ -392,7 +392,7 @@ var import_uniq = require("./lib/utils/uniq");
392
392
  var import_defaultThemes2 = require("./lib/editor/managers/ThemeManager/defaultThemes");
393
393
  (0, import_utils.registerTldrawLibraryVersion)(
394
394
  "@tldraw/editor",
395
- "5.4.0-canary.403aa122ec3e",
395
+ "5.4.0-canary.40b2bd5a6b96",
396
396
  "cjs"
397
397
  );
398
398
  //# sourceMappingURL=index.js.map
@@ -98,7 +98,7 @@ function createTLStore({
98
98
  },
99
99
  onMount: (editor) => {
100
100
  (0, import_utils.assert)(editor instanceof import_Editor.Editor);
101
- onMount?.(editor);
101
+ return onMount?.(editor);
102
102
  },
103
103
  collaboration
104
104
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/config/createTLStore.ts"],
4
- "sourcesContent": ["import { Signal, computed } from '@tldraw/state'\nimport { HistoryEntry, MigrationSequence, SerializedStore, Store, StoreSchema } from '@tldraw/store'\nimport {\n\tCustomRecordInfo,\n\tSchemaPropsInfo,\n\tTLAssetStore,\n\tTLRecord,\n\tTLStore,\n\tTLStoreProps,\n\tTLStoreSnapshot,\n\tTLThemes,\n\tTLUser,\n\tTLUserStore,\n\tUserRecordType,\n\tcreateCachedUserResolve,\n\tcreateTLSchema,\n\tcreateUserId,\n\tregisterColorsFromThemes,\n\tregisterFontsFromThemes,\n} from '@tldraw/tlschema'\nimport { FileHelpers, assert } from '@tldraw/utils'\nimport { Editor } from '../editor/Editor'\nimport { resolveThemes } from '../editor/managers/ThemeManager/ThemeManager'\nimport { TLAnyAssetUtilConstructor, checkAssets } from './defaultAssets'\nimport { TLAnyBindingUtilConstructor, checkBindings } from './defaultBindings'\nimport { TLAnyShapeUtilConstructor, checkShapesAndAddCore } from './defaultShapes'\nimport { TLEditorSnapshot, loadSnapshot } from './TLEditorSnapshot'\nimport { defaultUserPreferences, getUserPreferences } from './TLUserPreferences'\n\n/** @public */\nexport interface TLStoreBaseOptions {\n\t/** The initial data for the store. */\n\tinitialData?: SerializedStore<TLRecord>\n\n\t/** A snapshot of initial data to migrate and load into the store. */\n\tsnapshot?: Partial<TLEditorSnapshot> | TLStoreSnapshot\n\n\t/** The default name for the store. */\n\tdefaultName?: string\n\n\t/** How should this store upload & resolve assets? */\n\tassets?: TLAssetStore\n\n\t/**\n\t * Named theme definitions. When provided, custom color names are automatically\n\t * registered before the store is constructed so persisted data with those\n\t * colors passes validation on load.\n\t */\n\tthemes?: Partial<TLThemes>\n\n\t/** How should this store resolve users for attribution? */\n\tusers?: TLUserStore\n\n\t/** Called when the store is connected to an {@link @tldraw/editor#Editor}. */\n\tonMount?(editor: Editor): void | (() => void)\n}\n\n/** @public */\nexport type TLStoreSchemaOptions =\n\t| {\n\t\t\tschema?: StoreSchema<TLRecord, TLStoreProps>\n\t }\n\t| {\n\t\t\tshapeUtils?: readonly TLAnyShapeUtilConstructor[]\n\t\t\tbindingUtils?: readonly TLAnyBindingUtilConstructor[]\n\t\t\tassetUtils?: readonly TLAnyAssetUtilConstructor[]\n\t\t\tmigrations?: readonly MigrationSequence[]\n\t\t\trecords?: Record<string, CustomRecordInfo>\n\t }\n\n/** @public */\nexport type TLStoreOptions = TLStoreBaseOptions & {\n\tid?: string\n\t/** Collaboration options for the store. */\n\tcollaboration?: {\n\t\tstatus: Signal<'online' | 'offline'> | null\n\t\tmode?: Signal<'readonly' | 'readwrite'> | null\n\t}\n} & TLStoreSchemaOptions\n\n/** @public */\nexport type TLStoreEventInfo = HistoryEntry<TLRecord>\n\nconst defaultAssetResolve: NonNullable<TLAssetStore['resolve']> = (asset) => asset.props.src\n\nconst _defaultCurrentUser: Signal<TLUser | null> = computed('defaultCurrentUser', () => {\n\tconst prefs = getUserPreferences()\n\tif (!prefs.id) return null\n\treturn UserRecordType.create({\n\t\tid: createUserId(prefs.id),\n\t\tname: prefs.name ?? '',\n\t\tcolor: prefs.color ?? defaultUserPreferences.color,\n\t})\n})\n\n/** @public */\nexport const defaultUserStore: TLUserStore = {\n\tcurrentUser: _defaultCurrentUser,\n}\n\n/** @public */\nexport const inlineBase64AssetStore: TLAssetStore = {\n\tupload: async (_, file) => {\n\t\treturn { src: await FileHelpers.blobToDataUrl(file) }\n\t},\n}\n\n/**\n * A helper for creating a TLStore schema from either an object with shapeUtils, bindingUtils, and\n * migrations, or a schema.\n *\n * @param opts - Options for creating the schema.\n *\n * @public\n */\nexport function createTLSchemaFromUtils(\n\topts: TLStoreSchemaOptions\n): StoreSchema<TLRecord, TLStoreProps> {\n\tif ('schema' in opts && opts.schema) return opts.schema\n\n\treturn createTLSchema({\n\t\tshapes:\n\t\t\t'shapeUtils' in opts && opts.shapeUtils\n\t\t\t\t? utilsToMap(checkShapesAndAddCore(opts.shapeUtils))\n\t\t\t\t: undefined,\n\t\tbindings:\n\t\t\t'bindingUtils' in opts && opts.bindingUtils\n\t\t\t\t? utilsToMap(checkBindings(opts.bindingUtils))\n\t\t\t\t: undefined,\n\t\tassets:\n\t\t\t'assetUtils' in opts && opts.assetUtils\n\t\t\t\t? utilsToMap(checkAssets(opts.assetUtils))\n\t\t\t\t: undefined,\n\t\trecords: 'records' in opts ? opts.records : undefined,\n\t\tmigrations: 'migrations' in opts ? opts.migrations : undefined,\n\t})\n}\n\n/**\n * A helper for creating a TLStore.\n *\n * @param opts - Options for creating the store.\n *\n * @public\n */\nexport function createTLStore({\n\tinitialData,\n\tdefaultName = '',\n\tid,\n\tassets = inlineBase64AssetStore,\n\tusers = defaultUserStore,\n\tonMount,\n\tcollaboration,\n\tthemes,\n\t...rest\n}: TLStoreOptions = {}): TLStore {\n\tconst resolvedThemes = resolveThemes(themes)\n\tregisterColorsFromThemes(resolvedThemes)\n\tregisterFontsFromThemes(resolvedThemes)\n\tconst schema = createTLSchemaFromUtils(rest)\n\n\tconst store = new Store({\n\t\tid,\n\t\tschema,\n\t\tinitialData,\n\t\tprops: {\n\t\t\tdefaultName,\n\t\t\tassets: {\n\t\t\t\tupload: assets.upload,\n\t\t\t\tresolve: assets.resolve ?? defaultAssetResolve,\n\t\t\t\tremove: assets.remove ?? (() => Promise.resolve()),\n\t\t\t},\n\t\t\tusers: {\n\t\t\t\tcurrentUser: users.currentUser,\n\t\t\t\tresolve:\n\t\t\t\t\tusers.resolve ??\n\t\t\t\t\tcreateCachedUserResolve((userId) => {\n\t\t\t\t\t\tconst current = users.currentUser.get()\n\t\t\t\t\t\treturn current && current.id === createUserId(userId) ? current : null\n\t\t\t\t\t}),\n\t\t\t},\n\t\t\tonMount: (editor) => {\n\t\t\t\tassert(editor instanceof Editor)\n\t\t\t\tonMount?.(editor)\n\t\t\t},\n\t\t\tcollaboration,\n\t\t},\n\t})\n\n\tif (rest.snapshot) {\n\t\tif (initialData) throw new Error('Cannot provide both initialData and snapshot')\n\t\tloadSnapshot(store, rest.snapshot, { forceOverwriteSessionState: true })\n\t}\n\n\treturn store\n}\n\nfunction utilsToMap<T extends SchemaPropsInfo & { type: string }>(utils: T[]) {\n\treturn Object.fromEntries(\n\t\tutils.map((s): [string, SchemaPropsInfo] => [\n\t\t\ts.type,\n\t\t\t{\n\t\t\t\tprops: s.props,\n\t\t\t\tmigrations: s.migrations,\n\t\t\t},\n\t\t])\n\t)\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { Signal, computed } from '@tldraw/state'\nimport { HistoryEntry, MigrationSequence, SerializedStore, Store, StoreSchema } from '@tldraw/store'\nimport {\n\tCustomRecordInfo,\n\tSchemaPropsInfo,\n\tTLAssetStore,\n\tTLRecord,\n\tTLStore,\n\tTLStoreProps,\n\tTLStoreSnapshot,\n\tTLThemes,\n\tTLUser,\n\tTLUserStore,\n\tUserRecordType,\n\tcreateCachedUserResolve,\n\tcreateTLSchema,\n\tcreateUserId,\n\tregisterColorsFromThemes,\n\tregisterFontsFromThemes,\n} from '@tldraw/tlschema'\nimport { FileHelpers, assert } from '@tldraw/utils'\nimport { Editor } from '../editor/Editor'\nimport { resolveThemes } from '../editor/managers/ThemeManager/ThemeManager'\nimport { TLAnyAssetUtilConstructor, checkAssets } from './defaultAssets'\nimport { TLAnyBindingUtilConstructor, checkBindings } from './defaultBindings'\nimport { TLAnyShapeUtilConstructor, checkShapesAndAddCore } from './defaultShapes'\nimport { TLEditorSnapshot, loadSnapshot } from './TLEditorSnapshot'\nimport { defaultUserPreferences, getUserPreferences } from './TLUserPreferences'\n\n/** @public */\nexport interface TLStoreBaseOptions {\n\t/** The initial data for the store. */\n\tinitialData?: SerializedStore<TLRecord>\n\n\t/** A snapshot of initial data to migrate and load into the store. */\n\tsnapshot?: Partial<TLEditorSnapshot> | TLStoreSnapshot\n\n\t/** The default name for the store. */\n\tdefaultName?: string\n\n\t/** How should this store upload & resolve assets? */\n\tassets?: TLAssetStore\n\n\t/**\n\t * Named theme definitions. When provided, custom color names are automatically\n\t * registered before the store is constructed so persisted data with those\n\t * colors passes validation on load.\n\t */\n\tthemes?: Partial<TLThemes>\n\n\t/** How should this store resolve users for attribution? */\n\tusers?: TLUserStore\n\n\t/** Called when the store is connected to an {@link @tldraw/editor#Editor}. */\n\tonMount?(editor: Editor): void | (() => void)\n}\n\n/** @public */\nexport type TLStoreSchemaOptions =\n\t| {\n\t\t\tschema?: StoreSchema<TLRecord, TLStoreProps>\n\t }\n\t| {\n\t\t\tshapeUtils?: readonly TLAnyShapeUtilConstructor[]\n\t\t\tbindingUtils?: readonly TLAnyBindingUtilConstructor[]\n\t\t\tassetUtils?: readonly TLAnyAssetUtilConstructor[]\n\t\t\tmigrations?: readonly MigrationSequence[]\n\t\t\trecords?: Record<string, CustomRecordInfo>\n\t }\n\n/** @public */\nexport type TLStoreOptions = TLStoreBaseOptions & {\n\tid?: string\n\t/** Collaboration options for the store. */\n\tcollaboration?: {\n\t\tstatus: Signal<'online' | 'offline'> | null\n\t\tmode?: Signal<'readonly' | 'readwrite'> | null\n\t}\n} & TLStoreSchemaOptions\n\n/** @public */\nexport type TLStoreEventInfo = HistoryEntry<TLRecord>\n\nconst defaultAssetResolve: NonNullable<TLAssetStore['resolve']> = (asset) => asset.props.src\n\nconst _defaultCurrentUser: Signal<TLUser | null> = computed('defaultCurrentUser', () => {\n\tconst prefs = getUserPreferences()\n\tif (!prefs.id) return null\n\treturn UserRecordType.create({\n\t\tid: createUserId(prefs.id),\n\t\tname: prefs.name ?? '',\n\t\tcolor: prefs.color ?? defaultUserPreferences.color,\n\t})\n})\n\n/** @public */\nexport const defaultUserStore: TLUserStore = {\n\tcurrentUser: _defaultCurrentUser,\n}\n\n/** @public */\nexport const inlineBase64AssetStore: TLAssetStore = {\n\tupload: async (_, file) => {\n\t\treturn { src: await FileHelpers.blobToDataUrl(file) }\n\t},\n}\n\n/**\n * A helper for creating a TLStore schema from either an object with shapeUtils, bindingUtils, and\n * migrations, or a schema.\n *\n * @param opts - Options for creating the schema.\n *\n * @public\n */\nexport function createTLSchemaFromUtils(\n\topts: TLStoreSchemaOptions\n): StoreSchema<TLRecord, TLStoreProps> {\n\tif ('schema' in opts && opts.schema) return opts.schema\n\n\treturn createTLSchema({\n\t\tshapes:\n\t\t\t'shapeUtils' in opts && opts.shapeUtils\n\t\t\t\t? utilsToMap(checkShapesAndAddCore(opts.shapeUtils))\n\t\t\t\t: undefined,\n\t\tbindings:\n\t\t\t'bindingUtils' in opts && opts.bindingUtils\n\t\t\t\t? utilsToMap(checkBindings(opts.bindingUtils))\n\t\t\t\t: undefined,\n\t\tassets:\n\t\t\t'assetUtils' in opts && opts.assetUtils\n\t\t\t\t? utilsToMap(checkAssets(opts.assetUtils))\n\t\t\t\t: undefined,\n\t\trecords: 'records' in opts ? opts.records : undefined,\n\t\tmigrations: 'migrations' in opts ? opts.migrations : undefined,\n\t})\n}\n\n/**\n * A helper for creating a TLStore.\n *\n * @param opts - Options for creating the store.\n *\n * @public\n */\nexport function createTLStore({\n\tinitialData,\n\tdefaultName = '',\n\tid,\n\tassets = inlineBase64AssetStore,\n\tusers = defaultUserStore,\n\tonMount,\n\tcollaboration,\n\tthemes,\n\t...rest\n}: TLStoreOptions = {}): TLStore {\n\tconst resolvedThemes = resolveThemes(themes)\n\tregisterColorsFromThemes(resolvedThemes)\n\tregisterFontsFromThemes(resolvedThemes)\n\tconst schema = createTLSchemaFromUtils(rest)\n\n\tconst store = new Store({\n\t\tid,\n\t\tschema,\n\t\tinitialData,\n\t\tprops: {\n\t\t\tdefaultName,\n\t\t\tassets: {\n\t\t\t\tupload: assets.upload,\n\t\t\t\tresolve: assets.resolve ?? defaultAssetResolve,\n\t\t\t\tremove: assets.remove ?? (() => Promise.resolve()),\n\t\t\t},\n\t\t\tusers: {\n\t\t\t\tcurrentUser: users.currentUser,\n\t\t\t\tresolve:\n\t\t\t\t\tusers.resolve ??\n\t\t\t\t\tcreateCachedUserResolve((userId) => {\n\t\t\t\t\t\tconst current = users.currentUser.get()\n\t\t\t\t\t\treturn current && current.id === createUserId(userId) ? current : null\n\t\t\t\t\t}),\n\t\t\t},\n\t\t\tonMount: (editor) => {\n\t\t\t\tassert(editor instanceof Editor)\n\t\t\t\treturn onMount?.(editor)\n\t\t\t},\n\t\t\tcollaboration,\n\t\t},\n\t})\n\n\tif (rest.snapshot) {\n\t\tif (initialData) throw new Error('Cannot provide both initialData and snapshot')\n\t\tloadSnapshot(store, rest.snapshot, { forceOverwriteSessionState: true })\n\t}\n\n\treturn store\n}\n\nfunction utilsToMap<T extends SchemaPropsInfo & { type: string }>(utils: T[]) {\n\treturn Object.fromEntries(\n\t\tutils.map((s): [string, SchemaPropsInfo] => [\n\t\t\ts.type,\n\t\t\t{\n\t\t\t\tprops: s.props,\n\t\t\t\tmigrations: s.migrations,\n\t\t\t},\n\t\t])\n\t)\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -257,6 +257,10 @@ class Editor extends import_eventemitter3.default {
257
257
  if (!nextPageState) nextPageState = { ...prevPageState };
258
258
  nextPageState.editingShapeId = null;
259
259
  }
260
+ if (prevPageState.croppingShapeId && shapesNoLongerInPage.has(prevPageState.croppingShapeId)) {
261
+ if (!nextPageState) nextPageState = { ...prevPageState };
262
+ nextPageState.croppingShapeId = null;
263
+ }
260
264
  const hintingShapeIds = prevPageState.hintingShapeIds.filter(
261
265
  (id) => !shapesNoLongerInPage.has(id)
262
266
  );
@@ -587,7 +591,10 @@ class Editor extends import_eventemitter3.default {
587
591
  const mode = this.store.props.collaboration.mode;
588
592
  this.disposables.add(
589
593
  (0, import_state.react)("update collaboration mode", () => {
590
- this.store.put([{ ...this.getInstanceState(), isReadonly: mode.get() === "readonly" }]);
594
+ const isReadonly = mode.get() === "readonly";
595
+ (0, import_state.unsafe__withoutCapture)(
596
+ () => this._updateInstanceState({ isReadonly }, { history: "ignore" })
597
+ );
591
598
  })
592
599
  );
593
600
  }
@@ -1848,9 +1855,14 @@ class Editor extends import_eventemitter3.default {
1848
1855
  getSelectionRotatedScreenBounds() {
1849
1856
  const bounds = this.getSelectionRotatedPageBounds();
1850
1857
  if (!bounds) return void 0;
1851
- const { x, y } = this.pageToScreen(bounds.point);
1852
- const zoom = this.getZoomLevel();
1853
- return new import_Box.Box(x, y, bounds.width * zoom, bounds.height * zoom);
1858
+ const screenBounds = this.getViewportScreenBounds();
1859
+ const { x: cx, y: cy, z: zoom } = this.getCamera();
1860
+ return new import_Box.Box(
1861
+ (bounds.x + cx) * zoom + screenBounds.x,
1862
+ (bounds.y + cy) * zoom + screenBounds.y,
1863
+ bounds.width * zoom,
1864
+ bounds.height * zoom
1865
+ );
1854
1866
  }
1855
1867
  getFocusedGroupId() {
1856
1868
  return this.getCurrentPageState().focusedGroupId ?? this.getCurrentPageId();
@@ -1951,42 +1963,28 @@ class Editor extends import_eventemitter3.default {
1951
1963
  */
1952
1964
  setEditingShape(shape) {
1953
1965
  const id = typeof shape === "string" ? shape : shape?.id ?? null;
1954
- if (!id) {
1966
+ if (id && !this.canEditShape(id)) return this;
1967
+ this.run(() => {
1968
+ const prevEditingShapeId = this.getEditingShapeId();
1969
+ if (prevEditingShapeId) {
1970
+ const prevEditingShape = this.getShape(prevEditingShapeId);
1971
+ if (prevEditingShape) {
1972
+ this.getShapeUtil(prevEditingShape).onEditEnd?.(prevEditingShape);
1973
+ }
1974
+ }
1955
1975
  this.run(
1956
1976
  () => {
1957
- const prevEditingShapeId = this.getEditingShapeId();
1958
- if (prevEditingShapeId) {
1959
- const prevEditingShape = this.getShape(prevEditingShapeId);
1960
- if (prevEditingShape) {
1961
- this.getShapeUtil(prevEditingShape).onEditEnd?.(prevEditingShape);
1962
- }
1963
- }
1964
1977
  this._updateCurrentPageState({ editingShapeId: null });
1965
1978
  this._currentRichTextEditor.set(null);
1979
+ if (!id) return;
1980
+ this.select(id);
1981
+ this._updateCurrentPageState({ editingShapeId: id });
1982
+ const nextEditingShape = this.getShape(id);
1983
+ this.getShapeUtil(nextEditingShape).onEditStart?.(nextEditingShape);
1966
1984
  },
1967
1985
  { history: "ignore" }
1968
1986
  );
1969
- return this;
1970
- }
1971
- if (!this.canEditShape(id)) return this;
1972
- this.run(
1973
- () => {
1974
- const prevEditingShapeId = this.getEditingShapeId();
1975
- if (prevEditingShapeId) {
1976
- const prevEditingShape = this.getShape(prevEditingShapeId);
1977
- if (prevEditingShape) {
1978
- this.getShapeUtil(prevEditingShape).onEditEnd?.(prevEditingShape);
1979
- }
1980
- }
1981
- this._updateCurrentPageState({ editingShapeId: null });
1982
- this._currentRichTextEditor.set(null);
1983
- this.select(id);
1984
- this._updateCurrentPageState({ editingShapeId: id });
1985
- const nextEditingShape = this.getShape(id);
1986
- this.getShapeUtil(nextEditingShape).onEditStart?.(nextEditingShape);
1987
- },
1988
- { history: "ignore" }
1989
- );
1987
+ });
1990
1988
  return this;
1991
1989
  }
1992
1990
  // Rich text editor
@@ -2092,19 +2090,12 @@ class Editor extends import_eventemitter3.default {
2092
2090
  * @public
2093
2091
  */
2094
2092
  setErasingShapes(shapes) {
2095
- const ids = typeof shapes[0] === "string" ? shapes : shapes.map((shape) => shape.id);
2093
+ const ids = typeof shapes[0] === "string" ? shapes.slice() : shapes.map((shape) => shape.id);
2096
2094
  ids.sort();
2097
2095
  const erasingShapeIds = this.getErasingShapeIds();
2098
2096
  this.run(
2099
2097
  () => {
2100
- if (ids.length === erasingShapeIds.length) {
2101
- for (let i = 0; i < ids.length; i++) {
2102
- if (ids[i] !== erasingShapeIds[i]) {
2103
- this._updateCurrentPageState({ erasingShapeIds: ids });
2104
- break;
2105
- }
2106
- }
2107
- } else {
2098
+ if (!(0, import_utils.areArraysShallowEqual)(ids, erasingShapeIds)) {
2108
2099
  this._updateCurrentPageState({ erasingShapeIds: ids });
2109
2100
  }
2110
2101
  },
@@ -2137,6 +2128,7 @@ class Editor extends import_eventemitter3.default {
2137
2128
  if (!_shape) return false;
2138
2129
  const util = this.getShapeUtil(_shape);
2139
2130
  if (!util.canCrop(_shape)) return false;
2131
+ if (this.getIsReadonly()) return false;
2140
2132
  if (this.isShapeOrAncestorLocked(_shape)) return false;
2141
2133
  return true;
2142
2134
  }
@@ -2201,11 +2193,11 @@ class Editor extends import_eventemitter3.default {
2201
2193
  const collaborators = this.getCollaborators();
2202
2194
  let leaderPresence = null;
2203
2195
  while (targetUserId && !visited.includes(targetUserId)) {
2204
- leaderPresence = collaborators.find((c) => c.userId === targetUserId) ?? null;
2205
- targetUserId = leaderPresence?.followingUserId ?? null;
2206
- if (leaderPresence) {
2207
- visited.push(leaderPresence.userId);
2208
- }
2196
+ const nextPresence = collaborators.find((c) => c.userId === targetUserId);
2197
+ if (!nextPresence) break;
2198
+ leaderPresence = nextPresence;
2199
+ targetUserId = nextPresence.followingUserId ?? null;
2200
+ visited.push(nextPresence.userId);
2209
2201
  }
2210
2202
  return leaderPresence;
2211
2203
  }
@@ -2346,7 +2338,7 @@ class Editor extends import_eventemitter3.default {
2346
2338
  ...this._cameraOptions.__unsafe__getWithoutCapture(),
2347
2339
  ...opts
2348
2340
  });
2349
- if (next.zoomSteps?.length < 1) next.zoomSteps = [1];
2341
+ if (!next.zoomSteps || next.zoomSteps.length < 1) next.zoomSteps = [1];
2350
2342
  this._cameraOptions.set(next);
2351
2343
  this.setCamera(this.getCamera());
2352
2344
  return this;
@@ -2367,8 +2359,8 @@ class Editor extends import_eventemitter3.default {
2367
2359
  const vsb = this.getViewportScreenBounds();
2368
2360
  if (cameraOptions.constraints) {
2369
2361
  const { constraints } = cameraOptions;
2370
- const py = Math.min(constraints.padding.y, vsb.w / 2);
2371
- const px = Math.min(constraints.padding.x, vsb.h / 2);
2362
+ const px = Math.min(constraints.padding.x, vsb.w / 2);
2363
+ const py = Math.min(constraints.padding.y, vsb.h / 2);
2372
2364
  const bounds = import_Box.Box.From(cameraOptions.constraints.bounds);
2373
2365
  const zx = (vsb.w - px * 2) / bounds.w;
2374
2366
  const zy = (vsb.h - py * 2) / bounds.h;
@@ -2407,12 +2399,12 @@ class Editor extends import_eventemitter3.default {
2407
2399
  break;
2408
2400
  }
2409
2401
  case "inside": {
2410
- if (z < zx) x = (0, import_utils2.clamp)(x, minX, (vsb.w - px) / z - bounds.w);
2402
+ if (z < zx) x = (0, import_utils2.clamp)(x, minX, (vsb.w - px) / z - bounds.w - bounds.x);
2411
2403
  else x = (0, import_utils2.clamp)(x, minX + freeW, minX);
2412
2404
  break;
2413
2405
  }
2414
2406
  case "outside": {
2415
- x = (0, import_utils2.clamp)(x, px / z - bounds.w, (vsb.w - px) / z);
2407
+ x = (0, import_utils2.clamp)(x, px / z - bounds.w - bounds.x, (vsb.w - px) / z - bounds.x);
2416
2408
  break;
2417
2409
  }
2418
2410
  case "free": {
@@ -2433,12 +2425,12 @@ class Editor extends import_eventemitter3.default {
2433
2425
  break;
2434
2426
  }
2435
2427
  case "inside": {
2436
- if (z < zy) y = (0, import_utils2.clamp)(y, minY, (vsb.h - py) / z - bounds.h);
2428
+ if (z < zy) y = (0, import_utils2.clamp)(y, minY, (vsb.h - py) / z - bounds.h - bounds.y);
2437
2429
  else y = (0, import_utils2.clamp)(y, minY + freeH, minY);
2438
2430
  break;
2439
2431
  }
2440
2432
  case "outside": {
2441
- y = (0, import_utils2.clamp)(y, py / z - bounds.h, (vsb.h - py) / z);
2433
+ y = (0, import_utils2.clamp)(y, py / z - bounds.h - bounds.y, (vsb.h - py) / z - bounds.y);
2442
2434
  break;
2443
2435
  }
2444
2436
  case "free": {
@@ -2886,7 +2878,7 @@ class Editor extends import_eventemitter3.default {
2886
2878
  let newCy = cy + dy;
2887
2879
  let newCz = cz;
2888
2880
  if (dirZ !== 0) {
2889
- newCz = cz * (1 + dirZ * currentSpeed * elapsed);
2881
+ newCz = cz * Math.exp(dirZ * currentSpeed * elapsed);
2890
2882
  const center = this.getViewportScreenCenter();
2891
2883
  newCx += center.x / newCz - center.x / cz;
2892
2884
  newCy += center.y / newCz - center.y / cz;
@@ -4050,7 +4042,9 @@ class Editor extends import_eventemitter3.default {
4050
4042
  if (pageMask) {
4051
4043
  if (pageMask.length === 0) return void 0;
4052
4044
  const { corners } = pageBounds;
4053
- if (corners.every((p, i) => p && import_Vec.Vec.Equals(p, pageMask[i]))) return pageBounds.clone();
4045
+ if (pageMask.length === corners.length && corners.every((p, i) => import_Vec.Vec.Equals(p, pageMask[i]))) {
4046
+ return pageBounds.clone();
4047
+ }
4054
4048
  const intersection = (0, import_intersect.intersectPolygonPolygon)(pageMask, corners);
4055
4049
  if (!intersection) return;
4056
4050
  return import_Box.Box.FromPoints(intersection);
@@ -4289,7 +4283,7 @@ class Editor extends import_eventemitter3.default {
4289
4283
  const pointInShapeSpace = this.getPointInShapeSpace(shape, point);
4290
4284
  const shapeUtil = this.getShapeUtil(shape);
4291
4285
  const isShapeFrameLike = this.isShapeFrameLike(shape);
4292
- if (isShapeFrameLike || (this.isShapeOfType(shape, "note") || this.isShapeOfType(shape, "arrow") || this.isShapeOfType(shape, "geo") && shape.props.fill === "none") && shapeUtil.getText(shape)?.trim()) {
4286
+ if (isGroup && (isShapeFrameLike || (this.isShapeOfType(shape, "note") || this.isShapeOfType(shape, "arrow") || this.isShapeOfType(shape, "geo") && shape.props.fill === "none") && shapeUtil.getText(shape)?.trim())) {
4293
4287
  for (const childGeometry of geometry.children) {
4294
4288
  if (childGeometry.isLabel && childGeometry.isPointInBounds(pointInShapeSpace)) {
4295
4289
  return shape;
@@ -5212,26 +5206,17 @@ class Editor extends import_eventemitter3.default {
5212
5206
  toggleLock(shapes) {
5213
5207
  const ids = typeof shapes[0] === "string" ? shapes : shapes.map((s) => s.id);
5214
5208
  if (this.getIsReadonly() || ids.length === 0) return this;
5215
- let allLocked = true, allUnlocked = true;
5209
+ let allLocked = true;
5216
5210
  const shapesToToggle = [];
5217
5211
  for (const id of ids) {
5218
5212
  const shape = this.getShape(id);
5219
5213
  if (shape) {
5220
5214
  shapesToToggle.push(shape);
5221
- if (shape.isLocked) {
5222
- allUnlocked = false;
5223
- } else {
5224
- allLocked = false;
5225
- }
5215
+ if (!shape.isLocked) allLocked = false;
5226
5216
  }
5227
5217
  }
5228
5218
  this.run(() => {
5229
- if (allUnlocked) {
5230
- this.updateShapes(
5231
- shapesToToggle.map((shape) => ({ id: shape.id, type: shape.type, isLocked: true }))
5232
- );
5233
- this.setSelectedShapes([]);
5234
- } else if (allLocked) {
5219
+ if (allLocked) {
5235
5220
  this.updateShapes(
5236
5221
  shapesToToggle.map((shape) => ({ id: shape.id, type: shape.type, isLocked: false }))
5237
5222
  );
@@ -5239,6 +5224,7 @@ class Editor extends import_eventemitter3.default {
5239
5224
  this.updateShapes(
5240
5225
  shapesToToggle.map((shape) => ({ id: shape.id, type: shape.type, isLocked: true }))
5241
5226
  );
5227
+ this.setSelectedShapes([]);
5242
5228
  }
5243
5229
  });
5244
5230
  return this;
@@ -5595,7 +5581,7 @@ class Editor extends import_eventemitter3.default {
5595
5581
  }
5596
5582
  const commonBounds = import_Box.Box.Common(allBounds);
5597
5583
  const maxWidth = commonBounds.width;
5598
- shapeClustersToPack.sort((a, b) => a.pageBounds.width - b.pageBounds.width).sort((a, b) => a.pageBounds.height - b.pageBounds.height);
5584
+ shapeClustersToPack.sort((a, b) => b.pageBounds.width - a.pageBounds.width).sort((a, b) => b.pageBounds.height - a.pageBounds.height);
5599
5585
  const startWidth = Math.max(Math.ceil(Math.sqrt(area / 0.95)), maxWidth);
5600
5586
  const spaces = [new import_Box.Box(commonBounds.x, commonBounds.y, startWidth, Infinity)];
5601
5587
  let width = 0;
@@ -8720,10 +8706,9 @@ function withIsolatedShapes(editor, shapeIds, callback) {
8720
8706
  }
8721
8707
  function getCameraFitXFitY(editor, cameraOptions) {
8722
8708
  if (!cameraOptions.constraints) throw Error("Should have constraints here");
8723
- const {
8724
- padding: { x: px, y: py }
8725
- } = cameraOptions.constraints;
8726
8709
  const vsb = editor.getViewportScreenBounds();
8710
+ const px = Math.min(cameraOptions.constraints.padding.x, vsb.w / 2);
8711
+ const py = Math.min(cameraOptions.constraints.padding.y, vsb.h / 2);
8727
8712
  const bounds = import_Box.Box.From(cameraOptions.constraints.bounds);
8728
8713
  const zx = (vsb.w - px * 2) / bounds.w;
8729
8714
  const zy = (vsb.h - py * 2) / bounds.h;