UNPKG

semantic-ui-react

Version:
219 lines (161 loc) 9.74 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = exports.getAutoControlledStateValue = void 0; var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread")); 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 _getPrototypeOf3 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf")); var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized")); var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _isUndefined2 = _interopRequireDefault(require("lodash/isUndefined")); var _startsWith2 = _interopRequireDefault(require("lodash/startsWith")); var _filter2 = _interopRequireDefault(require("lodash/filter")); var _isEmpty2 = _interopRequireDefault(require("lodash/isEmpty")); var _keys2 = _interopRequireDefault(require("lodash/keys")); var _intersection2 = _interopRequireDefault(require("lodash/intersection")); var _has2 = _interopRequireDefault(require("lodash/has")); var _each2 = _interopRequireDefault(require("lodash/each")); var _invoke2 = _interopRequireDefault(require("lodash/invoke")); var _react = require("react"); var getDefaultPropName = function getDefaultPropName(prop) { return "default".concat(prop[0].toUpperCase() + prop.slice(1)); }; /** * Return the auto controlled state value for a give prop. The initial value is chosen in this order: * - regular props * - then, default props * - then, initial state * - then, `checked` defaults to false * - then, `value` defaults to '' or [] if props.multiple * - else, undefined * * @param {string} propName A prop name * @param {object} [props] A props object * @param {object} [state] A state object * @param {boolean} [includeDefaults=false] Whether or not to heed the default props or initial state */ var getAutoControlledStateValue = function getAutoControlledStateValue(propName, props, state) { var includeDefaults = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; // regular props var propValue = props[propName]; if (propValue !== undefined) return propValue; if (includeDefaults) { // defaultProps var defaultProp = props[getDefaultPropName(propName)]; if (defaultProp !== undefined) return defaultProp; // initial state - state may be null or undefined if (state) { var initialState = state[propName]; if (initialState !== undefined) return initialState; } } // React doesn't allow changing from uncontrolled to controlled components, // default checked/value if they were not present. if (propName === 'checked') return false; if (propName === 'value') return props.multiple ? [] : ''; // otherwise, undefined }; exports.getAutoControlledStateValue = getAutoControlledStateValue; var AutoControlledComponent = /*#__PURE__*/ function (_Component) { (0, _inherits2["default"])(AutoControlledComponent, _Component); function AutoControlledComponent() { var _getPrototypeOf2; var _this; (0, _classCallCheck2["default"])(this, AutoControlledComponent); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = (0, _possibleConstructorReturn2["default"])(this, (_getPrototypeOf2 = (0, _getPrototypeOf3["default"])(AutoControlledComponent)).call.apply(_getPrototypeOf2, [this].concat(args))); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "trySetState", function (state, callback) { var newState = Object.keys(state).reduce(function (acc, prop) { // ignore props defined by the parent if (_this.props[prop] !== undefined) return acc; acc[prop] = state[prop]; return acc; }, {}); if (Object.keys(newState).length > 0) _this.setState(newState, callback); }); var autoControlledProps = _this.constructor.autoControlledProps; var _state = (0, _invoke2["default"])((0, _assertThisInitialized2["default"])(_this), 'getInitialAutoControlledState', _this.props) || {}; if (process.env.NODE_ENV !== 'production') { var _this$constructor = _this.constructor, defaultProps = _this$constructor.defaultProps, name = _this$constructor.name, propTypes = _this$constructor.propTypes; // require static autoControlledProps if (!autoControlledProps) { console.error("Auto controlled ".concat(name, " must specify a static autoControlledProps array.")); } // require propTypes (0, _each2["default"])(autoControlledProps, function (prop) { var defaultProp = getDefaultPropName(prop); // regular prop if (!(0, _has2["default"])(propTypes, defaultProp)) { console.error("".concat(name, " is missing \"").concat(defaultProp, "\" propTypes validation for auto controlled prop \"").concat(prop, "\".")); } // its default prop if (!(0, _has2["default"])(propTypes, prop)) { console.error("".concat(name, " is missing propTypes validation for auto controlled prop \"").concat(prop, "\".")); } }); // prevent autoControlledProps in defaultProps // // When setting state, auto controlled props values always win (so the parent can manage them). // It is not reasonable to decipher the difference between props from the parent and defaultProps. // Allowing defaultProps results in trySetState always deferring to the defaultProp value. // Auto controlled props also listed in defaultProps can never be updated. // // To set defaults for an AutoControlled prop, you can set the initial state in the // constructor or by using an ES7 property initializer: // https://babeljs.io/blog/2015/06/07/react-on-es6-plus#property-initializers var illegalDefaults = (0, _intersection2["default"])(autoControlledProps, (0, _keys2["default"])(defaultProps)); if (!(0, _isEmpty2["default"])(illegalDefaults)) { console.error(['Do not set defaultProps for autoControlledProps. You can set defaults by', 'setting state in the constructor or using an ES7 property initializer', '(https://babeljs.io/blog/2015/06/07/react-on-es6-plus#property-initializers)', "See ".concat(name, " props: \"").concat(illegalDefaults, "\".")].join(' ')); } // prevent listing defaultProps in autoControlledProps // // Default props are automatically handled. // Listing defaults in autoControlledProps would result in allowing defaultDefaultValue props. var illegalAutoControlled = (0, _filter2["default"])(autoControlledProps, function (prop) { return (0, _startsWith2["default"])(prop, 'default'); }); if (!(0, _isEmpty2["default"])(illegalAutoControlled)) { console.error(['Do not add default props to autoControlledProps.', 'Default props are automatically handled.', "See ".concat(name, " autoControlledProps: \"").concat(illegalAutoControlled, "\".")].join(' ')); } } // Auto controlled props are copied to state. // Set initial state by copying auto controlled props to state. // Also look for the default prop for any auto controlled props (foo => defaultFoo) // so we can set initial values from defaults. var initialAutoControlledState = autoControlledProps.reduce(function (acc, prop) { acc[prop] = getAutoControlledStateValue(prop, _this.props, _state, true); if (process.env.NODE_ENV !== 'production') { var defaultPropName = getDefaultPropName(prop); var _name = _this.constructor.name; // prevent defaultFoo={} along side foo={} if (!(0, _isUndefined2["default"])(_this.props[defaultPropName]) && !(0, _isUndefined2["default"])(_this.props[prop])) { console.error("".concat(_name, " prop \"").concat(prop, "\" is auto controlled. Specify either ").concat(defaultPropName, " or ").concat(prop, ", but not both.")); } } return acc; }, {}); _this.state = (0, _objectSpread2["default"])({}, _state, initialAutoControlledState); return _this; } // eslint-disable-next-line camelcase (0, _createClass2["default"])(AutoControlledComponent, [{ key: "UNSAFE_componentWillReceiveProps", value: function UNSAFE_componentWillReceiveProps(nextProps) { var autoControlledProps = this.constructor.autoControlledProps; // Solve the next state for autoControlledProps var newState = autoControlledProps.reduce(function (acc, prop) { var isNextDefined = !(0, _isUndefined2["default"])(nextProps[prop]); // if next is defined then use its value if (isNextDefined) acc[prop] = nextProps[prop]; return acc; }, {}); if (Object.keys(newState).length > 0) this.setState(newState); } /** * Safely attempt to set state for props that might be controlled by the user. * Second argument is a state object that is always passed to setState. * @param {object} state State that corresponds to controlled props. * @param {function} [callback] Callback which is called after setState applied. */ }]); return AutoControlledComponent; }(_react.Component); exports["default"] = AutoControlledComponent;