"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
Object.defineProperty(exports, "MediaControls", {
  enumerable: true,
  get: function get() {
    return _MediaControls.default;
  }
});
Object.defineProperty(exports, "Video", {
  enumerable: true,
  get: function get() {
    return _Video.default;
  }
});
exports.VideoPlayerBase = exports.VideoPlayer = exports.default = void 0;

var _ApiDecorator = _interopRequireDefault(require("@enact/core/internal/ApiDecorator"));

var _dispatcher = require("@enact/core/dispatcher");

var _handle = require("@enact/core/handle");

var _keymap = require("@enact/core/keymap");

var _platform = require("@enact/core/platform");

var _util = require("@enact/core/util");

var _i18n = _interopRequireDefault(require("@enact/i18n"));

var _DurationFmt = _interopRequireDefault(require("@enact/i18n/ilib/lib/DurationFmt"));

var _util2 = require("@enact/i18n/util");

var _spotlight = _interopRequireDefault(require("@enact/spotlight"));

var _SpotlightContainerDecorator = require("@enact/spotlight/SpotlightContainerDecorator");

var _Spottable = require("@enact/spotlight/Spottable");

var _Announce = _interopRequireDefault(require("@enact/ui/AnnounceDecorator/Announce"));

var _ComponentOverride = _interopRequireDefault(require("@enact/ui/ComponentOverride"));

var _FloatingLayer = require("@enact/ui/FloatingLayer");

var _FloatingLayerDecorator = require("@enact/ui/FloatingLayer/FloatingLayerDecorator");

var _Media = _interopRequireDefault(require("@enact/ui/Media"));

var _Slottable = _interopRequireDefault(require("@enact/ui/Slottable"));

var _Touchable = _interopRequireDefault(require("@enact/ui/Touchable"));

var _equals = _interopRequireDefault(require("ramda/src/equals"));

var _propTypes = _interopRequireDefault(require("prop-types"));

var _react = _interopRequireDefault(require("react"));

var _reactDom = _interopRequireDefault(require("react-dom"));

var _shallowEqual = _interopRequireDefault(require("recompose/shallowEqual"));

var _$L = _interopRequireDefault(require("../internal/$L"));

var _Skinnable = _interopRequireDefault(require("../Skinnable"));

var _Spinner = _interopRequireDefault(require("../Spinner"));

var _util3 = require("./util");

var _Overlay = _interopRequireDefault(require("./Overlay"));

var _MediaControls = _interopRequireDefault(require("./MediaControls"));

var _MediaTitle = _interopRequireDefault(require("./MediaTitle"));

var _MediaSlider = _interopRequireDefault(require("./MediaSlider"));

var _FeedbackContent = _interopRequireDefault(require("./FeedbackContent"));

var _FeedbackTooltip = _interopRequireDefault(require("./FeedbackTooltip"));

var _Times = _interopRequireDefault(require("./Times"));

var _Video = _interopRequireDefault(require("./Video"));

var _VideoPlayer = _interopRequireDefault(require("./VideoPlayer.less"));

var _class, _temp, _initialiseProps;

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }

function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }

function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }

function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }

function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }

function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

var SpottableDiv = (0, _Touchable.default)((0, _Spottable.Spottable)('div'));
var RootContainer = (0, _SpotlightContainerDecorator.SpotlightContainerDecorator)({
  enterTo: 'default-element',
  defaultElement: [".".concat(_VideoPlayer.default.controlsHandleAbove), ".".concat(_VideoPlayer.default.controlsFrame)]
}, 'div');
var ControlsContainer = (0, _SpotlightContainerDecorator.SpotlightContainerDecorator)({
  enterTo: '',
  straightOnly: true
}, 'div');

var forwardWithState = function forwardWithState(type) {
  return (0, _handle.adaptEvent)((0, _handle.call)('addStateToEvent'), (0, _handle.forwardWithPrevent)(type));
}; // provide forwarding of events on media controls


var forwardControlsAvailable = (0, _handle.forward)('onControlsAvailable');
var forwardPlay = forwardWithState('onPlay');
var forwardPause = forwardWithState('onPause');
var forwardRewind = forwardWithState('onRewind');
var forwardFastForward = forwardWithState('onFastForward');
var forwardJumpBackward = forwardWithState('onJumpBackward');
var forwardJumpForward = forwardWithState('onJumpForward');
var AnnounceState = {
  // Video is loaded but additional announcements have not been made
  READY: 0,
  // The title should be announced
  TITLE: 1,
  // The title has been announce
  TITLE_READ: 2,
  // The infoComponents should be announce
  INFO: 3,
  // All announcements have been made
  DONE: 4
};
/**
 * Every callback sent by [VideoPlayer]{@link moonstone/VideoPlayer} receives a status package,
 * which includes an object with the following key/value pairs as the first argument:
 *
 * @typedef {Object} videoStatus
 * @memberof moonstone/VideoPlayer
 * @property {String} type - Type of event that triggered this callback
 * @property {Number} currentTime - Playback index of the media in seconds
 * @property {Number} duration - Media's entire duration in seconds
 * @property {Boolean} paused - Playing vs paused state. `true` means the media is paused
 * @property {Number} playbackRate - Current playback rate, as a number
 * @property {Number} proportionLoaded - A value between `0` and `1` representing the proportion of the media that has loaded
 * @property {Number} proportionPlayed - A value between `0` and `1` representing the proportion of the media that has already been shown
 *
 * @public
 */

/**
 * A set of playback rates when media fast forwards, rewinds, slow-fowards, or slow-rewinds.
 *
 * The number used for each operation is proportional to the normal playing speed, 1. If the rate
 * is less than 1, it will play slower than normal speed, and, if it is larger than 1, it will play
 * faster. If it is negative, it will play backward.
 *
 * The order of numbers represents the incremental order of rates that will be used for each
 * operation. Note that all rates are expressed as strings and fractions are used rather than decimals
 * (e.g.: `'1/2'`, not `'0.5'`).
 *
 * @typedef {Object} playbackRateHash
 * @memberof moonstone/VideoPlayer
 * @property {String[]} fastForward - An array of playback rates when media fast forwards
 * @property {String[]} rewind - An array of playback rates when media rewinds
 * @property {String[]} slowForward - An array of playback rates when media slow-forwards
 * @property {String[]} slowRewind - An array of playback rates when media slow-rewinds
 *
 * @public
 */

/**
 * A player for video {@link moonstone/VideoPlayer.VideoPlayerBase}.
 *
 * @class VideoPlayerBase
 * @memberof moonstone/VideoPlayer
 * @ui
 * @public
 */

