@fieldnotes/core 0.11.3 → 0.13.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
@@ -37,7 +37,6 @@ __export(index_exports, {
37
37
  HistoryRecorder: () => HistoryRecorder,
38
38
  HistoryStack: () => HistoryStack,
39
39
  ImageTool: () => ImageTool,
40
- InputFilter: () => InputFilter,
41
40
  InputHandler: () => InputHandler,
42
41
  LayerManager: () => LayerManager,
43
42
  MeasureTool: () => MeasureTool,
@@ -399,13 +398,7 @@ function exportState(elements, camera, layers = []) {
399
398
  position: { ...camera.position },
400
399
  zoom: camera.zoom
401
400
  },
402
- elements: elements.map((el) => {
403
- const clone = structuredClone(el);
404
- if (clone.type === "arrow") {
405
- delete clone.cachedControlPoint;
406
- }
407
- return clone;
408
- }),
401
+ elements: elements.map((el) => structuredClone(el)),
409
402
  layers: layers.map((l) => ({ ...l }))
410
403
  };
411
404
  }
@@ -843,61 +836,6 @@ var Background = class {
843
836
  }
844
837
  };
845
838
 
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
-
901
839
  // src/canvas/input-handler.ts
902
840
  var ZOOM_SENSITIVITY = 1e-3;
903
841
  var MIDDLE_BUTTON = 1;
@@ -923,9 +861,6 @@ var InputHandler = class {
923
861
  historyRecorder;
924
862
  historyStack;
925
863
  isToolActive = false;
926
- lastPointerEvent = null;
927
- inputFilter = new InputFilter();
928
- deferredDown = null;
929
864
  abortController = new AbortController();
930
865
  setToolManager(toolManager, toolContext) {
931
866
  this.toolManager = toolManager;
@@ -933,9 +868,6 @@ var InputHandler = class {
933
868
  }
934
869
  destroy() {
935
870
  this.abortController.abort();
936
- this.inputFilter.reset();
937
- this.deferredDown = null;
938
- this.lastPointerEvent = null;
939
871
  }
940
872
  bind() {
941
873
  const opts = { signal: this.abortController.signal };
@@ -971,18 +903,11 @@ var InputHandler = class {
971
903
  this.lastPointer = { x: e.clientX, y: e.clientY };
972
904
  return;
973
905
  }
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
- }
906
+ if (this.activePointers.size === 1 && e.button === 0) {
981
907
  this.dispatchToolDown(e);
982
908
  }
983
909
  };
984
910
  onPointerMove = (e) => {
985
- this.lastPointerEvent = e;
986
911
  if (this.activePointers.has(e.pointerId)) {
987
912
  this.activePointers.set(e.pointerId, { x: e.clientX, y: e.clientY });
988
913
  }
@@ -999,22 +924,11 @@ var InputHandler = class {
999
924
  }
1000
925
  if (this.isToolActive) {
1001
926
  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
- }
1009
927
  } else if (this.activePointers.size === 0) {
1010
928
  this.dispatchToolHover(e);
1011
929
  }
1012
930
  };
