@nasser-sw/fabric 7.0.1-beta31 → 7.0.1-beta32

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.
@@ -0,0 +1,164 @@
1
+ {
2
+ "name": "@nasser-sw/fabric",
3
+ "description": "Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.",
4
+ "homepage": "http://fabricjs.com/",
5
+ "version": "7.0.1-beta32",
6
+ "author": "Juriy Zaytsev <kangax@gmail.com>",
7
+ "contributors": [
8
+ {
9
+ "name": "Andrea Bogazzi",
10
+ "email": "andreabogazzi79@gmail.com",
11
+ "url": "https://github.com/asturur"
12
+ },
13
+ {
14
+ "name": "Shachar Nencel",
15
+ "email": "shacharnen@gmail.com",
16
+ "url": "https://github.com/ShaMan123"
17
+ },
18
+ {
19
+ "name": "Steve Eberhardt",
20
+ "email": "melchiar2@gmail.com",
21
+ "url": "https://github.com/melchiar"
22
+ }
23
+ ],
24
+ "keywords": [
25
+ "canvas",
26
+ "graphic",
27
+ "graphics",
28
+ "SVG",
29
+ "node-canvas",
30
+ "parser",
31
+ "HTML5",
32
+ "object model"
33
+ ],
34
+ "publishConfig": {
35
+ "access": "public"
36
+ },
37
+ "repository": {
38
+ "type": "git",
39
+ "url": "https://github.com/fabricjs/fabric.js"
40
+ },
41
+ "bugs": {
42
+ "url": "https://github.com/fabricjs/fabric.js/issues"
43
+ },
44
+ "license": "MIT",
45
+ "scripts": {
46
+ "docs": "typedoc",
47
+ "cli": "node ./scripts/index.mjs",
48
+ "sandboxscript": "node ./scripts/sandbox.mjs",
49
+ "build": "npm run cli -- build",
50
+ "build:fast": "npm run build -- -f",
51
+ "dev": "npm run cli -- dev",
52
+ "start": "npm run sandboxscript -- start",
53
+ "export": "npm run cli -- website export",
54
+ "test:vitest": "vitest --run --project unit-node",
55
+ "test:vitest:chromium": "vitest --run --project unit-chromium",
56
+ "test:vitest:firefox": "vitest --run --project unit-firefox",
57
+ "test:vitest:all": "vitest --run",
58
+ "test:vitest:coverage": "vitest --run --coverage --project unit-node",
59
+ "test:vitest:coverage:watch": "npm run test:vitest --coverage=true",
60
+ "coverage:merge": "nyc merge coveragefiles .nyc_output/merged-coverage.json",
61
+ "coverage:report": "nyc report --skip-full=true --reporter=lcov --reporter=text --reporter=text-summary",
62
+ "coverage:report:ci": "nyc report --reporter=text-summary",
63
+ "test:e2e": "npm run playwright:typecheck && playwright test",
64
+ "playwright:typecheck": "tsc -p ./e2e/tsconfig.json --noEmit",
65
+ "sandbox": "npm run sandboxscript -- sandbox",
66
+ "local-server": "serve ./ -l tcp://localhost:8080",
67
+ "lint": "eslint src extensions",
68
+ "prettier:check": "prettier --check .",
69
+ "prettier:write": "prettier --write ."
70
+ },
71
+ "devDependencies": {
72
+ "@babel/cli": "^7.28.3",
73
+ "@babel/core": "^7.28.3",
74
+ "@babel/preset-env": "^7.28.3",
75
+ "@babel/preset-typescript": "^7.27.1",
76
+ "@eslint/js": "^9.31.0",
77
+ "@playwright/test": "^1.55.0",
78
+ "@rollup/plugin-babel": "^6.0.4",
79
+ "@rollup/plugin-json": "^6.1.0",
80
+ "@rollup/plugin-terser": "^0.4.4",
81
+ "@rollup/plugin-typescript": "^12.1.4",
82
+ "@types/fs-extra": "^11.0.4",
83
+ "@types/jsdom": "^21.1.7",
84
+ "@types/micromatch": "^4.0.9",
85
+ "@types/node": "^24.3.0",
86
+ "@vitest/browser": "^3.2.4",
87
+ "@vitest/coverage-v8": "^3.2.4",
88
+ "@vitest/ui": "^3.2.4",
89
+ "babel-plugin-transform-imports": "git+https://git@github.com/fabricjs/babel-plugin-transform-imports.git",
90
+ "chalk": "^5.6.0",
91
+ "commander": "^14.0.0",
92
+ "es-toolkit": "1.39.7",
93
+ "eslint-config-prettier": "^10.1.8",
94
+ "fs-extra": "^11.3.1",
95
+ "inquirer": "^12.9.4",
96
+ "micromatch": "^4.0.8",
97
+ "moment": "^2.30.1",
98
+ "nyc": "^17.1.0",
99
+ "prettier": "^3.6.2",
100
+ "ps-list": "^8.1.1",
101
+ "rollup": "^4.48.0",
102
+ "semver": "^7.7.2",
103
+ "serve": "^14.2.4",
104
+ "tslib": "^2.8.1",
105
+ "typescript": "^5.9.2",
106
+ "typescript-eslint": "^8.40.0",
107
+ "v8-to-istanbul": "^9.3.0",
108
+ "vite": "^6.3.5",
109
+ "vitest": "^3.2.4"
110
+ },
111
+ "engines": {
112
+ "node": ">=18.0.0"
113
+ },
114
+ "overrides": {
115
+ "canvas": {
116
+ "canvas": "3.2.0"
117
+ }
118
+ },
119
+ "module": "./dist/index.mjs",
120
+ "types": "./dist/index.d.ts",
121
+ "typesVersions": {
122
+ ">=4.2": {
123
+ "*": [
124
+ "dist/index.d.ts"
125
+ ],
126
+ "node": [
127
+ "dist/index.node.d.ts"
128
+ ]
129
+ }
130
+ },
131
+ "sideEffects": false,
132
+ "exports": {
133
+ ".": {
134
+ "types": "./dist/index.d.ts",
135
+ "import": "./dist/index.min.mjs",
136
+ "require": "./dist/index.min.js",
137
+ "default": "./dist/index.min.js"
138
+ },
139
+ "./es": {
140
+ "types": "./dist/index.d.ts",
141
+ "import": "./dist/fabric.min.mjs",
142
+ "require": null,
143
+ "default": null
144
+ },
145
+ "./node": {
146
+ "node": "./dist/index.node.cjs",
147
+ "types": "./dist/index.node.d.ts",
148
+ "import": "./dist/index.node.mjs",
149
+ "require": "./dist/index.node.cjs",
150
+ "default": "./dist/index.node.cjs"
151
+ },
152
+ "./extensions": {
153
+ "node": "./dist-extensions/index.mjs",
154
+ "types": "./dist-extensions/extensions/index.d.ts",
155
+ "import": "./dist-extensions/index.mjs",
156
+ "require": null,
157
+ "default": "./dist-extensions/fabric-extensions.min.js"
158
+ }
159
+ },
160
+ "optionalDependencies": {
161
+ "canvas": "^3.2.0",
162
+ "jsdom": "^26.1.0"
163
+ }
164
+ }
package/dist/index.js CHANGED
@@ -9338,9 +9338,12 @@
9338
9338
  * Position handler for expand controls
