<commit_before>import React from 'react';
import arrayFindIndex from 'array-find-index';
import classNames from 'classnames';

import getDisplayText from './utils/getDisplayText';
import getControlComponent from './utils/getControlComponent';

import './index.scss';

const log = console.log;
const logError = console.error || log;
const logWarning = console.warn || log;

/*
 * AudioPlayer
 *
 * Accepts 'playlist' prop of the form:
 *
 * [{ "url": "./path/to/file.mp3",
 *    "displayText": "ArtistA - Track 1" },
 *  { "url": "https://domain.com/track2.ogg",
 *    "displayText": "ArtistB - Track 2" }]
 *
 * Accepts 'autoplay' prop (true/[false]).
 *
 * Accepts 'autoplayDelayInSeconds' prop (default 0).
 *
 * Accepts 'gapLengthInSeconds' prop (default 0).
 * Specifies gap at end of one track before next
 * track begins (ignored for manual skip).
 *
 * Accepts 'cycle' prop (default true,
 * starts playing at the beginning of the playlist
 * when finished if true).
 *
 * Accepts 'pauseOnSeekPreview' prop (default true,
 * pauses audio while user is selecting new time
 * for playback)
 *
 * Accepts 'disableSeek' prop (default false,
 * disables seeking through the audio if true).
 *
 * Accepts 'stayOnBackSkipThreshold' prop, default 5,
 * is number of seconds to progress until pressing back skip
 * restarts the current track.
 *
 * Accepts 'style' prop, object, is applied to
 * outermost div (React styles).
 *
 * Accepts 'onMediaEvent' prop, an object used for
 * listening to media events on the underlying audio element.
 *
 * Accepts 'audioElementRef' prop, a function called after
 * the component mounts and before it unmounts with the
 * internally-referenced HTML audio element as its only parameter.
 * Similar to: https://facebook.github.io/react/docs/refs-and-the-dom.html
 */
class AudioPlayer extends React.Component {

  constructor (props) {
    super(props);

    // index matching requested track (whether track has loaded or not)
    this.currentTrackIndex = 0;

    this.defaultState = {
      /* activeTrackIndex will change to match
       * this.currentTrackIndex once metadata has loaded
       */
      activeTrackIndex: -1,
      // indicates whether audio player should be paused
      paused: true,
      /* elapsed time for current track, in seconds -
       * DISPLAY ONLY! the actual elapsed time may
       * not match up if we're currently seeking, since
       * the new time is visually previewed before the
       * audio seeks.
       */
      displayedTime: 0,
      /* true if the user is currently dragging the mouse
       * to seek a new track position
       */
      seekInProgress: false,
      /* true if audio was playing when seek previewing began,
       * it was paused, and it should be resumed on seek
       * complete
       */
      awaitingResumeOnSeekComplete: false
    };

    this.state = {
      ...this.defaultState,
      // html audio element used for playback
      audio: null
    };

    // bind methods fired on React events
    this.togglePause = this.togglePause.bind(this);
    this.skipToNextTrack = this.skipToNextTrack.bind(this);
    this.backSkip = this.backSkip.bind(this);
    this.handleSeekPreview = this.handleSeekPreview.bind(this);
    this.handleSeekComplete = this.handleSeekComplete.bind(this);

    // audio event listeners to add on mount and remove on unmount
    this.audioPlayListener = () => this.setState({ paused: false });
    this.audioPauseListener = () => this.setState({ paused: true });
    this.audioEndListener = () => {
      const gapLengthInSeconds = this.props.gapLengthInSeconds || 0;
      clearTimeout(this.gapLengthTimeout);
      this.gapLengthTimeout = setTimeout(() => this.skipToNextTrack(), gapLengthInSeconds * 1000);
    };
    this.audioStallListener = () => this.togglePause(true);
    this.audioTimeUpdateListener = () => this.handleTimeUpdate();
    this.audioMetadataLoadedListener = () => this.setState({
      activeTrackIndex: this.currentTrackIndex
    });
  }

  componentDidMount () {
    const audio = document.createElement('audio');
    this.setState({ audio }, () => {

      // add event listeners on the audio element
      audio.preload = 'metadata';
      audio.addEventListener('play', this.audioPlayListener);
      audio.addEventListener('pause', this.audioPauseListener);
      audio.addEventListener('ended', this.audioEndListener);
      audio.addEventListener('stalled', this.audioStallListener);
      audio.addEventListener('timeupdate', this.audioTimeUpdateListener);
      audio.addEventListener('loadedmetadata', this.audioMetadataLoadedListener);
      this.addMediaEventListeners(this.props.onMediaEvent);

      if (this.props.playlist && this.props.playlist.length) {
        this.updateSource();
        if (this.props.autoplay) {
          const delay = this.props.autoplayDelayInSeconds || 0;
          clearTimeout(this.delayTimeout);
          this.delayTimeout = setTimeout(() => this.togglePause(false), delay * 1000);
        }
      }

    });

    if (this.props.audioElementRef) {
      this.props.audioElementRef(audio);
    }
  }

  componentWillReceiveProps (nextProps) {
    // Update media event listeners that may have changed
    this.removeMediaEventListeners(this.props.onMediaEvent);
    this.addMediaEventListeners(nextProps.onMediaEvent);

    const newPlaylist = nextProps.playlist;
    if (!newPlaylist || !newPlaylist.length) {
      this.state.audio.src = '';
      this.currentTrackIndex = 0;
      return this.setState(this.defaultState);
    }

    const oldPlaylist = this.props.playlist;

    const currentTrackUrl = ((oldPlaylist || [])[this.currentTrackIndex] || {}).url;
    this.currentTrackIndex = arrayFindIndex(newPlaylist, track => {
      return track.url && currentTrackUrl === track.url;
    });
    /* if the track we're already playing is in the new playlist, update the
     * activeTrackIndex.
     */
    if (this.currentTrackIndex !== -1) {
      this.setState({
        activeTrackIndex: this.currentTrackIndex
      });
    }
  }

  componentDidUpdate () {
    /* if we loaded a new playlist and reset the current track marker, we
     * should load up the first one.
     */
    if (this.currentTrackIndex === -1) {
      this.skipToNextTrack(false);
    }
  }

  componentWillUnmount () {
    const { audio } = this.state;
    // remove event listeners on the audio element
    audio.removeEventListener('play', this.audioPlayListener);
    audio.removeEventListener('pause', this.audioPauseListener);
    audio.removeEventListener('ended', this.audioEndListener);
    audio.removeEventListener('stalled', this.audioStallListener);
    audio.removeEventListener('timeupdate', this.audioTimeUpdateListener);
    audio.removeEventListener('loadedmetadata', this.audioMetadataLoadedListener);
    removeMediaEventListeners(this.props.onMediaEvent);

    clearTimeout(this.gapLengthTimeout);
    clearTimeout(this.delayTimeout);

    // pause the audio element before we unmount
    audio.pause();

    if (this.props.audioElementRef) {
      this.props.audioElementRef(audio);
    }
  }

  addMediaEventListeners (mediaEvents) {
    if (!mediaEvents) {
      return;
    }
    Object.keys(mediaEvents).forEach((type) => {
      if (typeof mediaEvents[type] !== 'function') {
        return;
      }
      this.state.audio.addEventListener(type, mediaEvents[type]);
    });
  }

  removeMediaEventListeners (mediaEvents) {
    if (!mediaEvents) {
      return;
    }
    Object.keys(mediaEvents).forEach((type) => {
      if (typeof mediaEvents[type] !== 'function') {
        return;
      }
      this.state.audio.removeEventListener(type, mediaEvents[type]);
    });
  }

  togglePause (value) {
    const { playlist } = this.props;
    const { audio, paused } = this.state;
    if (!audio) {
      return;
    }
    const pause = typeof value === 'boolean' ? value : !paused;
    if (pause) {
      return audio.pause();
    }
    if (!playlist || !playlist.length) {
      return;
    }
    try {
      audio.play();
    } catch (error) {
      logError(error);
      const warningMessage =
        'Audio playback failed at ' +
        new Date().toLocaleTimeString() +
        '! (Perhaps autoplay is disabled in this browser.)';
      logWarning(warningMessage);
    }
  }

  skipToNextTrack (shouldPlay) {
    const { playlist, cycle } = this.props;
    const { audio } = this.state;
    if (!audio) {
      return;
    }
    audio.pause();
    if (!playlist || !playlist.length) {
      return;
    }
    let i = this.currentTrackIndex + 1;
    if (i >= playlist.length) {
      i = 0;
    }
    this.currentTrackIndex = i;
    this.setState({
      activeTrackIndex: -1,
      displayedTime: 0
    }, () => {
      this.updateSource();
      const shouldPauseOnCycle = (!cycle && i === 0);
      const shouldPause = shouldPauseOnCycle || (typeof shouldPlay === 'boolean' ? !shouldPlay : false);
      this.togglePause(shouldPause);
    });
  }

  backSkip () {
    const { playlist, stayOnBackSkipThreshold } = this.props;
    const { audio } = this.state;
    if (!playlist || !playlist.length) {
      return;
    }
    let stayThreshold = stayOnBackSkipThreshold;
    if (isNaN(stayThreshold)) {
      stayThreshold = 5;
    }
    if (audio.currentTime >= stayThreshold) {
      return audio.currentTime = 0;
    }
    let i = this.currentTrackIndex - 1;
    if (i < 0) {
      i = playlist.length - 1;
    }
    this.currentTrackIndex = i - 1;
    this.skipToNextTrack();
  }

  updateSource () {
    this.state.audio.src = this.props.playlist[this.currentTrackIndex].url;
  }

  handleTimeUpdate () {
    const { seekInProgress, audio } = this.state;
    if (!seekInProgress && audio) {
      this.setState({
        displayedTime: audio.currentTime
      });
    }
  }

  handleSeekPreview (progress) {
    const { paused, awaitingResumeOnSeekComplete, audio } = this.state;
    if (this.isSeekUnavailable()) {
      return;
    }
    if (!paused && this.props.pauseOnSeekPreview && !awaitingResumeOnSeekComplete) {
      this.setState({
        awaitingResumeOnSeekComplete: true
      });
      this.togglePause(true);
    }
    const progressInBounds = Math.max(0, Math.min(progress, 1));
    this.setState({
      displayedTime: progressInBounds * this.state.audio.duration,
      seekInProgress: true
    });
  }

  handleSeekComplete () {
    const { displayedTime, awaitingResumeOnSeekComplete, audio } = this.state;
    this.setState({
      seekInProgress: false
    });
    if (isNaN(displayedTime)) {
      return;
    }
    audio.currentTime = displayedTime;
    if (awaitingResumeOnSeekComplete) {
      audio.play();
      this.setState({
        awaitingResumeOnSeekComplete: false
      });
    }
  }

