@syncfusion/ej2-richtexteditor 25.1.42 → 25.2.4

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 (57) hide show
  1. package/CHANGELOG.md +26 -4
  2. package/dist/ej2-richtexteditor.min.js +2 -2
  3. package/dist/ej2-richtexteditor.umd.min.js +2 -2
  4. package/dist/ej2-richtexteditor.umd.min.js.map +1 -1
  5. package/dist/es6/ej2-richtexteditor.es2015.js +110 -24
  6. package/dist/es6/ej2-richtexteditor.es2015.js.map +1 -1
  7. package/dist/es6/ej2-richtexteditor.es5.js +115 -26
  8. package/dist/es6/ej2-richtexteditor.es5.js.map +1 -1
  9. package/dist/global/ej2-richtexteditor.min.js +2 -2
  10. package/dist/global/ej2-richtexteditor.min.js.map +1 -1
  11. package/dist/global/index.d.ts +1 -1
  12. package/package.json +12 -12
  13. package/src/common/util.d.ts +8 -0
  14. package/src/common/util.js +52 -0
  15. package/src/editor-manager/plugin/dom-node.js +1 -1
  16. package/src/editor-manager/plugin/ms-word-clean-up.js +2 -2
  17. package/src/editor-manager/plugin/undo.js +3 -1
  18. package/src/rich-text-editor/actions/html-editor.js +2 -10
  19. package/src/rich-text-editor/actions/paste-clean-up.d.ts +1 -0
  20. package/src/rich-text-editor/actions/paste-clean-up.js +52 -12
  21. package/src/rich-text-editor/base/rich-text-editor.d.ts +1 -0
  22. package/src/rich-text-editor/base/rich-text-editor.js +6 -2
  23. package/styles/bootstrap-dark.css +3 -6
  24. package/styles/bootstrap.css +3 -6
  25. package/styles/bootstrap4.css +3 -6
  26. package/styles/bootstrap5-dark.css +3 -6
  27. package/styles/bootstrap5.css +3 -6
  28. package/styles/fabric-dark.css +3 -6
  29. package/styles/fabric.css +3 -6
  30. package/styles/fluent-dark.css +3 -6
  31. package/styles/fluent.css +3 -6
  32. package/styles/highcontrast-light.css +3 -6
  33. package/styles/highcontrast.css +3 -6
  34. package/styles/material-dark.css +3 -6
  35. package/styles/material.css +3 -6
  36. package/styles/material3-dark.css +3 -6
  37. package/styles/material3.css +3 -6
  38. package/styles/rich-text-editor/_layout.scss +3 -6
  39. package/styles/rich-text-editor/bootstrap-dark.css +3 -6
  40. package/styles/rich-text-editor/bootstrap.css +3 -6
  41. package/styles/rich-text-editor/bootstrap4.css +3 -6
  42. package/styles/rich-text-editor/bootstrap5-dark.css +3 -6
  43. package/styles/rich-text-editor/bootstrap5.css +3 -6
  44. package/styles/rich-text-editor/fabric-dark.css +3 -6
  45. package/styles/rich-text-editor/fabric.css +3 -6
  46. package/styles/rich-text-editor/fluent-dark.css +3 -6
  47. package/styles/rich-text-editor/fluent.css +3 -6
  48. package/styles/rich-text-editor/highcontrast-light.css +3 -6
  49. package/styles/rich-text-editor/highcontrast.css +3 -6
  50. package/styles/rich-text-editor/material-dark.css +3 -6
  51. package/styles/rich-text-editor/material.css +3 -6
  52. package/styles/rich-text-editor/material3-dark.css +3 -6
  53. package/styles/rich-text-editor/material3.css +3 -6
  54. package/styles/rich-text-editor/tailwind-dark.css +3 -6
  55. package/styles/rich-text-editor/tailwind.css +3 -6
  56. package/styles/tailwind-dark.css +3 -6
  57. package/styles/tailwind.css +3 -6
@@ -4477,6 +4477,10 @@ function updateTextNode$1(value, enterAction) {
4477
4477
  tableElm[i].classList.remove('e-rte-paste-onenote-table');
4478
4478
  continue;
4479
4479
  }
4480
+ else if (tableElm[i].classList.contains('e-rte-paste-html-table')) {
4481
+ tableElm[i].classList.remove('e-rte-paste-html-table');
4482
+ continue;
4483
+ }
4480
4484
  }
4481
4485
  }
4482
4486
  const imageElm = resultElm.querySelectorAll('img');
@@ -4581,6 +4585,54 @@ function nestedListCleanUp(range) {
4581
4585
  }
4582
4586
  }
4583
4587
  }
