@instructure/canvas-rce 5.14.1 → 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 (489) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/DEVELOPMENT.md +2 -2
  3. package/README.md +0 -8
  4. package/__tests__/common/indicate.test.js +84 -0
  5. package/__tests__/common/mimeClass.test.js +85 -0
  6. package/__tests__/module/contentInsertionUtils.test.js +52 -0
  7. package/__tests__/module/indicatorRegion.test.js +75 -0
  8. package/__tests__/module/normalizeLocale.test.js +46 -0
  9. package/__tests__/module/normalizeProps.test.js +51 -0
  10. package/__tests__/module/sanitizePlugins.test.js +48 -0
  11. package/__tests__/module/wrapInitCb.test.js +56 -0
  12. package/__tests__/rcs/api.test.js +819 -0
  13. package/{mocha-reporter-config.js → __tests__/sidebar/actions/all_files.test.js} +10 -9
  14. package/__tests__/sidebar/actions/data.test.js +196 -0
  15. package/__tests__/sidebar/actions/utils.js +44 -0
  16. package/{es/rce/__mocks__/_mockStudioPlayer.js → __tests__/sidebar/reducers/all_files.test.js} +12 -4
  17. package/babel.config.js +3 -1
  18. package/es/bridge/Bridge.js +18 -73
  19. package/es/bridge/index.js +1 -0
  20. package/es/canvasFileBrowser/FileBrowser.js +21 -77
  21. package/es/canvasFileBrowser/en-US.js +3 -6
  22. package/es/common/FlashAlert.js +15 -39
  23. package/es/common/browser.js +4 -2
  24. package/es/common/fileUrl.js +105 -64
  25. package/es/common/incremental-loading/LoadMoreButton.js +4 -4
  26. package/es/common/incremental-loading/LoadingIndicator.js +1 -2
  27. package/es/common/incremental-loading/LoadingStatus.js +5 -13
  28. package/es/common/incremental-loading/index.js +1 -0
  29. package/es/common/incremental-loading/useIncrementalLoading.js +1 -3
  30. package/es/common/indicate.js +16 -10
  31. package/es/common/mimeClass.js +3 -4
  32. package/es/common/natcompare.js +1 -4
  33. package/es/defaultTinymceConfig.js +5 -3
  34. package/es/elementDenylist.js +1 -0
  35. package/es/enhance-user-content/doc_previews.js +24 -35
  36. package/es/enhance-user-content/enhance_user_content.js +32 -67
  37. package/es/enhance-user-content/external_links.js +6 -9
  38. package/es/enhance-user-content/index.js +1 -0
  39. package/es/enhance-user-content/instructure_helper.js +22 -50
  40. package/es/enhance-user-content/jqueryish_funcs.js +8 -11
  41. package/es/enhance-user-content/mathml.js +48 -107
  42. package/es/enhance-user-content/media_comment_thumbnail.js +6 -25
  43. package/es/format-message.js +4 -5
  44. package/es/getThemeVars.js +8 -6
  45. package/es/getTranslations.js +1 -78
  46. package/es/index.d.ts +59 -0
  47. package/es/index.js +6 -6
  48. package/es/rce/AlertMessageArea.js +15 -16
  49. package/es/rce/DraggingBlocker.js +4 -2
  50. package/es/rce/KeyboardShortcutModal.js +3 -2
  51. package/es/rce/RCE.js +16 -17
  52. package/es/rce/RCEGlobals.js +12 -10
  53. package/es/rce/RCEVariants.js +29 -14
  54. package/es/rce/RCEWrapper.js +530 -641
  55. package/es/rce/RCEWrapper.utils.js +131 -0
  56. package/es/rce/RCEWrapperProps.js +9 -5
  57. package/es/rce/RceHtmlEditor.js +17 -19
  58. package/es/rce/ResizeHandle.js +4 -10
  59. package/es/rce/RestoreAutoSaveModal.js +1 -2
  60. package/es/rce/ShowOnFocusButton/index.js +2 -8
  61. package/es/rce/StatusBar.js +10 -44
  62. package/es/rce/alertHandler.js +1 -4
  63. package/es/rce/contentInsertion.js +36 -59
  64. package/es/rce/contentInsertionUtils.js +6 -8
  65. package/es/rce/contentRendering.js +13 -17
  66. package/es/rce/customEvents.js +1 -0
  67. package/es/rce/editorLanguage.js +23 -11
  68. package/es/rce/indicatorRegion.js +7 -7
  69. package/es/rce/normalizeLocale.js +5 -3
  70. package/es/rce/normalizeProps.js +7 -5
  71. package/es/rce/plugins/instructure-ui-icons/plugin.js +21 -3
  72. package/es/rce/plugins/instructure_color/clickCallback.js +82 -0
  73. package/es/rce/plugins/instructure_color/components/ColorPicker.js +294 -0
  74. package/es/rce/plugins/instructure_color/components/ColorPopup.js +67 -0
  75. package/es/rce/plugins/instructure_color/components/colorUtils.js +60 -0
  76. package/es/rce/plugins/instructure_color/plugin.js +40 -0
  77. package/es/rce/plugins/instructure_condensed_buttons/core/ListUtils.js +10 -3
  78. package/es/rce/plugins/instructure_condensed_buttons/plugin.js +1 -0
  79. package/es/rce/plugins/instructure_condensed_buttons/ui/alignment-button.js +1 -2
  80. package/es/rce/plugins/instructure_condensed_buttons/ui/directionality-button.js +3 -2
  81. package/es/rce/plugins/instructure_condensed_buttons/ui/indent-outdent-button.js +1 -0
  82. package/es/rce/plugins/instructure_condensed_buttons/ui/list-button.js +26 -25
  83. package/es/rce/plugins/instructure_condensed_buttons/ui/subscript-superscript-button.js +2 -3
  84. package/es/rce/plugins/instructure_documents/clickCallback.js +1 -0
  85. package/es/rce/plugins/instructure_documents/components/DocumentsPanel.js +1 -9
  86. package/es/rce/plugins/instructure_documents/components/Link.js +4 -20
  87. package/es/rce/plugins/instructure_documents/plugin.js +7 -14
  88. package/es/rce/plugins/instructure_equation/EquationEditorModal/advancedOnlySyntax.js +4 -2
  89. package/es/rce/plugins/instructure_equation/EquationEditorModal/advancedPreference.js +1 -2
  90. package/es/rce/plugins/instructure_equation/EquationEditorModal/index.js +17 -37
  91. package/es/rce/plugins/instructure_equation/EquationEditorModal/latexTextareaUtil.js +14 -15
  92. package/es/rce/plugins/instructure_equation/EquationEditorModal/parseLatex.js +6 -5
  93. package/es/rce/plugins/instructure_equation/EquationEditorModal/styles.js +4 -2
  94. package/es/rce/plugins/instructure_equation/EquationEditorToolbar/buttons.js +14 -8
  95. package/es/rce/plugins/instructure_equation/EquationEditorToolbar/index.js +13 -18
  96. package/es/rce/plugins/instructure_equation/MathIcon/index.js +4 -5
  97. package/es/rce/plugins/instructure_equation/MathIcon/svgs.js +1 -1
  98. package/es/rce/plugins/instructure_equation/clickCallback.js +2 -5
  99. package/es/rce/plugins/instructure_equation/mathlive/index.js +167 -16
  100. package/es/rce/plugins/instructure_equation/plugin.js +7 -10
  101. package/es/rce/plugins/instructure_fullscreen/plugin.js +1 -6
  102. package/es/rce/plugins/instructure_html_view/clickCallback.js +1 -0
  103. package/es/rce/plugins/instructure_html_view/plugin.js +5 -4
  104. package/es/rce/plugins/instructure_icon_maker/clickCallback.js +5 -8
  105. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ColorSection.js +47 -51
  106. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/CreateIconMakerForm.js +10 -10
  107. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/Footer.js +11 -11
  108. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/Group.js +6 -6
  109. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/Header.js +8 -10
  110. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/Course.js +32 -31
  111. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/ImageOptions.js +24 -35
  112. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/ImageSection.js +32 -32
  113. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/ModeSelect.js +11 -11
  114. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/MultiColor/index.js +16 -15
  115. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/MultiColor/svg.js +1 -0
  116. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/SVGList.js +11 -11
  117. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/SVGThumbnail.js +9 -13
  118. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/SingleColor/index.js +12 -13
  119. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/SingleColor/svg.js +33 -80
  120. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/Upload.js +34 -28
  121. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/index.js +1 -0
  122. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/propTypes.js +1 -0
  123. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/utils.js +5 -5
  124. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/Preview.js +7 -8
  125. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ShapeSection.js +5 -7
  126. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/TextSection.js +5 -10
  127. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/index.js +1 -0
  128. package/es/rce/plugins/instructure_icon_maker/components/IconMakerTray.js +38 -60
  129. package/es/rce/plugins/instructure_icon_maker/components/SavedIconMakerList.js +4 -4
  130. package/es/rce/plugins/instructure_icon_maker/plugin.js +10 -14
  131. package/es/rce/plugins/instructure_icon_maker/reducers/imageSection.js +37 -38
  132. package/es/rce/plugins/instructure_icon_maker/reducers/svgSettings.js +24 -24
  133. package/es/rce/plugins/instructure_icon_maker/registerEditToolbar.js +2 -4
  134. package/es/rce/plugins/instructure_icon_maker/svg/constants.js +4 -3
  135. package/es/rce/plugins/instructure_icon_maker/svg/font.js +3 -1
  136. package/es/rce/plugins/instructure_icon_maker/svg/image.js +74 -90
  137. package/es/rce/plugins/instructure_icon_maker/svg/index.js +17 -24
  138. package/es/rce/plugins/instructure_icon_maker/svg/metadata.js +1 -0
  139. package/es/rce/plugins/instructure_icon_maker/svg/settings.js +48 -58
  140. package/es/rce/plugins/instructure_icon_maker/svg/shape.js +5 -54
  141. package/es/rce/plugins/instructure_icon_maker/svg/text.js +35 -124
  142. package/es/rce/plugins/instructure_icon_maker/svg/utils.js +3 -11
  143. package/es/rce/plugins/instructure_icon_maker/utils/IconMakerClose.js +4 -9
  144. package/es/rce/plugins/instructure_icon_maker/utils/IconMakerFormHasChanges.js +1 -15
  145. package/es/rce/plugins/instructure_icon_maker/utils/addIconMakerAttributes.js +3 -4
  146. package/es/rce/plugins/instructure_icon_maker/utils/iconValidation.js +2 -3
  147. package/es/rce/plugins/instructure_icon_maker/utils/iconsLabels.js +1 -0
  148. package/es/rce/plugins/instructure_icon_maker/utils/useDebouncedValue.js +12 -13
  149. package/es/rce/plugins/instructure_image/ImageEmbedOptions.js +9 -31
  150. package/es/rce/plugins/instructure_image/ImageList/Image.js +8 -14
  151. package/es/rce/plugins/instructure_image/ImageList/index.js +8 -10
  152. package/es/rce/plugins/instructure_image/ImageOptionsTray/TrayController.js +9 -31
  153. package/es/rce/plugins/instructure_image/ImageOptionsTray/index.js +6 -19
  154. package/es/rce/plugins/instructure_image/Images/index.js +1 -3
  155. package/es/rce/plugins/instructure_image/clickCallback.js +1 -0
  156. package/es/rce/plugins/instructure_image/plugin.js +14 -20
  157. package/es/rce/plugins/instructure_links/clickCallback.js +1 -0
  158. package/es/rce/plugins/instructure_links/components/AccordionSection.js +8 -8
  159. package/es/rce/plugins/instructure_links/components/CollectionPanel.js +1 -3
  160. package/es/rce/plugins/instructure_links/components/Link.js +68 -84
  161. package/es/rce/plugins/instructure_links/components/LinkOptionsDialog/LinkOptionsDialogController.js +2 -23
  162. package/es/rce/plugins/instructure_links/components/LinkOptionsDialog/index.js +3 -6
  163. package/es/rce/plugins/instructure_links/components/LinkOptionsTray/LinkOptionsTrayController.js +3 -20
  164. package/es/rce/plugins/instructure_links/components/LinkOptionsTray/index.js +3 -14
  165. package/es/rce/plugins/instructure_links/components/LinkSet.js +32 -57
  166. package/es/rce/plugins/instructure_links/components/LinksPanel.js +22 -10
  167. package/es/rce/plugins/instructure_links/components/NavigationPanel.js +7 -9
  168. package/es/rce/plugins/instructure_links/components/NoResults.js +7 -14
  169. package/es/rce/plugins/instructure_links/plugin.js +23 -49
  170. package/es/rce/plugins/instructure_links/validateURL.js +81 -36
  171. package/es/rce/plugins/instructure_media_embed/clickCallback.js +5 -9
  172. package/es/rce/plugins/instructure_media_embed/components/Embed.js +7 -7
  173. package/es/rce/plugins/instructure_media_embed/plugin.js +7 -3
  174. package/es/rce/plugins/instructure_paste/pasteMenuCommand.js +1 -5
  175. package/es/rce/plugins/instructure_paste/plugin.js +29 -33
  176. package/es/rce/plugins/instructure_rce_external_tools/ExternalToolsEnv.js +31 -79
  177. package/es/rce/plugins/instructure_rce_external_tools/RceToolWrapper.js +24 -83
  178. package/es/rce/plugins/instructure_rce_external_tools/components/ExternalToolDialog/ExternalToolDialog.js +39 -69
  179. package/es/rce/plugins/instructure_rce_external_tools/components/ExternalToolDialog/ExternalToolDialogModal.js +1 -2
  180. package/es/rce/plugins/instructure_rce_external_tools/components/ExternalToolDialog/ExternalToolDialogTray.js +1 -1
  181. package/es/rce/plugins/instructure_rce_external_tools/components/ExternalToolSelectionDialog/ExternalToolSelectionDialog.js +5 -14
  182. package/es/rce/plugins/instructure_rce_external_tools/components/ExternalToolSelectionDialog/ExternalToolSelectionItem.js +1 -2
  183. package/es/rce/plugins/instructure_rce_external_tools/components/util/ExpandoText.js +1 -0
  184. package/es/rce/plugins/instructure_rce_external_tools/components/util/ToolLaunchIframe.js +2 -1
  185. package/es/rce/plugins/instructure_rce_external_tools/constants.js +28 -0
  186. package/es/rce/plugins/instructure_rce_external_tools/dialog-helper.js +20 -6
  187. package/es/rce/plugins/instructure_rce_external_tools/helpers/tags.js +0 -2
  188. package/es/rce/plugins/instructure_rce_external_tools/jquery/jquery.dropdownList.js +129 -136
  189. package/es/rce/plugins/instructure_rce_external_tools/lti11-content-items/RceLti11ContentItem.js +110 -112
  190. package/es/rce/plugins/instructure_rce_external_tools/lti13-content-items/Lti13ContentItemJson.js +1 -0
  191. package/es/rce/plugins/instructure_rce_external_tools/lti13-content-items/RceLti13ContentItem.js +4 -21
  192. package/es/rce/plugins/instructure_rce_external_tools/lti13-content-items/models/BaseLinkContentItem.js +5 -19
  193. package/es/rce/plugins/instructure_rce_external_tools/lti13-content-items/models/HtmlFragmentContentItem.js +1 -6
  194. package/es/rce/plugins/instructure_rce_external_tools/lti13-content-items/models/ImageContentItem.js +1 -9
  195. package/es/rce/plugins/instructure_rce_external_tools/lti13-content-items/models/LinkContentItem.js +1 -1
  196. package/es/rce/plugins/instructure_rce_external_tools/lti13-content-items/models/ResourceLinkContentItem.js +3 -5
  197. package/es/rce/plugins/instructure_rce_external_tools/lti13-content-items/processEditorContentItems.js +23 -16
  198. package/es/rce/plugins/instructure_rce_external_tools/lti13-content-items/rceLti13ContentItemFromJson.js +3 -4
  199. package/es/rce/plugins/instructure_rce_external_tools/plugin.js +11 -20
  200. package/es/rce/plugins/instructure_rce_external_tools/util/addParentFrameContextToUrl.js +1 -1
  201. package/es/rce/plugins/instructure_rce_external_tools/util/externalToolsForToolbar.js +42 -0
  202. package/es/rce/plugins/instructure_record/AudioOptionsTray/TrayController.js +6 -35
  203. package/es/rce/plugins/instructure_record/AudioOptionsTray/index.js +13 -17
  204. package/es/rce/plugins/instructure_record/MediaPanel/index.js +1 -9
  205. package/es/rce/plugins/instructure_record/VideoOptionsTray/TrayController.js +16 -66
  206. package/es/rce/plugins/instructure_record/VideoOptionsTray/index.js +21 -35
  207. package/es/rce/plugins/instructure_record/clickCallback.js +32 -44
  208. package/es/rce/plugins/instructure_record/mediaTranslations.js +1 -0
  209. package/es/rce/plugins/instructure_record/plugin.js +11 -18
  210. package/es/rce/plugins/instructure_search_and_replace/clickCallback.js +4 -8
  211. package/es/rce/plugins/instructure_search_and_replace/components/FindReplaceTray.js +34 -51
  212. package/es/rce/plugins/instructure_search_and_replace/components/FindReplaceTrayController.js +12 -30
  213. package/es/rce/plugins/instructure_search_and_replace/getSelectionContext.js +2 -9
  214. package/es/rce/plugins/instructure_search_and_replace/plugin.js +2 -5
  215. package/es/rce/plugins/instructure_studio_media_options/plugin.js +1 -1
  216. package/es/rce/plugins/instructure_wordcount/clickCallback.js +5 -9
  217. package/es/rce/plugins/instructure_wordcount/components/WordCountModal.js +27 -37
  218. package/es/rce/plugins/instructure_wordcount/plugin.js +1 -0
  219. package/es/rce/plugins/instructure_wordcount/utils/countContent.js +4 -11
  220. package/es/rce/plugins/instructure_wordcount/utils/tableContent.js +6 -8
  221. package/es/rce/plugins/shared/CanvasContentTray.js +29 -63
  222. package/es/rce/plugins/shared/CheckerboardStyling.js +1 -1
  223. package/es/rce/plugins/shared/ColorInput.js +27 -39
  224. package/es/rce/plugins/shared/ConditionalTooltip.js +6 -6
  225. package/es/rce/plugins/shared/ContentSelection.js +29 -78
  226. package/es/rce/plugins/shared/DimensionUtils.js +3 -12
  227. package/es/rce/plugins/shared/DimensionsInput/DimensionInput.js +6 -6
  228. package/es/rce/plugins/shared/DimensionsInput/index.js +37 -15
  229. package/es/rce/plugins/shared/DimensionsInput/useDimensionsState.js +5 -29
  230. package/es/rce/plugins/shared/ErrorBoundary.js +2 -5
  231. package/es/rce/plugins/shared/EventUtils.js +2 -4
  232. package/es/rce/plugins/shared/Filter.js +8 -38
  233. package/es/rce/plugins/shared/FixedContentTray.js +16 -17
  234. package/es/rce/plugins/shared/ImageCropper/DirectionRegion.js +4 -12
  235. package/es/rce/plugins/shared/ImageCropper/Modal.js +16 -20
  236. package/es/rce/plugins/shared/ImageCropper/Preview.js +18 -24
  237. package/es/rce/plugins/shared/ImageCropper/constants.js +1 -0
  238. package/es/rce/plugins/shared/ImageCropper/controls/CustomNumberInput.js +10 -14
  239. package/es/rce/plugins/shared/ImageCropper/controls/ResetControls.js +4 -4
  240. package/es/rce/plugins/shared/ImageCropper/controls/RotationControls.js +5 -15
  241. package/es/rce/plugins/shared/ImageCropper/controls/ShapeControls.js +8 -11
  242. package/es/rce/plugins/shared/ImageCropper/controls/ZoomControls.js +5 -16
  243. package/es/rce/plugins/shared/ImageCropper/controls/index.js +5 -5
  244. package/es/rce/plugins/shared/ImageCropper/controls/useDebouncedNumericValue.js +16 -31
  245. package/es/rce/plugins/shared/ImageCropper/controls/utils.js +1 -2
  246. package/es/rce/plugins/shared/ImageCropper/imageCropUtils.js +19 -31
  247. package/es/rce/plugins/shared/ImageCropper/index.js +1 -0
  248. package/es/rce/plugins/shared/ImageCropper/propTypes.js +1 -0
  249. package/es/rce/plugins/shared/ImageCropper/reducers/imageCropper.js +15 -14
  250. package/es/rce/plugins/shared/ImageCropper/shape.js +1 -0
  251. package/es/rce/plugins/shared/ImageCropper/svg/index.js +1 -2
  252. package/es/rce/plugins/shared/ImageCropper/svg/shape.js +5 -22
  253. package/es/rce/plugins/shared/ImageCropper/svg/utils.js +3 -4
  254. package/es/rce/plugins/shared/ImageCropper/useKeyMouseEvents.js +20 -50
  255. package/es/rce/plugins/shared/ImageCropper/useMouseWheel.js +8 -10
  256. package/es/rce/plugins/shared/ImageOptionsForm.js +18 -20
  257. package/es/rce/plugins/shared/LinkDisplay.js +9 -11
  258. package/es/rce/plugins/shared/PreviewIcon.js +9 -15
  259. package/es/rce/plugins/shared/Previewable.js +1 -0
  260. package/es/rce/plugins/shared/RceFileBrowser.js +7 -10
  261. package/es/rce/plugins/shared/StoreContext.js +9 -12
  262. package/es/rce/plugins/shared/StudioLtiSupportUtils.js +15 -12
  263. package/es/rce/plugins/shared/UnknownFileTypePanel.js +1 -0
  264. package/es/rce/plugins/shared/Upload/CanvasContentPanel.js +19 -25
  265. package/es/rce/plugins/shared/Upload/CategoryProcessor.js +2 -3
  266. package/es/rce/plugins/shared/Upload/ComputerPanel.js +19 -40
  267. package/es/rce/plugins/shared/Upload/PanelFilter.js +10 -20
  268. package/es/rce/plugins/shared/Upload/SvgCategoryProcessor.js +4 -3
  269. package/es/rce/plugins/shared/Upload/UploadFile.js +32 -38
  270. package/es/rce/plugins/shared/Upload/UploadFileModal.js +37 -59
  271. package/es/rce/plugins/shared/Upload/UrlPanel.js +5 -5
  272. package/es/rce/plugins/shared/Upload/UsageRightsSelectBox.js +25 -36
  273. package/es/rce/plugins/shared/Upload/doFileUpload.js +10 -13
  274. package/es/rce/plugins/shared/Upload/index.js +1 -0
  275. package/es/rce/plugins/shared/ai_tools/AIResponseModal.js +8 -11
  276. package/es/rce/plugins/shared/ai_tools/AIToolsTray.js +19 -40
  277. package/es/rce/plugins/shared/ai_tools/aiicons.js +3 -2
  278. package/es/rce/plugins/shared/ai_tools/index.js +1 -0
  279. package/es/rce/plugins/shared/buildDownloadUrl.js +0 -2
  280. package/es/rce/plugins/shared/canvasContentUtils.js +7 -11
  281. package/es/rce/plugins/shared/compressionUtils.js +18 -28
  282. package/es/rce/plugins/shared/dateUtils.js +1 -1
  283. package/es/rce/plugins/shared/do-fetch-api-effect/defaultFetchOptions.js +4 -2
  284. package/es/rce/plugins/shared/do-fetch-api-effect/doFetchApi.js +18 -24
  285. package/es/rce/plugins/shared/do-fetch-api-effect/get-cookie.js +1 -1
  286. package/es/rce/plugins/shared/do-fetch-api-effect/index.js +1 -0
  287. package/es/rce/plugins/shared/do-fetch-api-effect/parse-link-header.js +6 -20
  288. package/es/rce/plugins/shared/do-fetch-api-effect/query-string-encoding.js +5 -3
  289. package/es/rce/plugins/shared/fileShape.js +4 -9
  290. package/es/rce/plugins/shared/fileTypeUtils.js +34 -47
  291. package/es/rce/plugins/shared/fileUtils.js +1 -2
  292. package/es/rce/plugins/shared/linkUtils.js +1 -16
  293. package/es/rce/plugins/shared/round.js +2 -2
  294. package/es/rce/plugins/shared/trayUtils.js +7 -3
  295. package/es/rce/plugins/shared/useDataUrl.js +13 -14
  296. package/es/rce/plugins/shared/useFilterSettings.js +3 -3
  297. package/es/rce/plugins/tinymce-a11y-checker/components/ColorField.js +4 -8
  298. package/es/rce/plugins/tinymce-a11y-checker/components/checker.js +12 -72
  299. package/es/rce/plugins/tinymce-a11y-checker/components/color-picker.js +1 -2
  300. package/es/rce/plugins/tinymce-a11y-checker/components/placeholder-svg.js +1 -0
  301. package/es/rce/plugins/tinymce-a11y-checker/components/pointer.js +1 -0
  302. package/es/rce/plugins/tinymce-a11y-checker/node-checker.js +2 -9
  303. package/es/rce/plugins/tinymce-a11y-checker/plugin.js +18 -24
  304. package/es/rce/plugins/tinymce-a11y-checker/rules/adjacent-links.js +3 -26
  305. package/es/rce/plugins/tinymce-a11y-checker/rules/headings-sequence.js +9 -38
  306. package/es/rce/plugins/tinymce-a11y-checker/rules/headings-start-at-h2.js +2 -7
  307. package/es/rce/plugins/tinymce-a11y-checker/rules/img-alt-filename.js +1 -2
  308. package/es/rce/plugins/tinymce-a11y-checker/rules/img-alt-length.js +1 -1
  309. package/es/rce/plugins/tinymce-a11y-checker/rules/img-alt.js +1 -2
  310. package/es/rce/plugins/tinymce-a11y-checker/rules/index.js +1 -0
  311. package/es/rce/plugins/tinymce-a11y-checker/rules/large-text-contrast.js +2 -6
  312. package/es/rce/plugins/tinymce-a11y-checker/rules/list-structure.js +5 -24
  313. package/es/rce/plugins/tinymce-a11y-checker/rules/paragraphs-for-headings.js +1 -3
  314. package/es/rce/plugins/tinymce-a11y-checker/rules/small-text-contrast.js +2 -8
  315. package/es/rce/plugins/tinymce-a11y-checker/rules/table-caption.js +1 -3
  316. package/es/rce/plugins/tinymce-a11y-checker/rules/table-header-scope.js +1 -2
  317. package/es/rce/plugins/tinymce-a11y-checker/rules/table-header.js +1 -9
  318. package/es/rce/plugins/tinymce-a11y-checker/utils/colors.js +1 -0
  319. package/es/rce/plugins/tinymce-a11y-checker/utils/describe.js +1 -7
  320. package/es/rce/plugins/tinymce-a11y-checker/utils/dom.js +3 -30
  321. package/es/rce/plugins/tinymce-a11y-checker/utils/indicate.js +18 -18
  322. package/es/rce/plugins/tinymce-a11y-checker/utils/rgb-hex.js +6 -12
  323. package/es/rce/plugins/tinymce-a11y-checker/utils/strings.js +1 -4
  324. package/es/rce/root.js +17 -16
  325. package/es/rce/sanitizePlugins.js +1 -3
  326. package/es/rce/style.js +1 -4
  327. package/es/rce/tinyRCE.js +14 -9
  328. package/es/rce/tinymce.oxide.content.min.css.js +1 -0
  329. package/es/rce/tinymce.oxide.skin.min.css.js +1 -0
  330. package/es/rce/transformContent.js +9 -11
  331. package/es/rce/types.js +1 -0
  332. package/es/rce/userOS.js +1 -1
  333. package/es/rce/wrapInitCb.js +50 -43
  334. package/es/rcs/api.js +100 -171
  335. package/es/rcs/buildError.js +8 -20
  336. package/es/rcs/fake.js +9 -20
  337. package/es/sidebar/actions/all_files.js +2 -0
  338. package/es/sidebar/actions/data.js +4 -7
  339. package/es/sidebar/actions/documents.js +19 -18
  340. package/es/sidebar/actions/files.js +21 -28
  341. package/es/sidebar/actions/filter.js +5 -5
  342. package/es/sidebar/actions/flickr.js +1 -1
  343. package/es/sidebar/actions/images.js +32 -37
  344. package/es/sidebar/actions/links.js +1 -0
  345. package/es/sidebar/actions/media.js +27 -28
  346. package/es/sidebar/actions/session.js +2 -5
  347. package/es/sidebar/actions/ui.js +1 -0
  348. package/es/sidebar/actions/upload.js +38 -74
  349. package/es/sidebar/containers/Sidebar.js +1 -2
  350. package/es/sidebar/containers/sidebarHandlers.js +9 -13
  351. package/es/sidebar/dragHtml.js +11 -5
  352. package/es/sidebar/reducers/all_files.js +5 -6
  353. package/es/sidebar/reducers/collection.js +12 -15
  354. package/es/sidebar/reducers/collections.js +6 -8
  355. package/es/sidebar/reducers/documents.js +7 -16
  356. package/es/sidebar/reducers/files.js +4 -6
  357. package/es/sidebar/reducers/filter.js +8 -23
  358. package/es/sidebar/reducers/flickr.js +10 -12
  359. package/es/sidebar/reducers/folder.js +16 -18
  360. package/es/sidebar/reducers/folders.js +4 -6
  361. package/es/sidebar/reducers/images.js +4 -16
  362. package/es/sidebar/reducers/index.js +3 -1
  363. package/es/sidebar/reducers/media.js +7 -16
  364. package/es/sidebar/reducers/newPageLinkExpanded.js +2 -5
  365. package/es/sidebar/reducers/noop.js +2 -2
  366. package/es/sidebar/reducers/rootFolderId.js +2 -5
  367. package/es/sidebar/reducers/session.js +4 -6
  368. package/es/sidebar/reducers/ui.js +6 -25
  369. package/es/sidebar/reducers/upload.js +16 -64
  370. package/es/sidebar/store/configureStore.js +1 -0
  371. package/es/sidebar/store/initialState.js +14 -26
  372. package/es/translations/locales/ab.js +1 -0
  373. package/es/translations/locales/ar.js +72 -8
  374. package/es/translations/locales/ca.js +72 -8
  375. package/es/translations/locales/cs.js +1 -0
  376. package/es/translations/locales/cs_CZ.js +1 -0
  377. package/es/translations/locales/cy.js +72 -8
  378. package/es/translations/locales/da-x-k12.js +72 -8
  379. package/es/translations/locales/da.js +72 -8
  380. package/es/translations/locales/da_DK.js +1 -0
  381. package/es/translations/locales/de.js +72 -8
  382. package/es/translations/locales/el.js +4 -0
  383. package/es/translations/locales/en-AU-x-unimelb.js +72 -8
  384. package/es/translations/locales/en-GB-x-ukhe.js +72 -8
  385. package/es/translations/locales/en.js +72 -8
  386. package/es/translations/locales/en_AU.js +72 -8
  387. package/es/translations/locales/en_CA.js +72 -8
  388. package/es/translations/locales/en_CY.js +72 -8
  389. package/es/translations/locales/en_GB.js +72 -8
  390. package/es/translations/locales/en_NZ.js +1 -0
  391. package/es/translations/locales/en_SE.js +1 -0
  392. package/es/translations/locales/en_US.js +1 -0
  393. package/es/translations/locales/es.js +72 -8
  394. package/es/translations/locales/es_ES.js +72 -8
  395. package/es/translations/locales/es_GT.js +1 -0
  396. package/es/translations/locales/fa_IR.js +7 -0
  397. package/es/translations/locales/fi.js +72 -8
  398. package/es/translations/locales/fr.js +72 -8
  399. package/es/translations/locales/fr_CA.js +73 -9
  400. package/es/translations/locales/ga.js +5 -13
  401. package/es/translations/locales/he.js +7 -0
  402. package/es/translations/locales/hi.js +72 -8
  403. package/es/translations/locales/ht.js +72 -8
  404. package/es/translations/locales/hu.js +7 -6
  405. package/es/translations/locales/hu_HU.js +1 -0
  406. package/es/translations/locales/hy.js +1 -0
  407. package/es/translations/locales/id.js +72 -8
  408. package/es/translations/locales/id_ID.js +1 -0
  409. package/es/translations/locales/is.js +72 -8
  410. package/es/translations/locales/it.js +72 -8
  411. package/es/translations/locales/ja.js +72 -8
  412. package/es/translations/locales/ko.js +1 -0
  413. package/es/translations/locales/ko_KR.js +1 -0
  414. package/es/translations/locales/lt.js +1 -0
  415. package/es/translations/locales/lt_LT.js +1 -0
  416. package/es/translations/locales/mi.js +72 -8
  417. package/es/translations/locales/mn_MN.js +1 -0
  418. package/es/translations/locales/ms.js +72 -8
  419. package/es/translations/locales/nb-x-k12.js +72 -8
  420. package/es/translations/locales/nb.js +72 -8
  421. package/es/translations/locales/nl.js +72 -8
  422. package/es/translations/locales/nl_NL.js +1 -0
  423. package/es/translations/locales/nn.js +7 -6
  424. package/es/translations/locales/pl.js +72 -8
  425. package/es/translations/locales/pt.js +72 -8
  426. package/es/translations/locales/pt_BR.js +72 -8
  427. package/es/translations/locales/ro.js +1 -0
  428. package/es/translations/locales/ru.js +72 -8
  429. package/es/translations/locales/se.js +1 -0
  430. package/es/translations/locales/sl.js +72 -8
  431. package/es/translations/locales/sv-x-k12.js +72 -8
  432. package/es/translations/locales/sv.js +72 -8
  433. package/es/translations/locales/sv_SE.js +1 -0
  434. package/es/translations/locales/tg.js +1 -0
  435. package/es/translations/locales/th.js +72 -8
  436. package/es/translations/locales/th_TH.js +1 -0
  437. package/es/translations/locales/tl_PH.js +1 -0
  438. package/es/translations/locales/tr.js +7 -0
  439. package/es/translations/locales/uk_UA.js +7 -0
  440. package/es/translations/locales/vi.js +72 -8
  441. package/es/translations/locales/vi_VN.js +1 -0
  442. package/es/translations/locales/zh-Hans.js +72 -8
  443. package/es/translations/locales/zh-Hant.js +72 -8
  444. package/es/translations/locales/zh.js +72 -8
  445. package/es/translations/locales/zh_HK.js +72 -8
  446. package/es/translations/locales/zh_TW.Big5.js +1 -0
  447. package/es/translations/locales/zh_TW.js +1 -0
  448. package/es/translations/tinymce/ar_SA.js +1 -0
  449. package/es/translations/tinymce/fi.js +1 -0
  450. package/es/translations/tinymce/ga.js +1 -0
  451. package/es/translations/tinymce/id.js +1 -0
  452. package/es/translations/tinymce/ru.js +1 -0
  453. package/es/translations/tinymce/ru_RU.js +1 -0
  454. package/es/translations/tinymce/sl.js +1 -0
  455. package/es/translations/tinymce/sr.js +1 -0
  456. package/es/translations/tinymce/th.js +1 -0
  457. package/es/translations/tinymce/uk_UA.js +1 -0
  458. package/es/translations/tinymce/vi_VN.js +1 -0
  459. package/es/util/TypedDict.js +4 -2
  460. package/es/util/elem-util.js +1 -1
  461. package/es/util/encrypted-storage.js +3 -13
  462. package/es/util/file-url-util.js +2 -7
  463. package/es/util/fullscreenHelpers.js +9 -9
  464. package/es/util/instui-icon-helper.js +4 -3
  465. package/es/util/loadingPlaceholder.js +39 -41
  466. package/es/util/simpleCache.js +1 -5
  467. package/es/util/string-util.js +1 -1
  468. package/es/util/textarea-editing-util.js +3 -7
  469. package/es/util/tinymce-plugin-util.js +0 -5
  470. package/es/util/url-util.js +20 -29
  471. package/eslint.config.js +250 -0
  472. package/jest.config.js +1 -1
  473. package/locales/en.json +190 -10
  474. package/package.json +78 -82
  475. package/scripts/build-canvas +2 -1
  476. package/scripts/build.js +4 -4
  477. package/scripts/installTranslations.js +7 -8
  478. package/testcafe/RCEWrapper.test.js +0 -1
  479. package/testcafe/StatusBar.test.js +0 -1
  480. package/testcafe/axe.test.js +3 -4
  481. package/testcafe/enhanceUserContent.test.js +0 -1
  482. package/tsconfig.json +21 -16
  483. package/{es/rce/__mocks__/styleMock.js → types/format-message-generate-id.d.ts} +6 -2
  484. package/{es/rce/plugins/shared/__mocks__/screenfull.js → types/js-beautify.d.ts} +4 -7
  485. package/.eslintrc +0 -45
  486. package/.prettierignore +0 -6
  487. package/es/rce/__mocks__/_mockCryptoEs.js +0 -124
  488. package/es/rce/__mocks__/tinymceReact.js +0 -55
  489. package/es/rce/plugins/tinymce-a11y-checker/rules/__mocks__/index.js +0 -53