var VideoPlayerBase = (_temp = _class =
/*#__PURE__*/
function (_React$Component) {
  _inherits(VideoPlayerBase, _React$Component);

  function VideoPlayerBase(props) {
    var _this;

    _classCallCheck(this, VideoPlayerBase);

    _this = _possibleConstructorReturn(this, (VideoPlayerBase.__proto__ || Object.getPrototypeOf(VideoPlayerBase)).call(this, props)); // Internal State

    _initialiseProps.call(_assertThisInitialized(_this));

    _this.video = null;
    _this.pulsedPlaybackRate = null;
    _this.pulsedPlaybackState = null;
    _this.prevCommand = props.noAutoPlay ? 'pause' : 'play';
    _this.showMiniFeedback = false;
    _this.speedIndex = 0;
    _this.id = _this.generateId();

    _this.selectPlaybackRates('fastForward');

    _this.sliderKnobProportion = 0;
    _this.mediaControlsSpotlightId = props.spotlightId + '_mediaControls';
    _this.moreButtonSpotlightId = _this.mediaControlsSpotlightId + '_moreButton';

    _this.initI18n(); // Re-render-necessary State


    _this.state = {
      announce: AnnounceState.READY,
      currentTime: 0,
      duration: 0,
      error: false,
      loading: false,
      paused: props.noAutoPlay,
      playbackRate: 1,
      titleOffsetHeight: 0,
      bottomOffsetHeight: 0,
      // Non-standard state computed from properties
      bottomControlsRendered: false,
      feedbackAction: 'idle',
      feedbackVisible: false,
      infoVisible: false,
      mediaControlsVisible: false,
      mediaSliderVisible: false,
      miniFeedbackVisible: false,
      proportionLoaded: 0,
      proportionPlayed: 0,
      sourceUnavailable: true,
      titleVisible: true
    };

    if (props.setApiProvider) {
      props.setApiProvider(_assertThisInitialized(_this));
    }

    return _this;
  }

  _createClass(VideoPlayerBase, [{
    key: "componentDidMount",
    value: function componentDidMount() {
      (0, _dispatcher.on)('mousemove', this.activityDetected);
      (0, _dispatcher.on)('keydown', this.handleGlobalKeyDown);
      this.startDelayedFeedbackHide();
    }
  }, {
    key: "shouldComponentUpdate",
    value: function shouldComponentUpdate(nextProps, nextState) {
      if ( // Use shallow props compare instead of source comparison to support possible changes
      // from mediaComponent.
      (0, _shallowEqual.default)(this.props, nextProps) && !this.state.miniFeedbackVisible && this.state.miniFeedbackVisible === nextState.miniFeedbackVisible && !this.state.mediaSliderVisible && this.state.mediaSliderVisible === nextState.mediaSliderVisible && this.state.loading === nextState.loading && this.props.loading === nextProps.loading && (this.state.currentTime !== nextState.currentTime || this.state.proportionPlayed !== nextState.proportionPlayed || this.state.sliderTooltipTime !== nextState.sliderTooltipTime)) {
        return false;
      }

      return true;
    }
  }, {
    key: "componentWillUpdate",
    value: function componentWillUpdate(nextProps) {
      var isInfoComponentsEqual = (0, _equals.default)(this.props.infoComponents, nextProps.infoComponents),
          titleHeight = this.state.titleOffsetHeight,
          shouldCalculateTitleOffset = (!titleHeight && isInfoComponentsEqual || titleHeight && !isInfoComponentsEqual) && this.state.mediaControlsVisible;
      this.initI18n();

      if (shouldCalculateTitleOffset) {
        var titleOffsetHeight = this.getHeightForElement('infoComponents');

        if (titleOffsetHeight) {
          this.setState({
            titleOffsetHeight: titleOffsetHeight
          });
        }
      }
    }
  }, {
    key: "componentDidUpdate",
    value: function componentDidUpdate(prevProps, prevState) {
      var _this2 = this;

      if (!this.state.mediaControlsVisible && prevState.mediaControlsVisible !== this.state.mediaControlsVisible || !this.state.mediaSliderVisible && prevState.mediaSliderVisible !== this.state.mediaSliderVisible) {
        this.context.closeAllFloatingLayers();
      }

      if (this.props.spotlightId !== prevProps.spotlightId) {
        this.mediaControlsSpotlightId = this.props.spotlightId + '_mediaControls';
        this.moreButtonSpotlightId = this.mediaControlsSpotlightId + '_moreButton';
      }

      if (!this.state.mediaControlsVisible && prevState.mediaControlsVisible) {
        forwardControlsAvailable({
          available: false
        }, this.props);
        this.stopAutoCloseTimeout();

        if (!this.props.spotlightDisabled) {
          // If last focused item were in a user specified components (e.g. leftComponents,
          // rightComponents, children, etc.), we need to explicitly blur the element when
          // MediaControls hide. See ENYO-5454
          var current = _spotlight.default.getCurrent();

          var mediaControls = document.querySelector("[data-spotlight-id=\"".concat(this.mediaControlsSpotlightId, "\"]"));

          if (current && mediaControls && mediaControls.contains(current)) {
            current.blur();
          } // when in pointer mode, the focus call below will only update the last focused for
          // the video player and not set the active container to the video player which will
          // cause focus to land back on the media controls button when spotlight restores
          // focus.


          if (_spotlight.default.getPointerMode()) {
            _spotlight.default.setActiveContainer(this.props.spotlightId);
          } // Set focus to the hidden spottable control - maintaining focus on available spottable
          // controls, which prevents an addiitional 5-way attempt in order to re-show media controls


          _spotlight.default.focus(".".concat(_VideoPlayer.default.controlsHandleAbove));
        }
      } else if (this.state.mediaControlsVisible && !prevState.mediaControlsVisible) {
        forwardControlsAvailable({
          available: true
        }, this.props);
        this.startAutoCloseTimeout();

        if (!this.props.spotlightDisabled) {
          var _current = _spotlight.default.getCurrent();

          if (!_current || this.player.contains(_current)) {
            // Set focus within media controls when they become visible.
            _spotlight.default.focus(this.mediaControlsSpotlightId);
          }
        }
      } // Once video starts loading it queues bottom control render until idle


      if (this.state.bottomControlsRendered && !prevState.bottomControlsRendered && !this.state.mediaControlsVisible) {
        this.showControls();
      }

      if (this.state.mediaControlsVisible && prevState.infoVisible !== this.state.infoVisible) {
        var _current2 = _spotlight.default.getCurrent();

        if (_current2 && _current2.dataset && _current2.dataset.spotlightId === this.moreButtonSpotlightId) {
          // need to blur manually to read out `infoComponent`
          _current2.blur();
        }

        setTimeout(function () {
          _spotlight.default.focus(_this2.moreButtonSpotlightId);
        }, 1);
      }
    }
  }, {
    key: "componentWillUnmount",
    value: function componentWillUnmount() {
      (0, _dispatcher.off)('mousemove', this.activityDetected);
      (0, _dispatcher.off)('keydown', this.handleGlobalKeyDown);
      this.stopRewindJob();
      this.stopAutoCloseTimeout();
      this.stopDelayedTitleHide();
      this.stopDelayedFeedbackHide();
      this.stopDelayedMiniFeedbackHide();
      this.announceJob.stop();
      this.renderBottomControl.stop();
      this.sliderTooltipTimeJob.stop();
      this.slider5WayPressJob.stop();
    } //
    // Internal Methods
    //

  }, {
    key: "isTimeBeyondSelection",
    value: function isTimeBeyondSelection(time) {
      var selection = this.props.selection; // if selection isn't set or only contains the starting value, there isn't a valid selection
      // with which to test the time

      if (selection != null && selection.length >= 2) {
        var _selection = _slicedToArray(selection, 2),
            start = _selection[0],
            end = _selection[1];

        return time > end || time < start;
      }

      return false;
    }
  }, {
    key: "preventTimeChange",
    value: function preventTimeChange(time) {
      return this.isTimeBeyondSelection(time) && !(0, _handle.forwardWithPrevent)('onSeekOutsideSelection', {
        type: 'onSeekOutsideSelection',
        time: time
      }, this.props);
    }
    /**
     * If the announce state is either ready to read the title or ready to read info, advance the
     * state to "read".
     *
     * @returns {Boolean} Returns true to be used in event handlers
     * @private
     */

  }, {
    key: "getControlsAriaProps",
    value: function getControlsAriaProps() {
      if (this.state.announce === AnnounceState.TITLE) {
        return {
          'aria-labelledby': "".concat(this.id, "_title"),
          'aria-live': 'off',
          role: 'alert'
        };
      } else if (this.state.announce === AnnounceState.INFO) {
        return {
          'aria-labelledby': "".concat(this.id, "_info"),
          role: 'region'
        };
      }

      return null;
    }
  }, {
    key: "render",
    value: function render() {
      var _this3 = this;

      var _props = this.props,
          className = _props.className,
          disabled = _props.disabled,
          infoComponents = _props.infoComponents,
          loading = _props.loading,
          mediaControlsComponent = _props.mediaControlsComponent,
          noAutoPlay = _props.noAutoPlay,
          noMiniFeedback = _props.noMiniFeedback,
          noSlider = _props.noSlider,
          noSpinner = _props.noSpinner,
          selection = _props.selection,
          spotlightDisabled = _props.spotlightDisabled,
          spotlightId = _props.spotlightId,
          style = _props.style,
          thumbnailComponent = _props.thumbnailComponent,
          thumbnailSrc = _props.thumbnailSrc,
          title = _props.title,
          VideoComponent = _props.videoComponent,
          mediaProps = _objectWithoutProperties(_props, ["className", "disabled", "infoComponents", "loading", "mediaControlsComponent", "noAutoPlay", "noMiniFeedback", "noSlider", "noSpinner", "selection", "spotlightDisabled", "spotlightId", "style", "thumbnailComponent", "thumbnailSrc", "title", "videoComponent"]);

      delete mediaProps.announce;
      delete mediaProps.autoCloseTimeout;
      delete mediaProps.children;
      delete mediaProps.feedbackHideDelay;
      delete mediaProps.jumpBy;
      delete mediaProps.miniFeedbackHideDelay;
      delete mediaProps.noAutoShowMediaControls;
      delete mediaProps.noMediaSliderFeedback;
      delete mediaProps.onControlsAvailable;
      delete mediaProps.onFastForward;
      delete mediaProps.onJumpBackward;
      delete mediaProps.onJumpForward;
      delete mediaProps.onPause;
      delete mediaProps.onPlay;
      delete mediaProps.onRewind;
      delete mediaProps.onScrub;
      delete mediaProps.onSeekFailed;
      delete mediaProps.onSeekOutsideSelection;
      delete mediaProps.pauseAtEnd;
      delete mediaProps.playbackRateHash;
      delete mediaProps.seekDisabled;
      delete mediaProps.setApiProvider;
      delete mediaProps.thumbnailUnavailable;
      delete mediaProps.titleHideDelay;
      delete mediaProps.videoPath;
      mediaProps.autoPlay = !noAutoPlay;
      mediaProps.className = _VideoPlayer.default.video;
      mediaProps.controls = false;
      mediaProps.mediaComponent = 'video';
      mediaProps.onLoadStart = this.handleLoadStart;
      mediaProps.onUpdate = this.handleEvent;
      mediaProps.ref = this.setVideoRef;
      var controlsAriaProps = this.getControlsAriaProps();
      var proportionSelection = selection;

      if (proportionSelection != null && this.state.duration) {
        proportionSelection = selection.map(function (t) {
          return t / _this3.state.duration;
        });
      }

      return _react.default.createElement(RootContainer, {
        className: _VideoPlayer.default.videoPlayer + ' enact-fit' + (className ? ' ' + className : ''),
        onClick: this.activityDetected,
        ref: this.setPlayerRef,
        spotlightDisabled: spotlightDisabled,
        spotlightId: spotlightId,
        style: style
      }, // Duplicating logic from <ComponentOverride /> until enzyme supports forwardRef
      VideoComponent && ((typeof VideoComponent === 'function' || typeof VideoComponent === 'string') && _react.default.createElement(VideoComponent, mediaProps) || _react.default.isValidElement(VideoComponent) && _react.default.cloneElement(VideoComponent, mediaProps)) || null, _react.default.createElement(_Overlay.default, {
        bottomControlsVisible: this.state.mediaControlsVisible,
        onClick: this.onVideoClick
      }, !noSpinner && (this.state.loading || loading) ? _react.default.createElement(_Spinner.default, {
        centered: true
      }) : null), this.state.bottomControlsRendered ? _react.default.createElement("div", _extends({
        className: _VideoPlayer.default.fullscreen
      }, controlsAriaProps), _react.default.createElement(_FeedbackContent.default, {
        className: _VideoPlayer.default.miniFeedback,
        playbackRate: this.pulsedPlaybackRate || this.selectPlaybackRate(this.speedIndex),
        playbackState: this.pulsedPlaybackState || this.prevCommand,
        visible: this.state.miniFeedbackVisible && !noMiniFeedback
      }, (0, _util3.secondsToTime)(this.state.sliderTooltipTime, this.durfmt)), _react.default.createElement(ControlsContainer, {
        className: _VideoPlayer.default.bottom + (this.state.mediaControlsVisible ? '' : ' ' + _VideoPlayer.default.hidden),
        spotlightDisabled: spotlightDisabled || !this.state.mediaControlsVisible
      }, this.state.mediaSliderVisible ? _react.default.createElement("div", {
        className: _VideoPlayer.default.infoFrame
      }, _react.default.createElement(_MediaTitle.default, {
        id: this.id,
        infoVisible: this.state.infoVisible,
        style: {
          '--infoComponentsOffset': this.state.titleOffsetHeight + 'px'
        },
        title: title,
        visible: this.state.titleVisible && this.state.mediaControlsVisible
      }, infoComponents), _react.default.createElement(_Times.default, {
        current: this.state.currentTime,
        total: this.state.duration,
        formatter: this.durfmt
      })) : null, noSlider ? null : _react.default.createElement(_MediaSlider.default, {
        backgroundProgress: this.state.proportionLoaded,
        disabled: disabled || this.state.sourceUnavailable,
        forcePressed: this.state.slider5WayPressed,
        onBlur: this.handleSliderBlur,
        onChange: this.onSliderChange,
        onFocus: this.handleSliderFocus,
        onKeyDown: this.handleSliderKeyDown,
        onKnobMove: this.handleKnobMove,
        onSpotlightUp: this.handleSpotlightUpFromSlider,
        selection: proportionSelection,
        spotlightDisabled: spotlightDisabled || !this.state.mediaControlsVisible,
        value: this.state.proportionPlayed,
        visible: this.state.mediaSliderVisible
      }, _react.default.createElement(_FeedbackTooltip.default, {
        action: this.state.feedbackAction,
        duration: this.state.duration,
        formatter: this.durfmt,
        hidden: !this.state.feedbackVisible || this.state.sourceUnavailable,
        playbackRate: this.selectPlaybackRate(this.speedIndex),
        playbackState: this.prevCommand,
        thumbnailComponent: thumbnailComponent,
        thumbnailDeactivated: this.props.thumbnailUnavailable,
        thumbnailSrc: thumbnailSrc
      })), _react.default.createElement(_ComponentOverride.default, {
        component: mediaControlsComponent,
        mediaDisabled: disabled || this.state.sourceUnavailable,
        moreButtonSpotlightId: this.moreButtonSpotlightId,
        onBackwardButtonClick: this.handleRewind,
        onClose: this.handleMediaControlsClose,
        onFastForward: this.handleFastForward,
        onForwardButtonClick: this.handleFastForward,
        onJump: this.handleJump,
        onJumpBackwardButtonClick: this.onJumpBackward,
        onJumpForwardButtonClick: this.onJumpForward,
        onKeyDown: this.handleKeyDownFromControls,
        onPause: this.handlePause,
        onPlay: this.handlePlay,
        onRewind: this.handleRewind,
        onToggleMore: this.handleToggleMore,
        paused: this.state.paused,
        spotlightId: this.mediaControlsSpotlightId,
        spotlightDisabled: !this.state.mediaControlsVisible || spotlightDisabled,
        visible: this.state.mediaControlsVisible
      }))) : null, _react.default.createElement(SpottableDiv // This captures spotlight focus for use with 5-way.
      // It's non-visible but lives at the top of the VideoPlayer.
      , {
        className: _VideoPlayer.default.controlsHandleAbove,
        onClick: this.showControls,
        onSpotlightDown: this.showControls,
        spotlightDisabled: this.state.mediaControlsVisible || spotlightDisabled
      }), _react.default.createElement(_Announce.default, {
        ref: this.setAnnounceRef
      }));
    }
  }]);

  return VideoPlayerBase;
}(_react.default.Component), Object.defineProperty(_class, "displayName", {
  configurable: true,
  enumerable: true,
  writable: true,
  value: 'VideoPlayerBase'
}), Object.defineProperty(_class, "propTypes", {
  configurable: true,
  enumerable: true,
  writable: true,
  value:
  /** @lends moonstone/VideoPlayer.VideoPlayerBase.prototype */
  {
    /**
     * passed by AnnounceDecorator for accessibility
     *
     * @type {Function}
     * @private
     */
    announce: _propTypes.default.func,

    /**
     * The time (in milliseconds) before the control buttons will hide.
     *
     * Setting this to 0 or `null` disables closing, requiring user input to open and close.
     *
     * @type {Number}
     * @default 5000
     * @public
     */
    autoCloseTimeout: _propTypes.default.number,

    /**
     * Removes interactive capability from this component. This includes, but is not limited to,
     * key-press events, most clickable buttons, and prevents the showing of the controls.
     *
     * @type {Boolean}
     * @public
     */
    disabled: _propTypes.default.bool,

    /**
     * Amount of time (in milliseconds) after which the feedback text/icon part of the slider's
     * tooltip will automatically hidden after the last action.
     * Setting this to 0 or `null` disables feedbackHideDelay; feedback will always be present.
     *
     * @type {Number}
     * @default 3000
     * @public
     */
    feedbackHideDelay: _propTypes.default.number,

    /**
     * Components placed below the title.
     *
     * Typically these will be media descriptor icons, like how many audio channels, what codec
     * the video uses, but can also be a description for the video or anything else that seems
     * appropriate to provide information about the video to the user.
     *
     * @type {Node}
     * @public
     */
    infoComponents: _propTypes.default.node,

    /**
     * The number of seconds the player should skip forward or backward when a "jump" button is
     * pressed.
     *
     * @type {Number}
     * @default 30
     * @public
     */
    jumpBy: _propTypes.default.number,

    /**
     * Manually set the loading state of the media, in case you have information that
     * `VideoPlayer` does not have.
     *
     * @type {Boolean}
     * @public
     */
    loading: _propTypes.default.bool,

    /**
     * Overrides the default media control component to support customized behaviors.
     *
     * The provided component will receive the following props from `VideoPlayer`:
     *
     * * `mediaDisabled` - `true` when the media controls are not interactive
     * * `onBackwardButtonClick` - Called when the rewind button is pressed
     * * `onClose` - Called when cancel key is pressed when the media controls are visible
     * * `onFastForward` - Called when the media is fast forwarded via a key event
     * * `onForwardButtonClick` - Called when the fast forward button is pressed
     * * `onJump` - Called when the media jumps either forward or backward
     * * `onJumpBackwardButtonClick` - Called when the jump backward button is pressed
     * * `onJumpForwardButtonClick` - Called when the jump forward button is pressed
     * * `onKeyDown` - Called when a key is pressed
     * * `onPause` - Called when the media is paused via a key event
     * * `onPlay` - Called when the media is played via a key event
     * * `onRewind` - Called when the media is rewound via a key event
     * * `onToggleMore` - Called when the more components are hidden or shown
     * * `paused` - `true` when the media is paused
     * * `spotlightId` - The spotlight container Id for the media controls
     * * `spotlightDisabled` - `true` when spotlight is disabled for the media controls
     * * `visible` - `true` when the media controls should be displayed
     *
     * @type {Function|Element}
     * @default `moonstone/VideoPlayer.MediaControls`
     * @public
     */
    mediaControlsComponent: _propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.object]),

    /**
     * Amount of time (in milliseconds), after the last user action, that the `miniFeedback`
     * will automatically hide.
     * Setting this to 0 or `null` disables `miniFeedbackHideDelay`; `miniFeedback` will always
     * be present.
     *
     * @type {Number}
     * @default 2000
     * @public
     */
    miniFeedbackHideDelay: _propTypes.default.number,

    /**
     * Disable audio for this video.
     *
     * In a TV context, this is handled by the remote control, not programmatically in the
     * VideoPlayer API.
     *
     * @type {Boolean}
     * @default false
     * @public
     */
    muted: _propTypes.default.bool,

    /**
     * Prevents the default behavior of playing a video immediately after it's loaded.
     *
     * @type {Boolean}
     * @default false
     * @public
     */
    noAutoPlay: _propTypes.default.bool,

    /**
     * Prevents the default behavior of showing media controls immediately after it's loaded.
     *
     * @type {Boolean}
     * @default false
     * @public
     */
    noAutoShowMediaControls: _propTypes.default.bool,

    /**
     * Hides media slider feedback when fast forward or rewind while media controls are hidden.
     *
     * @type {Boolean}
     * @default false
     * @public
     */
    noMediaSliderFeedback: _propTypes.default.bool,

    /**
     * Removes the mini feedback.
     *
     * @type {Boolean}
     * @default false
     * @public
     */
    noMiniFeedback: _propTypes.default.bool,

    /**
     * Removes the media slider.
     *
     * @type {Boolean}
     * @default false
     * @public
     */
    noSlider: _propTypes.default.bool,

    /**
     * Removes spinner while loading.
     *
     * @type {Boolean}
     * @public
     */
    noSpinner: _propTypes.default.bool,

    /**
     * Called when the player's controls change availability, whether they are shown
     * or hidden.
     *
     * The current status is sent as the first argument in an object with a key `available`
     * which will be either `true` or `false`. (e.g.: `onControlsAvailable({available: true})`)
     *
     * @type {Function}
     * @public
     */
    onControlsAvailable: _propTypes.default.func,

    /**
     * Called when the video is fast forwarded.
     *
     * @type {Function}
     * @public
     */
    onFastForward: _propTypes.default.func,

    /**
     * Called when the user clicks the JumpBackward button.
     *
     * Is passed a {@link moonstone/VideoPlayer.videoStatus} as the first argument.
     *
     * @type {Function}
     * @public
     */
    onJumpBackward: _propTypes.default.func,

    /**
     * Called when the user clicks the JumpForward button.
     *
     * Is passed a {@link moonstone/VideoPlayer.videoStatus} as the first argument.
     *
     * @type {Function}
     * @public
     */
    onJumpForward: _propTypes.default.func,

    /**
     * Called when video is paused
     *
     * @type {Function}
     * @public
     */
    onPause: _propTypes.default.func,

    /**
     * Called when video is played
     *
     * @type {Function}
     * @public
     */
    onPlay: _propTypes.default.func,

    /**
     * Called when video is rewound.
     *
     * @type {Function}
     * @public
     */
    onRewind: _propTypes.default.func,

    /**
     * Called when the user is moving the VideoPlayer's Slider knob independently of
     * the current playback position.
     *
     * It is passed an object with a `seconds` key (float value) to indicate the current time
     * index. It can be used to update the `thumbnailSrc` to the reflect the current scrub
     * position.
     *
     * @type {Function}
     * @public
     */
    onScrub: _propTypes.default.func,

    /**
     * Called when seek is attempted while `seekDisabled` is true.
     *
     * @type {Function}
     */
    onSeekFailed: _propTypes.default.func,

    /**
     * Called when seeking outside of the current `selection` range.
     *
     * By default, the seek will still be performed. Calling `preventDefault()` on the event
     * will prevent the seek operation.
     *
     * @type {Function}
     * @public
     */
    onSeekOutsideSelection: _propTypes.default.func,

    /**
     * Pauses the video when it reaches either the start or the end of the video during rewind,
     * slow rewind, fast forward, or slow forward.
     *
     * @type {Boolean}
     * @default false
     * @public
     */
    pauseAtEnd: _propTypes.default.bool,

    /**
     * Mapping of playback rate names to playback rate values that may be set.
     *
     * @type {moonstone/VideoPlayer.playbackRateHash}
     * @default {
     *	fastForward: ['2', '4', '8', '16'],
     *	rewind: ['-2', '-4', '-8', '-16'],
     *	slowForward: ['1/4', '1/2'],
     *	slowRewind: ['-1/2', '-1']
     * }
     * @public
     */
    playbackRateHash: _propTypes.default.shape({
      fastForward: _propTypes.default.arrayOf(_propTypes.default.string),
      rewind: _propTypes.default.arrayOf(_propTypes.default.string),
      slowForward: _propTypes.default.arrayOf(_propTypes.default.string),
      slowRewind: _propTypes.default.arrayOf(_propTypes.default.string)
    }),

    /**
     * Disables seek function.
     *
     * Note that jump by arrow keys will also be disabled when `true`.
     *
     * @type {Boolean}
     * @public
     */
    seekDisabled: _propTypes.default.bool,

    /**
     * A range of the video to display as selected.
     *
     * The value of `selection` may either be:
     * * `null` or `undefined` for no selection,
     * * a single-element array with the start time of the selection
     * * a two-element array containing both the start and end time of the selection in seconds
     *
     * When the start time is specified, the media slider will show filled starting at that
     * time to the current time.
     *
     * When the end time is specified, the slider's background will be filled between the two
     * times.
     *
     * @type {Number[]}
     * @public
     */
    selection: _propTypes.default.arrayOf(_propTypes.default.number),

    /**
     * Registers the VideoPlayer component with an
     * {@link core/internal/ApiDecorator.ApiDecorator}.
     *
     * @type {Function}
     * @private
     */
    setApiProvider: _propTypes.default.func,

    /**
     * The video source.
     *
     * Any children `<source>` tag elements of [VideoPlayer]{@link moonstone/VideoPlayer} will
     * be sent directly to the `videoComponent` as video sources.
     *
     * @type {Node}
     * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source
     * @public
     */
    source: _propTypes.default.node,

    /**
     * Disables spotlight navigation into the component.
     *
     * @type {Boolean}
     * @public
     */
    spotlightDisabled: _propTypes.default.bool,

    /**
     * The spotlight container ID for the player.
     *
     * @type {String}
     * @public
     * @default 'videoPlayer'
     */
    spotlightId: _propTypes.default.string,

    /**
     * The thumbnail component to be used instead of the built-in version.
     *
     * The internal thumbnail style will not be applied to this component. This component
     * follows the same rules as the built-in version.
     *
     * @type {Node}
     * @public
     */
    thumbnailComponent: _propTypes.default.node,

    /**
     * Thumbnail image source to show on the slider knob.
     *
     * This is a standard {@link moonstone/Image} component so it supports all of the same
     * options for the `src` property. If no `thumbnailComponent` and no `thumbnailSrc` is set,
     * no tooltip will display.
     *
     * @type {String|Object}
     * @public
     */
    thumbnailSrc: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.object]),

    /**
    * Enables the thumbnail transition from opaque to translucent.
    *
    * @type {Boolean}
    * @public
    */
    thumbnailUnavailable: _propTypes.default.bool,

    /**
     * Title for the video being played.
     *
     * @type {Node}
     * @public
     */
    title: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.node]),

    /**
     * The time (in milliseconds) before the title disappears from the controls.
     *
     * Setting this to `0` disables hiding.
     *
     * @type {Number}
     * @default 5000
     * @public
     */
    titleHideDelay: _propTypes.default.number,

    /**
     * Video component to use.
     *
     * The default renders an `HTMLVideoElement`. Custom video components must have a similar
     * API structure, exposing the following APIs:
     *
     * Properties:
     * * `currentTime` {Number} - Playback index of the media in seconds
     * * `duration` {Number} - Media's entire duration in seconds
     * * `error` {Boolean} - `true` if video playback has errored.
     * * `loading` {Boolean} - `true` if video playback is loading.
     * * `paused` {Boolean} - Playing vs paused state. `true` means the media is paused
     * * `playbackRate` {Number} - Current playback rate, as a number
     * * `proportionLoaded` {Number} - A value between `0` and `1`
     *	representing the proportion of the media that has loaded
     * * `proportionPlayed` {Number} - A value between `0` and `1` representing the
     *	proportion of the media that has already been shown
     *
     * Events:
     * * `onLoadStart` - Called when the video starts to load
     * * `onUpdate` - Sent when any of the properties were updated
     *
     * Methods:
     * * `play()` - play video
     * * `pause()` - pause video
     * * `load()` - load video
     *
     * The [`source`]{@link moonstone/VideoPlayer.VideoBase.source} property is passed to
     * the video component as a child node.
     *
     * @type {Component|Element}
     * @default {@link ui/Media.Media}
     * @public
     */
    videoComponent: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.func, _propTypes.default.element])
  }
}), Object.defineProperty(_class, "contextTypes", {
  configurable: true,
  enumerable: true,
  writable: true,
  value: _FloatingLayerDecorator.contextTypes
}), Object.defineProperty(_class, "defaultProps", {
  configurable: true,
  enumerable: true,
  writable: true,
  value: {
    autoCloseTimeout: 5000,
    feedbackHideDelay: 3000,
    jumpBy: 30,
    mediaControlsComponent: _MediaControls.default,
    miniFeedbackHideDelay: 2000,
    playbackRateHash: {
      fastForward: ['2', '4', '8', '16'],
      rewind: ['-2', '-4', '-8', '-16'],
      slowForward: ['1/4', '1/2'],
      slowRewind: ['-1/2', '-1']
    },
    spotlightId: 'videoPlayer',
    titleHideDelay: 5000,
    videoComponent: _Media.default
  }
}), _initialiseProps = function _initialiseProps() {
  var _this4 = this;

  Object.defineProperty(this, "announceJob", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: new _util.Job(function (msg) {
      return _this4.announceRef && _this4.announceRef.announce(msg);
    }, 200)
  });
  Object.defineProperty(this, "announce", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value(msg) {
      _this4.announceJob.start(msg);
    }
  });
  Object.defineProperty(this, "getHeightForElement", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value(elementName) {
      var element = _this4.player.querySelector(".".concat(_VideoPlayer.default[elementName]));

      if (element) {
        return element.offsetHeight;
      } else {
        return 0;
      }
    }
  });
  Object.defineProperty(this, "initI18n", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      var locale = _i18n.default.getLocale();

      if (_this4.locale !== locale && (typeof window === "undefined" ? "undefined" : _typeof(window)) === 'object') {
        _this4.locale = locale;
        _this4.durfmt = new _DurationFmt.default({
          length: 'medium',
          style: 'clock',
          useNative: false
        });
      }
    }
  });
  Object.defineProperty(this, "activityDetected", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      // console.count('activityDetected');
      _this4.startAutoCloseTimeout();
    }
  });
  Object.defineProperty(this, "startAutoCloseTimeout", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      // If this.state.more is used as a reference for when this function should fire, timing for
      // detection of when "more" is pressed vs when the state is updated is mismatched. Using an
      // instance variable that's only set and used for this express purpose seems cleanest.
      if (_this4.props.autoCloseTimeout && _this4.state.mediaControlsVisible) {
        _this4.autoCloseJob.startAfter(_this4.props.autoCloseTimeout);
      }
    }
  });
  Object.defineProperty(this, "stopAutoCloseTimeout", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      _this4.autoCloseJob.stop();
    }
  });
  Object.defineProperty(this, "generateId", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      return Math.random().toString(36).substr(2, 8);
    }
  });
  Object.defineProperty(this, "markAnnounceRead", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      if (_this4.state.announce === AnnounceState.TITLE) {
        _this4.setState({
          announce: AnnounceState.TITLE_READ
        });
      } else if (_this4.state.announce === AnnounceState.INFO) {
        _this4.setState({
          announce: AnnounceState.DONE
        });
      }

      return true;
    }
  });
  Object.defineProperty(this, "showControls", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      if (_this4.props.disabled) {
        return;
      }

      _this4.startDelayedFeedbackHide();

      _this4.startDelayedTitleHide();

      _this4.setState(function (_ref) {
        var announce = _ref.announce;

        if (announce === AnnounceState.READY) {
          // if we haven't read the title yet, do so this time
          announce = AnnounceState.TITLE;
        } else if (announce === AnnounceState.TITLE) {
          // if we have read the title, advance to INFO so title isn't read again
          announce = AnnounceState.TITLE_READ;
        }

        return {
          announce: announce,
          bottomControlsRendered: true,
          feedbackAction: 'idle',
          feedbackVisible: true,
          mediaControlsVisible: true,
          mediaSliderVisible: true,
          miniFeedbackVisible: false,
          titleVisible: true
        };
      });
    }
  });
  Object.defineProperty(this, "hideControls", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      _this4.stopDelayedFeedbackHide();

      _this4.stopDelayedMiniFeedbackHide();

      _this4.stopDelayedTitleHide();

      _this4.stopAutoCloseTimeout();

      _this4.setState({
        feedbackAction: 'idle',
        feedbackVisible: false,
        mediaControlsVisible: false,
        mediaSliderVisible: false,
        miniFeedbackVisible: false,
        infoVisible: false
      });

      _this4.markAnnounceRead();
    }
  });
  Object.defineProperty(this, "toggleControls", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      if (_this4.state.mediaControlsVisible) {
        _this4.hideControls();
      } else {
        _this4.showControls();
      }
    }
  });
  Object.defineProperty(this, "doAutoClose", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      _this4.stopDelayedFeedbackHide();

      _this4.stopDelayedTitleHide();

      _this4.setState(function (_ref2) {
        var mediaSliderVisible = _ref2.mediaSliderVisible,
            miniFeedbackVisible = _ref2.miniFeedbackVisible;
        return {
          feedbackVisible: false,
          mediaControlsVisible: false,
          mediaSliderVisible: mediaSliderVisible && miniFeedbackVisible,
          infoVisible: false
        };
      });

      _this4.markAnnounceRead();
    }
  });
  Object.defineProperty(this, "autoCloseJob", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: new _util.Job(this.doAutoClose)
  });
  Object.defineProperty(this, "startDelayedTitleHide", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      if (_this4.props.titleHideDelay) {
        _this4.hideTitleJob.startAfter(_this4.props.titleHideDelay);
      }
    }
  });
  Object.defineProperty(this, "stopDelayedTitleHide", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      _this4.hideTitleJob.stop();
    }
  });
  Object.defineProperty(this, "hideTitle", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      _this4.setState({
        titleVisible: false
      });
    }
  });
  Object.defineProperty(this, "hideTitleJob", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: new _util.Job(this.hideTitle)
  });
  Object.defineProperty(this, "startDelayedFeedbackHide", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      if (_this4.props.feedbackHideDelay) {
        _this4.hideFeedbackJob.startAfter(_this4.props.feedbackHideDelay);
      }
    }
  });
  Object.defineProperty(this, "stopDelayedFeedbackHide", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      _this4.hideFeedbackJob.stop();
    }
  });
  Object.defineProperty(this, "showFeedback", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      if (_this4.state.mediaControlsVisible) {
        _this4.setState({
          feedbackVisible: true,
          feedbackAction: 'idle'
        });
      } else {
        var shouldShowSlider = _this4.pulsedPlaybackState !== null || (0, _util3.calcNumberValueOfPlaybackRate)(_this4.playbackRate) !== 1;

        if (_this4.showMiniFeedback && (!_this4.state.miniFeedbackVisible || _this4.state.mediaSliderVisible !== shouldShowSlider)) {
          _this4.setState(function (_ref3) {
            var loading = _ref3.loading,
                duration = _ref3.duration,
                error = _ref3.error;
            return {
              mediaSliderVisible: shouldShowSlider && !_this4.props.noMediaSliderFeedback,
              miniFeedbackVisible: !(loading || !duration || error)
            };
          });
        }
      }
    }
  });
  Object.defineProperty(this, "hideFeedback", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      if (_this4.state.feedbackVisible) {
        _this4.setState({
          feedbackVisible: false,
          feedbackAction: 'idle'
        });
      }
    }
  });
  Object.defineProperty(this, "hideFeedbackJob", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: new _util.Job(this.hideFeedback)
  });
  Object.defineProperty(this, "startDelayedMiniFeedbackHide", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      var delay = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _this4.props.miniFeedbackHideDelay;

      if (delay) {
        _this4.hideMiniFeedbackJob.startAfter(delay);
      }
    }
  });
  Object.defineProperty(this, "stopDelayedMiniFeedbackHide", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      _this4.hideMiniFeedbackJob.stop();
    }
  });
  Object.defineProperty(this, "hideMiniFeedback", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      if (_this4.state.miniFeedbackVisible) {
        _this4.showMiniFeedback = false;

        _this4.setState({
          mediaSliderVisible: false,
          miniFeedbackVisible: false
        });
      }
    }
  });
  Object.defineProperty(this, "hideMiniFeedbackJob", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: new _util.Job(this.hideMiniFeedback)
  });
  Object.defineProperty(this, "handle", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: _handle.handle.bind(this)
  });
  Object.defineProperty(this, "showControlsFromPointer", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      _spotlight.default.setPointerMode(false);

      _this4.showControls();
    }
  });
  Object.defineProperty(this, "clearPulsedPlayback", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      _this4.pulsedPlaybackRate = null;
      _this4.pulsedPlaybackState = null;
    }
  });
  Object.defineProperty(this, "shouldShowMiniFeedback", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value(ev) {
      if (ev.type === 'keyup') {
        _this4.showMiniFeedback = true;
      }

      return true;
    }
  });
  Object.defineProperty(this, "handleLoadStart", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      _this4.firstPlayReadFlag = true;
      _this4.prevCommand = _this4.props.noAutoPlay ? 'pause' : 'play';
      _this4.speedIndex = 0;

      _this4.setState({
        announce: AnnounceState.READY,
        currentTime: 0,
        sourceUnavailable: true,
        proportionPlayed: 0,
        proportionLoaded: 0
      });

      if (!_this4.props.noAutoShowMediaControls) {
        if (!_this4.state.bottomControlsRendered) {
          _this4.renderBottomControl.idle();
        } else {
          _this4.showControls();
        }
      }
    }
  });
  Object.defineProperty(this, "handlePlay", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: this.handle(forwardPlay, this.shouldShowMiniFeedback, function () {
      return _this4.play();
    })
  });
  Object.defineProperty(this, "handlePause", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: this.handle(forwardPause, this.shouldShowMiniFeedback, function () {
      return _this4.pause();
    })
  });
  Object.defineProperty(this, "handleRewind", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: this.handle(forwardRewind, this.shouldShowMiniFeedback, function () {
      return _this4.rewind();
    })
  });
  Object.defineProperty(this, "handleFastForward", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: this.handle(forwardFastForward, this.shouldShowMiniFeedback, function () {
      return _this4.fastForward();
    })
  });
  Object.defineProperty(this, "handleJump", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value(_ref4) {
      var keyCode = _ref4.keyCode;

      if (_this4.props.seekDisabled) {
        (0, _handle.forward)('onSeekFailed', {}, _this4.props);
      } else {
        var jumpBy = ((0, _keymap.is)('left', keyCode) ? -1 : 1) * _this4.props.jumpBy;
        var time = Math.min(_this4.state.duration, Math.max(0, _this4.state.currentTime + jumpBy));
        if (_this4.preventTimeChange(time)) return;
        _this4.showMiniFeedback = true;

        _this4.jump(jumpBy);

        _this4.announceJob.startAfter(500, (0, _util3.secondsToTime)(_this4.video.currentTime, _this4.durfmt, {
          includeHour: true
        }));
      }
    }
  });
  Object.defineProperty(this, "handleGlobalKeyDown", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: this.handle((0, _handle.returnsTrue)(this.activityDetected), (0, _handle.forKey)('down'), function () {
      return !_this4.state.mediaControlsVisible && !_spotlight.default.getCurrent() && _spotlight.default.getPointerMode() && !_this4.props.spotlightDisabled;
    }, _handle.preventDefault, _handle.stopImmediate, this.showControlsFromPointer)
  });
  Object.defineProperty(this, "handleEvent", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      var el = _this4.video;
      var updatedState = {
        // Standard media properties
        currentTime: el.currentTime,
        duration: el.duration,
        paused: el.playbackRate !== 1 || el.paused,
        playbackRate: el.playbackRate,
        // Non-standard state computed from properties
        error: el.error,
        loading: el.loading,
        proportionLoaded: el.proportionLoaded,
        proportionPlayed: el.proportionPlayed || 0,
        sliderTooltipTime: _this4.sliderScrubbing ? _this4.sliderKnobProportion * el.duration : el.currentTime,
        // note: `el.loading && this.state.sourceUnavailable == false` is equivalent to `oncanplaythrough`
        sourceUnavailable: el.loading && _this4.state.sourceUnavailable || el.error
      }; // If there's an error, we're obviously not loading, no matter what the readyState is.

      if (updatedState.error) updatedState.loading = false;
      var isRewind = _this4.prevCommand === 'rewind' || _this4.prevCommand === 'slowRewind';
      var isForward = _this4.prevCommand === 'fastForward' || _this4.prevCommand === 'slowForward';

      if (_this4.props.pauseAtEnd && (el.currentTime === 0 && isRewind || el.currentTime === el.duration && isForward)) {
        _this4.pause();
      }

      _this4.setState(updatedState);
    }
  });
  Object.defineProperty(this, "renderBottomControl", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: new _util.Job(function () {
      if (!_this4.state.bottomControlsRendered) {
        _this4.setState({
          bottomControlsRendered: true
        });
      }
    })
  });
  Object.defineProperty(this, "getMediaState", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      return {
        currentTime: _this4.state.currentTime,
        duration: _this4.state.duration,
        paused: _this4.state.paused,
        playbackRate: _this4.video.playbackRate,
        proportionLoaded: _this4.state.proportionLoaded,
        proportionPlayed: _this4.state.proportionPlayed
      };
    }
  });
  Object.defineProperty(this, "send", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value(action, props) {
      _this4.clearPulsedPlayback();

      _this4.showFeedback();

      _this4.startDelayedFeedbackHide();

      _this4.video[action](props);
    }
  });
  Object.defineProperty(this, "play", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      if (_this4.state.sourceUnavailable) {
        return;
      }

      _this4.speedIndex = 0; // must happen before send() to ensure feedback uses the right value
      // TODO: refactor into this.state member

      _this4.prevCommand = 'play';

      _this4.setPlaybackRate(1);

      _this4.send('play');

      _this4.announce((0, _$L.default)('Play'));

      _this4.startDelayedMiniFeedbackHide(5000);
    }
  });
  Object.defineProperty(this, "pause", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      if (_this4.state.sourceUnavailable) {
        return;
      }

      _this4.speedIndex = 0; // must happen before send() to ensure feedback uses the right value
      // TODO: refactor into this.state member

      _this4.prevCommand = 'pause';

      _this4.setPlaybackRate(1);

      _this4.send('pause');

      _this4.announce((0, _$L.default)('Pause'));

      _this4.stopDelayedMiniFeedbackHide();
    }
  });
  Object.defineProperty(this, "seek", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value(timeIndex) {
      if (!_this4.props.seekDisabled && !isNaN(_this4.video.duration) && !_this4.state.sourceUnavailable) {
        _this4.video.currentTime = timeIndex;
      } else {
        (0, _handle.forward)('onSeekFailed', {}, _this4.props);
      }
    }
  });
  Object.defineProperty(this, "jump", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value(distance) {
      if (_this4.state.sourceUnavailable) {
        return;
      }

      _this4.pulsedPlaybackRate = (0, _util2.toUpperCase)(new _DurationFmt.default({
        length: 'long'
      }).format({
        second: _this4.props.jumpBy
      }));
      _this4.pulsedPlaybackState = distance > 0 ? 'jumpForward' : 'jumpBackward';

      _this4.showFeedback();

      _this4.startDelayedFeedbackHide();

      _this4.seek(_this4.state.currentTime + distance);

      _this4.startDelayedMiniFeedbackHide();
    }
  });
  Object.defineProperty(this, "fastForward", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      if (_this4.state.sourceUnavailable) {
        return;
      }

      var shouldResumePlayback = false;

      switch (_this4.prevCommand) {
        case 'slowForward':
          if (_this4.speedIndex === _this4.playbackRates.length - 1) {
            // reached to the end of array => fastforward
            _this4.selectPlaybackRates('fastForward');

            _this4.speedIndex = 0;
            _this4.prevCommand = 'fastForward';
          } else {
            _this4.speedIndex = _this4.clampPlaybackRate(_this4.speedIndex + 1);
          }

          break;

        case 'pause':
          _this4.selectPlaybackRates('slowForward');

          if (_this4.state.paused) {
            shouldResumePlayback = true;
          }

          _this4.speedIndex = 0;
          _this4.prevCommand = 'slowForward';
          break;

        case 'fastForward':
          _this4.speedIndex = _this4.clampPlaybackRate(_this4.speedIndex + 1);
          _this4.prevCommand = 'fastForward';
          break;

        default:
          _this4.selectPlaybackRates('fastForward');

          _this4.speedIndex = 0;
          _this4.prevCommand = 'fastForward';

          if (_this4.state.paused) {
            shouldResumePlayback = true;
          }

          break;
      }

      _this4.setPlaybackRate(_this4.selectPlaybackRate(_this4.speedIndex));

      if (shouldResumePlayback) _this4.send('play');

      _this4.stopDelayedFeedbackHide();

      _this4.stopDelayedMiniFeedbackHide();

      _this4.clearPulsedPlayback();

      _this4.showFeedback();
    }
  });
  Object.defineProperty(this, "rewind", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      if (_this4.state.sourceUnavailable) {
        return;
      }

      var rateForSlowRewind = _this4.props.playbackRateHash['slowRewind'];
      var shouldResumePlayback = false,
          command = 'rewind';

      if (_this4.video.currentTime === 0) {
        // Do not rewind if currentTime is 0. We're already at the beginning.
        return;
      }

      switch (_this4.prevCommand) {
        case 'slowRewind':
          if (_this4.speedIndex === _this4.playbackRates.length - 1) {
            // reached to the end of array => go to rewind
            _this4.selectPlaybackRates(command);

            _this4.speedIndex = 0;
            _this4.prevCommand = command;
          } else {
            _this4.speedIndex = _this4.clampPlaybackRate(_this4.speedIndex + 1);
          }

          break;

        case 'pause':
          // If it's possible to slowRewind, do it, otherwise just leave it as normal rewind : QEVENTSEVT-17386
          if (rateForSlowRewind && rateForSlowRewind.length >= 0) {
            command = 'slowRewind';
          }

          _this4.selectPlaybackRates(command);

          if (_this4.state.paused && _this4.state.duration > _this4.state.currentTime) {
            shouldResumePlayback = true;
          }

          _this4.speedIndex = 0;
          _this4.prevCommand = command;
          break;

        case 'rewind':
          _this4.speedIndex = _this4.clampPlaybackRate(_this4.speedIndex + 1);
          _this4.prevCommand = command;
          break;

        default:
          _this4.selectPlaybackRates(command);

          _this4.speedIndex = 0;
          _this4.prevCommand = command;
          break;
      }

      _this4.setPlaybackRate(_this4.selectPlaybackRate(_this4.speedIndex));

      if (shouldResumePlayback) _this4.send('play');

      _this4.stopDelayedFeedbackHide();

      _this4.stopDelayedMiniFeedbackHide();

      _this4.clearPulsedPlayback();

      _this4.showFeedback();
    }
  });
  Object.defineProperty(this, "videoProxy", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: typeof Proxy !== 'function' ? null : new Proxy({}, {
      get: function get(target, name) {
        var value = _this4.video[name];

        if (typeof value === 'function') {
          value = value.bind(_this4.video);
        }

        return value;
      },
      set: function set(target, name, value) {
        return _this4.video[name] = value;
      }
    })
  });
  Object.defineProperty(this, "getVideoNode", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      return _this4.videoProxy || _this4.video;
    }
  });
  Object.defineProperty(this, "areControlsVisible", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      return _this4.state.mediaControlsVisible;
    }
  });
  Object.defineProperty(this, "selectPlaybackRates", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value(cmd) {
      _this4.playbackRates = _this4.props.playbackRateHash[cmd];
    }
  });
  Object.defineProperty(this, "clampPlaybackRate", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value(idx) {
      if (!_this4.playbackRates) {
        return;
      }

      return idx % _this4.playbackRates.length;
    }
  });
  Object.defineProperty(this, "selectPlaybackRate", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value(idx) {
      return _this4.playbackRates[idx];
    }
  });
  Object.defineProperty(this, "setPlaybackRate", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value(rate) {
      // Stop rewind (if happenning)
      _this4.stopRewindJob(); // Make sure rate is a string


      _this4.playbackRate = rate = String(rate);
      var pbNumber = (0, _util3.calcNumberValueOfPlaybackRate)(rate);

      if (!_platform.platform.webos) {
        // ReactDOM throws error for setting negative value for playbackRate
        _this4.video.playbackRate = pbNumber < 0 ? 0 : pbNumber; // For supporting cross browser behavior

        if (pbNumber < 0) {
          _this4.beginRewind();
        }
      } else {
        // Set native playback rate
        _this4.video.playbackRate = pbNumber;
      }
    }
  });
  Object.defineProperty(this, "rewindManually", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      var now = (0, _util.perfNow)(),
          distance = now - _this4.rewindBeginTime,
          pbRate = (0, _util3.calcNumberValueOfPlaybackRate)(_this4.playbackRate),
          adjustedDistance = distance * pbRate / 1000;

      _this4.jump(adjustedDistance);

      _this4.stopDelayedMiniFeedbackHide();

      _this4.clearPulsedPlayback();

      _this4.startRewindJob(); // Issue another rewind tick

    }
  });
  Object.defineProperty(this, "rewindJob", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: new _util.Job(this.rewindManually, 100)
  });
  Object.defineProperty(this, "startRewindJob", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      _this4.rewindBeginTime = (0, _util.perfNow)();

      _this4.rewindJob.start();
    }
  });
  Object.defineProperty(this, "stopRewindJob", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      _this4.rewindJob.stop();
    }
  });
  Object.defineProperty(this, "beginRewind", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      _this4.send('pause');

      _this4.startRewindJob();
    }
  });
  Object.defineProperty(this, "addStateToEvent", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value(ev) {
      return _objectSpread({
        // More props from `ev` may be added here as needed, but a full copy via `...ev`
        // overloads Storybook's Action Logger and likely has other perf fallout.
        type: ev.type
      }, _this4.getMediaState());
    }
  });
  Object.defineProperty(this, "disablePointerMode", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      _spotlight.default.setPointerMode(false);

      return true;
    }
  });
  Object.defineProperty(this, "handleKeyDownFromControls", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: this.handle( // onKeyDown is used as a proxy for when the title has been read because it can only occur
    // after the controls have been shown.
    this.markAnnounceRead, (0, _handle.forKey)('down'), this.disablePointerMode, this.hideControls)
  });
  Object.defineProperty(this, "onVideoClick", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      _this4.toggleControls();
    }
  });
  Object.defineProperty(this, "onSliderChange", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value(_ref5) {
      var _value = _ref5.value;
      var time = _value * _this4.state.duration;
      if (_this4.preventTimeChange(time)) return;

      _this4.seek(time);

      _this4.sliderScrubbing = false;
    }
  });
  Object.defineProperty(this, "sliderTooltipTimeJob", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: new _util.Job(function (time) {
      return _this4.setState({
        sliderTooltipTime: time
      });
    }, 20)
  });
  Object.defineProperty(this, "handleKnobMove", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value(ev) {
      _this4.sliderScrubbing = true; // prevent announcing repeatedly when the knob is detached from the progress.
      // TODO: fix Slider to not send onKnobMove when the knob hasn't, in fact, moved

      if (_this4.sliderKnobProportion !== ev.proportion) {
        _this4.sliderKnobProportion = ev.proportion;
        var seconds = Math.floor(_this4.sliderKnobProportion * _this4.video.duration);

        if (!isNaN(seconds)) {
          _this4.sliderTooltipTimeJob.throttle(seconds);

          var knobTime = (0, _util3.secondsToTime)(seconds, _this4.durfmt, {
            includeHour: true
          });
          (0, _handle.forward)('onScrub', _objectSpread({}, ev, {
            seconds: seconds
          }), _this4.props);

          _this4.announce("".concat((0, _$L.default)('jump to'), " ").concat(knobTime));
        }
      }
    }
  });
  Object.defineProperty(this, "handleSliderFocus", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      var seconds = Math.floor(_this4.sliderKnobProportion * _this4.video.duration);
      _this4.sliderScrubbing = true;

      _this4.setState({
        feedbackAction: 'focus',
        feedbackVisible: true
      });

      _this4.stopDelayedFeedbackHide();

      if (!isNaN(seconds)) {
        _this4.sliderTooltipTimeJob.throttle(seconds);

        var knobTime = (0, _util3.secondsToTime)(seconds, _this4.durfmt, {
          includeHour: true
        });
        (0, _handle.forward)('onScrub', {
          detached: _this4.sliderScrubbing,
          proportion: _this4.sliderKnobProportion,
          seconds: seconds
        }, _this4.props);

        _this4.announce("".concat((0, _$L.default)('jump to'), " ").concat(knobTime));
      }
    }
  });
  Object.defineProperty(this, "handleSliderBlur", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value() {
      _this4.sliderScrubbing = false;

      _this4.startDelayedFeedbackHide();

      _this4.setState(function (_ref6) {
        var currentTime = _ref6.currentTime;
        return {
          feedbackAction: 'blur',
          feedbackVisible: true,
          sliderTooltipTime: currentTime
        };
      });
    }
  });
  Object.defineProperty(this, "slider5WayPressJob", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: new _util.Job(function () {
      _this4.setState({
        slider5WayPressed: false
      });
    }, 200)
  });
  Object.defineProperty(this, "handleSliderKeyDown", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value(ev) {
      var keyCode = ev.keyCode;

      if ((0, _keymap.is)('enter', keyCode)) {
        _this4.setState({
          slider5WayPressed: true
        }, _this4.slider5WayPressJob.start());
      } else if ((0, _keymap.is)('down', keyCode)) {
        _spotlight.default.setPointerMode(false);

        if (_spotlight.default.focus(_this4.mediaControlsSpotlightId)) {
          (0, _handle.preventDefault)(ev);
          (0, _handle.stopImmediate)(ev);

          _this4.activityDetected();
        }
      } else if ((0, _keymap.is)('up', keyCode)) {
        (0, _handle.preventDefault)(ev);
        (0, _handle.stopImmediate)(ev);

        _this4.handleSliderBlur();

        _this4.hideControls();
      } else {
        _this4.activityDetected();
      }
    }
  });
  Object.defineProperty(this, "onJumpBackward", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: this.handle(forwardJumpBackward, function () {
      return _this4.jump(-1 * _this4.props.jumpBy);
    })
  });
  Object.defineProperty(this, "onJumpForward", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: this.handle(forwardJumpForward, function () {
      return _this4.jump(_this4.props.jumpBy);
    })
  });
  Object.defineProperty(this, "handleToggleMore", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value(_ref7) {
      var showMoreComponents = _ref7.showMoreComponents;

      if (!showMoreComponents) {
        _this4.startAutoCloseTimeout(); // Restore the timer since we are leaving "more.
        // Restore the title-hide now that we're finished with "more".


        _this4.startDelayedTitleHide();
      } else {
        // Interrupt the title-hide since we don't want it hiding autonomously in "more".
        _this4.stopDelayedTitleHide();
      }

      _this4.setState(function (_ref8) {
        var announce = _ref8.announce;
        return {
          infoVisible: showMoreComponents,
          titleVisible: true,
          announce: announce < AnnounceState.INFO ? AnnounceState.INFO : AnnounceState.DONE
        };
      });
    }
  });
  Object.defineProperty(this, "handleMediaControlsClose", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value(ev) {
      _this4.hideControls();

      ev.stopPropagation();
    }
  });
  Object.defineProperty(this, "setPlayerRef", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value(node) {
      // TODO: We've moved SpotlightContainerDecorator up to allow VP to be spottable but also
      // need a ref to the root node to query for children and set CSS variables.
      // eslint-disable-next-line react/no-find-dom-node
      _this4.player = _reactDom.default.findDOMNode(node);
    }
  });
  Object.defineProperty(this, "setVideoRef", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value(video) {
      _this4.video = video;
    }
  });
  Object.defineProperty(this, "setAnnounceRef", {
    configurable: true,
    enumerable: true,
    writable: true,
    value: function value(node) {
      _this4.announceRef = node;
    }
  });
}, _temp);
/**
 * A standard HTML5 video player for Moonstone. It behaves, responds to, and operates like a
 * `<video>` tag in its support for `<source>`.  It also accepts custom tags such as
 * `<infoComponents>` for displaying additional information in the title area and `<MediaControls>`
 * for handling media playback controls and adding more controls.
 *
 * Example usage:
 * ```
 *	<VideoPlayer title="Hilarious Cat Video" poster="http://my.cat.videos/boots-poster.jpg">
 *		<source src="http://my.cat.videos/boots.mp4" type="video/mp4" />
 *		<infoComponents>A video about my cat Boots, wearing boots.</infoComponents>
 *		<MediaControls>
 *			<leftComponents><IconButton backgroundOpacity="translucent">star</IconButton></leftComponents>
 *			<rightComponents><IconButton backgroundOpacity="translucent">flag</IconButton></rightComponents>
 *
 *			<Button backgroundOpacity="translucent">Add To Favorites</Button>
 *			<IconButton backgroundOpacity="translucent">search</IconButton>
 *		</MediaControls>
 *	</VideoPlayer>
 * ```
 *
 * To invoke methods (e.g.: `fastForward()`) or get the current state (`getMediaState()`), store a
 * ref to the `VideoPlayer` within your component:
 *
 * ```
 * 	...
 *
 * 	setVideoPlayer = (node) => {
 * 		this.videoPlayer = node;
 * 	}
 *
 * 	play () {
 * 		this.videoPlayer.play();
 * 	}
 *
 * 	render () {
 * 		return (
 * 			<VideoPlayer ref={this.setVideoPlayer} />
 * 		);
 * 	}
 * ```
 *
 * @class VideoPlayer
 * @memberof moonstone/VideoPlayer
 * @mixes ui/Slottable.Slottable
 * @ui
 * @public
 */

exports.VideoPlayerBase = VideoPlayerBase;
var VideoPlayer = (0, _ApiDecorator.default)({
  api: ['areControlsVisible', 'fastForward', 'getMediaState', 'getVideoNode', 'hideControls', 'jump', 'pause', 'play', 'rewind', 'seek', 'showControls', 'showFeedback', 'toggleControls']
}, (0, _Slottable.default)({
  slots: ['infoComponents', 'mediaControlsComponent', 'source', 'thumbnailComponent', 'videoComponent']
}, (0, _FloatingLayer.FloatingLayerDecorator)({
  floatLayerId: 'videoPlayerFloatingLayer'
}, (0, _Skinnable.default)(VideoPlayerBase))));
exports.VideoPlayer = VideoPlayer;
var _default = VideoPlayer;
exports.default = _default;