@anu3ev/fabric-image-editor 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.
Files changed (3) hide show
  1. package/dist/main.js +40 -38
  2. package/package.json +1 -1
  3. package/readme.md +9 -6
package/dist/main.js CHANGED
@@ -35,7 +35,7 @@ var C = (h, t, e) => new Promise((s, n) => {
35
35
  }, i = (r) => r.done ? s(r.value) : Promise.resolve(r.value).then(o, a);
36
36
  i((e = e.apply(h, t)).next());
37
37
  });
38
- import { ActiveSelection as D, Textbox as gt, util as mt, controlsUtils as pe, InteractiveFabricObject as Me, loadSVGFromURL as Ne, FabricImage as ht, Point as bt, Gradient as ye, Rect as Le, Circle as xe, Triangle as ke, Group as $, Canvas as Be, Pattern as _e } from "fabric";
38
+ import { ActiveSelection as D, Textbox as gt, util as mt, controlsUtils as pe, InteractiveFabricObject as Me, loadSVGFromURL as Ne, FabricImage as ht, Point as bt, Gradient as ye, Rect as Le, Circle as xe, Triangle as ke, Group as $, Canvas as _e, Pattern as Be } from "fabric";
39
39
  import { create as Re } from "jsondiffpatch";
40
40
  import Ue from "diff-match-patch";
41
41
  var ze = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict", x = function() {
@@ -463,18 +463,18 @@ class He {
463
463
  this.worker.terminate();
464
464
  }
465
465
  }
466
- const F = 12, Ze = 2, Dt = 8, Ot = 20, We = 100, Tt = 20, Nt = 8, Pe = 100, vt = 32, xt = 1, Ve = "#2B2D33", kt = "#3D8BF4", Bt = "#FFFFFF";
466
+ const F = 12, Ze = 2, Dt = 8, Ot = 20, We = 100, Tt = 20, Nt = 8, Pe = 100, vt = 32, xt = 1, Ve = "#2B2D33", kt = "#3D8BF4", _t = "#FFFFFF";
467
467
  function Mt(h, t, e, s, n) {
468
468
  const o = F, a = Ze;
469
- h.save(), h.translate(t, e), h.rotate(mt.degreesToRadians(n.angle)), h.fillStyle = Bt, h.strokeStyle = kt, h.lineWidth = xt, h.beginPath(), h.roundRect(-o / 2, -o / 2, o, o, a), h.fill(), h.stroke(), h.restore();
469
+ h.save(), h.translate(t, e), h.rotate(mt.degreesToRadians(n.angle)), h.fillStyle = _t, h.strokeStyle = kt, h.lineWidth = xt, h.beginPath(), h.roundRect(-o / 2, -o / 2, o, o, a), h.fill(), h.stroke(), h.restore();
470
470
  }
471
471
  function be(h, t, e, s, n) {
472
472
  const o = Dt, a = Ot, i = We;
473
- h.save(), h.translate(t, e), h.rotate(mt.degreesToRadians(n.angle)), h.fillStyle = Bt, h.strokeStyle = kt, h.lineWidth = xt, h.beginPath(), h.roundRect(-o / 2, -a / 2, o, a, i), h.fill(), h.stroke(), h.restore();
473
+ h.save(), h.translate(t, e), h.rotate(mt.degreesToRadians(n.angle)), h.fillStyle = _t, h.strokeStyle = kt, h.lineWidth = xt, h.beginPath(), h.roundRect(-o / 2, -a / 2, o, a, i), h.fill(), h.stroke(), h.restore();
474
474
  }
475
475
  function ve(h, t, e, s, n) {
476
476
  const o = Tt, a = Nt, i = Pe;
477
- h.save(), h.translate(t, e), h.rotate(mt.degreesToRadians(n.angle)), h.fillStyle = Bt, h.strokeStyle = kt, h.lineWidth = xt, h.beginPath(), h.roundRect(-o / 2, -a / 2, o, a, i), h.fill(), h.stroke(), h.restore();
477
+ h.save(), h.translate(t, e), h.rotate(mt.degreesToRadians(n.angle)), h.fillStyle = _t, h.strokeStyle = kt, h.lineWidth = xt, h.beginPath(), h.roundRect(-o / 2, -a / 2, o, a, i), h.fill(), h.stroke(), h.restore();
478
478
  }
