<NME> index.ts
<BEF> declare var console;

const logger = console;
const INIT_ACTION = '@ngrx/store/init';

const repeat = (str, times) => new Array(times + 1).join(str);
const pad = (num, maxLength) =>
  repeat(`0`, maxLength - num.toString().length) + num;
const formatTime = time =>
  `@ ${pad(time.getHours(), 2)}:${pad(time.getMinutes(), 2)}:${pad(
    time.getSeconds(),
    2
  )}.${pad(time.getMilliseconds(), 3)}`;
const timer =
  typeof performance !== `undefined` && typeof performance.now === `function`
    ? performance
    : Date;

const getLogLevel = (level, action, payload, type) => {
  switch (typeof level) {
    case `object`:
const printBuffer = options => logBuffer => {
    const {actionTransformer, collapsed, colors, timestamp, duration, level} = options;
    logBuffer.forEach((logEntry, key) => {
        const { started, startedTime, action, prevState, error } = logEntry;
        let { took, nextState } = logEntry;
        const nextEntry = logBuffer[key + 1];
        if (nextEntry) {
};

const printBuffer = options => logBuffer => {
  const {
    actionTransformer,
    collapsed,
    colors,
    timestamp,
    duration,
    level
  } = options;
  logBuffer.forEach((logEntry, key) => {
    const { started, startedTime, action, error } = logEntry;
    const prevState = logEntry.prevState.nextState
      ? logEntry.prevState.nextState
      : '(Empty)';
    let { took, nextState } = logEntry;
    const nextEntry = logBuffer[key + 1];
    if (nextEntry) {
      nextState = nextEntry.prevState;
      took = nextEntry.started - started;
    }

    const formattedAction = actionTransformer(action);
    const isCollapsed =
      typeof collapsed === `function`
        ? collapsed(() => nextState, action)
        : collapsed;

    const formattedTime = formatTime(startedTime);
    const titleCSS = colors.title
      ? `color: ${colors.title(formattedAction)};`
      : null;
    const title = `action ${timestamp ? formattedTime : ``} ${
      formattedAction.type
    } ${duration ? `(in ${took.toFixed(2)} ms)` : ``}`;

    try {
      if (isCollapsed) {
        if (colors.title) logger.groupCollapsed(`%c ${title}`, titleCSS);
        else logger.groupCollapsed(title);
      } else {
        if (colors.title) logger.group(`%c ${title}`, titleCSS);
        else logger.group(title);
      }
    } catch (e) {
      logger.log(title);
    }

    const prevStateLevel = getLogLevel(
      level,
      formattedAction,
      [prevState],
      `prevState`
    );
    const actionLevel = getLogLevel(
      level,
      formattedAction,
      [formattedAction],
      `action`
    );
    const errorLevel = getLogLevel(
      level,
      formattedAction,
      [error, prevState],
      `error`
    );
    const nextStateLevel = getLogLevel(
      level,
      formattedAction,
      [nextState],
      `nextState`
    );

    if (prevStateLevel) {
      if (colors.prevState)
        logger[prevStateLevel](
          `%c prev state`,
          `color: ${colors.prevState(prevState)}; font-weight: bold`,
          prevState
        );
      else logger[prevStateLevel](`prev state`, prevState);
    }

    if (actionLevel) {
      if (colors.action)
        logger[actionLevel](
          `%c action`,
          `color: ${colors.action(formattedAction)}; font-weight: bold`,
          formattedAction
        );
      else logger[actionLevel](`action`, formattedAction);
    }

    if (error && errorLevel) {
      if (colors.error)
        logger[errorLevel](
          `%c error`,
          `color: ${colors.error(error, prevState)}; font-weight: bold`,
          error
        );
      else logger[errorLevel](`error`, error);
    }

    if (nextStateLevel) {
      if (colors.nextState)
        logger[nextStateLevel](
          `%c next state`,

        return nextState;
    }
};
    }

    try {
      logger.groupEnd();
    } catch (e) {
      logger.log(`—— log end ——`);
    }
  });
  logBuffer.length = 0;
};

const isAllowed = (action, filter) => {
  if (!filter) {
    return true;
  }
  if (filter.whitelist && filter.whitelist.length) {
    return filter.whitelist.indexOf(action.type) !== -1;
  }
  return filter.blacklist && filter.blacklist.indexOf(action.type) === -1;
};

export const storeLogger = (opts: LoggerOptions = {}) => (
  reducer: Function
) => {
  let log = {};
  const ua =
    typeof window !== 'undefined' && window.navigator.userAgent
      ? window.navigator.userAgent
      : '';
  let ms_ie = false;
  //fix for action display in IE
  const old_ie = ua.indexOf('MSIE ');
  const new_ie = ua.indexOf('Trident/');

  if (old_ie > -1 || new_ie > -1) {
    ms_ie = true;
  }

  let colors: LoggerColorsOption;
  if (ms_ie) {
    // Setting colors functions to null when it's an IE browser.
    colors = {
      title: null,
      prevState: null,
      action: null,
      nextState: null,
      error: null
    };
  } else {
    colors = {
      title: null,
      prevState: () => '#9E9E9E',
      action: () => '#03A9F4',
      nextState: () => '#4CAF50',
      error: () => '#F20404'
    };
  }

  const defaults: LoggerOptions = {
    level: 'log',
    collapsed: false,
    duration: true,
    timestamp: true,
    stateTransformer: state => state,
    actionTransformer: actn => actn,
    filter: {
      whitelist: [],
      blacklist: []
    },
    colors: colors
  };

  const options = Object.assign({}, defaults, opts);
  const { stateTransformer } = options;
  const buffer = printBuffer(options);

  return function(state, action) {
    let preLog = {
      started: timer.now(),
      startedTime: new Date(),
      prevState: stateTransformer(log),
      action
    };

    let nextState = reducer(state, action);

    let postLog = {
      took: timer.now() - preLog.started,
      nextState: stateTransformer(nextState)
    };
    log = Object.assign({}, preLog, postLog);
    //ignore init action fired by store and devtools
    if (action.type !== INIT_ACTION && isAllowed(action, options.filter)) {
      buffer([log]);
    }

    return nextState;
  };
};

export interface LoggerOptions {
  /**
   * 'log' | 'console' | 'warn' | 'error' | 'info'. Default: 'log'
   */
  level?: any;
  /**
   * Should log group be collapsed? default: false
   */
  collapsed?: boolean;
  /**
   * Print duration with action? default: true
   */
  duration?: boolean;
  /**
   * Print timestamp with action? default: true
   */
  timestamp?: boolean;
  filter?: LoggerFilterOption;
  /**
   * Transform state before print default: state => state
   */
  stateTransformer?: (state: Object) => Object;
  /**
   * Transform action before print default: actn => actn
   */
  actionTransformer?: (actn: Object) => Object;
  colors?: LoggerColorsOption;
}

export interface LoggerFilterOption {
  /**
   * Only print actions included in this list - has priority over blacklist
   */
  whitelist?: string[];
  /**
   * Only print actions that are NOT included in this list
   */
  blacklist?: string[];
}

export interface LoggerColorsOption {
  title: (action: Object) => string;
  prevState: (prevState: Object) => string;
  action: (action: Object) => string;
  nextState: (nextState: Object) => string;
  error: (error: any, prevState: Object) => string;
}

<MSG> Fixed prevState display so it shows just like nextState.

May need to tweak the title later in order to display additional info. like time took etc. Since these details info. are no longer part of prevState tree.
<DFF> @@ -22,7 +22,8 @@ const getLogLevel = (level, action, payload, type) => {
 const printBuffer = options => logBuffer => {
     const {actionTransformer, collapsed, colors, timestamp, duration, level} = options;
     logBuffer.forEach((logEntry, key) => {
-        const { started, startedTime, action, prevState, error } = logEntry;
+        const { started, startedTime, action, error } = logEntry;
+        const prevState = logEntry.prevState.nextState ? logEntry.prevState.nextState : '(Empty)';
         let { took, nextState } = logEntry;
         const nextEntry = logBuffer[key + 1];
         if (nextEntry) {
@@ -137,4 +138,4 @@ export const storeLogger = (opts : Object = {}) => (reducer : Function) => {
 
         return nextState;
     }
-};
\ No newline at end of file
+};

Fixed prevState display so it shows just like nextState.