UNPKG

@instructure/quiz-interactions

Version:

A React UI component Library for quiz interaction types.

705 lines (691 loc) • 30.6 kB
import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray"; import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck"; import _createClass from "@babel/runtime/helpers/esm/createClass"; import _possibleConstructorReturn from "@babel/runtime/helpers/esm/possibleConstructorReturn"; import _getPrototypeOf from "@babel/runtime/helpers/esm/getPrototypeOf"; import _inherits from "@babel/runtime/helpers/esm/inherits"; import _defineProperty from "@babel/runtime/helpers/esm/defineProperty"; var _dec, _class, _RichFillBlankEdit; function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _callSuper(_this, derived, args) { function isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { return !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (e) { return false; } } derived = _getPrototypeOf(derived); return _possibleConstructorReturn(_this, isNativeReflectConstruct() ? Reflect.construct(derived, args || [], _getPrototypeOf(_this).constructor) : derived.apply(_this, args)); } /** @jsx jsx */ import { Component } from 'react'; import PropTypes from 'prop-types'; import concat from 'lodash/fp/concat'; import find from 'lodash/fp/find'; import get from 'lodash/get'; import { v4 as uuid } from 'uuid'; import update from 'immutability-helper'; import findIndex from 'lodash/findIndex'; import omit from 'lodash/omit'; import isEqual from 'lodash/isEqual'; import escape from 'lodash/escape'; import { Checkbox } from '@instructure/ui-checkbox'; import { jsx } from '@instructure/emotion'; import QuestionSettingsContainer from '../../common/edit/components/QuestionSettingsContainer'; import QuestionContainer from '../../common/edit/components/QuestionContainer'; import RichFillBlankInteractionType from '../../../records/interactions/rich_fill_blank'; import BlankTypeSelect from '../../fill_blank/Edit/answer_field/BlankTypeSelect'; import WordBankDistractors from './WordBankDistractors'; import generateStyle from './styles'; import generateComponentTheme from './theme'; import withEditTools from '../../../util/withEditTools'; import t from '@instructure/quiz-i18n/es/format-message'; import QuestionSettingsPanel from '../../common/edit/components/QuestionSettingsPanel'; import CalculatorOptionWithOqaatAlert from '../../common/edit/components/CalculatorOptionWithOqaatAlert'; import { ScreenReaderContent } from '@instructure/ui-a11y-content'; import { Text } from '@instructure/ui-text'; import { Flex, withStyleOverrides, FormFieldGroup } from '@instructure/quiz-common'; /** --- category: RichFillInTheBlank --- Rich Fill in the Blank Edit component ```jsx_example function Example (props) { const exampleProps = { interactionData: { blanks: [{ answerType: 'openEntry', id: 'uuid-blank1' }, { answerType: 'openEntry', id: 'uuid-blank2' }, { answerType: 'openEntry', id: 'uuid-blank3' }, { answerType: 'openEntry', id: 'uuid-blank4' }, { answerType: 'openEntry', id: 'uuid-blank5' }, { answerType: 'dropdown', id: 'uuid-blank6', choices: [ { id: 'uuid6-choice1', position: 1, itemBody: 'with' }, { id: 'uuid6-choice2', position: 2, itemBody: 'on' }, { id: 'uuid6-choice3', position: 3, itemBody: 'which' } ] }, { answerType: 'wordbank', id: 'uuid-blank7', choices: [ { id: 'uuid7-choice1', position: 1, itemBody: 'bathwater' }, { id: 'uuid7-choice2', position: 2, itemBody: 'bathtub' }, { id: 'uuid7-choice3', position: 3, itemBody: 'water' } ] }] }, scoringData: { workingItemBody: "<p>`Don't` `throw` `the` `baby` `out` `with` the `bathwater`.</p>", value: [{ id: 'uuid-blank1', scoringAlgorithm: 'TextCloseEnough', scoringData: { blankText: 'Don\'t', editDistance: '1', ignoreCase: true, value: 'Don\'t' } }, { id: 'uuid-blank2', scoringAlgorithm: 'TextEquivalence', scoringData: { blankText: 'throw', value: 'throw' } }, { id: 'uuid-blank3', scoringAlgorithm: 'TextContainsAnswer', scoringData: { blankText: 'the', value: 'the' } }, { id: 'uuid-blank4', scoringAlgorithm: 'TextInChoices', scoringData: { blankText: 'baby', value: ['baby', 'kid', 'child'] } }, { id: 'uuid-blank5', scoringAlgorithm: 'TextRegex', scoringData: { blankText: 'out', value: 'out' } }, { id: 'uuid-blank6', scoringAlgorithm: 'Equivalence', scoringData: { blankText: 'with', value: 'uuid6-choice1' } }, { id: 'uuid-blank7', scoringAlgorithm: 'Equivalence', scoringData: { blankText: 'bathwater', value: 'uuid7-choice1' } }] } } return ( <RichFillBlankEdit {...exampleProps} {...props} /> ) } <SettingsSwitcher locales={LOCALES}> <EditStateProvider> <Example /> </EditStateProvider> </SettingsSwitcher> ``` **/ var RichFillBlankEdit = (_dec = withStyleOverrides(generateStyle, generateComponentTheme), withEditTools(_class = _dec(_class = (_RichFillBlankEdit = /*#__PURE__*/function (_Component) { function RichFillBlankEdit() { var _this2; _classCallCheck(this, RichFillBlankEdit); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this2 = _callSuper(this, RichFillBlankEdit, [].concat(args)); _defineProperty(_this2, "validBlankRegex", function () { return new RegExp(_this2.props.interactionType.validBlankRegex, 'g'); }); // Other edit components use the `getErrors` helper passed in from the // withEditTools higher-order component, but fill blank has its own error // handling logic _defineProperty(_this2, "getErrors", function (path) { if (_this2.props.errorsAreShowing) { return get(_this2.props.errors, path, null); } return null; }); _defineProperty(_this2, "blankValues", function () { return (_this2.props.scoringData.value || []).map(function (blankValue) { return blankValue.scoringData.blankText; }); }); _defineProperty(_this2, "arrayDiff", function (arr1, arr2) { // items in arr1 that are not in arr2 (accounting for duplicate items) // examples (arr1 - arr2 = return): // [a,b,c] - [a] = [b,c] // [a,a,b] - [a] = [a,b] // [a,b] - [b,c] = [a] var arr1Copy = _toConsumableArray(arr1); arr2.forEach(function (blank) { var blankIndex = arr1Copy.indexOf(blank); if (blankIndex > -1) { arr1Copy.splice(blankIndex, 1); } }); return arr1Copy; }); _defineProperty(_this2, "defaultBlankScoringData", function (blankValue, id) { return { id: id, scoringAlgorithm: 'TextContainsAnswer', scoringData: { value: blankValue, blankText: blankValue } }; }); _defineProperty(_this2, "defaultBlankInteractionData", function (blankValue, id) { return { id: id, answerType: 'openEntry' }; }); _defineProperty(_this2, "updateScoringDataBlankTexts", function (scoringDataValue, interactionDataBlankValues, blankMatches) { return scoringDataValue.map(function (scoringDataBlankValue, i) { var prevBlankText = scoringDataBlankValue.scoringData.blankText; var newBlankText = blankMatches[i]; if (prevBlankText === newBlankText) { return scoringDataBlankValue; } var scoringAlgorithm = scoringDataBlankValue.scoringAlgorithm; var answerType = interactionDataBlankValues[i].answerType; var scoringDataMods = { blankText: blankMatches[i] }; if (answerType === 'openEntry') { if (['TextRegex', 'TextContainsAnswer', 'TextEquivalence', 'Equivalence', 'TextCloseEnough'].includes(scoringAlgorithm)) { scoringDataMods.value = blankMatches[i]; } else if (scoringAlgorithm === 'TextInChoices') { scoringDataMods.value = scoringDataBlankValue.scoringData.value; scoringDataMods.value[0] = blankMatches[i]; } } if (answerType === 'wordbank' && scoringDataBlankValue.scoringData.choiceId) { scoringDataMods.value = blankMatches[i]; } return _objectSpread(_objectSpread({}, scoringDataBlankValue), {}, { scoringData: _objectSpread(_objectSpread({}, scoringDataBlankValue.scoringData), scoringDataMods) }); }); }); _defineProperty(_this2, "updateInteractionDataBlankTexts", function (interactionDataBlankValues, newScoringDataValue, blankMatches) { return interactionDataBlankValues.map(function (interactionDataBlankValue, i) { if (['dropdown', 'wordbank'].includes(interactionDataBlankValue.answerType)) { var choices = interactionDataBlankValue.choices; var blankId = interactionDataBlankValue.id; var blankScoringDataValue = newScoringDataValue.find(function (value) { return value.id === blankId; }); if (choices && blankScoringDataValue) { var correctChoiceIdx = choices.findIndex(function (choice) { return choice.id === blankScoringDataValue.scoringData.value; }); choices[correctChoiceIdx].itemBody = blankMatches[i]; } return _objectSpread(_objectSpread({}, interactionDataBlankValue), choices && { choices: choices }); } return interactionDataBlankValue; }); }); _defineProperty(_this2, "updateWordBankChoicesTexts", function (wordBankChoices, scoringDataValue) { if (!wordBankChoices) return; return wordBankChoices.map(function (wordBankChoice) { var choiceScoringData = scoringDataValue.find(function (scoringData) { return scoringData.scoringData.choiceId === wordBankChoice.id; }); return _objectSpread(_objectSpread({}, wordBankChoice), choiceScoringData && { itemBody: choiceScoringData.scoringData.blankText }); }); }); _defineProperty(_this2, "indexForWordBankChoice", function (choiceId) { return findIndex(_this2.props.interactionData.wordBankChoices, function (wordBankChoice) { return wordBankChoice.id === choiceId; }); }); _defineProperty(_this2, "makeNewProperties", function (interactionData) { // syncs shuffling properties data with new interaction data. // this runs each time we changeItemState so that we dont have // to manage syncing properties and interactionData on each individual // change to blank type or blank creation/deletion var blankRules = interactionData.blanks.reduce(function (memo, blank, blankIndex) { // eslint-disable-next-line no-param-reassign memo[blankIndex] = blank.answerType === 'openEntry' ? { children: null } : { children: { choices: { shuffled: true } } }; return memo; }, {}); var newShuffleRules = { shuffleRules: { blanks: { children: blankRules } } }; return Object.assign({}, _this2.props.properties, newShuffleRules); }); _defineProperty(_this2, "changeItemState", function (modifications, blankId) { var newestIntData = Object.assign({}, _this2.props.interactionData, modifications.interactionData); var newProperties = _this2.makeNewProperties(newestIntData); var newMods = { properties: newProperties }; if (modifications.scoringData) { newMods.scoringData = modifications.scoringData; } var newModifications = Object.assign({}, modifications, newMods); _this2.props.changeItemState(newModifications, blankId); }); _defineProperty(_this2, "insert", function (arr, index) { for (var _len2 = arguments.length, newItems = new Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) { newItems[_key2 - 2] = arguments[_key2]; } return [].concat(_toConsumableArray(arr.slice(0, index)), newItems, _toConsumableArray(arr.slice(index))); }); _defineProperty(_this2, "blankIdsFromValues", function (removedBlanks) { var blankIds = []; var scoringDataValue = _toConsumableArray(_this2.props.scoringData.value); removedBlanks.forEach(function (blank) { var blankValueIndex = scoringDataValue.findIndex(function (blankValue) { return blankValue.scoringData.blankText === blank; }); if (blankValueIndex > -1) { blankIds.push(scoringDataValue[blankValueIndex].id); scoringDataValue.splice(blankValueIndex, 1); } }); return blankIds; }); // ================ // HANDLERS // ================ _defineProperty(_this2, "handleCheckboxChange", function (event) { var interactionData = update(_this2.props.interactionData, _defineProperty({}, event.target.value, { $set: !_this2.props.interactionData[event.target.value] })); _this2.changeItemState({ interactionData: interactionData }); }); _defineProperty(_this2, "handleCalculatorTypeChange", function (e, value) { _this2.changeItemState({ calculatorType: value }); }); _defineProperty(_this2, "updateScoringDataForBlank", function (blankId) { return function (scoringDataMods) { var indexForBlank = _this2.indexForBlank(blankId); var workingItemBody = _this2.props.scoringData.workingItemBody; var index = 0; var newWorkingItemBody = workingItemBody.replace(_this2.validBlankRegex(), function (match) { return index++ === indexForBlank ? "`".concat(escape(scoringDataMods.scoringData.blankText), "`") : match; }); var scoringData = update(_this2.props.scoringData, { workingItemBody: { $set: newWorkingItemBody }, value: _defineProperty({}, indexForBlank, { $merge: scoringDataMods }) }); var interactionData = _this2.props.interactionData; // if the text of a wordbank choice was updated, // reflect the change in the wordBankChoices list if (scoringDataMods.scoringData.choiceId && _this2.props.interactionData.wordBankChoices) { var wordBankChoiceIndex = _this2.indexForWordBankChoice(scoringDataMods.scoringData.choiceId); if (wordBankChoiceIndex > -1) { interactionData = update(interactionData, { wordBankChoices: _defineProperty({}, wordBankChoiceIndex, { itemBody: { $set: scoringDataMods.scoringData.blankText } }) }); } } _this2.changeItemState({ scoringData: scoringData, interactionData: interactionData }, blankId); }; }); // Setting choices to null will remove the choice from the blank. This is necessary // because when switching between blank types we need a way to remove the choices // data from the interactionData since it won't be relevant to the new type (not // to mention that leaving it will expose the openEntry's answer) _defineProperty(_this2, "updateBlank", function (blankId) { return function (modifications) { var indexForBlank = _this2.indexForBlank(blankId); var blankData = _this2.props.interactionData.blanks[indexForBlank]; var mods = modifications; if (modifications.choices === null) { mods = omit(modifications, ['choices']); blankData = omit(_this2.props.interactionData.blanks[indexForBlank], ['choices']); } // if there's a new wordbank choice, add it to the wordBankChoice list var wordBankChoicesMods; if (modifications.choice) { wordBankChoicesMods = update(_this2.props.interactionData.wordBankChoices || [{ id: uuid(), itemBody: '' }], { $push: [modifications.choice] }); } // omit "choice" because "choice" is added to wordBankChoices, not the blank itself mods = omit(modifications, ['choice']); var finalMods = update(blankData, { $merge: mods }); var interactionData = update(_this2.props.interactionData, _objectSpread({ blanks: _defineProperty({}, indexForBlank, { $set: finalMods }) }, wordBankChoicesMods && { wordBankChoices: { $set: wordBankChoicesMods } })); // if the blank no longer has answerType "wordbank", // remove the choice from wordBankChoices var noLongerWordbank = blankData.answerType === 'wordbank' && modifications.answerType && modifications.answerType !== 'wordbank'; if (noLongerWordbank && interactionData.wordBankChoices) { var scoringDataForBlank = _this2.props.scoringData.value[indexForBlank]; var wordBankChoiceIndex = _this2.indexForWordBankChoice(scoringDataForBlank.scoringData.choiceId); interactionData = update(interactionData, { wordBankChoices: { $splice: [[wordBankChoiceIndex, 1]] } }); } // if there are aren't any wordbank blanks, // clear out wordBankChoices list if (!interactionData.blanks.some(function (blank) { return blank.answerType === 'wordbank'; })) { interactionData = update(interactionData, { $unset: ['wordBankChoices'] }); } _this2.changeItemState({ interactionData: interactionData }, blankId); }; }); _defineProperty(_this2, "handleDescriptionChange", function (itemBody) { var blankMatches = (itemBody.match(_this2.validBlankRegex()) || []).map(function (match) { return _this2.htmlDecode(match.slice(1, -1)); }); var knownBlanks = _this2.blankValues(); var newScoringDataValue = _this2.props.scoringData.value || []; var newInteractionDataBlanks = _this2.props.interactionData.blanks || []; var newWordBankChoices = _this2.props.interactionData.wordBankChoices; var updateBlankTexts = function updateBlankTexts() { newScoringDataValue = _this2.updateScoringDataBlankTexts(newScoringDataValue, newInteractionDataBlanks, blankMatches); newInteractionDataBlanks = _this2.updateInteractionDataBlankTexts(newInteractionDataBlanks, newScoringDataValue, blankMatches); newWordBankChoices = _this2.updateWordBankChoicesTexts(newWordBankChoices, newScoringDataValue); }; if (blankMatches.length === knownBlanks.length) { // update blank values (may or may not have changed) updateBlankTexts(); } else { // remove any removed blanks var removedBlanks = _this2.arrayDiff(knownBlanks, blankMatches); var removedBlankIds = _this2.blankIdsFromValues(removedBlanks); var removedWordBankChoiceIds = []; newScoringDataValue = newScoringDataValue.filter(function (blankValue) { if (removedBlankIds.includes(blankValue.id) && blankValue.scoringData.choiceId) { removedWordBankChoiceIds.push(blankValue.scoringData.choiceId); } return !removedBlankIds.includes(blankValue.id); }); newInteractionDataBlanks = newInteractionDataBlanks.filter(function (blankValue) { return !removedBlankIds.includes(blankValue.id); }); if (newWordBankChoices) { newWordBankChoices = newWordBankChoices.filter(function (wordBankChoice) { return !removedWordBankChoiceIds.includes(wordBankChoice.id); }); // if there are aren't any wordbank blanks, clear out wordBankChoices list if (!newInteractionDataBlanks.some(function (blank) { return blank.answerType === 'wordbank'; })) { newWordBankChoices = null; } } // add any newly added blanks var newBlanks = _this2.arrayDiff(blankMatches, knownBlanks); newBlanks.forEach(function (newBlank) { var id = uuid(); var index = blankMatches.indexOf(newBlank); newScoringDataValue = _this2.insert(newScoringDataValue, index, _this2.defaultBlankScoringData(newBlank, id)); newInteractionDataBlanks = _this2.insert(newInteractionDataBlanks, index, _this2.defaultBlankInteractionData(newBlank, id)); }); } // There are many ways for the scoringData/interactionData to get desynced from what the RCE shows, // especially considering we allow blanks to have duplicate blankText, and users can change // multiple blanks at once by pasting anything in the RCE. This check is intended as a failsafe. // If the blankTexts don't match what's in the RCE, just force them to match. var blankTexts = newScoringDataValue.map(function (blankValue) { return blankValue.scoringData.blankText; }); if (!isEqual(blankTexts, blankMatches)) { updateBlankTexts(); } _this2.props.changeItemState({ interactionData: _objectSpread({ blanks: newInteractionDataBlanks }, newWordBankChoices && { wordBankChoices: newWordBankChoices }), scoringData: { workingItemBody: itemBody, value: newScoringDataValue } }); }); _defineProperty(_this2, "renderExplanation", function () { return jsx(Flex, { direction: "column", padding: "0 0 small 0" }, jsx(Text, null, t('Type a statement and surround a word with backticks to indicate where a student will fill in the answer.'))); }); return _this2; } _inherits(RichFillBlankEdit, _Component); return _createClass(RichFillBlankEdit, [{ key: "indexForBlank", value: function indexForBlank(blankId) { return findIndex(this.props.interactionData.blanks, function (blank) { return blank.id === blankId; }); } }, { key: "htmlDecode", value: function htmlDecode(input) { var doc = new DOMParser().parseFromString(input, 'text/html'); return doc.documentElement.textContent; } }, { key: "renderBlanksOptions", value: // ============= // RENDERING // ============= function renderBlanksOptions() { var _this3 = this; var hasIndividualWordBanks = this.props.interactionData.blanks.some(function (blank) { return blank.answerType === 'wordbank' && blank.choices && blank.choices.length; }); return this.props.interactionData.blanks.map(function (blank, blankIndex) { var blankScoringData = find({ id: blank.id }, _this3.props.scoringData.value) || {}; var choicesErrors = concat(_this3.getErrors("scoringData.value[".concat(blankIndex, "].scoringData.value.$errors")) || [], _this3.getErrors("interactionData.blanks[".concat(blankIndex, "].choices.$errors")) || []); return jsx(BlankTypeSelect, { key: blank.id, answerType: blank.answerType, blankPosition: blankIndex + 1, blankScoringAlgorithm: blankScoringData.scoringAlgorithm, blankScoringData: blankScoringData.scoringData, choices: blank.choices, disabled: _this3.props.overrideEditableForRegrading, interactionDataErrors: _this3.getErrors("interactionData.blanks[".concat(blankIndex, "]")) || {}, name: blank.id, notifyScreenreader: _this3.props.notifyScreenreader, onModalClose: _this3.props.onModalClose, onModalOpen: _this3.props.onModalOpen, scoringDataErrors: _this3.getErrors("scoringData.value[".concat(blankIndex, "].scoringData")) || {}, choicesErrors: choicesErrors, validationErrorsFromApi: _this3.props.validationErrorsFromApi[blank.id] || [], wordBankChoices: _this3.props.interactionData.wordBankChoices, updateBlank: _this3.updateBlank(blank.id), updateBlankScoringData: _this3.updateScoringDataForBlank(blank.id), useCommonWordbank: _this3.props.fitbCommonWordbankEnabled && !hasIndividualWordBanks }); }); } }, { key: "renderOptionsDescription", value: function renderOptionsDescription() { return jsx(ScreenReaderContent, null, t('Fill in the blank options')); } }, { key: "render", value: function render() { var stemErrors = this.getErrors('scoringData.workingItemBody') || []; var blankErrors = this.getErrors(['interactionData', 'blanks', '$errors']) || []; return jsx("div", null, this.renderExplanation(), jsx(QuestionContainer, { disabled: this.props.overrideEditableForRegrading, enableRichContentEditor: this.props.enableRichContentEditor, itemBody: this.props.scoringData.workingItemBody, onDescriptionChange: this.handleDescriptionChange, onModalClose: this.props.onModalClose, onModalOpen: this.props.onModalOpen, openImportModal: this.props.openImportModal, stemErrors: stemErrors.concat(blankErrors) || [] }, this.renderBlanksOptions(), jsx(WordBankDistractors, { changeItemState: this.props.changeItemState, indexForWordBankChoice: this.indexForWordBankChoice, interactionData: this.props.interactionData, interactionDataErrors: this.getErrors('interactionData.wordBankChoices') || {}, notifyScreenreader: this.props.notifyScreenreader, onModalClose: this.props.onModalClose, onModalOpen: this.props.onModalOpen, overrideEditableForRegrading: this.props.overrideEditableForRegrading, scoringData: this.props.scoringData })), jsx(QuestionSettingsContainer, { additionalOptions: this.props.additionalOptions }, jsx(QuestionSettingsPanel, { label: t('Options'), defaultExpanded: true }, jsx(FormFieldGroup, { rowSpacing: "small", description: this.renderOptionsDescription() }, this.props.interactionData.wordBankChoices && jsx(Checkbox, { label: t('Allow word bank choices to be reused'), value: "reuseWordBankChoices", onChange: this.handleCheckboxChange, checked: this.props.interactionData.reuseWordBankChoices, disabled: this.props.overrideEditableForRegrading }), this.props.showCalculatorOption && jsx(CalculatorOptionWithOqaatAlert, { disabled: this.props.overrideEditableForRegrading, calculatorValue: this.props.calculatorType, onCalculatorTypeChange: this.handleCalculatorTypeChange, oqaatChecked: this.props.oneQuestionAtATime, onOqaatChange: this.props.setOneQuestionAtATime }))))); } }]); }(Component), _defineProperty(_RichFillBlankEdit, "displayName", 'RichFillBlankEdit'), _defineProperty(_RichFillBlankEdit, "componentId", "Quizzes".concat(_RichFillBlankEdit.displayName)), _defineProperty(_RichFillBlankEdit, "interactionType", RichFillBlankInteractionType), _defineProperty(_RichFillBlankEdit, "propTypes", { additionalOptions: PropTypes.array, calculatorType: PropTypes.string, changeItemState: PropTypes.func.isRequired, enableRichContentEditor: PropTypes.bool, errors: PropTypes.object, errorsAreShowing: PropTypes.bool, fitbCommonWordbankEnabled: PropTypes.bool, interactionData: PropTypes.object.isRequired, interactionType: PropTypes.shape({ validBlankRegex: PropTypes.string }).isRequired, notifyScreenreader: PropTypes.func.isRequired, onModalClose: PropTypes.func, onModalOpen: PropTypes.func, oneQuestionAtATime: PropTypes.bool, openImportModal: PropTypes.func, overrideEditableForRegrading: PropTypes.bool, properties: PropTypes.shape({ shuffleRules: PropTypes.shape({ blanks: PropTypes.shape({ children: PropTypes.object }) }) }), scoringData: PropTypes.object.isRequired, setOneQuestionAtATime: PropTypes.func, validationErrorsFromApi: PropTypes.object, styles: PropTypes.object, showCalculatorOption: PropTypes.bool }), _defineProperty(_RichFillBlankEdit, "defaultProps", { calculatorType: 'none', enableRichContentEditor: true, fitbCommonWordbankEnabled: false, oneQuestionAtATime: false, overrideEditableForRegrading: false, setOneQuestionAtATime: Function.prototype, additionalOptions: void 0, errors: void 0, errorsAreShowing: void 0, onModalClose: void 0, onModalOpen: void 0, openImportModal: void 0, properties: {}, scoringData: void 0, validationErrorsFromApi: {}, showCalculatorOption: true }), _RichFillBlankEdit)) || _class) || _class); export { RichFillBlankEdit as default };