@fieldnotes/core 0.30.0 → 0.31.1

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
@@ -711,6 +711,7 @@ declare class PencilTool implements Tool {
711
711
  }
712
712
 
713
713
  interface EraserToolOptions {
714
+ /** Eraser radius in SCREEN pixels (matches the cursor circle; converted to world units per zoom). */
714
715
  radius?: number;
715
716
  mode?: 'partial' | 'stroke';
716
717
  }
@@ -763,6 +764,7 @@ declare class SelectTool implements Tool {
763
764
  private setHovered;
764
765
  private handleResize;
765
766
  private hitTestResizeHandle;
767
+ private hitTestLineHandles;
766
768
  private getHandlePositions;
767
769
  private renderMarquee;
768
770
  private renderSelectionBoxes;
@@ -971,6 +973,6 @@ declare class TemplateTool implements Tool {
971
973
  private notifyOptionsChange;
972
974
  }
973
975
 
974
- declare const VERSION = "0.30.0";
976
+ declare const VERSION = "0.31.1";
975
977
 
976
978
  export { type ActiveFormats, type ArrowElement, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, type BackgroundOptions, type BackgroundPattern, type Binding, type Bounds, Camera, type CameraChangeInfo, type CameraOptions, type CanvasElement, type CanvasState, type Command, DEFAULT_NOTE_FONT_SIZE, ElementStore, type ElementStyle, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, type ExportImageOptions, type FontSizePreset, type GridElement, type GridInfo, HandTool, type HexOrientation, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, type Layer, LayerManager, MeasureTool, type MeasureToolOptions, type Measurement, type NoteElement, NoteTool, type NoteToolOptions, PencilTool, type PencilToolOptions, type Point, type PointerState, type RenderStatsSnapshot, SelectTool, type ShapeElement, type ShapeKind, ShapeTool, type ShapeToolOptions, type ShortcutBindings, type ShortcutOptions, type ShortcutsApi, type Size, type StrokeElement, type StrokePoint, type TemplateElement, type TemplateShape, TemplateTool, type TemplateToolOptions, type TextElement, TextTool, type TextToolOptions, type Tool, type ToolContext, ToolManager, type ToolName, VERSION, Viewport, type ViewportOptions, boundsIntersect, createArrow, createGrid, createHtmlElement, createImage, createNote, createShape, createStroke, createTemplate, createText, drawHexPath, exportImage, getActiveFormats, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, getElementBounds, getElementStyle, getElementsBoundingBox, getHexCellsInCone, getHexCellsInLine, getHexCellsInRadius, getHexCellsInSquare, getHexDistance, isNearBezier, setFontSize, smartSnap, snapPoint, snapToHexCenter, styleToPatch, toggleBold, toggleItalic, toggleStrikethrough, toggleUnderline };
package/dist/index.d.ts CHANGED
@@ -711,6 +711,7 @@ declare class PencilTool implements Tool {
711
711
  }
712
712
 
713
713
  interface EraserToolOptions {
714
+ /** Eraser radius in SCREEN pixels (matches the cursor circle; converted to world units per zoom). */
714
715
  radius?: number;
715
716
  mode?: 'partial' | 'stroke';
716
717
  }
@@ -763,6 +764,7 @@ declare class SelectTool implements Tool {
763
764
  private setHovered;
764
765
  private handleResize;
765
766
  private hitTestResizeHandle;
767
+ private hitTestLineHandles;
766
768
  private getHandlePositions;
767
769
  private renderMarquee;
768
770
  private renderSelectionBoxes;
@@ -971,6 +973,6 @@ declare class TemplateTool implements Tool {
971
973
  private notifyOptionsChange;
972
974
  }
973
975
 
974
- declare const VERSION = "0.30.0";
976
+ declare const VERSION = "0.31.1";
975
977
 
976
978
  export { type ActiveFormats, type ArrowElement, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, type BackgroundOptions, type BackgroundPattern, type Binding, type Bounds, Camera, type CameraChangeInfo, type CameraOptions, type CanvasElement, type CanvasState, type Command, DEFAULT_NOTE_FONT_SIZE, ElementStore, type ElementStyle, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, type ExportImageOptions, type FontSizePreset, type GridElement, type GridInfo, HandTool, type HexOrientation, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, type Layer, LayerManager, MeasureTool, type MeasureToolOptions, type Measurement, type NoteElement, NoteTool, type NoteToolOptions, PencilTool, type PencilToolOptions, type Point, type PointerState, type RenderStatsSnapshot, SelectTool, type ShapeElement, type ShapeKind, ShapeTool, type ShapeToolOptions, type ShortcutBindings, type ShortcutOptions, type ShortcutsApi, type Size, type StrokeElement, type StrokePoint, type TemplateElement, type TemplateShape, TemplateTool, type TemplateToolOptions, type TextElement, TextTool, type TextToolOptions, type Tool, type ToolContext, ToolManager, type ToolName, VERSION, Viewport, type ViewportOptions, boundsIntersect, createArrow, createGrid, createHtmlElement, createImage, createNote, createShape, createStroke, createTemplate, createText, drawHexPath, exportImage, getActiveFormats, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, getElementBounds, getElementStyle, getElementsBoundingBox, getHexCellsInCone, getHexCellsInLine, getHexCellsInRadius, getHexCellsInSquare, getHexDistance, isNearBezier, setFontSize, smartSnap, snapPoint, snapToHexCenter, styleToPatch, toggleBold, toggleItalic, toggleStrikethrough, toggleUnderline };
package/dist/index.js CHANGED
@@ -2196,6 +2196,13 @@ function getArrowRenderGeometry(arrow) {
2196
2196
  }
2197
2197
 
2198
2198
  // src/elements/shape-geometry.ts
2199
+ function lineFromEndpoints(a, b) {
2200
+ return {
2201
+ position: { x: Math.min(a.x, b.x), y: Math.min(a.y, b.y) },
2202
+ size: { w: Math.abs(b.x - a.x), h: Math.abs(b.y - a.y) },
2203
+ flip: b.x > a.x !== b.y > a.y
2204
+ };
2205
+ }
2199
2206
  function lineEndpoints(shape) {
2200
2207
  const { x, y } = shape.position;
2201
2208
  const { w, h } = shape.size;
@@ -6369,11 +6376,12 @@ var EraserTool = class {
6369
6376
  }
6370
6377
  eraseAt(state, ctx) {
6371
6378
  const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });
6379
+ const worldRadius = this.radius / ctx.camera.zoom;
6372
6380
  const queryBounds = {
6373
- x: world.x - this.radius,
6374
- y: world.y - this.radius,
6375
- w: this.radius * 2,
6376
- h: this.radius * 2
6381
+ x: world.x - worldRadius,
6382
+ y: world.y - worldRadius,
6383
+ w: worldRadius * 2,
6384
+ h: worldRadius * 2
6377
6385
  };
6378
6386
  const candidates = ctx.store.queryRect(queryBounds);
6379
6387
  let erased = false;
@@ -6381,14 +6389,14 @@ var EraserTool = class {
6381
6389
  if (el.type !== "stroke") continue;
6382
6390
  if (ctx.isLayerVisible && !ctx.isLayerVisible(el.layerId)) continue;
6383
6391
  if (ctx.isLayerLocked && ctx.isLayerLocked(el.layerId)) continue;
6384
- if (!this.strokeIntersects(el, world)) continue;
6392
+ if (!this.strokeIntersects(el, world, worldRadius)) continue;
6385
6393
  if (this.mode === "stroke") {
6386
6394
  ctx.store.remove(el.id);
6387
6395
  erased = true;
6388
6396
  continue;
6389
6397
  }
6390
6398
  const localEraser = { x: world.x - el.position.x, y: world.y - el.position.y };
6391
- const runs = erasePoints(el.points, localEraser, this.radius);
6399
+ const runs = erasePoints(el.points, localEraser, worldRadius);
6392
6400
  if (runs === null) continue;
6393
6401
  ctx.store.remove(el.id);
6394
6402
  for (const run of runs) {
@@ -6408,8 +6416,8 @@ var EraserTool = class {
6408
6416
  }
6409
6417
  if (erased) ctx.requestRender();
6410
6418
  }
6411
- strokeIntersects(stroke, point) {
6412
- return hitTestStroke(stroke, point, this.radius);
6419
+ strokeIntersects(stroke, point, worldRadius) {
6420
+ return hitTestStroke(stroke, point, worldRadius);
6413
6421
  }
6414
6422
  };
6415
6423
 
@@ -6601,6 +6609,12 @@ var SelectTool = class {
6601
6609
  ctx.requestRender();
6602
6610
  return;
6603
6611
  }
6612
+ const lineHit = this.hitTestLineHandles(world, ctx);
6613
+ if (lineHit) {
6614
+ this.mode = { type: "line-handle", elementId: lineHit.elementId, fixed: lineHit.fixed };
6615
+ ctx.requestRender();
6616
+ return;
6617
+ }
6604
6618
  const templateResizeHit = this.hitTestTemplateResizeHandle(world, ctx);
6605
6619
  if (templateResizeHit) {
6606
6620
  this.mode = { type: "resizing-template", elementId: templateResizeHit };
@@ -6656,6 +6670,15 @@ var SelectTool = class {
6656
6670
  applyArrowHandleDrag(this.mode.handle, this.mode.elementId, world, ctx);
6657
6671
  return;
6658
6672
  }
6673
+ if (this.mode.type === "line-handle") {
6674
+ ctx.setCursor?.("grabbing");
6675
+ const el = ctx.store.getById(this.mode.elementId);
6676
+ if (el && el.type === "shape") {
6677
+ ctx.store.update(el.id, lineFromEndpoints(this.mode.fixed, world));
6678
+ }
6679
+ ctx.requestRender();
6680
+ return;
6681
+ }
6659
6682
  if (this.mode.type === "resizing-template") {
6660
6683
  ctx.setCursor?.("nwse-resize");
6661
6684
  this.handleTemplateResize(world, ctx);
@@ -6824,6 +6847,10 @@ var SelectTool = class {
6824
6847
  ctx.setCursor?.(getArrowHandleCursor(arrowHit.handle, false));
6825
6848
  return null;
6826
6849
  }
6850
+ if (this.hitTestLineHandles(world, ctx)) {
6851
+ ctx.setCursor?.("grab");
6852
+ return null;
6853
+ }
6827
6854
  const templateResizeHit = this.hitTestTemplateResizeHandle(world, ctx);
6828
6855
  if (templateResizeHit) {
6829
6856
  ctx.setCursor?.("nwse-resize");
@@ -6911,6 +6938,7 @@ var SelectTool = class {
6911
6938
  for (const id of this._selectedIds) {
6912
6939
  const el = ctx.store.getById(id);
6913
6940
  if (!el || !("size" in el)) continue;
6941
+ if (el.type === "shape" && el.shape === "line") continue;
6914
6942
  const bounds = getElementBounds(el);
6915
6943
  if (!bounds) continue;
6916
6944
  const corners = this.getHandlePositions(bounds);
@@ -6922,6 +6950,20 @@ var SelectTool = class {
6922
6950
  }
6923
6951
  return null;
6924
6952
  }
6953
+ hitTestLineHandles(world, ctx) {
6954
+ if (this._selectedIds.length === 0) return null;
6955
+ const zoom = ctx.camera.zoom;
6956
+ const r = (HANDLE_SIZE / 2 + HANDLE_HIT_PADDING2) / zoom;
6957
+ const r2 = r * r;
6958
+ for (const id of this._selectedIds) {
6959
+ const el = ctx.store.getById(id);
6960
+ if (!el || el.type !== "shape" || el.shape !== "line") continue;
6961
+ const [a, b] = lineEndpoints(el);
6962
+ if ((world.x - a.x) ** 2 + (world.y - a.y) ** 2 <= r2) return { elementId: id, fixed: b };
6963
+ if ((world.x - b.x) ** 2 + (world.y - b.y) ** 2 <= r2) return { elementId: id, fixed: a };
6964
+ }
6965
+ return null;
6966
+ }
6925
6967
  getHandlePositions(bounds) {
6926
6968
  return [
6927
6969
  ["nw", { x: bounds.x, y: bounds.y }],
@@ -6959,6 +7001,19 @@ var SelectTool = class {
6959
7001
  this.renderBindingHighlights(canvasCtx, el, zoom);
6960
7002
  continue;
6961
7003
  }
7004
+ if (el.type === "shape" && el.shape === "line") {
7005
+ canvasCtx.setLineDash([]);
7006
+ canvasCtx.fillStyle = "#ffffff";
7007
+ const r = handleWorldSize / 2;
7008
+ for (const p of lineEndpoints(el)) {
7009
+ canvasCtx.beginPath();
7010
+ canvasCtx.arc(p.x, p.y, r, 0, Math.PI * 2);
7011
+ canvasCtx.fill();
7012
+ canvasCtx.stroke();
7013
+ }
7014
+ canvasCtx.setLineDash([4 / zoom, 4 / zoom]);
7015
+ continue;
7016
+ }
6962
7017
  const bounds = getElementBounds(el);
6963
7018
  if (!bounds) continue;
6964
7019
  const pad = SELECTION_PAD / zoom;
@@ -7969,7 +8024,7 @@ var TemplateTool = class {
7969
8024
  };
7970
8025
 
7971
8026
  // src/index.ts
7972
- var VERSION = "0.30.0";
8027
+ var VERSION = "0.31.1";
7973
8028
  export {
7974
8029
  ArrowTool,
7975
8030
  AutoSave,