@tldraw/editor 3.8.0-canary.dd058c1cfe16 → 3.8.0-canary.e04872aba13e

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 (110) hide show
  1. package/dist-cjs/index.d.ts +264 -63
  2. package/dist-cjs/index.js +15 -8
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/components/default-components/DefaultCanvas.js +2 -5
  5. package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
  6. package/dist-cjs/lib/config/TLSessionStateSnapshot.js.map +2 -2
  7. package/dist-cjs/lib/config/createTLStore.js +4 -2
  8. package/dist-cjs/lib/config/createTLStore.js.map +2 -2
  9. package/dist-cjs/lib/editor/Editor.js +98 -23
  10. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  11. package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js.map +2 -2
  12. package/dist-cjs/lib/editor/managers/TextManager.js +1 -0
  13. package/dist-cjs/lib/editor/managers/TextManager.js.map +2 -2
  14. package/dist-cjs/lib/editor/shapes/ShapeUtil.js +13 -0
  15. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
  16. package/dist-cjs/lib/editor/shapes/shared/resizeScaled.js +66 -0
  17. package/dist-cjs/lib/editor/shapes/shared/resizeScaled.js.map +7 -0
  18. package/dist-cjs/lib/editor/types/SvgExportContext.js.map +2 -2
  19. package/dist-cjs/lib/editor/types/emit-types.js.map +1 -1
  20. package/dist-cjs/lib/editor/types/external-content.js.map +1 -1
  21. package/dist-cjs/lib/editor/types/misc-types.js.map +1 -1
  22. package/dist-cjs/lib/exports/StyleEmbedder.js.map +2 -2
  23. package/dist-cjs/lib/exports/exportToSvg.js.map +2 -2
  24. package/dist-cjs/lib/exports/getSvgAsImage.js +83 -0
  25. package/dist-cjs/lib/exports/getSvgAsImage.js.map +7 -0
  26. package/dist-cjs/lib/exports/getSvgJsx.js +16 -3
  27. package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
  28. package/dist-cjs/lib/hooks/useDocumentEvents.js +1 -3
  29. package/dist-cjs/lib/hooks/useDocumentEvents.js.map +2 -2
  30. package/dist-cjs/lib/hooks/useLocalStore.js +1 -1
  31. package/dist-cjs/lib/hooks/useLocalStore.js.map +2 -2
  32. package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js +4 -0
  33. package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js.map +3 -3
  34. package/dist-cjs/lib/options.js +2 -2
  35. package/dist-cjs/lib/options.js.map +2 -2
  36. package/dist-cjs/lib/utils/browserCanvasMaxSize.js +75 -0
  37. package/dist-cjs/lib/utils/browserCanvasMaxSize.js.map +7 -0
  38. package/dist-cjs/lib/utils/dom.js +6 -0
  39. package/dist-cjs/lib/utils/dom.js.map +2 -2
  40. package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js +3 -1
  41. package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js.map +2 -2
  42. package/dist-cjs/version.js +3 -3
  43. package/dist-cjs/version.js.map +1 -1
  44. package/dist-esm/index.d.mts +264 -63
  45. package/dist-esm/index.mjs +9 -1
  46. package/dist-esm/index.mjs.map +2 -2
  47. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +2 -5
  48. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
  49. package/dist-esm/lib/config/TLSessionStateSnapshot.mjs.map +2 -2
  50. package/dist-esm/lib/config/createTLStore.mjs +4 -2
  51. package/dist-esm/lib/config/createTLStore.mjs.map +2 -2
  52. package/dist-esm/lib/editor/Editor.mjs +98 -23
  53. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  54. package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs.map +2 -2
  55. package/dist-esm/lib/editor/managers/TextManager.mjs +1 -0
  56. package/dist-esm/lib/editor/managers/TextManager.mjs.map +2 -2
  57. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +13 -0
  58. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
  59. package/dist-esm/lib/editor/shapes/shared/resizeScaled.mjs +46 -0
  60. package/dist-esm/lib/editor/shapes/shared/resizeScaled.mjs.map +7 -0
  61. package/dist-esm/lib/editor/types/SvgExportContext.mjs.map +2 -2
  62. package/dist-esm/lib/exports/StyleEmbedder.mjs.map +2 -2
  63. package/dist-esm/lib/exports/exportToSvg.mjs.map +2 -2
  64. package/dist-esm/lib/exports/getSvgAsImage.mjs +63 -0
  65. package/dist-esm/lib/exports/getSvgAsImage.mjs.map +7 -0
  66. package/dist-esm/lib/exports/getSvgJsx.mjs +16 -3
  67. package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
  68. package/dist-esm/lib/hooks/useDocumentEvents.mjs +2 -4
  69. package/dist-esm/lib/hooks/useDocumentEvents.mjs.map +2 -2
  70. package/dist-esm/lib/hooks/useLocalStore.mjs +1 -1
  71. package/dist-esm/lib/hooks/useLocalStore.mjs.map +2 -2
  72. package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs +4 -0
  73. package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs.map +3 -3
  74. package/dist-esm/lib/options.mjs +2 -2
  75. package/dist-esm/lib/options.mjs.map +2 -2
  76. package/dist-esm/lib/utils/browserCanvasMaxSize.mjs +45 -0
  77. package/dist-esm/lib/utils/browserCanvasMaxSize.mjs.map +7 -0
  78. package/dist-esm/lib/utils/dom.mjs +6 -0
  79. package/dist-esm/lib/utils/dom.mjs.map +2 -2
  80. package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs +3 -1
  81. package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs.map +2 -2
  82. package/dist-esm/version.mjs +3 -3
  83. package/dist-esm/version.mjs.map +1 -1
  84. package/editor.css +2 -1
  85. package/package.json +22 -20
  86. package/src/index.ts +20 -1
  87. package/src/lib/components/default-components/DefaultCanvas.tsx +2 -5
  88. package/src/lib/config/TLSessionStateSnapshot.ts +3 -1
  89. package/src/lib/config/createTLStore.ts +4 -2
  90. package/src/lib/editor/Editor.ts +147 -57
  91. package/src/lib/editor/managers/SnapManager/BoundsSnaps.ts +4 -4
  92. package/src/lib/editor/managers/TextManager.ts +1 -0
  93. package/src/lib/editor/shapes/ShapeUtil.ts +49 -1
  94. package/src/lib/editor/shapes/shared/resizeScaled.ts +61 -0
  95. package/src/lib/editor/types/SvgExportContext.tsx +21 -0
  96. package/src/lib/editor/types/emit-types.ts +1 -0
  97. package/src/lib/editor/types/external-content.ts +90 -50
  98. package/src/lib/editor/types/misc-types.ts +55 -2
  99. package/src/lib/exports/StyleEmbedder.ts +1 -1
  100. package/src/lib/exports/exportToSvg.tsx +2 -2
  101. package/src/lib/exports/getSvgAsImage.ts +92 -0
  102. package/src/lib/exports/getSvgJsx.tsx +17 -2
  103. package/src/lib/hooks/useDocumentEvents.ts +2 -11
  104. package/src/lib/hooks/useLocalStore.ts +1 -1
  105. package/src/lib/hooks/usePassThroughWheelEvents.ts +7 -0
  106. package/src/lib/options.ts +5 -2
  107. package/src/lib/utils/browserCanvasMaxSize.ts +65 -0
  108. package/src/lib/utils/dom.ts +12 -0
  109. package/src/lib/utils/sync/TLLocalSyncClient.ts +3 -1
  110. package/src/version.ts +3 -3