479
479
  const Ge = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTE4Ljc1IDQuMzc1djMuNzVhLjYyNS42MjUgMCAwIDEtLjYyNS42MjVoLTMuNzVhLjYyNS42MjUgMCAwIDEgMC0xLjI1aDIuMTRsLTIuMDc3LTEuOTAzLS4wMi0uMDE5YTYuMjUgNi4yNSAwIDEgMC0uMTMgOC45NjcuNjI2LjYyNiAwIDAgMSAuODYuOTA5QTcuNDU2IDcuNDU2IDAgMCAxIDEwIDE3LjVoLS4xMDNhNy41IDcuNSAwIDEgMSA1LjM5Ni0xMi44MTJMMTcuNSA2LjcwM1Y0LjM3NWEuNjI1LjYyNSAwIDAgMSAxLjI1IDBaIi8+PC9zdmc+", we = new Image();
480
480
  we.src = Ge;
@@ -972,7 +972,7 @@ const as = {
972
972
  "white-space": "nowrap",
973
973
  "box-shadow": "0 2px 8px rgba(0, 0, 0, 0.2)"
974
974
  }, je = 16, Ie = 16, is = "fabric-editor-angle-indicator";
975
- class _t {
975
+ class Bt {
976
976
  constructor({ editor: t }) {
977
977
  this.isActive = !1, this.currentAngle = 0, this.editor = t, this.canvas = t.canvas, this.options = t.options, this._createDOM(), this._bindEvents();
978
978
  }
@@ -1000,7 +1000,7 @@ class _t {
1000
1000
  return;
1001
1001
  }
1002
1002
  const s = e.angle || 0;
1003
- this.currentAngle = _t._normalizeAngle(s), this.el.textContent = `${this.currentAngle}°`, this._positionIndicator(t.e), this.isActive || this._showIndicator();
1003
+ this.currentAngle = Bt._normalizeAngle(s), this.el.textContent = `${this.currentAngle}°`, this._positionIndicator(t.e), this.isActive || this._showIndicator();
1004
1004
  }
1005
1005
  /**
1006
1006
  * Обработчик отпускания кнопки мыши
@@ -1538,7 +1538,7 @@ class H {
1538
1538
  [T]
1539
1539
  );
1540
1540
  if (d) {
1541
- const w = m * 0.264583, L = b * 0.264583, B = (yield this.editor.moduleLoader.loadModule("jspdf")).jsPDF, Y = new B({
1541
+ const w = m * 0.264583, L = b * 0.264583, _ = (yield this.editor.moduleLoader.loadModule("jspdf")).jsPDF, Y = new _({
1542
1542
  orientation: w > L ? "landscape" : "portrait",
1543
1543
  unit: "mm",
1544
1544
  format: [w, L]
@@ -1552,8 +1552,8 @@ class H {
1552
1552
  };
1553
1553
  return a.fire("editor:canvas-exported", W), W;
1554
1554
  }
1555
- const _ = Y.output("blob"), Z = {
1556
- image: new File([_], e, { type: "application/pdf" }),
1555
+ const B = Y.output("blob"), Z = {
1556
+ image: new File([B], e, { type: "application/pdf" }),
1557
1557
  format: "pdf",
1558
1558
  contentType: "application/pdf",
1559
1559
  fileName: e
@@ -2442,8 +2442,8 @@ class ps {
2442
2442
  const { canvas: a, montageArea: i } = this.editor, r = a.viewportTransform, c = a.getWidth(), d = a.getHeight(), l = t.x - r[4], u = t.y - r[5], g = Math.abs(n), f = e - s;
2443
2443
  if (Math.abs(f) / g <= 0.1)
2444
2444
  return { x: l, y: u };
2445
- const b = c / 2, p = d / 2, M = i.left, S = i.top, O = b - M * s, T = p - S * s, y = (O - r[4]) / (e - s), A = (T - r[5]) / (e - s), N = y * g, I = A * g, v = N * o, w = I * o, L = Math.abs(v) > Math.abs(l) ? l : v, B = Math.abs(w) > Math.abs(u) ? u : w;
2446
- return { x: L, y: B };
2445
+ const b = c / 2, p = d / 2, M = i.left, S = i.top, O = b - M * s, T = p - S * s, y = (O - r[4]) / (e - s), A = (T - r[5]) / (e - s), N = y * g, I = A * g, v = N * o, w = I * o, L = Math.abs(v) > Math.abs(l) ? l : v, _ = Math.abs(w) > Math.abs(u) ? u : w;
2446
+ return { x: L, y: _ };
2447
2447
  }
2448
2448
  /**
2449
2449
  * Применяет плавное центрирование viewport при приближении к defaultZoom.
@@ -3996,9 +3996,9 @@ const Et = 0.01;
3996
3996
  class k {
3997
3997
  constructor({ editor: t }) {
3998
3998
  var e;
3999
- this.handleTextEditingEntered = () => {
3999
+ this._handleTextEditingEntered = () => {
4000
4000
  this.isTextEditingActive = !0;
4001
- }, this.handleTextChanged = (s) => {
4001
+ }, this._handleTextChanged = (s) => {
4002
4002
  var r, c;
4003
4003
  const { target: n } = s;
4004
4004
  if (!k._isTextbox(n)) return;
@@ -4013,7 +4013,7 @@ class k {
4013
4013
  } else u < l ? n.textCaseRaw = i.slice(0, u) : n.textCaseRaw = o.toLocaleLowerCase();
4014
4014
  } else
4015
4015
  n.textCaseRaw = o;
4016
- }, this.handleTextEditingExited = (s) => {
4016
+ }, this._handleTextEditingExited = (s) => {
4017
4017
  var i, r;
4018
4018
  const { target: n } = s;
4019
4019
  if (!k._isTextbox(n)) return;
@@ -4029,7 +4029,7 @@ class k {
4029
4029
  }), setTimeout(() => {
4030
4030
  this.isTextEditingActive = !1, this.editor.historyManager.saveState();
4031
4031
  }, hs);
4032
- }, this.handleObjectScaling = (s) => {
4032
+ }, this._handleObjectScaling = (s) => {
4033
4033
  var Z, G, W, tt, et, st, nt, ot, at, it, rt, ct, dt, lt;
4034
4034
  const { target: n, transform: o } = s;
4035
4035
  if (!k._isTextbox(n) || !o) return;
@@ -4046,27 +4046,21 @@ class k {
4046
4046
  scaleX: 1,
4047
4047
  scaleY: 1
4048
4048
  });
4049
- const B = (dt = n.width) != null ? dt : T, Y = Math.abs(B - v) > Et;
4050
- let _ = g;
4051
- Y && (b || M) && (A === "right" ? _ = N - B : A === "center" && (_ = I - B / 2)), n.set({ left: _ }), a.baseLeft = _, o.scaleX = 1, o.scaleY = 1;
4049
+ const _ = (dt = n.width) != null ? dt : T, Y = Math.abs(_ - v) > Et;
4050
+ let B = g;
4051
+ Y && (b || M) && (A === "right" ? B = N - _ : A === "center" && (B = I - _ / 2)), n.set({ left: B }), a.baseLeft = B, o.scaleX = 1, o.scaleY = 1;
4052
4052
  const { original: R } = o;
4053
- R && (R.scaleX = 1, R.scaleY = 1, R.width = B, R.height = n.height, R.left = _), n.setCoords(), this.canvas.requestRenderAll(), a.baseWidth = B, a.baseFontSize = (lt = n.fontSize) != null ? lt : y, a.hasWidthChange = Y || L;
4054
- }, this.handleObjectModified = (s) => {
4053
+ R && (R.scaleX = 1, R.scaleY = 1, R.width = _, R.height = n.height, R.left = B), n.setCoords(), this.canvas.requestRenderAll(), a.baseWidth = _, a.baseFontSize = (lt = n.fontSize) != null ? lt : y, a.hasWidthChange = Y || L;
4054
+ }, this._handleObjectModified = (s) => {
4055
4055
  var r, c, d;
4056
4056
  const { target: n } = s;
4057
4057
  if (!k._isTextbox(n)) return;
4058
4058
  const o = this.scalingState.get(n);
4059
4059
  if (this.scalingState.delete(n), !(o != null && o.hasWidthChange)) return;
4060
4060
  const a = (r = n.width) != null ? r : n.calcTextWidth(), i = (d = (c = n.fontSize) != null ? c : o == null ? void 0 : o.baseFontSize) != null ? d : 16;
4061
- this.updateText(n, { width: a, fontSize: i }), n.set({ scaleX: 1, scaleY: 1 }), n.setCoords();
4061
+ this.updateText({ target: n, style: { width: a, fontSize: i } }), n.set({ scaleX: 1, scaleY: 1 }), n.setCoords();
4062
4062
  }, this.editor = t, this.canvas = t.canvas, this.fonts = (e = t.options.fonts) != null ? e : [], this.scalingState = /* @__PURE__ */ new WeakMap(), this.isTextEditingActive = !1, this._bindEvents();
4063
4063
  }
