@nasser-sw/fabric 7.0.1-beta16 → 7.0.1-beta17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/.claude/settings.local.json +7 -0
  2. package/dist/index.js +1982 -649
  3. package/dist/index.js.map +1 -1
  4. package/dist/index.min.js +1 -1
  5. package/dist/index.min.js.map +1 -1
  6. package/dist/index.min.mjs +1 -1
  7. package/dist/index.min.mjs.map +1 -1
  8. package/dist/index.mjs +1982 -649
  9. package/dist/index.mjs.map +1 -1
  10. package/dist/index.node.cjs +1982 -649
  11. package/dist/index.node.cjs.map +1 -1
  12. package/dist/index.node.mjs +1982 -649
  13. package/dist/index.node.mjs.map +1 -1
  14. package/dist/package.json.min.mjs +1 -1
  15. package/dist/package.json.mjs +1 -1
  16. package/dist/src/shapes/IText/IText.d.ts +31 -6
  17. package/dist/src/shapes/IText/IText.d.ts.map +1 -1
  18. package/dist/src/shapes/IText/IText.min.mjs +1 -1
  19. package/dist/src/shapes/IText/IText.min.mjs.map +1 -1
  20. package/dist/src/shapes/IText/IText.mjs +495 -126
  21. package/dist/src/shapes/IText/IText.mjs.map +1 -1
  22. package/dist/src/shapes/IText/ITextBehavior.d.ts +12 -0
  23. package/dist/src/shapes/IText/ITextBehavior.d.ts.map +1 -1
  24. package/dist/src/shapes/IText/ITextBehavior.min.mjs +1 -1
  25. package/dist/src/shapes/IText/ITextBehavior.min.mjs.map +1 -1
  26. package/dist/src/shapes/IText/ITextBehavior.mjs +127 -36
  27. package/dist/src/shapes/IText/ITextBehavior.mjs.map +1 -1
  28. package/dist/src/shapes/IText/ITextClickBehavior.d.ts.map +1 -1
  29. package/dist/src/shapes/IText/ITextClickBehavior.min.mjs +1 -1
  30. package/dist/src/shapes/IText/ITextClickBehavior.min.mjs.map +1 -1
  31. package/dist/src/shapes/IText/ITextClickBehavior.mjs +21 -4
  32. package/dist/src/shapes/IText/ITextClickBehavior.mjs.map +1 -1
  33. package/dist/src/shapes/IText/ITextKeyBehavior.min.mjs +1 -1
  34. package/dist/src/shapes/IText/ITextKeyBehavior.min.mjs.map +1 -1
  35. package/dist/src/shapes/IText/ITextKeyBehavior.mjs +17 -21
  36. package/dist/src/shapes/IText/ITextKeyBehavior.mjs.map +1 -1
  37. package/dist/src/shapes/Text/Text.d.ts +69 -1
  38. package/dist/src/shapes/Text/Text.d.ts.map +1 -1
  39. package/dist/src/shapes/Text/Text.min.mjs +1 -1
  40. package/dist/src/shapes/Text/Text.min.mjs.map +1 -1
  41. package/dist/src/shapes/Text/Text.mjs +374 -60
  42. package/dist/src/shapes/Text/Text.mjs.map +1 -1
  43. package/dist/src/shapes/Text/constants.d.ts.map +1 -1
  44. package/dist/src/shapes/Text/constants.min.mjs +1 -1
  45. package/dist/src/shapes/Text/constants.min.mjs.map +1 -1
  46. package/dist/src/shapes/Text/constants.mjs +2 -1
  47. package/dist/src/shapes/Text/constants.mjs.map +1 -1
  48. package/dist/src/shapes/Textbox.d.ts +8 -1
  49. package/dist/src/shapes/Textbox.d.ts.map +1 -1
  50. package/dist/src/shapes/Textbox.min.mjs +1 -1
  51. package/dist/src/shapes/Textbox.min.mjs.map +1 -1
  52. package/dist/src/shapes/Textbox.mjs +406 -63
  53. package/dist/src/shapes/Textbox.mjs.map +1 -1
  54. package/dist/src/text/hitTest.min.mjs +1 -1
  55. package/dist/src/text/hitTest.min.mjs.map +1 -1
  56. package/dist/src/text/hitTest.mjs +1 -198
  57. package/dist/src/text/hitTest.mjs.map +1 -1
  58. package/dist/src/text/layout.min.mjs +1 -1
  59. package/dist/src/text/layout.min.mjs.map +1 -1
  60. package/dist/src/text/layout.mjs +122 -5
  61. package/dist/src/text/layout.mjs.map +1 -1
  62. package/dist/src/text/overlayEditor.min.mjs +1 -1
  63. package/dist/src/text/overlayEditor.min.mjs.map +1 -1
  64. package/dist/src/text/overlayEditor.mjs +132 -142
  65. package/dist/src/text/overlayEditor.mjs.map +1 -1
  66. package/dist/src/text/unicode.d.ts +28 -0
  67. package/dist/src/text/unicode.d.ts.map +1 -1
  68. package/dist/src/text/unicode.min.mjs +1 -1
  69. package/dist/src/text/unicode.min.mjs.map +1 -1
  70. package/dist/src/text/unicode.mjs +294 -1
  71. package/dist/src/text/unicode.mjs.map +1 -1
  72. package/dist-extensions/src/shapes/IText/IText.d.ts +31 -6
  73. package/dist-extensions/src/shapes/IText/IText.d.ts.map +1 -1
  74. package/dist-extensions/src/shapes/IText/ITextBehavior.d.ts +12 -0
  75. package/dist-extensions/src/shapes/IText/ITextBehavior.d.ts.map +1 -1
  76. package/dist-extensions/src/shapes/IText/ITextClickBehavior.d.ts.map +1 -1
  77. package/dist-extensions/src/shapes/Text/Text.d.ts +69 -1
  78. package/dist-extensions/src/shapes/Text/Text.d.ts.map +1 -1
  79. package/dist-extensions/src/shapes/Text/constants.d.ts.map +1 -1
  80. package/dist-extensions/src/shapes/Textbox.d.ts +8 -1
  81. package/dist-extensions/src/shapes/Textbox.d.ts.map +1 -1
  82. package/dist-extensions/src/text/unicode.d.ts +28 -0
  83. package/dist-extensions/src/text/unicode.d.ts.map +1 -1
  84. package/package.json +164 -164
  85. package/rtl-debug.html +358 -200
  86. package/src/shapes/IText/IText.ts +524 -110
  87. package/src/shapes/IText/ITextBehavior.ts +174 -80
  88. package/src/shapes/IText/ITextClickBehavior.ts +20 -6
  89. package/src/shapes/IText/ITextKeyBehavior.ts +15 -15
  90. package/src/shapes/Text/Text.ts +488 -107
  91. package/src/shapes/Text/constants.ts +4 -2
  92. package/src/shapes/Textbox.ts +414 -65
  93. package/src/text/layout.ts +150 -23
  94. package/src/text/overlayEditor.ts +148 -148
  95. package/src/text/unicode.ts +177 -2
