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