@gechiui/components
Version:
UI components for GeChiUI.
275 lines (229 loc) • 7.71 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.composeStateReducers = void 0;
exports.useInputControlStateReducer = useInputControlStateReducer;
var _lodash = require("lodash");
var _element = require("@gechiui/element");
var _state = require("./state");
var actions = _interopRequireWildcard(require("./actions"));
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
/**
* External dependencies
*/
/**
* GeChiUI dependencies
*/
/**
* Internal dependencies
*/
/**
* Prepares initialState for the reducer.
*
* @param initialState The initial state.
* @return Prepared initialState for the reducer
*/
function mergeInitialState() {
let initialState = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _state.initialInputControlState;
const {
value
} = initialState;
return { ..._state.initialInputControlState,
...initialState,
initialValue: value
};
}
/**
* Composes multiple stateReducers into a single stateReducer, building
* the pipeline to control the flow for state and actions.
*
* @param fns State reducers.
* @return The single composed stateReducer.
*/
const composeStateReducers = function () {
for (var _len = arguments.length, fns = new Array(_len), _key = 0; _key < _len; _key++) {
fns[_key] = arguments[_key];
}
return function () {
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
}
return fns.reduceRight((state, fn) => {
const fnState = fn(...args);
return (0, _lodash.isEmpty)(fnState) ? state : { ...state,
...fnState
};
}, {});
};
};
/**
* Creates a reducer that opens the channel for external state subscription
* and modification.
*
* This technique uses the "stateReducer" design pattern:
* https://kentcdodds.com/blog/the-state-reducer-pattern/
*
* @param composedStateReducers A custom reducer that can subscribe and modify state.
* @return The reducer.
*/
exports.composeStateReducers = composeStateReducers;
function inputControlStateReducer(composedStateReducers) {
return (state, action) => {
const nextState = { ...state
};
switch (action.type) {
/**
* Keyboard events
*/
case actions.PRESS_UP:
nextState.isDirty = false;
break;
case actions.PRESS_DOWN:
nextState.isDirty = false;
break;
/**
* Drag events
*/
case actions.DRAG_START:
nextState.isDragging = true;
break;
case actions.DRAG_END:
nextState.isDragging = false;
break;
/**
* Input events
*/
case actions.CHANGE:
nextState.error = null;
nextState.value = action.payload.value;
if (state.isPressEnterToChange) {
nextState.isDirty = true;
}
break;
case actions.COMMIT:
nextState.value = action.payload.value;
nextState.isDirty = false;
break;
case actions.RESET:
nextState.error = null;
nextState.isDirty = false;
nextState.value = action.payload.value || state.initialValue;
break;
case actions.UPDATE:
nextState.value = action.payload.value;
nextState.isDirty = false;
break;
/**
* Validation
*/
case actions.INVALIDATE:
nextState.error = action.payload.error;
break;
}
if (action.payload.event) {
nextState._event = action.payload.event;
}
/**
* Send the nextState + action to the composedReducers via
* this "bridge" mechanism. This allows external stateReducers
* to hook into actions, and modify state if needed.
*/
return composedStateReducers(nextState, action);
};
}
/**
* A custom hook that connects and external stateReducer with an internal
* reducer. This hook manages the internal state of InputControl.
* However, by connecting an external stateReducer function, other
* components can react to actions as well as modify state before it is
* applied.
*
* This technique uses the "stateReducer" design pattern:
* https://kentcdodds.com/blog/the-state-reducer-pattern/
*
* @param stateReducer An external state reducer.
* @param initialState The initial state for the reducer.
* @return State, dispatch, and a collection of actions.
*/
function useInputControlStateReducer() {
let stateReducer = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _state.initialStateReducer;
let initialState = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _state.initialInputControlState;
const [state, dispatch] = (0, _element.useReducer)(inputControlStateReducer(stateReducer), mergeInitialState(initialState));
const createChangeEvent = type => (nextValue, event) => {
/**
* Persist allows for the (Synthetic) event to be used outside of
* this function call.
* https://reactjs.org/docs/events.html#event-pooling
*/
if (event && event.persist) {
event.persist();
}
dispatch({
type,
payload: {
value: nextValue,
event
}
});
};
const createKeyEvent = type => event => {
/**
* Persist allows for the (Synthetic) event to be used outside of
* this function call.
* https://reactjs.org/docs/events.html#event-pooling
*/
if (event && event.persist) {
event.persist();
}
dispatch({
type,
payload: {
event
}
});
};
const createDragEvent = type => payload => {
dispatch({
type,
payload
});
};
/**
* Actions for the reducer
*/
const change = createChangeEvent(actions.CHANGE);
const invalidate = (error, event) => dispatch({
type: actions.INVALIDATE,
payload: {
error,
event
}
});
const reset = createChangeEvent(actions.RESET);
const commit = createChangeEvent(actions.COMMIT);
const update = createChangeEvent(actions.UPDATE);
const dragStart = createDragEvent(actions.DRAG_START);
const drag = createDragEvent(actions.DRAG);
const dragEnd = createDragEvent(actions.DRAG_END);
const pressUp = createKeyEvent(actions.PRESS_UP);
const pressDown = createKeyEvent(actions.PRESS_DOWN);
const pressEnter = createKeyEvent(actions.PRESS_ENTER);
return {
change,
commit,
dispatch,
drag,
dragEnd,
dragStart,
invalidate,
pressDown,
pressEnter,
pressUp,
reset,
state,
update
};
}
//# sourceMappingURL=reducer.js.map