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