text: import { createModuleReducer } from '@intactile/redux-utils';
  
  import {
    UNDO,
    REDO,
    ADD_UNDO_ITEM,
    BEGIN_GROUP,
    END_GROUP,
    CLEAR_HISTORY,
    REWRITE_HISTORY
  } from './actions';
  
  const initialState = {
    undoQueue: [],
    redoQueue: [],
    groupLevel: 0
  };
  
  const limitArraySize = (array, maxSize) =>
    array.length > maxSize ? array.splice(maxSize, array.length - maxSize) : array;
  
  function createUndoReducer({ redoHistorySize = 10 }) {
    return function undoReducer(state) {
      const { undoQueue, redoQueue } = state;
      return undoQueue.length === 0
        ? state
        : {
            ...state,
            undoQueue: undoQueue.slice(1),
            redoQueue: limitArraySize([undoQueue[0], ...redoQueue], redoHistorySize)
          };
    };
  }
  
  function redoReducer(state) {
    const { undoQueue, redoQueue } = state;
    return redoQueue.length === 0
      ? state
      : {
          ...state,
          undoQueue: [redoQueue[0], ...undoQueue],
          redoQueue: redoQueue.slice(1)
        };
  }
  
  const groupAction = (state, action) => {
    const { groupLevel, groupCreated } = state;
    const { payload: undoItem } = action;
    return (groupLevel > 0 && groupCreated) || undoItem.isGroupedWithPrevious;
  };
  
  function createAddUndoItemReducer({ undoHistorySize = 50 }) {
    return function addUndoItemReducer(state, action) {
      const { undoQueue, groupLevel } = state;
      const { payload: undoItem } = action;
      let newUndoQueue = undoQueue;
      if (groupAction(state, action)) {
        const groupedAction = [undoItem, ...undoQueue[0]];
        newUndoQueue = [groupedAction, ...undoQueue.slice(1)];
      } else {
        newUndoQueue = [[undoItem], ...undoQueue];
      }
      newUndoQueue = limitArraySize(newUndoQueue, undoHistorySize);
      return {
        ...state,
        undoQueue: limitArraySize(newUndoQueue),
        groupCreated: groupLevel > 0 ? true : undefined,
        redoQueue: []
      };
    };
  }
  
  function beginGroupReducer(state) {
    return {
      ...state,
      groupLevel: state.groupLevel + 1
    };
  }
  
  function endGroupReducer(state) {
    return {
      ...state,
      groupLevel: state.groupLevel - 1,
      groupCreated: state.groupCreated && state.groupLevel > 1
    };
  }
  
  function clearHistoryReducer() {
    return initialState;
  }
  
  function rewriteHistoryReducer(state, { payload: rewrittenState }) {
    return {
      ...state,
      ...rewrittenState
    };
  }
  
  export default function createUndoHistoryReducer(conf = {}) {
    return createModuleReducer(
      {
        [UNDO]: createUndoReducer(conf),
        [REDO]: redoReducer,
        [ADD_UNDO_ITEM]: createAddUndoItemReducer(conf),
        [BEGIN_GROUP]: beginGroupReducer,
        [END_GROUP]: endGroupReducer,
        [CLEAR_HISTORY]: clearHistoryReducer,
        [REWRITE_HISTORY]: rewriteHistoryReducer
      },
      initialState
    );
  }
  