@fieldnotes/core 0.11.1 → 0.11.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.cjs CHANGED
@@ -37,6 +37,7 @@ __export(index_exports, {
37
37
  HistoryRecorder: () => HistoryRecorder,
38
38
  HistoryStack: () => HistoryStack,
39
39
  ImageTool: () => ImageTool,
40
+ InputFilter: () => InputFilter,
40
41
  InputHandler: () => InputHandler,
41
42
  LayerManager: () => LayerManager,
42
43
  MeasureTool: () => MeasureTool,
@@ -842,6 +843,61 @@ var Background = class {
842
843
  }
843
844
  };
844
845
 
846
+ // src/canvas/input-filter.ts
847
+ var InputFilter = class _InputFilter {
848
+ activePenId = null;
849
+ pendingTap = null;
850
+ static MIN_MOVE_DISTANCE = 3;
851
+ filterDown(e) {
852
+ if (e.pointerType === "pen") {
853
+ this.activePenId = e.pointerId;
854
+ return { event: e, action: "dispatch" };
855
+ }
856
+ if (e.pointerType === "touch" && this.activePenId !== null) {
857
+ return { event: e, action: "suppress" };
858
+ }
859
+ if (e.pointerType === "touch") {
860
+ this.pendingTap = { pointerId: e.pointerId, x: e.clientX, y: e.clientY };
861
+ return { event: e, action: "defer" };
862
+ }
863
+ return { event: e, action: "dispatch" };
864
+ }
865
+ filterMove(e) {
866
+ if (e.pointerType === "touch" && this.activePenId !== null) {
867
+ return { event: e, action: "suppress" };
868
+ }
869
+ if (this.pendingTap && e.pointerId === this.pendingTap.pointerId) {
870
+ const dx = e.clientX - this.pendingTap.x;
871
+ const dy = e.clientY - this.pendingTap.y;
872
+ if (dx * dx + dy * dy > _InputFilter.MIN_MOVE_DISTANCE * _InputFilter.MIN_MOVE_DISTANCE) {
873
+ this.pendingTap = null;
874
+ return { event: e, action: "dispatch" };
875
+ }
876
+ return { event: e, action: "suppress" };
877
+ }
878
+ return { event: e, action: "dispatch" };
879
+ }
880
+ filterUp(e) {
881
+ if (e.pointerId === this.activePenId) {
882
+ this.activePenId = null;
883
+ return { event: e, action: "dispatch" };
884
+ }
885
+ if (e.pointerType === "touch" && this.activePenId !== null) {
886
+ return { event: e, action: "suppress" };
887
+ }
888
+ if (this.pendingTap && e.pointerId === this.pendingTap.pointerId) {
889
+ const tap = { x: this.pendingTap.x, y: this.pendingTap.y };
890
+ this.pendingTap = null;
891
+ return { event: e, action: "dispatch", pendingTap: tap };
892
+ }
893
+ return { event: e, action: "dispatch" };
894
+ }
895
+ reset() {
896
+ this.activePenId = null;
897
+ this.pendingTap = null;
898
+ }
899
+ };
900
+
845
901
  // src/canvas/input-handler.ts
846
902
  var ZOOM_SENSITIVITY = 1e-3;
847
903
  var MIDDLE_BUTTON = 1;
@@ -868,6 +924,8 @@ var InputHandler = class {
868
924
  historyStack;
869
925
  isToolActive = false;
870
926
  lastPointerEvent = null;
927
+ inputFilter = new InputFilter();
928
+ deferredDown = null;
871
929
  abortController = new AbortController();
872
930
  setToolManager(toolManager, toolContext) {
873
931
  this.toolManager = toolManager;
@@ -875,6 +933,8 @@ var InputHandler = class {
875
933
  }
876
934
  destroy() {
877
935
  this.abortController.abort();
936
+ this.inputFilter.reset();
937
+ this.deferredDown = null;
878
938
  this.lastPointerEvent = null;
879
939
  }
880
940
  bind() {
@@ -912,6 +972,12 @@ var InputHandler = class {
912
972
  return;
913
973
  }
914
974
  if (this.activePointers.size === 1 && (e.button === 0 || e.pointerType === "touch" || e.pointerType === "pen")) {
975
+ const result = this.inputFilter.filterDown(e);
976
+ if (result.action === "suppress") return;
977
+ if (result.action === "defer") {
978
+ this.deferredDown = e;
979
+ return;
980
+ }
915
981
  this.dispatchToolDown(e);
916
982
  }
917
983
  };
@@ -933,6 +999,13 @@ var InputHandler = class {
933
999
  }
934
1000
  if (this.isToolActive) {
935
1001
  this.dispatchToolMove(e);
1002
+ } else if (this.deferredDown) {
1003
+ const result = this.inputFilter.filterMove(e);
1004
+ if (result.action === "dispatch") {
1005
+ this.dispatchToolDown(this.deferredDown);
1006
+ this.deferredDown = null;
1007
+ this.dispatchToolMove(e);
1008
+ }
936
1009
  } else if (this.activePointers.size === 0) {
937
1010
  this.dispatchToolHover(e);
938
1011
  }
@@ -949,9 +1022,16 @@ var InputHandler = class {
949
1022
  if (this.isPanning && this.activePointers.size === 0) {
950
1023
  this.isPanning = false;
951
1024
  }
1025
+ const upResult = this.inputFilter.filterUp(e);
952
1026
  if (this.isToolActive) {
953
1027
  this.dispatchToolUp(e);
954
1028
  this.isToolActive = false;
1029
+ } else if (this.deferredDown && upResult.pendingTap) {
1030
+ this.dispatchToolDown(this.deferredDown);
1031
+ this.dispatchToolUp(e);
1032
+ this.deferredDown = null;
1033
+ } else {
1034
+ this.deferredDown = null;
955
1035
  }
956
1036
  };
957
1037
  onKeyDown = (e) => {
@@ -984,6 +1064,8 @@ var InputHandler = class {
984
1064
  }
985
1065
  };
986
1066
  startPinch() {
1067
+ this.inputFilter.reset();
1068
+ this.deferredDown = null;
987
1069
  this.isPanning = true;
988
1070
  const [a, b] = this.getPinchPoints();
989
1071
  this.lastPinchDistance = this.distance(a, b);
@@ -1023,7 +1105,8 @@ var InputHandler = class {
1023
1105
  return {
1024
1106
  x: e.clientX - rect.left,
1025
1107
  y: e.clientY - rect.top,
1026
- pressure: e.pressure
1108
+ pressure: e.pressure,
1109
+ pointerType: e.pointerType === "touch" || e.pointerType === "pen" ? e.pointerType : "mouse"
1027
1110
  };
1028
1111
  }
1029
1112
  dispatchToolDown(e) {
@@ -1081,6 +1164,7 @@ var InputHandler = class {
1081
1164
  this.dispatchToolUp(e);
1082
1165
  this.isToolActive = false;
1083
1166
  }
1167
+ this.deferredDown = null;
1084
1168
  }
1085
1169
  };
1086
1170
 
@@ -6330,7 +6414,7 @@ var UpdateLayerCommand = class {
6330
6414
  };
6331
6415
 
6332
6416
  // src/index.ts
6333
- var VERSION = "0.11.0";
6417
+ var VERSION = "0.11.2";
6334
6418
  // Annotate the CommonJS export names for ESM import in node:
6335
6419
  0 && (module.exports = {
6336
6420
  AddElementCommand,
@@ -6350,6 +6434,7 @@ var VERSION = "0.11.0";
6350
6434
  HistoryRecorder,
6351
6435
  HistoryStack,
6352
6436
  ImageTool,
6437
+ InputFilter,
6353
6438
  InputHandler,
6354
6439
  LayerManager,
6355
6440
  MeasureTool,
package/dist/index.d.cts CHANGED
@@ -238,6 +238,7 @@ interface PointerState {
238
238
  x: number;
239
239
  y: number;
240
240
  pressure: number;
241
+ pointerType: 'mouse' | 'touch' | 'pen';
241
242
  }
242
243
  interface Tool {
243
244
  readonly name: string;
@@ -424,6 +425,8 @@ declare class InputHandler {
424
425
  private historyStack;
425
426
  private isToolActive;
426
427
  private lastPointerEvent;
428
+ private readonly inputFilter;
429
+ private deferredDown;
427
430
  private readonly abortController;
428
431
  constructor(element: HTMLElement, camera: Camera, options?: InputHandlerOptions);
429
432
  setToolManager(toolManager: ToolManager, toolContext: ToolContext): void;
@@ -451,6 +454,27 @@ declare class InputHandler {
451
454
  private cancelToolIfActive;
452
455
  }
453
456
 
457
+ type FilterAction = 'dispatch' | 'suppress' | 'defer';
458
+ interface FilteredEvent {
459
+ event: PointerEvent;
460
+ action: FilterAction;
461
+ }
462
+ interface FilteredUpEvent extends FilteredEvent {
463
+ pendingTap?: {
464
+ x: number;
465
+ y: number;
466
+ };
467
+ }
468
+ declare class InputFilter {
469
+ private activePenId;
470
+ private pendingTap;
471
+ static readonly MIN_MOVE_DISTANCE = 3;
472
+ filterDown(e: PointerEvent): FilteredEvent;
473
+ filterMove(e: PointerEvent): FilteredEvent;
474
+ filterUp(e: PointerEvent): FilteredUpEvent;
475
+ reset(): void;
476
+ }
477
+
454
478
  interface FontSizePreset {
455
479
  label: string;
456
480
  size: number;
@@ -1120,6 +1144,6 @@ declare class UpdateLayerCommand implements Command {
1120
1144
  undo(_store: ElementStore): void;
1121
1145
  }
1122
1146
 
1123
- declare const VERSION = "0.11.0";
1147
+ declare const VERSION = "0.11.2";
1124
1148
 
1125
- export { type ActiveFormats, AddElementCommand, type ArrowElement, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, Background, type BackgroundOptions, type BackgroundPattern, BatchCommand, type Binding, type Bounds, Camera, type CameraChangeInfo, type CameraOptions, type CanvasElement, type CanvasState, type Command, CreateLayerCommand, DEFAULT_FONT_SIZE_PRESETS, DEFAULT_NOTE_FONT_SIZE, ElementRenderer, ElementStore, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, EventBus, type ExportImageOptions, type FontSizePreset, type GridElement, type GridInfo, HandTool, type HexOrientation, HistoryRecorder, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, InputHandler, type Layer, LayerManager, MeasureTool, type MeasureToolOptions, type Measurement, NoteEditor, type NoteEditorOptions, type NoteElement, NoteTool, type NoteToolOptions, NoteToolbar, PencilTool, type PencilToolOptions, type Point, type PointerState, Quadtree, RemoveElementCommand, RemoveLayerCommand, type RenderStatsSnapshot, SelectTool, type ShapeElement, type ShapeKind, ShapeTool, type ShapeToolOptions, type Size, type StrokeElement, type StrokePoint, type StyledRun, type TemplateElement, type TemplateShape, TemplateTool, type TemplateToolOptions, type TextElement, TextTool, type TextToolOptions, type Tool, type ToolContext, ToolManager, type ToolName, UpdateElementCommand, UpdateLayerCommand, VERSION, Viewport, type ViewportOptions, boundsIntersect, clearStaleBindings, createArrow, createGrid, createHtmlElement, createId, createImage, createNote, createShape, createStroke, createTemplate, createText, drawHexPath, exportImage, exportState, findBindTarget, findBoundArrows, getActiveFormats, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, getEdgeIntersection, getElementBounds, getElementCenter, getHexCellsInCone, getHexCellsInLine, getHexCellsInRadius, getHexCellsInSquare, getHexDistance, isBindable, isNearBezier, parseState, sanitizeNoteHtml, setFontSize, smartSnap, snapPoint, snapToHexCenter, toggleBold, toggleItalic, toggleStrikethrough, toggleUnderline, unbindArrow, updateBoundArrow };
1149
+ export { type ActiveFormats, AddElementCommand, type ArrowElement, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, Background, type BackgroundOptions, type BackgroundPattern, BatchCommand, type Binding, type Bounds, Camera, type CameraChangeInfo, type CameraOptions, type CanvasElement, type CanvasState, type Command, CreateLayerCommand, DEFAULT_FONT_SIZE_PRESETS, DEFAULT_NOTE_FONT_SIZE, ElementRenderer, ElementStore, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, EventBus, type ExportImageOptions, type FilterAction, type FilteredEvent, type FilteredUpEvent, type FontSizePreset, type GridElement, type GridInfo, HandTool, type HexOrientation, HistoryRecorder, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, InputFilter, InputHandler, type Layer, LayerManager, MeasureTool, type MeasureToolOptions, type Measurement, NoteEditor, type NoteEditorOptions, type NoteElement, NoteTool, type NoteToolOptions, NoteToolbar, PencilTool, type PencilToolOptions, type Point, type PointerState, Quadtree, RemoveElementCommand, RemoveLayerCommand, type RenderStatsSnapshot, SelectTool, type ShapeElement, type ShapeKind, ShapeTool, type ShapeToolOptions, type Size, type StrokeElement, type StrokePoint, type StyledRun, type TemplateElement, type TemplateShape, TemplateTool, type TemplateToolOptions, type TextElement, TextTool, type TextToolOptions, type Tool, type ToolContext, ToolManager, type ToolName, UpdateElementCommand, UpdateLayerCommand, VERSION, Viewport, type ViewportOptions, boundsIntersect, clearStaleBindings, createArrow, createGrid, createHtmlElement, createId, createImage, createNote, createShape, createStroke, createTemplate, createText, drawHexPath, exportImage, exportState, findBindTarget, findBoundArrows, getActiveFormats, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, getEdgeIntersection, getElementBounds, getElementCenter, getHexCellsInCone, getHexCellsInLine, getHexCellsInRadius, getHexCellsInSquare, getHexDistance, isBindable, isNearBezier, parseState, sanitizeNoteHtml, setFontSize, smartSnap, snapPoint, snapToHexCenter, toggleBold, toggleItalic, toggleStrikethrough, toggleUnderline, unbindArrow, updateBoundArrow };
package/dist/index.d.ts CHANGED
@@ -238,6 +238,7 @@ interface PointerState {
238
238
  x: number;
239
239
  y: number;
240
240
  pressure: number;
241
+ pointerType: 'mouse' | 'touch' | 'pen';
241
242
  }
242
243
  interface Tool {
243
244
  readonly name: string;
@@ -424,6 +425,8 @@ declare class InputHandler {
424
425
  private historyStack;
425
426
  private isToolActive;
426
427
  private lastPointerEvent;
428
+ private readonly inputFilter;
429
+ private deferredDown;
427
430
  private readonly abortController;
428
431
  constructor(element: HTMLElement, camera: Camera, options?: InputHandlerOptions);
429
432
  setToolManager(toolManager: ToolManager, toolContext: ToolContext): void;
@@ -451,6 +454,27 @@ declare class InputHandler {
451
454
  private cancelToolIfActive;
452
455
  }
453
456
 
457
+ type FilterAction = 'dispatch' | 'suppress' | 'defer';
458
+ interface FilteredEvent {
459
+ event: PointerEvent;
460
+ action: FilterAction;
461
+ }
462
+ interface FilteredUpEvent extends FilteredEvent {
463
+ pendingTap?: {
464
+ x: number;
465
+ y: number;
466
+ };
467
+ }
468
+ declare class InputFilter {
469
+ private activePenId;
470
+ private pendingTap;
471
+ static readonly MIN_MOVE_DISTANCE = 3;
472
+ filterDown(e: PointerEvent): FilteredEvent;
473
+ filterMove(e: PointerEvent): FilteredEvent;
474
+ filterUp(e: PointerEvent): FilteredUpEvent;
475
+ reset(): void;
476
+ }
477
+
454
478
  interface FontSizePreset {
455
479
  label: string;
456
480
  size: number;
@@ -1120,6 +1144,6 @@ declare class UpdateLayerCommand implements Command {
1120
1144
  undo(_store: ElementStore): void;
1121
1145
  }
1122
1146
 
1123
- declare const VERSION = "0.11.0";
1147
+ declare const VERSION = "0.11.2";
1124
1148
 
1125
- export { type ActiveFormats, AddElementCommand, type ArrowElement, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, Background, type BackgroundOptions, type BackgroundPattern, BatchCommand, type Binding, type Bounds, Camera, type CameraChangeInfo, type CameraOptions, type CanvasElement, type CanvasState, type Command, CreateLayerCommand, DEFAULT_FONT_SIZE_PRESETS, DEFAULT_NOTE_FONT_SIZE, ElementRenderer, ElementStore, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, EventBus, type ExportImageOptions, type FontSizePreset, type GridElement, type GridInfo, HandTool, type HexOrientation, HistoryRecorder, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, InputHandler, type Layer, LayerManager, MeasureTool, type MeasureToolOptions, type Measurement, NoteEditor, type NoteEditorOptions, type NoteElement, NoteTool, type NoteToolOptions, NoteToolbar, PencilTool, type PencilToolOptions, type Point, type PointerState, Quadtree, RemoveElementCommand, RemoveLayerCommand, type RenderStatsSnapshot, SelectTool, type ShapeElement, type ShapeKind, ShapeTool, type ShapeToolOptions, type Size, type StrokeElement, type StrokePoint, type StyledRun, type TemplateElement, type TemplateShape, TemplateTool, type TemplateToolOptions, type TextElement, TextTool, type TextToolOptions, type Tool, type ToolContext, ToolManager, type ToolName, UpdateElementCommand, UpdateLayerCommand, VERSION, Viewport, type ViewportOptions, boundsIntersect, clearStaleBindings, createArrow, createGrid, createHtmlElement, createId, createImage, createNote, createShape, createStroke, createTemplate, createText, drawHexPath, exportImage, exportState, findBindTarget, findBoundArrows, getActiveFormats, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, getEdgeIntersection, getElementBounds, getElementCenter, getHexCellsInCone, getHexCellsInLine, getHexCellsInRadius, getHexCellsInSquare, getHexDistance, isBindable, isNearBezier, parseState, sanitizeNoteHtml, setFontSize, smartSnap, snapPoint, snapToHexCenter, toggleBold, toggleItalic, toggleStrikethrough, toggleUnderline, unbindArrow, updateBoundArrow };
1149
+ export { type ActiveFormats, AddElementCommand, type ArrowElement, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, Background, type BackgroundOptions, type BackgroundPattern, BatchCommand, type Binding, type Bounds, Camera, type CameraChangeInfo, type CameraOptions, type CanvasElement, type CanvasState, type Command, CreateLayerCommand, DEFAULT_FONT_SIZE_PRESETS, DEFAULT_NOTE_FONT_SIZE, ElementRenderer, ElementStore, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, EventBus, type ExportImageOptions, type FilterAction, type FilteredEvent, type FilteredUpEvent, type FontSizePreset, type GridElement, type GridInfo, HandTool, type HexOrientation, HistoryRecorder, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, InputFilter, InputHandler, type Layer, LayerManager, MeasureTool, type MeasureToolOptions, type Measurement, NoteEditor, type NoteEditorOptions, type NoteElement, NoteTool, type NoteToolOptions, NoteToolbar, PencilTool, type PencilToolOptions, type Point, type PointerState, Quadtree, RemoveElementCommand, RemoveLayerCommand, type RenderStatsSnapshot, SelectTool, type ShapeElement, type ShapeKind, ShapeTool, type ShapeToolOptions, type Size, type StrokeElement, type StrokePoint, type StyledRun, type TemplateElement, type TemplateShape, TemplateTool, type TemplateToolOptions, type TextElement, TextTool, type TextToolOptions, type Tool, type ToolContext, ToolManager, type ToolName, UpdateElementCommand, UpdateLayerCommand, VERSION, Viewport, type ViewportOptions, boundsIntersect, clearStaleBindings, createArrow, createGrid, createHtmlElement, createId, createImage, createNote, createShape, createStroke, createTemplate, createText, drawHexPath, exportImage, exportState, findBindTarget, findBoundArrows, getActiveFormats, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, getEdgeIntersection, getElementBounds, getElementCenter, getHexCellsInCone, getHexCellsInLine, getHexCellsInRadius, getHexCellsInSquare, getHexDistance, isBindable, isNearBezier, parseState, sanitizeNoteHtml, setFontSize, smartSnap, snapPoint, snapToHexCenter, toggleBold, toggleItalic, toggleStrikethrough, toggleUnderline, unbindArrow, updateBoundArrow };
package/dist/index.js CHANGED
@@ -736,6 +736,61 @@ var Background = class {
736
736
  }
737
737
  };
738
738
 
739
+ // src/canvas/input-filter.ts
740
+ var InputFilter = class _InputFilter {
741
+ activePenId = null;
742
+ pendingTap = null;
743
+ static MIN_MOVE_DISTANCE = 3;
744
+ filterDown(e) {
745
+ if (e.pointerType === "pen") {
746
+ this.activePenId = e.pointerId;
747
+ return { event: e, action: "dispatch" };
748
+ }
749
+ if (e.pointerType === "touch" && this.activePenId !== null) {
750
+ return { event: e, action: "suppress" };
751
+ }
752
+ if (e.pointerType === "touch") {
753
+ this.pendingTap = { pointerId: e.pointerId, x: e.clientX, y: e.clientY };
754
+ return { event: e, action: "defer" };
755
+ }
756
+ return { event: e, action: "dispatch" };
757
+ }
758
+ filterMove(e) {
759
+ if (e.pointerType === "touch" && this.activePenId !== null) {
760
+ return { event: e, action: "suppress" };
761
+ }
762
+ if (this.pendingTap && e.pointerId === this.pendingTap.pointerId) {
763
+ const dx = e.clientX - this.pendingTap.x;
764
+ const dy = e.clientY - this.pendingTap.y;
765
+ if (dx * dx + dy * dy > _InputFilter.MIN_MOVE_DISTANCE * _InputFilter.MIN_MOVE_DISTANCE) {
766
+ this.pendingTap = null;
767
+ return { event: e, action: "dispatch" };
768
+ }
769
+ return { event: e, action: "suppress" };
770
+ }
771
+ return { event: e, action: "dispatch" };
772
+ }
773
+ filterUp(e) {
774
+ if (e.pointerId === this.activePenId) {
775
+ this.activePenId = null;
776
+ return { event: e, action: "dispatch" };
777
+ }
778
+ if (e.pointerType === "touch" && this.activePenId !== null) {
779
+ return { event: e, action: "suppress" };
780
+ }
781
+ if (this.pendingTap && e.pointerId === this.pendingTap.pointerId) {
782
+ const tap = { x: this.pendingTap.x, y: this.pendingTap.y };
783
+ this.pendingTap = null;
784
+ return { event: e, action: "dispatch", pendingTap: tap };
785
+ }
786
+ return { event: e, action: "dispatch" };
787
+ }
788
+ reset() {
789
+ this.activePenId = null;
790
+ this.pendingTap = null;
791
+ }
792
+ };
793
+
739
794
  // src/canvas/input-handler.ts
740
795
  var ZOOM_SENSITIVITY = 1e-3;
741
796
  var MIDDLE_BUTTON = 1;
@@ -762,6 +817,8 @@ var InputHandler = class {
762
817
  historyStack;
763
818
  isToolActive = false;
764
819
  lastPointerEvent = null;
820
+ inputFilter = new InputFilter();
821
+ deferredDown = null;
765
822
  abortController = new AbortController();
766
823
  setToolManager(toolManager, toolContext) {
767
824
  this.toolManager = toolManager;
@@ -769,6 +826,8 @@ var InputHandler = class {
769
826
  }
770
827
  destroy() {
771
828
  this.abortController.abort();
829
+ this.inputFilter.reset();
830
+ this.deferredDown = null;
772
831
  this.lastPointerEvent = null;
773
832
  }
774
833
  bind() {
@@ -806,6 +865,12 @@ var InputHandler = class {
806
865
  return;
807
866
  }
808
867
  if (this.activePointers.size === 1 && (e.button === 0 || e.pointerType === "touch" || e.pointerType === "pen")) {
868
+ const result = this.inputFilter.filterDown(e);
869
+ if (result.action === "suppress") return;
870
+ if (result.action === "defer") {
871
+ this.deferredDown = e;
872
+ return;
873
+ }
809
874
  this.dispatchToolDown(e);
810
875
  }
811
876
  };
@@ -827,6 +892,13 @@ var InputHandler = class {
827
892
  }
828
893
  if (this.isToolActive) {
829
894
  this.dispatchToolMove(e);
895
+ } else if (this.deferredDown) {
896
+ const result = this.inputFilter.filterMove(e);
897
+ if (result.action === "dispatch") {
898
+ this.dispatchToolDown(this.deferredDown);
899
+ this.deferredDown = null;
900
+ this.dispatchToolMove(e);
901
+ }
830
902
  } else if (this.activePointers.size === 0) {
831
903
  this.dispatchToolHover(e);
832
904
  }
@@ -843,9 +915,16 @@ var InputHandler = class {
843
915
  if (this.isPanning && this.activePointers.size === 0) {
844
916
  this.isPanning = false;
845
917
  }
918
+ const upResult = this.inputFilter.filterUp(e);
846
919
  if (this.isToolActive) {
847
920
  this.dispatchToolUp(e);
848
921
  this.isToolActive = false;
922
+ } else if (this.deferredDown && upResult.pendingTap) {
923
+ this.dispatchToolDown(this.deferredDown);
924
+ this.dispatchToolUp(e);
925
+ this.deferredDown = null;
926
+ } else {
927
+ this.deferredDown = null;
849
928
  }
850
929
  };
851
930
  onKeyDown = (e) => {
@@ -878,6 +957,8 @@ var InputHandler = class {
878
957
  }
879
958
  };
880
959
  startPinch() {
960
+ this.inputFilter.reset();
961
+ this.deferredDown = null;
881
962
  this.isPanning = true;
882
963
  const [a, b] = this.getPinchPoints();
883
964
  this.lastPinchDistance = this.distance(a, b);
@@ -917,7 +998,8 @@ var InputHandler = class {
917
998
  return {
918
999
  x: e.clientX - rect.left,
919
1000
  y: e.clientY - rect.top,
920
- pressure: e.pressure
1001
+ pressure: e.pressure,
1002
+ pointerType: e.pointerType === "touch" || e.pointerType === "pen" ? e.pointerType : "mouse"
921
1003
  };
922
1004
  }
923
1005
  dispatchToolDown(e) {
@@ -975,6 +1057,7 @@ var InputHandler = class {
975
1057
  this.dispatchToolUp(e);
976
1058
  this.isToolActive = false;
977
1059
  }
1060
+ this.deferredDown = null;
978
1061
  }
979
1062
  };
980
1063
 
@@ -6224,7 +6307,7 @@ var UpdateLayerCommand = class {
6224
6307
  };
6225
6308
 
6226
6309
  // src/index.ts
6227
- var VERSION = "0.11.0";
6310
+ var VERSION = "0.11.2";
6228
6311
  export {
6229
6312
  AddElementCommand,
6230
6313
  ArrowTool,
@@ -6243,6 +6326,7 @@ export {
6243
6326
  HistoryRecorder,
6244
6327
  HistoryStack,
6245
6328
  ImageTool,
6329
+ InputFilter,
6246
6330
  InputHandler,
6247
6331
  LayerManager,
6248
6332
  MeasureTool,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fieldnotes/core",
3
- "version": "0.11.1",
3
+ "version": "0.11.2",
4
4
  "description": "Vanilla TypeScript infinite canvas engine",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",