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