9339
9339
  * Positions controls at the expansion boundary, not the object boundary
9340
9340
  * Note: expansion values are stored in UNSCALED local object coordinates
9341
+ *
9342
+ * Key insight: dim already includes zoom, and finalMatrix undoes zoom.
9343
+ * So we need to express expansion as a PROPORTION of dim, not as a separate offset.
9344
+ * This ensures the expansion scales correctly with zoom.
9341
9345
  */
9342
9346
  positionHandler(dim, finalMatrix, fabricObject, currentControl) {
9343
- var _fabricObject$canvas;
9344
9347
  const expansion = getExpansion(fabricObject);
9345
9348
  const {
9346
9349
  expandLeft,
@@ -9349,56 +9352,39 @@
9349
9352
  expandBottom
9350
9353
  } = expansion;
9351
9354
 
9352
- // dim already includes object's scale AND viewport zoom via _calculateCurrentDimensions
9353
- // which calls: _getTransformedDimensions().transform(viewportTransform, true)
9354
- const halfWidth = dim.x / 2;
9355
- const halfHeight = dim.y / 2;
9356
-
9357
- // Expansion values are in UNSCALED coordinates.
9358
- // dim includes both object scale AND viewport zoom.
9359
- // We need to scale expansion by both to match dim.
9360
- const zoom = ((_fabricObject$canvas = fabricObject.canvas) === null || _fabricObject$canvas === void 0 ? void 0 : _fabricObject$canvas.getZoom()) || 1;
9361
- const scaleFactorX = (fabricObject.scaleX || 1) * zoom;
9362
- const scaleFactorY = (fabricObject.scaleY || 1) * zoom;
9363
-
9364
- // Scale expansion values to match dim's coordinate space (includes zoom)
9365
- const scaledExpandLeft = expandLeft * scaleFactorX;
9366
- const scaledExpandRight = expandRight * scaleFactorX;
9367
- const scaledExpandTop = expandTop * scaleFactorY;
9368
- const scaledExpandBottom = expandBottom * scaleFactorY;
9369
-
9370
- // Calculate the expanded half dimensions
9371
- const expandedHalfWidth = halfWidth + (scaledExpandLeft + scaledExpandRight) / 2;
9372
- const expandedHalfHeight = halfHeight + (scaledExpandTop + scaledExpandBottom) / 2;
9373
-
9374
- // Calculate offset from center based on asymmetric expansion
9375
- const centerOffsetX = (scaledExpandRight - scaledExpandLeft) / 2;
9376
- const centerOffsetY = (scaledExpandBottom - scaledExpandTop) / 2;
9377
- let posX;
9378
- let posY;
9379
-
9380
- // Position based on which side this control is on
9355
+ // Get object's base dimensions (unscaled)
9356
+ const objWidth = fabricObject.width || 1;
9357
+ const objHeight = fabricObject.height || 1;
9358
+
9359
+ // Express expansion as a proportion of object size
9360
+ // dim includes zoom, finalMatrix applies inverse zoom
9361
+ // The result matches drawExpandPreview which also uses ratio * size
9362
+ const expandLeftRatio = expandLeft / objWidth;
9363
+ const expandRightRatio = expandRight / objWidth;
9364
+ const expandTopRatio = expandTop / objHeight;
9365
+ const expandBottomRatio = expandBottom / objHeight;
9366
+
9367
+ // Calculate position as a multiple of dim (same pattern as default control)
9368
+ // this.x is -0.5 for left, 0 for center, 0.5 for right
9369
+ let xMultiplier = this.x;
9370
+ let yMultiplier = this.y;
9381
9371
  if (this.x < 0) {
9382
- // Left side controls
9383
- posX = -expandedHalfWidth + centerOffsetX;
9372
+ // Left side: extend further left
9373
+ xMultiplier = this.x - expandLeftRatio;
9384
9374
  } else if (this.x > 0) {
9385
- // Right side controls
9386
- posX = expandedHalfWidth + centerOffsetX;
9387
- } else {
9388
- // Center (top/bottom only)
9389
- posX = centerOffsetX;
9375
+ // Right side: extend further right
9376
+ xMultiplier = this.x + expandRightRatio;
9390
9377
  }
9391
9378
  if (this.y < 0) {
9392
- // Top side controls
9393
- posY = -expandedHalfHeight + centerOffsetY;
9379
+ // Top side: extend further up
9380
+ yMultiplier = this.y - expandTopRatio;
9394
9381
  } else if (this.y > 0) {
9395
- // Bottom side controls
9396
- posY = expandedHalfHeight + centerOffsetY;
9397
- } else {
9398
- // Center (left/right only)
9399
- posY = centerOffsetY;
9382
+ // Bottom side: extend further down
9383
+ yMultiplier = this.y + expandBottomRatio;
9400
9384
  }
9401
- return new Point(posX, posY).transform(finalMatrix);
9385
+
9386
+ // Same formula as default positionHandler, just with adjusted multipliers
9387
+ return new Point(xMultiplier * dim.x + this.offsetX, yMultiplier * dim.y + this.offsetY).transform(finalMatrix);
9402
9388
  }
