UNPKG

organism-react-video

Version:
327 lines (316 loc) 10.8 kB
"use strict"; var _interopRequireDefault = require("reshow-runtime/helpers/interopRequireDefault"); var _interopRequireWildcard = require("reshow-runtime/helpers/interopRequireWildcard"); exports.__esModule = true; exports["default"] = void 0; var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("reshow-runtime/helpers/objectWithoutPropertiesLoose")); var _createClass2 = _interopRequireDefault(require("reshow-runtime/helpers/createClass")); var _classCallCheck2 = _interopRequireDefault(require("reshow-runtime/helpers/classCallCheck")); var _defineProperty2 = _interopRequireDefault(require("reshow-runtime/helpers/defineProperty")); var _objectSpread2 = _interopRequireDefault(require("reshow-runtime/helpers/objectSpread2")); var React = _interopRequireWildcard(require("react")); var _organismReactIframe = require("organism-react-iframe"); var _winDoc = require("win-doc"); var _reshowConstant = require("reshow-constant"); var _reshowHooks = require("reshow-hooks"); var _callFunc = _interopRequireDefault(require("call-func")); var _getRandomId = require("get-random-id"); var _ResponsiveVideo = _interopRequireDefault(require("../organisms/ResponsiveVideo.js")); var _jsxRuntime = require("react/jsx-runtime"); var _excluded = ["videoId", "videoParams", "hostname", "onStateChange", "onClick", "onLoad"], _excluded2 = ["loading", "onError"]; // @ts-check var useEffect = React.useEffect, useImperativeHandle = React.useImperativeHandle, forwardRef = React.forwardRef, useRef = React.useRef, useState = React.useState; /** * Iframe api * https://www.youtube.com/iframe_api * https://www.youtube.com/s/player/eff63141/www-widgetapi.vflset/www-widgetapi.js * * Play State * https://developers.google.com/youtube/iframe_api_reference#Playback_status */ /** * @typedef {import('organism-react-iframe').IframeContainerExpose} IframeContainerExpose */ /** * @param {string} func * @param {any[]=} args * @param {string=} id * @returns {string} */ var message = function message(func, args, id) { return JSON.stringify({ event: "command", id: id, func: func, args: args }); }; var defaultVideoParams = { autoplay: 1, loop: 1, showinfo: 0, controls: 0, rel: 0, mute: 1, modestbranding: 1, iv_load_policy: 3, enablejsapi: 1 }; /** * @typedef {import("../organisms/ResponsiveVideo").ResponsiveVideoProps} ResponsiveVideoProps */ /** * @typedef {object} YoutubeRWDExtendsProps * @property {"eager"|"lazy"} [loading] * @property {string} [videoId] * @property {{[key: string]: any}} [videoParams] * @property {string|boolean} [hostname] * @property {boolean} [disable] * @property {string} [id] * @property {Function} [onStateChange] * @property {Function} [onLoad] * @property {Function} [onError] */ /** * @typedef {ResponsiveVideoProps & YoutubeRWDExtendsProps} YoutubeRWDProps */ /** * @param {YoutubeRWDExtendsProps} props * @see https://developers.google.com/youtube/player_parameters */ var getYoutubeUrl = function getYoutubeUrl(_ref) { var videoId = _ref.videoId, videoParams = _ref.videoParams, hostname = _ref.hostname; var nextVideoParams = (0, _objectSpread2["default"])({}, videoParams); if (nextVideoParams["enablejsapi"] && hostname) { nextVideoParams["origin"] = hostname; } if (nextVideoParams["loop"]) { nextVideoParams.playlist = videoId; } var aParams = []; (0, _reshowConstant.KEYS)(nextVideoParams).forEach(function (key) { return aParams.push(key + "=" + encodeURIComponent(nextVideoParams[key])); }); var src = "https://www.youtube.com/embed/" + videoId + "?" + aParams.join("&"); return src; }; /** * @interface */ var PlayerState = /*#__PURE__*/(0, _createClass2["default"])(function PlayerState() { (0, _classCallCheck2["default"])(this, PlayerState); /** * @type number */ (0, _defineProperty2["default"])(this, "state", void 0); /** * @type boolean */ (0, _defineProperty2["default"])(this, "isPlaying", void 0); }); /** * @typedef {object} YoutubeRWDExpose * @property {Function} restart * @property {Function} pause * @property {function():PlayerState} togglePlayback * @property {function(string):void} postMessage * @property {ExecPost} exec * @property {function():HTMLIFrameElement|undefined} getIframe * @property {function():PlayerState} getPlayerState */ /** * @callback ExecPost * @param {string} cmd * @param {any[]=} args */ /** * @param {YoutubeRWDProps} props */ var useYoutubeRWD = function useYoutubeRWD(props) { var lastProps = (0, _reshowHooks.useRefUpdate)(props); var _lastProps$current = lastProps.current, videoId = _lastProps$current.videoId, videoParams = _lastProps$current.videoParams, propsHostname = _lastProps$current.hostname, onStateChange = _lastProps$current.onStateChange, onClick = _lastProps$current.onClick, onLoad = _lastProps$current.onLoad, restProps = (0, _objectWithoutPropertiesLoose2["default"])(_lastProps$current, _excluded); var lastPlayerState = useRef({ state: -1, isPlaying: false }); var lastMessageId = useRef(lastProps.current.id); if (null == lastMessageId.current) { lastMessageId.current = (0, _getRandomId.getSN)("youtube-widget"); } var thisVideoParams = (0, _reshowHooks.useRefUpdate)((0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, defaultVideoParams), videoParams)); var lastHostname = /**@type React.RefObject<string|boolean|undefined>*/ useRef(undefined); var lastIframe = /**@type {React.RefObject<IframeContainerExpose|null>}*/ useRef(null); var _useState = useState({ load: false }), state = _useState[0], setState = _useState[1]; useEffect(function () { var loc = (0, _winDoc.doc)().location; var strLoc = loc.protocol + "//" + loc.hostname; if (loc.port) { strLoc += ":" + loc.port; } lastHostname.current = null == propsHostname ? strLoc : propsHostname; setState({ load: true }); var gWin = (0, _winDoc.win)(); gWin.addEventListener("message", handler.message); return function () { gWin.removeEventListener("message", handler.message); }; }, []); /** * @type {YoutubeRWDExpose} */ var expose = { restart: function restart() { expose.exec("playVideo"); }, pause: function pause() { expose.exec("pauseVideo"); }, togglePlayback: function togglePlayback() { if (lastPlayerState.current.isPlaying) { expose.pause(); } else { expose.restart(); } return lastPlayerState.current; }, postMessage: function postMessage(message) { var _lastIframe$current; var iframe = (_lastIframe$current = lastIframe.current) === null || _lastIframe$current === void 0 ? void 0 : _lastIframe$current.getEl(); if (iframe) { var _iframe$contentWindow; var origin = /**@type string*/ lastHostname.current ? lastHostname.current : "*"; return (_iframe$contentWindow = iframe.contentWindow) === null || _iframe$contentWindow === void 0 ? void 0 : _iframe$contentWindow.window.postMessage(message, origin); } }, exec: function exec(cmd, args) { var cmdMessage = message(cmd, args, lastMessageId.current); return expose.postMessage(cmdMessage); }, getIframe: function getIframe() { var _lastIframe$current2; return (_lastIframe$current2 = lastIframe.current) === null || _lastIframe$current2 === void 0 ? void 0 : _lastIframe$current2.getEl(); }, getPlayerState: function getPlayerState() { return lastPlayerState.current; } }; var handler = { listening: function listening() { var message = JSON.stringify({ event: "listening", channel: "widget", id: lastMessageId.current }); expose.postMessage(message); expose.exec("addEventListener", ["onStateChange"]); }, load: function load(/**@type Event*/e) { if (thisVideoParams.current.autoplay) { expose.restart(); } handler.listening(); (0, _callFunc["default"])(lastProps.current.onLoad, [e]); }, click: function click(/**@type React.MouseEvent*/e) { (0, _callFunc["default"])(lastProps.current.onClick, [e]); }, message: function message(/**@type MessageEvent*/e) { var _data; if (null == e) { return null; } var data = e.data; if ("string" === typeof data) { try { data = JSON.parse(e.data); } catch (e) {} } if (((_data = data) === null || _data === void 0 ? void 0 : _data.id) === lastMessageId.current) { var _data2; var playerState = (_data2 = data) === null || _data2 === void 0 || (_data2 = _data2.info) === null || _data2 === void 0 ? void 0 : _data2.playerState; if (null != playerState) { var isPlaying = false; switch (playerState) { case 1: case 3: isPlaying = true; break; } lastPlayerState.current = { state: playerState, isPlaying: isPlaying }; } (0, _callFunc["default"])(lastProps.current.onStateChange, [data]); } } }; return { expose: expose, handler: handler, nextProps: restProps, lastIframe: lastIframe, state: state, src: state.load ? getYoutubeUrl({ videoId: videoId, videoParams: thisVideoParams.current, hostname: lastHostname.current }) : undefined }; }; /** * @type React.ForwardRefExoticComponent<?, YoutubeRWDProps> */ var YoutubeRWD = forwardRef(function (props, ref) { var _useYoutubeRWD = useYoutubeRWD(props), expose = _useYoutubeRWD.expose, handler = _useYoutubeRWD.handler, nextProps = _useYoutubeRWD.nextProps, lastIframe = _useYoutubeRWD.lastIframe, state = _useYoutubeRWD.state, src = _useYoutubeRWD.src; var loading = nextProps.loading, onError = nextProps.onError, restProps = (0, _objectWithoutPropertiesLoose2["default"])(nextProps, _excluded2); useImperativeHandle(ref, function () { return expose; }, []); if (!state.load) { return null; } return /*#__PURE__*/(0, _jsxRuntime.jsx)(_ResponsiveVideo["default"], (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, restProps), {}, { onClick: handler.click, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_organismReactIframe.IframeContainer, { loading: loading, allow: "autoplay; fullscreen; encrypted-media", src: src, ref: lastIframe, onLoad: handler.load, onError: onError }) })); }); var _default = exports["default"] = YoutubeRWD; module.exports = exports.default;