  isSeekUnavailable () {
    return Boolean(
      !this.props.playlist ||
      !this.props.playlist.length ||
      this.props.disableSeek
    );
  }

  render () {
    const { playlist, controls, style } = this.props;
    const {
      activeTrackIndex,
      paused,
      displayedTime,
      seekInProgress,
      awaitingResumeOnSeekComplete,
      audio
    } = this.state;
    const controlComponentProps = {
      audio,
      playlist,
      activeTrackIndex,
      paused,
      displayedTime,
      seekInProgress,
      awaitingResumeOnSeekComplete,
      seekUnavailable: this.isSeekUnavailable(),
      onTogglePause: this.togglePause,
      onBackSkip: this.backSkip,
      onForwardSkip: this.skipToNextTrack,
      onSeekPreview: this.handleSeekPreview,
      onSeekComplete: this.handleSeekComplete
    };
    return (
      <div
        className="audio_player"
        title={getDisplayText(playlist, activeTrackIndex)}
        style={style}
      >
        {controls.map((control, index) => {
          const ControlComponent = getControlComponent(control);
          if (!ControlComponent) {
            if (typeof control === 'string') {
              logWarning(`Provided control "${control}" could not be matched.`);
            }
            return null;
          }
          return <ControlComponent key={index} {...controlComponentProps} />;
        })}
      </div>
    );
  }

}

AudioPlayer.propTypes = {
  playlist: React.PropTypes.array,
  controls: React.PropTypes.array,
  autoplay: React.PropTypes.bool,
  autoplayDelayInSeconds: React.PropTypes.number,
  gapLengthInSeconds: React.PropTypes.number,
  cycle: React.PropTypes.bool,
  pauseOnSeekPreview: React.PropTypes.bool,
  disableSeek: React.PropTypes.bool,
  stayOnBackSkipThreshold: React.PropTypes.number,
  style: React.PropTypes.object,
  onMediaEvent: React.PropTypes.object,
  audioElementRef: React.PropTypes.func
};

AudioPlayer.defaultProps = {
  controls: [
    'spacer',
    'backskip',
    'playpause',
    'forwardskip',
    'spacer',
    'progress'
  ],
  cycle: true,
  pauseOnSeekPreview: true
};

module.exports = AudioPlayer;
<commit_msg>defaultProps added where appropriate.<commit_after>import React from 'react';
import arrayFindIndex from 'array-find-index';
import classNames from 'classnames';

import getDisplayText from './utils/getDisplayText';
import getControlComponent from './utils/getControlComponent';

import './index.scss';

const log = console.log;
const logError = console.error || log;
const logWarning = console.warn || log;

/*
 * AudioPlayer
 *
 * Accepts 'playlist' prop of the form:
 *
 * [{ "url": "./path/to/file.mp3",
 *    "displayText": "ArtistA - Track 1" },
 *  { "url": "https://domain.com/track2.ogg",
 *    "displayText": "ArtistB - Track 2" }]
 *
 * Accepts 'autoplay' prop (true/[false]).
 *
 * Accepts 'autoplayDelayInSeconds' prop (default 0).
 *
 * Accepts 'gapLengthInSeconds' prop (default 0).
 * Specifies gap at end of one track before next
 * track begins (ignored for manual skip).
 *
 * Accepts 'cycle' prop (default true,
 * starts playing at the beginning of the playlist
 * when finished if true).
 *
 * Accepts 'pauseOnSeekPreview' prop (default true,
 * pauses audio while user is selecting new time
 * for playback)
 *
 * Accepts 'disableSeek' prop (default false,
 * disables seeking through the audio if true).
 *
 * Accepts 'stayOnBackSkipThreshold' prop, default 5,
 * is number of seconds to progress until pressing back skip
 * restarts the current track.
 *
 * Accepts 'style' prop, object, is applied to
 * outermost div (React styles).
 *
 * Accepts 'onMediaEvent' prop, an object used for
 * listening to media events on the underlying audio element.
 *
 * Accepts 'audioElementRef' prop, a function called after
 * the component mounts and before it unmounts with the
 * internally-referenced HTML audio element as its only parameter.
 * Similar to: https://facebook.github.io/react/docs/refs-and-the-dom.html
 */
class AudioPlayer extends React.Component {

  constructor (props) {
    super(props);

    // index matching requested track (whether track has loaded or not)
    this.currentTrackIndex = 0;

    this.defaultState = {
      /* activeTrackIndex will change to match
       * this.currentTrackIndex once metadata has loaded
       */
      activeTrackIndex: -1,
      // indicates whether audio player should be paused
      paused: true,
      /* elapsed time for current track, in seconds -
       * DISPLAY ONLY! the actual elapsed time may
       * not match up if we're currently seeking, since
       * the new time is visually previewed before the
       * audio seeks.
       */
      displayedTime: 0,
      /* true if the user is currently dragging the mouse
       * to seek a new track position
       */
      seekInProgress: false,
      /* true if audio was playing when seek previewing began,
       * it was paused, and it should be resumed on seek
       * complete
       */
      awaitingResumeOnSeekComplete: false
    };

    this.state = {
      ...this.defaultState,
      // html audio element used for playback
      audio: null
    };

    // bind methods fired on React events
    this.togglePause = this.togglePause.bind(this);
    this.skipToNextTrack = this.skipToNextTrack.bind(this);
    this.backSkip = this.backSkip.bind(this);
    this.handleSeekPreview = this.handleSeekPreview.bind(this);
    this.handleSeekComplete = this.handleSeekComplete.bind(this);

    // audio event listeners to add on mount and remove on unmount
    this.audioPlayListener = () => this.setState({ paused: false });
    this.audioPauseListener = () => this.setState({ paused: true });
    this.audioEndListener = () => {
      clearTimeout(this.gapLengthTimeout);
      this.gapLengthTimeout = setTimeout(() => {
        this.skipToNextTrack();
      }, this.props.gapLengthInSeconds * 1000);
    };
    this.audioStallListener = () => this.togglePause(true);
    this.audioTimeUpdateListener = () => this.handleTimeUpdate();
    this.audioMetadataLoadedListener = () => this.setState({
      activeTrackIndex: this.currentTrackIndex
    });
  }

  componentDidMount () {
    const audio = document.createElement('audio');
    this.setState({ audio }, () => {

      // add event listeners on the audio element
      audio.preload = 'metadata';
      audio.addEventListener('play', this.audioPlayListener);
      audio.addEventListener('pause', this.audioPauseListener);
      audio.addEventListener('ended', this.audioEndListener);
      audio.addEventListener('stalled', this.audioStallListener);
      audio.addEventListener('timeupdate', this.audioTimeUpdateListener);
      audio.addEventListener('loadedmetadata', this.audioMetadataLoadedListener);
      this.addMediaEventListeners(this.props.onMediaEvent);

      if (this.props.playlist && this.props.playlist.length) {
        this.updateSource();
        if (this.props.autoplay) {
          clearTimeout(this.delayTimeout);
          this.delayTimeout = setTimeout(() => {
            this.togglePause(false);
          }, this.props.autoplayDelayInSeconds * 1000);
        }
      }

    });

    if (this.props.audioElementRef) {
      this.props.audioElementRef(audio);
    }
  }

  componentWillReceiveProps (nextProps) {
    // Update media event listeners that may have changed
    this.removeMediaEventListeners(this.props.onMediaEvent);
    this.addMediaEventListeners(nextProps.onMediaEvent);

    const newPlaylist = nextProps.playlist;
    if (!newPlaylist || !newPlaylist.length) {
      this.state.audio.src = '';
      this.currentTrackIndex = 0;
      return this.setState(this.defaultState);
    }

    const oldPlaylist = this.props.playlist;

    const currentTrackUrl = ((oldPlaylist || [])[this.currentTrackIndex] || {}).url;
    this.currentTrackIndex = arrayFindIndex(newPlaylist, track => {
      return track.url && currentTrackUrl === track.url;
    });
    /* if the track we're already playing is in the new playlist, update the
     * activeTrackIndex.
     */
    if (this.currentTrackIndex !== -1) {
      this.setState({
        activeTrackIndex: this.currentTrackIndex
      });
    }
  }

  componentDidUpdate () {
    /* if we loaded a new playlist and reset the current track marker, we
     * should load up the first one.
     */
    if (this.currentTrackIndex === -1) {
      this.skipToNextTrack(false);
    }
  }

  componentWillUnmount () {
    const { audio } = this.state;
    // remove event listeners on the audio element
    audio.removeEventListener('play', this.audioPlayListener);
    audio.removeEventListener('pause', this.audioPauseListener);
    audio.removeEventListener('ended', this.audioEndListener);
    audio.removeEventListener('stalled', this.audioStallListener);
    audio.removeEventListener('timeupdate', this.audioTimeUpdateListener);
    audio.removeEventListener('loadedmetadata', this.audioMetadataLoadedListener);
    removeMediaEventListeners(this.props.onMediaEvent);

    clearTimeout(this.gapLengthTimeout);
    clearTimeout(this.delayTimeout);

    // pause the audio element before we unmount
    audio.pause();

    if (this.props.audioElementRef) {
      this.props.audioElementRef(audio);
    }
  }

  addMediaEventListeners (mediaEvents) {
    if (!mediaEvents) {
      return;
    }
    Object.keys(mediaEvents).forEach((type) => {
      if (typeof mediaEvents[type] !== 'function') {
        return;
      }
      this.state.audio.addEventListener(type, mediaEvents[type]);
    });
  }

  removeMediaEventListeners (mediaEvents) {
    if (!mediaEvents) {
      return;
    }
    Object.keys(mediaEvents).forEach((type) => {
      if (typeof mediaEvents[type] !== 'function') {
        return;
      }
      this.state.audio.removeEventListener(type, mediaEvents[type]);
    });
  }

  togglePause (value) {
    const { playlist } = this.props;
    const { audio, paused } = this.state;
    if (!audio) {
      return;
    }
    const pause = typeof value === 'boolean' ? value : !paused;
    if (pause) {
      return audio.pause();
    }
    if (!playlist || !playlist.length) {
      return;
    }
    try {
      audio.play();
    } catch (error) {
      logError(error);
      const warningMessage =
        'Audio playback failed at ' +
        new Date().toLocaleTimeString() +
        '! (Perhaps autoplay is disabled in this browser.)';
      logWarning(warningMessage);
    }
  }

