roosterjs 8.17.0 → 8.18.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.
@@ -1,4 +1,4 @@
1
- // Type definitions for roosterjs (Version 8.17.0)
1
+ // Type definitions for roosterjs (Version 8.18.0)
2
2
  // Generated by dts tool from roosterjs
3
3
  // Project: https://github.com/Microsoft/roosterjs
4
4
 
@@ -733,7 +733,11 @@ export const enum ExperimentalFeatures {
733
733
  /**
734
734
  * Align table elements to left, center and right using setAlignment API
735
735
  */
736
- TableAlignment = "TableAlignment"
736
+ TableAlignment = "TableAlignment",
737
+ /**
738
+ * Provide additional Tab Key Features. Requires Text Features Content Editable Features
739
+ */
740
+ TabKeyTextFeatures = "TabKeyTextFeatures"
737
741
  }
738
742
 
739
743
  /**
@@ -1773,6 +1777,14 @@ export interface Entity {
1773
1777
  * The format state
1774
1778
  */
1775
1779
  export interface FormatState extends PendableFormatState, ElementBasedFormatState, StyleBasedFormatState, EditorUndoState {
1780
+ /**
1781
+ * Whether editor is in dark mode
1782
+ */
1783
+ isDarkMode?: boolean;
1784
+ /**
1785
+ * Current zoom scale of editor
1786
+ */
1787
+ zoomScale?: number;
1776
1788
  }
1777
1789
 
1778
1790
  /**
@@ -1837,6 +1849,10 @@ export interface ElementBasedFormatState {
1837
1849
  * Header level (0-6, 0 means no header)
1838
1850
  */
1839
1851
  headerLevel?: number;
1852
+ /**
1853
+ * Whether the cursor is in table
1854
+ */
1855
+ isInTable?: boolean;
1840
1856
  }
1841
1857
 
1842
1858
  /**
@@ -2325,6 +2341,10 @@ export interface TableFormat {
2325
2341
  * Table Borders Type
2326
2342
  */
2327
2343
  tableBorderFormat?: TableBorderFormat;
2344
+ /**
2345
+ * If true, the new format will not overlay cells that has color applied
2346
+ */
2347
+ keepCellShade?: boolean;
2328
2348
  }
2329
2349
 
2330
2350
  /**
@@ -3796,6 +3816,27 @@ export interface TableFeatureSettings {
3796
3816
  upDownInTable: boolean;
3797
3817
  }
3798
3818
 
3819
+ /**
3820
+ * Settings for text features
3821
+ */
3822
+ export interface TextFeatureSettings {
3823
+ /**
3824
+ * Requires @see ExperimentalFeatures.TabKeyTextFeatures to be enabled
3825
+ * When press Tab:
3826
+ * If Whole Paragraph selected, indent paragraph,
3827
+ * If range is collapsed, add spaces
3828
+ * If range is not collapsed but not all the paragraph is selected, remove selection and add
3829
+ * spaces
3830
+ */
3831
+ indentWhenTabText: boolean;
3832
+ /**
3833
+ * Requires @see ExperimentalFeatures.TabKeyTextFeatures to be enabled
3834
+ * When press Tab:
3835
+ * If Whole Paragraph selected, outdent paragraph
3836
+ */
3837
+ outdentWhenTabText: boolean;
3838
+ }
3839
+
3799
3840
  /**
3800
3841
  * An interface to define a replacement rule for CustomReplace plugin
3801
3842
  */
@@ -5076,8 +5117,10 @@ export function getInnerHTML(node: HTMLElement | DocumentFragment): string;
5076
5117
  * @param color The color to set, it can be a string of color name/value or a ModeIndependentColor object
5077
5118
  * @param isBackgroundColor Whether set background color or text color
5078
5119
  * @param isDarkMode Whether current mode is dark mode. @default false
5120
+ * @param shouldAdaptTheFontColor Whether the font color needs to be adapted to be visible in a dark or bright background color. @default false
5121
+ * @param defaultFontColor Set the default colors that needs to be set to the to be visible.
5079
5122
  */
5080
- export function setColor(element: HTMLElement, color: string | ModeIndependentColor, isBackgroundColor: boolean, isDarkMode?: boolean): void;
5123
+ export function setColor(element: HTMLElement, color: string | ModeIndependentColor, isBackgroundColor: boolean, isDarkMode?: boolean, shouldAdaptTheFontColor?: boolean): void;
5081
5124
 
5082
5125
  /**
5083
5126
  * A wrapper function of Element.matches
@@ -5268,7 +5311,7 @@ export class VTable {
5268
5311
  * the writeBack() function will handle everything related to DOM change
5269
5312
  */