@@ -190,7 +190,9 @@ class OverlayEditor {
190
190
  requestAnimationFrame(() => {
191
191
  if (!this.isDestroyed) {
192
192
  this.applyOverlayStyle();
193
- console.log('📐 Height changed - rechecking alignment after repositioning:');
193
+ // console.log(
194
+ // '📐 Height changed - rechecking alignment after repositioning:',
195
+ // );
194
196
  }
195
197
  });
196
198
  }
@@ -286,7 +288,7 @@ class OverlayEditor {
286
288
 
287
289
  // Special handling for text objects loaded from JSON - ensure they're properly initialized
288
290
  if (target.dirty !== false && target.initDimensions) {
289
- console.log('🔧 Ensuring text object is properly initialized before overlay editing');
291
+ // console.log('🔧 Ensuring text object is properly initialized before overlay editing');
290
292
  // Force re-initialization if the text object seems to be in a dirty state
291
293
  target.initDimensions();
292
294
  }
@@ -303,11 +305,11 @@ class OverlayEditor {
303
305
  const autoDetectedDirection = this.firstStrongDir(this.textarea.value || '');
304
306
 
305
307
  // DEBUG: Log alignment details
306
- console.log('🔍 ALIGNMENT DEBUG:');
307
- console.log(' Fabric textAlign:', textAlign);
308
- console.log(' Fabric direction:', target.direction);
309
- console.log(' Text content:', JSON.stringify(target.text));
310
- console.log(' Detected direction:', autoDetectedDirection);
308
+ // console.log('🔍 ALIGNMENT DEBUG:');
309
+ // console.log(' Fabric textAlign:', textAlign);
310
+ // console.log(' Fabric direction:', (target as any).direction);
311
+ // console.log(' Text content:', JSON.stringify(target.text));
312
+ // console.log(' Detected direction:', autoDetectedDirection);
311
313
 
312
314
  // Map fabric.js justify to CSS
313
315
  if (textAlign.includes('justify')) {
@@ -325,7 +327,7 @@ class OverlayEditor {
325
327
  // If text is RTL but fabric says justify-left, override to justify-right for better UX
326
328
  if (autoDetectedDirection === 'rtl') {
327
329
  this.textarea.style.textAlignLast = 'right';
328
- console.log(' → Overrode justify-left to justify-right for RTL text');
330
+ // console.log(' → Overrode justify-left to justify-right for RTL text');
329
331
  } else {
330
332
  this.textarea.style.textAlignLast = 'left';
331
333
  }
@@ -333,7 +335,7 @@ class OverlayEditor {
333
335
  // If text is LTR but fabric says justify-right, override to justify-left for better UX
334
336
  if (autoDetectedDirection === 'ltr') {
335
337
  this.textarea.style.textAlignLast = 'left';
336
- console.log(' → Overrode justify-right to justify-left for LTR text');
338
+ // console.log(' → Overrode justify-right to justify-left for LTR text');
337
339
  } else {
338
340
  this.textarea.style.textAlignLast = 'right';
339
341
  }
@@ -352,16 +354,17 @@ class OverlayEditor {
352
354
  // Try to force better justify behavior
353
355
  this.textarea.style.textJustifyTrim = 'none';
354
356
  this.textarea.style.textAutospace = 'none';
355
- console.log(' → Applied justify alignment:', textAlign, 'with last-line:', this.textarea.style.textAlignLast);
357
+
358
+ // console.log(' → Applied justify alignment:', textAlign, 'with last-line:', this.textarea.style.textAlignLast);
356
359
  } catch (error) {
357
- console.warn(' → Justify setup failed, falling back to standard alignment:', error);
360
+ // console.warn(' → Justify setup failed, falling back to standard alignment:', error);
358
361
  cssTextAlign = textAlign.replace('justify-', '').replace('justify', 'left');
359
362
  }
360
363
  } else {
361
364
  this.textarea.style.textAlignLast = 'auto';
362
365
  this.textarea.style.textJustify = 'auto';
363
366
  this.textarea.style.wordSpacing = 'normal';
364
- console.log(' → Applied standard alignment:', cssTextAlign);
367
+ // console.log(' → Applied standard alignment:', cssTextAlign);
365
368
  }
366
369
  this.textarea.style.textAlign = cssTextAlign;
367
370
  this.textarea.style.color = ((_target$fill = target.fill) === null || _target$fill === void 0 ? void 0 : _target$fill.toString()) || '#000';
@@ -387,37 +390,31 @@ class OverlayEditor {
387
390
  this.textarea.style.hyphens = 'none';
388
391
 
389
392
  // DEBUG: Log final CSS properties
390
- console.log('🎨 FINAL TEXTAREA CSS:');
391
- console.log(' textAlign:', this.textarea.style.textAlign);
392
- console.log(' textAlignLast:', this.textarea.style.textAlignLast);
393
- console.log(' direction:', this.textarea.style.direction);
394
- console.log(' unicodeBidi:', this.textarea.style.unicodeBidi);
395
- console.log(' width:', this.textarea.style.width);
396
- console.log(' textJustify:', this.textarea.style.textJustify);
397
- console.log(' wordSpacing:', this.textarea.style.wordSpacing);
398
- console.log(' whiteSpace:', this.textarea.style.whiteSpace);
393
+ // console.log('🎨 FINAL TEXTAREA CSS:');
394
+ // console.log(' textAlign:', this.textarea.style.textAlign);
395
+ // console.log(' textAlignLast:', this.textarea.style.textAlignLast);
396
+ // console.log(' direction:', this.textarea.style.direction);
397
+ // console.log(' unicodeBidi:', this.textarea.style.unicodeBidi);
398
+ // console.log(' width:', this.textarea.style.width);
399
+ // console.log(' textJustify:', (this.textarea.style as any).textJustify);
400
+ // console.log(' wordSpacing:', (this.textarea.style as any).wordSpacing);
401
+ // console.log(' whiteSpace:', this.textarea.style.whiteSpace);
399
402
 
400
403
  // If justify, log Fabric object dimensions for comparison
401
- if (textAlign.includes('justify')) {
402
- var _calcTextWidth, _ref;
403
- console.log('🔧 FABRIC OBJECT JUSTIFY INFO:');
404
- console.log(' Fabric width:', target.width);
405
- console.log(' Fabric calcTextWidth:', (_calcTextWidth = (_ref = target).calcTextWidth) === null || _calcTextWidth === void 0 ? void 0 : _calcTextWidth.call(_ref));
406
- console.log(' Fabric textAlign:', target.textAlign);
407
- console.log(' Text lines:', target.textLines);
408
- }
404
+ if (textAlign.includes('justify')) ;
409
405
 
410
406
  // Debug font properties matching
411
- console.log('🔤 FONT PROPERTIES COMPARISON:');
412
- console.log(' Fabric fontFamily:', target.fontFamily);
413
- console.log(' Fabric fontWeight:', target.fontWeight);
414
- console.log(' Fabric fontStyle:', target.fontStyle);
415
- console.log(' Fabric fontSize:', target.fontSize);
416
- console.log(' → Textarea fontFamily:', this.textarea.style.fontFamily);
417
- console.log(' → Textarea fontWeight:', this.textarea.style.fontWeight);
418
- console.log(' → Textarea fontStyle:', this.textarea.style.fontStyle);
419
- console.log(' → Textarea fontSize:', this.textarea.style.fontSize);
420
- console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
407
+ // console.log('🔤 FONT PROPERTIES COMPARISON:');
408
+ // console.log(' Fabric fontFamily:', target.fontFamily);
409
+ // console.log(' Fabric fontWeight:', target.fontWeight);
410
+ // console.log(' Fabric fontStyle:', target.fontStyle);
411
+ // console.log(' Fabric fontSize:', target.fontSize);
412
+ // console.log(' → Textarea fontFamily:', this.textarea.style.fontFamily);
413
+ // console.log(' → Textarea fontWeight:', this.textarea.style.fontWeight);
414
+ // console.log(' → Textarea fontStyle:', this.textarea.style.fontStyle);
415
+ // console.log(' → Textarea fontSize:', this.textarea.style.fontSize);
416
+
417
+ // console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
421
418
 
422
419
  // Enhanced font rendering to better match fabric.js canvas rendering
423
420
  // Default to auto for more natural rendering
@@ -432,11 +429,12 @@ class OverlayEditor {
432
429
  if (isBold) {
433
430
  this.textarea.style.webkitFontSmoothing = 'subpixel-antialiased';
434
431
  this.textarea.style.mozOsxFontSmoothing = 'unset';
435
- console.log('🔤 Applied enhanced bold rendering for better thickness matching');
432
+ // console.log('🔤 Applied enhanced bold rendering for better thickness matching');
436
433
  }
437
- console.log('🎨 FONT SMOOTHING APPLIED:');
438
- console.log(' webkitFontSmoothing:', this.textarea.style.webkitFontSmoothing);
439
- console.log(' mozOsxFontSmoothing:', this.textarea.style.mozOsxFontSmoothing);
434
+
435
+ // console.log('🎨 FONT SMOOTHING APPLIED:');
436
+ // console.log(' webkitFontSmoothing:', (this.textarea.style as any).webkitFontSmoothing);
437
+ // console.log(' mozOsxFontSmoothing:', (this.textarea.style as any).mozOsxFontSmoothing);
440
438
 
441
439
  // Initial bounds are set correctly by Fabric.js - don't force update here
442
440
  }
@@ -465,137 +463,130 @@ class OverlayEditor {
465
463
  width: canvasBounds.width * zoom,
466
464
  height: canvasBounds.height * zoom
467
465
  };
468
- console.log('🔍 BOUNDING BOX COMPARISON:');
469
- console.log('📦 Textarea Rect:', {
470
- left: Math.round(textareaRect.left * 100) / 100,
471
- top: Math.round(textareaRect.top * 100) / 100,
472
- width: Math.round(textareaRect.width * 100) / 100,
473
- height: Math.round(textareaRect.height * 100) / 100
474
- });
475
- console.log('📦 Host Div Rect:', {
476
- left: Math.round(hostRect.left * 100) / 100,
477
- top: Math.round(hostRect.top * 100) / 100,
478
- width: Math.round(hostRect.width * 100) / 100,
479
- height: Math.round(hostRect.height * 100) / 100
480
- });
481
- console.log('📦 Canvas Object Bounds (screen):', {
482
- left: Math.round(screenObjectBounds.left * 100) / 100,
483
- top: Math.round(screenObjectBounds.top * 100) / 100,
484
- width: Math.round(screenObjectBounds.width * 100) / 100,
485
- height: Math.round(screenObjectBounds.height * 100) / 100
486
- });
487
- console.log('📦 Canvas Object Bounds (canvas):', canvasBounds);
466
+
467
+ // console.log('🔍 BOUNDING BOX COMPARISON:');
468
+ // console.log('📦 Textarea Rect:', {
469
+ // left: Math.round(textareaRect.left * 100) / 100,
470
+ // top: Math.round(textareaRect.top * 100) / 100,
471
+ // width: Math.round(textareaRect.width * 100) / 100,
472
+ // height: Math.round(textareaRect.height * 100) / 100,
473
+ // });
474
+ // console.log('📦 Host Div Rect:', {
475
+ // left: Math.round(hostRect.left * 100) / 100,
476
+ // top: Math.round(hostRect.top * 100) / 100,
477
+ // width: Math.round(hostRect.width * 100) / 100,
478
+ // height: Math.round(hostRect.height * 100) / 100,
479
+ // });
480
+ // console.log('📦 Canvas Object Bounds (screen):', {
481
+ // left: Math.round(screenObjectBounds.left * 100) / 100,
482
+ // top: Math.round(screenObjectBounds.top * 100) / 100,
483
+ // width: Math.round(screenObjectBounds.width * 100) / 100,
484
+ // height: Math.round(screenObjectBounds.height * 100) / 100,
485
+ // });
486
+ // console.log('📦 Canvas Object Bounds (canvas):', canvasBounds);
488
487
 
489
488
  // Calculate differences
490
- const hostVsObject = {
489
+ ({
491
490
  leftDiff: Math.round((hostRect.left - screenObjectBounds.left) * 100) / 100,
492
491
  topDiff: Math.round((hostRect.top - screenObjectBounds.top) * 100) / 100,
493
492
  widthDiff: Math.round((hostRect.width - screenObjectBounds.width) * 100) / 100,
494
493
  heightDiff: Math.round((hostRect.height - screenObjectBounds.height) * 100) / 100
495
- };
496
- const textareaVsObject = {
494
+ });
495
+ ({
497
496
  leftDiff: Math.round((textareaRect.left - screenObjectBounds.left) * 100) / 100,
498
497
  topDiff: Math.round((textareaRect.top - screenObjectBounds.top) * 100) / 100,
499
498
  widthDiff: Math.round((textareaRect.width - screenObjectBounds.width) * 100) / 100,
500
499
  heightDiff: Math.round((textareaRect.height - screenObjectBounds.height) * 100) / 100
501
- };
502
- console.log('📏 Host Div vs Canvas Object Diff:', hostVsObject);
503
- console.log('📏 Textarea vs Canvas Object Diff:', textareaVsObject);
504
-
505
- // Check if they're aligned (within 2px tolerance)
506
- const tolerance = 2;
507
- const hostAligned = Math.abs(hostVsObject.leftDiff) < tolerance && Math.abs(hostVsObject.topDiff) < tolerance && Math.abs(hostVsObject.widthDiff) < tolerance && Math.abs(hostVsObject.heightDiff) < tolerance;
508
- const textareaAligned = Math.abs(textareaVsObject.leftDiff) < tolerance && Math.abs(textareaVsObject.topDiff) < tolerance && Math.abs(textareaVsObject.widthDiff) < tolerance && Math.abs(textareaVsObject.heightDiff) < tolerance;
509
- console.log(hostAligned ? '✅ Host Div ALIGNED with canvas object' : '❌ Host Div MISALIGNED with canvas object');
510
- console.log(textareaAligned ? '✅ Textarea ALIGNED with canvas object' : '❌ Textarea MISALIGNED with canvas object');
511
- console.log('🔍 Zoom:', zoom, 'Viewport Transform:', vpt);
512
- console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
500
+ });
501
+
502
+ // console.log(
503
+ // hostAligned
504
+ // ? '✅ Host Div ALIGNED with canvas object'
505
+ // : '❌ Host Div MISALIGNED with canvas object',
506
+ // );
507
+ // console.log(
508
+ // textareaAligned
509
+ // ? '✅ Textarea ALIGNED with canvas object'
510
+ // : ' Textarea MISALIGNED with canvas object',
511
+ // );
512
+ // console.log('🔍 Zoom:', zoom, 'Viewport Transform:', vpt);
513
+ // console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
513
514
  }
514
515
 
515
516
  /**
516
517
  * Debug method to compare text wrapping between textarea and Fabric text object
517
518
  */
518
519
  debugTextWrapping() {
519
- const target = this.target;
520
+ this.target;
520
521
  const text = this.textarea.value;
521
- console.log('📝 TEXT WRAPPING COMPARISON:');
522
- console.log('📄 Text Content:', `"${text}"`);
523
- console.log('📄 Text Length:', text.length);
522
+
523
+ // console.log('📝 TEXT WRAPPING COMPARISON:');
524
+ // console.log('📄 Text Content:', `"${text}"`);
525
+ // console.log('📄 Text Length:', text.length);
524
526
 
525
527
  // Analyze line breaks
526
528
  const explicitLines = text.split('\n');
527
- console.log('📄 Explicit Lines (\\n):', explicitLines.length);
529
+ // console.log('📄 Explicit Lines (\\n):', explicitLines.length);
528
530
  explicitLines.forEach((line, i) => {
529
- console.log(` Line ${i + 1}: "${line}" (${line.length} chars)`);
531
+ // console.log(` Line ${i + 1}: "${line}" (${line.length} chars)`);
530
532
  });
531
533
 
532
534
  // Get textarea computed styles for wrapping analysis
533
535
  const textareaStyles = window.getComputedStyle(this.textarea);
534
- console.log('📐 Textarea Wrapping Styles:');
535
- console.log(' width:', textareaStyles.width);
536
- console.log(' fontSize:', textareaStyles.fontSize);
537
- console.log(' fontFamily:', textareaStyles.fontFamily);
538
- console.log(' fontWeight:', textareaStyles.fontWeight);
539
- console.log(' letterSpacing:', textareaStyles.letterSpacing);
540
- console.log(' lineHeight:', textareaStyles.lineHeight);
541
- console.log(' whiteSpace:', textareaStyles.whiteSpace);
542
- console.log(' wordWrap:', textareaStyles.wordWrap);
543
- console.log(' overflowWrap:', textareaStyles.overflowWrap);
544
- console.log(' direction:', textareaStyles.direction);
545
- console.log(' textAlign:', textareaStyles.textAlign);
536
+ // console.log('📐 Textarea Wrapping Styles:');
537
+ // console.log(' width:', textareaStyles.width);
538
+ // console.log(' fontSize:', textareaStyles.fontSize);
539
+ // console.log(' fontFamily:', textareaStyles.fontFamily);
540
+ // console.log(' fontWeight:', textareaStyles.fontWeight);
541
+ // console.log(' letterSpacing:', textareaStyles.letterSpacing);
542
+ // console.log(' lineHeight:', textareaStyles.lineHeight);
543
+ // console.log(' whiteSpace:', textareaStyles.whiteSpace);
544
+ // console.log(' wordWrap:', textareaStyles.wordWrap);
545
+ // console.log(' overflowWrap:', textareaStyles.overflowWrap);
546
+ // console.log(' direction:', textareaStyles.direction);
547
+ // console.log(' textAlign:', textareaStyles.textAlign);
546
548
 
547
549
  // Get Fabric text object properties for comparison
548
- console.log('📐 Fabric Text Object Properties:');
549
- console.log(' width:', target.width);
550
- console.log(' fontSize:', target.fontSize);
551
- console.log(' fontFamily:', target.fontFamily);
552
- console.log(' fontWeight:', target.fontWeight);
553
- console.log(' charSpacing:', target.charSpacing);
554
- console.log(' lineHeight:', target.lineHeight);
555
- console.log(' direction:', target.direction);
556
- console.log(' textAlign:', target.textAlign);
557
- console.log(' scaleX:', target.scaleX);
558
- console.log(' scaleY:', target.scaleY);
550
+ // console.log('📐 Fabric Text Object Properties:');
551
+ // console.log(' width:', (target as any).width);
552
+ // console.log(' fontSize:', target.fontSize);
553
+ // console.log(' fontFamily:', target.fontFamily);
554
+ // console.log(' fontWeight:', target.fontWeight);
555
+ // console.log(' charSpacing:', target.charSpacing);
556
+ // console.log(' lineHeight:', target.lineHeight);
557
+ // console.log(' direction:', (target as any).direction);
558
+ // console.log(' textAlign:', (target as any).textAlign);
559
+ // console.log(' scaleX:', target.scaleX);
560
+ // console.log(' scaleY:', target.scaleY);
559
561
 
560
562
  // Calculate effective dimensions for comparison - use actual rendered width
561
563
  // **THE FIX:** Use getBoundingRect to get the *actual rendered width* of the Fabric object.
562
- const fabricEffectiveWidth = this.target.getBoundingRect().width;
564
+ this.target.getBoundingRect().width;
563
565
  // Use the exact width set on textarea for comparison
564
566
  const textareaComputedWidth = parseFloat(window.getComputedStyle(this.textarea).width);
565
- const textareaEffectiveWidth = textareaComputedWidth / this.canvas.getZoom();
566
- const widthDiff = Math.abs(textareaEffectiveWidth - fabricEffectiveWidth);
567
- console.log('📏 Effective Width Comparison:');
568
- console.log(' Textarea Effective Width:', textareaEffectiveWidth);
569
- console.log(' Fabric Effective Width:', fabricEffectiveWidth);
570
- console.log(' Width Difference:', widthDiff.toFixed(2) + 'px');
571
- console.log(widthDiff < 1 ? ' Widths MATCH for wrapping' : ' Width MISMATCH may cause different wrapping');
572
-
573
- // Check text direction and bidi handling
574
- const hasRTLText = /[\u0590-\u05FF\u0600-\u06FF\u0750-\u077F\uFB50-\uFDFF\uFE70-\uFEFF]/.test(text);
575
- const hasBidiText = /[\u0590-\u06FF]/.test(text) && /[a-zA-Z]/.test(text);
576
- console.log('🌍 Text Direction Analysis:');
577
- console.log(' Has RTL characters:', hasRTLText);
578
- console.log(' Has mixed Bidi text:', hasBidiText);
579
- console.log(' Textarea direction:', textareaStyles.direction);
580
- console.log(' Fabric direction:', target.direction || 'auto');
581
- console.log(' Textarea unicodeBidi:', textareaStyles.unicodeBidi);
567
+ textareaComputedWidth / this.canvas.getZoom();
568
+
569
+ // console.log('🌍 Text Direction Analysis:');
570
+ // console.log(' Has RTL characters:', hasRTLText);
571
+ // console.log(' Has mixed Bidi text:', hasBidiText);
572
+ // console.log(' Textarea direction:', textareaStyles.direction);
573
+ // console.log(' Fabric direction:', (target as any).direction || 'auto');
574
+ // console.log(' Textarea unicodeBidi:', textareaStyles.unicodeBidi);
582
575
 
583
576
  // Measure actual rendered line count
584
577
  const textareaScrollHeight = this.textarea.scrollHeight;
585
578
  const textareaLineHeight = parseFloat(textareaStyles.lineHeight) || parseFloat(textareaStyles.fontSize) * 1.2;
586
579
  const estimatedTextareaLines = Math.round(textareaScrollHeight / textareaLineHeight);
587
- console.log('📊 Line Count Analysis:');
588
- console.log(' Textarea scrollHeight:', textareaScrollHeight);
589
- console.log(' Textarea lineHeight:', textareaLineHeight);
590
- console.log(' Estimated rendered lines:', estimatedTextareaLines);
591
- console.log(' Explicit line breaks:', explicitLines.length);
592
- if (estimatedTextareaLines > explicitLines.length) {
593
- console.log('🔄 Text wrapping detected in textarea');
594
- console.log(' Wrapped lines:', estimatedTextareaLines - explicitLines.length);
595
- } else {
596
- console.log('📏 No text wrapping in textarea');
597
- }
598
- console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
580
+
581
+ // console.log('📊 Line Count Analysis:');
582
+ // console.log(' Textarea scrollHeight:', textareaScrollHeight);
583
+ // console.log(' Textarea lineHeight:', textareaLineHeight);
584
+ // console.log(' Estimated rendered lines:', estimatedTextareaLines);
585
+ // console.log(' Explicit line breaks:', explicitLines.length);
586
+
587
+ if (estimatedTextareaLines > explicitLines.length) ;
588
+
589
+ // console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
599
590
  }
600
591
 
601
592
  /**
@@ -684,17 +675,16 @@ class OverlayEditor {
684
675
 
685
676
  // Only update direction when not explicitly set on the object
686
677
  if (!hasExplicitDirection && detectedDirection && detectedDirection !== currentDirection) {
687
- console.log(`🔄 Overlay Exit: Auto-detected direction change from "${currentDirection}" to "${detectedDirection}"`);
688
- console.log(` Text content: "${finalText.substring(0, 50)}..."`);
678
+ // console.log(`🔄 Overlay Exit: Auto-detected direction change from "${currentDirection}" to "${detectedDirection}"`);
679
+ // console.log(` Text content: "${finalText.substring(0, 50)}..."`);
689
680
 
690
681
  // Update the fabric object's direction
691
682
  this.target.set('direction', detectedDirection);
692
683
 
693
684
  // Force a re-render to apply the direction change
694
685
  this.canvas.requestRenderAll();
695
- console.log(`✅ Fabric object direction updated to: ${detectedDirection}`);
696
- } else {
697
- console.log(`📝 Overlay Exit: Direction unchanged (${currentDirection}), text: "${finalText.substring(0, 30)}..."`);
686
+
687
+ // console.log(`✅ Fabric object direction updated to: ${detectedDirection}`);
698
688
  }
699
689
  if (this.onCommit) {
700
690
  this.onCommit(finalText);