UNPKG

@instructure/quiz-interactions

Version:

A React UI component Library for quiz interaction types.

374 lines (368 loc) • 17.1 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = void 0; var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); 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 _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _react = _interopRequireWildcard(require("react")); var _propTypes = _interopRequireDefault(require("prop-types")); var _isEmpty = _interopRequireDefault(require("lodash/fp/isEmpty")); var _quizRce = require("@instructure/quiz-rce"); var _uiText = require("@instructure/ui-text"); var _uiButtons = require("@instructure/ui-buttons"); var _quizCommon = require("@instructure/quiz-common"); var _uiIcons = require("@instructure/ui-icons"); var _uiModal = require("@instructure/ui-modal"); var _uiHeading = require("@instructure/ui-heading"); var _uiTable = require("@instructure/ui-table"); var _TargetContainer = _interopRequireDefault(require("../common/TargetContainer")); var _formatMessage = _interopRequireDefault(require("@instructure/quiz-i18n/es/format-message")); var _Target = _interopRequireDefault(require("./Target")); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; } 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 = (0, _getPrototypeOf2["default"])(derived); return (0, _possibleConstructorReturn2["default"])(_this, isNativeReflectConstruct() ? Reflect.construct(derived, args || [], (0, _getPrototypeOf2["default"])(_this).constructor) : derived.apply(_this, args)); } /** --- category: HotSpot --- HotSpot Take component ```jsx_example function Example (props) { const exampleProps = { itemBody: 'Which of these players is David Ferrer', interactionData: { imageUrl: 'https://i.ytimg.com/vi/LgkAebhJ7iE/maxresdefault.jpg' }, userResponse: { value: { x: 0.3, y: 0.3 } } } return ( <HotSpotTake {...exampleProps} {...props} /> ) } <SettingsSwitcher locales={LOCALES}> <TakeStateProvider> <Example /> </TakeStateProvider> </SettingsSwitcher> ``` **/ var HotSpotTake = exports["default"] = /*#__PURE__*/function (_Component) { function HotSpotTake(props) { var _this2; (0, _classCallCheck2["default"])(this, HotSpotTake); _this2 = _callSuper(this, HotSpotTake, [props]); (0, _defineProperty2["default"])(_this2, "canAddPoint", function () { var _this2$state = _this2.state, selectedCoordinates = _this2$state.selectedCoordinates, keyboardCoordinates = _this2$state.keyboardCoordinates; var hotspotsCount = _this2.props.interactionData.hotspotsCount; var totalSelections = selectedCoordinates.length + (keyboardCoordinates ? 1 : 0); return totalSelections < (hotspotsCount || 1); }); (0, _defineProperty2["default"])(_this2, "saveSelectedPoint", function () { var _this2$state2 = _this2.state, selectedCoordinates = _this2$state2.selectedCoordinates, keyboardCoordinates = _this2$state2.keyboardCoordinates; var _this2$props = _this2.props, multipleHotSpotEnabled = _this2$props.multipleHotSpotEnabled, hotspotsCount = _this2$props.interactionData.hotspotsCount; if (!keyboardCoordinates) return; var updatedCoordinates = [].concat((0, _toConsumableArray2["default"])(selectedCoordinates), [keyboardCoordinates]); _this2.setState({ selectedCoordinates: updatedCoordinates, keyboardCoordinates: null, isSelectingPoint: false }); var response = !multipleHotSpotEnabled && (!hotspotsCount || hotspotsCount === 1) ? keyboardCoordinates : updatedCoordinates; _this2.props.handleResponseUpdate(response); }); (0, _defineProperty2["default"])(_this2, "handleKeyDown", function (event) { var stepSize = 0.05; var key = event.key; if (!_this2.state.focusedContainer) return; if (_this2.isAnyInputFocused()) return; if (key === 's') { _this2.startSelectingPoint(); } else if (key === 'd' && _this2.state.isSelectingPoint) { _this2.saveSelectedPoint(); } else if (key === 'Backspace' || key === 'Delete') { _this2.handleResetSelections(); } else if (_this2.isArrowKey(key) && _this2.state.keyboardCoordinates) { event.preventDefault(); _this2.movePosition(key, stepSize); } }); (0, _defineProperty2["default"])(_this2, "startSelectingPoint", function () { if (!_this2.canAddPoint()) return; _this2.setState({ keyboardCoordinates: { x: 0.5, y: 0.5 }, isSelectingPoint: true }); }); (0, _defineProperty2["default"])(_this2, "isArrowKey", function (key) { return ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(key); }); (0, _defineProperty2["default"])(_this2, "movePosition", function (key, stepSize) { var _this2$state$keyboard = _this2.state.keyboardCoordinates, x = _this2$state$keyboard.x, y = _this2$state$keyboard.y; var offsets = { ArrowUp: { x: x, y: Math.max(y - stepSize, 0) }, ArrowDown: { x: x, y: Math.min(y + stepSize, 1) }, ArrowLeft: { x: Math.max(x - stepSize, 0), y: y }, ArrowRight: { x: Math.min(x + stepSize, 1), y: y } }; _this2.setState({ keyboardCoordinates: offsets[key] }); }); (0, _defineProperty2["default"])(_this2, "handleSetCoordinates", function (coordinatesArray) { if (!_this2.canAddPoint()) return; var selectedCoordinates = _this2.state.selectedCoordinates; var _this2$props2 = _this2.props, multipleHotSpotEnabled = _this2$props2.multipleHotSpotEnabled, hotspotsCount = _this2$props2.interactionData.hotspotsCount; var x = coordinatesArray[0].x / _this2.targetContainer.state.imageWidth; var y = coordinatesArray[0].y / _this2.targetContainer.state.imageHeight; var updatedCoordinates = [].concat((0, _toConsumableArray2["default"])(selectedCoordinates), [{ x: x, y: y }]); _this2.setState({ selectedCoordinates: updatedCoordinates }); var response = !multipleHotSpotEnabled && (!hotspotsCount || hotspotsCount === 1) ? { x: x, y: y } : updatedCoordinates; _this2.props.handleResponseUpdate(response); }); (0, _defineProperty2["default"])(_this2, "targetContainerRef", function (node) { _this2.targetContainer = node; }); (0, _defineProperty2["default"])(_this2, "handleResetSelections", function () { _this2.setState({ selectedCoordinates: [], keyboardCoordinates: null }); _this2.props.handleResponseUpdate([]); }); (0, _defineProperty2["default"])(_this2, "handleCloseShortcutsClick", function () { _this2.setState({ shortcutsModalOpen: false }); }); (0, _defineProperty2["default"])(_this2, "handleOpenShortcutsClick", function () { _this2.setState({ shortcutsModalOpen: true }); }); _this2.state = { selectedCoordinates: [], keyboardCoordinates: null, isSelectingPoint: false, focusedContainer: null, shortcutsModalOpen: false }; return _this2; } (0, _inherits2["default"])(HotSpotTake, _Component); return (0, _createClass2["default"])(HotSpotTake, [{ key: "componentDidMount", value: function componentDidMount() { var _this$props$userRespo; window.addEventListener('keydown', this.handleKeyDown); var value = (_this$props$userRespo = this.props.userResponse) === null || _this$props$userRespo === void 0 ? void 0 : _this$props$userRespo.value; if (!(0, _isEmpty["default"])(value)) { this.setState({ selectedCoordinates: Array.isArray(value) ? value : [value] }); } } }, { key: "componentWillUnmount", value: function componentWillUnmount() { window.removeEventListener('keydown', this.handleKeyDown); } }, { key: "isAnyInputFocused", value: function isAnyInputFocused() { var inputs = document.querySelectorAll('input'); return Array.from(inputs).some(function (input) { return input === document.activeElement; }); } }, { key: "render", value: // =========== // RENDER // =========== function render() { var _this3 = this; var _this$state = this.state, selectedCoordinates = _this$state.selectedCoordinates, keyboardCoordinates = _this$state.keyboardCoordinates; var hotspots = selectedCoordinates.length > 0 || keyboardCoordinates ? [].concat((0, _toConsumableArray2["default"])(selectedCoordinates.map(function (coordinate) { return { coordinates: [coordinate], drawingType: _Target["default"] }; })), (0, _toConsumableArray2["default"])(keyboardCoordinates ? [{ coordinates: [keyboardCoordinates], drawingType: _Target["default"] }] : [])) : [{ coordinates: [{}], drawingType: _Target["default"] }]; var keyboardShortcuts = [{ id: 'select', shortcut: 'S', action: (0, _formatMessage["default"])('Select a point') }, { id: 'save', shortcut: 'D', action: (0, _formatMessage["default"])('Save the position') }, { id: 'delete', shortcut: 'Backspace/Delete', action: (0, _formatMessage["default"])('Clear all selections') }, { id: 'move', shortcut: 'Arrow keys', action: (0, _formatMessage["default"])('Move the point') }]; return /*#__PURE__*/_react["default"].createElement(_quizRce.ItemBodyWrapper, { itemBody: this.props.itemBody }, /*#__PURE__*/_react["default"].createElement("div", { className: "fs-mask" }, /*#__PURE__*/_react["default"].createElement(_TargetContainer["default"], { hotspots: hotspots, handleSetCoordinates: this.handleSetCoordinates, ref: this.targetContainerRef, url: this.props.interactionData.imageUrl, onFocus: function onFocus() { return _this3.setState({ focusedContainer: _this3.targetContainer }); }, onBlur: function onBlur() { return _this3.setState({ focusedContainer: null }); } })), /*#__PURE__*/_react["default"].createElement(_quizCommon.Flex, { direction: "row", justifyItems: "space-between", alignItems: "center", gap: "small", margin: "x-small 0 0" }, /*#__PURE__*/_react["default"].createElement(_quizCommon.Flex.Item, null, this.state.selectedCoordinates.length > 0 && /*#__PURE__*/_react["default"].createElement(_uiButtons.CondensedButton, { onClick: this.handleResetSelections, "data-automation": "sdk-hotspot-take-clear-selections-button" }, (0, _formatMessage["default"])('Clear my selection'))), /*#__PURE__*/_react["default"].createElement(_quizCommon.Flex.Item, null, /*#__PURE__*/_react["default"].createElement(_uiButtons.IconButton, { color: "secondary", screenReaderLabel: (0, _formatMessage["default"])('Show keyboard shortcuts'), withBackground: false, withBorder: false, onClick: this.handleOpenShortcutsClick }, /*#__PURE__*/_react["default"].createElement(_uiIcons.IconKeyboardShortcutsLine, null)), /*#__PURE__*/_react["default"].createElement(_uiModal.Modal, { size: "medium", label: (0, _formatMessage["default"])('Keyboard shortcuts'), open: this.state.shortcutsModalOpen, onDismiss: this.handleCloseShortcutsClick, shouldCloseOnDocumentClick: true }, /*#__PURE__*/_react["default"].createElement(_uiModal.Modal.Header, null, /*#__PURE__*/_react["default"].createElement(_uiHeading.Heading, { level: "h2" }, (0, _formatMessage["default"])('Keyboard shortcuts')), /*#__PURE__*/_react["default"].createElement(_uiButtons.CloseButton, { placement: "end", offset: "small", onClick: this.handleCloseShortcutsClick, screenReaderLabel: (0, _formatMessage["default"])('Close') })), /*#__PURE__*/_react["default"].createElement(_uiModal.Modal.Body, null, /*#__PURE__*/_react["default"].createElement(_uiTable.Table, { caption: (0, _formatMessage["default"])('Keyboard shortcuts') }, /*#__PURE__*/_react["default"].createElement(_uiTable.Table.Head, null, /*#__PURE__*/_react["default"].createElement(_uiTable.Table.Row, null, /*#__PURE__*/_react["default"].createElement(_uiTable.Table.ColHeader, { id: "shortcut" }, (0, _formatMessage["default"])('Shortcut')), /*#__PURE__*/_react["default"].createElement(_uiTable.Table.ColHeader, { id: "action" }, (0, _formatMessage["default"])('Action')))), /*#__PURE__*/_react["default"].createElement(_uiTable.Table.Body, null, keyboardShortcuts.map(function (_ref) { var id = _ref.id, shortcut = _ref.shortcut, action = _ref.action; return /*#__PURE__*/_react["default"].createElement(_uiTable.Table.Row, { key: id }, /*#__PURE__*/_react["default"].createElement(_uiTable.Table.RowHeader, null, /*#__PURE__*/_react["default"].createElement(_uiText.Text, { id: "shortcut-".concat(id) }, shortcut)), /*#__PURE__*/_react["default"].createElement(_uiTable.Table.Cell, null, /*#__PURE__*/_react["default"].createElement(_uiText.Text, { id: "action-".concat(id) }, action))); })))), /*#__PURE__*/_react["default"].createElement(_uiModal.Modal.Footer, null, /*#__PURE__*/_react["default"].createElement(_uiButtons.Button, { onClick: this.handleCloseShortcutsClick }, (0, _formatMessage["default"])('Close'))))))); } }]); }(_react.Component); (0, _defineProperty2["default"])(HotSpotTake, "propTypes", { handleResponseUpdate: _propTypes["default"].func.isRequired, interactionData: _propTypes["default"].shape({ imageUrl: _propTypes["default"].string.isRequired, hotspotsCount: _propTypes["default"].number }).isRequired, itemBody: _propTypes["default"].string.isRequired, userResponse: _propTypes["default"].shape({ value: _propTypes["default"].oneOfType([_propTypes["default"].arrayOf(_propTypes["default"].shape({ x: _propTypes["default"].number, y: _propTypes["default"].number })), _propTypes["default"].shape({ x: _propTypes["default"].number, y: _propTypes["default"].number })]).isRequired }), scoringData: _propTypes["default"].shape({ value: _propTypes["default"].arrayOf(_propTypes["default"].shape({ x: _propTypes["default"].number, y: _propTypes["default"].number })).isRequired }), multipleHotSpotEnabled: _propTypes["default"].bool });