@enact/sandstone
Version:
Large-screen/TV support library for Enact, containing a variety of UI components.
936 lines (931 loc) • 38.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = exports.MediaControlsDecorator = exports.MediaControlsBase = exports.MediaControls = void 0;
var _dispatcher = require("@enact/core/dispatcher");
var _handle = require("@enact/core/handle");
var _kind = _interopRequireDefault(require("@enact/core/kind"));
var _hoc = _interopRequireDefault(require("@enact/core/hoc"));
var _keymap = require("@enact/core/keymap");
var _util = require("@enact/core/util");
var _ApiDecorator = _interopRequireDefault(require("@enact/core/internal/ApiDecorator"));
var _propTypes = _interopRequireDefault(require("@enact/core/internal/prop-types"));
var _spotlight = _interopRequireDefault(require("@enact/spotlight"));
var _Pause = _interopRequireDefault(require("@enact/spotlight/Pause"));
var _SpotlightContainerDecorator = require("@enact/spotlight/SpotlightContainerDecorator");
var _Cancelable = _interopRequireDefault(require("@enact/ui/Cancelable"));
var _Slottable = _interopRequireDefault(require("@enact/ui/Slottable"));
var _propTypes2 = _interopRequireDefault(require("prop-types"));
var _react = require("react");
var _ActionGuide = _interopRequireDefault(require("../ActionGuide"));
var _Button = _interopRequireDefault(require("../Button"));
var _$L = _interopRequireDefault(require("../internal/$L"));
var _util2 = require("../internal/util");
var _Skinnable = _interopRequireDefault(require("../Skinnable"));
var _util3 = require("./util");
var _MediaControlsModule = _interopRequireDefault(require("./MediaControls.module.css"));
var _jsxRuntime = require("react/jsx-runtime");
var _excluded = ["mediaControlsRef"],
_excluded2 = ["actionGuideAriaLabel", "actionGuideButtonAriaLabel", "actionGuideDisabled", "actionGuideLabel", "actionGuideShowing", "children", "id", "jumpBackwardAriaLabel", "jumpBackwardIcon", "jumpButtonsDisabled", "jumpForwardAriaLabel", "jumpForwardIcon", "bottomComponents", "mediaControlsRef", "mediaDisabled", "moreComponentsSpotlightId", "noJumpButtons", "onActionGuideClick", "onJumpBackwardButtonClick", "onJumpForwardButtonClick", "onKeyDownFromMediaButtons", "onPlayButtonClick", "paused", "pauseIcon", "playIcon", "playPauseButtonDisabled", "showMoreComponents", "moreComponentsRendered", "moreButtonsClassName", "moreComponentsClassName", "actionGuideClassName", "spotlightDisabled", "spotlightId"];
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
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, _toPropertyKey(descriptor.key), descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
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, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : String(i); }
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; 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 _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; }
var DivComponent = function DivComponent(_ref) {
var mediaControlsRef = _ref.mediaControlsRef,
rest = _objectWithoutProperties(_ref, _excluded);
return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", _objectSpread({
ref: mediaControlsRef
}, rest));
};
DivComponent.propTypes = {
/*
* Called with the reference to the mediaControls node.
*
* @type {Object|Function}
* @public
*/
mediaControlsRef: _propTypes["default"].ref
};
var OuterContainer = (0, _SpotlightContainerDecorator.SpotlightContainerDecorator)({
defaultElement: [".".concat(_SpotlightContainerDecorator.spotlightDefaultClass)],
leaveFor: {
left: '',
right: ''
}
}, DivComponent);
var Container = (0, _SpotlightContainerDecorator.SpotlightContainerDecorator)({
enterTo: 'default-element'
}, 'div');
var MediaButton = (0, _util2.onlyUpdateForProps)(_Button["default"], ['children', 'className', 'disabled', 'icon', 'onClick', 'spotlightDisabled']);
var forwardToggleMore = (0, _handle.forward)('onToggleMore');
var animationDuration = 300;
/**
* A set of components for controlling media playback and rendering additional components.
*
* @class MediaControlsBase
* @memberof sandstone/MediaPlayer
* @ui
* @private
*/
var MediaControlsBase = exports.MediaControlsBase = (0, _kind["default"])({
name: 'MediaControls',
// intentionally assigning these props to MediaControls instead of Base (which is private)
propTypes: /** @lends sandstone/MediaPlayer.MediaControls.prototype */{
/**
* DOM id for the component.
*
* This child component `ActionGuide`'s id is generated from the id.
*
* @type {String}
* @required
* @public
*/
id: _propTypes2["default"].string.isRequired,
/**
* The `aria-label` for the action guide.
*
* @type {String}
* @public
*/
actionGuideAriaLabel: _propTypes2["default"].string,
/**
* The `aria-label` for the action guide button.
*
* @type {String}
* @public
*/
actionGuideButtonAriaLabel: _propTypes2["default"].string,
/**
* Disables the ActionGuide.
*
* @type {Boolean}
* @public
*/
actionGuideDisabled: _propTypes2["default"].bool,
/**
* The label for the action guide.
*
* @type {String}
* @public
*/
actionGuideLabel: _propTypes2["default"].string,
/**
* These components are placed below the action guide. Typically these will be media playlist controls.
*
* @type {Node}
* @public
*/
bottomComponents: _propTypes2["default"].node,
/**
* The `aria-label` for the jumpBackward button.
*
* @type {String}
* @public
*/
jumpBackwardAriaLabel: _propTypes2["default"].string,
/**
* Jump backward {@link sandstone/Icon.Icon|icon} name. Accepts any
* {@link sandstone/Icon.Icon|icon} component type.
*
* @type {String}
* @default 'jumpbackward'
* @public
*/
jumpBackwardIcon: _propTypes2["default"].string,
/**
* Disables state on the media "jump" buttons; the outer pair.
*
* @type {Boolean}
* @public
*/
jumpButtonsDisabled: _propTypes2["default"].bool,
/**
* The `aria-label` for the jumpForward button.
*
* @type {String}
* @public
*/
jumpForwardAriaLabel: _propTypes2["default"].string,
/**
* Jump forward {@link sandstone/Icon.Icon|icon} name. Accepts any
* {@link sandstone/Icon.Icon|icon} component type.
*
* @type {String}
* @default 'jumpforward'
* @public
*/
jumpForwardIcon: _propTypes2["default"].string,
/**
* Called with the reference to the mediaControls node.
*
* @type {Object|Function}
* @public
*/
mediaControlsRef: _propTypes["default"].ref,
/**
* Disables the media buttons.
*
* @type {Boolean}
* @public
*/
mediaDisabled: _propTypes2["default"].bool,
/**
* When `true`, more components are rendered. This does not indicate the visibility of more components.
*
* @type {Boolean}
* @public
*/
moreComponentsRendered: _propTypes2["default"].bool,
/**
* The spotlight ID for the moreComponent container.
*
* @type {String}
* @public
* @default 'moreComponents'
*/
moreComponentsSpotlightId: _propTypes2["default"].string,
/**
* Removes the "jump" buttons. The buttons that skip forward or backward in the video.
*
* @type {Boolean}
* @public
*/
noJumpButtons: _propTypes2["default"].bool,
/**
* Called when the button in ActionGuide is clicked.
*
* @type {Function}
* @param {Object} event
* @public
*/
onActionGuideClick: _propTypes2["default"].func,
/**
* Called when cancel/back key events are fired.
*
* @type {Function}
* @public
*/
onClose: _propTypes2["default"].func,
/**
* Called when the user clicks the JumpBackward button
*
* @type {Function}
* @public
*/
onJumpBackwardButtonClick: _propTypes2["default"].func,
/**
* Called when the user clicks the JumpForward button.
*
* @type {Function}
* @public
*/
onJumpForwardButtonClick: _propTypes2["default"].func,
/**
* Called when the user presses a media control button.
*
* @type {Function}
* @public
*/
onKeyDownFromMediaButtons: _propTypes2["default"].func,
/**
* Called when the user clicks the Play button.
*
* @type {Function}
* @public
*/
onPlayButtonClick: _propTypes2["default"].func,
/**
* `true` when the video is paused.
*
* @type {Boolean}
* @public
*/
paused: _propTypes2["default"].bool,
/**
* A string which is sent to the `pause` icon of the player controls. This can be
* anything that is accepted by {@link sandstone/Icon.Icon|Icon}. This will be temporarily replaced by
* the {@link sandstone/MediaPlayer.MediaControls.playIcon|playIcon} when the
* {@link sandstone/MediaPlayer.MediaControls.paused|paused} boolean is `false`.
*
* @type {String}
* @default 'pause'
* @public
*/
pauseIcon: _propTypes2["default"].string,
/**
* A string which is sent to the `play` icon of the player controls. This can be
* anything that is accepted by {@link sandstone/Icon.Icon}. This will be temporarily replaced by
* the {@link sandstone/MediaPlayer.MediaControls.pauseIcon|pauseIcon} when the
* {@link sandstone/MediaPlayer.MediaControls.paused|paused} boolean is `true`.
*
* @type {String}
* @default 'play'
* @public
*/
playIcon: _propTypes2["default"].string,
/**
* Disables the media "play"/"pause" button.
*
* @type {Boolean}
* @public
*/
playPauseButtonDisabled: _propTypes2["default"].bool,
/**
* When `true`, more components are visible.
*
* @type {Boolean}
* @private
*/
showMoreComponents: _propTypes2["default"].bool,
/**
* `true` controls are disabled from Spotlight.
*
* @type {Boolean}
* @public
*/
spotlightDisabled: _propTypes2["default"].bool,
/**
* The spotlight ID for the media controls container.
*
* @type {String}
* @public
* @default 'mediaControls'
*/
spotlightId: _propTypes2["default"].string,
/**
* The visibility of the component. When `false`, the component will be hidden.
*
* @type {Boolean}
* @default true
* @public
*/
visible: _propTypes2["default"].bool
},
defaultProps: {
jumpBackwardIcon: 'jumpbackward',
jumpForwardIcon: 'jumpforward',
moreComponentsSpotlightId: 'moreComponents',
spotlightId: 'mediaControls',
pauseIcon: 'pause',
playIcon: 'play',
visible: true
},
styles: {
css: _MediaControlsModule["default"],
className: 'controlsFrame'
},
computed: {
actionGuideClassName: function actionGuideClassName(_ref2) {
var styler = _ref2.styler,
showMoreComponents = _ref2.showMoreComponents;
return styler.join({
hidden: showMoreComponents
});
},
actionGuideShowing: function actionGuideShowing(_ref3) {
var bottomComponents = _ref3.bottomComponents,
children = _ref3.children;
return (0, _util3.countReactChildren)(children) || bottomComponents;
},
className: function className(_ref4) {
var visible = _ref4.visible,
styler = _ref4.styler;
return styler.append({
hidden: !visible
});
},
moreButtonsClassName: function moreButtonsClassName(_ref5) {
var styler = _ref5.styler;
return styler.join('mediaControls', 'moreButtonsComponents');
},
moreComponentsClassName: function moreComponentsClassName(_ref6) {
var styler = _ref6.styler,
showMoreComponents = _ref6.showMoreComponents;
return styler.join({
hidden: !showMoreComponents
}, 'moreComponents');
},
moreComponentsRendered: function moreComponentsRendered(_ref7) {
var showMoreComponents = _ref7.showMoreComponents,
_moreComponentsRendered = _ref7.moreComponentsRendered;
return showMoreComponents || _moreComponentsRendered;
}
},
render: function render(_ref8) {
var actionGuideAriaLabel = _ref8.actionGuideAriaLabel,
actionGuideButtonAriaLabel = _ref8.actionGuideButtonAriaLabel,
actionGuideDisabled = _ref8.actionGuideDisabled,
actionGuideLabel = _ref8.actionGuideLabel,
actionGuideShowing = _ref8.actionGuideShowing,
children = _ref8.children,
id = _ref8.id,
jumpBackwardAriaLabel = _ref8.jumpBackwardAriaLabel,
jumpBackwardIcon = _ref8.jumpBackwardIcon,
jumpButtonsDisabled = _ref8.jumpButtonsDisabled,
jumpForwardAriaLabel = _ref8.jumpForwardAriaLabel,
jumpForwardIcon = _ref8.jumpForwardIcon,
bottomComponents = _ref8.bottomComponents,
mediaControlsRef = _ref8.mediaControlsRef,
mediaDisabled = _ref8.mediaDisabled,
moreComponentsSpotlightId = _ref8.moreComponentsSpotlightId,
noJumpButtons = _ref8.noJumpButtons,
onActionGuideClick = _ref8.onActionGuideClick,
onJumpBackwardButtonClick = _ref8.onJumpBackwardButtonClick,
onJumpForwardButtonClick = _ref8.onJumpForwardButtonClick,
onKeyDownFromMediaButtons = _ref8.onKeyDownFromMediaButtons,
onPlayButtonClick = _ref8.onPlayButtonClick,
paused = _ref8.paused,
pauseIcon = _ref8.pauseIcon,
playIcon = _ref8.playIcon,
playPauseButtonDisabled = _ref8.playPauseButtonDisabled,
showMoreComponents = _ref8.showMoreComponents,
moreComponentsRendered = _ref8.moreComponentsRendered,
moreButtonsClassName = _ref8.moreButtonsClassName,
moreComponentsClassName = _ref8.moreComponentsClassName,
actionGuideClassName = _ref8.actionGuideClassName,
spotlightDisabled = _ref8.spotlightDisabled,
spotlightId = _ref8.spotlightId,
rest = _objectWithoutProperties(_ref8, _excluded2);
delete rest.onClose;
delete rest.visible;
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(OuterContainer, _objectSpread(_objectSpread({}, rest), {}, {
id: id,
mediaControlsRef: mediaControlsRef,
spotlightId: spotlightId,
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(Container, {
className: _MediaControlsModule["default"].mediaControls,
spotlightDisabled: spotlightDisabled,
onKeyDown: onKeyDownFromMediaButtons,
children: [noJumpButtons ? null : /*#__PURE__*/(0, _jsxRuntime.jsx)(MediaButton, {
"aria-label": jumpBackwardAriaLabel || (0, _$L["default"])('Previous'),
backgroundOpacity: "transparent",
css: _MediaControlsModule["default"],
disabled: mediaDisabled || jumpButtonsDisabled,
icon: jumpBackwardIcon,
onClick: onJumpBackwardButtonClick,
size: "large",
spotlightDisabled: spotlightDisabled
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(MediaButton, {
"aria-label": paused ? (0, _$L["default"])('Play') : (0, _$L["default"])('Pause'),
className: _SpotlightContainerDecorator.spotlightDefaultClass,
backgroundOpacity: "transparent",
css: _MediaControlsModule["default"],
disabled: mediaDisabled || playPauseButtonDisabled,
icon: paused ? playIcon : pauseIcon,
onClick: onPlayButtonClick,
size: "large",
spotlightDisabled: spotlightDisabled
}), noJumpButtons ? null : /*#__PURE__*/(0, _jsxRuntime.jsx)(MediaButton, {
"aria-label": jumpForwardAriaLabel || (0, _$L["default"])('Next'),
backgroundOpacity: "transparent",
css: _MediaControlsModule["default"],
disabled: mediaDisabled || jumpButtonsDisabled,
icon: jumpForwardIcon,
onClick: onJumpForwardButtonClick,
size: "large",
spotlightDisabled: spotlightDisabled
})]
}), actionGuideShowing ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_ActionGuide["default"], {
id: "".concat(id, "_actionGuide"),
"aria-label": actionGuideAriaLabel != null ? actionGuideAriaLabel : null,
buttonAriaLabel: actionGuideButtonAriaLabel,
css: _MediaControlsModule["default"],
className: actionGuideClassName,
icon: "arrowsmalldown",
onClick: onActionGuideClick,
disabled: actionGuideDisabled,
children: actionGuideLabel
}) : null, moreComponentsRendered ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(Container, {
spotlightId: moreComponentsSpotlightId,
className: moreComponentsClassName,
spotlightDisabled: !showMoreComponents || spotlightDisabled,
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(Container, {
className: moreButtonsClassName,
children: children
}), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
children: bottomComponents
})]
}) : null]
}));
}
});
/**
* Media control behaviors to apply to {@link sandstone/MediaPlayer.MediaControlsBase|MediaControlsBase}.
* Provides built-in support for showing more components and key handling for basic playback
* controls.
*
* @class MediaControlsDecorator
* @memberof sandstone/MediaPlayer
* @mixes ui/Slottable.Slottable
* @hoc
* @private
*/
var MediaControlsDecorator = exports.MediaControlsDecorator = (0, _hoc["default"])(function (config, Wrapped) {
var MediaControlsDecoratorHOC = /*#__PURE__*/function (_Component) {
_inherits(MediaControlsDecoratorHOC, _Component);
var _super = _createSuper(MediaControlsDecoratorHOC);
function MediaControlsDecoratorHOC(props) {
var _this;
_classCallCheck(this, MediaControlsDecoratorHOC);
_this = _super.call(this, props);
_this.moreComponentsRenderingJob = new _util.Job(function () {
_this.setState({
moreComponentsRendered: true
});
});
_this.calculateMoreComponentsHeight = function () {
if (!_this.mediaControlsNode) {
_this.bottomComponentsHeight = 0;
return;
}
var bottomElement = _this.mediaControlsNode.querySelector(".".concat(_MediaControlsModule["default"].moreComponents));
_this.bottomComponentsHeight = bottomElement ? bottomElement.scrollHeight : 0;
};
_this.handleKeyDown = function (ev) {
var _this$props = _this.props,
mediaDisabled = _this$props.mediaDisabled,
no5WayJump = _this$props.no5WayJump,
visible = _this$props.visible;
var current = _spotlight["default"].getCurrent();
if (!no5WayJump && !visible && !mediaDisabled && !current && ((0, _keymap.is)('left', ev.keyCode) || (0, _keymap.is)('right', ev.keyCode))) {
_this.paused.pause();
_this.startListeningForPulses(ev.keyCode);
}
};
_this.handleKeyUp = function (ev) {
var _this$props2 = _this.props,
mediaDisabled = _this$props2.mediaDisabled,
no5WayJump = _this$props2.no5WayJump,
rateChangeDisabled = _this$props2.rateChangeDisabled,
playPauseButtonDisabled = _this$props2.playPauseButtonDisabled;
if (mediaDisabled) return;
if (!playPauseButtonDisabled) {
if ((0, _keymap.is)('play', ev.keyCode)) {
(0, _handle.forward)('onPlay', ev, _this.props);
} else if ((0, _keymap.is)('pause', ev.keyCode)) {
(0, _handle.forward)('onPause', ev, _this.props);
}
}
if (!no5WayJump && ((0, _keymap.is)('left', ev.keyCode) || (0, _keymap.is)('right', ev.keyCode))) {
_this.stopListeningForPulses();
_this.paused.resume();
}
if (!rateChangeDisabled) {
if ((0, _keymap.is)('rewind', ev.keyCode)) {
(0, _handle.forward)('onRewind', ev, _this.props);
} else if ((0, _keymap.is)('fastForward', ev.keyCode)) {
(0, _handle.forward)('onFastForward', ev, _this.props);
}
}
};
_this.handleBlur = function () {
_this.stopListeningForPulses();
_this.paused.resume();
};
_this.handleActionGuideClick = function () {
if (!_this.state.showMoreComponents) {
_this.showMoreComponents();
}
};
_this.startListeningForPulses = function (keyCode) {
// Ignore new pulse calls if key code is same, otherwise start new series if we're pulsing
if (_this.pulsing && keyCode !== _this.pulsingKeyCode) {
_this.stopListeningForPulses();
}
if (!_this.pulsing) {
_this.pulsingKeyCode = keyCode;
_this.pulsing = true;
_this.keyLoop = setTimeout(_this.handlePulse, _this.props.initialJumpDelay);
(0, _handle.forward)('onJump', {
keyCode: keyCode
}, _this.props);
}
};
_this.handlePulse = function () {
(0, _handle.forward)('onJump', {
keyCode: _this.pulsingKeyCode
}, _this.props);
_this.keyLoop = setTimeout(_this.handlePulse, _this.props.jumpDelay);
};
_this.handlePlayButtonClick = function (ev) {
(0, _handle.forward)('onPlayButtonClick', ev, _this.props);
if (_this.props.paused) {
(0, _handle.forward)('onPlay', ev, _this.props);
} else {
(0, _handle.forward)('onPause', ev, _this.props);
}
};
_this.getMediaControls = function (node) {
if (!node) {
_this.actionGuideHeight = 0;
return;
}
_this.mediaControlsNode = _this.mediaControlsRef.current;
var guideElement = _this.mediaControlsNode.querySelector(".".concat(_MediaControlsModule["default"].actionGuide));
_this.actionGuideHeight = guideElement ? guideElement.scrollHeight : 0;
};
_this.areMoreComponentsAvailable = function () {
return _this.state.showMoreComponents;
};
_this.showMoreComponents = function () {
_this.setState({
showMoreComponents: true
});
};
_this.hideMoreComponents = function () {
_this.setState({
showMoreComponents: false
});
};
_this.handleClose = function (ev) {
if (_this.props.visible) {
(0, _handle.forward)('onClose', ev, _this.props);
}
};
_this.handleFinish = function () {
if (_this.state.showMoreComponents) {
_this.paused.resume();
if (!_spotlight["default"].getPointerMode()) {
_spotlight["default"].focus(_this.moreComponentsSpotlightId);
}
}
};
_this.handleCancel = function () {
_this.paused.resume();
};
_this.mediaControlsNode = null;
_this.moreComponentsNode = null;
_this.actionGuideHeight = 0;
_this.animation = null;
_this.bottomComponentsHeight = 0;
_this.moreComponentsSpotlightId = 'moreComponents';
_this.keyLoop = null;
_this.pulsingKeyCode = null;
_this.pulsing = null;
_this.paused = new _Pause["default"]('MediaPlayer');
_this.mediaControlsRef = /*#__PURE__*/(0, _react.createRef)();
_this.state = {
showMoreComponents: false,
moreComponentsRendered: false
};
if (props.setApiProvider) {
props.setApiProvider(_assertThisInitialized(_this));
}
return _this;
}
_createClass(MediaControlsDecoratorHOC, [{
key: "componentDidMount",
value: function componentDidMount() {
(0, _dispatcher.on)('keydown', this.handleKeyDown, document);
(0, _dispatcher.on)('keyup', this.handleKeyUp, document);
(0, _dispatcher.on)('blur', this.handleBlur, window);
}
}, {
key: "componentDidUpdate",
value: function componentDidUpdate(prevProps, prevState) {
// Need to render `moreComponents` to show it. For performance, render `moreComponents` if it is actually shown.
if (!prevState.showMoreComponents && this.state.showMoreComponents && !this.state.moreComponentsRendered) {
this.moreComponentsRenderingJob.startRafAfter();
} else if (prevState.showMoreComponents && !this.state.showMoreComponents) {
this.moreComponentsRenderingJob.stop();
}
if (!prevState.moreComponentsRendered && this.state.moreComponentsRendered || this.state.moreComponentsRendered && prevProps.bottomComponents !== this.props.bottomComponents || !(0, _util2.compareChildren)(this.props.children, prevProps.children)) {
this.calculateMoreComponentsHeight();
}
if (this.state.showMoreComponents && !prevState.moreComponentsRendered && this.state.moreComponentsRendered || this.state.moreComponentsRendered && prevState.showMoreComponents !== this.state.showMoreComponents) {
forwardToggleMore({
type: 'onToggleMore',
showMoreComponents: this.state.showMoreComponents,
liftDistance: this.bottomComponentsHeight - this.actionGuideHeight
}, this.props);
if (this.state.showMoreComponents) {
this.moreComponentsNode = this.moreComponentsNode || this.mediaControlsNode.querySelector(".".concat(_MediaControlsModule["default"].moreComponents));
this.paused.pause();
this.animation = this.moreComponentsNode.animate([{
transform: 'none',
opacity: 0,
offset: 0
}, {
transform: "translateY(".concat(-this.actionGuideHeight, "px)"),
opacity: 1,
offset: 1
}], {
duration: animationDuration,
fill: 'forwards'
});
this.animation.onfinish = this.handleFinish;
this.animation.oncancel = this.handleCancel;
} else if (this.animation != null) {
this.animation.cancel();
}
}
// if media controls disabled, reset key loop
if (!prevProps.mediaDisabled && this.props.mediaDisabled || !prevProps.visible && this.props.visible) {
this.stopListeningForPulses();
this.paused.resume();
}
}
}, {
key: "componentWillUnmount",
value: function componentWillUnmount() {
(0, _dispatcher.off)('keydown', this.handleKeyDown, document);
(0, _dispatcher.off)('keyup', this.handleKeyUp, document);
(0, _dispatcher.off)('blur', this.handleBlur, window);
this.stopListeningForPulses();
this.moreComponentsRenderingJob.stop();
if (this.animation) {
this.animation.cancel();
}
}
}, {
key: "stopListeningForPulses",
value: function stopListeningForPulses() {
this.pulsing = false;
if (this.keyLoop) {
clearTimeout(this.keyLoop);
this.keyLoop = null;
}
}
}, {
key: "toggleMoreComponents",
value: function toggleMoreComponents() {
this.setState(function (prevState) {
return {
showMoreComponents: !prevState.showMoreComponents
};
});
}
}, {
key: "render",
value: function render() {
var props = Object.assign({}, this.props);
delete props.initialJumpDelay;
delete props.jumpDelay;
delete props.moreActionDisabled;
delete props.no5WayJump;
delete props.onFastForward;
delete props.onJump;
delete props.onPause;
delete props.onPlay;
delete props.onRewind;
delete props.onToggleMore;
delete props.rateChangeDisabled;
delete props.setApiProvider;
return /*#__PURE__*/(0, _jsxRuntime.jsx)(Wrapped, _objectSpread(_objectSpread({}, props), {}, {
mediaControlsRef: this.mediaControlsRef,
actionGuideDisabled: this.props.moreActionDisabled,
moreComponentsRendered: this.state.moreComponentsRendered,
moreComponentsSpotlightId: this.moreComponentsSpotlightId,
onActionGuideClick: this.handleActionGuideClick,
onClose: this.handleClose,
onPlayButtonClick: this.handlePlayButtonClick,
ref: this.getMediaControls,
showMoreComponents: this.state.showMoreComponents
}));
}
}], [{
key: "getDerivedStateFromProps",
value: function getDerivedStateFromProps(props) {
if (!props.visible) {
return {
showMoreComponents: false
};
}
return null;
}
}]);
return MediaControlsDecoratorHOC;
}(_react.Component);
MediaControlsDecoratorHOC.displayName = 'MediaControlsDecorator';
MediaControlsDecoratorHOC.propTypes = /** @lends sandstone/MediaPlayer.MediaControlsDecorator.prototype */{
/**
* The label for the action guide.
*
* @type {String}
* @public
*/
actionGuideLabel: _propTypes2["default"].string,
/**
* These components are placed below the children. Typically these will be media playlist items.
*
* @type {Node}
* @public
*/
bottomComponents: _propTypes2["default"].node,
/**
* The number of milliseconds that the player will pause before firing the
* first jump event on a right or left pulse.
*
* @type {Number}
* @default 400
* @public
*/
initialJumpDelay: _propTypes2["default"].number,
/**
* The number of milliseconds that the player will throttle before firing a
* jump event on a right or left pulse.
*
* @type {Number}
* @default 200
* @public
*/
jumpDelay: _propTypes2["default"].number,
/**
* Disables the media buttons.
*
* @type {Boolean}
* @public
*/
mediaDisabled: _propTypes2["default"].bool,
/**
* Disables showing more components.
*
* @type {Boolean}
* @public
*/
moreActionDisabled: _propTypes2["default"].bool,
/**
* Setting this to `true` will disable left and right keys for seeking.
*
* @type {Boolean}
* @public
*/
no5WayJump: _propTypes2["default"].bool,
/**
* Called when media fast forwards.
*
* @type {Function}
* @public
*/
onFastForward: _propTypes2["default"].func,
/**
* Called when media jumps.
*
* @type {Function}
* @public
*/
onJump: _propTypes2["default"].func,
/**
* Called when media gets paused.
*
* @type {Function}
* @public
*/
onPause: _propTypes2["default"].func,
/**
* Called when media starts playing.
*
* @type {Function}
* @public
*/
onPlay: _propTypes2["default"].func,
/**
* Called when media rewinds.
*
* @type {Function}
* @public
*/
onRewind: _propTypes2["default"].func,
/**
* Called when the visibility of more components is changed
*
* Event payload includes:
*
* * `type` - Type of event, `'onToggleMore'`
* * `showMoreComponents` - `true` when the components are visible`
* * `liftDistance` - The distance, in pixels, the component animates
*
* @type {Function}
* @public
*/
onToggleMore: _propTypes2["default"].func,
/**
* The video pause state.
*
* @type {Boolean}
* @public
*/
paused: _propTypes2["default"].bool,
/**
* Disables state on the media "play"/"pause" button
*
* @type {Boolean}
* @public
*/
playPauseButtonDisabled: _propTypes2["default"].bool,
/**
* Disables the media playback-rate control via rewind and fast forward keys
*
* @type {Boolean}
* @public
*/
rateChangeDisabled: _propTypes2["default"].bool,
/**
* Registers the MediaControls component with an
* {@link core/internal/ApiDecorator.ApiDecorator|ApiDecorator}.
*
* @type {Function}
* @private
*/
setApiProvider: _propTypes2["default"].func,
/**
* The visibility of the component. When `false`, the component will be hidden.
*
* @type {Boolean}
* @public
*/
visible: _propTypes2["default"].bool
};
MediaControlsDecoratorHOC.defaultProps = {
initialJumpDelay: 400,
jumpDelay: 200
};
return (0, _Slottable["default"])({
slots: ['bottomComponents']
}, MediaControlsDecoratorHOC);
});
var handleCancel = function handleCancel(ev, _ref9) {
var onClose = _ref9.onClose;
if (onClose) {
onClose(ev);
}
};
/**
* A set of components for controlling media playback and rendering additional components.
*
* This uses {@link ui/Slottable|Slottable} to accept the custom tags, `<bottomComponents>`
* to add components to the bottom of the media controls. Any additional children will be
* rendered into the "more" controls area. Showing the additional components is handled by
* `MediaControls` when the user navigates down from the media buttons.
*
* @class MediaControls
* @memberof sandstone/MediaPlayer
* @mixes ui/Cancelable.Cancelable
* @mixes sandstone/Skinnable.Skinnable
* @ui
* @public
*/
var MediaControls = exports.MediaControls = (0, _ApiDecorator["default"])({
api: ['areMoreComponentsAvailable', 'showMoreComponents', 'hideMoreComponents']
}, MediaControlsDecorator((0, _Cancelable["default"])({
modal: true,
onCancel: handleCancel
}, (0, _Skinnable["default"])(MediaControlsBase))));
MediaControls.defaultSlot = 'mediaControlsComponent';
var _default = exports["default"] = MediaControls;