UNPKG

@gechiui/components

Version:
275 lines (229 loc) 7.71 kB
"use strict"; 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