roosterjs 9.5.1 → 9.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/rooster.js CHANGED
@@ -2094,8 +2094,8 @@ exports["default"] = getDarkColor;
2094
2094
  "use strict";
2095
2095
 
2096
2096
  Object.defineProperty(exports, "__esModule", ({ value: true }));
2097
- exports.formatTextSegmentBeforeSelectionMarker = exports.formatSegmentWithContentModel = exports.formatParagraphWithContentModel = exports.formatImageWithContentModel = exports.formatTableWithContentModel = exports.clearSelectedCells = exports.insertTableColumn = exports.insertTableRow = exports.insertEntity = exports.toggleCode = exports.setParagraphMargin = exports.adjustImageSelection = exports.setImageAltText = exports.adjustLinkSelection = exports.removeLink = exports.insertLink = exports.clearFormat = exports.getFormatState = exports.changeImage = exports.setImageBoxShadow = exports.setImageBorder = exports.setSpacing = exports.toggleBlockQuote = exports.setHeadingLevel = exports.setDirection = exports.setAlignment = exports.setIndentation = exports.setListStartNumber = exports.setListStyle = exports.insertImage = exports.changeCapitalization = exports.applySegmentFormat = exports.changeFontSize = exports.setTextColor = exports.setFontSize = exports.setFontName = exports.setBackgroundColor = exports.toggleSuperscript = exports.toggleSubscript = exports.toggleStrikethrough = exports.toggleUnderline = exports.toggleItalic = exports.toggleBold = exports.toggleNumbering = exports.toggleBullet = exports.applyTableBorderFormat = exports.editTable = exports.setTableCellShade = exports.formatTable = exports.insertTable = void 0;
2098
- exports.getListAnnounceData = exports.matchLink = exports.setModelIndentation = exports.findListItemsInSameThread = exports.setModelListStartNumber = exports.setModelListStyle = exports.setListType = exports.formatInsertPointWithContentModel = void 0;
2097
+ exports.formatSegmentWithContentModel = exports.formatParagraphWithContentModel = exports.formatImageWithContentModel = exports.formatTableWithContentModel = exports.clearSelectedCells = exports.insertTableColumn = exports.insertTableRow = exports.insertEntity = exports.toggleCode = exports.setParagraphMargin = exports.adjustImageSelection = exports.setImageAltText = exports.adjustLinkSelection = exports.removeLink = exports.insertLink = exports.clearFormat = exports.getFormatState = exports.changeImage = exports.setImageBoxShadow = exports.setImageBorder = exports.setSpacing = exports.toggleBlockQuote = exports.setHeadingLevel = exports.setDirection = exports.setAlignment = exports.setIndentation = exports.setListStartNumber = exports.setListStyle = exports.insertImage = exports.splitTextSegment = exports.changeCapitalization = exports.applySegmentFormat = exports.changeFontSize = exports.setTextColor = exports.setFontSize = exports.setFontName = exports.setBackgroundColor = exports.toggleSuperscript = exports.toggleSubscript = exports.toggleStrikethrough = exports.toggleUnderline = exports.toggleItalic = exports.toggleBold = exports.toggleNumbering = exports.toggleBullet = exports.applyTableBorderFormat = exports.editTable = exports.setTableCellShade = exports.formatTable = exports.insertTable = void 0;
2098
+ exports.getListAnnounceData = exports.matchLink = exports.setModelIndentation = exports.findListItemsInSameThread = exports.setModelListStartNumber = exports.setModelListStyle = exports.setListType = exports.formatInsertPointWithContentModel = exports.formatTextSegmentBeforeSelectionMarker = void 0;
2099
2099
  var insertTable_1 = __webpack_require__(/*! ./publicApi/table/insertTable */ "./packages/roosterjs-content-model-api/lib/publicApi/table/insertTable.ts");
2100
2100
  Object.defineProperty(exports, "insertTable", ({ enumerable: true, get: function () { return insertTable_1.insertTable; } }));
2101
2101
  var formatTable_1 = __webpack_require__(/*! ./publicApi/table/formatTable */ "./packages/roosterjs-content-model-api/lib/publicApi/table/formatTable.ts");
@@ -2136,6 +2136,8 @@ var applySegmentFormat_1 = __webpack_require__(/*! ./publicApi/segment/applySegm
2136
2136
  Object.defineProperty(exports, "applySegmentFormat", ({ enumerable: true, get: function () { return applySegmentFormat_1.applySegmentFormat; } }));
2137
2137
  var changeCapitalization_1 = __webpack_require__(/*! ./publicApi/segment/changeCapitalization */ "./packages/roosterjs-content-model-api/lib/publicApi/segment/changeCapitalization.ts");
2138
2138
  Object.defineProperty(exports, "changeCapitalization", ({ enumerable: true, get: function () { return changeCapitalization_1.changeCapitalization; } }));
2139
+ var splitTextSegment_1 = __webpack_require__(/*! ./publicApi/segment/splitTextSegment */ "./packages/roosterjs-content-model-api/lib/publicApi/segment/splitTextSegment.ts");
2140
+ Object.defineProperty(exports, "splitTextSegment", ({ enumerable: true, get: function () { return splitTextSegment_1.splitTextSegment; } }));
2139
2141
  var insertImage_1 = __webpack_require__(/*! ./publicApi/image/insertImage */ "./packages/roosterjs-content-model-api/lib/publicApi/image/insertImage.ts");
2140
2142
  Object.defineProperty(exports, "insertImage", ({ enumerable: true, get: function () { return insertImage_1.insertImage; } }));
2141
2143
  var setListStyle_1 = __webpack_require__(/*! ./publicApi/list/setListStyle */ "./packages/roosterjs-content-model-api/lib/publicApi/list/setListStyle.ts");
@@ -2953,7 +2955,24 @@ function insertEntityModel(model, entityModel, position, isBlock, focusAfterEnti
2953
2955
  exports.insertEntityModel = insertEntityModel;
2954
2956
  function getInsertPoint(model, insertPointOverride, context) {
2955
2957
  if (insertPointOverride) {
2956
- return insertPointOverride;
2958
+ var paragraph = insertPointOverride.paragraph, marker = insertPointOverride.marker, tableContext = insertPointOverride.tableContext, path = insertPointOverride.path;
2959
+ var index = paragraph.segments.indexOf(marker);
2960
+ var previousSegment = index > 0 ? paragraph.segments[index - 1] : null;
2961
+ // It is possible that the real selection is right before the override selection marker.
2962
+ // This happens when:
2963
+ // [Override marker][Entity node to wrap][Real marker]
2964
+ // Then we will move the entity node into entity wrapper, causes the override marker and real marker are at the same place
2965
+ // And recreating content model causes real marker to appear before override marker.
2966
+ // Once that happens, we need to use the real marker instead so that after insert entity, real marker can be placed
2967
+ // after new entity (if insertPointOverride==true)
2968
+ return (previousSegment === null || previousSegment === void 0 ? void 0 : previousSegment.segmentType) == 'SelectionMarker' && previousSegment.isSelected
2969
+ ? {
2970
+ marker: previousSegment,
2971
+ paragraph: paragraph,
2972
+ tableContext: tableContext,
2973
+ path: path,
2974
+ }
2975
+ : insertPointOverride;
2957
2976
  }
2958
2977
  else {
2959
2978
  var deleteResult = (0, roosterjs_content_model_dom_1.deleteSelection)(model, [], context);
@@ -5861,6 +5880,47 @@ function setTextColor(editor, textColor) {
5861
5880
  exports.setTextColor = setTextColor;
5862
5881
 
5863
5882
 
5883
+ /***/ }),
5884
+
5885
+ /***/ "./packages/roosterjs-content-model-api/lib/publicApi/segment/splitTextSegment.ts":
5886
+ /*!****************************************************************************************!*\
5887
+ !*** ./packages/roosterjs-content-model-api/lib/publicApi/segment/splitTextSegment.ts ***!
5888
+ \****************************************************************************************/
5889
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
5890
+
5891
+ "use strict";
5892
+
5893
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
5894
+ exports.splitTextSegment = void 0;
5895
+ var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
5896
+ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
5897
+ /**
5898
+ * Split given text segments from the given range
5899
+ * @param textSegment segment to split
5900
+ * @param parent parent paragraph the text segment exist in
5901
+ * @param start starting point of the split
5902
+ * @param end ending point of the split
5903
+ * @returns text segment from the indicated split.
5904
+ */
5905
+ function splitTextSegment(textSegment, parent, start, end) {
5906
+ var _a;
5907
+ var text = textSegment.text;
5908
+ var index = parent.segments.indexOf(textSegment);
5909
+ var middleSegment = (0, roosterjs_content_model_dom_1.createText)(text.substring(start, end), textSegment.format, textSegment.link, textSegment.code);
5910
+ var newSegments = [middleSegment];
5911
+ if (start > 0) {
5912
+ newSegments.unshift((0, roosterjs_content_model_dom_1.createText)(text.substring(0, start), textSegment.format, textSegment.link, textSegment.code));
5913
+ }
5914
+ if (end < text.length) {
5915
+ newSegments.push((0, roosterjs_content_model_dom_1.createText)(text.substring(end), textSegment.format, textSegment.link, textSegment.code));
5916
+ }
5917
+ newSegments.forEach(function (segment) { return (segment.isSelected = textSegment.isSelected); });
5918
+ (_a = parent.segments).splice.apply(_a, (0, tslib_1.__spreadArray)([index, 1], (0, tslib_1.__read)(newSegments), false));
5919
+ return middleSegment;
5920
+ }
5921
+ exports.splitTextSegment = splitTextSegment;
5922
+
5923
+
5864
5924
  /***/ }),
5865
5925
 
5866
5926
  /***/ "./packages/roosterjs-content-model-api/lib/publicApi/segment/toggleBold.ts":