1013
931
  onPointerUp = (e) => {
1014
- try {
1015
- this.element.releasePointerCapture(e.pointerId);
1016
- } catch {
1017
- }
1018
932
  this.activePointers.delete(e.pointerId);
1019
933
  if (this.activePointers.size < 2) {
1020
934
  this.lastPinchDistance = 0;
@@ -1022,16 +936,9 @@ var InputHandler = class {
1022
936
  if (this.isPanning && this.activePointers.size === 0) {
1023
937
  this.isPanning = false;
1024
938
  }
1025
- const upResult = this.inputFilter.filterUp(e);
1026
939
  if (this.isToolActive) {
1027
940
  this.dispatchToolUp(e);
1028
941
  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;
1035
942
  }
1036
943
  };
1037
944
  onKeyDown = (e) => {
@@ -1054,18 +961,9 @@ var InputHandler = class {
1054
961
  onKeyUp = (e) => {
1055
962
  if (e.key === " ") {
1056
963
  this.spaceHeld = false;
1057
- if (this.activePointers.size === 0) {
1058
- if (this.lastPointerEvent) {
1059
- this.dispatchToolHover(this.lastPointerEvent);
1060
- } else {
1061
- this.toolContext?.setCursor?.("default");
1062
- }
1063
- }
1064
964
  }
1065
965
  };
1066
966
  startPinch() {
1067
- this.inputFilter.reset();
1068
- this.deferredDown = null;
1069
967
  this.isPanning = true;
1070
968
  const [a, b] = this.getPinchPoints();
1071
969
  this.lastPinchDistance = this.distance(a, b);
@@ -1105,8 +1003,7 @@ var InputHandler = class {
1105
1003
  return {
1106
1004
  x: e.clientX - rect.left,
1107
1005
  y: e.clientY - rect.top,
1108
- pressure: e.pressure,
1109
- pointerType: e.pointerType === "touch" || e.pointerType === "pen" ? e.pointerType : "mouse"
1006
+ pressure: e.pressure
1110
1007
  };
1111
1008
  }
1112
1009
  dispatchToolDown(e) {
@@ -1164,7 +1061,6 @@ var InputHandler = class {
1164
1061
  this.dispatchToolUp(e);
1165
1062
  this.isToolActive = false;
1166
1063
  }
1167
- this.deferredDown = null;
1168
1064
  }
1169
1065
  };
1170
1066
 
@@ -1412,23 +1308,19 @@ var ElementStore = class {
1412
1308
  bus = new EventBus();
1413
1309
  layerOrderMap = /* @__PURE__ */ new Map();
1414
1310
  spatialIndex = new Quadtree({ x: -1e5, y: -1e5, w: 2e5, h: 2e5 });
1415
- sortedCache = null;
1416
1311
  get count() {
1417
1312
  return this.elements.size;
1418
1313
  }
1419
1314
  setLayerOrder(order) {
1420
1315
  this.layerOrderMap = new Map(order);
1421
- this.sortedCache = null;
1422
1316
  }
1423
1317
  getAll() {
1424
- if (this.sortedCache) return this.sortedCache;
1425
- this.sortedCache = [...this.elements.values()].sort((a, b) => {
1318
+ return [...this.elements.values()].sort((a, b) => {
1426
1319
  const layerA = this.layerOrderMap.get(a.layerId) ?? 0;
1427
1320
  const layerB = this.layerOrderMap.get(b.layerId) ?? 0;
1428
1321
  if (layerA !== layerB) return layerA - layerB;
1429
1322
  return a.zIndex - b.zIndex;
1430
1323
  });
1431
- return this.sortedCache;
1432
1324
  }
1433
1325
  getById(id) {
1434
1326
  return this.elements.get(id);
@@ -1439,7 +1331,6 @@ var ElementStore = class {
1439
1331
  );
1440
1332
  }
1441
1333
  add(element) {
1442
- this.sortedCache = null;
1443
1334
  this.elements.set(element.id, element);
1444
1335
  const bounds = getElementBounds(element);
1445
1336
  if (bounds) this.spatialIndex.insert(element.id, bounds);
@@ -1448,15 +1339,11 @@ var ElementStore = class {
1448
1339
  update(id, partial) {
1449
1340
  const existing = this.elements.get(id);
1450
1341
  if (!existing) return;
1451
- this.sortedCache = null;
1452
1342
  const updated = { ...existing, ...partial, id: existing.id, type: existing.type };
1453
1343
  if (updated.type === "arrow") {
1454
1344
  const arrow = updated;
1455
1345
  arrow.cachedControlPoint = getArrowControlPoint(arrow.from, arrow.to, arrow.bend);
1456
1346
  }
1457
- if (updated.type === "note" && "text" in partial) {
1458
- updated.text = sanitizeNoteHtml(updated.text);
1459
- }
1460
1347
  this.elements.set(id, updated);
1461
1348
  const newBounds = getElementBounds(updated);
1462
1349
  if (newBounds) {
@@ -1467,13 +1354,11 @@ var ElementStore = class {
1467
1354
  remove(id) {
1468
1355
  const element = this.elements.get(id);
1469
1356
  if (!element) return;
1470
- this.sortedCache = null;
1471
1357
  this.elements.delete(id);
1472
1358
  this.spatialIndex.remove(id);
1473
1359
  this.bus.emit("remove", element);
1474
1360
  }
1475
1361
  clear() {
1476
- this.sortedCache = null;
1477
1362
  this.elements.clear();
1478
1363
  this.spatialIndex.clear();
1479
1364
  this.bus.emit("clear", null);
@@ -1482,7 +1367,6 @@ var ElementStore = class {
1482
1367
  return this.getAll().map((el) => ({ ...el }));
1483
1368
  }
1484
1369
  loadSnapshot(elements) {
1485
- this.sortedCache = null;
1486
1370
  this.elements.clear();
1487
1371
  this.spatialIndex.clear();
1488
1372
  for (const el of elements) {
@@ -1490,10 +1374,6 @@ var ElementStore = class {
1490
1374
  const bounds = getElementBounds(el);
1491
1375
  if (bounds) this.spatialIndex.insert(el.id, bounds);
1492
1376
  }
1493
- this.bus.emit("clear", null);
1494
- for (const el of elements) {
1495
- this.bus.emit("add", el);
1496
- }
1497
1377
  }
1498
1378
  queryRect(rect) {
1499
1379
  const ids = this.spatialIndex.query(rect);
@@ -2574,7 +2454,7 @@ function createNote(input) {
2574
2454
  locked: input.locked ?? false,
2575
2455
  layerId: input.layerId ?? "",
2576
2456
  size: input.size ?? { w: 200, h: 100 },
2577
- text: sanitizeNoteHtml(input.text ?? ""),
2457
+ text: input.text ?? "",
2578
2458
  backgroundColor: input.backgroundColor ?? "#ffeb3b",
2579
2459
  textColor: input.textColor ?? "#000000",
2580
2460
  fontSize: input.fontSize ?? DEFAULT_NOTE_FONT_SIZE
@@ -4681,10 +4561,7 @@ var Viewport = class {
4681
4561
  position: "relative",
4682
4562
  width: "100%",
4683
4563
  height: "100%",
4684
- overflow: "hidden",
4685
- overscrollBehavior: "none",
4686
- userSelect: "none",
4687
- webkitUserSelect: "none"
4564
+ overflow: "hidden"
4688
4565
  });
4689
4566
  return el;
4690
4567
  }
@@ -6430,7 +6307,7 @@ var UpdateLayerCommand = class {
6430
6307
  };
6431
6308
 
6432
6309
  // src/index.ts
6433
- var VERSION = "0.11.3";
6310
+ var VERSION = "0.11.0";
6434
6311
  // Annotate the CommonJS export names for ESM import in node:
6435
6312
  0 && (module.exports = {
6436
6313
  AddElementCommand,
@@ -6450,7 +6327,6 @@ var VERSION = "0.11.3";
6450
6327
  HistoryRecorder,
6451
6328
  HistoryStack,
6452
6329
  ImageTool,
6453
- InputFilter,
6454
6330
  InputHandler,
6455
6331
  LayerManager,
6456
6332
  MeasureTool,
package/dist/index.d.cts CHANGED
@@ -200,7 +200,6 @@ declare class ElementStore {
200
200
  private bus;
201
201
  private layerOrderMap;
202
202
  private spatialIndex;
203
- private sortedCache;
204
203
  get count(): number;
205
204
  setLayerOrder(order: Map<string, number>): void;
206
205
  getAll(): CanvasElement[];
@@ -239,7 +238,6 @@ interface PointerState {
239
238
  x: number;
240
239
  y: number;
241
240
  pressure: number;
242
- pointerType: 'mouse' | 'touch' | 'pen';
243
241
  }
244
242
  interface Tool {
245
243
  readonly name: string;
@@ -425,9 +423,6 @@ declare class InputHandler {
425
423
  private historyRecorder;
426
424
  private historyStack;
427
425
  private isToolActive;
428
- private lastPointerEvent;
429
- private readonly inputFilter;
430
- private deferredDown;
431
426
  private readonly abortController;
432
427
  constructor(element: HTMLElement, camera: Camera, options?: InputHandlerOptions);
433
428
  setToolManager(toolManager: ToolManager, toolContext: ToolContext): void;
@@ -455,27 +450,6 @@ declare class InputHandler {
455
450
  private cancelToolIfActive;
456
451
  }
457
452
 
458
- type FilterAction = 'dispatch' | 'suppress' | 'defer';
459
- interface FilteredEvent {
460
- event: PointerEvent;
461
- action: FilterAction;
462
- }
463
- interface FilteredUpEvent extends FilteredEvent {
464
- pendingTap?: {
465
- x: number;
466
- y: number;
467
- };
468
- }
469
- declare class InputFilter {
470
- private activePenId;
471
- private pendingTap;
472
- static readonly MIN_MOVE_DISTANCE = 3;
473
- filterDown(e: PointerEvent): FilteredEvent;
474
- filterMove(e: PointerEvent): FilteredEvent;
475
- filterUp(e: PointerEvent): FilteredUpEvent;
476
- reset(): void;
477
- }
478
-
479
453
  interface FontSizePreset {
480
454
  label: string;
481
455
  size: number;
@@ -1145,6 +1119,6 @@ declare class UpdateLayerCommand implements Command {
1145
1119
  undo(_store: ElementStore): void;
1146
1120
  }
1147
1121
 
1148
- declare const VERSION = "0.11.3";
1122
+ declare const VERSION = "0.11.0";
1149
1123
 
1150
- 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 };
1124
+ 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 };
package/dist/index.d.ts CHANGED
@@ -200,7 +200,6 @@ declare class ElementStore {
200
200
  private bus;
201
201
  private layerOrderMap;
202
202
  private spatialIndex;
203
- private sortedCache;
204
203
  get count(): number;
205
204
  setLayerOrder(order: Map<string, number>): void;
206
205
  getAll(): CanvasElement[];
@@ -239,7 +238,6 @@ interface PointerState {
239
238
  x: number;
240
239
  y: number;
241
240
  pressure: number;
242
- pointerType: 'mouse' | 'touch' | 'pen';
243
241
  }
244
242
  interface Tool {
245
243
  readonly name: string;
@@ -425,9 +423,6 @@ declare class InputHandler {
425
423
  private historyRecorder;
426
424
  private historyStack;
427
425
  private isToolActive;
428
- private lastPointerEvent;
429
- private readonly inputFilter;
430
- private deferredDown;
431
426
  private readonly abortController;
432
427
  constructor(element: HTMLElement, camera: Camera, options?: InputHandlerOptions);
433
428
  setToolManager(toolManager: ToolManager, toolContext: ToolContext): void;
@@ -455,27 +450,6 @@ declare class InputHandler {
455
450
  private cancelToolIfActive;
456
451
  }
457
452
 
458
- type FilterAction = 'dispatch' | 'suppress' | 'defer';
459
- interface FilteredEvent {
460
- event: PointerEvent;
461
- action: FilterAction;
462
- }
463
- interface FilteredUpEvent extends FilteredEvent {
464
- pendingTap?: {
465
- x: number;
466
- y: number;
467
- };
468
- }
469
- declare class InputFilter {
470
- private activePenId;
471
- private pendingTap;
472
- static readonly MIN_MOVE_DISTANCE = 3;
473
- filterDown(e: PointerEvent): FilteredEvent;
474
- filterMove(e: PointerEvent): FilteredEvent;
475
- filterUp(e: PointerEvent): FilteredUpEvent;
476
- reset(): void;
477
- }
478
-
479
453
  interface FontSizePreset {
480
454
  label: string;
481
455
  size: number;
@@ -1145,6 +1119,6 @@ declare class UpdateLayerCommand implements Command {
1145
1119
  undo(_store: ElementStore): void;
1146
1120
  }
1147
1121
 
1148
- declare const VERSION = "0.11.3";
1122
+ declare const VERSION = "0.11.0";
1149
1123
 
1150
- 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 };
1124
+ 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 };
package/dist/index.js CHANGED
@@ -292,13 +292,7 @@ function exportState(elements, camera, layers = []) {
292
292
  position: { ...camera.position },
293
293
  zoom: camera.zoom
294
294
  },
295
- elements: elements.map((el) => {
296
- const clone = structuredClone(el);
297
- if (clone.type === "arrow") {
298
- delete clone.cachedControlPoint;
299
- }
300
- return clone;
301
- }),
295
+ elements: elements.map((el) => structuredClone(el)),
302
296
  layers: layers.map((l) => ({ ...l }))
303
297
  };
304
298
  }
@@ -736,61 +730,6 @@ var Background = class {
736
730
  }
737
731
  };
738
732
 
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
-
794
733
  // src/canvas/input-handler.ts
795
734
  var ZOOM_SENSITIVITY = 1e-3;
796
735
  var MIDDLE_BUTTON = 1;
@@ -816,9 +755,6 @@ var InputHandler = class {
816
755
  historyRecorder;
817
756
  historyStack;
818
757
  isToolActive = false;
819
- lastPointerEvent = null;
820
- inputFilter = new InputFilter();
821
- deferredDown = null;
822
758
  abortController = new AbortController();
823
759
  setToolManager(toolManager, toolContext) {
824
760
  this.toolManager = toolManager;
@@ -826,9 +762,6 @@ var InputHandler = class {
826
762
  }
827
763
  destroy() {
828
764
  this.abortController.abort();
829
- this.inputFilter.reset();
830
- this.deferredDown = null;
831
- this.lastPointerEvent = null;
832
765
  }
833
766
  bind() {
834
767
  const opts = { signal: this.abortController.signal };
@@ -864,18 +797,11 @@ var InputHandler = class {
864
797
  this.lastPointer = { x: e.clientX, y: e.clientY };
865
798
  return;
866
799
  }
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
- }
800
+ if (this.activePointers.size === 1 && e.button === 0) {
874
801
  this.dispatchToolDown(e);
875
802
  }
876
803
  };
877
804
  onPointerMove = (e) => {
878
- this.lastPointerEvent = e;
879
805
  if (this.activePointers.has(e.pointerId)) {
880
806
  this.activePointers.set(e.pointerId, { x: e.clientX, y: e.clientY });
881
807
  }
@@ -892,22 +818,11 @@ var InputHandler = class {
892
818
  }
893
819
  if (this.isToolActive) {
894
820
  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
- }
902
821
  } else if (this.activePointers.size === 0) {
903
822
  this.dispatchToolHover(e);
904
823
  }
905
824
  };
906
825
  onPointerUp = (e) => {
907
- try {
908
- this.element.releasePointerCapture(e.pointerId);
909
- } catch {
910
- }
911
826
  this.activePointers.delete(e.pointerId);
912
827
  if (this.activePointers.size < 2) {
913
828
  this.lastPinchDistance = 0;
@@ -915,16 +830,9 @@ var InputHandler = class {
915
830
  if (this.isPanning && this.activePointers.size === 0) {
916
831
  this.isPanning = false;
917
832
  }
918
- const upResult = this.inputFilter.filterUp(e);
919
833
  if (this.isToolActive) {
920
834
  this.dispatchToolUp(e);
921
835
  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;
928
836
  }
929
837
  };
930
838
  onKeyDown = (e) => {
@@ -947,18 +855,9 @@ var InputHandler = class {
947
855
  onKeyUp = (e) => {
948
856
  if (e.key === " ") {
949
857
  this.spaceHeld = false;
950
- if (this.activePointers.size === 0) {
951
- if (this.lastPointerEvent) {
952
- this.dispatchToolHover(this.lastPointerEvent);
953
- } else {
954
- this.toolContext?.setCursor?.("default");
955
- }
956
- }
957
858
  }
958
859
  };
959
860
  startPinch() {
960
- this.inputFilter.reset();
961
- this.deferredDown = null;
962
861
  this.isPanning = true;
963
862
  const [a, b] = this.getPinchPoints();
964
863
  this.lastPinchDistance = this.distance(a, b);
@@ -998,8 +897,7 @@ var InputHandler = class {
998
897
  return {
999
898
  x: e.clientX - rect.left,
1000
899
  y: e.clientY - rect.top,
1001
- pressure: e.pressure,
1002
- pointerType: e.pointerType === "touch" || e.pointerType === "pen" ? e.pointerType : "mouse"
900
+ pressure: e.pressure
1003
901
  };
1004
902
  }
1005
903
  dispatchToolDown(e) {
@@ -1057,7 +955,6 @@ var InputHandler = class {
1057
955
  this.dispatchToolUp(e);
1058
956
  this.isToolActive = false;
1059
957
  }
1060
- this.deferredDown = null;
1061
958
  }
1062
959
  };
1063
960
 
@@ -1305,23 +1202,19 @@ var ElementStore = class {
1305
1202
  bus = new EventBus();
1306
1203
  layerOrderMap = /* @__PURE__ */ new Map();
1307
1204
  spatialIndex = new Quadtree({ x: -1e5, y: -1e5, w: 2e5, h: 2e5 });
1308
- sortedCache = null;
1309
1205
  get count() {
1310
1206
  return this.elements.size;
1311
1207
  }
1312
1208
  setLayerOrder(order) {
1313
1209
  this.layerOrderMap = new Map(order);
1314
- this.sortedCache = null;
1315
1210
  }
1316
1211
  getAll() {
1317
- if (this.sortedCache) return this.sortedCache;
1318
- this.sortedCache = [...this.elements.values()].sort((a, b) => {
1212
+ return [...this.elements.values()].sort((a, b) => {
1319
1213
  const layerA = this.layerOrderMap.get(a.layerId) ?? 0;
1320
1214
  const layerB = this.layerOrderMap.get(b.layerId) ?? 0;
1321
1215
  if (layerA !== layerB) return layerA - layerB;
1322
1216
  return a.zIndex - b.zIndex;
1323
1217
  });
1324
- return this.sortedCache;
1325
1218
  }
1326
1219
  getById(id) {
1327
1220
  return this.elements.get(id);
@@ -1332,7 +1225,6 @@ var ElementStore = class {
1332
1225
  );
1333
1226
  }
1334
1227
  add(element) {
1335
- this.sortedCache = null;
1336
1228
  this.elements.set(element.id, element);
1337
1229
  const bounds = getElementBounds(element);
1338
1230
  if (bounds) this.spatialIndex.insert(element.id, bounds);
@@ -1341,15 +1233,11 @@ var ElementStore = class {
1341
1233
  update(id, partial) {
1342
1234
  const existing = this.elements.get(id);
1343
1235
  if (!existing) return;
1344
- this.sortedCache = null;
1345
1236
  const updated = { ...existing, ...partial, id: existing.id, type: existing.type };
1346
1237
  if (updated.type === "arrow") {
1347
1238
  const arrow = updated;
1348
1239
  arrow.cachedControlPoint = getArrowControlPoint(arrow.from, arrow.to, arrow.bend);
1349
1240
  }
1350
- if (updated.type === "note" && "text" in partial) {
1351
- updated.text = sanitizeNoteHtml(updated.text);
1352
- }
1353
1241
  this.elements.set(id, updated);
1354
1242
  const newBounds = getElementBounds(updated);
1355
1243
  if (newBounds) {
@@ -1360,13 +1248,11 @@ var ElementStore = class {
1360
1248
  remove(id) {
1361
1249
  const element = this.elements.get(id);
1362
1250
  if (!element) return;
1363
- this.sortedCache = null;
1364
1251
  this.elements.delete(id);
1365
1252
  this.spatialIndex.remove(id);
1366
1253
  this.bus.emit("remove", element);
1367
1254
  }
1368
1255
  clear() {
1369
- this.sortedCache = null;
1370
1256
  this.elements.clear();
1371
1257
  this.spatialIndex.clear();
1372
1258
  this.bus.emit("clear", null);
@@ -1375,7 +1261,6 @@ var ElementStore = class {
1375
1261
  return this.getAll().map((el) => ({ ...el }));
1376
1262
  }
1377
1263
  loadSnapshot(elements) {
1378
- this.sortedCache = null;
1379
1264
  this.elements.clear();
1380
1265
  this.spatialIndex.clear();
1381
1266
  for (const el of elements) {
@@ -1383,10 +1268,6 @@ var ElementStore = class {
1383
1268
  const bounds = getElementBounds(el);
1384
1269
  if (bounds) this.spatialIndex.insert(el.id, bounds);
1385
1270
  }
1386
- this.bus.emit("clear", null);
1387
- for (const el of elements) {
1388
- this.bus.emit("add", el);
1389
- }
1390
1271
  }
1391
1272
  queryRect(rect) {
1392
1273
  const ids = this.spatialIndex.query(rect);
@@ -2467,7 +2348,7 @@ function createNote(input) {
2467
2348
  locked: input.locked ?? false,
2468
2349
  layerId: input.layerId ?? "",
2469
2350
  size: input.size ?? { w: 200, h: 100 },
2470
- text: sanitizeNoteHtml(input.text ?? ""),
2351
+ text: input.text ?? "",
2471
2352
  backgroundColor: input.backgroundColor ?? "#ffeb3b",
2472
2353
  textColor: input.textColor ?? "#000000",
2473
2354
  fontSize: input.fontSize ?? DEFAULT_NOTE_FONT_SIZE
@@ -4574,10 +4455,7 @@ var Viewport = class {
4574
4455
  position: "relative",
4575
4456
  width: "100%",
4576
4457
  height: "100%",
4577
- overflow: "hidden",
4578
- overscrollBehavior: "none",
4579
- userSelect: "none",
4580
- webkitUserSelect: "none"
4458
+ overflow: "hidden"
4581
4459
  });
4582
4460
  return el;
4583
4461
  }
@@ -6323,7 +6201,7 @@ var UpdateLayerCommand = class {
6323
6201
  };
6324
6202
 
6325
6203
  // src/index.ts
6326
- var VERSION = "0.11.3";
6204
+ var VERSION = "0.11.0";
6327
6205
  export {
6328
6206
  AddElementCommand,
6329
6207
  ArrowTool,
@@ -6342,7 +6220,6 @@ export {
6342
6220
  HistoryRecorder,
6343
6221
  HistoryStack,
6344
6222
  ImageTool,
6345
- InputFilter,
6346
6223
  InputHandler,
6347
6224
  LayerManager,
6348
6225
  MeasureTool,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fieldnotes/core",
3
- "version": "0.11.3",
3
+ "version": "0.13.0",
4
4
  "description": "Vanilla TypeScript infinite canvas engine",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",