@fieldnotes/core 0.3.1 → 0.4.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.d.cts CHANGED
@@ -74,7 +74,16 @@ interface TextElement extends BaseElement {
74
74
  color: string;
75
75
  textAlign: 'left' | 'center' | 'right';
76
76
  }
77
- type CanvasElement = StrokeElement | NoteElement | ArrowElement | ImageElement | HtmlElement | TextElement;
77
+ type ShapeKind = 'rectangle' | 'ellipse';
78
+ interface ShapeElement extends BaseElement {
79
+ type: 'shape';
80
+ shape: ShapeKind;
81
+ size: Size;
82
+ strokeColor: string;
83
+ strokeWidth: number;
84
+ fillColor: string;
85
+ }
86
+ type CanvasElement = StrokeElement | NoteElement | ArrowElement | ImageElement | HtmlElement | TextElement | ShapeElement;
78
87
  type ElementType = CanvasElement['type'];
79
88
 
80
89
  interface CanvasState {
@@ -209,7 +218,7 @@ interface Tool {
209
218
  onDeactivate?(ctx: ToolContext): void;
210
219
  renderOverlay?(ctx: CanvasRenderingContext2D): void;
211
220
  }
212
- type ToolName = 'hand' | 'select' | 'pencil' | 'eraser' | 'arrow' | 'note' | 'image' | 'text';
221
+ type ToolName = 'hand' | 'select' | 'pencil' | 'eraser' | 'arrow' | 'note' | 'image' | 'text' | 'shape';
213
222
 
214
223
  declare class ToolManager {
215
224
  private tools;
@@ -406,6 +415,9 @@ declare class ElementRenderer {
406
415
  private renderArrow;
407
416
  private renderArrowhead;
408
417
  private getVisualEndpoints;
418
+ private renderShape;
419
+ private fillShapePath;
420
+ private strokeShapePath;
409
421
  }
410
422
 
411
423
  declare class NoteEditor {
@@ -475,6 +487,15 @@ declare function createNote(input: NoteInput): NoteElement;
475
487
  declare function createArrow(input: ArrowInput): ArrowElement;
476
488
  declare function createImage(input: ImageInput): ImageElement;
477
489
  declare function createHtmlElement(input: HtmlInput): HtmlElement;
490
+ interface ShapeInput extends BaseDefaults {
491
+ position: Point;
492
+ size: Size;
493
+ shape?: ShapeKind;
494
+ strokeColor?: string;
495
+ strokeWidth?: number;
496
+ fillColor?: string;
497
+ }
498
+ declare function createShape(input: ShapeInput): ShapeElement;
478
499
  declare function createText(input: TextInput): TextElement;
479
500
 
480
501
  interface Rect {
@@ -679,6 +700,35 @@ declare class ImageTool implements Tool {
679
700
  onPointerUp(state: PointerState, ctx: ToolContext): void;
680
701
  }
681
702
 
682
- declare const VERSION = "0.3.1";
703
+ interface ShapeToolOptions {
704
+ shape?: ShapeKind;
705
+ strokeColor?: string;
706
+ strokeWidth?: number;
707
+ fillColor?: string;
708
+ }
709
+ declare class ShapeTool implements Tool {
710
+ readonly name = "shape";
711
+ private drawing;
712
+ private start;
713
+ private end;
714
+ private shiftHeld;
715
+ private shape;
716
+ private strokeColor;
717
+ private strokeWidth;
718
+ private fillColor;
719
+ constructor(options?: ShapeToolOptions);
720
+ setOptions(options: ShapeToolOptions): void;
721
+ onActivate(_ctx: ToolContext): void;
722
+ onDeactivate(_ctx: ToolContext): void;
723
+ onPointerDown(state: PointerState, ctx: ToolContext): void;
724
+ onPointerMove(state: PointerState, ctx: ToolContext): void;
725
+ onPointerUp(_state: PointerState, ctx: ToolContext): void;
726
+ renderOverlay(ctx: CanvasRenderingContext2D): void;
727
+ private computeRect;
728
+ private onKeyDown;
729
+ private onKeyUp;
730
+ }
731
+
732
+ declare const VERSION = "0.4.0";
683
733
 
684
- export { AddElementCommand, type ArrowElement, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, Background, type BackgroundOptions, type BackgroundPattern, BatchCommand, type Binding, type Bounds, Camera, type CameraOptions, type CanvasElement, type CanvasState, type Command, ElementRenderer, ElementStore, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, EventBus, HandTool, HistoryRecorder, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, InputHandler, NoteEditor, type NoteElement, NoteTool, type NoteToolOptions, PencilTool, type PencilToolOptions, type Point, type PointerState, RemoveElementCommand, SelectTool, type Size, type StrokeElement, type StrokePoint, type TextElement, TextTool, type TextToolOptions, type Tool, type ToolContext, ToolManager, type ToolName, UpdateElementCommand, VERSION, Viewport, type ViewportOptions, clearStaleBindings, createArrow, createHtmlElement, createId, createImage, createNote, createStroke, createText, exportState, findBindTarget, findBoundArrows, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, getEdgeIntersection, getElementBounds, getElementCenter, isBindable, isNearBezier, parseState, unbindArrow, updateBoundArrow };
734
+ export { AddElementCommand, type ArrowElement, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, Background, type BackgroundOptions, type BackgroundPattern, BatchCommand, type Binding, type Bounds, Camera, type CameraOptions, type CanvasElement, type CanvasState, type Command, ElementRenderer, ElementStore, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, EventBus, HandTool, HistoryRecorder, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, InputHandler, NoteEditor, type NoteElement, NoteTool, type NoteToolOptions, PencilTool, type PencilToolOptions, type Point, type PointerState, RemoveElementCommand, SelectTool, type ShapeElement, type ShapeKind, ShapeTool, type ShapeToolOptions, type Size, type StrokeElement, type StrokePoint, type TextElement, TextTool, type TextToolOptions, type Tool, type ToolContext, ToolManager, type ToolName, UpdateElementCommand, VERSION, Viewport, type ViewportOptions, clearStaleBindings, createArrow, createHtmlElement, createId, createImage, createNote, createShape, createStroke, createText, exportState, findBindTarget, findBoundArrows, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, getEdgeIntersection, getElementBounds, getElementCenter, isBindable, isNearBezier, parseState, unbindArrow, updateBoundArrow };
package/dist/index.d.ts CHANGED
@@ -74,7 +74,16 @@ interface TextElement extends BaseElement {
74
74
  color: string;
75
75
  textAlign: 'left' | 'center' | 'right';
76
76
  }
77
- type CanvasElement = StrokeElement | NoteElement | ArrowElement | ImageElement | HtmlElement | TextElement;
77
+ type ShapeKind = 'rectangle' | 'ellipse';
78
+ interface ShapeElement extends BaseElement {
79
+ type: 'shape';
80
+ shape: ShapeKind;
81
+ size: Size;
82
+ strokeColor: string;
83
+ strokeWidth: number;
84
+ fillColor: string;
85
+ }
86
+ type CanvasElement = StrokeElement | NoteElement | ArrowElement | ImageElement | HtmlElement | TextElement | ShapeElement;
78
87
  type ElementType = CanvasElement['type'];
79
88
 
80
89
  interface CanvasState {
@@ -209,7 +218,7 @@ interface Tool {
209
218
  onDeactivate?(ctx: ToolContext): void;
210
219
  renderOverlay?(ctx: CanvasRenderingContext2D): void;
211
220
  }
212
- type ToolName = 'hand' | 'select' | 'pencil' | 'eraser' | 'arrow' | 'note' | 'image' | 'text';
221
+ type ToolName = 'hand' | 'select' | 'pencil' | 'eraser' | 'arrow' | 'note' | 'image' | 'text' | 'shape';
213
222
 
214
223
  declare class ToolManager {
215
224
  private tools;
@@ -406,6 +415,9 @@ declare class ElementRenderer {
406
415
  private renderArrow;
407
416
  private renderArrowhead;
408
417
  private getVisualEndpoints;
418
+ private renderShape;
419
+ private fillShapePath;
420
+ private strokeShapePath;
409
421
  }
410
422
 
411
423
  declare class NoteEditor {
@@ -475,6 +487,15 @@ declare function createNote(input: NoteInput): NoteElement;
475
487
  declare function createArrow(input: ArrowInput): ArrowElement;
476
488
  declare function createImage(input: ImageInput): ImageElement;
477
489
  declare function createHtmlElement(input: HtmlInput): HtmlElement;
490
+ interface ShapeInput extends BaseDefaults {
491
+ position: Point;
492
+ size: Size;
493
+ shape?: ShapeKind;
494
+ strokeColor?: string;
495
+ strokeWidth?: number;
496
+ fillColor?: string;
497
+ }
498
+ declare function createShape(input: ShapeInput): ShapeElement;
478
499
  declare function createText(input: TextInput): TextElement;
479
500
 
480
501
  interface Rect {
@@ -679,6 +700,35 @@ declare class ImageTool implements Tool {
679
700
  onPointerUp(state: PointerState, ctx: ToolContext): void;
680
701
  }
681
702
 
682
- declare const VERSION = "0.3.1";
703
+ interface ShapeToolOptions {
704
+ shape?: ShapeKind;
705
+ strokeColor?: string;
706
+ strokeWidth?: number;
707
+ fillColor?: string;
708
+ }
709
+ declare class ShapeTool implements Tool {
710
+ readonly name = "shape";
711
+ private drawing;
712
+ private start;
713
+ private end;
714
+ private shiftHeld;
715
+ private shape;
716
+ private strokeColor;
717
+ private strokeWidth;
718
+ private fillColor;
719
+ constructor(options?: ShapeToolOptions);
720
+ setOptions(options: ShapeToolOptions): void;
721
+ onActivate(_ctx: ToolContext): void;
722
+ onDeactivate(_ctx: ToolContext): void;
723
+ onPointerDown(state: PointerState, ctx: ToolContext): void;
724
+ onPointerMove(state: PointerState, ctx: ToolContext): void;
725
+ onPointerUp(_state: PointerState, ctx: ToolContext): void;
726
+ renderOverlay(ctx: CanvasRenderingContext2D): void;
727
+ private computeRect;
728
+ private onKeyDown;
729
+ private onKeyUp;
730
+ }
731
+
732
+ declare const VERSION = "0.4.0";
683
733
 
684
- export { AddElementCommand, type ArrowElement, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, Background, type BackgroundOptions, type BackgroundPattern, BatchCommand, type Binding, type Bounds, Camera, type CameraOptions, type CanvasElement, type CanvasState, type Command, ElementRenderer, ElementStore, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, EventBus, HandTool, HistoryRecorder, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, InputHandler, NoteEditor, type NoteElement, NoteTool, type NoteToolOptions, PencilTool, type PencilToolOptions, type Point, type PointerState, RemoveElementCommand, SelectTool, type Size, type StrokeElement, type StrokePoint, type TextElement, TextTool, type TextToolOptions, type Tool, type ToolContext, ToolManager, type ToolName, UpdateElementCommand, VERSION, Viewport, type ViewportOptions, clearStaleBindings, createArrow, createHtmlElement, createId, createImage, createNote, createStroke, createText, exportState, findBindTarget, findBoundArrows, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, getEdgeIntersection, getElementBounds, getElementCenter, isBindable, isNearBezier, parseState, unbindArrow, updateBoundArrow };
734
+ export { AddElementCommand, type ArrowElement, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, Background, type BackgroundOptions, type BackgroundPattern, BatchCommand, type Binding, type Bounds, Camera, type CameraOptions, type CanvasElement, type CanvasState, type Command, ElementRenderer, ElementStore, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, EventBus, HandTool, HistoryRecorder, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, InputHandler, NoteEditor, type NoteElement, NoteTool, type NoteToolOptions, PencilTool, type PencilToolOptions, type Point, type PointerState, RemoveElementCommand, SelectTool, type ShapeElement, type ShapeKind, ShapeTool, type ShapeToolOptions, type Size, type StrokeElement, type StrokePoint, type TextElement, TextTool, type TextToolOptions, type Tool, type ToolContext, ToolManager, type ToolName, UpdateElementCommand, VERSION, Viewport, type ViewportOptions, clearStaleBindings, createArrow, createHtmlElement, createId, createImage, createNote, createShape, createStroke, createText, exportState, findBindTarget, findBoundArrows, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, getEdgeIntersection, getElementBounds, getElementCenter, isBindable, isNearBezier, parseState, unbindArrow, updateBoundArrow };
package/dist/index.js CHANGED
@@ -70,7 +70,7 @@ function validateState(data) {
70
70
  }
71
71
  cleanBindings(obj["elements"]);
72
72
  }
73
- var VALID_TYPES = /* @__PURE__ */ new Set(["stroke", "note", "arrow", "image", "html", "text"]);
73
+ var VALID_TYPES = /* @__PURE__ */ new Set(["stroke", "note", "arrow", "image", "html", "text", "shape"]);
74
74
  function validateElement(el) {
75
75
  if (!el || typeof el !== "object") {
76
76
  throw new Error("Invalid element: expected an object");
@@ -111,6 +111,9 @@ function migrateElement(obj) {
111
111
  }
112
112
  }
113
113
  }
114
+ if (obj["type"] === "shape" && typeof obj["shape"] !== "string") {
115
+ obj["shape"] = "rectangle";
116
+ }
114
117
  }
115
118
 
116
119
  // src/core/auto-save.ts
@@ -694,7 +697,7 @@ function isNearLine(point, a, b, threshold) {
694
697
  }
695
698
 
696
699
  // src/elements/arrow-binding.ts
697
- var BINDABLE_TYPES = /* @__PURE__ */ new Set(["note", "text", "image", "html"]);
700
+ var BINDABLE_TYPES = /* @__PURE__ */ new Set(["note", "text", "image", "html", "shape"]);
698
701
  function isBindable(element) {
699
702
  return BINDABLE_TYPES.has(element.type);
700
703
  }
@@ -914,6 +917,9 @@ var ElementRenderer = class {
914
917
  case "arrow":
915
918
  this.renderArrow(ctx, element);
916
919
  break;
920
+ case "shape":
921
+ this.renderShape(ctx, element);
922
+ break;
917
923
  }
918
924
  }
919
925
  renderStroke(ctx, stroke) {
@@ -1006,6 +1012,49 @@ var ElementRenderer = class {
1006
1012
  }
1007
1013
  return { visualFrom, visualTo };
1008
1014
  }
1015
+ renderShape(ctx, shape) {
1016
+ ctx.save();
1017
+ if (shape.fillColor !== "none") {
1018
+ ctx.fillStyle = shape.fillColor;
1019
+ this.fillShapePath(ctx, shape);
1020
+ }
1021
+ if (shape.strokeWidth > 0) {
1022
+ ctx.strokeStyle = shape.strokeColor;
1023
+ ctx.lineWidth = shape.strokeWidth;
1024
+ this.strokeShapePath(ctx, shape);
1025
+ }
1026
+ ctx.restore();
1027
+ }
1028
+ fillShapePath(ctx, shape) {
1029
+ switch (shape.shape) {
1030
+ case "rectangle":
1031
+ ctx.fillRect(shape.position.x, shape.position.y, shape.size.w, shape.size.h);
1032
+ break;
1033
+ case "ellipse": {
1034
+ const cx = shape.position.x + shape.size.w / 2;
1035
+ const cy = shape.position.y + shape.size.h / 2;
1036
+ ctx.beginPath();
1037
+ ctx.ellipse(cx, cy, shape.size.w / 2, shape.size.h / 2, 0, 0, Math.PI * 2);
1038
+ ctx.fill();
1039
+ break;
1040
+ }
1041
+ }
1042
+ }
1043
+ strokeShapePath(ctx, shape) {
1044
+ switch (shape.shape) {
1045
+ case "rectangle":
1046
+ ctx.strokeRect(shape.position.x, shape.position.y, shape.size.w, shape.size.h);
1047
+ break;
1048
+ case "ellipse": {
1049
+ const cx = shape.position.x + shape.size.w / 2;
1050
+ const cy = shape.position.y + shape.size.h / 2;
1051
+ ctx.beginPath();
1052
+ ctx.ellipse(cx, cy, shape.size.w / 2, shape.size.h / 2, 0, 0, Math.PI * 2);
1053
+ ctx.stroke();
1054
+ break;
1055
+ }
1056
+ }
1057
+ }
1009
1058
  };
1010
1059
 
1011
1060
  // src/elements/note-editor.ts
@@ -1413,6 +1462,20 @@ function createHtmlElement(input) {
1413
1462
  size: input.size
1414
1463
  };
1415
1464
  }
1465
+ function createShape(input) {
1466
+ return {
1467
+ id: createId("shape"),
1468
+ type: "shape",
1469
+ position: input.position,
1470
+ zIndex: input.zIndex ?? 0,
1471
+ locked: input.locked ?? false,
1472
+ shape: input.shape ?? "rectangle",
1473
+ size: input.size,
1474
+ strokeColor: input.strokeColor ?? "#000000",
1475
+ strokeWidth: input.strokeWidth ?? 2,
1476
+ fillColor: input.fillColor ?? "none"
1477
+ };
1478
+ }
1416
1479
  function createText(input) {
1417
1480
  return {
1418
1481
  id: createId("text"),
@@ -2854,8 +2917,123 @@ var ImageTool = class {
2854
2917
  }
2855
2918
  };
2856
2919
 
2920
+ // src/tools/shape-tool.ts
2921
+ var ShapeTool = class {
2922
+ name = "shape";
2923
+ drawing = false;
2924
+ start = { x: 0, y: 0 };
2925
+ end = { x: 0, y: 0 };
2926
+ shiftHeld = false;
2927
+ shape;
2928
+ strokeColor;
2929
+ strokeWidth;
2930
+ fillColor;
2931
+ constructor(options = {}) {
2932
+ this.shape = options.shape ?? "rectangle";
2933
+ this.strokeColor = options.strokeColor ?? "#000000";
2934
+ this.strokeWidth = options.strokeWidth ?? 2;
2935
+ this.fillColor = options.fillColor ?? "none";
2936
+ }
2937
+ setOptions(options) {
2938
+ if (options.shape !== void 0) this.shape = options.shape;
2939
+ if (options.strokeColor !== void 0) this.strokeColor = options.strokeColor;
2940
+ if (options.strokeWidth !== void 0) this.strokeWidth = options.strokeWidth;
2941
+ if (options.fillColor !== void 0) this.fillColor = options.fillColor;
2942
+ }
2943
+ onActivate(_ctx) {
2944
+ if (typeof window !== "undefined") {
2945
+ window.addEventListener("keydown", this.onKeyDown);
2946
+ window.addEventListener("keyup", this.onKeyUp);
2947
+ }
2948
+ }
2949
+ onDeactivate(_ctx) {
2950
+ this.shiftHeld = false;
2951
+ if (typeof window !== "undefined") {
2952
+ window.removeEventListener("keydown", this.onKeyDown);
2953
+ window.removeEventListener("keyup", this.onKeyUp);
2954
+ }
2955
+ }
2956
+ onPointerDown(state, ctx) {
2957
+ this.drawing = true;
2958
+ this.start = ctx.camera.screenToWorld({ x: state.x, y: state.y });
2959
+ this.end = { ...this.start };
2960
+ }
2961
+ onPointerMove(state, ctx) {
2962
+ if (!this.drawing) return;
2963
+ this.end = ctx.camera.screenToWorld({ x: state.x, y: state.y });
2964
+ ctx.requestRender();
2965
+ }
2966
+ onPointerUp(_state, ctx) {
2967
+ if (!this.drawing) return;
2968
+ this.drawing = false;
2969
+ const { position, size } = this.computeRect();
2970
+ if (size.w === 0 || size.h === 0) return;
2971
+ const shape = createShape({
2972
+ position,
2973
+ size,
2974
+ shape: this.shape,
2975
+ strokeColor: this.strokeColor,
2976
+ strokeWidth: this.strokeWidth,
2977
+ fillColor: this.fillColor
2978
+ });
2979
+ ctx.store.add(shape);
2980
+ ctx.requestRender();
2981
+ ctx.switchTool?.("select");
2982
+ }
2983
+ renderOverlay(ctx) {
2984
+ if (!this.drawing) return;
2985
+ const { position, size } = this.computeRect();
2986
+ if (size.w === 0 && size.h === 0) return;
2987
+ ctx.save();
2988
+ ctx.globalAlpha = 0.5;
2989
+ ctx.strokeStyle = this.strokeColor;
2990
+ ctx.lineWidth = this.strokeWidth;
2991
+ if (this.fillColor !== "none") {
2992
+ ctx.fillStyle = this.fillColor;
2993
+ }
2994
+ switch (this.shape) {
2995
+ case "rectangle":
2996
+ if (this.fillColor !== "none") {
2997
+ ctx.fillRect(position.x, position.y, size.w, size.h);
2998
+ }
2999
+ ctx.strokeRect(position.x, position.y, size.w, size.h);
3000
+ break;
3001
+ case "ellipse": {
3002
+ const cx = position.x + size.w / 2;
3003
+ const cy = position.y + size.h / 2;
3004
+ ctx.beginPath();
3005
+ ctx.ellipse(cx, cy, size.w / 2, size.h / 2, 0, 0, Math.PI * 2);
3006
+ if (this.fillColor !== "none") ctx.fill();
3007
+ ctx.stroke();
3008
+ break;
3009
+ }
3010
+ }
3011
+ ctx.restore();
3012
+ }
3013
+ computeRect() {
3014
+ let x = Math.min(this.start.x, this.end.x);
3015
+ let y = Math.min(this.start.y, this.end.y);
3016
+ let w = Math.abs(this.end.x - this.start.x);
3017
+ let h = Math.abs(this.end.y - this.start.y);
3018
+ if (this.shiftHeld) {
3019
+ const side = Math.max(w, h);
3020
+ w = side;
3021
+ h = side;
3022
+ x = this.end.x >= this.start.x ? this.start.x : this.start.x - side;
3023
+ y = this.end.y >= this.start.y ? this.start.y : this.start.y - side;
3024
+ }
3025
+ return { position: { x, y }, size: { w, h } };
3026
+ }
3027
+ onKeyDown = (e) => {
3028
+ if (e.key === "Shift") this.shiftHeld = true;
3029
+ };
3030
+ onKeyUp = (e) => {
3031
+ if (e.key === "Shift") this.shiftHeld = false;
3032
+ };
3033
+ };
3034
+
2857
3035
  // src/index.ts
2858
- var VERSION = "0.3.1";
3036
+ var VERSION = "0.4.0";
2859
3037
  export {
2860
3038
  AddElementCommand,
2861
3039
  ArrowTool,
@@ -2877,6 +3055,7 @@ export {
2877
3055
  PencilTool,
2878
3056
  RemoveElementCommand,
2879
3057
  SelectTool,
3058
+ ShapeTool,
2880
3059
  TextTool,
2881
3060
  ToolManager,
2882
3061
  UpdateElementCommand,
@@ -2888,6 +3067,7 @@ export {
2888
3067
  createId,
2889
3068
  createImage,
2890
3069
  createNote,
3070
+ createShape,
2891
3071
  createStroke,
2892
3072
  createText,
2893
3073
  exportState,