@fieldnotes/core 0.3.1 → 0.4.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
@@ -43,6 +43,7 @@ interface NoteElement extends BaseElement {
43
43
  size: Size;
44
44
  text: string;
45
45
  backgroundColor: string;
46
+ textColor: string;
46
47
  }
47
48
  interface Binding {
48
49
  elementId: string;
@@ -74,7 +75,16 @@ interface TextElement extends BaseElement {
74
75
  color: string;
75
76
  textAlign: 'left' | 'center' | 'right';
76
77
  }
77
- type CanvasElement = StrokeElement | NoteElement | ArrowElement | ImageElement | HtmlElement | TextElement;
78
+ type ShapeKind = 'rectangle' | 'ellipse';
79
+ interface ShapeElement extends BaseElement {
80
+ type: 'shape';
81
+ shape: ShapeKind;
82
+ size: Size;
83
+ strokeColor: string;
84
+ strokeWidth: number;
85
+ fillColor: string;
86
+ }
87
+ type CanvasElement = StrokeElement | NoteElement | ArrowElement | ImageElement | HtmlElement | TextElement | ShapeElement;
78
88
  type ElementType = CanvasElement['type'];
79
89
 
80
90
  interface CanvasState {
@@ -209,7 +219,7 @@ interface Tool {
209
219
  onDeactivate?(ctx: ToolContext): void;
210
220
  renderOverlay?(ctx: CanvasRenderingContext2D): void;
211
221
  }
212
- type ToolName = 'hand' | 'select' | 'pencil' | 'eraser' | 'arrow' | 'note' | 'image' | 'text';
222
+ type ToolName = 'hand' | 'select' | 'pencil' | 'eraser' | 'arrow' | 'note' | 'image' | 'text' | 'shape';
213
223
 
214
224
  declare class ToolManager {
215
225
  private tools;
@@ -406,6 +416,9 @@ declare class ElementRenderer {
406
416
  private renderArrow;
407
417
  private renderArrowhead;
408
418
  private getVisualEndpoints;
419
+ private renderShape;
420
+ private fillShapePath;
421
+ private strokeShapePath;
409
422
  }
410
423
 
411
424
  declare class NoteEditor {
@@ -443,6 +456,7 @@ interface NoteInput extends BaseDefaults {
443
456
  size?: Size;
444
457
  text?: string;
445
458
  backgroundColor?: string;
459
+ textColor?: string;
446
460
  }
447
461
  interface ArrowInput extends BaseDefaults {
448
462
  from: Point;
@@ -475,6 +489,15 @@ declare function createNote(input: NoteInput): NoteElement;
475
489
  declare function createArrow(input: ArrowInput): ArrowElement;
476
490
  declare function createImage(input: ImageInput): ImageElement;
477
491
  declare function createHtmlElement(input: HtmlInput): HtmlElement;
492
+ interface ShapeInput extends BaseDefaults {
493
+ position: Point;
494
+ size: Size;
495
+ shape?: ShapeKind;
496
+ strokeColor?: string;
497
+ strokeWidth?: number;
498
+ fillColor?: string;
499
+ }
500
+ declare function createShape(input: ShapeInput): ShapeElement;
478
501
  declare function createText(input: TextInput): TextElement;
479
502
 
480
503
  interface Rect {
@@ -633,11 +656,13 @@ declare class ArrowTool implements Tool {
633
656
 
634
657
  interface NoteToolOptions {
635
658
  backgroundColor?: string;
659
+ textColor?: string;
636
660
  size?: Size;
637
661
  }
638
662
  declare class NoteTool implements Tool {
639
663
  readonly name = "note";
640
664
  private backgroundColor;
665
+ private textColor;
641
666
  private size;
642
667
  constructor(options?: NoteToolOptions);
643
668
  setOptions(options: NoteToolOptions): void;
@@ -679,6 +704,35 @@ declare class ImageTool implements Tool {
679
704
  onPointerUp(state: PointerState, ctx: ToolContext): void;
680
705
  }
681
706
 
682
- declare const VERSION = "0.3.1";
707
+ interface ShapeToolOptions {
708
+ shape?: ShapeKind;
709
+ strokeColor?: string;
710
+ strokeWidth?: number;
711
+ fillColor?: string;
712
+ }
713
+ declare class ShapeTool implements Tool {
714
+ readonly name = "shape";
715
+ private drawing;
716
+ private start;
717
+ private end;
718
+ private shiftHeld;
719
+ private shape;
720
+ private strokeColor;
721
+ private strokeWidth;
722
+ private fillColor;
723
+ constructor(options?: ShapeToolOptions);
724
+ setOptions(options: ShapeToolOptions): void;
725
+ onActivate(_ctx: ToolContext): void;
726
+ onDeactivate(_ctx: ToolContext): void;
727
+ onPointerDown(state: PointerState, ctx: ToolContext): void;
728
+ onPointerMove(state: PointerState, ctx: ToolContext): void;
729
+ onPointerUp(_state: PointerState, ctx: ToolContext): void;
730
+ renderOverlay(ctx: CanvasRenderingContext2D): void;
731
+ private computeRect;
732
+ private onKeyDown;
733
+ private onKeyUp;
734
+ }
735
+
736
+ declare const VERSION = "0.4.1";
683
737
 
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 };
738
+ 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
@@ -43,6 +43,7 @@ interface NoteElement extends BaseElement {
43
43
  size: Size;
44
44
  text: string;
45
45
  backgroundColor: string;
46
+ textColor: string;
46
47
  }
47
48
  interface Binding {
48
49
  elementId: string;
@@ -74,7 +75,16 @@ interface TextElement extends BaseElement {
74
75
  color: string;
75
76
  textAlign: 'left' | 'center' | 'right';
76
77
  }
77
- type CanvasElement = StrokeElement | NoteElement | ArrowElement | ImageElement | HtmlElement | TextElement;
78
+ type ShapeKind = 'rectangle' | 'ellipse';
79
+ interface ShapeElement extends BaseElement {
80
+ type: 'shape';
81
+ shape: ShapeKind;
82
+ size: Size;
83
+ strokeColor: string;
84
+ strokeWidth: number;
85
+ fillColor: string;
86
+ }
87
+ type CanvasElement = StrokeElement | NoteElement | ArrowElement | ImageElement | HtmlElement | TextElement | ShapeElement;
78
88
  type ElementType = CanvasElement['type'];
79
89
 
80
90
  interface CanvasState {
@@ -209,7 +219,7 @@ interface Tool {
209
219
  onDeactivate?(ctx: ToolContext): void;
210
220
  renderOverlay?(ctx: CanvasRenderingContext2D): void;
211
221
  }
212
- type ToolName = 'hand' | 'select' | 'pencil' | 'eraser' | 'arrow' | 'note' | 'image' | 'text';
222
+ type ToolName = 'hand' | 'select' | 'pencil' | 'eraser' | 'arrow' | 'note' | 'image' | 'text' | 'shape';
213
223
 
214
224
  declare class ToolManager {
215
225
  private tools;
@@ -406,6 +416,9 @@ declare class ElementRenderer {
406
416
  private renderArrow;
407
417
  private renderArrowhead;
408
418
  private getVisualEndpoints;
419
+ private renderShape;
420
+ private fillShapePath;
421
+ private strokeShapePath;
409
422
  }
410
423
 
411
424
  declare class NoteEditor {
@@ -443,6 +456,7 @@ interface NoteInput extends BaseDefaults {
443
456
  size?: Size;
444
457
  text?: string;
445
458
  backgroundColor?: string;
459
+ textColor?: string;
446
460
  }
447
461
  interface ArrowInput extends BaseDefaults {
448
462
  from: Point;
@@ -475,6 +489,15 @@ declare function createNote(input: NoteInput): NoteElement;
475
489
  declare function createArrow(input: ArrowInput): ArrowElement;
476
490
  declare function createImage(input: ImageInput): ImageElement;
477
491
  declare function createHtmlElement(input: HtmlInput): HtmlElement;
492
+ interface ShapeInput extends BaseDefaults {
493
+ position: Point;
494
+ size: Size;
495
+ shape?: ShapeKind;
496
+ strokeColor?: string;
497
+ strokeWidth?: number;
498
+ fillColor?: string;
499
+ }
500
+ declare function createShape(input: ShapeInput): ShapeElement;
478
501
  declare function createText(input: TextInput): TextElement;
479
502
 
480
503
  interface Rect {
@@ -633,11 +656,13 @@ declare class ArrowTool implements Tool {
633
656
 
634
657
  interface NoteToolOptions {
635
658
  backgroundColor?: string;
659
+ textColor?: string;
636
660
  size?: Size;
637
661
  }
638
662
  declare class NoteTool implements Tool {
639
663
  readonly name = "note";
640
664
  private backgroundColor;
665
+ private textColor;
641
666
  private size;
642
667
  constructor(options?: NoteToolOptions);
643
668
  setOptions(options: NoteToolOptions): void;
@@ -679,6 +704,35 @@ declare class ImageTool implements Tool {
679
704
  onPointerUp(state: PointerState, ctx: ToolContext): void;
680
705
  }
681
706
 
682
- declare const VERSION = "0.3.1";
707
+ interface ShapeToolOptions {
708
+ shape?: ShapeKind;
709
+ strokeColor?: string;
710
+ strokeWidth?: number;
711
+ fillColor?: string;
712
+ }
713
+ declare class ShapeTool implements Tool {
714
+ readonly name = "shape";
715
+ private drawing;
716
+ private start;
717
+ private end;
718
+ private shiftHeld;
719
+ private shape;
720
+ private strokeColor;
721
+ private strokeWidth;
722
+ private fillColor;
723
+ constructor(options?: ShapeToolOptions);
724
+ setOptions(options: ShapeToolOptions): void;
725
+ onActivate(_ctx: ToolContext): void;
726
+ onDeactivate(_ctx: ToolContext): void;
727
+ onPointerDown(state: PointerState, ctx: ToolContext): void;
728
+ onPointerMove(state: PointerState, ctx: ToolContext): void;
729
+ onPointerUp(_state: PointerState, ctx: ToolContext): void;
730
+ renderOverlay(ctx: CanvasRenderingContext2D): void;
731
+ private computeRect;
732
+ private onKeyDown;
733
+ private onKeyUp;
734
+ }
735
+
736
+ declare const VERSION = "0.4.1";
683
737
 
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 };
738
+ 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,12 @@ function migrateElement(obj) {
111
111
  }
112
112
  }
113
113
  }
114
+ if (obj["type"] === "shape" && typeof obj["shape"] !== "string") {
115
+ obj["shape"] = "rectangle";
116
+ }
117
+ if (obj["type"] === "note" && typeof obj["textColor"] !== "string") {
118
+ obj["textColor"] = "#000000";
119
+ }
114
120
  }
115
121
 
116
122
  // src/core/auto-save.ts
@@ -694,7 +700,7 @@ function isNearLine(point, a, b, threshold) {
694
700
  }
695
701
 
696
702
  // src/elements/arrow-binding.ts
697
- var BINDABLE_TYPES = /* @__PURE__ */ new Set(["note", "text", "image", "html"]);
703
+ var BINDABLE_TYPES = /* @__PURE__ */ new Set(["note", "text", "image", "html", "shape"]);
698
704
  function isBindable(element) {
699
705
  return BINDABLE_TYPES.has(element.type);
700
706
  }
@@ -914,6 +920,9 @@ var ElementRenderer = class {
914
920
  case "arrow":
915
921
  this.renderArrow(ctx, element);
916
922
  break;
923
+ case "shape":
924
+ this.renderShape(ctx, element);
925
+ break;
917
926
  }
918
927
  }
919
928
  renderStroke(ctx, stroke) {
@@ -1006,6 +1015,49 @@ var ElementRenderer = class {
1006
1015
  }
1007
1016
  return { visualFrom, visualTo };
1008
1017
  }
1018
+ renderShape(ctx, shape) {
1019
+ ctx.save();
1020
+ if (shape.fillColor !== "none") {
1021
+ ctx.fillStyle = shape.fillColor;
1022
+ this.fillShapePath(ctx, shape);
1023
+ }
1024
+ if (shape.strokeWidth > 0) {
1025
+ ctx.strokeStyle = shape.strokeColor;
1026
+ ctx.lineWidth = shape.strokeWidth;
1027
+ this.strokeShapePath(ctx, shape);
1028
+ }
1029
+ ctx.restore();
1030
+ }
1031
+ fillShapePath(ctx, shape) {
1032
+ switch (shape.shape) {
1033
+ case "rectangle":
1034
+ ctx.fillRect(shape.position.x, shape.position.y, shape.size.w, shape.size.h);
1035
+ break;
1036
+ case "ellipse": {
1037
+ const cx = shape.position.x + shape.size.w / 2;
1038
+ const cy = shape.position.y + shape.size.h / 2;
1039
+ ctx.beginPath();
1040
+ ctx.ellipse(cx, cy, shape.size.w / 2, shape.size.h / 2, 0, 0, Math.PI * 2);
1041
+ ctx.fill();
1042
+ break;
1043
+ }
1044
+ }
1045
+ }
1046
+ strokeShapePath(ctx, shape) {
1047
+ switch (shape.shape) {
1048
+ case "rectangle":
1049
+ ctx.strokeRect(shape.position.x, shape.position.y, shape.size.w, shape.size.h);
1050
+ break;
1051
+ case "ellipse": {
1052
+ const cx = shape.position.x + shape.size.w / 2;
1053
+ const cy = shape.position.y + shape.size.h / 2;
1054
+ ctx.beginPath();
1055
+ ctx.ellipse(cx, cy, shape.size.w / 2, shape.size.h / 2, 0, 0, Math.PI * 2);
1056
+ ctx.stroke();
1057
+ break;
1058
+ }
1059
+ }
1060
+ }
1009
1061
  };
1010
1062
 
1011
1063
  // src/elements/note-editor.ts
@@ -1372,7 +1424,8 @@ function createNote(input) {
1372
1424
  locked: input.locked ?? false,
1373
1425
  size: input.size ?? { w: 200, h: 100 },
1374
1426
  text: input.text ?? "",
1375
- backgroundColor: input.backgroundColor ?? "#ffeb3b"
1427
+ backgroundColor: input.backgroundColor ?? "#ffeb3b",
1428
+ textColor: input.textColor ?? "#000000"
1376
1429
  };
1377
1430
  }
1378
1431
  function createArrow(input) {
@@ -1413,6 +1466,20 @@ function createHtmlElement(input) {
1413
1466
  size: input.size
1414
1467
  };
1415
1468
  }
1469
+ function createShape(input) {
1470
+ return {
1471
+ id: createId("shape"),
1472
+ type: "shape",
1473
+ position: input.position,
1474
+ zIndex: input.zIndex ?? 0,
1475
+ locked: input.locked ?? false,
1476
+ shape: input.shape ?? "rectangle",
1477
+ size: input.size,
1478
+ strokeColor: input.strokeColor ?? "#000000",
1479
+ strokeWidth: input.strokeWidth ?? 2,
1480
+ fillColor: input.fillColor ?? "none"
1481
+ };
1482
+ }
1416
1483
  function createText(input) {
1417
1484
  return {
1418
1485
  id: createId("text"),
@@ -1757,6 +1824,7 @@ var Viewport = class {
1757
1824
  node.dataset["initialized"] = "true";
1758
1825
  Object.assign(node.style, {
1759
1826
  backgroundColor: element.backgroundColor,
1827
+ color: element.textColor,
1760
1828
  padding: "8px",
1761
1829
  borderRadius: "4px",
1762
1830
  boxShadow: "0 2px 8px rgba(0,0,0,0.15)",
@@ -1778,6 +1846,7 @@ var Viewport = class {
1778
1846
  node.textContent = element.text || "";
1779
1847
  }
1780
1848
  node.style.backgroundColor = element.backgroundColor;
1849
+ node.style.color = element.textColor;
1781
1850
  }
1782
1851
  }
1783
1852
  if (element.type === "image") {
@@ -2756,13 +2825,16 @@ var ArrowTool = class {
2756
2825
  var NoteTool = class {
2757
2826
  name = "note";
2758
2827
  backgroundColor;
2828
+ textColor;
2759
2829
  size;
2760
2830
  constructor(options = {}) {
2761
2831
  this.backgroundColor = options.backgroundColor ?? "#ffeb3b";
2832
+ this.textColor = options.textColor ?? "#000000";
2762
2833
  this.size = options.size ?? { w: 200, h: 100 };
2763
2834
  }
2764
2835
  setOptions(options) {
2765
2836
  if (options.backgroundColor !== void 0) this.backgroundColor = options.backgroundColor;
2837
+ if (options.textColor !== void 0) this.textColor = options.textColor;
2766
2838
  if (options.size !== void 0) this.size = options.size;
2767
2839
  }
2768
2840
  onPointerDown(_state, _ctx) {
@@ -2774,7 +2846,8 @@ var NoteTool = class {
2774
2846
  const note = createNote({
2775
2847
  position: world,
2776
2848
  size: { ...this.size },
2777
- backgroundColor: this.backgroundColor
2849
+ backgroundColor: this.backgroundColor,
2850
+ textColor: this.textColor
2778
2851
  });
2779
2852
  ctx.store.add(note);
2780
2853
  ctx.requestRender();
@@ -2854,8 +2927,123 @@ var ImageTool = class {
2854
2927
  }
2855
2928
  };
2856
2929
 
2930
+ // src/tools/shape-tool.ts
2931
+ var ShapeTool = class {
2932
+ name = "shape";
2933
+ drawing = false;
2934
+ start = { x: 0, y: 0 };
2935
+ end = { x: 0, y: 0 };
2936
+ shiftHeld = false;
2937
+ shape;
2938
+ strokeColor;
2939
+ strokeWidth;
2940
+ fillColor;
2941
+ constructor(options = {}) {
2942
+ this.shape = options.shape ?? "rectangle";
2943
+ this.strokeColor = options.strokeColor ?? "#000000";
2944
+ this.strokeWidth = options.strokeWidth ?? 2;
2945
+ this.fillColor = options.fillColor ?? "none";
2946
+ }
2947
+ setOptions(options) {
2948
+ if (options.shape !== void 0) this.shape = options.shape;
2949
+ if (options.strokeColor !== void 0) this.strokeColor = options.strokeColor;
2950
+ if (options.strokeWidth !== void 0) this.strokeWidth = options.strokeWidth;
2951
+ if (options.fillColor !== void 0) this.fillColor = options.fillColor;
2952
+ }
2953
+ onActivate(_ctx) {
2954
+ if (typeof window !== "undefined") {
2955
+ window.addEventListener("keydown", this.onKeyDown);
2956
+ window.addEventListener("keyup", this.onKeyUp);
2957
+ }
2958
+ }
2959
+ onDeactivate(_ctx) {
2960
+ this.shiftHeld = false;
2961
+ if (typeof window !== "undefined") {
2962
+ window.removeEventListener("keydown", this.onKeyDown);
2963
+ window.removeEventListener("keyup", this.onKeyUp);
2964
+ }
2965
+ }
2966
+ onPointerDown(state, ctx) {
2967
+ this.drawing = true;
2968
+ this.start = ctx.camera.screenToWorld({ x: state.x, y: state.y });
2969
+ this.end = { ...this.start };
2970
+ }
2971
+ onPointerMove(state, ctx) {
2972
+ if (!this.drawing) return;
2973
+ this.end = ctx.camera.screenToWorld({ x: state.x, y: state.y });
2974
+ ctx.requestRender();
2975
+ }
2976
+ onPointerUp(_state, ctx) {
2977
+ if (!this.drawing) return;
2978
+ this.drawing = false;
2979
+ const { position, size } = this.computeRect();
2980
+ if (size.w === 0 || size.h === 0) return;
2981
+ const shape = createShape({
2982
+ position,
2983
+ size,
2984
+ shape: this.shape,
2985
+ strokeColor: this.strokeColor,
2986
+ strokeWidth: this.strokeWidth,
2987
+ fillColor: this.fillColor
2988
+ });
2989
+ ctx.store.add(shape);
2990
+ ctx.requestRender();
2991
+ ctx.switchTool?.("select");
2992
+ }
2993
+ renderOverlay(ctx) {
2994
+ if (!this.drawing) return;
2995
+ const { position, size } = this.computeRect();
2996
+ if (size.w === 0 && size.h === 0) return;
2997
+ ctx.save();
2998
+ ctx.globalAlpha = 0.5;
2999
+ ctx.strokeStyle = this.strokeColor;
3000
+ ctx.lineWidth = this.strokeWidth;
3001
+ if (this.fillColor !== "none") {
3002
+ ctx.fillStyle = this.fillColor;
3003
+ }
3004
+ switch (this.shape) {
3005
+ case "rectangle":
3006
+ if (this.fillColor !== "none") {
3007
+ ctx.fillRect(position.x, position.y, size.w, size.h);
3008
+ }
3009
+ ctx.strokeRect(position.x, position.y, size.w, size.h);
3010
+ break;
3011
+ case "ellipse": {
3012
+ const cx = position.x + size.w / 2;
3013
+ const cy = position.y + size.h / 2;
3014
+ ctx.beginPath();
3015
+ ctx.ellipse(cx, cy, size.w / 2, size.h / 2, 0, 0, Math.PI * 2);
3016
+ if (this.fillColor !== "none") ctx.fill();
3017
+ ctx.stroke();
3018
+ break;
3019
+ }
3020
+ }
3021
+ ctx.restore();
3022
+ }
3023
+ computeRect() {
3024
+ let x = Math.min(this.start.x, this.end.x);
3025
+ let y = Math.min(this.start.y, this.end.y);
3026
+ let w = Math.abs(this.end.x - this.start.x);
3027
+ let h = Math.abs(this.end.y - this.start.y);
3028
+ if (this.shiftHeld) {
3029
+ const side = Math.max(w, h);
3030
+ w = side;
3031
+ h = side;
3032
+ x = this.end.x >= this.start.x ? this.start.x : this.start.x - side;
3033
+ y = this.end.y >= this.start.y ? this.start.y : this.start.y - side;
3034
+ }
3035
+ return { position: { x, y }, size: { w, h } };
3036
+ }
3037
+ onKeyDown = (e) => {
3038
+ if (e.key === "Shift") this.shiftHeld = true;
3039
+ };
3040
+ onKeyUp = (e) => {
3041
+ if (e.key === "Shift") this.shiftHeld = false;
3042
+ };
3043
+ };
3044
+
2857
3045
  // src/index.ts
2858
- var VERSION = "0.3.1";
3046
+ var VERSION = "0.4.1";
2859
3047
  export {
2860
3048
  AddElementCommand,
2861
3049
  ArrowTool,
@@ -2877,6 +3065,7 @@ export {
2877
3065
  PencilTool,
2878
3066
  RemoveElementCommand,
2879
3067
  SelectTool,
3068
+ ShapeTool,
2880
3069
  TextTool,
2881
3070
  ToolManager,
2882
3071
  UpdateElementCommand,
@@ -2888,6 +3077,7 @@ export {
2888
3077
  createId,
2889
3078
  createImage,
2890
3079
  createNote,
3080
+ createShape,
2891
3081
  createStroke,
2892
3082
  createText,
2893
3083
  exportState,