@nasser-sw/fabric 7.0.1-beta12 → 7.0.1-beta13

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.
@@ -410,7 +410,7 @@ class Cache {
410
410
  }
411
411
  const cache = new Cache();
412
412
 
413
- var version = "7.0.1-beta11";
413
+ var version = "7.0.1-beta12";
414
414
 
415
415
  // use this syntax so babel plugin see this import here
416
416
  const VERSION = version;
@@ -20772,9 +20772,9 @@ function getBrowserLines(target) {
20772
20772
 
20773
20773
  let measuringContext;
20774
20774
 
20775
- /**
20776
- * Return a context for measurement of text string.
20777
- * if created it gets stored for reuse
20775
+ /**
20776
+ * Return a context for measurement of text string.
20777
+ * if created it gets stored for reuse
20778
20778
  */
20779
20779
  function getMeasuringContext() {
20780
20780
  if (!measuringContext) {
@@ -20787,17 +20787,17 @@ function getMeasuringContext() {
20787
20787
  return measuringContext;
20788
20788
  }
20789
20789
 
20790
- /**
20791
- * Measure and return the info of a single grapheme.
20792
- * needs the the info of previous graphemes already filled
20793
- * Override to customize measuring
20790
+ /**
20791
+ * Measure and return the info of a single grapheme.
20792
+ * needs the the info of previous graphemes already filled
20793
+ * Override to customize measuring
20794
20794
  */
20795
20795
 
20796
20796
  // @TODO this is not complete
20797
20797
 
20798
- /**
20799
- * Text class
20800
- * @see {@link http://fabricjs.com/fabric-intro-part-2#text}
20798
+ /**
20799
+ * Text class
20800
+ * @see {@link http://fabricjs.com/fabric-intro-part-2#text}
20801
20801
  */
20802
20802
  class FabricText extends StyledText {
20803
20803
  static getDefaults() {
@@ -20808,11 +20808,11 @@ class FabricText extends StyledText {
20808
20808
  }
20809
20809
  constructor(text, options) {
20810
20810
  super();
20811
- /**
20812
- * contains characters bounding boxes
20813
- * This variable is considered to be protected.
20814
- * But for how mixins are implemented right now, we can't leave it private
20815
- * @protected
20811
+ /**
20812
+ * contains characters bounding boxes
20813
+ * This variable is considered to be protected.
20814
+ * But for how mixins are implemented right now, we can't leave it private
20815
+ * @protected
20816
20816
  */
20817
20817
  _defineProperty(this, "__charBounds", []);
20818
20818
  Object.assign(this, FabricText.ownDefaults);
@@ -20829,9 +20829,9 @@ class FabricText extends StyledText {
20829
20829
  this.setCoords();
20830
20830
  }
20831
20831
 
20832
- /**
20833
- * If text has a path, it will add the extra information needed
20834
- * for path and text calculations
20832
+ /**
20833
+ * If text has a path, it will add the extra information needed
20834
+ * for path and text calculations
20835
20835
  */
20836
20836
  setPathInfo() {
20837
20837
  const path = this.path;
@@ -20840,10 +20840,10 @@ class FabricText extends StyledText {
20840
20840
  }
20841
20841
  }
20842
20842
 
20843
- /**
20844
- * @private
20845
- * Divides text into lines of text and lines of graphemes.
20846
- * Uses browser lines when available for pixel-perfect consistency.
20843
+ /**
20844
+ * @private
20845
+ * Divides text into lines of text and lines of graphemes.
20846
+ * Uses browser lines when available for pixel-perfect consistency.
20847
20847
  */
20848
20848
  _splitText() {
20849
20849
  // Check if we have valid browser lines and should use them
@@ -20859,9 +20859,9 @@ class FabricText extends StyledText {
20859
20859
  return newLines;
20860
20860
  }
20861
20861
 
20862
- /**
20863
- * Create TextLinesInfo from browser-extracted lines
20864
- * @private
20862
+ /**
20863
+ * Create TextLinesInfo from browser-extracted lines
20864
+ * @private
20865
20865
  */
20866
20866
  _splitTextFromBrowserLines(browserLines) {
20867
20867
  const lines = [];
@@ -20895,10 +20895,10 @@ class FabricText extends StyledText {
20895
20895
  return result;
20896
20896
  }
20897
20897
 
20898
- /**
20899
- * Initialize or update text dimensions.
20900
- * Updates this.width and this.height with the proper values.
20901
- * Does not return dimensions.
20898
+ /**
20899
+ * Initialize or update text dimensions.
20900
+ * Updates this.width and this.height with the proper values.
20901
+ * Does not return dimensions.
20902
20902
  */
20903
20903
  initDimensions() {
20904
20904
  // Check if font is ready for accurate measurements
@@ -20944,14 +20944,14 @@ class FabricText extends StyledText {
20944
20944
  }
20945
20945
  }
20946
20946
 
20947
- /**
20948
- * Enlarge space boxes and shift the others
20947
+ /**
20948
+ * Enlarge space boxes and shift the others
20949
20949
  */
20950
20950
  enlargeSpaces() {
20951
20951
  let diffSpace, currentLineWidth, numberOfSpaces, accumulatedSpace, line, charBound, spaces;
20952
20952
  const isRtl = this.direction === 'rtl';
20953
20953
  for (let i = 0, len = this._textLines.length; i < len; i++) {
20954
- if (!this.textAlign.includes('justify') && (i === len - 1 || this.isEndOfWrapping(i))) {
20954
+ if (!this.textAlign.includes('justify') || i === len - 1 || this.isEndOfWrapping(i)) {
20955
20955
  continue;
20956
20956
  }
20957
20957
  accumulatedSpace = 0;
@@ -21007,18 +21007,18 @@ class FabricText extends StyledText {
21007
21007
  }
21008
21008
  }
21009
21009
 
21010
- /**
21011
- * Advanced layout using new text engine (Konva-compatible)
21012
- * @private
21010
+ /**
21011
+ * Advanced layout using new text engine (Konva-compatible)
21012
+ * @private
21013
21013
  */
21014
21014
  _layoutTextAdvanced() {
21015
21015
  const options = this._getAdvancedLayoutOptions();
21016
21016
  return layoutText(options);
21017
21017
  }
21018
21018
 
21019
- /**
21020
- * Get advanced layout options from current text properties
21021
- * @private
21019
+ /**
21020
+ * Get advanced layout options from current text properties
21021
+ * @private
21022
21022
  */
21023
21023
  _getAdvancedLayoutOptions() {
21024
21024
  return {
@@ -21040,9 +21040,9 @@ class FabricText extends StyledText {
21040
21040
  };
21041
21041
  }
21042
21042
 
21043
- /**
21044
- * Map Fabric textAlign to Konva align format
21045
- * @private
21043
+ /**
21044
+ * Map Fabric textAlign to Konva align format
21045
+ * @private
21046
21046
  */
21047
21047
  _mapTextAlignToAlign(textAlign) {
21048
21048
  switch (textAlign) {
@@ -21063,8 +21063,8 @@ class FabricText extends StyledText {
21063
21063
  }
21064
21064
  }
21065
21065
 
21066
- /**
21067
- * Enhanced initDimensions that uses advanced layout when enabled
21066
+ /**
21067
+ * Enhanced initDimensions that uses advanced layout when enabled
21068
21068
  */
21069
21069
  initDimensionsAdvanced() {
21070
21070
  if (!this.enableAdvancedLayout) {
@@ -21093,9 +21093,9 @@ class FabricText extends StyledText {
21093
21093
  this.dirty = true;
21094
21094
  }
21095
21095
 
21096
- /**
21097
- * Convert new layout format to legacy _textLines and __charBounds format
21098
- * @private
21096
+ /**
21097
+ * Convert new layout format to legacy _textLines and __charBounds format
21098
+ * @private
21099
21099
  */
21100
21100
  _convertLayoutToLegacyFormat(layout) {
21101
21101
  this._textLines = layout.lines.map(line => line.graphemes);
@@ -21117,30 +21117,30 @@ class FabricText extends StyledText {
21117
21117
  }
21118
21118
  }
21119
21119
 
21120
- /**
21121
- * Detect if the text line is ended with an hard break
21122
- * text and itext do not have wrapping, return false
21123
- * @return {Boolean}
21120
+ /**
21121
+ * Detect if the text line is ended with an hard break
21122
+ * text and itext do not have wrapping, return false
21123
+ * @return {Boolean}
21124
21124
  */
21125
21125
  isEndOfWrapping(lineIndex) {
21126
21126
  return lineIndex === this._textLines.length - 1;
21127
21127
  }
21128
21128
 
21129
- /**
21130
- * Detect if a line has a linebreak and so we need to account for it when moving
21131
- * and counting style.
21132
- * It return always 1 for text and Itext. Textbox has its own implementation
21133
- * @return Number
21129
+ /**
21130
+ * Detect if a line has a linebreak and so we need to account for it when moving
21131
+ * and counting style.
21132
+ * It return always 1 for text and Itext. Textbox has its own implementation
21133
+ * @return Number
21134
21134
  */
21135
21135
 
21136
21136
  missingNewlineOffset(_lineIndex) {
21137
21137
  return 1;
21138
21138
  }
21139
21139
 
21140
- /**
21141
- * Returns 2d representation (lineIndex and charIndex) of cursor
21142
- * @param {Number} selectionStart
21143
- * @param {Boolean} [skipWrapping] consider the location for unwrapped lines. useful to manage styles.
21140
+ /**
21141
+ * Returns 2d representation (lineIndex and charIndex) of cursor
21142
+ * @param {Number} selectionStart
21143
+ * @param {Boolean} [skipWrapping] consider the location for unwrapped lines. useful to manage styles.
21144
21144
  */
21145
21145
  get2DCursorLocation(selectionStart, skipWrapping) {
21146
21146
  const lines = skipWrapping ? this._unwrappedTextLines : this._textLines;
@@ -21160,24 +21160,24 @@ class FabricText extends StyledText {
21160
21160
  };
21161
21161
  }
21162
21162
 
21163
- /**
21164
- * Returns string representation of an instance
21165
- * @return {String} String representation of text object
21163
+ /**
21164
+ * Returns string representation of an instance
21165
+ * @return {String} String representation of text object
21166
21166
  */
21167
21167
  toString() {
21168
21168
  return `#<Text (${this.complexity()}): { "text": "${this.text}", "fontFamily": "${this.fontFamily}" }>`;
21169
21169
  }
21170
21170
 
21171
- /**
21172
- * Return the dimension and the zoom level needed to create a cache canvas
21173
- * big enough to host the object to be cached.
21174
- * @private
21175
- * @param {Object} dim.x width of object to be cached
21176
- * @param {Object} dim.y height of object to be cached
21177
- * @return {Object}.width width of canvas
21178
- * @return {Object}.height height of canvas
21179
- * @return {Object}.zoomX zoomX zoom value to unscale the canvas before drawing cache
21180
- * @return {Object}.zoomY zoomY zoom value to unscale the canvas before drawing cache
21171
+ /**
21172
+ * Return the dimension and the zoom level needed to create a cache canvas
21173
+ * big enough to host the object to be cached.
21174
+ * @private
21175
+ * @param {Object} dim.x width of object to be cached
21176
+ * @param {Object} dim.y height of object to be cached
21177
+ * @return {Object}.width width of canvas
21178
+ * @return {Object}.height height of canvas
21179
+ * @return {Object}.zoomX zoomX zoom value to unscale the canvas before drawing cache
21180
+ * @return {Object}.zoomY zoomY zoom value to unscale the canvas before drawing cache
21181
21181
  */
21182
21182
  _getCacheCanvasDimensions() {
21183
21183
  const dims = super._getCacheCanvasDimensions();
@@ -21187,9 +21187,9 @@ class FabricText extends StyledText {
21187
21187
  return dims;
21188
21188
  }
21189
21189
 
21190
- /**
21191
- * @private
21192
- * @param {CanvasRenderingContext2D} ctx Context to render on
21190
+ /**
21191
+ * @private
21192
+ * @param {CanvasRenderingContext2D} ctx Context to render on
21193
21193
  */
21194
21194
  _render(ctx) {
21195
21195
  const path = this.path;
@@ -21202,9 +21202,9 @@ class FabricText extends StyledText {
21202
21202
  this._renderTextDecoration(ctx, 'linethrough');
21203
21203
  }
21204
21204
 
21205
- /**
21206
- * @private
21207
- * @param {CanvasRenderingContext2D} ctx Context to render on
21205
+ /**
21206
+ * @private
21207
+ * @param {CanvasRenderingContext2D} ctx Context to render on
21208
21208
  */
21209
21209
  _renderText(ctx) {
21210
21210
  // Skip text rendering if in overlay editing mode
@@ -21220,15 +21220,15 @@ class FabricText extends StyledText {
21220
21220
  }
21221
21221
  }
21222
21222
 
21223
- /**
21224
- * Set the font parameter of the context with the object properties or with charStyle
21225
- * @private
21226
- * @param {CanvasRenderingContext2D} ctx Context to render on
21227
- * @param {Object} [charStyle] object with font style properties
21228
- * @param {String} [charStyle.fontFamily] Font Family
21229
- * @param {Number} [charStyle.fontSize] Font size in pixels. ( without px suffix )
21230
- * @param {String} [charStyle.fontWeight] Font weight
21231
- * @param {String} [charStyle.fontStyle] Font style (italic|normal)
21223
+ /**
21224
+ * Set the font parameter of the context with the object properties or with charStyle
21225
+ * @private
21226
+ * @param {CanvasRenderingContext2D} ctx Context to render on
21227
+ * @param {Object} [charStyle] object with font style properties
21228
+ * @param {String} [charStyle.fontFamily] Font Family
21229
+ * @param {Number} [charStyle.fontSize] Font size in pixels. ( without px suffix )
21230
+ * @param {String} [charStyle.fontWeight] Font weight
21231
+ * @param {String} [charStyle.fontStyle] Font style (italic|normal)
21232
21232
  */
21233
21233
  _setTextStyles(ctx, charStyle, forMeasuring) {
21234
21234
  ctx.textBaseline = 'alphabetic';
@@ -21248,11 +21248,11 @@ class FabricText extends StyledText {
21248
21248
  ctx.font = this._getFontDeclaration(charStyle, forMeasuring);
21249
21249
  }
21250
21250
 
21251
- /**
21252
- * calculate and return the text Width measuring each line.
21253
- * @private
21254
- * @param {CanvasRenderingContext2D} ctx Context to render on
21255
- * @return {Number} Maximum width of Text object
21251
+ /**
21252
+ * calculate and return the text Width measuring each line.
21253
+ * @private
21254
+ * @param {CanvasRenderingContext2D} ctx Context to render on
21255
+ * @return {Number} Maximum width of Text object
21256
21256
  */
21257
21257
  calcTextWidth() {
21258
21258
  let maxWidth = this.getLineWidth(0);
@@ -21265,23 +21265,23 @@ class FabricText extends StyledText {
21265
21265
  return maxWidth;
21266
21266
  }
21267
21267
 
21268
- /**
21269
- * @private
21270
- * @param {String} method Method name ("fillText" or "strokeText")
21271
- * @param {CanvasRenderingContext2D} ctx Context to render on
21272
- * @param {String} line Text to render
21273
- * @param {Number} left Left position of text
21274
- * @param {Number} top Top position of text
21275
- * @param {Number} lineIndex Index of a line in a text
21268
+ /**
21269
+ * @private
21270
+ * @param {String} method Method name ("fillText" or "strokeText")
21271
+ * @param {CanvasRenderingContext2D} ctx Context to render on
21272
+ * @param {String} line Text to render
21273
+ * @param {Number} left Left position of text
21274
+ * @param {Number} top Top position of text
21275
+ * @param {Number} lineIndex Index of a line in a text
21276
21276
  */
21277
21277
  _renderTextLine(method, ctx, line, left, top, lineIndex) {
21278
21278
  this._renderChars(method, ctx, line, left, top, lineIndex);
21279
21279
  }
21280
21280
 
21281
- /**
21282
- * Renders the text background for lines, taking care of style
21283
- * @private
21284
- * @param {CanvasRenderingContext2D} ctx Context to render on
21281
+ /**
21282
+ * Renders the text background for lines, taking care of style
21283
+ * @private
21284
+ * @param {CanvasRenderingContext2D} ctx Context to render on
21285
21285
  */
21286
21286
  _renderTextLinesBackground(ctx) {
21287
21287
  if (!this.textBackgroundColor && !this.styleHas('textBackgroundColor')) {
@@ -21344,15 +21344,15 @@ class FabricText extends StyledText {
21344
21344
  this._removeShadow(ctx);
21345
21345
  }
21346
21346
 
21347
- /**
21348
- * measure and return the width of a single character.
21349
- * possibly overridden to accommodate different measure logic or
21350
- * to hook some external lib for character measurement
21351
- * @private
21352
- * @param {String} _char, char to be measured
21353
- * @param {Object} charStyle style of char to be measured
21354
- * @param {String} [previousChar] previous char
21355
- * @param {Object} [prevCharStyle] style of previous char
21347
+ /**
21348
+ * measure and return the width of a single character.
21349
+ * possibly overridden to accommodate different measure logic or
21350
+ * to hook some external lib for character measurement
21351
+ * @private
21352
+ * @param {String} _char, char to be measured
21353
+ * @param {Object} charStyle style of char to be measured
21354
+ * @param {String} [previousChar] previous char
21355
+ * @param {Object} [prevCharStyle] style of previous char
21356
21356
  */
21357
21357
  _measureChar(_char, charStyle, previousChar, prevCharStyle) {
21358
21358
  const fontCache = cache.getFontCache(charStyle),
@@ -21397,19 +21397,19 @@ class FabricText extends StyledText {
21397
21397
  };
21398
21398
  }
21399
21399
 
21400
- /**
21401
- * Computes height of character at given position
21402
- * @param {Number} line the line index number
21403
- * @param {Number} _char the character index number
21404
- * @return {Number} fontSize of the character
21400
+ /**
21401
+ * Computes height of character at given position
21402
+ * @param {Number} line the line index number
21403
+ * @param {Number} _char the character index number
21404
+ * @return {Number} fontSize of the character
21405
21405
  */
21406
21406
  getHeightOfChar(line, _char) {
21407
21407
  return this.getValueOfPropertyAt(line, _char, 'fontSize');
21408
21408
  }
21409
21409
 
21410
- /**
21411
- * measure a text line measuring all characters.
21412
- * @param {Number} lineIndex line number
21410
+ /**
21411
+ * measure a text line measuring all characters.
21412
+ * @param {Number} lineIndex line number
21413
21413
  */
21414
21414
  measureLine(lineIndex) {
21415
21415
  const lineInfo = this._measureLine(lineIndex);
@@ -21422,11 +21422,11 @@ class FabricText extends StyledText {
21422
21422
  return lineInfo;
21423
21423
  }
21424
21424
 
21425
- /**
21426
- * measure every grapheme of a line, populating __charBounds
21427
- * @param {Number} lineIndex
21428
- * @return {Object} object.width total width of characters
21429
- * @return {Object} object.numOfSpaces length of chars that match this._reSpacesAndTabs
21425
+ /**
21426
+ * measure every grapheme of a line, populating __charBounds
21427
+ * @param {Number} lineIndex
21428
+ * @return {Object} object.width total width of characters
21429
+ * @return {Object} object.numOfSpaces length of chars that match this._reSpacesAndTabs
21430
21430
  */
21431
21431
  _measureLine(lineIndex) {
21432
21432
  let width = 0,
@@ -21489,13 +21489,13 @@ class FabricText extends StyledText {
21489
21489
  };
21490
21490
  }
21491
21491
 
21492
- /**
21493
- * Calculate the angle and the left,top position of the char that follow a path.
21494
- * It appends it to graphemeInfo to be reused later at rendering
21495
- * @private
21496
- * @param {Number} positionInPath to be measured
21497
- * @param {GraphemeBBox} graphemeInfo current grapheme box information
21498
- * @param {Object} startingPoint position of the point
21492
+ /**
21493
+ * Calculate the angle and the left,top position of the char that follow a path.
21494
+ * It appends it to graphemeInfo to be reused later at rendering
21495
+ * @private
21496
+ * @param {Number} positionInPath to be measured
21497
+ * @param {GraphemeBBox} graphemeInfo current grapheme box information
21498
+ * @param {Object} startingPoint position of the point
21499
21499
  */
21500
21500
  _setGraphemeOnPath(positionInPath, graphemeInfo) {
21501
21501
  const centerPosition = positionInPath + graphemeInfo.kernedWidth / 2,
@@ -21508,13 +21508,13 @@ class FabricText extends StyledText {
21508
21508
  graphemeInfo.angle = info.angle + (this.pathSide === RIGHT ? Math.PI : 0);
21509
21509
  }
21510
21510
 
21511
- /**
21512
- *
21513
- * @param {String} grapheme to be measured
21514
- * @param {Number} lineIndex index of the line where the char is
21515
- * @param {Number} charIndex position in the line
21516
- * @param {String} [prevGrapheme] character preceding the one to be measured
21517
- * @returns {GraphemeBBox} grapheme bbox
21511
+ /**
21512
+ *
21513
+ * @param {String} grapheme to be measured
21514
+ * @param {Number} lineIndex index of the line where the char is
21515
+ * @param {Number} charIndex position in the line
21516
+ * @param {String} [prevGrapheme] character preceding the one to be measured
21517
+ * @returns {GraphemeBBox} grapheme bbox
21518
21518
  */
21519
21519
  _getGraphemeBox(grapheme, lineIndex, charIndex, prevGrapheme, skipLeft) {
21520
21520
  const style = this.getCompleteStyleDeclaration(lineIndex, charIndex),
@@ -21542,10 +21542,10 @@ class FabricText extends StyledText {
21542
21542
  return box;
21543
21543
  }
21544
21544
 
21545
- /**
21546
- * Calculate height of line at 'lineIndex'
21547
- * @param {Number} lineIndex index of line to calculate
21548
- * @return {Number}
21545
+ /**
21546
+ * Calculate height of line at 'lineIndex'
21547
+ * @param {Number} lineIndex index of line to calculate
21548
+ * @return {Number}
21549
21549
  */
21550
21550
  getHeightOfLine(lineIndex) {
21551
21551
  if (this.__lineHeights[lineIndex]) {
@@ -21561,8 +21561,8 @@ class FabricText extends StyledText {
21561
21561
  return this.__lineHeights[lineIndex] = maxHeight * this.lineHeight * this._fontSizeMult;
21562
21562
  }
21563
21563
 
21564
- /**
21565
- * Calculate text box height
21564
+ /**
21565
+ * Calculate text box height
21566
21566
  */
21567
21567
  calcTextHeight() {
21568
21568
  let lineHeight,
@@ -21574,26 +21574,26 @@ class FabricText extends StyledText {
21574
21574
  return height;
21575
21575
  }
21576
21576
 
21577
- /**
21578
- * @private
21579
- * @return {Number} Left offset
21577
+ /**
21578
+ * @private
21579
+ * @return {Number} Left offset
21580
21580
  */
21581
21581
  _getLeftOffset() {
21582
21582
  return this.direction === 'ltr' ? -this.width / 2 : this.width / 2;
21583
21583
  }
21584
21584
 
21585
- /**
21586
- * @private
21587
- * @return {Number} Top offset
21585
+ /**
21586
+ * @private
21587
+ * @return {Number} Top offset
21588
21588
  */
21589
21589
  _getTopOffset() {
21590
21590
  return -this.height / 2;
21591
21591
  }
21592
21592
 
21593
- /**
21594
- * @private
21595
- * @param {CanvasRenderingContext2D} ctx Context to render on
21596
- * @param {String} method Method name ("fillText" or "strokeText")
21593
+ /**
21594
+ * @private
21595
+ * @param {CanvasRenderingContext2D} ctx Context to render on
21596
+ * @param {String} method Method name ("fillText" or "strokeText")
21597
21597
  */
21598
21598
  _renderTextCommon(ctx, method) {
21599
21599
  ctx.save();
@@ -21610,9 +21610,9 @@ class FabricText extends StyledText {
21610
21610
  ctx.restore();
21611
21611
  }
21612
21612
 
21613
- /**
21614
- * @private
21615
- * @param {CanvasRenderingContext2D} ctx Context to render on
21613
+ /**
21614
+ * @private
21615
+ * @param {CanvasRenderingContext2D} ctx Context to render on
21616
21616
  */
21617
21617
  _renderTextFill(ctx) {
21618
21618
  if (!this.fill && !this.styleHas(FILL)) {
@@ -21621,9 +21621,9 @@ class FabricText extends StyledText {
21621
21621
  this._renderTextCommon(ctx, 'fillText');
21622
21622
  }
21623
21623
 
21624
- /**
21625
- * @private
21626
- * @param {CanvasRenderingContext2D} ctx Context to render on
21624
+ /**
21625
+ * @private
21626
+ * @param {CanvasRenderingContext2D} ctx Context to render on
21627
21627
  */
21628
21628
  _renderTextStroke(ctx) {
21629
21629
  if ((!this.stroke || this.strokeWidth === 0) && this.isEmptyStyles()) {
@@ -21640,14 +21640,14 @@ class FabricText extends StyledText {
21640
21640
  ctx.restore();
21641
21641
  }
21642
21642
 
21643
- /**
21644
- * @private
21645
- * @param {String} method fillText or strokeText.
21646
- * @param {CanvasRenderingContext2D} ctx Context to render on
21647
- * @param {Array} line Content of the line, splitted in an array by grapheme
21648
- * @param {Number} left
21649
- * @param {Number} top
21650
- * @param {Number} lineIndex
21643
+ /**
21644
+ * @private
21645
+ * @param {String} method fillText or strokeText.
21646
+ * @param {CanvasRenderingContext2D} ctx Context to render on
21647
+ * @param {Array} line Content of the line, splitted in an array by grapheme
21648
+ * @param {Number} left
21649
+ * @param {Number} top
21650
+ * @param {Number} lineIndex
21651
21651
  */
21652
21652
  _renderChars(method, ctx, line, left, top, lineIndex) {
21653
21653
  const lineHeight = this.getHeightOfLine(lineIndex),
@@ -21729,16 +21729,16 @@ class FabricText extends StyledText {
21729
21729
  ctx.restore();
21730
21730
  }
21731
21731
 
21732
- /**
21733
- * This function try to patch the missing gradientTransform on canvas gradients.
21734
- * transforming a context to transform the gradient, is going to transform the stroke too.
21735
- * we want to transform the gradient but not the stroke operation, so we create
21736
- * a transformed gradient on a pattern and then we use the pattern instead of the gradient.
21737
- * this method has drawbacks: is slow, is in low resolution, needs a patch for when the size
21738
- * is limited.
21739
- * @private
21740
- * @param {TFiller} filler a fabric gradient instance
21741
- * @return {CanvasPattern} a pattern to use as fill/stroke style
21732
+ /**
21733
+ * This function try to patch the missing gradientTransform on canvas gradients.
21734
+ * transforming a context to transform the gradient, is going to transform the stroke too.
21735
+ * we want to transform the gradient but not the stroke operation, so we create
21736
+ * a transformed gradient on a pattern and then we use the pattern instead of the gradient.
21737
+ * this method has drawbacks: is slow, is in low resolution, needs a patch for when the size
21738
+ * is limited.
21739
+ * @private
21740
+ * @param {TFiller} filler a fabric gradient instance
21741
+ * @return {CanvasPattern} a pattern to use as fill/stroke style
21742
21742
  */
21743
21743
  _applyPatternGradientTransformText(filler) {
21744
21744
  // TODO: verify compatibility with strokeUniform
@@ -21794,12 +21794,12 @@ class FabricText extends StyledText {
21794
21794
  };
21795
21795
  }
21796
21796
 
21797
- /**
21798
- * This function prepare the canvas for a stroke style, and stroke and strokeWidth
21799
- * need to be sent in as defined
21800
- * @param {CanvasRenderingContext2D} ctx
21801
- * @param {CompleteTextStyleDeclaration} style with stroke and strokeWidth defined
21802
- * @returns
21797
+ /**
21798
+ * This function prepare the canvas for a stroke style, and stroke and strokeWidth
21799
+ * need to be sent in as defined
21800
+ * @param {CanvasRenderingContext2D} ctx
21801
+ * @param {CompleteTextStyleDeclaration} style with stroke and strokeWidth defined
21802
+ * @returns
21803
21803
  */
21804
21804
  _setStrokeStyles(ctx, _ref) {
21805
21805
  let {
@@ -21814,12 +21814,12 @@ class FabricText extends StyledText {
21814
21814
  return this.handleFiller(ctx, 'strokeStyle', stroke);
21815
21815
  }
21816
21816
 
21817
- /**
21818
- * This function prepare the canvas for a ill style, and fill
21819
- * need to be sent in as defined
21820
- * @param {CanvasRenderingContext2D} ctx
21821
- * @param {CompleteTextStyleDeclaration} style with ill defined
21822
- * @returns
21817
+ /**
21818
+ * This function prepare the canvas for a ill style, and fill
21819
+ * need to be sent in as defined
21820
+ * @param {CanvasRenderingContext2D} ctx
21821
+ * @param {CompleteTextStyleDeclaration} style with ill defined
21822
+ * @returns
21823
21823
  */
21824
21824
  _setFillStyles(ctx, _ref2) {
21825
21825
  let {
@@ -21828,16 +21828,16 @@ class FabricText extends StyledText {
21828
21828
  return this.handleFiller(ctx, 'fillStyle', fill);
21829
21829
  }
21830
21830
 
21831
- /**
21832
- * @private
21833
- * @param {String} method
21834
- * @param {CanvasRenderingContext2D} ctx Context to render on
21835
- * @param {Number} lineIndex
21836
- * @param {Number} charIndex
21837
- * @param {String} _char
21838
- * @param {Number} left Left coordinate
21839
- * @param {Number} top Top coordinate
21840
- * @param {Number} lineHeight Height of the line
21831
+ /**
21832
+ * @private
21833
+ * @param {String} method
21834
+ * @param {CanvasRenderingContext2D} ctx Context to render on
21835
+ * @param {Number} lineIndex
21836
+ * @param {Number} charIndex
21837
+ * @param {String} _char
21838
+ * @param {Number} left Left coordinate
21839
+ * @param {Number} top Top coordinate
21840
+ * @param {Number} lineHeight Height of the line
21841
21841
  */
21842
21842
  _renderChar(method, ctx, lineIndex, charIndex, _char, left, top) {
21843
21843
  const decl = this._getStyleDeclaration(lineIndex, charIndex),
@@ -21866,30 +21866,30 @@ class FabricText extends StyledText {
21866
21866
  ctx.restore();
21867
21867
  }
21868
21868
 
21869
- /**
21870
- * Turns the character into a 'superior figure' (i.e. 'superscript')
21871
- * @param {Number} start selection start
21872
- * @param {Number} end selection end
21869
+ /**
21870
+ * Turns the character into a 'superior figure' (i.e. 'superscript')
21871
+ * @param {Number} start selection start
21872
+ * @param {Number} end selection end
21873
21873
  */
21874
21874
  setSuperscript(start, end) {
21875
21875
  this._setScript(start, end, this.superscript);
21876
21876
  }
21877
21877
 
21878
- /**
21879
- * Turns the character into an 'inferior figure' (i.e. 'subscript')
21880
- * @param {Number} start selection start
21881
- * @param {Number} end selection end
21878
+ /**
21879
+ * Turns the character into an 'inferior figure' (i.e. 'subscript')
21880
+ * @param {Number} start selection start
21881
+ * @param {Number} end selection end
21882
21882
  */
21883
21883
  setSubscript(start, end) {
21884
21884
  this._setScript(start, end, this.subscript);
21885
21885
  }
21886
21886
 
21887
- /**
21888
- * Applies 'schema' at given position
21889
- * @private
21890
- * @param {Number} start selection start
21891
- * @param {Number} end selection end
21892
- * @param {Number} schema
21887
+ /**
21888
+ * Applies 'schema' at given position
21889
+ * @private
21890
+ * @param {Number} start selection start
21891
+ * @param {Number} end selection end
21892
+ * @param {Number} schema
21893
21893
  */
21894
21894
  _setScript(start, end, schema) {
21895
21895
  const loc = this.get2DCursorLocation(start, true),
@@ -21902,10 +21902,10 @@ class FabricText extends StyledText {
21902
21902
  this.setSelectionStyles(style, start, end);
21903
21903
  }
21904
21904
 
21905
- /**
21906
- * @private
21907
- * @param {Number} lineIndex index text line
21908
- * @return {Number} Line left offset
21905
+ /**
21906
+ * @private
21907
+ * @param {Number} lineIndex index text line
21908
+ * @return {Number} Line left offset
21909
21909
  */
21910
21910
  _getLineLeftOffset(lineIndex) {
21911
21911
  const lineWidth = this.getLineWidth(lineIndex),
@@ -21955,8 +21955,8 @@ class FabricText extends StyledText {
21955
21955
  return leftOffset;
21956
21956
  }
21957
21957
 
21958
- /**
21959
- * @private
21958
+ /**
21959
+ * @private
21960
21960
  */
21961
21961
  _clearCache() {
21962
21962
  this._forceClearCache = false;
@@ -21965,12 +21965,12 @@ class FabricText extends StyledText {
21965
21965
  this.__charBounds = [];
21966
21966
  }
21967
21967
 
21968
- /**
21969
- * Measure a single line given its index. Used to calculate the initial
21970
- * text bounding box. The values are calculated and stored in __lineWidths cache.
21971
- * @private
21972
- * @param {Number} lineIndex line number
21973
- * @return {Number} Line width
21968
+ /**
21969
+ * Measure a single line given its index. Used to calculate the initial
21970
+ * text bounding box. The values are calculated and stored in __lineWidths cache.
21971
+ * @private
21972
+ * @param {Number} lineIndex line number
21973
+ * @return {Number} Line width
21974
21974
  */
21975
21975
  getLineWidth(lineIndex) {
21976
21976
  if (this.__lineWidths[lineIndex] !== undefined) {
@@ -21989,12 +21989,12 @@ class FabricText extends StyledText {
21989
21989
  return 0;
21990
21990
  }
21991
21991
 
21992
- /**
21993
- * Retrieves the value of property at given character position
21994
- * @param {Number} lineIndex the line number
21995
- * @param {Number} charIndex the character number
21996
- * @param {String} property the property name
21997
- * @returns the value of 'property'
21992
+ /**
21993
+ * Retrieves the value of property at given character position
21994
+ * @param {Number} lineIndex the line number
21995
+ * @param {Number} charIndex the character number
21996
+ * @param {String} property the property name
21997
+ * @returns the value of 'property'
21998
21998
  */
21999
21999
  getValueOfPropertyAt(lineIndex, charIndex, property) {
22000
22000
  var _charStyle$property;
@@ -22002,9 +22002,9 @@ class FabricText extends StyledText {
22002
22002
  return (_charStyle$property = charStyle[property]) !== null && _charStyle$property !== void 0 ? _charStyle$property : this[property];
22003
22003
  }
22004
22004
 
22005
- /**
22006
- * @private
22007
- * @param {CanvasRenderingContext2D} ctx Context to render on
22005
+ /**
22006
+ * @private
22007
+ * @param {CanvasRenderingContext2D} ctx Context to render on
22008
22008
  */
22009
22009
  _renderTextDecoration(ctx, type) {
22010
22010
  if (!this[type] && !this.styleHas(type)) {
@@ -22088,10 +22088,10 @@ class FabricText extends StyledText {
22088
22088
  this._removeShadow(ctx);
22089
22089
  }
22090
22090
 
22091
- /**
22092
- * return font declaration string for canvas context
22093
- * @param {Object} [styleObject] object
22094
- * @returns {String} font declaration formatted for canvas context.
22091
+ /**
22092
+ * return font declaration string for canvas context
22093
+ * @param {Object} [styleObject] object
22094
+ * @returns {String} font declaration formatted for canvas context.
22095
22095
  */
22096
22096
  _getFontDeclaration() {
22097
22097
  let {
@@ -22117,9 +22117,9 @@ class FabricText extends StyledText {
22117
22117
  return [fontStyle, fontWeight, `${forMeasuring ? this.CACHE_FONT_SIZE : fontSize}px`, parsedFontFamily].join(' ');
22118
22118
  }
22119
22119
 
22120
- /**
22121
- * Renders text instance on a specified context
22122
- * @param {CanvasRenderingContext2D} ctx Context to render on
22120
+ /**
22121
+ * Renders text instance on a specified context
22122
+ * @param {CanvasRenderingContext2D} ctx Context to render on
22123
22123
  */
22124
22124
  render(ctx) {
22125
22125
  if (!this.visible) {
@@ -22134,22 +22134,22 @@ class FabricText extends StyledText {
22134
22134
  super.render(ctx);
22135
22135
  }
22136
22136
 
22137
- /**
22138
- * Override this method to customize grapheme splitting
22139
- * @todo the util `graphemeSplit` needs to be injectable in some way.
22140
- * is more comfortable to inject the correct util rather than having to override text
22141
- * in the middle of the prototype chain
22142
- * @param {string} value
22143
- * @returns {string[]} array of graphemes
22137
+ /**
22138
+ * Override this method to customize grapheme splitting
22139
+ * @todo the util `graphemeSplit` needs to be injectable in some way.
22140
+ * is more comfortable to inject the correct util rather than having to override text
22141
+ * in the middle of the prototype chain
22142
+ * @param {string} value
22143
+ * @returns {string[]} array of graphemes
22144
22144
  */
22145
22145
  graphemeSplit(value) {
22146
22146
  return graphemeSplit(value);
22147
22147
  }
22148
22148
 
22149
- /**
22150
- * Returns the text as an array of lines.
22151
- * @param {String} text text to split
22152
- * @returns Lines in the text
22149
+ /**
22150
+ * Returns the text as an array of lines.
22151
+ * @param {String} text text to split
22152
+ * @returns Lines in the text
22153
22153
  */
22154
22154
  _splitTextIntoLines(text) {
22155
22155
  const lines = text.split(this._reNewline),
@@ -22175,18 +22175,18 @@ class FabricText extends StyledText {
22175
22175
  };
22176
22176
  }
22177
22177
 
22178
- /**
22179
- * Check if text contains Arabic characters
22180
- * @private
22178
+ /**
22179
+ * Check if text contains Arabic characters
22180
+ * @private
22181
22181
  */
22182
22182
  _containsArabicText(text) {
22183
22183
  return /[\u0600-\u06FF\u0750-\u077F\uFB50-\uFDFF\uFE70-\uFEFF]/.test(text);
22184
22184
  }
22185
22185
 
22186
- /**
22187
- * Returns object representation of an instance
22188
- * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
22189
- * @return {Object} Object representation of an instance
22186
+ /**
22187
+ * Returns object representation of an instance
22188
+ * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
22189
+ * @return {Object} Object representation of an instance
22190
22190
  */
22191
22191
  toObject() {
22192
22192
  let propertiesToInclude = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
@@ -22229,23 +22229,23 @@ class FabricText extends StyledText {
22229
22229
  return this;
22230
22230
  }
22231
22231
 
22232
- /**
22233
- * Returns complexity of an instance
22234
- * @return {Number} complexity
22232
+ /**
22233
+ * Returns complexity of an instance
22234
+ * @return {Number} complexity
22235
22235
  */
22236
22236
  complexity() {
22237
22237
  return 1;
22238
22238
  }
22239
22239
 
22240
- /**
22241
- * List of generic font families
22242
- * @see https://developer.mozilla.org/en-US/docs/Web/CSS/font-family#generic-name
22240
+ /**
22241
+ * List of generic font families
22242
+ * @see https://developer.mozilla.org/en-US/docs/Web/CSS/font-family#generic-name
22243
22243
  */
22244
22244
 
22245
- /**
22246
- * Returns FabricText instance from an SVG element (<b>not yet implemented</b>)
22247
- * @param {HTMLElement} element Element to parse
22248
- * @param {Object} [options] Options object
22245
+ /**
22246
+ * Returns FabricText instance from an SVG element (<b>not yet implemented</b>)
22247
+ * @param {HTMLElement} element Element to parse
22248
+ * @param {Object} [options] Options object
22249
22249
  */
22250
22250
  static async fromElement(element, options, cssRules) {
22251
22251
  const parsedAttributes = parseAttributes(element, FabricText.ATTRIBUTE_NAMES, cssRules);
@@ -22284,10 +22284,10 @@ class FabricText extends StyledText {
22284
22284
  scaledDiff = lineHeightDiff * textHeightScaleFactor,
22285
22285
  textHeight = text.getScaledHeight() + scaledDiff;
22286
22286
  let offX = 0;
22287
- /*
22288
- Adjust positioning:
22289
- x/y attributes in SVG correspond to the bottom-left corner of text bounding box
22290
- fabric output by default at top, left.
22287
+ /*
22288
+ Adjust positioning:
22289
+ x/y attributes in SVG correspond to the bottom-left corner of text bounding box
22290
+ fabric output by default at top, left.
22291
22291
  */
22292
22292
  if (textAnchor === CENTER) {
22293
22293
  offX = text.getScaledWidth() / 2;
@@ -22305,9 +22305,9 @@ class FabricText extends StyledText {
22305
22305
 
22306
22306
  /* _FROM_SVG_END_ */
22307
22307
 
22308
- /**
22309
- * Check if the font is ready for accurate measurements
22310
- * @private
22308
+ /**
22309
+ * Check if the font is ready for accurate measurements
22310
+ * @private
22311
22311
  */
22312
22312
  _isFontReady() {
22313
22313
  if (typeof document === 'undefined' || !('fonts' in document)) {
@@ -22320,9 +22320,9 @@ class FabricText extends StyledText {
22320
22320
  }
22321
22321
  }
22322
22322
 
22323
- /**
22324
- * Schedule re-initialization after font loads
22325
- * @private
22323
+ /**
22324
+ * Schedule re-initialization after font loads
22325
+ * @private
22326
22326
  */
22327
22327
  _scheduleInitAfterFontLoad() {
22328
22328
  if (typeof document === 'undefined' || !('fonts' in document)) {
@@ -22358,8 +22358,8 @@ class FabricText extends StyledText {
22358
22358
  });
22359
22359
  }
22360
22360
 
22361
- /**
22362
- * Force complete text re-initialization (useful after JSON loading)
22361
+ /**
22362
+ * Force complete text re-initialization (useful after JSON loading)
22363
22363
  */
22364
22364
  forceTextReinitialization() {
22365
22365
  console.log('🔄 Force reinitializing text object');
@@ -22387,10 +22387,10 @@ class FabricText extends StyledText {
22387
22387
  }
22388
22388
  }
22389
22389
 
22390
- /**
22391
- * Returns FabricText instance from an object representation
22392
- * @param {Object} object plain js Object to create an instance from
22393
- * @returns {Promise<FabricText>}
22390
+ /**
22391
+ * Returns FabricText instance from an object representation
22392
+ * @param {Object} object plain js Object to create an instance from
22393
+ * @returns {Promise<FabricText>}
22394
22394
  */
22395
22395
  static fromObject(object) {
22396
22396
  return this._fromObject({
@@ -22492,10 +22492,10 @@ class FabricText extends StyledText {
22492
22492
  });
22493
22493
  }
22494
22494
  }
22495
- /**
22496
- * Properties that requires a text layout recalculation when changed
22497
- * @type string[]
22498
- * @protected
22495
+ /**
22496
+ * Properties that requires a text layout recalculation when changed
22497
+ * @type string[]
22498
+ * @protected
22499
22499
  */
22500
22500
  _defineProperty(FabricText, "textLayoutProperties", textLayoutProperties);
22501
22501
  _defineProperty(FabricText, "cacheProperties", [...cacheProperties, ...additionalProps]);
@@ -22503,9 +22503,9 @@ _defineProperty(FabricText, "ownDefaults", textDefaultValues);
22503
22503
  _defineProperty(FabricText, "type", 'Text');
22504
22504
  _defineProperty(FabricText, "genericFonts", ['serif', 'sans-serif', 'monospace', 'cursive', 'fantasy', 'system-ui', 'ui-serif', 'ui-sans-serif', 'ui-monospace', 'ui-rounded', 'math', 'emoji', 'fangsong']);
22505
22505
  /* _FROM_SVG_START_ */
22506
- /**
22507
- * List of attribute names to account for when parsing SVG element (used by {@link FabricText.fromElement})
22508
- * @see: http://www.w3.org/TR/SVG/text.html#TextElement
22506
+ /**
22507
+ * List of attribute names to account for when parsing SVG element (used by {@link FabricText.fromElement})
22508
+ * @see: http://www.w3.org/TR/SVG/text.html#TextElement
22509
22509
  */
22510
22510
  _defineProperty(FabricText, "ATTRIBUTE_NAMES", SHARED_ATTRIBUTES.concat('x', 'y', 'dx', 'dy', 'font-family', 'font-style', 'font-weight', 'font-size', 'letter-spacing', 'text-decoration', 'text-anchor'));
22511
22511
  applyMixins(FabricText, [TextSVGExportMixin]);
@@ -26644,11 +26644,11 @@ const textboxDefaultValues = {
26644
26644
 
26645
26645
  // @TODO this is not complete
26646
26646
 
26647
- /**
26648
- * Textbox class, based on IText, allows the user to resize the text rectangle
26649
- * and wraps lines automatically. Textboxes have their Y scaling locked, the
26650
- * user can only change width. Height is adjusted automatically based on the
26651
- * wrapping of lines.
26647
+ /**
26648
+ * Textbox class, based on IText, allows the user to resize the text rectangle
26649
+ * and wraps lines automatically. Textboxes have their Y scaling locked, the
26650
+ * user can only change width. Height is adjusted automatically based on the
26651
+ * wrapping of lines.
26652
26652
  */
26653
26653
  class Textbox extends IText {
26654
26654
  static getDefaults() {
@@ -26658,10 +26658,10 @@ class Textbox extends IText {
26658
26658
  };
26659
26659
  }
26660
26660
 
26661
- /**
26662
- * Constructor
26663
- * @param {String} text Text string
26664
- * @param {Object} [options] Options object
26661
+ /**
26662
+ * Constructor
26663
+ * @param {String} text Text string
26664
+ * @param {Object} [options] Options object
26665
26665
  */
26666
26666
  constructor(text, options) {
26667
26667
  super(text, {
@@ -26671,10 +26671,10 @@ class Textbox extends IText {
26671
26671
  this.initializeEventListeners();
26672
26672
  }
26673
26673
 
26674
- /**
26675
- * Creates the default control object.
26676
- * If you prefer to have on instance of controls shared among all objects
26677
- * make this function return an empty object and add controls to the ownDefaults object
26674
+ /**
26675
+ * Creates the default control object.
26676
+ * If you prefer to have on instance of controls shared among all objects
26677
+ * make this function return an empty object and add controls to the ownDefaults object
26678
26678
  */
26679
26679
  static createControls() {
26680
26680
  return {
@@ -26682,11 +26682,11 @@ class Textbox extends IText {
26682
26682
  };
26683
26683
  }
26684
26684
 
26685
- /**
26686
- * Unlike superclass's version of this function, Textbox does not update
26687
- * its width.
26688
- * @private
26689
- * @override
26685
+ /**
26686
+ * Unlike superclass's version of this function, Textbox does not update
26687
+ * its width.
26688
+ * @private
26689
+ * @override
26690
26690
  */
26691
26691
  initDimensions() {
26692
26692
  if (!this.initialized) {
@@ -26754,6 +26754,7 @@ class Textbox extends IText {
26754
26754
  if (this._usingBrowserWrapping) {
26755
26755
  this._browserWrapInitialized = true;
26756
26756
  }
26757
+ this.calcTextWidth();
26757
26758
  if (this.textAlign.includes(JUSTIFY)) {
26758
26759
  // For browser wrapping fonts, apply browser-calculated justify spaces
26759
26760
  if (this._usingBrowserWrapping) {
@@ -26828,11 +26829,38 @@ class Textbox extends IText {
26828
26829
  } else {
26829
26830
  this.height = this.calcTextHeight();
26830
26831
  }
26832
+
26833
+ // Double-check that justify was applied by checking space widths
26834
+ if (this.textAlign.includes('justify') && this.__charBounds) {
26835
+ setTimeout(() => {
26836
+ // Verify justify was applied by checking if space widths vary
26837
+ let hasVariableSpaces = false;
26838
+ this.__charBounds.forEach((lineBounds, i) => {
26839
+ if (lineBounds && this._textLines && this._textLines[i]) {
26840
+ const spaces = lineBounds.filter((bound, j) => /\s/.test(this._textLines[i][j]));
26841
+ if (spaces.length > 1) {
26842
+ const firstSpaceWidth = spaces[0].width;
26843
+ hasVariableSpaces = spaces.some(space => Math.abs(space.width - firstSpaceWidth) > 0.1);
26844
+ }
26845
+ }
26846
+ });
26847
+ if (!hasVariableSpaces && this.__charBounds.length > 0) {
26848
+ console.warn(' ⚠️ Justify spaces still uniform - forcing enlargeSpaces again');
26849
+ if (this.enlargeSpaces) {
26850
+ var _this$canvas3;
26851
+ this.enlargeSpaces();
26852
+ (_this$canvas3 = this.canvas) === null || _this$canvas3 === void 0 || _this$canvas3.requestRenderAll();
26853
+ }
26854
+ } else {
26855
+ console.log(' ✅ Justify spaces properly expanded');
26856
+ }
26857
+ }, 10);
26858
+ }
26831
26859
  }
26832
26860
 
26833
- /**
26834
- * Schedule justify calculation after font loads (Textbox-specific)
26835
- * @private
26861
+ /**
26862
+ * Schedule justify calculation after font loads (Textbox-specific)
26863
+ * @private
26836
26864
  */
26837
26865
  _scheduleJustifyAfterFontLoad() {
26838
26866
  if (typeof document === 'undefined' || !('fonts' in document)) {
@@ -26846,22 +26874,22 @@ class Textbox extends IText {
26846
26874
  this._fontJustifyScheduled = true;
26847
26875
  const fontSpec = `${this.fontSize}px ${this.fontFamily}`;
26848
26876
  document.fonts.load(fontSpec).then(() => {
26849
- var _this$canvas3;
26877
+ var _this$canvas4;
26850
26878
  this._fontJustifyScheduled = false;
26851
26879
  console.log('🔧 Textbox: Font loaded, applying justify alignment');
26852
26880
 
26853
26881
  // Re-run initDimensions to ensure proper justify calculation
26854
26882
  this.initDimensions();
26855
- (_this$canvas3 = this.canvas) === null || _this$canvas3 === void 0 || _this$canvas3.requestRenderAll();
26883
+ (_this$canvas4 = this.canvas) === null || _this$canvas4 === void 0 || _this$canvas4.requestRenderAll();
26856
26884
  }).catch(() => {
26857
26885
  this._fontJustifyScheduled = false;
26858
26886
  console.warn('⚠️ Textbox: Font loading failed, justify may be incorrect');
26859
26887
  });
26860
26888
  }
26861
26889
 
26862
- /**
26863
- * Advanced dimensions calculation using new layout engine
26864
- * @private
26890
+ /**
26891
+ * Advanced dimensions calculation using new layout engine
26892
+ * @private
26865
26893
  */
26866
26894
  initDimensionsAdvanced() {
26867
26895
  if (!this.initialized) {
@@ -26916,9 +26944,9 @@ class Textbox extends IText {
26916
26944
  this.dirty = true;
26917
26945
  }
26918
26946
 
26919
- /**
26920
- * Generate style map from new layout format
26921
- * @private
26947
+ /**
26948
+ * Generate style map from new layout format
26949
+ * @private
26922
26950
  */
26923
26951
  _generateStyleMapFromLayout(layout) {
26924
26952
  const map = {};
@@ -26940,12 +26968,12 @@ class Textbox extends IText {
26940
26968
  return map;
26941
26969
  }
26942
26970
 
26943
- /**
26944
- * Generate an object that translates the style object so that it is
26945
- * broken up by visual lines (new lines and automatic wrapping).
26946
- * The original text styles object is broken up by actual lines (new lines only),
26947
- * which is only sufficient for Text / IText
26948
- * @private
26971
+ /**
26972
+ * Generate an object that translates the style object so that it is
26973
+ * broken up by visual lines (new lines and automatic wrapping).
26974
+ * The original text styles object is broken up by actual lines (new lines only),
26975
+ * which is only sufficient for Text / IText
26976
+ * @private
26949
26977
  */
26950
26978
  _generateStyleMap(textInfo) {
26951
26979
  let realLineCount = 0,
@@ -26972,10 +27000,10 @@ class Textbox extends IText {
26972
27000
  return map;
26973
27001
  }
26974
27002
 
26975
- /**
26976
- * Returns true if object has a style property or has it on a specified line
26977
- * @param {Number} lineIndex
26978
- * @return {Boolean}
27003
+ /**
27004
+ * Returns true if object has a style property or has it on a specified line
27005
+ * @param {Number} lineIndex
27006
+ * @return {Boolean}
26979
27007
  */
26980
27008
  styleHas(property, lineIndex) {
26981
27009
  if (this._styleMap && !this.isWrapping) {
@@ -26987,10 +27015,10 @@ class Textbox extends IText {
26987
27015
  return super.styleHas(property, lineIndex);
26988
27016
  }
26989
27017
 
26990
- /**
26991
- * Returns true if object has no styling or no styling in a line
26992
- * @param {Number} lineIndex , lineIndex is on wrapped lines.
26993
- * @return {Boolean}
27018
+ /**
27019
+ * Returns true if object has no styling or no styling in a line
27020
+ * @param {Number} lineIndex , lineIndex is on wrapped lines.
27021
+ * @return {Boolean}
26994
27022
  */
26995
27023
  isEmptyStyles(lineIndex) {
26996
27024
  if (!this.styles) {
@@ -27027,11 +27055,11 @@ class Textbox extends IText {
27027
27055
  return true;
27028
27056
  }
27029
27057
 
27030
- /**
27031
- * @protected
27032
- * @param {Number} lineIndex
27033
- * @param {Number} charIndex
27034
- * @return {TextStyleDeclaration} a style object reference to the existing one or a new empty object when undefined
27058
+ /**
27059
+ * @protected
27060
+ * @param {Number} lineIndex
27061
+ * @param {Number} charIndex
27062
+ * @return {TextStyleDeclaration} a style object reference to the existing one or a new empty object when undefined
27035
27063
  */
27036
27064
  _getStyleDeclaration(lineIndex, charIndex) {
27037
27065
  if (this._styleMap && !this.isWrapping) {
@@ -27045,59 +27073,59 @@ class Textbox extends IText {
27045
27073
  return super._getStyleDeclaration(lineIndex, charIndex);
27046
27074
  }
27047
27075
 
27048
- /**
27049
- * @param {Number} lineIndex
27050
- * @param {Number} charIndex
27051
- * @param {Object} style
27052
- * @private
27076
+ /**
27077
+ * @param {Number} lineIndex
27078
+ * @param {Number} charIndex
27079
+ * @param {Object} style
27080
+ * @private
27053
27081
  */
27054
27082
  _setStyleDeclaration(lineIndex, charIndex, style) {
27055
27083
  const map = this._styleMap[lineIndex];
27056
27084
  super._setStyleDeclaration(map.line, map.offset + charIndex, style);
27057
27085
  }
27058
27086
 
27059
- /**
27060
- * @param {Number} lineIndex
27061
- * @param {Number} charIndex
27062
- * @private
27087
+ /**
27088
+ * @param {Number} lineIndex
27089
+ * @param {Number} charIndex
27090
+ * @private
27063
27091
  */
27064
27092
  _deleteStyleDeclaration(lineIndex, charIndex) {
27065
27093
  const map = this._styleMap[lineIndex];
27066
27094
  super._deleteStyleDeclaration(map.line, map.offset + charIndex);
27067
27095
  }
27068
27096
 
27069
- /**
27070
- * probably broken need a fix
27071
- * Returns the real style line that correspond to the wrapped lineIndex line
27072
- * Used just to verify if the line does exist or not.
27073
- * @param {Number} lineIndex
27074
- * @returns {Boolean} if the line exists or not
27075
- * @private
27097
+ /**
27098
+ * probably broken need a fix
27099
+ * Returns the real style line that correspond to the wrapped lineIndex line
27100
+ * Used just to verify if the line does exist or not.
27101
+ * @param {Number} lineIndex
27102
+ * @returns {Boolean} if the line exists or not
27103
+ * @private
27076
27104
  */
27077
27105
  _getLineStyle(lineIndex) {
27078
27106
  const map = this._styleMap[lineIndex];
27079
27107
  return !!this.styles[map.line];
27080
27108
  }
27081
27109
 
27082
- /**
27083
- * Set the line style to an empty object so that is initialized
27084
- * @param {Number} lineIndex
27085
- * @param {Object} style
27086
- * @private
27110
+ /**
27111
+ * Set the line style to an empty object so that is initialized
27112
+ * @param {Number} lineIndex
27113
+ * @param {Object} style
27114
+ * @private
27087
27115
  */
27088
27116
  _setLineStyle(lineIndex) {
27089
27117
  const map = this._styleMap[lineIndex];
27090
27118
  super._setLineStyle(map.line);
27091
27119
  }
27092
27120
 
27093
- /**
27094
- * Wraps text using the 'width' property of Textbox. First this function
27095
- * splits text on newlines, so we preserve newlines entered by the user.
27096
- * Then it wraps each line using the width of the Textbox by calling
27097
- * _wrapLine().
27098
- * @param {Array} lines The string array of text that is split into lines
27099
- * @param {Number} desiredWidth width you want to wrap to
27100
- * @returns {Array} Array of lines
27121
+ /**
27122
+ * Wraps text using the 'width' property of Textbox. First this function
27123
+ * splits text on newlines, so we preserve newlines entered by the user.
27124
+ * Then it wraps each line using the width of the Textbox by calling
27125
+ * _wrapLine().
27126
+ * @param {Array} lines The string array of text that is split into lines
27127
+ * @param {Number} desiredWidth width you want to wrap to
27128
+ * @returns {Array} Array of lines
27101
27129
  */
27102
27130
  _wrapText(lines, desiredWidth) {
27103
27131
  this.isWrapping = true;
@@ -27111,12 +27139,12 @@ class Textbox extends IText {
27111
27139
  return wrapped;
27112
27140
  }
27113
27141
 
27114
- /**
27115
- * For each line of text terminated by an hard line stop,
27116
- * measure each word width and extract the largest word from all.
27117
- * The returned words here are the one that at the end will be rendered.
27118
- * @param {string[]} lines the lines we need to measure
27119
- *
27142
+ /**
27143
+ * For each line of text terminated by an hard line stop,
27144
+ * measure each word width and extract the largest word from all.
27145
+ * The returned words here are the one that at the end will be rendered.
27146
+ * @param {string[]} lines the lines we need to measure
27147
+ *
27120
27148
  */
27121
27149
  getGraphemeDataForRender(lines) {
27122
27150
  const splitByGrapheme = this.splitByGrapheme,
@@ -27149,17 +27177,17 @@ class Textbox extends IText {
27149
27177
  };
27150
27178
  }
27151
27179
 
27152
- /**
27153
- * Helper function to measure a string of text, given its lineIndex and charIndex offset
27154
- * It gets called when charBounds are not available yet.
27155
- * Override if necessary
27156
- * Use with {@link Textbox#wordSplit}
27157
- *
27158
- * @param {CanvasRenderingContext2D} ctx
27159
- * @param {String} text
27160
- * @param {number} lineIndex
27161
- * @param {number} charOffset
27162
- * @returns {number}
27180
+ /**
27181
+ * Helper function to measure a string of text, given its lineIndex and charIndex offset
27182
+ * It gets called when charBounds are not available yet.
27183
+ * Override if necessary
27184
+ * Use with {@link Textbox#wordSplit}
27185
+ *
27186
+ * @param {CanvasRenderingContext2D} ctx
27187
+ * @param {String} text
27188
+ * @param {number} lineIndex
27189
+ * @param {number} charOffset
27190
+ * @returns {number}
27163
27191
  */
27164
27192
  _measureWord(word, lineIndex) {
27165
27193
  let charOffset = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
@@ -27174,26 +27202,26 @@ class Textbox extends IText {
27174
27202
  return width;
27175
27203
  }
27176
27204
 
27177
- /**
27178
- * Override this method to customize word splitting
27179
- * Use with {@link Textbox#_measureWord}
27180
- * @param {string} value
27181
- * @returns {string[]} array of words
27205
+ /**
27206
+ * Override this method to customize word splitting
27207
+ * Use with {@link Textbox#_measureWord}
27208
+ * @param {string} value
27209
+ * @returns {string[]} array of words
27182
27210
  */
27183
27211
  wordSplit(value) {
27184
27212
  return value.split(this._wordJoiners);
27185
27213
  }
27186
27214
 
27187
- /**
27188
- * Wraps a line of text using the width of the Textbox as desiredWidth
27189
- * and leveraging the known width o words from GraphemeData
27190
- * @private
27191
- * @param {Number} lineIndex
27192
- * @param {Number} desiredWidth width you want to wrap the line to
27193
- * @param {GraphemeData} graphemeData an object containing all the lines' words width.
27194
- * @param {Number} reservedSpace space to remove from wrapping for custom functionalities
27195
- * @returns {Array} Array of line(s) into which the given text is wrapped
27196
- * to.
27215
+ /**
27216
+ * Wraps a line of text using the width of the Textbox as desiredWidth
27217
+ * and leveraging the known width o words from GraphemeData
27218
+ * @private
27219
+ * @param {Number} lineIndex
27220
+ * @param {Number} desiredWidth width you want to wrap the line to
27221
+ * @param {GraphemeData} graphemeData an object containing all the lines' words width.
27222
+ * @param {Number} reservedSpace space to remove from wrapping for custom functionalities
27223
+ * @returns {Array} Array of line(s) into which the given text is wrapped
27224
+ * to.
27197
27225
  */
27198
27226
  _wrapLine(lineIndex, desiredWidth, _ref) {
27199
27227
  let {
@@ -27275,11 +27303,11 @@ class Textbox extends IText {
27275
27303
  return graphemeLines;
27276
27304
  }
27277
27305
 
27278
- /**
27279
- * Detect if the text line is ended with an hard break
27280
- * text and itext do not have wrapping, return false
27281
- * @param {Number} lineIndex text to split
27282
- * @return {Boolean}
27306
+ /**
27307
+ * Detect if the text line is ended with an hard break
27308
+ * text and itext do not have wrapping, return false
27309
+ * @param {Number} lineIndex text to split
27310
+ * @return {Boolean}
27283
27311
  */
27284
27312
  isEndOfWrapping(lineIndex) {
27285
27313
  if (!this._styleMap[lineIndex + 1]) {
@@ -27293,12 +27321,12 @@ class Textbox extends IText {
27293
27321
  return false;
27294
27322
  }
27295
27323
 
27296
- /**
27297
- * Detect if a line has a linebreak and so we need to account for it when moving
27298
- * and counting style.
27299
- * This is important only for splitByGrapheme at the end of wrapping.
27300
- * If we are not wrapping the offset is always 1
27301
- * @return Number
27324
+ /**
27325
+ * Detect if a line has a linebreak and so we need to account for it when moving
27326
+ * and counting style.
27327
+ * This is important only for splitByGrapheme at the end of wrapping.
27328
+ * If we are not wrapping the offset is always 1
27329
+ * @return Number
27302
27330
  */
27303
27331
  missingNewlineOffset(lineIndex, skipWrapping) {
27304
27332
  if (this.splitByGrapheme && !skipWrapping) {
@@ -27307,12 +27335,12 @@ class Textbox extends IText {
27307
27335
  return 1;
27308
27336
  }
27309
27337
 
27310
- /**
27311
- * Gets lines of text to render in the Textbox. This function calculates
27312
- * text wrapping on the fly every time it is called.
27313
- * @param {String} text text to split
27314
- * @returns {Array} Array of lines in the Textbox.
27315
- * @override
27338
+ /**
27339
+ * Gets lines of text to render in the Textbox. This function calculates
27340
+ * text wrapping on the fly every time it is called.
27341
+ * @param {String} text text to split
27342
+ * @returns {Array} Array of lines in the Textbox.
27343
+ * @override
27316
27344
  */
27317
27345
  _splitTextIntoLines(text) {
27318
27346
  // Check if we need browser wrapping using smart font detection
@@ -27359,9 +27387,9 @@ class Textbox extends IText {
27359
27387
  return newText;
27360
27388
  }
27361
27389
 
27362
- /**
27363
- * Use browser's native text wrapping for accurate handling of fonts without English glyphs
27364
- * @private
27390
+ /**
27391
+ * Use browser's native text wrapping for accurate handling of fonts without English glyphs
27392
+ * @private
27365
27393
  */
27366
27394
  _splitTextIntoLinesWithBrowser(text) {
27367
27395
  if (typeof document === 'undefined') {
@@ -27487,9 +27515,9 @@ class Textbox extends IText {
27487
27515
  };
27488
27516
  }
27489
27517
 
27490
- /**
27491
- * Extract justify space measurements from browser
27492
- * @private
27518
+ /**
27519
+ * Extract justify space measurements from browser
27520
+ * @private
27493
27521
  */
27494
27522
  _extractJustifySpaceMeasurements(element, lines) {
27495
27523
  console.log(`🔤 Extracting browser justify space measurements for ${lines.length} lines`);
@@ -27525,9 +27553,9 @@ class Textbox extends IText {
27525
27553
  return spaceWidths;
27526
27554
  }
27527
27555
 
27528
- /**
27529
- * Apply browser-calculated justify space measurements
27530
- * @private
27556
+ /**
27557
+ * Apply browser-calculated justify space measurements
27558
+ * @private
27531
27559
  */
27532
27560
  _applyBrowserJustifySpaces() {
27533
27561
  if (!this._textLines || !this.__charBounds) {
@@ -27550,23 +27578,59 @@ class Textbox extends IText {
27550
27578
  const lineBounds = this.__charBounds[lineIndex];
27551
27579
  const lineSpaceWidths = spaceWidths[lineIndex];
27552
27580
  let spaceIndex = 0;
27581
+ let accumulatedSpace = 0;
27582
+ const isRtl = this.direction === 'rtl';
27583
+ const spaceDiffs = [];
27584
+
27585
+ // First, calculate the difference for each space
27553
27586
  for (let charIndex = 0; charIndex < line.length; charIndex++) {
27554
27587
  if (/\s/.test(line[charIndex]) && spaceIndex < lineSpaceWidths.length) {
27555
- const expandedWidth = lineSpaceWidths[spaceIndex];
27556
- if (lineBounds[charIndex]) {
27557
- const oldWidth = lineBounds[charIndex].width;
27558
- lineBounds[charIndex].width = expandedWidth;
27559
- console.log(`🔤 Line ${lineIndex} space ${spaceIndex}: ${oldWidth.toFixed(1)}px -> ${expandedWidth.toFixed(1)}px`);
27588
+ const charBound = lineBounds[charIndex];
27589
+ if (charBound) {
27590
+ spaceDiffs.push(lineSpaceWidths[spaceIndex] - charBound.width);
27560
27591
  }
27561
27592
  spaceIndex++;
27562
27593
  }
27563
27594
  }
27595
+ spaceIndex = 0;
27596
+ let remainingDiff = spaceDiffs.reduce((a, b) => a + b, 0);
27597
+ for (let charIndex = 0; charIndex < line.length; charIndex++) {
27598
+ const charBound = lineBounds[charIndex];
27599
+ if (!charBound) continue;
27600
+ if (isRtl) {
27601
+ charBound.left += remainingDiff;
27602
+ } else {
27603
+ charBound.left += accumulatedSpace;
27604
+ }
27605
+ if (/\s/.test(line[charIndex]) && spaceIndex < spaceDiffs.length) {
27606
+ const diff = spaceDiffs[spaceIndex];
27607
+ const oldWidth = charBound.width;
27608
+ charBound.width += diff;
27609
+ charBound.kernedWidth += diff;
27610
+ console.log(`🔤 Line ${lineIndex} space ${spaceIndex}: ${oldWidth.toFixed(1)}px -> ${charBound.width.toFixed(1)}px`);
27611
+ if (isRtl) {
27612
+ remainingDiff -= diff;
27613
+ } else {
27614
+ accumulatedSpace += diff;
27615
+ }
27616
+ spaceIndex++;
27617
+ }
27618
+ }
27619
+ // also need to update the last charBound
27620
+ const lastBound = lineBounds[line.length];
27621
+ if (lastBound) {
27622
+ if (isRtl) {
27623
+ lastBound.left += remainingDiff;
27624
+ } else {
27625
+ lastBound.left += accumulatedSpace;
27626
+ }
27627
+ }
27564
27628
  });
27565
27629
  }
27566
27630
 
27567
- /**
27568
- * Fallback to default Fabric wrapping
27569
- * @private
27631
+ /**
27632
+ * Fallback to default Fabric wrapping
27633
+ * @private
27570
27634
  */
27571
27635
  _splitTextIntoLinesDefault(text) {
27572
27636
  const newText = super._splitTextIntoLines(text),
@@ -27598,12 +27662,12 @@ class Textbox extends IText {
27598
27662
  }
27599
27663
  }
27600
27664
 
27601
- /**
27602
- * Initialize event listeners for safety snap functionality
27603
- * @private
27665
+ /**
27666
+ * Initialize event listeners for safety snap functionality
27667
+ * @private
27604
27668
  */
27605
27669
  initializeEventListeners() {
27606
- var _this$canvas4;
27670
+ var _this$canvas5;
27607
27671
  // Track which side is being used for resize to handle position compensation
27608
27672
  let resizeOrigin = null;
27609
27673
 
@@ -27634,7 +27698,7 @@ class Textbox extends IText {
27634
27698
  });
27635
27699
 
27636
27700
  // Also listen to canvas-level modified event as backup
27637
- (_this$canvas4 = this.canvas) === null || _this$canvas4 === void 0 || _this$canvas4.on('object:modified', e => {
27701
+ (_this$canvas5 = this.canvas) === null || _this$canvas5 === void 0 || _this$canvas5.on('object:modified', e => {
27638
27702
  if (e.target === this) {
27639
27703
  const currentResizeOrigin = resizeOrigin; // Capture the value before reset
27640
27704
  setTimeout(() => this.safetySnapWidth(currentResizeOrigin), 10);
@@ -27643,12 +27707,12 @@ class Textbox extends IText {
27643
27707
  });
27644
27708
  }
27645
27709
 
27646
- /**
27647
- * Safety snap to prevent glyph clipping after manual resize.
27648
- * Similar to Polotno - checks if any glyphs are too close to edges
27649
- * and automatically expands width if needed.
27650
- * @private
27651
- * @param resizeOrigin - Which side was used for resizing ('left' or 'right')
27710
+ /**
27711
+ * Safety snap to prevent glyph clipping after manual resize.
27712
+ * Similar to Polotno - checks if any glyphs are too close to edges
27713
+ * and automatically expands width if needed.
27714
+ * @private
27715
+ * @param resizeOrigin - Which side was used for resizing ('left' or 'right')
27652
27716
  */
27653
27717
  safetySnapWidth(resizeOrigin) {
27654
27718
  // For Textbox objects, we always want to check for clipping regardless of isWrapping flag
@@ -27678,7 +27742,7 @@ class Textbox extends IText {
27678
27742
  const safetyThreshold = 2; // px - very subtle trigger
27679
27743
 
27680
27744
  if (maxRequiredWidth > this.width - safetyThreshold) {
27681
- var _this$canvas5;
27745
+ var _this$canvas6;
27682
27746
  // Set width to exactly what's needed + minimal safety margin
27683
27747
  const newWidth = maxRequiredWidth + 1; // Add just 1px safety margin
27684
27748
 
@@ -27711,13 +27775,13 @@ class Textbox extends IText {
27711
27775
  this.__overlayEditor.refresh();
27712
27776
  }, 0);
27713
27777
  }
27714
- (_this$canvas5 = this.canvas) === null || _this$canvas5 === void 0 || _this$canvas5.requestRenderAll();
27778
+ (_this$canvas6 = this.canvas) === null || _this$canvas6 === void 0 || _this$canvas6.requestRenderAll();
27715
27779
  }
27716
27780
  }
27717
27781
 
27718
- /**
27719
- * Fix character selection mismatch after JSON loading for browser-wrapped fonts
27720
- * @private
27782
+ /**
27783
+ * Fix character selection mismatch after JSON loading for browser-wrapped fonts
27784
+ * @private
27721
27785
  */
27722
27786
  _fixCharacterMappingAfterJsonLoad() {
27723
27787
  if (this._usingBrowserWrapping) {
@@ -27737,9 +27801,9 @@ class Textbox extends IText {
27737
27801
  }
27738
27802
  }
27739
27803
 
27740
- /**
27741
- * Force complete textbox re-initialization (useful after JSON loading)
27742
- * Overrides Text version with Textbox-specific logic
27804
+ /**
27805
+ * Force complete textbox re-initialization (useful after JSON loading)
27806
+ * Overrides Text version with Textbox-specific logic
27743
27807
  */
27744
27808
  forceTextReinitialization() {
27745
27809
  console.log('🔄 Force reinitializing Textbox object');
@@ -27762,7 +27826,7 @@ class Textbox extends IText {
27762
27826
  // Double-check that justify was applied by checking space widths
27763
27827
  if (this.textAlign.includes('justify') && this.__charBounds) {
27764
27828
  setTimeout(() => {
27765
- var _this$canvas6;
27829
+ var _this$canvas7;
27766
27830
  // Verify justify was applied by checking if space widths vary
27767
27831
  let hasVariableSpaces = false;
27768
27832
  this.__charBounds.forEach((lineBounds, i) => {
@@ -27791,36 +27855,36 @@ class Textbox extends IText {
27791
27855
  this.height = this.calcTextHeight();
27792
27856
  console.log(`🔧 JUSTIFY: Used calcTextHeight: ${this.height}px`);
27793
27857
  }
27794
- (_this$canvas6 = this.canvas) === null || _this$canvas6 === void 0 || _this$canvas6.requestRenderAll();
27858
+ (_this$canvas7 = this.canvas) === null || _this$canvas7 === void 0 || _this$canvas7.requestRenderAll();
27795
27859
  }, 10);
27796
27860
  }
27797
27861
  }
27798
27862
 
27799
- /**
27800
- * Returns object representation of an instance
27801
- * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
27802
- * @return {Object} object representation of an instance
27863
+ /**
27864
+ * Returns object representation of an instance
27865
+ * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
27866
+ * @return {Object} object representation of an instance
27803
27867
  */
27804
27868
  toObject() {
27805
27869
  let propertiesToInclude = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
27806
27870
  return super.toObject(['minWidth', 'splitByGrapheme', ...propertiesToInclude]);
27807
27871
  }
27808
27872
  }
27809
- /**
27810
- * Minimum width of textbox, in pixels.
27811
- * @type Number
27873
+ /**
27874
+ * Minimum width of textbox, in pixels.
27875
+ * @type Number
27812
27876
  */
27813
- /**
27814
- * Minimum calculated width of a textbox, in pixels.
27815
- * fixed to 2 so that an empty textbox cannot go to 0
27816
- * and is still selectable without text.
27817
- * @type Number
27877
+ /**
27878
+ * Minimum calculated width of a textbox, in pixels.
27879
+ * fixed to 2 so that an empty textbox cannot go to 0
27880
+ * and is still selectable without text.
27881
+ * @type Number
27818
27882
  */
27819
- /**
27820
- * Use this boolean property in order to split strings that have no white space concept.
27821
- * this is a cheap way to help with chinese/japanese
27822
- * @type Boolean
27823
- * @since 2.6.0
27883
+ /**
27884
+ * Use this boolean property in order to split strings that have no white space concept.
27885
+ * this is a cheap way to help with chinese/japanese
27886
+ * @type Boolean
27887
+ * @since 2.6.0
27824
27888
  */
27825
27889
  _defineProperty(Textbox, "type", 'Textbox');
27826
27890
  _defineProperty(Textbox, "textLayoutProperties", [...IText.textLayoutProperties, 'width']);