@tsdraw/core 0.7.0 → 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.cjs CHANGED
@@ -225,25 +225,34 @@ var StateNode = class {
225
225
 
226
226
  // src/canvas/viewport.ts
227
227
  function createViewport() {
228
- return { x: 0, y: 0, zoom: 1 };
228
+ return { x: 0, y: 0, zoom: 1, rotation: 0 };
229
229
  }
230
230
  function screenToPage(viewport, screenX, screenY) {
231
+ const tx = screenX - viewport.x;
232
+ const ty = screenY - viewport.y;
233
+ const cos = Math.cos(viewport.rotation);
234
+ const sin = Math.sin(viewport.rotation);
231
235
  return {
232
- x: (screenX - viewport.x) / viewport.zoom,
233
- y: (screenY - viewport.y) / viewport.zoom
236
+ x: (tx * cos + ty * sin) / viewport.zoom,
237
+ y: (-tx * sin + ty * cos) / viewport.zoom
234
238
  };
235
239
  }
236
240
  function pageToScreen(viewport, pageX, pageY) {
241
+ const scaledX = pageX * viewport.zoom;
242
+ const scaledY = pageY * viewport.zoom;
243
+ const cos = Math.cos(viewport.rotation);
244
+ const sin = Math.sin(viewport.rotation);
237
245
  return {
238
- x: pageX * viewport.zoom + viewport.x,
239
- y: pageY * viewport.zoom + viewport.y
246
+ x: scaledX * cos - scaledY * sin + viewport.x,
247
+ y: scaledX * sin + scaledY * cos + viewport.y
240
248
  };
241
249
  }
242
250
  function setViewport(viewport, updater) {
243
251
  return {
244
252
  x: updater.x ?? viewport.x,
245
253
  y: updater.y ?? viewport.y,
246
- zoom: updater.zoom ?? viewport.zoom
254
+ zoom: updater.zoom ?? viewport.zoom,
255
+ rotation: updater.rotation ?? viewport.rotation
247
256
  };
248
257
  }
249
258
  function panViewport(viewport, dx, dy) {
@@ -255,9 +264,23 @@ function zoomViewport(viewport, factor, centerX, centerY) {
255
264
  return { ...viewport, zoom };
256
265
  }
257
266
  const pageBefore = screenToPage(viewport, centerX, centerY);
258
- const x = centerX - pageBefore.x * zoom;
259
- const y = centerY - pageBefore.y * zoom;
260
- return { x, y, zoom };
267
+ const cos = Math.cos(viewport.rotation);
268
+ const sin = Math.sin(viewport.rotation);
269
+ const x = centerX - (pageBefore.x * zoom * cos - pageBefore.y * zoom * sin);
270
+ const y = centerY - (pageBefore.x * zoom * sin + pageBefore.y * zoom * cos);
271
+ return { x, y, zoom, rotation: viewport.rotation };
272
+ }
273
+ function rotateViewport(viewport, delta, centerX, centerY) {
274
+ const rotation = viewport.rotation + delta;
275
+ if (centerX == null || centerY == null) {
276
+ return { ...viewport, rotation };
277
+ }
278
+ const pageBefore = screenToPage(viewport, centerX, centerY);
279
+ const cos = Math.cos(rotation);
280
+ const sin = Math.sin(rotation);
281
+ const x = centerX - (pageBefore.x * viewport.zoom * cos - pageBefore.y * viewport.zoom * sin);
282
+ const y = centerY - (pageBefore.x * viewport.zoom * sin + pageBefore.y * viewport.zoom * cos);
283
+ return { x, y, zoom: viewport.zoom, rotation };
261
284
  }
262
285
 
263
286
  // src/utils/colors.ts
@@ -290,6 +313,7 @@ var CanvasRenderer = class {
290
313
  render(ctx, viewport, shapes) {
291
314
  ctx.save();
292
315
  ctx.translate(viewport.x, viewport.y);
316
+ ctx.rotate(viewport.rotation);
293
317
  ctx.scale(viewport.zoom, viewport.zoom);
294
318
  for (const shape of shapes) {
295
319
  if (shape.type === "draw") {
@@ -450,9 +474,6 @@ function flattenSegments(shape) {
450
474
  }
451
475
  out.push(D);
452
476
  }
453
- if (out.length > 0 && !shape.props.isPen) {
454
- for (const p of out) p.pressure = 0.5;
455
- }
456
477
  return out;
457
478
  }
458
479
  function getLineDash(dash, width) {
@@ -783,8 +804,8 @@ var PenDrawingState = class extends StateNode {
783
804
  const penActive = inputs.getIsPen();
784
805
  const z = this._startInfo?.point?.z ?? 0.5;
785
806
  this._isPenDevice = penActive;
786
- this._hasPressure = penActive && z !== 0 || z > 0 && z < 0.5 || z > 0.5 && z < 1;
787
- const pressure = this._hasPressure ? toFixed(z * 1.25) : 0.5;
807
+ this._hasPressure = penActive || z !== 0.5;
808
+ const pressure = this._hasPressure ? toFixed(z) : 0.5;
788
809
  this._phase = inputs.getShiftKey() ? "straight" : "free";
789
810
  this._extending = false;
790
811
  this._lastSample = { ...origin };
@@ -879,8 +900,15 @@ var PenDrawingState = class extends StateNode {
879
900
  const { id, props: { size, scale } } = target;
880
901
  const { segments } = shape.props;
881
902
  const curPt = inputs.getCurrentPagePoint();
903
+ if (!this._hasPressure) {
904
+ const liveZ = curPt.z ?? 0.5;
905
+ if (liveZ !== 0.5 || inputs.getIsPen()) {
906
+ this._hasPressure = true;
907
+ this.editor.updateShapes([{ id, type: "draw", props: { isPen: true } }]);
908
+ }
909
+ }
882
910
  const local = this.editor.getPointInShapeSpace(shape, curPt);
883
- const pressure = this._hasPressure ? toFixed((curPt.z ?? 0.5) * 1.25) : 0.5;
911
+ const pressure = this._hasPressure ? toFixed(curPt.z ?? 0.5) : 0.5;
884
912
  const pt = { x: toFixed(local.x), y: toFixed(local.y), z: pressure };
885
913
  switch (this._phase) {
886
914
  case "starting_straight": {
@@ -1026,7 +1054,7 @@ var PenDrawingState = class extends StateNode {
1026
1054
  const firstPt = {
1027
1055
  x: 0,
1028
1056
  y: 0,
1029
- z: this._hasPressure ? toFixed((curPage.z ?? 0.5) * 1.25) : 0.5
1057
+ z: this._hasPressure ? toFixed(curPage.z ?? 0.5) : 0.5
1030
1058
  };
1031
1059
  this._activePts = [firstPt];
1032
1060
  this.editor.createShape({
@@ -1736,7 +1764,8 @@ var Editor = class {
1736
1764
  this.viewport = {
1737
1765
  x: partial.x ?? this.viewport.x,
1738
1766
  y: partial.y ?? this.viewport.y,
1739
- zoom: Math.max(0.1, Math.min(4, rawZoom))
1767
+ zoom: Math.max(0.1, Math.min(4, rawZoom)),
1768
+ rotation: partial.rotation ?? this.viewport.rotation
1740
1769
  };
1741
1770
  this.emitChange();
1742
1771
  }
@@ -1746,6 +1775,18 @@ var Editor = class {
1746
1775
  y: this.viewport.y + dy
1747
1776
  });
1748
1777
  }
1778
+ zoomAt(factor, screenX, screenY) {
1779
+ this.viewport = zoomViewport(this.viewport, factor, screenX, screenY);
1780
+ this.emitChange();
1781
+ }
1782
+ rotateAt(delta, screenX, screenY) {
1783
+ this.viewport = rotateViewport(this.viewport, delta, screenX, screenY);
1784
+ this.emitChange();
1785
+ }
1786
+ deleteShapes(ids) {
1787
+ if (ids.length === 0) return;
1788
+ this.store.deleteShapes(ids);
1789
+ }
1749
1790
  getDocumentSnapshot() {
1750
1791
  return {
1751
1792
  records: documentSnapshotToRecords(this.store.getSnapshot())
@@ -1764,7 +1805,8 @@ var Editor = class {
1764
1805
  viewport: {
1765
1806
  x: this.viewport.x,
1766
1807
  y: this.viewport.y,
1767
- zoom: this.viewport.zoom
1808
+ zoom: this.viewport.zoom,
1809
+ rotation: this.viewport.rotation
1768
1810
  },
1769
1811
  currentToolId: this.getCurrentToolId(),
1770
1812
  drawStyle: this.getCurrentDrawStyle(),
@@ -1772,7 +1814,10 @@ var Editor = class {
1772
1814
  };
1773
1815
  }
1774
1816
  loadSessionStateSnapshot(snapshot) {
1775
- this.setViewport(snapshot.viewport);
1817
+ this.setViewport({
1818
+ ...snapshot.viewport,
1819
+ rotation: snapshot.viewport.rotation ?? 0
1820
+ });
1776
1821
  this.setCurrentDrawStyle({
1777
1822
  color: snapshot.drawStyle.color,
1778
1823
  dash: snapshot.drawStyle.dash,
@@ -2213,6 +2258,7 @@ exports.pointHitsShape = pointHitsShape;
2213
2258
  exports.recordsToDocumentSnapshot = recordsToDocumentSnapshot;
2214
2259
  exports.resolveThemeColor = resolveThemeColor;
2215
2260
  exports.rotatePoint = rotatePoint;
2261
+ exports.rotateViewport = rotateViewport;
2216
2262
  exports.screenToPage = screenToPage;
2217
2263
  exports.segmentHitsShape = segmentHitsShape;
2218
2264
  exports.segmentTouchesPolyline = segmentTouchesPolyline;