@instructure/canvas-rce 6.0.0 → 7.2.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.
- package/CHANGELOG.md +46 -0
- package/__tests__/common/indicate.test.js +5 -6
- package/es/bridge/Bridge.js +2 -4
- package/es/canvasFileBrowser/FileBrowser.js +2 -4
- package/es/common/browser.js +2 -2
- package/es/common/fileUrl.js +13 -3
- package/es/defaultTinymceConfig.d.ts +1 -1
- package/es/defaultTinymceConfig.js +149 -114
- package/es/enhance-user-content/enhance_user_content.js +7 -1
- package/es/enhance-user-content/instructure_helper.js +4 -0
- package/es/enhance-user-content/youtube_overlay.d.ts +1 -0
- package/es/enhance-user-content/youtube_overlay.js +87 -0
- package/es/format-message.d.js +1 -0
- package/es/format-message.js +5 -0
- package/es/index.d.ts +1 -1
- package/es/rce/RCE.d.ts +0 -1
- package/es/rce/RCE.js +5 -10
- package/es/rce/RCEGlobals.d.ts +0 -2
- package/es/rce/RCEGlobals.js +0 -1
- package/es/rce/RCEVariants.d.ts +8 -3
- package/es/rce/RCEVariants.js +36 -10
- package/es/rce/RCEWrapper.d.ts +3 -5
- package/es/rce/RCEWrapper.js +68 -83
- package/es/rce/RCEWrapperProps.d.ts +1 -1
- package/es/rce/ShowOnFocusButton/index.js +4 -2
- package/es/rce/StatusBar.js +61 -15
- package/es/rce/alertHandler.js +6 -7
- package/es/rce/plugins/instructure-ui-icons/plugin.js +2 -2
- package/es/rce/plugins/instructure_equation/EquationEditorModal/index.d.ts +1 -1
- package/es/rce/plugins/instructure_equation/EquationEditorModal/index.js +6 -10
- package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/Course.d.ts +5 -15
- package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/Course.js +4 -10
- package/es/rce/plugins/instructure_image/ImageEmbedOptions.d.ts +7 -0
- package/es/rce/plugins/instructure_image/ImageEmbedOptions.js +49 -9
- package/es/rce/plugins/instructure_rce_external_tools/components/ExternalToolDialog/ExternalToolDialog.d.ts +1 -8
- package/es/rce/plugins/instructure_rce_external_tools/components/ExternalToolDialog/ExternalToolDialog.js +13 -33
- package/es/rce/plugins/instructure_rce_external_tools/components/ExternalToolDialog/ExternalToolDialogModal.d.ts +1 -2
- package/es/rce/plugins/instructure_rce_external_tools/components/ExternalToolDialog/ExternalToolDialogModal.js +2 -1
- package/es/rce/plugins/instructure_record/AudioOptionsTray/TrayController.js +1 -2
- package/es/rce/plugins/instructure_record/VideoOptionsTray/TrayController.js +2 -4
- package/es/rce/plugins/instructure_record/VideoOptionsTray/index.js +10 -7
- package/es/rce/plugins/shared/ContentSelection.js +4 -7
- package/es/rce/plugins/shared/DimensionsInput/index.js +3 -3
- package/es/rce/plugins/shared/FixedContentTray.d.ts +7 -23
- package/es/rce/plugins/shared/FixedContentTray.js +7 -16
- package/es/rce/plugins/shared/ImageCropper/constants.d.ts +1 -1
- package/es/rce/plugins/shared/ImageCropper/constants.js +1 -1
- package/es/rce/plugins/shared/ImageCropper/controls/CustomNumberInput.js +1 -1
- package/es/rce/plugins/shared/PreviewIcon.js +1 -1
- package/es/rce/plugins/shared/ai_tools/aiicons.d.ts +3 -3
- package/es/rce/plugins/shared/ai_tools/aiicons.js +11 -11
- package/es/rce/plugins/shared/fileTypeUtils.js +1 -1
- package/es/rce/plugins/tinymce-a11y-checker/components/checker.js +7 -1
- package/es/rce/plugins/tinymce-a11y-checker/plugin.js +50 -52
- package/es/rce/plugins/tinymce-a11y-checker/utils/indicate.d.ts +1 -1
- package/es/rce/plugins/tinymce-a11y-checker/utils/indicate.js +1 -1
- package/es/rce/style.js +47 -45
- package/es/rcs/api.d.ts +4 -1
- package/es/rcs/api.js +9 -13
- package/es/translations/locales/ar.js +29 -5
- package/es/translations/locales/ca.js +32 -8
- package/es/translations/locales/cy.js +29 -5
- package/es/translations/locales/da-x-k12.js +29 -5
- package/es/translations/locales/da.js +29 -5
- package/es/translations/locales/de.js +29 -5
- package/es/translations/locales/en-AU-x-unimelb.js +29 -5
- package/es/translations/locales/en-GB-x-ukhe.js +29 -5
- package/es/translations/locales/en.js +20 -5
- package/es/translations/locales/en_AU.js +29 -5
- package/es/translations/locales/en_CA.js +29 -5
- package/es/translations/locales/en_CY.js +29 -5
- package/es/translations/locales/en_GB.js +29 -5
- package/es/translations/locales/es.js +29 -5
- package/es/translations/locales/es_ES.js +29 -5
- package/es/translations/locales/fa_IR.js +0 -3
- package/es/translations/locales/fi.js +29 -5
- package/es/translations/locales/fr.js +29 -5
- package/es/translations/locales/fr_CA.js +30 -6
- package/es/translations/locales/ga.js +46 -22
- package/es/translations/locales/hi.js +29 -5
- package/es/translations/locales/ht.js +29 -5
- package/es/translations/locales/hu.js +0 -6
- package/es/translations/locales/id.js +29 -5
- package/es/translations/locales/is.js +23 -5
- package/es/translations/locales/it.js +29 -5
- package/es/translations/locales/ja.js +29 -5
- package/es/translations/locales/mi.js +29 -5
- package/es/translations/locales/ms.js +29 -5
- package/es/translations/locales/nb-x-k12.js +29 -5
- package/es/translations/locales/nb.js +29 -5
- package/es/translations/locales/nl.js +29 -5
- package/es/translations/locales/nn.js +0 -6
- package/es/translations/locales/pl.js +29 -5
- package/es/translations/locales/pt.js +29 -5
- package/es/translations/locales/pt_BR.js +29 -5
- package/es/translations/locales/ru.js +29 -5
- package/es/translations/locales/sl.js +29 -5
- package/es/translations/locales/sv-x-k12.js +29 -5
- package/es/translations/locales/sv.js +29 -5
- package/es/translations/locales/th.js +29 -5
- package/es/translations/locales/uk_UA.js +0 -6
- package/es/translations/locales/vi.js +29 -5
- package/es/translations/locales/zh-Hans.js +29 -5
- package/es/translations/locales/zh-Hant.js +29 -5
- package/es/translations/locales/zh.js +29 -5
- package/es/translations/locales/zh_HK.js +29 -5
- package/es/util/contextHelper.d.ts +7 -0
- package/{testcafe/axe.test.js → es/util/contextHelper.js} +10 -21
- package/es/util/loadingPlaceholder.js +11 -11
- package/eslint.config.js +3 -25
- package/jest/jest-setup.js +27 -2
- package/jest.config.js +5 -1
- package/package.json +62 -85
- package/testcafe/RCEWrapper.test.js +0 -319
- package/testcafe/StatusBar.test.js +0 -108
- package/testcafe/enhanceUserContent.html +0 -58
- package/testcafe/enhanceUserContent.test.js +0 -44
- package/testcafe/entry.jsx +0 -77
- package/testcafe/testcafe.html +0 -14
- package/webpack.testcafe.config.js +0 -61
package/es/rce/RCEWrapper.js
CHANGED
|
@@ -19,6 +19,7 @@ import _pt from "prop-types";
|
|
|
19
19
|
|
|
20
20
|
import React, { Suspense } from 'react';
|
|
21
21
|
import { Editor } from '@tinymce/tinymce-react';
|
|
22
|
+
import tinymce from 'tinymce';
|
|
22
23
|
import _ from 'lodash';
|
|
23
24
|
import { StoreProvider } from './plugins/shared/StoreContext';
|
|
24
25
|
import { IconKeyboardShortcutsLine } from '@instructure/ui-icons';
|
|
@@ -64,6 +65,7 @@ import { getMenubarForVariant, getMenuForVariant, getToolbarForVariant, getStatu
|
|
|
64
65
|
import { focusFirstMenuButton, focusToolbar, isElementWithinTable, mergeMenu, mergeMenuItems, mergePlugins, mergeToolbar, parsePluginsToExclude, patchAutosavedContent } from './RCEWrapper.utils';
|
|
65
66
|
import { externalToolsForToolbar } from './plugins/instructure_rce_external_tools/util/externalToolsForToolbar';
|
|
66
67
|
import { initScreenreaderOnFormat } from './screenreaderOnFormat';
|
|
68
|
+
import { normalizeContainingContext } from '../util/contextHelper';
|
|
67
69
|
const RestoreAutoSaveModal = /*#__PURE__*/React.lazy(() => import('./RestoreAutoSaveModal'));
|
|
68
70
|
const RceHtmlEditor = /*#__PURE__*/React.lazy(() => import('./RceHtmlEditor'));
|
|
69
71
|
const ASYNC_FOCUS_TIMEOUT = 250;
|
|
@@ -141,6 +143,7 @@ class RCEWrapper extends React.Component {
|
|
|
141
143
|
this._showOnFocusButton = void 0;
|
|
142
144
|
this._statusBarId = void 0;
|
|
143
145
|
this._textareaEl = void 0;
|
|
146
|
+
this._effectiveContainingContext = void 0;
|
|
144
147
|
this.AIToolsTray = void 0;
|
|
145
148
|
this.editor = void 0;
|
|
146
149
|
this.initialContent = void 0;
|
|
@@ -208,6 +211,7 @@ class RCEWrapper extends React.Component {
|
|
|
208
211
|
this.toggleFullscreen = () => {
|
|
209
212
|
this.handleClickFullscreen();
|
|
210
213
|
};
|
|
214
|
+
// @ts-expect-error
|
|
211
215
|
this._onFullscreenChange = event => {
|
|
212
216
|
if (document[FS_ELEMENT]) {
|
|
213
217
|
// @ts-expect-error
|
|
@@ -238,6 +242,7 @@ class RCEWrapper extends React.Component {
|
|
|
238
242
|
this.handleFocusRCE = () => {
|
|
239
243
|
this.handleFocus();
|
|
240
244
|
};
|
|
245
|
+
// @ts-expect-error
|
|
241
246
|
this.handleBlurRCE = event => {
|
|
242
247
|
if (event.relatedTarget === null) {
|
|
243
248
|
// focus might be moving to tinymce
|
|
@@ -268,13 +273,11 @@ class RCEWrapper extends React.Component {
|
|
|
268
273
|
if (event.code === 'F9' && event.altKey) {
|
|
269
274
|
event.preventDefault();
|
|
270
275
|
event.stopPropagation();
|
|
271
|
-
this.setFocusAbilityForHeader(true);
|
|
272
276
|
// @ts-expect-error
|
|
273
277
|
focusFirstMenuButton(this._elementRef.current);
|
|
274
278
|
} else if (event.code === 'F10' && event.altKey) {
|
|
275
279
|
event.preventDefault();
|
|
276
280
|
event.stopPropagation();
|
|
277
|
-
this.setFocusAbilityForHeader(true);
|
|
278
281
|
// @ts-expect-error
|
|
279
282
|
focusToolbar(this._elementRef.current);
|
|
280
283
|
} else if (event.code === 'F8' && event.altKey) {
|
|
@@ -329,20 +332,6 @@ class RCEWrapper extends React.Component {
|
|
|
329
332
|
tinyapp.setAttribute('tabIndex', '-1');
|
|
330
333
|
}
|
|
331
334
|
|
|
332
|
-
// Adds a focusout event listener for handling screen reader navigation focus
|
|
333
|
-
const header = this._elementRef.current?.querySelector('.tox-editor-header');
|
|
334
|
-
if (header) {
|
|
335
|
-
// @ts-expect-error
|
|
336
|
-
header.addEventListener('focusout', e => {
|
|
337
|
-
// @ts-expect-error
|
|
338
|
-
const leavingHeader = !header.contains(e.relatedTarget);
|
|
339
|
-
if (leavingHeader) {
|
|
340
|
-
this.setFocusAbilityForHeader(false);
|
|
341
|
-
}
|
|
342
|
-
});
|
|
343
|
-
}
|
|
344
|
-
this.setFocusAbilityForHeader(false);
|
|
345
|
-
|
|
346
335
|
// Probably should do this in tinymce.scss, but we only want it in new rce
|
|
347
336
|
textarea.style.resize = 'none';
|
|
348
337
|
editor.on('keydown', this.handleKey);
|
|
@@ -388,6 +377,12 @@ class RCEWrapper extends React.Component {
|
|
|
388
377
|
});
|
|
389
378
|
}
|
|
390
379
|
};
|
|
380
|
+
/**
|
|
381
|
+
* Fix keyboard navigation in the expanded toolbar
|
|
382
|
+
*
|
|
383
|
+
* NOTE: This is a workaround for https://github.com/tinymce/tinymce/issues/8618
|
|
384
|
+
* and should be removed once that issue is resolved and the tinymce dependency is updated to include it.
|
|
385
|
+
*/
|
|
391
386
|
this.fixToolbarKeyboardNavigation = () => {
|
|
392
387
|
// The keyboard navigation config in tinymce for the expanded toolbar is incorrectly configured,
|
|
393
388
|
// and stops at [data-alloy-tabstop] elements.
|
|
@@ -397,6 +392,19 @@ class RCEWrapper extends React.Component {
|
|
|
397
392
|
// in https://github.com/tinymce/tinymce/blob/develop/modules/alloy/src/main/ts/ephox/alloy/ui/schema/SplitSlidingToolbarSchema.ts
|
|
398
393
|
this._elementRef.current?.querySelectorAll('.tox-toolbar-overlord button[data-alloy-tabstop]').forEach(it => it.removeAttribute('data-alloy-tabstop'));
|
|
399
394
|
};
|
|
395
|
+
/**
|
|
396
|
+
* Sets up selection saving and restoration logic.
|
|
397
|
+
*
|
|
398
|
+
* There are certain actions a user can take when the RCE is not focused that clear the selection inside the
|
|
399
|
+
* editor, such as invoking the Find feature of the browser. If the user then tries to insert content without
|
|
400
|
+
* going back to the editor, the content would be inserted at the top of the RCE, instead of where their cursor
|
|
401
|
+
* was.
|
|
402
|
+
*
|
|
403
|
+
* This method adds logic that saves and restores the selection to work around the issue.
|
|
404
|
+
*
|
|
405
|
+
* @private
|
|
406
|
+
*/
|
|
407
|
+
// @ts-expect-error
|
|
400
408
|
this._setupSelectionSaving = editor => {
|
|
401
409
|
// @ts-expect-error
|
|
402
410
|
let savedSelection = null;
|
|
@@ -455,6 +463,7 @@ class RCEWrapper extends React.Component {
|
|
|
455
463
|
});
|
|
456
464
|
};
|
|
457
465
|
this.announcing = 0;
|
|
466
|
+
/* ********** autosave support *************** */
|
|
458
467
|
this.initAutoSave = editor => {
|
|
459
468
|
var _this$props$userCache;
|
|
460
469
|
this.storage = new EncryptedStorage((_this$props$userCache = this.props.userCacheKey) !== null && _this$props$userCache !== void 0 ? _this$props$userCache : '');
|
|
@@ -489,6 +498,7 @@ class RCEWrapper extends React.Component {
|
|
|
489
498
|
}
|
|
490
499
|
}
|
|
491
500
|
};
|
|
501
|
+
// remove any autosaved value that's too old
|
|
492
502
|
this.cleanupAutoSave = (deleteAll = false) => {
|
|
493
503
|
if (this.storage) {
|
|
494
504
|
const expiry = deleteAll ? Date.now() : Date.now() - (this.props.autosave?.maxAge || 0);
|
|
@@ -504,6 +514,7 @@ class RCEWrapper extends React.Component {
|
|
|
504
514
|
}
|
|
505
515
|
}
|
|
506
516
|
};
|
|
517
|
+
// @ts-expect-error
|
|
507
518
|
this.restoreAutoSave = ans => {
|
|
508
519
|
this.setState({
|
|
509
520
|
confirmAutoSave: false
|
|
@@ -518,6 +529,7 @@ class RCEWrapper extends React.Component {
|
|
|
518
529
|
// let the content be restored
|
|
519
530
|
debounce(this.checkAccessibility, 1000)();
|
|
520
531
|
};
|
|
532
|
+
// @ts-expect-error
|
|
521
533
|
this.doAutoSave = (e, retry = false) => {
|
|
522
534
|
if (this.storage) {
|
|
523
535
|
const editor = this.mceInstance();
|
|
@@ -542,6 +554,7 @@ class RCEWrapper extends React.Component {
|
|
|
542
554
|
}
|
|
543
555
|
}
|
|
544
556
|
};
|
|
557
|
+
/* *********** end autosave support *************** */
|
|
545
558
|
this.onWordCountUpdate = e => {
|
|
546
559
|
if (!this.editor) return;
|
|
547
560
|
const shouldIgnore = countShouldIgnore(this.editor, 'body', 'words');
|
|
@@ -554,6 +567,7 @@ class RCEWrapper extends React.Component {
|
|
|
554
567
|
} else return null;
|
|
555
568
|
});
|
|
556
569
|
};
|
|
570
|
+
// @ts-expect-error
|
|
557
571
|
this.onNodeChange = e => {
|
|
558
572
|
// This is basically copied out of the tinymce silver theme code for the status bar
|
|
559
573
|
const path = e.parents.filter(p => p.nodeName !== 'BR' && !p.getAttribute('data-mce-bogus') && p.getAttribute('data-mce-type') !== 'bookmark')
|
|
@@ -589,7 +603,9 @@ class RCEWrapper extends React.Component {
|
|
|
589
603
|
height: newHeight
|
|
590
604
|
});
|
|
591
605
|
// play nice and send the same event that the silver theme would send
|
|
592
|
-
editor.fire('ResizeEditor'
|
|
606
|
+
editor.fire('ResizeEditor', {
|
|
607
|
+
deltaY: coordinates.deltaY
|
|
608
|
+
});
|
|
593
609
|
}
|
|
594
610
|
};
|
|
595
611
|
this.onA11yChecker = triggerElementId => {
|
|
@@ -705,13 +721,6 @@ class RCEWrapper extends React.Component {
|
|
|
705
721
|
content: this.mceInstance().getContent()
|
|
706
722
|
};
|
|
707
723
|
};
|
|
708
|
-
this.setFocusAbilityForHeader = focusable => {
|
|
709
|
-
// Sets aria-hidden to prevent screen readers focus in RCE menus and toolbar
|
|
710
|
-
const header = this._elementRef.current?.querySelector('.tox-editor-header');
|
|
711
|
-
if (header) {
|
|
712
|
-
header.setAttribute('aria-hidden', focusable ? 'false' : 'true');
|
|
713
|
-
}
|
|
714
|
-
};
|
|
715
724
|
this.handleTextareaChange = () => {
|
|
716
725
|
if (this.isHidden()) {
|
|
717
726
|
this.setCode(this.textareaValue());
|
|
@@ -737,6 +746,9 @@ class RCEWrapper extends React.Component {
|
|
|
737
746
|
};
|
|
738
747
|
});
|
|
739
748
|
};
|
|
749
|
+
/**
|
|
750
|
+
* Used for reseting the value during tests
|
|
751
|
+
*/
|
|
740
752
|
this.resetAlertId = () => {
|
|
741
753
|
if (this.state.messages.length > 0) {
|
|
742
754
|
throw new Error('There are messages currently, you cannot reset when they are non-zero');
|
|
@@ -828,6 +840,7 @@ class RCEWrapper extends React.Component {
|
|
|
828
840
|
this._handleFullscreenResize();
|
|
829
841
|
});
|
|
830
842
|
this.AIToolsTray = undefined;
|
|
843
|
+
this._effectiveContainingContext = normalizeContainingContext(this.props.trayProps?.containingContext);
|
|
831
844
|
}
|
|
832
845
|
|
|
833
846
|
// when the RCE is put into fullscreen we need to move the div
|
|
@@ -853,7 +866,6 @@ class RCEWrapper extends React.Component {
|
|
|
853
866
|
new_math_equation_handling = false,
|
|
854
867
|
explicit_latex_typesetting = false,
|
|
855
868
|
rce_transform_loaded_content = false,
|
|
856
|
-
media_links_use_attachment_id = false,
|
|
857
869
|
rce_find_replace = false,
|
|
858
870
|
file_verifiers_for_quiz_links = false,
|
|
859
871
|
consolidated_media_player = false
|
|
@@ -862,7 +874,6 @@ class RCEWrapper extends React.Component {
|
|
|
862
874
|
new_math_equation_handling,
|
|
863
875
|
explicit_latex_typesetting,
|
|
864
876
|
rce_transform_loaded_content,
|
|
865
|
-
media_links_use_attachment_id,
|
|
866
877
|
file_verifiers_for_quiz_links,
|
|
867
878
|
rce_find_replace,
|
|
868
879
|
consolidated_media_player
|
|
@@ -1119,8 +1130,7 @@ class RCEWrapper extends React.Component {
|
|
|
1119
1130
|
if (this.editor) {
|
|
1120
1131
|
return this.editor;
|
|
1121
1132
|
}
|
|
1122
|
-
|
|
1123
|
-
return editors.filter(ed => ed.id === this.props.textareaId)[0];
|
|
1133
|
+
return this.props.tinymce.get(this.props.textareaId);
|
|
1124
1134
|
}
|
|
1125
1135
|
|
|
1126
1136
|
// @ts-expect-error
|
|
@@ -1195,9 +1205,6 @@ class RCEWrapper extends React.Component {
|
|
|
1195
1205
|
document[FS_EXIT]();
|
|
1196
1206
|
}
|
|
1197
1207
|
}
|
|
1198
|
-
|
|
1199
|
-
// @ts-expect-error
|
|
1200
|
-
|
|
1201
1208
|
_getStatusBarHeight() {
|
|
1202
1209
|
// the height prop is the height of the editor and does not include
|
|
1203
1210
|
// the status bar. we'll need this later.
|
|
@@ -1343,9 +1350,6 @@ class RCEWrapper extends React.Component {
|
|
|
1343
1350
|
}, ASYNC_FOCUS_TIMEOUT);
|
|
1344
1351
|
}
|
|
1345
1352
|
}
|
|
1346
|
-
|
|
1347
|
-
// @ts-expect-error
|
|
1348
|
-
|
|
1349
1353
|
// @ts-expect-error
|
|
1350
1354
|
call(methodName, ...args) {
|
|
1351
1355
|
// since exists? has a ? and cant be a regular function just return true
|
|
@@ -1356,28 +1360,6 @@ class RCEWrapper extends React.Component {
|
|
|
1356
1360
|
// @ts-expect-error
|
|
1357
1361
|
return this[methodName](...args);
|
|
1358
1362
|
}
|
|
1359
|
-
|
|
1360
|
-
/**
|
|
1361
|
-
* Fix keyboard navigation in the expanded toolbar
|
|
1362
|
-
*
|
|
1363
|
-
* NOTE: This is a workaround for https://github.com/tinymce/tinymce/issues/8618
|
|
1364
|
-
* and should be removed once that issue is resolved and the tinymce dependency is updated to include it.
|
|
1365
|
-
*/
|
|
1366
|
-
|
|
1367
|
-
/**
|
|
1368
|
-
* Sets up selection saving and restoration logic.
|
|
1369
|
-
*
|
|
1370
|
-
* There are certain actions a user can take when the RCE is not focused that clear the selection inside the
|
|
1371
|
-
* editor, such as invoking the Find feature of the browser. If the user then tries to insert content without
|
|
1372
|
-
* going back to the editor, the content would be inserted at the top of the RCE, instead of where their cursor
|
|
1373
|
-
* was.
|
|
1374
|
-
*
|
|
1375
|
-
* This method adds logic that saves and restores the selection to work around the issue.
|
|
1376
|
-
*
|
|
1377
|
-
* @private
|
|
1378
|
-
*/
|
|
1379
|
-
// @ts-expect-error
|
|
1380
|
-
|
|
1381
1363
|
announceContextToolbars(editor) {
|
|
1382
1364
|
editor.on('NodeChange', () => {
|
|
1383
1365
|
const node = editor.selection.getNode();
|
|
@@ -1416,14 +1398,21 @@ class RCEWrapper extends React.Component {
|
|
|
1416
1398
|
this.announcing = 0;
|
|
1417
1399
|
}
|
|
1418
1400
|
});
|
|
1401
|
+
editor.on('ResizeEditor', ({
|
|
1402
|
+
deltaY
|
|
1403
|
+
}) => {
|
|
1404
|
+
if (!deltaY) return;
|
|
1405
|
+
if (deltaY < 0) {
|
|
1406
|
+
this.setState({
|
|
1407
|
+
announcement: formatMessage('The height of Rich Content Area is decreased.')
|
|
1408
|
+
});
|
|
1409
|
+
} else {
|
|
1410
|
+
this.setState({
|
|
1411
|
+
announcement: formatMessage('The height of Rich Content Area is increased.')
|
|
1412
|
+
});
|
|
1413
|
+
}
|
|
1414
|
+
});
|
|
1419
1415
|
}
|
|
1420
|
-
|
|
1421
|
-
/* ********** autosave support *************** */
|
|
1422
|
-
|
|
1423
|
-
// remove any autosaved value that's too old
|
|
1424
|
-
|
|
1425
|
-
// @ts-expect-error
|
|
1426
|
-
|
|
1427
1416
|
getAutoSaved(key) {
|
|
1428
1417
|
let autosaved = null;
|
|
1429
1418
|
try {
|
|
@@ -1448,17 +1437,9 @@ class RCEWrapper extends React.Component {
|
|
|
1448
1437
|
return this.props.autosave?.enabled && editorVisible && document.querySelectorAll('.rce-wrapper').length === 1 && storageAvailable();
|
|
1449
1438
|
}
|
|
1450
1439
|
get autoSaveKey() {
|
|
1451
|
-
|
|
1452
|
-
const userId = this.props.trayProps?.containingContext.userId;
|
|
1440
|
+
const userId = this._effectiveContainingContext?.userId || '-';
|
|
1453
1441
|
return `rceautosave:${userId}${window.location.href}:${this.props.textareaId}`;
|
|
1454
1442
|
}
|
|
1455
|
-
|
|
1456
|
-
// @ts-expect-error
|
|
1457
|
-
|
|
1458
|
-
/* *********** end autosave support *************** */
|
|
1459
|
-
|
|
1460
|
-
// @ts-expect-error
|
|
1461
|
-
|
|
1462
1443
|
componentWillUnmount() {
|
|
1463
1444
|
if (this.state.shouldShowEditor) {
|
|
1464
1445
|
window.clearTimeout(this.blurTimer);
|
|
@@ -1679,11 +1660,6 @@ class RCEWrapper extends React.Component {
|
|
|
1679
1660
|
this.mceInstance().hide();
|
|
1680
1661
|
}
|
|
1681
1662
|
}
|
|
1682
|
-
|
|
1683
|
-
/**
|
|
1684
|
-
* Used for reseting the value during tests
|
|
1685
|
-
*/
|
|
1686
|
-
|
|
1687
1663
|
renderHtmlEditor() {
|
|
1688
1664
|
// the div keeps the editor from collapsing while the code editor is downloaded
|
|
1689
1665
|
return /*#__PURE__*/React.createElement(Suspense, {
|
|
@@ -1732,7 +1708,12 @@ class RCEWrapper extends React.Component {
|
|
|
1732
1708
|
}
|
|
1733
1709
|
});
|
|
1734
1710
|
}
|
|
1735
|
-
const
|
|
1711
|
+
const statusBarOptions = {
|
|
1712
|
+
aiTextTools: this.props.ai_text_tools,
|
|
1713
|
+
isDesktop: tinymce.Env.deviceType.isDesktop(),
|
|
1714
|
+
a11yResizers: !!this.props.features?.rce_a11y_resize
|
|
1715
|
+
};
|
|
1716
|
+
const statusBarFeatures = getStatusBarFeaturesForVariant(this.variant, statusBarOptions);
|
|
1736
1717
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("style", null, this.style.css), /*#__PURE__*/React.createElement(StoreProvider, {
|
|
1737
1718
|
jwt: this.props.trayProps?.jwt,
|
|
1738
1719
|
refreshToken: this.props.trayProps?.refreshToken,
|
|
@@ -1754,7 +1735,7 @@ class RCEWrapper extends React.Component {
|
|
|
1754
1735
|
} : undefined,
|
|
1755
1736
|
onFocus: this.handleFocusRCE,
|
|
1756
1737
|
onBlur: this.handleBlurRCE
|
|
1757
|
-
}, this.state.shouldShowOnFocusButton && /*#__PURE__*/React.createElement(ShowOnFocusButton, {
|
|
1738
|
+
}, this.state.shouldShowOnFocusButton && tinymce.Env.deviceType.isDesktop() && /*#__PURE__*/React.createElement(ShowOnFocusButton, {
|
|
1758
1739
|
id: `show-on-focus-btn-${this.id}`,
|
|
1759
1740
|
onClick: this.openKBShortcutModal,
|
|
1760
1741
|
margin: "xx-small",
|
|
@@ -1820,7 +1801,7 @@ class RCEWrapper extends React.Component {
|
|
|
1820
1801
|
disabledPlugins: this.pluginsToExclude,
|
|
1821
1802
|
features: statusBarFeatures,
|
|
1822
1803
|
onAI: this.handleAIClick
|
|
1823
|
-
}), this.
|
|
1804
|
+
}), this._effectiveContainingContext && /*#__PURE__*/React.createElement(CanvasContentTray, Object.assign({
|
|
1824
1805
|
mountNode: instuiPopupMountNodeFn,
|
|
1825
1806
|
key: this.id,
|
|
1826
1807
|
canvasOrigin: this.getCanvasUrl(),
|
|
@@ -1829,7 +1810,9 @@ class RCEWrapper extends React.Component {
|
|
|
1829
1810
|
onTrayClosing: this.handleContentTrayClosing,
|
|
1830
1811
|
use_rce_icon_maker: this.props.use_rce_icon_maker
|
|
1831
1812
|
}, trayProps, {
|
|
1813
|
+
containingContext: this._effectiveContainingContext
|
|
1832
1814
|
// @ts-expect-error
|
|
1815
|
+
,
|
|
1833
1816
|
storeProps: storeProps
|
|
1834
1817
|
})), /*#__PURE__*/React.createElement(KeyboardShortcutModal, {
|
|
1835
1818
|
onExited: this.KBShortcutModalExited,
|
|
@@ -1858,7 +1841,10 @@ class RCEWrapper extends React.Component {
|
|
|
1858
1841
|
open: this.state.confirmAutoSave,
|
|
1859
1842
|
onNo: () => this.restoreAutoSave(false),
|
|
1860
1843
|
onYes: () => this.restoreAutoSave(true)
|
|
1861
|
-
})) : null,
|
|
1844
|
+
})) : null, this.state.announcement &&
|
|
1845
|
+
/*#__PURE__*/
|
|
1846
|
+
// @ts-expect-error
|
|
1847
|
+
React.createElement(Alert, {
|
|
1862
1848
|
screenReaderOnly: true,
|
|
1863
1849
|
liveRegion: this.props.liveRegion
|
|
1864
1850
|
}, this.state.announcement));
|
|
@@ -1869,8 +1855,7 @@ RCEWrapper.propTypes = {
|
|
|
1869
1855
|
ai_text_tools: _pt.bool,
|
|
1870
1856
|
autosave: _pt.shape({
|
|
1871
1857
|
enabled: _pt.bool,
|
|
1872
|
-
maxAge: _pt.number
|
|
1873
|
-
interval: _pt.number
|
|
1858
|
+
maxAge: _pt.number
|
|
1874
1859
|
}),
|
|
1875
1860
|
canvasOrigin: _pt.string,
|
|
1876
1861
|
defaultContent: _pt.string,
|
|
@@ -170,6 +170,6 @@ export declare const rceWrapperPropTypes: {
|
|
|
170
170
|
maxMruTools: PropTypes.Requireable<number>;
|
|
171
171
|
}>>;
|
|
172
172
|
ai_text_tools: PropTypes.Requireable<boolean>;
|
|
173
|
-
variant: PropTypes.Requireable<"full" | "lite" | "text-only" | "text-block">;
|
|
173
|
+
variant: PropTypes.Requireable<"full" | "lite" | "text-only" | "text-block" | "block-content-editor">;
|
|
174
174
|
};
|
|
175
175
|
export type RCEWrapperProps = PropTypes.InferProps<typeof rceWrapperPropTypes>;
|
|
@@ -26,8 +26,10 @@ import React, { Component } from 'react';
|
|
|
26
26
|
import { func, node, oneOfType, string } from 'prop-types';
|
|
27
27
|
import { IconButton } from '@instructure/ui-buttons';
|
|
28
28
|
const hideStyle = {
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
opacity: 0,
|
|
30
|
+
width: 0,
|
|
31
|
+
height: 0,
|
|
32
|
+
overflow: 'hidden'
|
|
31
33
|
};
|
|
32
34
|
export default class ShowOnFocusButton extends Component {
|
|
33
35
|
constructor(...args) {
|
package/es/rce/StatusBar.js
CHANGED
|
@@ -28,7 +28,7 @@ import { Badge } from '@instructure/ui-badge';
|
|
|
28
28
|
import { InstUISettingsProvider } from '@instructure/emotion';
|
|
29
29
|
import { Text } from '@instructure/ui-text';
|
|
30
30
|
import { SVGIcon } from '@instructure/ui-svg-images';
|
|
31
|
-
import { IconA11yLine, IconKeyboardShortcutsLine, IconMiniArrowEndLine, IconFullScreenLine, IconExitFullScreenLine } from '@instructure/ui-icons';
|
|
31
|
+
import { IconA11yLine, IconKeyboardShortcutsLine, IconMiniArrowEndLine, IconFullScreenLine, IconExitFullScreenLine, IconAddLine, IconCheckMarkIndeterminateLine } from '@instructure/ui-icons';
|
|
32
32
|
import formatMessage from '../format-message';
|
|
33
33
|
import ResizeHandle from './ResizeHandle';
|
|
34
34
|
import { FS_ENABLED } from '../util/fullscreenHelpers';
|
|
@@ -62,7 +62,7 @@ StatusBar.propTypes = {
|
|
|
62
62
|
onAI: func
|
|
63
63
|
};
|
|
64
64
|
StatusBar.defaultProps = {
|
|
65
|
-
a11yBadgeColor: '#
|
|
65
|
+
a11yBadgeColor: '#2B7ABC',
|
|
66
66
|
a11yErrorsCount: 0,
|
|
67
67
|
disabledPlugins: []
|
|
68
68
|
};
|
|
@@ -80,16 +80,15 @@ function renderPathString({
|
|
|
80
80
|
}
|
|
81
81
|
function emptyTagIcon() {
|
|
82
82
|
return /*#__PURE__*/React.createElement(SVGIcon, {
|
|
83
|
-
viewBox: "0 0
|
|
84
|
-
|
|
83
|
+
viewBox: "0 0 1920 1920",
|
|
84
|
+
width: "1em",
|
|
85
|
+
height: "1em"
|
|
85
86
|
}, /*#__PURE__*/React.createElement("g", {
|
|
86
|
-
role: "presentation"
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
fontSize: "16"
|
|
92
|
-
}, "</>")));
|
|
87
|
+
role: "presentation",
|
|
88
|
+
transform: "scale(28.7) translate(0, 8)"
|
|
89
|
+
}, /*#__PURE__*/React.createElement("path", {
|
|
90
|
+
d: "M0 29.61L0 25.51L23.71 15.50L23.71 19.87L4.91 27.59L23.71 35.38L23.71 39.75L0 29.61ZM26.46 45.87L36.84 8.86L40.36 8.86L30.00 45.87L26.46 45.87ZM66.80 29.61L43.09 39.75L43.09 35.38L61.87 27.59L43.09 19.87L43.09 15.50L66.80 25.51L66.80 29.61Z"
|
|
91
|
+
})));
|
|
93
92
|
}
|
|
94
93
|
function findFocusable(el) {
|
|
95
94
|
// eslint-disable-next-line react/no-find-dom-node
|
|
@@ -287,10 +286,15 @@ export default function StatusBar(props) {
|
|
|
287
286
|
title: formatMessage('View word and character counts')
|
|
288
287
|
}, wordCount)));
|
|
289
288
|
}
|
|
290
|
-
function renderSection3(
|
|
289
|
+
function renderSection3({
|
|
290
|
+
html_view,
|
|
291
|
+
fullscreen,
|
|
292
|
+
resize_handle,
|
|
293
|
+
a11y_resize_handlers
|
|
294
|
+
}) {
|
|
291
295
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
|
|
292
296
|
className: css(styles.separator)
|
|
293
|
-
}), html_view && renderToggleHtml(), fullscreen && renderFullscreen(), resize_handle && renderResizeHandle());
|
|
297
|
+
}), html_view && renderToggleHtml(), a11y_resize_handlers && renderAccessibleResizeHandle(), fullscreen && renderFullscreen(), resize_handle && renderResizeHandle());
|
|
294
298
|
}
|
|
295
299
|
function descMsg() {
|
|
296
300
|
return preferredHtmlEditor() === RAW_HTML_EDITOR_VIEW ? formatMessage('Shift-O to open the pretty html editor.') : formatMessage('The pretty html editor is not keyboard accessible. Press Shift O to open the raw html editor.');
|
|
@@ -351,7 +355,11 @@ export default function StatusBar(props) {
|
|
|
351
355
|
screenReaderLabel: fullscreen,
|
|
352
356
|
withBackground: false,
|
|
353
357
|
withBorder: false
|
|
354
|
-
},
|
|
358
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
359
|
+
style: {
|
|
360
|
+
fontSize: '0.9rem'
|
|
361
|
+
}
|
|
362
|
+
}, props.rceIsFullscreen ? /*#__PURE__*/React.createElement(IconExitFullScreenLine, null) : /*#__PURE__*/React.createElement(IconFullScreenLine, null)));
|
|
355
363
|
}
|
|
356
364
|
function renderResizeHandle() {
|
|
357
365
|
if (props.rceIsFullscreen) return null;
|
|
@@ -364,10 +372,43 @@ export default function StatusBar(props) {
|
|
|
364
372
|
}
|
|
365
373
|
});
|
|
366
374
|
}
|
|
375
|
+
function renderAccessibleResizeHandle() {
|
|
376
|
+
if (props.rceIsFullscreen) return null;
|
|
377
|
+
const increaseBtnId = 'rce-resize-increase-btn';
|
|
378
|
+
const decreaseBtnId = 'rce-resize-decrease-btn';
|
|
379
|
+
const handleResize = deltaY => {
|
|
380
|
+
props.onResize(null, {
|
|
381
|
+
deltaY,
|
|
382
|
+
deltaX: 0
|
|
383
|
+
});
|
|
384
|
+
};
|
|
385
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(IconButton, {
|
|
386
|
+
"data-btn-id": increaseBtnId,
|
|
387
|
+
"data-testid": increaseBtnId,
|
|
388
|
+
color: "secondary",
|
|
389
|
+
title: formatMessage('Increase Rich Content Area'),
|
|
390
|
+
tabIndex: tabIndexForBtn(increaseBtnId),
|
|
391
|
+
onFocus: () => setFocusedBtnId(increaseBtnId),
|
|
392
|
+
withBackground: false,
|
|
393
|
+
withBorder: false,
|
|
394
|
+
onClick: () => handleResize(5)
|
|
395
|
+
}, /*#__PURE__*/React.createElement(IconAddLine, null)), /*#__PURE__*/React.createElement(IconButton, {
|
|
396
|
+
"data-btn-id": decreaseBtnId,
|
|
397
|
+
"data-testid": decreaseBtnId,
|
|
398
|
+
color: "secondary",
|
|
399
|
+
title: formatMessage('Decrease Rich Content Area'),
|
|
400
|
+
tabIndex: tabIndexForBtn(decreaseBtnId),
|
|
401
|
+
onFocus: () => setFocusedBtnId(decreaseBtnId),
|
|
402
|
+
withBackground: false,
|
|
403
|
+
withBorder: false,
|
|
404
|
+
onClick: () => handleResize(-5)
|
|
405
|
+
}, /*#__PURE__*/React.createElement(IconCheckMarkIndeterminateLine, null)));
|
|
406
|
+
}
|
|
367
407
|
const flexJustify = isHtmlView() ? 'end' : 'start';
|
|
368
408
|
const html_view = isFeature('html_view') && isAvailable('instructure_html_view');
|
|
369
409
|
const fullscreen = isFeature('fullscreen') && isAvailable('instructure_fullscreen');
|
|
370
410
|
const resize_handle = isFeature('resize_handle');
|
|
411
|
+
const a11y_resize_handlers = isFeature('a11y_resize_handlers');
|
|
371
412
|
return /*#__PURE__*/React.createElement(InstUISettingsProvider, {
|
|
372
413
|
theme: {
|
|
373
414
|
componentOverrides: {
|
|
@@ -388,7 +429,12 @@ export default function StatusBar(props) {
|
|
|
388
429
|
}, isHtmlView() ? renderHtmlEditorMessage() : renderPath()), /*#__PURE__*/React.createElement(Flex.Item, {
|
|
389
430
|
role: "toolbar",
|
|
390
431
|
title: formatMessage('Editor Status Bar')
|
|
391
|
-
}, renderIconButtons(), isFeature('word_count') && isAvailable('instructure_wordcount') && renderWordCount(), (html_view || fullscreen || resize_handle) && renderSection3(
|
|
432
|
+
}, renderIconButtons(), isFeature('word_count') && isAvailable('instructure_wordcount') && renderWordCount(), (html_view || fullscreen || resize_handle) && renderSection3({
|
|
433
|
+
html_view,
|
|
434
|
+
fullscreen,
|
|
435
|
+
resize_handle,
|
|
436
|
+
a11y_resize_handlers
|
|
437
|
+
}))));
|
|
392
438
|
}
|
|
393
439
|
const styles = StyleSheet.create({
|
|
394
440
|
separator: {
|
package/es/rce/alertHandler.js
CHANGED
|
@@ -24,6 +24,12 @@
|
|
|
24
24
|
*/
|
|
25
25
|
export class AlertHandler {
|
|
26
26
|
constructor(alertFunc) {
|
|
27
|
+
/**
|
|
28
|
+
* Calls the registered alertFunc assuming one has been set, otherwise
|
|
29
|
+
* it throws.
|
|
30
|
+
*
|
|
31
|
+
* @memberof AlertHandler
|
|
32
|
+
*/
|
|
27
33
|
this.handleAlert = alert => {
|
|
28
34
|
if (this.alertFunc == null) {
|
|
29
35
|
throw new Error('Tried to alert without alertFunc being set first');
|
|
@@ -32,12 +38,5 @@ export class AlertHandler {
|
|
|
32
38
|
};
|
|
33
39
|
this.alertFunc = alertFunc;
|
|
34
40
|
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Calls the registered alertFunc assuming one has been set, otherwise
|
|
38
|
-
* it throws.
|
|
39
|
-
*
|
|
40
|
-
* @memberof AlertHandler
|
|
41
|
-
*/
|
|
42
41
|
}
|
|
43
42
|
export default new AlertHandler();
|
|
@@ -112,13 +112,13 @@ tinymce.PluginManager.add('instructure-ui-icons', function (editor) {
|
|
|
112
112
|
embed: {
|
|
113
113
|
src: `<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
114
114
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.7647 5.21417C13.6694 5.21417 13.5773 5.23988 13.482 5.24631C12.8329 3.36281 11.0795 2 9 2C6.53506 2 4.52435 3.91029 4.28294 6.34234C4.09341 6.31127 3.90176 6.28556 3.70588 6.28556C1.66235 6.28556 0 7.96764 0 10.0354C0 12.1032 1.66235 13.7853 3.70588 13.7853L5 13.7853V12.7139L3.70588 12.7139C2.24682 12.7139 1.05882 11.5129 1.05882 10.0354C1.05882 8.55798 2.24682 7.35695 3.70588 7.35695C4.40259 7.35695 5.06012 7.62908 5.55882 8.12192L6.29894 7.35588C6.00565 7.0666 5.66788 6.84483 5.30894 6.66912C5.38941 4.67419 7.00835 3.07139 9 3.07139C11.0435 3.07139 12.7059 4.75347 12.7059 6.82126C12.7059 7.1491 12.6635 7.47266 12.582 7.78658L13.6059 8.06085C13.7107 7.65801 13.7647 7.24124 13.7647 6.82126C13.7647 6.64019 13.7308 6.4677 13.7118 6.29199C13.7298 6.29199 13.7467 6.28556 13.7647 6.28556C15.516 6.28556 16.9412 7.72765 16.9412 9.49973C16.9412 11.2718 15.516 12.7139 13.7647 12.7139L13 12.7139V13.7853L13.7647 13.7853C16.1005 13.7853 18 11.8632 18 9.49973C18 7.13624 16.1005 5.21417 13.7647 5.21417Z" fill="#2B3B46"/>
|
|
115
|
-
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.72039 10.6479L8.3603 11.1813L6.75882 13.1025L8.36029 15.0239L7.72038 15.5573L5.6748 13.1024L7.72039 10.6479ZM10.2802 10.6479L12.3258 13.1024L10.2802 15.5573L9.64031 15.0239L11.2418 13.1025L9.6403 11.1813L10.2802 10.6479Z" fill="#
|
|
115
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.72039 10.6479L8.3603 11.1813L6.75882 13.1025L8.36029 15.0239L7.72038 15.5573L5.6748 13.1024L7.72039 10.6479ZM10.2802 10.6479L12.3258 13.1024L10.2802 15.5573L9.64031 15.0239L11.2418 13.1025L9.6403 11.1813L10.2802 10.6479Z" fill="#273540"/>
|
|
116
116
|
</svg>`
|
|
117
117
|
},
|
|
118
118
|
buttons: {
|
|
119
119
|
src: `
|
|
120
120
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 18 18">
|
|
121
|
-
<g fill="#
|
|
121
|
+
<g fill="#273540" clip-path="url(#clip0)">
|
|
122
122
|
<path fill-rule="evenodd" d="M.999993 11l.000001 6H6.99999v-6H.999993zm-.99999933 7H7.99999v-8H-.00000668l3.5e-7 8zM4 7c1.65685 0 3-1.34315 3-3S5.65685 1 4 1 1 2.34315 1 4s1.34315 3 3 3zm0 1c2.20914 0 4-1.79086 4-4S6.20914 0 4 0-3e-7 1.79086-3e-7 4 1.79086 8 4 8z" clip-rule="evenodd"/>
|
|
123
123
|
<path d="M12.5 10h1v8h-1v-8z"/>
|
|
124
124
|
<path d="M17 13.5v1H9v-1h8z"/>
|
|
@@ -13,7 +13,7 @@ declare class EquationEditorModal extends React.Component<any, any, any> {
|
|
|
13
13
|
executeCommand: (cmd: any, advancedCmd: any) => void;
|
|
14
14
|
handleModalCancel: () => void;
|
|
15
15
|
handleModalDone: () => void;
|
|
16
|
-
renderMathInAdvancedPreview: import("@instructure/debounce").Debounced
|
|
16
|
+
renderMathInAdvancedPreview: import("@instructure/debounce").Debounced<() => void>;
|
|
17
17
|
setPreviewElementContent(): void;
|
|
18
18
|
toggleAdvanced: () => void;
|
|
19
19
|
toggleAndUpdatePreference: () => void;
|
|
@@ -49,6 +49,9 @@ export default class EquationEditorModal extends Component {
|
|
|
49
49
|
};
|
|
50
50
|
this.previewElement = /*#__PURE__*/React.createRef();
|
|
51
51
|
this.advancedEditor = /*#__PURE__*/React.createRef();
|
|
52
|
+
// ********* //
|
|
53
|
+
// Callbacks //
|
|
54
|
+
// ********* //
|
|
52
55
|
this.executeCommand = (cmd, advancedCmd) => {
|
|
53
56
|
if (this.state.advanced) {
|
|
54
57
|
const insertionText = advancedCmd || cmd;
|
|
@@ -123,6 +126,9 @@ export default class EquationEditorModal extends Component {
|
|
|
123
126
|
this.handleFieldRef = node => {
|
|
124
127
|
this.mathField = node;
|
|
125
128
|
};
|
|
129
|
+
// ******************* //
|
|
130
|
+
// Rendering functions //
|
|
131
|
+
// ******************* //
|
|
126
132
|
this.renderFooter = () => {
|
|
127
133
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Button, {
|
|
128
134
|
"data-testid": "equation-editor-modal-cancel",
|
|
@@ -247,11 +253,6 @@ export default class EquationEditorModal extends Component {
|
|
|
247
253
|
const normalizedLatex = latex.replace(/\s+/, '');
|
|
248
254
|
return containsAdvancedSyntax(normalizedLatex);
|
|
249
255
|
}
|
|
250
|
-
|
|
251
|
-
// ********* //
|
|
252
|
-
// Callbacks //
|
|
253
|
-
// ********* //
|
|
254
|
-
|
|
255
256
|
setPreviewElementContent() {
|
|
256
257
|
if (this.state.workingFormula) {
|
|
257
258
|
this.renderMathInAdvancedPreview();
|
|
@@ -259,11 +260,6 @@ export default class EquationEditorModal extends Component {
|
|
|
259
260
|
this.previewElement.current.innerHTML = '';
|
|
260
261
|
}
|
|
261
262
|
}
|
|
262
|
-
|
|
263
|
-
// ******************* //
|
|
264
|
-
// Rendering functions //
|
|
265
|
-
// ******************* //
|
|
266
|
-
|
|
267
263
|
componentDidMount() {
|
|
268
264
|
this.registerBasicEditorListener();
|
|
269
265
|
this.setPreviewElementContent();
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export default Course;
|
|
2
|
-
declare function Course({ dispatch, onChange, onLoading, onLoaded, canvasOrigin }: {
|
|
3
|
-
dispatch
|
|
4
|
-
onChange
|
|
5
|
-
onLoading
|
|
6
|
-
onLoaded
|
|
2
|
+
declare function Course({ dispatch, onChange, onLoading, onLoaded, canvasOrigin, }: {
|
|
3
|
+
dispatch?: (() => void) | undefined;
|
|
4
|
+
onChange?: (() => void) | undefined;
|
|
5
|
+
onLoading?: (() => void) | undefined;
|
|
6
|
+
onLoaded?: (() => void) | undefined;
|
|
7
7
|
canvasOrigin: any;
|
|
8
8
|
}): React.JSX.Element;
|
|
9
9
|
declare namespace Course {
|
|
@@ -14,16 +14,6 @@ declare namespace Course {
|
|
|
14
14
|
let onLoaded: PropTypes.Requireable<(...args: any[]) => any>;
|
|
15
15
|
let canvasOrigin: PropTypes.Validator<string>;
|
|
16
16
|
}
|
|
17
|
-
namespace defaultProps {
|
|
18
|
-
export function dispatch_1(): void;
|
|
19
|
-
export { dispatch_1 as dispatch };
|
|
20
|
-
export function onChange_1(): void;
|
|
21
|
-
export { onChange_1 as onChange };
|
|
22
|
-
export function onLoading_1(): void;
|
|
23
|
-
export { onLoading_1 as onLoading };
|
|
24
|
-
export function onLoaded_1(): void;
|
|
25
|
-
export { onLoaded_1 as onLoaded };
|
|
26
|
-
}
|
|
27
17
|
}
|
|
28
18
|
import React from 'react';
|
|
29
19
|
import PropTypes from 'prop-types';
|