5270
5313
  export class VList {
5271
- private rootList;
5314
+ rootList: HTMLOListElement | HTMLUListElement;
5272
5315
  readonly items: VListItem[];
5273
5316
  /**
5274
5317
  * Create a new instance of VList class
@@ -5336,6 +5379,16 @@ export class VList {
5336
5379
  * @param list The vList to merge from
5337
5380
  */
5338
5381
  mergeVList(list: VList): void;
5382
+ /**
5383
+ * Get the index of the List Item in the current List
5384
+ * @param input List item to find in the root list
5385
+ */
5386
+ getListItemIndex(input: Node): number;
5387
+ /**
5388
+ * Get the Start property of the root list of this VList
5389
+ * @returns Start number of the list
5390
+ */
5391
+ getStart(): number | undefined;
5339
5392
  private findListItems;
5340
5393
  private populateItems;
5341
5394
  }
@@ -2761,6 +2761,7 @@ function getElementBasedFormatState(editor, event) {
2761
2761
  canUnlink: !!editor.queryElements('a[href]', 1 /* OnSelection */)[0],
2762
2762
  canAddImageAltText: !!editor.queryElements('img', 1 /* OnSelection */)[0],
2763
2763
  isBlockQuote: !!editor.queryElements('blockquote', 1 /* OnSelection */)[0],
2764
+ isInTable: !!editor.queryElements('table', 1 /* OnSelection */)[0],
2764
2765
  };
2765
2766
  }
2766
2767
  exports.getElementBasedFormatState = getElementBasedFormatState;
@@ -2775,7 +2776,7 @@ exports.getElementBasedFormatState = getElementBasedFormatState;
2775
2776
  * @returns The format state at cursor
2776
2777
  */
2777
2778
  function getFormatState(editor, event) {
2778
- return __assign(__assign(__assign(__assign({}, editor.getPendableFormatState(false /* forceGetStateFromDom */)), getElementBasedFormatState(editor, event)), editor.getStyleBasedFormatState()), editor.getUndoState());
2779
+ return __assign(__assign(__assign(__assign(__assign({}, editor.getPendableFormatState(false /* forceGetStateFromDom */)), getElementBasedFormatState(editor, event)), editor.getStyleBasedFormatState()), editor.getUndoState()), { isDarkMode: editor.isDarkMode(), zoomScale: editor.getZoomScale() });
2779
2780
  }
2780
2781
  exports.default = getFormatState;
2781
2782
 