@@ -1,5 +1,3 @@
1
- // @ts-nocheck
2
-
3
1
  /*
4
2
  * Copyright (C) 2019 - present Instructure, Inc.
5
3
  *
@@ -17,10 +15,14 @@
17
15
  * You should have received a copy of the GNU Affero General Public License along
18
16
  * with this program. If not, see <http://www.gnu.org/licenses/>.
19
17
  */
20
- import { IconArrowOpenDownLine, IconAttachMediaLine, IconBoldLine, IconBulletListAlphaLine, IconBulletListCircleOutlineLine, IconBulletListLine, IconBulletListRomanLine, IconBulletListSquareLine, IconClearTextFormattingLine, IconDocumentLine, IconExitFullScreenLine, IconFullScreenLine, IconImageLine, IconIndentLine, IconItalicLine, IconLinkLine, IconLtiLine, IconNumberedListLine, IconOutdentLine, IconRemoveLinkLine, IconStrikethroughLine, IconTextCenteredLine, IconTextDirectionLtrLine, IconTextDirectionRtlLine, IconTextEndLine, IconTextStartLine, IconTextSubscriptLine, IconTextSuperscriptLine, IconUnderlineLine } from '@instructure/ui-icons/es/svg';
18
+
19
+ import { IconArrowOpenDownLine, IconAttachMediaLine, IconBoldLine, IconBulletListAlphaLine, IconBulletListCircleOutlineLine, IconBulletListLine, IconBulletListRomanLine, IconBulletListSquareLine, IconClearTextFormattingLine, IconDocumentLine, IconExitFullScreenLine, IconFullScreenLine, IconImageLine, IconIndentLine, IconItalicLine, IconLinkLine, IconLtiLine, IconNumberedListLine, IconOutdentLine, IconRemoveLinkLine, IconStrikethroughLine, IconTextCenteredLine, IconTextDirectionLtrLine, IconTextDirectionRtlLine, IconTextEndLine, IconTextStartLine, IconTextSubscriptLine, IconTextSuperscriptLine, IconUnderlineLine
20
+ // @ts-expect-error
21
+ } from '@instructure/ui-icons/es/svg';
21
22
  import tinymce from 'tinymce';
