UNPKG

react-on-off

Version:

Flexible React components to manage on/off states

408 lines (341 loc) 11.6 kB
import React, { Component, createContext } from 'react'; import PropTypes from 'prop-types'; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } _setPrototypeOf(subClass.prototype, superClass && superClass.prototype); if (superClass) _setPrototypeOf(subClass, superClass); } function _getPrototypeOf(o) { _getPrototypeOf = Object.getPrototypeOf || function _getPrototypeOf(o) { return o.__proto__; }; return _getPrototypeOf(o); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } var noop = function noop() {}; var OnOff = /*#__PURE__*/ function (_Component) { function OnOff() { var _getPrototypeOf2; var _temp, _this; _classCallCheck(this, OnOff); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return _possibleConstructorReturn(_this, (_temp = _this = _possibleConstructorReturn(this, (_getPrototypeOf2 = _getPrototypeOf(OnOff)).call.apply(_getPrototypeOf2, [this].concat(args))), _defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "state", { on: Boolean(_this.props.defaultOn) }), "getOnState", function () { return _this.isControlled() ? Boolean(_this.props.on) : _this.state.on; }), "setOnState", function (nextOn) { var prevOn = _this.getOnState(); var stateChanged = prevOn !== nextOn; var isControlled = _this.isControlled(); if (isControlled && stateChanged) { _this.props.onChange(nextOn); } else if (!isControlled && stateChanged) { _this.setState({ on: nextOn }, function () { return _this.props.onChange(nextOn); }); } }), "setOn", function () { return _this.setOnState(true); }), "setOff", function () { return _this.setOnState(false); }), "toggle", function () { return _this.setOnState(!_this.getOnState()); }), _temp)); } _createClass(OnOff, [{ key: "shouldComponentUpdate", value: function shouldComponentUpdate(nextProps, nextState) { return this.isControlled() ? this.props.on !== nextProps.on : this.state.on !== nextState.on; } }, { key: "isControlled", value: function isControlled() { return this.props.on !== undefined; } }, { key: "render", value: function render() { var on = this.getOnState(); return this.props.children({ on: on, off: !on, setOn: this.setOn, setOff: this.setOff, toggle: this.toggle }); } }]); _inherits(OnOff, _Component); return OnOff; }(Component); _defineProperty(_defineProperty(OnOff, "propTypes", { defaultOn: PropTypes.bool, on: PropTypes.bool, onChange: PropTypes.func, children: PropTypes.func.isRequired }), "defaultProps", { defaultOn: false, onChange: noop }); var defaultContext = { on: undefined, setOn: noop, setOff: noop, toggle: noop, registerItem: function registerItem(id) { return id || "_internalDefaultId"; }, unregisterItem: noop }; var _createContext = createContext(defaultContext), Provider = _createContext.Provider, Consumer = _createContext.Consumer; var getNextIndex = function getNextIndex(index) { return function () { return index++; }; }; var generateId = getNextIndex(0); var OnOffCollection = /*#__PURE__*/ function (_Component) { function OnOffCollection() { var _getPrototypeOf2; var _temp, _this; _classCallCheck(this, OnOffCollection); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return _possibleConstructorReturn(_this, (_temp = _this = _possibleConstructorReturn(this, (_getPrototypeOf2 = _getPrototypeOf(OnOffCollection)).call.apply(_getPrototypeOf2, [this].concat(args))), _defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "getOnState", function () { return _this.isControlled() ? _this.props.on : _this.state.on; }), "setOnState", function (nextOnId) { var prevOnId = _this.getOnState(); var stateChanged = prevOnId !== nextOnId; var isControlled = _this.isControlled(); if (isControlled && stateChanged) { _this.props.onChange(nextOnId); } else if (!isControlled && stateChanged) { _this.setState({ on: nextOnId }, function () { return _this.props.onChange(nextOnId); }); } }), "setOn", function (nextOnId) { return _this.setOnState(nextOnId); }), "setOff", function (nextOnId) { if (nextOnId === _this.state.on) { _this.setOnState(null); } }), "toggle", function (nextOnId) { var prevOnId = _this.getOnState(); _this.setOnState(prevOnId !== nextOnId ? nextOnId : null); }), "registerItem", function (itemId) { return itemId || String(_this.idGenerator()); }), "unregisterItem", function (itemId) { if (itemId === _this.getOnState()) { _this.setOnState(null); } }), "idGenerator", generateId), "state", { on: _this.props.defaultOn, setOn: _this.setOn, setOff: _this.setOff, toggle: _this.toggle, registerItem: _this.registerItem, unregisterItem: _this.unregisterItem }), _temp)); } _createClass(OnOffCollection, [{ key: "shouldComponentUpdate", value: function shouldComponentUpdate(nextProps, nextState) { return this.isControlled() ? this.props.on !== nextProps.on : this.state.on !== nextState.on; } }, { key: "isControlled", value: function isControlled() { return this.props.on !== undefined; } }, { key: "render", value: function render() { return React.createElement(Provider, { value: _objectSpread({}, this.state, { on: this.getOnState() }) }, this.props.children); } }]); _inherits(OnOffCollection, _Component); return OnOffCollection; }(Component); _defineProperty(_defineProperty(OnOffCollection, "propTypes", { defaultOn: PropTypes.string, on: PropTypes.string, onChange: PropTypes.func }), "defaultProps", { defaultOn: null, onChange: noop }); var OnOffItemImpl = /*#__PURE__*/ function (_Component) { function OnOffItemImpl() { var _getPrototypeOf2; var _temp, _this; _classCallCheck(this, OnOffItemImpl); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return _possibleConstructorReturn(_this, (_temp = _this = _possibleConstructorReturn(this, (_getPrototypeOf2 = _getPrototypeOf(OnOffItemImpl)).call.apply(_getPrototypeOf2, [this].concat(args))), _defineProperty(_defineProperty(_defineProperty(_defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "state", { id: _this.props.context.registerItem(_this.props.id) }), "setOn", function () { return _this.props.context.setOn(_this.state.id); }), "setOff", function () { return _this.props.context.setOff(_this.state.id); }), "toggle", function () { return _this.props.context.toggle(_this.state.id); }), _temp)); } _createClass(OnOffItemImpl, [{ key: "componentWillUnmount", value: function componentWillUnmount() { this.props.context.unregisterItem(this.props.id); } }, { key: "shouldComponentUpdate", value: function shouldComponentUpdate(nextProps) { var id = this.state.id; var prevOnId = this.props.context.on; var nextOnId = nextProps.context.on; var itemIsOn = prevOnId === id; return itemIsOn && nextOnId !== id || !itemIsOn && nextOnId === id; } }, { key: "render", value: function render() { var id = this.state.id; var on = this.props.context.on === id; return this.props.children({ id: id, on: on, off: !on, setOn: this.setOn, setOff: this.setOff, toggle: this.toggle }); } }]); _inherits(OnOffItemImpl, _Component); return OnOffItemImpl; }(Component); _defineProperty(OnOffItemImpl, "propTypes", { id: PropTypes.string, children: PropTypes.func.isRequired, context: PropTypes.shape({ on: PropTypes.string, setOn: PropTypes.func.isRequired, setOff: PropTypes.func.isRequired, toggle: PropTypes.func.isRequired, registerItem: PropTypes.func.isRequired, unregisterItem: PropTypes.func.isRequired }).isRequired }); var OnOffItem = function OnOffItem(props) { return React.createElement(Consumer, null, function (contextValue) { return React.createElement(OnOffItemImpl, _extends({}, props, { context: contextValue })); }); }; OnOffItem.propTypes = { id: PropTypes.string, children: PropTypes.func.isRequired }; export { OnOff, OnOffCollection, OnOffItem };