@@ -111,6 +111,7 @@ import {
111
111
  ZOOM_TO_FIT_PADDING
112
112
  } from "../constants.mjs";
113
113
  import { exportToSvg } from "../exports/exportToSvg.mjs";
114
+ import { getSvgAsImage } from "../exports/getSvgAsImage.mjs";
114
115
  import { tlenv } from "../globals/environment.mjs";
115
116
  import { tlmenus } from "../globals/menus.mjs";
116
117
  import { tltime } from "../globals/time.mjs";
@@ -838,6 +839,10 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
838
839
  assert(shapeUtil, `No shape util found for type "${type}"`);
839
840
  return shapeUtil;
840
841
  }
842
+ hasShapeUtil(arg) {
843
+ const type = typeof arg === "string" ? arg : arg.type;
844
+ return hasOwnProperty(this.shapeUtils, type);
845
+ }
841
846
  getBindingUtil(arg) {
842
847
  const type = typeof arg === "string" ? arg : arg.type;
843
848
  const bindingUtil = getOwnProperty(this.bindingUtils, type);
@@ -1064,9 +1069,20 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
1064
1069
  },
1065
1070
  extras: {
1066
1071
  activeStateNode: this.root.getPath(),
1067
- selectedShapes: this.getSelectedShapes(),
1072
+ selectedShapes: this.getSelectedShapes().map((s) => {
1073
+ const { props, ...rest } = s;
1074
+ const { text: _text, richText: _richText, ...restProps } = props;
1075
+ return {
1076
+ ...rest,
1077
+ props: restProps
1078
+ };
1079
+ }),
1080
+ selectionCount: this.getSelectedShapes().length,
1068
1081
  editingShape: editingShapeId ? this.getShape(editingShapeId) : void 0,
1069
- inputs: this.inputs
1082
+ inputs: this.inputs,
1083
+ pageState: this.getCurrentPageState(),
1084
+ instanceState: this.getInstanceState(),
1085
+ collaboratorCount: this.getCollaboratorsOnCurrentPage().length
1070
1086
  }
