react-on-off
Version:
Flexible React components to manage on/off states
408 lines (341 loc) • 11.6 kB
JavaScript
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 };