roosterjs 9.6.0 → 9.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/rooster.js CHANGED
@@ -2094,8 +2094,8 @@ exports["default"] = getDarkColor;
2094
2094
  "use strict";
2095
2095
 
2096
2096
  Object.defineProperty(exports, "__esModule", ({ value: true }));
2097
- exports.formatTextSegmentBeforeSelectionMarker = exports.formatSegmentWithContentModel = exports.formatParagraphWithContentModel = exports.formatImageWithContentModel = exports.formatTableWithContentModel = exports.clearSelectedCells = exports.insertTableColumn = exports.insertTableRow = exports.insertEntity = exports.toggleCode = exports.setParagraphMargin = exports.adjustImageSelection = exports.setImageAltText = exports.adjustLinkSelection = exports.removeLink = exports.insertLink = exports.clearFormat = exports.getFormatState = exports.changeImage = exports.setImageBoxShadow = exports.setImageBorder = exports.setSpacing = exports.toggleBlockQuote = exports.setHeadingLevel = exports.setDirection = exports.setAlignment = exports.setIndentation = exports.setListStartNumber = exports.setListStyle = exports.insertImage = exports.changeCapitalization = exports.applySegmentFormat = exports.changeFontSize = exports.setTextColor = exports.setFontSize = exports.setFontName = exports.setBackgroundColor = exports.toggleSuperscript = exports.toggleSubscript = exports.toggleStrikethrough = exports.toggleUnderline = exports.toggleItalic = exports.toggleBold = exports.toggleNumbering = exports.toggleBullet = exports.applyTableBorderFormat = exports.editTable = exports.setTableCellShade = exports.formatTable = exports.insertTable = void 0;
2098
- exports.getListAnnounceData = exports.matchLink = exports.setModelIndentation = exports.findListItemsInSameThread = exports.setModelListStartNumber = exports.setModelListStyle = exports.setListType = exports.formatInsertPointWithContentModel = void 0;
2097
+ exports.formatSegmentWithContentModel = exports.formatParagraphWithContentModel = exports.formatImageWithContentModel = exports.formatTableWithContentModel = exports.clearSelectedCells = exports.insertTableColumn = exports.insertTableRow = exports.insertEntity = exports.toggleCode = exports.setParagraphMargin = exports.adjustImageSelection = exports.setImageAltText = exports.adjustLinkSelection = exports.removeLink = exports.insertLink = exports.clearFormat = exports.getFormatState = exports.changeImage = exports.setImageBoxShadow = exports.setImageBorder = exports.setSpacing = exports.toggleBlockQuote = exports.setHeadingLevel = exports.setDirection = exports.setAlignment = exports.setIndentation = exports.setListStartNumber = exports.setListStyle = exports.insertImage = exports.splitTextSegment = exports.changeCapitalization = exports.applySegmentFormat = exports.changeFontSize = exports.setTextColor = exports.setFontSize = exports.setFontName = exports.setBackgroundColor = exports.toggleSuperscript = exports.toggleSubscript = exports.toggleStrikethrough = exports.toggleUnderline = exports.toggleItalic = exports.toggleBold = exports.toggleNumbering = exports.toggleBullet = exports.applyTableBorderFormat = exports.editTable = exports.setTableCellShade = exports.formatTable = exports.insertTable = void 0;
2098
+ exports.getListAnnounceData = exports.matchLink = exports.setModelIndentation = exports.findListItemsInSameThread = exports.setModelListStartNumber = exports.setModelListStyle = exports.setListType = exports.formatInsertPointWithContentModel = exports.formatTextSegmentBeforeSelectionMarker = void 0;
2099
2099
  var insertTable_1 = __webpack_require__(/*! ./publicApi/table/insertTable */ "./packages/roosterjs-content-model-api/lib/publicApi/table/insertTable.ts");
2100
2100
  Object.defineProperty(exports, "insertTable", ({ enumerable: true, get: function () { return insertTable_1.insertTable; } }));
2101
2101
  var formatTable_1 = __webpack_require__(/*! ./publicApi/table/formatTable */ "./packages/roosterjs-content-model-api/lib/publicApi/table/formatTable.ts");
@@ -2136,6 +2136,8 @@ var applySegmentFormat_1 = __webpack_require__(/*! ./publicApi/segment/applySegm
2136
2136
  Object.defineProperty(exports, "applySegmentFormat", ({ enumerable: true, get: function () { return applySegmentFormat_1.applySegmentFormat; } }));
2137
2137
  var changeCapitalization_1 = __webpack_require__(/*! ./publicApi/segment/changeCapitalization */ "./packages/roosterjs-content-model-api/lib/publicApi/segment/changeCapitalization.ts");
2138
2138
  Object.defineProperty(exports, "changeCapitalization", ({ enumerable: true, get: function () { return changeCapitalization_1.changeCapitalization; } }));
2139
+ var splitTextSegment_1 = __webpack_require__(/*! ./publicApi/segment/splitTextSegment */ "./packages/roosterjs-content-model-api/lib/publicApi/segment/splitTextSegment.ts");
2140
+ Object.defineProperty(exports, "splitTextSegment", ({ enumerable: true, get: function () { return splitTextSegment_1.splitTextSegment; } }));
2139
2141
  var insertImage_1 = __webpack_require__(/*! ./publicApi/image/insertImage */ "./packages/roosterjs-content-model-api/lib/publicApi/image/insertImage.ts");
2140
2142
  Object.defineProperty(exports, "insertImage", ({ enumerable: true, get: function () { return insertImage_1.insertImage; } }));
2141
2143
  var setListStyle_1 = __webpack_require__(/*! ./publicApi/list/setListStyle */ "./packages/roosterjs-content-model-api/lib/publicApi/list/setListStyle.ts");
@@ -5878,6 +5880,47 @@ function setTextColor(editor, textColor) {
5878
5880
  exports.setTextColor = setTextColor;
5879
5881
 
5880
5882
 
5883
+ /***/ }),
5884
+
5885
+ /***/ "./packages/roosterjs-content-model-api/lib/publicApi/segment/splitTextSegment.ts":
5886
+ /*!****************************************************************************************!*\
5887
+ !*** ./packages/roosterjs-content-model-api/lib/publicApi/segment/splitTextSegment.ts ***!
5888
+ \****************************************************************************************/
5889
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
5890
+
5891
+ "use strict";
5892
+
5893
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
5894
+ exports.splitTextSegment = void 0;
5895
+ var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
5896
+ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
5897
+ /**
5898
+ * Split given text segments from the given range
5899
+ * @param textSegment segment to split
5900
+ * @param parent parent paragraph the text segment exist in
5901
+ * @param start starting point of the split
5902
+ * @param end ending point of the split
5903
+ * @returns text segment from the indicated split.
5904
+ */
5905
+ function splitTextSegment(textSegment, parent, start, end) {
5906
+ var _a;
5907
+ var text = textSegment.text;
5908
+ var index = parent.segments.indexOf(textSegment);
5909
+ var middleSegment = (0, roosterjs_content_model_dom_1.createText)(text.substring(start, end), textSegment.format, textSegment.link, textSegment.code);
5910
+ var newSegments = [middleSegment];
5911
+ if (start > 0) {
5912
+ newSegments.unshift((0, roosterjs_content_model_dom_1.createText)(text.substring(0, start), textSegment.format, textSegment.link, textSegment.code));
5913
+ }
5914
+ if (end < text.length) {
5915
+ newSegments.push((0, roosterjs_content_model_dom_1.createText)(text.substring(end), textSegment.format, textSegment.link, textSegment.code));
5916
+ }
5917
+ newSegments.forEach(function (segment) { return (segment.isSelected = textSegment.isSelected); });
5918
+ (_a = parent.segments).splice.apply(_a, (0, tslib_1.__spreadArray)([index, 1], (0, tslib_1.__read)(newSegments), false));
5919
+ return middleSegment;
5920
+ }
5921
+ exports.splitTextSegment = splitTextSegment;
5922
+
5923
+
5881
5924
  /***/ }),
5882
5925
 
5883
5926
  /***/ "./packages/roosterjs-content-model-api/lib/publicApi/segment/toggleBold.ts":
@@ -8427,7 +8470,7 @@ exports.coreApiMap = {
8427
8470
 
8428
8471
  Object.defineProperty(exports, "__esModule", ({ value: true }));
8429
8472
  exports.createContentModel = void 0;
8430
- var updateCachedSelection_1 = __webpack_require__(/*! ../../corePlugin/cache/updateCachedSelection */ "./packages/roosterjs-content-model-core/lib/corePlugin/cache/updateCachedSelection.ts");
8473
+ var updateCache_1 = __webpack_require__(/*! ../../corePlugin/cache/updateCache */ "./packages/roosterjs-content-model-core/lib/corePlugin/cache/updateCache.ts");
8431
8474
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
8432
8475
  /**
8433
8476
  * @internal
@@ -8463,8 +8506,7 @@ var createContentModel = function (core, option, selectionOverride) {
8463
8506
  }
8464
8507
  var model = (0, roosterjs_content_model_dom_1.domToContentModel)(core.logicalRoot, domToModelContext);
8465
8508
  if (saveIndex) {
8466
- core.cache.cachedModel = model;
8467
- (0, updateCachedSelection_1.updateCachedSelection)(core.cache, selection);
8509
+ (0, updateCache_1.updateCache)(core.cache, model, selection);
8468
8510
  }
8469
8511
  return model;
8470
8512
  };
@@ -9166,7 +9208,7 @@ exports.restoreUndoSnapshot = restoreUndoSnapshot;
9166
9208
 
9167
9209
  Object.defineProperty(exports, "__esModule", ({ value: true }));
9168
9210
  exports.setContentModel = void 0;
9169
- var updateCachedSelection_1 = __webpack_require__(/*! ../../corePlugin/cache/updateCachedSelection */ "./packages/roosterjs-content-model-core/lib/corePlugin/cache/updateCachedSelection.ts");
9211
+ var updateCache_1 = __webpack_require__(/*! ../../corePlugin/cache/updateCache */ "./packages/roosterjs-content-model-core/lib/corePlugin/cache/updateCache.ts");
9170
9212
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
9171
9213
  /**
9172
9214
  * @internal
@@ -9184,15 +9226,15 @@ var setContentModel = function (core, model, option, onNodeCreated) {
9184
9226
  modelToDomContext.onNodeCreated = onNodeCreated;
9185
9227
  var selection = (0, roosterjs_content_model_dom_1.contentModelToDom)(core.logicalRoot.ownerDocument, core.logicalRoot, model, modelToDomContext);
9186
9228
  if (!core.lifecycle.shadowEditFragment) {
9187
- (0, updateCachedSelection_1.updateCachedSelection)(core.cache, selection || undefined);
9229
+ // Clear pending mutations since we will use our latest model object to replace existing cache
9230
+ (_a = core.cache.textMutationObserver) === null || _a === void 0 ? void 0 : _a.flushMutations(true /*ignoreMutations*/);
9231
+ (0, updateCache_1.updateCache)(core.cache, model, selection);
9188
9232
  if (!(option === null || option === void 0 ? void 0 : option.ignoreSelection) && selection) {
9189
9233
  core.api.setDOMSelection(core, selection);
9190
9234
  }
9191
9235
  else {
9192
9236
  core.selection.selection = selection;
9193
9237
  }
9194
- // Clear pending mutations since we will use our latest model object to replace existing cache
9195
- (_a = core.cache.textMutationObserver) === null || _a === void 0 ? void 0 : _a.flushMutations(model);
9196
9238
  }
9197
9239
  return selection;
9198
9240
  };
@@ -9205,12 +9247,13 @@ exports.setContentModel = setContentModel;
9205
9247
  /*!**************************************************************************************************!*\
9206
9248
  !*** ./packages/roosterjs-content-model-core/lib/coreApi/setDOMSelection/addRangeToSelection.ts ***!
9207
9249
  \**************************************************************************************************/
