@faizaanceg/snitch
Version:
Snitch - Control visibility of your views
201 lines (181 loc) • 5.34 kB
JavaScript
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 };