UNPKG

@instructure/quiz-interactions

Version:

A React UI component Library for quiz interaction types.

185 lines (183 loc) • 9.54 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = withEditTools; 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 _get = _interopRequireDefault(require("lodash/get")); var _isEqual = _interopRequireDefault(require("lodash/isEqual")); var _pick = _interopRequireDefault(require("lodash/pick")); 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 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) { (0, _defineProperty2["default"])(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 = (0, _getPrototypeOf2["default"])(derived); return (0, _possibleConstructorReturn2["default"])(_this, isNativeReflectConstruct() ? Reflect.construct(derived, args || [], (0, _getPrototypeOf2["default"])(_this).constructor) : derived.apply(_this, args)); } // TODO: Kill this HOC and use composition instead. This thing is a nightmare to maintain... /** * Higher Order Component used in Edit views to pass generic helper functions */ function withEditTools(WrappedComponent) { var _Wrapper; var Wrapper = /*#__PURE__*/function (_Component) { function Wrapper() { var _this2; (0, _classCallCheck2["default"])(this, Wrapper); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this2 = _callSuper(this, Wrapper, [].concat(args)); (0, _defineProperty2["default"])(_this2, "node", null); /** * default handling of stem changes */ (0, _defineProperty2["default"])(_this2, "handleDescriptionChange", function (itemBody) { return _this2.props.changeItemState({ itemBody: itemBody }); }); /** * helper function that gives out errors in instui format */ (0, _defineProperty2["default"])(_this2, "getErrors", function (path) { var fallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; var errors = (0, _get["default"])(_this2.props.errors, path); if (errors != null && _this2.props.errorsAreShowing) { return formatErrors(errors); } return fallback; }); (0, _defineProperty2["default"])(_this2, "getWrappedComponent", function () { return _this2.node; }); (0, _defineProperty2["default"])(_this2, "handleRef", function (node) { _this2.node = node; }); return _this2; } (0, _inherits2["default"])(Wrapper, _Component); return (0, _createClass2["default"])(Wrapper, [{ key: "componentDidMount", value: // If the props passed to the component on mount result in validation // errors, call the changeItemState callback with the validation errors to // notify the parent component function componentDidMount() { var itemState = this.getItemState(); if (Object.keys(itemState.errors).length > 0) { this.props.changeItemState(itemState); } } }, { key: "componentDidUpdate", value: function componentDidUpdate(prevProps) { var itemState = this.getItemState(); if (!(0, _isEqual["default"])(itemState.errors, prevProps.errors)) { this.props.changeItemState(itemState); } } }, { key: "getItem", value: function getItem() { var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.props; return (0, _pick["default"])(props, ['calculatorType', 'interactionData', 'itemBody', 'properties', 'scoringAlgorithm', 'scoringData']); } }, { key: "getItemErrors", value: function getItemErrors(item) { return WrappedComponent.interactionType.getErrors(item); } }, { key: "getItemState", value: function getItemState() { var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.props; var item = this.getItem(props); var errors = this.getItemErrors(item); return _objectSpread(_objectSpread({}, item), {}, { errors: errors }); } }, { key: "render", value: /** * render the decorated component, passing helpers through props */ function render() { return /*#__PURE__*/_react["default"].createElement(WrappedComponent, Object.assign({ ref: this.handleRef, onDescriptionChange: this.handleDescriptionChange, getErrors: this.getErrors }, this.props)); } }]); }(_react.Component); _Wrapper = Wrapper; (0, _defineProperty2["default"])(Wrapper, "displayName", "".concat(_Wrapper.name, "(").concat(WrappedComponent.displayName, ")")); // [jsimon]: I originally tried to switch these PropTypes.object calls to WrappedComponent.propTypes.<name> but // these props don't exist on every edit component. To make matters worse, their shape isn't consistent so we can't // make these more specific. (0, _defineProperty2["default"])(Wrapper, "propTypes", { changeItemState: _propTypes["default"].func.isRequired, errors: _propTypes["default"].object, errorsAreShowing: _propTypes["default"].bool, interactionData: _propTypes["default"].object, itemBody: _propTypes["default"].string, properties: _propTypes["default"].object, scoringData: _propTypes["default"].object, children: _propTypes["default"].node }); (0, _defineProperty2["default"])(Wrapper, "defaultProps", { errors: void 0, errorsAreShowing: void 0, interactionData: void 0, itemBody: void 0, properties: void 0, scoringData: void 0, children: void 0 }); Wrapper.WrappedComponent = WrappedComponent; return Wrapper; } // These can be included by components that use withEditTools, to provide // propType validation without including these private, internal props in the // auto-generated documentation. withEditTools.injectedProps = { getErrors: _propTypes["default"].func.isRequired, onDescriptionChange: _propTypes["default"].func.isRequired }; function formatErrors(node) { if (typeof node === 'string') { return { text: node, type: 'error' }; } else if (Array.isArray(node)) { return node.map(formatErrors); } else if (typeof node === 'object') { return Object.keys(node).reduce(function (obj, key) { return _objectSpread(_objectSpread({}, obj), {}, (0, _defineProperty2["default"])({}, key, formatErrors(node[key]))); }, {}); } return node; }