@instructure/quiz-interactions
Version:
A React UI component Library for quiz interaction types.
185 lines (183 loc) • 9.54 kB
JavaScript
;
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;
}