@instructure/canvas-rce 5.14.2 → 5.15.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.
Files changed (267) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/DEVELOPMENT.md +1 -1
  3. package/es/bridge/Bridge.js +10 -17
  4. package/es/canvasFileBrowser/FileBrowser.js +10 -19
  5. package/es/common/FlashAlert.js +8 -11
  6. package/es/common/fileUrl.js +6 -10
  7. package/es/common/incremental-loading/LoadMoreButton.js +3 -4
  8. package/es/common/incremental-loading/LoadingStatus.js +4 -11
  9. package/es/common/indicate.js +1 -2
  10. package/es/defaultTinymceConfig.js +1 -1
  11. package/es/enhance-user-content/doc_previews.js +10 -10
  12. package/es/enhance-user-content/enhance_user_content.js +4 -7
  13. package/es/enhance-user-content/external_links.js +1 -1
  14. package/es/enhance-user-content/instructure_helper.js +11 -17
  15. package/es/enhance-user-content/mathml.js +15 -27
  16. package/es/enhance-user-content/media_comment_thumbnail.js +3 -10
  17. package/es/format-message.js +2 -2
  18. package/es/index.d.ts +59 -0
  19. package/es/index.js +3 -5
  20. package/es/rce/AlertMessageArea.js +15 -16
  21. package/es/rce/KeyboardShortcutModal.js +2 -2
  22. package/es/rce/RCE.js +6 -8
  23. package/es/rce/RCEVariants.js +2 -4
  24. package/es/rce/RCEWrapper.js +397 -289
  25. package/es/rce/RCEWrapper.utils.js +131 -0
  26. package/es/rce/RCEWrapperProps.js +2 -3
  27. package/es/rce/RceHtmlEditor.js +12 -11
  28. package/es/rce/ResizeHandle.js +1 -2
  29. package/es/rce/ShowOnFocusButton/index.js +2 -2
  30. package/es/rce/StatusBar.js +5 -10
  31. package/es/rce/contentInsertion.js +1 -2
  32. package/es/rce/contentRendering.js +6 -5
  33. package/es/rce/editorLanguage.js +1 -1
  34. package/es/rce/indicatorRegion.js +1 -2
  35. package/es/rce/normalizeProps.js +4 -4
  36. package/es/rce/plugins/instructure_color/clickCallback.js +2 -4
  37. package/es/rce/plugins/instructure_color/components/ColorPicker.js +17 -22
  38. package/es/rce/plugins/instructure_color/components/ColorPopup.js +7 -8
  39. package/es/rce/plugins/instructure_condensed_buttons/ui/list-button.js +4 -10
  40. package/es/rce/plugins/instructure_condensed_buttons/ui/subscript-superscript-button.js +1 -1
  41. package/es/rce/plugins/instructure_documents/components/Link.js +1 -2
  42. package/es/rce/plugins/instructure_equation/EquationEditorModal/index.js +5 -8
  43. package/es/rce/plugins/instructure_equation/EquationEditorModal/latexTextareaUtil.js +3 -3
  44. package/es/rce/plugins/instructure_equation/EquationEditorModal/parseLatex.js +3 -3
  45. package/es/rce/plugins/instructure_equation/EquationEditorToolbar/buttons.js +2 -2
  46. package/es/rce/plugins/instructure_equation/EquationEditorToolbar/index.js +9 -11
  47. package/es/rce/plugins/instructure_equation/MathIcon/index.js +3 -4
  48. package/es/rce/plugins/instructure_equation/mathlive/index.js +167 -16
  49. package/es/rce/plugins/instructure_fullscreen/plugin.js +0 -2
  50. package/es/rce/plugins/instructure_icon_maker/clickCallback.js +3 -4
  51. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ColorSection.js +46 -49
  52. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/CreateIconMakerForm.js +9 -10
  53. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/Footer.js +10 -11
  54. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/Group.js +5 -6
  55. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/Header.js +7 -8
  56. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/Course.js +7 -9
  57. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/ImageOptions.js +19 -26
  58. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/ImageSection.js +8 -12
  59. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/ModeSelect.js +6 -7
  60. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/MultiColor/index.js +5 -6
  61. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/SVGList.js +6 -7
  62. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/SVGThumbnail.js +8 -10
  63. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/SingleColor/index.js +5 -6
  64. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/SingleColor/svg.js +32 -80
  65. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/Upload.js +7 -8
  66. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/utils.js +4 -5
  67. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/Preview.js +3 -4
  68. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ShapeSection.js +4 -5
  69. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/TextSection.js +4 -5
  70. package/es/rce/plugins/instructure_icon_maker/components/IconMakerTray.js +22 -29
  71. package/es/rce/plugins/instructure_icon_maker/registerEditToolbar.js +1 -1
  72. package/es/rce/plugins/instructure_icon_maker/svg/image.js +5 -7
  73. package/es/rce/plugins/instructure_icon_maker/svg/index.js +6 -9
  74. package/es/rce/plugins/instructure_icon_maker/svg/settings.js +17 -20
  75. package/es/rce/plugins/instructure_icon_maker/svg/shape.js +4 -5
  76. package/es/rce/plugins/instructure_icon_maker/svg/text.js +28 -32
  77. package/es/rce/plugins/instructure_icon_maker/svg/utils.js +2 -4
  78. package/es/rce/plugins/instructure_icon_maker/utils/IconMakerClose.js +2 -3
  79. package/es/rce/plugins/instructure_icon_maker/utils/iconValidation.js +1 -2
  80. package/es/rce/plugins/instructure_image/ImageEmbedOptions.js +3 -7
  81. package/es/rce/plugins/instructure_image/ImageList/Image.js +7 -8
  82. package/es/rce/plugins/instructure_image/ImageList/index.js +7 -8
  83. package/es/rce/plugins/instructure_image/ImageOptionsTray/TrayController.js +2 -4
  84. package/es/rce/plugins/instructure_image/ImageOptionsTray/index.js +3 -3
  85. package/es/rce/plugins/instructure_image/plugin.js +1 -2
  86. package/es/rce/plugins/instructure_links/components/AccordionSection.js +7 -8
  87. package/es/rce/plugins/instructure_links/components/Link.js +61 -65
  88. package/es/rce/plugins/instructure_links/components/LinkOptionsDialog/LinkOptionsDialogController.js +1 -2
  89. package/es/rce/plugins/instructure_links/components/LinkOptionsDialog/index.js +2 -2
  90. package/es/rce/plugins/instructure_links/components/LinkOptionsTray/index.js +2 -2
  91. package/es/rce/plugins/instructure_links/components/LinkSet.js +28 -37
  92. package/es/rce/plugins/instructure_links/components/LinksPanel.js +21 -8
  93. package/es/rce/plugins/instructure_links/components/NoResults.js +6 -7
  94. package/es/rce/plugins/instructure_links/plugin.js +6 -9
  95. package/es/rce/plugins/instructure_media_embed/clickCallback.js +3 -4
  96. package/es/rce/plugins/instructure_media_embed/components/Embed.js +6 -7
  97. package/es/rce/plugins/instructure_paste/plugin.js +5 -7
  98. package/es/rce/plugins/instructure_rce_external_tools/ExternalToolsEnv.js +24 -33
  99. package/es/rce/plugins/instructure_rce_external_tools/RceToolWrapper.js +7 -38
  100. package/es/rce/plugins/instructure_rce_external_tools/components/ExternalToolDialog/ExternalToolDialog.js +30 -29
  101. package/es/rce/plugins/instructure_rce_external_tools/components/ExternalToolSelectionDialog/ExternalToolSelectionDialog.js +3 -4
  102. package/es/rce/plugins/instructure_rce_external_tools/dialog-helper.js +1 -2
  103. package/es/rce/plugins/instructure_rce_external_tools/jquery/jquery.dropdownList.js +3 -4
  104. package/es/rce/plugins/instructure_rce_external_tools/lti11-content-items/RceLti11ContentItem.js +17 -24
  105. package/es/rce/plugins/instructure_rce_external_tools/lti13-content-items/RceLti13ContentItem.js +2 -2
  106. package/es/rce/plugins/instructure_rce_external_tools/lti13-content-items/models/BaseLinkContentItem.js +4 -5
  107. package/es/rce/plugins/instructure_rce_external_tools/lti13-content-items/processEditorContentItems.js +8 -9
  108. package/es/rce/plugins/instructure_rce_external_tools/lti13-content-items/rceLti13ContentItemFromJson.js +0 -1
  109. package/es/rce/plugins/instructure_rce_external_tools/plugin.js +4 -4
  110. package/es/rce/plugins/instructure_rce_external_tools/util/externalToolsForToolbar.js +42 -0
  111. package/es/rce/plugins/instructure_record/AudioOptionsTray/TrayController.js +5 -10
  112. package/es/rce/plugins/instructure_record/AudioOptionsTray/index.js +12 -13
  113. package/es/rce/plugins/instructure_record/VideoOptionsTray/TrayController.js +8 -15
  114. package/es/rce/plugins/instructure_record/VideoOptionsTray/index.js +19 -20
  115. package/es/rce/plugins/instructure_record/clickCallback.js +26 -30
  116. package/es/rce/plugins/instructure_search_and_replace/clickCallback.js +2 -3
  117. package/es/rce/plugins/instructure_search_and_replace/components/FindReplaceTray.js +14 -16
  118. package/es/rce/plugins/instructure_search_and_replace/components/FindReplaceTrayController.js +9 -12
  119. package/es/rce/plugins/instructure_search_and_replace/plugin.js +1 -2
  120. package/es/rce/plugins/instructure_wordcount/clickCallback.js +3 -4
  121. package/es/rce/plugins/instructure_wordcount/components/WordCountModal.js +26 -33
  122. package/es/rce/plugins/instructure_wordcount/utils/countContent.js +3 -3
  123. package/es/rce/plugins/instructure_wordcount/utils/tableContent.js +5 -8
  124. package/es/rce/plugins/shared/CanvasContentTray.js +9 -16
  125. package/es/rce/plugins/shared/ColorInput.js +22 -25
  126. package/es/rce/plugins/shared/ConditionalTooltip.js +5 -6
  127. package/es/rce/plugins/shared/ContentSelection.js +12 -20
  128. package/es/rce/plugins/shared/DimensionUtils.js +2 -4
  129. package/es/rce/plugins/shared/EventUtils.js +1 -1
  130. package/es/rce/plugins/shared/FixedContentTray.js +13 -14
  131. package/es/rce/plugins/shared/ImageCropper/DirectionRegion.js +3 -4
  132. package/es/rce/plugins/shared/ImageCropper/Modal.js +12 -13
  133. package/es/rce/plugins/shared/ImageCropper/Preview.js +11 -13
  134. package/es/rce/plugins/shared/ImageCropper/controls/CustomNumberInput.js +8 -9
  135. package/es/rce/plugins/shared/ImageCropper/controls/ResetControls.js +3 -4
  136. package/es/rce/plugins/shared/ImageCropper/controls/RotationControls.js +4 -5
  137. package/es/rce/plugins/shared/ImageCropper/controls/ShapeControls.js +7 -11
  138. package/es/rce/plugins/shared/ImageCropper/controls/ZoomControls.js +4 -5
  139. package/es/rce/plugins/shared/ImageCropper/controls/index.js +4 -5
  140. package/es/rce/plugins/shared/ImageCropper/controls/useDebouncedNumericValue.js +13 -15
  141. package/es/rce/plugins/shared/ImageCropper/imageCropUtils.js +18 -21
  142. package/es/rce/plugins/shared/ImageCropper/svg/shape.js +4 -5
  143. package/es/rce/plugins/shared/ImageCropper/svg/utils.js +2 -4
  144. package/es/rce/plugins/shared/ImageCropper/useKeyMouseEvents.js +1 -4
  145. package/es/rce/plugins/shared/ImageOptionsForm.js +17 -18
  146. package/es/rce/plugins/shared/LinkDisplay.js +8 -9
  147. package/es/rce/plugins/shared/PreviewIcon.js +8 -9
  148. package/es/rce/plugins/shared/RceFileBrowser.js +2 -3
  149. package/es/rce/plugins/shared/StoreContext.js +8 -10
  150. package/es/rce/plugins/shared/StudioLtiSupportUtils.js +5 -6
  151. package/es/rce/plugins/shared/Upload/CanvasContentPanel.js +6 -7
  152. package/es/rce/plugins/shared/Upload/CategoryProcessor.js +1 -2
  153. package/es/rce/plugins/shared/Upload/ComputerPanel.js +11 -14
  154. package/es/rce/plugins/shared/Upload/PanelFilter.js +7 -8
  155. package/es/rce/plugins/shared/Upload/UploadFile.js +19 -22
  156. package/es/rce/plugins/shared/Upload/UploadFileModal.js +28 -34
  157. package/es/rce/plugins/shared/Upload/UrlPanel.js +4 -5
  158. package/es/rce/plugins/shared/Upload/UsageRightsSelectBox.js +18 -24
  159. package/es/rce/plugins/shared/Upload/doFileUpload.js +6 -7
  160. package/es/rce/plugins/shared/ai_tools/AIResponseModal.js +7 -8
  161. package/es/rce/plugins/shared/ai_tools/AIToolsTray.js +14 -17
  162. package/es/rce/plugins/shared/ai_tools/aiicons.js +2 -2
  163. package/es/rce/plugins/shared/canvasContentUtils.js +1 -2
  164. package/es/rce/plugins/shared/compressionUtils.js +17 -20
  165. package/es/rce/plugins/shared/do-fetch-api-effect/doFetchApi.js +12 -15
  166. package/es/rce/plugins/shared/do-fetch-api-effect/get-cookie.js +1 -1
  167. package/es/rce/plugins/shared/fileTypeUtils.js +3 -6
  168. package/es/rce/plugins/shared/round.js +1 -2
  169. package/es/rce/plugins/shared/trayUtils.js +3 -0
  170. package/es/rce/plugins/shared/useDataUrl.js +4 -5
  171. package/es/rce/plugins/tinymce-a11y-checker/components/ColorField.js +2 -2
  172. package/es/rce/plugins/tinymce-a11y-checker/components/checker.js +8 -10
  173. package/es/rce/plugins/tinymce-a11y-checker/node-checker.js +1 -3
  174. package/es/rce/plugins/tinymce-a11y-checker/plugin.js +14 -17
  175. package/es/rce/plugins/tinymce-a11y-checker/rules/headings-start-at-h2.js +1 -2
  176. package/es/rce/plugins/tinymce-a11y-checker/rules/large-text-contrast.js +1 -2
  177. package/es/rce/plugins/tinymce-a11y-checker/rules/small-text-contrast.js +1 -2
  178. package/es/rce/plugins/tinymce-a11y-checker/utils/dom.js +2 -4
  179. package/es/rce/plugins/tinymce-a11y-checker/utils/indicate.js +2 -3
  180. package/es/rce/plugins/tinymce-a11y-checker/utils/rgb-hex.js +1 -4
  181. package/es/rce/root.js +9 -9
  182. package/es/rce/tinyRCE.js +1 -0
  183. package/es/rce/transformContent.js +1 -1
  184. package/es/rcs/api.js +39 -55
  185. package/es/rcs/buildError.js +3 -3
  186. package/es/rcs/fake.js +5 -7
  187. package/es/sidebar/actions/documents.js +10 -12
  188. package/es/sidebar/actions/files.js +18 -22
  189. package/es/sidebar/actions/filter.js +4 -5
  190. package/es/sidebar/actions/images.js +20 -26
  191. package/es/sidebar/actions/media.js +15 -18
  192. package/es/sidebar/actions/session.js +1 -2
  193. package/es/sidebar/actions/upload.js +26 -37
  194. package/es/sidebar/containers/sidebarHandlers.js +6 -12
  195. package/es/sidebar/dragHtml.js +6 -2
  196. package/es/sidebar/reducers/all_files.js +1 -3
  197. package/es/sidebar/reducers/collection.js +1 -3
  198. package/es/sidebar/reducers/collections.js +1 -3
  199. package/es/sidebar/reducers/documents.js +1 -3
  200. package/es/sidebar/reducers/files.js +1 -3
  201. package/es/sidebar/reducers/filter.js +7 -15
  202. package/es/sidebar/reducers/flickr.js +1 -3
  203. package/es/sidebar/reducers/folder.js +1 -3
  204. package/es/sidebar/reducers/folders.js +1 -3
  205. package/es/sidebar/reducers/images.js +1 -3
  206. package/es/sidebar/reducers/media.js +1 -3
  207. package/es/sidebar/reducers/newPageLinkExpanded.js +1 -3
  208. package/es/sidebar/reducers/noop.js +1 -2
  209. package/es/sidebar/reducers/rootFolderId.js +1 -3
  210. package/es/sidebar/reducers/session.js +1 -3
  211. package/es/sidebar/reducers/ui.js +3 -9
  212. package/es/sidebar/reducers/upload.js +8 -24
  213. package/es/sidebar/store/initialState.js +1 -2
  214. package/es/translations/locales/ar.js +6 -0
  215. package/es/translations/locales/ca.js +6 -0
  216. package/es/translations/locales/cy.js +6 -0
  217. package/es/translations/locales/da-x-k12.js +6 -0
  218. package/es/translations/locales/da.js +6 -0
  219. package/es/translations/locales/de.js +6 -0
  220. package/es/translations/locales/en-AU-x-unimelb.js +6 -0
  221. package/es/translations/locales/en-GB-x-ukhe.js +6 -0
  222. package/es/translations/locales/en_AU.js +6 -0
  223. package/es/translations/locales/en_CA.js +6 -0
  224. package/es/translations/locales/en_CY.js +6 -0
  225. package/es/translations/locales/en_GB.js +6 -0
  226. package/es/translations/locales/es.js +6 -0
  227. package/es/translations/locales/es_ES.js +6 -0
  228. package/es/translations/locales/fi.js +6 -0
  229. package/es/translations/locales/fr.js +6 -0
  230. package/es/translations/locales/fr_CA.js +6 -0
  231. package/es/translations/locales/hi.js +6 -0
  232. package/es/translations/locales/ht.js +6 -0
  233. package/es/translations/locales/id.js +6 -0
  234. package/es/translations/locales/is.js +6 -0
  235. package/es/translations/locales/it.js +6 -0
  236. package/es/translations/locales/ja.js +6 -0
  237. package/es/translations/locales/mi.js +6 -0
  238. package/es/translations/locales/ms.js +6 -0
  239. package/es/translations/locales/nb-x-k12.js +6 -0
  240. package/es/translations/locales/nb.js +6 -0
  241. package/es/translations/locales/nl.js +6 -0
  242. package/es/translations/locales/pl.js +6 -0
  243. package/es/translations/locales/pt.js +6 -0
  244. package/es/translations/locales/pt_BR.js +6 -0
  245. package/es/translations/locales/ru.js +6 -0
  246. package/es/translations/locales/sl.js +6 -0
  247. package/es/translations/locales/sv-x-k12.js +6 -0
  248. package/es/translations/locales/sv.js +6 -0
  249. package/es/translations/locales/th.js +6 -0
  250. package/es/translations/locales/vi.js +6 -0
  251. package/es/translations/locales/zh-Hans.js +6 -0
  252. package/es/translations/locales/zh-Hant.js +6 -0
  253. package/es/translations/locales/zh.js +6 -0
  254. package/es/translations/locales/zh_HK.js +6 -0
  255. package/es/util/elem-util.js +1 -1
  256. package/es/util/file-url-util.js +1 -1
  257. package/es/util/fullscreenHelpers.js +6 -9
  258. package/es/util/loadingPlaceholder.js +2 -3
  259. package/es/util/simpleCache.js +1 -2
  260. package/es/util/url-util.js +5 -5
  261. package/eslint.config.js +15 -4
  262. package/locales/en.json +190 -10
  263. package/package.json +56 -55
  264. package/scripts/installTranslations.js +7 -8
  265. package/tsconfig.json +1 -1
  266. package/types/format-message-generate-id.d.ts +22 -0
  267. package/types/js-beautify.d.ts +21 -0