  skipToNextTrack (shouldPlay) {
    const { playlist, cycle } = this.props;
    const { audio } = this.state;
    if (!audio) {
      return;
    }
    audio.pause();
    if (!playlist || !playlist.length) {
      return;
    }
    let i = this.currentTrackIndex + 1;
    if (i >= playlist.length) {
      i = 0;
    }
    this.currentTrackIndex = i;
    this.setState({
      activeTrackIndex: -1,
      displayedTime: 0
    }, () => {
      this.updateSource();
      const shouldPauseOnCycle = (!cycle && i === 0);
      const shouldPause = shouldPauseOnCycle || (typeof shouldPlay === 'boolean' ? !shouldPlay : false);
      this.togglePause(shouldPause);
    });
  }

  backSkip () {
    const { playlist, stayOnBackSkipThreshold } = this.props;
    const { audio } = this.state;
    if (!playlist || !playlist.length) {
      return;
    }
    if (audio.currentTime >= stayOnBackSkipThreshold) {
      return audio.currentTime = 0;
    }
    let i = this.currentTrackIndex - 1;
    if (i < 0) {
      i = playlist.length - 1;
    }
    this.currentTrackIndex = i - 1;
    this.skipToNextTrack();
  }

  updateSource () {
    this.state.audio.src = this.props.playlist[this.currentTrackIndex].url;
  }

  handleTimeUpdate () {
    const { seekInProgress, audio } = this.state;
    if (!seekInProgress && audio) {
      this.setState({
        displayedTime: audio.currentTime
      });
    }
  }

  handleSeekPreview (progress) {
    const { paused, awaitingResumeOnSeekComplete, audio } = this.state;
    if (this.isSeekUnavailable()) {
      return;
    }
    if (!paused && this.props.pauseOnSeekPreview && !awaitingResumeOnSeekComplete) {
      this.setState({
        awaitingResumeOnSeekComplete: true
      });
      this.togglePause(true);
    }
    const progressInBounds = Math.max(0, Math.min(progress, 1));
    this.setState({
      displayedTime: progressInBounds * this.state.audio.duration,
      seekInProgress: true
    });
  }

  handleSeekComplete () {
    const { displayedTime, awaitingResumeOnSeekComplete, audio } = this.state;
    this.setState({
      seekInProgress: false
    });
    if (isNaN(displayedTime)) {
      return;
    }
    audio.currentTime = displayedTime;
    if (awaitingResumeOnSeekComplete) {
      audio.play();
      this.setState({
        awaitingResumeOnSeekComplete: false
      });
    }
  }

  isSeekUnavailable () {
    return Boolean(
      !this.props.playlist ||
      !this.props.playlist.length ||
      this.props.disableSeek
    );
  }

  render () {
    const { playlist, controls, style } = this.props;
    const {
      activeTrackIndex,
      paused,
      displayedTime,
      seekInProgress,
      awaitingResumeOnSeekComplete,
      audio
    } = this.state;
    const controlComponentProps = {
      audio,
      playlist,
      activeTrackIndex,
      paused,
      displayedTime,
      seekInProgress,
      awaitingResumeOnSeekComplete,
      seekUnavailable: this.isSeekUnavailable(),
      onTogglePause: this.togglePause,
      onBackSkip: this.backSkip,
      onForwardSkip: this.skipToNextTrack,
      onSeekPreview: this.handleSeekPreview,
      onSeekComplete: this.handleSeekComplete
    };
    return (
      <div
        className="audio_player"
        title={getDisplayText(playlist, activeTrackIndex)}
        style={style}
      >
        {controls.map((control, index) => {
          const ControlComponent = getControlComponent(control);
          if (!ControlComponent) {
            if (typeof control === 'string') {
              logWarning(`Provided control "${control}" could not be matched.`);
            }
            return null;
          }
          return <ControlComponent key={index} {...controlComponentProps} />;
        })}
      </div>
    );
  }

}

AudioPlayer.propTypes = {
  playlist: React.PropTypes.array,
  controls: React.PropTypes.array,
  autoplay: React.PropTypes.bool,
  autoplayDelayInSeconds: React.PropTypes.number,
  gapLengthInSeconds: React.PropTypes.number,
  cycle: React.PropTypes.bool,
  pauseOnSeekPreview: React.PropTypes.bool,
  disableSeek: React.PropTypes.bool,
  stayOnBackSkipThreshold: React.PropTypes.number,
  style: React.PropTypes.object,
  onMediaEvent: React.PropTypes.object,
  audioElementRef: React.PropTypes.func
};

AudioPlayer.defaultProps = {
  controls: [
    'spacer',
    'backskip',
    'playpause',
    'forwardskip',
    'spacer',
    'progress'
  ],
  autoplay: false,
  autoplayDelayInSeconds: 0,
  gapLengthInSeconds: 0,
  cycle: true,
  pauseOnSeekPreview: true,
  disableSeek: false,
  stayOnBackSkipThreshold: 5
};

module.exports = AudioPlayer;
<|endoftext|>


<commit_before>/**
 * REACT LOCATION PICKER
 */

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Map from './GoogleMap';

const google = window.google;

/* Default configuration */
const DEFAULT_RADIUS = 1000;
const DEFAULT_ZOOM = 10;

/* Circle options */
// https://developers.google.com/maps/documentation/javascript/3.exp/reference#CircleOptions
const DEFAULT_CIRCLE_OPTIONS = {
  fillColor: "red",
  fillOpacity: 0.20,
  strokeColor: "red",
  strokeOpacity: 1,
  strokeWeight: 1.2,
};

class LocationPicker extends Component {
  constructor (props) {
    super(props);

    this.state = {
      position: props.defaultPosition,
      shouldRecenterMap: false
    };

    this.handleMarkerDragEnd = this.handleMarkerDragEnd.bind(this);
  }

  componentWillReceiveProps (nextProps) {
    const { defaultPosition } = nextProps;
    if (JSON.stringify(defaultPosition) !== JSON.stringify(this.props.defaultPosition)) {
      this.setState({ position: defaultPosition, shouldRecenterMap: true }, () => {
        // Reverse geocode new default position
        this.geocodePosition(defaultPosition)
        .then(address => {
          this.notify(defaultPosition, address);
        })
        .catch(err => {
          console.error(err);
          this.notify(defaultPosition, "");
        });
      });
    }
  }

  notify (position, address) {
    const { onChange } = this.props;
    const location = {
      position,
      address
    };
    onChange && onChange(location);
  }
  /**
   * Handle Map marker position change
   * @param { MouseEvent } mouseEvent // https://developers.google.com/maps/documentation/javascript/3.exp/reference#MouseEvent
   */
  handleMarkerDragEnd (mouseEvent) {
    const { onChange } = this.props;
    // Get latitude and longitude
    const lat = mouseEvent.latLng.lat();
    const lng = mouseEvent.latLng.lng();
    const position = { lat, lng };
    this.setState({ position, shouldRecenterMap: false });
    this.geocodePosition(position)
      .then(address => {
        this.notify(position, address);
      })
      .catch(err => {
        console.error(err);
        this.notify(position, "");
      });
  }

  /**
   * Geocode position to address
   * @param { Object } position
   * @return { Promise }
   */
  geocodePosition (position) {

    // Geocoder instance
    const geocoder = new google.maps.Geocoder();

    return new Promise((resolve, reject) => {
      geocoder.geocode({ 'location': position }, (results, status) => {
        if (status === google.maps.GeocoderStatus.OK)
          resolve(results[0].formatted_address);
        else
          reject(status);
      });
    });
  };

  render () {
    const {
      zoom,
      radius,
      circleOptions,
      containerElement,
      mapElement
    } = this.props;

    const { position, shouldRecenterMap } = this.state;

    return (
      <Map
        containerElement={containerElement}
        mapElement={mapElement}
        handleMarkerDragEnd={this.handleMarkerDragEnd}
        position={position}
        circleOptions={circleOptions}
        radius={radius}
        defaultZoom={zoom}
        shouldRecenterMap={shouldRecenterMap}
      />
    );
  }
}

LocationPicker.propTypes = {
  containerElement: PropTypes.node.isRequired,
  mapElement: PropTypes.node.isRequired,
  onChange: PropTypes.func.isRequired,
  defaultPosition: PropTypes.object.isRequired,
  zoom: PropTypes.number,
  radius: PropTypes.number,
  circleOptions: PropTypes.object
};

LocationPicker.defaultProps = {
  zoom: DEFAULT_ZOOM,
  radius: DEFAULT_RADIUS,
  circleOptions: DEFAULT_CIRCLE_OPTIONS
};

export default LocationPicker;
<commit_msg>Return everything from the Geocoding API<commit_after>/**
 * REACT LOCATION PICKER
 */

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Map from './GoogleMap';

const google = window.google;

/* Default configuration */
const DEFAULT_RADIUS = 1000;
const DEFAULT_ZOOM = 10;

/* Circle options */
// https://developers.google.com/maps/documentation/javascript/3.exp/reference#CircleOptions
const DEFAULT_CIRCLE_OPTIONS = {
  fillColor: 'red',
  fillOpacity: 0.2,
  strokeColor: 'red',
  strokeOpacity: 1,
  strokeWeight: 1.2
};

class LocationPicker extends Component {
  constructor(props) {
    super(props);

    this.state = {
      position: props.defaultPosition,
      shouldRecenterMap: false
    };

    this.handleMarkerDragEnd = this.handleMarkerDragEnd.bind(this);
  }

  componentWillReceiveProps(nextProps) {
    const { defaultPosition } = nextProps;
    if (
      JSON.stringify(defaultPosition) !==
      JSON.stringify(this.props.defaultPosition)
    ) {
      this.setState(
        { position: defaultPosition, shouldRecenterMap: true },
        () => {
          // Reverse geocode new default position
          this.geocodePosition(defaultPosition)
            .then(places => {
              this.notify(defaultPosition, places);
            })
            .catch(err => {
              console.error(err);
              this.notify(defaultPosition, []);
            });
        }
      );
    }
  }

  notify(position, places) {
    const { onChange } = this.props;
    const location = {
      position,
      places,
      address: places.length > 0 ? places[0].formatted_address : ''
    };
    onChange && onChange(location);
  }
  /**
   * Handle Map marker position change
   * @param { MouseEvent } mouseEvent // https://developers.google.com/maps/documentation/javascript/3.exp/reference#MouseEvent
   */
  handleMarkerDragEnd(mouseEvent) {
    const { onChange } = this.props;
    // Get latitude and longitude
    const lat = mouseEvent.latLng.lat();
    const lng = mouseEvent.latLng.lng();
    const position = { lat, lng };
    this.setState({ position, shouldRecenterMap: false });
    this.geocodePosition(position)
      .then(places => {
        this.notify(position, places);
      })
      .catch(err => {
        console.error(err);
        this.notify(position, []);
      });
  }

