@instructure/canvas-rce 5.9.0 → 5.11.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 (79) hide show
  1. package/.mocharc.js +7 -0
  2. package/CHANGELOG.md +47 -0
  3. package/Dockerfile +1 -1
  4. package/es/common/mimeClass.js +70 -67
  5. package/es/enhance-user-content/doc_previews.js +1 -1
  6. package/es/enhance-user-content/enhance_user_content.js +9 -1
  7. package/es/enhance-user-content/mathml.js +8 -5
  8. package/es/getThemeVars.js +3 -4
  9. package/es/rce/RCE.js +1 -3
  10. package/es/rce/RCEWrapper.js +3 -48
  11. package/es/rce/RceHtmlEditor.js +20 -38
  12. package/es/rce/plugins/instructure_equation/EquationEditorModal/parseLatex.js +0 -2
  13. package/es/rce/plugins/instructure_links/components/Link.js +3 -9
  14. package/es/rce/plugins/instructure_links/components/LinkSet.js +4 -8
  15. package/es/rce/plugins/instructure_links/components/NoResults.js +5 -10
  16. package/es/rce/plugins/instructure_links/plugin.js +1 -7
  17. package/es/rce/plugins/instructure_rce_external_tools/components/ExternalToolDialog/ExternalToolDialog.js +1 -2
  18. package/es/rce/plugins/instructure_rce_external_tools/components/ExternalToolDialog/ExternalToolDialogModal.js +4 -5
  19. package/es/rce/plugins/instructure_rce_external_tools/components/ExternalToolDialog/ExternalToolDialogTray.js +6 -12
  20. package/es/rce/plugins/instructure_rce_external_tools/components/ExternalToolSelectionDialog/ExternalToolSelectionDialog.js +2 -2
  21. package/es/rce/plugins/instructure_rce_external_tools/lti13-content-items/models/ResourceLinkContentItem.js +1 -1
  22. package/es/rce/plugins/instructure_record/VideoOptionsTray/TrayController.js +7 -2
  23. package/es/rce/plugins/instructure_record/VideoOptionsTray/index.js +3 -9
  24. package/es/rce/plugins/instructure_wordcount/components/WordCountModal.js +8 -16
  25. package/es/rce/plugins/shared/CanvasContentTray.js +15 -9
  26. package/es/rce/plugins/shared/ContentSelection.js +7 -3
  27. package/es/rce/plugins/shared/ImageCropper/Preview.js +8 -7
  28. package/es/rce/plugins/shared/LinkDisplay.js +2 -2
  29. package/es/rce/plugins/shared/fileTypeUtils.js +14 -6
  30. package/{lib/rce/plugins/tinymce-a11y-checker/components/color-field.js → es/rce/plugins/tinymce-a11y-checker/components/ColorField.js} +9 -7
  31. package/es/rce/plugins/tinymce-a11y-checker/components/checker.js +27 -24
  32. package/es/rce/plugins/tinymce-a11y-checker/rules/large-text-contrast.js +9 -0
  33. package/es/rce/plugins/tinymce-a11y-checker/rules/small-text-contrast.js +9 -0
  34. package/es/rce/root.js +1 -3
  35. package/es/rce/transformContent.js +8 -0
  36. package/es/sidebar/actions/upload.js +3 -1
  37. package/es/translations/locales/de.js +4 -4
  38. package/jest/jest-setup.js +2 -1
  39. package/lib/common/mimeClass.js +70 -67
  40. package/lib/enhance-user-content/doc_previews.js +1 -1
  41. package/lib/enhance-user-content/enhance_user_content.js +9 -1
  42. package/lib/enhance-user-content/mathml.js +8 -5
  43. package/lib/getThemeVars.js +3 -4
  44. package/lib/rce/RCE.js +1 -3
  45. package/lib/rce/RCEWrapper.js +3 -48
  46. package/lib/rce/RceHtmlEditor.js +20 -38
  47. package/lib/rce/plugins/instructure_equation/EquationEditorModal/parseLatex.js +0 -2
  48. package/lib/rce/plugins/instructure_links/components/Link.js +3 -9
  49. package/lib/rce/plugins/instructure_links/components/LinkSet.js +4 -8
  50. package/lib/rce/plugins/instructure_links/components/NoResults.js +5 -10
  51. package/lib/rce/plugins/instructure_links/plugin.js +1 -7
  52. package/lib/rce/plugins/instructure_rce_external_tools/components/ExternalToolDialog/ExternalToolDialog.js +1 -2
  53. package/lib/rce/plugins/instructure_rce_external_tools/components/ExternalToolDialog/ExternalToolDialogModal.js +4 -5
  54. package/lib/rce/plugins/instructure_rce_external_tools/components/ExternalToolDialog/ExternalToolDialogTray.js +6 -12
  55. package/lib/rce/plugins/instructure_rce_external_tools/components/ExternalToolSelectionDialog/ExternalToolSelectionDialog.js +2 -2
  56. package/lib/rce/plugins/instructure_rce_external_tools/lti13-content-items/models/ResourceLinkContentItem.js +1 -1
  57. package/lib/rce/plugins/instructure_record/VideoOptionsTray/TrayController.js +7 -2
  58. package/lib/rce/plugins/instructure_record/VideoOptionsTray/index.js +3 -9
  59. package/lib/rce/plugins/instructure_wordcount/components/WordCountModal.js +8 -16
  60. package/lib/rce/plugins/shared/CanvasContentTray.js +15 -9
  61. package/lib/rce/plugins/shared/ContentSelection.js +7 -3
  62. package/lib/rce/plugins/shared/ImageCropper/Preview.js +8 -7
  63. package/lib/rce/plugins/shared/LinkDisplay.js +2 -2
  64. package/lib/rce/plugins/shared/fileTypeUtils.js +14 -6
  65. package/{es/rce/plugins/tinymce-a11y-checker/components/color-field.js → lib/rce/plugins/tinymce-a11y-checker/components/ColorField.js} +9 -7
  66. package/lib/rce/plugins/tinymce-a11y-checker/components/checker.js +27 -24
  67. package/lib/rce/plugins/tinymce-a11y-checker/rules/large-text-contrast.js +9 -0
  68. package/lib/rce/plugins/tinymce-a11y-checker/rules/small-text-contrast.js +9 -0
  69. package/lib/rce/root.js +1 -3
  70. package/lib/rce/transformContent.js +8 -0
  71. package/lib/sidebar/actions/upload.js +3 -1
  72. package/lib/translations/locales/de.js +4 -4
  73. package/locales/en.json +1438 -89
  74. package/package.json +58 -55
  75. package/canvas/README.md +0 -84
  76. package/canvas/locales/en.json +0 -934
  77. package/canvas/package.json +0 -189
  78. package/es/rce/getBrowser.js +0 -53
  79. package/lib/rce/getBrowser.js +0 -53
