@pie-element/math-templated 5.0.2-esm.0 → 5.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/esm/configure.js DELETED
@@ -1,1342 +0,0 @@
1
- import * as React from 'react';
2
- import React__default from 'react';
3
- import ReactDOM from 'react-dom';
4
- import debug from 'debug';
5
- import defaults from 'lodash/defaults';
6
- import isArray from 'lodash/isArray';
7
- import { ModelUpdatedEvent, InsertImageEvent, DeleteImageEvent, InsertSoundEvent, DeleteSoundEvent } from '@pie-framework/pie-configure-events';
8
- import PropTypes from 'prop-types';
9
- import { withStyles } from '@material-ui/core/styles';
10
- import Typography from '@material-ui/core/Typography';
11
- import Select from '@material-ui/core/Select';
12
- import MenuItem from '@material-ui/core/MenuItem';
13
- import Info from '@material-ui/icons/Info';
14
- import Tooltip from '@material-ui/core/Tooltip';
15
- import cloneDeep from 'lodash/cloneDeep';
16
- import pick from 'lodash/pick';
17
- import throttle from 'lodash/throttle';
18
- import { InputContainer, dropdown, layout, settings } from '@pie-lib/config-ui';
19
- import EditableHtml, { ALL_PLUGINS } from '@pie-lib/editable-html';
20
- import { MathToolbar } from '@pie-lib/math-toolbar';
21
- import Card from '@material-ui/core/Card';
22
- import CardContent from '@material-ui/core/CardContent';
23
- import Button from '@material-ui/core/Button';
24
- import FormControlLabel from '@material-ui/core/FormControlLabel';
25
- import InputLabel from '@material-ui/core/InputLabel';
26
- import Checkbox from '@material-ui/core/Checkbox';
27
- import IconButton from '@material-ui/core/IconButton';
28
- import Delete from '@material-ui/icons/Delete';
29
- import { color } from '@pie-lib/render-ui';
30
-
31
- function _extends() {
32
- _extends = Object.assign || function (target) {
33
- for (var i = 1; i < arguments.length; i++) {
34
- var source = arguments[i];
35
-
36
- for (var key in source) {
37
- if (Object.prototype.hasOwnProperty.call(source, key)) {
38
- target[key] = source[key];
39
- }
40
- }
41
- }
42
-
43
- return target;
44
- };
45
-
46
- return _extends.apply(this, arguments);
47
- }
48
-
49
- class Response extends React.Component {
50
- constructor(props) {
51
- super(props);
52
-
53
- this.onChange = name => evt => {
54
- const {
55
- response,
56
- onResponseChange,
57
- responseKey
58
- } = this.props;
59
-
60
- const newResponse = _extends({}, response);
61
-
62
- newResponse[name] = evt.target.value;
63
- onResponseChange(newResponse, responseKey);
64
- };
65
-
66
- this.onConfigChanged = name => evt => {
67
- const {
68
- response,
69
- onResponseChange,
70
- responseKey
71
- } = this.props;
72
-
73
- const newResponse = _extends({}, response);
74
-
75
- newResponse[name] = evt.target.checked;
76
- onResponseChange(newResponse, responseKey);
77
- };
78
-
79
- this.onLiteralOptionsChange = name => () => {
80
- const {
81
- response,
82
- onResponseChange,
83
- responseKey
84
- } = this.props;
85
-
86
- const newResponse = _extends({}, response);
87
-
88
- newResponse[name] = !response[name];
89
- onResponseChange(newResponse, responseKey);
90
- };
91
-
92
- this.onAnswerChange = answer => {
93
- const {
94
- response,
95
- onResponseChange,
96
- responseKey
97
- } = this.props;
98
-
99
- const newResponse = _extends({}, response);
100
-
101
- newResponse.answer = answer;
102
- onResponseChange(newResponse, responseKey);
103
- };
104
-
105
- this.onAlternateAnswerChange = alternateId => answer => {
106
- const {
107
- response,
108
- onResponseChange,
109
- responseKey
110
- } = this.props;
111
-
112
- const newResponse = _extends({}, response);
113
-
114
- newResponse.alternates[alternateId] = answer;
115
- onResponseChange(newResponse, responseKey);
116
- };
117
-
118
- this.onAddAlternate = () => {
119
- const {
120
- response,
121
- onResponseChange,
122
- responseKey
123
- } = this.props;
124
- const {
125
- alternateIdCounter
126
- } = this.state;
127
-
128
- const newResponse = _extends({}, response);
129
-
130
- if (!newResponse.alternates) {
131
- newResponse.alternates = {};
132
- }
133
-
134
- newResponse.alternates[alternateIdCounter] = '';
135
- onResponseChange(newResponse, responseKey);
136
- this.setState({
137
- alternateIdCounter: alternateIdCounter + 1
138
- });
139
- };
140
-
141
- this.onRemoveAlternate = alternateId => () => {
142
- const {
143
- response,
144
- onResponseChange,
145
- responseKey
146
- } = this.props;
147
-
148
- const newResponse = _extends({}, response);
149
-
150
- delete newResponse.alternates[alternateId];
151
- onResponseChange(newResponse, responseKey);
152
- this.setState(state => ({
153
- showKeypad: _extends({}, state.showKeypad, {
154
- openCount: !state.showKeypad[alternateId] ? state.showKeypad.openCount : state.showKeypad.openCount - 1
155
- })
156
- }));
157
- };
158
-
159
- this.onDone = () => {
160
- const {
161
- onResponseDone
162
- } = this.props;
163
- this.setState(state => ({
164
- showKeypad: _extends({}, state.showKeypad, {
165
- openCount: state.showKeypad.openCount - 1,
166
- main: false
167
- })
168
- }));
169
- onResponseDone();
170
- };
171
-
172
- this.onFocus = () => {
173
- this.setState(state => ({
174
- showKeypad: _extends({}, state.showKeypad, {
175
- openCount: !state.showKeypad.main ? state.showKeypad.openCount + 1 : state.showKeypad.openCount,
176
- main: true
177
- })
178
- }));
179
- };
180
-
181
- this.onAlternateFocus = alternateId => () => {
182
- this.setState(state => ({
183
- showKeypad: _extends({}, state.showKeypad, {
184
- openCount: !state.showKeypad[alternateId] ? state.showKeypad.openCount + 1 : state.showKeypad.openCount,
185
- [alternateId]: true
186
- })
187
- }));
188
- };
189
-
190
- this.onAlternateDone = alternateId => () => {
191
- this.setState(state => ({
192
- showKeypad: _extends({}, state.showKeypad, {
193
- openCount: state.showKeypad.openCount - 1,
194
- [alternateId]: false
195
- })
196
- }));
197
- };
198
-
199
- const {
200
- response: {
201
- alternates
202
- } = {}
203
- } = props || {};
204
- const alternatesLength = Object.keys(alternates || {}).length;
205
- this.state = {
206
- alternateIdCounter: alternatesLength + 1,
207
- showKeypad: {
208
- openCount: 0,
209
- main: false
210
- }
211
- };
212
- }
213
-
214
- render() {
215
- const {
216
- classes,
217
- mode,
218
- responseKey,
219
- response,
220
- cAllowTrailingZeros,
221
- cIgnoreOrder,
222
- error
223
- } = this.props;
224
- const {
225
- showKeypad
226
- } = this.state;
227
- const {
228
- validation,
229
- answer,
230
- alternates,
231
- ignoreOrder,
232
- allowTrailingZeros
233
- } = response;
234
- const hasAlternates = Object.keys(alternates || {}).length > 0;
235
- const classNames = {
236
- editor: classes.responseEditor,
237
- mathToolbar: classes.mathToolbar
238
- };
239
- const styles = {
240
- minHeight: `${showKeypad.openCount > 0 ? 430 : 230}px`
241
- }; // add 1 to index to display R 1 instead of R 0
242
-
243
- const keyToDisplay = `R ${parseInt(responseKey) + 1}`;
244
- return /*#__PURE__*/React.createElement(Card, {
245
- className: classes.responseContainer,
246
- style: styles
247
- }, /*#__PURE__*/React.createElement(CardContent, {
248
- className: classes.cardContent
249
- }, /*#__PURE__*/React.createElement("div", {
250
- className: classes.titleBar
251
- }, /*#__PURE__*/React.createElement(Typography, {
252
- className: classes.title,
253
- component: "div"
254
- }, "Response for ", /*#__PURE__*/React.createElement("div", {
255
- className: classes.responseBox
256
- }, keyToDisplay)), /*#__PURE__*/React.createElement(InputContainer, {
257
- label: "Validation",
258
- className: classes.selectContainer
259
- }, /*#__PURE__*/React.createElement(Select, {
260
- className: classes.select,
261
- onChange: this.onChange('validation'),
262
- value: validation || 'literal'
263
- }, /*#__PURE__*/React.createElement(MenuItem, {
264
- value: "literal"
265
- }, "Literal Validation"), /*#__PURE__*/React.createElement(MenuItem, {
266
- value: "symbolic"
267
- }, "Symbolic Validation")))), validation === 'literal' && /*#__PURE__*/React.createElement("div", {
268
- className: classes.flexContainer
269
- }, cAllowTrailingZeros.enabled && /*#__PURE__*/React.createElement(FormControlLabel, {
270
- label: cAllowTrailingZeros.label,
271
- control: /*#__PURE__*/React.createElement(Checkbox, {
272
- className: classes.customColor,
273
- checked: allowTrailingZeros,
274
- onChange: this.onLiteralOptionsChange('allowTrailingZeros')
275
- })
276
- }), cIgnoreOrder.enabled && /*#__PURE__*/React.createElement(FormControlLabel, {
277
- label: cIgnoreOrder.label,
278
- control: /*#__PURE__*/React.createElement(Checkbox, {
279
- className: classes.customColor,
280
- checked: ignoreOrder,
281
- onChange: this.onLiteralOptionsChange('ignoreOrder')
282
- })
283
- })), /*#__PURE__*/React.createElement("div", {
284
- className: classes.inputContainer
285
- }, /*#__PURE__*/React.createElement(InputLabel, null, "Correct Answer"), /*#__PURE__*/React.createElement(MathToolbar, {
286
- keypadMode: mode,
287
- classNames: classNames,
288
- controlledKeypad: true,
289
- showKeypad: showKeypad.main,
290
- latex: answer || '',
291
- onChange: this.onAnswerChange,
292
- onFocus: this.onFocus,
293
- onDone: this.onDone,
294
- error: error && error.answer
295
- }), error && error.answer ? /*#__PURE__*/React.createElement("div", {
296
- className: classes.errorText
297
- }, error.answer) : null), hasAlternates && Object.keys(alternates).map((alternateId, altIdx) => /*#__PURE__*/React.createElement("div", {
298
- className: classes.inputContainer,
299
- key: alternateId
300
- }, /*#__PURE__*/React.createElement(InputLabel, null, "Alternate", Object.keys(alternates).length > 1 ? ` ${altIdx + 1}` : ''), /*#__PURE__*/React.createElement("div", {
301
- className: classes.alternateBar
302
- }, /*#__PURE__*/React.createElement(MathToolbar, {
303
- classNames: classNames,
304
- controlledKeypad: true,
305
- keypadMode: mode,
306
- showKeypad: showKeypad[alternateId] || false,
307
- latex: alternates[alternateId] || '',
308
- onChange: this.onAlternateAnswerChange(alternateId),
309
- onFocus: this.onAlternateFocus(alternateId),
310
- onDone: this.onAlternateDone(alternateId),
311
- error: error && error[alternateId]
312
- }), /*#__PURE__*/React.createElement(IconButton, {
313
- className: classes.removeAlternateButton,
314
- onClick: this.onRemoveAlternate(alternateId)
315
- }, /*#__PURE__*/React.createElement(Delete, null))), error && error[alternateId] ? /*#__PURE__*/React.createElement("div", {
316
- className: classes.errorText
317
- }, error[alternateId]) : null)), /*#__PURE__*/React.createElement(Button, {
318
- className: classes.alternateButton,
319
- type: "primary",
320
- onClick: this.onAddAlternate
321
- }, "ADD ALTERNATE")));
322
- }
323
-
324
- }
325
- Response.propTypes = {
326
- classes: PropTypes.object.isRequired,
327
- defaultResponse: PropTypes.bool,
328
- error: PropTypes.object,
329
- mode: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
330
- onResponseChange: PropTypes.func.isRequired,
331
- onResponseDone: PropTypes.func.isRequired,
332
- response: PropTypes.object.isRequired,
333
- cIgnoreOrder: PropTypes.object.isRequired,
334
- cAllowTrailingZeros: PropTypes.object.isRequired,
335
- responseKey: PropTypes.number.isRequired
336
- };
337
- Response.defaultProps = {
338
- defaultResponse: false,
339
- mode: '8'
340
- };
341
-
342
- const styles = theme => ({
343
- responseContainer: {
344
- marginBottom: theme.spacing.unit * 2.5,
345
- width: '100%',
346
- minWidth: '548px',
347
- border: `1px solid ${theme.palette.grey[700]}`,
348
- display: 'flex',
349
- flexDirection: 'column',
350
- justifyContent: 'space-between'
351
- },
352
- cardContent: {
353
- paddingBottom: `${theme.spacing.unit * 2}px !important`
354
- },
355
- title: {
356
- fontWeight: 700,
357
- fontSize: '1.2rem',
358
- flex: 3
359
- },
360
- selectContainer: {
361
- flex: 2
362
- },
363
- inputContainer: {
364
- marginBottom: theme.spacing.unit * 2
365
- },
366
- titleBar: {
367
- display: 'flex',
368
- alignItems: 'center',
369
- justifyContent: 'space-between'
370
- },
371
- responseEditor: {
372
- display: 'flex',
373
- alignItems: 'center',
374
- justifyContent: 'center',
375
- width: '100%',
376
- minWidth: '500px',
377
- maxWidth: '900px',
378
- height: 'auto',
379
- minHeight: '40px'
380
- },
381
- mathToolbar: {
382
- width: '100%'
383
- },
384
- alternateButton: {
385
- border: `1px solid ${theme.palette.grey['A100']}`
386
- },
387
- removeAlternateButton: {
388
- marginLeft: theme.spacing.unit
389
- },
390
- errorText: {
391
- fontSize: theme.typography.fontSize - 2,
392
- color: theme.palette.error.main,
393
- paddingTop: theme.spacing.unit
394
- },
395
- responseBox: {
396
- background: theme.palette.grey['A100'],
397
- color: theme.palette.grey['A700'],
398
- display: 'inline',
399
- minWidth: '50px',
400
- padding: '8px',
401
- border: '1px solid #C0C3CF'
402
- },
403
- alternateBar: {
404
- display: 'flex',
405
- justifyContent: 'space-between',
406
- alignItems: 'center'
407
- },
408
- customColor: {
409
- color: `${color.tertiary()} !important`
410
- }
411
- });
412
-
413
- var Response$1 = withStyles(styles)(Response);
414
-
415
- // do not remove \t from \times, \triangle, \tan, \theta or \therefore
416
- const tSymbols = 'imes|riangle|an|heta|herefore'; // do not remove \n from \nthroot, \nparallel, \ncong, \napprox, \neq, \ne or \nsim
417
-
418
- const nSymbols = 'throot|parallel|cong|approx|eq|e|sim'; // match all \t and \n that are not part of math symbols that starts with \t or \n
419
-
420
- const matchTabAndNewLine = new RegExp(`(\\t(?!${tSymbols}))|(\\n(?!${nSymbols}))|(\\\\t(?!${tSymbols}))|(\\\\n(?!${nSymbols}))`, 'g');
421
- const removeUnwantedCharacters = markup => markup.replace(matchTabAndNewLine, '').replace(/\\"/g, '"').replace(/\\\//g, '/');
422
-
423
- const createElementFromHTML$1 = (htmlString = '') => {
424
- const div = document.createElement('div');
425
- div.innerHTML = htmlString.trim();
426
- return div;
427
- };
428
-
429
- const processMarkup = markup => {
430
- const newMarkup = removeUnwantedCharacters(markup || '');
431
- const slateMarkup = createElementFromHTML$1(newMarkup || '');
432
- slateMarkup.querySelectorAll('[data-type="math_templated"]').forEach(s => s.replaceWith(`{{${s.dataset.index}}}`));
433
- return slateMarkup.innerHTML;
434
- };
435
- const REGEX = /\{\{(\d+)\}\}/g;
436
- const createSlateMarkup = (markup, responses) => {
437
- if (!markup) {
438
- return '';
439
- }
440
-
441
- const newMarkup = removeUnwantedCharacters(markup);
442
- return newMarkup.replace(REGEX, (match, groupIndex) => {
443
- var _responses$groupIndex;
444
-
445
- const responseValue = ((_responses$groupIndex = responses[groupIndex]) == null ? void 0 : _responses$groupIndex.answer) || '';
446
- return `<span data-type="math_templated" data-index="${groupIndex}" data-value="${responseValue}"></span>`;
447
- });
448
- };
449
-
450
- const generateValidationMessage = config => {
451
- const {
452
- maxResponseAreas
453
- } = config;
454
- const responseAreasMessage = '\nCorrect answers should not be blank.' + '\nEach answer defined for a response area should be unique.' + '\nThere should be at least 1 ' + (maxResponseAreas ? `and at most ${maxResponseAreas} ` : '') + 'response area' + (maxResponseAreas ? 's' : '') + ' defined.';
455
- return 'Validation requirements:' + responseAreasMessage;
456
- };
457
-
458
- const {
459
- Panel,
460
- toggle
461
- } = settings;
462
-
463
- const createElementFromHTML = htmlString => {
464
- const div = document.createElement('div');
465
- div.innerHTML = htmlString.trim();
466
- return div;
467
- };
468
-
469
- class Design extends React__default.Component {
470
- constructor(...args) {
471
- super(...args);
472
- this.state = {};
473
-
474
- this.handleChange = (key, value) => {
475
- const {
476
- onModelChanged,
477
- model
478
- } = this.props;
479
- const updatedModel = cloneDeep(model);
480
- updatedModel[key] = value;
481
- onModelChanged(updatedModel);
482
- };
483
-
484
- this.onResponseChange = (response, index) => {
485
- const {
486
- model,
487
- onModelChanged
488
- } = this.props;
489
-
490
- const newModel = _extends({}, model);
491
-
492
- newModel.responses[index] = response;
493
- onModelChanged(newModel);
494
- };
495
-
496
- this.onResponseDone = () => {
497
- const {
498
- model,
499
- onModelChanged
500
- } = this.props;
501
- onModelChanged(_extends({}, model, {
502
- slateMarkup: createSlateMarkup(model.markup, model.responses)
503
- }));
504
- };
505
-
506
- this.onChangeResponse = (index, newVal) => {
507
- const {
508
- model,
509
- onModelChanged
510
- } = this.props;
511
- const {
512
- responses
513
- } = model;
514
-
515
- if (!responses[index]) {
516
- responses[index] = [{
517
- answer: newVal || '',
518
- id: 'response' + index,
519
- allowSpaces: true
520
- }];
521
- } else {
522
- responses[index][0].answer = newVal || '';
523
- }
524
-
525
- onModelChanged(_extends({}, model, {
526
- responses
527
- }));
528
- };
529
-
530
- this.onResponsesChanged = responses => {
531
- this.props.onModelChanged(_extends({}, this.props.model, {
532
- responses
533
- }));
534
- };
535
-
536
- this.onChange = markup => {
537
- const {
538
- model: {
539
- responses,
540
- validationDefault,
541
- allowTrailingZerosDefault,
542
- ignoreOrderDefault
543
- },
544
- onModelChanged
545
- } = this.props;
546
- const newResponses = {};
547
- const domMarkup = createElementFromHTML(markup);
548
- const responseAreas = domMarkup.querySelectorAll('[data-type="math_templated"]');
549
- responseAreas.forEach((element, index) => {
550
- const {
551
- value,
552
- index: dataIndex
553
- } = element.dataset;
554
-
555
- if (!value) {
556
- element.dataset.value = '';
557
- }
558
-
559
- newResponses[index] = responses[dataIndex] || {
560
- allowSpaces: true,
561
- validation: validationDefault || 'symbolic',
562
- allowTrailingZeros: allowTrailingZerosDefault || false,
563
- ignoreOrder: ignoreOrderDefault || false,
564
- answer: '',
565
- alternates: {}
566
- };
567
- element.dataset.index = index.toString();
568
- });
569
- console.log('newResponses', newResponses);
570
- const processedMarkup = processMarkup(markup);
571
-
572
- const callback = () => onModelChanged(_extends({}, this.props.model, {
573
- slateMarkup: domMarkup.innerHTML,
574
- responses: newResponses,
575
- markup: processedMarkup
576
- }));
577
-
578
- this.setState({
579
- cachedResponses: undefined
580
- }, callback);
581
- };
582
-
583
- this.onHandleAreaChange = throttle(nodes => {
584
- const {
585
- model: {
586
- responses
587
- },
588
- onModelChanged
589
- } = this.props;
590
- const {
591
- cachedResponses
592
- } = this.state;
593
-
594
- if (!nodes) {
595
- return;
596
- }
597
-
598
- const newChoices = responses ? cloneDeep(responses) : {};
599
- const newCachedResponses = cachedResponses ? cloneDeep(cachedResponses) : {};
600
- nodes.forEach(node => {
601
- const keyForNode = node.data.get('index');
602
-
603
- if (!newChoices[keyForNode] && newCachedResponses[keyForNode]) {
604
- Object.assign(newChoices, pick(newCachedResponses, keyForNode));
605
-
606
- if (newCachedResponses.hasOwnProperty(keyForNode)) {
607
- delete newCachedResponses[keyForNode];
608
- }
609
- } else {
610
- Object.assign(newCachedResponses, pick(newChoices, keyForNode));
611
-
612
- if (newChoices.hasOwnProperty(keyForNode)) {
613
- delete newChoices[keyForNode];
614
- }
615
- }
616
- });
617
-
618
- const callback = () => onModelChanged(_extends({}, this.props.model, {
619
- responses: newChoices
620
- }));
621
-
622
- this.setState({
623
- cachedResponses: newCachedResponses
624
- }, callback);
625
- }, 500, {
626
- trailing: false,
627
- leading: true
628
- });
629
-
630
- this.onBlur = e => {
631
- const {
632
- relatedTarget,
633
- currentTarget
634
- } = e || {};
635
-
636
- function getParentWithRoleTooltip(element, depth = 0) {
637
- // only run this max 16 times
638
- if (!element || depth >= 16) return null;
639
- const parent = element.offsetParent;
640
- if (!parent) return null;
641
-
642
- if (parent.getAttribute('role') === 'tooltip') {
643
- return parent;
644
- }
645
-
646
- return getParentWithRoleTooltip(parent, depth + 1);
647
- }
648
-
649
- function getDeepChildDataKeypad(element, depth = 0) {
650
- var _element$children;
651
-
652
- // only run this max 4 times
653
- if (!element || depth >= 4) return null;
654
- const child = element == null ? void 0 : (_element$children = element.children) == null ? void 0 : _element$children[0];
655
- if (!child) return null;
656
-
657
- if (child.attributes && child.attributes['data-keypad']) {
658
- return child;
659
- }
660
-
661
- return getDeepChildDataKeypad(child, depth + 1);
662
- }
663
-
664
- const parentWithTooltipRole = getParentWithRoleTooltip(relatedTarget);
665
- const childWithDataKeypad = parentWithTooltipRole ? getDeepChildDataKeypad(parentWithTooltipRole) : null;
666
-
667
- if (!relatedTarget || !currentTarget || !(childWithDataKeypad != null && childWithDataKeypad.attributes['data-keypad'])) {
668
- this.setState({
669
- activeAnswerBlock: ''
670
- });
671
- }
672
- };
673
- }
674
-
675
- componentDidMount() {
676
- const {
677
- model: {
678
- slateMarkup
679
- }
680
- } = this.props;
681
- this.setState({
682
- markup: slateMarkup
683
- });
684
- }
685
-
686
- render() {
687
- const {
688
- classes,
689
- configuration,
690
- imageSupport,
691
- model,
692
- onConfigurationChanged,
693
- onModelChanged,
694
- uploadSoundSupport
695
- } = this.props;
696
- const {
697
- baseInputConfiguration = {},
698
- contentDimensions = {},
699
- prompt = {},
700
- rationale = {},
701
- settingsPanelDisabled,
702
- teacherInstructions = {},
703
- language = {},
704
- languageChoices = {},
705
- spellCheck = {},
706
- playerSpellCheck = {},
707
- maxImageWidth = {},
708
- maxImageHeight = {},
709
- mathMlOptions = {},
710
- template = {},
711
- editSource = {},
712
- ignoreOrder: cIgnoreOrder = {},
713
- allowTrailingZeros: cAllowTrailingZeros = {},
714
- partialScoring = {},
715
- maxResponseAreas
716
- } = configuration || {};
717
- const {
718
- errors,
719
- extraCSSRules,
720
- promptEnabled,
721
- rationaleEnabled,
722
- spellCheckEnabled,
723
- teacherInstructionsEnabled,
724
- toolbarEditorPosition,
725
- responses,
726
- equationEditor
727
- } = model || {};
728
- const {
729
- prompt: promptError,
730
- rationale: rationaleError,
731
- responseAreas: responseAreasError,
732
- teacherInstructions: teacherInstructionsError,
733
- responses: responsesErrors = {}
734
- } = errors || {};
735
- const validationMessage = generateValidationMessage(configuration);
736
- const panelSettings = {
737
- 'language.enabled': language.settings && toggle(language.label, true),
738
- language: language.settings && language.enabled && dropdown(languageChoices.label, languageChoices.options)
739
- };
740
- const panelProperties = {
741
- teacherInstructionsEnabled: teacherInstructions.settings && toggle(teacherInstructions.label),
742
- rationaleEnabled: rationale.settings && toggle(rationale.label),
743
- promptEnabled: prompt.settings && toggle(prompt.label),
744
- spellCheckEnabled: spellCheck.settings && toggle(spellCheck.label),
745
- playerSpellCheckEnabled: playerSpellCheck.settings && toggle(playerSpellCheck.label),
746
- 'editSource.enabled': (editSource == null ? void 0 : editSource.settings) && toggle(editSource.label, true),
747
- partialScoring: partialScoring.settings && toggle(partialScoring.label)
748
- };
749
- const defaultImageMaxWidth = maxImageWidth && maxImageWidth.prompt;
750
- const defaultImageMaxHeight = maxImageHeight && maxImageHeight.prompt;
751
- const toolbarOpts = {
752
- position: toolbarEditorPosition === 'top' ? 'top' : 'bottom'
753
- };
754
-
755
- const getPluginProps = (props = {}, baseInputConfiguration = {}) => _extends({}, baseInputConfiguration, props);
756
-
757
- return /*#__PURE__*/React__default.createElement(layout.ConfigLayout, {
758
- extraCSSRules: extraCSSRules,
759
- dimensions: contentDimensions,
760
- hideSettings: settingsPanelDisabled,
761
- settings: /*#__PURE__*/React__default.createElement(Panel, {
762
- model: model,
763
- configuration: configuration,
764
- onChangeModel: updatedModel => onModelChanged(updatedModel),
765
- onChangeConfiguration: onConfigurationChanged,
766
- groups: {
767
- Settings: panelSettings,
768
- Properties: panelProperties
769
- }
770
- })
771
- }, teacherInstructionsEnabled && /*#__PURE__*/React__default.createElement(InputContainer, {
772
- label: teacherInstructions.label,
773
- className: classes.promptHolder
774
- }, /*#__PURE__*/React__default.createElement(EditableHtml, {
775
- className: classes.prompt,
776
- markup: model.teacherInstructions || '',
777
- onChange: value => this.handleChange('teacherInstructions', value),
778
- imageSupport: imageSupport,
779
- nonEmpty: false,
780
- error: teacherInstructionsError,
781
- toolbarOpts: toolbarOpts,
782
- pluginProps: getPluginProps(teacherInstructions == null ? void 0 : teacherInstructions.inputConfiguration, baseInputConfiguration),
783
- spellCheck: spellCheckEnabled,
784
- maxImageWidth: maxImageWidth && maxImageWidth.teacherInstructions || defaultImageMaxWidth,
785
- maxImageHeight: maxImageHeight && maxImageHeight.teacherInstructions || defaultImageMaxHeight,
786
- uploadSoundSupport: uploadSoundSupport,
787
- languageCharactersProps: [{
788
- language: 'spanish'
789
- }, {
790
- language: 'special'
791
- }],
792
- mathMlOptions: mathMlOptions
793
- }), teacherInstructionsError && /*#__PURE__*/React__default.createElement("div", {
794
- className: classes.errorText
795
- }, teacherInstructionsError)), promptEnabled && /*#__PURE__*/React__default.createElement(InputContainer, {
796
- label: prompt.label,
797
- className: classes.promptHolder
798
- }, /*#__PURE__*/React__default.createElement(EditableHtml, {
799
- className: classes.prompt,
800
- markup: model.prompt,
801
- onChange: value => this.handleChange('prompt', value),
802
- imageSupport: imageSupport,
803
- nonEmpty: false,
804
- disableUnderline: true,
805
- error: promptError,
806
- toolbarOpts: toolbarOpts,
807
- pluginProps: getPluginProps(teacherInstructions == null ? void 0 : teacherInstructions.inputConfiguration, baseInputConfiguration),
808
- spellCheck: spellCheckEnabled,
809
- maxImageWidth: defaultImageMaxWidth,
810
- maxImageHeight: defaultImageMaxHeight,
811
- uploadSoundSupport: uploadSoundSupport,
812
- languageCharactersProps: [{
813
- language: 'spanish'
814
- }, {
815
- language: 'special'
816
- }],
817
- mathMlOptions: mathMlOptions
818
- }), promptError && /*#__PURE__*/React__default.createElement("div", {
819
- className: classes.errorText
820
- }, promptError)), /*#__PURE__*/React__default.createElement("div", {
821
- className: classes.tooltipContainer
822
- }, /*#__PURE__*/React__default.createElement(Typography, {
823
- className: classes.title,
824
- component: 'div'
825
- }, "Response Template"), /*#__PURE__*/React__default.createElement(Tooltip, {
826
- classes: {
827
- tooltip: classes.tooltip
828
- },
829
- disableFocusListener: true,
830
- disableTouchListener: true,
831
- placement: 'right',
832
- title: validationMessage
833
- }, /*#__PURE__*/React__default.createElement(Info, {
834
- fontSize: 'small',
835
- color: 'primary'
836
- }))), /*#__PURE__*/React__default.createElement(EditableHtml, {
837
- activePlugins: ALL_PLUGINS,
838
- toolbarOpts: {
839
- position: 'top'
840
- },
841
- spellCheck: spellCheckEnabled,
842
- pluginProps: getPluginProps(template == null ? void 0 : template.inputConfiguration, baseInputConfiguration),
843
- responseAreaProps: {
844
- type: 'math-templated',
845
- respAreaToolbar: null,
846
- error: () => responsesErrors,
847
- onHandleAreaChange: this.onHandleAreaChange,
848
- maxResponseAreas: maxResponseAreas
849
- },
850
- className: classes.markup,
851
- markup: model.slateMarkup,
852
- onChange: this.onChange,
853
- imageSupport: imageSupport,
854
- disableImageAlignmentButtons: true,
855
- onBlur: this.onBlur,
856
- disabled: false,
857
- highlightShape: false,
858
- error: responseAreasError,
859
- uploadSoundSupport: uploadSoundSupport,
860
- languageCharactersProps: [{
861
- language: 'spanish'
862
- }, {
863
- language: 'special'
864
- }],
865
- mathMlOptions: mathMlOptions
866
- }), responseAreasError && /*#__PURE__*/React__default.createElement("div", {
867
- className: classes.responseAreaError
868
- }, responseAreasError), /*#__PURE__*/React__default.createElement(Typography, {
869
- className: classes.title
870
- }, "Define Response"), /*#__PURE__*/React__default.createElement(InputContainer, {
871
- label: "Response Template Equation Editor",
872
- className: classes.selectContainer
873
- }, /*#__PURE__*/React__default.createElement(Select, {
874
- className: classes.select,
875
- onChange: event => this.handleChange('equationEditor', event.target.value),
876
- value: equationEditor
877
- }, /*#__PURE__*/React__default.createElement(MenuItem, {
878
- value: "non-negative-integers"
879
- }, "Numeric - Non-Negative Integers"), /*#__PURE__*/React__default.createElement(MenuItem, {
880
- value: "integers"
881
- }, "Numeric - Integers"), /*#__PURE__*/React__default.createElement(MenuItem, {
882
- value: "decimals"
883
- }, "Numeric - Decimals"), /*#__PURE__*/React__default.createElement(MenuItem, {
884
- value: "fractions"
885
- }, "Numeric - Fractions"), /*#__PURE__*/React__default.createElement(MenuItem, {
886
- value: 1
887
- }, "Grade 1 - 2"), /*#__PURE__*/React__default.createElement(MenuItem, {
888
- value: 3
889
- }, "Grade 3 - 5"), /*#__PURE__*/React__default.createElement(MenuItem, {
890
- value: 6
891
- }, "Grade 6 - 7"), /*#__PURE__*/React__default.createElement(MenuItem, {
892
- value: 8
893
- }, "Grade 8 - HS"), /*#__PURE__*/React__default.createElement(MenuItem, {
894
- value: 'geometry'
895
- }, "Geometry"), /*#__PURE__*/React__default.createElement(MenuItem, {
896
- value: 'advanced-algebra'
897
- }, "Advanced Algebra"), /*#__PURE__*/React__default.createElement(MenuItem, {
898
- value: 'statistics'
899
- }, "Statistics"), /*#__PURE__*/React__default.createElement(MenuItem, {
900
- value: 'item-authoring'
901
- }, "Item Authoring"))), Object.keys(responses || {}).map((responseKey, idx) => {
902
- const response = responses[idx];
903
-
904
- if (response) {
905
- return /*#__PURE__*/React__default.createElement(Response$1, {
906
- key: idx,
907
- responseKey: idx,
908
- mode: equationEditor,
909
- response: response,
910
- onResponseChange: this.onResponseChange,
911
- onResponseDone: this.onResponseDone,
912
- index: idx,
913
- cIgnoreOrder: cIgnoreOrder,
914
- cAllowTrailingZeros: cAllowTrailingZeros,
915
- error: responsesErrors && responsesErrors[idx]
916
- });
917
- }
918
-
919
- return null;
920
- }), rationaleEnabled && /*#__PURE__*/React__default.createElement(InputContainer, {
921
- label: rationale.label,
922
- className: classes.promptHolder
923
- }, /*#__PURE__*/React__default.createElement(EditableHtml, {
924
- className: classes.prompt,
925
- markup: model.rationale || '',
926
- onChange: value => this.handleChange('rationale', value),
927
- imageSupport: imageSupport,
928
- nonEmpty: false,
929
- error: rationaleError,
930
- toolbarOpts: toolbarOpts,
931
- pluginProps: getPluginProps(rationale == null ? void 0 : rationale.inputConfiguration, _extends({}, baseInputConfiguration, {
932
- math: {
933
- controlledKeypadMode: false
934
- }
935
- })),
936
- spellCheck: spellCheckEnabled,
937
- maxImageWidth: maxImageWidth && maxImageWidth.rationale || defaultImageMaxWidth,
938
- maxImageHeight: maxImageHeight && maxImageHeight.rationale || defaultImageMaxHeight,
939
- uploadSoundSupport: uploadSoundSupport,
940
- languageCharactersProps: [{
941
- language: 'spanish'
942
- }, {
943
- language: 'special'
944
- }],
945
- mathMlOptions: mathMlOptions
946
- }), rationaleError && /*#__PURE__*/React__default.createElement("div", {
947
- className: classes.errorText
948
- }, rationaleError)));
949
- }
950
-
951
- }
952
- Design.propTypes = {
953
- model: PropTypes.object.isRequired,
954
- configuration: PropTypes.object.isRequired,
955
- classes: PropTypes.object.isRequired,
956
- onModelChanged: PropTypes.func.isRequired,
957
- onConfigurationChanged: PropTypes.func.isRequired,
958
- imageSupport: PropTypes.shape({
959
- add: PropTypes.func.isRequired,
960
- delete: PropTypes.func.isRequired
961
- }),
962
- uploadSoundSupport: PropTypes.object
963
- };
964
- var Main = withStyles(theme => ({
965
- promptHolder: {
966
- width: '100%',
967
- paddingTop: theme.spacing.unit * 2,
968
- marginBottom: theme.spacing.unit * 2
969
- },
970
- prompt: {
971
- width: '100%'
972
- },
973
- errorText: {
974
- color: theme.palette.error.main,
975
- fontSize: '0.75rem',
976
- marginTop: theme.spacing.unit
977
- },
978
- responseAreaError: {
979
- color: theme.palette.error.main,
980
- fontSize: '0.75rem',
981
- marginBottom: theme.spacing.unit
982
- },
983
- markup: {
984
- width: '100%',
985
- marginTop: theme.spacing.unit * 2,
986
- marginBottom: theme.spacing.unit * 3
987
- },
988
- selectContainer: {
989
- width: '100%',
990
- marginTop: theme.spacing.unit * 2
991
- },
992
- select: {
993
- width: '100%'
994
- },
995
- title: {
996
- fontSize: theme.typography.fontSize * 1.25,
997
- fontWeight: 'bold'
998
- },
999
- tooltipContainer: {
1000
- display: 'flex',
1001
- alignItems: 'center',
1002
- gap: '8px'
1003
- },
1004
- tooltip: {
1005
- fontSize: theme.typography.fontSize - 2,
1006
- whiteSpace: 'pre',
1007
- maxWidth: '500px'
1008
- }
1009
- }))(Design);
1010
-
1011
- // Should be exactly the same as controller/defaults.js
1012
- var sensibleDefaults = {
1013
- model: {
1014
- allowTrailingZerosDefault: false,
1015
- equationEditor: '8',
1016
- ignoreOrderDefault: false,
1017
- markup: '',
1018
- playerSpellCheckEnabled: true,
1019
- prompt: '',
1020
- promptEnabled: true,
1021
- rationale: '',
1022
- rationaleEnabled: true,
1023
- responses: {},
1024
- spellCheckEnabled: true,
1025
- teacherInstructions: '',
1026
- teacherInstructionsEnabled: true,
1027
- toolbarEditorPosition: 'bottom',
1028
- validationDefault: 'literal'
1029
- },
1030
- configuration: {
1031
- ignoreOrder: {
1032
- settings: false,
1033
- label: 'Ignore Order',
1034
- enabled: true
1035
- },
1036
- allowTrailingZeros: {
1037
- settings: false,
1038
- label: 'Allow Trailing Zeros',
1039
- enabled: true
1040
- },
1041
- partialScoring: {
1042
- settings: true,
1043
- label: 'Allow Partial Scoring'
1044
- },
1045
- baseInputConfiguration: {
1046
- html: {
1047
- disabled: true
1048
- },
1049
- audio: {
1050
- disabled: false
1051
- },
1052
- video: {
1053
- disabled: false
1054
- },
1055
- image: {
1056
- disabled: false
1057
- },
1058
- h3: {
1059
- disabled: true
1060
- },
1061
- blockquote: {
1062
- disabled: true
1063
- },
1064
- textAlign: {
1065
- disabled: true
1066
- },
1067
- showParagraphs: {
1068
- disabled: false
1069
- },
1070
- separateParagraphs: {
1071
- disabled: true
1072
- }
1073
- },
1074
- prompt: {
1075
- label: 'Prompt',
1076
- settings: true,
1077
- inputConfiguration: {
1078
- audio: {
1079
- disabled: false
1080
- },
1081
- video: {
1082
- disabled: false
1083
- },
1084
- image: {
1085
- disabled: false
1086
- }
1087
- },
1088
- required: false
1089
- },
1090
- spellCheck: {
1091
- label: 'Spellcheck',
1092
- settings: false,
1093
- enabled: true
1094
- },
1095
- editSource: {
1096
- label: 'Edit Source',
1097
- settings: false,
1098
- enabled: false
1099
- },
1100
- playerSpellCheck: {
1101
- label: 'Student Spellcheck',
1102
- settings: true,
1103
- enabled: true
1104
- },
1105
- teacherInstructions: {
1106
- settings: true,
1107
- label: 'Teacher Instructions',
1108
- inputConfiguration: {
1109
- audio: {
1110
- disabled: false
1111
- },
1112
- video: {
1113
- disabled: false
1114
- },
1115
- image: {
1116
- disabled: false
1117
- }
1118
- },
1119
- required: false
1120
- },
1121
- rationale: {
1122
- settings: true,
1123
- label: 'Rationale',
1124
- inputConfiguration: {
1125
- audio: {
1126
- disabled: false
1127
- },
1128
- video: {
1129
- disabled: false
1130
- },
1131
- image: {
1132
- disabled: false
1133
- }
1134
- },
1135
- required: false
1136
- },
1137
- template: {
1138
- inputConfiguration: {
1139
- audio: {
1140
- disabled: false
1141
- },
1142
- video: {
1143
- disabled: false
1144
- },
1145
- image: {
1146
- disabled: false
1147
- }
1148
- }
1149
- },
1150
- maxImageWidth: {
1151
- teacherInstructions: 300,
1152
- prompt: 300,
1153
- rationale: 300
1154
- },
1155
- maxImageHeight: {
1156
- teacherInstructions: 300,
1157
- prompt: 300,
1158
- rationale: 300
1159
- },
1160
- mathMlOptions: {
1161
- mmlOutput: false,
1162
- mmlEditing: false
1163
- },
1164
- language: {
1165
- settings: false,
1166
- label: 'Specify Language',
1167
- enabled: false
1168
- },
1169
- languageChoices: {
1170
- label: 'Language Choices',
1171
- options: []
1172
- },
1173
- maxResponseAreas: 10
1174
- }
1175
- };
1176
-
1177
- const log = debug('math-templated:configure');
1178
- class MathTemplateConfigure extends HTMLElement {
1179
- constructor() {
1180
- super();
1181
- this._model = MathTemplateConfigure.prepareModel();
1182
- this._configuration = sensibleDefaults.configuration;
1183
- this.onModelChanged = this.onModelChanged.bind(this);
1184
- this.onConfigurationChanged = this.onConfigurationChanged.bind(this);
1185
- }
1186
-
1187
- set model(s) {
1188
- this._model = MathTemplateConfigure.prepareModel(s);
1189
-
1190
- this._render();
1191
- }
1192
-
1193
- set configuration(c) {
1194
- var _c$language;
1195
-
1196
- this._configuration = defaults(c, sensibleDefaults.configuration); // if language:enabled is true, then the corresponding default item model should include a language value;
1197
- // if it is false, then the language field should be omitted from the item model.
1198
- // if a default item model includes a language value (e.g., en_US) and the corresponding authoring view settings have language:settings = true,
1199
- // then (a) language:enabled should also be true, and (b) that default language value should be represented in languageChoices[] (as a key).
1200
-
1201
- if ((_c$language = c.language) != null && _c$language.enabled) {
1202
- var _c$languageChoices, _c$languageChoices$op;
1203
-
1204
- if ((_c$languageChoices = c.languageChoices) != null && (_c$languageChoices$op = _c$languageChoices.options) != null && _c$languageChoices$op.length) {
1205
- this._model.language = c.languageChoices.options[0].value;
1206
- }
1207
- } else if (c.language.settings && this._model.language) {
1208
- this._configuration.language.enabled = true;
1209
-
1210
- if (!this._configuration.languageChoices.options || !this._configuration.languageChoices.options.length) {
1211
- this._configuration.languageChoices.options = [];
1212
- } // check if the language is already included in the languageChoices.options array
1213
- // and if not, then add it.
1214
-
1215
-
1216
- if (!this._configuration.languageChoices.options.find(option => option.value === this._model.language)) {
1217
- this._configuration.languageChoices.options.push({
1218
- value: this._model.language,
1219
- label: this._model.language
1220
- });
1221
- }
1222
- } else {
1223
- delete this._model.language;
1224
- }
1225
-
1226
- this._render();
1227
- }
1228
-
1229
- set disableSidePanel(s) {
1230
- this._disableSidePanel = s;
1231
-
1232
- this._render();
1233
- }
1234
-
1235
- dispatchModelUpdated(reset) {
1236
- const resetValue = !!reset;
1237
- this.dispatchEvent(new ModelUpdatedEvent(this._model, resetValue));
1238
- }
1239
-
1240
- onModelChanged(m, reset) {
1241
- this._model = MathTemplateConfigure.prepareModel(m);
1242
-
1243
- this._render();
1244
-
1245
- this.dispatchModelUpdated(reset);
1246
- }
1247
-
1248
- onConfigurationChanged(c) {
1249
- this._configuration = c;
1250
-
1251
- this._render();
1252
- }
1253
- /** @param {done, progress, file} handler */
1254
-
1255
-
1256
- insertImage(handler) {
1257
- this.dispatchEvent(new InsertImageEvent(handler));
1258
- }
1259
-
1260
- onDeleteImage(src, done) {
1261
- this.dispatchEvent(new DeleteImageEvent(src, done));
1262
- }
1263
-
1264
- insertSound(handler) {
1265
- this.dispatchEvent(new InsertSoundEvent(handler));
1266
- }
1267
-
1268
- onDeleteSound(src, done) {
1269
- this.dispatchEvent(new DeleteSoundEvent(src, done));
1270
- }
1271
-
1272
- _render() {
1273
- log('_render');
1274
- let element = /*#__PURE__*/React__default.createElement(Main, {
1275
- model: this._model,
1276
- configuration: this._configuration,
1277
- onModelChanged: this.onModelChanged,
1278
- onConfigurationChanged: this.onConfigurationChanged,
1279
- disableSidePanel: this._disableSidePanel,
1280
- imageSupport: {
1281
- add: this.insertImage.bind(this),
1282
- delete: this.onDeleteImage.bind(this)
1283
- },
1284
- uploadSoundSupport: {
1285
- add: this.insertSound.bind(this),
1286
- delete: this.onDeleteSound.bind(this)
1287
- }
1288
- });
1289
- ReactDOM.render(element, this);
1290
- }
1291
-
1292
- }
1293
-
1294
- MathTemplateConfigure.prepareModel = (model = {}) => {
1295
- const {
1296
- validationDefault,
1297
- allowTrailingZerosDefault,
1298
- ignoreOrderDefault,
1299
- responses = {}
1300
- } = model;
1301
- const updatedResponses = Object.keys(responses).reduce((acc, responseId) => {
1302
- const correctResponse = responses[responseId];
1303
- acc[responseId] = _extends({}, correctResponse, {
1304
- validation: correctResponse.validation || validationDefault,
1305
- allowTrailingZeros: correctResponse.allowTrailingZeros || allowTrailingZerosDefault,
1306
- ignoreOrder: correctResponse.ignoreOrder || ignoreOrderDefault
1307
- });
1308
- return acc;
1309
- }, {});
1310
-
1311
- const joinedObj = _extends({}, sensibleDefaults.model, model, {
1312
- responses: updatedResponses
1313
- });
1314
-
1315
- const slateMarkup = joinedObj.slateMarkup || createSlateMarkup(joinedObj.markup, joinedObj.responses);
1316
- const processedMarkup = processMarkup(slateMarkup); // this was added to treat an exception, when the model has responses without the "answer" property
1317
-
1318
- if (joinedObj.responses) {
1319
- Object.keys(joinedObj.responses).forEach(key => {
1320
- if (isArray(joinedObj.responses[key])) {
1321
- joinedObj.responses[key] = (joinedObj.responses[key] || []).map((item, index) => {
1322
- if (!item.answer) {
1323
- log('Choice does not contain "answer" property, which is required.', item);
1324
- return _extends({
1325
- answer: `${index}`
1326
- }, item);
1327
- }
1328
-
1329
- return item;
1330
- });
1331
- }
1332
- });
1333
- }
1334
-
1335
- return _extends({}, joinedObj, {
1336
- slateMarkup,
1337
- markup: processedMarkup
1338
- });
1339
- };
1340
-
1341
- export { MathTemplateConfigure as default };
1342
- //# sourceMappingURL=configure.js.map