  /**
   * Geocode position to places
   * @param { Object } position
   * @return { Promise }
   */
  geocodePosition(position) {
    // Geocoder instance
    const geocoder = new google.maps.Geocoder();

    return new Promise((resolve, reject) => {
      geocoder.geocode({ location: position }, (results, status) => {
        if (status === google.maps.GeocoderStatus.OK) {
          resolve(results);
        } else {
          reject(status);
        }
      });
    });
  }

  render() {
    const {
      zoom,
      radius,
      circleOptions,
      containerElement,
      mapElement
    } = this.props;

    const { position, shouldRecenterMap } = this.state;

    return (
      <Map
        containerElement={containerElement}
        mapElement={mapElement}
        handleMarkerDragEnd={this.handleMarkerDragEnd}
        position={position}
        circleOptions={circleOptions}
        radius={radius}
        defaultZoom={zoom}
        shouldRecenterMap={shouldRecenterMap}
      />
    );
  }
}

LocationPicker.propTypes = {
  containerElement: PropTypes.node.isRequired,
  mapElement: PropTypes.node.isRequired,
  onChange: PropTypes.func.isRequired,
  defaultPosition: PropTypes.object.isRequired,
  zoom: PropTypes.number,
  radius: PropTypes.number,
  circleOptions: PropTypes.object
};

LocationPicker.defaultProps = {
  zoom: DEFAULT_ZOOM,
  radius: DEFAULT_RADIUS,
  circleOptions: DEFAULT_CIRCLE_OPTIONS
};

export default LocationPicker;
<|endoftext|>


<commit_before>import Gitter from 'node-gitter';
import GitterBot from './bot';
import config from '../config.json';
import { authGet, authSet, chatlinks, help, rank, shrug, test } from './commands';

// create gitter bot
const gitter = new Gitter(config.token);
const bot = new GitterBot(gitter);

// join all rooms configured in the config
config.rooms.forEach(room => bot.join(room));

// handle new messages
bot.onMessageCreated((room, message) => {
    if (message.text === 'hi' || message.text === '!test') {
        test(room, message);
    } else if (message.text === '!help') {
        help(room, message);
    } else if (message.text === '!auth') {
        authGet(room, message);
    } else if (message.text.indexOf('!auth ') === 0) {
        authSet(room, message);
    } else if (message.text === '!rank') {
        rank(room, message);
    } else if (message.text === '!shrug' || message.text === '/shrug') {
        shrug(room, message);
    } else {
        chatlinks(room, message);
    }
});
<commit_msg>I guess I have to commit this too for !achievements to work... its getting late<commit_after>import Gitter from 'node-gitter';
import GitterBot from './bot';
import config from '../config.json';
import { achievement, authGet, authSet, chatlinks, help, rank, shrug, test } from './commands';

// create gitter bot
const gitter = new Gitter(config.token);
const bot = new GitterBot(gitter);

// join all rooms configured in the config
config.rooms.forEach(room => bot.join(room));

// handle new messages
bot.onMessageCreated((room, message) => {
    if (message.text === 'hi' || message.text === '!test') {
        test(room, message);
    } else if (message.text === '!help') {
        help(room, message);
    } else if (message.text.indexOf('!achievement ') === 0) {
        achievement(room, message);
    } else if (message.text === '!auth') {
        authGet(room, message);
    } else if (message.text.indexOf('!auth ') === 0) {
        authSet(room, message);
    } else if (message.text === '!rank') {
        rank(room, message);
    } else if (message.text === '!shrug' || message.text === '/shrug') {
        shrug(room, message);
    } else {
        chatlinks(room, message);
    }
});
<|endoftext|>


<commit_before>module.exports = function mutableProxyFactory(defaultTarget) {
  let mutableHandler;
  let mutableTarget;

  function setTarget(target) {
    if (!(target instanceof Object)) {
      throw new Error(`Target "${target}" is not an object`);
    }
    mutableTarget = target;
  }

  function setHandler(handler) {
    Object.keys(handler).forEach(key => {
      const value = handler[key];

      if (typeof value !== 'function') {
        throw new Error(`Trap "${key}: ${value}" is not a function`);
      }

      if (!Reflect[key]) {
        throw new Error(`Trap "${key}: ${value}" is not a valid trap`);
      }
    });
    mutableHandler = handler;
  }

  if (defaultTarget) {
    setTarget(defaultTarget);
  }
  setHandler(Reflect);

  // Dynamically forward all the traps to the associated methods on the mutable handler
  const handler = new Proxy({}, {
    get(target, property) {
      return (...args) => mutableHandler[property].apply(null, [mutableTarget, ...args.slice(1)]);
    }
  });

  return {
    setTarget,
    setHandler,
    getTarget() {
      return mutableTarget;
    },
    getHandler() {
      return mutableHandler;
    },
    proxy: new Proxy(mutableTarget, handler)
  };
};
<commit_msg>Default target properly<commit_after>module.exports = function mutableProxyFactory(defaultTarget = {}) {
  let mutableHandler;
  let mutableTarget;

  function setTarget(target) {
    if (!(target instanceof Object)) {
      throw new Error(`Target "${target}" is not an object`);
    }
    mutableTarget = target;
  }

  function setHandler(handler) {
    Object.keys(handler).forEach(key => {
      const value = handler[key];

      if (typeof value !== 'function') {
        throw new Error(`Trap "${key}: ${value}" is not a function`);
      }

      if (!Reflect[key]) {
        throw new Error(`Trap "${key}: ${value}" is not a valid trap`);
      }
    });
    mutableHandler = handler;
  }

  setTarget(defaultTarget);
  setHandler(Reflect);

  // Dynamically forward all the traps to the associated methods on the mutable handler
  const handler = new Proxy({}, {
    get(target, property) {
      return (...args) => mutableHandler[property].apply(null, [mutableTarget, ...args.slice(1)]);
    }
  });

  return {
    setTarget,
    setHandler,
    getTarget() {
      return mutableTarget;
    },
    getHandler() {
      return mutableHandler;
    },
    proxy: new Proxy(mutableTarget, handler)
  };
};
<|endoftext|>


<commit_before>function createFunctions(Reflux, PromiseFactory) {

    const _ = Reflux.utils;

    /**
     * Returns a Promise for the triggered action
     *
     * @return {Promise}
     *   Resolved by completed child action.
     *   Rejected by failed child action.
     *   If listenAndPromise'd, then promise associated to this trigger.
     *   Otherwise, the promise is for next child action completion.
     */
    function triggerPromise() {
        var me = this;
        var args = arguments;

        var canHandlePromise =
            this.children.indexOf("completed") >= 0 &&
            this.children.indexOf("failed") >= 0;

        var createdPromise = new PromiseFactory(function(resolve, reject) {
            // If `listenAndPromise` is listening
            // patch `promise` w/ context-loaded resolve/reject
            if (me.willCallPromise) {
                _.nextTick(function() {
                    var previousPromise = me.promise;
                    me.promise = function (inputPromise) {
                        inputPromise.then(resolve, reject);
                        // Back to your regularly schedule programming.
                        me.promise = previousPromise;
                        return me.promise.apply(me, arguments);
                    };
                    me.trigger.apply(me, args);
                });
                return;
            }

            if (canHandlePromise) {
                var removeSuccess = me.completed.listen(function () {
                    var args = Array.prototype.slice.call(arguments);
                    removeSuccess();
                    removeFailed();
                    resolve(args.length > 1 ? args : args[0]);
                });

                var removeFailed = me.failed.listen(function () {
                    var args = Array.prototype.slice.call(arguments);
                    removeSuccess();
                    removeFailed();
                    reject(args.length > 1 ? args : args[0]);
                });
            }

            me.trigger.apply(me, args);

            if (!canHandlePromise) {
                resolve();
            }
        });

        return createdPromise;
    }

    /**
     * Attach handlers to promise that trigger the completed and failed
     * child publishers, if available.
     *
     * @param {Object} p The promise to attach to
     */
    function promise(p) {
        var me = this;

        var canHandlePromise =
            this.children.indexOf("completed") >= 0 &&
            this.children.indexOf("failed") >= 0;

        if (!canHandlePromise){
            throw new Error("Publisher must have \"completed\" and \"failed\" child publishers");
        }

        p.then(function(response) {
            return me.completed(response);
        }, function(error) {
            return me.failed(error);
        });
    }

    /**
     * Subscribes the given callback for action triggered, which should
     * return a promise that in turn is passed to `this.promise`
     *
     * @param {Function} callback The callback to register as event handler
     */
    function listenAndPromise(callback, bindContext) {
        var me = this;
        bindContext = bindContext || this;
        this.willCallPromise = (this.willCallPromise || 0) + 1;

        var removeListen = this.listen(function() {

            if (!callback) {
                throw new Error("Expected a function returning a promise but got " + callback);
            }

            var args = arguments,
                returnedPromise = callback.apply(bindContext, args);
            return me.promise.call(me, returnedPromise);
        }, bindContext);

        return function () {
          me.willCallPromise--;
          removeListen.call(me);
        };

    }

    return {
        triggerPromise: triggerPromise,
        promise: promise,
        listenAndPromise: listenAndPromise
    };
}

/**
 * Sets up reflux with Promise functionality
 */