9403
9389
 
9404
9390
  /**
@@ -9453,16 +9439,17 @@
9453
9439
  } = transform;
9454
9440
  const expansion = getExpansion(target);
9455
9441
 
9456
- // Use Fabric's getLocalPoint with center origin (returns scaled coordinates)
9442
+ // Use Fabric's getLocalPoint with center origin
9457
9443
  const localPoint = getLocalPoint(transform, CENTER, CENTER, x, y);
9458
9444
  const scaleX = target.scaleX || 1;
9459
- const scaledHalfWidth = target.width * scaleX / 2;
9445
+ // Use _getTransformedDimensions for consistency with scale handlers
9446
+ const dim = target._getTransformedDimensions();
9447
+ const scaledHalfWidth = dim.x / 2;
9460
9448
 
9461
- // Calculate expansion in scaled coordinates first
9449
+ // Calculate expansion in scaled coordinates
9462
9450
  const scaledExpansion = Math.max(0, -scaledHalfWidth - localPoint.x);
9463
9451
 
9464
- // Store in UNSCALED coordinates (divide by scale)
9465
- // This ensures positionHandler can scale it back correctly
9452
+ // Store in UNSCALED object coordinates (divide by scale)
9466
9453
  const newExpandLeft = scaledExpansion / scaleX;
9467
9454
  if (Math.abs(newExpandLeft - expansion.expandLeft) > 0.5) {
9468
9455
  var _target$canvas;
@@ -10396,12 +10383,15 @@
10396
10383
  * Draw the expansion preview area
10397
10384
  * Called during border rendering when in expand mode
10398
10385
  * @param ctx Canvas rendering context
10399
- * @param size Object dimensions (already includes scale and viewport zoom via _calculateCurrentDimensions)
10400
- * @param options Decomposed transform options (contains scaleX, scaleY from object transform only)
10386
+ * @param size Object dimensions (already in correct coordinate space from drawBorders)
10387
+ * @param options Decomposed transform options (contains scaleX, scaleY)
10401
10388
  * Note: expansion values are stored in local object coordinates
10389
+ *
10390
+ * Key insight: size is proportional to object dimensions.
10391
+ * Express expansion as a proportion of object size, then scale by size.
10392
+ * This ensures correct behavior with zoom and grouped objects.
10402
10393
  */