4588
+ /**
4589
+ * Method to scroll the content to the cursor position
4590
+ *
4591
+ * @param {Document} document - specifies the document.
4592
+ * @param {HTMLElement | HTMLBodyElement} inputElement - specifies the input element.
4593
+ * @returns {void}
4594
+ */
4595
+ function scrollToCursor(document, inputElement) {
4596
+ const rootElement = inputElement.nodeName === 'BODY' ?
4597
+ inputElement.ownerDocument.defaultView.frameElement.closest('.e-richtexteditor') :
4598
+ inputElement.closest('.e-richtexteditor');
4599
+ const height = rootElement.style.height;
4600
+ if (document.getSelection().rangeCount === 0) {
4601
+ return;
4602
+ }
4603
+ const range = document.getSelection().getRangeAt(0);
4604
+ const finalFocusElement = range.startContainer.nodeName === '#text' ? range.startContainer.parentElement :
4605
+ range.startContainer;
4606
+ const rect = finalFocusElement.getBoundingClientRect();
4607
+ const cursorTop = rect.top;
4608
+ const cursorBottom = rect.bottom;
4609
+ const rootRect = rootElement.getBoundingClientRect();
4610
+ const hasMargin = rootElement.querySelectorAll('.e-count-enabled, .e-resize-enabled').length > 0;
4611
+ if (inputElement.nodeName === 'BODY') {
4612
+ if (height === 'auto') {
4613
+ if (window.innerHeight < cursorTop) {
4614
+ finalFocusElement.scrollIntoView(false);
4615
+ }
4616
+ }
4617
+ else {
4618
+ if (cursorTop > inputElement.getBoundingClientRect().height) {
4619
+ finalFocusElement.scrollIntoView({ block: 'nearest', inline: 'nearest' });
4620
+ }
4621
+ }
4622
+ }
4623
+ else {
4624
+ if (height === 'auto') {
4625
+ if (window.innerHeight < cursorTop) {
4626
+ finalFocusElement.scrollIntoView({ block: 'end', inline: 'nearest' });
4627
+ }
4628
+ }
4629
+ else {
4630
+ if (cursorBottom > rootRect.bottom) {
4631
+ rootElement.querySelector('.e-rte-content').scrollTop += (cursorBottom - rootRect.bottom) + (hasMargin ? 20 : 0);
4632
+ }
4633
+ }
4634
+ }
4635
+ }
4584
4636
 