export default function(promiseFactory) {
    return function(Reflux) {
        const { triggerPromise, promise, listenAndPromise } = createFunctions(Reflux, promiseFactory);
        Reflux.PublisherMethods.triggerAsync = triggerPromise;
        Reflux.PublisherMethods.promise = promise;
        Reflux.PublisherMethods.listenAndPromise = listenAndPromise;
    };
}
<commit_msg>Fix Uncaught in promise errors in console when no catch is provided<commit_after>function createFunctions(Reflux, PromiseFactory) {

    const _ = Reflux.utils;

    /**
     * Returns a Promise for the triggered action
     *
     * @return {Promise}
     *   Resolved by completed child action.
     *   Rejected by failed child action.
     *   If listenAndPromise'd, then promise associated to this trigger.
     *   Otherwise, the promise is for next child action completion.
     */
    function triggerPromise() {
        var me = this;
        var args = arguments;

        var canHandlePromise =
            this.children.indexOf("completed") >= 0 &&
            this.children.indexOf("failed") >= 0;

        var createdPromise = new PromiseFactory(function(resolve, reject) {
            // If `listenAndPromise` is listening
            // patch `promise` w/ context-loaded resolve/reject
            if (me.willCallPromise) {
                _.nextTick(function() {
                    var previousPromise = me.promise;
                    me.promise = function (inputPromise) {
                        inputPromise.then(resolve, reject);
                        // Back to your regularly schedule programming.
                        me.promise = previousPromise;
                        return me.promise.apply(me, arguments);
                    };
                    me.trigger.apply(me, args);
                });
                return;
            }

            if (canHandlePromise) {
                var removeSuccess = me.completed.listen(function () {
                    var args = Array.prototype.slice.call(arguments);
                    removeSuccess();
                    removeFailed();
                    resolve(args.length > 1 ? args : args[0]);
                });

                var removeFailed = me.failed.listen(function () {
                    var args = Array.prototype.slice.call(arguments);
                    removeSuccess();
                    removeFailed();
                    reject(args.length > 1 ? args : args[0]);
                });
            }

            me.trigger.apply(me, args);

            if (!canHandlePromise) {
                resolve();
            }
        });

        // Ensure that the promise does trigger "Uncaught (in promise)" errors in console if no error handler is added
        // See: https://github.com/reflux/reflux-promise/issues/4
        createdPromise.catch(function() {});

        return createdPromise;
    }

    /**
     * Attach handlers to promise that trigger the completed and failed
     * child publishers, if available.
     *
     * @param {Object} p The promise to attach to
     */
    function promise(p) {
        var me = this;

        var canHandlePromise =
            this.children.indexOf("completed") >= 0 &&
            this.children.indexOf("failed") >= 0;

        if (!canHandlePromise){
            throw new Error("Publisher must have \"completed\" and \"failed\" child publishers");
        }

        p.then(function(response) {
            return me.completed(response);
        }, function(error) {
            return me.failed(error);
        });
    }

    /**
     * Subscribes the given callback for action triggered, which should
     * return a promise that in turn is passed to `this.promise`
     *
     * @param {Function} callback The callback to register as event handler
     */
    function listenAndPromise(callback, bindContext) {
        var me = this;
        bindContext = bindContext || this;
        this.willCallPromise = (this.willCallPromise || 0) + 1;

        var removeListen = this.listen(function() {

            if (!callback) {
                throw new Error("Expected a function returning a promise but got " + callback);
            }

            var args = arguments,
                returnedPromise = callback.apply(bindContext, args);
            return me.promise.call(me, returnedPromise);
        }, bindContext);

        return function () {
          me.willCallPromise--;
          removeListen.call(me);
        };

    }

    return {
        triggerPromise: triggerPromise,
        promise: promise,
        listenAndPromise: listenAndPromise
    };
}

/**
 * Sets up reflux with Promise functionality
 */
export default function(promiseFactory) {
    return function(Reflux) {
        const { triggerPromise, promise, listenAndPromise } = createFunctions(Reflux, promiseFactory);
        Reflux.PublisherMethods.triggerAsync = triggerPromise;
        Reflux.PublisherMethods.promise = promise;
        Reflux.PublisherMethods.listenAndPromise = listenAndPromise;
    };
}
<|endoftext|>


<commit_before>const axios = require('axios');
const services = require('./services');
const domains = require('./domains');

module.exports = (token) => {
  return new Promise((resolve, reject) => {
    if (!token) {
      reject('Fastly-Domain expected Fastly-Key, received undefined');
    }

    services(token)
      .then(services => {
        return domains(token, services);
      })
      .then(domains => {
        resolve(domains);
      })
      .catch(err => {
        reject(err.message);
      });
  });
};
<commit_msg>Refactor index.js with async/await<commit_after>'use strict';

let services = require('./services');
let domains = require('./domains');

module.exports = async token => {
  const serviceIDs = await services(token);
  const userDomains = await domains(token, serviceIDs);
  return userDomains;
};
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';

export default class MultiStep extends Component {
  constructor(props) {
    super(props);
    this.state = {
      showPreviousBtn: false,
      showNextBtn: true,
      compState: 0,
      navState: this.getNavStates(0, this.props.steps.length)
    };
    this.hidden = {
      display: 'none'
    };
    this.handleOnClick = this.handleOnClick.bind(this);
    this.handleKeyDown = this.handleKeyDown.bind(this);
    this.next = this.next.bind(this);
    this.previous = this.previous.bind(this);
  }

  getNavStates(indx, length) {
    let styles = [];
    for (let i=0; i<length; i++) {
      if(i < indx) {
        styles.push('done')
      }
      else if(i === indx) {
        styles.push('doing')
      }
      else {
        styles.push('todo')
      }
    }
    return { current: indx, styles: styles }
  }

  checkNavState(currentStep){
    if(currentStep > 0 && currentStep !== this.props.steps.length - 1){
      this.setState({
        showPreviousBtn: true,
        showNextBtn: true
      })
    }
    else if(currentStep === 0) {
      this.setState({
        showPreviousBtn: false,
        showNextBtn: true
      })
    }
    else {
      this.setState({
        showPreviousBtn: true,
        showNextBtn: false
      })
    }
  }

  setNavState(next) {
    this.setState({navState: this.getNavStates(next, this.props.steps.length)})
    if (next < this.props.steps.length) {
      this.setState({compState: next})
    }
    this.checkNavState(next);
  }

  handleKeyDown(evt) {
    if (evt.which === 13) {
      this.next()
    }
  }

  handleOnClick(evt) {
    if (evt.target.value === (this.props.steps.length - 1) &&
      this.state.compState === (this.props.steps.length - 1)) {
      this.setNavState(this.props.steps.length)
    }
    else {
      this.setNavState(evt.target.value)
    }
  }

  next() {
    this.setNavState(this.state.compState + 1)
  }

  previous() {
    if (this.state.compState > 0) {
      this.setNavState(this.state.compState - 1)
    }
  }

  getClassName(className, i){
    return className + "-" + this.state.navState.styles[i];
  }

  renderSteps() {
    return this.props.steps.map((s, i)=> (

        {i+1}
        {this.props.steps[i].name}

    ));
  }

  render() {

    return (

          {this.renderSteps()}

        {this.props.steps[this.state.compState].component}

          <button style={this.state.showPreviousBtn ? {} : this.hidden}
                  className="multistep__btn--prev"
                  onClick={this.previous}>Previous</button>

          <button style={this.state.showNextBtn ? {} : this.hidden}
                  className="multistep__btn--next"
                  onClick={this.next}>Next</button>

    );
  }
}

MultiStep.defaultProps = {
  showNavigation: true
};<commit_msg>Use currentTarget to identify element w/ handler<commit_after>import React, { Component, PropTypes } from 'react';

export default class MultiStep extends Component {
  constructor(props) {
    super(props);
    this.state = {
      showPreviousBtn: false,
      showNextBtn: true,
      compState: 0,
      navState: this.getNavStates(0, this.props.steps.length)
    };
    this.hidden = {
      display: 'none'
    };
    this.handleOnClick = this.handleOnClick.bind(this);
    this.handleKeyDown = this.handleKeyDown.bind(this);
    this.next = this.next.bind(this);
    this.previous = this.previous.bind(this);
  }

  getNavStates(indx, length) {
    let styles = [];
    for (let i=0; i<length; i++) {
      if(i < indx) {
        styles.push('done')
      }
      else if(i === indx) {
        styles.push('doing')
      }
      else {
        styles.push('todo')
      }
    }
    return { current: indx, styles: styles }
  }

  checkNavState(currentStep){
    if(currentStep > 0 && currentStep !== this.props.steps.length - 1){
      this.setState({
        showPreviousBtn: true,
        showNextBtn: true
      })
    }
    else if(currentStep === 0) {
      this.setState({
        showPreviousBtn: false,
        showNextBtn: true
      })
    }
    else {
      this.setState({
        showPreviousBtn: true,
        showNextBtn: false
      })
    }
  }

  setNavState(next) {
    this.setState({navState: this.getNavStates(next, this.props.steps.length)})
    if (next < this.props.steps.length) {
      this.setState({compState: next})
    }
    this.checkNavState(next);
  }

  handleKeyDown(evt) {
    if (evt.which === 13) {
      this.next()
    }
  }

  handleOnClick(evt) {
    if (evt.currentTarget.value === (this.props.steps.length - 1) &&
      this.state.compState === (this.props.steps.length - 1)) {
      this.setNavState(this.props.steps.length)
    }
    else {
      this.setNavState(evt.currentTarget.value)
    }
  }

  next() {
    this.setNavState(this.state.compState + 1)
  }

  previous() {
    if (this.state.compState > 0) {
      this.setNavState(this.state.compState - 1)
    }
  }

  getClassName(className, i){
    return className + "-" + this.state.navState.styles[i];
  }

  renderSteps() {
    return this.props.steps.map((s, i)=> (

        {i+1}
        {this.props.steps[i].name}

    ));
  }

  render() {

    return (

          {this.renderSteps()}

        {this.props.steps[this.state.compState].component}

          <button style={this.state.showPreviousBtn ? {} : this.hidden}
                  className="multistep__btn--prev"
                  onClick={this.previous}>Previous</button>

          <button style={this.state.showNextBtn ? {} : this.hidden}
                  className="multistep__btn--next"
                  onClick={this.next}>Next</button>

    );
  }
}

MultiStep.defaultProps = {
  showNavigation: true
};
<|endoftext|>


<commit_before>// Bit-wise rotate left
var rotl = function (n, b) {
    return (n << b) | (n >>> (32 - b));
};

// Bit-wise rotate right
var rotr = function (n, b) {
    return (n << (32 - b)) | (n >>> b);
};

// Swap big-endian to little-endian and vice versa
var endian = function (n) {
    // If number given, swap endian
    if (n.constructor == Number) {
        return rotl(n,  8) & 0x00FF00FF | rotl(n, 24) & 0xFF00FF00;
    }

    // Else, assume array and swap all items
    for (var i = 0; i < n.length; i++) {
        n[i] = endian(n[i]);
    }
    return n;
}

var Key = require('./eckey');

module.exports = {
    Address: require('./address'),
    Key: Key.ECKey,
    ECKey: Key.ECKey,
    ECPubKey: Key.ECPubKey,
    Message: require('./message'),
    BigInteger: require('./jsbn/jsbn'),
    Crypto: require('./crypto-js/crypto'),
    Script: require('./script'),
    Opcode: require('./opcode'),
    Transaction: require('./transaction').Transaction,
    Util: require('./util'),
    TransactionIn: require('./transaction').TransactionIn,
    TransactionOut: require('./transaction').TransactionOut,
    ECPointFp: require('./jsbn/ec').ECPointFp,
    Wallet: require('./wallet'),

    ecdsa: require('./ecdsa'),
    BIP32key: require('./bip32'),

    // base58 encoding/decoding to bytes
    base58: require('./base58'),

    // conversions
    convert: require('./convert'),

    endian: endian
}
<commit_msg>Replace BIP32key with HDWallet in index.js<commit_after>// Bit-wise rotate left
var rotl = function (n, b) {
    return (n << b) | (n >>> (32 - b));
};

