roosterjs 8.40.1 → 8.41.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/rooster.js CHANGED
@@ -2844,9 +2844,11 @@ function getElementBasedFormatState(editor, event) {
2844
2844
  canUnlink: !!editor.queryElements('a[href]', 1 /* OnSelection */)[0],
2845
2845
  canAddImageAltText: !!editor.queryElements('img', 1 /* OnSelection */)[0],
2846
2846
  isBlockQuote: !!editor.queryElements('blockquote', 1 /* OnSelection */)[0],
2847
+ isCodeBlock: !!editor.queryElements('pre>code', 1 /* OnSelection */)[0],
2847
2848
  isInTable: !!table,
2848
2849
  tableFormat: tableFormat,
2849
2850
  tableHasHeader: hasHeader,
2851
+ canMergeTableCell: canMergeTableCell(editor),
2850
2852
  };
2851
2853
  }
2852
2854
  exports.getElementBasedFormatState = getElementBasedFormatState;
@@ -2864,6 +2866,23 @@ function getFormatState(editor, event) {
2864
2866
  return __assign(__assign(__assign(__assign(__assign({}, editor.getPendableFormatState(false /* forceGetStateFromDom */)), getElementBasedFormatState(editor, event)), editor.getStyleBasedFormatState()), editor.getUndoState()), { isDarkMode: editor.isDarkMode(), zoomScale: editor.getZoomScale() });
2865
2867
  }
2866
2868
  exports.default = getFormatState;
2869
+ /**
2870
+ * Checks whether the editor selection range is starting and ending at a table element.
2871
+ * @param editor Editor Instance
2872
+ * @returns
2873
+ */
2874
+ var canMergeTableCell = function (editor) {
2875
+ var selection = editor.getSelectionRangeEx();
2876
+ var isATable = selection && selection.type === 1 /* TableSelection */;
2877
+ if (isATable && selection.coordinates) {
2878
+ var _a = selection.coordinates, firstCell = _a.firstCell, lastCell = _a.lastCell;
2879
+ if (firstCell.x !== lastCell.x || firstCell.y !== lastCell.y) {
2880
+ return true;
2881
+ }
2882
+ return false;
2883
+ }
2884
+ return false;
2885
+ };
2867
2886
 
2868
2887
 
2869
2888
  /***/ }),
@@ -3238,7 +3257,7 @@ var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./
3238
3257
  **/
3239
3258
  function setBackgroundColor(editor, color) {
3240
3259
  (0, applyInlineStyle_1.default)(editor, function (element, isInnerNode) {
3241
- (0, roosterjs_editor_dom_1.setColor)(element, isInnerNode ? '' : color, true /*isBackground*/, editor.isDarkMode());
3260
+ (0, roosterjs_editor_dom_1.setColor)(element, isInnerNode ? '' : color, true /*isBackground*/, editor.isDarkMode(), false /*shouldAdaptFontColor*/, editor.getDarkColorHandler());
3242
3261
  }, 'setBackgroundColor');
3243
3262
  }
3244
3263
  exports.default = setBackgroundColor;
@@ -3543,7 +3562,7 @@ var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./
3543
3562
  function setTextColor(editor, color, shouldApplyInlineStyle) {
3544
3563
  (0, applyListItemWrap_1.default)(editor, 'color', function (element, isInnerNode) {
3545
3564
  if (!shouldApplyInlineStyle || shouldApplyInlineStyle(element)) {
3546
- (0, roosterjs_editor_dom_1.setColor)(element, isInnerNode ? '' : color, false /*isBackground*/, editor.isDarkMode());
3565
+ (0, roosterjs_editor_dom_1.setColor)(element, isInnerNode ? '' : color, false /*isBackground*/, editor.isDarkMode(), false /*shouldAdaptFontColor*/, editor.getDarkColorHandler());
3547
3566
  }
3548
3567
  }, 'setTextColor');
3549
3568
  }
