wotnot-video-react
Version:
Video-React is a web video player built from the ground up for an HTML5 world using React library.
1,903 lines (1,646 loc) • 131 kB
JavaScript
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import classNames from 'classnames';
import { createStore } from 'redux';
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 _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 _inheritsLoose(subClass, superClass) {
subClass.prototype = Object.create(superClass.prototype);
subClass.prototype.constructor = subClass;
subClass.__proto__ = superClass;
}
function _objectWithoutPropertiesLoose(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];
}
return target;
}
function _assertThisInitialized(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
var LOAD_START = 'video-react/LOAD_START';
var CAN_PLAY = 'video-react/CAN_PLAY';
var WAITING = 'video-react/WAITING';
var CAN_PLAY_THROUGH = 'video-react/CAN_PLAY_THROUGH';
var PLAYING = 'video-react/PLAYING';
var PLAY = 'video-react/PLAY';
var PAUSE = 'video-react/PAUSE';
var END = 'video-react/END';
var SEEKING = 'video-react/SEEKING';
var SEEKED = 'video-react/SEEKED';
var SEEKING_TIME = 'video-react/SEEKING_TIME';
var END_SEEKING = 'video-react/END_SEEKING';
var DURATION_CHANGE = 'video-react/DURATION_CHANGE';
var TIME_UPDATE = 'video-react/TIME_UPDATE';
var VOLUME_CHANGE = 'video-react/VOLUME_CHANGE';
var PROGRESS_CHANGE = 'video-react/PROGRESS_CHANGE';
var RATE_CHANGE = 'video-react/RATE_CHANGE';
var SUSPEND = 'video-react/SUSPEND';
var ABORT = 'video-react/ABORT';
var EMPTIED = 'video-react/EMPTIED';
var STALLED = 'video-react/STALLED';
var LOADED_META_DATA = 'video-react/LOADED_META_DATA';
var LOADED_DATA = 'video-react/LOADED_DATA';
var RESIZE = 'video-react/RESIZE';
var ERROR = 'video-react/ERROR';
var ACTIVATE_TEXT_TRACK = 'video-react/ACTIVATE_TEXT_TRACK';
function handleLoadStart(videoProps) {
return {
type: LOAD_START,
videoProps: videoProps
};
}
function handleCanPlay(videoProps) {
return {
type: CAN_PLAY,
videoProps: videoProps
};
}
function handleWaiting(videoProps) {
return {
type: WAITING,
videoProps: videoProps
};
}
function handleCanPlayThrough(videoProps) {
return {
type: CAN_PLAY_THROUGH,
videoProps: videoProps
};
}
function handlePlaying(videoProps) {
return {
type: PLAYING,
videoProps: videoProps
};
}
function handlePlay(videoProps) {
return {
type: PLAY,
videoProps: videoProps
};
}
function handlePause(videoProps) {
return {
type: PAUSE,
videoProps: videoProps
};
}
function handleEnd(videoProps) {
return {
type: END,
videoProps: videoProps
};
}
function handleSeeking(videoProps) {
return {
type: SEEKING,
videoProps: videoProps
};
}
function handleSeeked(videoProps) {
return {
type: SEEKED,
videoProps: videoProps
};
}
function handleDurationChange(videoProps) {
return {
type: DURATION_CHANGE,
videoProps: videoProps
};
}
function handleTimeUpdate(videoProps) {
return {
type: TIME_UPDATE,
videoProps: videoProps
};
}
function handleVolumeChange(videoProps) {
return {
type: VOLUME_CHANGE,
videoProps: videoProps
};
}
function handleProgressChange(videoProps) {
return {
type: PROGRESS_CHANGE,
videoProps: videoProps
};
}
function handleRateChange(videoProps) {
return {
type: RATE_CHANGE,
videoProps: videoProps
};
}
function handleSuspend(videoProps) {
return {
type: SUSPEND,
videoProps: videoProps
};
}
function handleAbort(videoProps) {
return {
type: ABORT,
videoProps: videoProps
};
}
function handleEmptied(videoProps) {
return {
type: EMPTIED,
videoProps: videoProps
};
}
function handleStalled(videoProps) {
return {
type: STALLED,
videoProps: videoProps
};
}
function handleLoadedMetaData(videoProps) {
return {
type: LOADED_META_DATA,
videoProps: videoProps
};
}
function handleLoadedData(videoProps) {
return {
type: LOADED_DATA,
videoProps: videoProps
};
}
function handleResize(videoProps) {
return {
type: RESIZE,
videoProps: videoProps
};
}
function handleError(videoProps) {
return {
type: ERROR,
videoProps: videoProps
};
}
function handleSeekingTime(time) {
return {
type: SEEKING_TIME,
time: time
};
}
function handleEndSeeking(time) {
return {
type: END_SEEKING,
time: time
};
}
function activateTextTrack(textTrack) {
return {
type: ACTIVATE_TEXT_TRACK,
textTrack: textTrack
};
}
var videoActions = /*#__PURE__*/Object.freeze({
__proto__: null,
LOAD_START: LOAD_START,
CAN_PLAY: CAN_PLAY,
WAITING: WAITING,
CAN_PLAY_THROUGH: CAN_PLAY_THROUGH,
PLAYING: PLAYING,
PLAY: PLAY,
PAUSE: PAUSE,
END: END,
SEEKING: SEEKING,
SEEKED: SEEKED,
SEEKING_TIME: SEEKING_TIME,
END_SEEKING: END_SEEKING,
DURATION_CHANGE: DURATION_CHANGE,
TIME_UPDATE: TIME_UPDATE,
VOLUME_CHANGE: VOLUME_CHANGE,
PROGRESS_CHANGE: PROGRESS_CHANGE,
RATE_CHANGE: RATE_CHANGE,
SUSPEND: SUSPEND,
ABORT: ABORT,
EMPTIED: EMPTIED,
STALLED: STALLED,
LOADED_META_DATA: LOADED_META_DATA,
LOADED_DATA: LOADED_DATA,
RESIZE: RESIZE,
ERROR: ERROR,
ACTIVATE_TEXT_TRACK: ACTIVATE_TEXT_TRACK,
handleLoadStart: handleLoadStart,
handleCanPlay: handleCanPlay,
handleWaiting: handleWaiting,
handleCanPlayThrough: handleCanPlayThrough,
handlePlaying: handlePlaying,
handlePlay: handlePlay,
handlePause: handlePause,
handleEnd: handleEnd,
handleSeeking: handleSeeking,
handleSeeked: handleSeeked,
handleDurationChange: handleDurationChange,
handleTimeUpdate: handleTimeUpdate,
handleVolumeChange: handleVolumeChange,
handleProgressChange: handleProgressChange,
handleRateChange: handleRateChange,
handleSuspend: handleSuspend,
handleAbort: handleAbort,
handleEmptied: handleEmptied,
handleStalled: handleStalled,
handleLoadedMetaData: handleLoadedMetaData,
handleLoadedData: handleLoadedData,
handleResize: handleResize,
handleError: handleError,
handleSeekingTime: handleSeekingTime,
handleEndSeeking: handleEndSeeking,
activateTextTrack: activateTextTrack
});
var Fullscreen = /*#__PURE__*/function () {
function Fullscreen() {}
var _proto = Fullscreen.prototype;
_proto.request = function request(elm) {
if (elm.requestFullscreen) {
elm.requestFullscreen();
} else if (elm.webkitRequestFullscreen) {
elm.webkitRequestFullscreen();
} else if (elm.mozRequestFullScreen) {
elm.mozRequestFullScreen();
} else if (elm.msRequestFullscreen) {
elm.msRequestFullscreen();
}
};
_proto.exit = function exit() {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
};
_proto.addEventListener = function addEventListener(handler, domRef) {
domRef.addEventListener('fullscreenchange', handler);
domRef.addEventListener('webkitfullscreenchange', handler);
domRef.addEventListener('mozfullscreenchange', handler);
domRef.addEventListener('MSFullscreenChange', handler);
};
_proto.removeEventListener = function removeEventListener(handler, domRef) {
domRef.removeEventListener('fullscreenchange', handler);
domRef.removeEventListener('webkitfullscreenchange', handler);
domRef.removeEventListener('mozfullscreenchange', handler);
domRef.removeEventListener('MSFullscreenChange', handler);
};
_createClass(Fullscreen, [{
key: "isFullscreen",
get: function get() {
return document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement;
}
}, {
key: "enabled",
get: function get() {
return document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled;
}
}]);
return Fullscreen;
}();
var fullscreen = new Fullscreen();
var OPERATE = 'video-react/OPERATE';
var FULLSCREEN_CHANGE = 'video-react/FULLSCREEN_CHANGE';
var PLAYER_ACTIVATE = 'video-react/PLAYER_ACTIVATE';
var USER_ACTIVATE = 'video-react/USER_ACTIVATE';
function handleFullscreenChange(isFullscreen) {
return {
type: FULLSCREEN_CHANGE,
isFullscreen: isFullscreen
};
}
function activate(activity) {
return {
type: PLAYER_ACTIVATE,
activity: activity
};
}
function userActivate(activity) {
return {
type: USER_ACTIVATE,
activity: activity
};
}
function play(operation) {
if (operation === void 0) {
operation = {
action: 'play',
source: ''
};
}
this.video.play();
return {
type: OPERATE,
operation: operation
};
}
function pause(operation) {
if (operation === void 0) {
operation = {
action: 'pause',
source: ''
};
}
this.video.pause();
return {
type: OPERATE,
operation: operation
};
}
function togglePlay(operation) {
if (operation === void 0) {
operation = {
action: 'toggle-play',
source: ''
};
}
this.video.togglePlay();
return {
type: OPERATE,
operation: operation
};
} // seek video by time
function seek(time, operation) {
if (operation === void 0) {
operation = {
action: 'seek',
source: ''
};
}
this.video.seek(time);
return {
type: OPERATE,
operation: operation
};
} // jump forward x seconds
function forward(seconds, operation) {
if (operation === void 0) {
operation = {
action: "forward-" + seconds,
source: ''
};
}
this.video.forward(seconds);
return {
type: OPERATE,
operation: operation
};
} // jump back x seconds
function replay(seconds, operation) {
if (operation === void 0) {
operation = {
action: "replay-" + seconds,
source: ''
};
}
this.video.replay(seconds);
return {
type: OPERATE,
operation: operation
};
}
function changeRate(rate, operation) {
if (operation === void 0) {
operation = {
action: 'change-rate',
source: ''
};
}
this.video.playbackRate = rate;
return {
type: OPERATE,
operation: operation
};
}
function changeVolume(volume, operation) {
if (operation === void 0) {
operation = {
action: 'change-volume',
source: ''
};
}
var v = volume;
if (volume < 0) {
v = 0;
}
if (volume > 1) {
v = 1;
}
this.video.volume = v;
return {
type: OPERATE,
operation: operation
};
}
function mute(muted, operation) {
if (operation === void 0) {
operation = {
action: muted ? 'muted' : 'unmuted',
source: ''
};
}
this.video.muted = muted;
return {
type: OPERATE,
operation: operation
};
}
function toggleFullscreen(player) {
if (fullscreen.enabled) {
if (fullscreen.isFullscreen) {
fullscreen.exit();
} else {
fullscreen.request(this.rootElement);
}
return {
type: OPERATE,
operation: {
action: 'toggle-fullscreen',
source: ''
}
};
}
return {
type: FULLSCREEN_CHANGE,
isFullscreen: !player.isFullscreen
};
}
var playerActions = /*#__PURE__*/Object.freeze({
__proto__: null,
OPERATE: OPERATE,
FULLSCREEN_CHANGE: FULLSCREEN_CHANGE,
PLAYER_ACTIVATE: PLAYER_ACTIVATE,
USER_ACTIVATE: USER_ACTIVATE,
handleFullscreenChange: handleFullscreenChange,
activate: activate,
userActivate: userActivate,
play: play,
pause: pause,
togglePlay: togglePlay,
seek: seek,
forward: forward,
replay: replay,
changeRate: changeRate,
changeVolume: changeVolume,
mute: mute,
toggleFullscreen: toggleFullscreen
});
var initialState = {
currentSrc: null,
duration: 0,
currentTime: 0,
seekingTime: 0,
buffered: null,
waiting: false,
seeking: false,
paused: true,
autoPaused: false,
ended: false,
playbackRate: 1,
muted: false,
volume: 1,
readyState: 0,
networkState: 0,
videoWidth: 0,
videoHeight: 0,
hasStarted: false,
userActivity: true,
isActive: false,
isFullscreen: false,
activeTextTrack: null
};
function player(state, action) {
if (state === void 0) {
state = initialState;
}
switch (action.type) {
case USER_ACTIVATE:
return _extends({}, state, {
userActivity: action.activity
});
case PLAYER_ACTIVATE:
return _extends({}, state, {
isActive: action.activity
});
case FULLSCREEN_CHANGE:
return _extends({}, state, {
isFullscreen: !!action.isFullscreen
});
case SEEKING_TIME:
return _extends({}, state, {
seekingTime: action.time
});
case END_SEEKING:
return _extends({}, state, {
seekingTime: 0
});
case LOAD_START:
return _extends({}, state, action.videoProps, {
hasStarted: false,
ended: false
});
case CAN_PLAY:
return _extends({}, state, action.videoProps, {
waiting: false
});
case WAITING:
return _extends({}, state, action.videoProps, {
waiting: true
});
case CAN_PLAY_THROUGH:
case PLAYING:
return _extends({}, state, action.videoProps, {
waiting: false
});
case PLAY:
return _extends({}, state, action.videoProps, {
ended: false,
paused: false,
autoPaused: false,
waiting: false,
hasStarted: true
});
case PAUSE:
return _extends({}, state, action.videoProps, {
paused: true
});
case END:
return _extends({}, state, action.videoProps, {
ended: true
});
case SEEKING:
return _extends({}, state, action.videoProps, {
seeking: true
});
case SEEKED:
return _extends({}, state, action.videoProps, {
seeking: false
});
case ERROR:
return _extends({}, state, action.videoProps, {
error: 'UNKNOWN ERROR',
ended: true
});
case DURATION_CHANGE:
case TIME_UPDATE:
case VOLUME_CHANGE:
case PROGRESS_CHANGE:
case RATE_CHANGE:
case SUSPEND:
case ABORT:
case EMPTIED:
case STALLED:
case LOADED_META_DATA:
case LOADED_DATA:
case RESIZE:
return _extends({}, state, action.videoProps);
case ACTIVATE_TEXT_TRACK:
return _extends({}, state, {
activeTextTrack: action.textTrack
});
default:
return state;
}
}
var initialState$1 = {
count: 0,
operation: {
action: '',
source: ''
}
};
function operation(state, action) {
if (state === void 0) {
state = initialState$1;
}
switch (action.type) {
case OPERATE:
return _extends({}, state, {
count: state.count + 1,
operation: _extends({}, state.operation, action.operation)
});
default:
return state;
}
}
function reducer (state, action) {
if (state === void 0) {
state = {};
}
return {
player: player(state.player, action),
operation: operation(state.operation, action)
};
}
var playerReducer = player;
var operationReducer = operation;
var Manager = /*#__PURE__*/function () {
function Manager(store) {
this.store = store || createStore(reducer);
this.video = null;
this.rootElement = null;
}
var _proto = Manager.prototype;
_proto.getActions = function getActions() {
var manager = this;
var dispatch = this.store.dispatch;
var actions = _extends({}, playerActions, videoActions);
function bindActionCreator(actionCreator) {
return function bindAction() {
// eslint-disable-next-line prefer-rest-params
var action = actionCreator.apply(manager, arguments);
if (typeof action !== 'undefined') {
dispatch(action);
}
};
}
return Object.keys(actions).filter(function (key) {
return typeof actions[key] === 'function';
}).reduce(function (boundActions, key) {
boundActions[key] = bindActionCreator(actions[key]);
return boundActions;
}, {});
};
_proto.getState = function getState() {
return this.store.getState();
} // subscribe state change
;
_proto.subscribeToStateChange = function subscribeToStateChange(listener, getState) {
if (!getState) {
getState = this.getState.bind(this);
}
var prevState = getState();
var handleChange = function handleChange() {
var state = getState();
if (state === prevState) {
return;
}
var prevStateCopy = prevState;
prevState = state;
listener(state, prevStateCopy);
};
return this.store.subscribe(handleChange);
} // subscribe to operation state change
;
_proto.subscribeToOperationStateChange = function subscribeToOperationStateChange(listener) {
var _this = this;
return this.subscribeToStateChange(listener, function () {
return _this.getState().operation;
});
} // subscribe to player state change
;
_proto.subscribeToPlayerStateChange = function subscribeToPlayerStateChange(listener) {
var _this2 = this;
return this.subscribeToStateChange(listener, function () {
return _this2.getState().player;
});
};
return Manager;
}();
var propTypes = {
actions: PropTypes.object,
player: PropTypes.object,
position: PropTypes.string,
className: PropTypes.string
};
var defaultProps = {
position: 'left'
};
var BigPlayButton = /*#__PURE__*/function (_Component) {
_inheritsLoose(BigPlayButton, _Component);
function BigPlayButton(props, context) {
var _this;
_this = _Component.call(this, props, context) || this;
_this.handleClick = _this.handleClick.bind(_assertThisInitialized(_this));
return _this;
}
var _proto = BigPlayButton.prototype;
_proto.componentDidMount = function componentDidMount() {};
_proto.handleClick = function handleClick() {
var actions = this.props.actions;
actions.play();
};
_proto.render = function render() {
var _this$props = this.props,
player = _this$props.player,
position = _this$props.position;
return /*#__PURE__*/React.createElement("button", {
className: classNames('video-react-button', 'video-react-big-play-button', "video-react-big-play-button-" + position, this.props.className, {
'big-play-button-hide': player.hasStarted || !player.currentSrc
}),
type: "button",
"aria-live": "polite",
tabIndex: "0",
onClick: this.handleClick
}, /*#__PURE__*/React.createElement("span", {
className: "video-react-control-text"
}, "Play Video"));
};
return BigPlayButton;
}(Component);
BigPlayButton.propTypes = propTypes;
BigPlayButton.defaultProps = defaultProps;
BigPlayButton.displayName = 'BigPlayButton';
var propTypes$1 = {
player: PropTypes.object,
className: PropTypes.string
};
function LoadingSpinner(_ref) {
var player = _ref.player,
className = _ref.className;
if (player.error) {
return null;
}
return /*#__PURE__*/React.createElement("div", {
className: classNames('video-react-loading-spinner', className)
});
}
LoadingSpinner.propTypes = propTypes$1;
LoadingSpinner.displayName = 'LoadingSpinner';
var propTypes$2 = {
poster: PropTypes.string,
player: PropTypes.object,
actions: PropTypes.object,
className: PropTypes.string
};
function PosterImage(_ref) {
var poster = _ref.poster,
player = _ref.player,
actions = _ref.actions,
className = _ref.className;
if (!poster || player.hasStarted) {
return null;
}
return /*#__PURE__*/React.createElement("div", {
className: classNames('video-react-poster', className),
style: {
backgroundImage: "url(\"" + poster + "\")"
},
onClick: function onClick() {
if (player.paused) {
actions.play();
}
}
});
}
PosterImage.propTypes = propTypes$2;
PosterImage.displayName = 'PosterImage';
// eslint-disable-next-line no-self-compare
var isNaN = Number.isNaN || function (value) {
return value !== value;
};
/**
* @file format-time.js
*
* Format seconds as a time string, H:MM:SS or M:SS
* Supplying a guide (in seconds) will force a number of leading zeros
* to cover the length of the guide
*
* @param {Number} seconds Number of seconds to be turned into a string
* @param {Number} guide Number (in seconds) to model the string after
* @return {String} Time formatted as H:MM:SS or M:SS
* @private
* @function formatTime
*/
function formatTime(seconds, guide) {
if (seconds === void 0) {
seconds = 0;
}
if (guide === void 0) {
guide = seconds;
}
var s = Math.floor(seconds % 60);
var m = Math.floor(seconds / 60 % 60);
var h = Math.floor(seconds / 3600);
var gm = Math.floor(guide / 60 % 60);
var gh = Math.floor(guide / 3600); // handle invalid times
if (isNaN(seconds) || seconds === Infinity) {
// '-' is false for all relational operators (e.g. <, >=) so this setting
// will add the minimum number of fields specified by the guide
h = '-';
m = '-';
s = '-';
} // Check if we need to show hours
h = h > 0 || gh > 0 ? h + ":" : ''; // If hours are showing, we may need to add a leading zero.
// Always show at least one digit of minutes.
m = ((h || gm >= 10) && m < 10 ? "0" + m : m) + ":"; // Check if leading zero is need for seconds
s = s < 10 ? "0" + s : s;
return h + m + s;
} // Check if the element belongs to a video element
// only accept <source />, <track />,
// <MyComponent isVideoChild />
// elements
function isVideoChild(c) {
if (c.props && c.props.isVideoChild) {
return true;
}
return c.type === 'source' || c.type === 'track';
}
var find = function find(elements, func) {
return elements.filter(func)[0];
}; // check if two components are the same type
var isTypeEqual = function isTypeEqual(component1, component2) {
var type1 = component1.type;
var type2 = component2.type;
if (typeof type1 === 'string' || typeof type2 === 'string') {
return type1 === type2;
}
if (typeof type1 === 'function' && typeof type2 === 'function') {
return type1.displayName === type2.displayName;
}
return false;
}; // merge default children
// sort them by `order` property
// filter them by `disabled` property
function mergeAndSortChildren(defaultChildren, _children, _parentProps, defaultOrder) {
if (defaultOrder === void 0) {
defaultOrder = 1;
}
var children = React.Children.toArray(_children);
var order = _parentProps.order,
parentProps = _objectWithoutPropertiesLoose(_parentProps, ["order"]); // ignore order from parent
return children.filter(function (e) {
return !e.props.disabled;
}) // filter the disabled components
.concat(defaultChildren.filter(function (c) {
return !find(children, function (component) {
return isTypeEqual(component, c);
});
})).map(function (element) {
var defaultComponent = find(defaultChildren, function (c) {
return isTypeEqual(c, element);
});
var defaultProps = defaultComponent ? defaultComponent.props : {};
var props = _extends({}, parentProps, defaultProps, element.props);
var e = /*#__PURE__*/React.cloneElement(element, props, element.props.children);
return e;
}).sort(function (a, b) {
return (a.props.order || defaultOrder) - (b.props.order || defaultOrder);
});
}
/**
* Temporary utility for generating the warnings
*/
function deprecatedWarning(oldMethodCall, newMethodCall) {
// eslint-disable-next-line no-console
console.warn("WARNING: " + oldMethodCall + " will be deprecated soon! Please use " + newMethodCall + " instead.");
}
function throttle(callback, limit) {
var _arguments = arguments;
var wait = false;
return function () {
if (!wait) {
// eslint-disable-next-line prefer-rest-params
callback.apply(void 0, _arguments);
wait = true;
setTimeout(function () {
wait = false;
}, limit);
}
};
}
var mediaProperties = ['error', 'src', 'srcObject', 'currentSrc', 'crossOrigin', 'networkState', 'preload', 'buffered', 'readyState', 'seeking', 'currentTime', 'duration', 'paused', 'defaultPlaybackRate', 'playbackRate', 'played', 'seekable', 'ended', 'autoplay', 'loop', 'mediaGroup', 'controller', 'controls', 'volume', 'muted', 'defaultMuted', 'audioTracks', 'videoTracks', 'textTracks', 'width', 'height', 'videoWidth', 'videoHeight', 'poster'];
var propTypes$3 = {
actions: PropTypes.object,
player: PropTypes.object,
children: PropTypes.any,
startTime: PropTypes.number,
loop: PropTypes.bool,
muted: PropTypes.bool,
autoPlay: PropTypes.bool,
playsInline: PropTypes.bool,
src: PropTypes.string,
poster: PropTypes.string,
className: PropTypes.string,
preload: PropTypes.oneOf(['auto', 'metadata', 'none']),
crossOrigin: PropTypes.string,
onLoadStart: PropTypes.func,
onWaiting: PropTypes.func,
onCanPlay: PropTypes.func,
onCanPlayThrough: PropTypes.func,
onPlaying: PropTypes.func,
onEnded: PropTypes.func,
onSeeking: PropTypes.func,
onSeeked: PropTypes.func,
onPlay: PropTypes.func,
onPause: PropTypes.func,
onProgress: PropTypes.func,
onDurationChange: PropTypes.func,
onError: PropTypes.func,
onSuspend: PropTypes.func,
onAbort: PropTypes.func,
onEmptied: PropTypes.func,
onStalled: PropTypes.func,
onLoadedMetadata: PropTypes.func,
onLoadedData: PropTypes.func,
onTimeUpdate: PropTypes.func,
onRateChange: PropTypes.func,
onVolumeChange: PropTypes.func,
onResize: PropTypes.func
};
var Video = /*#__PURE__*/function (_Component) {
_inheritsLoose(Video, _Component);
function Video(props) {
var _this;
_this = _Component.call(this, props) || this;
_this.video = null; // the html5 video
_this.play = _this.play.bind(_assertThisInitialized(_this));
_this.pause = _this.pause.bind(_assertThisInitialized(_this));
_this.seek = _this.seek.bind(_assertThisInitialized(_this));
_this.forward = _this.forward.bind(_assertThisInitialized(_this));
_this.replay = _this.replay.bind(_assertThisInitialized(_this));
_this.toggleFullscreen = _this.toggleFullscreen.bind(_assertThisInitialized(_this));
_this.getProperties = _this.getProperties.bind(_assertThisInitialized(_this));
_this.renderChildren = _this.renderChildren.bind(_assertThisInitialized(_this));
_this.handleLoadStart = _this.handleLoadStart.bind(_assertThisInitialized(_this));
_this.handleCanPlay = _this.handleCanPlay.bind(_assertThisInitialized(_this));
_this.handleCanPlayThrough = _this.handleCanPlayThrough.bind(_assertThisInitialized(_this));
_this.handlePlay = _this.handlePlay.bind(_assertThisInitialized(_this));
_this.handlePlaying = _this.handlePlaying.bind(_assertThisInitialized(_this));
_this.handlePause = _this.handlePause.bind(_assertThisInitialized(_this));
_this.handleEnded = _this.handleEnded.bind(_assertThisInitialized(_this));
_this.handleWaiting = _this.handleWaiting.bind(_assertThisInitialized(_this));
_this.handleSeeking = _this.handleSeeking.bind(_assertThisInitialized(_this));
_this.handleSeeked = _this.handleSeeked.bind(_assertThisInitialized(_this));
_this.handleFullscreenChange = _this.handleFullscreenChange.bind(_assertThisInitialized(_this));
_this.handleError = _this.handleError.bind(_assertThisInitialized(_this));
_this.handleSuspend = _this.handleSuspend.bind(_assertThisInitialized(_this));
_this.handleAbort = _this.handleAbort.bind(_assertThisInitialized(_this));
_this.handleEmptied = _this.handleEmptied.bind(_assertThisInitialized(_this));
_this.handleStalled = _this.handleStalled.bind(_assertThisInitialized(_this));
_this.handleLoadedMetaData = _this.handleLoadedMetaData.bind(_assertThisInitialized(_this));
_this.handleLoadedData = _this.handleLoadedData.bind(_assertThisInitialized(_this));
_this.handleTimeUpdate = _this.handleTimeUpdate.bind(_assertThisInitialized(_this));
_this.handleRateChange = _this.handleRateChange.bind(_assertThisInitialized(_this));
_this.handleVolumeChange = _this.handleVolumeChange.bind(_assertThisInitialized(_this));
_this.handleDurationChange = _this.handleDurationChange.bind(_assertThisInitialized(_this));
_this.handleProgress = throttle(_this.handleProgress.bind(_assertThisInitialized(_this)), 250);
_this.handleKeypress = _this.handleKeypress.bind(_assertThisInitialized(_this));
_this.handleTextTrackChange = _this.handleTextTrackChange.bind(_assertThisInitialized(_this));
return _this;
}
var _proto = Video.prototype;
_proto.componentDidMount = function componentDidMount() {
this.forceUpdate(); // make sure the children can get the video property
if (this.video && this.video.textTracks) {
this.video.textTracks.onaddtrack = this.handleTextTrackChange;
this.video.textTracks.onremovetrack = this.handleTextTrackChange;
}
} // get all video properties
;
_proto.getProperties = function getProperties() {
var _this2 = this;
if (!this.video) {
return null;
}
return mediaProperties.reduce(function (properties, key) {
properties[key] = _this2.video[key];
return properties;
}, {});
} // get playback rate
;
_proto.handleTextTrackChange = function handleTextTrackChange() {
var _this$props = this.props,
actions = _this$props.actions,
player = _this$props.player;
if (this.video && this.video.textTracks) {
var activeTextTrack = Array.from(this.video.textTracks).find(function (textTrack) {
return textTrack.mode === 'showing';
});
if (activeTextTrack !== player.activeTextTrack) {
actions.activateTextTrack(activeTextTrack);
}
}
} // play the video
;
_proto.play = function play() {
var promise = this.video.play();
if (promise !== undefined) {
promise.catch(function () {}).then(function () {});
}
} // pause the video
;
_proto.pause = function pause() {
var promise = this.video.pause();
if (promise !== undefined) {
promise.catch(function () {}).then(function () {});
}
} // Change the video source and re-load the video:
;
_proto.load = function load() {
this.video.load();
} // Add a new text track to the video
;
_proto.addTextTrack = function addTextTrack() {
var _this$video;
(_this$video = this.video).addTextTrack.apply(_this$video, arguments);
} // Check if your browser can play different types of video:
;
_proto.canPlayType = function canPlayType() {
var _this$video2;
(_this$video2 = this.video).canPlayType.apply(_this$video2, arguments);
} // toggle play
;
_proto.togglePlay = function togglePlay() {
if (this.video.paused) {
this.play();
} else {
this.pause();
}
} // seek video by time
;
_proto.seek = function seek(time) {
try {
this.video.currentTime = time;
} catch (e) {// console.log(e, 'Video is not ready.')
}
} // jump forward x seconds
;
_proto.forward = function forward(seconds) {
this.seek(this.video.currentTime + seconds);
} // jump back x seconds
;
_proto.replay = function replay(seconds) {
this.forward(-seconds);
} // enter or exist full screen
;
_proto.toggleFullscreen = function toggleFullscreen() {
var _this$props2 = this.props,
player = _this$props2.player,
actions = _this$props2.actions;
actions.toggleFullscreen(player);
} // Fired when the user agent
// begins looking for media data
;
_proto.handleLoadStart = function handleLoadStart() {
var _this$props3 = this.props,
actions = _this$props3.actions,
onLoadStart = _this$props3.onLoadStart;
actions.handleLoadStart(this.getProperties());
if (onLoadStart) {
onLoadStart.apply(void 0, arguments);
}
} // A handler for events that
// signal that waiting has ended
;
_proto.handleCanPlay = function handleCanPlay() {
var _this$props4 = this.props,
actions = _this$props4.actions,
onCanPlay = _this$props4.onCanPlay;
actions.handleCanPlay(this.getProperties());
if (onCanPlay) {
onCanPlay.apply(void 0, arguments);
}
} // A handler for events that
// signal that waiting has ended
;
_proto.handleCanPlayThrough = function handleCanPlayThrough() {
var _this$props5 = this.props,
actions = _this$props5.actions,
onCanPlayThrough = _this$props5.onCanPlayThrough;
actions.handleCanPlayThrough(this.getProperties());
if (onCanPlayThrough) {
onCanPlayThrough.apply(void 0, arguments);
}
} // A handler for events that
// signal that waiting has ended
;
_proto.handlePlaying = function handlePlaying() {
var _this$props6 = this.props,
actions = _this$props6.actions,
onPlaying = _this$props6.onPlaying;
actions.handlePlaying(this.getProperties());
if (onPlaying) {
onPlaying.apply(void 0, arguments);
}
} // Fired whenever the media has been started
;
_proto.handlePlay = function handlePlay() {
var _this$props7 = this.props,
actions = _this$props7.actions,
onPlay = _this$props7.onPlay;
actions.handlePlay(this.getProperties());
if (onPlay) {
onPlay.apply(void 0, arguments);
}
} // Fired whenever the media has been paused
;
_proto.handlePause = function handlePause() {
var _this$props8 = this.props,
actions = _this$props8.actions,
onPause = _this$props8.onPause;
actions.handlePause(this.getProperties());
if (onPause) {
onPause.apply(void 0, arguments);
}
} // Fired when the duration of
// the media resource is first known or changed
;
_proto.handleDurationChange = function handleDurationChange() {
var _this$props9 = this.props,
actions = _this$props9.actions,
onDurationChange = _this$props9.onDurationChange;
actions.handleDurationChange(this.getProperties());
if (onDurationChange) {
onDurationChange.apply(void 0, arguments);
}
} // Fired while the user agent
// is downloading media data
;
_proto.handleProgress = function handleProgress() {
var _this$props10 = this.props,
actions = _this$props10.actions,
onProgress = _this$props10.onProgress;
if (this.video) {
actions.handleProgressChange(this.getProperties());
}
if (onProgress) {
onProgress.apply(void 0, arguments);
}
} // Fired when the end of the media resource
// is reached (currentTime == duration)
;
_proto.handleEnded = function handleEnded() {
var _this$props11 = this.props,
loop = _this$props11.loop,
player = _this$props11.player,
actions = _this$props11.actions,
onEnded = _this$props11.onEnded;
if (loop) {
this.seek(0);
this.play();
} else if (!player.paused) {
this.pause();
}
actions.handleEnd(this.getProperties());
if (onEnded) {
onEnded.apply(void 0, arguments);
}
} // Fired whenever the media begins waiting
;
_proto.handleWaiting = function handleWaiting() {
var _this$props12 = this.props,
actions = _this$props12.actions,
onWaiting = _this$props12.onWaiting;
actions.handleWaiting(this.getProperties());
if (onWaiting) {
onWaiting.apply(void 0, arguments);
}
} // Fired whenever the player
// is jumping to a new time
;
_proto.handleSeeking = function handleSeeking() {
var _this$props13 = this.props,
actions = _this$props13.actions,
onSeeking = _this$props13.onSeeking;
actions.handleSeeking(this.getProperties());
if (onSeeking) {
onSeeking.apply(void 0, arguments);
}
} // Fired when the player has
// finished jumping to a new time
;
_proto.handleSeeked = function handleSeeked() {
var _this$props14 = this.props,
actions = _this$props14.actions,
onSeeked = _this$props14.onSeeked;
actions.handleSeeked(this.getProperties());
if (onSeeked) {
onSeeked.apply(void 0, arguments);
}
} // Handle Fullscreen Change
;
_proto.handleFullscreenChange = function handleFullscreenChange() {} // Fires when the browser is
// intentionally not getting media data
;
_proto.handleSuspend = function handleSuspend() {
var _this$props15 = this.props,
actions = _this$props15.actions,
onSuspend = _this$props15.onSuspend;
actions.handleSuspend(this.getProperties());
if (onSuspend) {
onSuspend.apply(void 0, arguments);
}
} // Fires when the loading of an audio/video is aborted
;
_proto.handleAbort = function handleAbort() {
var _this$props16 = this.props,
actions = _this$props16.actions,
onAbort = _this$props16.onAbort;
actions.handleAbort(this.getProperties());
if (onAbort) {
onAbort.apply(void 0, arguments);
}
} // Fires when the current playlist is empty
;
_proto.handleEmptied = function handleEmptied() {
var _this$props17 = this.props,
actions = _this$props17.actions,
onEmptied = _this$props17.onEmptied;
actions.handleEmptied(this.getProperties());
if (onEmptied) {
onEmptied.apply(void 0, arguments);
}
} // Fires when the browser is trying to
// get media data, but data is not available
;
_proto.handleStalled = function handleStalled() {
var _this$props18 = this.props,
actions = _this$props18.actions,
onStalled = _this$props18.onStalled;
actions.handleStalled(this.getProperties());
if (onStalled) {
onStalled.apply(void 0, arguments);
}
} // Fires when the browser has loaded
// meta data for the audio/video
;
_proto.handleLoadedMetaData = function handleLoadedMetaData() {
var _this$props19 = this.props,
actions = _this$props19.actions,
onLoadedMetadata = _this$props19.onLoadedMetadata,
startTime = _this$props19.startTime;
if (startTime && startTime > 0) {
this.video.currentTime = startTime;
}
actions.handleLoadedMetaData(this.getProperties());
if (onLoadedMetadata) {
onLoadedMetadata.apply(void 0, arguments);
}
} // Fires when the browser has loaded
// the current frame of the audio/video
;
_proto.handleLoadedData = function handleLoadedData() {
var _this$props20 = this.props,
actions = _this$props20.actions,
onLoadedData = _this$props20.onLoadedData;
actions.handleLoadedData(this.getProperties());
if (onLoadedData) {
onLoadedData.apply(void 0, arguments);
}
} // Fires when the current
// playback position has changed
;
_proto.handleTimeUpdate = function handleTimeUpdate() {
var _this$props21 = this.props,
actions = _this$props21.actions,
onTimeUpdate = _this$props21.onTimeUpdate;
actions.handleTimeUpdate(this.getProperties());
if (onTimeUpdate) {
onTimeUpdate.apply(void 0, arguments);
}
}
/**
* Fires when the playing speed of the audio/video is changed
*/
;
_proto.handleRateChange = function handleRateChange() {
var _this$props22 = this.props,
actions = _this$props22.actions,
onRateChange = _this$props22.onRateChange;
actions.handleRateChange(this.getProperties());
if (onRateChange) {
onRateChange.apply(void 0, arguments);
}
} // Fires when the volume has been changed
;
_proto.handleVolumeChange = function handleVolumeChange() {
var _this$props23 = this.props,
actions = _this$props23.actions,
onVolumeChange = _this$props23.onVolumeChange;
actions.handleVolumeChange(this.getProperties());
if (onVolumeChange) {
onVolumeChange.apply(void 0, arguments);
}
} // Fires when an error occurred
// during the loading of an audio/video
;
_proto.handleError = function handleError() {
var _this$props24 = this.props,
actions = _this$props24.actions,
onError = _this$props24.onError;
actions.handleError(this.getProperties());
if (onError) {
onError.apply(void 0, arguments);
}
};
_proto.handleResize = function handleResize() {
var _this$props25 = this.props,
actions = _this$props25.actions,
onResize = _this$props25.onResize;
actions.handleResize(this.getProperties());
if (onResize) {
onResize.apply(void 0, arguments);
}
};
_proto.handleKeypress = function handleKeypress() {};
_proto.renderChildren = function renderChildren() {
var _this3 = this;
var props = _extends({}, this.props, {
video: this.video
}); // to make sure the children can get video property
if (!this.video) {
return null;
} // only keep <source />, <track />, <MyComponent isVideoChild /> elements
return React.Children.toArray(this.props.children).filter(isVideoChild).map(function (c) {
var cprops;
if (typeof c.type === 'string') {
// add onError to <source />
if (c.type === 'source') {
cprops = _extends({}, c.props);
var preOnError = cprops.onError;
cprops.onError = function () {
if (preOnError) {
preOnError.apply(void 0, arguments);
}
_this3.handleError.apply(_this3, arguments);
};
}
} else {
cprops = props;
}
return /*#__PURE__*/React.cloneElement(c, cprops);
});
};
_proto.render = function render() {
var _this4 = this;
var _this$props26 = this.props,
loop = _this$props26.loop,
poster = _this$props26.poster,
preload = _this$props26.preload,
src = _this$props26.src,
autoPlay = _this$props26.autoPlay,
playsInline = _this$props26.playsInline,
muted = _this$props26.muted,
crossOrigin = _this$props26.crossOrigin,
videoId = _this$props26.videoId;
return /*#__PURE__*/React.createElement("video", {
className: classNames('video-react-video', this.props.className),
id: videoId,
crossOrigin: crossOrigin,
ref: function ref(c) {
_this4.video = c;
},
muted: muted,
preload: preload,
loop: loop,
playsInline: playsInline,
autoPlay: autoPlay,
poster: poster,
src: src,
onLoadStart: this.handleLoadStart,
onWaiting: this.handleWaiting,
onCanPlay: this.handleCanPlay,
onCanPlayThrough: this.handleCanPlayThrough,
onPlaying: this.handlePlaying,
onEnded: this.handleEnded,
onSeeking: this.handleSeeking,
onSeeked: this.handleSeeked,
onPlay: this.handlePlay,
onPause: this.handlePause,
onProgress: this.handleProgress,
onDurationChange: this.handleDurationChange,
onError: this.handleError,
onSuspend: this.handleSuspend,
onAbort: this.handleAbort,
onEmptied: this.handleEmptied,
onStalled: this.handleStalled,
onLoadedMetadata: this.handleLoadedMetaData,
onLoadedData: this.handleLoadedData,
onTimeUpdate: this.handleTimeUpdate,
onRateChange: this.handleRateChange,
onVolumeChange: this.handleVolumeChange,
tabIndex: "-1"
}, this.renderChildren());
};
_createClass(Video, [{
key: "playbackRate",
get: function get() {
return this.video.playbackRate;
} // set playback rate
// speed of video
,
set: function set(rate) {
this.video.playbackRate = rate;
}
}, {
key: "muted",
get: function get() {
return this.video.muted;
},
set: function set(val) {
this.video.muted = val;
}
}, {
key: "volume",
get: function get() {
return this.video.volume;
},
set: function set(val) {
if (val > 1) {
val = 1;
}
if (val < 0) {
val = 0;
}
this.video.volume = val;
} // video width
}, {
key: "videoWidth",
get: function get() {
return this.video.videoWidth;
} // video height
}, {
key: "videoHeight",
get: function get() {
return this.video.videoHeight;
}
}]);
return Video;
}(Component);
Video.propTypes = propTypes$3;
Video.displayName = 'Video';
var propTypes$4 = {
manager: PropTypes.object,
className: PropTypes.string
};
var Bezel = /*#__PURE__*/function (_Component) {
_inheritsLoose(Bezel, _Component);
function Bezel(props, context) {
var _this;
_this = _Component.call(this, props, context) || this;
_this.timer = null;
props.manager.subscribeToOperationStateChange(_this.handleStateChange.bind(_assertThisInitialized(_this)));
_this.state = {
hidden: true,
operation: {}
};
return _this;
}
var _proto = Bezel.prototype;
_proto.handleStateChange = function handleStateChange(state, prevState) {
var _this2 = this;
if (state.count !== prevState.count && state.operation.source === 'shortcut') {
if (this.timer) {
// previous animation is not finished
clearTimeout(this.timer); // cancel it
this.timer = null;
} // show it
// update operation
this.setState({
hidden: false,
count: state.count,
operation: state.operation
}); // hide it after 0.5s
this.timer = setTimeout(function () {
_this2.setState({
hidden: true
});
_this2.timer = null;
}, 500);
}
};
_proto.render = function render() {
// only displays for shortcut so far
if (this.state.operation.source !== 'shortcut') {
return null;
}
var style = this.state.hidden ? {
display: 'none'
} : null;
return /*#__PURE__*/React.createElement("div", {
className: classNames({
'video-react-bezel': true,
'video-react-bezel-animation': this.state.count % 2 === 0,
'video-react-bezel-animation-alt': this.state.count % 2 === 1
}, this.props.className),
style: style,
role: "status",
"aria-label": this.state.operation.action
}, /*#__PURE__*/React.createElement("div", {
className: classNames('video-react-bezel-icon', "video-react-bezel-icon-" + this.state.operation.action)
}));
};
return Bezel;
}(Component);
Bezel.propTypes = propTypes$4;
Bezel.displayName = 'Bezel';
/**
* Offset Left
* getBoundingClientRect technique from
* John Resig http://ejohn.org/blog/getboundingclientrect-is-awesome/
*
* @function findElPosition
* @param {ReactNodeRef} el React Node ref from which to get offset
* @return {Object}
*/
function findElPosition(el) {
var box;
if (el.getBoundingClientRect && el.parentNode) {
box = el.getBoundingClientRect();
}
if (!box) {
return {
left: 0,
top: 0
};
}
var _document = document,
body = _document.body,
docEl = _document.documentElement;
var clientLeft = docEl.clientLeft || body.clientLeft || 0;
var scrollLeft = window.pageXOffset || body.scrollLeft;
var left = box.left + scrollLeft - clientLeft;
var clientTop = docEl.clientTop || body.clientTop || 0;
var scrollTop = window.pageYOffset || body.scrollTop;
var top = box.top + scrollTop - clientTop; // Android sometimes returns slightly off decimal values, so need to round
return {
left: Math.round(left),
top: Math.round(top)
};
}
/**
* Get pointer position in a React Node ref
* Returns an object with x and y coordinates.
* The base on the coordinates are the bottom left of the element.
*
* @function getPointerPosition
* @param {ReactNodeRef} el React Node ref on which to get the pointer position on
* @param {Event} event Event object
* @return {Object} This object will have x and y coordinates corresponding to the mouse position
*/
function getPointerPosition(el, event) {
var position = {};
var box = findElPosition(el);
var boxW = el.offsetWidth;
var boxH = el.offsetHeight;
var boxY = box.top;
var boxX = box.left;
var evtPageY = event.pageY;
var evtPageX = event.pageX;
if (event.changedTouches) {
evtPageX = event.changedTouches[0].pageX;
evtPageY = event.changedTouches[0].pageY;
}
position.y = Math.max(0, Math.min(1, (boxY - evtPageY + boxH) / boxH));
position.x = Math.max(0, Math.min(1, (evtPageX - boxX) / boxW));
return position;
} // blur an element
function focusNode(reactNode) {
if (reactNode && reactNode.focus) {
reactNode.focus();
}
} // check if an element has a class name
function hasClass(elm, cls) {
var classes = elm.className.split(' ');
for (var i = 0; i < classes.length; i++) {
if (classes[i].toLowerCase() === cls.toLowerCase()) {
return true;
}
}
return false;
}
var propTypes$5 = {
clickable: PropTypes.bool,