// Bit-wise rotate right
var rotr = function (n, b) {
    return (n << (32 - b)) | (n >>> b);
};

// Swap big-endian to little-endian and vice versa
var endian = function (n) {
    // If number given, swap endian
    if (n.constructor == Number) {
        return rotl(n,  8) & 0x00FF00FF | rotl(n, 24) & 0xFF00FF00;
    }

    // Else, assume array and swap all items
    for (var i = 0; i < n.length; i++) {
        n[i] = endian(n[i]);
    }
    return n;
}

var Key = require('./eckey');

module.exports = {
    Address: require('./address'),
    Key: Key.ECKey,
    ECKey: Key.ECKey,
    ECPubKey: Key.ECPubKey,
    Message: require('./message'),
    BigInteger: require('./jsbn/jsbn'),
    Crypto: require('./crypto-js/crypto'),
    Script: require('./script'),
    Opcode: require('./opcode'),
    Transaction: require('./transaction').Transaction,
    Util: require('./util'),
    TransactionIn: require('./transaction').TransactionIn,
    TransactionOut: require('./transaction').TransactionOut,
    ECPointFp: require('./jsbn/ec').ECPointFp,
    Wallet: require('./wallet'),

    ecdsa: require('./ecdsa'),
    HDWallet: require('./hdwallet.js'),

    // base58 encoding/decoding to bytes
    base58: require('./base58'),

    // conversions
    convert: require('./convert'),

    endian: endian
}
<|endoftext|>


<commit_before>import React from 'react';
import createReactClass from 'create-react-class';
import { render } from 'react-dom';
import { AppContainer } from 'react-hot-loader';
import 'normalize.css';
import Root from './root';
import registry from './lib/registry';
import './index.css';

if (process.env.NODE_ENV !== 'production') {
  require('./utils.css'); // eslint-disable-line
}

// Log the version number
console.log(`Netlify CMS version ${NETLIFY_CMS_VERSION}`);

// Create mount element dynamically
const el = document.createElement('div');
el.id = 'root';
document.body.appendChild(el);

render((
  <AppContainer>
    <Root />
  </AppContainer>
), el);

if (module.hot) {
  module.hot.accept('./root', () => { render(Root); });
}

const buildtInPlugins = [{
  label: 'Image',
  id: 'image',
  fromBlock: match => match && {
    image: match[2],
    alt: match[1],
  },
  toBlock: data => `![${ data.alt }](${ data.image })`,
  toPreview: (data, getAsset) => ,
  pattern: /^!\[([^\]]+)]\(([^)]+)\)$/,
  fields: [{
    label: 'Image',
    name: 'image',
    widget: 'image',
  }, {
    label: 'Alt Text',
    name: 'alt',
  }],
}];
buildtInPlugins.forEach(plugin => registry.registerEditorComponent(plugin));

const CMS = {};
for (const method in registry) { // eslint-disable-line
  CMS[method] = registry[method];
}

if (typeof window !== 'undefined') {
  window.CMS = CMS;
  window.createClass = window.createClass || createReactClass;
  window.h = window.h || React.createElement;
}

export default CMS;
<commit_msg>Fix empty image fields saving null or undefined.<commit_after>import React from 'react';
import createReactClass from 'create-react-class';
import { render } from 'react-dom';
import { AppContainer } from 'react-hot-loader';
import 'normalize.css';
import Root from './root';
import registry from './lib/registry';
import './index.css';

if (process.env.NODE_ENV !== 'production') {
  require('./utils.css'); // eslint-disable-line
}

// Log the version number
console.log(`Netlify CMS version ${NETLIFY_CMS_VERSION}`);

// Create mount element dynamically
const el = document.createElement('div');
el.id = 'root';
document.body.appendChild(el);

render((
  <AppContainer>
    <Root />
  </AppContainer>
), el);

if (module.hot) {
  module.hot.accept('./root', () => { render(Root); });
}

const builtInPlugins = [{
  label: 'Image',
  id: 'image',
  fromBlock: match => match && {
    image: match[2],
    alt: match[1],
  },
  toBlock: data => `![${ data.alt || "" }](${ data.image || "" })`,
  toPreview: (data, getAsset) => ,
  pattern: /^!\[([^\]]+)]\(([^)]+)\)$/,
  fields: [{
    label: 'Image',
    name: 'image',
    widget: 'image',
  }, {
    label: 'Alt Text',
    name: 'alt',
  }],
}];
builtInPlugins.forEach(plugin => registry.registerEditorComponent(plugin));

const CMS = {};
for (const method in registry) { // eslint-disable-line
  CMS[method] = registry[method];
}

if (typeof window !== 'undefined') {
  window.CMS = CMS;
  window.createClass = window.createClass || createReactClass;
  window.h = window.h || React.createElement;
}

export default CMS;
<|endoftext|>


<commit_before>import Bar from './BaseCharts/Bar'
import Doughnut from './BaseCharts/Doughnut'
import Line from './BaseCharts/Line'
import Pie from './BaseCharts/Pie'
import PolarArea from './BaseCharts/PolarArea'
import Radar from './BaseCharts/Radar'
import Bubble from './BaseCharts/Bubble'
import reactiveProp from '../mixins/reactiveProp'
import reactiveData from '../mixins/reactiveData'

const VueCharts = {
  Bar,
  Doughnut,
  Line,
  Pie,
  PolarArea,
  Radar,
  Bubble,
  reactiveProp,
  reactiveData
}

module.exports = VueCharts
<commit_msg>🐛 Fix paths<commit_after>import Bar from './BaseCharts/Bar'
import Doughnut from './BaseCharts/Doughnut'
import Line from './BaseCharts/Line'
import Pie from './BaseCharts/Pie'
import PolarArea from './BaseCharts/PolarArea'
import Radar from './BaseCharts/Radar'
import Bubble from './BaseCharts/Bubble'
import reactiveProp from './mixins/reactiveProp'
import reactiveData from './mixins/reactiveData'

const VueCharts = {
  Bar,
  Doughnut,
  Line,
  Pie,
  PolarArea,
  Radar,
  Bubble,
  reactiveProp,
  reactiveData
}
<|endoftext|>


<commit_before>import fs from 'fs';
import path from 'path';
import Walker from 'node-source-walk';
import walkdir from 'walkdir';
import minimatch from 'minimatch';
import component from './component';

function constructComponent(source, name) {
  return source[name].reduce((result, current) =>
    Object.assign(result, {
      [current]: require(path.resolve(__dirname, name, current)),
    }), {});
}

const availableParsers = constructComponent(component, 'parser');

const availableDetectors = constructComponent(component, 'detector');

const defaultOptions = {
  ignoreDirs: [
    '.git',
    '.svn',
    '.hg',
    '.idea',
    'node_modules',
    'bower_components',
  ],
  parsers: {
    '*.js': availableParsers.es6,
    '*.jsx': availableParsers.jsx,
  },
  detectors: [
    availableDetectors.importDeclaration,
    availableDetectors.requireCallExpression,
    availableDetectors.gruntLoadTaskCallExpression,
  ],
};

function unifyParser(parsers) {
  return Object.assign({}, ...Object.keys(parsers).map(key => ({
    [key]: parsers[key] instanceof Array ? parsers[key] : [parsers[key]],
  })));
}

function safeDetect(detector, node) {
  try {
    return detector(node);
  } catch (error) {
    return [];
  }
}

function minus(array1, array2) {
  return array1.filter(item => array2.indexOf(item) === -1);
}

function intersect(array1, array2) {
  return array1.filter(item => array2.indexOf(item) !== -1);
}

function unique(array) {
  return array.filter((value, index) => array.indexOf(value) === index);
}

function getDependencies(filename, parser, detectors) {
  return new Promise((resolve, reject) => {
    fs.readFile(filename, 'utf8', (error, content) => {
      if (error) {
        reject(error);
      }

      try {
        const ast = parser(content);
        resolve(ast);
      } catch (syntaxError) {
        reject(syntaxError);
      }
    });
  }).then(ast => {
    const walker = new Walker();
    let dependencies = [];

    walker.walk(ast, node => {
      const results = detectors.map(detector => safeDetect(detector, node));
      dependencies = dependencies.concat(...results);
    });

    return dependencies
      .filter(dependency => dependency)
      .map(dependency => dependency.replace
        ? dependency.replace(/\/.*$/, '')
        : dependency);
  });
}

function checkFile(filename, deps, devDeps, parsers, detectors) {
  const basename = path.basename(filename);
  const targets = [].concat(...Object.keys(parsers)
    .filter(glob => minimatch(basename, glob))
    .map(key => parsers[key]));

  return targets.map(parser =>
    getDependencies(filename, parser, detectors)
      .then(used => ({
        dependencies: minus(deps, used),
        devDependencies: minus(devDeps, used),
      }), error => ({
        dependencies: deps,
        devDependencies: devDeps,
        invalidFiles: {
          [filename]: error,
        },
      })));
}

function checkDirectory(dir, ignoreDirs, deps, devDeps, parsers, detectors) {
  return new Promise(resolve => {
    const promises = [];
    const finder = walkdir(dir, { 'no_recurse': true });

    finder.on('directory', subdir =>
      ignoreDirs.indexOf(path.basename(subdir)) !== -1
      ? null
      : promises.push(
          checkDirectory(subdir, ignoreDirs, deps, devDeps, parsers, detectors)));

    finder.on('file', filename =>
      promises.push(...checkFile(filename, deps, devDeps, parsers, detectors)));

    finder.on('end', () =>
      resolve(Promise.all(promises).then(results =>
        results.reduce((obj, current) => ({
          dependencies: intersect(obj.dependencies, current.dependencies),
          devDependencies: intersect(obj.devDependencies, current.devDependencies),
          invalidFiles: Object.assign(obj.invalidFiles, current.invalidFiles),
          invalidDirs: Object.assign(obj.invalidDirs, current.invalidDirs),
        }), {
          dependencies: deps,
          devDependencies: devDeps,
          invalidFiles: {},
          invalidDirs: {},
        }))));

    finder.on('error', (dirPath, error) =>
      promises.push(Promise.resolve({
        dependencies: deps,
        devDependencies: devDeps,
        invalidDirs: {
          [dirPath]: error,
        },
      })));
  });
}

function isIgnored(ignoreMatches, dependency) {
  return ignoreMatches.some(match => minimatch(dependency, match));
}

