@azure/communication-react 1.17.0-alpha-202405170014 → 1.17.0-alpha-202405220013

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.
Files changed (105) hide show
  1. package/dist/dist-cjs/communication-react/{ChatMessageComponentAsRichTextEditBox-BLFNaheX.js → ChatMessageComponentAsRichTextEditBox-CDsn-zU7.js} +22 -17
  2. package/dist/dist-cjs/communication-react/ChatMessageComponentAsRichTextEditBox-CDsn-zU7.js.map +1 -0
  3. package/dist/dist-cjs/communication-react/{RichTextSendBoxWrapper-BhTpuspw.js → RichTextSendBoxWrapper-Dm4S2bpT.js} +6 -8
  4. package/dist/dist-cjs/communication-react/{RichTextSendBoxWrapper-BhTpuspw.js.map → RichTextSendBoxWrapper-Dm4S2bpT.js.map} +1 -1
  5. package/dist/dist-cjs/communication-react/{index-C9I6Mcil.js → index-DO36MBbq.js} +907 -480
  6. package/dist/dist-cjs/communication-react/index-DO36MBbq.js.map +1 -0
  7. package/dist/dist-cjs/communication-react/index.js +5 -7
  8. package/dist/dist-cjs/communication-react/index.js.map +1 -1
  9. package/dist/dist-esm/acs-ui-common/src/telemetryVersion.js +1 -1
  10. package/dist/dist-esm/acs-ui-common/src/telemetryVersion.js.map +1 -1
  11. package/dist/dist-esm/react-components/src/components/ChatMessage/MyMessageComponents/ChatMessageComponentAsRichTextEditBox.js +17 -10
  12. package/dist/dist-esm/react-components/src/components/ChatMessage/MyMessageComponents/ChatMessageComponentAsRichTextEditBox.js.map +1 -1
  13. package/dist/dist-esm/react-components/src/components/InputBoxComponent.js +1 -1
  14. package/dist/dist-esm/react-components/src/components/InputBoxComponent.js.map +1 -1
  15. package/dist/dist-esm/react-components/src/components/MessageStatusIcon.js +1 -3
  16. package/dist/dist-esm/react-components/src/components/MessageStatusIcon.js.map +1 -1
  17. package/dist/dist-esm/react-components/src/components/ReactionButton.js +1 -1
  18. package/dist/dist-esm/react-components/src/components/ReactionButton.js.map +1 -1
  19. package/dist/dist-esm/react-components/src/components/RichTextEditor/Plugins/ContextMenuPlugin.d.ts +9 -0
  20. package/dist/dist-esm/react-components/src/components/RichTextEditor/Plugins/ContextMenuPlugin.js +29 -0
  21. package/dist/dist-esm/react-components/src/components/RichTextEditor/Plugins/ContextMenuPlugin.js.map +1 -0
  22. package/dist/dist-esm/react-components/src/components/RichTextEditor/Plugins/CopyPastePlugin.d.ts +1 -1
  23. package/dist/dist-esm/react-components/src/components/RichTextEditor/Plugins/CopyPastePlugin.js +15 -20
  24. package/dist/dist-esm/react-components/src/components/RichTextEditor/Plugins/CopyPastePlugin.js.map +1 -1
  25. package/dist/dist-esm/react-components/src/components/RichTextEditor/Plugins/KeyboardInputPlugin.d.ts +12 -0
  26. package/dist/dist-esm/react-components/src/components/RichTextEditor/Plugins/KeyboardInputPlugin.js +23 -0
  27. package/dist/dist-esm/react-components/src/components/RichTextEditor/Plugins/KeyboardInputPlugin.js.map +1 -0
  28. package/dist/dist-esm/react-components/src/components/RichTextEditor/Plugins/PlaceholderPlugin.d.ts +15 -0
  29. package/dist/dist-esm/react-components/src/components/RichTextEditor/Plugins/PlaceholderPlugin.js +39 -0
  30. package/dist/dist-esm/react-components/src/components/RichTextEditor/Plugins/PlaceholderPlugin.js.map +1 -0
  31. package/dist/dist-esm/react-components/src/components/RichTextEditor/Plugins/RichTextToolbarPlugin.d.ts +24 -0
  32. package/dist/dist-esm/react-components/src/components/RichTextEditor/Plugins/RichTextToolbarPlugin.js +66 -0
  33. package/dist/dist-esm/react-components/src/components/RichTextEditor/Plugins/RichTextToolbarPlugin.js.map +1 -0
  34. package/dist/dist-esm/react-components/src/components/RichTextEditor/Plugins/TableEditContextMenuProvider.d.ts +20 -0
  35. package/dist/dist-esm/react-components/src/components/RichTextEditor/Plugins/TableEditContextMenuProvider.js +46 -0
  36. package/dist/dist-esm/react-components/src/components/RichTextEditor/Plugins/TableEditContextMenuProvider.js.map +1 -0
  37. package/dist/dist-esm/react-components/src/components/RichTextEditor/Plugins/UpdateContentPlugin.d.ts +29 -0
  38. package/dist/dist-esm/react-components/src/components/RichTextEditor/Plugins/UpdateContentPlugin.js +71 -0
  39. package/dist/dist-esm/react-components/src/components/RichTextEditor/Plugins/UpdateContentPlugin.js.map +1 -0
  40. package/dist/dist-esm/react-components/src/components/RichTextEditor/RichTextEditor.d.ts +7 -10
  41. package/dist/dist-esm/react-components/src/components/RichTextEditor/RichTextEditor.js +170 -91
  42. package/dist/dist-esm/react-components/src/components/RichTextEditor/RichTextEditor.js.map +1 -1
  43. package/dist/dist-esm/react-components/src/components/RichTextEditor/RichTextInputBoxComponent.d.ts +0 -1
  44. package/dist/dist-esm/react-components/src/components/RichTextEditor/RichTextInputBoxComponent.js +29 -12
  45. package/dist/dist-esm/react-components/src/components/RichTextEditor/RichTextInputBoxComponent.js.map +1 -1
  46. package/dist/dist-esm/react-components/src/components/RichTextEditor/RichTextSendBox.js +12 -46
  47. package/dist/dist-esm/react-components/src/components/RichTextEditor/RichTextSendBox.js.map +1 -1
  48. package/dist/dist-esm/react-components/src/components/RichTextEditor/Toolbar/RichTextToolbar.d.ts +19 -0
  49. package/dist/dist-esm/react-components/src/components/RichTextEditor/Toolbar/RichTextToolbar.js +209 -0
  50. package/dist/dist-esm/react-components/src/components/RichTextEditor/Toolbar/RichTextToolbar.js.map +1 -0
  51. package/dist/dist-esm/react-components/src/components/RichTextEditor/Toolbar/Table/RichTextInsertTableCommandBarItem.d.ts +7 -0
  52. package/dist/dist-esm/react-components/src/components/RichTextEditor/Toolbar/Table/RichTextInsertTableCommandBarItem.js +49 -0
  53. package/dist/dist-esm/react-components/src/components/RichTextEditor/Toolbar/Table/RichTextInsertTableCommandBarItem.js.map +1 -0
  54. package/dist/dist-esm/react-components/src/components/RichTextEditor/{Buttons → Toolbar}/Table/RichTextInsertTablePane.d.ts +2 -2
  55. package/dist/dist-esm/react-components/src/components/RichTextEditor/{Buttons → Toolbar}/Table/RichTextInsertTablePane.js +3 -3
  56. package/dist/dist-esm/react-components/src/components/RichTextEditor/Toolbar/Table/RichTextInsertTablePane.js.map +1 -0
  57. package/dist/dist-esm/react-components/src/components/RichTextEditor/Toolbar/Table/RichTextToolbarTableIcon.d.ts +6 -0
  58. package/dist/dist-esm/react-components/src/components/RichTextEditor/Toolbar/Table/RichTextToolbarTableIcon.js +13 -0
  59. package/dist/dist-esm/react-components/src/components/RichTextEditor/Toolbar/Table/RichTextToolbarTableIcon.js.map +1 -0
  60. package/dist/dist-esm/react-components/src/components/TextFieldWithMention/TextFieldWithMention.js +1 -1
  61. package/dist/dist-esm/react-components/src/components/TextFieldWithMention/TextFieldWithMention.js.map +1 -1
  62. package/dist/dist-esm/react-components/src/components/VideoEffects/VideoBackgroundEffectsPicker.d.ts +5 -7
  63. package/dist/dist-esm/react-components/src/components/VideoEffects/VideoBackgroundEffectsPicker.js +1 -1
  64. package/dist/dist-esm/react-components/src/components/VideoEffects/VideoBackgroundEffectsPicker.js.map +1 -1
  65. package/dist/dist-esm/react-components/src/components/VideoEffects/VideoEffectsItem.d.ts +5 -3
  66. package/dist/dist-esm/react-components/src/components/VideoEffects/VideoEffectsItem.js +2 -8
  67. package/dist/dist-esm/react-components/src/components/VideoEffects/VideoEffectsItem.js.map +1 -1
  68. package/dist/dist-esm/react-components/src/components/styles/MessageThread.styles.js +3 -1
  69. package/dist/dist-esm/react-components/src/components/styles/MessageThread.styles.js.map +1 -1
  70. package/dist/dist-esm/react-components/src/components/styles/RichTextEditor.styles.d.ts +3 -3
  71. package/dist/dist-esm/react-components/src/components/styles/RichTextEditor.styles.js +4 -5
  72. package/dist/dist-esm/react-components/src/components/styles/RichTextEditor.styles.js.map +1 -1
  73. package/dist/dist-esm/react-components/src/components/utils/RichTextEditorUtils.d.ts +37 -0
  74. package/dist/dist-esm/react-components/src/components/utils/RichTextEditorUtils.js +60 -0
  75. package/dist/dist-esm/react-components/src/components/utils/RichTextEditorUtils.js.map +1 -0
  76. package/dist/dist-esm/react-components/src/components/utils/RichTextTableUtils.d.ts +11 -0
  77. package/dist/dist-esm/react-components/src/components/utils/RichTextTableUtils.js +95 -0
  78. package/dist/dist-esm/react-components/src/components/utils/RichTextTableUtils.js.map +1 -1
  79. package/dist/dist-esm/react-components/src/components/utils.d.ts +1 -1
  80. package/dist/dist-esm/react-components/src/components/utils.js +1 -3
  81. package/dist/dist-esm/react-components/src/components/utils.js.map +1 -1
  82. package/dist/dist-esm/react-composites/src/composites/CallComposite/components/SidePane/useVideoEffectsPane.js +7 -4
  83. package/dist/dist-esm/react-composites/src/composites/CallComposite/components/SidePane/useVideoEffectsPane.js.map +1 -1
  84. package/dist/dist-esm/react-composites/src/composites/common/VideoEffectsPane.d.ts +4 -1
  85. package/dist/dist-esm/react-composites/src/composites/common/VideoEffectsPane.js +3 -3
  86. package/dist/dist-esm/react-composites/src/composites/common/VideoEffectsPane.js.map +1 -1
  87. package/package.json +6 -8
  88. package/dist/dist-cjs/communication-react/ChatMessageComponentAsRichTextEditBox-BLFNaheX.js.map +0 -1
  89. package/dist/dist-cjs/communication-react/index-C9I6Mcil.js.map +0 -1
  90. package/dist/dist-esm/react-components/src/components/RichTextEditor/Buttons/RichTextRibbonButtons.d.ts +0 -7
  91. package/dist/dist-esm/react-components/src/components/RichTextEditor/Buttons/RichTextRibbonButtons.js +0 -86
  92. package/dist/dist-esm/react-components/src/components/RichTextEditor/Buttons/RichTextRibbonButtons.js.map +0 -1
  93. package/dist/dist-esm/react-components/src/components/RichTextEditor/Buttons/Table/RichTextInsertTableButton.d.ts +0 -7
  94. package/dist/dist-esm/react-components/src/components/RichTextEditor/Buttons/Table/RichTextInsertTableButton.js +0 -55
  95. package/dist/dist-esm/react-components/src/components/RichTextEditor/Buttons/Table/RichTextInsertTableButton.js.map +0 -1
  96. package/dist/dist-esm/react-components/src/components/RichTextEditor/Buttons/Table/RichTextInsertTablePane.js.map +0 -1
  97. package/dist/dist-esm/react-components/src/components/RichTextEditor/Buttons/Table/RichTextTableContextMenu.d.ts +0 -8
  98. package/dist/dist-esm/react-components/src/components/RichTextEditor/Buttons/Table/RichTextTableContextMenu.js +0 -66
  99. package/dist/dist-esm/react-components/src/components/RichTextEditor/Buttons/Table/RichTextTableContextMenu.js.map +0 -1
  100. package/dist/dist-esm/react-components/src/components/RichTextEditor/Buttons/Table/insertTableAction.d.ts +0 -9
  101. package/dist/dist-esm/react-components/src/components/RichTextEditor/Buttons/Table/insertTableAction.js +0 -56
  102. package/dist/dist-esm/react-components/src/components/RichTextEditor/Buttons/Table/insertTableAction.js.map +0 -1
  103. package/dist/dist-esm/react-components/src/components/utils/RichTextEditorStringsUtils.d.ts +0 -15
  104. package/dist/dist-esm/react-components/src/components/utils/RichTextEditorStringsUtils.js +0 -39
  105. package/dist/dist-esm/react-components/src/components/utils/RichTextEditorStringsUtils.js.map +0 -1