@@ -3287,18 +3288,28 @@ var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./
3287
3288
  function setIndentation(editor, indentation) {
3288
3289
  var handler = indentation == 0 /* Increase */ ? indent : outdent;
3289
3290
  (0, blockFormat_1.default)(editor, function (region, start, end) {
3291
+ var _a;
3290
3292
  var blocks = (0, roosterjs_editor_dom_1.getSelectedBlockElementsInRegion)(region, true /*createBlockIfEmpty*/);
3291
3293
  var blockGroups = [[]];
3292
3294
  for (var i = 0; i < blocks.length; i++) {
3293
3295
  var startNode = blocks[i].getStartNode();
3294
3296
  var vList = (0, roosterjs_editor_dom_1.createVListFromRegion)(region, true /*includeSiblingLists*/, startNode);
3295
3297
  if (vList) {
3296
- blockGroups.push([]);
3297
3298
  while (blocks[i + 1] && vList.contains(blocks[i + 1].getStartNode())) {
3298
3299
  i++;
3299
3300
  }
3300
- vList.setIndentation(start, end, indentation);
3301
- vList.writeBack();
3301
+ if (((_a = vList.items[0]) === null || _a === void 0 ? void 0 : _a.getNode()) == startNode &&
3302
+ vList.getListItemIndex(startNode) == vList.getStart() &&
3303
+ (indentation == 0 /* Increase */ ||
3304
+ editor.getElementAtCursor('blockquote', startNode))) {
3305
+ var block = editor.getBlockElementAtNode(vList.rootList);
3306
+ blockGroups.push([block]);
3307
+ }
3308
+ else {
3309
+ vList.setIndentation(start, end, indentation);
3310
+ vList.writeBack();
3311
+ blockGroups.push([]);
3312
+ }
3302
3313
  }
3303
3314
  else {
3304
3315
  blockGroups[blockGroups.length - 1].push(blocks[i]);
@@ -3873,7 +3884,7 @@ function applyCellShading(editor, color) {
3873
3884
  var regions = editor.getSelectedRegions();
3874
3885
  regions.forEach(function (region) {
3875
3886
  if ((0, roosterjs_editor_dom_1.safeInstanceOf)(region.rootNode, 'HTMLTableCellElement')) {
3876
- (0, roosterjs_editor_dom_1.setColor)(region.rootNode, color, true /* isBackgroundColor */, editor.isDarkMode());
3887
+ (0, roosterjs_editor_dom_1.setColor)(region.rootNode, color, true /* isBackgroundColor */, editor.isDarkMode(), true /** shouldAdaptFontColor */);
3877
3888
  region.rootNode.dataset[CELL_SHADE] = 'true';
3878
3889
  region.rootNode.dataset[TEMP_BACKGROUND_COLOR] =
3879
3890
  region.rootNode.style.backgroundColor;
@@ -5514,7 +5525,7 @@ var STYLE_ID = 'tableStyle';
5514
5525
  */
5515
5526
  var selectTable = function (core, table, coordinates) {
5516
5527
  unselect(core);
5517
- if (coordinates && table) {
5528
+ if (areValidCoordinates(coordinates) && table) {
5518
5529
  ensureUniqueId(table, TABLE_ID);
5519
5530
  ensureUniqueId(core.contentDiv, CONTENT_DIV_ID);
5520
5531
  var ranges = select(core, table, coordinates);
@@ -5666,6 +5677,21 @@ function removeImportant(cell) {
5666
5677
  }
5667
5678
  }
5668
5679
  }
5680
+ function areValidCoordinates(input) {
5681
+ if (input) {
5682
+ var _a = input || {}, firstCell = _a.firstCell, lastCell = _a.lastCell;
5683
+ if (firstCell && lastCell) {
5684
+ var handler = function (coordinate) {
5685
+ return isValidCoordinate(coordinate.x) && isValidCoordinate(coordinate.y);
5686
+ };
5687
+ return handler(firstCell) && handler(lastCell);
5688
+ }
5689
+ }
5690
+ return false;
5691
+ }
5692
+ function isValidCoordinate(input) {
5693
+ return (!!input || input == 0) && input > -1;
5694
+ }
5669
5695
 
5670
5696
 
5671
5697
  /***/ }),
@@ -5971,7 +5997,7 @@ var CopyPastePlugin = /** @class */ (function () {
5971
5997
  return _this.getTempDiv();
5972
5998
  },
5973
5999
  removeTempDiv: function (div) {
5974
- _this.cleanUpAndRestoreSelection(div, range);
6000
+ _this.cleanUpAndRestoreSelection(div, range, false /* isCopy */);
5975
6001
  },
5976
6002
  });
5977
6003
  };
@@ -6030,7 +6056,7 @@ var CopyPastePlugin = /** @class */ (function () {
6030
6056
  isCut: isCut,
6031
6057
  });
6032
6058
  this.editor.runAsync(function (editor) {
6033
- _this.cleanUpAndRestoreSelection(tempDiv_1, originalRange_1);
6059
+ _this.cleanUpAndRestoreSelection(tempDiv_1, originalRange_1, !isCut /* isCopy */);
6034
6060
  if (isCut) {
6035
6061
  editor.addUndoSnapshot(function () {
6036
6062
  var position = _this.editor.deleteSelectedContent();
@@ -6058,8 +6084,8 @@ var CopyPastePlugin = /** @class */ (function () {
6058
6084
  div.focus();
6059
6085
  return div;
6060
6086
  };
6061
- CopyPastePlugin.prototype.cleanUpAndRestoreSelection = function (tempDiv, range) {
6062
- if (roosterjs_editor_dom_1.Browser.isAndroid) {
6087
+ CopyPastePlugin.prototype.cleanUpAndRestoreSelection = function (tempDiv, range, isCopy) {
6088
+ if (isCopy && roosterjs_editor_dom_1.Browser.isAndroid) {
6063
6089
  range.collapse();
6064
6090
  }
6065
6091
  this.editor.select(range);
@@ -11784,7 +11810,7 @@ var VList = /** @class */ (function () {
11784
11810
  * If there is no order list item, result will be undefined
11785
11811
  */
11786
11812
  VList.prototype.getLastItemNumber = function () {
11787
- var start = getStart(this.rootList);
11813
+ var start = this.getStart();
11788
11814
  return start === undefined
11789
11815
  ? start
11790
11816
  : start -
@@ -11807,7 +11833,7 @@ var VList = /** @class */ (function () {
11807
11833
  var doc = this.rootList.ownerDocument;
11808
11834
  var listStack = [doc.createDocumentFragment()];
11809
11835
  var placeholder = doc.createTextNode('');
11810
- var start = getStart(this.rootList) || 1;
11836
+ var start = this.getStart() || 1;
11811
11837
  var lastList;
11812
11838
  // Use a placeholder to hold the position since the root list may be moved into document fragment later
11813
11839
  this.rootList.parentNode.replaceChild(placeholder, this.rootList);
@@ -11915,6 +11941,34 @@ var VList = /** @class */ (function () {
11915
11941
  (_a = list.rootList.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(list.rootList);
11916
11942
  }
11917
11943
  };
11944
+ /**
11945
+ * Get the index of the List Item in the current List
11946
+ * @param input List item to find in the root list
11947
+ */
11948
+ VList.prototype.getListItemIndex = function (input) {
11949
+ if (this.items) {
11950
+ var listIndex = this.getStart() - 1;
11951
+ for (var index = 0; index < this.items.length; index++) {
11952
+ var child = this.items[index];
11953
+ if (child.getListType() == 1 /* Ordered */ &&
11954
+ child.getLevel() == 1 &&
11955
+ !child.isDummy()) {
11956
+ listIndex++;
11957
+ }
11958
+ if (child.getNode() == input) {
11959
+ return listIndex;
11960
+ }
11961
+ }
11962
+ }
11963
+ return -1;
11964
+ };
11965
+ /**
11966
+ * Get the Start property of the root list of this VList
11967
+ * @returns Start number of the list
11968
+ */
11969
+ VList.prototype.getStart = function () {
11970
+ return (0, safeInstanceOf_1.default)(this.rootList, 'HTMLOListElement') ? this.rootList.start : undefined;
11971
+ };
11918
11972
  VList.prototype.findListItems = function (start, end, callback) {
11919
11973
  if (this.items.length == 0) {
11920
11974
  return [];
@@ -11989,9 +12043,6 @@ function moveLiToList(li) {
11989
12043
  (0, unwrap_1.default)(li.parentNode);
11990
12044
  }
11991
12045
  }
11992
- function getStart(list) {
11993
- return (0, safeInstanceOf_1.default)(list, 'HTMLOListElement') ? list.start : undefined;
11994
- }
11995
12046
 
11996
12047
 
11997
12048
  /***/ }),
@@ -14018,6 +14069,7 @@ var DEFAULT_FORMAT = {
14018
14069
  bgColorOdd: '#ABABAB20',
14019
14070
  headerRowColor: '#ABABAB',
14020
14071
  tableBorderFormat: 0 /* DEFAULT */,
14072
+ keepCellShade: false,
14021
14073
  };
14022
14074
  /**
14023
14075
  * A virtual table class, represent an HTML table, by expand all merged cells to each separated cells
@@ -14105,7 +14157,9 @@ var VTable = /** @class */ (function () {
14105
14157
  return;
14106
14158
  }
14107
14159
  this.formatInfo = __assign(__assign(__assign({}, DEFAULT_FORMAT), (this.formatInfo || {})), (format || {}));
14108
- this.deleteCellShadeDataset(this.cells);
14160
+ if (!this.formatInfo.keepCellShade) {
14161
+ this.deleteCellShadeDataset(this.cells);
14162
+ }
14109
14163
  };
14110
14164
  /**
14111
14165
  * Remove the cellShade dataset to apply a new style format at the cell.
@@ -14597,13 +14651,13 @@ function setCellColor(cells, format) {
14597
14651
  if (cell.td && !hasCellShade(cell)) {
14598
14652
  if (hasBandedRows) {
14599
14653
  var backgroundColor = color(index);
14600
- (0, setColor_1.default)(cell.td, backgroundColor || TRANSPARENT, true /** isBackgroundColor*/);
14654
+ (0, setColor_1.default)(cell.td, backgroundColor || TRANSPARENT, true /** isBackgroundColor*/, true /** shouldAdaptFontColor */);
14601
14655
  }
14602
14656
  else if (shouldColorWholeTable) {
14603
14657
  (0, setColor_1.default)(cell.td, format.bgColorOdd || TRANSPARENT, true /** isBackgroundColor*/);
14604
14658
  }
14605
14659
  else {
14606
- (0, setColor_1.default)(cell.td, TRANSPARENT, true /** isBackgroundColor*/);
14660
+ (0, setColor_1.default)(cell.td, TRANSPARENT, true /** isBackgroundColor*/, true /** shouldAdaptFontColor */);
14607
14661
  }
14608
14662
  }
14609
14663
  });
@@ -14613,7 +14667,7 @@ function setCellColor(cells, format) {
14613
14667
  row.forEach(function (cell, index) {
14614
14668
  var backgroundColor = color(index);
14615
14669
  if (cell.td && backgroundColor && !hasCellShade(cell)) {
14616
- (0, setColor_1.default)(cell.td, backgroundColor, true /** isBackgroundColor*/);
14670
+ (0, setColor_1.default)(cell.td, backgroundColor, true /** isBackgroundColor*/, true /** shouldAdaptFontColor */);
14617
14671
  }
14618
14672
  });
14619
14673
  });
@@ -14778,9 +14832,9 @@ function setFirstColumnFormat(cells, format) {
14778
14832
  cells.forEach(function (row, rowIndex) {
14779
14833
  row.forEach(function (cell, cellIndex) {
14780
14834
  if (cell.td && cellIndex === 0) {
14781
- if (rowIndex !== 0) {
14835
+ if (rowIndex !== 0 && !hasCellShade(cell)) {
14782
14836
  cell.td.style.borderTopColor = TRANSPARENT;
14783
- (0, setColor_1.default)(cell.td, TRANSPARENT, true /** isBackgroundColor*/);
14837
+ (0, setColor_1.default)(cell.td, TRANSPARENT, true /** isBackgroundColor*/, true /** shouldAdaptFontColor */);
14784
14838
  }
14785
14839
  if (rowIndex !== cells.length - 1 && rowIndex !== 0) {
14786
14840
  cell.td.style.borderBottomColor = TRANSPARENT;
@@ -14809,7 +14863,9 @@ function setHeaderRowFormat(cells, format) {
14809
14863
  }
14810
14864
  (_b = cells[0]) === null || _b === void 0 ? void 0 : _b.forEach(function (cell) {
14811
14865
  if (cell.td && format.headerRowColor) {
14812
- (0, setColor_1.default)(cell.td, format.headerRowColor, true /** isBackgroundColor*/);
14866
+ if (!hasCellShade(cell)) {
14867
+ (0, setColor_1.default)(cell.td, format.headerRowColor, true /** isBackgroundColor*/, true /** shouldAdaptFontColor */);
14868
+ }
14813
14869
  cell.td.style.borderRightColor = format.headerRowColor;
14814
14870
  cell.td.style.borderLeftColor = format.headerRowColor;
14815
14871
  cell.td.style.borderTopColor = format.headerRowColor;
@@ -16210,14 +16266,24 @@ exports.default = safeInstanceOf;
16210
16266
  "use strict";
16211
16267
 
16212
16268
  Object.defineProperty(exports, "__esModule", { value: true });
16269
+ var WHITE = '#ffffff';
16270
+ var GRAY = '#333333';
16271
+ var BLACK = '#000000';
16272
+ var TRANSPARENT = 'transparent';
16273
+ //Using the HSL (hue, saturation and lightness) representation for RGB color values, if the value of the lightness is less than 20, the color is dark
16274
+ var DARK_COLORS_LIGHTNESS = 20;
16275
+ //If the value of the lightness is more than 80, the color is bright
16276
+ var BRIGHT_COLORS_LIGHTNESS = 80;
16213
16277
  /**
16214
16278
  * Set text color or background color to the given element
16215
16279
  * @param element The element to set color to
16216
16280
  * @param color The color to set, it can be a string of color name/value or a ModeIndependentColor object
16217
16281
  * @param isBackgroundColor Whether set background color or text color
16218
16282
  * @param isDarkMode Whether current mode is dark mode. @default false
16283
+ * @param shouldAdaptTheFontColor Whether the font color needs to be adapted to be visible in a dark or bright background color. @default false
16284
+ * @param defaultFontColor Set the default colors that needs to be set to the to be visible.
16219
16285
  */
16220
- function setColor(element, color, isBackgroundColor, isDarkMode) {
16286
+ function setColor(element, color, isBackgroundColor, isDarkMode, shouldAdaptTheFontColor) {
16221
16287
  var colorString = typeof color === 'string' ? color.trim() : '';
16222
16288
  var modeIndependentColor = typeof color === 'string' ? null : color;
16223
16289
  if (colorString || modeIndependentColor) {
@@ -16235,9 +16301,98 @@ function setColor(element, color, isBackgroundColor, isDarkMode) {
16235
16301
  element.dataset[dataSetName] = modeIndependentColor.lightModeColor;
16236
16302
  }
16237
16303
  }
16304
+ if (isBackgroundColor && shouldAdaptTheFontColor) {
16305
+ adaptFontColorToBackgroundColor(element, isDarkMode);
16306
+ }
16238
16307
  }
16239
16308
  }
16240
16309
  exports.default = setColor;
16310
+ /**
16311
+ * Change the font color to white or some other color, so the text can be visible with a darker background
16312
+ * @param element The element that contains text.
16313
+ */
16314
+ function adaptFontColorToBackgroundColor(element, isDarkMode) {
16315
+ var _a;
16316
+ if ((_a = element.firstElementChild) === null || _a === void 0 ? void 0 : _a.hasAttribute('style')) {
16317
+ return;
16318
+ }
16319
+ var backgroundColor = element.style.getPropertyValue('background-color');
16320
+ var lightModeBackgroundColor = (isDarkMode &&
16321
+ (element.dataset["ogsb" /* OriginalStyleBackgroundColor */] ||
16322
+ element.dataset["ogab" /* OriginalAttributeBackgroundColor */])) ||
16323
+ backgroundColor;
16324
+ if (!lightModeBackgroundColor || lightModeBackgroundColor === TRANSPARENT) {
16325
+ return;
16326
+ }
16327
+ var isADarkOrBrightOrNone = isADarkOrBrightColor(lightModeBackgroundColor);
16328
+ switch (isADarkOrBrightOrNone) {
16329
+ case 1 /* DARK */:
16330
+ var fontForDark = {
16331
+ lightModeColor: WHITE,
16332
+ darkModeColor: GRAY,
16333
+ };
16334
+ setColor(element, fontForDark, false /*isBackground*/, isDarkMode);
16335
+ break;
16336
+ case 0 /* BRIGHT */:
16337
+ var fontForLight = {
16338
+ lightModeColor: BLACK,
16339
+ darkModeColor: WHITE,
16340
+ };
16341
+ setColor(element, fontForLight, false /*isBackground*/, isDarkMode);
16342
+ break;
16343
+ }
16344
+ }
16345
+ function isADarkOrBrightColor(color) {
16346
+ var lightness = calculateLightness(color);
16347
+ if (lightness < DARK_COLORS_LIGHTNESS) {
16348
+ return 1 /* DARK */;
16349
+ }
16350
+ else if (lightness > BRIGHT_COLORS_LIGHTNESS) {
16351
+ return 0 /* BRIGHT */;
16352
+ }
16353
+ return 2 /* NONE */;
16354
+ }
16355
+ /**
16356
+ * Calculate the lightness of HSL (hue, saturation and lightness) representation
16357
+ * @param color a RBG or RGBA COLOR
16358
+ * @returns
16359
+ */
16360
+ function calculateLightness(color) {
16361
+ var _a, _b;
16362
+ var r;
16363
+ var g;
16364
+ var b;
16365
+ if (color.substring(0, 1) == '#') {
16366
+ _a = getColorsFromHEX(color), r = _a[0], g = _a[1], b = _a[2];
16367
+ }
16368
+ else {
16369
+ _b = getColorsFromRGB(color), r = _b[0], g = _b[1], b = _b[2];
16370
+ }
16371
+ // Use the values of r,g,b to calculate the lightness in the HSl representation
16372
+ //First calculate the fraction of the light in each color, since in css the value of r,g,b is in the interval of [0,255], we have
16373
+ var red = r / 255;
16374
+ var green = g / 255;
16375
+ var blue = b / 255;
16376
+ //Then the lightness in the HSL representation is the average between maximum fraction of r,g,b and the minimum fraction
16377
+ return (Math.max(red, green, blue) + Math.min(red, green, blue)) * 50;
16378
+ }
16379
+ function getColorsFromHEX(color) {
16380
+ if (color.length === 4) {
16381
+ color = color.replace(/(.)/g, '$1$1');
16382
+ }
16383
+ var colors = color.replace('#', '');
16384
+ var r = parseInt(colors.substr(0, 2), 16);
16385
+ var g = parseInt(colors.substr(2, 2), 16);
16386
+ var b = parseInt(colors.substr(4, 2), 16);
16387
+ return [r, g, b];
16388
+ }
16389
+ function getColorsFromRGB(color) {
16390
+ var colors = color.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)$/);
16391
+ var r = parseInt(colors[1]);
16392
+ var g = parseInt(colors[2]);
16393
+ var b = parseInt(colors[3]);
16394
+ return [r, g, b];
16395
+ }
16241
16396
 
16242
16397
 
16243
16398
  /***/ }),
@@ -18047,6 +18202,137 @@ exports.TableFeatures = {
18047
18202
  };
18048
18203
 
18049
18204
 
18205
+ /***/ }),
18206
+
18207
+ /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/textFeatures.ts":
18208
+ /*!********************************************************************************************!*\
18209
+ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/textFeatures.ts ***!
18210
+ \********************************************************************************************/
18211
+ /*! no static exports found */
18212
+ /***/ (function(module, exports, __webpack_require__) {
18213
+
18214
+ "use strict";
18215
+
18216
+ Object.defineProperty(exports, "__esModule", { value: true });
18217
+ exports.TextFeatures = void 0;
18218
+ var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
18219
+ var roosterjs_editor_api_1 = __webpack_require__(/*! roosterjs-editor-api */ "./packages/roosterjs-editor-api/lib/index.ts");
18220
+ var TAB_SPACES = 6;
18221
+ /**
18222
+ * Requires @see ExperimentalFeatures.TabKeyTextFeatures to be enabled
18223
+ * Provides additional functionality when press Tab:
18224
+ * If Whole Paragraph selected, indent paragraph,
18225
+ * If range is collapsed, add tab spaces
18226
+ * If range is not collapsed but not all the paragraph is selected, replace selection with Tab spaces
18227
+ * If there are more than one block in the selection, indent all selection
18228
+ */
18229
+ var IndentWhenTabText = {
18230
+ keys: [9 /* TAB */],
18231
+ shouldHandleEvent: function (event, editor) {
18232
+ return editor.isFeatureEnabled("TabKeyTextFeatures" /* TabKeyTextFeatures */) &&
18233
+ !event.rawEvent.shiftKey &&
18234
+ !editor.getElementAtCursor('LI,TABLE', null /*startFrom*/, event);
18235
+ },
18236
+ handleEvent: function (event, editor) {
18237
+ var selection = editor.getSelectionRangeEx();
18238
+ if (selection.type == 0 /* Normal */) {
18239
+ editor.addUndoSnapshot(function () {
18240
+ if (selection.areAllCollapsed) {
18241
+ insertTab(editor, event);
18242
+ }
18243
+ else {
18244
+ var ranges = selection.ranges;
18245
+ var range = ranges[0];
18246
+ if (shouldSetIndentation(editor, range)) {
18247
+ (0, roosterjs_editor_api_1.setIndentation)(editor, 0 /* Increase */);
18248
+ }
18249
+ else {
18250
+ var tempRange = (0, roosterjs_editor_dom_1.createRange)(range.startContainer, range.startOffset);
18251
+ ranges.forEach(function (range) { return range.deleteContents(); });
18252
+ editor.select(tempRange);
18253
+ insertTab(editor, event);
18254
+ }
18255
+ }
18256
+ });
18257
+ event.rawEvent.preventDefault();
18258
+ }
18259
+ },
18260
+ };
18261
+ /**
18262
+ * Requires @see ExperimentalFeatures.TabKeyTextFeatures to be enabled
18263
+ * If Whole Paragraph selected, outdent paragraph on Tab press
18264
+ */
18265
+ var OutdentWhenTabText = {
18266
+ keys: [9 /* TAB */],
18267
+ shouldHandleEvent: function (event, editor) {
18268
+ if (event.rawEvent.shiftKey &&
18269
+ editor.isFeatureEnabled("TabKeyTextFeatures" /* TabKeyTextFeatures */)) {
18270
+ var selection = editor.getSelectionRangeEx();
18271
+ return (selection.type == 0 /* Normal */ &&
18272
+ !selection.areAllCollapsed &&
18273
+ editor.getElementAtCursor('blockquote', null, event) &&
18274
+ !editor.getElementAtCursor('LI,TABLE', null /*startFrom*/, event) &&
18275
+ shouldSetIndentation(editor, selection.ranges[0]));
18276
+ }
18277
+ return false;
18278
+ },
18279
+ handleEvent: function (event, editor) {
18280
+ editor.addUndoSnapshot(function () { return (0, roosterjs_editor_api_1.setIndentation)(editor, 1 /* Decrease */); });
18281
+ event.rawEvent.preventDefault();
18282
+ },
18283
+ };
18284
+ /**
18285
+ * @internal
18286
+ */
18287
+ exports.TextFeatures = {
18288
+ indentWhenTabText: IndentWhenTabText,
18289
+ outdentWhenTabText: OutdentWhenTabText,
18290
+ };
18291
+ function shouldSetIndentation(editor, range) {
18292
+ var result = false;
18293
+ var startPosition = roosterjs_editor_dom_1.Position.getStart(range);
18294
+ var endPosition = roosterjs_editor_dom_1.Position.getEnd(range);
18295
+ var firstBlock = editor.getBlockElementAtNode(startPosition.node);
18296
+ var lastBlock = editor.getBlockElementAtNode(endPosition.node);
18297
+ if (!firstBlock.equals(lastBlock)) {
18298
+ //If the selections has more than one block, we indent all the blocks in the selection
18299
+ return true;
18300
+ }
18301
+ else {
18302
+ //We only indent a single block if all the block is selected.
18303
+ var blockStart = new roosterjs_editor_dom_1.Position(firstBlock.getStartNode(), 0 /* Begin */);
18304
+ var blockEnd = new roosterjs_editor_dom_1.Position(firstBlock.getEndNode(), -1 /* End */);
18305
+ var rangeBefore = (0, roosterjs_editor_dom_1.createRange)(blockStart, roosterjs_editor_dom_1.Position.getStart(range));
18306
+ var rangeAfter = (0, roosterjs_editor_dom_1.createRange)(roosterjs_editor_dom_1.Position.getEnd(range), blockEnd);
18307
+ if (!result && isRangeEmpty(rangeBefore) && isRangeEmpty(rangeAfter)) {
18308
+ result = true;
18309
+ }
18310
+ return result;
18311
+ }
18312
+ }
18313
+ function isRangeEmpty(range) {
18314
+ return (range.toString() == '' &&
18315
+ (0, roosterjs_editor_dom_1.queryElements)(range.commonAncestorContainer, 'img,table,ul,ol', null, 2 /* InSelection */, range).length == 0);
18316
+ }
18317
+ function insertTab(editor, event) {
18318
+ var span = editor.getDocument().createElement('span');
18319
+ var searcher = editor.getContentSearcherOfCursor(event);
18320
+ var charsBefore = searcher.getSubStringBefore(Number.MAX_SAFE_INTEGER);
18321
+ var numberOfChars = TAB_SPACES - (charsBefore.length % TAB_SPACES);
18322
+ var textContent = '';
18323
+ for (var index = 0; index < numberOfChars; index++) {
18324
+ textContent += '&ensp;';
18325
+ }
18326
+ editor.insertNode(span);
18327
+ editor.insertContent(textContent, {
18328
+ position: 5 /* Range */,
18329
+ range: (0, roosterjs_editor_dom_1.createRange)(span, 0 /* Begin */),
18330
+ updateCursor: false,
18331
+ });
18332
+ editor.select((0, roosterjs_editor_dom_1.createRange)(span, -3 /* After */));
18333
+ }
18334
+
18335
+
18050
18336
  /***/ }),
18051
18337
 
18052
18338
  /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/getAllFeatures.ts":
@@ -18079,7 +18365,8 @@ var quoteFeatures_1 = __webpack_require__(/*! ./features/quoteFeatures */ "./pac
18079
18365
  var shortcutFeatures_1 = __webpack_require__(/*! ./features/shortcutFeatures */ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/shortcutFeatures.ts");
18080
18366
  var structuredNodeFeatures_1 = __webpack_require__(/*! ./features/structuredNodeFeatures */ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/structuredNodeFeatures.ts");
18081
18367
  var tableFeatures_1 = __webpack_require__(/*! ./features/tableFeatures */ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/tableFeatures.ts");
18082
- var allFeatures = __assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign({}, listFeatures_1.ListFeatures), quoteFeatures_1.QuoteFeatures), tableFeatures_1.TableFeatures), structuredNodeFeatures_1.StructuredNodeFeatures), autoLinkFeatures_1.AutoLinkFeatures), shortcutFeatures_1.ShortcutFeatures), cursorFeatures_1.CursorFeatures), markdownFeatures_1.MarkdownFeatures), entityFeatures_1.EntityFeatures);
18368
+ var textFeatures_1 = __webpack_require__(/*! ./features/textFeatures */ "./packages/roosterjs-editor-plugins/lib/plugins/ContentEdit/features/textFeatures.ts");
18369
+ var allFeatures = __assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign({}, listFeatures_1.ListFeatures), quoteFeatures_1.QuoteFeatures), tableFeatures_1.TableFeatures), structuredNodeFeatures_1.StructuredNodeFeatures), autoLinkFeatures_1.AutoLinkFeatures), shortcutFeatures_1.ShortcutFeatures), cursorFeatures_1.CursorFeatures), markdownFeatures_1.MarkdownFeatures), entityFeatures_1.EntityFeatures), textFeatures_1.TextFeatures);
18083
18370
  /**
18084
18371
  * Get all content edit features provided by roosterjs
18085
18372
  */