@tsdraw/core 0.8.0 → 0.8.2

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.d.cts CHANGED
@@ -429,18 +429,15 @@ interface ShapeBounds {
429
429
  }
430
430
  declare function buildSquareBounds(anchorX: number, anchorY: number, cursorX: number, cursorY: number): ShapeBounds;
431
431
  declare function buildRectangleBounds(anchorX: number, anchorY: number, cursorX: number, cursorY: number): ShapeBounds;
432
- declare function buildDefaultCenteredRectangleBounds(centerX: number, centerY: number): ShapeBounds;
433
432
  declare function buildRectangleSegments(width: number, height: number): DrawSegment[];
434
433
  declare function buildCircleBounds(anchorX: number, anchorY: number, cursorX: number, cursorY: number): ShapeBounds;
435
434
  declare function buildEllipseBounds(anchorX: number, anchorY: number, cursorX: number, cursorY: number): ShapeBounds;
436
- declare function buildDefaultCenteredEllipseBounds(centerX: number, centerY: number): ShapeBounds;
437
435
  declare function buildEllipseSegments(width: number, height: number): DrawSegment[];
438
436
 
439
437
  interface GeometricDrawingStateConfig {
440
438
  idleStateId: string;
441
439
  buildConstrainedBounds: (anchorX: number, anchorY: number, cursorX: number, cursorY: number) => ShapeBounds;
442
440
  buildUnconstrainedBounds: (anchorX: number, anchorY: number, cursorX: number, cursorY: number) => ShapeBounds;
443
- buildDefaultBounds: (centerX: number, centerY: number) => ShapeBounds;
444
441
  buildSegments: (width: number, height: number) => DrawSegment[];
445
442
  }
446
443
  declare abstract class GeometricDrawingState extends StateNode {
@@ -465,7 +462,6 @@ declare class SquareDrawingState extends GeometricDrawingState {
465
462
  idleStateId: string;
466
463
  buildConstrainedBounds: typeof buildSquareBounds;
467
464
  buildUnconstrainedBounds: typeof buildRectangleBounds;
468
- buildDefaultBounds: typeof buildDefaultCenteredRectangleBounds;
469
465
  buildSegments: typeof buildRectangleSegments;
470
466
  };
471
467
  }
@@ -481,7 +477,6 @@ declare class CircleDrawingState extends GeometricDrawingState {
481
477
  idleStateId: string;
482
478
  buildConstrainedBounds: typeof buildCircleBounds;
483
479
  buildUnconstrainedBounds: typeof buildEllipseBounds;
484
- buildDefaultBounds: typeof buildDefaultCenteredEllipseBounds;
485
480
  buildSegments: typeof buildEllipseSegments;
486
481
  };
487
482
  }
package/dist/index.d.ts CHANGED
@@ -429,18 +429,15 @@ interface ShapeBounds {
429
429
  }
430
430
  declare function buildSquareBounds(anchorX: number, anchorY: number, cursorX: number, cursorY: number): ShapeBounds;
431
431
  declare function buildRectangleBounds(anchorX: number, anchorY: number, cursorX: number, cursorY: number): ShapeBounds;
432
- declare function buildDefaultCenteredRectangleBounds(centerX: number, centerY: number): ShapeBounds;
433
432
  declare function buildRectangleSegments(width: number, height: number): DrawSegment[];
434
433
  declare function buildCircleBounds(anchorX: number, anchorY: number, cursorX: number, cursorY: number): ShapeBounds;
435
434
  declare function buildEllipseBounds(anchorX: number, anchorY: number, cursorX: number, cursorY: number): ShapeBounds;
436
- declare function buildDefaultCenteredEllipseBounds(centerX: number, centerY: number): ShapeBounds;
437
435
  declare function buildEllipseSegments(width: number, height: number): DrawSegment[];
438
436
 
439
437
  interface GeometricDrawingStateConfig {
440
438
  idleStateId: string;
441
439
  buildConstrainedBounds: (anchorX: number, anchorY: number, cursorX: number, cursorY: number) => ShapeBounds;
442
440
  buildUnconstrainedBounds: (anchorX: number, anchorY: number, cursorX: number, cursorY: number) => ShapeBounds;
443
- buildDefaultBounds: (centerX: number, centerY: number) => ShapeBounds;
444
441
  buildSegments: (width: number, height: number) => DrawSegment[];
445
442
  }
446
443
  declare abstract class GeometricDrawingState extends StateNode {
@@ -465,7 +462,6 @@ declare class SquareDrawingState extends GeometricDrawingState {
465
462
  idleStateId: string;
466
463
  buildConstrainedBounds: typeof buildSquareBounds;
467
464
  buildUnconstrainedBounds: typeof buildRectangleBounds;
468
- buildDefaultBounds: typeof buildDefaultCenteredRectangleBounds;
469
465
  buildSegments: typeof buildRectangleSegments;
470
466
  };
471
467
  }
@@ -481,7 +477,6 @@ declare class CircleDrawingState extends GeometricDrawingState {
481
477
  idleStateId: string;
482
478
  buildConstrainedBounds: typeof buildCircleBounds;
483
479
  buildUnconstrainedBounds: typeof buildEllipseBounds;
484
- buildDefaultBounds: typeof buildDefaultCenteredEllipseBounds;
485
480
  buildSegments: typeof buildEllipseSegments;
486
481
  };
487
482
  }
package/dist/index.js CHANGED
@@ -601,6 +601,7 @@ var ToolManager = class {
601
601
  getCurrentState() {
602
602
  return this.currentState;
603
603
  }
604
+ // Transition between states within the same tool (ex. pen_idle -> pen_drawing)
604
605
  transition(stateId, info) {
605
606
  const next = this.states.get(stateId);
606
607
  if (!next) return;
@@ -1127,6 +1128,7 @@ var GeometricDrawingState = class extends StateNode {
1127
1128
  });
1128
1129
  this.currentShapeId = nextShapeId;
1129
1130
  }