1071
1087
  };
1072
1088
  } catch {
@@ -1174,8 +1190,8 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
1174
1190
  *
1175
1191
  * @example
1176
1192
  * ```ts
1177
- * state.getStateDescendant('select')
1178
- * state.getStateDescendant('select.brushing')
1193
+ * editor.getStateDescendant('select')
1194
+ * editor.getStateDescendant('select.brushing')
1179
1195
  * ```
1180
1196
  *
1181
1197
  * @param path - The descendant's path of state ids, separated by periods.
@@ -1229,7 +1245,7 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
1229
1245
  if (partial.isChangingStyle === true) {
1230
1246
  this._isChangingStyleTimeout = this.timers.setTimeout(() => {
1231
1247
  this._updateInstanceState({ isChangingStyle: false }, { history: "ignore" });
1232
- }, 2e3);
1248
+ }, 1e3);
1233
1249
  }
1234
1250
  }
1235
1251
  return this;
@@ -3180,11 +3196,14 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
3180
3196
  if (!assetId) return null;
3181
3197
  const asset = this.getAsset(assetId);
3182
3198
  if (!asset) return null;
3183
- const { screenScale = 1, shouldResolveToOriginal = false } = context;
3199
+ const {
3200
+ screenScale = 1,
3201
+ shouldResolveToOriginal = false,
3202
+ dpr = this.getInstanceState().devicePixelRatio
3203
+ } = context;
3184
3204
  const zoomStepFunction = (zoom) => Math.pow(2, Math.ceil(Math.log2(zoom)));
3185
- const steppedScreenScale = Math.max(0.125, zoomStepFunction(screenScale));
3205
+ const steppedScreenScale = zoomStepFunction(screenScale);
3186
3206
  const networkEffectiveType = "connection" in navigator ? navigator.connection.effectiveType : null;
3187
- const dpr = this.getInstanceState().devicePixelRatio;
3188
3207
  return await this.store.props.assets.resolve(asset, {
3189
3208
  screenScale: screenScale || 1,
3190
3209
  steppedScreenScale,
@@ -5105,6 +5124,7 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
5105
5124
  scale = new Vec(Math.sign(scale.x) * Math.abs(scale.y), scale.y);
5106
5125
  }
5107
5126
  }
5127
+ let didResize = false;
5108
5128
  if (util.onResize && util.canResize(initialShape)) {
5109
5129
  const newPagePoint = this._scalePagePoint(
5110
5130
  Mat.applyToPoint(pageTransform, new Vec(0, 0)),
@@ -5129,24 +5149,28 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
5129
5149
  util.onResizeStart?.(initialShape) ?? void 0
5130
5150
  );
5131
5151
  }