function hasBin(rootDir, dependency) {
  try {
    const depPkg = require(path.join(rootDir, 'node_modules', dependency, 'package.json'));
    return depPkg.hasOwnProperty('bin');
  } catch (error) {
    return false;
  }
}

function filterDependencies(rootDir, ignoreMatches, dependencies) {
  return Object.keys(dependencies)
    .filter(dependency => !hasBin(rootDir, dependency))
    .filter(dependency => !isIgnored(ignoreMatches, dependency));
}

export default function depcheck(rootDir, options, cb) {
  const parsers = unifyParser(options.parsers || defaultOptions.parsers);
  const detectors = options.detectors || defaultOptions.detectors;
  const ignoreMatches = options.ignoreMatches || [];
  const ignoreDirs = unique(defaultOptions.ignoreDirs.concat(options.ignoreDirs));

  const metadata = options.package || require(path.join(rootDir, 'package.json'));
  const dependencies = metadata.dependencies || {};
  const devDependencies = metadata.devDependencies || {};
  const deps = filterDependencies(rootDir, ignoreMatches, dependencies);
  const devDeps = filterDependencies(rootDir, ignoreMatches, options.withoutDev ? [] : devDependencies);

  return checkDirectory(rootDir, ignoreDirs, deps, devDeps, parsers, detectors)
    .then(cb);
}

depcheck.parser = availableParsers;
depcheck.detector = availableDetectors;
<commit_msg>Refine the checkDirectory code.<commit_after>import fs from 'fs';
import path from 'path';
import Walker from 'node-source-walk';
import walkdir from 'walkdir';
import minimatch from 'minimatch';
import component from './component';

function constructComponent(source, name) {
  return source[name].reduce((result, current) =>
    Object.assign(result, {
      [current]: require(path.resolve(__dirname, name, current)),
    }), {});
}

const availableParsers = constructComponent(component, 'parser');

const availableDetectors = constructComponent(component, 'detector');

const defaultOptions = {
  ignoreDirs: [
    '.git',
    '.svn',
    '.hg',
    '.idea',
    'node_modules',
    'bower_components',
  ],
  parsers: {
    '*.js': availableParsers.es6,
    '*.jsx': availableParsers.jsx,
  },
  detectors: [
    availableDetectors.importDeclaration,
    availableDetectors.requireCallExpression,
    availableDetectors.gruntLoadTaskCallExpression,
  ],
};

function unifyParser(parsers) {
  return Object.assign({}, ...Object.keys(parsers).map(key => ({
    [key]: parsers[key] instanceof Array ? parsers[key] : [parsers[key]],
  })));
}

function safeDetect(detector, node) {
  try {
    return detector(node);
  } catch (error) {
    return [];
  }
}

function minus(array1, array2) {
  return array1.filter(item => array2.indexOf(item) === -1);
}

function intersect(array1, array2) {
  return array1.filter(item => array2.indexOf(item) !== -1);
}

function unique(array) {
  return array.filter((value, index) => array.indexOf(value) === index);
}

function getDependencies(filename, parser, detectors) {
  return new Promise((resolve, reject) => {
    fs.readFile(filename, 'utf8', (error, content) => {
      if (error) {
        reject(error);
      }

      try {
        const ast = parser(content);
        resolve(ast);
      } catch (syntaxError) {
        reject(syntaxError);
      }
    });
  }).then(ast => {
    const walker = new Walker();
    let dependencies = [];

    walker.walk(ast, node => {
      const results = detectors.map(detector => safeDetect(detector, node));
      dependencies = dependencies.concat(...results);
    });

    return dependencies
      .filter(dependency => dependency)
      .map(dependency => dependency.replace
        ? dependency.replace(/\/.*$/, '')
        : dependency);
  });
}

function checkFile(filename, deps, devDeps, parsers, detectors) {
  const basename = path.basename(filename);
  const targets = [].concat(...Object.keys(parsers)
    .filter(glob => minimatch(basename, glob))
    .map(key => parsers[key]));

  return targets.map(parser =>
    getDependencies(filename, parser, detectors)
      .then(used => ({
        dependencies: minus(deps, used),
        devDependencies: minus(devDeps, used),
      }), error => ({
        dependencies: deps,
        devDependencies: devDeps,
        invalidFiles: {
          [filename]: error,
        },
      })));
}

function checkDirectory(dir, ignoreDirs, deps, devDeps, parsers, detectors) {
  return new Promise(resolve => {
    const promises = [];
    const finder = walkdir(dir, { 'no_recurse': true });

    finder.on('directory', subdir =>
      ignoreDirs.indexOf(path.basename(subdir)) === -1 &&
      promises.push(
        checkDirectory(subdir, ignoreDirs, deps, devDeps, parsers, detectors)));

    finder.on('file', filename =>
      promises.push(
        ...checkFile(filename, deps, devDeps, parsers, detectors)));

    finder.on('error', (dirPath, error) =>
      promises.push(Promise.resolve({
        dependencies: deps,
        devDependencies: devDeps,
        invalidDirs: {
          [dirPath]: error,
        },
      })));

    finder.on('end', () =>
      resolve(Promise.all(promises).then(results =>
        results.reduce((obj, current) => ({
          dependencies: intersect(obj.dependencies, current.dependencies),
          devDependencies: intersect(obj.devDependencies, current.devDependencies),
          invalidFiles: Object.assign(obj.invalidFiles, current.invalidFiles),
          invalidDirs: Object.assign(obj.invalidDirs, current.invalidDirs),
        }), {
          dependencies: deps,
          devDependencies: devDeps,
          invalidFiles: {},
          invalidDirs: {},
        }))));
  });
}

function isIgnored(ignoreMatches, dependency) {
  return ignoreMatches.some(match => minimatch(dependency, match));
}

function hasBin(rootDir, dependency) {
  try {
    const depPkg = require(path.join(rootDir, 'node_modules', dependency, 'package.json'));
    return depPkg.hasOwnProperty('bin');
  } catch (error) {
    return false;
  }
}

function filterDependencies(rootDir, ignoreMatches, dependencies) {
  return Object.keys(dependencies)
    .filter(dependency => !hasBin(rootDir, dependency))
    .filter(dependency => !isIgnored(ignoreMatches, dependency));
}

export default function depcheck(rootDir, options, cb) {
  const parsers = unifyParser(options.parsers || defaultOptions.parsers);
  const detectors = options.detectors || defaultOptions.detectors;
  const ignoreMatches = options.ignoreMatches || [];
  const ignoreDirs = unique(defaultOptions.ignoreDirs.concat(options.ignoreDirs));

  const metadata = options.package || require(path.join(rootDir, 'package.json'));
  const dependencies = metadata.dependencies || {};
  const devDependencies = metadata.devDependencies || {};
  const deps = filterDependencies(rootDir, ignoreMatches, dependencies);
  const devDeps = filterDependencies(rootDir, ignoreMatches, options.withoutDev ? [] : devDependencies);

  return checkDirectory(rootDir, ignoreDirs, deps, devDeps, parsers, detectors)
    .then(cb);
}

depcheck.parser = availableParsers;
depcheck.detector = availableDetectors;
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import { Table, Column, Cell } from 'fixed-data-table-2';
import _ from 'underscore';

// import '../dist/fixed-data-table.css';
// import '../dist/agr.css';

import { ASC, DESC, NONE } from './constants';
import Header from './components/Header';
import Download from './components/Download';
import Filter from './components/ColumnFilter';
import Dimensions from 'react-dimensions';
import debug from 'debug';

class FlyBaseDataGrid extends Component {
  constructor(props) {
    super(props);
    this.state = {
      sortDir: this.initSortCols(),
      items: props.data,
      filter: '',
    };
    this.handleSort   = this.handleSort.bind(this);
    this.handleColumnFilter = this.handleColumnFilter.bind(this);
  }

  initSortCols() {
    const sortCols = {};
    this.props.columns.forEach((col) => sortCols[col.id] = NONE);
    return sortCols;
  }

  handleColumnFilter(e, column){

      //  reset all column filter boxes to "" on focus change
      //  reset grid to default items
     const filterText = e.target.value.toLowerCase();

      const temp = this.props.data;

      var value;
      function isMatch(item){

         value = item[column];

        return (value.toString().toLowerCase().indexOf(filterText)!=-1);

      }

      const filteredItems = temp.filter((item) => { return isMatch(item); });

      if (!filteredItems.length){
         filteredItems.push({ id: "", name: "", address: "", state: "", zip: ""});
      }

     this.setState({
       items: filteredItems,
       filter: filterText
      });
  }

  handleSort(column) {
    let current = this.state.sortDir;
    const sortDir = current[column];

    let sortedItems = _.sortBy(this.state.items, column);
    if ( sortDir === ASC) {
      sortedItems.reverse();
    }

    // Reset all column sorts before we set the new sort direction below.
    current = this.initSortCols();

    // Reverse sort
    if (sortDir === ASC) {
      current[column] = DESC;
    }
    else {
      current[column] = ASC;
    }

    // Set state with new sorted order.
    this.setState({
      sortDir: current,
      items: sortedItems,
    });
 }

  render() {
    const { columns, data, showColumnFilter, downloadButton, ...props } = this.props;
    const { items } = this.state;

    const style = {
      backgroundColor: 'blue',
      paddingLeft: 0,
      listStyle: 'none'
    };

    return (

            { columns.map((column) =>
                     <Column

                       width={200}
                       allowCellsRecycling={false}
                       key={column.id}
                       flexGrow={1}
                       columnKey={column.id}

                       header={

                           {column.name}

                       }

                       cell={
                         (props) => {
                           const row = items[props.rowIndex];
                           let text = row[column.id];
                           if (column.render) {
                             text = column.render(text, row, column.id);
                           }
                           return (
                             <Cell {...props}>
                               {text}
                             </Cell>
                           )
                         }
                       }
                     />
                    )
            }

        {
          downloadButton.map((type) => <Download columns={columns} className={'btn btn-default'} key={type} type={type} items={items} /> )
        }

    );
  }
}

// See https://facebook.github.io/react/docs/typechecking-with-proptypes.html
FlyBaseDataGrid.propTypes = {
  data: PropTypes.array.isRequired,
  columns: PropTypes.arrayOf(
    PropTypes.shape({
      id: PropTypes.string,
      name: PropTypes.string,
  }),
  ).isRequired,
  rowHeight: PropTypes.number,
  headerHeight: PropTypes.number,
  width: PropTypes.number,
  height: PropTypes.number,
  showFilter: PropTypes.bool,
};

FlyBaseDataGrid.defaultProps = {
  rowHeight: 50,
  headerHeight: 50,
  width: 1000,
  height: 500,
  showFilter: false,
};