@@ -1,4 +1,4 @@
1
- var _Intl, _Intl$DateTimeFormat, _Intl$DateTimeFormat$;
1
+ import _pt from "prop-types";
2
2
  /*
3
3
  * Copyright (C) 2018 - present Instructure, Inc.
4
4
  *
@@ -21,7 +21,6 @@ import React, { Suspense } from 'react';
21
21
  import { Editor } from '@tinymce/tinymce-react';
22
22
  import _ from 'lodash';
23
23
  import { StoreProvider } from './plugins/shared/StoreContext';
24
- import { RCEWrapperInterface } from './types';
25
24
  import { IconKeyboardShortcutsLine } from '@instructure/ui-icons';
26
25
  import { Alert } from '@instructure/ui-alerts';
27
26
  import { Spinner } from '@instructure/ui-spinner';
@@ -33,12 +32,12 @@ import getCookie from '../common/getCookie';
33
32
  import formatMessage from '../format-message';
34
33
  import * as contentInsertion from './contentInsertion';
35
34
  import indicatorRegion from './indicatorRegion';
36
- import editorLanguage from './editorLanguage';
35
+ import { editorLanguage } from './editorLanguage';
37
36
  import normalizeLocale from './normalizeLocale';
38
37
  import { sanitizePlugins } from './sanitizePlugins';
39
38
  import RCEGlobals from './RCEGlobals';
40
39
  import defaultTinymceConfig from '../defaultTinymceConfig';
41
- import { FS_CHANGEEVENT, FS_ELEMENT, FS_ENABLED, FS_EXIT, FS_REQUEST, instuiPopupMountNode } from '../util/fullscreenHelpers';
40
+ import { FS_CHANGEEVENT, FS_ELEMENT, FS_ENABLED, FS_EXIT, FS_REQUEST, instuiPopupMountNodeFn } from '../util/fullscreenHelpers';
42
41
  import indicate from '../common/indicate';
43
42
  import bridge from '../bridge';
44
43
  import CanvasContentTray from './plugins/shared/CanvasContentTray';
@@ -57,11 +56,13 @@ import contentCSS from './tinymce.oxide.content.min.css';
57
56
  import { rceWrapperPropTypes } from './RCEWrapperProps';
58
57
  import { insertPlaceholder, placeholderInfoFor, removePlaceholder } from '../util/loadingPlaceholder';
59
58
  import { transformRceContentForEditing } from './transformContent';
59
+ // @ts-expect-error
60
60
  import { IconMoreSolid } from '@instructure/ui-icons/es/svg';
61
61
  import EncryptedStorage from '../util/encrypted-storage';
62
62
  import buildStyle from './style';
63
- import { externalToolsForToolbar } from './plugins/instructure_rce_external_tools/RceToolWrapper';
64
63
  import { getMenubarForVariant, getMenuForVariant, getToolbarForVariant, getStatusBarFeaturesForVariant } from './RCEVariants';
64
+ import { focusFirstMenuButton, focusToolbar, isElementWithinTable, mergeMenu, mergeMenuItems, mergePlugins, mergeToolbar, parsePluginsToExclude, patchAutosavedContent } from './RCEWrapper.utils';
65
+ import { externalToolsForToolbar } from './plugins/instructure_rce_external_tools/util/externalToolsForToolbar';
65
66
  const RestoreAutoSaveModal = /*#__PURE__*/React.lazy(() => import('./RestoreAutoSaveModal'));
66
67
  const RceHtmlEditor = /*#__PURE__*/React.lazy(() => import('./RceHtmlEditor'));
67
68
  const ASYNC_FOCUS_TIMEOUT = 250;
@@ -94,24 +95,6 @@ function injectTinySkin() {
94
95
  document.head.insertBefore(style, beforeMe);
95
96
  }
96
97
  const editorWrappers = new WeakMap();
97
- function focusToolbar(el) {
98
- const $firstToolbarButton = el.querySelector('.tox-tbtn');
99
- $firstToolbarButton && $firstToolbarButton.focus();
100
- }
101
- function focusFirstMenuButton(el) {
102
- const $firstMenu = el.querySelector('.tox-mbtn');
103
- $firstMenu && $firstMenu.focus();
104
- }
105
- function isElementWithinTable(node) {
106
- let elem = node;
107
- while (elem) {
108
- if (elem.tagName === 'TABLE' || elem.tagName === 'TD' || elem.tagName === 'TH') {
109
- return true;
110
- }
111
- elem = elem.parentElement;
112
- }
113
- return false;
114
- }
115
98
 
116
99
  // determines if localStorage is available for our use.
117
100
  // see https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API
@@ -147,12 +130,37 @@ class RCEWrapper extends React.Component {
147
130
  return editorWrappers.get(editor);
148
131
  }
