UNPKG

@instructure/quiz-interactions

Version:

A React UI component Library for quiz interaction types.

703 lines (702 loc) • 32.1 kB
/** @jsx jsx */ function _array_like_to_array(arr, len) { if (len == null || len > arr.length) len = arr.length; for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i]; return arr2; } function _array_without_holes(arr) { if (Array.isArray(arr)) return _array_like_to_array(arr); } function _define_property(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _iterable_to_array(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } function _non_iterable_spread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _object_spread(target) { for(var i = 1; i < arguments.length; i++){ var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === "function") { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function(key) { _define_property(target, key, source[key]); }); } return target; } 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 _object_spread_props(target, source) { source = source != null ? source : {}; 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 _object_without_properties(source, excluded) { if (source == null) return {}; var target = _object_without_properties_loose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for(i = 0; i < sourceSymbolKeys.length; i++){ key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } function _object_without_properties_loose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for(i = 0; i < sourceKeys.length; i++){ key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } function _to_consumable_array(arr) { return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread(); } function _unsupported_iterable_to_array(o, minLen) { if (!o) return; if (typeof o === "string") return _array_like_to_array(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(n); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen); } import React, { useMemo } 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 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/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'; function BlanksOptions(param) { var blanks = param.blanks, scoringDataValue = param.scoringDataValue, fitbCommonWordbankEnabled = param.fitbCommonWordbankEnabled, overrideEditableForRegrading = param.overrideEditableForRegrading, wordBankChoices = param.wordBankChoices, notifyScreenreader = param.notifyScreenreader, onModalClose = param.onModalClose, onModalOpen = param.onModalOpen, validationErrorsFromApi = param.validationErrorsFromApi, getErrors = param.getErrors, updateBlank = param.updateBlank, updateScoringDataForBlank = param.updateScoringDataForBlank, isSurvey = param.isSurvey; var hasIndividualWordBanks = blanks.some(function(blank) { return blank.answerType === 'wordbank' && blank.choices && blank.choices.length; }); return blanks.map(function(blank, blankIndex) { var blankScoringData = find({ id: blank.id }, scoringDataValue) || {}; var choicesErrors = concat(getErrors("scoringData.value[".concat(blankIndex, "].scoringData.value.$errors")) || [], getErrors("interactionData.blanks[".concat(blankIndex, "].choices.$errors")) || []); return /*#__PURE__*/ jsx(BlankTypeSelect, { key: blank.id, answerType: blank.answerType, blankPosition: blankIndex + 1, blankScoringAlgorithm: blankScoringData.scoringAlgorithm, blankScoringData: blankScoringData.scoringData, choices: blank.choices, disabled: overrideEditableForRegrading, interactionDataErrors: getErrors("interactionData.blanks[".concat(blankIndex, "]")) || {}, name: blank.id, notifyScreenreader: notifyScreenreader, onModalClose: onModalClose, onModalOpen: onModalOpen, scoringDataErrors: getErrors("scoringData.value[".concat(blankIndex, "].scoringData")) || {}, choicesErrors: choicesErrors, validationErrorsFromApi: validationErrorsFromApi[blank.id] || [], wordBankChoices: wordBankChoices, updateBlank: updateBlank(blank.id), updateBlankScoringData: updateScoringDataForBlank(blank.id), useCommonWordbank: fitbCommonWordbankEnabled && !hasIndividualWordBanks, isSurvey: isSurvey }); }); } BlanksOptions.propTypes = { blanks: PropTypes.array.isRequired, scoringDataValue: PropTypes.array, fitbCommonWordbankEnabled: PropTypes.bool, overrideEditableForRegrading: PropTypes.bool, wordBankChoices: PropTypes.array, notifyScreenreader: PropTypes.func.isRequired, onModalClose: PropTypes.func, onModalOpen: PropTypes.func, validationErrorsFromApi: PropTypes.object, getErrors: PropTypes.func.isRequired, updateBlank: PropTypes.func.isRequired, updateScoringDataForBlank: PropTypes.func.isRequired, isSurvey: PropTypes.bool }; var RichFillBlankEdit = /*#__PURE__*/ React.forwardRef(function(props, ref) { var validBlankRegex = useMemo(function() { return new RegExp(props.interactionType.validBlankRegex, 'g'); }, [ props.interactionType.validBlankRegex ]); // Other edit components use the `getErrors` helper passed in from the // withEditTools higher-order component, but fill blank has its own error // handling logic var getErrors = function(path) { if (props.errorsAreShowing) { return get(props.errors, path, null); } return null; }; var blankValues = function() { return (props.scoringData.value || []).map(function(blankValue) { return blankValue.scoringData.blankText; }); }; var 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 = _to_consumable_array(arr1); arr2.forEach(function(blank) { var blankIndex = arr1Copy.indexOf(blank); if (blankIndex > -1) { arr1Copy.splice(blankIndex, 1); } }); return arr1Copy; }; var defaultBlankScoringData = function(blankValue, id) { return { id: id, scoringAlgorithm: 'TextContainsAnswer', scoringData: { value: blankValue, blankText: blankValue } }; }; var defaultBlankInteractionData = function(blankValue, id) { return { id: id, answerType: 'openEntry' }; }; var 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 _object_spread_props(_object_spread({}, scoringDataBlankValue), { scoringData: _object_spread({}, scoringDataBlankValue.scoringData, scoringDataMods) }); }); }; var 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 _object_spread({}, interactionDataBlankValue, choices && { choices: choices }); } return interactionDataBlankValue; }); }; var 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 _object_spread({}, wordBankChoice, choiceScoringData && { itemBody: choiceScoringData.scoringData.blankText }); }); }; var insert = function(arr, index) { for(var _len = arguments.length, newItems = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++){ newItems[_key - 2] = arguments[_key]; } return _to_consumable_array(arr.slice(0, index)).concat(_to_consumable_array(newItems), _to_consumable_array(arr.slice(index))); }; var blankIdsFromValues = function(removedBlanks) { var blankIds = []; var scoringDataValue = _to_consumable_array(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; }; function indexForBlank(blankId) { return props.interactionData.blanks.findIndex(function(blank) { return blank.id === blankId; }); } var indexForWordBankChoice = function(choiceId) { return props.interactionData.wordBankChoices.findIndex(function(wordBankChoice) { return wordBankChoice.id === choiceId; }); }; var 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({}, props.properties, newShuffleRules); }; var changeItemState = function(modifications, blankId) { var newestIntData = Object.assign({}, props.interactionData, modifications.interactionData); var newProperties = makeNewProperties(newestIntData); var newMods = { properties: newProperties }; if (modifications.scoringData) { newMods.scoringData = modifications.scoringData; } var newModifications = Object.assign({}, modifications, newMods); props.changeItemState(newModifications, blankId); }; // ================ // HANDLERS // ================ var handleCheckboxChange = function(event) { var interactionData = update(props.interactionData, _define_property({}, event.target.value, { $set: !props.interactionData[event.target.value] })); changeItemState({ interactionData: interactionData }); }; var handleCalculatorTypeChange = function(e, value) { changeItemState({ calculatorType: value }); }; var updateScoringDataForBlank = function(blankId) { return function(scoringDataMods) { var indexForBlankValue = indexForBlank(blankId); var workingItemBody = props.scoringData.workingItemBody; var index = 0; var newWorkingItemBody = workingItemBody.replace(validBlankRegex, function(match) { return index++ === indexForBlankValue ? "`".concat(escape(scoringDataMods.scoringData.blankText), "`") : match; }); var scoringData = update(props.scoringData, { workingItemBody: { $set: newWorkingItemBody }, value: _define_property({}, indexForBlankValue, { $merge: scoringDataMods }) }); var interactionData = props.interactionData; // if the text of a wordbank choice was updated, // reflect the change in the wordBankChoices list if (scoringDataMods.scoringData.choiceId && props.interactionData.wordBankChoices) { var wordBankChoiceIndex = indexForWordBankChoice(scoringDataMods.scoringData.choiceId); if (wordBankChoiceIndex > -1) { interactionData = update(interactionData, { wordBankChoices: _define_property({}, wordBankChoiceIndex, { itemBody: { $set: scoringDataMods.scoringData.blankText } }) }); } } 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) var updateBlank = function(blankId) { return function(modifications) { var indexForBlankValue = indexForBlank(blankId); var blankData = props.interactionData.blanks[indexForBlankValue]; var mods = modifications; if (modifications.choices === null) { var _ = modifications.choices, modsWithoutChoices = _object_without_properties(modifications, [ "choices" ]); mods = modsWithoutChoices; var _props_interactionData_blanks_indexForBlankValue = props.interactionData.blanks[indexForBlankValue], __ = _props_interactionData_blanks_indexForBlankValue.choices, blankDataWithoutChoices = _object_without_properties(_props_interactionData_blanks_indexForBlankValue, [ "choices" ]); blankData = blankDataWithoutChoices; } // if there's a new wordbank choice, add it to the wordBankChoice list var wordBankChoicesMods; if (modifications.choice) { wordBankChoicesMods = update(props.interactionData.wordBankChoices || [ { id: uuid(), itemBody: '' } ], { $push: [ modifications.choice ] }); } // omit "choice" because "choice" is added to wordBankChoices, not the blank itself var ___ = modifications.choice, modsWithoutChoice = _object_without_properties(modifications, [ "choice" ]); mods = modsWithoutChoice; var finalMods = update(blankData, { $merge: mods }); var interactionData = update(props.interactionData, _object_spread({ blanks: _define_property({}, indexForBlankValue, { $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 = props.scoringData.value[indexForBlankValue]; var wordBankChoiceIndex = 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' ] }); } changeItemState({ interactionData: interactionData }, blankId); }; }; var htmlDecode = function(input) { var doc = new DOMParser().parseFromString(input, 'text/html'); return doc.documentElement.textContent; }; var handleDescriptionChange = function(itemBody) { var blankMatches = (itemBody.match(validBlankRegex) || []).map(function(match) { return htmlDecode(match.slice(1, -1)); }); var knownBlanks = blankValues(); var newScoringDataValue = props.scoringData.value || []; var newInteractionDataBlanks = props.interactionData.blanks || []; var newWordBankChoices = props.interactionData.wordBankChoices; var updateBlankTexts = function() { newScoringDataValue = updateScoringDataBlankTexts(newScoringDataValue, newInteractionDataBlanks, blankMatches); newInteractionDataBlanks = updateInteractionDataBlankTexts(newInteractionDataBlanks, newScoringDataValue, blankMatches); newWordBankChoices = 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 = arrayDiff(knownBlanks, blankMatches); var removedBlankIds = 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 = arrayDiff(blankMatches, knownBlanks); newBlanks.forEach(function(newBlank) { var id = uuid(); var index = blankMatches.indexOf(newBlank); newScoringDataValue = insert(newScoringDataValue, index, defaultBlankScoringData(newBlank, id)); newInteractionDataBlanks = insert(newInteractionDataBlanks, index, 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(); } props.changeItemState({ interactionData: _object_spread({ blanks: newInteractionDataBlanks }, newWordBankChoices && { wordBankChoices: newWordBankChoices }), scoringData: { workingItemBody: itemBody, value: newScoringDataValue } }); }; var stemErrors = getErrors('scoringData.workingItemBody') || []; var blankErrors = getErrors([ 'interactionData', 'blanks', '$errors' ]) || []; return /*#__PURE__*/ jsx("div", { ref: ref }, /*#__PURE__*/ jsx(Flex, { direction: "column", padding: "0 0 small 0" }, /*#__PURE__*/ jsx(Text, null, t('Type a statement and surround a word with backticks to indicate where a student will fill in the answer. (e.g., "Roses are `red`, violets are `blue`")'))), /*#__PURE__*/ jsx(QuestionContainer, { disabled: props.overrideEditableForRegrading, enableRichContentEditor: props.enableRichContentEditor, itemBody: props.scoringData.workingItemBody, onDescriptionChange: handleDescriptionChange, onModalClose: props.onModalClose, onModalOpen: props.onModalOpen, openImportModal: props.openImportModal, stemErrors: stemErrors.concat(blankErrors) || [] }, /*#__PURE__*/ jsx(BlanksOptions, { blanks: props.interactionData.blanks, scoringDataValue: props.scoringData.value, fitbCommonWordbankEnabled: props.fitbCommonWordbankEnabled, overrideEditableForRegrading: props.overrideEditableForRegrading, wordBankChoices: props.interactionData.wordBankChoices, notifyScreenreader: props.notifyScreenreader, onModalClose: props.onModalClose, onModalOpen: props.onModalOpen, validationErrorsFromApi: props.validationErrorsFromApi, getErrors: getErrors, updateBlank: updateBlank, updateScoringDataForBlank: updateScoringDataForBlank, isSurvey: props.isSurvey }), /*#__PURE__*/ jsx(WordBankDistractors, { changeItemState: props.changeItemState, indexForWordBankChoice: indexForWordBankChoice, interactionData: props.interactionData, interactionDataErrors: getErrors('interactionData.wordBankChoices') || {}, notifyScreenreader: props.notifyScreenreader, onModalClose: props.onModalClose, onModalOpen: props.onModalOpen, overrideEditableForRegrading: props.overrideEditableForRegrading, scoringData: props.scoringData, isSurvey: props.isSurvey })), /*#__PURE__*/ jsx(QuestionSettingsContainer, { additionalOptions: props.additionalOptions }, /*#__PURE__*/ jsx(QuestionSettingsPanel, { label: t('Options'), defaultExpanded: true }, /*#__PURE__*/ jsx(FormFieldGroup, { rowSpacing: "small", description: /*#__PURE__*/ jsx(ScreenReaderContent, null, t('Fill in the blank options')) }, props.interactionData.wordBankChoices && /*#__PURE__*/ jsx(Checkbox, { label: t('Allow word bank choices to be reused'), value: "reuseWordBankChoices", onChange: handleCheckboxChange, checked: props.interactionData.reuseWordBankChoices, disabled: props.overrideEditableForRegrading }), props.showCalculatorOption && /*#__PURE__*/ jsx(CalculatorOptionWithOqaatAlert, { disabled: props.overrideEditableForRegrading, calculatorValue: props.calculatorType, onCalculatorTypeChange: handleCalculatorTypeChange, oqaatChecked: props.oneQuestionAtATime, onOqaatChange: props.setOneQuestionAtATime }))))); }); RichFillBlankEdit.displayName = 'RichFillBlankEdit'; RichFillBlankEdit.interactionType = RichFillBlankInteractionType; 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, isSurvey: PropTypes.bool }; 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 }; var RichFillBlankEditWithTools = withEditTools(RichFillBlankEdit); var RichFillBlankEditWithStyles = withStyleOverrides(generateStyle, generateComponentTheme)(RichFillBlankEditWithTools); RichFillBlankEditWithStyles.componentId = "Quizzes".concat(RichFillBlankEdit.displayName); export default RichFillBlankEditWithStyles;