10403
10394
  drawExpandPreview(ctx, size, options) {
10404
- var _this$canvas6;
10405
10395
  if (!this.expandMode) return;
10406
10396
  const {
10407
10397
  expandLeft,
@@ -10410,21 +10400,20 @@
10410
10400
  expandBottom
10411
10401
  } = this.expansion;
10412
10402
 
10413
- // Expansion values are stored in UNSCALED object coordinates.
10414
- // size includes both object scale AND viewport zoom (via _calculateCurrentDimensions).
10415
- // options.scaleX/Y only contains object scale (from calcTransformMatrix, no viewport).
10416
- // We need to multiply by zoom to match size's coordinate space.
10417
- const zoom = ((_this$canvas6 = this.canvas) === null || _this$canvas6 === void 0 ? void 0 : _this$canvas6.getZoom()) || 1;
10418
- const scaleFactorX = ((options === null || options === void 0 ? void 0 : options.scaleX) || this.scaleX || 1) * zoom;
10419
- const scaleFactorY = ((options === null || options === void 0 ? void 0 : options.scaleY) || this.scaleY || 1) * zoom;
10420
-
10421
- // Scale expansion values to screen coordinates (includes zoom)
10422
- const scaledExpandLeft = expandLeft * scaleFactorX;
10423
- const scaledExpandRight = expandRight * scaleFactorX;
10424
- const scaledExpandTop = expandTop * scaleFactorY;
10425
- const scaledExpandBottom = expandBottom * scaleFactorY;
10426
-
10427
- // size already accounts for full transform, add scaled expansion
10403
+ // Express expansion as proportions of object dimensions
10404
+ // size already includes scale and zoom, so ratio * size gives correct scaling
10405
+ const expandLeftRatio = expandLeft / (this.width || 1);
10406
+ const expandRightRatio = expandRight / (this.width || 1);
10407
+ const expandTopRatio = expandTop / (this.height || 1);
10408
+ const expandBottomRatio = expandBottom / (this.height || 1);
10409
+
10410
+ // Scale expansion proportionally to size
10411
+ const scaledExpandLeft = expandLeftRatio * size.x;
10412
+ const scaledExpandRight = expandRightRatio * size.x;
10413
+ const scaledExpandTop = expandTopRatio * size.y;
10414
+ const scaledExpandBottom = expandBottomRatio * size.y;
10415
+
10416
+ // Calculate expanded dimensions
10428
10417
  const expandedWidth = size.x + scaledExpandLeft + scaledExpandRight;
10429
10418
  const expandedHeight = size.y + scaledExpandTop + scaledExpandBottom;
10430
10419
 
@@ -31808,11 +31797,8 @@
31808
31797
  // Draw edit mode overlay if in edit mode
31809
31798
  if (this.isEditMode && this._editModeClipPath) {
31810
31799
  this._renderEditModeOverlay(ctx, false);
31811
-
31812
- // In expand mode, re-render the content image's controls ON TOP of the overlay
31813
- if (this._contentExpandMode && this._contentImage) {
31814
- this._contentImage._renderControls(ctx);
31815
- }
31800
+ // Note: Controls are rendered by the canvas's normal rendering pipeline
31801
+ // with proper viewport transforms - no manual _renderControls call needed
31816
31802
  }
31817
31803
  }
31818
31804