9208
- /***/ ((__unused_webpack_module, exports) => {
9250
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
9209
9251
 
9210
9252
  "use strict";
9211
9253
 
9212
9254
  Object.defineProperty(exports, "__esModule", ({ value: true }));
9213
9255
  exports.addRangeToSelection = void 0;
9256
+ var areSameSelections_1 = __webpack_require__(/*! ../../corePlugin/cache/areSameSelections */ "./packages/roosterjs-content-model-core/lib/corePlugin/cache/areSameSelections.ts");
9214
9257
  /**
9215
9258
  * @internal
9216
9259
  */
@@ -9220,11 +9263,7 @@ function addRangeToSelection(doc, range, isReverted) {
9220
9263
  var selection = (_a = doc.defaultView) === null || _a === void 0 ? void 0 : _a.getSelection();
9221
9264
  if (selection) {
9222
9265
  var currentRange = selection.rangeCount > 0 && selection.getRangeAt(0);
9223
- if (currentRange &&
9224
- currentRange.startContainer == range.startContainer &&
9225
- currentRange.endContainer == range.endContainer &&
9226
- currentRange.startOffset == range.startOffset &&
9227
- currentRange.endOffset == range.endOffset) {
9266
+ if (currentRange && (0, areSameSelections_1.areSameRanges)(currentRange, range)) {
9228
9267
  return;
9229
9268
  }
9230
9269
  selection.removeAllRanges();
@@ -9239,40 +9278,6 @@ function addRangeToSelection(doc, range, isReverted) {
9239
9278
  exports.addRangeToSelection = addRangeToSelection;
9240
9279
 
9241
9280
 
9242
- /***/ }),
9243
-
9244
- /***/ "./packages/roosterjs-content-model-core/lib/coreApi/setDOMSelection/ensureImageHasSpanParent.ts":
9245
- /*!*******************************************************************************************************!*\
9246
- !*** ./packages/roosterjs-content-model-core/lib/coreApi/setDOMSelection/ensureImageHasSpanParent.ts ***!
9247
- \*******************************************************************************************************/
9248
- /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
9249
-
9250
- "use strict";
9251
-
9252
- Object.defineProperty(exports, "__esModule", ({ value: true }));
9253
- exports.ensureImageHasSpanParent = void 0;
9254
- var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
9255
- /**
9256
- * @internal
9257
- * Ensure image is wrapped by a span element
9258
- * @param image
9259
- * @returns the image
9260
- */
9261
- function ensureImageHasSpanParent(image) {
9262
- var parent = image.parentElement;
9263
- if (parent &&
9264
- (0, roosterjs_content_model_dom_1.isNodeOfType)(parent, 'ELEMENT_NODE') &&
9265
- (0, roosterjs_content_model_dom_1.isElementOfType)(parent, 'span') &&
9266
- parent.firstChild == image &&
9267
- parent.lastChild == image) {
9268
- return image;
9269
- }
9270
- (0, roosterjs_content_model_dom_1.wrap)(image.ownerDocument, image, 'span');
9271
- return image;
9272
- }
9273
- exports.ensureImageHasSpanParent = ensureImageHasSpanParent;
9274
-
9275
-
9276
9281
  /***/ }),
9277
9282
 
9278
9283
  /***/ "./packages/roosterjs-content-model-core/lib/coreApi/setDOMSelection/findLastedCoInMergedCell.ts":
@@ -9375,7 +9380,7 @@ exports.findTableCellElement = findTableCellElement;
9375
9380
  Object.defineProperty(exports, "__esModule", ({ value: true }));
9376
9381
  exports.setDOMSelection = void 0;
9377
9382
  var addRangeToSelection_1 = __webpack_require__(/*! ./addRangeToSelection */ "./packages/roosterjs-content-model-core/lib/coreApi/setDOMSelection/addRangeToSelection.ts");
9378
- var ensureImageHasSpanParent_1 = __webpack_require__(/*! ./ensureImageHasSpanParent */ "./packages/roosterjs-content-model-core/lib/coreApi/setDOMSelection/ensureImageHasSpanParent.ts");
9383
+ var areSameSelections_1 = __webpack_require__(/*! ../../corePlugin/cache/areSameSelections */ "./packages/roosterjs-content-model-core/lib/corePlugin/cache/areSameSelections.ts");
9379
9384
  var ensureUniqueId_1 = __webpack_require__(/*! ../setEditorStyle/ensureUniqueId */ "./packages/roosterjs-content-model-core/lib/coreApi/setEditorStyle/ensureUniqueId.ts");
9380
9385
  var findLastedCoInMergedCell_1 = __webpack_require__(/*! ./findLastedCoInMergedCell */ "./packages/roosterjs-content-model-core/lib/coreApi/setDOMSelection/findLastedCoInMergedCell.ts");
9381
9386
  var findTableCellElement_1 = __webpack_require__(/*! ./findTableCellElement */ "./packages/roosterjs-content-model-core/lib/coreApi/setDOMSelection/findTableCellElement.ts");
@@ -9388,11 +9393,16 @@ var TABLE_ID = 'table';
9388
9393
  var CARET_CSS_RULE = 'caret-color: transparent';
9389
9394
  var TRANSPARENT_SELECTION_CSS_RULE = 'background-color: transparent !important;';
9390
9395
  var SELECTION_SELECTOR = '*::selection';
9396
+ var DEFAULT_SELECTION_BORDER_COLOR = '#DB626C';
9391
9397
  /**
9392
9398
  * @internal
9393
9399
  */
9394
9400
  var setDOMSelection = function (core, selection, skipSelectionChangedEvent) {
9395
9401
  var _a, _b, _c;
9402
+ var existingSelection = core.api.getDOMSelection(core);
9403
+ if (existingSelection && selection && (0, areSameSelections_1.areSameSelections)(existingSelection, selection)) {
9404
+ return;
9405
+ }
9396
9406
  // We are applying a new selection, so we don't need to apply cached selection in DOMEventPlugin.
9397
9407
  // Set skipReselectOnFocus to skip this behavior
9398
9408
  var skipReselectOnFocus = core.selection.skipReselectOnFocus;
@@ -9405,15 +9415,12 @@ var setDOMSelection = function (core, selection, skipSelectionChangedEvent) {
9405
9415
  try {
9406
9416
  switch (selection === null || selection === void 0 ? void 0 : selection.type) {
9407
9417
  case 'image':
9408
- var image = (0, ensureImageHasSpanParent_1.ensureImageHasSpanParent)(selection.image);
9409
- core.selection.selection = {
9410
- type: 'image',
9411
- image: image,
9412
- };
9418
+ var image = selection.image;
9419
+ core.selection.selection = selection;
9413
9420
  var imageSelectionColor = isDarkMode
9414
9421
  ? core.selection.imageSelectionBorderColorDark
9415
9422
  : core.selection.imageSelectionBorderColor;
9416
- core.api.setEditorStyle(core, DOM_SELECTION_CSS_KEY, "outline-style:solid!important; outline-color:" + imageSelectionColor + "!important;display: " + (core.environment.isSafari ? '-webkit-inline-flex' : 'inline-flex') + ";", ["span:has(>img#" + (0, ensureUniqueId_1.ensureUniqueId)(image, IMAGE_ID) + ")"]);
9423
+ core.api.setEditorStyle(core, DOM_SELECTION_CSS_KEY, "outline-style:solid!important; outline-color:" + (imageSelectionColor || DEFAULT_SELECTION_BORDER_COLOR) + "!important;", ["#" + (0, ensureUniqueId_1.ensureUniqueId)(image, IMAGE_ID)]);
9417
9424
  core.api.setEditorStyle(core, HIDE_SELECTION_CSS_KEY, TRANSPARENT_SELECTION_CSS_RULE, [SELECTION_SELECTOR]);
9418
9425
  setRangeSelection(doc, image, false /* collapse */);
9419
9426
  break;
@@ -9808,10 +9815,10 @@ function handledExclusively(event, plugin) {
9808
9815
 
9809
9816
  Object.defineProperty(exports, "__esModule", ({ value: true }));
9810
9817
  exports.createCachePlugin = void 0;
9811
- var areSameSelection_1 = __webpack_require__(/*! ./areSameSelection */ "./packages/roosterjs-content-model-core/lib/corePlugin/cache/areSameSelection.ts");
9818
+ var areSameSelections_1 = __webpack_require__(/*! ./areSameSelections */ "./packages/roosterjs-content-model-core/lib/corePlugin/cache/areSameSelections.ts");
9812
9819
  var textMutationObserver_1 = __webpack_require__(/*! ./textMutationObserver */ "./packages/roosterjs-content-model-core/lib/corePlugin/cache/textMutationObserver.ts");
9813
9820
  var domIndexerImpl_1 = __webpack_require__(/*! ./domIndexerImpl */ "./packages/roosterjs-content-model-core/lib/corePlugin/cache/domIndexerImpl.ts");
9814
- var updateCachedSelection_1 = __webpack_require__(/*! ./updateCachedSelection */ "./packages/roosterjs-content-model-core/lib/corePlugin/cache/updateCachedSelection.ts");
9821
+ var updateCache_1 = __webpack_require__(/*! ./updateCache */ "./packages/roosterjs-content-model-core/lib/corePlugin/cache/updateCache.ts");
9815
9822
  /**
9816
9823
  * ContentModel cache plugin manages cached Content Model, and refresh the cache when necessary
9817
9824
  */
@@ -9824,40 +9831,37 @@ var CachePlugin = /** @class */ (function () {
9824
9831
  function CachePlugin(option, contentDiv) {
9825
9832
  var _this = this;
9826
9833
  this.editor = null;
9827
- this.onMutation = function (isTextChangeOnly) {
9834
+ this.onMutation = function (mutation) {
9835
+ var _a;
9828
9836
  if (_this.editor) {
9829
- if (isTextChangeOnly) {
9830
- _this.updateCachedModel(_this.editor, true /*forceUpdate*/);
9831
- }
9832
- else {
9833
- _this.invalidateCache();
9837
+ switch (mutation.type) {
9838
+ case 'childList':
9839
+ if (!((_a = _this.state.domIndexer) === null || _a === void 0 ? void 0 : _a.reconcileChildList(mutation.addedNodes, mutation.removedNodes))) {
9840
+ _this.invalidateCache();
9841
+ }
9842
+ break;
9843
+ case 'text':
9844
+ _this.updateCachedModel(_this.editor, true /*forceUpdate*/);
9845
+ break;
9846
+ case 'unknown':
9847
+ _this.invalidateCache();
9848
+ break;
9834
9849
  }
9835
9850
  }
9836
9851
  };
9837
- this.onSkipMutation = function (newModel) {
9838
- var _a;
9839
- if (!((_a = _this.editor) === null || _a === void 0 ? void 0 : _a.isInShadowEdit())) {
9840
- _this.state.cachedModel = newModel;
9841
- _this.state.cachedSelection = undefined;
9842
- }
9843
- };
9844
9852
  this.onNativeSelectionChange = function () {
9845
9853
  var _a;
9846
9854
  if ((_a = _this.editor) === null || _a === void 0 ? void 0 : _a.hasFocus()) {
9847
9855
  _this.updateCachedModel(_this.editor);
9848
9856
  }
9849
9857
  };
9850
- if (option.disableCache) {
9851
- this.state = {};
9852
- }
9853
- else {
9854
- var domIndexer = new domIndexerImpl_1.DomIndexerImpl(option.experimentalFeatures &&
9855
- option.experimentalFeatures.indexOf('PersistCache') >= 0);
9856
- this.state = {
9857
- domIndexer: domIndexer,
9858
- textMutationObserver: (0, textMutationObserver_1.createTextMutationObserver)(contentDiv, domIndexer, this.onMutation, this.onSkipMutation),
9858
+ this.state = option.disableCache
9859
+ ? {}
9860
+ : {
9861
+ domIndexer: new domIndexerImpl_1.DomIndexerImpl(option.experimentalFeatures &&
9862
+ option.experimentalFeatures.indexOf('PersistCache') >= 0),
9863
+ textMutationObserver: (0, textMutationObserver_1.createTextMutationObserver)(contentDiv, this.onMutation),
9859
9864
  };
9860
- }
9861
9865
  }
9862
9866
  /**
9863
9867
  * Get name of this plugin
@@ -9922,8 +9926,7 @@ var CachePlugin = /** @class */ (function () {
9922
9926
  case 'contentChanged':
9923
9927
  var contentModel = event.contentModel, selection = event.selection;
9924
9928
  if (contentModel && this.state.domIndexer) {
9925
- this.state.cachedModel = contentModel;
9926
- (0, updateCachedSelection_1.updateCachedSelection)(this.state, selection);
9929
+ (0, updateCache_1.updateCache)(this.state, contentModel, selection);
9927
9930
  }
9928
9931
  else {
9929
9932
  this.invalidateCache();
@@ -9940,6 +9943,9 @@ var CachePlugin = /** @class */ (function () {
9940
9943
  };
9941
9944
  CachePlugin.prototype.updateCachedModel = function (editor, forceUpdate) {
9942
9945
  var _a;
9946
+ if (editor.isInShadowEdit()) {
9947
+ return;
9948
+ }
9943
9949
  var cachedSelection = this.state.cachedSelection;
9944
9950
  this.state.cachedSelection = undefined; // Clear it to force getDOMSelection() retrieve the latest selection range
9945
9951
  var newRangeEx = editor.getDOMSelection() || undefined;
@@ -9947,7 +9953,7 @@ var CachePlugin = /** @class */ (function () {
9947
9953
  var isSelectionChanged = forceUpdate ||
9948
9954
  !cachedSelection ||
9949
9955
  !newRangeEx ||
9950
- !(0, areSameSelection_1.areSameSelection)(newRangeEx, cachedSelection);
9956
+ !(0, areSameSelections_1.areSameSelections)(newRangeEx, cachedSelection);
9951
9957
  if (isSelectionChanged) {
9952
9958
  if (!model ||
9953
9959
  !newRangeEx ||
@@ -9955,7 +9961,7 @@ var CachePlugin = /** @class */ (function () {
9955
9961
  this.invalidateCache();
9956
9962
  }
9957
9963
  else {
9958
- (0, updateCachedSelection_1.updateCachedSelection)(this.state, newRangeEx);
9964
+ (0, updateCache_1.updateCache)(this.state, model, newRangeEx);
9959
9965
  }
9960
9966
  }
9961
9967
  else {
@@ -9978,21 +9984,21 @@ exports.createCachePlugin = createCachePlugin;
9978
9984
 
9979
9985
  /***/ }),
9980
9986
 
9981
- /***/ "./packages/roosterjs-content-model-core/lib/corePlugin/cache/areSameSelection.ts":
9982
- /*!****************************************************************************************!*\
9983
- !*** ./packages/roosterjs-content-model-core/lib/corePlugin/cache/areSameSelection.ts ***!
9984
- \****************************************************************************************/
9987
+ /***/ "./packages/roosterjs-content-model-core/lib/corePlugin/cache/areSameSelections.ts":
9988
+ /*!*****************************************************************************************!*\
9989
+ !*** ./packages/roosterjs-content-model-core/lib/corePlugin/cache/areSameSelections.ts ***!
9990
+ \*****************************************************************************************/
9985
9991
  /***/ ((__unused_webpack_module, exports) => {
9986
9992
 
9987
9993
  "use strict";
9988
9994
 
9989
9995
  Object.defineProperty(exports, "__esModule", ({ value: true }));
9990
- exports.areSameSelection = void 0;
9996
+ exports.areSameRanges = exports.areSameTableSelections = exports.areSameSelections = void 0;
9991
9997
  /**
9992
9998
  * @internal
9993
9999
  * Check if the given selections are the same
9994
10000
  */
9995
- function areSameSelection(sel1, sel2) {
10001
+ function areSameSelections(sel1, sel2) {
9996
10002
  if (sel1 == sel2) {
9997
10003
  return true;
9998
10004
  }
@@ -10000,22 +10006,56 @@ function areSameSelection(sel1, sel2) {
10000
10006
  case 'image':
10001
10007
  return sel2.type == 'image' && sel2.image == sel1.image;
10002
10008
  case 'table':
10003
- return (sel2.type == 'table' &&
10004
- sel2.table == sel1.table &&
10005
- sel2.firstColumn == sel1.firstColumn &&
10006
- sel2.lastColumn == sel1.lastColumn &&
10007
- sel2.firstRow == sel1.firstRow &&
10008
- sel2.lastRow == sel1.lastRow);
10009
+ return sel2.type == 'table' && areSameTableSelections(sel1, sel2);
10009
10010
  case 'range':
10010
10011
  default:
10011
- return (sel2.type == 'range' &&
10012
- sel1.range.startContainer == sel2.start.node &&
10013
- sel1.range.endContainer == sel2.end.node &&
10014
- sel1.range.startOffset == sel2.start.offset &&
10015
- sel1.range.endOffset == sel2.end.offset);
10012
+ if (sel2.type == 'range') {
10013
+ var range1 = sel1.range;
10014
+ if (isCacheSelection(sel2)) {
10015
+ var start = sel2.start, end = sel2.end;
10016
+ return (range1.startContainer == start.node &&
10017
+ range1.endContainer == end.node &&
10018
+ range1.startOffset == start.offset &&
10019
+ range1.endOffset == end.offset);
10020
+ }
10021
+ else {
10022
+ return areSameRanges(range1, sel2.range);
10023
+ }
10024
+ }
10025
+ else {
10026
+ return false;
10027
+ }
10016
10028
  }
10017
10029
  }
10018
- exports.areSameSelection = areSameSelection;
10030
+ exports.areSameSelections = areSameSelections;
10031
+ function areSame(o1, o2, keys) {
10032
+ return keys.every(function (k) { return o1[k] == o2[k]; });
10033
+ }
10034
+ var TableSelectionKeys = [
10035
+ 'table',
10036
+ 'firstColumn',
10037
+ 'lastColumn',
10038
+ 'firstRow',
10039
+ 'lastRow',
10040
+ ];
10041
+ var RangeKeys = ['startContainer', 'endContainer', 'startOffset', 'endOffset'];
10042
+ /**
10043
+ * @internal
10044
+ */
10045
+ function areSameTableSelections(t1, t2) {
10046
+ return areSame(t1, t2, TableSelectionKeys);
10047
+ }
10048
+ exports.areSameTableSelections = areSameTableSelections;
10049
+ /**
10050
+ * @internal
10051
+ */
10052
+ function areSameRanges(r1, r2) {
10053
+ return areSame(r1, r2, RangeKeys);
10054
+ }
10055
+ exports.areSameRanges = areSameRanges;
10056
+ function isCacheSelection(sel) {
10057
+ return !!sel.start;
10058
+ }
10019
10059
 
10020
10060
 
10021
10061
  /***/ }),
@@ -10354,12 +10394,10 @@ exports.DomIndexerImpl = DomIndexerImpl;
10354
10394
  Object.defineProperty(exports, "__esModule", ({ value: true }));
10355
10395
  exports.createTextMutationObserver = void 0;
10356
10396
  var TextMutationObserverImpl = /** @class */ (function () {
10357
- function TextMutationObserverImpl(contentDiv, domIndexer, onMutation, onSkipMutation) {
10397
+ function TextMutationObserverImpl(contentDiv, onMutation) {
10358
10398
  var _this = this;
10359
10399
  this.contentDiv = contentDiv;
10360
- this.domIndexer = domIndexer;
10361
10400
  this.onMutation = onMutation;
10362
- this.onSkipMutation = onSkipMutation;
10363
10401
  this.onMutationInternal = function (mutations) {
10364
10402
  var canHandle = true;
10365
10403
  var firstTarget = null;
@@ -10400,14 +10438,20 @@ var TextMutationObserverImpl = /** @class */ (function () {
10400
10438
  break;
10401
10439
  }
10402
10440
  }
10403
- if (canHandle && (addedNodes.length > 0 || removedNodes.length > 0)) {
10404
- canHandle = _this.domIndexer.reconcileChildList(addedNodes, removedNodes);
10405
- }
10406
- if (canHandle && reconcileText) {
10407
- _this.onMutation(true /*textOnly*/);
10441
+ if (canHandle) {
10442
+ if (addedNodes.length > 0 || removedNodes.length > 0) {
10443
+ _this.onMutation({
10444
+ type: 'childList',
10445
+ addedNodes: addedNodes,
10446
+ removedNodes: removedNodes,
10447
+ });
10448
+ }
10449
+ if (reconcileText) {
10450
+ _this.onMutation({ type: 'text' });
10451
+ }
10408
10452
  }
10409
- else if (!canHandle) {
10410
- _this.onMutation(false /*textOnly*/);
10453
+ else {
10454
+ _this.onMutation({ type: 'unknown' });
10411
10455
  }
10412
10456
  };
10413
10457
  this.observer = new MutationObserver(this.onMutationInternal);
@@ -10423,12 +10467,9 @@ var TextMutationObserverImpl = /** @class */ (function () {
10423
10467
  TextMutationObserverImpl.prototype.stopObserving = function () {
10424
10468
  this.observer.disconnect();
10425
10469
  };
10426
- TextMutationObserverImpl.prototype.flushMutations = function (model) {
10470
+ TextMutationObserverImpl.prototype.flushMutations = function (ignoreMutations) {
10427
10471
  var mutations = this.observer.takeRecords();
10428
- if (model) {
10429
- this.onSkipMutation(model);
10430
- }
10431
- else {
10472
+ if (!ignoreMutations) {
10432
10473
  this.onMutationInternal(mutations);
10433
10474
  }
10434
10475
  };
@@ -10437,28 +10478,29 @@ var TextMutationObserverImpl = /** @class */ (function () {
10437
10478
  /**
10438
10479
  * @internal
10439
10480
  */
10440
- function createTextMutationObserver(contentDiv, domIndexer, onMutation, onSkipMutation) {
10441
- return new TextMutationObserverImpl(contentDiv, domIndexer, onMutation, onSkipMutation);
10481
+ function createTextMutationObserver(contentDiv, onMutation) {
10482
+ return new TextMutationObserverImpl(contentDiv, onMutation);
10442
10483
  }
10443
10484
  exports.createTextMutationObserver = createTextMutationObserver;
10444
10485
 
10445
10486
 
10446
10487
  /***/ }),
10447
10488
 
10448
- /***/ "./packages/roosterjs-content-model-core/lib/corePlugin/cache/updateCachedSelection.ts":
10449
- /*!*********************************************************************************************!*\
10450
- !*** ./packages/roosterjs-content-model-core/lib/corePlugin/cache/updateCachedSelection.ts ***!
10451
- \*********************************************************************************************/
10489
+ /***/ "./packages/roosterjs-content-model-core/lib/corePlugin/cache/updateCache.ts":
10490
+ /*!***********************************************************************************!*\
10491
+ !*** ./packages/roosterjs-content-model-core/lib/corePlugin/cache/updateCache.ts ***!
10492
+ \***********************************************************************************/
10452
10493
  /***/ ((__unused_webpack_module, exports) => {
10453
10494
 
10454
10495
  "use strict";
10455
10496
 
10456
10497
  Object.defineProperty(exports, "__esModule", ({ value: true }));
10457
- exports.updateCachedSelection = void 0;
10498
+ exports.updateCache = void 0;
10458
10499
  /**
10459
10500
  * @internal
10460
10501
  */
10461
- function updateCachedSelection(state, selection) {
10502
+ function updateCache(state, model, selection) {
10503
+ state.cachedModel = model;
10462
10504
  if ((selection === null || selection === void 0 ? void 0 : selection.type) == 'range') {
10463
10505
  var _a = selection.range, startContainer = _a.startContainer, startOffset = _a.startOffset, endContainer = _a.endContainer, endOffset = _a.endOffset, isReverted = selection.isReverted;
10464
10506
  state.cachedSelection = {
@@ -10475,10 +10517,10 @@ function updateCachedSelection(state, selection) {
10475
10517
  };
10476
10518
  }
10477
10519
  else {
10478
- state.cachedSelection = selection;
10520
+ state.cachedSelection = selection !== null && selection !== void 0 ? selection : undefined;
10479
10521
  }
10480
10522
  }
10481
- exports.updateCachedSelection = updateCachedSelection;
10523
+ exports.updateCache = updateCache;
10482
10524
 
10483
10525
 
10484
10526
  /***/ }),
@@ -12378,7 +12420,6 @@ var isSingleImageInSelection_1 = __webpack_require__(/*! ./isSingleImageInSelect
12378
12420
  var normalizePos_1 = __webpack_require__(/*! ./normalizePos */ "./packages/roosterjs-content-model-core/lib/corePlugin/selection/normalizePos.ts");
12379
12421
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
12380
12422
  var MouseLeftButton = 0;
12381
- var MouseMiddleButton = 1;
12382
12423
  var MouseRightButton = 2;
12383
12424
  var Up = 'ArrowUp';
12384
12425
  var Down = 'ArrowDown';
@@ -12493,16 +12534,17 @@ var SelectionPlugin = /** @class */ (function () {
12493
12534
  var newSelection = _this.editor.getDOMSelection();
12494
12535
  //If am image selection changed to a wider range due a keyboard event, we should update the selection
12495
12536
  var selection = _this.editor.getDocument().getSelection();
12496
- if ((newSelection === null || newSelection === void 0 ? void 0 : newSelection.type) == 'image' && selection) {
12497
- if (selection && !(0, isSingleImageInSelection_1.isSingleImageInSelection)(selection)) {
12498
- var range = selection.getRangeAt(0);
12499
- _this.editor.setDOMSelection({
12500
- type: 'range',
12501
- range: range,
12502
- isReverted: selection.focusNode != range.endContainer ||
12503
- selection.focusOffset != range.endOffset,
12504
- });
12505
- }
12537
+ if ((newSelection === null || newSelection === void 0 ? void 0 : newSelection.type) == 'image' &&
12538
+ selection &&
12539
+ selection.focusNode &&
12540
+ !(0, isSingleImageInSelection_1.isSingleImageInSelection)(selection)) {
12541
+ var range = selection.getRangeAt(0);
12542
+ _this.editor.setDOMSelection({
12543
+ type: 'range',
12544
+ range: range,
12545
+ isReverted: selection.focusNode != range.endContainer ||
12546
+ selection.focusOffset != range.endOffset,
12547
+ });
12506
12548
  }
12507
12549
  // Safari has problem to handle onBlur event. When blur, we cannot get the original selection from editor.
12508
12550
  // So we always save a selection whenever editor has focus. Then after blur, we can still use this cached selection.
@@ -12584,7 +12626,7 @@ var SelectionPlugin = /** @class */ (function () {
12584
12626
  this.onMouseDown(this.editor, event.rawEvent);
12585
12627
  break;
12586
12628
  case 'mouseUp':
12587
- this.onMouseUp(event);
12629
+ this.onMouseUp();
12588
12630
  break;
12589
12631
  case 'keyDown':
12590
12632
  this.onKeyDown(this.editor, event.rawEvent);
@@ -12604,15 +12646,20 @@ var SelectionPlugin = /** @class */ (function () {
12604
12646
  var selection = editor.getDOMSelection();
12605
12647
  var image;
12606
12648
  // Image selection
12607
- if (rawEvent.button === MouseRightButton &&
12608
- (image =
12609
- (_a = this.getClickingImage(rawEvent)) !== null && _a !== void 0 ? _a : this.getContainedTargetImage(rawEvent, selection)) &&
12610
- image.isContentEditable) {
12611
- this.selectImageWithRange(image, rawEvent);
12612
- return;
12649
+ if ((selection === null || selection === void 0 ? void 0 : selection.type) == 'image' &&
12650
+ (rawEvent.button == MouseLeftButton ||
12651
+ (rawEvent.button == MouseRightButton &&
12652
+ !this.getClickingImage(rawEvent) &&
12653
+ !this.getContainedTargetImage(rawEvent, selection)))) {
12654
+ this.setDOMSelection(null /*domSelection*/, null /*tableSelection*/);
12613
12655
  }
12614
- else if ((selection === null || selection === void 0 ? void 0 : selection.type) == 'image' && selection.image !== rawEvent.target) {
12615
- this.selectBeforeOrAfterElement(editor, selection.image);
12656
+ if ((image =
12657
+ (_a = this.getClickingImage(rawEvent)) !== null && _a !== void 0 ? _a : this.getContainedTargetImage(rawEvent, selection)) &&
12658
+ image.isContentEditable) {
12659
+ this.setDOMSelection({
12660
+ type: 'image',
12661
+ image: image,
12662
+ }, null);
12616
12663
  return;
12617
12664
  }
12618
12665
  // Table selection
@@ -12641,32 +12688,7 @@ var SelectionPlugin = /** @class */ (function () {
12641
12688
  });
12642
12689
  }
12643
12690
  };
12644
- SelectionPlugin.prototype.selectImageWithRange = function (image, event) {
12645
- var _a;
12646
- var range = image.ownerDocument.createRange();
12647
- range.selectNode(image);
12648
- var domSelection = (_a = this.editor) === null || _a === void 0 ? void 0 : _a.getDOMSelection();
12649
- if ((domSelection === null || domSelection === void 0 ? void 0 : domSelection.type) == 'image' && image == domSelection.image) {
12650
- event.preventDefault();
12651
- }
12652
- else {
12653
- this.setDOMSelection({
12654
- type: 'range',
12655
- isReverted: false,
12656
- range: range,
12657
- }, null);
12658
- }
12659
- };
12660
- SelectionPlugin.prototype.onMouseUp = function (event) {
12661
- var image;
12662
- if ((image = this.getClickingImage(event.rawEvent)) &&
12663
- image.isContentEditable &&
12664
- event.rawEvent.button != MouseMiddleButton &&
12665
- (event.rawEvent.button ==
12666
- MouseRightButton /* it's not possible to drag using right click */ ||
12667
- event.isClicking)) {
12668
- this.selectImageWithRange(image, event.rawEvent);
12669
- }
12691
+ SelectionPlugin.prototype.onMouseUp = function () {
12670
12692
  this.detachMouseEvent();
12671
12693
  };
12672
12694
  SelectionPlugin.prototype.onKeyDown = function (editor, rawEvent) {
@@ -12744,6 +12766,7 @@ var SelectionPlugin = /** @class */ (function () {
12744
12766
  return;
12745
12767
  }
12746
12768
  var lastCo = (0, findCoordinate_1.findCoordinate)(tableSel === null || tableSel === void 0 ? void 0 : tableSel.parsedTable, end, domHelper);
12769
+ var tabMove = false;
12747
12770
  var _h = this.state.tableSelection, parsedTable = _h.parsedTable, oldCo = _h.firstCo, table = _h.table;
12748
12771
  if (lastCo && tableSel.table == table) {
12749
12772
  if (lastCo.col != oldCo.col && (key == Up || key == Down)) {
@@ -12781,7 +12804,8 @@ var SelectionPlugin = /** @class */ (function () {
12781
12804
  }
12782
12805
  var cell = parsedTable[row][col];
12783
12806
  if (typeof cell != 'string') {
12784
- this.setRangeSelectionInTable(cell, 0, this.editor);
12807
+ tabMove = true;
12808
+ this.setRangeSelectionInTable(cell, 0, this.editor, true /* selectAll */);
12785
12809
  lastCo.row = row;
12786
12810
  lastCo.col = col;
12787
12811
  break;
@@ -12799,18 +12823,23 @@ var SelectionPlugin = /** @class */ (function () {
12799
12823
  (_f = this.editor) === null || _f === void 0 ? void 0 : _f.announce({ defaultStrings: 'announceOnFocusLastCell' });
12800
12824
  }
12801
12825
  }
12802
- if (!collapsed && lastCo) {
12826
+ if (!collapsed && lastCo && !tabMove) {
12803
12827
  this.state.tableSelection = tableSel;
12804
12828
  this.updateTableSelection(lastCo);
12805
12829
  }
12806
12830
  }
12807
12831
  };
12808
- SelectionPlugin.prototype.setRangeSelectionInTable = function (cell, nodeOffset, editor) {
12809
- // Get deepest editable position in the cell
12810
- var _a = (0, normalizePos_1.normalizePos)(cell, nodeOffset), node = _a.node, offset = _a.offset;
12832
+ SelectionPlugin.prototype.setRangeSelectionInTable = function (cell, nodeOffset, editor, selectAll) {
12811
12833
  var range = editor.getDocument().createRange();
12812
- range.setStart(node, offset);
12813
- range.collapse(true /*toStart*/);
12834
+ if (selectAll) {
12835
+ range.selectNodeContents(cell);
12836
+ }
12837
+ else {
12838
+ // Get deepest editable position in the cell
12839
+ var _a = (0, normalizePos_1.normalizePos)(cell, nodeOffset), node = _a.node, offset = _a.offset;
12840
+ range.setStart(node, offset);
12841
+ range.collapse(true /* toStart */);
12842
+ }
12814
12843
  this.setDOMSelection({
12815
12844
  type: 'range',
12816
12845
  range: range,
@@ -17542,16 +17571,14 @@ var normalizeRect_1 = __webpack_require__(/*! ../normalizeRect */ "./packages/ro
17542
17571
  * @param pos The input DOM insert point
17543
17572
  */
17544
17573
  function getDOMInsertPointRect(doc, pos) {
17545
- var _a;
17546
- var node = pos.node, offset = pos.offset;
17574
+ var _a, _b;
17547
17575
  var range = doc.createRange();
17548
- range.setStart(node, offset);
17549
- // 1) try to get rect using range.getBoundingClientRect()
17550
- var rect = (0, normalizeRect_1.normalizeRect)(range.getBoundingClientRect());
17551
- if (rect) {
17552
- return rect;
17553
- }
17554
- // 2) try to get rect using range.getClientRects
17576
+ return ((_b = (_a = tryGetRectFromPos(pos, range)) !== null && _a !== void 0 ? _a : tryGetRectFromPos((pos = normalizeInsertPoint(pos)), range)) !== null && _b !== void 0 ? _b : tryGetRectFromNode(pos.node) // 3. fallback to node rect using getBoundingClientRect
17577
+ );
17578
+ }
17579
+ exports.getDOMInsertPointRect = getDOMInsertPointRect;
17580
+ function normalizeInsertPoint(pos) {
17581
+ var node = pos.node, offset = pos.offset;
17555
17582
  while (node.lastChild) {
17556
17583
  if (offset == node.childNodes.length) {
17557
17584
  node = node.lastChild;
@@ -17562,32 +17589,26 @@ function getDOMInsertPointRect(doc, pos) {
17562
17589
  offset = 0;
17563
17590
  }
17564
17591
  }
17565
- var rects = range.getClientRects && range.getClientRects();
17566
- rect = rects && rects.length == 1 ? (0, normalizeRect_1.normalizeRect)(rects[0]) : null;
17592
+ return { node: node, offset: offset };
17593
+ }
17594
+ function tryGetRectFromPos(pos, range) {
17595
+ var node = pos.node, offset = pos.offset;
17596
+ range.setStart(node, offset);
17597
+ range.setEnd(node, offset);
17598
+ var rect = (0, normalizeRect_1.normalizeRect)(range.getBoundingClientRect());
17567
17599
  if (rect) {
17568
17600
  return rect;
17569
17601
  }
17570
- // 3) if node is text node, try inserting a SPAN and get the rect of SPAN for others
17571
- if ((0, isNodeOfType_1.isNodeOfType)(node, 'TEXT_NODE')) {
17572
- var span = node.ownerDocument.createElement('span');
17573
- span.textContent = '\u200b';
17574
- range.insertNode(span);
17575
- rect = (0, normalizeRect_1.normalizeRect)(span.getBoundingClientRect());
17576
- (_a = span.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(span);
17577
- if (rect) {
17578
- return rect;
17579
- }
17580
- }
17581
- // 4) try getBoundingClientRect on element
17582
- if ((0, isNodeOfType_1.isNodeOfType)(node, 'ELEMENT_NODE') && node.getBoundingClientRect) {
17583
- rect = (0, normalizeRect_1.normalizeRect)(node.getBoundingClientRect());
17584
- if (rect) {
17585
- return rect;
17586
- }
17602
+ else {
17603
+ var rects = range.getClientRects && range.getClientRects();
17604
+ return rects && rects.length == 1 ? (0, normalizeRect_1.normalizeRect)(rects[0]) : null;
17587
17605
  }
17588
- return null;
17589
17606
  }
17590
- exports.getDOMInsertPointRect = getDOMInsertPointRect;
17607
+ function tryGetRectFromNode(node) {
17608
+ return (0, isNodeOfType_1.isNodeOfType)(node, 'ELEMENT_NODE') && node.getBoundingClientRect
17609
+ ? (0, normalizeRect_1.normalizeRect)(node.getBoundingClientRect())
17610
+ : null;
17611
+ }
17591
17612
 
17592
17613
 
17593
17614
  /***/ }),
@@ -25881,8 +25902,7 @@ function removeUnnecessarySpan(root) {
25881
25902
  for (var child = root.firstChild; child;) {
25882
25903
  if ((0, isNodeOfType_1.isNodeOfType)(child, 'ELEMENT_NODE') &&
25883
25904
  child.tagName == 'SPAN' &&
25884
- child.attributes.length == 0 &&
25885
- !isImageSpan(child)) {
25905
+ child.attributes.length == 0) {
25886
25906
  var node = child;
25887
25907
  var refNode = child.nextSibling;
25888
25908
  child = child.nextSibling;
@@ -25899,11 +25919,6 @@ function removeUnnecessarySpan(root) {
25899
25919
  }
25900
25920
  }
25901
25921
  exports.removeUnnecessarySpan = removeUnnecessarySpan;
25902
- var isImageSpan = function (child) {
25903
- return ((0, isNodeOfType_1.isNodeOfType)(child.firstChild, 'ELEMENT_NODE') &&
25904
- child.firstChild.tagName == 'IMG' &&
25905
- child.firstChild == child.lastChild);
25906
- };
25907
25922
 
25908
25923
 
25909
25924
  /***/ }),
@@ -26313,7 +26328,7 @@ var getChangeSource = function (shouldList, shouldHyphen, shouldLink) {
26313
26328
 
26314
26329
  Object.defineProperty(exports, "__esModule", ({ value: true }));
26315
26330
  exports.transformHyphen = void 0;
26316
- var splitTextSegment_1 = __webpack_require__(/*! ../../pluginUtils/splitTextSegment */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/splitTextSegment.ts");
26331
+ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
26317
26332
  /**
26318
26333
  * @internal
26319
26334
  */
@@ -26322,7 +26337,7 @@ function transformHyphen(previousSegment, paragraph, context) {
26322
26337
  var dashes = segments[segments.length - 2];
26323
26338
  if (dashes === '--') {
26324
26339
  var textIndex = previousSegment.text.lastIndexOf('--');
26325
- var textSegment = (0, splitTextSegment_1.splitTextSegment)(previousSegment, paragraph, textIndex, textIndex + 2);
26340
+ var textSegment = (0, roosterjs_content_model_api_1.splitTextSegment)(previousSegment, paragraph, textIndex, textIndex + 2);
26326
26341
  textSegment.text = textSegment.text.replace('--', '—');
26327
26342
  context.canUndoByBackspace = true;
26328
26343
  return true;
@@ -26332,7 +26347,7 @@ function transformHyphen(previousSegment, paragraph, context) {
26332
26347
  var hasDashes = text && (text === null || text === void 0 ? void 0 : text.indexOf('--')) > -1;
26333
26348
  if (hasDashes && text.trim() !== '--') {
26334
26349
  var textIndex = previousSegment.text.indexOf(text);
26335
- var textSegment = (0, splitTextSegment_1.splitTextSegment)(previousSegment, paragraph, textIndex, textIndex + text.length - 1);
26350
+ var textSegment = (0, roosterjs_content_model_api_1.splitTextSegment)(previousSegment, paragraph, textIndex, textIndex + text.length - 1);
26336
26351
  var textLength = textSegment.text.length;
26337
26352
  if (textSegment.text[0] !== '-' && textSegment.text[textLength - 1] !== '-') {
26338
26353
  textSegment.text = textSegment.text.replace('--', '—');
@@ -26365,8 +26380,10 @@ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-mo
26365
26380
  */
26366
26381
  function createLink(editor) {
26367
26382
  var anchorNode = null;
26383
+ var links = [];
26368
26384
  (0, roosterjs_content_model_api_1.formatTextSegmentBeforeSelectionMarker)(editor, function (_model, linkSegment, _paragraph) {
26369
26385
  if (linkSegment.link) {
26386
+ links.push(linkSegment.link);
26370
26387
  return true;
26371
26388
  }
26372
26389
  var linkData = null;
@@ -26378,13 +26395,16 @@ function createLink(editor) {
26378
26395
  },
26379
26396
  dataset: {},
26380
26397
  });
26398
+ if (linkSegment.link) {
26399
+ links.push(linkSegment.link);
26400
+ }
26381
26401
  return true;
26382
26402
  }
26383
26403
  return false;
26384
26404
  }, {
26385
26405
  changeSource: roosterjs_content_model_dom_1.ChangeSource.AutoLink,
26386
- onNodeCreated: function (_modelElement, node) {
26387
- if (!anchorNode) {
26406
+ onNodeCreated: function (modelElement, node) {
26407
+ if (!anchorNode && links.indexOf(modelElement) >= 0) {
26388
26408
  anchorNode = node;
26389
26409
  }
26390
26410
  },
@@ -26407,7 +26427,6 @@ exports.createLink = createLink;
26407
26427
  Object.defineProperty(exports, "__esModule", ({ value: true }));
26408
26428
  exports.createLinkAfterSpace = void 0;
26409
26429
  var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
26410
- var splitTextSegment_1 = __webpack_require__(/*! ../../pluginUtils/splitTextSegment */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/splitTextSegment.ts");
26411
26430
  /**
26412
26431
  * @internal
26413
26432
  */
@@ -26416,7 +26435,7 @@ function createLinkAfterSpace(previousSegment, paragraph, context) {
26416
26435
  var url = link === null || link === void 0 ? void 0 : link.trim();
26417
26436
  var linkData = null;
26418
26437
  if (url && link && (linkData = (0, roosterjs_content_model_api_1.matchLink)(url))) {
26419
- var linkSegment = (0, splitTextSegment_1.splitTextSegment)(previousSegment, paragraph, previousSegment.text.length - link.trimLeft().length, previousSegment.text.trimRight().length);
26438
+ var linkSegment = (0, roosterjs_content_model_api_1.splitTextSegment)(previousSegment, paragraph, previousSegment.text.length - link.trimLeft().length, previousSegment.text.trimRight().length);
26420
26439
  linkSegment.link = {
26421
26440
  format: {
26422
26441
  href: linkData.normalizedUrl,
@@ -26842,7 +26861,7 @@ var triggerList = function (model, listType, styleType, index) {
26842
26861
 
26843
26862
  Object.defineProperty(exports, "__esModule", ({ value: true }));
26844
26863
  exports.transformFraction = void 0;
26845
- var splitTextSegment_1 = __webpack_require__(/*! ../../pluginUtils/splitTextSegment */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/splitTextSegment.ts");
26864
+ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
26846
26865
  var FRACTIONS = new Map([
26847
26866
  ['1/2', '½'],
26848
26867
  ['1/4', '¼'],
@@ -26858,7 +26877,7 @@ function transformFraction(previousSegment, paragraph, context) {
26858
26877
  if (fraction && text) {
26859
26878
  var textLength = previousSegment.text.length - 1;
26860
26879
  var textIndex = textLength - fraction.length;
26861
- var textSegment = (0, splitTextSegment_1.splitTextSegment)(previousSegment, paragraph, textIndex, textLength);
26880
+ var textSegment = (0, roosterjs_content_model_api_1.splitTextSegment)(previousSegment, paragraph, textIndex, textLength);
26862
26881
  textSegment.text = text;
26863
26882
  context.canUndoByBackspace = true;
26864
26883
  return true;
@@ -26880,7 +26899,7 @@ exports.transformFraction = transformFraction;
26880
26899
 
26881
26900
  Object.defineProperty(exports, "__esModule", ({ value: true }));
26882
26901
  exports.transformOrdinals = void 0;
26883
- var splitTextSegment_1 = __webpack_require__(/*! ../../pluginUtils/splitTextSegment */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/splitTextSegment.ts");
26902
+ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
26884
26903
  var getOrdinal = function (value) {
26885
26904
  var ORDINALS = {
26886
26905
  1: 'st',
@@ -26899,7 +26918,7 @@ function transformOrdinals(previousSegment, paragraph, context) {
26899
26918
  var ordinal = value.substring(value.length - 2);
26900
26919
  var ordinalValue = parseInt(value);
26901
26920
  if (ordinalValue && getOrdinal(ordinalValue) === ordinal) {
26902
- var ordinalSegment = (0, splitTextSegment_1.splitTextSegment)(previousSegment, paragraph, previousSegment.text.length - 3, previousSegment.text.length - 1);
26921
+ var ordinalSegment = (0, roosterjs_content_model_api_1.splitTextSegment)(previousSegment, paragraph, previousSegment.text.length - 3, previousSegment.text.length - 1);
26903
26922
  ordinalSegment.format.superOrSubScriptSequence = 'super';
26904
26923
  context.canUndoByBackspace = true;
26905
26924
  return true;
@@ -27120,6 +27139,9 @@ var keyboardTab_1 = __webpack_require__(/*! ./keyboardTab */ "./packages/rooster
27120
27139
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
27121
27140
  var BACKSPACE_KEY = 8;
27122
27141
  var DELETE_KEY = 46;
27142
+ var DefaultOptions = {
27143
+ handleTabKey: true,
27144
+ };
27123
27145
  /**
27124
27146
  * Edit plugins helps editor to do editing operation on top of content model.
27125
27147
  * This includes:
@@ -27128,7 +27150,13 @@ var DELETE_KEY = 46;
27128
27150
  * 3. Tab Key
27129
27151
  */
27130
27152
  var EditPlugin = /** @class */ (function () {
27131
- function EditPlugin() {
27153
+ /**
27154
+ * @param options An optional parameter that takes in an object of type EditOptions, which includes the following properties:
27155
+ * handleTabKey: A boolean that enables or disables Tab key handling. Defaults to true.
27156
+ */
27157
+ function EditPlugin(options) {
27158
+ if (options === void 0) { options = DefaultOptions; }
27159
+ this.options = options;
27132
27160
  this.editor = null;
27133
27161
  this.disposer = null;
27134
27162
  this.shouldHandleNextInputEvent = false;
@@ -27201,6 +27229,7 @@ var EditPlugin = /** @class */ (function () {
27201
27229
  */
27202
27230
  EditPlugin.prototype.willHandleEventExclusively = function (event) {
27203
27231
  if (this.editor &&
27232
+ this.options.handleTabKey &&
27204
27233
  event.eventType == 'keyDown' &&
27205
27234
  event.rawEvent.key == 'Tab' &&
27206
27235
  !event.rawEvent.shiftKey) {
@@ -27242,7 +27271,9 @@ var EditPlugin = /** @class */ (function () {
27242
27271
  }
27243
27272
  break;
27244
27273
  case 'Tab':
27245
- (0, keyboardTab_1.keyboardTab)(editor, rawEvent);
27274
+ if (this.options.handleTabKey) {
27275
+ (0, keyboardTab_1.keyboardTab)(editor, rawEvent);
27276
+ }
27246
27277
  break;
27247
27278
  case 'Unidentified':
27248
27279
  if (editor.getEnvironment().isAndroid) {
@@ -28901,8 +28932,10 @@ var canRegenerateImage_1 = __webpack_require__(/*! ./utils/canRegenerateImage */
28901
28932
  var imageEditUtils_1 = __webpack_require__(/*! ./utils/imageEditUtils */ "./packages/roosterjs-content-model-plugins/lib/imageEdit/utils/imageEditUtils.ts");
28902
28933
  var createImageWrapper_1 = __webpack_require__(/*! ./utils/createImageWrapper */ "./packages/roosterjs-content-model-plugins/lib/imageEdit/utils/createImageWrapper.ts");
28903
28934
  var cropperContext_1 = __webpack_require__(/*! ./Cropper/cropperContext */ "./packages/roosterjs-content-model-plugins/lib/imageEdit/Cropper/cropperContext.ts");
28935
+ var findEditingImage_1 = __webpack_require__(/*! ./utils/findEditingImage */ "./packages/roosterjs-content-model-plugins/lib/imageEdit/utils/findEditingImage.ts");
28904
28936
  var getDropAndDragHelpers_1 = __webpack_require__(/*! ./utils/getDropAndDragHelpers */ "./packages/roosterjs-content-model-plugins/lib/imageEdit/utils/getDropAndDragHelpers.ts");
28905
28937
  var getHTMLImageOptions_1 = __webpack_require__(/*! ./utils/getHTMLImageOptions */ "./packages/roosterjs-content-model-plugins/lib/imageEdit/utils/getHTMLImageOptions.ts");
28938
+ var getSelectedImage_1 = __webpack_require__(/*! ./utils/getSelectedImage */ "./packages/roosterjs-content-model-plugins/lib/imageEdit/utils/getSelectedImage.ts");
28906
28939
  var updateImageEditInfo_1 = __webpack_require__(/*! ./utils/updateImageEditInfo */ "./packages/roosterjs-content-model-plugins/lib/imageEdit/utils/updateImageEditInfo.ts");
28907
28940
  var ImageEditElementClass_1 = __webpack_require__(/*! ./types/ImageEditElementClass */ "./packages/roosterjs-content-model-plugins/lib/imageEdit/types/ImageEditElementClass.ts");
28908
28941
  var resizerContext_1 = __webpack_require__(/*! ./Resizer/resizerContext */ "./packages/roosterjs-content-model-plugins/lib/imageEdit/Resizer/resizerContext.ts");
@@ -28917,9 +28950,9 @@ var DefaultOptions = {
28917
28950
  preserveRatio: true,
28918
28951
  disableRotate: false,
28919
28952
  disableSideResize: false,
28920
- onSelectState: 'resize',
28953
+ onSelectState: ['resize', 'rotate'],
28921
28954
  };
28922
- var IMAGE_EDIT_CHANGE_SOURCE = 'ImageEdit';
28955
+ var MouseRightButton = 2;
28923
28956
  /**
28924
28957
  * ImageEdit plugin handles the following image editing features:
28925
28958
  * - Resize image
@@ -28947,6 +28980,8 @@ var ImageEditPlugin = /** @class */ (function () {
28947
28980
  this.croppers = [];
28948
28981
  this.zoomScale = 1;
28949
28982
  this.disposer = null;
28983
+ //EXPOSED FOR TEST ONLY
28984
+ this.isEditing = false;
28950
28985
  }
28951
28986
  /**
28952
28987
  * Get name of this plugin
@@ -28966,7 +29001,9 @@ var ImageEditPlugin = /** @class */ (function () {
28966
29001
  this.disposer = editor.attachDomEvent({
28967
29002
  blur: {
28968
29003
  beforeDispatch: function () {
28969
- _this.formatImageWithContentModel(editor, true /* shouldSelectImage */, true /* shouldSelectAsImageSelection*/);
29004
+ if (_this.editor) {
29005
+ _this.applyFormatWithContentModel(_this.editor, _this.isCropMode, true /* shouldSelectImage */);
29006
+ }
28970
29007
  },
28971
29008
  },
28972
29009
  });
@@ -28978,6 +29015,7 @@ var ImageEditPlugin = /** @class */ (function () {
28978
29015
  */
28979
29016
  ImageEditPlugin.prototype.dispose = function () {
28980
29017
  this.editor = null;
29018
+ this.isEditing = false;
28981
29019
  this.cleanInfo();
28982
29020
  if (this.disposer) {
28983
29021
  this.disposer();
@@ -28990,16 +29028,145 @@ var ImageEditPlugin = /** @class */ (function () {
28990
29028
  * exclusively by another plugin.
28991
29029
  * @param event The event to handle:
28992
29030
  */
28993
- ImageEditPlugin.prototype.onPluginEvent = function (_event) { };
28994
- ImageEditPlugin.prototype.startEditing = function (editor, image, apiOperation) {
28995
- var imageSpan = image.parentElement;
28996
- if (!imageSpan || (imageSpan && !(0, roosterjs_content_model_dom_1.isElementOfType)(imageSpan, 'span'))) {
29031
+ ImageEditPlugin.prototype.onPluginEvent = function (event) {
29032
+ if (!this.editor) {
28997
29033
  return;
28998
29034
  }
28999
- this.imageEditInfo = (0, updateImageEditInfo_1.getSelectedImageMetadata)(editor, image);
29035
+ switch (event.eventType) {
29036
+ case 'mouseUp':
29037
+ this.mouseUpHandler(this.editor, event);
29038
+ break;
29039
+ case 'keyDown':
29040
+ this.keyDownHandler(this.editor, event);
29041
+ break;
29042
+ }
29043
+ };
29044
+ ImageEditPlugin.prototype.isImageSelection = function (target) {
29045
+ return ((0, roosterjs_content_model_dom_1.isNodeOfType)(target, 'ELEMENT_NODE') &&
29046
+ ((0, roosterjs_content_model_dom_1.isElementOfType)(target, 'img') ||
29047
+ !!((0, roosterjs_content_model_dom_1.isElementOfType)(target, 'span') &&
29048
+ target.firstElementChild &&
29049
+ (0, roosterjs_content_model_dom_1.isNodeOfType)(target.firstElementChild, 'ELEMENT_NODE') &&
29050
+ (0, roosterjs_content_model_dom_1.isElementOfType)(target.firstElementChild, 'img'))));
29051
+ };
29052
+ ImageEditPlugin.prototype.mouseUpHandler = function (editor, event) {
29053
+ var selection = editor.getDOMSelection();
29054
+ if ((selection && selection.type == 'image') || this.isEditing) {
29055
+ var shouldSelectImage = this.isImageSelection(event.rawEvent.target) &&
29056
+ event.rawEvent.button === MouseRightButton;
29057
+ this.applyFormatWithContentModel(editor, this.isCropMode, shouldSelectImage);
29058
+ }
29059
+ };
29060
+ //Sometimes the cursor can be inside the editing image and inside shadow dom, then the cursor need to moved out of shadow dom
29061
+ ImageEditPlugin.prototype.selectBeforeEditingImage = function (editor, element) {
29062
+ var parent = element.parentNode;
29063
+ if (parent && (0, roosterjs_content_model_dom_1.isNodeOfType)(parent, 'ELEMENT_NODE') && parent.shadowRoot) {
29064
+ element = parent;
29065
+ parent = parent.parentNode;
29066
+ }
29067
+ var index = parent && (0, roosterjs_content_model_dom_1.toArray)(parent.childNodes).indexOf(element);
29068
+ if (index !== null && index >= 0 && parent) {
29069
+ var doc = editor.getDocument();
29070
+ var range = doc.createRange();
29071
+ range.setStart(parent, index);
29072
+ range.collapse();
29073
+ editor.setDOMSelection({
29074
+ type: 'range',
29075
+ range: range,
29076
+ isReverted: false,
29077
+ });
29078
+ }
29079
+ };
29080
+ ImageEditPlugin.prototype.keyDownHandler = function (editor, event) {
29081
+ if (this.isEditing) {
29082
+ if (event.rawEvent.key === 'Escape') {
29083
+ this.removeImageWrapper();
29084
+ }
29085
+ else {
29086
+ var selection = editor.getDOMSelection();
29087
+ var isImageSelection = (selection === null || selection === void 0 ? void 0 : selection.type) == 'image';
29088
+ if (isImageSelection) {
29089
+ this.selectBeforeEditingImage(editor, selection.image);
29090
+ }
29091
+ this.applyFormatWithContentModel(editor, this.isCropMode, ((0, roosterjs_content_model_dom_1.isModifierKey)(event.rawEvent) || event.rawEvent.shiftKey) && isImageSelection //if it's a modifier key over a image, the image should select the image
29092
+ );
29093
+ }
29094
+ }
29095
+ };
29096
+ ImageEditPlugin.prototype.applyFormatWithContentModel = function (editor, isCropMode, shouldSelectImage, isApiOperation) {
29097
+ var _this = this;
29098
+ var editingImageModel;
29099
+ var selection = editor.getDOMSelection();
29100
+ editor.formatContentModel(function (model) {
29101
+ var editingImage = (0, getSelectedImage_1.getSelectedImage)(model);
29102
+ var previousSelectedImage = isApiOperation
29103
+ ? editingImage
29104
+ : (0, findEditingImage_1.findEditingImage)(model);
29105
+ var result = false;
29106
+ if (shouldSelectImage ||
29107
+ (previousSelectedImage === null || previousSelectedImage === void 0 ? void 0 : previousSelectedImage.image) != (editingImage === null || editingImage === void 0 ? void 0 : editingImage.image) ||
29108
+ (previousSelectedImage === null || previousSelectedImage === void 0 ? void 0 : previousSelectedImage.image.dataset.isEditing) ||
29109
+ isApiOperation) {
29110
+ var _a = _this, lastSrc_1 = _a.lastSrc, selectedImage_1 = _a.selectedImage, imageEditInfo_1 = _a.imageEditInfo, clonedImage_1 = _a.clonedImage;
29111
+ if ((_this.isEditing || isApiOperation) &&
29112
+ previousSelectedImage &&
29113
+ lastSrc_1 &&
29114
+ selectedImage_1 &&
29115
+ imageEditInfo_1 &&
29116
+ clonedImage_1) {
29117
+ (0, roosterjs_content_model_dom_1.mutateSegment)(previousSelectedImage.paragraph, previousSelectedImage.image, function (image) {
29118
+ (0, applyChange_1.applyChange)(editor, selectedImage_1, image, imageEditInfo_1, lastSrc_1, _this.wasImageResized || _this.isCropMode, clonedImage_1);
29119
+ delete image.dataset.isEditing;
29120
+ image.isSelected = shouldSelectImage;
29121
+ image.isSelectedAsImageSelection = shouldSelectImage;
29122
+ });
29123
+ _this.cleanInfo();
29124
+ result = true;
29125
+ }
29126
+ _this.isEditing = false;
29127
+ _this.isCropMode = false;
29128
+ if (editingImage &&
29129
+ (selection === null || selection === void 0 ? void 0 : selection.type) == 'image' &&
29130
+ !shouldSelectImage &&
29131
+ !isApiOperation) {
29132
+ _this.isEditing = true;
29133
+ _this.isCropMode = isCropMode;
29134
+ (0, roosterjs_content_model_dom_1.mutateSegment)(editingImage.paragraph, editingImage.image, function (image) {
29135
+ editingImageModel = image;
29136
+ _this.imageEditInfo = (0, updateImageEditInfo_1.updateImageEditInfo)(image, selection.image);
29137
+ image.dataset.isEditing = 'true';
29138
+ });
29139
+ result = true;
29140
+ }
29141
+ }
29142
+ return result;
29143
+ }, {
29144
+ onNodeCreated: function (model, node) {
29145
+ if (!isApiOperation &&
29146
+ editingImageModel &&
29147
+ editingImageModel == model &&
29148
+ editingImageModel.dataset.isEditing &&
29149
+ (0, roosterjs_content_model_dom_1.isNodeOfType)(node, 'ELEMENT_NODE') &&
29150
+ (0, roosterjs_content_model_dom_1.isElementOfType)(node, 'img')) {
29151
+ if (isCropMode) {
29152
+ _this.startCropMode(editor, node);
29153
+ }
29154
+ else {
29155
+ _this.startRotateAndResize(editor, node);
29156
+ }
29157
+ }
29158
+ },
29159
+ }, {
29160
+ tryGetFromCache: true,
29161
+ });
29162
+ };
29163
+ ImageEditPlugin.prototype.startEditing = function (editor, image, apiOperation) {
29164
+ if (!this.imageEditInfo) {
29165
+ this.imageEditInfo = (0, updateImageEditInfo_1.getSelectedImageMetadata)(editor, image);
29166
+ }
29000
29167
  this.lastSrc = image.getAttribute('src');
29001
29168
  this.imageHTMLOptions = (0, getHTMLImageOptions_1.getHTMLImageOptions)(editor, this.options, this.imageEditInfo);
29002
- var _a = (0, createImageWrapper_1.createImageWrapper)(editor, image, imageSpan, this.options, this.imageEditInfo, this.imageHTMLOptions, apiOperation || this.options.onSelectState), resizers = _a.resizers, rotators = _a.rotators, wrapper = _a.wrapper, shadowSpan = _a.shadowSpan, imageClone = _a.imageClone, croppers = _a.croppers;
29169
+ var _a = (0, createImageWrapper_1.createImageWrapper)(editor, image, this.options, this.imageEditInfo, this.imageHTMLOptions, apiOperation), resizers = _a.resizers, rotators = _a.rotators, wrapper = _a.wrapper, shadowSpan = _a.shadowSpan, imageClone = _a.imageClone, croppers = _a.croppers;
29003
29170
  this.shadowSpan = shadowSpan;
29004
29171
  this.selectedImage = image;
29005
29172
  this.wrapper = wrapper;
@@ -29013,34 +29180,33 @@ var ImageEditPlugin = /** @class */ (function () {
29013
29180
  "span:has(>img#" + this.selectedImage.id + ")",
29014
29181
  ]);
29015
29182
  };
29016
- ImageEditPlugin.prototype.startRotateAndResize = function (editor, image, apiOperation) {
29183
+ ImageEditPlugin.prototype.startRotateAndResize = function (editor, image) {
29017
29184
  var _this = this;
29018
29185
  var _a;
29019
- if (this.wrapper && this.selectedImage && this.shadowSpan) {
29020
- this.removeImageWrapper();
29021
- }
29022
- this.startEditing(editor, image, apiOperation);
29023
- if (this.selectedImage && this.imageEditInfo && this.wrapper && this.clonedImage) {
29024
- this.dndHelpers = (0, tslib_1.__spreadArray)((0, tslib_1.__spreadArray)([], (0, tslib_1.__read)((0, getDropAndDragHelpers_1.getDropAndDragHelpers)(this.wrapper, this.imageEditInfo, this.options, ImageEditElementClass_1.ImageEditElementClass.ResizeHandle, resizerContext_1.Resizer, function () {
29025
- if (_this.imageEditInfo &&
29026
- _this.selectedImage &&
29027
- _this.wrapper &&
29028
- _this.clonedImage) {
29029
- (0, updateWrapper_1.updateWrapper)(_this.imageEditInfo, _this.options, _this.selectedImage, _this.clonedImage, _this.wrapper, _this.resizers);
29030
- _this.wasImageResized = true;
29031
- }
29032
- }, this.zoomScale)), false), (0, tslib_1.__read)((0, getDropAndDragHelpers_1.getDropAndDragHelpers)(this.wrapper, this.imageEditInfo, this.options, ImageEditElementClass_1.ImageEditElementClass.RotateHandle, rotatorContext_1.Rotator, function () {
29033
- var _a;
29034
- if (_this.imageEditInfo &&
29035
- _this.selectedImage &&
29036
- _this.wrapper &&
29037
- _this.clonedImage) {
29038
- (0, updateWrapper_1.updateWrapper)(_this.imageEditInfo, _this.options, _this.selectedImage, _this.clonedImage, _this.wrapper, _this.rotators);
29039
- _this.updateRotateHandleState(editor, _this.selectedImage, _this.wrapper, _this.rotators, (_a = _this.imageEditInfo) === null || _a === void 0 ? void 0 : _a.angleRad);
29040
- }
29041
- }, this.zoomScale)), false);
29042
- (0, updateWrapper_1.updateWrapper)(this.imageEditInfo, this.options, this.selectedImage, this.clonedImage, this.wrapper, this.resizers);
29043
- this.updateRotateHandleState(editor, this.selectedImage, this.wrapper, this.rotators, (_a = this.imageEditInfo) === null || _a === void 0 ? void 0 : _a.angleRad);
29186
+ if (this.imageEditInfo) {
29187
+ this.startEditing(editor, image, ['resize', 'rotate']);
29188
+ if (this.selectedImage && this.imageEditInfo && this.wrapper && this.clonedImage) {
29189
+ this.dndHelpers = (0, tslib_1.__spreadArray)((0, tslib_1.__spreadArray)([], (0, tslib_1.__read)((0, getDropAndDragHelpers_1.getDropAndDragHelpers)(this.wrapper, this.imageEditInfo, this.options, ImageEditElementClass_1.ImageEditElementClass.ResizeHandle, resizerContext_1.Resizer, function () {
29190
+ if (_this.imageEditInfo &&
29191
+ _this.selectedImage &&
29192
+ _this.wrapper &&
29193
+ _this.clonedImage) {
29194
+ (0, updateWrapper_1.updateWrapper)(_this.imageEditInfo, _this.options, _this.selectedImage, _this.clonedImage, _this.wrapper, _this.resizers);
29195
+ _this.wasImageResized = true;
29196
+ }
29197
+ }, this.zoomScale)), false), (0, tslib_1.__read)((0, getDropAndDragHelpers_1.getDropAndDragHelpers)(this.wrapper, this.imageEditInfo, this.options, ImageEditElementClass_1.ImageEditElementClass.RotateHandle, rotatorContext_1.Rotator, function () {
29198
+ var _a;
29199
+ if (_this.imageEditInfo &&
29200
+ _this.selectedImage &&
29201
+ _this.wrapper &&
29202
+ _this.clonedImage) {
29203
+ (0, updateWrapper_1.updateWrapper)(_this.imageEditInfo, _this.options, _this.selectedImage, _this.clonedImage, _this.wrapper);
29204
+ _this.updateRotateHandleState(editor, _this.selectedImage, _this.wrapper, _this.rotators, (_a = _this.imageEditInfo) === null || _a === void 0 ? void 0 : _a.angleRad);
29205
+ }
29206
+ }, this.zoomScale)), false);
29207
+ (0, updateWrapper_1.updateWrapper)(this.imageEditInfo, this.options, this.selectedImage, this.clonedImage, this.wrapper, this.resizers);
29208
+ this.updateRotateHandleState(editor, this.selectedImage, this.wrapper, this.rotators, (_a = this.imageEditInfo) === null || _a === void 0 ? void 0 : _a.angleRad);
29209
+ }
29044
29210
  }
29045
29211
  };
29046
29212
  ImageEditPlugin.prototype.updateRotateHandleState = function (editor, image, wrapper, rotators, angleRad) {
@@ -29056,49 +29222,52 @@ var ImageEditPlugin = /** @class */ (function () {
29056
29222
  }
29057
29223
  };
29058
29224
  ImageEditPlugin.prototype.isOperationAllowed = function (operation) {
29059
- return operation === 'resize' || operation === 'rotate' || operation === 'flip';
29225
+ return (operation === 'resize' ||
29226
+ operation === 'rotate' ||
29227
+ operation === 'flip' ||
29228
+ operation === 'crop');
29060
29229
  };
29061
29230
  ImageEditPlugin.prototype.canRegenerateImage = function (image) {
29062
29231
  return (0, canRegenerateImage_1.canRegenerateImage)(image);
29063
29232
  };
29064
- ImageEditPlugin.prototype.cropImage = function () {
29233
+ ImageEditPlugin.prototype.startCropMode = function (editor, image) {
29065
29234
  var _this = this;
29066
- var _a, _b;
29067
- var selection = (_a = this.editor) === null || _a === void 0 ? void 0 : _a.getDOMSelection();
29068
- if (!this.editor || !selection || selection.type !== 'image') {
29235
+ if (this.imageEditInfo) {
29236
+ this.startEditing(editor, image, ['crop']);
29237
+ if (this.imageEditInfo && this.selectedImage && this.wrapper && this.clonedImage) {
29238
+ this.dndHelpers = (0, tslib_1.__spreadArray)([], (0, tslib_1.__read)((0, getDropAndDragHelpers_1.getDropAndDragHelpers)(this.wrapper, this.imageEditInfo, this.options, ImageEditElementClass_1.ImageEditElementClass.CropHandle, cropperContext_1.Cropper, function () {
29239
+ if (_this.imageEditInfo &&
29240
+ _this.selectedImage &&
29241
+ _this.wrapper &&
29242
+ _this.clonedImage) {
29243
+ (0, updateWrapper_1.updateWrapper)(_this.imageEditInfo, _this.options, _this.selectedImage, _this.clonedImage, _this.wrapper, undefined, _this.croppers);
29244
+ _this.isCropMode = true;
29245
+ }
29246
+ }, this.zoomScale)), false);
29247
+ (0, updateWrapper_1.updateWrapper)(this.imageEditInfo, this.options, this.selectedImage, this.clonedImage, this.wrapper, undefined, this.croppers);
29248
+ }
29249
+ }
29250
+ };
29251
+ ImageEditPlugin.prototype.cropImage = function () {
29252
+ if (!this.editor) {
29069
29253
  return;
29070
29254
  }
29071
- var image = selection.image;
29072
- if (this.wrapper && this.selectedImage && this.shadowSpan) {
29073
- image = (_b = this.removeImageWrapper()) !== null && _b !== void 0 ? _b : image;
29255
+ if (!this.editor.getEnvironment().isSafari) {
29256
+ this.editor.focus(); // Safari will keep the selection when click crop, then the focus() call should not be called
29074
29257
  }
29075
- this.startEditing(this.editor, image, 'crop');
29076
- if (!this.selectedImage || !this.imageEditInfo || !this.wrapper || !this.clonedImage) {
29077
- return;
29258
+ var selection = this.editor.getDOMSelection();
29259
+ if ((selection === null || selection === void 0 ? void 0 : selection.type) == 'image') {
29260
+ this.applyFormatWithContentModel(this.editor, true /* isCropMode */, false /* shouldSelectImage */);
29078
29261
  }
29079
- this.dndHelpers = (0, tslib_1.__spreadArray)([], (0, tslib_1.__read)((0, getDropAndDragHelpers_1.getDropAndDragHelpers)(this.wrapper, this.imageEditInfo, this.options, ImageEditElementClass_1.ImageEditElementClass.CropHandle, cropperContext_1.Cropper, function () {
29080
- if (_this.imageEditInfo &&
29081
- _this.selectedImage &&
29082
- _this.wrapper &&
29083
- _this.clonedImage) {
29084
- (0, updateWrapper_1.updateWrapper)(_this.imageEditInfo, _this.options, _this.selectedImage, _this.clonedImage, _this.wrapper, undefined, _this.croppers);
29085
- _this.isCropMode = true;
29086
- }
29087
- }, this.zoomScale)), false);
29088
- (0, updateWrapper_1.updateWrapper)(this.imageEditInfo, this.options, this.selectedImage, this.clonedImage, this.wrapper, undefined, this.croppers);
29089
29262
  };
29090
29263
  ImageEditPlugin.prototype.editImage = function (editor, image, apiOperation, operation) {
29091
- var _a;
29092
- if (this.wrapper && this.selectedImage && this.shadowSpan) {
29093
- image = (_a = this.removeImageWrapper()) !== null && _a !== void 0 ? _a : image;
29094
- }
29095
29264
  this.startEditing(editor, image, apiOperation);
29096
29265
  if (!this.selectedImage || !this.imageEditInfo || !this.wrapper || !this.clonedImage) {
29097
29266
  return;
29098
29267
  }
29099
29268
  operation(this.imageEditInfo);
29100
29269
  (0, updateWrapper_1.updateWrapper)(this.imageEditInfo, this.options, this.selectedImage, this.clonedImage, this.wrapper);
29101
- this.formatImageWithContentModel(editor, true /* shouldSelect*/, true /* shouldSelectAsImageSelection*/);
29270
+ this.applyFormatWithContentModel(editor, false /* isCrop */, true /* shouldSelect*/, true /* isApiOperation */);
29102
29271
  };
29103
29272
  ImageEditPlugin.prototype.cleanInfo = function () {
29104
29273
  var _a;
@@ -29118,42 +29287,6 @@ var ImageEditPlugin = /** @class */ (function () {
29118
29287
  this.rotators = [];
29119
29288
  this.croppers = [];
29120
29289
  };
29121
- ImageEditPlugin.prototype.formatImageWithContentModel = function (editor, shouldSelectImage, shouldSelectAsImageSelection) {
29122
- var _this = this;
29123
- if (this.lastSrc &&
29124
- this.selectedImage &&
29125
- this.imageEditInfo &&
29126
- this.clonedImage &&
29127
- this.shadowSpan) {
29128
- editor.formatContentModel(function (model) {
29129
- var selectedSegmentsAndParagraphs = (0, roosterjs_content_model_dom_1.getSelectedSegmentsAndParagraphs)(model, false);
29130
- if (!selectedSegmentsAndParagraphs[0]) {
29131
- return false;
29132
- }
29133
- var segment = selectedSegmentsAndParagraphs[0][0];
29134
- var paragraph = selectedSegmentsAndParagraphs[0][1];
29135
- if (paragraph && segment.segmentType == 'Image') {
29136
- (0, roosterjs_content_model_dom_1.mutateSegment)(paragraph, segment, function (image) {
29137
- if (_this.lastSrc &&
29138
- _this.selectedImage &&
29139
- _this.imageEditInfo &&
29140
- _this.clonedImage) {
29141
- (0, applyChange_1.applyChange)(editor, _this.selectedImage, image, _this.imageEditInfo, _this.lastSrc, _this.wasImageResized || _this.isCropMode, _this.clonedImage);
29142
- image.isSelected = shouldSelectImage;
29143
- image.isSelectedAsImageSelection = shouldSelectAsImageSelection;
29144
- }
29145
- });
29146
- return true;
29147
- }
29148
- return false;
29149
- }, {
29150
- changeSource: IMAGE_EDIT_CHANGE_SOURCE,
29151
- onNodeCreated: function () {
29152
- _this.cleanInfo();
29153
- },
29154
- });
29155
- }
29156
- };
29157
29290
  ImageEditPlugin.prototype.removeImageWrapper = function () {
29158
29291
  var image = null;
29159
29292
  if (this.shadowSpan && this.shadowSpan.parentElement) {
@@ -29176,7 +29309,7 @@ var ImageEditPlugin = /** @class */ (function () {
29176
29309
  }
29177
29310
  var image = selection.image;
29178
29311
  if (this.editor) {
29179
- this.editImage(this.editor, image, 'flip', function (imageEditInfo) {
29312
+ this.editImage(this.editor, image, ['flip'], function (imageEditInfo) {
29180
29313
  var angleRad = imageEditInfo.angleRad || 0;
29181
29314
  var isInVerticalPostion = (angleRad >= Math.PI / 2 && angleRad < (3 * Math.PI) / 4) ||
29182
29315
  (angleRad <= -Math.PI / 2 && angleRad > (-3 * Math.PI) / 4);
@@ -29207,15 +29340,19 @@ var ImageEditPlugin = /** @class */ (function () {
29207
29340
  }
29208
29341
  var image = selection.image;
29209
29342
  if (this.editor) {
29210
- this.editImage(this.editor, image, 'rotate', function (imageEditInfo) {
29343
+ this.editImage(this.editor, image, [], function (imageEditInfo) {
29211
29344
  imageEditInfo.angleRad = (imageEditInfo.angleRad || 0) + angleRad;
29212
29345
  });
29213
29346
  }
29214
29347
  };
29215
- //EXPOSED FOR TEST ONLY
29216
- ImageEditPlugin.prototype.getWrapper = function () {
29217
- return this.wrapper;
29218
- };
29348
+ Object.defineProperty(ImageEditPlugin.prototype, "isEditingImage", {
29349
+ //EXPOSED FOR TEST ONLY
29350
+ get: function () {
29351
+ return this.isEditing;
29352
+ },
29353
+ enumerable: false,
29354
+ configurable: true
29355
+ });
29219
29356
  return ImageEditPlugin;
29220
29357
  }());
29221
29358
  exports.ImageEditPlugin = ImageEditPlugin;
@@ -29780,7 +29917,8 @@ var updateImageEditInfo_1 = __webpack_require__(/*! ./updateImageEditInfo */ "./
29780
29917
  function applyChange(editor, image, contentModelImage, editInfo, previousSrc, wasResizedOrCropped, editingImage) {
29781
29918
  var _a;
29782
29919
  var newSrc = '';
29783
- var initEditInfo = (_a = (0, updateImageEditInfo_1.getSelectedImageMetadata)(editor, editingImage !== null && editingImage !== void 0 ? editingImage : image)) !== null && _a !== void 0 ? _a : undefined;
29920
+ var imageEditing = editingImage !== null && editingImage !== void 0 ? editingImage : image;
29921
+ var initEditInfo = (_a = (0, updateImageEditInfo_1.updateImageEditInfo)(contentModelImage, imageEditing)) !== null && _a !== void 0 ? _a : undefined;
29784
29922
  var state = (0, checkEditInfoState_1.checkEditInfoState)(editInfo, initEditInfo);
29785
29923
  switch (state) {
29786
29924
  case 'ResizeOnly':
@@ -29812,12 +29950,12 @@ function applyChange(editor, image, contentModelImage, editInfo, previousSrc, wa
29812
29950
  if (newSrc == editInfo.src) {
29813
29951
  // If newSrc is the same with original one, it means there is only size change, but no rotation, no cropping,
29814
29952
  // so we don't need to keep edit info, we can delete it
29815
- (0, updateImageEditInfo_1.updateImageEditInfo)(contentModelImage, null);
29953
+ (0, updateImageEditInfo_1.updateImageEditInfo)(contentModelImage, imageEditing, null);
29816
29954
  }
29817
29955
  else {
29818
29956
  // Otherwise, save the new edit info to the image so that next time when we edit the same image, we know
29819
29957
  // the edit info
29820
- (0, updateImageEditInfo_1.updateImageEditInfo)(contentModelImage, editInfo);
29958
+ (0, updateImageEditInfo_1.updateImageEditInfo)(contentModelImage, imageEditing, editInfo);
29821
29959
  }
29822
29960
  // Write back the change to image, and set its new size
29823
29961
  var generatedImageSize = (0, generateImageSize_1.getGeneratedImageSize)(editInfo);
@@ -29828,11 +29966,6 @@ function applyChange(editor, image, contentModelImage, editInfo, previousSrc, wa
29828
29966
  if (wasResizedOrCropped || state == 'FullyChanged') {
29829
29967
  contentModelImage.format.width = generatedImageSize.targetWidth + 'px';
29830
29968
  contentModelImage.format.height = generatedImageSize.targetHeight + 'px';
29831
- // Remove width/height style so that it won't affect the image size, since style width/height has higher priority
29832
- image.style.removeProperty('width');
29833
- image.style.removeProperty('height');
29834
- image.style.removeProperty('max-width');
29835
- image.style.removeProperty('max-height');
29836
29969
  }
29837
29970
  }
29838
29971
  exports.applyChange = applyChange;
@@ -29959,25 +30092,27 @@ exports.createImageWrapper = void 0;
29959
30092
  var createImageCropper_1 = __webpack_require__(/*! ../Cropper/createImageCropper */ "./packages/roosterjs-content-model-plugins/lib/imageEdit/Cropper/createImageCropper.ts");
29960
30093
  var createImageResizer_1 = __webpack_require__(/*! ../Resizer/createImageResizer */ "./packages/roosterjs-content-model-plugins/lib/imageEdit/Resizer/createImageResizer.ts");
29961
30094
  var createImageRotator_1 = __webpack_require__(/*! ../Rotator/createImageRotator */ "./packages/roosterjs-content-model-plugins/lib/imageEdit/Rotator/createImageRotator.ts");
30095
+ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
29962
30096
  /**
29963
30097
  * @internal
29964
30098
  */
29965
- function createImageWrapper(editor, image, imageSpan, options, editInfo, htmlOptions, operation) {
30099
+ function createImageWrapper(editor, image, options, editInfo, htmlOptions, operation) {
29966
30100
  var imageClone = cloneImage(image, editInfo);
29967
30101
  var doc = editor.getDocument();
29968
30102
  var rotators = [];
29969
- if (!options.disableRotate && operation === 'rotate') {
30103
+ if (!options.disableRotate && operation.indexOf('rotate') > -1) {
29970
30104
  rotators = (0, createImageRotator_1.createImageRotator)(doc, htmlOptions);
29971
30105
  }
29972
30106
  var resizers = [];
29973
- if (operation === 'resize') {
30107
+ if (operation.indexOf('resize') > -1) {
29974
30108
  resizers = (0, createImageResizer_1.createImageResizer)(doc);
29975
30109
  }
29976
30110
  var croppers = [];
29977
- if (operation === 'crop') {
30111
+ if (operation.indexOf('crop') > -1) {
29978
30112
  croppers = (0, createImageCropper_1.createImageCropper)(doc);
29979
30113
  }
29980
30114
  var wrapper = createWrapper(editor, imageClone, options, editInfo, resizers, rotators, croppers);
30115
+ var imageSpan = (0, roosterjs_content_model_dom_1.wrap)(doc, image, 'span');
29981
30116
  var shadowSpan = createShadowSpan(wrapper, imageSpan);
29982
30117
  return { wrapper: wrapper, shadowSpan: shadowSpan, imageClone: imageClone, resizers: resizers, rotators: rotators, croppers: croppers };
29983
30118
  }
@@ -29997,8 +30132,10 @@ var createWrapper = function (editor, image, options, editInfo, resizers, rotato
29997
30132
  var imageBox = doc.createElement('div');
29998
30133
  imageBox.setAttribute("style", "position:relative;width:100%;height:100%;overflow:hidden;transform:scale(1);");
29999
30134
  imageBox.appendChild(image);
30000
- wrapper.setAttribute('style', "max-width: 100%; position: relative; display: inline-flex; font-size: 24px; margin: 0px; transform: rotate(" + ((_a = editInfo.angleRad) !== null && _a !== void 0 ? _a : 0) + "rad); text-align: left;");
30001
- wrapper.style.display = editor.getEnvironment().isSafari ? 'inline-block' : 'inline-flex';
30135
+ wrapper.setAttribute('style', "font-size: 24px; margin: 0px; transform: rotate(" + ((_a = editInfo.angleRad) !== null && _a !== void 0 ? _a : 0) + "rad);");
30136
+ wrapper.style.display = editor.getEnvironment().isSafari
30137
+ ? '-webkit-inline-flex'
30138
+ : 'inline-flex';
30002
30139
  var border = createBorder(editor, options.borderColor);
30003
30140
  wrapper.appendChild(imageBox);
30004
30141
  wrapper.appendChild(border);
@@ -30087,6 +30224,59 @@ function doubleCheckResize(editInfo, preserveRatio, actualWidth, actualHeight) {
30087
30224
  exports.doubleCheckResize = doubleCheckResize;
30088
30225
 
30089
30226
 
30227
+ /***/ }),
30228
+
30229
+ /***/ "./packages/roosterjs-content-model-plugins/lib/imageEdit/utils/findEditingImage.ts":
30230
+ /*!******************************************************************************************!*\
30231
+ !*** ./packages/roosterjs-content-model-plugins/lib/imageEdit/utils/findEditingImage.ts ***!
30232
+ \******************************************************************************************/
30233
+ /***/ ((__unused_webpack_module, exports) => {
30234
+
30235
+ "use strict";
30236
+
30237
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
30238
+ exports.findEditingImage = void 0;
30239
+ /**
30240
+ * @internal
30241
+ */
30242
+ function findEditingImage(group) {
30243
+ for (var i = 0; i < group.blocks.length; i++) {
30244
+ var block = group.blocks[i];
30245
+ switch (block.blockType) {
30246
+ case 'BlockGroup':
30247
+ var result = findEditingImage(block);
30248
+ if (result) {
30249
+ return result;
30250
+ }
30251
+ break;
30252
+ case 'Paragraph':
30253
+ for (var j = 0; j < block.segments.length; j++) {
30254
+ var segment = block.segments[j];
30255
+ switch (segment.segmentType) {
30256
+ case 'Image':
30257
+ if (segment.dataset.isEditing) {
30258
+ return {
30259
+ paragraph: block,
30260
+ image: segment,
30261
+ };
30262
+ }
30263
+ break;
30264
+ case 'General':
30265
+ var result_1 = findEditingImage(segment);
30266
+ if (result_1) {
30267
+ return result_1;
30268
+ }
30269
+ break;
30270
+ }
30271
+ }
30272
+ break;
30273
+ }
30274
+ }
30275
+ return null;
30276
+ }
30277
+ exports.findEditingImage = findEditingImage;
30278
+
30279
+
30090
30280
  /***/ }),
30091
30281
 
30092
30282
  /***/ "./packages/roosterjs-content-model-plugins/lib/imageEdit/utils/generateDataURL.ts":
@@ -30271,28 +30461,33 @@ exports.getHTMLImageOptions = getHTMLImageOptions;
30271
30461
 
30272
30462
  /***/ }),
30273
30463
 
30274
- /***/ "./packages/roosterjs-content-model-plugins/lib/imageEdit/utils/getSelectedContentModelImage.ts":
30275
- /*!******************************************************************************************************!*\
30276
- !*** ./packages/roosterjs-content-model-plugins/lib/imageEdit/utils/getSelectedContentModelImage.ts ***!
30277
- \******************************************************************************************************/
30464
+ /***/ "./packages/roosterjs-content-model-plugins/lib/imageEdit/utils/getSelectedImage.ts":
30465
+ /*!******************************************************************************************!*\
30466
+ !*** ./packages/roosterjs-content-model-plugins/lib/imageEdit/utils/getSelectedImage.ts ***!
30467
+ \******************************************************************************************/
30278
30468
  /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
30279
30469
 
30280
30470
  "use strict";
30281
30471
 
30282
30472
  Object.defineProperty(exports, "__esModule", ({ value: true }));
30283
- exports.getSelectedContentModelImage = void 0;
30473
+ exports.getSelectedImage = void 0;
30284
30474
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
30285
30475
  /**
30286
30476
  * @internal
30287
30477
  */
30288
- function getSelectedContentModelImage(model) {
30289
- var selectedSegments = (0, roosterjs_content_model_dom_1.getSelectedSegments)(model, false /*includeFormatHolder*/);
30290
- if (selectedSegments.length == 1 && selectedSegments[0].segmentType == 'Image') {
30291
- return selectedSegments[0];
30478
+ function getSelectedImage(model) {
30479
+ var selections = (0, roosterjs_content_model_dom_1.getSelectedSegmentsAndParagraphs)(model, false);
30480
+ if (selections.length == 1 && selections[0][0].segmentType == 'Image' && selections[0][1]) {
30481
+ return {
30482
+ image: selections[0][0],
30483
+ paragraph: selections[0][1],
30484
+ };
30485
+ }
30486
+ else {
30487
+ return null;
30292
30488
  }
30293
- return null;
30294
30489
  }
30295
- exports.getSelectedContentModelImage = getSelectedContentModelImage;
30490
+ exports.getSelectedImage = getSelectedImage;
30296
30491
 
30297
30492
 
30298
30493
  /***/ }),
@@ -30464,18 +30659,19 @@ exports.updateHandleCursor = updateHandleCursor;
30464
30659
  Object.defineProperty(exports, "__esModule", ({ value: true }));
30465
30660
  exports.getSelectedImageMetadata = exports.updateImageEditInfo = void 0;
30466
30661
  var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
30467
- var getSelectedContentModelImage_1 = __webpack_require__(/*! ./getSelectedContentModelImage */ "./packages/roosterjs-content-model-plugins/lib/imageEdit/utils/getSelectedContentModelImage.ts");
30662
+ var getSelectedImage_1 = __webpack_require__(/*! ./getSelectedImage */ "./packages/roosterjs-content-model-plugins/lib/imageEdit/utils/getSelectedImage.ts");
30468
30663
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
30469
30664
  /**
30470
30665
  * @internal
30471
30666
  */
30472
- function updateImageEditInfo(contentModelImage, newImageMetadata) {
30473
- (0, roosterjs_content_model_dom_1.updateImageMetadata)(contentModelImage, newImageMetadata !== undefined
30667
+ function updateImageEditInfo(contentModelImage, image, newImageMetadata) {
30668
+ var contentModelMetadata = (0, roosterjs_content_model_dom_1.updateImageMetadata)(contentModelImage, newImageMetadata !== undefined
30474
30669
  ? function (format) {
30475
30670
  format = newImageMetadata;
30476
30671
  return format;
30477
30672
  }
30478
30673
  : undefined);
30674
+ return (0, tslib_1.__assign)((0, tslib_1.__assign)({}, getInitialEditInfo(image)), contentModelMetadata);
30479
30675
  }
30480
30676
  exports.updateImageEditInfo = updateImageEditInfo;
30481
30677
  function getInitialEditInfo(image) {
@@ -30499,9 +30695,12 @@ function getInitialEditInfo(image) {
30499
30695
  function getSelectedImageMetadata(editor, image) {
30500
30696
  var imageMetadata = getInitialEditInfo(image);
30501
30697
  editor.formatContentModel(function (model) {
30502
- var selectedImage = (0, getSelectedContentModelImage_1.getSelectedContentModelImage)(model);
30503
- if (selectedImage) {
30504
- imageMetadata = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, imageMetadata), selectedImage.dataset);
30698
+ var selectedImage = (0, getSelectedImage_1.getSelectedImage)(model);
30699
+ if (selectedImage === null || selectedImage === void 0 ? void 0 : selectedImage.image) {
30700
+ (0, roosterjs_content_model_dom_1.mutateSegment)(selectedImage.paragraph, selectedImage === null || selectedImage === void 0 ? void 0 : selectedImage.image, function (modelImage) {
30701
+ imageMetadata = updateImageEditInfo(modelImage, image);
30702
+ });
30703
+ return true;
30505
30704
  }
30506
30705
  return false;
30507
30706
  });
@@ -30581,7 +30780,7 @@ function updateWrapper(editInfo, options, image, clonedImage, wrapper, resizers,
30581
30780
  (0, imageEditUtils_1.setSize)(cropOverlays[1], undefined, 0, 0, cropBottomPx, cropRightPx, undefined);
30582
30781
  (0, imageEditUtils_1.setSize)(cropOverlays[2], cropLeftPx, undefined, 0, 0, undefined, cropBottomPx);
30583
30782
  (0, imageEditUtils_1.setSize)(cropOverlays[3], 0, cropTopPx, undefined, 0, cropLeftPx, undefined);
30584
- if (angleRad) {
30783
+ if (angleRad !== undefined) {
30585
30784
  (0, updateHandleCursor_1.updateHandleCursor)(croppers, angleRad);
30586
30785
  }
30587
30786
  }
@@ -30598,7 +30797,7 @@ function updateWrapper(editInfo, options, image, clonedImage, wrapper, resizers,
30598
30797
  }
30599
30798
  })
30600
30799
  .filter(function (handle) { return !!handle; });
30601
- if (angleRad) {
30800
+ if (angleRad !== undefined) {
30602
30801
  (0, updateHandleCursor_1.updateHandleCursor)(resizeHandles, angleRad);
30603
30802
  }
30604
30803
  (0, updateSideHandlesVisibility_1.updateSideHandlesVisibility)(resizeHandles, smallImage);
@@ -30881,7 +31080,6 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
30881
31080
  exports.setFormat = void 0;
30882
31081
  var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
30883
31082
  var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
30884
- var splitTextSegment_1 = __webpack_require__(/*! ../../pluginUtils/splitTextSegment */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/splitTextSegment.ts");
30885
31083
  /**
30886
31084
  * @internal
30887
31085
  */
@@ -30896,7 +31094,7 @@ function setFormat(editor, character, format, codeFormat) {
30896
31094
  .substring(0, lastCharIndex - 1)
30897
31095
  .lastIndexOf(character);
30898
31096
  if (lastCharIndex - firstCharIndex > 2) {
30899
- var formattedText = (0, splitTextSegment_1.splitTextSegment)(previousSegment, paragraph, firstCharIndex, lastCharIndex);
31097
+ var formattedText = (0, roosterjs_content_model_api_1.splitTextSegment)(previousSegment, paragraph, firstCharIndex, lastCharIndex);
30900
31098
  formattedText.text = formattedText.text.replace(character, '').slice(0, -1);
30901
31099
  formattedText.format = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, formattedText.format), format);
30902
31100
  if (codeFormat) {
@@ -32705,7 +32903,7 @@ exports.PickerPlugin = PickerPlugin;
32705
32903
 
32706
32904
  Object.defineProperty(exports, "__esModule", ({ value: true }));
32707
32905
  exports.getQueryString = void 0;
32708
- var splitTextSegment_1 = __webpack_require__(/*! ../pluginUtils/splitTextSegment */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/splitTextSegment.ts");
32906
+ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
32709
32907
  /**
32710
32908
  * @internal
32711
32909
  */
@@ -32722,7 +32920,7 @@ function getQueryString(triggerCharacter, paragraph, previousSegment, splittedSe
32722
32920
  if (index >= 0) {
32723
32921
  result = segment.text.substring(index) + result;
32724
32922
  splittedSegmentResult === null || splittedSegmentResult === void 0 ? void 0 : splittedSegmentResult.unshift(index > 0
32725
- ? (0, splitTextSegment_1.splitTextSegment)(segment, paragraph, index, segment.text.length)
32923
+ ? (0, roosterjs_content_model_api_1.splitTextSegment)(segment, paragraph, index, segment.text.length)
32726
32924
  : segment);
32727
32925
  break;
32728
32926
  }
@@ -32988,42 +33186,6 @@ function getIntersectedRect(elements, additionalRects) {
32988
33186
  exports.getIntersectedRect = getIntersectedRect;
32989
33187
 
32990
33188
 
32991
- /***/ }),
32992
-
32993
- /***/ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/splitTextSegment.ts":
32994
- /*!**************************************************************************************!*\
32995
- !*** ./packages/roosterjs-content-model-plugins/lib/pluginUtils/splitTextSegment.ts ***!
32996
- \**************************************************************************************/
32997
- /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
32998
-
32999
- "use strict";
33000
-
33001
- Object.defineProperty(exports, "__esModule", ({ value: true }));
33002
- exports.splitTextSegment = void 0;
33003
- var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
33004
- var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
33005
- /**
33006
- * @internal
33007
- */
33008
- function splitTextSegment(textSegment, parent, start, end) {
33009
- var _a;
33010
- var text = textSegment.text;
33011
- var index = parent.segments.indexOf(textSegment);
33012
- var middleSegment = (0, roosterjs_content_model_dom_1.createText)(text.substring(start, end), textSegment.format, textSegment.link, textSegment.code);
33013
- var newSegments = [middleSegment];
33014
- if (start > 0) {
33015
- newSegments.unshift((0, roosterjs_content_model_dom_1.createText)(text.substring(0, start), textSegment.format, textSegment.link, textSegment.code));
33016
- }
33017
- if (end < text.length) {
33018
- newSegments.push((0, roosterjs_content_model_dom_1.createText)(text.substring(end), textSegment.format, textSegment.link, textSegment.code));
33019
- }
33020
- newSegments.forEach(function (segment) { return (segment.isSelected = textSegment.isSelected); });
33021
- (_a = parent.segments).splice.apply(_a, (0, tslib_1.__spreadArray)([index, 1], (0, tslib_1.__read)(newSegments), false));
33022
- return middleSegment;
33023
- }
33024
- exports.splitTextSegment = splitTextSegment;
33025
-
33026
-
33027
33189
  /***/ }),
33028
33190
 
33029
33191
  /***/ "./packages/roosterjs-content-model-plugins/lib/shortcut/ShortcutPlugin.ts":
@@ -33711,8 +33873,10 @@ var TableEditor = /** @class */ (function () {
33711
33873
  _this.disposeTableInserter();
33712
33874
  _this.disposeCellResizers();
33713
33875
  };
33714
- this.onEndTableMove = function () {
33715
- _this.disposeTableMover();
33876
+ this.onEndTableMove = function (disposeHandler) {
33877
+ if (disposeHandler) {
33878
+ _this.disposeTableMover();
33879
+ }
33716
33880
  return _this.onFinishEditing();
33717
33881
  };
33718
33882
  this.onInserted = function () {
@@ -34486,9 +34650,9 @@ function onDragEnd(context, event, initValue) {
34486
34650
  // Reset cursor
34487
34651
  setTableMoverCursor(editor, false);
34488
34652
  if (element == context.div) {
34489
- // Table mover was only clicked, select whole table
34653
+ // Table mover was only clicked, select whole table and do not dismiss the handler element.
34490
34654
  selectWholeTable(table);
34491
- context.onEnd();
34655
+ context.onEnd(false /* disposeHandler */);
34492
34656
  return true;
34493
34657
  }
34494
34658
  else {
@@ -34497,7 +34661,7 @@ function onDragEnd(context, event, initValue) {
34497
34661
  !editor.getDOMHelper().isNodeInEditor(element) ||
34498
34662
  disableMovement) {
34499
34663
  editor.setDOMSelection((_a = initValue === null || initValue === void 0 ? void 0 : initValue.initialSelection) !== null && _a !== void 0 ? _a : null);
34500
- context.onEnd();
34664
+ context.onEnd(true /* disposeHandler */);
34501
34665
  return false;
34502
34666
  }
34503
34667
  var insertionSuccess_1 = false;
@@ -34555,7 +34719,7 @@ function onDragEnd(context, event, initValue) {
34555
34719
  // No movement, restore initial selection
34556
34720
  editor.setDOMSelection((_b = initValue === null || initValue === void 0 ? void 0 : initValue.initialSelection) !== null && _b !== void 0 ? _b : null);
34557
34721
  }
34558
- context.onEnd();
34722
+ context.onEnd(true /* disposeHandler */);
34559
34723
  return insertionSuccess_1;
34560
34724
  }
34561
34725
  }
@@ -34813,6 +34977,7 @@ exports.getCMTableFromTable = getCMTableFromTable;
34813
34977
 
34814
34978
  Object.defineProperty(exports, "__esModule", ({ value: true }));
34815
34979
  exports.WatermarkPlugin = void 0;
34980
+ var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
34816
34981
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
34817
34982
  var isModelEmptyFast_1 = __webpack_require__(/*! ./isModelEmptyFast */ "./packages/roosterjs-content-model-plugins/lib/watermark/isModelEmptyFast.ts");
34818
34983
  var WATERMARK_CONTENT_KEY = '_WatermarkContent';
@@ -34833,6 +34998,7 @@ var WatermarkPlugin = /** @class */ (function () {
34833
34998
  this.watermark = watermark;
34834
34999
  this.editor = null;
34835
35000
  this.isShowing = false;
35001
+ this.darkTextColor = null;
34836
35002
  this.format = format || {
34837
35003
  fontSize: '14px',
34838
35004
  textColor: '#AAAAAA',
@@ -34872,6 +35038,21 @@ var WatermarkPlugin = /** @class */ (function () {
34872
35038
  // When input text, editor must not be empty, so we can do hide watermark now without checking content model
34873
35039
  this.showHide(editor, false /*isEmpty*/);
34874
35040
  }
35041
+ else if (event.eventType == 'contentChanged' &&
35042
+ (event.source == roosterjs_content_model_dom_1.ChangeSource.SwitchToDarkMode ||
35043
+ event.source == roosterjs_content_model_dom_1.ChangeSource.SwitchToLightMode) &&
35044
+ this.isShowing) {
35045
+ // When the placeholder is shown and user switches the mode, we need to update watermark style
35046
+ if (event.source == roosterjs_content_model_dom_1.ChangeSource.SwitchToDarkMode &&
35047
+ !this.darkTextColor &&
35048
+ this.format.textColor) {
35049
+ // Get the dark color only once when dark mode is enabled for the first time
35050
+ this.darkTextColor = editor
35051
+ .getColorManager()
35052
+ .getDarkColor(this.format.textColor, undefined, 'text');
35053
+ }
35054
+ this.applyWatermarkStyle(editor);
35055
+ }
34875
35056
  else if (event.eventType == 'editorReady' ||
34876
35057
  event.eventType == 'contentChanged' ||
34877
35058
  event.eventType == 'input' ||
@@ -34892,15 +35073,18 @@ var WatermarkPlugin = /** @class */ (function () {
34892
35073
  }
34893
35074
  };
34894
35075
  WatermarkPlugin.prototype.show = function (editor) {
34895
- var _this = this;
35076
+ this.applyWatermarkStyle(editor);
35077
+ this.isShowing = true;
35078
+ };
35079
+ WatermarkPlugin.prototype.applyWatermarkStyle = function (editor) {
34896
35080
  var rule = "position: absolute; pointer-events: none; content: \"" + this.watermark + "\";";
35081
+ var format = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, this.format), { textColor: editor.isDarkMode() ? this.darkTextColor : this.format.textColor });
34897
35082
  (0, roosterjs_content_model_dom_1.getObjectKeys)(styleMap).forEach(function (x) {
34898
- if (_this.format[x]) {
34899
- rule += styleMap[x] + ": " + _this.format[x] + "!important;";
35083
+ if (format[x]) {
35084
+ rule += styleMap[x] + ": " + format[x] + "!important;";
34900
35085
  }
34901
35086
  });
34902
35087
  editor.setEditorStyle(WATERMARK_CONTENT_KEY, rule, 'before');
34903
- this.isShowing = true;
34904
35088
  };
34905
35089
  WatermarkPlugin.prototype.hide = function (editor) {
34906
35090
  editor.setEditorStyle(WATERMARK_CONTENT_KEY, null);