@tsdraw/core 0.6.2 → 0.8.0

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/index.js CHANGED
@@ -223,25 +223,34 @@ var StateNode = class {
223
223
 
224
224
  // src/canvas/viewport.ts
225
225
  function createViewport() {
226
- return { x: 0, y: 0, zoom: 1 };
226
+ return { x: 0, y: 0, zoom: 1, rotation: 0 };
227
227
  }
228
228
  function screenToPage(viewport, screenX, screenY) {
229
+ const tx = screenX - viewport.x;
230
+ const ty = screenY - viewport.y;
231
+ const cos = Math.cos(viewport.rotation);
232
+ const sin = Math.sin(viewport.rotation);
229
233
  return {
230
- x: (screenX - viewport.x) / viewport.zoom,
231
- y: (screenY - viewport.y) / viewport.zoom
234
+ x: (tx * cos + ty * sin) / viewport.zoom,
235
+ y: (-tx * sin + ty * cos) / viewport.zoom
232
236
  };
233
237
  }
234
238
  function pageToScreen(viewport, pageX, pageY) {
239
+ const scaledX = pageX * viewport.zoom;
240
+ const scaledY = pageY * viewport.zoom;
241
+ const cos = Math.cos(viewport.rotation);
242
+ const sin = Math.sin(viewport.rotation);
235
243
  return {
236
- x: pageX * viewport.zoom + viewport.x,
237
- y: pageY * viewport.zoom + viewport.y
244
+ x: scaledX * cos - scaledY * sin + viewport.x,
245
+ y: scaledX * sin + scaledY * cos + viewport.y
238
246
  };
239
247
  }
240
248
  function setViewport(viewport, updater) {
241
249
  return {
242
250
  x: updater.x ?? viewport.x,
243
251
  y: updater.y ?? viewport.y,
244
- zoom: updater.zoom ?? viewport.zoom
252
+ zoom: updater.zoom ?? viewport.zoom,
253
+ rotation: updater.rotation ?? viewport.rotation
245
254
  };
246
255
  }
247
256
  function panViewport(viewport, dx, dy) {
@@ -253,9 +262,23 @@ function zoomViewport(viewport, factor, centerX, centerY) {
253
262
  return { ...viewport, zoom };
254
263
  }
255
264
  const pageBefore = screenToPage(viewport, centerX, centerY);
256
- const x = centerX - pageBefore.x * zoom;
257
- const y = centerY - pageBefore.y * zoom;
258
- return { x, y, zoom };
265
+ const cos = Math.cos(viewport.rotation);
266
+ const sin = Math.sin(viewport.rotation);
267
+ const x = centerX - (pageBefore.x * zoom * cos - pageBefore.y * zoom * sin);
268
+ const y = centerY - (pageBefore.x * zoom * sin + pageBefore.y * zoom * cos);
269
+ return { x, y, zoom, rotation: viewport.rotation };
270
+ }
271
+ function rotateViewport(viewport, delta, centerX, centerY) {
272
+ const rotation = viewport.rotation + delta;
273
+ if (centerX == null || centerY == null) {
274
+ return { ...viewport, rotation };
275
+ }
276
+ const pageBefore = screenToPage(viewport, centerX, centerY);
277
+ const cos = Math.cos(rotation);
278
+ const sin = Math.sin(rotation);
279
+ const x = centerX - (pageBefore.x * viewport.zoom * cos - pageBefore.y * viewport.zoom * sin);
280
+ const y = centerY - (pageBefore.x * viewport.zoom * sin + pageBefore.y * viewport.zoom * cos);
281
+ return { x, y, zoom: viewport.zoom, rotation };
259
282
  }
260
283
 
261
284
  // src/utils/colors.ts
@@ -288,6 +311,7 @@ var CanvasRenderer = class {
288
311
  render(ctx, viewport, shapes) {
289
312
  ctx.save();
290
313
  ctx.translate(viewport.x, viewport.y);
314
+ ctx.rotate(viewport.rotation);
291
315
  ctx.scale(viewport.zoom, viewport.zoom);
292
316
  for (const shape of shapes) {
293
317
  if (shape.type === "draw") {
@@ -296,11 +320,16 @@ var CanvasRenderer = class {
296
320
  }
297
321
  ctx.restore();
298
322
  }
323
+ // Paints a single stroke
299
324
  paintStroke(ctx, shape) {
300
325
  const width = (STROKE_WIDTHS[shape.props.size] ?? 3.5) * shape.props.scale;
301
326
  const samples = flattenSegments(shape);
302
327
  if (samples.length === 0) return;
303
328
  const color = resolveThemeColor(shape.props.color, this.theme);
329
+ const fillStyle = shape.props.fill ?? "none";
330
+ if (shape.props.isClosed && fillStyle !== "none") {
331
+ this.paintClosedShapeFill(ctx, samples, color, fillStyle);
332
+ }
304
333
  if (shape.props.dash !== "draw") {
305
334
  this.paintDashedStroke(ctx, samples, width, color, shape.props.dash);
306
335
  return;
@@ -347,6 +376,30 @@ var CanvasRenderer = class {
347
376
  ctx.stroke();
348
377
  ctx.restore();
349
378
  }
379
+ // Closed shapes are shapes where their start and end point are the same
380
+ paintClosedShapeFill(ctx, samples, color, fillStyle) {
381
+ if (samples.length < 3) return;
382
+ ctx.save();
383
+ ctx.beginPath();
384
+ ctx.moveTo(samples[0].x, samples[0].y);
385
+ for (let i = 1; i < samples.length; i++) {
386
+ const sample = samples[i];
387
+ ctx.lineTo(sample.x, sample.y);
388
+ }
389
+ ctx.closePath();
390
+ if (fillStyle === "solid") {
391
+ ctx.fillStyle = color;
392
+ ctx.globalAlpha = 0.55;
393
+ } else if (fillStyle === "none") {
394
+ ctx.fillStyle = this.theme === "dark" ? "#0f0f0f" : "#fafafa";
395
+ ctx.globalAlpha = 1;
396
+ } else {
397
+ ctx.fillStyle = color;
398
+ ctx.globalAlpha = 0.28;
399
+ }
400
+ ctx.fill();
401
+ ctx.restore();
402
+ }
350
403
  };
351
404
  var PRESSURE_FLOOR = 0.025;
352
405
  var STYLUS_CURVE = (t) => t * 0.65 + Math.sin(t * Math.PI / 2) * 0.35;
@@ -360,7 +413,7 @@ function remap(value, inRange, outRange, clamp = false) {
360
413
  return outLo + (outHi - outLo) * clamped;
361
414
  }
362
415
  function strokeConfig(shape, width) {
363
- const done = shape.props.isComplete;
416
+ const done = shape.props.isComplete || shape.props.isClosed === true;
364
417
  if (shape.props.isPen) {
365
418
  return {
366
419
  size: 1 + width * 1.2,
@@ -419,9 +472,6 @@ function flattenSegments(shape) {
419
472
  }
420
473
  out.push(D);
421
474
  }
422
- if (out.length > 0 && !shape.props.isPen) {
423
- for (const p of out) p.pressure = 0.5;
424
- }
425
475
  return out;
426
476
  }
427
477
  function getLineDash(dash, width) {
@@ -752,8 +802,8 @@ var PenDrawingState = class extends StateNode {
752
802
  const penActive = inputs.getIsPen();
753
803
  const z = this._startInfo?.point?.z ?? 0.5;
754
804
  this._isPenDevice = penActive;
755
- this._hasPressure = penActive && z !== 0 || z > 0 && z < 0.5 || z > 0.5 && z < 1;
756
- const pressure = this._hasPressure ? toFixed(z * 1.25) : 0.5;
805
+ this._hasPressure = penActive || z !== 0.5;
806
+ const pressure = this._hasPressure ? toFixed(z) : 0.5;
757
807
  this._phase = inputs.getShiftKey() ? "straight" : "free";
758
808
  this._extending = false;
759
809
  this._lastSample = { ...origin };
@@ -848,8 +898,15 @@ var PenDrawingState = class extends StateNode {
848
898
  const { id, props: { size, scale } } = target;
849
899
  const { segments } = shape.props;
850
900
  const curPt = inputs.getCurrentPagePoint();
901
+ if (!this._hasPressure) {
902
+ const liveZ = curPt.z ?? 0.5;
903
+ if (liveZ !== 0.5 || inputs.getIsPen()) {
904
+ this._hasPressure = true;
905
+ this.editor.updateShapes([{ id, type: "draw", props: { isPen: true } }]);
906
+ }
907
+ }
851
908
  const local = this.editor.getPointInShapeSpace(shape, curPt);
852
- const pressure = this._hasPressure ? toFixed((curPt.z ?? 0.5) * 1.25) : 0.5;
909
+ const pressure = this._hasPressure ? toFixed(curPt.z ?? 0.5) : 0.5;
853
910
  const pt = { x: toFixed(local.x), y: toFixed(local.y), z: pressure };
854
911
  switch (this._phase) {
855
912
  case "starting_straight": {
@@ -995,7 +1052,7 @@ var PenDrawingState = class extends StateNode {
995
1052
  const firstPt = {
996
1053
  x: 0,
997
1054
  y: 0,
998
- z: this._hasPressure ? toFixed((curPage.z ?? 0.5) * 1.25) : 0.5
1055
+ z: this._hasPressure ? toFixed(curPage.z ?? 0.5) : 0.5
999
1056
  };
1000
1057
  this._activePts = [firstPt];
1001
1058
  this.editor.createShape({
@@ -1033,6 +1090,236 @@ var PenDrawingState = class extends StateNode {
1033
1090
  }
1034
1091
  };
1035
1092
 
1093
+ // src/tools/square/states/SquareIdleState.ts
1094
+ var SquareIdleState = class extends StateNode {
1095
+ static id = "square_idle";
1096
+ onPointerDown(info) {
1097
+ this.ctx.transition("square_drawing", info);
1098
+ }
1099
+ };
1100
+
1101
+ // src/tools/geometric/states/GeometricDrawingState.ts
1102
+ var GeometricDrawingState = class extends StateNode {
1103
+ currentShapeId = null;
1104
+ startedAt = { point: { x: 0, y: 0, z: 0.5 } };
1105
+ onEnter(info) {
1106
+ this.startedAt = info ?? { point: { x: 0, y: 0, z: 0.5 } };
1107
+ const originPoint = this.editor.input.getOriginPagePoint();
1108
+ const drawStyle = this.editor.getCurrentDrawStyle();
1109
+ const nextShapeId = this.editor.createShapeId();
1110
+ const config = this.getConfig();
1111
+ this.editor.createShape({
1112
+ id: nextShapeId,
1113
+ type: "draw",
1114
+ x: originPoint.x,
1115
+ y: originPoint.y,
1116
+ props: {
1117
+ color: drawStyle.color,
1118
+ dash: drawStyle.dash,
1119
+ fill: drawStyle.fill,
1120
+ size: drawStyle.size,
1121
+ scale: 1,
1122
+ isPen: false,
1123
+ isComplete: false,
1124
+ isClosed: true,
1125
+ segments: config.buildSegments(1, 1)
1126
+ }
1127
+ });
1128
+ this.currentShapeId = nextShapeId;
1129
+ }
1130
+ onPointerMove() {
1131
+ const activeShape = this.getActiveShape();
1132
+ if (!activeShape) return;
1133
+ const config = this.getConfig();
1134
+ const originPoint = this.editor.input.getOriginPagePoint();
1135
+ const cursorPoint = this.editor.input.getCurrentPagePoint();
1136
+ const shapeBounds = this.editor.input.getShiftKey() ? config.buildConstrainedBounds(originPoint.x, originPoint.y, cursorPoint.x, cursorPoint.y) : config.buildUnconstrainedBounds(originPoint.x, originPoint.y, cursorPoint.x, cursorPoint.y);
1137
+ this.editor.store.updateShape(activeShape.id, {
1138
+ x: shapeBounds.x,
1139
+ y: shapeBounds.y,
1140
+ props: {
1141
+ ...activeShape.props,
1142
+ segments: config.buildSegments(shapeBounds.width, shapeBounds.height),
1143
+ isClosed: true
1144
+ }
1145
+ });
1146
+ }
1147
+ onPointerUp() {
1148
+ this.completeShape();
1149
+ }
1150
+ onCancel() {
1151
+ this.removeCurrentShape();
1152
+ this.ctx.transition(this.getConfig().idleStateId, this.startedAt);
1153
+ }
1154
+ onInterrupt() {
1155
+ this.completeShape();
1156
+ }
1157
+ onKeyDown() {
1158
+ this.onPointerMove();
1159
+ }
1160
+ onKeyUp() {
1161
+ this.onPointerMove();
1162
+ }
1163
+ completeShape() {
1164
+ const activeShape = this.getActiveShape();
1165
+ const config = this.getConfig();
1166
+ if (!activeShape) {
1167
+ this.ctx.transition(config.idleStateId, this.startedAt);
1168
+ return;
1169
+ }
1170
+ const originPoint = this.editor.input.getOriginPagePoint();
1171
+ const cursorPoint = this.editor.input.getCurrentPagePoint();
1172
+ const finalizedBounds = this.editor.input.getIsDragging() ? this.editor.input.getShiftKey() ? config.buildConstrainedBounds(originPoint.x, originPoint.y, cursorPoint.x, cursorPoint.y) : config.buildUnconstrainedBounds(originPoint.x, originPoint.y, cursorPoint.x, cursorPoint.y) : config.buildDefaultBounds(originPoint.x, originPoint.y);
1173
+ this.editor.store.updateShape(activeShape.id, {
1174
+ x: finalizedBounds.x,
1175
+ y: finalizedBounds.y,
1176
+ props: {
1177
+ ...activeShape.props,
1178
+ fill: this.editor.getCurrentDrawStyle().fill,
1179
+ isComplete: true,
1180
+ isClosed: true,
1181
+ segments: config.buildSegments(finalizedBounds.width, finalizedBounds.height)
1182
+ }
1183
+ });
1184
+ this.currentShapeId = null;
1185
+ this.ctx.transition(config.idleStateId);
1186
+ }
1187
+ removeCurrentShape() {
1188
+ if (!this.currentShapeId) return;
1189
+ this.editor.store.deleteShapes([this.currentShapeId]);
1190
+ this.currentShapeId = null;
1191
+ }
1192
+ getActiveShape() {
1193
+ if (!this.currentShapeId) return null;
1194
+ const shape = this.editor.getShape(this.currentShapeId);
1195
+ if (!shape || shape.type !== "draw") return null;
1196
+ return shape;
1197
+ }
1198
+ };
1199
+
1200
+ // src/tools/geometric/geometricShapeHelpers.ts
1201
+ var MIN_SIDE_LENGTH = 1;
1202
+ var DEFAULT_RECTANGLE_WIDTH = 180;
1203
+ var DEFAULT_RECTANGLE_HEIGHT = 120;
1204
+ var DEFAULT_ELLIPSE_WIDTH = 180;
1205
+ var DEFAULT_ELLIPSE_HEIGHT = 120;
1206
+ function toSizedBounds(anchorX, anchorY, cursorX, cursorY, forceEqualSides) {
1207
+ const rawDeltaX = cursorX - anchorX;
1208
+ const rawDeltaY = cursorY - anchorY;
1209
+ const sideLength = Math.max(Math.abs(rawDeltaX), Math.abs(rawDeltaY), MIN_SIDE_LENGTH);
1210
+ if (forceEqualSides) {
1211
+ const nextDeltaX = rawDeltaX < 0 ? -sideLength : sideLength;
1212
+ const nextDeltaY = rawDeltaY < 0 ? -sideLength : sideLength;
1213
+ return normalizeBounds(anchorX, anchorY, anchorX + nextDeltaX, anchorY + nextDeltaY);
1214
+ }
1215
+ return normalizeBounds(anchorX, anchorY, cursorX, cursorY);
1216
+ }
1217
+ function normalizeBounds(startX, startY, endX, endY) {
1218
+ const x = Math.min(startX, endX);
1219
+ const y = Math.min(startY, endY);
1220
+ const width = Math.max(Math.abs(endX - startX), MIN_SIDE_LENGTH);
1221
+ const height = Math.max(Math.abs(endY - startY), MIN_SIDE_LENGTH);
1222
+ return { x, y, width, height };
1223
+ }
1224
+ function buildSquareBounds(anchorX, anchorY, cursorX, cursorY) {
1225
+ return toSizedBounds(anchorX, anchorY, cursorX, cursorY, true);
1226
+ }
1227
+ function buildRectangleBounds(anchorX, anchorY, cursorX, cursorY) {
1228
+ return toSizedBounds(anchorX, anchorY, cursorX, cursorY, false);
1229
+ }
1230
+ function buildDefaultCenteredRectangleBounds(centerX, centerY) {
1231
+ const halfWidth = DEFAULT_RECTANGLE_WIDTH / 2;
1232
+ const halfHeight = DEFAULT_RECTANGLE_HEIGHT / 2;
1233
+ return {
1234
+ x: centerX - halfWidth,
1235
+ y: centerY - halfHeight,
1236
+ width: DEFAULT_RECTANGLE_WIDTH,
1237
+ height: DEFAULT_RECTANGLE_HEIGHT
1238
+ };
1239
+ }
1240
+ function buildRectangleSegments(width, height) {
1241
+ const topLeft = { x: 0, y: 0, z: 0.5 };
1242
+ const topRight = { x: width, y: 0, z: 0.5 };
1243
+ const bottomRight = { x: width, y: height, z: 0.5 };
1244
+ const bottomLeft = { x: 0, y: height, z: 0.5 };
1245
+ return [
1246
+ { type: "straight", path: encodePoints([topLeft, topRight]) },
1247
+ { type: "straight", path: encodePoints([topRight, bottomRight]) },
1248
+ { type: "straight", path: encodePoints([bottomRight, bottomLeft]) },
1249
+ { type: "straight", path: encodePoints([bottomLeft, topLeft]) }
1250
+ ];
1251
+ }
1252
+ function buildCircleBounds(anchorX, anchorY, cursorX, cursorY) {
1253
+ return toSizedBounds(anchorX, anchorY, cursorX, cursorY, true);
1254
+ }
1255
+ function buildEllipseBounds(anchorX, anchorY, cursorX, cursorY) {
1256
+ return toSizedBounds(anchorX, anchorY, cursorX, cursorY, false);
1257
+ }
1258
+ function buildDefaultCenteredEllipseBounds(centerX, centerY) {
1259
+ const halfWidth = DEFAULT_ELLIPSE_WIDTH / 2;
1260
+ const halfHeight = DEFAULT_ELLIPSE_HEIGHT / 2;
1261
+ return {
1262
+ x: centerX - halfWidth,
1263
+ y: centerY - halfHeight,
1264
+ width: DEFAULT_ELLIPSE_WIDTH,
1265
+ height: DEFAULT_ELLIPSE_HEIGHT
1266
+ };
1267
+ }
1268
+ function buildEllipseSegments(width, height) {
1269
+ const centerX = width / 2;
1270
+ const centerY = height / 2;
1271
+ const radiusX = width / 2;
1272
+ const radiusY = height / 2;
1273
+ const sampleCount = 64;
1274
+ const sampledPoints = [];
1275
+ for (let sampleIndex = 0; sampleIndex <= sampleCount; sampleIndex += 1) {
1276
+ const progress = sampleIndex / sampleCount;
1277
+ const angle = progress * Math.PI * 2;
1278
+ sampledPoints.push({
1279
+ x: centerX + Math.cos(angle) * radiusX,
1280
+ y: centerY + Math.sin(angle) * radiusY,
1281
+ z: 0.5
1282
+ });
1283
+ }
1284
+ return [{ type: "free", path: encodePoints(sampledPoints) }];
1285
+ }
1286
+
1287
+ // src/tools/square/states/SquareDrawingState.ts
1288
+ var SquareDrawingState = class extends GeometricDrawingState {
1289
+ static id = "square_drawing";
1290
+ getConfig() {
1291
+ return {
1292
+ idleStateId: "square_idle",
1293
+ buildConstrainedBounds: buildSquareBounds,
1294
+ buildUnconstrainedBounds: buildRectangleBounds,
1295
+ buildDefaultBounds: buildDefaultCenteredRectangleBounds,
1296
+ buildSegments: buildRectangleSegments
1297
+ };
1298
+ }
1299
+ };
1300
+
1301
+ // src/tools/circle/states/CircleIdleState.ts
1302
+ var CircleIdleState = class extends StateNode {
1303
+ static id = "circle_idle";
1304
+ onPointerDown(info) {
1305
+ this.ctx.transition("circle_drawing", info);
1306
+ }
1307
+ };
1308
+
1309
+ // src/tools/circle/states/CircleDrawingState.ts
1310
+ var CircleDrawingState = class extends GeometricDrawingState {
1311
+ static id = "circle_drawing";
1312
+ getConfig() {
1313
+ return {
1314
+ idleStateId: "circle_idle",
1315
+ buildConstrainedBounds: buildCircleBounds,
1316
+ buildUnconstrainedBounds: buildEllipseBounds,
1317
+ buildDefaultBounds: buildDefaultCenteredEllipseBounds,
1318
+ buildSegments: buildEllipseSegments
1319
+ };
1320
+ }
1321
+ };
1322
+
1036
1323
  // src/tools/eraser/states/EraserIdleState.ts
1037
1324
  var EraserIdleState = class extends StateNode {
1038
1325
  static id = "eraser_idle";
@@ -1346,6 +1633,7 @@ var Editor = class {
1346
1633
  drawStyle = {
1347
1634
  color: "black",
1348
1635
  dash: "draw",
1636
+ fill: "none",
1349
1637
  size: "m"
1350
1638
  };
1351
1639
  toolStateContext;
@@ -1405,6 +1693,8 @@ var Editor = class {
1405
1693
  getDefaultToolDefinitions() {
1406
1694
  return [
1407
1695
  { id: "pen", initialStateId: PenIdleState.id, stateConstructors: [PenIdleState, PenDrawingState] },
1696
+ { id: "square", initialStateId: SquareIdleState.id, stateConstructors: [SquareIdleState, SquareDrawingState] },
1697
+ { id: "circle", initialStateId: CircleIdleState.id, stateConstructors: [CircleIdleState, CircleDrawingState] },
1408
1698
  { id: "eraser", initialStateId: EraserIdleState.id, stateConstructors: [EraserIdleState, EraserPointingState, EraserErasingState] },
1409
1699
  { id: "select", initialStateId: SelectIdleState.id, stateConstructors: [SelectIdleState] },
1410
1700
  { id: "hand", initialStateId: HandIdleState.id, stateConstructors: [HandIdleState, HandDraggingState] }
@@ -1472,7 +1762,8 @@ var Editor = class {
1472
1762
  this.viewport = {
1473
1763
  x: partial.x ?? this.viewport.x,
1474
1764
  y: partial.y ?? this.viewport.y,
1475
- zoom: Math.max(0.1, Math.min(4, rawZoom))
1765
+ zoom: Math.max(0.1, Math.min(4, rawZoom)),
1766
+ rotation: partial.rotation ?? this.viewport.rotation
1476
1767
  };
1477
1768
  this.emitChange();
1478
1769
  }
@@ -1482,6 +1773,18 @@ var Editor = class {
1482
1773
  y: this.viewport.y + dy
1483
1774
  });
1484
1775
  }
1776
+ zoomAt(factor, screenX, screenY) {
1777
+ this.viewport = zoomViewport(this.viewport, factor, screenX, screenY);
1778
+ this.emitChange();
1779
+ }
1780
+ rotateAt(delta, screenX, screenY) {
1781
+ this.viewport = rotateViewport(this.viewport, delta, screenX, screenY);
1782
+ this.emitChange();
1783
+ }
1784
+ deleteShapes(ids) {
1785
+ if (ids.length === 0) return;
1786
+ this.store.deleteShapes(ids);
1787
+ }
1485
1788
  getDocumentSnapshot() {
1486
1789
  return {
1487
1790
  records: documentSnapshotToRecords(this.store.getSnapshot())
@@ -1500,7 +1803,8 @@ var Editor = class {
1500
1803
  viewport: {
1501
1804
  x: this.viewport.x,
1502
1805
  y: this.viewport.y,
1503
- zoom: this.viewport.zoom
1806
+ zoom: this.viewport.zoom,
1807
+ rotation: this.viewport.rotation
1504
1808
  },
1505
1809
  currentToolId: this.getCurrentToolId(),
1506
1810
  drawStyle: this.getCurrentDrawStyle(),
@@ -1508,8 +1812,16 @@ var Editor = class {
1508
1812
  };
1509
1813
  }
1510
1814
  loadSessionStateSnapshot(snapshot) {
1511
- this.setViewport(snapshot.viewport);
1512
- this.setCurrentDrawStyle(snapshot.drawStyle);
1815
+ this.setViewport({
1816
+ ...snapshot.viewport,
1817
+ rotation: snapshot.viewport.rotation ?? 0
1818
+ });
1819
+ this.setCurrentDrawStyle({
1820
+ color: snapshot.drawStyle.color,
1821
+ dash: snapshot.drawStyle.dash,
1822
+ fill: snapshot.drawStyle.fill ?? "none",
1823
+ size: snapshot.drawStyle.size
1824
+ });
1513
1825
  if (this.tools.hasTool(snapshot.currentToolId)) {
1514
1826
  this.setCurrentTool(snapshot.currentToolId);
1515
1827
  }
@@ -1890,6 +2202,6 @@ function applyResize(editor, handle, startBounds, startShapes, pointer, lockAspe
1890
2202
  }
1891
2203
  }
1892
2204
 
1893
- export { CanvasRenderer, DEFAULT_COLORS, DRAG_DISTANCE_SQUARED, DocumentStore, ERASER_MARGIN, Editor, EraserErasingState, EraserIdleState, EraserPointingState, HandDraggingState, HandIdleState, InputManager, MAX_POINTS_PER_SHAPE, PenDrawingState, PenIdleState, STROKE_WIDTHS, SelectIdleState, StateNode, ToolManager, applyMove, applyResize, applyRotation, boundsContainPoint, boundsIntersect, boundsOf, buildStartPositions, buildTransformSnapshots, closestOnSegment, createViewport, decodeFirstPoint, decodeLastPoint, decodePathToPoints, decodePoints, distance, documentSnapshotToRecords, encodePoints, getSelectionBoundsPage, getShapeBounds2 as getShapeBounds, getShapesInBounds, getTopShapeAtPoint, isSelectTool, minDistanceToPolyline, normalizeSelectionBounds, padBounds, pageToScreen, panViewport, pointHitsShape, recordsToDocumentSnapshot, resolveThemeColor, rotatePoint, screenToPage, segmentHitsShape, segmentTouchesPolyline, setViewport, shapePagePoints, sqDistance, zoomViewport };
2205
+ export { CanvasRenderer, CircleDrawingState, CircleIdleState, DEFAULT_COLORS, DRAG_DISTANCE_SQUARED, DocumentStore, ERASER_MARGIN, Editor, EraserErasingState, EraserIdleState, EraserPointingState, HandDraggingState, HandIdleState, InputManager, MAX_POINTS_PER_SHAPE, PenDrawingState, PenIdleState, STROKE_WIDTHS, SelectIdleState, SquareDrawingState, SquareIdleState, StateNode, ToolManager, applyMove, applyResize, applyRotation, boundsContainPoint, boundsIntersect, boundsOf, buildStartPositions, buildTransformSnapshots, closestOnSegment, createViewport, decodeFirstPoint, decodeLastPoint, decodePathToPoints, decodePoints, distance, documentSnapshotToRecords, encodePoints, getSelectionBoundsPage, getShapeBounds2 as getShapeBounds, getShapesInBounds, getTopShapeAtPoint, isSelectTool, minDistanceToPolyline, normalizeSelectionBounds, padBounds, pageToScreen, panViewport, pointHitsShape, recordsToDocumentSnapshot, resolveThemeColor, rotatePoint, rotateViewport, screenToPage, segmentHitsShape, segmentTouchesPolyline, setViewport, shapePagePoints, sqDistance, zoomViewport };
1894
2206
  //# sourceMappingURL=index.js.map
1895
2207
  //# sourceMappingURL=index.js.map