@@ -6858,8 +6918,8 @@ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-mo
6858
6918
  function formatSegmentWithContentModel(editor, apiName, toggleStyleCallback, segmentHasStyleCallback, includingFormatHolder, afterFormatCallback) {
6859
6919
  editor.formatContentModel(function (model, context) {
6860
6920
  var segmentAndParagraphs = (0, roosterjs_content_model_dom_1.getSelectedSegmentsAndParagraphs)(model, !!includingFormatHolder, false /*includingEntity*/, true /*mutate*/);
6861
- var isCollapsedSelection = segmentAndParagraphs.length == 1 &&
6862
- segmentAndParagraphs[0][0].segmentType == 'SelectionMarker';
6921
+ var isCollapsedSelection = segmentAndParagraphs.length >= 1 &&
6922
+ segmentAndParagraphs.every(function (x) { return x[0].segmentType == 'SelectionMarker'; });
6863
6923
  if (isCollapsedSelection) {
6864
6924
  var para_1 = segmentAndParagraphs[0][1];
6865
6925
  var path_1 = segmentAndParagraphs[0][2];
@@ -7711,19 +7771,6 @@ exports.mergePasteContent = exports.cloneModelForPaste = void 0;
7711
7771
  var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
7712
7772
  var createDomToModelContextForSanitizing_1 = __webpack_require__(/*! ../createModelFromHtml/createDomToModelContextForSanitizing */ "./packages/roosterjs-content-model-core/lib/command/createModelFromHtml/createDomToModelContextForSanitizing.ts");
7713
7773
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
7714
- var EmptySegmentFormat = {
7715
- backgroundColor: '',
7716
- fontFamily: '',
7717
- fontSize: '',
7718
- fontWeight: '',
7719
- italic: false,
7720
- letterSpacing: '',
7721
- lineHeight: '',
7722
- strikethrough: false,
7723
- superOrSubScriptSequence: '',
7724
- textColor: '',
7725
- underline: false,
7726
- };
7727
7774
  var CloneOption = {
7728
7775
  includeCachedElement: function (node, type) { return (type == 'cache' ? undefined : node); },
7729
7776
  };
@@ -7758,7 +7805,7 @@ function mergePasteContent(editor, eventResult, clipboardData) {
7758
7805
  ? customizedMerge(model, pasteModel)
7759
7806
  : (0, roosterjs_content_model_dom_1.mergeModel)(model, pasteModel, context, mergeOption);
7760
7807
  if (insertPoint) {
7761
- context.newPendingFormat = (0, tslib_1.__assign)((0, tslib_1.__assign)((0, tslib_1.__assign)({}, EmptySegmentFormat), model.format), insertPoint.marker.format);
7808
+ context.newPendingFormat = (0, tslib_1.__assign)((0, tslib_1.__assign)((0, tslib_1.__assign)({}, roosterjs_content_model_dom_1.EmptySegmentFormat), model.format), insertPoint.marker.format);
7762
7809
  }
7763
7810
  return true;
7764
7811
  }, {
@@ -8423,7 +8470,7 @@ exports.coreApiMap = {
8423
8470
 
8424
8471
  Object.defineProperty(exports, "__esModule", ({ value: true }));
8425
8472
  exports.createContentModel = void 0;
8426
- var updateCachedSelection_1 = __webpack_require__(/*! ../../corePlugin/cache/updateCachedSelection */ "./packages/roosterjs-content-model-core/lib/corePlugin/cache/updateCachedSelection.ts");
8473
+ var updateCache_1 = __webpack_require__(/*! ../../corePlugin/cache/updateCache */ "./packages/roosterjs-content-model-core/lib/corePlugin/cache/updateCache.ts");
8427
8474
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
8428
8475
  /**
8429
8476
  * @internal
@@ -8459,8 +8506,7 @@ var createContentModel = function (core, option, selectionOverride) {
8459
8506
  }
8460
8507
  var model = (0, roosterjs_content_model_dom_1.domToContentModel)(core.logicalRoot, domToModelContext);
8461
8508
  if (saveIndex) {
8462
- core.cache.cachedModel = model;
8463
- (0, updateCachedSelection_1.updateCachedSelection)(core.cache, selection);
8509
+ (0, updateCache_1.updateCache)(core.cache, model, selection);
8464
8510
  }
8465
8511
  return model;
8466
8512
  };
@@ -9162,7 +9208,7 @@ exports.restoreUndoSnapshot = restoreUndoSnapshot;
9162
9208
 
9163
9209
  Object.defineProperty(exports, "__esModule", ({ value: true }));
9164
9210
  exports.setContentModel = void 0;
9165
- var updateCachedSelection_1 = __webpack_require__(/*! ../../corePlugin/cache/updateCachedSelection */ "./packages/roosterjs-content-model-core/lib/corePlugin/cache/updateCachedSelection.ts");
9211
+ var updateCache_1 = __webpack_require__(/*! ../../corePlugin/cache/updateCache */ "./packages/roosterjs-content-model-core/lib/corePlugin/cache/updateCache.ts");
9166
9212
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
9167
9213
  /**
9168
9214
  * @internal
@@ -9180,16 +9226,15 @@ var setContentModel = function (core, model, option, onNodeCreated) {
9180
9226
  modelToDomContext.onNodeCreated = onNodeCreated;
9181
9227
  var selection = (0, roosterjs_content_model_dom_1.contentModelToDom)(core.logicalRoot.ownerDocument, core.logicalRoot, model, modelToDomContext);
9182
9228
  if (!core.lifecycle.shadowEditFragment) {
9183
- (0, updateCachedSelection_1.updateCachedSelection)(core.cache, selection || undefined);
9229
+ // Clear pending mutations since we will use our latest model object to replace existing cache
9230
+ (_a = core.cache.textMutationObserver) === null || _a === void 0 ? void 0 : _a.flushMutations(true /*ignoreMutations*/);
9231
+ (0, updateCache_1.updateCache)(core.cache, model, selection);
9184
9232
  if (!(option === null || option === void 0 ? void 0 : option.ignoreSelection) && selection) {
9185
9233
  core.api.setDOMSelection(core, selection);
9186
9234
  }
9187
9235
  else {
9188
9236
  core.selection.selection = selection;
9189
9237
  }
9190
- // Clear pending mutations since we will use our latest model object to replace existing cache
9191
- (_a = core.cache.textMutationObserver) === null || _a === void 0 ? void 0 : _a.flushMutations();
9192
- core.cache.cachedModel = model;
9193
9238
  }
9194
9239
  return selection;
9195
9240
  };
@@ -9202,12 +9247,13 @@ exports.setContentModel = setContentModel;
9202
9247
  /*!**************************************************************************************************!*\
9203
9248
  !*** ./packages/roosterjs-content-model-core/lib/coreApi/setDOMSelection/addRangeToSelection.ts ***!
9204
9249
  \**************************************************************************************************/
9205
- /***/ ((__unused_webpack_module, exports) => {
9250
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
9206
9251
 
9207
9252
  "use strict";
9208
9253
 
9209
9254
  Object.defineProperty(exports, "__esModule", ({ value: true }));
9210
9255
  exports.addRangeToSelection = void 0;
9256
+ var areSameSelections_1 = __webpack_require__(/*! ../../corePlugin/cache/areSameSelections */ "./packages/roosterjs-content-model-core/lib/corePlugin/cache/areSameSelections.ts");
9211
9257
  /**
9212
9258
  * @internal
9213
9259
  */
@@ -9217,11 +9263,7 @@ function addRangeToSelection(doc, range, isReverted) {
9217
9263
  var selection = (_a = doc.defaultView) === null || _a === void 0 ? void 0 : _a.getSelection();
9218
9264
  if (selection) {
9219
9265
  var currentRange = selection.rangeCount > 0 && selection.getRangeAt(0);
9220
- if (currentRange &&
9221
- currentRange.startContainer == range.startContainer &&
9222
- currentRange.endContainer == range.endContainer &&
9223
- currentRange.startOffset == range.startOffset &&
9224
- currentRange.endOffset == range.endOffset) {
9266
+ if (currentRange && (0, areSameSelections_1.areSameRanges)(currentRange, range)) {
9225
9267
  return;
9226
9268
  }
9227
9269
  selection.removeAllRanges();
@@ -9236,40 +9278,6 @@ function addRangeToSelection(doc, range, isReverted) {
9236
9278
  exports.addRangeToSelection = addRangeToSelection;
9237
9279
 
9238
9280
 
9239
- /***/ }),
9240
-
9241
- /***/ "./packages/roosterjs-content-model-core/lib/coreApi/setDOMSelection/ensureImageHasSpanParent.ts":
9242
- /*!*******************************************************************************************************!*\
9243
- !*** ./packages/roosterjs-content-model-core/lib/coreApi/setDOMSelection/ensureImageHasSpanParent.ts ***!
9244
- \*******************************************************************************************************/
9245
- /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
9246
-
9247
- "use strict";
9248
-
9249
- Object.defineProperty(exports, "__esModule", ({ value: true }));
9250
- exports.ensureImageHasSpanParent = void 0;
9251
- var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
9252
- /**
9253
- * @internal
9254
- * Ensure image is wrapped by a span element
9255
- * @param image
9256
- * @returns the image
9257
- */
9258
- function ensureImageHasSpanParent(image) {
9259
- var parent = image.parentElement;
9260
- if (parent &&
9261
- (0, roosterjs_content_model_dom_1.isNodeOfType)(parent, 'ELEMENT_NODE') &&
9262
- (0, roosterjs_content_model_dom_1.isElementOfType)(parent, 'span') &&
9263
- parent.firstChild == image &&
9264
- parent.lastChild == image) {
9265
- return image;
9266
- }
9267
- (0, roosterjs_content_model_dom_1.wrap)(image.ownerDocument, image, 'span');
9268
- return image;
9269
- }
9270
- exports.ensureImageHasSpanParent = ensureImageHasSpanParent;
9271
-
9272
-
9273
9281
  /***/ }),
9274
9282
 
9275
9283
  /***/ "./packages/roosterjs-content-model-core/lib/coreApi/setDOMSelection/findLastedCoInMergedCell.ts":
@@ -9372,7 +9380,7 @@ exports.findTableCellElement = findTableCellElement;
9372
9380
  Object.defineProperty(exports, "__esModule", ({ value: true }));
9373
9381
  exports.setDOMSelection = void 0;
9374
9382
  var addRangeToSelection_1 = __webpack_require__(/*! ./addRangeToSelection */ "./packages/roosterjs-content-model-core/lib/coreApi/setDOMSelection/addRangeToSelection.ts");
9375
- var ensureImageHasSpanParent_1 = __webpack_require__(/*! ./ensureImageHasSpanParent */ "./packages/roosterjs-content-model-core/lib/coreApi/setDOMSelection/ensureImageHasSpanParent.ts");
9383
+ var areSameSelections_1 = __webpack_require__(/*! ../../corePlugin/cache/areSameSelections */ "./packages/roosterjs-content-model-core/lib/corePlugin/cache/areSameSelections.ts");
9376
9384
  var ensureUniqueId_1 = __webpack_require__(/*! ../setEditorStyle/ensureUniqueId */ "./packages/roosterjs-content-model-core/lib/coreApi/setEditorStyle/ensureUniqueId.ts");
9377
9385
  var findLastedCoInMergedCell_1 = __webpack_require__(/*! ./findLastedCoInMergedCell */ "./packages/roosterjs-content-model-core/lib/coreApi/setDOMSelection/findLastedCoInMergedCell.ts");
9378
9386
  var findTableCellElement_1 = __webpack_require__(/*! ./findTableCellElement */ "./packages/roosterjs-content-model-core/lib/coreApi/setDOMSelection/findTableCellElement.ts");
@@ -9385,11 +9393,16 @@ var TABLE_ID = 'table';
9385
9393
  var CARET_CSS_RULE = 'caret-color: transparent';
9386
9394
  var TRANSPARENT_SELECTION_CSS_RULE = 'background-color: transparent !important;';
9387
9395
  var SELECTION_SELECTOR = '*::selection';
9396
+ var DEFAULT_SELECTION_BORDER_COLOR = '#DB626C';
9388
9397
  /**
9389
9398
  * @internal
9390
9399
  */
9391
9400
  var setDOMSelection = function (core, selection, skipSelectionChangedEvent) {
9392
9401
  var _a, _b, _c;
9402
+ var existingSelection = core.api.getDOMSelection(core);
9403
+ if (existingSelection && selection && (0, areSameSelections_1.areSameSelections)(existingSelection, selection)) {
9404
+ return;
9405
+ }
9393
9406
  // We are applying a new selection, so we don't need to apply cached selection in DOMEventPlugin.
9394
9407
  // Set skipReselectOnFocus to skip this behavior
9395
9408
  var skipReselectOnFocus = core.selection.skipReselectOnFocus;
@@ -9402,15 +9415,12 @@ var setDOMSelection = function (core, selection, skipSelectionChangedEvent) {
9402
9415
  try {
9403
9416
  switch (selection === null || selection === void 0 ? void 0 : selection.type) {
9404
9417
  case 'image':
9405
- var image = (0, ensureImageHasSpanParent_1.ensureImageHasSpanParent)(selection.image);
9406
- core.selection.selection = {
9407
- type: 'image',
9408
- image: image,
9409
- };
9418
+ var image = selection.image;
9419
+ core.selection.selection = selection;
9410
9420
  var imageSelectionColor = isDarkMode
9411
9421
  ? core.selection.imageSelectionBorderColorDark
9412
9422
  : core.selection.imageSelectionBorderColor;
9413
- core.api.setEditorStyle(core, DOM_SELECTION_CSS_KEY, "outline-style:solid!important; outline-color:" + imageSelectionColor + "!important;display: " + (core.environment.isSafari ? '-webkit-inline-flex' : 'inline-flex') + ";", ["span:has(>img#" + (0, ensureUniqueId_1.ensureUniqueId)(image, IMAGE_ID) + ")"]);
9423
+ core.api.setEditorStyle(core, DOM_SELECTION_CSS_KEY, "outline-style:solid!important; outline-color:" + (imageSelectionColor || DEFAULT_SELECTION_BORDER_COLOR) + "!important;", ["#" + (0, ensureUniqueId_1.ensureUniqueId)(image, IMAGE_ID)]);
9414
9424
  core.api.setEditorStyle(core, HIDE_SELECTION_CSS_KEY, TRANSPARENT_SELECTION_CSS_RULE, [SELECTION_SELECTOR]);
9415
9425
  setRangeSelection(doc, image, false /* collapse */);
9416
9426
  break;
@@ -9805,10 +9815,10 @@ function handledExclusively(event, plugin) {
9805
9815
 
9806
9816
  Object.defineProperty(exports, "__esModule", ({ value: true }));
9807
9817
  exports.createCachePlugin = void 0;
9808
- var areSameSelection_1 = __webpack_require__(/*! ./areSameSelection */ "./packages/roosterjs-content-model-core/lib/corePlugin/cache/areSameSelection.ts");
9818
+ var areSameSelections_1 = __webpack_require__(/*! ./areSameSelections */ "./packages/roosterjs-content-model-core/lib/corePlugin/cache/areSameSelections.ts");
9809
9819
  var textMutationObserver_1 = __webpack_require__(/*! ./textMutationObserver */ "./packages/roosterjs-content-model-core/lib/corePlugin/cache/textMutationObserver.ts");
9810
9820
  var domIndexerImpl_1 = __webpack_require__(/*! ./domIndexerImpl */ "./packages/roosterjs-content-model-core/lib/corePlugin/cache/domIndexerImpl.ts");
9811
- var updateCachedSelection_1 = __webpack_require__(/*! ./updateCachedSelection */ "./packages/roosterjs-content-model-core/lib/corePlugin/cache/updateCachedSelection.ts");
9821
+ var updateCache_1 = __webpack_require__(/*! ./updateCache */ "./packages/roosterjs-content-model-core/lib/corePlugin/cache/updateCache.ts");
9812
9822
  /**
9813
9823
  * ContentModel cache plugin manages cached Content Model, and refresh the cache when necessary
9814
9824
  */
@@ -9821,13 +9831,21 @@ var CachePlugin = /** @class */ (function () {
9821
9831
  function CachePlugin(option, contentDiv) {
9822
9832
  var _this = this;
9823
9833
  this.editor = null;
9824
- this.onMutation = function (isTextChangeOnly) {
9834
+ this.onMutation = function (mutation) {
9835
+ var _a;
9825
9836
  if (_this.editor) {
9826
- if (isTextChangeOnly) {
9827
- _this.updateCachedModel(_this.editor, true /*forceUpdate*/);
9828
- }
9829
- else {
9830
- _this.invalidateCache();
9837
+ switch (mutation.type) {
9838
+ case 'childList':
9839
+ if (!((_a = _this.state.domIndexer) === null || _a === void 0 ? void 0 : _a.reconcileChildList(mutation.addedNodes, mutation.removedNodes))) {
9840
+ _this.invalidateCache();
9841
+ }
9842
+ break;
9843
+ case 'text':
9844
+ _this.updateCachedModel(_this.editor, true /*forceUpdate*/);
9845
+ break;
9846
+ case 'unknown':
9847
+ _this.invalidateCache();
9848
+ break;
9831
9849
  }
9832
9850
  }
9833
9851
  };
@@ -9908,8 +9926,7 @@ var CachePlugin = /** @class */ (function () {
9908
9926
  case 'contentChanged':
9909
9927
  var contentModel = event.contentModel, selection = event.selection;
9910
9928
  if (contentModel && this.state.domIndexer) {
9911
- this.state.cachedModel = contentModel;
9912
- (0, updateCachedSelection_1.updateCachedSelection)(this.state, selection);
9929
+ (0, updateCache_1.updateCache)(this.state, contentModel, selection);
9913
9930
  }
9914
9931
  else {
9915
9932
  this.invalidateCache();
@@ -9926,6 +9943,9 @@ var CachePlugin = /** @class */ (function () {
9926
9943
  };
9927
9944
  CachePlugin.prototype.updateCachedModel = function (editor, forceUpdate) {
9928
9945
  var _a;
9946
+ if (editor.isInShadowEdit()) {
9947
+ return;
9948
+ }
9929
9949
  var cachedSelection = this.state.cachedSelection;
9930
9950
  this.state.cachedSelection = undefined; // Clear it to force getDOMSelection() retrieve the latest selection range
9931
9951
  var newRangeEx = editor.getDOMSelection() || undefined;
@@ -9933,7 +9953,7 @@ var CachePlugin = /** @class */ (function () {
9933
9953
  var isSelectionChanged = forceUpdate ||
9934
9954
  !cachedSelection ||
9935
9955
  !newRangeEx ||
9936
- !(0, areSameSelection_1.areSameSelection)(newRangeEx, cachedSelection);
9956
+ !(0, areSameSelections_1.areSameSelections)(newRangeEx, cachedSelection);
9937
9957
  if (isSelectionChanged) {
9938
9958
  if (!model ||
9939
9959
  !newRangeEx ||
@@ -9941,7 +9961,7 @@ var CachePlugin = /** @class */ (function () {
9941
9961
  this.invalidateCache();
9942
9962
  }
9943
9963
  else {
9944
- (0, updateCachedSelection_1.updateCachedSelection)(this.state, newRangeEx);
9964
+ (0, updateCache_1.updateCache)(this.state, model, newRangeEx);
9945
9965
  }
9946
9966
  }
9947
9967
  else {
@@ -9964,21 +9984,21 @@ exports.createCachePlugin = createCachePlugin;
9964
9984
 
9965
9985
  /***/ }),
9966
9986
 
9967
- /***/ "./packages/roosterjs-content-model-core/lib/corePlugin/cache/areSameSelection.ts":
9968
- /*!****************************************************************************************!*\
9969
- !*** ./packages/roosterjs-content-model-core/lib/corePlugin/cache/areSameSelection.ts ***!
9970
- \****************************************************************************************/
9987
+ /***/ "./packages/roosterjs-content-model-core/lib/corePlugin/cache/areSameSelections.ts":
9988
+ /*!*****************************************************************************************!*\
9989
+ !*** ./packages/roosterjs-content-model-core/lib/corePlugin/cache/areSameSelections.ts ***!
9990
+ \*****************************************************************************************/
9971
9991
  /***/ ((__unused_webpack_module, exports) => {
9972
9992
 
9973
9993
  "use strict";
9974
9994
 
9975
9995
  Object.defineProperty(exports, "__esModule", ({ value: true }));
9976
- exports.areSameSelection = void 0;
9996
+ exports.areSameRanges = exports.areSameTableSelections = exports.areSameSelections = void 0;
9977
9997
  /**
9978
9998
  * @internal
9979
9999
  * Check if the given selections are the same
9980
10000
  */
9981
- function areSameSelection(sel1, sel2) {
10001
+ function areSameSelections(sel1, sel2) {
9982
10002
  if (sel1 == sel2) {
9983
10003
  return true;
9984
10004
  }
@@ -9986,22 +10006,56 @@ function areSameSelection(sel1, sel2) {
9986
10006
  case 'image':
9987
10007
  return sel2.type == 'image' && sel2.image == sel1.image;
9988
10008
  case 'table':
9989
- return (sel2.type == 'table' &&
9990
- sel2.table == sel1.table &&
9991
- sel2.firstColumn == sel1.firstColumn &&
9992
- sel2.lastColumn == sel1.lastColumn &&
9993
- sel2.firstRow == sel1.firstRow &&
9994
- sel2.lastRow == sel1.lastRow);
10009
+ return sel2.type == 'table' && areSameTableSelections(sel1, sel2);
9995
10010
  case 'range':
9996
10011
  default:
9997
- return (sel2.type == 'range' &&
9998
- sel1.range.startContainer == sel2.start.node &&
9999
- sel1.range.endContainer == sel2.end.node &&
10000
- sel1.range.startOffset == sel2.start.offset &&
10001
- sel1.range.endOffset == sel2.end.offset);
10012
+ if (sel2.type == 'range') {
10013
+ var range1 = sel1.range;
10014
+ if (isCacheSelection(sel2)) {
10015
+ var start = sel2.start, end = sel2.end;
10016
+ return (range1.startContainer == start.node &&
10017
+ range1.endContainer == end.node &&
10018
+ range1.startOffset == start.offset &&
10019
+ range1.endOffset == end.offset);
10020
+ }
10021
+ else {
10022
+ return areSameRanges(range1, sel2.range);
10023
+ }
10024
+ }
10025
+ else {
10026
+ return false;
10027
+ }
10002
10028
  }
10003
10029
  }
10004
- exports.areSameSelection = areSameSelection;
10030
+ exports.areSameSelections = areSameSelections;
10031
+ function areSame(o1, o2, keys) {
10032
+ return keys.every(function (k) { return o1[k] == o2[k]; });
10033
+ }
10034
+ var TableSelectionKeys = [
10035
+ 'table',
10036
+ 'firstColumn',
10037
+ 'lastColumn',
10038
+ 'firstRow',
10039
+ 'lastRow',
10040
+ ];
10041
+ var RangeKeys = ['startContainer', 'endContainer', 'startOffset', 'endOffset'];
10042
+ /**
10043
+ * @internal
10044
+ */
10045
+ function areSameTableSelections(t1, t2) {
10046
+ return areSame(t1, t2, TableSelectionKeys);
10047
+ }
10048
+ exports.areSameTableSelections = areSameTableSelections;
10049
+ /**
10050
+ * @internal
10051
+ */
10052
+ function areSameRanges(r1, r2) {
10053
+ return areSame(r1, r2, RangeKeys);
10054
+ }
10055
+ exports.areSameRanges = areSameRanges;
10056
+ function isCacheSelection(sel) {
10057
+ return !!sel.start;
10058
+ }
10005
10059
 
10006
10060
 
10007
10061
  /***/ }),
@@ -10026,6 +10080,9 @@ function isIndexedSegment(node) {
10026
10080
  Array.isArray(paragraph.segments) &&
10027
10081
  Array.isArray(segments));
10028
10082
  }
10083
+ function getIndexedSegmentItem(node) {
10084
+ return node && isIndexedSegment(node) ? node.__roosterjsContentModel : null;
10085
+ }
10029
10086
  /**
10030
10087
  * @internal
10031
10088
  * Implementation of DomIndexer
@@ -10049,9 +10106,7 @@ var DomIndexerImpl = /** @class */ (function () {
10049
10106
  previousText = child;
10050
10107
  }
10051
10108
  else {
10052
- var item = isIndexedSegment(previousText)
10053
- ? previousText.__roosterjsContentModel
10054
- : undefined;
10109
+ var item = getIndexedSegmentItem(previousText);
10055
10110
  if (item && isIndexedSegment(child)) {
10056
10111
  item.segments = item.segments.concat(child.__roosterjsContentModel.segments);
10057
10112
  child.__roosterjsContentModel.segments = [];
@@ -10124,6 +10179,32 @@ var DomIndexerImpl = /** @class */ (function () {
10124
10179
  }
10125
10180
  return false;
10126
10181
  };
10182
+ DomIndexerImpl.prototype.reconcileChildList = function (addedNodes, removedNodes) {
10183
+ if (!this.persistCache) {
10184
+ return false;
10185
+ }
10186
+ var canHandle = true;
10187
+ var context = {
10188
+ segIndex: -1,
10189
+ };
10190
+ // First process added nodes
10191
+ var addedNode = addedNodes[0];
10192
+ if (addedNodes.length == 1 && (0, roosterjs_content_model_dom_1.isNodeOfType)(addedNode, 'TEXT_NODE')) {
10193
+ canHandle = this.reconcileAddedNode(addedNode, context);
10194
+ }
10195
+ else if (addedNodes.length > 0) {
10196
+ canHandle = false;
10197
+ }
10198
+ // Second, process removed nodes
10199
+ var removedNode = removedNodes[0];
10200
+ if (canHandle && removedNodes.length == 1) {
10201
+ canHandle = this.reconcileRemovedNode(removedNode, context);
10202
+ }
10203
+ else if (removedNodes.length > 0) {
10204
+ canHandle = false;
10205
+ }
10206
+ return canHandle && !context.pendingTextNode;
10207
+ };
10127
10208
  DomIndexerImpl.prototype.isCollapsed = function (selection) {
10128
10209
  var start = selection.start, end = selection.end;
10129
10210
  return start.node == end.node && start.offset == end.offset;
@@ -10141,8 +10222,9 @@ var DomIndexerImpl = /** @class */ (function () {
10141
10222
  };
10142
10223
  DomIndexerImpl.prototype.insertMarker = function (node, isAfter) {
10143
10224
  var marker;
10144
- if (node && isIndexedSegment(node)) {
10145
- var _a = node.__roosterjsContentModel, paragraph = _a.paragraph, segments = _a.segments;
10225
+ var segmentItem = node && getIndexedSegmentItem(node);
10226
+ if (segmentItem) {
10227
+ var paragraph = segmentItem.paragraph, segments = segmentItem.segments;
10146
10228
  var index = paragraph.segments.indexOf(segments[0]);
10147
10229
  if (index >= 0) {
10148
10230
  var formatSegment = (!isAfter && paragraph.segments[index - 1]) || paragraph.segments[index];
@@ -10212,6 +10294,88 @@ var DomIndexerImpl = /** @class */ (function () {
10212
10294
  }
10213
10295
  return selectable;
10214
10296
  };
10297
+ DomIndexerImpl.prototype.reconcileAddedNode = function (node, context) {
10298
+ var segmentItem = null;
10299
+ var index = -1;
10300
+ var existingSegment;
10301
+ var previousSibling = node.previousSibling, nextSibling = node.nextSibling;
10302
+ if ((segmentItem = getIndexedSegmentItem(previousSibling)) &&
10303
+ (existingSegment = segmentItem.segments[segmentItem.segments.length - 1]) &&
10304
+ (index = segmentItem.paragraph.segments.indexOf(existingSegment)) >= 0) {
10305
+ // When we can find indexed segment before current one, use it as the insert index
10306
+ this.indexNode(segmentItem.paragraph, index + 1, node, existingSegment.format);
10307
+ }
10308
+ else if ((segmentItem = getIndexedSegmentItem(nextSibling)) &&
10309
+ (existingSegment = segmentItem.segments[0]) &&
10310
+ (index = segmentItem.paragraph.segments.indexOf(existingSegment)) >= 0) {
10311
+ // When we can find indexed segment after current one, use it as the insert index
10312
+ this.indexNode(segmentItem.paragraph, index, node, existingSegment.format);
10313
+ }
10314
+ else if (context.paragraph && context.segIndex >= 0) {
10315
+ // When there is indexed paragraph from removed nodes, we can use it as the insert index
10316
+ this.indexNode(context.paragraph, context.segIndex, node, context.format);
10317
+ }
10318
+ else if (context.pendingTextNode === undefined) {
10319
+ // When we can't find the insert index, set current node as pending node
10320
+ // so later we can pick it up when we have enough info when processing removed node
10321
+ // Only do this when pendingTextNode is undefined. If it is null it means there was already a pending node before
10322
+ // and in that case we should return false since we can't handle two pending text node
10323
+ context.pendingTextNode = node;
10324
+ }
10325
+ else {
10326
+ return false;
10327
+ }
10328
+ return true;
10329
+ };
10330
+ DomIndexerImpl.prototype.reconcileRemovedNode = function (node, context) {
10331
+ var segmentItem = null;
10332
+ var removingSegment;
10333
+ if (context.segIndex < 0 &&
10334
+ !context.paragraph && // No previous removed segment or related paragraph found, and
10335
+ (segmentItem = getIndexedSegmentItem(node)) && // The removed node is indexed, and
10336
+ (removingSegment = segmentItem.segments[0]) // There is at least one related segment
10337
+ ) {
10338
+ // Now we can remove the indexed segment from the paragraph, and remember it, later we may need to use it
10339
+ context.format = removingSegment.format;
10340
+ context.paragraph = segmentItem.paragraph;
10341
+ context.segIndex = segmentItem.paragraph.segments.indexOf(segmentItem.segments[0]);
10342
+ if (context.segIndex < 0) {
10343
+ // Indexed segment is not under paragraph, something wrong happens, we cannot keep handling
10344
+ return false;
10345
+ }
10346
+ for (var i = 0; i < segmentItem.segments.length; i++) {
10347
+ var index = segmentItem.paragraph.segments.indexOf(segmentItem.segments[i]);
10348
+ if (index >= 0) {
10349
+ segmentItem.paragraph.segments.splice(index, 1);
10350
+ }
10351
+ }
10352
+ if (context.pendingTextNode) {
10353
+ // If we have pending text node added but not indexed, do it now
10354
+ this.indexNode(context.paragraph, context.segIndex, context.pendingTextNode, segmentItem.segments[0].format);
10355
+ // Set to null since we have processed it.
10356
+ // Next time we see a pending node we know we have already processed one so it is a situation we cannot handle
10357
+ context.pendingTextNode = null;
10358
+ }
10359
+ return true;
10360
+ }
10361
+ else {
10362
+ return false;
10363
+ }
10364
+ };
10365
+ DomIndexerImpl.prototype.indexNode = function (paragraph, index, textNode, format) {
10366
+ var _a;
10367
+ var copiedFormat = format ? (0, tslib_1.__assign)({}, format) : undefined;
10368
+ if (copiedFormat) {
10369
+ (0, roosterjs_content_model_dom_1.getObjectKeys)(copiedFormat).forEach(function (key) {
10370
+ if (roosterjs_content_model_dom_1.EmptySegmentFormat[key] === undefined) {
10371
+ delete copiedFormat[key];
10372
+ }
10373
+ });
10374
+ }
10375
+ var text = (0, roosterjs_content_model_dom_1.createText)((_a = textNode.textContent) !== null && _a !== void 0 ? _a : '', copiedFormat);
10376
+ paragraph.segments.splice(index, 0, text);
10377
+ this.onSegment(textNode, paragraph, [text]);
10378
+ };
10215
10379
  return DomIndexerImpl;
10216
10380
  }());
10217
10381
  exports.DomIndexerImpl = DomIndexerImpl;
@@ -10235,11 +10399,59 @@ var TextMutationObserverImpl = /** @class */ (function () {
10235
10399
  this.contentDiv = contentDiv;
10236
10400
  this.onMutation = onMutation;
10237
10401
  this.onMutationInternal = function (mutations) {
10238
- var _a;
10239
- var firstTarget = (_a = mutations[0]) === null || _a === void 0 ? void 0 : _a.target;
10240
- if (firstTarget) {
10241
- var isTextChangeOnly = mutations.every(function (mutation) { return mutation.type == 'characterData' && mutation.target == firstTarget; });
10242
- _this.onMutation(isTextChangeOnly);
10402
+ var canHandle = true;
10403
+ var firstTarget = null;
10404
+ var lastTextChangeNode = null;
10405
+ var addedNodes = [];
10406
+ var removedNodes = [];
10407
+ var reconcileText = false;
10408
+ for (var i = 0; i < mutations.length && canHandle; i++) {
10409
+ var mutation = mutations[i];
10410
+ switch (mutation.type) {
10411
+ case 'attributes':
10412
+ if (mutation.target != _this.contentDiv) {
10413
+ // We cannot handle attributes changes on editor content for now
10414
+ canHandle = false;
10415
+ }
10416
+ break;
10417
+ case 'characterData':
10418
+ if (lastTextChangeNode && lastTextChangeNode != mutation.target) {
10419
+ // Multiple text nodes got changed, we don't know how to handle it
10420
+ canHandle = false;
10421
+ }
10422
+ else {
10423
+ lastTextChangeNode = mutation.target;
10424
+ reconcileText = true;
10425
+ }
10426
+ break;
10427
+ case 'childList':
10428
+ if (!firstTarget) {
10429
+ firstTarget = mutation.target;
10430
+ }
10431
+ else if (firstTarget != mutation.target) {
10432
+ canHandle = false;
10433
+ }
10434
+ if (canHandle) {
10435
+ addedNodes = addedNodes.concat(Array.from(mutation.addedNodes));
10436
+ removedNodes = removedNodes.concat(Array.from(mutation.removedNodes));
10437
+ }
10438
+ break;
10439
+ }
10440
+ }
10441
+ if (canHandle) {
10442
+ if (addedNodes.length > 0 || removedNodes.length > 0) {
10443
+ _this.onMutation({
10444
+ type: 'childList',
10445
+ addedNodes: addedNodes,
10446
+ removedNodes: removedNodes,
10447
+ });
10448
+ }
10449
+ if (reconcileText) {
10450
+ _this.onMutation({ type: 'text' });
10451
+ }
10452
+ }
10453
+ else {
10454
+ _this.onMutation({ type: 'unknown' });
10243
10455
  }
10244
10456
  };
10245
10457
  this.observer = new MutationObserver(this.onMutationInternal);
@@ -10255,9 +10467,11 @@ var TextMutationObserverImpl = /** @class */ (function () {
10255
10467
  TextMutationObserverImpl.prototype.stopObserving = function () {
10256
10468
  this.observer.disconnect();
10257
10469
  };
10258
- TextMutationObserverImpl.prototype.flushMutations = function () {
10470
+ TextMutationObserverImpl.prototype.flushMutations = function (ignoreMutations) {
10259
10471
  var mutations = this.observer.takeRecords();
10260
- this.onMutationInternal(mutations);
10472
+ if (!ignoreMutations) {
10473
+ this.onMutationInternal(mutations);
10474
+ }
10261
10475
  };
10262
10476
  return TextMutationObserverImpl;
10263
10477
  }());
@@ -10272,20 +10486,21 @@ exports.createTextMutationObserver = createTextMutationObserver;
10272
10486
 
10273
10487
  /***/ }),
10274
10488
 
10275
- /***/ "./packages/roosterjs-content-model-core/lib/corePlugin/cache/updateCachedSelection.ts":
10276
- /*!*********************************************************************************************!*\
10277
- !*** ./packages/roosterjs-content-model-core/lib/corePlugin/cache/updateCachedSelection.ts ***!
10278
- \*********************************************************************************************/
10489
+ /***/ "./packages/roosterjs-content-model-core/lib/corePlugin/cache/updateCache.ts":
10490
+ /*!***********************************************************************************!*\
10491
+ !*** ./packages/roosterjs-content-model-core/lib/corePlugin/cache/updateCache.ts ***!
10492
+ \***********************************************************************************/
10279
10493
  /***/ ((__unused_webpack_module, exports) => {
10280
10494
 
10281
10495
  "use strict";
10282
10496
 
10283
10497
  Object.defineProperty(exports, "__esModule", ({ value: true }));
10284
- exports.updateCachedSelection = void 0;
10498
+ exports.updateCache = void 0;
10285
10499
  /**
10286
10500
  * @internal
10287
10501
  */
10288
- function updateCachedSelection(state, selection) {
10502
+ function updateCache(state, model, selection) {
10503
+ state.cachedModel = model;
10289
10504
  if ((selection === null || selection === void 0 ? void 0 : selection.type) == 'range') {
10290
10505
  var _a = selection.range, startContainer = _a.startContainer, startOffset = _a.startOffset, endContainer = _a.endContainer, endOffset = _a.endOffset, isReverted = selection.isReverted;
10291
10506
  state.cachedSelection = {
@@ -10302,10 +10517,10 @@ function updateCachedSelection(state, selection) {
10302
10517
  };
10303
10518
  }
10304
10519
  else {
10305
- state.cachedSelection = selection;
10520
+ state.cachedSelection = selection !== null && selection !== void 0 ? selection : undefined;
10306
10521
  }
10307
10522
  }
10308
- exports.updateCachedSelection = updateCachedSelection;
10523
+ exports.updateCache = updateCache;
10309
10524
 
10310
10525
 
10311
10526
  /***/ }),
@@ -12205,7 +12420,6 @@ var isSingleImageInSelection_1 = __webpack_require__(/*! ./isSingleImageInSelect
12205
12420
  var normalizePos_1 = __webpack_require__(/*! ./normalizePos */ "./packages/roosterjs-content-model-core/lib/corePlugin/selection/normalizePos.ts");
12206
12421
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
12207
12422
  var MouseLeftButton = 0;
12208
- var MouseMiddleButton = 1;
12209
12423
  var MouseRightButton = 2;
12210
12424
  var Up = 'ArrowUp';
12211
12425
  var Down = 'ArrowDown';
@@ -12320,16 +12534,17 @@ var SelectionPlugin = /** @class */ (function () {
12320
12534
  var newSelection = _this.editor.getDOMSelection();
12321
12535
  //If am image selection changed to a wider range due a keyboard event, we should update the selection
12322
12536
  var selection = _this.editor.getDocument().getSelection();
12323
- if ((newSelection === null || newSelection === void 0 ? void 0 : newSelection.type) == 'image' && selection) {
12324
- if (selection && !(0, isSingleImageInSelection_1.isSingleImageInSelection)(selection)) {
12325
- var range = selection.getRangeAt(0);
12326
- _this.editor.setDOMSelection({
12327
- type: 'range',
12328
- range: range,
12329
- isReverted: selection.focusNode != range.endContainer ||
12330
- selection.focusOffset != range.endOffset,
12331
- });
12332
- }
12537
+ if ((newSelection === null || newSelection === void 0 ? void 0 : newSelection.type) == 'image' &&
12538
+ selection &&
12539
+ selection.focusNode &&
12540
+ !(0, isSingleImageInSelection_1.isSingleImageInSelection)(selection)) {
12541
+ var range = selection.getRangeAt(0);
12542
+ _this.editor.setDOMSelection({
12543
+ type: 'range',
12544
+ range: range,
12545
+ isReverted: selection.focusNode != range.endContainer ||
12546
+ selection.focusOffset != range.endOffset,
12547
+ });
12333
12548
  }
12334
12549
  // Safari has problem to handle onBlur event. When blur, we cannot get the original selection from editor.
12335
12550
  // So we always save a selection whenever editor has focus. Then after blur, we can still use this cached selection.
@@ -12411,7 +12626,7 @@ var SelectionPlugin = /** @class */ (function () {
12411
12626
  this.onMouseDown(this.editor, event.rawEvent);
12412
12627
  break;
12413
12628
  case 'mouseUp':
12414
- this.onMouseUp(event);
12629
+ this.onMouseUp();
12415
12630
  break;
12416
12631
  case 'keyDown':
12417
12632
  this.onKeyDown(this.editor, event.rawEvent);
@@ -12431,15 +12646,20 @@ var SelectionPlugin = /** @class */ (function () {
12431
12646
  var selection = editor.getDOMSelection();
12432
12647
  var image;
12433
12648
  // Image selection
12434
- if (rawEvent.button === MouseRightButton &&
12435
- (image =
12436
- (_a = this.getClickingImage(rawEvent)) !== null && _a !== void 0 ? _a : this.getContainedTargetImage(rawEvent, selection)) &&
12437
- image.isContentEditable) {
12438
- this.selectImageWithRange(image, rawEvent);
12439
- return;
12649
+ if ((selection === null || selection === void 0 ? void 0 : selection.type) == 'image' &&
12650
+ (rawEvent.button == MouseLeftButton ||
12651
+ (rawEvent.button == MouseRightButton &&
12652
+ !this.getClickingImage(rawEvent) &&
12653
+ !this.getContainedTargetImage(rawEvent, selection)))) {
12654
+ this.setDOMSelection(null /*domSelection*/, null /*tableSelection*/);
12440
12655
  }
12441
- else if ((selection === null || selection === void 0 ? void 0 : selection.type) == 'image' && selection.image !== rawEvent.target) {
12442
- this.selectBeforeOrAfterElement(editor, selection.image);
12656
+ if ((image =
12657
+ (_a = this.getClickingImage(rawEvent)) !== null && _a !== void 0 ? _a : this.getContainedTargetImage(rawEvent, selection)) &&
12658
+ image.isContentEditable) {
12659
+ this.setDOMSelection({
12660
+ type: 'image',
12661
+ image: image,
12662
+ }, null);
12443
12663
  return;
12444
12664
  }
12445
12665
  // Table selection
@@ -12468,32 +12688,7 @@ var SelectionPlugin = /** @class */ (function () {
12468
12688
  });
12469
12689
  }
12470
12690
  };
12471
- SelectionPlugin.prototype.selectImageWithRange = function (image, event) {
12472
- var _a;
12473
- var range = image.ownerDocument.createRange();
12474
- range.selectNode(image);
12475
- var domSelection = (_a = this.editor) === null || _a === void 0 ? void 0 : _a.getDOMSelection();
12476
- if ((domSelection === null || domSelection === void 0 ? void 0 : domSelection.type) == 'image' && image == domSelection.image) {
12477
- event.preventDefault();
12478
- }
12479
- else {
12480
- this.setDOMSelection({
12481
- type: 'range',
12482
- isReverted: false,
12483
- range: range,
12484
- }, null);
12485
- }
12486
- };
12487
- SelectionPlugin.prototype.onMouseUp = function (event) {
12488
- var image;
12489
- if ((image = this.getClickingImage(event.rawEvent)) &&
12490
- image.isContentEditable &&
12491
- event.rawEvent.button != MouseMiddleButton &&
12492
- (event.rawEvent.button ==
12493
- MouseRightButton /* it's not possible to drag using right click */ ||
12494
- event.isClicking)) {
12495
- this.selectImageWithRange(image, event.rawEvent);
12496
- }
12691
+ SelectionPlugin.prototype.onMouseUp = function () {
12497
12692
  this.detachMouseEvent();
12498
12693
  };
12499
12694
  SelectionPlugin.prototype.onKeyDown = function (editor, rawEvent) {
@@ -12571,6 +12766,7 @@ var SelectionPlugin = /** @class */ (function () {
12571
12766
  return;
12572
12767
  }
12573
12768
  var lastCo = (0, findCoordinate_1.findCoordinate)(tableSel === null || tableSel === void 0 ? void 0 : tableSel.parsedTable, end, domHelper);
12769
+ var tabMove = false;
12574
12770
  var _h = this.state.tableSelection, parsedTable = _h.parsedTable, oldCo = _h.firstCo, table = _h.table;
12575
12771
  if (lastCo && tableSel.table == table) {
12576
12772
  if (lastCo.col != oldCo.col && (key == Up || key == Down)) {
@@ -12608,7 +12804,8 @@ var SelectionPlugin = /** @class */ (function () {
12608
12804
  }
12609
12805
  var cell = parsedTable[row][col];
12610
12806
  if (typeof cell != 'string') {
12611
- this.setRangeSelectionInTable(cell, 0, this.editor);
12807
+ tabMove = true;
12808
+ this.setRangeSelectionInTable(cell, 0, this.editor, true /* selectAll */);
12612
12809
  lastCo.row = row;
12613
12810
  lastCo.col = col;
12614
12811
  break;
@@ -12626,18 +12823,23 @@ var SelectionPlugin = /** @class */ (function () {
12626
12823
  (_f = this.editor) === null || _f === void 0 ? void 0 : _f.announce({ defaultStrings: 'announceOnFocusLastCell' });
12627
12824
  }
12628
12825
  }
12629
- if (!collapsed && lastCo) {
12826
+ if (!collapsed && lastCo && !tabMove) {
12630
12827
  this.state.tableSelection = tableSel;
12631
12828
  this.updateTableSelection(lastCo);
12632
12829
  }
12633
12830
  }
12634
12831
  };
12635
- SelectionPlugin.prototype.setRangeSelectionInTable = function (cell, nodeOffset, editor) {
12636
- // Get deepest editable position in the cell
12637
- var _a = (0, normalizePos_1.normalizePos)(cell, nodeOffset), node = _a.node, offset = _a.offset;
12832
+ SelectionPlugin.prototype.setRangeSelectionInTable = function (cell, nodeOffset, editor, selectAll) {
12638
12833
  var range = editor.getDocument().createRange();
12639
- range.setStart(node, offset);
12640
- range.collapse(true /*toStart*/);
12834
+ if (selectAll) {
12835
+ range.selectNodeContents(cell);
12836
+ }
12837
+ else {
12838
+ // Get deepest editable position in the cell
12839
+ var _a = (0, normalizePos_1.normalizePos)(cell, nodeOffset), node = _a.node, offset = _a.offset;
12840
+ range.setStart(node, offset);
12841
+ range.collapse(true /* toStart */);
12842
+ }
12641
12843
  this.setDOMSelection({
12642
12844
  type: 'range',
12643
12845
  range: range,
@@ -14614,6 +14816,36 @@ exports.ChangeSource = {
14614
14816
  };
14615
14817
 
14616
14818
 
14819
+ /***/ }),
14820
+
14821
+ /***/ "./packages/roosterjs-content-model-dom/lib/constants/EmptySegmentFormat.ts":
14822
+ /*!**********************************************************************************!*\
14823
+ !*** ./packages/roosterjs-content-model-dom/lib/constants/EmptySegmentFormat.ts ***!
14824
+ \**********************************************************************************/
14825
+ /***/ ((__unused_webpack_module, exports) => {
14826
+
14827
+ "use strict";
14828
+
14829
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
14830
+ exports.EmptySegmentFormat = void 0;
14831
+ /**
14832
+ * Provide a default empty instance of segment format with all its properties
14833
+ */
14834
+ exports.EmptySegmentFormat = {
14835
+ backgroundColor: '',
14836
+ fontFamily: '',
14837
+ fontSize: '',
14838
+ fontWeight: '',
14839
+ italic: false,
14840
+ letterSpacing: '',
14841
+ lineHeight: '',
14842
+ strikethrough: false,
14843
+ superOrSubScriptSequence: '',
14844
+ textColor: '',
14845
+ underline: false,
14846
+ };
14847
+
14848
+
14617
14849
  /***/ }),
14618
14850
 
14619
14851
  /***/ "./packages/roosterjs-content-model-dom/lib/constants/NumberingListType.ts":
@@ -17339,16 +17571,14 @@ var normalizeRect_1 = __webpack_require__(/*! ../normalizeRect */ "./packages/ro
17339
17571
  * @param pos The input DOM insert point
17340
17572
  */
17341
17573
  function getDOMInsertPointRect(doc, pos) {
17342
- var _a;
17343
- var node = pos.node, offset = pos.offset;
17574
+ var _a, _b;
17344
17575
  var range = doc.createRange();
17345
- range.setStart(node, offset);
17346
- // 1) try to get rect using range.getBoundingClientRect()
17347
- var rect = (0, normalizeRect_1.normalizeRect)(range.getBoundingClientRect());
17348
- if (rect) {
17349
- return rect;
17350
- }
17351
- // 2) try to get rect using range.getClientRects
17576
+ return ((_b = (_a = tryGetRectFromPos(pos, range)) !== null && _a !== void 0 ? _a : tryGetRectFromPos((pos = normalizeInsertPoint(pos)), range)) !== null && _b !== void 0 ? _b : tryGetRectFromNode(pos.node) // 3. fallback to node rect using getBoundingClientRect
17577
+ );
17578
+ }
17579
+ exports.getDOMInsertPointRect = getDOMInsertPointRect;
17580
+ function normalizeInsertPoint(pos) {
17581
+ var node = pos.node, offset = pos.offset;
17352
17582
  while (node.lastChild) {
17353
17583
  if (offset == node.childNodes.length) {
17354
17584
  node = node.lastChild;
@@ -17359,32 +17589,26 @@ function getDOMInsertPointRect(doc, pos) {
17359
17589
  offset = 0;
17360
17590
  }
17361
17591
  }
17362
- var rects = range.getClientRects && range.getClientRects();
17363
- rect = rects && rects.length == 1 ? (0, normalizeRect_1.normalizeRect)(rects[0]) : null;
17592
+ return { node: node, offset: offset };
17593
+ }
17594
+ function tryGetRectFromPos(pos, range) {
17595
+ var node = pos.node, offset = pos.offset;
17596
+ range.setStart(node, offset);
17597
+ range.setEnd(node, offset);
17598
+ var rect = (0, normalizeRect_1.normalizeRect)(range.getBoundingClientRect());
17364
17599
  if (rect) {
17365
17600
  return rect;
17366
17601
  }
17367
- // 3) if node is text node, try inserting a SPAN and get the rect of SPAN for others
17368
- if ((0, isNodeOfType_1.isNodeOfType)(node, 'TEXT_NODE')) {
17369
- var span = node.ownerDocument.createElement('span');
17370
- span.textContent = '\u200b';
17371
- range.insertNode(span);
17372
- rect = (0, normalizeRect_1.normalizeRect)(span.getBoundingClientRect());
17373
- (_a = span.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(span);
17374
- if (rect) {
17375
- return rect;
17376
- }
17377
- }
17378
- // 4) try getBoundingClientRect on element
17379
- if ((0, isNodeOfType_1.isNodeOfType)(node, 'ELEMENT_NODE') && node.getBoundingClientRect) {
17380
- rect = (0, normalizeRect_1.normalizeRect)(node.getBoundingClientRect());
17381
- if (rect) {
17382
- return rect;
17383
- }
17602
+ else {
17603
+ var rects = range.getClientRects && range.getClientRects();
17604
+ return rects && rects.length == 1 ? (0, normalizeRect_1.normalizeRect)(rects[0]) : null;
17384
17605
  }
17385
- return null;
17386
17606
  }
17387
- exports.getDOMInsertPointRect = getDOMInsertPointRect;
17607
+ function tryGetRectFromNode(node) {
17608
+ return (0, isNodeOfType_1.isNodeOfType)(node, 'ELEMENT_NODE') && node.getBoundingClientRect
17609
+ ? (0, normalizeRect_1.normalizeRect)(node.getBoundingClientRect())
17610
+ : null;
17611
+ }
17388
17612
 
17389
17613
 
17390
17614
  /***/ }),
@@ -19804,7 +20028,7 @@ exports.shouldSetValue = shouldSetValue;
19804
20028
  Object.defineProperty(exports, "__esModule", ({ value: true }));
19805
20029
  exports.createEntity = exports.createGeneralBlock = exports.createGeneralSegment = exports.createParagraphDecorator = exports.createContentModelDocument = exports.createImage = exports.createText = exports.createTableCell = exports.createTable = exports.createSelectionMarker = exports.createParagraph = exports.createFormatContainer = exports.createListItem = exports.createBr = exports.normalizeRect = exports.isWhiteSpacePreserved = exports.reuseCachedElement = exports.findClosestBlockEntityContainer = exports.isBlockEntityContainer = exports.isEntityDelimiter = exports.addDelimiters = exports.generateEntityClassNames = exports.parseEntityFormat = exports.getAllEntityWrappers = exports.findClosestEntityWrapper = exports.isEntityElement = exports.unwrap = exports.wrap = exports.wrapAllChildNodes = exports.moveChildNodes = exports.toArray = exports.getObjectKeys = exports.isElementOfType = exports.isNodeOfType = exports.hasMetadata = exports.getMetadata = exports.updateMetadata = exports.buildSelectionMarker = exports.isBlockElement = exports.areSameFormats = exports.parseFormat = exports.getRegularSelectionOffsets = exports.tableProcessor = exports.entityProcessor = exports.processChildNode = exports.handleRegularSelection = exports.childProcessor = exports.contentModelToText = exports.contentModelToDom = exports.domToContentModel = void 0;
19806
20030
  exports.cacheGetEventData = exports.extractClipboardItems = exports.transformColor = exports.readFile = exports.parseTableCells = exports.normalizeText = exports.isSpace = exports.isPunctuation = exports.extractBorderValues = exports.combineBorderValue = exports.isCursorMovingKey = exports.isModifierKey = exports.isCharacterValue = exports.getDOMInsertPointRect = exports.getSelectionRootNode = exports.isBold = exports.createModelToDomConfig = exports.createModelToDomContextWithConfig = exports.createModelToDomContext = exports.createDomToModelConfig = exports.createDomToModelContextWithConfig = exports.createDomToModelContext = exports.defaultGenerateColorKey = exports.parseColor = exports.setColor = exports.getColor = exports.DeprecatedColors = exports.BorderKeys = exports.parseValueWithUnit = exports.getAutoListStyleType = exports.getOrderedListNumberStr = exports.setParagraphNotImplicit = exports.normalizeSingleSegment = exports.isEmpty = exports.addSegment = exports.unwrapBlock = exports.isGeneralSegment = exports.normalizeContentModel = exports.normalizeParagraph = exports.addTextSegment = exports.addLink = exports.addCode = exports.addBlock = exports.mutateSegment = exports.mutateSegments = exports.mutateBlock = exports.createTableRow = exports.createEmptyModel = exports.createListLevel = exports.createDivider = void 0;
19807
- exports.UnorderedListStyleMap = exports.OrderedListStyleMap = exports.TableBorderFormat = exports.NumberingListType = exports.BulletListType = exports.ChangeSource = exports.ListMetadataDefinition = exports.getListMetadata = exports.updateListMetadata = exports.getTableMetadata = exports.updateTableMetadata = exports.getTableCellMetadata = exports.updateTableCellMetadata = exports.getImageMetadata = exports.updateImageMetadata = exports.runEditSteps = exports.getClosestAncestorBlockGroupIndex = exports.getSegmentTextFormat = exports.getListStyleTypeFromString = exports.retrieveModelFormatState = exports.setTableCellBackgroundColor = exports.MIN_ALLOWED_TABLE_CELL_HEIGHT = exports.MIN_ALLOWED_TABLE_CELL_WIDTH = exports.normalizeTable = exports.setFirstColumnFormatBorders = exports.applyTableFormat = exports.deleteBlock = exports.deleteSegment = exports.deleteSelection = exports.mergeModel = exports.cloneModel = exports.setSelection = exports.hasSelectionInBlockGroup = exports.hasSelectionInSegment = exports.hasSelectionInBlock = exports.getSelectedCells = exports.getSelectedSegmentsAndParagraphs = exports.getSelectedSegments = exports.getSelectedParagraphs = exports.getOperationalBlocks = exports.getFirstSelectedTable = exports.getFirstSelectedListItem = exports.iterateSelections = exports.isBlockGroupOfType = void 0;
20031
+ exports.EmptySegmentFormat = exports.UnorderedListStyleMap = exports.OrderedListStyleMap = exports.TableBorderFormat = exports.NumberingListType = exports.BulletListType = exports.ChangeSource = exports.ListMetadataDefinition = exports.getListMetadata = exports.updateListMetadata = exports.getTableMetadata = exports.updateTableMetadata = exports.getTableCellMetadata = exports.updateTableCellMetadata = exports.getImageMetadata = exports.updateImageMetadata = exports.runEditSteps = exports.getClosestAncestorBlockGroupIndex = exports.getSegmentTextFormat = exports.getListStyleTypeFromString = exports.retrieveModelFormatState = exports.setTableCellBackgroundColor = exports.MIN_ALLOWED_TABLE_CELL_HEIGHT = exports.MIN_ALLOWED_TABLE_CELL_WIDTH = exports.normalizeTable = exports.setFirstColumnFormatBorders = exports.applyTableFormat = exports.deleteBlock = exports.deleteSegment = exports.deleteSelection = exports.mergeModel = exports.cloneModel = exports.setSelection = exports.hasSelectionInBlockGroup = exports.hasSelectionInSegment = exports.hasSelectionInBlock = exports.getSelectedCells = exports.getSelectedSegmentsAndParagraphs = exports.getSelectedSegments = exports.getSelectedParagraphs = exports.getOperationalBlocks = exports.getFirstSelectedTable = exports.getFirstSelectedListItem = exports.iterateSelections = exports.isBlockGroupOfType = void 0;
19808
20032
  var domToContentModel_1 = __webpack_require__(/*! ./domToModel/domToContentModel */ "./packages/roosterjs-content-model-dom/lib/domToModel/domToContentModel.ts");
19809
20033
  Object.defineProperty(exports, "domToContentModel", ({ enumerable: true, get: function () { return domToContentModel_1.domToContentModel; } }));
19810
20034
  var contentModelToDom_1 = __webpack_require__(/*! ./modelToDom/contentModelToDom */ "./packages/roosterjs-content-model-dom/lib/modelToDom/contentModelToDom.ts");
@@ -20052,6 +20276,8 @@ var OrderedListStyleMap_1 = __webpack_require__(/*! ./constants/OrderedListStyle
20052
20276
  Object.defineProperty(exports, "OrderedListStyleMap", ({ enumerable: true, get: function () { return OrderedListStyleMap_1.OrderedListStyleMap; } }));
20053
20277
  var UnorderedListStyleMap_1 = __webpack_require__(/*! ./constants/UnorderedListStyleMap */ "./packages/roosterjs-content-model-dom/lib/constants/UnorderedListStyleMap.ts");
20054
20278
  Object.defineProperty(exports, "UnorderedListStyleMap", ({ enumerable: true, get: function () { return UnorderedListStyleMap_1.UnorderedListStyleMap; } }));
20279
+ var EmptySegmentFormat_1 = __webpack_require__(/*! ./constants/EmptySegmentFormat */ "./packages/roosterjs-content-model-dom/lib/constants/EmptySegmentFormat.ts");
20280
+ Object.defineProperty(exports, "EmptySegmentFormat", ({ enumerable: true, get: function () { return EmptySegmentFormat_1.EmptySegmentFormat; } }));
20055
20281
 
20056
20282
 
20057
20283
  /***/ }),
@@ -22375,27 +22601,14 @@ var createParagraph_1 = __webpack_require__(/*! ../creators/createParagraph */ "
22375
22601
  var createSelectionMarker_1 = __webpack_require__(/*! ../creators/createSelectionMarker */ "./packages/roosterjs-content-model-dom/lib/modelApi/creators/createSelectionMarker.ts");
22376
22602
  var createTableCell_1 = __webpack_require__(/*! ../creators/createTableCell */ "./packages/roosterjs-content-model-dom/lib/modelApi/creators/createTableCell.ts");
22377
22603
  var deleteSelection_1 = __webpack_require__(/*! ./deleteSelection */ "./packages/roosterjs-content-model-dom/lib/modelApi/editing/deleteSelection.ts");
22604
+ var EmptySegmentFormat_1 = __webpack_require__(/*! ../../constants/EmptySegmentFormat */ "./packages/roosterjs-content-model-dom/lib/constants/EmptySegmentFormat.ts");
22378
22605
  var getClosestAncestorBlockGroupIndex_1 = __webpack_require__(/*! ./getClosestAncestorBlockGroupIndex */ "./packages/roosterjs-content-model-dom/lib/modelApi/editing/getClosestAncestorBlockGroupIndex.ts");
22379
22606
  var getObjectKeys_1 = __webpack_require__(/*! ../..//domUtils/getObjectKeys */ "./packages/roosterjs-content-model-dom/lib/domUtils/getObjectKeys.ts");
22380
22607
  var mutate_1 = __webpack_require__(/*! ../common/mutate */ "./packages/roosterjs-content-model-dom/lib/modelApi/common/mutate.ts");
22381
22608
  var normalizeContentModel_1 = __webpack_require__(/*! ../common/normalizeContentModel */ "./packages/roosterjs-content-model-dom/lib/modelApi/common/normalizeContentModel.ts");
22382
22609
  var normalizeTable_1 = __webpack_require__(/*! ./normalizeTable */ "./packages/roosterjs-content-model-dom/lib/modelApi/editing/normalizeTable.ts");
22383
22610
  var HeadingTags = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'];
22384
- // An object to provide keys of required properties of segment format, do NOT use any of its values
22385
- var RequiredEmptySegmentFormat = {
22386
- backgroundColor: null,
22387
- fontFamily: null,
22388
- fontSize: null,
22389
- fontWeight: null,
22390
- italic: null,
22391
- letterSpacing: null,
22392
- lineHeight: null,
22393
- strikethrough: null,
22394
- superOrSubScriptSequence: null,
22395
- textColor: null,
22396
- underline: null,
22397
- };
22398
- var KeysOfSegmentFormat = (0, getObjectKeys_1.getObjectKeys)(RequiredEmptySegmentFormat);
22611
+ var KeysOfSegmentFormat = (0, getObjectKeys_1.getObjectKeys)(EmptySegmentFormat_1.EmptySegmentFormat);
22399
22612
  /**
22400
22613
  * Merge source model into target mode
22401
22614
  * @param target Target Content Model that will merge content into
@@ -25689,8 +25902,7 @@ function removeUnnecessarySpan(root) {
25689
25902
  for (var child = root.firstChild; child;) {
25690
25903
  if ((0, isNodeOfType_1.isNodeOfType)(child, 'ELEMENT_NODE') &&
25691
25904
  child.tagName == 'SPAN' &&
25692
- child.attributes.length == 0 &&
25693
- !isImageSpan(child)) {
25905
+ child.attributes.length == 0) {
25694
25906
  var node = child;
25695
25907
  var refNode = child.nextSibling;
25696
25908
  child = child.nextSibling;
@@ -25707,11 +25919,6 @@ function removeUnnecessarySpan(root) {
25707
25919
  }
25708
25920
  }
25709
25921
  exports.removeUnnecessarySpan = removeUnnecessarySpan;
25710
- var isImageSpan = function (child) {
25711
- return ((0, isNodeOfType_1.isNodeOfType)(child.firstChild, 'ELEMENT_NODE') &&
25712
- child.firstChild.tagName == 'IMG' &&
25713
- child.firstChild == child.lastChild);
25714
- };
25715
25922
 
25716
25923
 
25717
25924
  /***/ }),
@@ -26121,7 +26328,7 @@ var getChangeSource = function (shouldList, shouldHyphen, shouldLink) {
26121
26328
 
26122
26329
  Object.defineProperty(exports, "__esModule", ({ value: true }));
26123
26330
  exports.transformHyphen = void 0;
26124
- var splitTextSegment_1 = __webpack_require__(/*! ../../pluginUtils/splitTextSegment */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/splitTextSegment.ts");
26331
+ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
26125
26332
  /**
26126
26333
  * @internal
26127
26334
  */
@@ -26130,7 +26337,7 @@ function transformHyphen(previousSegment, paragraph, context) {
26130
26337
  var dashes = segments[segments.length - 2];
26131
26338
  if (dashes === '--') {
26132
26339
  var textIndex = previousSegment.text.lastIndexOf('--');
26133
- var textSegment = (0, splitTextSegment_1.splitTextSegment)(previousSegment, paragraph, textIndex, textIndex + 2);
26340
+ var textSegment = (0, roosterjs_content_model_api_1.splitTextSegment)(previousSegment, paragraph, textIndex, textIndex + 2);
26134
26341
  textSegment.text = textSegment.text.replace('--', '—');
26135
26342
  context.canUndoByBackspace = true;
26136
26343
  return true;
@@ -26140,7 +26347,7 @@ function transformHyphen(previousSegment, paragraph, context) {
26140
26347
  var hasDashes = text && (text === null || text === void 0 ? void 0 : text.indexOf('--')) > -1;
26141
26348
  if (hasDashes && text.trim() !== '--') {
26142
26349
  var textIndex = previousSegment.text.indexOf(text);
26143
- var textSegment = (0, splitTextSegment_1.splitTextSegment)(previousSegment, paragraph, textIndex, textIndex + text.length - 1);
26350
+ var textSegment = (0, roosterjs_content_model_api_1.splitTextSegment)(previousSegment, paragraph, textIndex, textIndex + text.length - 1);
26144
26351
  var textLength = textSegment.text.length;
26145
26352
  if (textSegment.text[0] !== '-' && textSegment.text[textLength - 1] !== '-') {
26146
26353
  textSegment.text = textSegment.text.replace('--', '—');
@@ -26173,8 +26380,10 @@ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-mo
26173
26380
  */
26174
26381
  function createLink(editor) {
26175
26382
  var anchorNode = null;
26383
+ var links = [];
26176
26384
  (0, roosterjs_content_model_api_1.formatTextSegmentBeforeSelectionMarker)(editor, function (_model, linkSegment, _paragraph) {
26177
26385
  if (linkSegment.link) {
26386
+ links.push(linkSegment.link);
26178
26387
  return true;
26179
26388
  }
26180
26389
  var linkData = null;
@@ -26186,13 +26395,16 @@ function createLink(editor) {
26186
26395
  },
26187
26396
  dataset: {},
26188
26397
  });
26398
+ if (linkSegment.link) {
26399
+ links.push(linkSegment.link);
26400
+ }
26189
26401
  return true;
26190
26402
  }
26191
26403
  return false;
26192
26404
  }, {
26193
26405
  changeSource: roosterjs_content_model_dom_1.ChangeSource.AutoLink,
26194
- onNodeCreated: function (_modelElement, node) {
26195
- if (!anchorNode) {
26406
+ onNodeCreated: function (modelElement, node) {
26407
+ if (!anchorNode && links.indexOf(modelElement) >= 0) {
26196
26408
  anchorNode = node;
26197
26409
  }
26198
26410
  },
@@ -26215,7 +26427,6 @@ exports.createLink = createLink;
26215
26427
  Object.defineProperty(exports, "__esModule", ({ value: true }));
26216
26428
  exports.createLinkAfterSpace = void 0;
26217
26429
  var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
26218
- var splitTextSegment_1 = __webpack_require__(/*! ../../pluginUtils/splitTextSegment */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/splitTextSegment.ts");
26219
26430
  /**
26220
26431
  * @internal
26221
26432
  */
@@ -26224,7 +26435,7 @@ function createLinkAfterSpace(previousSegment, paragraph, context) {
26224
26435
  var url = link === null || link === void 0 ? void 0 : link.trim();
26225
26436
  var linkData = null;
26226
26437
  if (url && link && (linkData = (0, roosterjs_content_model_api_1.matchLink)(url))) {
26227
- var linkSegment = (0, splitTextSegment_1.splitTextSegment)(previousSegment, paragraph, previousSegment.text.length - link.trimLeft().length, previousSegment.text.trimRight().length);
26438
+ var linkSegment = (0, roosterjs_content_model_api_1.splitTextSegment)(previousSegment, paragraph, previousSegment.text.length - link.trimLeft().length, previousSegment.text.trimRight().length);
26228
26439
  linkSegment.link = {
26229
26440
  format: {
26230
26441
  href: linkData.normalizedUrl,
@@ -26359,7 +26570,7 @@ function getListTypeStyle(model, shouldSearchForBullet, shouldSearchForNumbering
26359
26570
  listMarkerSegment &&
26360
26571
  listMarkerSegment.segmentType == 'Text') {
26361
26572
  var listMarker = listMarkerSegment.text.trim();
26362
- var bulletType = bulletListType[listMarker];
26573
+ var bulletType = bulletListType.get(listMarker);
26363
26574
  if (bulletType && shouldSearchForBullet) {
26364
26575
  return { listType: 'UL', styleType: bulletType };
26365
26576
  }
@@ -26410,16 +26621,16 @@ var getPreviousListStyle = function (list) {
26410
26621
  return (_a = (0, roosterjs_content_model_dom_1.updateListMetadata)(list.levels[0])) === null || _a === void 0 ? void 0 : _a.orderedStyleType;
26411
26622
  }
26412
26623
  };
26413
- var bulletListType = {
26414
- '*': roosterjs_content_model_dom_1.BulletListType.Disc,
26415
- '-': roosterjs_content_model_dom_1.BulletListType.Dash,
26416
- '--': roosterjs_content_model_dom_1.BulletListType.Square,
26417
- '->': roosterjs_content_model_dom_1.BulletListType.LongArrow,
26418
- '-->': roosterjs_content_model_dom_1.BulletListType.DoubleLongArrow,
26419
- '=>': roosterjs_content_model_dom_1.BulletListType.UnfilledArrow,
26420
- '>': roosterjs_content_model_dom_1.BulletListType.ShortArrow,
26421
- '—': roosterjs_content_model_dom_1.BulletListType.Hyphen,
26422
- };
26624
+ var bulletListType = new Map([
26625
+ ['*', roosterjs_content_model_dom_1.BulletListType.Disc],
26626
+ ['-', roosterjs_content_model_dom_1.BulletListType.Dash],
26627
+ ['--', roosterjs_content_model_dom_1.BulletListType.Square],
26628
+ ['->', roosterjs_content_model_dom_1.BulletListType.LongArrow],
26629
+ ['-->', roosterjs_content_model_dom_1.BulletListType.DoubleLongArrow],
26630
+ ['=>', roosterjs_content_model_dom_1.BulletListType.UnfilledArrow],
26631
+ ['>', roosterjs_content_model_dom_1.BulletListType.ShortArrow],
26632
+ ['—', roosterjs_content_model_dom_1.BulletListType.Hyphen],
26633
+ ]);
26423
26634
  var isNewList = function (listMarker) {
26424
26635
  var marker = listMarker.replace(/[^\w\s]/g, '');
26425
26636
  var pattern = /^[1aAiI]$/;
@@ -26650,23 +26861,24 @@ var triggerList = function (model, listType, styleType, index) {
26650
26861
 
26651
26862
  Object.defineProperty(exports, "__esModule", ({ value: true }));
26652
26863
  exports.transformFraction = void 0;
26653
- var splitTextSegment_1 = __webpack_require__(/*! ../../pluginUtils/splitTextSegment */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/splitTextSegment.ts");
26654
- var FRACTIONS = {
26655
- '1/2': '½',
26656
- '1/4': '¼',
26657
- '3/4': '¾',
26658
- };
26864
+ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
26865
+ var FRACTIONS = new Map([
26866
+ ['1/2', '½'],
26867
+ ['1/4', '¼'],
26868
+ ['3/4', '¾'],
26869
+ ]);
26659
26870
  /**
26660
26871
  * @internal
26661
26872
  */
26662
26873
  function transformFraction(previousSegment, paragraph, context) {
26663
26874
  var _a;
26664
26875
  var fraction = (_a = previousSegment.text.split(' ').pop()) === null || _a === void 0 ? void 0 : _a.trim();
26665
- if (fraction && FRACTIONS[fraction]) {
26876
+ var text = fraction ? FRACTIONS.get(fraction) : undefined;
26877
+ if (fraction && text) {
26666
26878
  var textLength = previousSegment.text.length - 1;
26667
26879
  var textIndex = textLength - fraction.length;
26668
- var textSegment = (0, splitTextSegment_1.splitTextSegment)(previousSegment, paragraph, textIndex, textLength);
26669
- textSegment.text = FRACTIONS[fraction];
26880
+ var textSegment = (0, roosterjs_content_model_api_1.splitTextSegment)(previousSegment, paragraph, textIndex, textLength);
26881
+ textSegment.text = text;
26670
26882
  context.canUndoByBackspace = true;
26671
26883
  return true;
26672
26884
  }
@@ -26687,7 +26899,7 @@ exports.transformFraction = transformFraction;
26687
26899
 
26688
26900
  Object.defineProperty(exports, "__esModule", ({ value: true }));
26689
26901
  exports.transformOrdinals = void 0;
26690
- var splitTextSegment_1 = __webpack_require__(/*! ../../pluginUtils/splitTextSegment */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/splitTextSegment.ts");
26902
+ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
26691
26903
  var getOrdinal = function (value) {
26692
26904
  var ORDINALS = {
26693
26905
  1: 'st',
@@ -26706,7 +26918,7 @@ function transformOrdinals(previousSegment, paragraph, context) {
26706
26918
  var ordinal = value.substring(value.length - 2);
26707
26919
  var ordinalValue = parseInt(value);
26708
26920
  if (ordinalValue && getOrdinal(ordinalValue) === ordinal) {
26709
- var ordinalSegment = (0, splitTextSegment_1.splitTextSegment)(previousSegment, paragraph, previousSegment.text.length - 3, previousSegment.text.length - 1);
26921
+ var ordinalSegment = (0, roosterjs_content_model_api_1.splitTextSegment)(previousSegment, paragraph, previousSegment.text.length - 3, previousSegment.text.length - 1);
26710
26922
  ordinalSegment.format.superOrSubScriptSequence = 'super';
26711
26923
  context.canUndoByBackspace = true;
26712
26924
  return true;
@@ -26927,6 +27139,9 @@ var keyboardTab_1 = __webpack_require__(/*! ./keyboardTab */ "./packages/rooster
26927
27139
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
26928
27140
  var BACKSPACE_KEY = 8;
26929
27141
  var DELETE_KEY = 46;
27142
+ var DefaultOptions = {
27143
+ handleTabKey: true,
27144
+ };
26930
27145
  /**
26931
27146
  * Edit plugins helps editor to do editing operation on top of content model.
26932
27147
  * This includes:
@@ -26935,7 +27150,13 @@ var DELETE_KEY = 46;
26935
27150
  * 3. Tab Key
26936
27151
  */
26937
27152
  var EditPlugin = /** @class */ (function () {
26938
- function EditPlugin() {
27153
+ /**
27154
+ * @param options An optional parameter that takes in an object of type EditOptions, which includes the following properties:
27155
+ * handleTabKey: A boolean that enables or disables Tab key handling. Defaults to true.
27156
+ */
27157
+ function EditPlugin(options) {
27158
+ if (options === void 0) { options = DefaultOptions; }
27159
+ this.options = options;
26939
27160
  this.editor = null;
26940
27161
  this.disposer = null;
26941
27162
  this.shouldHandleNextInputEvent = false;
@@ -27008,6 +27229,7 @@ var EditPlugin = /** @class */ (function () {
27008
27229
  */
27009
27230
  EditPlugin.prototype.willHandleEventExclusively = function (event) {
27010
27231
  if (this.editor &&
27232
+ this.options.handleTabKey &&
27011
27233
  event.eventType == 'keyDown' &&
27012
27234
  event.rawEvent.key == 'Tab' &&
27013
27235
  !event.rawEvent.shiftKey) {
@@ -27049,7 +27271,9 @@ var EditPlugin = /** @class */ (function () {
27049
27271
  }
27050
27272
  break;
27051
27273
  case 'Tab':
27052
- (0, keyboardTab_1.keyboardTab)(editor, rawEvent);
27274
+ if (this.options.handleTabKey) {
27275
+ (0, keyboardTab_1.keyboardTab)(editor, rawEvent);
27276
+ }
27053
27277
  break;
27054
27278
  case 'Unidentified':
27055
27279
  if (editor.getEnvironment().isAndroid) {
@@ -28708,8 +28932,10 @@ var canRegenerateImage_1 = __webpack_require__(/*! ./utils/canRegenerateImage */
28708
28932
  var imageEditUtils_1 = __webpack_require__(/*! ./utils/imageEditUtils */ "./packages/roosterjs-content-model-plugins/lib/imageEdit/utils/imageEditUtils.ts");
28709
28933
  var createImageWrapper_1 = __webpack_require__(/*! ./utils/createImageWrapper */ "./packages/roosterjs-content-model-plugins/lib/imageEdit/utils/createImageWrapper.ts");
28710
28934
  var cropperContext_1 = __webpack_require__(/*! ./Cropper/cropperContext */ "./packages/roosterjs-content-model-plugins/lib/imageEdit/Cropper/cropperContext.ts");
28935
+ var findEditingImage_1 = __webpack_require__(/*! ./utils/findEditingImage */ "./packages/roosterjs-content-model-plugins/lib/imageEdit/utils/findEditingImage.ts");
28711
28936
  var getDropAndDragHelpers_1 = __webpack_require__(/*! ./utils/getDropAndDragHelpers */ "./packages/roosterjs-content-model-plugins/lib/imageEdit/utils/getDropAndDragHelpers.ts");
28712
28937
  var getHTMLImageOptions_1 = __webpack_require__(/*! ./utils/getHTMLImageOptions */ "./packages/roosterjs-content-model-plugins/lib/imageEdit/utils/getHTMLImageOptions.ts");
28938
+ var getSelectedImage_1 = __webpack_require__(/*! ./utils/getSelectedImage */ "./packages/roosterjs-content-model-plugins/lib/imageEdit/utils/getSelectedImage.ts");
28713
28939
  var updateImageEditInfo_1 = __webpack_require__(/*! ./utils/updateImageEditInfo */ "./packages/roosterjs-content-model-plugins/lib/imageEdit/utils/updateImageEditInfo.ts");
28714
28940
  var ImageEditElementClass_1 = __webpack_require__(/*! ./types/ImageEditElementClass */ "./packages/roosterjs-content-model-plugins/lib/imageEdit/types/ImageEditElementClass.ts");
28715
28941
  var resizerContext_1 = __webpack_require__(/*! ./Resizer/resizerContext */ "./packages/roosterjs-content-model-plugins/lib/imageEdit/Resizer/resizerContext.ts");
@@ -28724,9 +28950,9 @@ var DefaultOptions = {
28724
28950
  preserveRatio: true,
28725
28951
  disableRotate: false,
28726
28952
  disableSideResize: false,
28727
- onSelectState: 'resize',
28953
+ onSelectState: ['resize', 'rotate'],
28728
28954
  };
28729
- var IMAGE_EDIT_CHANGE_SOURCE = 'ImageEdit';
28955
+ var MouseRightButton = 2;
28730
28956
  /**
28731
28957
  * ImageEdit plugin handles the following image editing features:
28732
28958
  * - Resize image
@@ -28754,6 +28980,8 @@ var ImageEditPlugin = /** @class */ (function () {
28754
28980
  this.croppers = [];
28755
28981
  this.zoomScale = 1;
28756
28982
  this.disposer = null;
28983
+ //EXPOSED FOR TEST ONLY
28984
+ this.isEditing = false;
28757
28985
  }
28758
28986
  /**
28759
28987
  * Get name of this plugin
@@ -28773,7 +29001,9 @@ var ImageEditPlugin = /** @class */ (function () {
28773
29001
  this.disposer = editor.attachDomEvent({
28774
29002
  blur: {
28775
29003
  beforeDispatch: function () {
28776
- _this.formatImageWithContentModel(editor, true /* shouldSelectImage */, true /* shouldSelectAsImageSelection*/);
29004
+ if (_this.editor) {
29005
+ _this.applyFormatWithContentModel(_this.editor, _this.isCropMode, true /* shouldSelectImage */);
29006
+ }
28777
29007
  },
28778
29008
  },
28779
29009
  });
@@ -28785,6 +29015,7 @@ var ImageEditPlugin = /** @class */ (function () {
28785
29015
  */
28786
29016
  ImageEditPlugin.prototype.dispose = function () {
28787
29017
  this.editor = null;
29018
+ this.isEditing = false;
28788
29019
  this.cleanInfo();
28789
29020
  if (this.disposer) {
28790
29021
  this.disposer();
@@ -28797,16 +29028,145 @@ var ImageEditPlugin = /** @class */ (function () {
28797
29028
  * exclusively by another plugin.
28798
29029
  * @param event The event to handle:
28799
29030
  */
28800
- ImageEditPlugin.prototype.onPluginEvent = function (_event) { };
28801
- ImageEditPlugin.prototype.startEditing = function (editor, image, apiOperation) {
28802
- var imageSpan = image.parentElement;
28803
- if (!imageSpan || (imageSpan && !(0, roosterjs_content_model_dom_1.isElementOfType)(imageSpan, 'span'))) {
29031
+ ImageEditPlugin.prototype.onPluginEvent = function (event) {
29032
+ if (!this.editor) {
28804
29033
  return;
28805
29034
  }
28806
- this.imageEditInfo = (0, updateImageEditInfo_1.getSelectedImageMetadata)(editor, image);
29035
+ switch (event.eventType) {
29036
+ case 'mouseUp':
29037
+ this.mouseUpHandler(this.editor, event);
29038
+ break;
29039
+ case 'keyDown':
29040
+ this.keyDownHandler(this.editor, event);
29041
+ break;
29042
+ }
29043
+ };
29044
+ ImageEditPlugin.prototype.isImageSelection = function (target) {
29045
+ return ((0, roosterjs_content_model_dom_1.isNodeOfType)(target, 'ELEMENT_NODE') &&
29046
+ ((0, roosterjs_content_model_dom_1.isElementOfType)(target, 'img') ||
29047
+ !!((0, roosterjs_content_model_dom_1.isElementOfType)(target, 'span') &&
29048
+ target.firstElementChild &&
29049
+ (0, roosterjs_content_model_dom_1.isNodeOfType)(target.firstElementChild, 'ELEMENT_NODE') &&
29050
+ (0, roosterjs_content_model_dom_1.isElementOfType)(target.firstElementChild, 'img'))));
29051
+ };
29052
+ ImageEditPlugin.prototype.mouseUpHandler = function (editor, event) {
29053
+ var selection = editor.getDOMSelection();
29054
+ if ((selection && selection.type == 'image') || this.isEditing) {
29055
+ var shouldSelectImage = this.isImageSelection(event.rawEvent.target) &&
29056
+ event.rawEvent.button === MouseRightButton;
29057
+ this.applyFormatWithContentModel(editor, this.isCropMode, shouldSelectImage);
29058
+ }
29059
+ };
29060
+ //Sometimes the cursor can be inside the editing image and inside shadow dom, then the cursor need to moved out of shadow dom
29061
+ ImageEditPlugin.prototype.selectBeforeEditingImage = function (editor, element) {
29062
+ var parent = element.parentNode;
29063
+ if (parent && (0, roosterjs_content_model_dom_1.isNodeOfType)(parent, 'ELEMENT_NODE') && parent.shadowRoot) {
29064
+ element = parent;
29065
+ parent = parent.parentNode;
29066
+ }
29067
+ var index = parent && (0, roosterjs_content_model_dom_1.toArray)(parent.childNodes).indexOf(element);
29068
+ if (index !== null && index >= 0 && parent) {
29069
+ var doc = editor.getDocument();
29070
+ var range = doc.createRange();
29071
+ range.setStart(parent, index);
29072
+ range.collapse();
29073
+ editor.setDOMSelection({
29074
+ type: 'range',
29075
+ range: range,
29076
+ isReverted: false,
29077
+ });
29078
+ }
29079
+ };
29080
+ ImageEditPlugin.prototype.keyDownHandler = function (editor, event) {
29081
+ if (this.isEditing) {
29082
+ if (event.rawEvent.key === 'Escape') {
29083
+ this.removeImageWrapper();
29084
+ }
29085
+ else {
29086
+ var selection = editor.getDOMSelection();
29087
+ var isImageSelection = (selection === null || selection === void 0 ? void 0 : selection.type) == 'image';
29088
+ if (isImageSelection) {
29089
+ this.selectBeforeEditingImage(editor, selection.image);
29090
+ }
29091
+ this.applyFormatWithContentModel(editor, this.isCropMode, ((0, roosterjs_content_model_dom_1.isModifierKey)(event.rawEvent) || event.rawEvent.shiftKey) && isImageSelection //if it's a modifier key over a image, the image should select the image
29092
+ );
29093
+ }
29094
+ }
29095
+ };
29096
+ ImageEditPlugin.prototype.applyFormatWithContentModel = function (editor, isCropMode, shouldSelectImage, isApiOperation) {
29097
+ var _this = this;
29098
+ var editingImageModel;
29099
+ var selection = editor.getDOMSelection();
29100
+ editor.formatContentModel(function (model) {
29101
+ var editingImage = (0, getSelectedImage_1.getSelectedImage)(model);
29102
+ var previousSelectedImage = isApiOperation
29103
+ ? editingImage
29104
+ : (0, findEditingImage_1.findEditingImage)(model);
29105
+ var result = false;
29106
+ if (shouldSelectImage ||
29107
+ (previousSelectedImage === null || previousSelectedImage === void 0 ? void 0 : previousSelectedImage.image) != (editingImage === null || editingImage === void 0 ? void 0 : editingImage.image) ||
29108
+ (previousSelectedImage === null || previousSelectedImage === void 0 ? void 0 : previousSelectedImage.image.dataset.isEditing) ||
29109
+ isApiOperation) {
29110
+ var _a = _this, lastSrc_1 = _a.lastSrc, selectedImage_1 = _a.selectedImage, imageEditInfo_1 = _a.imageEditInfo, clonedImage_1 = _a.clonedImage;
29111
+ if ((_this.isEditing || isApiOperation) &&
29112
+ previousSelectedImage &&
29113
+ lastSrc_1 &&
29114
+ selectedImage_1 &&
29115
+ imageEditInfo_1 &&
29116
+ clonedImage_1) {
29117
+ (0, roosterjs_content_model_dom_1.mutateSegment)(previousSelectedImage.paragraph, previousSelectedImage.image, function (image) {
29118
+ (0, applyChange_1.applyChange)(editor, selectedImage_1, image, imageEditInfo_1, lastSrc_1, _this.wasImageResized || _this.isCropMode, clonedImage_1);
29119
+ delete image.dataset.isEditing;
29120
+ image.isSelected = shouldSelectImage;
29121
+ image.isSelectedAsImageSelection = shouldSelectImage;
29122
+ });
29123
+ _this.cleanInfo();
29124
+ result = true;
29125
+ }
29126
+ _this.isEditing = false;
29127
+ _this.isCropMode = false;
29128
+ if (editingImage &&
29129
+ (selection === null || selection === void 0 ? void 0 : selection.type) == 'image' &&
29130
+ !shouldSelectImage &&
29131
+ !isApiOperation) {
29132
+ _this.isEditing = true;
29133
+ _this.isCropMode = isCropMode;
29134
+ (0, roosterjs_content_model_dom_1.mutateSegment)(editingImage.paragraph, editingImage.image, function (image) {
29135
+ editingImageModel = image;
29136
+ _this.imageEditInfo = (0, updateImageEditInfo_1.updateImageEditInfo)(image, selection.image);
29137
+ image.dataset.isEditing = 'true';
29138
+ });
29139
+ result = true;
29140
+ }
29141
+ }
29142
+ return result;
29143
+ }, {
29144
+ onNodeCreated: function (model, node) {
29145
+ if (!isApiOperation &&
29146
+ editingImageModel &&
29147
+ editingImageModel == model &&
29148
+ editingImageModel.dataset.isEditing &&
29149
+ (0, roosterjs_content_model_dom_1.isNodeOfType)(node, 'ELEMENT_NODE') &&
29150
+ (0, roosterjs_content_model_dom_1.isElementOfType)(node, 'img')) {
29151
+ if (isCropMode) {
29152
+ _this.startCropMode(editor, node);
29153
+ }
29154
+ else {
29155
+ _this.startRotateAndResize(editor, node);
29156
+ }
29157
+ }
29158
+ },
29159
+ }, {
29160
+ tryGetFromCache: true,
29161
+ });
29162
+ };
29163
+ ImageEditPlugin.prototype.startEditing = function (editor, image, apiOperation) {
29164
+ if (!this.imageEditInfo) {
29165
+ this.imageEditInfo = (0, updateImageEditInfo_1.getSelectedImageMetadata)(editor, image);
29166
+ }
28807
29167
  this.lastSrc = image.getAttribute('src');
28808
29168
  this.imageHTMLOptions = (0, getHTMLImageOptions_1.getHTMLImageOptions)(editor, this.options, this.imageEditInfo);
28809
- var _a = (0, createImageWrapper_1.createImageWrapper)(editor, image, imageSpan, this.options, this.imageEditInfo, this.imageHTMLOptions, apiOperation || this.options.onSelectState), resizers = _a.resizers, rotators = _a.rotators, wrapper = _a.wrapper, shadowSpan = _a.shadowSpan, imageClone = _a.imageClone, croppers = _a.croppers;
29169
+ var _a = (0, createImageWrapper_1.createImageWrapper)(editor, image, this.options, this.imageEditInfo, this.imageHTMLOptions, apiOperation), resizers = _a.resizers, rotators = _a.rotators, wrapper = _a.wrapper, shadowSpan = _a.shadowSpan, imageClone = _a.imageClone, croppers = _a.croppers;
28810
29170
  this.shadowSpan = shadowSpan;
28811
29171
  this.selectedImage = image;
28812
29172
  this.wrapper = wrapper;
@@ -28820,34 +29180,33 @@ var ImageEditPlugin = /** @class */ (function () {
28820
29180
  "span:has(>img#" + this.selectedImage.id + ")",
28821
29181
  ]);
28822
29182
  };
28823
- ImageEditPlugin.prototype.startRotateAndResize = function (editor, image, apiOperation) {
29183
+ ImageEditPlugin.prototype.startRotateAndResize = function (editor, image) {
28824
29184
  var _this = this;
28825
29185
  var _a;
28826
- if (this.wrapper && this.selectedImage && this.shadowSpan) {
28827
- this.removeImageWrapper();
28828
- }
28829
- this.startEditing(editor, image, apiOperation);
28830
- if (this.selectedImage && this.imageEditInfo && this.wrapper && this.clonedImage) {
28831
- 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 () {
28832
- if (_this.imageEditInfo &&
28833
- _this.selectedImage &&
28834
- _this.wrapper &&
28835
- _this.clonedImage) {
28836
- (0, updateWrapper_1.updateWrapper)(_this.imageEditInfo, _this.options, _this.selectedImage, _this.clonedImage, _this.wrapper, _this.resizers);
28837
- _this.wasImageResized = true;
28838
- }
28839
- }, 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 () {
28840
- var _a;
28841
- if (_this.imageEditInfo &&
28842
- _this.selectedImage &&
28843
- _this.wrapper &&
28844
- _this.clonedImage) {
28845
- (0, updateWrapper_1.updateWrapper)(_this.imageEditInfo, _this.options, _this.selectedImage, _this.clonedImage, _this.wrapper, _this.rotators);
28846
- _this.updateRotateHandleState(editor, _this.selectedImage, _this.wrapper, _this.rotators, (_a = _this.imageEditInfo) === null || _a === void 0 ? void 0 : _a.angleRad);
28847
- }
28848
- }, this.zoomScale)), false);
28849
- (0, updateWrapper_1.updateWrapper)(this.imageEditInfo, this.options, this.selectedImage, this.clonedImage, this.wrapper, this.resizers);
28850
- this.updateRotateHandleState(editor, this.selectedImage, this.wrapper, this.rotators, (_a = this.imageEditInfo) === null || _a === void 0 ? void 0 : _a.angleRad);
29186
+ if (this.imageEditInfo) {
29187
+ this.startEditing(editor, image, ['resize', 'rotate']);
29188
+ if (this.selectedImage && this.imageEditInfo && this.wrapper && this.clonedImage) {
29189
+ this.dndHelpers = (0, tslib_1.__spreadArray)((0, tslib_1.__spreadArray)([], (0, tslib_1.__read)((0, getDropAndDragHelpers_1.getDropAndDragHelpers)(this.wrapper, this.imageEditInfo, this.options, ImageEditElementClass_1.ImageEditElementClass.ResizeHandle, resizerContext_1.Resizer, function () {
29190
+ if (_this.imageEditInfo &&
29191
+ _this.selectedImage &&
29192
+ _this.wrapper &&
29193
+ _this.clonedImage) {
29194
+ (0, updateWrapper_1.updateWrapper)(_this.imageEditInfo, _this.options, _this.selectedImage, _this.clonedImage, _this.wrapper, _this.resizers);
29195
+ _this.wasImageResized = true;
29196
+ }
29197
+ }, this.zoomScale)), false), (0, tslib_1.__read)((0, getDropAndDragHelpers_1.getDropAndDragHelpers)(this.wrapper, this.imageEditInfo, this.options, ImageEditElementClass_1.ImageEditElementClass.RotateHandle, rotatorContext_1.Rotator, function () {
29198
+ var _a;
29199
+ if (_this.imageEditInfo &&
29200
+ _this.selectedImage &&
29201
+ _this.wrapper &&
29202
+ _this.clonedImage) {
29203
+ (0, updateWrapper_1.updateWrapper)(_this.imageEditInfo, _this.options, _this.selectedImage, _this.clonedImage, _this.wrapper);
29204
+ _this.updateRotateHandleState(editor, _this.selectedImage, _this.wrapper, _this.rotators, (_a = _this.imageEditInfo) === null || _a === void 0 ? void 0 : _a.angleRad);
29205
+ }
29206
+ }, this.zoomScale)), false);
29207
+ (0, updateWrapper_1.updateWrapper)(this.imageEditInfo, this.options, this.selectedImage, this.clonedImage, this.wrapper, this.resizers);
29208
+ this.updateRotateHandleState(editor, this.selectedImage, this.wrapper, this.rotators, (_a = this.imageEditInfo) === null || _a === void 0 ? void 0 : _a.angleRad);
29209
+ }
28851
29210
  }
28852
29211
  };
28853
29212
  ImageEditPlugin.prototype.updateRotateHandleState = function (editor, image, wrapper, rotators, angleRad) {
@@ -28863,49 +29222,52 @@ var ImageEditPlugin = /** @class */ (function () {
28863
29222
  }
28864
29223
  };
28865
29224
  ImageEditPlugin.prototype.isOperationAllowed = function (operation) {
28866
- return operation === 'resize' || operation === 'rotate' || operation === 'flip';
29225
+ return (operation === 'resize' ||
29226
+ operation === 'rotate' ||
29227
+ operation === 'flip' ||
29228
+ operation === 'crop');
28867
29229
  };
28868
29230
  ImageEditPlugin.prototype.canRegenerateImage = function (image) {
28869
29231
  return (0, canRegenerateImage_1.canRegenerateImage)(image);
28870
29232
  };
28871
- ImageEditPlugin.prototype.cropImage = function () {
29233
+ ImageEditPlugin.prototype.startCropMode = function (editor, image) {
28872
29234
  var _this = this;
28873
- var _a, _b;
28874
- var selection = (_a = this.editor) === null || _a === void 0 ? void 0 : _a.getDOMSelection();
28875
- if (!this.editor || !selection || selection.type !== 'image') {
29235
+ if (this.imageEditInfo) {
29236
+ this.startEditing(editor, image, ['crop']);
29237
+ if (this.imageEditInfo && this.selectedImage && this.wrapper && this.clonedImage) {
29238
+ this.dndHelpers = (0, tslib_1.__spreadArray)([], (0, tslib_1.__read)((0, getDropAndDragHelpers_1.getDropAndDragHelpers)(this.wrapper, this.imageEditInfo, this.options, ImageEditElementClass_1.ImageEditElementClass.CropHandle, cropperContext_1.Cropper, function () {
29239
+ if (_this.imageEditInfo &&
29240
+ _this.selectedImage &&
29241
+ _this.wrapper &&
29242
+ _this.clonedImage) {
29243
+ (0, updateWrapper_1.updateWrapper)(_this.imageEditInfo, _this.options, _this.selectedImage, _this.clonedImage, _this.wrapper, undefined, _this.croppers);
29244
+ _this.isCropMode = true;
29245
+ }
29246
+ }, this.zoomScale)), false);
29247
+ (0, updateWrapper_1.updateWrapper)(this.imageEditInfo, this.options, this.selectedImage, this.clonedImage, this.wrapper, undefined, this.croppers);
29248
+ }
29249
+ }
29250
+ };
29251
+ ImageEditPlugin.prototype.cropImage = function () {
29252
+ if (!this.editor) {
28876
29253
  return;
28877
29254
  }
28878
- var image = selection.image;
28879
- if (this.wrapper && this.selectedImage && this.shadowSpan) {
28880
- image = (_b = this.removeImageWrapper()) !== null && _b !== void 0 ? _b : image;
29255
+ if (!this.editor.getEnvironment().isSafari) {
29256
+ this.editor.focus(); // Safari will keep the selection when click crop, then the focus() call should not be called
28881
29257
  }
28882
- this.startEditing(this.editor, image, 'crop');
28883
- if (!this.selectedImage || !this.imageEditInfo || !this.wrapper || !this.clonedImage) {
28884
- return;
29258
+ var selection = this.editor.getDOMSelection();
29259
+ if ((selection === null || selection === void 0 ? void 0 : selection.type) == 'image') {
29260
+ this.applyFormatWithContentModel(this.editor, true /* isCropMode */, false /* shouldSelectImage */);
28885
29261
  }
28886
- 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 () {
28887
- if (_this.imageEditInfo &&
28888
- _this.selectedImage &&
28889
- _this.wrapper &&
28890
- _this.clonedImage) {
28891
- (0, updateWrapper_1.updateWrapper)(_this.imageEditInfo, _this.options, _this.selectedImage, _this.clonedImage, _this.wrapper, undefined, _this.croppers);
28892
- _this.isCropMode = true;
28893
- }
28894
- }, this.zoomScale)), false);
28895
- (0, updateWrapper_1.updateWrapper)(this.imageEditInfo, this.options, this.selectedImage, this.clonedImage, this.wrapper, undefined, this.croppers);
28896
29262
  };
28897
29263
  ImageEditPlugin.prototype.editImage = function (editor, image, apiOperation, operation) {
28898
- var _a;
28899
- if (this.wrapper && this.selectedImage && this.shadowSpan) {
28900
- image = (_a = this.removeImageWrapper()) !== null && _a !== void 0 ? _a : image;
28901
- }
28902
29264
  this.startEditing(editor, image, apiOperation);
28903
29265
  if (!this.selectedImage || !this.imageEditInfo || !this.wrapper || !this.clonedImage) {
28904
29266
  return;
28905
29267
  }
28906
29268
  operation(this.imageEditInfo);
28907
29269
  (0, updateWrapper_1.updateWrapper)(this.imageEditInfo, this.options, this.selectedImage, this.clonedImage, this.wrapper);
28908
- this.formatImageWithContentModel(editor, true /* shouldSelect*/, true /* shouldSelectAsImageSelection*/);
29270
+ this.applyFormatWithContentModel(editor, false /* isCrop */, true /* shouldSelect*/, true /* isApiOperation */);
28909
29271
  };
28910
29272
  ImageEditPlugin.prototype.cleanInfo = function () {
28911
29273
  var _a;
@@ -28925,42 +29287,6 @@ var ImageEditPlugin = /** @class */ (function () {
28925
29287
  this.rotators = [];
28926
29288
  this.croppers = [];
28927
29289
  };
28928
- ImageEditPlugin.prototype.formatImageWithContentModel = function (editor, shouldSelectImage, shouldSelectAsImageSelection) {
28929
- var _this = this;
28930
- if (this.lastSrc &&
28931
- this.selectedImage &&
28932
- this.imageEditInfo &&
28933
- this.clonedImage &&
28934
- this.shadowSpan) {
28935
- editor.formatContentModel(function (model) {
28936
- var selectedSegmentsAndParagraphs = (0, roosterjs_content_model_dom_1.getSelectedSegmentsAndParagraphs)(model, false);
28937
- if (!selectedSegmentsAndParagraphs[0]) {
28938
- return false;
28939
- }
28940
- var segment = selectedSegmentsAndParagraphs[0][0];
28941
- var paragraph = selectedSegmentsAndParagraphs[0][1];
28942
- if (paragraph && segment.segmentType == 'Image') {
28943
- (0, roosterjs_content_model_dom_1.mutateSegment)(paragraph, segment, function (image) {
28944
- if (_this.lastSrc &&
28945
- _this.selectedImage &&
28946
- _this.imageEditInfo &&
28947
- _this.clonedImage) {
28948
- (0, applyChange_1.applyChange)(editor, _this.selectedImage, image, _this.imageEditInfo, _this.lastSrc, _this.wasImageResized || _this.isCropMode, _this.clonedImage);
28949
- image.isSelected = shouldSelectImage;
28950
- image.isSelectedAsImageSelection = shouldSelectAsImageSelection;
28951
- }
28952
- });
28953
- return true;
28954
- }
28955
- return false;
28956
- }, {
28957
- changeSource: IMAGE_EDIT_CHANGE_SOURCE,
28958
- onNodeCreated: function () {
28959
- _this.cleanInfo();
28960
- },
28961
- });
28962
- }
28963
- };
28964
29290
  ImageEditPlugin.prototype.removeImageWrapper = function () {
28965
29291
  var image = null;
28966
29292
  if (this.shadowSpan && this.shadowSpan.parentElement) {
@@ -28983,7 +29309,7 @@ var ImageEditPlugin = /** @class */ (function () {
28983
29309
  }
28984
29310
  var image = selection.image;
28985
29311
  if (this.editor) {
28986
- this.editImage(this.editor, image, 'flip', function (imageEditInfo) {
29312
+ this.editImage(this.editor, image, ['flip'], function (imageEditInfo) {
28987
29313
  var angleRad = imageEditInfo.angleRad || 0;
28988
29314
  var isInVerticalPostion = (angleRad >= Math.PI / 2 && angleRad < (3 * Math.PI) / 4) ||
28989
29315
  (angleRad <= -Math.PI / 2 && angleRad > (-3 * Math.PI) / 4);
@@ -29014,15 +29340,19 @@ var ImageEditPlugin = /** @class */ (function () {
29014
29340
  }
29015
29341
  var image = selection.image;
29016
29342
  if (this.editor) {
29017
- this.editImage(this.editor, image, 'rotate', function (imageEditInfo) {
29343
+ this.editImage(this.editor, image, [], function (imageEditInfo) {
29018
29344
  imageEditInfo.angleRad = (imageEditInfo.angleRad || 0) + angleRad;
29019
29345
  });
29020
29346
  }
29021
29347
  };
29022
- //EXPOSED FOR TEST ONLY
29023
- ImageEditPlugin.prototype.getWrapper = function () {
29024
- return this.wrapper;
29025
- };
29348
+ Object.defineProperty(ImageEditPlugin.prototype, "isEditingImage", {
29349
+ //EXPOSED FOR TEST ONLY
29350
+ get: function () {
29351
+ return this.isEditing;
29352
+ },
29353
+ enumerable: false,
29354
+ configurable: true
29355
+ });
29026
29356
  return ImageEditPlugin;
29027
29357
  }());
29028
29358
  exports.ImageEditPlugin = ImageEditPlugin;
@@ -29587,7 +29917,8 @@ var updateImageEditInfo_1 = __webpack_require__(/*! ./updateImageEditInfo */ "./
29587
29917
  function applyChange(editor, image, contentModelImage, editInfo, previousSrc, wasResizedOrCropped, editingImage) {
29588
29918
  var _a;
29589
29919
  var newSrc = '';
29590
- var initEditInfo = (_a = (0, updateImageEditInfo_1.getSelectedImageMetadata)(editor, editingImage !== null && editingImage !== void 0 ? editingImage : image)) !== null && _a !== void 0 ? _a : undefined;
29920
+ var imageEditing = editingImage !== null && editingImage !== void 0 ? editingImage : image;
29921
+ var initEditInfo = (_a = (0, updateImageEditInfo_1.updateImageEditInfo)(contentModelImage, imageEditing)) !== null && _a !== void 0 ? _a : undefined;
29591
29922
  var state = (0, checkEditInfoState_1.checkEditInfoState)(editInfo, initEditInfo);
29592
29923
  switch (state) {
29593
29924
  case 'ResizeOnly':
@@ -29619,12 +29950,12 @@ function applyChange(editor, image, contentModelImage, editInfo, previousSrc, wa
29619
29950
  if (newSrc == editInfo.src) {
29620
29951
  // If newSrc is the same with original one, it means there is only size change, but no rotation, no cropping,
29621
29952
  // so we don't need to keep edit info, we can delete it
29622
- (0, updateImageEditInfo_1.updateImageEditInfo)(contentModelImage, null);
29953
+ (0, updateImageEditInfo_1.updateImageEditInfo)(contentModelImage, imageEditing, null);
29623
29954
  }
29624
29955
  else {
29625
29956
  // Otherwise, save the new edit info to the image so that next time when we edit the same image, we know
29626
29957
  // the edit info
29627
- (0, updateImageEditInfo_1.updateImageEditInfo)(contentModelImage, editInfo);
29958
+ (0, updateImageEditInfo_1.updateImageEditInfo)(contentModelImage, imageEditing, editInfo);
29628
29959
  }
29629
29960
  // Write back the change to image, and set its new size
29630
29961
  var generatedImageSize = (0, generateImageSize_1.getGeneratedImageSize)(editInfo);
@@ -29635,11 +29966,6 @@ function applyChange(editor, image, contentModelImage, editInfo, previousSrc, wa
29635
29966
  if (wasResizedOrCropped || state == 'FullyChanged') {
29636
29967
  contentModelImage.format.width = generatedImageSize.targetWidth + 'px';
29637
29968
  contentModelImage.format.height = generatedImageSize.targetHeight + 'px';
29638
- // Remove width/height style so that it won't affect the image size, since style width/height has higher priority
29639
- image.style.removeProperty('width');
29640
- image.style.removeProperty('height');
29641
- image.style.removeProperty('max-width');
29642
- image.style.removeProperty('max-height');
29643
29969
  }
29644
29970
  }
29645
29971
  exports.applyChange = applyChange;
@@ -29766,25 +30092,27 @@ exports.createImageWrapper = void 0;
29766
30092
  var createImageCropper_1 = __webpack_require__(/*! ../Cropper/createImageCropper */ "./packages/roosterjs-content-model-plugins/lib/imageEdit/Cropper/createImageCropper.ts");
29767
30093
  var createImageResizer_1 = __webpack_require__(/*! ../Resizer/createImageResizer */ "./packages/roosterjs-content-model-plugins/lib/imageEdit/Resizer/createImageResizer.ts");
29768
30094
  var createImageRotator_1 = __webpack_require__(/*! ../Rotator/createImageRotator */ "./packages/roosterjs-content-model-plugins/lib/imageEdit/Rotator/createImageRotator.ts");
30095
+ var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
29769
30096
  /**
29770
30097
  * @internal
29771
30098
  */
29772
- function createImageWrapper(editor, image, imageSpan, options, editInfo, htmlOptions, operation) {
30099
+ function createImageWrapper(editor, image, options, editInfo, htmlOptions, operation) {
29773
30100
  var imageClone = cloneImage(image, editInfo);
29774
30101
  var doc = editor.getDocument();
29775
30102
  var rotators = [];
29776
- if (!options.disableRotate && operation === 'rotate') {
30103
+ if (!options.disableRotate && operation.indexOf('rotate') > -1) {
29777
30104
  rotators = (0, createImageRotator_1.createImageRotator)(doc, htmlOptions);
29778
30105
  }
29779
30106
  var resizers = [];
29780
- if (operation === 'resize') {
30107
+ if (operation.indexOf('resize') > -1) {
29781
30108
  resizers = (0, createImageResizer_1.createImageResizer)(doc);
29782
30109
  }
29783
30110
  var croppers = [];
29784
- if (operation === 'crop') {
30111
+ if (operation.indexOf('crop') > -1) {
29785
30112
  croppers = (0, createImageCropper_1.createImageCropper)(doc);
29786
30113
  }
29787
30114
  var wrapper = createWrapper(editor, imageClone, options, editInfo, resizers, rotators, croppers);
30115
+ var imageSpan = (0, roosterjs_content_model_dom_1.wrap)(doc, image, 'span');
29788
30116
  var shadowSpan = createShadowSpan(wrapper, imageSpan);
29789
30117
  return { wrapper: wrapper, shadowSpan: shadowSpan, imageClone: imageClone, resizers: resizers, rotators: rotators, croppers: croppers };
29790
30118
  }
@@ -29804,8 +30132,10 @@ var createWrapper = function (editor, image, options, editInfo, resizers, rotato
29804
30132
  var imageBox = doc.createElement('div');
29805
30133
  imageBox.setAttribute("style", "position:relative;width:100%;height:100%;overflow:hidden;transform:scale(1);");
29806
30134
  imageBox.appendChild(image);
29807
- 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;");
29808
- wrapper.style.display = editor.getEnvironment().isSafari ? 'inline-block' : 'inline-flex';
30135
+ wrapper.setAttribute('style', "font-size: 24px; margin: 0px; transform: rotate(" + ((_a = editInfo.angleRad) !== null && _a !== void 0 ? _a : 0) + "rad);");
30136
+ wrapper.style.display = editor.getEnvironment().isSafari
30137
+ ? '-webkit-inline-flex'
30138
+ : 'inline-flex';
29809
30139
  var border = createBorder(editor, options.borderColor);
29810
30140
  wrapper.appendChild(imageBox);
29811
30141
  wrapper.appendChild(border);
@@ -29894,6 +30224,59 @@ function doubleCheckResize(editInfo, preserveRatio, actualWidth, actualHeight) {
29894
30224
  exports.doubleCheckResize = doubleCheckResize;
29895
30225
 
29896
30226
 
30227
+ /***/ }),
30228
+
30229
+ /***/ "./packages/roosterjs-content-model-plugins/lib/imageEdit/utils/findEditingImage.ts":
30230
+ /*!******************************************************************************************!*\
30231
+ !*** ./packages/roosterjs-content-model-plugins/lib/imageEdit/utils/findEditingImage.ts ***!
30232
+ \******************************************************************************************/
30233
+ /***/ ((__unused_webpack_module, exports) => {
30234
+
30235
+ "use strict";
30236
+
30237
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
30238
+ exports.findEditingImage = void 0;
30239
+ /**
30240
+ * @internal
30241
+ */
30242
+ function findEditingImage(group) {
30243
+ for (var i = 0; i < group.blocks.length; i++) {
30244
+ var block = group.blocks[i];
30245
+ switch (block.blockType) {
30246
+ case 'BlockGroup':
30247
+ var result = findEditingImage(block);
30248
+ if (result) {
30249
+ return result;
30250
+ }
30251
+ break;
30252
+ case 'Paragraph':
30253
+ for (var j = 0; j < block.segments.length; j++) {
30254
+ var segment = block.segments[j];
30255
+ switch (segment.segmentType) {
30256
+ case 'Image':
30257
+ if (segment.dataset.isEditing) {
30258
+ return {
30259
+ paragraph: block,
30260
+ image: segment,
30261
+ };
30262
+ }
30263
+ break;
30264
+ case 'General':
30265
+ var result_1 = findEditingImage(segment);
30266
+ if (result_1) {
30267
+ return result_1;
30268
+ }
30269
+ break;
30270
+ }
30271
+ }
30272
+ break;
30273
+ }
30274
+ }
30275
+ return null;
30276
+ }
30277
+ exports.findEditingImage = findEditingImage;
30278
+
30279
+
29897
30280
  /***/ }),
29898
30281
 
29899
30282
  /***/ "./packages/roosterjs-content-model-plugins/lib/imageEdit/utils/generateDataURL.ts":
@@ -30078,28 +30461,33 @@ exports.getHTMLImageOptions = getHTMLImageOptions;
30078
30461
 
30079
30462
  /***/ }),
30080
30463
 
30081
- /***/ "./packages/roosterjs-content-model-plugins/lib/imageEdit/utils/getSelectedContentModelImage.ts":
30082
- /*!******************************************************************************************************!*\
30083
- !*** ./packages/roosterjs-content-model-plugins/lib/imageEdit/utils/getSelectedContentModelImage.ts ***!
30084
- \******************************************************************************************************/
30464
+ /***/ "./packages/roosterjs-content-model-plugins/lib/imageEdit/utils/getSelectedImage.ts":
30465
+ /*!******************************************************************************************!*\
30466
+ !*** ./packages/roosterjs-content-model-plugins/lib/imageEdit/utils/getSelectedImage.ts ***!
30467
+ \******************************************************************************************/
30085
30468
  /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
30086
30469
 
30087
30470
  "use strict";
30088
30471
 
30089
30472
  Object.defineProperty(exports, "__esModule", ({ value: true }));
30090
- exports.getSelectedContentModelImage = void 0;
30473
+ exports.getSelectedImage = void 0;
30091
30474
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
30092
30475
  /**
30093
30476
  * @internal
30094
30477
  */
30095
- function getSelectedContentModelImage(model) {
30096
- var selectedSegments = (0, roosterjs_content_model_dom_1.getSelectedSegments)(model, false /*includeFormatHolder*/);
30097
- if (selectedSegments.length == 1 && selectedSegments[0].segmentType == 'Image') {
30098
- return selectedSegments[0];
30478
+ function getSelectedImage(model) {
30479
+ var selections = (0, roosterjs_content_model_dom_1.getSelectedSegmentsAndParagraphs)(model, false);
30480
+ if (selections.length == 1 && selections[0][0].segmentType == 'Image' && selections[0][1]) {
30481
+ return {
30482
+ image: selections[0][0],
30483
+ paragraph: selections[0][1],
30484
+ };
30485
+ }
30486
+ else {
30487
+ return null;
30099
30488
  }
30100
- return null;
30101
30489
  }
30102
- exports.getSelectedContentModelImage = getSelectedContentModelImage;
30490
+ exports.getSelectedImage = getSelectedImage;
30103
30491
 
30104
30492
 
30105
30493
  /***/ }),
@@ -30271,18 +30659,19 @@ exports.updateHandleCursor = updateHandleCursor;
30271
30659
  Object.defineProperty(exports, "__esModule", ({ value: true }));
30272
30660
  exports.getSelectedImageMetadata = exports.updateImageEditInfo = void 0;
30273
30661
  var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
30274
- var getSelectedContentModelImage_1 = __webpack_require__(/*! ./getSelectedContentModelImage */ "./packages/roosterjs-content-model-plugins/lib/imageEdit/utils/getSelectedContentModelImage.ts");
30662
+ var getSelectedImage_1 = __webpack_require__(/*! ./getSelectedImage */ "./packages/roosterjs-content-model-plugins/lib/imageEdit/utils/getSelectedImage.ts");
30275
30663
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
30276
30664
  /**
30277
30665
  * @internal
30278
30666
  */
30279
- function updateImageEditInfo(contentModelImage, newImageMetadata) {
30280
- (0, roosterjs_content_model_dom_1.updateImageMetadata)(contentModelImage, newImageMetadata !== undefined
30667
+ function updateImageEditInfo(contentModelImage, image, newImageMetadata) {
30668
+ var contentModelMetadata = (0, roosterjs_content_model_dom_1.updateImageMetadata)(contentModelImage, newImageMetadata !== undefined
30281
30669
  ? function (format) {
30282
30670
  format = newImageMetadata;
30283
30671
  return format;
30284
30672
  }
30285
30673
  : undefined);
30674
+ return (0, tslib_1.__assign)((0, tslib_1.__assign)({}, getInitialEditInfo(image)), contentModelMetadata);
30286
30675
  }
30287
30676
  exports.updateImageEditInfo = updateImageEditInfo;
30288
30677
  function getInitialEditInfo(image) {
@@ -30306,9 +30695,12 @@ function getInitialEditInfo(image) {
30306
30695
  function getSelectedImageMetadata(editor, image) {
30307
30696
  var imageMetadata = getInitialEditInfo(image);
30308
30697
  editor.formatContentModel(function (model) {
30309
- var selectedImage = (0, getSelectedContentModelImage_1.getSelectedContentModelImage)(model);
30310
- if (selectedImage) {
30311
- imageMetadata = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, imageMetadata), selectedImage.dataset);
30698
+ var selectedImage = (0, getSelectedImage_1.getSelectedImage)(model);
30699
+ if (selectedImage === null || selectedImage === void 0 ? void 0 : selectedImage.image) {
30700
+ (0, roosterjs_content_model_dom_1.mutateSegment)(selectedImage.paragraph, selectedImage === null || selectedImage === void 0 ? void 0 : selectedImage.image, function (modelImage) {
30701
+ imageMetadata = updateImageEditInfo(modelImage, image);
30702
+ });
30703
+ return true;
30312
30704
  }
30313
30705
  return false;
30314
30706
  });
@@ -30388,7 +30780,7 @@ function updateWrapper(editInfo, options, image, clonedImage, wrapper, resizers,
30388
30780
  (0, imageEditUtils_1.setSize)(cropOverlays[1], undefined, 0, 0, cropBottomPx, cropRightPx, undefined);
30389
30781
  (0, imageEditUtils_1.setSize)(cropOverlays[2], cropLeftPx, undefined, 0, 0, undefined, cropBottomPx);
30390
30782
  (0, imageEditUtils_1.setSize)(cropOverlays[3], 0, cropTopPx, undefined, 0, cropLeftPx, undefined);
30391
- if (angleRad) {
30783
+ if (angleRad !== undefined) {
30392
30784
  (0, updateHandleCursor_1.updateHandleCursor)(croppers, angleRad);
30393
30785
  }
30394
30786
  }
@@ -30405,7 +30797,7 @@ function updateWrapper(editInfo, options, image, clonedImage, wrapper, resizers,
30405
30797
  }
30406
30798
  })
30407
30799
  .filter(function (handle) { return !!handle; });
30408
- if (angleRad) {
30800
+ if (angleRad !== undefined) {
30409
30801
  (0, updateHandleCursor_1.updateHandleCursor)(resizeHandles, angleRad);
30410
30802
  }
30411
30803
  (0, updateSideHandlesVisibility_1.updateSideHandlesVisibility)(resizeHandles, smallImage);
@@ -30688,7 +31080,6 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
30688
31080
  exports.setFormat = void 0;
30689
31081
  var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
30690
31082
  var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
30691
- var splitTextSegment_1 = __webpack_require__(/*! ../../pluginUtils/splitTextSegment */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/splitTextSegment.ts");
30692
31083
  /**
30693
31084
  * @internal
30694
31085
  */
@@ -30703,7 +31094,7 @@ function setFormat(editor, character, format, codeFormat) {
30703
31094
  .substring(0, lastCharIndex - 1)
30704
31095
  .lastIndexOf(character);
30705
31096
  if (lastCharIndex - firstCharIndex > 2) {
30706
- var formattedText = (0, splitTextSegment_1.splitTextSegment)(previousSegment, paragraph, firstCharIndex, lastCharIndex);
31097
+ var formattedText = (0, roosterjs_content_model_api_1.splitTextSegment)(previousSegment, paragraph, firstCharIndex, lastCharIndex);
30707
31098
  formattedText.text = formattedText.text.replace(character, '').slice(0, -1);
30708
31099
  formattedText.format = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, formattedText.format), format);
30709
31100
  if (codeFormat) {
@@ -32512,7 +32903,7 @@ exports.PickerPlugin = PickerPlugin;
32512
32903
 
32513
32904
  Object.defineProperty(exports, "__esModule", ({ value: true }));
32514
32905
  exports.getQueryString = void 0;
32515
- var splitTextSegment_1 = __webpack_require__(/*! ../pluginUtils/splitTextSegment */ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/splitTextSegment.ts");
32906
+ var roosterjs_content_model_api_1 = __webpack_require__(/*! roosterjs-content-model-api */ "./packages/roosterjs-content-model-api/lib/index.ts");
32516
32907
  /**
32517
32908
  * @internal
32518
32909
  */
@@ -32529,7 +32920,7 @@ function getQueryString(triggerCharacter, paragraph, previousSegment, splittedSe
32529
32920
  if (index >= 0) {
32530
32921
  result = segment.text.substring(index) + result;
32531
32922
  splittedSegmentResult === null || splittedSegmentResult === void 0 ? void 0 : splittedSegmentResult.unshift(index > 0
32532
- ? (0, splitTextSegment_1.splitTextSegment)(segment, paragraph, index, segment.text.length)
32923
+ ? (0, roosterjs_content_model_api_1.splitTextSegment)(segment, paragraph, index, segment.text.length)
32533
32924
  : segment);
32534
32925
  break;
32535
32926
  }
@@ -32795,42 +33186,6 @@ function getIntersectedRect(elements, additionalRects) {
32795
33186
  exports.getIntersectedRect = getIntersectedRect;
32796
33187
 
32797
33188
 
32798
- /***/ }),
32799
-
32800
- /***/ "./packages/roosterjs-content-model-plugins/lib/pluginUtils/splitTextSegment.ts":
32801
- /*!**************************************************************************************!*\
32802
- !*** ./packages/roosterjs-content-model-plugins/lib/pluginUtils/splitTextSegment.ts ***!
32803
- \**************************************************************************************/
32804
- /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
32805
-
32806
- "use strict";
32807
-
32808
- Object.defineProperty(exports, "__esModule", ({ value: true }));
32809
- exports.splitTextSegment = void 0;
32810
- var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
32811
- var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
32812
- /**
32813
- * @internal
32814
- */
32815
- function splitTextSegment(textSegment, parent, start, end) {
32816
- var _a;
32817
- var text = textSegment.text;
32818
- var index = parent.segments.indexOf(textSegment);
32819
- var middleSegment = (0, roosterjs_content_model_dom_1.createText)(text.substring(start, end), textSegment.format, textSegment.link, textSegment.code);
32820
- var newSegments = [middleSegment];
32821
- if (start > 0) {
32822
- newSegments.unshift((0, roosterjs_content_model_dom_1.createText)(text.substring(0, start), textSegment.format, textSegment.link, textSegment.code));
32823
- }
32824
- if (end < text.length) {
32825
- newSegments.push((0, roosterjs_content_model_dom_1.createText)(text.substring(end), textSegment.format, textSegment.link, textSegment.code));
32826
- }
32827
- newSegments.forEach(function (segment) { return (segment.isSelected = textSegment.isSelected); });
32828
- (_a = parent.segments).splice.apply(_a, (0, tslib_1.__spreadArray)([index, 1], (0, tslib_1.__read)(newSegments), false));
32829
- return middleSegment;
32830
- }
32831
- exports.splitTextSegment = splitTextSegment;
32832
-
32833
-
32834
33189
  /***/ }),
32835
33190
 
32836
33191
  /***/ "./packages/roosterjs-content-model-plugins/lib/shortcut/ShortcutPlugin.ts":
@@ -33518,8 +33873,10 @@ var TableEditor = /** @class */ (function () {
33518
33873
  _this.disposeTableInserter();
33519
33874
  _this.disposeCellResizers();
33520
33875
  };
33521
- this.onEndTableMove = function () {
33522
- _this.disposeTableMover();
33876
+ this.onEndTableMove = function (disposeHandler) {
33877
+ if (disposeHandler) {
33878
+ _this.disposeTableMover();
33879
+ }
33523
33880
  return _this.onFinishEditing();
33524
33881
  };
33525
33882
  this.onInserted = function () {
@@ -34293,9 +34650,9 @@ function onDragEnd(context, event, initValue) {
34293
34650
  // Reset cursor
34294
34651
  setTableMoverCursor(editor, false);
34295
34652
  if (element == context.div) {
34296
- // Table mover was only clicked, select whole table
34653
+ // Table mover was only clicked, select whole table and do not dismiss the handler element.
34297
34654
  selectWholeTable(table);
34298
- context.onEnd();
34655
+ context.onEnd(false /* disposeHandler */);
34299
34656
  return true;
34300
34657
  }
34301
34658
  else {
@@ -34304,7 +34661,7 @@ function onDragEnd(context, event, initValue) {
34304
34661
  !editor.getDOMHelper().isNodeInEditor(element) ||
34305
34662
  disableMovement) {
34306
34663
  editor.setDOMSelection((_a = initValue === null || initValue === void 0 ? void 0 : initValue.initialSelection) !== null && _a !== void 0 ? _a : null);
34307
- context.onEnd();
34664
+ context.onEnd(true /* disposeHandler */);
34308
34665
  return false;
34309
34666
  }
34310
34667
  var insertionSuccess_1 = false;
@@ -34362,7 +34719,7 @@ function onDragEnd(context, event, initValue) {
34362
34719
  // No movement, restore initial selection
34363
34720
  editor.setDOMSelection((_b = initValue === null || initValue === void 0 ? void 0 : initValue.initialSelection) !== null && _b !== void 0 ? _b : null);
34364
34721
  }
34365
- context.onEnd();
34722
+ context.onEnd(true /* disposeHandler */);
34366
34723
  return insertionSuccess_1;
34367
34724
  }
34368
34725
  }
@@ -34620,6 +34977,7 @@ exports.getCMTableFromTable = getCMTableFromTable;
34620
34977
 
34621
34978
  Object.defineProperty(exports, "__esModule", ({ value: true }));
34622
34979
  exports.WatermarkPlugin = void 0;
34980
+ var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
34623
34981
  var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
34624
34982
  var isModelEmptyFast_1 = __webpack_require__(/*! ./isModelEmptyFast */ "./packages/roosterjs-content-model-plugins/lib/watermark/isModelEmptyFast.ts");
34625
34983
  var WATERMARK_CONTENT_KEY = '_WatermarkContent';
@@ -34640,6 +34998,7 @@ var WatermarkPlugin = /** @class */ (function () {
34640
34998
  this.watermark = watermark;
34641
34999
  this.editor = null;
34642
35000
  this.isShowing = false;
35001
+ this.darkTextColor = null;
34643
35002
  this.format = format || {
34644
35003
  fontSize: '14px',
34645
35004
  textColor: '#AAAAAA',
@@ -34679,6 +35038,21 @@ var WatermarkPlugin = /** @class */ (function () {
34679
35038
  // When input text, editor must not be empty, so we can do hide watermark now without checking content model
34680
35039
  this.showHide(editor, false /*isEmpty*/);
34681
35040
  }
35041
+ else if (event.eventType == 'contentChanged' &&
35042
+ (event.source == roosterjs_content_model_dom_1.ChangeSource.SwitchToDarkMode ||
35043
+ event.source == roosterjs_content_model_dom_1.ChangeSource.SwitchToLightMode) &&
35044
+ this.isShowing) {
35045
+ // When the placeholder is shown and user switches the mode, we need to update watermark style
35046
+ if (event.source == roosterjs_content_model_dom_1.ChangeSource.SwitchToDarkMode &&
35047
+ !this.darkTextColor &&
35048
+ this.format.textColor) {
35049
+ // Get the dark color only once when dark mode is enabled for the first time
35050
+ this.darkTextColor = editor
35051
+ .getColorManager()
35052
+ .getDarkColor(this.format.textColor, undefined, 'text');
35053
+ }
35054
+ this.applyWatermarkStyle(editor);
35055
+ }
34682
35056
  else if (event.eventType == 'editorReady' ||
34683
35057
  event.eventType == 'contentChanged' ||
34684
35058
  event.eventType == 'input' ||
@@ -34699,15 +35073,18 @@ var WatermarkPlugin = /** @class */ (function () {
34699
35073
  }
34700
35074
  };
34701
35075
  WatermarkPlugin.prototype.show = function (editor) {
34702
- var _this = this;
35076
+ this.applyWatermarkStyle(editor);
35077
+ this.isShowing = true;
35078
+ };
35079
+ WatermarkPlugin.prototype.applyWatermarkStyle = function (editor) {
34703
35080
  var rule = "position: absolute; pointer-events: none; content: \"" + this.watermark + "\";";
35081
+ var format = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, this.format), { textColor: editor.isDarkMode() ? this.darkTextColor : this.format.textColor });
34704
35082
  (0, roosterjs_content_model_dom_1.getObjectKeys)(styleMap).forEach(function (x) {
34705
- if (_this.format[x]) {
34706
- rule += styleMap[x] + ": " + _this.format[x] + "!important;";
35083
+ if (format[x]) {
35084
+ rule += styleMap[x] + ": " + format[x] + "!important;";
34707
35085
  }
34708
35086
  });
34709
35087
  editor.setEditorStyle(WATERMARK_CONTENT_KEY, rule, 'before');
34710
- this.isShowing = true;
34711
35088
  };
34712
35089
  WatermarkPlugin.prototype.hide = function (editor) {
34713
35090
  editor.setEditorStyle(WATERMARK_CONTENT_KEY, null);