5152
+ const resizedShape = util.onResize(
5153
+ { ...initialShape, x, y },
5154
+ {
5155
+ newPoint: newLocalPoint,
5156
+ handle: opts.dragHandle ?? "bottom_right",
5157
+ // don't set isSingle to true for children
5158
+ mode: opts.mode ?? "scale_shape",
5159
+ scaleX: myScale.x,
5160
+ scaleY: myScale.y,
5161
+ initialBounds,
5162
+ initialShape
5163
+ }
5164
+ );
5165
+ if (resizedShape) {
5166
+ didResize = true;
5167
+ }
5132
5168
  workingShape = applyPartialToRecordWithProps(workingShape, {
5133
5169
  id,
5134
5170
  type: initialShape.type,
5135
5171
  x: newLocalPoint.x,
5136
5172
  y: newLocalPoint.y,
5137
- ...util.onResize(
5138
- { ...initialShape, x, y },
5139
- {
5140
- newPoint: newLocalPoint,
5141
- handle: opts.dragHandle ?? "bottom_right",
5142
- // don't set isSingle to true for children
5143
- mode: opts.mode ?? "scale_shape",
5144
- scaleX: myScale.x,
5145
- scaleY: myScale.y,
5146
- initialBounds,
5147
- initialShape
5148
- }
5149
- )
5173
+ ...resizedShape
5150
5174
  });
5151
5175
  if (!opts.skipStartAndEndCallbacks) {
5152
5176
  workingShape = applyPartialToRecordWithProps(
@@ -5155,7 +5179,8 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
5155
5179
  );
5156
5180
  }
5157
5181
  this.updateShapes([workingShape]);
5158
- } else {
5182
+ }
5183
+ if (!didResize) {
5159
5184
  const initialPageCenter = Mat.applyToPoint(pageTransform, initialBounds.center);
5160
5185
  const newPageCenter = this._scalePagePoint(
5161
5186
  initialPageCenter,
@@ -6302,7 +6327,7 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
6302
6327
  * @public
6303
6328
  */
6304
6329
  async getSvgElement(shapes, opts = {}) {
6305
- const ids = typeof shapes[0] === "string" ? shapes : shapes.map((s) => s.id);
6330
+ const ids = shapes.length === 0 ? this.getCurrentPageShapeIdsSorted() : typeof shapes[0] === "string" ? shapes : shapes.map((s) => s.id);
6306
6331
  if (ids.length === 0) return void 0;
6307
6332
  return exportToSvg(this, ids, opts);
6308
6333
  }
@@ -6332,6 +6357,55 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
6332
6357
  if (!result) return void 0;
6333
6358
  return result.svg;
6334
6359
  }
6360
+ /**
6361
+ * Get an exported image of the given shapes.
6362
+ *
6363
+ * @param shapes - The shapes (or shape ids) to export.
6364
+ * @param opts - Options for the export.
6365
+ *
6366
+ * @returns A blob of the image.
6367
+ * @public
6368
+ */
6369
+ async toImage(shapes, opts = {}) {
6370
+ const withDefaults = {
6371
+ format: "png",
6372
+ scale: 1,
6373
+ pixelRatio: opts.format === "svg" ? void 0 : 2,
6374
+ ...opts
6375
+ };
6376
+ const result = await this.getSvgString(shapes, withDefaults);
6377
+ if (!result) throw new Error("Could not create SVG");
6378
+ switch (withDefaults.format) {
6379
+ case "svg":
6380
+ return {
6381
+ blob: new Blob([result.svg], { type: "text/plain" }),
6382
+ width: result.width,
6383
+ height: result.height
6384
+ };
6385
+ case "jpeg":
6386
+ case "png":
6387
+ case "webp": {
6388
+ const blob = await getSvgAsImage(result.svg, {
6389
+ type: withDefaults.format,
6390
+ quality: withDefaults.quality,
6391
+ pixelRatio: withDefaults.pixelRatio,
6392
+ width: result.width,
6393
+ height: result.height
6394
+ });
6395
+ if (!blob) {
6396
+ throw new Error("Could not construct image.");
6397
+ }
6398
+ return {
6399
+ blob,
6400
+ width: result.width,
6401
+ height: result.height
6402
+ };
6403
+ }
6404
+ default: {
6405
+ exhaustiveSwitchError(withDefaults.format);
6406
+ }
6407
+ }
6408
+ }
6335
6409
  /**
6336
6410
  * Update the input points from a pointer, pinch, or wheel event.
6337
6411
  *
@@ -6825,6 +6899,7 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
6825
6899
  }
6826
6900
  _flushEventForTick(info) {
6827
6901
  if (this.getCrashingError()) return this;
6902
+ this.emit("before-event", info);
6828
6903
  const { inputs } = this;
6829
6904
  const { type } = info;
6830
6905
  if (info.type === "misc") {