1131
+ // Shift key switches between constrained and unconstrained bounds
1130
1132
  onPointerMove() {
1131
1133
  const activeShape = this.getActiveShape();
1132
1134
  if (!activeShape) return;
@@ -1160,6 +1162,9 @@ var GeometricDrawingState = class extends StateNode {
1160
1162
  onKeyUp() {
1161
1163
  this.onPointerMove();
1162
1164
  }
1165
+ // If user dragged, use the drag extents for the final shape
1166
+ // If they just clicked without dragging, use default-sized shape
1167
+ // If they dragged just a bit (most likely a click), remove the shape and go back to idle
1163
1168
  completeShape() {
1164
1169
  const activeShape = this.getActiveShape();
1165
1170
  const config = this.getConfig();
@@ -1169,7 +1174,15 @@ var GeometricDrawingState = class extends StateNode {
1169
1174
  }
1170
1175
  const originPoint = this.editor.input.getOriginPagePoint();
1171
1176
  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);
1177
+ const dx = cursorPoint.x - originPoint.x;
1178
+ const dy = cursorPoint.y - originPoint.y;
1179
+ const draggedFarEnough = dx * dx + dy * dy > this.editor.options.dragDistanceSquared;
1180
+ if (!draggedFarEnough) {
1181
+ this.removeCurrentShape();
1182
+ this.ctx.transition(config.idleStateId, this.startedAt);
1183
+ return;
1184
+ }
1185
+ const finalizedBounds = this.editor.input.getShiftKey() ? config.buildConstrainedBounds(originPoint.x, originPoint.y, cursorPoint.x, cursorPoint.y) : config.buildUnconstrainedBounds(originPoint.x, originPoint.y, cursorPoint.x, cursorPoint.y);
1173
1186
  this.editor.store.updateShape(activeShape.id, {
1174
1187
  x: finalizedBounds.x,
1175
1188
  y: finalizedBounds.y,
@@ -1199,10 +1212,6 @@ var GeometricDrawingState = class extends StateNode {
1199
1212
 
1200
1213
  // src/tools/geometric/geometricShapeHelpers.ts
1201
1214
  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
1215
  function toSizedBounds(anchorX, anchorY, cursorX, cursorY, forceEqualSides) {
1207
1216
  const rawDeltaX = cursorX - anchorX;
1208
1217
  const rawDeltaY = cursorY - anchorY;
@@ -1227,16 +1236,6 @@ function buildSquareBounds(anchorX, anchorY, cursorX, cursorY) {
1227
1236
  function buildRectangleBounds(anchorX, anchorY, cursorX, cursorY) {
1228
1237
  return toSizedBounds(anchorX, anchorY, cursorX, cursorY, false);
1229
1238
  }
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
1239
  function buildRectangleSegments(width, height) {
1241
1240
  const topLeft = { x: 0, y: 0, z: 0.5 };
1242
1241
  const topRight = { x: width, y: 0, z: 0.5 };
@@ -1255,16 +1254,6 @@ function buildCircleBounds(anchorX, anchorY, cursorX, cursorY) {
1255
1254
  function buildEllipseBounds(anchorX, anchorY, cursorX, cursorY) {
1256
1255
  return toSizedBounds(anchorX, anchorY, cursorX, cursorY, false);
1257
1256
  }
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
1257
  function buildEllipseSegments(width, height) {
1269
1258
  const centerX = width / 2;
1270
1259
  const centerY = height / 2;
@@ -1292,7 +1281,6 @@ var SquareDrawingState = class extends GeometricDrawingState {
1292
1281
  idleStateId: "square_idle",
1293
1282
  buildConstrainedBounds: buildSquareBounds,
1294
1283
  buildUnconstrainedBounds: buildRectangleBounds,
1295
- buildDefaultBounds: buildDefaultCenteredRectangleBounds,
1296
1284
  buildSegments: buildRectangleSegments
1297
1285
  };
1298
1286
  }
@@ -1314,7 +1302,6 @@ var CircleDrawingState = class extends GeometricDrawingState {
1314
1302
  idleStateId: "circle_idle",
1315
1303
  buildConstrainedBounds: buildCircleBounds,
1316
1304
  buildUnconstrainedBounds: buildEllipseBounds,
1317
- buildDefaultBounds: buildDefaultCenteredEllipseBounds,
1318
1305
  buildSegments: buildEllipseSegments
1319
1306
  };
1320
1307
  }
@@ -1480,6 +1467,8 @@ var EraserErasingState = class extends StateNode {
1480
1467
  onCancel() {
1481
1468
  this.ctx.transition("eraser_idle");
1482
1469
  }
1470
+ // On every pointer move, test the line from previous pointer position to current one against nearby shapes
1471
+ // Only select shapes whose bounding box overlaps the sweep area to avoid testing all shapes
1483
1472
  sweep() {
1484
1473
  const zoom = this.editor.getZoomLevel();
1485
1474
  const tolerance = ERASER_MARGIN / zoom;
@@ -1498,6 +1487,7 @@ var EraserErasingState = class extends StateNode {
1498
1487
  this._marked = [...hitIds];
1499
1488
  this.editor.setErasingShapes(this._marked);
1500
1489
  }
1490
+ // Delete marked shapes and reset, then go back to idle
1501
1491
  finish() {
1502
1492
  const ids = this.editor.getErasingShapeIds();
1503
1493
  if (ids.length > 0) {