149
132
  constructor(props) {
150
- var _this, _window, _window$location, _props$editorOptions, _props$editorOptions2;
151
133
  super(props);
152
- _this = this;
134
+ this._destroyCalled = false;
135
+ this._editorPlaceholderRef = void 0;
136
+ this._elementRef = void 0;
137
+ this._focusRegio = void 0;
138
+ this._focusRegion = void 0;
139
+ this._mceSerializedInitialHtmlCached = void 0;
140
+ this._showOnFocusButton = void 0;
141
+ this._statusBarId = void 0;
142
+ this._textareaEl = void 0;
143
+ this.AIToolsTray = void 0;
144
+ this.editor = void 0;
145
+ this.initialContent = void 0;
146
+ this.intersectionObserver = void 0;
147
+ this.language = void 0;
148
+ this.ltiToolFavorites = void 0;
149
+ this.mutationObserver = void 0;
150
+ this.pendingEventHandlers = void 0;
151
+ this.pluginsToExclude = void 0;
152
+ this.resizeObserver = void 0;
153
+ this.storage = void 0;
154
+ this.variant = void 0;
155
+ this.style = void 0;
156
+ this.insert_code = void 0;
157
+ this.get_code = void 0;
158
+ this.set_code = void 0;
153
159
  this.onRemove = () => {
154
160
  bridge.detachEditor(this);
155
- this.props.onRemove && this.props.onRemove(this);
161
+ if (this.props.onRemove) {
162
+ this.props.onRemove(this);
163
+ }
156
164
  };
157
165
  this.toggleView = newView => {
158
166
  // coming from the menubar, we don't have a newView,
@@ -160,25 +168,34 @@ class RCEWrapper extends React.Component {
160
168
  let newState;
161
169
  switch (this.state.editorView) {
162
170
  case WYSIWYG_VIEW:
163
- newState = {
164
- editorView: newView || PRETTY_HTML_EDITOR_VIEW
165
- };
166
- break;
171
+ {
172
+ newState = {
173
+ editorView: newView || PRETTY_HTML_EDITOR_VIEW
174
+ };
175
+ break;
176
+ }
167
177
  case PRETTY_HTML_EDITOR_VIEW:
168
- newState = {
169
- editorView: newView || WYSIWYG_VIEW
170
- };
171
- break;
178
+ {
179
+ newState = {
180
+ editorView: newView || WYSIWYG_VIEW
181
+ };
182
+ break;
183
+ }
172
184
  case RAW_HTML_EDITOR_VIEW:
173
- newState = {
174
- editorView: newView || WYSIWYG_VIEW
175
- };
185
+ {
186
+ newState = {
187
+ editorView: newView || WYSIWYG_VIEW
188
+ };
189
+ break;
190
+ }
191
+ default:
192
+ return;
176
193
  }
194
+ // @ts-expect-error
177
195
  this.setState(newState);
178
196
  this.checkAccessibility();
179
197
  if (newView === PRETTY_HTML_EDITOR_VIEW || newView === RAW_HTML_EDITOR_VIEW) {
180
- var _this$storage, _this$storage$setItem;
181
- (_this$storage = this.storage) === null || _this$storage === void 0 ? void 0 : (_this$storage$setItem = _this$storage.setItem) === null || _this$storage$setItem === void 0 ? void 0 : _this$storage$setItem.call(_this$storage, 'rce.htmleditor', newView);
198
+ this.storage?.setItem?.('rce.htmleditor', newView);
182
199
  }
183
200
 
184
201
  // Emit view change event
@@ -192,18 +209,18 @@ class RCEWrapper extends React.Component {
192
209
  };
193
210
  this._onFullscreenChange = event => {
194
211
  if (document[FS_ELEMENT]) {
195
- var _window$visualViewpor;
212
+ // @ts-expect-error
196
213
  this.resizeObserver.observe(document[FS_ELEMENT]);
197
- (_window$visualViewpor = window.visualViewport) === null || _window$visualViewpor === void 0 ? void 0 : _window$visualViewpor.addEventListener('resize', this._handleFullscreenResize);
214
+ window.visualViewport?.addEventListener('resize', this._handleFullscreenResize);
198
215
  this._handleFullscreenResize();
216
+ // @ts-expect-error
199
217
  this._focusRegion = FocusRegionManager.activateRegion(document[FS_ELEMENT], {
200
218
  shouldContainFocus: true
201
219
  });
202
220
  } else {
203
- var _window$visualViewpor2;
204
221
  event.target.removeEventListener(FS_CHANGEEVENT, this._onFullscreenChange);
205
222
  this.resizeObserver.unobserve(event.target);
206
- (_window$visualViewpor2 = window.visualViewport) === null || _window$visualViewpor2 === void 0 ? void 0 : _window$visualViewpor2.removeEventListener('resize', this._handleFullscreenResize);
223
+ window.visualViewport?.removeEventListener('resize', this._handleFullscreenResize);
207
224
  this._setHeight(this.state.fullscreenState.prevHeight);
208
225
  if (this._focusRegion) {
209
226
  FocusRegionManager.blurRegion(event.target, this._focusRegion.id);
@@ -212,36 +229,38 @@ class RCEWrapper extends React.Component {
212
229
  this.focusCurrentView();
213
230
  };
214
231
  this._handleFullscreenResize = () => {
215
- var _window$visualViewpor3, _document$FS_ELEMENT;
216
- const ht = ((_window$visualViewpor3 = window.visualViewport) === null || _window$visualViewpor3 === void 0 ? void 0 : _window$visualViewpor3.height) || ((_document$FS_ELEMENT = document[FS_ELEMENT]) === null || _document$FS_ELEMENT === void 0 ? void 0 : _document$FS_ELEMENT.offsetHeight);
217
- this._setHeight(ht - this._getStatusBarHeight());
232
+ const ht = window.visualViewport?.height || document[FS_ELEMENT]?.offsetHeight;
233
+ this._setHeight((ht || 0) - this._getStatusBarHeight());
218
234
  };
219
235
  this.contentTrayClosing = false;
220
236
  this.blurTimer = 0;
221
- this.handleFocusRCE = event => {
222
- this.handleFocus(event);
237
+ this.handleFocusRCE = () => {
238
+ this.handleFocus();
223
239
  };
224
240
  this.handleBlurRCE = event => {
225
- var _this$_elementRef$cur;
226
241
  if (event.relatedTarget === null) {
227
242
  // focus might be moving to tinymce
228
243
  this.handleBlur(event);
229
244
  }
230
- if (!((_this$_elementRef$cur = this._elementRef.current) !== null && _this$_elementRef$cur !== void 0 && _this$_elementRef$cur.contains(event.relatedTarget))) {
245
+ if (!this._elementRef.current?.contains(event.relatedTarget)) {
231
246
  this.handleBlur(event);
232
247
  }
233
248
  };
234
- this.handleFocusEditor = (event, _editor) => {
249
+ this.handleFocusEditor = _event => {
235
250
  // use .active to put a focus ring around the content area
236
251
  // when the editor has focus. This isn't perfect, but it's
237
252
  // what we've got for now.
238
253
  const ifr = this.iframe;
239
- ifr && ifr.parentElement.classList.add('active');
240
- this.handleFocus(event);
254
+ if (ifr?.parentElement) {
255
+ ifr.parentElement.classList.add('active');
256
+ }
257
+ this.handleFocus();
241
258
  };
242
- this.handleBlurEditor = (event, _editor) => {
259
+ this.handleBlurEditor = event => {
243
260
  const ifr = this.iframe;
244
- ifr && ifr.parentElement.classList.remove('active');
261
+ if (ifr?.parentElement) {
262
+ ifr.parentElement.classList.remove('active');
263
+ }
245
264
  this.handleBlur(event);
246
265
  };
247
266
  this.handleKey = event => {
@@ -249,11 +268,13 @@ class RCEWrapper extends React.Component {
249
268
  event.preventDefault();
250
269
  event.stopPropagation();
251
270
  this.setFocusAbilityForHeader(true);
271
+ // @ts-expect-error
252
272
  focusFirstMenuButton(this._elementRef.current);
253
273
  } else if (event.code === 'F10' && event.altKey) {
254
274
  event.preventDefault();
255
275
  event.stopPropagation();
256
276
  this.setFocusAbilityForHeader(true);
277
+ // @ts-expect-error
257
278
  focusToolbar(this._elementRef.current);
258
279
  } else if (event.code === 'F8' && event.altKey) {
259
280
  event.preventDefault();
@@ -277,19 +298,23 @@ class RCEWrapper extends React.Component {
277
298
  this.checkAccessibility();
278
299
  };
279
300
  this.onInit = (_event, editor) => {
280
- var _this$props$onInitted, _this$props;
301
+ // @ts-expect-error
281
302
  editor.rceWrapper = this;
282
303
  this.editor = editor;
283
304
  const textarea = this.editor.getElement();
284
305
 
285
306
  // expected by canvas
307
+ // @ts-expect-error
286
308
  textarea.dataset.rich_text = true;
287
309
 
288
310
  // start with the textarea and tinymce in sync
311
+ // @ts-expect-error
289
312
  textarea.value = this.getCode();
290
313
  textarea.style.height = this.state.height;
291
314
  if (document.body.classList.contains('Underline-All-Links__enabled')) {
292
- this.iframe.contentDocument.body.classList.add('Underline-All-Links__enabled');
315
+ if (this.iframe?.contentDocument) {
316
+ this.iframe.contentDocument.body.classList.add('Underline-All-Links__enabled');
317
+ }
293
318
  }
294
319
  editor.on('wordCountUpdate', this.onWordCountUpdate);
295
320
  // add an aria-label to the application div that wraps RCE
@@ -303,9 +328,11 @@ class RCEWrapper extends React.Component {
303
328
  }
304
329
 
305
330
  // Adds a focusout event listener for handling screen reader navigation focus
306
- const header = this._elementRef.current.querySelector('.tox-editor-header');
331
+ const header = this._elementRef.current?.querySelector('.tox-editor-header');
307
332
  if (header) {
333
+ // @ts-expect-error
308
334
  header.addEventListener('focusout', e => {
335
+ // @ts-expect-error
309
336
  const leavingHeader = !header.contains(e.relatedTarget);
310
337
  if (leavingHeader) {
311
338
  this.setFocusAbilityForHeader(false);
@@ -345,35 +372,36 @@ class RCEWrapper extends React.Component {
345
372
  this._setupSelectionSaving(editor);
346
373
  this.checkAccessibility();
347
374
  this.fixToolbarKeyboardNavigation();
348
- (_this$props$onInitted = (_this$props = this.props).onInitted) === null || _this$props$onInitted === void 0 ? void 0 : _this$props$onInitted.call(_this$props, editor);
375
+ if (this.props.onInitted) {
376
+ this.props.onInitted(editor);
377
+ }
349
378
 
350
379
  // cleans up highlight artifacts from findreplace plugin
351
380
  if (this.getRequiredFeatureStatuses().rce_find_replace) {
352
- editor.on('undo redo', e => {
353
- var _editor$dom, _editor$dom$doc, _editor$dom$doc$getEl, _editor$dom$doc$getEl2;
354
- if ((editor === null || editor === void 0 ? void 0 : (_editor$dom = editor.dom) === null || _editor$dom === void 0 ? void 0 : (_editor$dom$doc = _editor$dom.doc) === null || _editor$dom$doc === void 0 ? void 0 : (_editor$dom$doc$getEl = _editor$dom$doc.getElementsByClassName) === null || _editor$dom$doc$getEl === void 0 ? void 0 : (_editor$dom$doc$getEl2 = _editor$dom$doc$getEl.call(_editor$dom$doc, 'mce-match-marker')) === null || _editor$dom$doc$getEl2 === void 0 ? void 0 : _editor$dom$doc$getEl2.length) > 0) {
355
- var _editor$plugins, _editor$plugins$searc;
356
- (_editor$plugins = editor.plugins) === null || _editor$plugins === void 0 ? void 0 : (_editor$plugins$searc = _editor$plugins.searchreplace) === null || _editor$plugins$searc === void 0 ? void 0 : _editor$plugins$searc.done();
381
+ editor.on('undo redo', _e => {
382
+ if (editor?.dom?.doc?.getElementsByClassName?.('mce-match-marker')?.length > 0) {
383
+ editor.plugins?.searchreplace?.done();
357
384
  }
358
385
  });
359
386
  }
360
387
  };
361
388
  this.fixToolbarKeyboardNavigation = () => {
362
- var _this$_elementRef$cur2;
363
389
  // The keyboard navigation config in tinymce for the expanded toolbar is incorrectly configured,
364
390
  // and stops at [data-alloy-tabstop] elements.
365
391
  // It should be configured to stop on .tox-toolbar__group elements.
366
392
  // This workaround removes attribute, thusly causing navigation to work correctly again.
367
393
  // For the correct solution, Keying.config should have { selector: '.tox-toolbar__group' }
368
394
  // in https://github.com/tinymce/tinymce/blob/develop/modules/alloy/src/main/ts/ephox/alloy/ui/schema/SplitSlidingToolbarSchema.ts
369
- (_this$_elementRef$cur2 = this._elementRef.current) === null || _this$_elementRef$cur2 === void 0 ? void 0 : _this$_elementRef$cur2.querySelectorAll('.tox-toolbar-overlord button[data-alloy-tabstop]').forEach(it => it.removeAttribute('data-alloy-tabstop'));
395
+ this._elementRef.current?.querySelectorAll('.tox-toolbar-overlord button[data-alloy-tabstop]').forEach(it => it.removeAttribute('data-alloy-tabstop'));
370
396
  };
371
397
  this._setupSelectionSaving = editor => {
398
+ // @ts-expect-error
372
399
  let savedSelection = null;
373
400
  let selectionWasReset = false;
374
401
  let editorHasFocus = false;
375
402
  const restoreSelectionIfNecessary = () => {
376
- if (savedSelection && selectionWasReset) {
403
+ // @ts-expect-error
404
+ if (this.editor && savedSelection && selectionWasReset) {
377
405
  this.editor.selection.setRng(savedSelection.range, savedSelection.isForward);
378
406
  selectionWasReset = false;
379
407
  }
@@ -381,6 +409,7 @@ class RCEWrapper extends React.Component {
381
409
  editor.on('blur', () => {
382
410
  editorHasFocus = false;
383
411
  selectionWasReset = false;
412
+ if (!this.editor) return;
384
413
  savedSelection = {
385
414
  range: this.editor.selection.getRng().cloneRange(),
386
415
  isForward: this.editor.selection.isForward()
@@ -396,16 +425,16 @@ class RCEWrapper extends React.Component {
396
425
  selectionWasReset = false;
397
426
  });
398
427
  editor.on('SelectionChange', () => {
399
- var _selection$startConta;
400
428
  if (editorHasFocus) {
401
429
  // We don't care if a selection reset occurs when the editor has focus, the user probably intended that
402
430
  // At least they will see the effect
403
431
  return;
404
432
  }
433
+ if (!this.editor) return;
405
434
  const selection = this.editor.selection.normalize();
406
435
 
407
436
  // Detect a browser-reset selection (e.g. From invoking the Find command)
408
- if (((_selection$startConta = selection.startContainer) === null || _selection$startConta === void 0 ? void 0 : _selection$startConta.nodeName) === 'BODY' && selection.startContainer === selection.endContainer && selection.startOffset === 0 && selection.endOffset === 0) {
437
+ if (selection.startContainer?.nodeName === 'BODY' && selection.startContainer === selection.endContainer && selection.startOffset === 0 && selection.endOffset === 0) {
409
438
  selectionWasReset = true;
410
439
  }
411
440
  });
@@ -414,6 +443,7 @@ class RCEWrapper extends React.Component {
414
443
  });
415
444
  editor.on('ExecCommand', (/* event */
416
445
  ) => {
446
+ if (!this.editor) return;
417
447
  // Commands may have modified the selection, we need to recapture it
418
448
  savedSelection = {
419
449
  range: this.editor.selection.getRng().cloneRange(),
@@ -435,14 +465,15 @@ class RCEWrapper extends React.Component {
435
465
  // We'll compare just the text of the autosave content, since
436
466
  // Canvas is prone to swizzling images and iframes which will
437
467
  // make the editor content and autosave content never match up
438
- const editorContent = this.patchAutosavedContent(editor.getContent({
468
+ const editorContent = patchAutosavedContent(editor.getContent({
439
469
  no_events: true
440
470
  }), true);
441
- const autosavedContent = this.patchAutosavedContent(autosaved.content, true);
471
+ const autosavedContent = patchAutosavedContent(autosaved.content, true);
442
472
  if (autosavedContent !== editorContent) {
443
473
  this.setState({
444
474
  confirmAutoSave: true,
445
- autoSavedContent: this.patchAutosavedContent(autosaved.content)
475
+ // @ts-expect-error
476
+ autoSavedContent: patchAutosavedContent(autosaved.content)
446
477
  });
447
478
  } else {
448
479
  this.storage.removeItem(this.autoSaveKey);
@@ -450,22 +481,21 @@ class RCEWrapper extends React.Component {
450
481
  }
451
482
  } catch (ex) {
452
483
  // log and ignore
453
- // eslint-disable-next-line no-console
484
+
454
485
  console.error('Failed initializing rce autosave', ex);
455
486
  }
456
487
  }
457
488
  };
458
- this.cleanupAutoSave = function () {
459
- let deleteAll = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
460
- if (_this.storage) {
461
- const expiry = deleteAll ? Date.now() : Date.now() - _this.props.autosave.maxAge;
489
+ this.cleanupAutoSave = (deleteAll = false) => {
490
+ if (this.storage) {
491
+ const expiry = deleteAll ? Date.now() : Date.now() - (this.props.autosave?.maxAge || 0);
462
492
  let i = 0;
463
493
  let key;
464
- while (key = _this.storage.key(i++)) {
494
+ while (key = this.storage.key(i++)) {
465
495
  if (/^rceautosave:/.test(key)) {
466
- const autosaved = _this.getAutoSaved(key);
496
+ const autosaved = this.getAutoSaved(key);
467
497
  if (autosaved && autosaved.autosaveTimestamp < expiry) {
468
- _this.storage.removeItem(key);
498
+ this.storage.removeItem(key);
469
499
  }
470
500
  }
471
501
  }
@@ -479,15 +509,15 @@ class RCEWrapper extends React.Component {
479
509
  if (ans) {
480
510
  editor.setContent(this.state.autoSavedContent, {});
481
511
  }
512
+ // @ts-expect-error
482
513
  this.storage.removeItem(this.autoSaveKey);
483
514
  });
484
515
  // let the content be restored
485
516
  debounce(this.checkAccessibility, 1000)();
486
517
  };
487
- this.doAutoSave = function (e) {
488
- let retry = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
489
- if (_this.storage) {
490
- const editor = _this.mceInstance();
518
+ this.doAutoSave = (e, retry = false) => {
519
+ if (this.storage) {
520
+ const editor = this.mceInstance();
491
521
  // if the editor is empty don't save
492
522
  if (editor.dom.isEmpty(editor.getBody())) {
493
523
  return;
@@ -496,20 +526,21 @@ class RCEWrapper extends React.Component {
496
526
  no_events: true
497
527
  });
498
528
  try {
499
- _this.storage.setItem(_this.autoSaveKey, content);
529
+ this.storage.setItem(this.autoSaveKey, content);
500
530
  } catch (ex) {
501
531
  if (!retry) {
502
532
  // probably failed because there's not enough space
503
533
  // delete up all the other entries and try again
504
- _this.cleanupAutoSave(true);
505
- _this.doAutoSave(e, true);
534
+ this.cleanupAutoSave(true);
535
+ this.doAutoSave(e, true);
506
536
  } else {
507
- console.error('Autosave failed:', ex); // eslint-disable-line no-console
537
+ console.error('Autosave failed:', ex);
508
538
  }
509
539
  }
510
540
  }
511
541
  };
512
542
  this.onWordCountUpdate = e => {
543
+ if (!this.editor) return;
513
544
  const shouldIgnore = countShouldIgnore(this.editor, 'body', 'words');
514
545
  const updatedCount = e.wordCount.words - shouldIgnore;
515
546
  this.setState(state => {
@@ -522,14 +553,15 @@ class RCEWrapper extends React.Component {
522
553
  };
523
554
  this.onNodeChange = e => {
524
555
  // This is basically copied out of the tinymce silver theme code for the status bar
525
- const path = e.parents.filter(p => p.nodeName !== 'BR' && !p.getAttribute('data-mce-bogus') && p.getAttribute('data-mce-type') !== 'bookmark').map(p => p.nodeName.toLowerCase()).reverse();
556
+ const path = e.parents.filter(p => p.nodeName !== 'BR' && !p.getAttribute('data-mce-bogus') && p.getAttribute('data-mce-type') !== 'bookmark')
557
+ // @ts-expect-error
558
+ .map(p => p.nodeName.toLowerCase()).reverse();
526
559
  this.setState({
527
560
  path
528
561
  });
529
562
  };
530
563
  this.onEditorChange = (content, _editor) => {
531
- var _this$props$onContent, _this$props2;
532
- (_this$props$onContent = (_this$props2 = this.props).onContentChange) === null || _this$props$onContent === void 0 ? void 0 : _this$props$onContent.call(_this$props2, content);
564
+ this.props.onContentChange?.(content);
533
565
  // check accessibility when clearing the editor,
534
566
  // all other times should be checked by handleInputChange
535
567
  if (content === '') {
@@ -542,11 +574,14 @@ class RCEWrapper extends React.Component {
542
574
  const container = editor.getContainer();
543
575
  if (!container) return;
544
576
  const currentContainerHeight = Number.parseInt(container.style.height, 10);
545
- if (isNaN(currentContainerHeight)) return; // eslint-disable-line no-restricted-globals
577
+ if (isNaN(currentContainerHeight)) return;
546
578
  const modifiedHeight = currentContainerHeight + coordinates.deltaY;
547
579
  const newHeight = `${modifiedHeight}px`;
548
580
  container.style.height = newHeight;
549
- this.getTextarea().style.height = newHeight;
581
+ const textarea = this.getTextarea();
582
+ if (textarea) {
583
+ textarea.style.height = newHeight;
584
+ }
550
585
  this.setState({
551
586
  height: newHeight
552
587
  });
@@ -557,7 +592,7 @@ class RCEWrapper extends React.Component {
557
592
  this.onA11yChecker = triggerElementId => {
558
593
  const editor = this.mceInstance();
559
594
  editor.execCommand('openAccessibilityChecker', false, {
560
- mountNode: instuiPopupMountNode,
595
+ mountNode: instuiPopupMountNodeFn,
561
596
  triggerElementId,
562
597
  onFixError: errors => {
563
598
  this.setState({
@@ -571,6 +606,7 @@ class RCEWrapper extends React.Component {
571
606
  this.checkAccessibility = () => {
572
607
  const editor = this.mceInstance();
573
608
  editor.execCommand('checkAccessibility', false, {
609
+ // @ts-expect-error
574
610
  done: errors => {
575
611
  this.setState({
576
612
  a11yErrorsCount: errors.length
@@ -583,6 +619,7 @@ class RCEWrapper extends React.Component {
583
619
  this.openKBShortcutModal = () => {
584
620
  this.setState({
585
621
  KBShortcutModalOpen: true,
622
+ // @ts-expect-error
586
623
  KBShortcutFocusReturn: document.activeElement
587
624
  });
588
625
  };
@@ -595,27 +632,27 @@ class RCEWrapper extends React.Component {
595
632
  if (this.state.KBShortcutFocusReturn === this.iframe) {
596
633
  // launched using a kb shortcut
597
634
  // the iframe has focus so we need to forward it on to tinymce editor
598
- this.editor.focus(false);
635
+ if (this.editor) {
636
+ this.editor.focus(false);
637
+ }
599
638
  } else if (this.state.KBShortcutFocusReturn === document.getElementById(`show-on-focus-btn-${this.id}`)) {
600
- var _this$_showOnFocusBut;
601
639
  // launched from showOnFocus button
602
640
  // edge case where focusing KBShortcutFocusReturn doesn't work
603
- (_this$_showOnFocusBut = this._showOnFocusButton) === null || _this$_showOnFocusBut === void 0 ? void 0 : _this$_showOnFocusBut.focus();
641
+ this._showOnFocusButton?.focus();
604
642
  } else {
605
- var _this$state$KBShortcu;
606
643
  // launched from kb shortcut button on status bar
607
- (_this$state$KBShortcu = this.state.KBShortcutFocusReturn) === null || _this$state$KBShortcu === void 0 ? void 0 : _this$state$KBShortcu.focus();
644
+ this.state.KBShortcutFocusReturn?.focus();
608
645
  }
609
646
  };
610
647
  this.handleAIClick = () => {
611
648
  import('./plugins/shared/ai_tools').then(module => {
649
+ // @ts-expect-error
612
650
  this.AIToolsTray = module.AIToolsTray;
613
651
  this.setState({
614
652
  AIToolsOpen: true,
615
653
  AITToolsFocusReturn: document.activeElement
616
654
  });
617
655
  }).catch(ex => {
618
- // eslint-disable-next-line no-console
619
656
  console.error('Failed loading the AIToolsTray', ex);
620
657
  });
621
658
  };
@@ -628,16 +665,17 @@ class RCEWrapper extends React.Component {
628
665
  if (this.state.AITToolsFocusReturn === this.iframe) {
629
666
  // launched using a kb shortcut
630
667
  // the iframe has focus so we need to forward it on to tinymce editor
631
- this.editor.focus(false);
668
+ if (this.editor) {
669
+ this.editor.focus(false);
670
+ }
632
671
  } else if (this.state.AITToolsFocusReturn === document.getElementById(`show-on-focus-btn-${this.id}`)) {
633
- var _this$_showOnFocusBut2;
634
672
  // launched from showOnFocus button
635
673
  // edge case where focusing KBShortcutFocusReturn doesn't work
636
- (_this$_showOnFocusBut2 = this._showOnFocusButton) === null || _this$_showOnFocusBut2 === void 0 ? void 0 : _this$_showOnFocusBut2.focus();
674
+ this._showOnFocusButton?.focus();
637
675
  } else {
638
- var _this$state$AITToolsF;
639
676
  // launched from kb shortcut button on status bar
640
- (_this$state$AITToolsF = this.state.AITToolsFocusReturn) === null || _this$state$AITToolsF === void 0 ? void 0 : _this$state$AITToolsF.focus();
677
+ // @ts-expect-error
678
+ this.state.AITToolsFocusReturn?.focus();
641
679
  }
642
680
  };
643
681
  this.handleInsertAIContent = content => {
@@ -666,7 +704,7 @@ class RCEWrapper extends React.Component {
666
704
  };
667
705
  this.setFocusAbilityForHeader = focusable => {
668
706
  // Sets aria-hidden to prevent screen readers focus in RCE menus and toolbar
669
- const header = this._elementRef.current.querySelector('.tox-editor-header');
707
+ const header = this._elementRef.current?.querySelector('.tox-editor-header');
670
708
  if (header) {
671
709
  header.setAttribute('aria-hidden', focusable ? 'false' : 'true');
672
710
  }
@@ -674,6 +712,7 @@ class RCEWrapper extends React.Component {
674
712
  this.handleTextareaChange = () => {
675
713
  if (this.isHidden()) {
676
714
  this.setCode(this.textareaValue());
715
+ // @ts-expect-error
677
716
  this.doAutoSave();
678
717
  }
679
718
  };
@@ -717,21 +756,25 @@ class RCEWrapper extends React.Component {
717
756
  this.insert_code = this.insertCode;
718
757
 
719
758
  // test override points
759
+ // @ts-expect-error
720
760
  this.indicator = false;
721
761
  this._elementRef = /*#__PURE__*/React.createRef();
722
762
  this._editorPlaceholderRef = /*#__PURE__*/React.createRef();
763
+ // @ts-expect-error
723
764
  this._prettyHtmlEditorRef = /*#__PURE__*/React.createRef();
765
+ // @ts-expect-error
724
766
  this._showOnFocusButton = null;
725
767
 
726
768
  // Process initial content
769
+ // @ts-expect-error
727
770
  this.initialContent = this.getRequiredFeatureStatuses().rce_transform_loaded_content ? transformRceContentForEditing(this.props.defaultContent, {
728
- origin: this.props.canvasOrigin || ((_window = window) === null || _window === void 0 ? void 0 : (_window$location = _window.location) === null || _window$location === void 0 ? void 0 : _window$location.origin)
771
+ origin: this.props.canvasOrigin || window?.location?.origin
729
772
  }) : this.props.defaultContent;
730
773
  injectTinySkin();
731
774
 
732
775
  // FWIW, for historic reaasons, the height does not include the
733
776
  // height of the status bar (which used to be tinymce's)
734
- let _ht = ((_props$editorOptions = props.editorOptions) === null || _props$editorOptions === void 0 ? void 0 : _props$editorOptions.height) || DEFAULT_RCE_HEIGHT;
777
+ let _ht = props.editorOptions?.height || DEFAULT_RCE_HEIGHT;
735
778
  if (!Number.isNaN(_ht)) {
736
779
  _ht = `${_ht}px`;
737
780
  }
@@ -747,9 +790,12 @@ class RCEWrapper extends React.Component {
747
790
  announcement: null,
748
791
  confirmAutoSave: false,
749
792
  autoSavedContent: '',
793
+ // @ts-expect-error
750
794
  id: this.props.id || this.props.textareaId || `${uid('rce', 2)}`,
795
+ // @ts-expect-error
751
796
  height: _ht,
752
797
  fullscreenState: {
798
+ // @ts-expect-error
753
799
  prevHeight: _ht
754
800
  },
755
801
  a11yErrorsCount: 0,
@@ -758,16 +804,24 @@ class RCEWrapper extends React.Component {
758
804
  };
759
805
  this._statusBarId = `${this.state.id}_statusbar`;
760
806
  this.pendingEventHandlers = [];
807
+
808
+ // @ts-expect-error
761
809
  this.ltiToolFavorites = externalToolsForToolbar(this.props.ltiTools).map(e => `instructure_external_button_${e.id}`);
762
- this.pluginsToExclude = parsePluginsToExclude(((_props$editorOptions2 = props.editorOptions) === null || _props$editorOptions2 === void 0 ? void 0 : _props$editorOptions2.plugins) || []);
810
+ this.pluginsToExclude = parsePluginsToExclude(props.editorOptions?.plugins || []);
811
+
812
+ // @ts-expect-error
763
813
  this.resourceType = props.resourceType;
814
+ // @ts-expect-error
764
815
  this.resourceId = props.resourceId;
816
+
817
+ // @ts-expect-error
765
818
  this.variant = window.RCE_VARIANT || props.variant; // to facilitate testing
766
819
 
820
+ // @ts-expect-error
767
821
  this.tinymceInitOptions = this.wrapOptions(props.editorOptions);
768
822
  alertHandler.alertFunc = this.addAlert;
769
823
  this.handleContentTrayClosing = this.handleContentTrayClosing.bind(this);
770
- this.resizeObserver = new ResizeObserver(_entries => {
824
+ this.resizeObserver = new ResizeObserver(() => {
771
825
  this._handleFullscreenResize();
772
826
  });
773
827
  this.AIToolsTray = undefined;
@@ -783,7 +837,6 @@ class RCEWrapper extends React.Component {
783
837
  if (tinyauxlist.length) {
784
838
  const myaux = tinyauxlist[tinyauxlist.length - 1];
785
839
  if (myaux.id) {
786
- // eslint-disable-next-line no-console
787
840
  console.error('Unexpected ID on my tox-tinymce-aux element');
788
841
  }
789
842
  myaux.id = `tinyaux-${this.id}`;
@@ -815,7 +868,9 @@ class RCEWrapper extends React.Component {
815
868
  getRequiredConfigValues() {
816
869
  return {
817
870
  locale: normalizeLocale(this.props.language),
871
+ // @ts-expect-error
818
872
  flashAlertTimeout: this.props.flashAlertTimeout,
873
+ // @ts-expect-error
819
874
  timezone: this.props.timezone
820
875
  };
821
876
  }
@@ -824,7 +879,9 @@ class RCEWrapper extends React.Component {
824
879
  }
825
880
  getResourceIdentifiers() {
826
881
  return {
882
+ // @ts-expect-error
827
883
  resourceType: this.resourceType,
884
+ // @ts-expect-error
828
885
  resourceId: this.resourceId
829
886
  };
830
887
  }
@@ -834,6 +891,8 @@ class RCEWrapper extends React.Component {
834
891
  getCode() {
835
892
  return this.isHidden() ? this.textareaValue() : this.mceInstance().getContent();
836
893
  }
894
+
895
+ // @ts-expect-error
837
896
  checkReadyToGetCode(promptFunc) {
838
897
  let status = true;
839
898
  // Check for remaining placeholders
@@ -843,8 +902,7 @@ class RCEWrapper extends React.Component {
843
902
  return status;
844
903
  }
845
904
  setCode(newContent) {
846
- var _this$mceInstance;
847
- (_this$mceInstance = this.mceInstance()) === null || _this$mceInstance === void 0 ? void 0 : _this$mceInstance.setContent(newContent);
905
+ this.mceInstance()?.setContent(newContent);
848
906
  }
849
907
 
850
908
  // This function is called imperatively by the page that renders the RCE.
@@ -865,7 +923,9 @@ class RCEWrapper extends React.Component {
865
923
  return;
866
924
  }
867
925
  const editor = this.mceInstance();
926
+ // @ts-expect-error
868
927
  if (this.indicator) {
928
+ // @ts-expect-error
869
929
  this.indicator(editor, element);
870
930
  } else if (!this.isHidden()) {
871
931
  indicate(indicatorRegion(editor, element));
@@ -889,8 +949,17 @@ class RCEWrapper extends React.Component {
889
949
  if (height) {
890
950
  const ifr = this.iframe;
891
951
  if (ifr) {
892
- const editor_body_style = ifr.contentWindow.getComputedStyle(this.iframe.contentDocument.body);
893
- const editor_ht = ifr.contentDocument.body.clientHeight - parseInt(editor_body_style['padding-top'], 10) - parseInt(editor_body_style['padding-bottom'], 10);
952
+ // @ts-expect-error
953
+ const editor_body_style = ifr.contentWindow.getComputedStyle(
954
+ // @ts-expect-error
955
+ this.iframe.contentDocument.body);
956
+ const editor_ht =
957
+ // @ts-expect-error
958
+ ifr.contentDocument.body.clientHeight -
959
+ // @ts-expect-error
960
+ parseInt(editor_body_style['padding-top'], 10) -
961
+ // @ts-expect-error
962
+ parseInt(editor_body_style['padding-bottom'], 10);
894
963
  const para_margin_ht = 24;
895
964
  const reserve_ht = Math.ceil(height + para_margin_ht);
896
965
  if (reserve_ht > editor_ht) {
@@ -905,15 +974,20 @@ class RCEWrapper extends React.Component {
905
974
  if (!element || element.tagName !== 'IMG') {
906
975
  return;
907
976
  }
977
+ // @ts-expect-error
908
978
  if (!element.complete) {
979
+ // @ts-expect-error
909
980
  element.onload = () => this.checkImageLoadError(element);
910
981
  return;
911
982
  }
912
983
  // checking naturalWidth in a future event loop run prevents a race
913
984
  // condition between the onload callback and naturalWidth being set.
914
985
  setTimeout(() => {
986
+ // @ts-expect-error
915
987
  if (element.naturalWidth === 0) {
988
+ // @ts-expect-error
916
989
  element.style.border = '1px solid #000';
990
+ // @ts-expect-error
917
991
  element.style.padding = '2px';
918
992
  }
919
993
  }, 0);
@@ -964,12 +1038,11 @@ class RCEWrapper extends React.Component {
964
1038
  }
965
1039
  }
966
1040
  insertImage(image) {
967
- var _element$nextSibling, _element$nextSibling$;
968
1041
  const editor = this.mceInstance();
969
1042
  const element = contentInsertion.insertImage(editor, image, this.getCanvasUrl());
970
1043
 
971
1044
  // Removes TinyMCE's caret &nbsp; text if exists.
972
- if (element !== null && element !== void 0 && (_element$nextSibling = element.nextSibling) !== null && _element$nextSibling !== void 0 && (_element$nextSibling$ = _element$nextSibling.data) !== null && _element$nextSibling$ !== void 0 && _element$nextSibling$.startsWith('\xA0' /* nbsp */)) {
1045
+ if (element?.nextSibling?.data?.startsWith('\xA0' /* nbsp */)) {
973
1046
  element.nextSibling.splitText(1);
974
1047
  element.nextSibling.remove();
975
1048
  }
@@ -1027,10 +1100,12 @@ class RCEWrapper extends React.Component {
1027
1100
  }
1028
1101
 
1029
1102
  // since we may defer rendering tinymce, queue up any tinymce event handlers
1103
+ // @ts-expect-error
1030
1104
  tinymceOn(tinymceEventName, handler) {
1031
1105
  if (this.state.shouldShowEditor) {
1032
1106
  this.mceInstance().on(tinymceEventName, handler);
1033
1107
  } else {
1108
+ // @ts-expect-error
1034
1109
  this.pendingEventHandlers.push({
1035
1110
  name: tinymceEventName,
1036
1111
  handler
@@ -1044,39 +1119,43 @@ class RCEWrapper extends React.Component {
1044
1119
  const editors = this.props.tinymce.editors || [];
1045
1120
  return editors.filter(ed => ed.id === this.props.textareaId)[0];
1046
1121
  }
1047
- onTinyMCEInstance(command) {
1122
+
1123
+ // @ts-expect-error
1124
+ onTinyMCEInstance(command, ...args) {
1048
1125
  const editor = this.mceInstance();
1049
1126
  if (editor) {
1050
1127
  if (command === 'mceRemoveEditor') {
1051
1128
  editor.execCommand('mceNewDocument');
1052
1129
  } // makes sure content can't persist past removal
1053
- for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
1054
- args[_key - 1] = arguments[_key];
1055
- }
1056
1130
  editor.execCommand(command, false, ...args);
1057
1131
  }
1058
1132
  }
1059
1133
  destroy() {
1060
1134
  this._destroyCalled = true;
1061
1135
  this.unhandleTextareaChange();
1062
- this.props.handleUnmount && this.props.handleUnmount();
1136
+ if (this.props.handleUnmount) {
1137
+ this.props.handleUnmount();
1138
+ }
1063
1139
  }
1064
1140
  getTextarea() {
1065
- return document.getElementById(this.props.textareaId);
1141
+ const node = this.props.textareaId && document.getElementById(this.props.textareaId);
1142
+ if (node instanceof HTMLTextAreaElement) {
1143
+ return node;
1144
+ }
1145
+ return null;
1066
1146
  }
1067
1147
  textareaValue() {
1068
- return this.getTextarea().value;
1148
+ return this.getTextarea()?.value || '';
1069
1149
  }
1070
1150
  get id() {
1071
1151
  return this.state.id;
1072
1152
  }
1073
1153
  getHtmlEditorStorage() {
1074
- var _this$storage2, _this$storage2$getIte, _this$storage2$getIte2;
1075
1154
  const cookieValue = getCookie('rce.htmleditor');
1076
1155
  if (cookieValue) {
1077
1156
  document.cookie = `rce.htmleditor=${cookieValue};path=/;max-age=0`;
1078
1157
  }
1079
- const value = cookieValue || ((_this$storage2 = this.storage) === null || _this$storage2 === void 0 ? void 0 : (_this$storage2$getIte = _this$storage2.getItem) === null || _this$storage2$getIte === void 0 ? void 0 : (_this$storage2$getIte2 = _this$storage2$getIte.call(_this$storage2, 'rce.htmleditor')) === null || _this$storage2$getIte2 === void 0 ? void 0 : _this$storage2$getIte2.content);
1158
+ const value = cookieValue || this.storage?.getItem?.('rce.htmleditor')?.content;
1080
1159
  return value === RAW_HTML_EDITOR_VIEW || value === PRETTY_HTML_EDITOR_VIEW ? value : PRETTY_HTML_EDITOR_VIEW;
1081
1160
  }
1082
1161
  _isFullscreen() {
@@ -1090,14 +1169,17 @@ class RCEWrapper extends React.Component {
1090
1169
  const tinymenuhost = this._myTinymceAuxDiv();
1091
1170
  if (tinymenuhost) {
1092
1171
  tinymenuhost.remove();
1093
- this._elementRef.current.appendChild(tinymenuhost);
1172
+ this._elementRef.current?.appendChild(tinymenuhost);
1094
1173
  }
1095
- this._elementRef.current.addEventListener(FS_CHANGEEVENT, this._onFullscreenChange);
1096
- this.setState({
1097
- fullscreenState: {
1098
- prevHeight: this._elementRef.current.offsetHeight - this._getStatusBarHeight()
1099
- }
1100
- });
1174
+ this._elementRef.current?.addEventListener(FS_CHANGEEVENT, this._onFullscreenChange);
1175
+ if (typeof this._elementRef.current?.offsetHeight === 'number') {
1176
+ this.setState({
1177
+ fullscreenState: {
1178
+ prevHeight: this._elementRef.current.offsetHeight - this._getStatusBarHeight()
1179
+ }
1180
+ });
1181
+ }
1182
+ // @ts-expect-error
1101
1183
  this._elementRef.current[FS_REQUEST]();
1102
1184
  }
1103
1185
  _exitFullscreen() {
@@ -1110,10 +1192,14 @@ class RCEWrapper extends React.Component {
1110
1192
  document[FS_EXIT]();
1111
1193
  }
1112
1194
  }
1195
+
1196
+ // @ts-expect-error
1197
+
1113
1198
  _getStatusBarHeight() {
1114
1199
  // the height prop is the height of the editor and does not include
1115
1200
  // the status bar. we'll need this later.
1116
- return document.getElementById(this._statusBarId).offsetHeight;
1201
+ const node = document.getElementById(this._statusBarId);
1202
+ return node?.offsetHeight || 0;
1117
1203
  }
1118
1204
  _setHeight(newHeight) {
1119
1205
  const cssHeight = `${newHeight}px`;
@@ -1123,7 +1209,10 @@ class RCEWrapper extends React.Component {
1123
1209
  container.style.height = cssHeight;
1124
1210
  ed.fire('ResizeEditor');
1125
1211
  }
1126
- this.getTextarea().style.height = cssHeight;
1212
+ const textarea = this.getTextarea();
1213
+ if (textarea) {
1214
+ textarea.style.height = cssHeight;
1215
+ }
1127
1216
  this.setState({
1128
1217
  height: cssHeight
1129
1218
  });
@@ -1131,6 +1220,7 @@ class RCEWrapper extends React.Component {
1131
1220
  focus() {
1132
1221
  this.onTinyMCEInstance('mceFocus');
1133
1222
  // tinymce doesn't always call the focus handler.
1223
+ // @ts-expect-error
1134
1224
  this.handleFocusEditor(new Event('focus', {
1135
1225
  target: this.mceInstance()
1136
1226
  }));
@@ -1138,21 +1228,29 @@ class RCEWrapper extends React.Component {
1138
1228
  focusCurrentView() {
1139
1229
  switch (this.state.editorView) {
1140
1230
  case WYSIWYG_VIEW:
1141
- this.mceInstance().focus();
1142
- break;
1231
+ {
1232
+ this.mceInstance().focus();
1233
+ break;
1234
+ }
1143
1235
  case PRETTY_HTML_EDITOR_VIEW:
1144
- break;
1236
+ {
1237
+ break;
1238
+ }
1145
1239
  case RAW_HTML_EDITOR_VIEW:
1146
- this.getTextarea().focus();
1147
- break;
1240
+ {
1241
+ const textarea = this.getTextarea();
1242
+ if (textarea) {
1243
+ textarea.focus();
1244
+ }
1245
+ break;
1246
+ }
1148
1247
  }
1149
1248
  }
1150
1249
  is_dirty() {
1151
- var _this$mceInstance2;
1152
1250
  if (this.mceInstance().isDirty()) {
1153
1251
  return true;
1154
1252
  }
1155
- const currentHtml = this.isHidden() ? this.textareaValue() : (_this$mceInstance2 = this.mceInstance()) === null || _this$mceInstance2 === void 0 ? void 0 : _this$mceInstance2.getContent();
1253
+ const currentHtml = this.isHidden() ? this.textareaValue() : this.mceInstance()?.getContent();
1156
1254
  return currentHtml !== this._mceSerializedInitialHtml;
1157
1255
  }
1158
1256
 
@@ -1162,6 +1260,7 @@ class RCEWrapper extends React.Component {
1162
1260
  get _mceSerializedInitialHtml() {
1163
1261
  if (!this._mceSerializedInitialHtmlCached) {
1164
1262
  const el = window.document.createElement('div');
1263
+ // @ts-expect-error
1165
1264
  el.innerHTML = this.initialContent;
1166
1265
  const serializer = this.mceInstance().serializer;
1167
1266
  this._mceSerializedInitialHtmlCached = serializer.serialize(el, {
@@ -1185,10 +1284,12 @@ class RCEWrapper extends React.Component {
1185
1284
  get focused() {
1186
1285
  return this === bridge.getEditor();
1187
1286
  }
1188
- handleFocus(_event) {
1287
+ handleFocus() {
1189
1288
  if (!this.focused) {
1190
1289
  bridge.focusEditor(this);
1191
- this.props.onFocus && this.props.onFocus(this);
1290
+ if (this.props.onFocus) {
1291
+ this.props.onFocus(this);
1292
+ }
1192
1293
  }
1193
1294
  }
1194
1295
  handleContentTrayClosing(isClosing) {
@@ -1199,27 +1300,29 @@ class RCEWrapper extends React.Component {
1199
1300
  if (this.focused) {
1200
1301
  // because the old active element fires blur before the next element gets focus
1201
1302
  // we often need a moment to see if focus comes back
1303
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions
1202
1304
  event && event.persist && event.persist();
1203
1305
  this.blurTimer = window.setTimeout(() => {
1204
- var _this$_elementRef$cur3, _event$focusedEditor, _event$relatedTarget, _event$relatedTarget$;
1205
1306
  this.blurTimer = 0;
1206
1307
  if (this.contentTrayClosing) {
1207
1308
  // the CanvasContentTray is in the process of closing
1208
1309
  // wait until it finishes
1209
1310
  return;
1210
1311
  }
1211
- if ((_this$_elementRef$cur3 = this._elementRef.current) !== null && _this$_elementRef$cur3 !== void 0 && _this$_elementRef$cur3.contains(document.activeElement)) {
1312
+ if (this._elementRef.current?.contains(document.activeElement)) {
1212
1313
  // focus is still somewhere w/in me
1213
1314
  return;
1214
1315
  }
1215
1316
  const activeClass = document.activeElement && document.activeElement.getAttribute('class');
1216
- if ((event.focusedEditor === undefined || event.target.id === ((_event$focusedEditor = event.focusedEditor) === null || _event$focusedEditor === void 0 ? void 0 : _event$focusedEditor.id)) && activeClass !== null && activeClass !== void 0 && activeClass.includes('tox-')) {
1317
+ if (
1318
+ // @ts-expect-error
1319
+ (event.focusedEditor === undefined || event.target.id === event.focusedEditor?.id) && activeClass?.includes('tox-')) {
1217
1320
  // if a toolbar button has focus, then the user clicks on the "more" button
1218
1321
  // focus jumps to the body, then eventually to the popped up toolbar. This
1219
1322
  // catches that case.
1220
1323
  return;
1221
1324
  }
1222
- if (event !== null && event !== void 0 && (_event$relatedTarget = event.relatedTarget) !== null && _event$relatedTarget !== void 0 && (_event$relatedTarget$ = _event$relatedTarget.getAttribute('class')) !== null && _event$relatedTarget$ !== void 0 && _event$relatedTarget$.includes('tox-')) {
1325
+ if (event?.relatedTarget?.getAttribute('class')?.includes('tox-')) {
1223
1326
  // a tinymce popup has focus
1224
1327
  return;
1225
1328
  }
@@ -1231,19 +1334,23 @@ class RCEWrapper extends React.Component {
1231
1334
  }
1232
1335
  }
1233
1336
  bridge.blurEditor(this);
1234
- this.props.onBlur && this.props.onBlur(event);
1337
+ if (this.props.onBlur) {
1338
+ this.props.onBlur(event);
1339
+ }
1235
1340
  }, ASYNC_FOCUS_TIMEOUT);
1236
1341
  }
1237
1342
  }
1238
- call(methodName) {
1343
+
1344
+ // @ts-expect-error
1345
+
1346
+ // @ts-expect-error
1347
+ call(methodName, ...args) {
1239
1348
  // since exists? has a ? and cant be a regular function just return true
1240
1349
  // rather than calling as a fn on the editor
1241
1350
  if (methodName === 'exists?') {
1242
1351
  return true;
1243
1352
  }
1244
- for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
1245
- args[_key2 - 1] = arguments[_key2];
1246
- }
1353
+ // @ts-expect-error
1247
1354
  return this[methodName](...args);
1248
1355
  }
1249
1356
 
@@ -1266,10 +1373,12 @@ class RCEWrapper extends React.Component {
1266
1373
  *
1267
1374
  * @private
1268
1375
  */
1376
+ // @ts-expect-error
1269
1377
 
1270
1378
  announceContextToolbars(editor) {
1271
1379
  editor.on('NodeChange', () => {
1272
1380
  const node = editor.selection.getNode();
1381
+ // @ts-expect-error
1273
1382
  if (isImageEmbed(node, editor)) {
1274
1383
  if (this.announcing !== 1) {
1275
1384
  this.setState({
@@ -1288,7 +1397,7 @@ class RCEWrapper extends React.Component {
1288
1397
  });
1289
1398
  this.announcing = 2;
1290
1399
  }
1291
- } else if (isElementWithinTable(node, editor)) {
1400
+ } else if (isElementWithinTable(node)) {
1292
1401
  if (this.announcing !== 3) {
1293
1402
  this.setState({
1294
1403
  announcement: formatMessage('type Control F9 to access table options. {text}', {
@@ -1310,24 +1419,14 @@ class RCEWrapper extends React.Component {
1310
1419
 
1311
1420
  // remove any autosaved value that's too old
1312
1421
 
1313
- // if a placeholder image shows up in autosaved content, we have to remove it
1314
- // because the data url gets converted to a blob, which is not valid when restored.
1315
- // besides, the placeholder is intended to be temporary while the file
1316
- // is being uploaded
1317
- patchAutosavedContent(content, asText) {
1318
- const temp = document.createElement('div');
1319
- temp.innerHTML = content;
1320
- temp.querySelectorAll('[data-placeholder-for]').forEach(placeholder => {
1321
- placeholder.parentElement.removeChild(placeholder);
1322
- });
1323
- if (asText) return temp.textContent;
1324
- return temp.innerHTML;
1325
- }
1422
+ // @ts-expect-error
1423
+
1326
1424
  getAutoSaved(key) {
1327
1425
  let autosaved = null;
1328
1426
  try {
1329
1427
  autosaved = this.storage && this.storage.getItem(key);
1330
1428
  } catch (_ex) {
1429
+ // @ts-expect-error
1331
1430
  this.storage.removeItem(this.autoSaveKey);
1332
1431
  }
1333
1432
  return autosaved;
@@ -1337,44 +1436,51 @@ class RCEWrapper extends React.Component {
1337
1436
  // the latter condition is necessary because the popup RestoreAutoSaveModal
1338
1437
  // is lousey UX when there are >1
1339
1438
  get isAutoSaving() {
1439
+ if (!this.editor) return false;
1440
+
1340
1441
  // If the editor is invisible for some reason, don't show the autosave modal
1341
1442
  // This doesn't apply if the editor is off-screen or has visibility:hidden;
1342
1443
  // only if it isn't rendered or has display:none;
1343
1444
  const editorVisible = this.editor.getContainer().offsetParent;
1344
- return this.props.autosave.enabled && editorVisible && document.querySelectorAll('.rce-wrapper').length === 1 && storageAvailable();
1445
+ return this.props.autosave?.enabled && editorVisible && document.querySelectorAll('.rce-wrapper').length === 1 && storageAvailable();
1345
1446
  }
1346
1447
  get autoSaveKey() {
1347
- var _this$props$trayProps;
1348
- const userId = (_this$props$trayProps = this.props.trayProps) === null || _this$props$trayProps === void 0 ? void 0 : _this$props$trayProps.containingContext.userId;
1448
+ // @ts-expect-error
1449
+ const userId = this.props.trayProps?.containingContext.userId;
1349
1450
  return `rceautosave:${userId}${window.location.href}:${this.props.textareaId}`;
1350
1451
  }
1351
1452
 
1453
+ // @ts-expect-error
1454
+
1352
1455
  /* *********** end autosave support *************** */
1353
1456
 
1457
+ // @ts-expect-error
1458
+
1354
1459
  componentWillUnmount() {
1355
1460
  if (this.state.shouldShowEditor) {
1356
- var _this$mutationObserve, _this$intersectionObs;
1357
1461
  window.clearTimeout(this.blurTimer);
1358
1462
  if (!this._destroyCalled) {
1359
1463
  this.destroy();
1360
1464
  }
1361
- this._elementRef.current.removeEventListener('keydown', this.handleKey, true);
1362
- (_this$mutationObserve = this.mutationObserver) === null || _this$mutationObserve === void 0 ? void 0 : _this$mutationObserve.disconnect();
1363
- (_this$intersectionObs = this.intersectionObserver) === null || _this$intersectionObs === void 0 ? void 0 : _this$intersectionObs.disconnect();
1465
+ if (this._elementRef.current) {
1466
+ this._elementRef.current.removeEventListener('keydown', this.handleKey, true);
1467
+ }
1468
+ this.mutationObserver?.disconnect();
1469
+ this.intersectionObserver?.disconnect();
1364
1470
  }
1365
1471
  }
1366
- wrapOptions() {
1367
- var _this$props$trayProps2, _this$props$trayProps3, _this$props$trayProps4, _sanitizePlugins;
1368
- let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1369
- const rcsExists = !!((_this$props$trayProps2 = this.props.trayProps) !== null && _this$props$trayProps2 !== void 0 && _this$props$trayProps2.host && (_this$props$trayProps3 = this.props.trayProps) !== null && _this$props$trayProps3 !== void 0 && _this$props$trayProps3.jwt);
1472
+ wrapOptions(options = {}) {
1473
+ const rcsExists = !!(this.props.trayProps?.host && this.props.trayProps?.jwt);
1370
1474
  const userLocale = editorLanguage(this.language);
1475
+
1476
+ // @ts-expect-error
1371
1477
  const setupCallback = options.setup;
1372
1478
  const canvasPlugins = rcsExists ? ['instructure_image', 'instructure_documents', 'instructure_equation'] : [];
1373
1479
  if (rcsExists && !this.props.instRecordDisabled) {
1374
1480
  canvasPlugins.splice(2, 0, 'instructure_record');
1375
1481
  }
1376
1482
  const pastePlugins = rcsExists ? ['instructure_paste', 'paste'] : ['paste'];
1377
- if (rcsExists && this.props.use_rce_icon_maker && ((_this$props$trayProps4 = this.props.trayProps) === null || _this$props$trayProps4 === void 0 ? void 0 : _this$props$trayProps4.contextType) === 'course') {
1483
+ if (rcsExists && this.props.use_rce_icon_maker && this.props.trayProps?.contextType === 'course') {
1378
1484
  canvasPlugins.push('instructure_icon_maker');
1379
1485
  }
1380
1486
  if (document[FS_ENABLED]) {
@@ -1392,19 +1498,23 @@ class RCEWrapper extends React.Component {
1392
1498
  theme: 'silver',
1393
1499
  // some older code specified 'modern', which doesn't exist any more
1394
1500
 
1501
+ // @ts-expect-error
1395
1502
  height: options.height || DEFAULT_RCE_HEIGHT,
1396
1503
  language: userLocale,
1397
1504
  document_base_url: this.props.canvasOrigin,
1398
- block_formats: options.block_formats || [`${formatMessage('Heading 2')}=h2`, `${formatMessage('Heading 3')}=h3`, `${formatMessage('Heading 4')}=h4`, `${formatMessage('Preformatted')}=pre`, `${formatMessage('Paragraph')}=p`].join('; '),
1505
+ block_formats:
1506
+ // @ts-expect-error
1507
+ options.block_formats || [`${formatMessage('Heading 2')}=h2`, `${formatMessage('Heading 3')}=h3`, `${formatMessage('Heading 4')}=h4`, `${formatMessage('Preformatted')}=pre`, `${formatMessage('Paragraph')}=p`].join('; '),
1399
1508
  setup: editor => {
1400
- var _bridge$trayProps;
1401
1509
  addKebabIcon(editor);
1402
1510
  editorWrappers.set(editor, this);
1403
1511
  const trayPropsWithColor = {
1512
+ // @ts-expect-error
1404
1513
  brandColor: this.style.theme.canvasBrandColor,
1405
1514
  ...this.props.trayProps
1406
1515
  };
1407
- (_bridge$trayProps = bridge.trayProps) === null || _bridge$trayProps === void 0 ? void 0 : _bridge$trayProps.set(editor, trayPropsWithColor);
1516
+ bridge.trayProps?.set(editor, trayPropsWithColor);
1517
+ // @ts-expect-error
1408
1518
  bridge.userLocale = userLocale;
1409
1519
  bridge.canvasOrigin = this.props.canvasOrigin;
1410
1520
  if (typeof setupCallback === 'function') {
@@ -1415,7 +1525,9 @@ class RCEWrapper extends React.Component {
1415
1525
  // in the editor matches the styles of the app it will be displayed in when saved.
1416
1526
  // This is just so we inject the helper class names that tinyMCE uses for
1417
1527
  // things like table resizing and stuff.
1528
+ // @ts-expect-error
1418
1529
  content_css: options.content_css || [],
1530
+ // @ts-expect-error
1419
1531
  content_style: contentCSS + (options.content_style || ''),
1420
1532
  menubar: mergeMenuItems(getMenubarForVariant(this.variant), possibleNewMenubarItems),
1421
1533
  // default menu options listed at https://www.tiny.cloud/docs/configure/editor-appearance/#menu
@@ -1424,8 +1536,13 @@ class RCEWrapper extends React.Component {
1424
1536
  // since we currently can't effectively paste using the clipboard api anyway.
1425
1537
  // we include all the canvas specific items in the menu and toolbar
1426
1538
  // and rely on tinymce only showing them if the plugin is provided.
1539
+ // @ts-expect-error
1427
1540
  menu: mergeMenu(getMenuForVariant(this.variant), options.menu),
1428
- toolbar: mergeToolbar(getToolbarForVariant(this.variant, this.ltiToolFavorites), options.toolbar),
1541
+ toolbar: mergeToolbar(
1542
+ // @ts-expect-error
1543
+ getToolbarForVariant(this.variant, this.ltiToolFavorites),
1544
+ // @ts-expect-error
1545
+ options.toolbar),
1429
1546
  contextmenu: '',
1430
1547
  // show the browser's native context menu
1431
1548
 
@@ -1438,8 +1555,10 @@ class RCEWrapper extends React.Component {
1438
1555
  // handles all of that complexity. It that ever changes in the
1439
1556
  // future in an upgraded version, we will have to update the
1440
1557
  // logic in those other places as well.
1441
- plugins: mergePlugins(['autolink', 'media', 'table', 'link', 'directionality', 'lists', 'textpattern', 'hr', 'instructure_color', 'instructure-ui-icons', 'instructure_condensed_buttons', 'instructure_links', 'instructure_html_view', 'instructure_media_embed', 'a11y_checker', 'wordcount', 'instructure_wordcount', 'instructure_studio_media_options', 'instructure_rce_external_tools', ...pastePlugins, ...canvasPlugins], // filter out the plugins designated for removal
1442
- (_sanitizePlugins = sanitizePlugins(options.plugins)) === null || _sanitizePlugins === void 0 ? void 0 : _sanitizePlugins.filter(p => p.length > 0 && p[0] !== '-'), this.pluginsToExclude),
1558
+ plugins: mergePlugins(['autolink', 'media', 'table', 'link', 'directionality', 'lists', 'textpattern', 'hr', 'instructure_color', 'instructure-ui-icons', 'instructure_condensed_buttons', 'instructure_links', 'instructure_html_view', 'instructure_media_embed', 'a11y_checker', 'wordcount', 'instructure_wordcount', 'instructure_studio_media_options', 'instructure_rce_external_tools', ...pastePlugins, ...canvasPlugins],
1559
+ // filter out the plugins designated for removal
1560
+ // @ts-expect-error
1561
+ sanitizePlugins(options.plugins)?.filter(p => p.length > 0 && p[0] !== '-'), this.pluginsToExclude),
1443
1562
  textpattern_patterns: [{
1444
1563
  start: '* ',
1445
1564
  cmd: 'InsertUnorderedList'
@@ -1449,12 +1568,17 @@ class RCEWrapper extends React.Component {
1449
1568
  }]
1450
1569
  };
1451
1570
  if (this.props.trayProps) {
1571
+ // @ts-expect-error
1452
1572
  wrappedOpts.canvas_rce_user_context = {
1453
1573
  type: this.props.trayProps.contextType,
1454
1574
  id: this.props.trayProps.contextId
1455
1575
  };
1576
+
1577
+ // @ts-expect-error
1456
1578
  wrappedOpts.canvas_rce_containing_context = {
1579
+ // @ts-expect-error
1457
1580
  type: this.props.trayProps.containingContext.contextType,
1581
+ // @ts-expect-error
1458
1582
  id: this.props.trayProps.containingContext.contextId
1459
1583
  };
1460
1584
  }
@@ -1498,15 +1622,15 @@ class RCEWrapper extends React.Component {
1498
1622
  rootMargin: '200px 0px',
1499
1623
  threshold: 0.0
1500
1624
  });
1625
+ // @ts-expect-error
1501
1626
  this.intersectionObserver.observe(this._editorPlaceholderRef.current);
1502
1627
  }
1503
1628
  }
1504
1629
  componentDidUpdate(prevProps, prevState) {
1505
1630
  if (this.state.shouldShowEditor) {
1506
1631
  if (!prevState.shouldShowEditor) {
1507
- var _this$intersectionObs2;
1508
1632
  this.editorReallyDidMount();
1509
- (_this$intersectionObs2 = this.intersectionObserver) === null || _this$intersectionObs2 === void 0 ? void 0 : _this$intersectionObs2.disconnect();
1633
+ this.intersectionObserver?.disconnect();
1510
1634
  } else {
1511
1635
  this.registerTextareaChange();
1512
1636
  if (prevState.editorView !== this.state.editorView) {
@@ -1522,10 +1646,12 @@ class RCEWrapper extends React.Component {
1522
1646
  editorReallyDidMount() {
1523
1647
  const myTiny = this.mceInstance();
1524
1648
  this.pendingEventHandlers.forEach(e => {
1649
+ // @ts-expect-error
1525
1650
  myTiny.on(e.name, e.handler);
1526
1651
  });
1527
1652
  this._tagTinymceAuxDiv();
1528
1653
  this.registerTextareaChange();
1654
+ // @ts-expect-error
1529
1655
  this._elementRef.current.addEventListener('keydown', this.handleKey, true);
1530
1656
  // give the textarea its initial size
1531
1657
  this.onResize(null, {
@@ -1538,6 +1664,8 @@ class RCEWrapper extends React.Component {
1538
1664
  }
1539
1665
  bridge.renderEditor(this);
1540
1666
  }
1667
+
1668
+ // @ts-expect-error
1541
1669
  setEditorView(view) {
1542
1670
  switch (view) {
1543
1671
  case WYSIWYG_VIEW:
@@ -1571,24 +1699,29 @@ class RCEWrapper extends React.Component {
1571
1699
  as: "div",
1572
1700
  borderRadius: "medium",
1573
1701
  borderWidth: "small"
1574
- }, /*#__PURE__*/React.createElement(RceHtmlEditor, {
1702
+ }, /*#__PURE__*/React.createElement(RceHtmlEditor
1703
+ // @ts-expect-error
1704
+ , {
1575
1705
  ref: this._prettyHtmlEditorRef,
1576
1706
  height: this.state.height,
1577
1707
  code: this.getCode(),
1578
1708
  onChange: value => {
1579
- this.getTextarea().value = value;
1709
+ const node = this.getTextarea();
1710
+ if (node) {
1711
+ node.value = value;
1712
+ }
1580
1713
  this.handleTextareaChange();
1581
1714
  }
1582
1715
  })));
1583
1716
  }
1584
1717
  render() {
1585
- var _this$props$trayProps5, _this$props$trayProps6, _this$props$trayProps7, _this$props$trayProps8, _this$props$trayProps9;
1586
1718
  const {
1587
1719
  trayProps,
1588
1720
  ...mceProps
1589
1721
  } = this.props;
1590
1722
  if (!this.state.shouldShowEditor) {
1591
1723
  return /*#__PURE__*/React.createElement("div", {
1724
+ // @ts-expect-error
1592
1725
  ref: this._editorPlaceholderRef,
1593
1726
  style: {
1594
1727
  height: `${this.props.editorOptions.height}px`,
@@ -1598,17 +1731,20 @@ class RCEWrapper extends React.Component {
1598
1731
  }
1599
1732
  const statusBarFeatures = getStatusBarFeaturesForVariant(this.variant, this.props.ai_text_tools);
1600
1733
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("style", null, this.style.css), /*#__PURE__*/React.createElement(StoreProvider, {
1601
- jwt: (_this$props$trayProps5 = this.props.trayProps) === null || _this$props$trayProps5 === void 0 ? void 0 : _this$props$trayProps5.jwt,
1602
- refreshToken: (_this$props$trayProps6 = this.props.trayProps) === null || _this$props$trayProps6 === void 0 ? void 0 : _this$props$trayProps6.refreshToken,
1603
- host: (_this$props$trayProps7 = this.props.trayProps) === null || _this$props$trayProps7 === void 0 ? void 0 : _this$props$trayProps7.host,
1604
- contextType: (_this$props$trayProps8 = this.props.trayProps) === null || _this$props$trayProps8 === void 0 ? void 0 : _this$props$trayProps8.contextType,
1605
- contextId: (_this$props$trayProps9 = this.props.trayProps) === null || _this$props$trayProps9 === void 0 ? void 0 : _this$props$trayProps9.contextId,
1734
+ jwt: this.props.trayProps?.jwt,
1735
+ refreshToken: this.props.trayProps?.refreshToken,
1736
+ host: this.props.trayProps?.host,
1737
+ contextType: this.props.trayProps?.contextType,
1738
+ contextId: this.props.trayProps?.contextId,
1606
1739
  canvasOrigin: this.props.canvasOrigin
1607
1740
  }, storeProps => {
1608
- var _this$props$trayProps10;
1609
1741
  return /*#__PURE__*/React.createElement("div", {
1610
- key: this.id,
1611
- className: `${this.style.classNames.root} rce-wrapper`,
1742
+ key: this.id
1743
+ // @ts-expect-error
1744
+ ,
1745
+ className: `${this.style.classNames.root} rce-wrapper`
1746
+ // @ts-expect-error
1747
+ ,
1612
1748
  ref: this._elementRef,
1613
1749
  style: this.variant === 'full' ? {
1614
1750
  marginBottom: '.5rem'
@@ -1619,10 +1755,14 @@ class RCEWrapper extends React.Component {
1619
1755
  id: `show-on-focus-btn-${this.id}`,
1620
1756
  onClick: this.openKBShortcutModal,
1621
1757
  margin: "xx-small",
1622
- screenReaderLabel: formatMessage('View keyboard shortcuts'),
1758
+ screenReaderLabel: formatMessage('View keyboard shortcuts')
1759
+ // @ts-expect-error
1760
+ ,
1623
1761
  ref: el => this._showOnFocusButton = el
1624
1762
  }, /*#__PURE__*/React.createElement(IconKeyboardShortcutsLine, null)), /*#__PURE__*/React.createElement(AlertMessageArea, {
1625
- messages: this.state.messages,
1763
+ messages: this.state.messages
1764
+ // @ts-expect-error
1765
+ ,
1626
1766
  liveRegion: this.props.liveRegion,
1627
1767
  afterDismiss: this.removeAlert
1628
1768
  }), this.state.editorView === PRETTY_HTML_EDITOR_VIEW && this.renderHtmlEditor(), /*#__PURE__*/React.createElement("div", {
@@ -1631,15 +1771,25 @@ class RCEWrapper extends React.Component {
1631
1771
  }
1632
1772
  }, /*#__PURE__*/React.createElement(Editor, {
1633
1773
  id: mceProps.textareaId,
1634
- textareaName: mceProps.name,
1774
+ textareaName: mceProps.name
1775
+ // @ts-expect-error
1776
+ ,
1635
1777
  init: this.tinymceInitOptions,
1636
- initialValue: this.initialContent,
1778
+ initialValue: this.initialContent
1779
+ // @ts-expect-error
1780
+ ,
1637
1781
  onInit: this.onInit,
1638
1782
  onClick: this.handleFocusEditor,
1639
- onKeypress: this.handleFocusEditor,
1783
+ onKeypress: this.handleFocusEditor
1784
+ // @ts-expect-error
1785
+ ,
1640
1786
  onActivate: this.handleFocusEditor,
1641
- onRemove: this.onRemove,
1642
- onFocus: this.handleFocusEditor,
1787
+ onRemove: this.onRemove
1788
+ // @ts-expect-error
1789
+ ,
1790
+ onFocus: this.handleFocusEditor
1791
+ // @ts-expect-error
1792
+ ,
1643
1793
  onBlur: this.handleBlurEditor,
1644
1794
  onNodeChange: this.onNodeChange,
1645
1795
  onEditorChange: this.onEditorChange,
@@ -1656,7 +1806,9 @@ class RCEWrapper extends React.Component {
1656
1806
  onResize: this.onResize,
1657
1807
  onKBShortcutModalOpen: this.openKBShortcutModal,
1658
1808
  onA11yChecker: this.onA11yChecker,
1659
- onFullscreen: this.handleClickFullscreen,
1809
+ onFullscreen: this.handleClickFullscreen
1810
+ // @ts-expect-error
1811
+ ,
1660
1812
  a11yBadgeColor: this.style.theme.canvasBadgeBackgroundColor,
1661
1813
  a11yErrorsCount: this.state.a11yErrorsCount,
1662
1814
  onWordcountModalOpen: () => launchWordcountModal(this.mceInstance(), document, {
@@ -1665,8 +1817,8 @@ class RCEWrapper extends React.Component {
1665
1817
  disabledPlugins: this.pluginsToExclude,
1666
1818
  features: statusBarFeatures,
1667
1819
  onAI: this.handleAIClick
1668
- }), ((_this$props$trayProps10 = this.props.trayProps) === null || _this$props$trayProps10 === void 0 ? void 0 : _this$props$trayProps10.containingContext) && /*#__PURE__*/React.createElement(CanvasContentTray, Object.assign({
1669
- mountNode: instuiPopupMountNode,
1820
+ }), this.props.trayProps?.containingContext && /*#__PURE__*/React.createElement(CanvasContentTray, Object.assign({
1821
+ mountNode: instuiPopupMountNodeFn,
1670
1822
  key: this.id,
1671
1823
  canvasOrigin: this.getCanvasUrl(),
1672
1824
  bridge: bridge,
@@ -1674,15 +1826,19 @@ class RCEWrapper extends React.Component {
1674
1826
  onTrayClosing: this.handleContentTrayClosing,
1675
1827
  use_rce_icon_maker: this.props.use_rce_icon_maker
1676
1828
  }, trayProps, {
1829
+ // @ts-expect-error
1677
1830
  storeProps: storeProps
1678
1831
  })), /*#__PURE__*/React.createElement(KeyboardShortcutModal, {
1679
1832
  onExited: this.KBShortcutModalExited,
1680
1833
  onDismiss: this.closeKBShortcutModal,
1681
1834
  open: this.state.KBShortcutModalOpen
1682
- }), this.props.ai_text_tools && this.AIToolsTray && /*#__PURE__*/React.createElement(this.AIToolsTray, {
1835
+ }), this.props.ai_text_tools && this.AIToolsTray &&
1836
+ /*#__PURE__*/
1837
+ // @ts-expect-error
1838
+ React.createElement(this.AIToolsTray, {
1683
1839
  open: this.state.AIToolsOpen,
1684
1840
  container: document.querySelector('[role="main"]'),
1685
- mountNode: instuiPopupMountNode,
1841
+ mountNode: instuiPopupMountNodeFn,
1686
1842
  contextId: trayProps.contextId,
1687
1843
  contextType: trayProps.contextId,
1688
1844
  currentContent: this.getCurrentContentForAI(),
@@ -1706,11 +1862,36 @@ class RCEWrapper extends React.Component {
1706
1862
  }));
1707
1863
  }
1708
1864
  }
1709
-
1710
- // standard: string of tinymce menu commands
1711
- // e.g. 'instructure_links | inserttable instructure_media_embed | hr'
1712
- // custom: a string of tinymce menu commands
1713
- // returns: standard + custom with any duplicate commands removed from custom
1865
+ RCEWrapper.propTypes = {
1866
+ ai_text_tools: _pt.bool,
1867
+ autosave: _pt.shape({
1868
+ enabled: _pt.bool,
1869
+ maxAge: _pt.number,
1870
+ interval: _pt.number
1871
+ }),
1872
+ canvasOrigin: _pt.string,
1873
+ defaultContent: _pt.string,
1874
+ editorView: _pt.string,
1875
+ features: _pt.objectOf(_pt.any),
1876
+ handleUnmount: _pt.func,
1877
+ instRecordDisabled: _pt.bool,
1878
+ language: _pt.string,
1879
+ ltiToolFavorites: _pt.arrayOf(_pt.string),
1880
+ maxInitRenderedRCEs: _pt.number,
1881
+ name: _pt.string,
1882
+ onBlur: _pt.func,
1883
+ onContentChange: _pt.func,
1884
+ onFocus: _pt.func,
1885
+ onInitted: _pt.func,
1886
+ onRemove: _pt.func,
1887
+ readOnly: _pt.bool,
1888
+ renderKBShortcutModal: _pt.bool,
1889
+ textareaClassName: _pt.string,
1890
+ textareaId: _pt.string,
1891
+ tinymce: _pt.any.isRequired,
1892
+ use_rce_icon_maker: _pt.bool,
1893
+ userCacheKey: _pt.string
1894
+ };
1714
1895
  RCEWrapper.propTypes = rceWrapperPropTypes;
1715
1896
  RCEWrapper.defaultProps = {
1716
1897
  trayProps: null,
@@ -1721,83 +1902,10 @@ RCEWrapper.defaultProps = {
1721
1902
  ltiTools: [],
1722
1903
  maxInitRenderedRCEs: -1,
1723
1904
  features: {},
1724
- timezone: (_Intl = Intl) === null || _Intl === void 0 ? void 0 : (_Intl$DateTimeFormat = _Intl.DateTimeFormat()) === null || _Intl$DateTimeFormat === void 0 ? void 0 : (_Intl$DateTimeFormat$ = _Intl$DateTimeFormat.resolvedOptions()) === null || _Intl$DateTimeFormat$ === void 0 ? void 0 : _Intl$DateTimeFormat$.timeZone,
1905
+ timezone: Intl?.DateTimeFormat()?.resolvedOptions()?.timeZone,
1725
1906
  canvasOrigin: '',
1726
1907
  variant: 'full'
1727
1908
  };
1728
1909
  RCEWrapper.skinCssInjected = false;
1729
- function mergeMenuItems(standard, custom) {
1730
- var _custom$trim;
1731
- let c = custom === null || custom === void 0 ? void 0 : (_custom$trim = custom.trim) === null || _custom$trim === void 0 ? void 0 : _custom$trim.call(custom);
1732
- if (!c) return standard;
1733
- const s = new Set(standard.split(/[\s|]+/));
1734
- // remove any duplicates
1735
- c = c.split(/\s+/).filter(m => !s.has(m));
1736
- c = c.join(' ').replace(/^\s*\|\s*/, '').replace(/\s*\|\s*$/, '');
1737
- return `${standard} | ${c}`;
1738
- }
1739
-
1740
- // standard: the incoming tinymce menu object
1741
- // custom: tinymce menu object to merge into standard
1742
- // returns: the merged result by mutating incoming standard arg.
1743
- // It will add commands to existing menus, or add a new menu
1744
- // if the custom one does not exist
1745
- function mergeMenu(standard, custom) {
1746
- if (!custom) return standard;
1747
- Object.keys(custom).forEach(k => {
1748
- const curr_m = standard[k];
1749
- if (curr_m) {
1750
- curr_m.items = mergeMenuItems(curr_m.items, custom[k].items);
1751
- } else {
1752
- standard[k] = {
1753
- ...custom[k]
1754
- };
1755
- }
1756
- });
1757
- return standard;
1758
- }
1759
-
1760
- // standard: incoming tinymce toolbar array
1761
- // custom: tinymce toolbar array to merge into standard
1762
- // returns: the merged result by mutating the incoming standard arg.
1763
- // It will add commands to existing toolbars, or add a new toolbar
1764
- // if the custom one does not exist
1765
- function mergeToolbar(standard, custom) {
1766
- if (!custom) return standard;
1767
- // merge given toolbar data into the default toolbar
1768
- custom.forEach(tb => {
1769
- const curr_tb = standard.find(t => tb.name && formatMessage(tb.name) === t.name);
1770
- if (curr_tb) {
1771
- curr_tb.items.splice(curr_tb.items.length, 0, ...tb.items);
1772
- } else {
1773
- standard.push(tb);
1774
- }
1775
- });
1776
- return standard;
1777
- }
1778
-
1779
- // standard: incoming array of plugin names
1780
- // custom: array of plugin names to merge
1781
- // exclusions: array of plugins to remove
1782
- // returns: the merged result, duplicates and exclusions removed
1783
- function mergePlugins(standard) {
1784
- let custom = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
1785
- let exclusions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
1786
- const union = new Set(standard);
1787
- for (const c of custom) {
1788
- union.add(c);
1789
- }
1790
- for (const e of exclusions) {
1791
- union.delete(e);
1792
- }
1793
- return [...union];
1794
- }
1795
-
1796
- // plugins is an array of strings
1797
- // the convention is that plugins starting with '-',
1798
- // i.e. a hyphen, are to be disabled in the RCE instance
1799
- function parsePluginsToExclude(plugins) {
1800
- return plugins.filter(plugin => plugin.length > 0 && plugin[0] === '-').map(pluginToIgnore => pluginToIgnore.slice(1));
1801
- }
1802
1910
  export default RCEWrapper;
1803
1911
  export { mergeMenuItems, mergeMenu, mergeToolbar, mergePlugins, parsePluginsToExclude };