@bwp-web/canvas 0.6.0 → 0.6.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.
@@ -1 +1 @@
1
- {"version":3,"file":"cursorSnapping.d.ts","sourceRoot":"","sources":["../../src/alignment/cursorSnapping.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,YAAY,EAAE,KAAK,YAAY,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAI1E,MAAM,WAAW,gBAAgB;IAC/B,2DAA2D;IAC3D,KAAK,EAAE,KAAK,CAAC;IACb,8CAA8C;IAC9C,OAAO,EAAE,OAAO,CAAC;IACjB,4CAA4C;IAC5C,KAAK,EAAE,OAAO,CAAC;IACf,4CAA4C;IAC5C,KAAK,EAAE,OAAO,CAAC;IACf,iFAAiF;IACjF,aAAa,CAAC,EAAE,KAAK,EAAE,CAAC;IACxB,iFAAiF;IACjF,aAAa,CAAC,EAAE,KAAK,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,iBAAiB;IAChC;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,OAAO,CAAC,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC;IAC5B,uEAAuE;IACvE,YAAY,CAAC,EAAE,KAAK,EAAE,CAAC;IACvB;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,KAAK,EACf,OAAO,CAAC,EAAE,iBAAiB,GAC1B,gBAAgB,CA2DlB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,YAAY,EACpB,UAAU,EAAE,gBAAgB,EAC5B,KAAK,CAAC,EAAE,cAAc,GACrB,IAAI,CAwCN;AAeD,kEAAkE;AAClE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAEhE"}
1
+ {"version":3,"file":"cursorSnapping.d.ts","sourceRoot":"","sources":["../../src/alignment/cursorSnapping.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,YAAY,EAAE,KAAK,YAAY,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAI1E,MAAM,WAAW,gBAAgB;IAC/B,2DAA2D;IAC3D,KAAK,EAAE,KAAK,CAAC;IACb,8CAA8C;IAC9C,OAAO,EAAE,OAAO,CAAC;IACjB,4CAA4C;IAC5C,KAAK,EAAE,OAAO,CAAC;IACf,4CAA4C;IAC5C,KAAK,EAAE,OAAO,CAAC;IACf,iFAAiF;IACjF,aAAa,CAAC,EAAE,KAAK,EAAE,CAAC;IACxB,iFAAiF;IACjF,aAAa,CAAC,EAAE,KAAK,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,iBAAiB;IAChC;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,OAAO,CAAC,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC;IAC5B,uEAAuE;IACvE,YAAY,CAAC,EAAE,KAAK,EAAE,CAAC;IACvB;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,KAAK,EACf,OAAO,CAAC,EAAE,iBAAiB,GAC1B,gBAAgB,CA4DlB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,YAAY,EACpB,UAAU,EAAE,gBAAgB,EAC5B,KAAK,CAAC,EAAE,cAAc,GACrB,IAAI,CAwCN;AAeD,kEAAkE;AAClE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAEhE"}
@@ -1 +1 @@
1
- {"version":3,"file":"objectAlignment.d.ts","sourceRoot":"","sources":["../../src/alignment/objectAlignment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAkC,MAAM,QAAQ,CAAC;AAsBrE,MAAM,WAAW,sBAAsB;IACrC,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uCAAuC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yDAAyD;IACzD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yBAAyB;IACzB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAkOD;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,sBAAsB,GAC/B,MAAM,IAAI,CAGZ"}
1
+ {"version":3,"file":"objectAlignment.d.ts","sourceRoot":"","sources":["../../src/alignment/objectAlignment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAkC,MAAM,QAAQ,CAAC;AAyGrE,MAAM,WAAW,sBAAsB;IACrC,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uCAAuC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yDAAyD;IACzD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yBAAyB;IACzB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAmOD;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,sBAAsB,GAC/B,MAAM,IAAI,CAGZ"}
@@ -1 +1 @@
1
- {"version":3,"file":"background.d.ts","sourceRoot":"","sources":["../src/background.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,YAAY,EAAE,WAAW,EAAW,MAAM,QAAQ,CAAC;AAWtE;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,GAAG,IAAI,CAIpE;AAID,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,YAAY,EACpB,OAAO,CAAC,EAAE,kBAAkB,GAC3B,IAAI,CAiCN;AAID;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,MAAM,GACZ,IAAI,CA6BN;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAUlE;AAID;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,OAAO,GAChB,IAAI,CAgBN;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAInE;AAID,MAAM,WAAW,YAAY;IAC3B,+EAA+E;IAC/E,GAAG,EAAE,MAAM,CAAC;IACZ,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,oCAAoC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,YAAY,CAAC,CAkDvB;AAID,MAAM,WAAW,yBAA0B,SAAQ,kBAAkB;IACnE,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,YAAY,EACpB,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,yBAAyB,GAClC,OAAO,CAAC,WAAW,CAAC,CAqBtB"}
1
+ {"version":3,"file":"background.d.ts","sourceRoot":"","sources":["../src/background.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,YAAY,EAAE,WAAW,EAAW,MAAM,QAAQ,CAAC;AAWtE;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,GAAG,IAAI,CAIpE;AAID,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,YAAY,EACpB,OAAO,CAAC,EAAE,kBAAkB,GAC3B,IAAI,CAiCN;AAID;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,MAAM,GACZ,IAAI,CA6BN;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAUlE;AAID;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,OAAO,GAChB,IAAI,CAgBN;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAInE;AAID,MAAM,WAAW,YAAY;IAC3B,+EAA+E;IAC/E,GAAG,EAAE,MAAM,CAAC;IACZ,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,oCAAoC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,YAAY,CAAC,CAkDvB;AAID,MAAM,WAAW,yBAA0B,SAAQ,kBAAkB;IACnE,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,YAAY,EACpB,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,yBAAyB,GAClC,OAAO,CAAC,WAAW,CAAC,CA4BtB"}
@@ -14,6 +14,15 @@ export declare const BASE_CANVAS_SIZE = 1000;
14
14
  export declare const DEFAULT_SNAP_MARGIN = 6;
15
15
  /** Default angle snap interval in degrees. */
16
16
  export declare const DEFAULT_ANGLE_SNAP_INTERVAL = 15;
17
+ /**
18
+ * Compute the effective snap margin in scene-space units.
19
+ *
20
+ * When `scaleWithCanvasSize` is true (default), the margin grows
21
+ * proportionally with `max(canvasWidth, canvasHeight) / BASE_CANVAS_SIZE`
22
+ * so snapping feels consistent on large canvases (e.g. floor plans).
23
+ * The result is also divided by the current zoom level.
24
+ */
25
+ export declare function computeSnapMargin(canvasWidth: number, canvasHeight: number, zoom: number, baseMargin?: number, scaleWithCanvasSize?: boolean): number;
17
26
  /**
18
27
  * Minimum drag distance (in scene units) before a drag is treated as intentional.
19
28
  * Prevents accidental micro-drags from creating objects.
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAEA,0BAA0B;AAC1B,eAAO,MAAM,gBAAgB,MAAM,CAAC;AACpC,0BAA0B;AAC1B,eAAO,MAAM,gBAAgB,KAAK,CAAC;AACnC,0FAA0F;AAC1F,eAAO,MAAM,mBAAmB,QAAQ,CAAC;AACzC,gFAAgF;AAChF,eAAO,MAAM,iBAAiB,MAAM,CAAC;AACrC,2DAA2D;AAC3D,eAAO,MAAM,wBAAwB,OAAO,CAAC;AAI7C,0EAA0E;AAC1E,eAAO,MAAM,gBAAgB,OAAO,CAAC;AACrC,yFAAyF;AACzF,eAAO,MAAM,mBAAmB,IAAI,CAAC;AACrC,8CAA8C;AAC9C,eAAO,MAAM,2BAA2B,KAAK,CAAC;AAI9C;;;GAGG;AACH,eAAO,MAAM,aAAa,IAAI,CAAC;AAE/B;;GAEG;AACH,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAI1C,oDAAoD;AACpD,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAC3C,8EAA8E;AAC9E,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAI1C,eAAO,MAAM,4BAA4B,IAAI,CAAC;AAC9C,eAAO,MAAM,0BAA0B,YAAY,CAAC;AACpD,eAAO,MAAM,4BAA4B,YAAY,CAAC;AACtD,eAAO,MAAM,kCAAkC,IAAI,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAEA,0BAA0B;AAC1B,eAAO,MAAM,gBAAgB,MAAM,CAAC;AACpC,0BAA0B;AAC1B,eAAO,MAAM,gBAAgB,KAAK,CAAC;AACnC,0FAA0F;AAC1F,eAAO,MAAM,mBAAmB,QAAQ,CAAC;AACzC,gFAAgF;AAChF,eAAO,MAAM,iBAAiB,MAAM,CAAC;AACrC,2DAA2D;AAC3D,eAAO,MAAM,wBAAwB,OAAO,CAAC;AAI7C,0EAA0E;AAC1E,eAAO,MAAM,gBAAgB,OAAO,CAAC;AACrC,yFAAyF;AACzF,eAAO,MAAM,mBAAmB,IAAI,CAAC;AACrC,8CAA8C;AAC9C,eAAO,MAAM,2BAA2B,KAAK,CAAC;AAE9C;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,EACZ,UAAU,GAAE,MAA4B,EACxC,mBAAmB,GAAE,OAAc,GAClC,MAAM,CAKR;AAID;;;GAGG;AACH,eAAO,MAAM,aAAa,IAAI,CAAC;AAE/B;;GAEG;AACH,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAI1C,oDAAoD;AACpD,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAC3C,8EAA8E;AAC9E,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAI1C,eAAO,MAAM,4BAA4B,IAAI,CAAC;AAC9C,eAAO,MAAM,0BAA0B,YAAY,CAAC;AACpD,eAAO,MAAM,4BAA4B,YAAY,CAAC;AACtD,eAAO,MAAM,kCAAkC,IAAI,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"useEditCanvas.d.ts","sourceRoot":"","sources":["../../src/hooks/useEditCanvas.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,IAAI,YAAY,EAAE,KAAK,YAAY,EAAW,MAAM,QAAQ,CAAC;AAC5E,OAAO,EAEL,KAAK,iBAAiB,EAEtB,KAAK,YAAY,EAClB,MAAM,aAAa,CAAC;AAMrB,OAAO,EAEL,KAAK,sBAAsB,EAE3B,KAAK,mBAAmB,EACzB,MAAM,cAAc,CAAC;AACtB,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,iBAAiB,CAAC;AAOzB,OAAO,EAGL,KAAK,kBAAkB,EAExB,MAAM,eAAe,CAAC;AACvB,OAAO,EAEL,KAAK,cAAc,EAEpB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1C,MAAM,WAAW,oBAAoB;IACnC,kGAAkG;IAClG,UAAU,CAAC,EAAE,OAAO,GAAG,iBAAiB,CAAC;IACzC,mIAAmI;IACnI,SAAS,CAAC,EAAE,OAAO,GAAG,sBAAsB,CAAC;IAC7C;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,GAAG,mBAAmB,CAAC;IAC7C;;;;;OAKG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,GAAG,iBAAiB,CAAC;IACzC;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,qEAAqE;IACrE,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,GAAG,kBAAkB,CAAC;IAChD;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAC9B;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,GAAG,cAAc,CAAC;CACpC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,aAAa,CAAC,OAAO,CAAC,EAAE,oBAAoB;IAqRxD,8CAA8C;sBAzMrC,YAAY;IA2MrB,oDAAoD;;IAEpD,qCAAqC;;IAErC,6CAA6C;;IAE7C,yBAAyB;;QAEvB,wCAAwC;;QAExC,wDAAwD;wBAhDjB,YAAY;QAkDnD,wFAAwF;;QAExF,2DAA2D;;QAE3D,0DAA0D;;QAE1D,uDAAuD;;QAEvD,6DAA6D;;;IAG/D,+DAA+D;;IAE/D;;;;;;;;;;;;;;OAcG;qBA3R+B,SAAS,GAAG,IAAI;IA6RlD;;;;;;;OAOG;yBA7ES,MAAM,WAAW;QAAE,gBAAgB,CAAC,EAAE,OAAO,CAAA;KAAE;IA+E3D,8GAA8G;;IAE9G,4DAA4D;;IAE5D,sDAAsD;;IAQtD,iEAAiE;;IAQjE,mFAAmF;;IAEnF,kFAAkF;;EAGrF"}
1
+ {"version":3,"file":"useEditCanvas.d.ts","sourceRoot":"","sources":["../../src/hooks/useEditCanvas.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,IAAI,YAAY,EAAE,KAAK,YAAY,EAAW,MAAM,QAAQ,CAAC;AAC5E,OAAO,EAEL,KAAK,iBAAiB,EAEtB,KAAK,YAAY,EAClB,MAAM,aAAa,CAAC;AAMrB,OAAO,EAEL,KAAK,sBAAsB,EAE3B,KAAK,mBAAmB,EACzB,MAAM,cAAc,CAAC;AACtB,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,iBAAiB,CAAC;AAOzB,OAAO,EAGL,KAAK,kBAAkB,EAExB,MAAM,eAAe,CAAC;AACvB,OAAO,EAEL,KAAK,cAAc,EAEpB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1C,MAAM,WAAW,oBAAoB;IACnC,kGAAkG;IAClG,UAAU,CAAC,EAAE,OAAO,GAAG,iBAAiB,CAAC;IACzC,mIAAmI;IACnI,SAAS,CAAC,EAAE,OAAO,GAAG,sBAAsB,CAAC;IAC7C;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,GAAG,mBAAmB,CAAC;IAC7C;;;;;OAKG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,GAAG,iBAAiB,CAAC;IACzC;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,qEAAqE;IACrE,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,GAAG,kBAAkB,CAAC;IAChD;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAC9B;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,GAAG,cAAc,CAAC;CACpC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,aAAa,CAAC,OAAO,CAAC,EAAE,oBAAoB;IA+QxD,8CAA8C;sBAnMrC,YAAY;IAqMrB,oDAAoD;;IAEpD,qCAAqC;;IAErC,6CAA6C;;IAE7C,yBAAyB;;QAEvB,wCAAwC;;QAExC,wDAAwD;wBAhDjB,YAAY;QAkDnD,wFAAwF;;QAExF,2DAA2D;;QAE3D,0DAA0D;;QAE1D,uDAAuD;;QAEvD,6DAA6D;;;IAG/D,+DAA+D;;IAE/D;;;;;;;;;;;;;;OAcG;qBArR+B,SAAS,GAAG,IAAI;IAuRlD;;;;;;;OAOG;yBA7ES,MAAM,WAAW;QAAE,gBAAgB,CAAC,EAAE,OAAO,CAAA;KAAE;IA+E3D,8GAA8G;;IAE9G,4DAA4D;;IAE5D,sDAAsD;;IAQtD,iEAAiE;;IAQjE,mFAAmF;;IAEnF,kFAAkF;;EAGrF"}
package/dist/index.cjs CHANGED
@@ -183,6 +183,10 @@ var DEFAULT_VIEWPORT_PADDING = 0.05;
183
183
  var BASE_CANVAS_SIZE = 1e3;
184
184
  var DEFAULT_SNAP_MARGIN = 6;
185
185
  var DEFAULT_ANGLE_SNAP_INTERVAL = 15;
186
+ function computeSnapMargin(canvasWidth, canvasHeight, zoom, baseMargin = DEFAULT_SNAP_MARGIN, scaleWithCanvasSize = true) {
187
+ const sizeScale = scaleWithCanvasSize ? Math.max(canvasWidth || 800, canvasHeight || 600) / BASE_CANVAS_SIZE : 1;
188
+ return baseMargin * sizeScale / zoom;
189
+ }
186
190
  var MIN_DRAG_SIZE = 3;
187
191
  var POLYGON_CLOSE_THRESHOLD = 10;
188
192
  var DEFAULT_IMAGE_MAX_SIZE = 4096;
@@ -390,23 +394,23 @@ function enablePanAndZoom(canvas, options) {
390
394
  const targetX = canvasCenterX - objectCenter.x * zoom;
391
395
  const targetY = canvasCenterY - objectCenter.y * zoom;
392
396
  if (!panOpts?.animate) {
393
- const vt2 = canvas.viewportTransform;
394
- if (!vt2) return;
397
+ const viewportTransform2 = canvas.viewportTransform;
398
+ if (!viewportTransform2) return;
395
399
  canvas.setViewportTransform([
396
- vt2[0],
397
- vt2[1],
398
- vt2[2],
399
- vt2[3],
400
+ viewportTransform2[0],
401
+ viewportTransform2[1],
402
+ viewportTransform2[2],
403
+ viewportTransform2[3],
400
404
  targetX,
401
405
  targetY
402
406
  ]);
403
407
  return;
404
408
  }
405
409
  const duration = panOpts.duration ?? 300;
406
- const vt = canvas.viewportTransform;
407
- if (!vt) return;
408
- const startX = vt[4];
409
- const startY = vt[5];
410
+ const viewportTransform = canvas.viewportTransform;
411
+ if (!viewportTransform) return;
412
+ const startX = viewportTransform[4];
413
+ const startY = viewportTransform[5];
410
414
  const startTime = performance.now();
411
415
  function step(now) {
412
416
  const elapsed = now - startTime;
@@ -414,13 +418,13 @@ function enablePanAndZoom(canvas, options) {
414
418
  const eased = 1 - Math.pow(1 - t, 3);
415
419
  const currentX = startX + (targetX - startX) * eased;
416
420
  const currentY = startY + (targetY - startY) * eased;
417
- const currentVt = canvas.viewportTransform;
418
- if (!currentVt) return;
421
+ const currentTransform = canvas.viewportTransform;
422
+ if (!currentTransform) return;
419
423
  canvas.setViewportTransform([
420
- currentVt[0],
421
- currentVt[1],
422
- currentVt[2],
423
- currentVt[3],
424
+ currentTransform[0],
425
+ currentTransform[1],
426
+ currentTransform[2],
427
+ currentTransform[3],
424
428
  currentX,
425
429
  currentY
426
430
  ]);
@@ -607,6 +611,7 @@ async function setBackgroundImage(canvas, url, options) {
607
611
  imageUrl = result.url;
608
612
  }
609
613
  const img = await import_fabric4.FabricImage.fromURL(imageUrl, { crossOrigin: "anonymous" });
614
+ img.set({ left: img.width / 2, top: img.height / 2 });
610
615
  canvas.backgroundImage = img;
611
616
  if (prevContrast !== void 0 && prevContrast !== 1) {
612
617
  setBackgroundContrast(canvas, prevContrast);
@@ -800,63 +805,6 @@ registerSnapPointExtractor(
800
805
  // src/alignment/objectAlignment.ts
801
806
  var import_fabric7 = require("fabric");
802
807
 
803
- // src/alignment/objectAlignmentRendering.ts
804
- function drawAlignmentLine(config, origin, target) {
805
- const ctx = config.canvas.getTopContext();
806
- const vt = config.canvas.viewportTransform;
807
- const zoom = config.canvas.getZoom();
808
- ctx.save();
809
- ctx.transform(...vt);
810
- ctx.lineWidth = config.width / zoom;
811
- if (config.lineDash) ctx.setLineDash(config.lineDash);
812
- ctx.strokeStyle = config.color;
813
- ctx.beginPath();
814
- ctx.moveTo(origin.x, origin.y);
815
- ctx.lineTo(target.x, target.y);
816
- ctx.stroke();
817
- if (config.lineDash) ctx.setLineDash([]);
818
- drawXMarker(ctx, origin, config.xSize / zoom);
819
- drawXMarker(ctx, target, config.xSize / zoom);
820
- ctx.restore();
821
- }
822
- function drawXMarker(ctx, point, size) {
823
- ctx.save();
824
- ctx.translate(point.x, point.y);
825
- ctx.beginPath();
826
- ctx.moveTo(-size, -size);
827
- ctx.lineTo(size, size);
828
- ctx.moveTo(size, -size);
829
- ctx.lineTo(-size, size);
830
- ctx.stroke();
831
- ctx.restore();
832
- }
833
- function drawMarkerList(config, lines) {
834
- const ctx = config.canvas.getTopContext();
835
- const vt = config.canvas.viewportTransform;
836
- const zoom = config.canvas.getZoom();
837
- const markerSize = config.xSize / zoom;
838
- ctx.save();
839
- ctx.transform(...vt);
840
- ctx.lineWidth = config.width / zoom;
841
- ctx.strokeStyle = config.color;
842
- for (const item of lines) drawXMarker(ctx, item.target, markerSize);
843
- ctx.restore();
844
- }
845
- function drawVerticalAlignmentLines(config, lines) {
846
- for (const v of lines) {
847
- const { origin, target } = JSON.parse(v);
848
- const from = { x: target.x, y: origin.y };
849
- drawAlignmentLine(config, from, target);
850
- }
851
- }
852
- function drawHorizontalAlignmentLines(config, lines) {
853
- for (const h of lines) {
854
- const { origin, target } = JSON.parse(h);
855
- const from = { x: origin.x, y: target.y };
856
- drawAlignmentLine(config, from, target);
857
- }
858
- }
859
-
860
808
  // src/alignment/objectAlignmentMath.ts
861
809
  var OPPOSITE_ORIGIN_MAP = {
862
810
  tl: ["right", "bottom"],
@@ -980,6 +928,61 @@ function collectHorizontalSnapOffset(props) {
980
928
  }
981
929
 
982
930
  // src/alignment/objectAlignment.ts
931
+ function drawXMarker(ctx, point, size) {
932
+ ctx.save();
933
+ ctx.translate(point.x, point.y);
934
+ ctx.beginPath();
935
+ ctx.moveTo(-size, -size);
936
+ ctx.lineTo(size, size);
937
+ ctx.moveTo(size, -size);
938
+ ctx.lineTo(-size, size);
939
+ ctx.stroke();
940
+ ctx.restore();
941
+ }
942
+ function drawAlignmentLine(config, origin, target) {
943
+ const ctx = config.canvas.getTopContext();
944
+ const vt = config.canvas.viewportTransform;
945
+ const zoom = config.canvas.getZoom();
946
+ ctx.save();
947
+ ctx.transform(...vt);
948
+ ctx.lineWidth = config.width / zoom;
949
+ if (config.lineDash) ctx.setLineDash(config.lineDash);
950
+ ctx.strokeStyle = config.color;
951
+ ctx.beginPath();
952
+ ctx.moveTo(origin.x, origin.y);
953
+ ctx.lineTo(target.x, target.y);
954
+ ctx.stroke();
955
+ if (config.lineDash) ctx.setLineDash([]);
956
+ drawXMarker(ctx, origin, config.xSize / zoom);
957
+ drawXMarker(ctx, target, config.xSize / zoom);
958
+ ctx.restore();
959
+ }
960
+ function drawMarkerList(config, lines) {
961
+ const ctx = config.canvas.getTopContext();
962
+ const vt = config.canvas.viewportTransform;
963
+ const zoom = config.canvas.getZoom();
964
+ const markerSize = config.xSize / zoom;
965
+ ctx.save();
966
+ ctx.transform(...vt);
967
+ ctx.lineWidth = config.width / zoom;
968
+ ctx.strokeStyle = config.color;
969
+ for (const item of lines) drawXMarker(ctx, item.target, markerSize);
970
+ ctx.restore();
971
+ }
972
+ function drawVerticalAlignmentLines(config, lines) {
973
+ for (const v of lines) {
974
+ const { origin, target } = JSON.parse(v);
975
+ const from = { x: target.x, y: origin.y };
976
+ drawAlignmentLine(config, from, target);
977
+ }
978
+ }
979
+ function drawHorizontalAlignmentLines(config, lines) {
980
+ for (const h of lines) {
981
+ const { origin, target } = JSON.parse(h);
982
+ const from = { x: origin.x, y: target.y };
983
+ drawAlignmentLine(config, from, target);
984
+ }
985
+ }
983
986
  function adjustCornerForFlip(corner, target) {
984
987
  let adjusted = corner;
985
988
  if (target.flipX) {
@@ -1034,9 +1037,13 @@ var ObjectAlignmentGuides = class {
1034
1037
  }
1035
1038
  // --- Margin calculation ---
1036
1039
  computeMargin() {
1037
- const zoom = this.canvas.getZoom();
1038
- const sizeScale = this.scaleWithCanvasSize ? Math.max(this.canvas.width ?? 800, this.canvas.height ?? 600) / BASE_CANVAS_SIZE : 1;
1039
- return this.margin * sizeScale / zoom;
1040
+ return computeSnapMargin(
1041
+ this.canvas.width ?? 800,
1042
+ this.canvas.height ?? 600,
1043
+ this.canvas.getZoom(),
1044
+ this.margin,
1045
+ this.scaleWithCanvasSize
1046
+ );
1040
1047
  }
1041
1048
  // --- Snap point caching ---
1042
1049
  getCachedSnapPoints(object) {
@@ -1172,10 +1179,13 @@ function enableRotationSnap(canvas, options) {
1172
1179
  // src/alignment/cursorSnapping.ts
1173
1180
  var import_fabric8 = require("fabric");
1174
1181
  function snapCursorPoint(canvas, rawPoint, options) {
1175
- const zoom = canvas.getZoom();
1176
- const scaleWithSize = options?.scaleWithCanvasSize !== false;
1177
- const sizeScale = scaleWithSize ? Math.max(canvas.width ?? 800, canvas.height ?? 600) / BASE_CANVAS_SIZE : 1;
1178
- const margin = (options?.margin ?? DEFAULT_SNAP_MARGIN) * sizeScale / zoom;
1182
+ const margin = computeSnapMargin(
1183
+ canvas.width ?? 800,
1184
+ canvas.height ?? 600,
1185
+ canvas.getZoom(),
1186
+ options?.margin ?? DEFAULT_SNAP_MARGIN,
1187
+ options?.scaleWithCanvasSize !== false
1188
+ );
1179
1189
  const exclude = options?.exclude ?? /* @__PURE__ */ new Set();
1180
1190
  let targetPoints;
1181
1191
  if (options?.targetPoints) {
@@ -2228,20 +2238,7 @@ function enableScaledBorderRadius(canvas, options) {
2228
2238
  function getBaseStrokeWidth(obj) {
2229
2239
  return strokeBaseMap.get(obj) ?? obj.strokeWidth ?? 0;
2230
2240
  }
2231
- function serializeCanvas(canvas, options) {
2232
- const properties = [
2233
- "data",
2234
- "shapeType",
2235
- // Control styling — absent from Fabric's default toObject output
2236
- "borderColor",
2237
- "cornerColor",
2238
- "cornerStrokeColor",
2239
- "transparentCorners",
2240
- // Interaction locks — absent from Fabric's default toObject output
2241
- "lockRotation",
2242
- "lockUniScaling",
2243
- ...options?.properties ?? []
2244
- ];
2241
+ function prepareStrokeWidths(canvas) {
2245
2242
  const scaledWidths = /* @__PURE__ */ new Map();
2246
2243
  canvas.forEachObject((obj) => {
2247
2244
  const base = strokeBaseMap.get(obj);
@@ -2250,6 +2247,11 @@ function serializeCanvas(canvas, options) {
2250
2247
  obj.strokeWidth = base;
2251
2248
  }
2252
2249
  });
2250
+ return () => scaledWidths.forEach((scaled, obj) => {
2251
+ obj.strokeWidth = scaled;
2252
+ });
2253
+ }
2254
+ function prepareBorderRadii(canvas) {
2253
2255
  const appliedRadii = /* @__PURE__ */ new Map();
2254
2256
  canvas.forEachObject((obj) => {
2255
2257
  if (!(obj instanceof import_fabric16.Rect)) return;
@@ -2259,20 +2261,109 @@ function serializeCanvas(canvas, options) {
2259
2261
  obj.set({ rx: base.rx, ry: base.ry });
2260
2262
  }
2261
2263
  });
2262
- const json = canvas.toObject(properties);
2263
- delete json.backgroundColor;
2264
- scaledWidths.forEach((scaled, obj) => {
2265
- obj.strokeWidth = scaled;
2264
+ return () => appliedRadii.forEach((radii, obj) => {
2265
+ obj.set(radii);
2266
2266
  });
2267
- appliedRadii.forEach((radii, obj) => {
2268
- obj.set({ rx: radii.rx, ry: radii.ry });
2267
+ }
2268
+ function prepareObjectOrigins(canvas) {
2269
+ const savedOrigins = /* @__PURE__ */ new Map();
2270
+ canvas.forEachObject((obj) => {
2271
+ if (obj.originX === "left" && obj.originY === "top") return;
2272
+ savedOrigins.set(obj, {
2273
+ originX: obj.originX,
2274
+ originY: obj.originY,
2275
+ left: obj.left ?? 0,
2276
+ top: obj.top ?? 0
2277
+ });
2278
+ const leftTop = obj.getPositionByOrigin("left", "top");
2279
+ obj.set({
2280
+ originX: "left",
2281
+ originY: "top",
2282
+ left: leftTop.x,
2283
+ top: leftTop.y
2284
+ });
2285
+ });
2286
+ return () => savedOrigins.forEach((saved, obj) => {
2287
+ obj.set(saved);
2269
2288
  });
2289
+ }
2290
+ function prepareBackgroundOrigin(canvas) {
2291
+ const bg = canvas.backgroundImage;
2292
+ if (!(bg instanceof import_fabric16.FabricImage) || bg.originX === "left" && bg.originY === "top") {
2293
+ return () => {
2294
+ };
2295
+ }
2296
+ const saved = {
2297
+ originX: bg.originX,
2298
+ originY: bg.originY,
2299
+ left: bg.left ?? 0,
2300
+ top: bg.top ?? 0
2301
+ };
2302
+ const leftTop = bg.getPositionByOrigin("left", "top");
2303
+ bg.set({ originX: "left", originY: "top", left: leftTop.x, top: leftTop.y });
2304
+ return () => {
2305
+ bg.set(saved);
2306
+ };
2307
+ }
2308
+ function prepareStrokeWidthBaseData(canvas) {
2309
+ const savedData = /* @__PURE__ */ new Map();
2310
+ canvas.forEachObject((obj) => {
2311
+ const base = strokeBaseMap.get(obj) ?? obj.strokeWidth;
2312
+ if (base !== void 0 && base !== 0 && obj.data) {
2313
+ savedData.set(obj, obj.data);
2314
+ obj.data = {
2315
+ ...obj.data,
2316
+ strokeWidthBase: base
2317
+ };
2318
+ }
2319
+ });
2320
+ return () => savedData.forEach((originalData, obj) => {
2321
+ obj.data = originalData;
2322
+ });
2323
+ }
2324
+ function serializeCanvas(canvas, options) {
2325
+ const properties = [
2326
+ "data",
2327
+ "shapeType",
2328
+ // Control styling — absent from Fabric's default toObject output
2329
+ "borderColor",
2330
+ "cornerColor",
2331
+ "cornerStrokeColor",
2332
+ "transparentCorners",
2333
+ // Interaction locks — absent from Fabric's default toObject output
2334
+ "lockRotation",
2335
+ "lockUniScaling",
2336
+ ...options?.properties ?? []
2337
+ ];
2338
+ const restoreStrokeWidths = prepareStrokeWidths(canvas);
2339
+ const restoreBorderRadii = prepareBorderRadii(canvas);
2340
+ const restoreOrigins = prepareObjectOrigins(canvas);
2341
+ const restoreBgOrigin = prepareBackgroundOrigin(canvas);
2342
+ const restoreData = prepareStrokeWidthBaseData(canvas);
2343
+ const json = canvas.toObject(properties);
2344
+ delete json.backgroundColor;
2345
+ json.backgroundFilters = {
2346
+ opacity: getBackgroundContrast(canvas),
2347
+ inverted: getBackgroundInverted(canvas)
2348
+ };
2349
+ if (canvas.lockLightMode !== void 0) {
2350
+ json.lockLightMode = canvas.lockLightMode;
2351
+ }
2352
+ restoreStrokeWidths();
2353
+ restoreBorderRadii();
2354
+ restoreOrigins();
2355
+ restoreBgOrigin();
2356
+ restoreData();
2270
2357
  return json;
2271
2358
  }
2272
2359
  async function loadCanvas(canvas, json, options) {
2273
2360
  await canvas.loadFromJSON(json);
2274
2361
  canvas.backgroundColor = "";
2275
2362
  delete canvas.backgroundFilters;
2363
+ const rawCanvas = canvas;
2364
+ if (rawCanvas.lockLightMode !== void 0) {
2365
+ canvas.lockLightMode = rawCanvas.lockLightMode;
2366
+ }
2276
2367
  const bg = canvas.backgroundImage;
2277
2368
  if (bg instanceof import_fabric16.FabricImage) {
2278
2369
  if (bg.originX !== "center" || bg.originY !== "center") {
@@ -2465,105 +2556,104 @@ function useEditCanvas(options) {
2465
2556
  (canvas) => {
2466
2557
  canvasRef.current = canvas;
2467
2558
  const opts = optionsRef.current;
2468
- if (opts?.scaledStrokes !== false) {
2469
- enableScaledStrokes(canvas);
2470
- }
2471
- if (opts?.borderRadius !== false) {
2472
- const borderRadiusOpts = typeof opts?.borderRadius === "number" ? { radius: opts.borderRadius } : void 0;
2473
- enableScaledBorderRadius(canvas, borderRadiusOpts);
2474
- }
2475
- if (opts?.keyboardShortcuts !== false) {
2476
- keyboardCleanupRef.current = enableKeyboardShortcuts(canvas);
2477
- }
2478
- setCanvasAlignmentEnabled(canvas, opts?.enableAlignment);
2479
- if (opts?.panAndZoom !== false) {
2480
- viewportRef.current = enablePanAndZoom(
2481
- canvas,
2482
- typeof opts?.panAndZoom === "object" ? opts.panAndZoom : void 0
2483
- );
2484
- }
2485
- const alignmentEnabled = resolveAlignmentEnabled(
2486
- opts?.enableAlignment,
2487
- opts?.alignment
2488
- );
2489
- if (alignmentEnabled) {
2490
- alignmentCleanupRef.current = enableObjectAlignment(
2491
- canvas,
2492
- typeof opts?.alignment === "object" ? opts.alignment : void 0
2493
- );
2494
- }
2495
- if (opts?.rotationSnap !== false) {
2496
- rotationSnapCleanupRef.current = enableRotationSnap(
2497
- canvas,
2498
- typeof opts?.rotationSnap === "object" ? opts.rotationSnap : void 0
2559
+ setupFeatures();
2560
+ setupEventListeners();
2561
+ invokeOnReady();
2562
+ function setupFeatures() {
2563
+ if (opts?.scaledStrokes !== false) {
2564
+ enableScaledStrokes(canvas);
2565
+ }
2566
+ if (opts?.borderRadius !== false) {
2567
+ const borderRadiusOpts = typeof opts?.borderRadius === "number" ? { radius: opts.borderRadius } : void 0;
2568
+ enableScaledBorderRadius(canvas, borderRadiusOpts);
2569
+ }
2570
+ if (opts?.keyboardShortcuts !== false) {
2571
+ keyboardCleanupRef.current = enableKeyboardShortcuts(canvas);
2572
+ }
2573
+ setCanvasAlignmentEnabled(canvas, opts?.enableAlignment);
2574
+ if (opts?.panAndZoom !== false) {
2575
+ viewportRef.current = enablePanAndZoom(
2576
+ canvas,
2577
+ typeof opts?.panAndZoom === "object" ? opts.panAndZoom : void 0
2578
+ );
2579
+ }
2580
+ const alignmentEnabled = resolveAlignmentEnabled(
2581
+ opts?.enableAlignment,
2582
+ opts?.alignment
2499
2583
  );
2584
+ if (alignmentEnabled) {
2585
+ alignmentCleanupRef.current = enableObjectAlignment(
2586
+ canvas,
2587
+ typeof opts?.alignment === "object" ? opts.alignment : void 0
2588
+ );
2589
+ }
2590
+ if (opts?.rotationSnap !== false) {
2591
+ rotationSnapCleanupRef.current = enableRotationSnap(
2592
+ canvas,
2593
+ typeof opts?.rotationSnap === "object" ? opts.rotationSnap : void 0
2594
+ );
2595
+ }
2596
+ if (opts?.history) {
2597
+ const historyOpts = typeof opts.history === "object" ? opts.history : void 0;
2598
+ historyRef.current = createHistoryTracker(canvas, historyOpts);
2599
+ }
2500
2600
  }
2501
- canvas.on("mouse:wheel", () => {
2502
- setZoom(canvas.getZoom());
2503
- });
2504
- canvas.on("selection:created", (e) => {
2505
- setSelected(e.selected ?? []);
2506
- });
2507
- canvas.on("selection:updated", (e) => {
2508
- setSelected(e.selected ?? []);
2509
- });
2510
- canvas.on("selection:cleared", () => {
2511
- setSelected([]);
2512
- });
2513
- if (opts?.trackChanges) {
2514
- canvas.on("object:added", () => setIsDirty(true));
2515
- canvas.on("object:removed", () => setIsDirty(true));
2516
- canvas.on("object:modified", () => setIsDirty(true));
2517
- }
2518
- if (opts?.history) {
2519
- const syncHistoryState = () => {
2520
- const h = historyRef.current;
2521
- if (!h) return;
2522
- setTimeout(() => {
2523
- setCanUndo(h.canUndo());
2524
- setCanRedo(h.canRedo());
2525
- }, 350);
2526
- };
2527
- canvas.on("object:added", syncHistoryState);
2528
- canvas.on("object:removed", syncHistoryState);
2529
- canvas.on("object:modified", syncHistoryState);
2530
- }
2531
- if (opts?.vertexEdit !== false) {
2532
- const vertexOpts = typeof opts?.vertexEdit === "object" ? opts.vertexEdit : void 0;
2533
- canvas.on("mouse:dblclick", (e) => {
2534
- if (e.target && e.target instanceof import_fabric17.Polygon) {
2535
- vertexEditCleanupRef.current?.();
2536
- vertexEditCleanupRef.current = enableVertexEdit(canvas, e.target, {
2537
- ...vertexOpts,
2538
- onExit: () => {
2539
- vertexEditCleanupRef.current = null;
2540
- setIsEditingVertices(false);
2541
- }
2542
- });
2543
- setIsEditingVertices(true);
2544
- }
2545
- });
2546
- }
2547
- if (opts?.history) {
2548
- const historyOpts = typeof opts.history === "object" ? opts.history : void 0;
2549
- historyRef.current = createHistoryTracker(canvas, historyOpts);
2601
+ function setupEventListeners() {
2602
+ canvas.on("mouse:wheel", () => setZoom(canvas.getZoom()));
2603
+ canvas.on("selection:created", (e) => setSelected(e.selected ?? []));
2604
+ canvas.on("selection:updated", (e) => setSelected(e.selected ?? []));
2605
+ canvas.on("selection:cleared", () => setSelected([]));
2606
+ if (opts?.trackChanges) {
2607
+ canvas.on("object:added", () => setIsDirty(true));
2608
+ canvas.on("object:removed", () => setIsDirty(true));
2609
+ canvas.on("object:modified", () => setIsDirty(true));
2610
+ }
2611
+ if (opts?.history) {
2612
+ const syncHistoryState = () => {
2613
+ const h = historyRef.current;
2614
+ if (!h) return;
2615
+ setTimeout(() => {
2616
+ setCanUndo(h.canUndo());
2617
+ setCanRedo(h.canRedo());
2618
+ }, 350);
2619
+ };
2620
+ canvas.on("object:added", syncHistoryState);
2621
+ canvas.on("object:removed", syncHistoryState);
2622
+ canvas.on("object:modified", syncHistoryState);
2623
+ }
2624
+ if (opts?.vertexEdit !== false) {
2625
+ const vertexOpts = typeof opts?.vertexEdit === "object" ? opts.vertexEdit : void 0;
2626
+ canvas.on("mouse:dblclick", (e) => {
2627
+ if (e.target && e.target instanceof import_fabric17.Polygon) {
2628
+ vertexEditCleanupRef.current?.();
2629
+ vertexEditCleanupRef.current = enableVertexEdit(
2630
+ canvas,
2631
+ e.target,
2632
+ {
2633
+ ...vertexOpts,
2634
+ onExit: () => {
2635
+ vertexEditCleanupRef.current = null;
2636
+ setIsEditingVertices(false);
2637
+ }
2638
+ }
2639
+ );
2640
+ setIsEditingVertices(true);
2641
+ }
2642
+ });
2643
+ }
2550
2644
  }
2551
- const onReadyResult = opts?.onReady?.(canvas);
2552
- if (opts?.autoFitToBackground !== false) {
2645
+ function invokeOnReady() {
2646
+ const onReadyResult = opts?.onReady?.(canvas);
2553
2647
  Promise.resolve(onReadyResult).then(() => {
2554
- if (canvas.backgroundImage) {
2648
+ if (opts?.autoFitToBackground !== false && canvas.backgroundImage) {
2555
2649
  fitViewportToBackground(canvas);
2556
2650
  syncZoom(canvasRef, setZoom);
2557
2651
  }
2558
2652
  historyRef.current?.pushSnapshot();
2559
2653
  });
2560
- } else {
2561
- Promise.resolve(onReadyResult).then(() => {
2562
- historyRef.current?.pushSnapshot();
2563
- });
2564
2654
  }
2565
2655
  },
2566
- // onReady and panAndZoom are intentionally excluded — we only initialize once
2656
+ // Dependency array intentionally empty — we only initialize once on mount
2567
2657
  []
2568
2658
  );
2569
2659
  (0, import_react3.useEffect)(() => {