4585
4637
  /**
4586
4638
  * Update Toolbar Status
@@ -12198,7 +12250,7 @@ class DOMNode {
12198
12250
  unWrap(element) {
12199
12251
  const parent = element.parentNode;
12200
12252
  let unWrapNode = [];
12201
- while (element.firstChild) {
12253
+ while (element.firstChild && (element.previousSibling !== this.parent.querySelector('.e-mention-chip') || element.textContent !== ' ')) {
12202
12254
  unWrapNode.push(element.firstChild);
12203
12255
  parent.insertBefore(element.firstChild, element);
12204
12256
  }
@@ -18953,6 +19005,7 @@ class UndoRedoManager {
18953
19005
  this.parent.editableElement.innerHTML = '';
18954
19006
  this.parent.editableElement.appendChild(removedContent.cloneNode(true));
18955
19007
  this.parent.editableElement.focus();
19008
+ scrollToCursor(this.parent.currentDocument, this.parent.editableElement);
18956
19009
  if (isIDevice$1()) {
18957
19010
  setEditFrameFocus(this.parent.editableElement, e.selector);
18958
19011
  }
@@ -18985,6 +19038,7 @@ class UndoRedoManager {
18985
19038
  this.parent.editableElement.innerHTML = '';
18986
19039
  this.parent.editableElement.appendChild(addedContent.cloneNode(true));
18987
19040
  this.parent.editableElement.focus();
19041
+ scrollToCursor(this.parent.currentDocument, this.parent.editableElement);
18988
19042
  if (isIDevice$1()) {
18989
19043
  setEditFrameFocus(this.parent.editableElement, e.selector);
18990
19044
  }
@@ -19085,9 +19139,9 @@ class MsWordPaste {
19085
19139
  const patern2 = /class="?Mso|style="[^ ]*\bmso-/i;
19086
19140
  const patern3 = /(class="?Mso|class='?Mso|class="?Xl|class='?Xl|class=Xl|style="[^"]*\bmso-|style='[^']*\bmso-|w:WordDocument)/gi;
19087
19141
  const pattern4 = /style='mso-width-source:/i;
19142
+ const source = this.findSource(elm);
19088
19143
  if (patern.test(tempHTMLContent) || patern2.test(tempHTMLContent) || patern3.test(tempHTMLContent) ||
19089
19144
  pattern4.test(tempHTMLContent)) {
19090
- const source = this.findSource(elm);
19091
19145
  tempHTMLContent = tempHTMLContent.replace(/<img[^>]+>/i, '');
19092
19146
  this.addListClass(elm);
19093
19147
  listNodes = this.cleanUp(elm, listNodes);
@@ -19112,7 +19166,7 @@ class MsWordPaste {
19112
19166
  e.callBack(elm.innerHTML, this.cropImageDimensions, source);
19113
19167
  }
19114
19168
  else {
19115
- e.callBack(elm.innerHTML);
19169
+ e.callBack(elm.innerHTML, null, source);
19116
19170
  }
19117
19171
  }
19118
19172
  addDoubleBr(elm) {
@@ -21902,15 +21956,7 @@ class HtmlEditor {
21902
21956
  }
21903
21957
  else {
21904
21958
  this.parent.notify(enterHandler, { args: e.args });
21905
- const newRange = this.parent.getRange();
21906
- if (!isNullOrUndefined(newRange.startContainer) && this.parent.height !== 'auto' && newRange.startContainer.nodeName !== '#text'
21907
- && !this.parent.iframeSettings.enable && newRange.startContainer.getBoundingClientRect().bottom > this.parent.element.getBoundingClientRect().bottom) {
21908
- this.parent.element.querySelector('.e-rte-content').scrollTop += newRange.startContainer.getBoundingClientRect().bottom - this.parent.element.getBoundingClientRect().bottom;
21909
- }
21910
- else if (!isNullOrUndefined(newRange.startContainer) && this.parent.height === 'auto' && newRange.startContainer.nodeName !== '#text'
21911
- && !this.parent.iframeSettings.enable && window.innerHeight < newRange.startContainer.getBoundingClientRect().top) {
21912
- newRange.startContainer.scrollIntoView({ block: 'end', inline: 'nearest' });
21913
- }
21959
+ scrollToCursor(this.parent.contentModule.getDocument(), this.parent.inputElement);
21914
21960
  }
21915
21961
  }
21916
21962
  }
@@ -22942,7 +22988,9 @@ class PasteCleanup {
22942
22988
  popupObj.close();
22943
22989
  }
22944
22990
  this.parent.trigger(imageUploadFailed, e);
22945
- uploadObj.destroy();
22991
+ if (uploadObj && document.body.contains(uploadObj.element)) {
22992
+ uploadObj.destroy();
22993
+ }
22946
22994
  }
22947
22995
  popupClose(popupObj, uploadObj, imgElem, e) {
22948
22996
  this.parent.inputElement.contentEditable = 'true';
@@ -22957,7 +23005,7 @@ class PasteCleanup {
22957
23005
  });
22958
23006
  popupObj.close();
22959
23007
  imgElem.style.opacity = '1';
22960
- if (!uploadObj.isDestroyed) {
23008
+ if (uploadObj && document.body.contains(uploadObj.element)) {
22961
23009
  uploadObj.destroy();
22962
23010
  }
22963
23011
  this.toolbarEnableDisable(false);
@@ -23255,11 +23303,34 @@ class PasteCleanup {
23255
23303
  extend(args, { elements: returnArgs.elements, imageElements: returnArgs.imgElem }, true);
23256
23304
  this.parent.formatter.onSuccess(this.parent, args);
23257
23305
  }, clipBoardElem, null, null, this.parent.enterKey);
23306
+ scrollToCursor(this.parent.contentModule.getDocument(), this.parent.inputElement);
23258
23307
  this.removeTempClass();
23259
23308
  this.parent.notify(toolbarRefresh, {});
23260
23309
  this.cropImageHandler(this.parent.inputElement);
23261
23310
  }
23262
23311
  }
23312
+ convertBlobToBase64(element) {
23313
+ const imgElem = element.querySelectorAll('img');
23314
+ for (let i = 0; i < imgElem.length; i++) {
23315
+ if (imgElem[i].getAttribute('src') &&
23316
+ imgElem[i].getAttribute('src').startsWith("blob")) {
23317
+ let blobImageUrl = imgElem[i].getAttribute('src');
23318
+ let img = new Image();
23319
+ const onImageLoadEvent = () => {
23320
+ let canvas = document.createElement('canvas');
23321
+ let ctx = canvas.getContext('2d');
23322
+ canvas.width = img.width;
23323
+ canvas.height = img.height;
23324
+ ctx.drawImage(img, 0, 0);
23325
+ let base64String = canvas.toDataURL('image/png');
23326
+ imgElem[i].src = base64String;
23327
+ img.removeEventListener('load', onImageLoadEvent);
23328
+ };
23329
+ img.src = blobImageUrl;
23330
+ img.addEventListener('load', onImageLoadEvent);
23331
+ }
23332
+ }
23333
+ }
23263
23334
  cropImageHandler(element) {
23264
23335
  const allImgElm = element.querySelectorAll('.e-img-cropped');
23265
23336
  if (allImgElm.length > 0) {
@@ -23298,22 +23369,33 @@ class PasteCleanup {
23298
23369
  }
23299
23370
  }
23300
23371
  else {
23301
- this.imgUploading(this.parent.inputElement);
23302
- if (this.parent.iframeSettings.enable) {
23303
- this.parent.updateValue();
23372
+ if (!isNullOrUndefined(this.parent.insertImageSettings.saveUrl) && !isNullOrUndefined(this.parent.insertImageSettings.path) && !isNullOrUndefined(this.parent.inputElement.querySelectorAll("img")) && this.parent.inputElement.querySelectorAll("img")[0].src.startsWith("blob")) {
23373
+ this.convertBlobToBase64(this.parent.inputElement);
23374
+ setTimeout(() => {
23375
+ this.imgUploading(this.parent.inputElement);
23376
+ if (this.parent.iframeSettings.enable) {
23377
+ this.parent.updateValue();
23378
+ }
23379
+ }, 20);
23380
+ }
23381
+ else {
23382
+ this.imgUploading(this.parent.inputElement);
23383
+ if (this.parent.iframeSettings.enable) {
23384
+ this.parent.updateValue();
23385
+ }
23304
23386
  }
23305
23387
  }
23306
23388
  }
23307
23389
  addTableClass(element, source) {
23308
- source = isNullOrUndefined(source) ? '' : source;
23309
23390
  const tableElement = element.querySelectorAll('table');
23310
23391
  for (let i = 0; i < tableElement.length; i++) {
23311
- if (!tableElement[i].classList.contains('e-rte-table') && (source === 'html' || source === '')) {
23312
- tableElement[i].classList.add('e-rte-table');
23313
- }
23314
- else if (source && source !== 'html') {
23392
+ const isMSTeamsTable = tableElement[i].parentElement.nodeName === 'FIGURE';
23393
+ if (this.parent.pasteCleanupSettings.keepFormat && source && !isMSTeamsTable) {
23315
23394
  tableElement[i].classList.add('e-rte-paste-' + source + '-table');
23316
23395
  }
23396
+ else if (!tableElement[i].classList.contains('e-rte-table')) {
23397
+ tableElement[i].classList.add('e-rte-table');
23398
+ }
23317
23399
  }
23318
23400
  return element;
23319
23401
  }
@@ -33977,6 +34059,7 @@ let RichTextEditor = class RichTextEditor extends Component {
33977
34059
  this.persistData();
33978
34060
  setStyleAttribute(this.element, { 'width': formatUnit(this.width) });
33979
34061
  attributes(this.element, { role: 'application', 'aria-label': 'Rich Text Editor' });
34062
+ this.beforeRenderClassValue = this.element.getAttribute('class');
33980
34063
  }
33981
34064
  persistData() {
33982
34065
  if (this.enablePersistence && this.originalElement.tagName === 'TEXTAREA') {
@@ -34847,6 +34930,10 @@ let RichTextEditor = class RichTextEditor extends Component {
34847
34930
  if (this.isDestroyed || !this.isRendered) {
34848
34931
  return;
34849
34932
  }
34933
+ this.element.className = this.beforeRenderClassValue;
34934
+ this.removeHtmlAttributes();
34935
+ this.removeAttributes();
34936
+ this.beforeRenderClassValue = null;
34850
34937
  if (!isNullOrUndefined(this.timeInterval)) {
34851
34938
  clearInterval(this.timeInterval);
34852
34939
  this.timeInterval = null;
@@ -34914,8 +35001,6 @@ let RichTextEditor = class RichTextEditor extends Component {
34914
35001
  }
34915
35002
  }
34916
35003
  }
34917
- this.removeHtmlAttributes();
34918
- this.removeAttributes();
34919
35004
  super.destroy();
34920
35005
  this.isRendered = false;
34921
35006
  }
@@ -34946,6 +35031,7 @@ let RichTextEditor = class RichTextEditor extends Component {
34946
35031
  this.element.removeAttribute('aria-disabled');
34947
35032
  this.element.removeAttribute('role');
34948
35033
  this.element.removeAttribute('tabindex');
35034
+ this.element.removeAttribute('aria-label');
34949
35035
  }
34950
35036
  destroyDependentModules() {
34951
35037
  /* destroy dependent modules */