@@ -15,10 +15,10 @@
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
- import React, { useCallback, useEffect, useRef, useState } from 'react';
18
+ import React, { useEffect, useState } from 'react';
19
19
  import { func, string } from 'prop-types';
20
20
  import formatMessage from '../format-message';
21
- import { CodeEditor } from '@instructure/ui-code-editor';
21
+ import { SourceCodeEditor } from '@instructure/ui-source-code-editor';
22
22
  import beautify from 'js-beautify';
23
23
  const RceHtmlEditor = /*#__PURE__*/React.forwardRef((_ref, editorRef) => {
24
24
  let {
@@ -56,25 +56,7 @@ const RceHtmlEditor = /*#__PURE__*/React.forwardRef((_ref, editorRef) => {
56
56
 
57
57
  setDir(getComputedStyle(editorRef.current || document.body, null).direction);
58
58
  }, [dir, editorRef]);
59
- useEffect(() => {
60
- // scoping querySelector to the container div makes sure we're targeting this CodeEditor
61
- // The CodeMirror docs (https://codemirror.net/doc/manual.html#styling)
62
- // say this is the element we use to set the editor's height
63
- const editor = editorRef.current.querySelector('.CodeMirror');
64
- editor.CodeMirror.setSize(null, props.height);
65
- editor.style.margin = '0';
66
- editor.style.border = '0';
67
- }, [props.height, editorRef]);
68
- const isFocused = useRef(false); // move cursor to the top of the html code when the editor is focused for the first time
69
-
70
- const handleFocus = useCallback((editor, event) => {
71
- if (!isFocused.current) {
72
- editor.setCursor(0, 0);
73
- isFocused.current = true;
74
- }
75
-
76
- onFocus(event);
77
- }, [onFocus]); // setting height on the container keeps the RCE toolbar from jumping
59
+ const direction = ['ltr', 'rtl'].includes(dir) ? dir : 'ltr'; // setting height on the container keeps the RCE toolbar from jumping
78
60
 
79
61
  return /*#__PURE__*/React.createElement("div", {
80
62
  ref: editorRef,
@@ -84,28 +66,28 @@ const RceHtmlEditor = /*#__PURE__*/React.forwardRef((_ref, editorRef) => {
84
66
  overflow: 'hidden',
85
67
  textAlign: 'start'
86
68
  }
87
- }, /*#__PURE__*/React.createElement(CodeEditor, {
69
+ }, /*#__PURE__*/React.createElement(SourceCodeEditor, {
88
70
  label: label,
89
- language: "html",
90
- options: {
91
- lineNumbers: true,
92
- lineWrapping: true,
93
- autofocus: false,
94
- spellcheck: true,
95
- extraKeys: {
96
- Tab: false,
97
- 'Shift-Tab': false
98
- },
99
- screenReaderLabel: label,
100
- direction: dir,
101
- rtlMoveVisually: true
102
- },
71
+ language: "html" // see LF-745 for tracking of the following:
72
+ // TODO: needs prop for
73
+ // options={{
74
+ // extraKeys: {Tab: false, 'Shift-Tab': false},
75
+ // }}
76
+ // TODO: may need
77
+ // attachment={none | bottom | top}
78
+ ,
79
+ lineNumbers: true,
80
+ lineWrapping: true,
81
+ autoFocus: false,
82
+ spellcheck: true,
83
+ direction: direction,
84
+ rtlMoveVisually: true,
85
+ height: props.height,
103
86
  value: code,
104
87
  onChange: value => {
105
88
  setCode(value);
106
89
  props.onChange(value);
107
- },
108
- onFocus: handleFocus
90
+ }
109
91
  }));
110
92
  });
111
93
  RceHtmlEditor.propTypes = {
@@ -68,8 +68,6 @@ export const parseLatex = editor => {
68
68
  };
69
69
  } catch (ex) {
70
70
  // probably failed to create the new URL
71
- // eslint-disable-next-line no-console
72
- console.error(ex);
73
71
  return {};
74
72
  }
75
73
  } else if (wholeText) {
@@ -31,8 +31,6 @@ import { IconDragHandleLine, IconPublishSolid, IconUnpublishedSolid } from '@ins
31
31
  import RCEGlobals from '../../../RCEGlobals';
32
32
  import { getIcon } from '../../shared/linkUtils';
33
33
  export default function Link(props) {
34
- var _RCEGlobals$getFeatur;
35
-
36
34
  const internalLink = { ...props.link
37
35
  };
38
36
  const [isHovering, setIsHovering] = useState(false);
@@ -43,14 +41,10 @@ export default function Link(props) {
43
41
  date_type
44
42
  } = props.link;
45
43
  const type = props.type === 'quizzes' && props.link.quiz_type === 'quizzes.next' ? 'quizzes.next' : props.type;
44
+ internalLink['data-course-type'] = type; // Only included published attr if it makes sense for the link type
46
45
 
47
- if ((_RCEGlobals$getFeatur = RCEGlobals.getFeatures()) !== null && _RCEGlobals$getFeatur !== void 0 && _RCEGlobals$getFeatur.rce_ux_improvements) {
48
- internalLink['data-course-type'] = type; // Only included published attr if it makes sense for the link type
49
-
50
- const publishable = !['navigation', 'announcements'].includes(type);
51
- internalLink['data-published'] = publishable ? published : null;
52
- }
53
-
46
+ const publishable = !['navigation', 'announcements'].includes(type);
47
+ internalLink['data-published'] = publishable ? published : null;
54
48
  const Icon = getIcon(type);
55
49
  const color = published ? 'success' : 'primary';
56
50
  let dateString = null;
@@ -113,7 +113,7 @@ class LinkSet extends Component {
113
113
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ScreenReaderContent, {
114
114
  id: this.describedByID
115
115
  }, formatMessage('Click to insert a link into the editor.')), /*#__PURE__*/React.createElement(List, {
116
- variant: "unstyled",
116
+ isUnstyled: true,
117
117
  as: "ul",
118
118
  margin: "0"
119
119
  }, this.props.collection.links.map((link, index, array) => {
@@ -137,18 +137,14 @@ class LinkSet extends Component {
137
137
  }
138
138
 
139
139
  renderEmptyIndicator() {
140
- var _RCEGlobals$getFeatur, _this$props$searchStr;
140
+ var _this$props$searchStr;
141
141
 
142
- return (_RCEGlobals$getFeatur = RCEGlobals.getFeatures()) !== null && _RCEGlobals$getFeatur !== void 0 && _RCEGlobals$getFeatur.improved_no_results_messaging ? /*#__PURE__*/React.createElement(NoResults, {
142
+ return /*#__PURE__*/React.createElement(NoResults, {
143
143
  contextType: this.props.contextType,
144
144
  contextId: this.props.contextId,
145
145
  collectionType: this.props.type,
146
146
  isSearchResult: ((_this$props$searchStr = this.props.searchString) === null || _this$props$searchStr === void 0 ? void 0 : _this$props$searchStr.length) >= 3
147
- }) : /*#__PURE__*/React.createElement(View, {
148
- as: "div",
149
- role: "alert",
150
- padding: "medium"
151
- }, formatMessage('No results.'));
147
+ });
152
148
  }
153
149
 
154
150
  renderLoadingError() {
@@ -23,11 +23,7 @@ import { Flex } from '@instructure/ui-flex';
23
23
  import { Text } from '@instructure/ui-text';
24
24
  import { Link } from '@instructure/ui-link';
25
25
  import formatMessage from '../../../../format-message';
26
- import { getIcon } from '../../shared/linkUtils'; // Doing this to avoid TS2339 errors-- remove once we're on InstUI 8
27
-
28
- const {
29
- Item: FlexItem
30
- } = Flex;
26
+ import { getIcon } from '../../shared/linkUtils';
31
27
  export function buildUrl(contextType, contextId, collectionType) {
32
28
  var _typeMap$collectionTy;
33
29
 
@@ -72,15 +68,14 @@ export const NoResults = _ref => {
72
68
  justifyItems: "center",
73
69
  alignItems: "center",
74
70
  direction: "column"
75
- }, /*#__PURE__*/React.createElement(FlexItem, null, /*#__PURE__*/React.createElement(Icon, {
71
+ }, /*#__PURE__*/React.createElement(Flex.Item, null, /*#__PURE__*/React.createElement(Icon, {
76
72
  size: "large",
77
73
  color: "secondary",
78
74
  padding: "large"
79
- })), /*#__PURE__*/React.createElement(FlexItem, {
75
+ })), /*#__PURE__*/React.createElement(Flex.Item, {
80
76
  margin: "small 0 0"
81
- }, /*#__PURE__*/React.createElement(Text, null, getMessage(collectionType, isSearchResult))), !isSearchResult && /*#__PURE__*/React.createElement(FlexItem, null, /*#__PURE__*/React.createElement(Link, {
82
- href: buildUrl(contextType, contextId, collectionType) // @ts-expect-error
83
- ,
77
+ }, /*#__PURE__*/React.createElement(Text, null, getMessage(collectionType, isSearchResult))), !isSearchResult && /*#__PURE__*/React.createElement(Flex.Item, null, /*#__PURE__*/React.createElement(Link, {
78
+ href: buildUrl(contextType, contextId, collectionType),
84
79
  target: "_blank"
85
80
  }, formatMessage('Add one!')))));
86
81
  };
@@ -68,20 +68,14 @@ import bridge from '../../../bridge';
68
68
  import { getAnchorElement, isOKToLink } from '../../contentInsertionUtils';
69
69
  import LinkOptionsTrayController from './components/LinkOptionsTray/LinkOptionsTrayController';
70
70
  import { CREATE_LINK, EDIT_LINK } from './components/LinkOptionsDialog/LinkOptionsDialogController';
71
- import RCEGlobals from '../../RCEGlobals';
72
71
  import tinymce from 'tinymce';
73
72
  const trayController = new LinkOptionsTrayController();
74
73
  const COURSE_PLUGIN_KEY = 'course_links';
75
74
  const GROUP_PLUGIN_KEY = 'group_links';
76
75
 
77
76
  function getCommandName(selectedNode) {
78
- var _RCEGlobals$getFeatur;
79
-
80
- // show the Course Tray if it's a course link and the ux improvement flag is on,
81
- // otherwise show the default Link Tray
82
- const showCourseLinkTray = !!((_RCEGlobals$getFeatur = RCEGlobals.getFeatures()) !== null && _RCEGlobals$getFeatur !== void 0 && _RCEGlobals$getFeatur.rce_ux_improvements);
83
77
  const isCourseLink = selectedNode.getAttribute('data-course-type');
84
- return showCourseLinkTray && isCourseLink ? 'instructureTrayForCourseLinks' : 'instructureTrayToEditLink';
78
+ return isCourseLink ? 'instructureTrayForCourseLinks' : 'instructureTrayToEditLink';
85
79
  }
86
80
 
87
81
  function selectedAnchorCount(ed) {
@@ -31,7 +31,6 @@ import { ExternalToolDialogTray } from './ExternalToolDialogTray';
31
31
  import { ExternalToolDialogModal } from './ExternalToolDialogModal';
32
32
  import { showFlashAlert } from '../../../../../common/FlashAlert';
33
33
  import { parseUrlOrNull } from '../../../../../util/url-util';
34
- const FlexItem = Flex.Item;
35
34
  export default class ExternalToolDialog extends React.Component {
36
35
  constructor() {
37
36
  super(...arguments);
@@ -246,7 +245,7 @@ export default class ExternalToolDialog extends React.Component {
246
245
  }, formatMessage('The following content is partner provided'))), !state.iframeLoaded && /*#__PURE__*/React.createElement(Flex, {
247
246
  alignItems: "center",
248
247
  justifyItems: "center"
249
- }, /*#__PURE__*/React.createElement(FlexItem, null, /*#__PURE__*/React.createElement(Spinner, {
248
+ }, /*#__PURE__*/React.createElement(Flex.Item, null, /*#__PURE__*/React.createElement(Spinner, {
250
249
  renderTitle: formatMessage('Loading External Tool'),
251
250
  size: "large",
252
251
  margin: "0 0 0 medium"
@@ -18,7 +18,6 @@
18
18
  * with this program. If not, see <http://www.gnu.org/licenses/>.
19
19
  */
20
20
  import React from 'react';
21
- import { Flex } from '@instructure/ui-flex';
22
21
  import { Heading } from '@instructure/ui-heading';
23
22
  import { CloseButton } from '@instructure/ui-buttons';
24
23
  import { View } from '@instructure/ui-view';
@@ -33,12 +32,12 @@ export function ExternalToolDialogModal(props) {
33
32
  onOpen: props.onOpen,
34
33
  onClose: props.onClose,
35
34
  mountNode: props.mountNode
36
- }, /*#__PURE__*/React.createElement(Modal.Header, null, /*#__PURE__*/React.createElement(Flex, null, /*#__PURE__*/React.createElement(Flex.Item, {
37
- grow: true
38
- }, /*#__PURE__*/React.createElement(Heading, null, props.name)), /*#__PURE__*/React.createElement(Flex.Item, null, /*#__PURE__*/React.createElement(CloseButton, {
35
+ }, /*#__PURE__*/React.createElement(Modal.Header, null, /*#__PURE__*/React.createElement(Heading, null, props.name), /*#__PURE__*/React.createElement(CloseButton, {
36
+ placement: "end",
37
+ offset: "medium",
39
38
  onClick: props.onCloseButton,
40
39
  screenReaderLabel: formatMessage('Close')
41
- })))), /*#__PURE__*/React.createElement(Modal.Body, {
40
+ })), /*#__PURE__*/React.createElement(Modal.Body, {
42
41
  padding: "0"
43
42
  }, /*#__PURE__*/React.createElement(View, {
44
43
  as: "div",
@@ -1,3 +1,5 @@
1
+ import _pt from "prop-types";
2
+
1
3
  /*
2
4
  * Copyright (C) 2019 - present Instructure, Inc.
3
5
  *
@@ -16,14 +18,12 @@
16
18
  * with this program. If not, see <http://www.gnu.org/licenses/>.
17
19
  */
18
20
  import React from 'react';
19
- import PropTypes from 'prop-types';
20
21
  import { Tray } from '@instructure/ui-tray';
21
22
  import { View } from '@instructure/ui-view';
22
23
  import { Flex } from '@instructure/ui-flex';
23
24
  import { Heading } from '@instructure/ui-heading';
24
25
  import { CloseButton } from '@instructure/ui-buttons';
25
26
  import formatMessage from 'format-message';
26
- const FlexItem = Flex.Item;
27
27
  export function ExternalToolDialogTray(props) {
28
28
  const {
29
29
  label,
@@ -56,9 +56,9 @@ export function ExternalToolDialogTray(props) {
56
56
  }, /*#__PURE__*/React.createElement(Flex, {
57
57
  as: "div",
58
58
  padding: "small"
59
- }, /*#__PURE__*/React.createElement(FlexItem, {
59
+ }, /*#__PURE__*/React.createElement(Flex.Item, {
60
60
  shouldGrow: true
61
- }, /*#__PURE__*/React.createElement(Heading, null, name)), /*#__PURE__*/React.createElement(FlexItem, null, /*#__PURE__*/React.createElement(CloseButton, {
61
+ }, /*#__PURE__*/React.createElement(Heading, null, name)), /*#__PURE__*/React.createElement(Flex.Item, null, /*#__PURE__*/React.createElement(CloseButton, {
62
62
  onClick: onCloseButton,
63
63
  size: "small",
64
64
  screenReaderLabel: formatMessage('Close')
@@ -74,12 +74,6 @@ export function ExternalToolDialogTray(props) {
74
74
  }, children)))));
75
75
  }
76
76
  ExternalToolDialogTray.propTypes = {
77
- open: PropTypes.bool,
78
- label: PropTypes.string.isRequired,
79
- mountNode: PropTypes.oneOfType([PropTypes.element, PropTypes.func]),
80
- onOpen: PropTypes.func,
81
- onClose: PropTypes.func,
82
- onCloseButton: PropTypes.func,
83
- name: PropTypes.string.isRequired,
84
- children: PropTypes.node
77
+ onCloseButton: _pt.func,
78
+ name: _pt.string.isRequired
85
79
  };
@@ -70,7 +70,7 @@ export function ExternalToolSelectionDialog(props) {
70
70
  "data-mce-component": true,
71
71
  liveRegion: getLiveRegion,
72
72
  size: "medium",
73
- theme: {
73
+ themeOverride: {
74
74
  mediumMaxWidth: '42rem'
75
75
  },
76
76
  label: formatMessage('Apps'),
@@ -79,7 +79,7 @@ export function ExternalToolSelectionDialog(props) {
79
79
  open: true,
80
80
  shouldCloseOnDocumentClick: false
81
81
  }, /*#__PURE__*/React.createElement(Modal.Header, {
82
- theme: {
82
+ themeOverride: {
83
83
  padding: '0.5rem'
84
84
  }
85
85
  }, /*#__PURE__*/React.createElement(CloseButton, {
@@ -35,7 +35,7 @@ export default class ResourceLinkContentItem extends BaseLinkContentItem {
35
35
 
36
36
  buildUrl() {
37
37
  return addQueryParamsToUrl(this.context.ltiEndpoint, {
38
- display: 'borderless',
38
+ display: 'in_rce',
39
39
  resource_link_lookup_uuid: this.lookup_uuid,
40
40
  [PARENT_FRAME_CONTEXT_PARAM]: this.context.containingCanvasLtiToolId
41
41
  });
@@ -146,7 +146,7 @@ export default class TrayController {
146
146
  // If not, we can't update the MediaObject in the canvas db.
147
147
 
148
148
 
149
- if (videoOptions.media_object_id && videoOptions.media_object_id !== 'undefined' && !videoOptions.isLocked) {
149
+ if (videoOptions.media_object_id && videoOptions.media_object_id !== 'undefined') {
150
150
  videoOptions.updateMediaObject(data).then(_r => {
151
151
  if (this.$videoContainer && videoOptions.displayAs === 'embed') {
152
152
  this.$videoContainer.contentWindow.postMessage({
@@ -181,10 +181,15 @@ export default class TrayController {
181
181
  let vo = {};
182
182
 
183
183
  if (this._shouldOpen) {
184
+ /*
185
+ * When the tray is being opened again, it should be rendered fresh
186
+ * (clearing the internal state) so that the currently-selected video can
187
+ * be used for initial video options.
188
+ */
184
189
  this._renderId++;
190
+ vo = asVideoElement(this.$videoContainer) || {};
185
191
  }
186
192
 
187
- vo = asVideoElement(this.$videoContainer) || {};
188
193
  const element = /*#__PURE__*/React.createElement(VideoOptionsTray, {
189
194
  id: "video-options-tray",
190
195
  key: this._renderId,
@@ -38,13 +38,10 @@ import DimensionsInput, { useDimensionsState } from '../../shared/DimensionsInpu
38
38
  import { getTrayHeight } from '../../shared/trayUtils';
39
39
  import { instuiPopupMountNode } from '../../../../util/fullscreenHelpers';
40
40
  import { parsedStudioOptionsPropType } from '../../shared/StudioLtiSupportUtils';
41
- import RCEGlobals from '../../../RCEGlobals';
42
41
 
43
42
  const getLiveRegion = () => document.getElementById('flash_screenreader_holder');
44
43
 
45
44
  export default function VideoOptionsTray(_ref) {
46
- var _RCEGlobals$getConfig;
47
-
48
45
  let {
49
46
  videoOptions,
50
47
  onRequestClose,
@@ -71,9 +68,7 @@ export default function VideoOptionsTray(_ref) {
71
68
  const [minWidth] = useState(MIN_WIDTH_VIDEO);
72
69
  const [minHeight] = useState(Math.round(videoHeight / videoWidth * MIN_WIDTH_VIDEO));
73
70
  const [minPercentage] = useState(MIN_PERCENTAGE);
74
- const lock_statuses = (_RCEGlobals$getConfig = RCEGlobals.getConfig()) === null || _RCEGlobals$getConfig === void 0 ? void 0 : _RCEGlobals$getConfig.lockedAttachments;
75
71
  const isStudio = !!studioOptions;
76
- const isLocked = !!lock_statuses && !!lock_statuses[videoOptions.attachmentId];
77
72
  const showDisplayOptions = !isStudio || studioOptions.convertibleToLink;
78
73
  const showSizeControls = !isStudio || studioOptions.resizable;
79
74
  const dimensionsState = useDimensionsState(videoOptions, {
@@ -129,8 +124,7 @@ export default function VideoOptionsTray(_ref) {
129
124
  appliedWidth,
130
125
  displayAs,
131
126
  subtitles,
132
- updateMediaObject,
133
- isLocked
127
+ updateMediaObject
134
128
  });
135
129
  }
136
130
 
@@ -213,7 +207,7 @@ export default function VideoOptionsTray(_ref) {
213
207
  shouldShrink: true
214
208
  }, /*#__PURE__*/React.createElement(Flex, {
215
209
  direction: "column"
216
- }, !isLocked && /*#__PURE__*/React.createElement(Flex.Item, {
210
+ }, /*#__PURE__*/React.createElement(Flex.Item, {
217
211
  padding: "small"
218
212
  }, isStudio ? /*#__PURE__*/React.createElement(Flex, {
219
213
  direction: "column"
@@ -272,7 +266,7 @@ export default function VideoOptionsTray(_ref) {
272
266
  minWidth: minWidth,
273
267
  minPercentage: minPercentage,
274
268
  hidePercentage: true
275
- }))), !isStudio && !isLocked && /*#__PURE__*/React.createElement(Flex.Item, {
269
+ }))), !isStudio && /*#__PURE__*/React.createElement(Flex.Item, {
276
270
  padding: "small"
277
271
  }, /*#__PURE__*/React.createElement(FormFieldGroup, {
278
272
  description: formatMessage('Closed Captions/Subtitles')
@@ -24,41 +24,33 @@ import { BaseButton, CloseButton } from '@instructure/ui-buttons';
24
24
  import { Heading } from '@instructure/ui-heading';
25
25
  import { Table } from '@instructure/ui-table';
26
26
  import formatMessage from '../../../../format-message';
27
- import { instuiPopupMountNode } from '../../../../util/fullscreenHelpers'; // Doing this to avoid TS2339 errors -- TODO: remove once we're on InstUI 8
28
-
29
- const {
30
- Head,
31
- Row,
32
- ColHeader,
33
- Body,
34
- Cell
35
- } = Table;
27
+ import { instuiPopupMountNode } from '../../../../util/fullscreenHelpers';
36
28
 
37
29
  const renderBody = (headers, rows) => {
38
30
  return /*#__PURE__*/React.createElement(Table, {
39
31
  caption: formatMessage('Word Count')
40
- }, /*#__PURE__*/React.createElement(Head, null, /*#__PURE__*/React.createElement(Row, null, headers.map(_ref => {
32
+ }, /*#__PURE__*/React.createElement(Table.Head, null, /*#__PURE__*/React.createElement(Table.Row, null, headers.map(_ref => {
41
33
  let {
42
34
  id,
43
35
  getLabel
44
36
  } = _ref;
45
- return /*#__PURE__*/React.createElement(ColHeader, {
37
+ return /*#__PURE__*/React.createElement(Table.ColHeader, {
46
38
  key: id,
47
39
  id: id
48
40
  }, getLabel());
49
- }))), /*#__PURE__*/React.createElement(Body, null, rows.map(_ref2 => {
41
+ }))), /*#__PURE__*/React.createElement(Table.Body, null, rows.map(_ref2 => {
50
42
  let {
51
43
  label,
52
44
  documentCount,
53
45
  selectionCount
54
46
  } = _ref2;
55
- return /*#__PURE__*/React.createElement(Row, {
47
+ return /*#__PURE__*/React.createElement(Table.Row, {
56
48
  key: label
57
- }, /*#__PURE__*/React.createElement(Cell, {
49
+ }, /*#__PURE__*/React.createElement(Table.Cell, {
58
50
  key: "label"
59
- }, label), /*#__PURE__*/React.createElement(Cell, {
51
+ }, label), /*#__PURE__*/React.createElement(Table.Cell, {
60
52
  key: "document"
61
- }, documentCount), /*#__PURE__*/React.createElement(Cell, {
53
+ }, documentCount), /*#__PURE__*/React.createElement(Table.Cell, {
62
54
  key: "selection"
63
55
  }, selectionCount));
64
56
  })));
@@ -22,6 +22,7 @@ import { CloseButton, Button } from '@instructure/ui-buttons';
22
22
  import { Heading } from '@instructure/ui-heading';
23
23
  import { Spinner } from '@instructure/ui-spinner';
24
24
  import { Flex } from '@instructure/ui-flex';
25
+ import { View } from '@instructure/ui-view';
25
26
  import ErrorBoundary from './ErrorBoundary';
26
27
  import Bridge from '../../../bridge/Bridge';
27
28
  import formatMessage from '../../../format-message';
@@ -240,6 +241,7 @@ export default function CanvasContentTray(props) {
240
241
  const [hidingTrayOnAction, setHidingTrayOnAction] = useState(true);
241
242
  const trayRef = useRef(null);
242
243
  const scrollingAreaRef = useRef(null);
244
+ const closeButtonRef = useRef(null);
243
245
  const [filterSettings, setFilterSettings] = useFilterSettings();
244
246
  const [isEditTray, setIsEditTray] = useState(false);
245
247
  const [link, setLink] = useState(null);
@@ -266,6 +268,8 @@ export default function CanvasContentTray(props) {
266
268
  useEffect(() => {
267
269
  const controller = {
268
270
  showTrayForPlugin(plugin) {
271
+ var _closeButtonRef$curre;
272
+
269
273
  // increment a counter that's used as the key when rendering
270
274
  // this gets us a new instance everytime, which is necessary
271
275
  // to get the queries run so we have up to date data.
@@ -293,6 +297,8 @@ export default function CanvasContentTray(props) {
293
297
  } else {
294
298
  setIsEditTray(false);
295
299
  }
300
+
301
+ (_closeButtonRef$curre = closeButtonRef.current) === null || _closeButtonRef$curre === void 0 ? void 0 : _closeButtonRef$curre.focus();
296
302
  },
297
303
 
298
304
  hideTray(forceClose) {
@@ -463,19 +469,19 @@ export default function CanvasContentTray(props) {
463
469
  }, /*#__PURE__*/React.createElement(Flex.Item, {
464
470
  padding: "medium",
465
471
  shadow: "above"
466
- }, /*#__PURE__*/React.createElement(Flex, {
472
+ }, /*#__PURE__*/React.createElement(View, {
473
+ as: "div",
467
474
  margin: "none none medium none"
468
- }, /*#__PURE__*/React.createElement(Flex.Item, {
469
- shouldgrow: true,
470
- shouldshrink: true
471
475
  }, /*#__PURE__*/React.createElement(Heading, {
472
476
  level: "h2"
473
- }, getHeader())), /*#__PURE__*/React.createElement(Flex.Item, null, /*#__PURE__*/React.createElement(CloseButton, {
477
+ }, getHeader()), /*#__PURE__*/React.createElement(CloseButton, {
474
478
  placement: "end",
479
+ offset: "medium",
475
480
  onClick: handleDismissTray,
476
481
  "data-testid": "CloseButton_ContentTray",
477
- screenReaderLabel: formatMessage('Close')
478
- }))), isEditTray && /*#__PURE__*/React.createElement(LinkDisplay, {
482
+ screenReaderLabel: formatMessage('Close'),
483
+ elementRef: el => closeButtonRef.current = el
484
+ })), isEditTray && /*#__PURE__*/React.createElement(LinkDisplay, {
479
485
  linkText: linkText,
480
486
  placeholderText: (link === null || link === void 0 ? void 0 : link.title) || placeholderText,
481
487
  linkFileName: (link === null || link === void 0 ? void 0 : link.title) || '',
@@ -492,8 +498,8 @@ export default function CanvasContentTray(props) {
492
498
  isContentLoading: isLoading(storeProps),
493
499
  use_rce_icon_maker: props.use_rce_icon_maker
494
500
  }))), /*#__PURE__*/React.createElement(Flex.Item, {
495
- grow: true,
496
- shrink: true,
501
+ shouldGrow: true,
502
+ shouldShrink: true,
497
503
  margin: "xx-small xxx-small 0",
498
504
  elementRef: el => scrollingAreaRef.current = el
499
505
  }, /*#__PURE__*/React.createElement(Flex, {
@@ -32,7 +32,7 @@ export const DISPLAY_AS_EMBED = 'embed';
32
32
  export const DISPLAY_AS_EMBED_DISABLED = 'embed-disabled';
33
33
  export const DISPLAY_AS_DOWNLOAD_LINK = 'download-link';
34
34
  export function asImageEmbed($element) {
35
- const nodeName = $element.nodeName.toLowerCase();
35
+ const nodeName = $element === null || $element === void 0 ? void 0 : $element.nodeName.toLowerCase();
36
36
 
37
37
  if (nodeName !== 'img') {
38
38
  return null;
@@ -44,9 +44,11 @@ export function asImageEmbed($element) {
44
44
  };
45
45
  }
46
46
  export function asLink($element, editor) {
47
+ var _$link;
48
+
47
49
  let $link = $element;
48
50
 
49
- if ($link.tagName !== 'A') {
51
+ if (((_$link = $link) === null || _$link === void 0 ? void 0 : _$link.tagName) !== 'A') {
50
52
  // the user may have selected some text that is w/in a link
51
53
  // but didn't include the <a>. Let's see if that's true
52
54
  $link = editor.dom.getParent($link, 'a[href]');
@@ -213,7 +215,7 @@ function isMediaElement($element, mediaType) {
213
215
 
214
216
  // the video is hosted in an iframe, but tinymce
215
217
  // wraps it in a span with swizzled attribute names
216
- if (!($element !== null && $element !== void 0 && $element.getAttribute)) {
218
+ if (!($element !== null && $element !== void 0 && $element.getAttribute) || !$element) {
217
219
  return false;
218
220
  }
219
221
 
@@ -242,6 +244,8 @@ export function isAudioElement($element) {
242
244
  export function findMediaPlayerIframe(elem) {
243
245
  var _elem$firstElementChi;
244
246
 
247
+ if (!elem) return null;
248
+
245
249
  if (elem.tagName === 'IFRAME') {
246
250
  // we have the iframe
247
251
  return elem;
@@ -25,7 +25,6 @@ import { useMouseWheel } from './useMouseWheel';
25
25
  import { useKeyMouseTouchEvents } from './useKeyMouseEvents';
26
26
  import checkerboardStyle from '../CheckerboardStyling';
27
27
  import { View } from '@instructure/ui-view';
28
- import { getBrowser } from '../../../getBrowser';
29
28
  /**
30
29
  * Remove the node contents and append the svg element.
31
30
  */
@@ -86,17 +85,19 @@ export const Preview = _ref2 => {
86
85
  translateY: tempTranslateY,
87
86
  rotation,
88
87
  scaleRatio: tempScaleRatio
89
- }); // Clip is not supported in Safari until v16.
88
+ });
89
+
90
+ function isSafariVersion15OrLesser() {
91
+ const match = /Version\/(\d+).+Safari/.exec(navigator.userAgent);
92
+ return match ? parseInt(match[1], 10) < 16 : false;
93
+ } // Clip is not supported in Safari until v16.
90
94
  // It's needed here to prevent a strange screenreader
91
95
  // behavior that makes the cropper look bad. 'hidden'
92
96
  // suffices when clip is not available, although it's not perfect
93
97
  // TODO: remove when Safari versions >= 16 are more commonplace
94
98
 
95
- const {
96
- name,
97
- version
98
- } = getBrowser();
99
- const overflow = name === 'Safari' && parseFloat(version) < 16 ? 'hidden' : 'clip';
99
+
100
+ const overflow = isSafariVersion15OrLesser() ? 'hidden' : 'clip';
100
101
  return /*#__PURE__*/React.createElement("div", {
101
102
  style: {
102
103
  justifyContent: 'center',
@@ -81,8 +81,8 @@ export const LinkDisplay = _ref => {
81
81
  size: "x-small"
82
82
  }))), /*#__PURE__*/React.createElement(Flex.Item, {
83
83
  padding: "0 x-small 0 0",
84
- grow: true,
85
- shrink: true,
84
+ shouldGrow: true,
85
+ shouldShrink: true,
86
86
  textAlign: "start"
87
87
  }, /*#__PURE__*/React.createElement(View, {
88
88
  as: "div"