@@ -0,0 +1,24 @@
1
+ import type { ContentModelFormatState, EditorPlugin, IEditor, PluginEvent } from 'roosterjs-content-model-types';
2
+ /**
3
+ * KeyboardInputPlugin is a plugin for handling keyboard events in the editor.
4
+ */
5
+ export declare class RichTextToolbarPlugin implements EditorPlugin {
6
+ private formatState;
7
+ private editor;
8
+ onFormatChanged: ((formatState: ContentModelFormatState) => void) | null;
9
+ getName(): string;
10
+ initialize(editor: IEditor): void;
11
+ dispose(): void;
12
+ onPluginEvent(event: PluginEvent): void;
13
+ /**
14
+ * Handles the click event of a toolbar button.
15
+ * @param buttonAction - The action to be performed when the button is clicked.
16
+ */
17
+ onToolbarButtonClick(buttonAction: (editor: IEditor) => void): void;
18
+ /**
19
+ * Updates the format state of the rich text editor and triggers the `onFormatChanged` callback
20
+ * if there is any difference between the new and the current format states.
21
+ */
22
+ private updateFormat;
23
+ }
24
+ //# sourceMappingURL=RichTextToolbarPlugin.d.ts.map
@@ -0,0 +1,66 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+ import { getFormatState } from 'roosterjs-content-model-api';
4
+ import { getObjectKeys } from 'roosterjs-content-model-dom';
5
+ import { PluginEventType } from '../../utils/RichTextEditorUtils';
6
+ /**
7
+ * KeyboardInputPlugin is a plugin for handling keyboard events in the editor.
8
+ */
9
+ export class RichTextToolbarPlugin {
10
+ constructor() {
11
+ this.formatState = null;
12
+ this.editor = null;
13
+ this.onFormatChanged = null;
14
+ }
15
+ getName() {
16
+ return 'RichTextToolbarPlugin';
17
+ }
18
+ initialize(editor) {
19
+ this.editor = editor;
20
+ }
21
+ dispose() {
22
+ this.editor = null;
23
+ }
24
+ onPluginEvent(event) {
25
+ switch (event.eventType) {
26
+ // KeyDown and MouseUp are used to update the state when the editor is already shown and focused by the user
27
+ case PluginEventType.EditorReady:
28
+ case PluginEventType.ContentChanged:
29
+ case PluginEventType.ZoomChanged:
30
+ case PluginEventType.KeyDown:
31
+ case PluginEventType.MouseUp:
32
+ this.updateFormat();
33
+ break;
34
+ }
35
+ }
36
+ /**
37
+ * Handles the click event of a toolbar button.
38
+ * @param buttonAction - The action to be performed when the button is clicked.
39
+ */
40
+ onToolbarButtonClick(buttonAction) {
41
+ if (this.editor && !this.editor.isDisposed()) {
42
+ buttonAction(this.editor);
43
+ this.updateFormat();
44
+ }
45
+ }
46
+ /**
47
+ * Updates the format state of the rich text editor and triggers the `onFormatChanged` callback
48
+ * if there is any difference between the new and the current format states.
49
+ */
50
+ updateFormat() {
51
+ if (this.editor && this.onFormatChanged) {
52
+ const newFormatState = getFormatState(this.editor);
53
+ // use keys from the format that has more keys or the new format state if there is no current format state
54
+ const keys = !this.formatState || getObjectKeys(newFormatState).length > getObjectKeys(this.formatState).length
55
+ ? getObjectKeys(newFormatState)
56
+ : getObjectKeys(this.formatState);
57
+ // check if there is any difference between the new format state and the current format state
58
+ // otherwise the states will produce new objects every time even when the format state is the same
59
+ if (!this.formatState || keys.some((key) => { var _a; return newFormatState[key] !== ((_a = this.formatState) === null || _a === void 0 ? void 0 : _a[key]); })) {
60
+ this.formatState = newFormatState;
61
+ this.onFormatChanged(newFormatState);
62
+ }
63
+ }
64
+ }
65
+ }
66
+ //# sourceMappingURL=RichTextToolbarPlugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RichTextToolbarPlugin.js","sourceRoot":"","sources":["../../../../../../../../react-components/src/components/RichTextEditor/Plugins/RichTextToolbarPlugin.tsx"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAE5D,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAElE;;GAEG;AACH,MAAM,OAAO,qBAAqB;IAAlC;QACU,gBAAW,GAAmC,IAAI,CAAC;QACnD,WAAM,GAAmB,IAAI,CAAC;QACtC,oBAAe,GAA4D,IAAI,CAAC;IA0DlF,CAAC;IAxDC,OAAO;QACL,OAAO,uBAAuB,CAAC;IACjC,CAAC;IAED,UAAU,CAAC,MAAe;QACxB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,OAAO;QACL,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;IACrB,CAAC;IAED,aAAa,CAAC,KAAkB;QAC9B,QAAQ,KAAK,CAAC,SAAS,EAAE,CAAC;YACxB,4GAA4G;YAC5G,KAAK,eAAe,CAAC,WAAW,CAAC;YACjC,KAAK,eAAe,CAAC,cAAc,CAAC;YACpC,KAAK,eAAe,CAAC,WAAW,CAAC;YACjC,KAAK,eAAe,CAAC,OAAO,CAAC;YAC7B,KAAK,eAAe,CAAC,OAAO;gBAC1B,IAAI,CAAC,YAAY,EAAE,CAAC;gBACpB,MAAM;QACV,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,oBAAoB,CAAC,YAAuC;QAC1D,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,CAAC;YAC7C,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC1B,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,CAAC;IACH,CAAC;IAED;;;OAGG;IACK,YAAY;QAClB,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACxC,MAAM,cAAc,GAAG,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACnD,0GAA0G;YAC1G,MAAM,IAAI,GACR,CAAC,IAAI,CAAC,WAAW,IAAI,aAAa,CAAC,cAAc,CAAC,CAAC,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM;gBAChG,CAAC,CAAC,aAAa,CAAC,cAAc,CAAC;gBAC/B,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACtC,6FAA6F;YAC7F,kGAAkG;YAClG,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,WAAC,OAAA,cAAc,CAAC,GAAG,CAAC,MAAK,MAAA,IAAI,CAAC,WAAW,0CAAG,GAAG,CAAC,CAAA,CAAA,EAAA,CAAC,EAAE,CAAC;gBAC7F,IAAI,CAAC,WAAW,GAAG,cAAc,CAAC;gBAClC,IAAI,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC;YACvC,CAAC;QACH,CAAC;IACH,CAAC;CACF","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport { getFormatState } from 'roosterjs-content-model-api';\nimport { getObjectKeys } from 'roosterjs-content-model-dom';\nimport type { ContentModelFormatState, EditorPlugin, IEditor, PluginEvent } from 'roosterjs-content-model-types';\nimport { PluginEventType } from '../../utils/RichTextEditorUtils';\n\n/**\n * KeyboardInputPlugin is a plugin for handling keyboard events in the editor.\n */\nexport class RichTextToolbarPlugin implements EditorPlugin {\n private formatState: ContentModelFormatState | null = null;\n private editor: IEditor | null = null;\n onFormatChanged: ((formatState: ContentModelFormatState) => void) | null = null;\n\n getName(): string {\n return 'RichTextToolbarPlugin';\n }\n\n initialize(editor: IEditor): void {\n this.editor = editor;\n }\n\n dispose(): void {\n this.editor = null;\n }\n\n onPluginEvent(event: PluginEvent): void {\n switch (event.eventType) {\n // KeyDown and MouseUp are used to update the state when the editor is already shown and focused by the user\n case PluginEventType.EditorReady:\n case PluginEventType.ContentChanged:\n case PluginEventType.ZoomChanged:\n case PluginEventType.KeyDown:\n case PluginEventType.MouseUp:\n this.updateFormat();\n break;\n }\n }\n\n /**\n * Handles the click event of a toolbar button.\n * @param buttonAction - The action to be performed when the button is clicked.\n */\n onToolbarButtonClick(buttonAction: (editor: IEditor) => void): void {\n if (this.editor && !this.editor.isDisposed()) {\n buttonAction(this.editor);\n this.updateFormat();\n }\n }\n\n /**\n * Updates the format state of the rich text editor and triggers the `onFormatChanged` callback\n * if there is any difference between the new and the current format states.\n */\n private updateFormat(): void {\n if (this.editor && this.onFormatChanged) {\n const newFormatState = getFormatState(this.editor);\n // use keys from the format that has more keys or the new format state if there is no current format state\n const keys =\n !this.formatState || getObjectKeys(newFormatState).length > getObjectKeys(this.formatState).length\n ? getObjectKeys(newFormatState)\n : getObjectKeys(this.formatState);\n // check if there is any difference between the new format state and the current format state\n // otherwise the states will produce new objects every time even when the format state is the same\n if (!this.formatState || keys.some((key) => newFormatState[key] !== this.formatState?.[key])) {\n this.formatState = newFormatState;\n this.onFormatChanged(newFormatState);\n }\n }\n }\n}\n"]}
@@ -0,0 +1,20 @@
1
+ import type { ContextMenuProvider, IEditor } from 'roosterjs-content-model-types';
2
+ import { RichTextStrings } from '../RichTextSendBox';
3
+ import { IContextualMenuItem } from '@fluentui/react';
4
+ /**
5
+ * Provides a context menu for editing tables in the rich text editor.
6
+ */
7
+ export declare class TableEditContextMenuProvider implements ContextMenuProvider<IContextualMenuItem> {
8
+ private editor;
9
+ strings: Partial<RichTextStrings>;
10
+ private items;
11
+ updateStrings(strings: Partial<RichTextStrings>): void;
12
+ getName(): string;
13
+ initialize(editor: IEditor): void;
14
+ /**
15
+ * Dispose this plugin
16
+ */
17
+ dispose(): void;
18
+ getContextMenuItems(node: Node): IContextualMenuItem[] | null;
19
+ }
20
+ //# sourceMappingURL=TableEditContextMenuProvider.d.ts.map
@@ -0,0 +1,46 @@
1
+ import { getTableEditContextMenuItems } from '../../utils/RichTextTableUtils';
2
+ /**
3
+ * Provides a context menu for editing tables in the rich text editor.
4
+ */
5
+ export class TableEditContextMenuProvider {
6
+ constructor() {
7
+ this.editor = null;
8
+ this.strings = {};
9
+ this.items = null;
10
+ }
11
+ updateStrings(strings) {
12
+ this.strings = strings;
13
+ if (this.editor) {
14
+ this.items = getTableEditContextMenuItems(this.editor, this.strings);
15
+ }
16
+ }
17
+ getName() {
18
+ return 'TableEditContextMenuProvider';
19
+ }
20
+ initialize(editor) {
21
+ this.editor = editor;
22
+ this.items = getTableEditContextMenuItems(editor, this.strings);
23
+ }
24
+ /**
25
+ * Dispose this plugin
26
+ */
27
+ dispose() {
28
+ this.editor = null;
29
+ }
30
+ getContextMenuItems(node) {
31
+ // return this.items;
32
+ if (this.editor && isTableEditable(this.editor, node)) {
33
+ return this.items;
34
+ }
35
+ else {
36
+ return null;
37
+ }
38
+ }
39
+ }
40
+ const isTableEditable = (editor, node) => {
41
+ const domHelper = editor.getDOMHelper();
42
+ const td = domHelper.findClosestElementAncestor(node, 'TD,TH');
43
+ const table = td && domHelper.findClosestElementAncestor(td, 'table');
44
+ return (table === null || table === void 0 ? void 0 : table.isContentEditable) === true;
45
+ };
46
+ //# sourceMappingURL=TableEditContextMenuProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TableEditContextMenuProvider.js","sourceRoot":"","sources":["../../../../../../../../react-components/src/components/RichTextEditor/Plugins/TableEditContextMenuProvider.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAE9E;;GAEG;AACH,MAAM,OAAO,4BAA4B;IAAzC;QACU,WAAM,GAAmB,IAAI,CAAC;QACtC,YAAO,GAA6B,EAAE,CAAC;QAC/B,UAAK,GAAiC,IAAI,CAAC;IAiCrD,CAAC;IA/BC,aAAa,CAAC,OAAiC;QAC7C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,IAAI,CAAC,KAAK,GAAG,4BAA4B,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO,8BAA8B,CAAC;IACxC,CAAC;IAED,UAAU,CAAC,MAAe;QACxB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,KAAK,GAAG,4BAA4B,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IAClE,CAAC;IAED;;OAEG;IACH,OAAO;QACL,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;IACrB,CAAC;IAED,mBAAmB,CAAC,IAAU;QAC5B,qBAAqB;QACrB,IAAI,IAAI,CAAC,MAAM,IAAI,eAAe,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC;YACtD,OAAO,IAAI,CAAC,KAAK,CAAC;QACpB,CAAC;aAAM,CAAC;YACN,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;CACF;AAED,MAAM,eAAe,GAAG,CAAC,MAAe,EAAE,IAAU,EAAW,EAAE;IAC/D,MAAM,SAAS,GAAG,MAAM,CAAC,YAAY,EAAE,CAAC;IACxC,MAAM,EAAE,GAAG,SAAS,CAAC,0BAA0B,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC/D,MAAM,KAAK,GAAG,EAAE,IAAI,SAAS,CAAC,0BAA0B,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IAEtE,OAAO,CAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,iBAAiB,MAAK,IAAI,CAAC;AAC3C,CAAC,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\nimport type { ContextMenuProvider, IEditor } from 'roosterjs-content-model-types';\nimport { RichTextStrings } from '../RichTextSendBox';\nimport { IContextualMenuItem } from '@fluentui/react';\nimport { getTableEditContextMenuItems } from '../../utils/RichTextTableUtils';\n\n/**\n * Provides a context menu for editing tables in the rich text editor.\n */\nexport class TableEditContextMenuProvider implements ContextMenuProvider<IContextualMenuItem> {\n private editor: IEditor | null = null;\n strings: Partial<RichTextStrings> = {};\n private items: IContextualMenuItem[] | null = null;\n\n updateStrings(strings: Partial<RichTextStrings>): void {\n this.strings = strings;\n if (this.editor) {\n this.items = getTableEditContextMenuItems(this.editor, this.strings);\n }\n }\n\n getName(): string {\n return 'TableEditContextMenuProvider';\n }\n\n initialize(editor: IEditor): void {\n this.editor = editor;\n this.items = getTableEditContextMenuItems(editor, this.strings);\n }\n\n /**\n * Dispose this plugin\n */\n dispose(): void {\n this.editor = null;\n }\n\n getContextMenuItems(node: Node): IContextualMenuItem[] | null {\n // return this.items;\n if (this.editor && isTableEditable(this.editor, node)) {\n return this.items;\n } else {\n return null;\n }\n }\n}\n\nconst isTableEditable = (editor: IEditor, node: Node): boolean => {\n const domHelper = editor.getDOMHelper();\n const td = domHelper.findClosestElementAncestor(node, 'TD,TH');\n const table = td && domHelper.findClosestElementAncestor(td, 'table');\n\n return table?.isContentEditable === true;\n};\n"]}
@@ -0,0 +1,29 @@
1
+ import type { EditorPlugin, IEditor, PluginEvent } from 'roosterjs-content-model-types';
2
+ /**
3
+ * An update mode to indicate when the content update happens
4
+ */
5
+ export declare enum UpdateEvent {
6
+ Init = "Init",
7
+ Dispose = "Dispose",
8
+ ContentChanged = "ContentChanged",
9
+ UserInput = "UserInput",
10
+ Blur = "Blur"
11
+ }
12
+ /**
13
+ * A plugin to handle content update
14
+ */
15
+ export declare class UpdateContentPlugin implements EditorPlugin {
16
+ private editor;
17
+ private disposer;
18
+ onUpdate: ((event: UpdateEvent) => void) | null;
19
+ getName(): string;
20
+ /**
21
+ * Initialize this plugin
22
+ * @param editor The editor instance
23
+ */
24
+ initialize(editor: IEditor): void;
25
+ dispose(): void;
26
+ onPluginEvent(event: PluginEvent): void;
27
+ private onBlur;
28
+ }
29
+ //# sourceMappingURL=UpdateContentPlugin.d.ts.map
@@ -0,0 +1,71 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+ import { PluginEventType } from '../../utils/RichTextEditorUtils';
4
+ /**
5
+ * An update mode to indicate when the content update happens
6
+ */
7
+ export var UpdateEvent;
8
+ (function (UpdateEvent) {
9
+ UpdateEvent["Init"] = "Init";
10
+ UpdateEvent["Dispose"] = "Dispose";
11
+ UpdateEvent["ContentChanged"] = "ContentChanged";
12
+ UpdateEvent["UserInput"] = "UserInput";
13
+ UpdateEvent["Blur"] = "Blur";
14
+ })(UpdateEvent || (UpdateEvent = {}));
15
+ /**
16
+ * A plugin to handle content update
17
+ */
18
+ export class UpdateContentPlugin {
19
+ constructor() {
20
+ this.editor = null;
21
+ this.disposer = null;
22
+ // don't set callback in constructor to be able to update callback without plugin recreation
23
+ this.onUpdate = null;
24
+ this.onBlur = () => {
25
+ if (this.onUpdate === null) {
26
+ return;
27
+ }
28
+ this.onUpdate(UpdateEvent.Blur);
29
+ };
30
+ }
31
+ getName() {
32
+ return 'UpdateContentPlugin';
33
+ }
34
+ /**
35
+ * Initialize this plugin
36
+ * @param editor The editor instance
37
+ */
38
+ initialize(editor) {
39
+ this.editor = editor;
40
+ this.disposer = this.editor.attachDomEvent({
41
+ blur: { beforeDispatch: this.onBlur }
42
+ });
43
+ }
44
+ dispose() {
45
+ this.editor = null;
46
+ if (this.disposer) {
47
+ this.disposer();
48
+ this.disposer = null;
49
+ }
50
+ }
51
+ onPluginEvent(event) {
52
+ if (this.onUpdate === null) {
53
+ return;
54
+ }
55
+ switch (event.eventType) {
56
+ case PluginEventType.EditorReady:
57
+ this.onUpdate(UpdateEvent.Init);
58
+ break;
59
+ case PluginEventType.BeforeDispose:
60
+ this.onUpdate(UpdateEvent.Dispose);
61
+ break;
62
+ case PluginEventType.ContentChanged:
63
+ this.onUpdate(UpdateEvent.ContentChanged);
64
+ break;
65
+ case PluginEventType.Input:
66
+ this.onUpdate(UpdateEvent.UserInput);
67
+ break;
68
+ }
69
+ }
70
+ }
71
+ //# sourceMappingURL=UpdateContentPlugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UpdateContentPlugin.js","sourceRoot":"","sources":["../../../../../../../../react-components/src/components/RichTextEditor/Plugins/UpdateContentPlugin.tsx"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAGlC,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAElE;;GAEG;AACH,MAAM,CAAN,IAAY,WAMX;AAND,WAAY,WAAW;IACrB,4BAAa,CAAA;IACb,kCAAmB,CAAA;IACnB,gDAAiC,CAAA;IACjC,sCAAuB,CAAA;IACvB,4BAAa,CAAA;AACf,CAAC,EANW,WAAW,KAAX,WAAW,QAMtB;AAED;;GAEG;AACH,MAAM,OAAO,mBAAmB;IAAhC;QACU,WAAM,GAAmB,IAAI,CAAC;QAC9B,aAAQ,GAAwB,IAAI,CAAC;QAC7C,4FAA4F;QAC5F,aAAQ,GAA0C,IAAI,CAAC;QAiD/C,WAAM,GAAG,GAAS,EAAE;YAC1B,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;gBAC3B,OAAO;YACT,CAAC;YACD,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAClC,CAAC,CAAC;IACJ,CAAC;IArDC,OAAO;QACL,OAAO,qBAAqB,CAAC;IAC/B,CAAC;IAED;;;OAGG;IACH,UAAU,CAAC,MAAe;QACxB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC;YACzC,IAAI,EAAE,EAAE,cAAc,EAAE,IAAI,CAAC,MAAM,EAAE;SACtC,CAAC,CAAC;IACL,CAAC;IAED,OAAO;QACL,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QAEnB,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,IAAI,CAAC,QAAQ,EAAE,CAAC;YAChB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACvB,CAAC;IACH,CAAC;IAED,aAAa,CAAC,KAAkB;QAC9B,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;YAC3B,OAAO;QACT,CAAC;QACD,QAAQ,KAAK,CAAC,SAAS,EAAE,CAAC;YACxB,KAAK,eAAe,CAAC,WAAW;gBAC9B,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;gBAChC,MAAM;YAER,KAAK,eAAe,CAAC,aAAa;gBAChC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;gBACnC,MAAM;YAER,KAAK,eAAe,CAAC,cAAc;gBACjC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;gBAC1C,MAAM;YAER,KAAK,eAAe,CAAC,KAAK;gBACxB,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;gBACrC,MAAM;QACV,CAAC;IACH,CAAC;CAQF","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { EditorPlugin, IEditor, PluginEvent } from 'roosterjs-content-model-types';\nimport { PluginEventType } from '../../utils/RichTextEditorUtils';\n\n/**\n * An update mode to indicate when the content update happens\n */\nexport enum UpdateEvent {\n Init = 'Init',\n Dispose = 'Dispose',\n ContentChanged = 'ContentChanged',\n UserInput = 'UserInput',\n Blur = 'Blur'\n}\n\n/**\n * A plugin to handle content update\n */\nexport class UpdateContentPlugin implements EditorPlugin {\n private editor: IEditor | null = null;\n private disposer: (() => void) | null = null;\n // don't set callback in constructor to be able to update callback without plugin recreation\n onUpdate: ((event: UpdateEvent) => void) | null = null;\n\n getName(): string {\n return 'UpdateContentPlugin';\n }\n\n /**\n * Initialize this plugin\n * @param editor The editor instance\n */\n initialize(editor: IEditor): void {\n this.editor = editor;\n this.disposer = this.editor.attachDomEvent({\n blur: { beforeDispatch: this.onBlur }\n });\n }\n\n dispose(): void {\n this.editor = null;\n\n if (this.disposer) {\n this.disposer();\n this.disposer = null;\n }\n }\n\n onPluginEvent(event: PluginEvent): void {\n if (this.onUpdate === null) {\n return;\n }\n switch (event.eventType) {\n case PluginEventType.EditorReady:\n this.onUpdate(UpdateEvent.Init);\n break;\n\n case PluginEventType.BeforeDispose:\n this.onUpdate(UpdateEvent.Dispose);\n break;\n\n case PluginEventType.ContentChanged:\n this.onUpdate(UpdateEvent.ContentChanged);\n break;\n\n case PluginEventType.Input:\n this.onUpdate(UpdateEvent.UserInput);\n break;\n }\n }\n\n private onBlur = (): void => {\n if (this.onUpdate === null) {\n return;\n }\n this.onUpdate(UpdateEvent.Blur);\n };\n}\n"]}
@@ -1,7 +1,8 @@
1
1
  import React from 'react';