4064
- /**
4065
- * Уничтожает менеджер и снимает слушатели.
4066
- */
4067
- destroy() {
4068
- this.canvas.off("object:scaling", this.handleObjectScaling), this.canvas.off("object:modified", this.handleObjectModified), this.canvas.off("text:editing:exited", this.handleTextEditingExited), this.canvas.off("text:editing:entered", this.handleTextEditingEntered), this.canvas.off("text:changed", this.handleTextChanged);
4069
- }
4070
4064
  /**
4071
4065
  * Добавляет новый текстовый объект на канвас.
4072
4066
  * @param options — настройки текста
@@ -4159,12 +4153,14 @@ class k {
4159
4153
  }
4160
4154
  /**
4161
4155
  * Обновляет текстовый объект.
4162
- * @param target — объект, его id или активный объект (если не передан)
4163
- * @param style — стиль, который нужно применить
4164
4156
  * @param options — настройки обновления
4157
+ * @param options.target — объект, его id или активный объект (если не передан)
4158
+ * @param options.style — стиль, который нужно применить
4159
+ * @param options.withoutSave — не сохранять состояние в историю
4160
+ * @param options.skipRender — не вызывать перерисовку канваса
4165
4161
  */
4166
- updateText(t, e = {}, { withoutSave: s, skipRender: n } = {}) {
4167
- var Y, _, R, Z, G, W, tt, et, st, nt, ot, at, it, rt, ct, dt, lt, zt, Yt, Ht, Zt, Wt, Pt, Vt, Gt, Xt, Kt, $t, Qt, Jt, qt, te, ee, se, ne, oe, ae, ie, re, ce, de, le;
4162
+ updateText({ target: t, style: e = {}, withoutSave: s, skipRender: n } = {}) {
4163
+ var Y, B, R, Z, G, W, tt, et, st, nt, ot, at, it, rt, ct, dt, lt, zt, Yt, Ht, Zt, Wt, Pt, Vt, Gt, Xt, Kt, $t, Qt, Jt, qt, te, ee, se, ne, oe, ae, ie, re, ce, de, le;
4168
4164
  const o = this._resolveTextObject(t);
4169
4165
  if (!o) return null;
4170
4166
  const { historyManager: a } = this.editor;
@@ -4172,7 +4168,7 @@ class k {
4172
4168
  const i = {
4173
4169
  id: o.id,
4174
4170
  text: (Y = o.text) != null ? Y : void 0,
4175
- textCaseRaw: (_ = o.textCaseRaw) != null ? _ : void 0,
4171
+ textCaseRaw: (B = o.textCaseRaw) != null ? B : void 0,
4176
4172
  uppercase: !!o.uppercase,
4177
4173
  fontFamily: (R = o.fontFamily) != null ? R : void 0,
4178
4174
  fontSize: (Z = o.fontSize) != null ? Z : void 0,
@@ -4232,7 +4228,7 @@ class k {
4232
4228
  y.text = wt, o.textCaseRaw = v;
4233
4229
  } else o.textCaseRaw === void 0 && (o.textCaseRaw = A);
4234
4230
  o.uppercase = w, o.set(y), o.setCoords(), n || this.canvas.requestRenderAll(), a.resumeHistory(), s || a.saveState();
4235
- const B = {
4231
+ const _ = {
4236
4232
  id: o.id,
4237
4233
  text: (Vt = o.text) != null ? Vt : void 0,
4238
4234
  textCaseRaw: (Gt = o.textCaseRaw) != null ? Gt : void 0,
@@ -4266,9 +4262,15 @@ class k {
4266
4262
  },
4267
4263
  updates: y,
4268
4264
  before: i,
4269
- after: B
4265
+ after: _
4270
4266
  }), o;
4271
4267
  }
4268
+ /**
4269
+ * Уничтожает менеджер и снимает слушатели.
4270
+ */
4271
+ destroy() {
4272
+ this.canvas.off("object:scaling", this._handleObjectScaling), this.canvas.off("object:modified", this._handleObjectModified), this.canvas.off("text:editing:exited", this._handleTextEditingExited), this.canvas.off("text:editing:entered", this._handleTextEditingEntered), this.canvas.off("text:changed", this._handleTextChanged);
4273
+ }
4272
4274
  /**
4273
4275
  * Возвращает активный текст или ищет по id.
4274
4276
  */
@@ -4288,7 +4290,7 @@ class k {
4288
4290
  return !!t && t instanceof gt;
4289
4291
  }
4290
4292
  _bindEvents() {
4291
- this.canvas.on("object:scaling", this.handleObjectScaling), this.canvas.on("object:modified", this.handleObjectModified), this.canvas.on("text:editing:entered", this.handleTextEditingEntered), this.canvas.on("text:editing:exited", this.handleTextEditingExited), this.canvas.on("text:changed", this.handleTextChanged);
4293
+ this.canvas.on("object:scaling", this._handleObjectScaling), this.canvas.on("object:modified", this._handleObjectModified), this.canvas.on("text:editing:entered", this._handleTextEditingEntered), this.canvas.on("text:editing:exited", this._handleTextEditingExited), this.canvas.on("text:changed", this._handleTextChanged);
4292
4294
  }
4293
4295
  _ensureScalingState(t) {
4294
4296
  var s, n, o;
@@ -4349,7 +4351,7 @@ class Ut {
4349
4351
  showRotationAngle: d,
4350
4352
  _onReadyCallback: l
4351
4353
  } = this.options;
4352
- if (jt.apply(), this.canvas = new Be(this.containerId, this.options), this.moduleLoader = new Ye(), this.workerManager = new He(), this.errorManager = new St({ editor: this }), this.historyManager = new It({ editor: this }), this.toolbar = new os({ editor: this }), this.transformManager = new ms({ editor: this }), this.zoomManager = new ps({ editor: this }), this.canvasManager = new fs({ editor: this }), this.imageManager = new H({ editor: this }), this.layerManager = new At({ editor: this }), this.shapeManager = new ys({ editor: this }), this.interactionBlocker = new Ms({ editor: this }), this.backgroundManager = new Q({ editor: this }), this.clipboardManager = new bs({ editor: this }), this.objectLockManager = new Ct({ editor: this }), this.groupingManager = new vs({ editor: this }), this.selectionManager = new js({ editor: this }), this.deletionManager = new Rt({ editor: this }), this.panConstraintManager = new As({ editor: this }), this.fontManager = new Lt((u = this.options.fonts) != null ? u : []), this.textManager = new k({ editor: this }), d && (this.angleIndicator = new _t({ editor: this })), this._createMontageArea(), this._createClippingArea(), this.listeners = new ft({ editor: this, options: this.options }), this.canvasManager.setEditorContainerWidth(t), this.canvasManager.setEditorContainerHeight(e), this.canvasManager.setCanvasWrapperWidth(s), this.canvasManager.setCanvasWrapperHeight(n), this.canvasManager.setCanvasCSSWidth(o), this.canvasManager.setCanvasCSSHeight(a), this.canvasManager.updateCanvas(), this.zoomManager.calculateAndApplyDefaultZoom(), yield this.fontManager.loadFonts(), i != null && i.source) {
4354
+ if (jt.apply(), this.canvas = new _e(this.containerId, this.options), this.moduleLoader = new Ye(), this.workerManager = new He(), this.errorManager = new St({ editor: this }), this.historyManager = new It({ editor: this }), this.toolbar = new os({ editor: this }), this.transformManager = new ms({ editor: this }), this.zoomManager = new ps({ editor: this }), this.canvasManager = new fs({ editor: this }), this.imageManager = new H({ editor: this }), this.layerManager = new At({ editor: this }), this.shapeManager = new ys({ editor: this }), this.interactionBlocker = new Ms({ editor: this }), this.backgroundManager = new Q({ editor: this }), this.clipboardManager = new bs({ editor: this }), this.objectLockManager = new Ct({ editor: this }), this.groupingManager = new vs({ editor: this }), this.selectionManager = new js({ editor: this }), this.deletionManager = new Rt({ editor: this }), this.panConstraintManager = new As({ editor: this }), this.fontManager = new Lt((u = this.options.fonts) != null ? u : []), this.textManager = new k({ editor: this }), d && (this.angleIndicator = new Bt({ editor: this })), this._createMontageArea(), this._createClippingArea(), this.listeners = new ft({ editor: this, options: this.options }), this.canvasManager.setEditorContainerWidth(t), this.canvasManager.setEditorContainerHeight(e), this.canvasManager.setCanvasWrapperWidth(s), this.canvasManager.setCanvasWrapperHeight(n), this.canvasManager.setCanvasCSSWidth(o), this.canvasManager.setCanvasCSSHeight(a), this.canvasManager.updateCanvas(), this.zoomManager.calculateAndApplyDefaultZoom(), yield this.fontManager.loadFonts(), i != null && i.source) {
4353
4355
  const {
4354
4356
  source: g,
4355
4357
  scale: f = `image-${c}`,
@@ -4422,7 +4424,7 @@ class Ut {
4422
4424
  const t = document.createElement("canvas");
4423
4425
  t.width = 20, t.height = 20;
4424
4426
  const e = t.getContext("2d");
4425
- return e.fillStyle = "#ddd", e.fillRect(0, 0, 40, 40), e.fillStyle = "#ccc", e.fillRect(0, 0, 10, 10), e.fillRect(10, 10, 10, 10), new _e({
4427
+ return e.fillStyle = "#ddd", e.fillRect(0, 0, 40, 40), e.fillStyle = "#ccc", e.fillRect(0, 0, 10, 10), e.fillRect(10, 10, 10, 10), new Be({
4426
4428
  source: t,
4427
4429
  repeat: "repeat"
4428
4430
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anu3ev/fabric-image-editor",
3
- "version": "0.03.01",
3
+ "version": "0.4.0",
4
4
  "description": "JavaScript image editor built on FabricJS, allowing you to create instances with an integrated montage area and providing an API to modify and manage state.",
5
5
  "module": "dist/main.js",
6
6
  "files": [
package/readme.md CHANGED
@@ -129,17 +129,20 @@ const textbox = editor.textManager.addText({
129
129
  })
130
130
 
131
131
  // Update existing text
132
- editor.textManager.updateText(textbox, {
133
- text: 'HELLO FABRIC',
134
- uppercase: true,
135
- strokeColor: '#2563eb',
136
- strokeWidth: 2
132
+ editor.textManager.updateText({
133
+ target: textbox,
134
+ style: {
135
+ text: 'HELLO FABRIC',
136
+ uppercase: true,
137
+ strokeColor: '#2563eb',
138
+ strokeWidth: 2
139
+ }
137
140
  })
138
141
  ```
139
142
 
140
143
  ### Configuring Fonts
141
144
 
142
- By default the editor ships with a curated Google Fonts collection (Latin + Cyrillic coverage).
145
+ By default the editor ships with a curated Google Fonts collection (Latin + Cyrillic coverage).
143
146
  If you want to use your own fonts, supply a `fonts` array – the provided list will replace the defaults.
144
147
 
145
148
  ```typescript