export default FlyBaseDataGrid;
<commit_msg>add code to pass in maxHeight<commit_after>import React, { Component, PropTypes } from 'react';
import { Table, Column, Cell } from 'fixed-data-table-2';
import _ from 'underscore';

// import '../dist/fixed-data-table.css';
// import '../dist/agr.css';

import { ASC, DESC, NONE } from './constants';
import Header from './components/Header';
import Download from './components/Download';
import Filter from './components/ColumnFilter';
import Dimensions from 'react-dimensions';
import debug from 'debug';

class FlyBaseDataGrid extends Component {
  constructor(props) {
    super(props);
    this.state = {
      sortDir: this.initSortCols(),
      items: props.data,
      filter: '',
    };
    this.handleSort   = this.handleSort.bind(this);
    this.handleColumnFilter = this.handleColumnFilter.bind(this);
  }

  initSortCols() {
    const sortCols = {};
    this.props.columns.forEach((col) => sortCols[col.id] = NONE);
    return sortCols;
  }

  handleColumnFilter(e, column){

      //  reset all column filter boxes to "" on focus change
      //  reset grid to default items
     const filterText = e.target.value.toLowerCase();

      const temp = this.props.data;

      var value;
      function isMatch(item){

         value = item[column];

        return (value.toString().toLowerCase().indexOf(filterText)!=-1);

      }

      const filteredItems = temp.filter((item) => { return isMatch(item); });

      if (!filteredItems.length){
         filteredItems.push({ id: "", name: "", address: "", state: "", zip: ""});
      }

     this.setState({
       items: filteredItems,
       filter: filterText
      });
  }

  handleSort(column) {
    let current = this.state.sortDir;
    const sortDir = current[column];

    let sortedItems = _.sortBy(this.state.items, column);
    if ( sortDir === ASC) {
      sortedItems.reverse();
    }

    // Reset all column sorts before we set the new sort direction below.
    current = this.initSortCols();

    // Reverse sort
    if (sortDir === ASC) {
      current[column] = DESC;
    }
    else {
      current[column] = ASC;
    }

    // Set state with new sorted order.
    this.setState({
      sortDir: current,
      items: sortedItems,
    });
 }

  render() {
    const { columns, data, showColumnFilter, downloadButton, maxHeight, ...props } = this.props;
    const { items } = this.state;

    return (

            { columns.map((column) =>
                     <Column
                       width={200}
                       allowCellsRecycling={false}
                       key={column.id}
                       flexGrow={1}
                       columnKey={column.id}

                       header={

                           {column.name}

                       }

                       cell={
                         (props) => {
                           const row = items[props.rowIndex];
                           let text = row[column.id];
                           if (column.render) {
                             text = column.render(text, row, column.id);
                           }
                           return (
                             <Cell {...props}>
                               {text}
                             </Cell>
                           )
                         }
                       }
                     />
                    )
            }

        {
          downloadButton.map((type) => <Download columns={columns} className={'btn btn-default'} key={type} type={type} items={items} /> )
        }

    );
  }
}

// See https://facebook.github.io/react/docs/typechecking-with-proptypes.html
FlyBaseDataGrid.propTypes = {
  data: PropTypes.array.isRequired,
  columns: PropTypes.arrayOf(
    PropTypes.shape({
      id: PropTypes.string,
      name: PropTypes.string,
  }),
  ).isRequired,
  rowHeight: PropTypes.number,
  headerHeight: PropTypes.number,
  width: PropTypes.number,
  height: PropTypes.number,
  maxHeight: PropTypes.number,
  showFilter: PropTypes.bool,
};

FlyBaseDataGrid.defaultProps = {
  rowHeight: 50,
  headerHeight: 50,
  width: 1000,
  showFilter: false,
};

export default FlyBaseDataGrid;
<|endoftext|>


<commit_before>/**
 * fun-test is a simple function tester.
 *
 * @module fun-test
 */
;(function () {
  'use strict'

  /* imports */
  var specifier = require('specifier')
  var typeCheck = require('type-check').typeCheck
  var funAssert = require('fun-assert')

  /* exports */
  module.exports = funTest

  var optionsSpec = {
    input: [
    ],
    verifier: [
      funAssert.type('Function')
    ]
  }

  var specificationChecker = specifier(optionsSpec)

  /**
   * funTest is a simple function tester.
   *
   * @function funTest
   * @alias fun-test
   *
   * @param {Object} options all function parameters
   * @param {*} options.input to test
   * @param {Function} options.verifier for output of subject given input
   * @param {Function} [options.transformer] applied to subject prior to test
   */
  function funTest (options) {
    specificationChecker(options)

    return function test (subject, reporter) {
      try {
        if (options.transformer) {
          subject = options.transformer(subject)
        }

        subject(options.input, function (error, result) {
          try {
            options.verifier(error, result)
            reporter()
          } catch (e) {
            reporter(e)
          }
        })
      } catch (error) {
        reporter(error)
      }
    }
  }
})()

<commit_msg>[PATCH][REMOVE] try block from callback<commit_after>/**
 * fun-test is a simple function tester.
 *
 * @module fun-test
 */
;(function () {
  'use strict'

  /* imports */
  var specifier = require('specifier')
  var typeCheck = require('type-check').typeCheck
  var funAssert = require('fun-assert')

  /* exports */
  module.exports = funTest

  var optionsSpec = {
    input: [
    ],
    verifier: [
      funAssert.type('Function')
    ]
  }

  var specificationChecker = specifier(optionsSpec)

  /**
   * funTest is a simple function tester.
   *
   * @function funTest
   * @alias fun-test
   *
   * @param {Object} options all function parameters
   * @param {*} options.input to test
   * @param {Function} options.verifier for output of subject given input
   * @param {Function} [options.transformer] applied to subject prior to test
   */
  function funTest (options) {
    specificationChecker(options)

    return function test (subject, reporter) {
      try {
        if (options.transformer) {
          subject = options.transformer(subject)
        }

        subject(options.input, options.verifier)
        reporter()
      } catch (error) {
        reporter(error)
      }
    }
  }
})()

<|endoftext|>


<commit_before>// import * from './scripts/example';

// import './styles/style.css';
// import './styles/style.sass';
import 'normalize.css';
import './styles/style.scss';

/* ---------- Lax.js ---------- */
import lax from 'lax.js'

window.onload = function() {
	lax.setup() // init

	const updateLax = () => {
		lax.update(window.scrollY)
		window.requestAnimationFrame(updateLax)
	}

	window.requestAnimationFrame(updateLax)
}

/* ---------- Real vh ---------- */
// https://css-tricks.com/the-trick-to-viewport-units-on-mobile/

// We listen to the resize event
window.addEventListener('resize', () => {
  // We execute the same script as before
  let vh = window.innerHeight * 0.01;
  document.documentElement.style.setProperty('--vh', `${vh}px`);
});

/* ---------- Update hero perspective ---------- */
const heroElem = document.getElementsByClassName('section--hero')[0];
let mouseX = 0;
let mouseY = 0;
let clientBeta = 0;
let clientAlpha = 0;
let perspectiveX = 0;
let perspectiveY = 0;
window.addEventListener('scroll', updateHeroPerspective, {passive: true});
window.addEventListener('mousemove', updateHeroPerspective, {passive: true});
window.addEventListener("deviceorientation", updateHeroPerspective, true);
updateHeroPerspective();
let heroWaitingRefresh = false;

function updateHeroPerspective(event) {
	if(window.pageYOffset <= window.innerHeight && !heroWaitingRefresh) {
		if(event?.clientX !== undefined) mouseX = event.clientX;
		if(event?.clientY !== undefined) mouseY = event.clientY;
		if(event?.beta !== undefined) clientBeta = event.beta; // Y (rotation axis X)
		if(event?.beta !== undefined) clientAlpha = event.alpha; // X (rotation axis Y)

		heroWaitingRefresh = true;
		window.requestAnimationFrame(() => {
			perspectiveX = 0
			+ window.innerWidth/2
			+ (window.innerWidth/2 - mouseX)/10
			+ clientAlpha/180 * 100;

			perspectiveY = 0
			+ window.pageYOffset
			+ window.innerHeight / 4
			+ (window.innerHeight * 3/4 - mouseY)/10;

			heroElem.style.perspectiveOrigin = `${perspectiveX}px ${perspectiveY}px`;
			heroWaitingRefresh = false;
		});
	}
}

<commit_msg>Remove orientation<commit_after>// import * from './scripts/example';

// import './styles/style.css';
// import './styles/style.sass';
import 'normalize.css';
import './styles/style.scss';

/* ---------- Lax.js ---------- */
import lax from 'lax.js'

window.onload = function() {
	lax.setup() // init

	const updateLax = () => {
		lax.update(window.scrollY)
		window.requestAnimationFrame(updateLax)
	}

	window.requestAnimationFrame(updateLax)
}

/* ---------- Real vh ---------- */
// https://css-tricks.com/the-trick-to-viewport-units-on-mobile/

// We listen to the resize event
window.addEventListener('resize', () => {
  // We execute the same script as before
  let vh = window.innerHeight * 0.01;
  document.documentElement.style.setProperty('--vh', `${vh}px`);
});

/* ---------- Update hero perspective ---------- */
const heroElem = document.getElementsByClassName('section--hero')[0];
let mouseX = 0;
let mouseY = 0;
// let clientBeta = 0;
// let clientAlpha = 0;
let perspectiveX = 0;
let perspectiveY = 0;
window.addEventListener('scroll', updateHeroPerspective, {passive: true});
window.addEventListener('mousemove', updateHeroPerspective, {passive: true});
// window.addEventListener("deviceorientation", updateHeroPerspective, true);
updateHeroPerspective();
let heroWaitingRefresh = false;

function updateHeroPerspective(event) {
	if(window.pageYOffset <= window.innerHeight && !heroWaitingRefresh) {
		if(event?.clientX !== undefined) mouseX = event.clientX;
		if(event?.clientY !== undefined) mouseY = event.clientY;
		// if(event?.beta !== undefined) clientBeta = event.beta; // Y (rotation axis X)
		// if(event?.beta !== undefined) clientAlpha = event.alpha; // X (rotation axis Y)

		heroWaitingRefresh = true;
		window.requestAnimationFrame(() => {
			perspectiveX = 0
			+ window.innerWidth/2
			+ (window.innerWidth/2 - mouseX)/10;

			perspectiveY = 0
			+ window.pageYOffset
			+ window.innerHeight / 4
			+ (window.innerHeight * 3/4 - mouseY)/10;

			heroElem.style.perspectiveOrigin = `${perspectiveX}px ${perspectiveY}px`;
			heroWaitingRefresh = false;
		});
	}
}

<|endoftext|>