2
- import { RichTextSendBoxStrings } from './RichTextSendBox';
2
+ import { RichTextStrings } from './RichTextSendBox';
3
+ import type { ContentModelDocument } from 'roosterjs-content-model-types';
3
4
  /**
4
- * Props for {@link RichTextEditor}.
5
+ * Style props for {@link RichTextEditor}.
5
6
  *
6
7
  * @private
7
8
  */
@@ -16,20 +17,16 @@ export interface RichTextEditorStyleProps {
16
17
  */
17
18
  export interface RichTextEditorProps {
18
19
  initialContent?: string;
19
- content?: string;
20
20
  onChange: (newValue?: string) => void;
21
- onKeyDown?: (ev: React.KeyboardEvent<HTMLElement>) => void;
21
+ onKeyDown?: (ev: KeyboardEvent) => void;
22
+ onContentModelUpdate?: (contentModel: ContentModelDocument | undefined) => void;
23
+ contentModel?: ContentModelDocument | undefined;
22
24
  placeholderText?: string;
23
- strings: Partial<RichTextSendBoxStrings>;
25
+ strings: Partial<RichTextStrings>;
24
26
  showRichTextEditorFormatting: boolean;
25
27
  styles: RichTextEditorStyleProps;
26
28
  autoFocus?: 'sendBoxTextField';
27
29
  }
28
- /**
29
- * Props for {@link RichTextEditor}.
30
- *
31
- * @beta
32
- */
33
30
  /**
34
31
  * Represents a reference to the RichTextEditor component.
35
32
  */
@@ -1,27 +1,33 @@
1
1
  // Copyright (c) Microsoft Corporation.
2
2
  // Licensed under the MIT License.
3
- import React, { useCallback, useEffect, useImperativeHandle, useMemo, useRef } from 'react';
4
- import { ContentEdit, Watermark } from 'roosterjs-editor-plugins';
5
- import { Editor } from 'roosterjs-editor-core';
6
- import { CompatibleContentPosition, CompatibleGetContentMode, CompatiblePositionType } from 'roosterjs-editor-types-compatible';
7
- import { Rooster, createUpdateContentPlugin, UpdateMode, createRibbonPlugin, Ribbon, createContextMenuPlugin } from 'roosterjs-react';
8
- import { ribbonButtonStyle, ribbonOverflowButtonStyle, ribbonStyle, richTextEditorWrapperStyle, richTextEditorStyle } from '../styles/RichTextEditor.styles';
3
+ import React, { useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
4
+ import { richTextEditorWrapperStyle, richTextEditorStyle } from '../styles/RichTextEditor.styles';
9
5
  import { useTheme } from '../../theming';
10
- import { ribbonButtons } from './Buttons/RichTextRibbonButtons';
11
6
  import { isDarkThemed } from '../../theming/themeUtils';
12
- import { ribbonButtonsStrings } from '../utils/RichTextEditorStringsUtils';
13
- import { createTableEditMenuProvider } from './Buttons/Table/RichTextTableContextMenu';
14
7
  import CopyPastePlugin from './Plugins/CopyPastePlugin';
8
+ import { createModelFromHtml, Editor, exportContent } from 'roosterjs-content-model-core';
9
+ import { createParagraph, createSelectionMarker, setSelection } from 'roosterjs-content-model-dom';
10
+ import { KeyboardInputPlugin } from './Plugins/KeyboardInputPlugin';
11
+ import { AutoFormatPlugin, EditPlugin, PastePlugin, ShortcutPlugin } from 'roosterjs-content-model-plugins';
12
+ import { UpdateContentPlugin, UpdateEvent } from './Plugins/UpdateContentPlugin';
13
+ import { RichTextToolbar } from './Toolbar/RichTextToolbar';
14
+ import { RichTextToolbarPlugin } from './Plugins/RichTextToolbarPlugin';
15
+ import { ContextMenuPlugin } from './Plugins/ContextMenuPlugin';
16
+ import { TableEditContextMenuProvider } from './Plugins/TableEditContextMenuProvider';
17
+ import { borderApplier, dataSetApplier } from '../utils/RichTextEditorUtils';
18
+ import { ContextualMenu } from '@fluentui/react';
19
+ import PlaceholderPlugin from './Plugins/PlaceholderPlugin';
15
20
  /**
16
21
  * A component to wrap RoosterJS Rich Text Editor.
17
22
  *
18
23
  * @beta
19
24
  */
20
25
  export const RichTextEditor = React.forwardRef((props, ref) => {
21
- const { initialContent, onChange, placeholderText, strings, showRichTextEditorFormatting, content, autoFocus } = props;
26
+ const { initialContent, onChange, placeholderText, strings, showRichTextEditorFormatting, autoFocus, onKeyDown, onContentModelUpdate, contentModel } = props;
22
27
  const editor = useRef(null);
23
- const contentValue = useRef(content);
28
+ const editorDiv = useRef(null);
24
29
  const theme = useTheme();
30
+ const [contextMenuProps, setContextMenuProps] = useState(null);
25
31
  useImperativeHandle(ref, () => {
26
32
  return {
27
33
  focus() {
@@ -31,108 +37,181 @@ export const RichTextEditor = React.forwardRef((props, ref) => {
31
37
  },
32
38
  setEmptyContent() {
33
39
  if (editor.current) {
34
- editor.current.setContent('');
40
+ // remove all content from the editor and update the model
41
+ // ContentChanged event will be sent by RoosterJS automatically
42
+ editor.current.formatContentModel((model) => {
43
+ model.blocks = [];
44
+ return true;
45
+ });
46
+ //reset content model
47
+ onContentModelUpdate && onContentModelUpdate(undefined);
35
48
  }
36
49
  },
37
50
  getPlainContent() {
38
- var _a;
39
- return (_a = editor === null || editor === void 0 ? void 0 : editor.current) === null || _a === void 0 ? void 0 : _a.getContent(CompatibleGetContentMode.PlainTextFast);
51
+ if (editor.current) {
52
+ return exportContent(editor.current, 'PlainTextFast');
53
+ }
54
+ else {
55
+ return undefined;
56
+ }
40
57
  }
41
58
  };
59
+ }, [onContentModelUpdate]);
60
+ const toolbarPlugin = React.useMemo(() => {
61
+ return new RichTextToolbarPlugin();
42
62
  }, []);
43
- const ribbonPlugin = React.useMemo(() => {
44
- return createRibbonPlugin();
45
- }, []);
46
- const editorCreator = useCallback((div, options) => {
47
- const editorValue = new Editor(div, options);
48
- // this is to fix issue when editor is created or re-rendered and has existing text
49
- // Content model package has a correct behavior and this fix can be deleted
50
- if (contentValue.current !== undefined && contentValue.current.length > 0) {
51
- // in case if initialContent is not empty, RoosterJS doesn't set caret position to the end.
52
- focusAndUpdateContent(editorValue, contentValue.current);
53
- }
54
- else if (initialContent !== undefined && initialContent.length > 0) {
55
- // changing layout in rich text send box cause the editor to be recreated
56
- // to keep the content, we need to set messageContent to the current content
57
- focusAndUpdateContent(editorValue, initialContent);
58
- }
59
- editor.current = editorValue;
60
- return editorValue;
61
- },
62
- // trigger force editor reset when strings are changed to update context menu strings
63
- // see RosterJS documentation for 'editorCreator' for more details
64
- // the editorCreator callback shouldn't be updated when the initialContent is changed
65
- // eslint-disable-next-line react-hooks/exhaustive-deps
66
- [strings]);
67
- const placeholderPlugin = React.useMemo(() => {
68
- return new Watermark('');
63
+ const isDarkThemedValue = useMemo(() => {
64
+ return isDarkThemed(theme);
65
+ }, [theme]);
66
+ useEffect(() => {
67
+ var _a;
68
+ (_a = editor.current) === null || _a === void 0 ? void 0 : _a.setDarkModeState(isDarkThemedValue);
69
+ }, [isDarkThemedValue]);
70
+ const placeholderPlugin = useMemo(() => {
71
+ return new PlaceholderPlugin('');
69
72
  }, []);
70
73
  useEffect(() => {
71
74
  if (placeholderText !== undefined) {
72
- placeholderPlugin.updateWatermark(placeholderText);
75
+ placeholderPlugin.updatePlaceholder(placeholderText);
73
76
  }
74
77
  }, [placeholderPlugin, placeholderText]);
75
- const plugins = useMemo(() => {
76
- // contextPlugin and tableEditMenuProvider allow to show insert/delete menu for the table
77
- const contextPlugin = createContextMenuPlugin();
78
- const tableEditMenuProvider = createTableEditMenuProvider(strings);
79
- const contentEdit = new ContentEdit();
80
- const updateContentPlugin = createUpdateContentPlugin(UpdateMode.OnContentChangedEvent | UpdateMode.OnUserInput, (content) => {
81
- onChange && onChange(content);
78
+ const toolbar = useMemo(() => {
79
+ return React.createElement(RichTextToolbar, { plugin: toolbarPlugin, strings: strings });
80
+ }, [strings, toolbarPlugin]);
81
+ const updatePlugin = useMemo(() => {
82
+ return new UpdateContentPlugin();
83
+ }, []);
84
+ useEffect(() => {
85
+ // don't set callback in plugin constructor to update callback without plugin recreation
86
+ updatePlugin.onUpdate = (event) => {
87
+ if (editor.current === null) {
88
+ return;
89
+ }
90
+ if (event === UpdateEvent.Blur || event === UpdateEvent.Dispose) {
91
+ onContentModelUpdate && onContentModelUpdate(editor.current.getContentModelCopy('disconnected'));
92
+ }
93
+ else {
94
+ onChange && onChange(exportContent(editor.current));
95
+ }
96
+ };
97
+ }, [onChange, onContentModelUpdate, updatePlugin]);
98
+ const keyboardInputPlugin = useMemo(() => {
99
+ return new KeyboardInputPlugin();
100
+ }, []);
101
+ useEffect(() => {
102
+ // don't set callback in plugin constructor to update callback without plugin recreation
103
+ keyboardInputPlugin.onKeyDown = onKeyDown;
104
+ }, [keyboardInputPlugin, onKeyDown]);
105
+ const tableContextMenuPlugin = useMemo(() => {
106
+ return new TableEditContextMenuProvider();
107
+ }, []);
108
+ useEffect(() => {
109
+ tableContextMenuPlugin.updateStrings(strings);
110
+ }, [tableContextMenuPlugin, strings]);
111
+ const onContextMenuRender = useCallback((container, items, onDismiss) => {
112
+ setContextMenuProps({
113
+ items: items,
114
+ target: container,
115
+ onDismiss: onDismiss
82
116
  });
117
+ }, []);
118
+ const onContextMenuDismiss = useCallback(() => {
119
+ setContextMenuProps(null);
120
+ }, []);
121
+ const plugins = useMemo(() => {
122
+ const contentEdit = new EditPlugin();
123
+ // AutoFormatPlugin previously was a part of the edit plugin
124
+ const autoFormatPlugin = new AutoFormatPlugin({ autoBullet: true, autoNumbering: true, autoLink: true });
83
125
  const copyPastePlugin = new CopyPastePlugin();
126
+ const roosterPastePlugin = new PastePlugin(false);
127
+ const shortcutPlugin = new ShortcutPlugin();
128
+ const contextMenuPlugin = new ContextMenuPlugin(onContextMenuRender, onContextMenuDismiss);
84
129
  return [
85
- contentEdit,
86
130
  placeholderPlugin,
87
- updateContentPlugin,
88
- ribbonPlugin,
89
- contextPlugin,
90
- tableEditMenuProvider,
91
- copyPastePlugin
131
+ keyboardInputPlugin,
132
+ contentEdit,
133
+ autoFormatPlugin,
134
+ updatePlugin,
135
+ copyPastePlugin,
136
+ roosterPastePlugin,
137
+ toolbarPlugin,
138
+ shortcutPlugin,
139
+ // contextPlugin and tableEditMenuProvider allow to show insert/delete menu for the table
140
+ contextMenuPlugin,
141
+ tableContextMenuPlugin
92
142
  ];
93
- }, [onChange, placeholderPlugin, ribbonPlugin, strings]);
94
- const ribbon = useMemo(() => {
95
- const buttons = ribbonButtons(theme);
96
- return (React.createElement(Ribbon, { styles: ribbonStyle, buttons: buttons, plugin: ribbonPlugin, overflowButtonProps: {
97
- styles: ribbonButtonStyle(theme),
98
- menuProps: {
99
- items: [], // CommandBar will determine items rendered in overflow
100
- isBeakVisible: false,
101
- styles: ribbonOverflowButtonStyle(theme)
143
+ }, [
144
+ onContextMenuRender,
145
+ onContextMenuDismiss,
146
+ placeholderPlugin,
147
+ keyboardInputPlugin,
148
+ updatePlugin,
149
+ toolbarPlugin,
150
+ tableContextMenuPlugin
151
+ ]);
152
+ useEffect(() => {
153
+ var _a;
154
+ const initialModel = createEditorInitialModel(initialContent, contentModel);
155
+ if (editorDiv.current) {
156
+ editor.current = new Editor(editorDiv.current, {
157
+ inDarkMode: isDarkThemedValue,
158
+ // doNotAdjustEditorColor is used to disable default color and background color for Rooster component
159
+ doNotAdjustEditorColor: true,
160
+ // TODO: confirm the color during inline images implementation
161
+ imageSelectionBorderColor: 'blue',
162
+ plugins: plugins,
163
+ initialModel: initialModel,
164
+ defaultModelToDomOptions: {
165
+ formatApplierOverride: {
166
+ // apply border and dataset formats for table
167
+ border: borderApplier,
168
+ dataset: dataSetApplier
169
+ }
102
170
  }
103
- }, strings: ribbonButtonsStrings(strings), "data-testid": 'rich-text-editor-ribbon' }));
104
- }, [strings, ribbonPlugin, theme]);
105
- const defaultFormat = useMemo(() => {
106
- // without setting any styles, text input is not handled properly for tables (when insert or paste one in the editor)
107
- // because of https://github.com/microsoft/roosterjs/blob/14dbb947e3ae94580109cbd05e48ceb05327c4dc/packages/roosterjs-editor-core/lib/corePlugins/TypeInContainerPlugin.ts#L75
108
- // this issue is fixed for content model package
109
- return {
110
- backgroundColor: 'transparent'
171
+ });
172
+ }
173
+ if (autoFocus === 'sendBoxTextField') {
174
+ (_a = editor.current) === null || _a === void 0 ? void 0 : _a.focus();
175
+ }
176
+ return () => {
177
+ if (editor.current) {
178
+ editor.current.dispose();
179
+ editor.current = null;
180
+ }
111
181
  };
182
+ // don't update the editor on deps update as everything is handled in separate hooks or plugins
183
+ // eslint-disable-next-line react-hooks/exhaustive-deps
112
184
  }, []);
113
185
  return (React.createElement("div", { "data-testid": 'rich-text-editor-wrapper' },
114
- showRichTextEditorFormatting && ribbon,
186
+ showRichTextEditorFormatting && toolbar,
115
187
  React.createElement("div", { className: richTextEditorWrapperStyle(theme, !showRichTextEditorFormatting) },
116
- React.createElement(Rooster, { defaultFormat: defaultFormat, inDarkMode: isDarkThemed(theme), plugins: plugins, className: richTextEditorStyle(props.styles), editorCreator: editorCreator,
117
- // TODO: confirm the color during inline images implementation
118
- imageSelectionBorderColor: 'blue',
119
- // doNotAdjustEditorColor is used to fix the default background color for Rooster component
120
- doNotAdjustEditorColor: true, "data-testid": 'rooster-rich-text-editor',
121
- // if we don't use 'allowKeyboardEventPropagation' only the enter key is caught
122
- onKeyDown: props.onKeyDown, focusOnInit: autoFocus === 'sendBoxTextField' }))));
188
+ React.createElement("div", { ref: editorDiv, tabIndex: 0, role: "textbox", "aria-multiline": "true", "data-testid": 'rooster-rich-text-editor', className: richTextEditorStyle(props.styles) })),
189
+ contextMenuProps && React.createElement(ContextualMenu, Object.assign({}, contextMenuProps, { calloutProps: { isBeakVisible: false } }))));
123
190
  });
124
- const focusAndUpdateContent = (editor, content) => {
125
- // setting focus before setting content, works for Chrome and Edge but not Safari
126
- editor.setContent(content);
127
- // this is a recommended way (by RoosterJS team) to set focus at the end of the text
128
- // RoosterJS v9 has this issue fixed and this code can be removed
129
- // CompatibleContentPosition.DomEnd shouldn't be used here as it set focus after the editor div
130
- editor.insertContent('<span id="focus-position-span"></span>', { position: CompatibleContentPosition.End });
131
- const elements = editor.queryElements('#focus-position-span');
132
- if (elements.length > 0) {
133
- const placeholder = editor.queryElements('#focus-position-span')[0];
134
- editor.select(placeholder, CompatiblePositionType.Before);
135
- placeholder.remove();
191
+ const createEditorInitialModel = (initialContent, contentModel) => {
192
+ if (contentModel) {
193
+ // contentModel is the current content of the editor
194
+ return contentModel;
195
+ }
196
+ else {
197
+ const initialContentValue = initialContent;
198
+ const initialModel = initialContentValue && initialContentValue.length > 0 ? createModelFromHtml(initialContentValue) : undefined;
199
+ if (initialModel && initialModel.blocks.length > 0) {
200
+ // lastBlock should have blockType = paragraph, otherwise add a new paragraph
201
+ // to set focus to the end of the content
202
+ let lastBlock = initialModel.blocks[initialModel.blocks.length - 1];
203
+ if ((lastBlock === null || lastBlock === void 0 ? void 0 : lastBlock.blockType) === 'Paragraph') {
204
+ // now lastBlock is paragraph
205
+ }
206
+ else {
207
+ lastBlock = createParagraph(true);
208
+ initialModel.blocks.push(lastBlock);
209
+ }
210
+ const marker = createSelectionMarker();
211
+ lastBlock.segments.push(marker);
212
+ setSelection(initialModel, marker);
213
+ }
214
+ return initialModel;
136
215
  }
137
216
  };
138
217
  //# sourceMappingURL=RichTextEditor.js.map