@@ -4026,7 +4045,7 @@ function applyCellShading(editor, color) {
4026
4045
  var regions = editor.getSelectedRegions();
4027
4046
  regions.forEach(function (region) {
4028
4047
  if ((0, roosterjs_editor_dom_1.safeInstanceOf)(region.rootNode, 'HTMLTableCellElement')) {
4029
- (0, roosterjs_editor_dom_1.setColor)(region.rootNode, color, true /* isBackgroundColor */, editor.isDarkMode(), true /** shouldAdaptFontColor */);
4048
+ (0, roosterjs_editor_dom_1.setColor)(region.rootNode, color, true /* isBackgroundColor */, editor.isDarkMode(), true /** shouldAdaptFontColor */, editor.getDarkColorHandler());
4030
4049
  (0, roosterjs_editor_dom_1.saveTableCellMetadata)(region.rootNode, { bgColorOverride: true });
4031
4050
  }
4032
4051
  });
@@ -5178,7 +5197,7 @@ var ensureTypeInContainer = function (core, position, keyboardEvent, applyFormat
5178
5197
  position = new roosterjs_editor_dom_1.Position(formatNode, 0 /* Begin */);
5179
5198
  }
5180
5199
  if (formatNode && core.lifecycle.defaultFormat) {
5181
- (0, roosterjs_editor_dom_1.applyFormat)(formatNode, core.lifecycle.defaultFormat, core.lifecycle.isDarkMode);
5200
+ (0, roosterjs_editor_dom_1.applyFormat)(formatNode, core.lifecycle.defaultFormat, core.lifecycle.isDarkMode, core.darkColorHandler);
5182
5201
  }
5183
5202
  // If this is triggered by a keyboard event, let's select the new position
5184
5203
  if (keyboardEvent) {
@@ -5274,7 +5293,7 @@ var getContent = function (core, mode) {
5274
5293
  else if (mode == 3 /* PlainText */) {
5275
5294
  content = (0, roosterjs_editor_dom_1.getTextContent)(root);
5276
5295
  }
5277
- else if (triggerExtractContentEvent || core.lifecycle.isDarkMode) {
5296
+ else if (triggerExtractContentEvent || core.lifecycle.isDarkMode || core.darkColorHandler) {
5278
5297
  var clonedRoot = cloneNode(root);
5279
5298
  clonedRoot.normalize();
5280
5299
  var originalRange = core.api.getSelectionRange(core, true /*tryGetFromCache*/);
@@ -5286,8 +5305,8 @@ var getContent = function (core, mode) {
5286
5305
  ? (0, roosterjs_editor_dom_1.getSelectionPath)(core.contentDiv, originalRange)
5287
5306
  : null;
5288
5307
  var range = path && (0, roosterjs_editor_dom_1.createRange)(clonedRoot, path.start, path.end);
5289
- if (core.lifecycle.isDarkMode) {
5290
- core.api.transformColor(core, clonedRoot, false /*includeSelf*/, null /*callback*/, 1 /* DarkToLight */);
5308
+ if (core.lifecycle.isDarkMode || core.darkColorHandler) {
5309
+ core.api.transformColor(core, clonedRoot, false /*includeSelf*/, null /*callback*/, 1 /* DarkToLight */, !!core.darkColorHandler);
5291
5310
  }
5292
5311
  if (triggerExtractContentEvent) {
5293
5312
  core.api.triggerEvent(core, {
@@ -5601,38 +5620,78 @@ var getStyleBasedFormatState = function (core, node) {
5601
5620
  ];
5602
5621
  }
5603
5622
  var styles = node ? (0, roosterjs_editor_dom_1.getComputedStyles)(node) : [];
5604
- var isDarkMode = core.lifecycle.isDarkMode;
5605
- var root = core.contentDiv;
5606
- var ogTextColorNode = isDarkMode &&
5607
- (override[2]
5608
- ? pendableFormatSpan
5609
- : (0, roosterjs_editor_dom_1.findClosestElementAncestor)(node, root, ORIGINAL_STYLE_COLOR_SELECTOR));
5610
- var ogBackgroundColorNode = isDarkMode &&
5611
- (override[3]
5612
- ? pendableFormatSpan
5613
- : (0, roosterjs_editor_dom_1.findClosestElementAncestor)(node, root, ORIGINAL_STYLE_BACK_COLOR_SELECTOR));
5614
- return {
5615
- fontName: override[0] || styles[0],
5616
- fontSize: override[1] || styles[1],
5617
- textColor: override[2] || styles[2],
5618
- backgroundColor: override[3] || styles[3],
5619
- textColors: ogTextColorNode
5620
- ? {
5621
- darkModeColor: override[2] || styles[2],
5622
- lightModeColor: ogTextColorNode.dataset["ogsc" /* OriginalStyleColor */] ||
5623
- ogTextColorNode.dataset["ogac" /* OriginalAttributeColor */] ||
5624
- styles[2],
5623
+ var contentDiv = core.contentDiv, darkColorHandler = core.darkColorHandler, isDarkMode = core.lifecycle.isDarkMode;
5624
+ if (darkColorHandler) {
5625
+ var styleTextColor = void 0;
5626
+ var styleBackColor = void 0;
5627
+ while (node &&
5628
+ (0, roosterjs_editor_dom_1.contains)(contentDiv, node, true /*treatSameNodeAsContain*/) &&
5629
+ !(styleTextColor && styleBackColor)) {
5630
+ if (node.nodeType == 1 /* Element */) {
5631
+ var element = node;
5632
+ styleTextColor = styleTextColor || element.style.getPropertyValue('color');
5633
+ styleBackColor =
5634
+ styleBackColor || element.style.getPropertyValue('background-color');
5625
5635
  }
5626
- : undefined,
5627
- backgroundColors: ogBackgroundColorNode
5628
- ? {
5629
- darkModeColor: override[3] || styles[3],
5630
- lightModeColor: ogBackgroundColorNode.dataset["ogsb" /* OriginalStyleBackgroundColor */] ||
5631
- ogBackgroundColorNode.dataset["ogab" /* OriginalAttributeBackgroundColor */] ||
5632
- styles[3],
5633
- }
5634
- : undefined,
5635
- };
5636
+ node = node.parentNode;
5637
+ }
5638
+ if (!core.lifecycle.isDarkMode && node == core.contentDiv) {
5639
+ styleTextColor = styleTextColor || styles[2];
5640
+ styleBackColor = styleBackColor || styles[3];
5641
+ }
5642
+ var textColor = darkColorHandler.parseColorValue(override[2] || styleTextColor);
5643
+ var backColor = darkColorHandler.parseColorValue(override[3] || styleBackColor);
5644
+ return {
5645
+ fontName: override[0] || styles[0],
5646
+ fontSize: override[1] || styles[1],
5647
+ textColor: textColor.lightModeColor,
5648
+ backgroundColor: backColor.lightModeColor,
5649
+ textColors: textColor.darkModeColor
5650
+ ? {
5651
+ lightModeColor: textColor.lightModeColor,
5652
+ darkModeColor: textColor.darkModeColor,
5653
+ }
5654
+ : undefined,
5655
+ backgroundColors: backColor.darkModeColor
5656
+ ? {
5657
+ lightModeColor: backColor.lightModeColor,
5658
+ darkModeColor: backColor.darkModeColor,
5659
+ }
5660
+ : undefined,
5661
+ };
5662
+ }
5663
+ else {
5664
+ var ogTextColorNode = isDarkMode &&
5665
+ (override[2]
5666
+ ? pendableFormatSpan
5667
+ : (0, roosterjs_editor_dom_1.findClosestElementAncestor)(node, contentDiv, ORIGINAL_STYLE_COLOR_SELECTOR));
5668
+ var ogBackgroundColorNode = isDarkMode &&
5669
+ (override[3]
5670
+ ? pendableFormatSpan
5671
+ : (0, roosterjs_editor_dom_1.findClosestElementAncestor)(node, contentDiv, ORIGINAL_STYLE_BACK_COLOR_SELECTOR));
5672
+ return {
5673
+ fontName: override[0] || styles[0],
5674
+ fontSize: override[1] || styles[1],
5675
+ textColor: override[2] || styles[2],
5676
+ backgroundColor: override[3] || styles[3],
5677
+ textColors: ogTextColorNode
5678
+ ? {
5679
+ darkModeColor: override[2] || styles[2],
5680
+ lightModeColor: ogTextColorNode.dataset["ogsc" /* OriginalStyleColor */] ||
5681
+ ogTextColorNode.dataset["ogac" /* OriginalAttributeColor */] ||
5682
+ styles[2],
5683
+ }
5684
+ : undefined,
5685
+ backgroundColors: ogBackgroundColorNode
5686
+ ? {
5687
+ darkModeColor: override[3] || styles[3],
5688
+ lightModeColor: ogBackgroundColorNode.dataset["ogsb" /* OriginalStyleBackgroundColor */] ||
5689
+ ogBackgroundColorNode.dataset["ogab" /* OriginalAttributeBackgroundColor */] ||
5690
+ styles[3],
5691
+ }
5692
+ : undefined,
5693
+ };
5694
+ }
5636
5695
  };
5637
5696
  exports.getStyleBasedFormatState = getStyleBasedFormatState;
5638
5697
 
@@ -6374,21 +6433,38 @@ var ColorAttributeName = [
6374
6433
  * Pass true to this value to force do color transformation even editor core is in light mode
6375
6434
  */
6376
6435
  var transformColor = function (core, rootNode, includeSelf, callback, direction, forceTransform) {
6436
+ var darkColorHandler = core.darkColorHandler;
6377
6437
  var elements = rootNode && (forceTransform || core.lifecycle.isDarkMode)
6378
6438
  ? getAll(rootNode, includeSelf)
6379
6439
  : [];
6380
6440
  callback === null || callback === void 0 ? void 0 : callback();
6381
- if (direction == 1 /* DarkToLight */) {
6382
- transformToLightMode(elements);
6383
- }
6384
- else if (core.lifecycle.onExternalContentTransform) {
6385
- elements.forEach(function (element) { return core.lifecycle.onExternalContentTransform(element); });
6441
+ if (darkColorHandler) {
6442
+ transformV2(elements, darkColorHandler, direction == 0 /* LightToDark */);
6386
6443
  }
6387
6444
  else {
6388
- transformToDarkMode(elements, core.lifecycle.getDarkColor);
6445
+ if (direction == 1 /* DarkToLight */) {
6446
+ transformToLightMode(elements);
6447
+ }
6448
+ else if (core.lifecycle.onExternalContentTransform) {
6449
+ elements.forEach(function (element) { return core.lifecycle.onExternalContentTransform(element); });
6450
+ }
6451
+ else {
6452
+ transformToDarkMode(elements, core.lifecycle.getDarkColor);
6453
+ }
6389
6454
  }
6390
6455
  };
6391
6456
  exports.transformColor = transformColor;
6457
+ function transformV2(elements, darkColorHandler, toDark) {
6458
+ elements.forEach(function (element) {
6459
+ ColorAttributeName.forEach(function (names, i) {
6460
+ var color = darkColorHandler.parseColorValue(element.style.getPropertyValue(names[0 /* CssColor */]) ||
6461
+ element.getAttribute(names[1 /* HtmlColor */])).lightModeColor;
6462
+ if (color && color != 'inherit') {
6463
+ (0, roosterjs_editor_dom_1.setColor)(element, color, i != 0, toDark, false /*shouldAdaptFontColor*/, darkColorHandler);
6464
+ }
6465
+ });
6466
+ });
6467
+ }
6392
6468
  function transformToLightMode(elements) {
6393
6469
  elements.forEach(function (element) {
6394
6470
  ColorAttributeName.forEach(function (names) {
@@ -7558,6 +7634,15 @@ var ImageSelection = /** @class */ (function () {
7558
7634
  }
7559
7635
  }
7560
7636
  break;
7637
+ case 5 /* MouseDown */:
7638
+ var mouseTarget = event.rawEvent.target;
7639
+ var mouseSelection = this.editor.getSelectionRangeEx();
7640
+ if (mouseSelection &&
7641
+ mouseSelection.type === 2 /* ImageSelection */ &&
7642
+ mouseSelection.image !== mouseTarget) {
7643
+ this.editor.select(null);
7644
+ }
7645
+ break;
7561
7646
  case 2 /* KeyUp */:
7562
7647
  var key = event.rawEvent.key;
7563
7648
  var keyDownSelection = this.editor.getSelectionRangeEx();
@@ -7657,10 +7742,12 @@ var LifecyclePlugin = /** @class */ (function () {
7657
7742
  this.adjustColor = options.doNotAdjustEditorColor
7658
7743
  ? function () { }
7659
7744
  : function () {
7745
+ var _a;
7660
7746
  var textColors = DARK_MODE_DEFAULT_FORMAT.textColors, backgroundColors = DARK_MODE_DEFAULT_FORMAT.backgroundColors;
7661
7747
  var isDarkMode = _this.state.isDarkMode;
7662
- (0, roosterjs_editor_dom_1.setColor)(contentDiv, textColors, false /*isBackground*/, isDarkMode);
7663
- (0, roosterjs_editor_dom_1.setColor)(contentDiv, backgroundColors, true /*isBackground*/, isDarkMode);
7748
+ var darkColorHandler = (_a = _this.editor) === null || _a === void 0 ? void 0 : _a.getDarkColorHandler();
7749
+ (0, roosterjs_editor_dom_1.setColor)(contentDiv, textColors, false /*isBackground*/, isDarkMode, false /*shouldAdaptFontColor*/, darkColorHandler);
7750
+ (0, roosterjs_editor_dom_1.setColor)(contentDiv, backgroundColors, true /*isBackground*/, isDarkMode, false /*shouldAdaptFontColor*/, darkColorHandler);
7664
7751
  };
7665
7752
  this.state = {
7666
7753
  customData: {},
@@ -8140,7 +8227,10 @@ var PendingFormatStatePlugin = /** @class */ (function () {
8140
8227
  event.rawEvent.which <= 40 /* DOWN */) ||
8141
8228
  (this.state.pendableFormatPosition &&
8142
8229
  (currentPosition = this.getCurrentPosition()) &&
8143
- !this.state.pendableFormatPosition.equalTo(currentPosition))) {
8230
+ !this.state.pendableFormatPosition.equalTo(currentPosition)) ||
8231
+ (event.eventType == 7 /* ContentChanged */ &&
8232
+ (event.source == "SwitchToDarkMode" /* SwitchToDarkMode */ ||
8233
+ event.source == "SwitchToLightMode" /* SwitchToLightMode */))) {
8144
8234
  // If content or position is changed (by keyboard, mouse, or code),
8145
8235
  // check if current position is still the same with the cached one (if exist),
8146
8236
  // and clear cached format if position is changed since it is out-of-date now
@@ -8171,11 +8261,12 @@ var PendingFormatStatePlugin = /** @class */ (function () {
8171
8261
  span.appendChild(doc.createTextNode(ZERO_WIDTH_SPACE));
8172
8262
  span.style.setProperty('font-family', (_a = currentStyle.fontName) !== null && _a !== void 0 ? _a : null);
8173
8263
  span.style.setProperty('font-size', (_b = currentStyle.fontSize) !== null && _b !== void 0 ? _b : null);
8264
+ var darkColorHandler = this.editor.getDarkColorHandler();
8174
8265
  if (currentStyle.textColors || currentStyle.textColor) {
8175
- (0, roosterjs_editor_dom_1.setColor)(span, (currentStyle.textColors || currentStyle.textColor), false /*isBackground*/, isDarkMode);
8266
+ (0, roosterjs_editor_dom_1.setColor)(span, (currentStyle.textColors || currentStyle.textColor), false /*isBackground*/, isDarkMode, false /*shouldAdaptFontColor*/, darkColorHandler);
8176
8267
  }
8177
8268
  if (currentStyle.backgroundColors || currentStyle.backgroundColor) {
8178
- (0, roosterjs_editor_dom_1.setColor)(span, (currentStyle.backgroundColors || currentStyle.backgroundColor), true /*isBackground*/, isDarkMode);
8269
+ (0, roosterjs_editor_dom_1.setColor)(span, (currentStyle.backgroundColors || currentStyle.backgroundColor), true /*isBackground*/, isDarkMode, false /*shouldAdaptFontColor*/, darkColorHandler);
8179
8270
  }
8180
8271
  }
8181
8272
  if (span) {
@@ -8676,6 +8767,98 @@ var removeCellsOutsideSelection = function (vTable) {
8676
8767
  exports.removeCellsOutsideSelection = removeCellsOutsideSelection;
8677
8768
 
8678
8769
 
8770
+ /***/ }),
8771
+
8772
+ /***/ "./packages/roosterjs-editor-core/lib/editor/DarkColorHandlerImpl.ts":
8773
+ /*!***************************************************************************!*\
8774
+ !*** ./packages/roosterjs-editor-core/lib/editor/DarkColorHandlerImpl.ts ***!
8775
+ \***************************************************************************/
8776
+ /*! no static exports found */
8777
+ /***/ (function(module, exports, __webpack_require__) {
8778
+
8779
+ "use strict";
8780
+
8781
+ Object.defineProperty(exports, "__esModule", { value: true });
8782
+ var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
8783
+ var VARIABLE_REGEX = /^\s*var\(\s*(\-\-[a-zA-Z0-9\-_]+)\s*(?:,\s*(.*))?\)\s*$/;
8784
+ var VARIABLE_PREFIX = 'var(';
8785
+ var COLOR_VAR_PREFIX = 'darkColor';
8786
+ /**
8787
+ * @internal
8788
+ */
8789
+ var DarkColorHandlerImpl = /** @class */ (function () {
8790
+ function DarkColorHandlerImpl(contentDiv, getDarkColor) {
8791
+ this.contentDiv = contentDiv;
8792
+ this.getDarkColor = getDarkColor;
8793
+ this.knownColors = {};
8794
+ }
8795
+ /**
8796
+ * Given a light mode color value and an optional dark mode color value, register this color
8797
+ * so that editor can handle it, then return the CSS color value for current color mode.
8798
+ * @param lightModeColor Light mode color value
8799
+ * @param isDarkMode Whether current color mode is dark mode
8800
+ * @param darkModeColor Optional dark mode color value. If not passed, we will calculate one.
8801
+ */
8802
+ DarkColorHandlerImpl.prototype.registerColor = function (lightModeColor, isDarkMode, darkModeColor) {
8803
+ var parsedColor = this.parseColorValue(lightModeColor);
8804
+ var colorKey;
8805
+ if (parsedColor) {
8806
+ lightModeColor = parsedColor.lightModeColor;
8807
+ darkModeColor = parsedColor.darkModeColor || darkModeColor;
8808
+ colorKey = parsedColor.key;
8809
+ }
8810
+ if (isDarkMode && lightModeColor) {
8811
+ colorKey =
8812
+ colorKey || "--" + COLOR_VAR_PREFIX + "_" + lightModeColor.replace(/[^\d\w]/g, '_');
8813
+ if (!this.knownColors[colorKey]) {
8814
+ darkModeColor = darkModeColor || this.getDarkColor(lightModeColor);
8815
+ this.knownColors[colorKey] = { lightModeColor: lightModeColor, darkModeColor: darkModeColor };
8816
+ this.contentDiv.style.setProperty(colorKey, darkModeColor);
8817
+ }
8818
+ return "var(" + colorKey + ", " + lightModeColor + ")";
8819
+ }
8820
+ else {
8821
+ return lightModeColor;
8822
+ }
8823
+ };
8824
+ /**
8825
+ * Reset known color record, clean up registered color variables.
8826
+ */
8827
+ DarkColorHandlerImpl.prototype.reset = function () {
8828
+ var _this = this;
8829
+ (0, roosterjs_editor_dom_1.getObjectKeys)(this.knownColors).forEach(function (key) { return _this.contentDiv.style.removeProperty(key); });
8830
+ this.knownColors = {};
8831
+ };
8832
+ /**
8833
+ * Parse an existing color value, if it is in variable-based color format, extract color key,
8834
+ * light color and query related dark color if any
8835
+ * @param color The color string to parse
8836
+ */
8837
+ DarkColorHandlerImpl.prototype.parseColorValue = function (color) {
8838
+ var _a;
8839
+ var key;
8840
+ var lightModeColor = color || '';
8841
+ var darkModeColor;
8842
+ if (color) {
8843
+ var match = color.startsWith(VARIABLE_PREFIX) ? VARIABLE_REGEX.exec(color) : null;
8844
+ if (match) {
8845
+ if (match[2]) {
8846
+ key = match[1];
8847
+ lightModeColor = match[2];
8848
+ darkModeColor = (_a = this.knownColors[key]) === null || _a === void 0 ? void 0 : _a.darkModeColor;
8849
+ }
8850
+ else {
8851
+ lightModeColor = '';
8852
+ }
8853
+ }
8854
+ }
8855
+ return { key: key, lightModeColor: lightModeColor, darkModeColor: darkModeColor };
8856
+ };
8857
+ return DarkColorHandlerImpl;
8858
+ }());
8859
+ exports.default = DarkColorHandlerImpl;
8860
+
8861
+
8679
8862
  /***/ }),
8680
8863
 
8681
8864
  /***/ "./packages/roosterjs-editor-core/lib/editor/Editor.ts":
@@ -8700,6 +8883,7 @@ var __assign = (this && this.__assign) || function () {
8700
8883
  };
8701
8884
  Object.defineProperty(exports, "__esModule", { value: true });
8702
8885
  var createCorePlugins_1 = __webpack_require__(/*! ../corePlugins/createCorePlugins */ "./packages/roosterjs-editor-core/lib/corePlugins/createCorePlugins.ts");
8886
+ var DarkColorHandlerImpl_1 = __webpack_require__(/*! ./DarkColorHandlerImpl */ "./packages/roosterjs-editor-core/lib/editor/DarkColorHandlerImpl.ts");
8703
8887
  var coreApiMap_1 = __webpack_require__(/*! ../coreApi/coreApiMap */ "./packages/roosterjs-editor-core/lib/coreApi/coreApiMap.ts");
8704
8888
  var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
8705
8889
  /**
@@ -8742,6 +8926,9 @@ var Editor = /** @class */ (function () {
8742
8926
  ? [scrollContainer]
8743
8927
  : [scrollContainer, contentDiv]);
8744
8928
  }), imageSelectionBorderColor: options.imageSelectionBorderColor });
8929
+ if (this.isFeatureEnabled("VariableBasedDarkColor" /* VariableBasedDarkColor */)) {
8930
+ this.core.darkColorHandler = new DarkColorHandlerImpl_1.default(contentDiv, this.core.lifecycle.getDarkColor);
8931
+ }
8745
8932
  // 3. Initialize plugins
8746
8933
  this.core.plugins.forEach(function (plugin) { return plugin.initialize(_this); });
8747
8934
  // 4. Ensure user will type in a container node, not the editor content DIV
@@ -8751,10 +8938,12 @@ var Editor = /** @class */ (function () {
8751
8938
  * Dispose this editor, dispose all plugins and custom data
8752
8939
  */
8753
8940
  Editor.prototype.dispose = function () {
8941
+ var _a;
8754
8942
  var core = this.getCore();
8755
8943
  for (var i = core.plugins.length - 1; i >= 0; i--) {
8756
8944
  core.plugins[i].dispose();
8757
8945
  }
8946
+ (_a = core.darkColorHandler) === null || _a === void 0 ? void 0 : _a.reset();
8758
8947
  this.core = null;
8759
8948
  };
8760
8949
  /**
@@ -9465,6 +9654,12 @@ var Editor = /** @class */ (function () {
9465
9654
  var core = this.getCore();
9466
9655
  core.api.transformColor(core, node, true /*includeSelf*/, null /*callback*/, 0 /* LightToDark */);
9467
9656
  };
9657
+ /**
9658
+ * Get a darkColorHandler object for this editor. It will return null if experimental feature "VariableBasedDarkColor" is not enabled
9659
+ */
9660
+ Editor.prototype.getDarkColorHandler = function () {
9661
+ return this.getCore().darkColorHandler || null;
9662
+ };
9468
9663
  /**
9469
9664
  * Make the editor in "Shadow Edit" mode.
9470
9665
  * In Shadow Edit mode, all format change will finally be ignored.
@@ -18110,8 +18305,10 @@ var setColor_1 = __webpack_require__(/*! ./setColor */ "./packages/roosterjs-edi
18110
18305
  * Apply format to an HTML element
18111
18306
  * @param element The HTML element to apply format to
18112
18307
  * @param format The format to apply
18308
+ * @param isDarkMode Whether the content should be formatted in dark mode
18309
+ * @param darkColorHandler An optional dark color handler object. When it is passed, we will use this handler to do variable-based dark color instead of original dataset base dark color
18113
18310
  */
18114
- function applyFormat(element, format, isDarkMode) {
18311
+ function applyFormat(element, format, isDarkMode, darkColorHandler) {
18115
18312
  if (format) {
18116
18313
  var elementStyle = element.style;
18117
18314
  var fontFamily = format.fontFamily, fontSize = format.fontSize, textColor = format.textColor, textColors = format.textColors, backgroundColor = format.backgroundColor, backgroundColors = format.backgroundColors, bold = format.bold, italic = format.italic, underline = format.underline;
@@ -18122,16 +18319,16 @@ function applyFormat(element, format, isDarkMode) {
18122
18319
  elementStyle.fontSize = fontSize;
18123
18320
  }
18124
18321
  if (textColors) {
18125
- (0, setColor_1.default)(element, textColors, false /*isBackground*/, isDarkMode);
18322
+ (0, setColor_1.default)(element, textColors, false /*isBackground*/, isDarkMode, false /*shouldAdaptFontColor*/, darkColorHandler);
18126
18323
  }
18127
18324
  else if (textColor) {
18128
- (0, setColor_1.default)(element, textColor, false /*isBackground*/, isDarkMode);
18325
+ (0, setColor_1.default)(element, textColor, false /*isBackground*/, isDarkMode, false /*shouldAdaptFontColor*/, darkColorHandler);
18129
18326
  }
18130
18327
  if (backgroundColors) {
18131
- (0, setColor_1.default)(element, backgroundColors, true /*isBackground*/, isDarkMode);
18328
+ (0, setColor_1.default)(element, backgroundColors, true /*isBackground*/, isDarkMode, false /*shouldAdaptFontColor*/, darkColorHandler);
18132
18329
  }
18133
18330
  else if (backgroundColor) {
18134
- (0, setColor_1.default)(element, backgroundColor, true /*isBackground*/, isDarkMode);
18331
+ (0, setColor_1.default)(element, backgroundColor, true /*isBackground*/, isDarkMode, false /*shouldAdaptFontColor*/, darkColorHandler);
18135
18332
  }
18136
18333
  if (bold) {
18137
18334
  elementStyle.fontWeight = 'bold';
@@ -18368,7 +18565,7 @@ exports.KnownCreateElementData = (_a = {},
18368
18565
  },
18369
18566
  _a[6 /* ImageEditWrapper */] = {
18370
18567
  tag: 'span',
18371
- style: 'max-width:100%;position:fixed',
18568
+ style: 'max-width:100%;vertical-align:bottom',
18372
18569
  children: [
18373
18570
  {
18374
18571
  tag: 'div',
@@ -19385,28 +19582,35 @@ var TRANSPARENT_COLOR = 'transparent';
19385
19582
  * @param isBackgroundColor Whether set background color or text color
19386
19583
  * @param isDarkMode Whether current mode is dark mode. @default false
19387
19584
  * @param shouldAdaptTheFontColor Whether the font color needs to be adapted to be visible in a dark or bright background color. @default false
19388
- * @param defaultFontColor Set the default colors that needs to be set to the to be visible.
19585
+ * @param darkColorHandler An optional dark color handler object. When it is passed, we will use this handler to do variable-based dark color instead of original dataset base dark color
19389
19586
  */
19390
- function setColor(element, color, isBackgroundColor, isDarkMode, shouldAdaptTheFontColor) {
19587
+ function setColor(element, color, isBackgroundColor, isDarkMode, shouldAdaptTheFontColor, darkColorHandler) {
19391
19588
  var colorString = typeof color === 'string' ? color.trim() : '';
19392
19589
  var modeIndependentColor = typeof color === 'string' ? null : color;
19590
+ var cssName = isBackgroundColor ? 'background-color' : 'color';
19393
19591
  if (colorString || modeIndependentColor) {
19394
- element.style.setProperty(isBackgroundColor ? 'background-color' : 'color', (isDarkMode
19395
- ? modeIndependentColor === null || modeIndependentColor === void 0 ? void 0 : modeIndependentColor.darkModeColor
19396
- : modeIndependentColor === null || modeIndependentColor === void 0 ? void 0 : modeIndependentColor.lightModeColor) || colorString);
19397
- if (element.dataset) {
19398
- var dataSetName = isBackgroundColor
19399
- ? "ogsb" /* OriginalStyleBackgroundColor */
19400
- : "ogsc" /* OriginalStyleColor */;
19401
- if (!isDarkMode || color == TRANSPARENT_COLOR) {
19402
- delete element.dataset[dataSetName];
19403
- }
19404
- else if (modeIndependentColor) {
19405
- element.dataset[dataSetName] = modeIndependentColor.lightModeColor;
19592
+ if (darkColorHandler) {
19593
+ var colorValue = darkColorHandler.registerColor((modeIndependentColor === null || modeIndependentColor === void 0 ? void 0 : modeIndependentColor.lightModeColor) || colorString, !!isDarkMode, modeIndependentColor === null || modeIndependentColor === void 0 ? void 0 : modeIndependentColor.darkModeColor);
19594
+ element.style.setProperty(cssName, colorValue);
19595
+ }
19596
+ else {
19597
+ element.style.setProperty(cssName, (isDarkMode
19598
+ ? modeIndependentColor === null || modeIndependentColor === void 0 ? void 0 : modeIndependentColor.darkModeColor
19599
+ : modeIndependentColor === null || modeIndependentColor === void 0 ? void 0 : modeIndependentColor.lightModeColor) || colorString);
19600
+ if (element.dataset) {
19601
+ var dataSetName = isBackgroundColor
19602
+ ? "ogsb" /* OriginalStyleBackgroundColor */
19603
+ : "ogsc" /* OriginalStyleColor */;
19604
+ if (!isDarkMode || color == TRANSPARENT_COLOR) {
19605
+ delete element.dataset[dataSetName];
19606
+ }
19607
+ else if (modeIndependentColor) {
19608
+ element.dataset[dataSetName] = modeIndependentColor.lightModeColor;
19609
+ }
19406
19610
  }
19407
19611
  }
19408
19612
  if (isBackgroundColor && shouldAdaptTheFontColor) {
19409
- adaptFontColorToBackgroundColor(element, isDarkMode);
19613
+ adaptFontColorToBackgroundColor(element, (modeIndependentColor === null || modeIndependentColor === void 0 ? void 0 : modeIndependentColor.lightModeColor) || colorString, isDarkMode, darkColorHandler);
19410
19614
  }
19411
19615
  }
19412
19616
  }
@@ -19414,17 +19618,11 @@ exports.default = setColor;
19414
19618
  /**
19415
19619
  * Change the font color to white or some other color, so the text can be visible with a darker background
19416
19620
  * @param element The element that contains text.
19621
+ * @param lightModeBackgroundColor Existing background color in light mode
19622
+ * @param isDarkMode Whether the content is in dark mode
19623
+ * @param darkColorHandler An optional dark color handler object. When it is passed, we will use this handler to do variable-based dark color instead of original dataset base dark color
19417
19624
  */
19418
- function adaptFontColorToBackgroundColor(element, isDarkMode) {
19419
- var _a;
19420
- if ((_a = element.firstElementChild) === null || _a === void 0 ? void 0 : _a.hasAttribute('style')) {
19421
- return;
19422
- }
19423
- var backgroundColor = element.style.getPropertyValue('background-color');
19424
- var lightModeBackgroundColor = (isDarkMode &&
19425
- (element.dataset["ogsb" /* OriginalStyleBackgroundColor */] ||
19426
- element.dataset["ogab" /* OriginalAttributeBackgroundColor */])) ||
19427
- backgroundColor;
19625
+ function adaptFontColorToBackgroundColor(element, lightModeBackgroundColor, isDarkMode, darkColorHandler) {
19428
19626
  if (!lightModeBackgroundColor || lightModeBackgroundColor === TRANSPARENT) {
19429
19627
  return;
19430
19628
  }
@@ -19435,14 +19633,14 @@ function adaptFontColorToBackgroundColor(element, isDarkMode) {
19435
19633
  lightModeColor: WHITE,
19436
19634
  darkModeColor: GRAY,
19437
19635
  };
19438
- setColor(element, fontForDark, false /*isBackground*/, isDarkMode);
19636
+ setColor(element, fontForDark, false /*isBackground*/, isDarkMode, false /*shouldAdaptFontColor*/, darkColorHandler);
19439
19637
  break;
19440
19638
  case 0 /* BRIGHT */:
19441
19639
  var fontForLight = {
19442
19640
  lightModeColor: BLACK,
19443
19641
  darkModeColor: WHITE,
19444
19642
  };
19445
- setColor(element, fontForLight, false /*isBackground*/, isDarkMode);
19643
+ setColor(element, fontForLight, false /*isBackground*/, isDarkMode, false /*shouldAdaptFontColor*/, darkColorHandler);
19446
19644
  break;
19447
19645
  }
19448
19646
  }
@@ -22849,7 +23047,6 @@ var applyChange_1 = __webpack_require__(/*! ./editInfoUtils/applyChange */ "./pa
22849
23047
  var canRegenerateImage_1 = __webpack_require__(/*! ./api/canRegenerateImage */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/api/canRegenerateImage.ts");
22850
23048
  var DragAndDropHelper_1 = __webpack_require__(/*! ../../pluginUtils/DragAndDropHelper */ "./packages/roosterjs-editor-plugins/lib/pluginUtils/DragAndDropHelper.ts");
22851
23049
  var getGeneratedImageSize_1 = __webpack_require__(/*! ./editInfoUtils/getGeneratedImageSize */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/getGeneratedImageSize.ts");
22852
- var getLastZIndex_1 = __webpack_require__(/*! ./editInfoUtils/getLastZIndex */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/getLastZIndex.ts");
22853
23050
  var Cropper_1 = __webpack_require__(/*! ./imageEditors/Cropper */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/imageEditors/Cropper.ts");
22854
23051
  var editInfo_1 = __webpack_require__(/*! ./editInfoUtils/editInfo */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/editInfo.ts");
22855
23052
  var Rotator_1 = __webpack_require__(/*! ./imageEditors/Rotator */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/imageEditors/Rotator.ts");
@@ -22918,14 +23115,11 @@ var ImageEdit = /** @class */ (function () {
22918
23115
  * Remove the temp wrapper of the image
22919
23116
  */
22920
23117
  this.removeWrapper = function () {
22921
- var _a, _b;
22922
- var doc = _this.editor.getDocument();
22923
- if (_this.zoomWrapper && ((_a = doc.body) === null || _a === void 0 ? void 0 : _a.contains(_this.zoomWrapper))) {
22924
- (_b = doc.body) === null || _b === void 0 ? void 0 : _b.removeChild(_this.zoomWrapper);
22925
- _this.toggleImageVisibility(_this.image, true /** showImage */);
23118
+ if (_this.editor.contains(_this.image) && _this.wrapper) {
23119
+ (0, roosterjs_editor_dom_1.unwrap)(_this.image.parentNode);
22926
23120
  }
22927
23121
  _this.wrapper = null;
22928
- _this.zoomWrapper = null;
23122
+ _this.shadowSpan = null;
22929
23123
  };
22930
23124
  /**
22931
23125
  * Update image edit elements to reflect current editing result
@@ -22938,12 +23132,14 @@ var ImageEdit = /** @class */ (function () {
22938
23132
  var cropContainers = getEditElements(wrapper, "r_cropC" /* CropContainer */);
22939
23133
  var cropOverlays = getEditElements(wrapper, "r_cropO" /* CropOverlay */);
22940
23134
  var resizeHandles = getEditElements(wrapper, "r_resizeH" /* ResizeHandle */);
23135
+ var rotateCenter = getEditElements(wrapper, "r_rotateC" /* RotateCenter */)[0];
23136
+ var rotateHandle = getEditElements(wrapper, "r_rotateH" /* RotateHandle */)[0];
22941
23137
  var cropHandles = getEditElements(wrapper, "r_cropH" /* CropHandle */);
22942
23138
  // Cropping and resizing will show different UI, so check if it is cropping here first
22943
- var isCropping = cropContainers.length == 1 && cropOverlays.length == 4;
23139
+ _this.isCropping = cropContainers.length == 1 && cropOverlays.length == 4;
22944
23140
  var _a = _this.editInfo, angleRad = _a.angleRad, bottomPercent = _a.bottomPercent, leftPercent = _a.leftPercent, rightPercent = _a.rightPercent, topPercent = _a.topPercent;
22945
23141
  // Width/height of the image
22946
- var _b = (0, getGeneratedImageSize_1.default)(_this.editInfo, isCropping), targetWidth = _b.targetWidth, targetHeight = _b.targetHeight, originalWidth = _b.originalWidth, originalHeight = _b.originalHeight, visibleWidth = _b.visibleWidth, visibleHeight = _b.visibleHeight;
23142
+ var _b = (0, getGeneratedImageSize_1.default)(_this.editInfo, _this.isCropping), targetWidth = _b.targetWidth, targetHeight = _b.targetHeight, originalWidth = _b.originalWidth, originalHeight = _b.originalHeight, visibleWidth = _b.visibleWidth, visibleHeight = _b.visibleHeight;
22947
23143
  var marginHorizontal = (targetWidth - visibleWidth) / 2;
22948
23144
  var marginVertical = (targetHeight - visibleHeight) / 2;
22949
23145
  var cropLeftPx = originalWidth * leftPercent;
@@ -22955,16 +23151,15 @@ var ImageEdit = /** @class */ (function () {
22955
23151
  wrapper.style.height = getPx(visibleHeight);
22956
23152
  wrapper.style.margin = marginVertical + "px " + marginHorizontal + "px";
22957
23153
  wrapper.style.transform = "rotate(" + angleRad + "rad)";
22958
- _this.zoomWrapper.style.width = getPx(visibleWidth);
22959
- _this.zoomWrapper.style.height = getPx(visibleHeight);
22960
- fitImageContainer(_this.editor, _this.zoomWrapper, angleRad);
23154
+ _this.wrapper.style.width = getPx(visibleWidth);
23155
+ _this.wrapper.style.height = getPx(visibleHeight);
22961
23156
  // Update the text-alignment to avoid the image to overflow if the parent element have align center or right
22962
23157
  // or if the direction is Right To Left
22963
23158
  wrapper.style.textAlign = isRtl(wrapper.parentNode) ? 'right' : 'left';
22964
23159
  // Update size of the image
22965
23160
  _this.clonedImage.style.width = getPx(originalWidth);
22966
23161
  _this.clonedImage.style.height = getPx(originalHeight);
22967
- if (isCropping) {
23162
+ if (_this.isCropping) {
22968
23163
  // For crop, we also need to set position of the overlays
22969
23164
  setSize(cropContainers[0], cropLeftPx, cropTopPx, cropRightPx, cropBottomPx, undefined, undefined);
22970
23165
  setSize(cropOverlays[0], 0, 0, cropRightPx, undefined, undefined, cropTopPx);
@@ -22984,6 +23179,7 @@ var ImageEdit = /** @class */ (function () {
22984
23179
  (0, Resizer_1.doubleCheckResize)(_this.editInfo, _this.options.preserveRatio, clientWidth, clientHeight);
22985
23180
  _this.updateWrapper();
22986
23181
  }
23182
+ (0, Rotator_1.updateRotateHandlePosition)(_this.editInfo, _this.editor.getVisibleViewport(), marginVertical, rotateCenter, rotateHandle);
22987
23183
  updateHandleCursor(resizeHandles, angleRad);
22988
23184
  }
22989
23185
  }
@@ -23006,8 +23202,16 @@ var ImageEdit = /** @class */ (function () {
23006
23202
  * @param editor Editor instance
23007
23203
  */
23008
23204
  ImageEdit.prototype.initialize = function (editor) {
23205
+ var _this = this;
23009
23206
  this.editor = editor;
23010
- this.disposer = editor.addDomEventHandler('blur', this.onBlur);
23207
+ this.disposer = editor.addDomEventHandler({
23208
+ blur: function () { return _this.onBlur; },
23209
+ dragstart: function (e) {
23210
+ if (_this.image) {
23211
+ e.preventDefault();
23212
+ }
23213
+ },
23214
+ });
23011
23215
  };
23012
23216
  /**
23013
23217
  * Dispose this plugin
@@ -23031,16 +23235,21 @@ var ImageEdit = /** @class */ (function () {
23031
23235
  }
23032
23236
  break;
23033
23237
  case 5 /* MouseDown */:
23034
- this.setEditingImage(null);
23238
+ // When left click in a image that already in editing mode, do not quit edit mode
23239
+ var mouseTarget = e.rawEvent.target;
23240
+ var button = e.rawEvent.button;
23241
+ if (this.shadowSpan !== mouseTarget ||
23242
+ (this.shadowSpan === mouseTarget && button !== 0) ||
23243
+ this.isCropping) {
23244
+ this.setEditingImage(null);
23245
+ }
23035
23246
  break;
23036
23247
  case 0 /* KeyDown */:
23037
23248
  this.setEditingImage(null);
23038
23249
  break;
23039
23250
  case 7 /* ContentChanged */:
23040
- if (e.source !== "Format" /* Format */) {
23041
- // After contentChanged event, the current image wrapper may not be valid any more, remove all of them if any
23042
- this.removeWrapper();
23043
- }
23251
+ //After contentChanged event, the current image wrapper may not be valid any more, remove all of them if any
23252
+ this.removeWrapper();
23044
23253
  break;
23045
23254
  case 8 /* ExtractContentWithDom */:
23046
23255
  // When extract content, remove all image info since they may not be valid when load the content again
@@ -23048,8 +23257,8 @@ var ImageEdit = /** @class */ (function () {
23048
23257
  (0, editInfo_1.deleteEditInfo)(img);
23049
23258
  });
23050
23259
  break;
23051
- case 14 /* Scroll */:
23052
- this.setEditingImage(null);
23260
+ case 12 /* BeforeDispose */:
23261
+ this.removeWrapper();
23053
23262
  break;
23054
23263
  }
23055
23264
  };
@@ -23080,6 +23289,7 @@ var ImageEdit = /** @class */ (function () {
23080
23289
  this.editInfo = null;
23081
23290
  this.lastSrc = null;
23082
23291
  this.clonedImage = null;
23292
+ this.isCropping = false;
23083
23293
  }
23084
23294
  if (!this.image && (image === null || image === void 0 ? void 0 : image.isContentEditable)) {
23085
23295
  // If there is new image to edit, enter editing mode for this image
@@ -23098,7 +23308,6 @@ var ImageEdit = /** @class */ (function () {
23098
23308
  // Init drag and drop
23099
23309
  this.dndHelpers = __spreadArray(__spreadArray(__spreadArray(__spreadArray([], this.createDndHelpers("r_resizeH" /* ResizeHandle */, Resizer_1.Resizer), true), this.createDndHelpers("r_rotateH" /* RotateHandle */, Rotator_1.Rotator), true), this.createDndHelpers("r_cropH" /* CropHandle */, Cropper_1.Cropper), true), this.createDndHelpers("r_cropC" /* CropContainer */, Cropper_1.Cropper), true);
23100
23310
  this.editor.select(this.image);
23101
- this.toggleImageVisibility(this.image, false /** showImage */);
23102
23311
  }
23103
23312
  };
23104
23313
  /**
@@ -23111,18 +23320,12 @@ var ImageEdit = /** @class */ (function () {
23111
23320
  this.clonedImage.removeAttribute('id');
23112
23321
  this.wrapper = (0, roosterjs_editor_dom_1.createElement)(6 /* ImageEditWrapper */, this.image.ownerDocument);
23113
23322
  this.wrapper.firstChild.appendChild(this.clonedImage);
23114
- // keep the same vertical align
23115
- var originalVerticalAlign = getStylePropertyValue(this.image, 'vertical-align');
23116
- if (originalVerticalAlign) {
23117
- this.wrapper.style.verticalAlign = originalVerticalAlign;
23118
- }
23119
23323
  this.wrapper.style.display = roosterjs_editor_dom_1.Browser.isSafari ? 'inline-block' : 'inline-flex';
23120
23324
  // Cache current src so that we can compare it after edit see if src is changed
23121
23325
  this.lastSrc = this.image.getAttribute('src');
23122
23326
  // Set image src to original src to help show editing UI, also it will be used when regenerate image dataURL after editing
23123
23327
  this.clonedImage.src = this.editInfo.src;
23124
23328
  this.clonedImage.style.position = 'absolute';
23125
- this.clonedImage.style.maxWidth = null;
23126
23329
  // Get HTML for all edit elements (resize handle, rotate handle, crop handle and overlay, ...) and create HTML element
23127
23330
  var options = {
23128
23331
  borderColor: getColorString(this.options.borderColor, this.editor.isDarkMode()),
@@ -23144,24 +23347,15 @@ var ImageEdit = /** @class */ (function () {
23144
23347
  _this.wrapper.appendChild(element);
23145
23348
  }
23146
23349
  });
23147
- this.insertImageWrapper(this.editor, this.image, this.wrapper, this.editor.getZoomScale());
23148
- };
23149
- ImageEdit.prototype.toggleImageVisibility = function (image, showImage) {
23150
- var editorId = this.editor.getEditorDomAttribute('id');
23151
- var doc = this.editor.getDocument();
23152
- var editingId = 'editingId' + editorId;
23153
- if (showImage) {
23154
- (0, roosterjs_editor_dom_1.removeGlobalCssStyle)(doc, editingId);
23155
- }
23156
- else {
23157
- var cssRule = "#" + editorId + " #" + image.id + " {visibility: hidden}";
23158
- (0, roosterjs_editor_dom_1.setGlobalCssStyles)(doc, cssRule, editingId);
23159
- }
23350
+ this.insertImageWrapper(this.wrapper);
23160
23351
  };
23161
- ImageEdit.prototype.insertImageWrapper = function (editor, image, wrapper, scale) {
23162
- this.zoomWrapper = copyElementRect(image, createZoomWrapper(editor, wrapper, scale));
23163
- this.zoomWrapper.style.zIndex = "" + ((0, getLastZIndex_1.default)(editor.getScrollContainer()) + 1);
23164
- this.editor.getDocument().body.appendChild(this.zoomWrapper);
23352
+ ImageEdit.prototype.insertImageWrapper = function (wrapper) {
23353
+ this.shadowSpan = (0, roosterjs_editor_dom_1.wrap)(this.image, 'span');
23354
+ var shadowRoot = this.shadowSpan.attachShadow({
23355
+ mode: 'open',
23356
+ });
23357
+ this.shadowSpan.style.verticalAlign = 'bottom';
23358
+ shadowRoot.appendChild(wrapper);
23165
23359
  };
23166
23360
  /**
23167
23361
  * Create drag and drop helpers
@@ -23267,40 +23461,6 @@ function getColorString(color, isDarkMode) {
23267
23461
  }
23268
23462
  return isDarkMode ? color.darkModeColor.trim() : color.lightModeColor.trim();
23269
23463
  }
23270
- function fitImageContainer(editor, zoomWrapper, angle) {
23271
- var _a, _b;
23272
- var angleIndex = handleRadIndexCalculator(angle);
23273
- var isVertical = (angleIndex >= 2 && angleIndex < 4) || angleIndex >= 6;
23274
- var editorTop = (_b = (_a = editor.getScrollContainer()) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect()) === null || _b === void 0 ? void 0 : _b.top;
23275
- var _c = zoomWrapper === null || zoomWrapper === void 0 ? void 0 : zoomWrapper.getBoundingClientRect(), top = _c.top, width = _c.width, height = _c.height;
23276
- if (editorTop > top) {
23277
- var rotatePercent = 100 * Math.abs(angle);
23278
- var zoomWrapperHeight = editorTop - top;
23279
- var zoomWrapperHeightPercent = isVertical
23280
- ? rotatePercent * (zoomWrapperHeight / width)
23281
- : 100 * (zoomWrapperHeight / height);
23282
- zoomWrapper.style.clipPath = "polygon(0 " + zoomWrapperHeightPercent + "%, 100% " + zoomWrapperHeightPercent + "%, 100% " + (isVertical ? rotatePercent : '100') + "%, 0 " + (isVertical ? rotatePercent : '100') + "%)";
23283
- }
23284
- }
23285
- function copyElementRect(originalElement, element) {
23286
- var _a = originalElement.getBoundingClientRect(), top = _a.top, left = _a.left, right = _a.right, bottom = _a.bottom;
23287
- element.style.top = top + "px";
23288
- element.style.bottom = bottom + "px";
23289
- element.style.right = right + "px";
23290
- element.style.left = left + "px";
23291
- return element;
23292
- }
23293
- function createZoomWrapper(editor, wrapper, scale) {
23294
- var zoomWrapper = editor.getDocument().createElement('div');
23295
- zoomWrapper.style.transform = "scale(" + (scale || 1) + ")";
23296
- zoomWrapper.style.transformOrigin = 'top left';
23297
- zoomWrapper.style.position = 'fixed';
23298
- zoomWrapper.appendChild(wrapper);
23299
- return zoomWrapper;
23300
- }
23301
- function getStylePropertyValue(element, property) {
23302
- return element.ownerDocument.defaultView.getComputedStyle(element).getPropertyValue(property);
23303
- }
23304
23464
 
23305
23465
 
23306
23466
  /***/ }),
@@ -23527,7 +23687,6 @@ function applyChange(editor, image, editInfo, previousSrc, wasResized, editingIm
23527
23687
  var _a = (0, getGeneratedImageSize_1.default)(editInfo), targetWidth = _a.targetWidth, targetHeight = _a.targetHeight;
23528
23688
  image.src = newSrc;
23529
23689
  if (wasResized || state == 3 /* FullyChanged */) {
23530
- image.style.maxWidth = 'initial';
23531
23690
  image.width = targetWidth;
23532
23691
  image.height = targetHeight;
23533
23692
  image.style.width = targetWidth + 'px';
@@ -23759,40 +23918,6 @@ function getGeneratedImageSize(editInfo, beforeCrop) {
23759
23918
  exports.default = getGeneratedImageSize;
23760
23919
 
23761
23920
 
23762
- /***/ }),
23763
-
23764
- /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/getLastZIndex.ts":
23765
- /*!************************************************************************************************!*\
23766
- !*** ./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/getLastZIndex.ts ***!
23767
- \************************************************************************************************/
23768
- /*! no static exports found */
23769
- /***/ (function(module, exports, __webpack_require__) {
23770
-
23771
- "use strict";
23772
-
23773
- Object.defineProperty(exports, "__esModule", { value: true });
23774
- var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
23775
- /**
23776
- * @internal
23777
- * Search through from editor div to it's root for the latest z-index value
23778
- * @param editorDiv the editor div element
23779
- * @returns the z index value
23780
- */
23781
- function getLatestZIndex(editorDiv) {
23782
- var child = editorDiv;
23783
- var zIndex = 0;
23784
- while (child && (0, roosterjs_editor_dom_1.getTagOfNode)(child) !== 'BODY') {
23785
- var childZIndex = child.style.zIndex || getComputedStyle(child).zIndex;
23786
- if (childZIndex) {
23787
- zIndex = parseInt(child.style.zIndex);
23788
- }
23789
- child = child.parentElement;
23790
- }
23791
- return zIndex;
23792
- }
23793
- exports.default = getLatestZIndex;
23794
-
23795
-
23796
23921
  /***/ }),
23797
23922
 
23798
23923
  /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/getTargetSizeByPercentage.ts":
@@ -24190,7 +24315,7 @@ var __assign = (this && this.__assign) || function () {
24190
24315
  return __assign.apply(this, arguments);
24191
24316
  };
24192
24317
  Object.defineProperty(exports, "__esModule", { value: true });
24193
- exports.getRotateHTML = exports.Rotator = void 0;
24318
+ exports.getRotateHTML = exports.updateRotateHandlePosition = exports.Rotator = void 0;
24194
24319
  var ROTATE_SIZE = 32;
24195
24320
  var ROTATE_GAP = 15;
24196
24321
  var DEG_PER_RAD = 180 / Math.PI;
@@ -24225,6 +24350,26 @@ exports.Rotator = {
24225
24350
  }
24226
24351
  },
24227
24352
  };
24353
+ /**
24354
+ * @internal
24355
+ * Move rotate handle. When image is very close to the border of editor, rotate handle may not be visible.
24356
+ * Fix it by reduce the distance from image to rotate handle
24357
+ */
24358
+ function updateRotateHandlePosition(editInfo, editorRect, marginVertical, rotateCenter, rotateHandle) {
24359
+ var _a;
24360
+ var top = ((_a = rotateHandle.getBoundingClientRect()) === null || _a === void 0 ? void 0 : _a.top) - (editorRect === null || editorRect === void 0 ? void 0 : editorRect.top);
24361
+ var angleRad = editInfo.angleRad, heightPx = editInfo.heightPx;
24362
+ var cosAngle = Math.cos(angleRad);
24363
+ var adjustedDistance = cosAngle <= 0
24364
+ ? Number.MAX_SAFE_INTEGER
24365
+ : (top + heightPx / 2 + marginVertical) / cosAngle - heightPx / 2;
24366
+ var rotateGap = Math.max(Math.min(ROTATE_GAP, adjustedDistance), 0);
24367
+ var rotateTop = Math.max(Math.min(ROTATE_SIZE, adjustedDistance - rotateGap), 0);
24368
+ rotateCenter.style.top = -rotateGap + 'px';
24369
+ rotateCenter.style.height = rotateGap + 'px';
24370
+ rotateHandle.style.top = -rotateTop + 'px';
24371
+ }
24372
+ exports.updateRotateHandlePosition = updateRotateHandlePosition;
24228
24373
  /**
24229
24374
  * @internal
24230
24375
  * Get HTML for rotate elements, including the rotate handle with icon, and a line between the handle and the image
@@ -28540,7 +28685,7 @@ var Watermark = /** @class */ (function () {
28540
28685
  this.removeWatermark(wrapper);
28541
28686
  }
28542
28687
  else if (event.operation == 0 /* NewEntity */) {
28543
- (0, roosterjs_editor_dom_1.applyFormat)(wrapper, this.format, this.editor.isDarkMode());
28688
+ (0, roosterjs_editor_dom_1.applyFormat)(wrapper, this.format, this.editor.isDarkMode(), this.editor.getDarkColorHandler());
28544
28689
  wrapper.spellcheck = false;
28545
28690
  }
28546
28691
  }
@@ -29589,6 +29734,12 @@ var CompatibleExperimentalFeatures;
29589
29734
  * the block element (In most case, the DIV element) so keep the block element clean.
29590
29735
  */
29591
29736
  CompatibleExperimentalFeatures["DefaultFormatInSpan"] = "DefaultFormatInSpan";
29737
+ /**
29738
+ * Use variable-based dark mode solution rather than dataset-based solution.
29739
+ * When enable this feature, need to pass in a DarkModelHandler object to each call of setColor and applyFormat
29740
+ * if you need them work for dark mode
29741
+ */
29742
+ CompatibleExperimentalFeatures["VariableBasedDarkColor"] = "VariableBasedDarkColor";
29592
29743
  })(CompatibleExperimentalFeatures = exports.CompatibleExperimentalFeatures || (exports.CompatibleExperimentalFeatures = {}));
29593
29744
 
29594
29745