quiz-interactions
Version:
A React UI component Library for quiz interaction types.
259 lines (210 loc) • 10.3 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
var _react = _interopRequireWildcard(require("react"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _reactDom = _interopRequireDefault(require("react-dom"));
var _debounce = _interopRequireDefault(require("lodash/debounce"));
var _partial = _interopRequireDefault(require("lodash/partial"));
var _uiThemeable = require("@instructure/ui-themeable");
var _uiA11y = require("@instructure/ui-a11y");
var _uiElements = require("@instructure/ui-elements");
var _Errors = _interopRequireDefault(require("../../../common/edit/components/Errors"));
var _ContentEditable = _interopRequireDefault(require("../../../common/edit/components/ContentEditable"));
var _editStemController = _interopRequireDefault(require("./editStemController"));
var _theme = _interopRequireDefault(require("./theme"));
var _formatMessage = _interopRequireDefault(require("@instructure/quiz-i18n/lib/format-message"));
var _dec, _class, _class2, _temp;
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(source, true).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
var styles = {
componentId: 'sgCkN',
template: function template(theme) {
return "\n\n.sgCkN_fiOv{display:inline-block}\n\n[contenteditable=true]:empty:before{color:".concat(theme.tableColor || 'inherit', ";content:attr(placeholder)}\n\n.sgCkN_edUw{color:").concat(theme.editStemColor || 'inherit', ";display:inline-block;font-family:").concat(theme.editStemFontFamily || 'inherit', ";font-size:").concat(theme.editStemFontSize || 'inherit', ";font-weight:").concat(theme.editStemFontWeight || 'inherit', ";line-height:").concat(theme.editStemLineHeight || 'inherit', ";white-space:pre-wrap}\n\n.sgCkN_edUw:focus{outline:0 none}\n\n.sgCkN_eMDV{border:").concat(theme.highlightBorder || 'inherit', " solid ").concat(theme.highlightColor || 'inherit', ";border-radius:").concat(theme.highlightBorderRadius || 'inherit', ";margin-left:").concat(theme.highlightMargin || 'inherit', ";margin-right:").concat(theme.highlightMargin || 'inherit', ";padding:").concat(theme.highlightPadding || 'inherit', ";position:relative;word-wrap:break-word}");
},
'blankScreenReaderContentWrapper': 'sgCkN_fiOv',
'editableText': 'sgCkN_edUw',
'highlight': 'sgCkN_eMDV'
};
var NBSP_CHAR_CODE = 160;
var _ref =
/*#__PURE__*/
_react.default.createElement("hr", null);
var EditStem = (_dec = (0, _uiThemeable.themeable)(_theme.default, styles), _dec(_class = (_temp = _class2 =
/*#__PURE__*/
function (_Component) {
(0, _inherits2.default)(EditStem, _Component);
function EditStem(props) {
var _this;
(0, _classCallCheck2.default)(this, EditStem);
_this = (0, _possibleConstructorReturn2.default)(this, (0, _getPrototypeOf2.default)(EditStem).call(this, props));
_this.state = {
isFocused: false // own functions for stubbing purposes
};
_this.handlePaste = function (stemItem, e) {
_this.controller.handlePaste(e);
_this.props.onStemChange(stemItem, e);
};
_this.setFocus = function (isFocused) {
_this.setState({
isFocused: isFocused
});
};
_this.renderStemItem = function (stemItem) {
return stemItem.type === 'text' ? _this.renderContentEditable(stemItem) : _this.renderBlank(stemItem);
};
_this.controller = new _editStemController.default(_objectSpread({}, props, {
styles: styles
}));
_this.stemItemRefs = {};
return _this;
}
(0, _createClass2.default)(EditStem, [{
key: "_clearInterval",
value: function _clearInterval(cb) {
clearInterval(cb);
}
}, {
key: "_setInterval",
value: function _setInterval(cb, time) {
setInterval(cb, time);
} // =============
// LIFECYCLE
// =============
}, {
key: "componentDidMount",
value: function componentDidMount() {
var _this2 = this;
var oldOnSelectionChange = document.onselectionchange;
this._dom = _reactDom.default.findDOMNode(this);
var newOnSelectionChange = (0, _debounce.default)(function () {
var sel = window.getSelection();
var anchor = sel.anchorNode;
if (!anchor) return;
if (_this2._dom.contains(anchor) || // next line needed because of weird IE11 behavior
_this2._dom.contains(anchor.parentNode)) {
_this2.props.setSelectedText(sel.toString());
}
}, 100);
document.onselectionchange = function (e) {
oldOnSelectionChange && oldOnSelectionChange(e);
newOnSelectionChange();
};
this._oldOnSelectionChange = oldOnSelectionChange;
}
}, {
key: "componentWillUnmount",
value: function componentWillUnmount() {
document.onselectionchange = this._oldOnSelectionChange;
}
}, {
key: "componentWillReceiveProps",
value: function componentWillReceiveProps(nextProps) {
this.controller.componentWillReceiveProps(_objectSpread({}, nextProps, {
styles: styles
}));
}
}, {
key: "componentDidUpdate",
value: function componentDidUpdate(prevProps) {
if (!this.state.isFocused) {
return;
}
var focusData = this.controller.getFocusData(prevProps);
if (!focusData) {
return;
}
var focusRef = this.stemItemRefs[focusData.stemItem.id];
focusData.stemItem.type === 'blank' ? focusRef.focus() : focusRef.focusAndSetCursorOnPosition(focusData.cursorPosition);
}
}, {
key: "renderContentEditable",
// =============
// RENDERING
// =============
value: function renderContentEditable(stemItem) {
var _this3 = this;
var usePlaceholder = this.props.stemItems.length <= 1 && !this.state.isFocused;
var placeholder = usePlaceholder ? (0, _formatMessage.default)('Type a statement...') : '';
var content = this.controller.textForStemItem(stemItem);
if (!content || content === String.fromCharCode(NBSP_CHAR_CODE)) {
// nbsp is used to give a width to a final stem item if blank
// if we only have one stem, just use the placeholder to do this
content = usePlaceholder ? '' : String.fromCharCode(NBSP_CHAR_CODE);
}
return _react.default.createElement(_ContentEditable.default, {
label: _react.default.createElement(_uiA11y.ScreenReaderContent, null, (0, _formatMessage.default)('Statement')),
key: stemItem.id,
id: stemItem.id,
ref: function ref(span) {
_this3.stemItemRefs[stemItem.id] = span;
},
placeholder: placeholder,
enableFormatting: false,
disabled: this.props.disabled,
content: content,
onChange: (0, _partial.default)(this.props.onStemChange, stemItem),
onPaste: (0, _partial.default)(this.handlePaste, stemItem),
onKeyDown: this.props.onCreateBlankHotkey,
className: styles.editableText
});
}
}, {
key: "renderBlank",
value: function renderBlank(stemItem) {
var _this4 = this;
var dismissible = !this.props.disabled;
var text = this.controller.textForStemItem(stemItem);
return _react.default.createElement(_uiElements.Tag, {
key: stemItem.id,
dismissible: dismissible,
elementRef: function elementRef(button) {
_this4.stemItemRefs[stemItem.id] = button;
},
onClick: dismissible ? (0, _partial.default)(this.props.destroyBlank, stemItem) : null,
size: "large",
text: _react.default.createElement(_uiA11y.AccessibleContent, {
alt: (0, _formatMessage.default)('Delete "{ text }" blank', {
text: text
})
}, text),
variant: "inline"
});
}
}, {
key: "render",
value: function render() {
this.stemItemRefs = {};
return _react.default.createElement("div", {
onFocus: (0, _partial.default)(this.setFocus, true),
onBlur: (0, _partial.default)(this.setFocus, false)
}, _react.default.createElement(_Errors.default, {
errorList: this.props.errors
}, this.props.stemItems.map(this.renderStemItem)), _ref);
}
}]);
EditStem.displayName = "EditStem";
return EditStem;
}(_react.Component), _class2.propTypes = {
disabled: _propTypes.default.bool,
errors: _propTypes.default.array,
destroyBlank: _propTypes.default.func.isRequired,
onCreateBlankHotkey: _propTypes.default.func.isRequired,
onStemChange: _propTypes.default.func.isRequired,
setSelectedText: _propTypes.default.func.isRequired,
stemItems: _propTypes.default.array.isRequired
}, _class2.defaultProps = {
disabled: false,
errors: void 0
}, _temp)) || _class);
exports.default = EditStem;