UNPKG

@faizaanceg/snitch

Version:

Snitch - Control visibility of your views

201 lines (181 loc) 5.34 kB
import PropTypes from 'prop-types'; import { useEffect, useMemo } from 'react'; import { connect } from 'react-redux'; function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } var actionTypes = { OPEN: "[Snitch] Start", CLOSE: "[Snitch] Stop", TOGGLE: "[Snitch] Toggle" }; var initialState = { listeningTo: [], visibilityById: {} }; var actions = { listen: function listen(_) { return Object.assign({}, _, { type: actionTypes.OPEN }); }, unlisten: function unlisten(key) { return { key: key, type: actionTypes.CLOSE }; }, setVisibility: function setVisibility(props, trigger) { return { props: props, trigger: trigger, type: actionTypes.TOGGLE }; } }; var snitchMiddleware = function snitchMiddleware(reducerKey) { return function (store) { return function (next) { return function (action) { var result = next(action); if (action.type.startsWith("[Snitch]")) { return result; } store.getState()[reducerKey].listeningTo.filter(function (_ref) { var type = _ref[2], updateWhen = _ref[3]; return type === action.type && updateWhen(action); }).forEach(function (_) { return store.dispatch(actions.setVisibility(_, action)); }); return result; }; }; }; }; var snitchReducer = function snitchReducer(state, action) { if (state === void 0) { state = initialState; } switch (action.type) { case actionTypes.OPEN: { var _Object$assign; var opensOn = action.opensOn, closesOn = action.closesOn, key = action.key, opensWhen = action.opensWhen, closesWhen = action.closesWhen, defaultOpen = action.defaultOpen; return Object.assign({}, state, { listeningTo: [].concat(state.listeningTo, [].concat(opensOn).map(function (_) { return [key, 1, _, opensWhen]; }), [].concat(closesOn).map(function (_) { return [key, 0, _, closesWhen]; })), visibilityById: Object.assign({}, state.visibilityById, (_Object$assign = {}, _Object$assign[key] = { trigger: {}, isVisible: defaultOpen }, _Object$assign)) }); } case actionTypes.CLOSE: { var _Object$assign2; return Object.assign({}, state, { listeningTo: state.listeningTo.filter(function (_ref2) { var key = _ref2[0]; return key !== action.key; }), visibilityById: Object.assign({}, state.visibilityById, (_Object$assign2 = {}, _Object$assign2[action.key] = undefined, _Object$assign2)) }); } case actionTypes.TOGGLE: { var _Object$assign3; var _action$props = action.props, _key = _action$props[0], snitch = _action$props[1], trigger = action.trigger; return Object.assign({}, state, { visibilityById: Object.assign({}, state.visibilityById, (_Object$assign3 = {}, _Object$assign3[_key] = { isVisible: snitch === 1, trigger: trigger }, _Object$assign3)) }); } default: return state; } }; function Snitch(_ref) { var dispatch = _ref.dispatch, render = _ref.render, props = _objectWithoutPropertiesLoose(_ref, ["dispatch", "render"]); var key = useMemo(function () { return Symbol(); }, []); useEffect(function () { dispatch(actions.listen(Object.assign({}, props, { key: key }))); return function () { return dispatch(actions.unlisten(key)); }; }, []); var _props$visibilityById = props.visibilityById[key], state = _props$visibilityById === void 0 ? { trigger: {}, isVisible: props.defaultOpen } : _props$visibilityById; var setVisibility = function setVisibility(_) { return dispatch(actions.setVisibility([key, _], {})); }; return render({ show: state.isVisible, open: function open() { return setVisibility(1); }, close: function close() { return setVisibility(0); } }, state.trigger); } Snitch.propTypes = { closesOn: PropTypes.oneOfType([PropTypes.string, PropTypes.array]), closesWhen: PropTypes.func, defaultOpen: PropTypes.bool, dispatch: PropTypes.func.isRequired, opensOn: PropTypes.oneOfType([PropTypes.string, PropTypes.array]), opensWhen: PropTypes.func, render: PropTypes.func.isRequired, visibilityById: PropTypes.object.isRequired }; Snitch.defaultProps = { closesOn: [], closesWhen: function closesWhen() { return true; }, defaultOpen: false, opensOn: [], opensWhen: function opensWhen() { return true; } }; var connectWrapper = function connectWrapper(Component, reducerKey) { return connect(function (state) { return { visibilityById: state[reducerKey].visibilityById }; })(Component); }; export { snitchMiddleware, snitchReducer, Snitch, connectWrapper };