22
23
  tinymce.PluginManager.add('instructure-ui-icons', function (editor) {
23
24
  // the keys here are what tinymce calls it. the values are the svgs from instUI
25
+
24
26
  // there are few things here that are commented out that are things that we
25
27
  // might want to have our own icon for but one doesn't exist in @instructure/ui-icons
26
28
  const icons = {
@@ -55,6 +57,7 @@ tinymce.PluginManager.add('instructure-ui-icons', function (editor) {
55
57
  // that tinyMCE uses that we'd want to match our table icon. So unless we get instUI versions of all
56
58
  // those too, it probably makes sense to just use TinyMCE's for everything table related.
57
59
  // table: IconTableLine,
60
+
58
61
  // The `tox-icon-*` path ids on these 2 are important. It is what tinyMCE
59
62
  // looks for to update the color when you select a new one
60
63
  'text-color': {
@@ -75,6 +78,20 @@ tinymce.PluginManager.add('instructure-ui-icons', function (editor) {
75
78
  </g>
76
79
  </svg>`
77
80
  },
81
+ // the new color UI
82
+ color: {
83
+ src: `<svg data-id="color-button" width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
84
+ <g clip-path="url(#clip0_13_7929)">
85
+ <path d="M5.52715 0L4.48118 1.01914L5.82475 2.33149L0.672221 7.36027C-0.224074 8.23479 -0.224074 9.6186 0.672221 10.4931L0.74662 10.5671L5.45129 15.1575C6.34759 16.032 7.7673 16.032 8.6636 15.1575L14.3398 9.61917L14.8636 9.1096L7.61763 2.0397L7.02097 1.45754L6.87072 1.31093L5.52715 0ZM6.87072 3.35205L12.7716 9.1096L11.129 10.7123H2.9859L1.71673 9.47398C1.41797 9.18248 1.41797 8.67234 1.71673 8.38083L6.87072 3.35205ZM15.7593 11.6603L15.1611 12.5342C15.1611 12.5342 14.788 13.1167 14.3398 13.7726C14.1158 14.137 13.967 14.4288 13.8176 14.7931C13.6682 15.1575 13.5185 15.3764 13.5185 15.8137C13.5185 16.9797 14.5642 18 15.7593 18C16.9543 18 18 16.9797 18 15.8137C18 15.3764 17.8503 15.0849 17.7009 14.7205C17.5516 14.3562 17.3281 13.9915 17.1787 13.7C16.8052 13.0441 16.3574 12.4616 16.3574 12.4616L15.7593 11.6603Z" fill="currentColor"/>
86
+ </g>
87
+ <defs>
88
+ <clipPath id="clip0_13_7929">
89
+ <rect width="18" height="18" fill="white"/>
90
+ </clipPath>
91
+ </defs>
92
+ </svg>
93
+ `
94
+ },
78
95
  unlink: IconRemoveLinkLine,
79
96
  'unordered-list': IconBulletListLine,
80
97
  ltr: IconTextDirectionLtrLine,
@@ -117,6 +134,7 @@ tinymce.PluginManager.add('instructure-ui-icons', function (editor) {
117
134
  }
118
135
  };
119
136
  Object.keys(icons).forEach(key => {
137
+ // @ts-expect-error
120
138
  editor.ui.registry.addIcon(key, icons[key].src);
121
139
  });
122
140
  });
@@ -0,0 +1,82 @@
1
+ /*
2
+ * Copyright (C) 2023 - present Instructure, Inc.
3
+ *
4
+ * This file is part of Canvas.
5
+ *
6
+ * Canvas is free software: you can redistribute it and/or modify it under
7
+ * the terms of the GNU Affero General Public License as published by the Free
8
+ * Software Foundation, version 3 of the License.
9
+ *
10
+ * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
11
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12
+ * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
13
+ * details.
14
+ *
15
+ * You should have received a copy of the GNU Affero General Public License along
16
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+ import React from 'react';
20
+ import { createRoot } from 'react-dom/client';
21
+ import tinycolor from 'tinycolor2';
22
+ import { ColorPopup } from './components/ColorPopup';
23
+ const CONTAINER_ID = 'instructure-color-popup-container';
24
+ export default function (editor) {
25
+ let container = document.getElementById(CONTAINER_ID);
26
+ if (container == null) {
27
+ container = document.createElement('div');
28
+ container.id = CONTAINER_ID;
29
+ document.body.appendChild(container);
30
+ }
31
+ const handleDismiss = () => {
32
+ if (container) {
33
+ container._reactRoot?.unmount();
34
+ container._reactRoot = null;
35
+ }
36
+ };
37
+ const handleChange = newcolors => {
38
+ editor.undoManager.transact(() => {
39
+ if (newcolors.fgcolor) {
40
+ editor.execCommand('forecolor', false, newcolors.fgcolor);
41
+ }
42
+ if (newcolors.bgcolor) {
43
+ editor.execCommand('hilitecolor', false, newcolors.bgcolor);
44
+ }
45
+ if (newcolors.fgcolor || newcolors.bgcolor) {
46
+ editor.nodeChanged();
47
+ }
48
+ handleDismiss();
49
+ });
50
+ };
51
+ if (container?._reactRoot) {
52
+ handleDismiss();
53
+ document.removeEventListener('rce-text-block-popup-close', handleDismiss);
54
+ return;
55
+ }
56
+ document.addEventListener('rce-text-block-popup-close', handleDismiss);
57
+ const defaultTextColor = window.getComputedStyle(editor.getBody()).getPropertyValue('--ic-brand-font-color-dark').toLowerCase();
58
+ const styl = window.getComputedStyle(editor.selection.getNode());
59
+ const textColor = tinycolor(styl.getPropertyValue('color')).toHexString();
60
+ const bgColor_ = tinycolor(styl.getPropertyValue('background-color'));
61
+ const bgColor = bgColor_.getAlpha() === 1 ? bgColor_.toHexString() : bgColor_.toHex8String();
62
+ const target = document.querySelector('svg[data-id="color-button"]');
63
+ const root = createRoot(container);
64
+ container._reactRoot = root;
65
+ root.render(/*#__PURE__*/React.createElement(ColorPopup, {
66
+ tabs: {
67
+ foreground: {
68
+ color: textColor,
69
+ default: defaultTextColor
70
+ },
71
+ background: {
72
+ color: bgColor,
73
+ default: '#ffffff'
74
+ },
75
+ effectiveBgColor: '#ffffff'
76
+ },
77
+ open: true,
78
+ positionTarget: target,
79
+ onCancel: handleDismiss,
80
+ onChange: handleChange
81
+ }));
82
+ }
@@ -0,0 +1,294 @@
1
+ import _pt from "prop-types";
2
+ /*
3
+ * Copyright (C) 2024 - present Instructure, Inc.
4
+ *
5
+ * This file is part of Canvas.
6
+ *
7
+ * Canvas is free software: you can redistribute it and/or modify it under
8
+ * the terms of the GNU Affero General Public License as published by the Free
9
+ * Software Foundation, version 3 of the License.
10
+ *
11
+ * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
12
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13
+ * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
14
+ * details.
15
+ *
16
+ * You should have received a copy of the GNU Affero General Public License along
17
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ */
19
+
20
+ import React, { useCallback, useState } from 'react';
21
+ import tinycolor from 'tinycolor2';
22
+ import formatMessage from '../../../../format-message';
23
+ import { Button } from '@instructure/ui-buttons';
24
+ import { ColorPreset, ColorMixer, ColorContrast } from '@instructure/ui-color-picker';
25
+ import { Flex } from '@instructure/ui-flex';
26
+ import { Pill } from '@instructure/ui-pill';
27
+ import { RadioInputGroup, RadioInput } from '@instructure/ui-radio-input';
28
+ import { Tabs } from '@instructure/ui-tabs';
29
+ import { Text } from '@instructure/ui-text';
30
+ import { ToggleDetails } from '@instructure/ui-toggle-details';
31
+ import { View } from '@instructure/ui-view';
32
+ import { isTransparent, getContrastStatus, getDefaultColors } from './colorUtils';
33
+
34
+ // A custom type constraint that enforces at least one key is present
35
+
36
+ const ColorPicker = ({
37
+ tabs,
38
+ colorsInUse,
39
+ onCancel,
40
+ onSave
41
+ }) => {
42
+ const [currFgColor, setCurrFgColor] = useState(tabs.foreground?.color);
43
+ const [currBgColor, setCurrBgColor] = useState(isTransparent(tabs.background?.color) ? tabs.effectiveBgColor || '#ffffff' : tabs.background?.color);
44
+ const [currBorderColor, setCurrBorderColor] = useState(tabs.border?.color);
45
+ const [activeTab, setActiveTab] = useState(() => {
46
+ if (tabs.foreground) return 'foreground';
47
+ if (tabs.background) return 'background';
48
+ return 'border';
49
+ });
50
+ const [defaultColors] = useState(getDefaultColors());
51
+ const [customForeground, setCustomForeground] = useState(!!tabs.foreground?.color && tabs.foreground.color !== tabs.foreground.default);
52
+ const [customBackground, setCustomBackground] = useState(!isTransparent(tabs.background?.color) && tabs.background?.color !== tabs.background?.default);
53
+ const [customBorder, setCustomBorder] = useState(!isTransparent(tabs.border?.color) && tabs.border?.color !== tabs.border?.default);
54
+ const handleFgColorChange = useCallback(newColor => {
55
+ setCurrFgColor(newColor);
56
+ }, []);
57
+ const handleBgColorChange = useCallback(newColor => {
58
+ const c = tinycolor(newColor).toHexString();
59
+ setCurrBgColor(c);
60
+ }, []);
61
+ const handleBorderColorChange = useCallback(newColor => {
62
+ setCurrBorderColor(newColor);
63
+ }, []);
64
+ const handleTabChange = useCallback((_event, tabData) => {
65
+ setActiveTab(tabData.id);
66
+ }, []);
67
+ const handleChangePickAColor = useCallback((_e, value) => {
68
+ const isCustom = value === 'custom';
69
+ if (activeTab === 'foreground') {
70
+ setCustomForeground(isCustom);
71
+ if (!isCustom) {
72
+ setCurrFgColor(undefined);
73
+ }
74
+ } else if (activeTab === 'background') {
75
+ setCustomBackground(isCustom);
76
+ if (!isCustom) {
77
+ setCurrBgColor(undefined);
78
+ }
79
+ } else if (activeTab === 'border') {
80
+ setCustomBorder(isCustom);
81
+ if (!isCustom) {
82
+ setCurrBorderColor('#00000000');
83
+ }
84
+ }
85
+ }, [activeTab]);
86
+ const handleCancel = useCallback(() => {
87
+ onCancel();
88
+ }, [onCancel]);
89
+ const handleSubmit = useCallback(() => {
90
+ setActiveTab(currFgColor ? 'foreground' : 'background');
91
+ const newcolors = {};
92
+ if (customForeground && currFgColor) {
93
+ const c = tinycolor(currFgColor).toHexString();
94
+ newcolors.fgcolor = c;
95
+ }
96
+ if (customBackground && currBgColor) {
97
+ const c = tinycolor(currBgColor).toHexString();
98
+ newcolors.bgcolor = c;
99
+ }
100
+ if (currBorderColor) {
101
+ newcolors.bordercolor = customBorder && !isTransparent(currBorderColor) ? currBorderColor : undefined;
102
+ if (newcolors.bordercolor) {
103
+ const c = tinycolor(newcolors.bordercolor).toHexString();
104
+ newcolors.bordercolor = c;
105
+ }
106
+ }
107
+ onSave(newcolors);
108
+ }, [currBgColor, currBorderColor, currFgColor, customBackground, customBorder, customForeground, onSave]);
109
+ const getColorPresets = variant => {
110
+ const defaults = defaultColors;
111
+ if (tabs.background?.default) {
112
+ defaults[0] = tabs.background.default;
113
+ }
114
+ if (tabs.foreground?.default) {
115
+ defaults[1] = tabs.foreground.default;
116
+ }
117
+ // return only unique colors
118
+ return [...defaults, ...(colorsInUse?.[variant] || [])].filter((c, i, a) => a.indexOf(c) === i && !isTransparent(c));
119
+ };
120
+ const renderColorMixer = (variant, enabled) => {
121
+ let value = currBgColor;
122
+ let onSelectColor = handleBgColorChange;
123
+ if (variant === 'foreground') {
124
+ value = currFgColor;
125
+ onSelectColor = handleFgColorChange;
126
+ }
127
+ if (variant === 'border') {
128
+ value = currBorderColor;
129
+ onSelectColor = handleBorderColorChange;
130
+ }
131
+ if (isTransparent(value)) value = '#fff'; // or the ColorMixer will return a transparent color
132
+
133
+ return /*#__PURE__*/React.createElement(ColorMixer, {
134
+ "data-testid": "color-mixer",
135
+ disabled: !enabled,
136
+ value: value,
137
+ withAlpha: false,
138
+ onChange: onSelectColor,
139
+ rgbRedInputScreenReaderLabel: formatMessage('Input field for red'),
140
+ rgbGreenInputScreenReaderLabel: formatMessage('Input field for green'),
141
+ rgbBlueInputScreenReaderLabel: formatMessage('Input field for blue'),
142
+ rgbAlphaInputScreenReaderLabel: formatMessage('Input field for alpha'),
143
+ colorSliderNavigationExplanationScreenReaderLabel: formatMessage("You are on a color slider. To navigate the slider left or right, use the 'A' and 'D' buttons respectively"),
144
+ alphaSliderNavigationExplanationScreenReaderLabel: formatMessage("You are on an alpha slider. To navigate the slider left or right, use the 'A' and 'D' buttons respectively"),
145
+ colorPaletteNavigationExplanationScreenReaderLabel: formatMessage("You are on a color palette. To navigate on the palette up, left, down or right, use the 'W', 'A', 'S' and 'D' buttons respectively")
146
+ });
147
+ };
148
+ const renderColorPreset = (variant, enabled) => {
149
+ let currColor = currBgColor;
150
+ if (variant === 'foreground') currColor = currFgColor || defaultColors[1];
151
+ if (variant === 'border') currColor = currBorderColor || '#00000000';
152
+ let onSelectColor = handleBgColorChange;
153
+ if (variant === 'foreground') onSelectColor = handleFgColorChange;
154
+ if (variant === 'border') onSelectColor = handleBorderColorChange;
155
+ return /*#__PURE__*/React.createElement(ColorPreset, {
156
+ "data-testid": "color-preset",
157
+ disabled: !enabled,
158
+ label: formatMessage('Previously chosen colors'),
159
+ colors: getColorPresets(variant),
160
+ selected: currColor,
161
+ onSelect: onSelectColor
162
+ });
163
+ };
164
+
165
+ // this will only get called if either tabs.foreground or tabs.border is defined
166
+ const getFirstColor = () => {
167
+ let firstColor, firstColorLabel;
168
+ if (activeTab === 'foreground' || activeTab === 'background' && !!tabs.foreground) {
169
+ firstColor = currFgColor || tabs.foreground?.default || defaultColors[0];
170
+ firstColorLabel = formatMessage('Color');
171
+ } else if (activeTab === 'border' || activeTab === 'background' && !!tabs.border) {
172
+ firstColor = currBorderColor || tabs.border?.default || defaultColors[0];
173
+ firstColorLabel = formatMessage('Border');
174
+ }
175
+ // @ts-expect-error
176
+ return {
177
+ firstColor,
178
+ firstColorLabel
179
+ };
180
+ };
181
+ const renderColorContrastSummary = () => {
182
+ const {
183
+ firstColor
184
+ } = getFirstColor();
185
+ const ok = getContrastStatus(firstColor, currBgColor || tabs.effectiveBgColor || '#fff');
186
+ return /*#__PURE__*/React.createElement(Flex, {
187
+ as: "div",
188
+ gap: "x-large"
189
+ }, /*#__PURE__*/React.createElement(Text, {
190
+ weight: "bold"
191
+ }, formatMessage('Color Contrast')), /*#__PURE__*/React.createElement(Pill, {
192
+ color: ok ? 'success' : 'danger'
193
+ }, ok ? formatMessage('PASS') : formatMessage('FAIL')));
194
+ };
195
+ const renderColorContrast = () => {
196
+ if (!(tabs.background || tabs.effectiveBgColor)) return null;
197
+ if (!(tabs.foreground || tabs.border)) return null;
198
+ if (!currBgColor) return null;
199
+ const {
200
+ firstColor,
201
+ firstColorLabel
202
+ } = getFirstColor();
203
+ if (firstColor === null) return null;
204
+ return /*#__PURE__*/React.createElement(ToggleDetails, {
205
+ summary: renderColorContrastSummary(),
206
+ "data-testid": "color-contrast-summary"
207
+ }, /*#__PURE__*/React.createElement(View, {
208
+ as: "div",
209
+ margin: "small 0 0 0"
210
+ }, /*#__PURE__*/React.createElement(ColorContrast, {
211
+ "data-testid": "color-contrast",
212
+ firstColor: firstColor,
213
+ secondColor: currBgColor || tabs.effectiveBgColor || '#fff',
214
+ label: formatMessage('Color Contrast Ratio'),
215
+ successLabel: formatMessage('PASS'),
216
+ failureLabel: formatMessage('FAIL'),
217
+ normalTextLabel: formatMessage('Normal text'),
218
+ largeTextLabel: formatMessage('Large text'),
219
+ graphicsTextLabel: formatMessage('Graphics text'),
220
+ firstColorLabel: firstColorLabel,
221
+ secondColorLabel: formatMessage('Background')
222
+ })));
223
+ };
224
+ const renderTab = variant => {
225
+ let choosersEnabled = true;
226
+ if (variant === 'foreground') {
227
+ choosersEnabled = customForeground;
228
+ } else if (variant === 'background') {
229
+ choosersEnabled = customBackground;
230
+ } else if (variant === 'border') {
231
+ choosersEnabled = customBorder;
232
+ }
233
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(View, {
234
+ as: "div",
235
+ margin: "0 0 small 0"
236
+ }, /*#__PURE__*/React.createElement(RadioInputGroup, {
237
+ layout: "columns",
238
+ name: "pickcolor",
239
+ description: formatMessage('Pick a color'),
240
+ size: "small",
241
+ value: choosersEnabled ? 'custom' : 'none',
242
+ onChange: handleChangePickAColor
243
+ }, /*#__PURE__*/React.createElement(RadioInput, {
244
+ label: formatMessage('Default'),
245
+ value: "none"
246
+ }), /*#__PURE__*/React.createElement(RadioInput, {
247
+ label: formatMessage('Custom'),
248
+ value: "custom"
249
+ }))), renderColorMixer(variant, choosersEnabled), renderColorPreset(variant, choosersEnabled));
250
+ };
251
+ return /*#__PURE__*/React.createElement(View, {
252
+ as: "div",
253
+ "data-testid": "color-picker"
254
+ }, /*#__PURE__*/React.createElement(View, {
255
+ as: "div",
256
+ padding: "small",
257
+ "data-mce-component": true
258
+ }, /*#__PURE__*/React.createElement(Tabs, {
259
+ onRequestTabChange: handleTabChange
260
+ }, !!tabs.foreground && /*#__PURE__*/React.createElement(Tabs.Panel, {
261
+ id: "foreground",
262
+ renderTitle: formatMessage('Color'),
263
+ isSelected: activeTab === 'foreground'
264
+ }, renderTab('foreground')), !!tabs.background && /*#__PURE__*/React.createElement(Tabs.Panel, {
265
+ id: "background",
266
+ renderTitle: formatMessage('Background'),
267
+ isSelected: activeTab === 'background'
268
+ }, renderTab('background')), !!tabs.border && /*#__PURE__*/React.createElement(Tabs.Panel, {
269
+ id: "border",
270
+ renderTitle: formatMessage('Border'),
271
+ isSelected: activeTab === 'border'
272
+ }, renderTab('border'))), renderColorContrast()), /*#__PURE__*/React.createElement(View, {
273
+ as: "div",
274
+ background: "secondary",
275
+ padding: "small",
276
+ textAlign: "end"
277
+ }, /*#__PURE__*/React.createElement(Button, {
278
+ onClick: handleCancel
279
+ }, formatMessage('Cancel')), /*#__PURE__*/React.createElement(Button, {
280
+ onClick: handleSubmit,
281
+ margin: "0 0 0 small",
282
+ color: "primary"
283
+ }, formatMessage('Apply'))));
284
+ };
285
+ ColorPicker.propTypes = {
286
+ colorsInUse: _pt.shape({
287
+ foreground: _pt.arrayOf(_pt.string).isRequired,
288
+ background: _pt.arrayOf(_pt.string).isRequired,
289
+ border: _pt.arrayOf(_pt.string).isRequired
290
+ }),
291
+ onCancel: _pt.func.isRequired,
292
+ onSave: _pt.func.isRequired
293
+ };
294
+ export { ColorPicker };
@@ -0,0 +1,67 @@
1
+ import _pt from "prop-types";
2
+ /*
3
+ * Copyright (C) 2024 - present Instructure, Inc.
4
+ *
5
+ * This file is part of Canvas.
6
+ *
7
+ * Canvas is free software: you can redistribute it and/or modify it under
8
+ * the terms of the GNU Affero General Public License as published by the Free
9
+ * Software Foundation, version 3 of the License.
10
+ *
11
+ * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
12
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13
+ * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
14
+ * details.
15
+ *
16
+ * You should have received a copy of the GNU Affero General Public License along
17
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ */
19
+
20
+ import React, { useCallback, useState } from 'react';
21
+ import { Popover } from '@instructure/ui-popover';
22
+ import { ColorPicker } from './ColorPicker';
23
+ import formatMessage from '../../../../format-message';
24
+ const ColorPopup = ({
25
+ tabs,
26
+ open,
27
+ positionTarget,
28
+ onCancel,
29
+ onChange
30
+ }) => {
31
+ const [recreateKey, setRecreateKey] = useState(0);
32
+ const handleHideContent = useCallback(() => {
33
+ onCancel();
34
+ setRecreateKey(Date.now());
35
+ }, [onCancel]);
36
+ const handleSubmit = useCallback(newcolors => {
37
+ onChange(newcolors);
38
+ }, [onChange]);
39
+ const handleKey = useCallback(e => {
40
+ if (e.key === 'Escape') {
41
+ onCancel();
42
+ }
43
+ }, [onCancel]);
44
+ return /*#__PURE__*/React.createElement(Popover, {
45
+ key: recreateKey,
46
+ isShowingContent: open,
47
+ onHideContent: handleHideContent,
48
+ on: "click",
49
+ positionTarget: positionTarget,
50
+ screenReaderLabel: formatMessage('Color popup'),
51
+ shouldContainFocus: true,
52
+ shouldReturnFocus: true,
53
+ shouldCloseOnDocumentClick: true
54
+ }, /*#__PURE__*/React.createElement("div", {
55
+ onKeyDown: handleKey
56
+ }, /*#__PURE__*/React.createElement(ColorPicker, {
57
+ tabs: tabs,
58
+ onCancel: onCancel,
59
+ onSave: handleSubmit
60
+ })));
61
+ };
62
+ ColorPopup.propTypes = {
63
+ open: _pt.bool.isRequired,
64
+ onCancel: _pt.func.isRequired,
65
+ onChange: _pt.func.isRequired
66
+ };
67
+ export { ColorPopup };
@@ -0,0 +1,60 @@
1
+ /*
2
+ * Copyright (C) 2024 - present Instructure, Inc.
3
+ *
4
+ * This file is part of Canvas.
5
+ *
6
+ * Canvas is free software: you can redistribute it and/or modify it under
7
+ * the terms of the GNU Affero General Public License as published by the Free
8
+ * Software Foundation, version 3 of the License.
9
+ *
10
+ * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
11
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12
+ * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
13
+ * details.
14
+ *
15
+ * You should have received a copy of the GNU Affero General Public License along
16
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+ import conversions, { contrast } from '@instructure/ui-color-utils';
20
+ import tinycolor from 'tinycolor2';
21
+ const isTransparent = color => {
22
+ if (!color) {
23
+ return true;
24
+ }
25
+ const c = tinycolor(color);
26
+ return c.isValid() && c.getAlpha() === 0;
27
+ };
28
+
29
+ // the following is copied from the INSTUI ColorContrast component
30
+ // a function to handle this will eventually be exported
31
+ // from @instructure/ui-color-utils
32
+ const INSTUIcalcBlendedColor = (c1, c2) => {
33
+ const alpha = 1 - (1 - c1.a) * (1 - c2.a);
34
+ return {
35
+ r: c2.r * c2.a / alpha + c1.r * c1.a * (1 - c2.a) / alpha,
36
+ g: c2.g * c2.a / alpha + c1.g * c1.a * (1 - c2.a) / alpha,
37
+ b: c2.b * c2.a / alpha + c1.b * c1.a * (1 - c2.a) / alpha,
38
+ a: 1
39
+ };
40
+ };
41
+ const INSTUIcalcContrast = (firstColor, secondColor) => {
42
+ const c1RGBA = conversions.colorToRGB(firstColor);
43
+ const c2RGBA = conversions.colorToRGB(secondColor);
44
+ const c1OnWhite = INSTUIcalcBlendedColor({
45
+ r: 255,
46
+ g: 255,
47
+ b: 255,
48
+ a: 1
49
+ }, c1RGBA);
50
+ const c2OnC1OnWhite = INSTUIcalcBlendedColor(c1OnWhite, c2RGBA);
51
+ return contrast(conversions.colorToHex8(c1OnWhite), conversions.colorToHex8(c2OnC1OnWhite), 2);
52
+ };
53
+ const getContrastStatus = (color1, color2) => {
54
+ return INSTUIcalcContrast(color1, color2) >= 4.5;
55
+ };
56
+ const getDefaultColors = () => {
57
+ const fontcolor = window.getComputedStyle(document.documentElement).getPropertyValue('--ic-brand-font-color-dark') || '#000000';
58
+ return [fontcolor.toLowerCase(), '#ffffff'];
59
+ };
60
+ export { getContrastStatus, isTransparent, getDefaultColors };
@@ -0,0 +1,40 @@
1
+ /*
2
+ * Copyright (C) 2024 - present Instructure, Inc.
3
+ *
4
+ * This file is part of Canvas.
5
+ *
6
+ * Canvas is free software: you can redistribute it and/or modify it under
7
+ * the terms of the GNU Affero General Public License as published by the Free
8
+ * Software Foundation, version 3 of the License.
9
+ *
10
+ * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
11
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12
+ * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
13
+ * details.
14
+ *
15
+ * You should have received a copy of the GNU Affero General Public License along
16
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+ import tinymce from 'tinymce';
20
+ import formatMessage from '../../../format-message';
21
+ import clickCallback from './clickCallback';
22
+ tinymce.PluginManager.add('instructure_color', function (editor) {
23
+ editor.addCommand('launch_instructure_color', () => {
24
+ clickCallback(editor);
25
+ });
26
+ editor.ui.registry.addMenuItem('instructure_color', {
27
+ text: formatMessage('Color'),
28
+ icon: 'color',
29
+ onAction() {
30
+ editor.execCommand('launch_instructure_color');
31
+ }
32
+ });
33
+ editor.ui.registry.addButton('instructure_color', {
34
+ onAction() {
35
+ editor.execCommand('launch_instructure_color');
36
+ },
37
+ icon: 'color',
38
+ tooltip: formatMessage('Color')
39
+ });
40
+ });
@@ -4,13 +4,12 @@
4
4
  * For LGPL see License.txt in the project root for license information.
5
5
  * For commercial licenses see https://www.tiny.cloud/
6
6
  */
7
- const isChildOfBody = (editor, node) => !!editor.$.contains(editor.getBody(), node);
8
7
 
8
+ const isChildOfBody = (editor, node) => !!editor.$.contains(editor.getBody(), node);
9
9
  export const isTableCellNode = node => node && /^(TH|TD)$/.test(node.nodeName);
10
10
  export const isListNode = editor => node => node && /^(OL|UL|DL)$/.test(node.nodeName) && isChildOfBody(editor, node);
11
11
  export function listStyleForSelectionOfEditor(editor) {
12
12
  const listElm = editor.dom.getParent(editor.selection.getNode(), 'ol,ul');
13
-
14
13
  if (listElm) {
15
14
  return {
16
15
  // This is not type safe, but the above getParent selector enforces that this will be
@@ -21,4 +20,12 @@ export function listStyleForSelectionOfEditor(editor) {
21
20
  } else {
22
21
  return undefined;
23
22
  }
24
- }
23
+ }
24
+
25
+ /**
26
+ * Valid values of the "list-style-type" property.
27
+ *
28
+ * NOTE: Not all these types are supported by the RCE. For that, see `ListStyleTypeValue`
29
+ *
30
+ * From https://www.w3schools.com/cssref/pr_list-style-type.php
31
+ */
@@ -15,6 +15,7 @@
15
15
  * You should have received a copy of the GNU Affero General Public License along
16
16
  * with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
  */
18
+
18
19
  import registerAlignmentButton from './ui/alignment-button';
19
20
  import registerIndentOutdentButton from './ui/indent-outdent-button';
20
21
  import registerListButton from './ui/list-button';
@@ -15,6 +15,7 @@
15
15
  * You should have received a copy of the GNU Affero General Public License along
16
16
  * with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
  */
18
+
18
19
  import formatMessage from '../../../../format-message';
19
20
  import { toolbarIconHelperFor } from '../../../../util/tinymce-plugin-util';
20
21
  export default function (editor) {
@@ -47,14 +48,12 @@ export default function (editor) {
47
48
  }))),
48
49
  onSetup: api => {
49
50
  const iconHelper = toolbarIconHelperFor(editor, alignButtonLabel);
50
-
51
51
  function nodeChangeHandler() {
52
52
  const activeAlignment = alignToolbarButtons.find(b => editor.formatter.match(b.name));
53
53
  const icon = activeAlignment ? activeAlignment.icon : 'align-left';
54
54
  api.setActive(!!activeAlignment);
55
55
  iconHelper.updateIcon(icon);
56
56
  }
57
-
58
57
  nodeChangeHandler();
59
58
  editor.on('NodeChange', nodeChangeHandler);
60
59
  return () => editor.off('NodeChange', nodeChangeHandler);