@onesy/ui-react
Version: 
UI for React
835 lines (827 loc) • 33 kB
JavaScript
import _extends from "@babel/runtime/helpers/extends";
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
const _excluded = ["name", "src", "meta", "versions", "thumbnails", "mime", "duration", "tonal", "color", "size", "start", "end", "startControls", "endControls", "startButtons", "endButtons", "startButtonsEnd", "endButtonsEnd", "forward", "backward", "settings", "quality", "playbackSpeed", "pictureInPicture", "fullScreen", "startMediaSessionOnPlay", "disabled", "IconPlay", "IconPause", "IconForward", "IconBackward", "IconVolume", "IconVolumeMuted", "IconBack", "IconSettings", "IconQuality", "IconPlaybackSpeed", "IconPictureInPicture", "IconFullScreen", "IconFullScreenExit", "PlayButtonProps", "ForwardButtonProps", "BackwardButtonProps", "VolumeButtonProps", "IconButtonProps", "TypeProps", "TimelineProps", "VolumeProps", "SliderProps", "SettingsButtonProps", "SettingsMenuProps", "QualityButtonProps", "PictureInPictureButtonProps", "FullScreenButtonProps", "className", "Component"];
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; }
import React from 'react';
import { clamp, getLeadingZerosNumber, is, isEnvironment } from '@onesy/utils';
import { classNames, style as styleMethod, useOnesyTheme } from '@onesy/style-react';
import { OnesyDate, duration as durationMethod } from '@onesy/date';
import IconMaterialPlayArrow from '@onesy/icons-material-rounded-react/IconMaterialPlayArrowW100';
import IconMaterialPause from '@onesy/icons-material-rounded-react/IconMaterialPauseW100';
import IconMaterialForwardMedia from '@onesy/icons-material-rounded-react/IconMaterialForwardMediaW100';
import IconMaterialVolumeDownAlt from '@onesy/icons-material-rounded-react/IconMaterialVolumeDownAltW100';
import IconMaterialVolumeOff from '@onesy/icons-material-rounded-react/IconMaterialVolumeOffW100';
import IconMaterialFullscreen from '@onesy/icons-material-rounded-react/IconMaterialFullscreenW100';
import IconMaterialFullscreenExit from '@onesy/icons-material-rounded-react/IconMaterialFullscreenExitW100';
import IconMaterialSettings from '@onesy/icons-material-rounded-react/IconMaterialSettingsW100';
import IconMaterialTune from '@onesy/icons-material-rounded-react/IconMaterialTuneW100';
import IconMaterialSlowMotionVideo from '@onesy/icons-material-rounded-react/IconMaterialSlowMotionVideoW100';
import IconMaterialPictureInPictureAlt from '@onesy/icons-material-rounded-react/IconMaterialPictureInPictureAltW100';
import IconMaterialArrowBackIos from '@onesy/icons-material-rounded-react/IconMaterialArrowBackIosW100';
import LineElement from '../Line';
import SurfaceElement from '../Surface';
import SliderElement from '../Slider';
import IconButtonElement from '../IconButton';
import ExpandElement from '../Expand';
import TypeElement from '../Type';
import MenuElement from '../Menu';
import ListItemElement from '../ListItem';
import { staticClassName } from '../utils';
const useStyle = styleMethod(theme => ({
  root: {
    position: 'relative'
  },
  wrapper: {
    position: 'relative',
    borderRadius: 'inherit'
  },
  wrapperFullScreen: {
    height: '100vh',
    width: '100vw'
  },
  video: {
    background: 'black',
    flex: '1 1 auto',
    borderRadius: 'inherit',
    cursor: 'pointer',
    userSelect: 'none'
  },
  size_small: {
    borderRadius: theme.methods.shape.radius.value(0.5, 'px')
  },
  size_regular: {
    borderRadius: theme.methods.shape.radius.value(1.5, 'px')
  },
  size_large: {
    borderRadius: theme.methods.shape.radius.value(2, 'px')
  },
  fullScreen: {
    borderRadius: '0px'
  },
  controls: {
    position: 'absolute',
    bottom: '0px',
    left: '0px',
    width: '100%',
    borderRadius: 'inherit',
    transition: theme.methods.transitions.make('opacity'),
    '&.onesy-Surface-root': {
      background: 'linear-gradient(0deg, rgb(0, 0, 0, 0.24), transparent)'
    }
  },
  controlsHiddden: {
    opacity: 0,
    pointerEvents: 'none'
  },
  controlsFullScreen: {},
  controls_size_small: {
    padding: `${theme.methods.space.value(0.75, 'px')} ${theme.methods.space.value(1, 'px')} ${theme.methods.space.value(0.5, 'px')}`
  },
  controls_size_regular: {
    padding: `${theme.methods.space.value(1.5, 'px')} ${theme.methods.space.value(1.5, 'px')} ${theme.methods.space.value(1, 'px')}`
  },
  controls_size_large: {
    padding: `${theme.methods.space.value(2.25, 'px')} ${theme.methods.space.value(2, 'px')} ${theme.methods.space.value(1.5, 'px')}`
  },
  wrapperTimeline: {
    padding: `0 ${theme.methods.space.value(1.5, 'px')}`
  },
  timeline: {
    '&.onesy-Slider-root': {
      height: '20px !important',
      width: '100% !important',
      margin: 'unset !important',
      maxWidth: 'unset !important'
    }
  },
  volume: {
    flex: '1 1 auto',
    '&.onesy-Slider-root': {
      height: '24px !important',
      width: '100vw !important',
      maxWidth: '54px !important',
      margin: 'unset !important',
      borderRadius: '0px',
      '& .onesy-Slider-rail': {
        borderRadius: '0px'
      },
      '& .onesy-Slider-track': {
        borderRadius: '0px'
      }
    }
  },
  volumeExpand: {
    display: 'flex',
    alignItems: 'center',
    height: '100%'
  },
  time: {
    cursor: 'default',
    userSelect: 'none'
  },
  menuSettings: {
    maxHeight: 194,
    overflowY: 'auto'
  },
  endControls: {
    position: 'relative'
  },
  placeholder: {},
  bottomControls: {
    scrollbarWidth: 'none',
    overflow: 'auto hidden',
    '& > *': {
      flex: '0 0 auto'
    },
    '&::-webkit-scrollbar': {
      display: 'none'
    }
  },
  menuSettingsFullScreen: {
    '&.onesy-Modal-root': {
      position: 'fixed !important',
      transform: 'none !important',
      left: 'unset !important',
      right: '12px !important',
      bottom: '47.8906px !important'
    }
  }
}), {
  name: 'onesy-VideoPlayer'
});
const VideoPlayer = /*#__PURE__*/React.forwardRef((props_, ref) => {
  const theme = useOnesyTheme();
  const l = theme.l;
  const props = React.useMemo(() => _objectSpread(_objectSpread(_objectSpread({}, theme?.ui?.elements?.all?.props?.default), theme?.ui?.elements?.onesyVideoPlayer?.props?.default), props_), [props_]);
  const Line = React.useMemo(() => theme?.elements?.Line || LineElement, [theme]);
  const Surface = React.useMemo(() => theme?.elements?.Surface || SurfaceElement, [theme]);
  const Slider = React.useMemo(() => theme?.elements?.Slider || SliderElement, [theme]);
  const IconButton = React.useMemo(() => theme?.elements?.IconButton || IconButtonElement, [theme]);
  const Expand = React.useMemo(() => theme?.elements?.Expand || ExpandElement, [theme]);
  const Type = React.useMemo(() => theme?.elements?.Type || TypeElement, [theme]);
  const Menu = React.useMemo(() => theme?.elements?.Menu || MenuElement, [theme]);
  const ListItem = React.useMemo(() => theme?.elements?.ListItem || ListItemElement, [theme]);
  const {
      name,
      src,
      meta,
      versions,
      thumbnails,
      mime,
      duration: duration_,
      tonal = true,
      color,
      size = 'regular',
      start,
      end,
      startControls,
      endControls,
      startButtons,
      endButtons,
      startButtonsEnd,
      endButtonsEnd,
      forward,
      backward,
      settings = true,
      quality: quality_ = true,
      playbackSpeed: playbackSpeed_ = true,
      pictureInPicture: pictureInPicture_ = true,
      fullScreen: fullScreen_ = true,
      startMediaSessionOnPlay,
      disabled,
      IconPlay = IconMaterialPlayArrow,
      IconPause = IconMaterialPause,
      IconForward = IconMaterialForwardMedia,
      IconBackward = IconMaterialForwardMedia,
      IconVolume = IconMaterialVolumeDownAlt,
      IconVolumeMuted = IconMaterialVolumeOff,
      IconBack = IconMaterialArrowBackIos,
      IconSettings = IconMaterialSettings,
      IconQuality = IconMaterialTune,
      IconPlaybackSpeed = IconMaterialSlowMotionVideo,
      IconPictureInPicture = IconMaterialPictureInPictureAlt,
      IconFullScreen = IconMaterialFullscreen,
      IconFullScreenExit = IconMaterialFullscreenExit,
      PlayButtonProps,
      ForwardButtonProps,
      BackwardButtonProps,
      VolumeButtonProps,
      IconButtonProps,
      TypeProps,
      TimelineProps,
      VolumeProps,
      SliderProps,
      SettingsButtonProps,
      SettingsMenuProps,
      QualityButtonProps,
      PictureInPictureButtonProps,
      FullScreenButtonProps,
      className,
      Component
    } = props,
    other = _objectWithoutProperties(props, _excluded);
  const {
    classes
  } = useStyle();
  const [loaded, setLoaded] = React.useState(false);
  const [duration, setDuration] = React.useState(is('number', meta?.duration) ? meta.duration : undefined);
  const [time, setTime] = React.useState(0);
  const [play, setPlay] = React.useState(false);
  const [muted, setMuted] = React.useState(false);
  const [volume, setVolume] = React.useState(1);
  const [volumeVisible, setVolumeVisible] = React.useState(false);
  const [updating, setUpdating] = React.useState(false);
  const [mouseMoved, setMouseMoved] = React.useState();
  const [quality, setQuality] = React.useState();
  const [posterShow, setPosterShow] = React.useState(true);
  const [pictureInPicture, setPictureInPicture] = React.useState(false);
  const [fullScreen, setFullScreen] = React.useState(false);
  const [playbackSpeed, setPlaybackSpeed] = React.useState(1);
  const [openMenu, setOpenMenu] = React.useState();
  const refs = {
    root: React.useRef(null),
    video: React.useRef(null),
    controls: React.useRef(null),
    duration: React.useRef(null),
    time: React.useRef(null),
    play: React.useRef(null),
    updating: React.useRef(null),
    onPlay: React.useRef(null),
    onPause: React.useRef(null),
    onTimeChange: React.useRef(null),
    onBackward: React.useRef(null),
    onForward: React.useRef(null),
    onStop: React.useRef(null),
    startMediaSession: React.useRef(null),
    updateMediaSession: React.useRef(null),
    startMediaSessionOnPlay: React.useRef(null),
    fullScreen: React.useRef(fullScreen),
    mouseMoved: React.useRef(mouseMoved),
    timeoutMouseMoved: React.useRef(null)
  };
  refs.duration.current = duration;
  refs.time.current = time;
  refs.play.current = play;
  refs.updating.current = updating;
  refs.startMediaSessionOnPlay.current = startMediaSessionOnPlay;
  refs.fullScreen.current = fullScreen;
  refs.mouseMoved.current = mouseMoved;
  const allowedPictureInPicture = () => {
    if (isEnvironment('browser')) {
      const rootDocument = refs.root.current?.ownerDocument || window.document;
      return rootDocument.pictureInPictureEnabled;
    }
  };
  const startMediaSession = React.useCallback(() => {
    if ('mediaSession' in navigator) {
      window.navigator.mediaSession.metadata = new MediaMetadata({
        title: name
      });
      const methods = [{
        name: 'play',
        method: refs.onPlay.current
      }, {
        name: 'pause',
        method: refs.onPause.current
      }, {
        name: 'previoustrack',
        method: () => {}
      }, {
        name: 'nexttrack',
        method: () => {}
      }, {
        name: 'seekbackward',
        method: refs.onBackward.current
      }, {
        name: 'seekforward',
        method: refs.onForward.current
      }, {
        name: 'seekto',
        method: details => refs.onTimeChange.current(details.seekTime)
      }, {
        name: 'stop',
        method: refs.onStop.current
      }];
      for (const method of methods) {
        try {
          window.navigator.mediaSession.setActionHandler(method.name, method.method);
        } catch (error) {
          console.log(`MediaSession action ${method.name}, is not supported`);
        }
      }
    }
  }, [name]);
  const updateMediaSession = React.useCallback(() => {
    if ('mediaSession' in navigator) {
      window.navigator.mediaSession.setPositionState({
        duration: refs.duration.current,
        playbackRate: 1,
        position: clamp(refs.time.current, 0, refs.duration.current)
      });
    }
  }, [name]);
  refs.startMediaSession.current = startMediaSession;
  refs.updateMediaSession.current = updateMediaSession;
  const durationTime = duration_ || meta?.duration;
  const onVolumeChange = React.useCallback(value => {
    setVolume(value);
    refs.video.current.volume = value;
  }, []);
  const onTimeChange = React.useCallback(value => {
    setTime(value);
    refs.video.current.currentTime = value;
    // update MediaSession
    refs.updateMediaSession.current();
  }, []);
  const onPlaybackSpeed = React.useCallback(value_ => {
    const value = clamp(value_, 0, 2);
    setPlaybackSpeed(value);
    setOpenMenu(null);
    refs.video.current.playbackRate = value;
  }, []);
  const onForward = React.useCallback(details => {
    const part = refs.duration.current * 0.1;
    const toMove = clamp(details?.seekOffset || part, 1, refs.duration.current);
    const value = clamp(refs.time.current + toMove, 0, refs.duration.current);
    refs.onTimeChange.current(value);
  }, []);
  const onBackward = React.useCallback(details => {
    const part = refs.duration.current * 0.1;
    const toMove = clamp(details?.seekOffset || part, 1, refs.duration.current);
    const value = clamp(refs.time.current - toMove, 0, refs.duration.current);
    refs.onTimeChange.current(value);
  }, []);
  const onPlay = React.useCallback(() => {
    try {
      setPlay(true);
      refs.video.current.play();
      // start MediaSession
      if (refs.startMediaSessionOnPlay.current) refs.startMediaSession.current();
      // update MediaSession
      refs.updateMediaSession.current();
    } catch (error) {
      console.error(`videoPlayer`, error);
    }
  }, []);
  const onPause = React.useCallback(() => {
    setPlay(false);
    refs.video.current.pause();
  }, []);
  const onStop = React.useCallback(() => {
    setPlay(false);
    refs.video.current.pause();
    refs.video.current.currentTime = 0;
  }, []);
  const onMute = React.useCallback(() => {
    setMuted(true);
    refs.video.current.muted = true;
  }, []);
  const onUnmute = React.useCallback(() => {
    setMuted(false);
    refs.video.current.muted = false;
  }, []);
  refs.onPlay.current = onPlay;
  refs.onPause.current = onPause;
  refs.onTimeChange.current = onTimeChange;
  refs.onForward.current = onForward;
  refs.onBackward.current = onBackward;
  refs.onStop.current = onStop;
  const init = React.useCallback(() => {
    setLoaded(false);
    const video = refs.video.current;
    video.addEventListener('loadedmetadata', () => {
      const value = video.duration;
      if (!is('number', durationTime) && is('number', value)) {
        if (refs.duration.current === undefined) setDuration(value);
        setLoaded(true);
      }
    });
    video.addEventListener('ended', () => {
      refs.onStop.current();
    });
    video.addEventListener('timeupdate', () => {
      const value = video.currentTime;
      if (!refs.updating.current && refs.time.current !== value) {
        setTime(value);
        // update MediaSession
        refs.updateMediaSession.current();
      }
    });
    video.addEventListener('ratechange', () => {
      const value = video.playbackRate;
      setPlaybackSpeed(value);
    });
    // start MediaSession
    startMediaSession();
    if (is('number', durationTime)) {
      if (refs.duration.current === undefined) setDuration(durationTime);
      setLoaded(true);
    }
    const rootDocument = isEnvironment('browser') ? refs.root.current?.ownerDocument || window.document : undefined;
    const methodPictureInPicture = () => {
      if (rootDocument.pictureInPictureElement) {
        setPictureInPicture(true);
      } else {
        setPictureInPicture(false);
      }
    };
    const methodFullScreen = () => {
      if (rootDocument.fullscreenElement) {
        setFullScreen(true);
      } else {
        setFullScreen(false);
      }
    };
    const methodMouseMove = () => {
      if (refs.play.current) {
        clearTimeout(refs.timeoutMouseMoved.current);
        setMouseMoved({
          moved: true,
          unix: OnesyDate.unix
        });
        refs.timeoutMouseMoved.current = setTimeout(() => {
          setMouseMoved({
            moved: false,
            unix: OnesyDate.unix
          });
        }, 4000);
      }
    };
    refs.root.current?.addEventListener('mousemove', methodMouseMove);
    refs.root.current?.addEventListener('touchstart', methodMouseMove);
    refs.root.current?.addEventListener('touchmove', methodMouseMove);
    rootDocument.addEventListener('enterpictureinpicture', methodPictureInPicture);
    rootDocument.addEventListener('leavepictureinpicture', methodPictureInPicture);
    rootDocument.addEventListener('fullscreenchange', methodFullScreen);
    video.src = src;
    return () => {
      refs.root.current?.removeEventListener('mousemove', methodMouseMove);
      refs.root.current?.removeEventListener('touchstart', methodMouseMove);
      refs.root.current?.removeEventListener('touchmove', methodMouseMove);
      rootDocument.removeEventListener('enterpictureinpicture', methodPictureInPicture);
      rootDocument.removeEventListener('leavepictureinpicture', methodPictureInPicture);
      rootDocument.removeEventListener('fullscreenchange', methodFullScreen);
    };
  }, [src, durationTime, startMediaSession]);
  React.useEffect(() => {
    if (loaded) {
      let urlNew = src;
      if (quality) {
        if (quality?.meta?.resolution) urlNew += `?version=${quality?.meta?.resolution}`;
      }
      const currentTime = refs.video.current.currentTime;
      const playbackRate = refs.video.current.playbackRate;
      const playing = refs.play.current;
      // pause
      if (playing) refs.onPause.current();
      // poster remove
      setPosterShow(false);
      refs.video.current.poster = '';
      refs.video.current.src = urlNew;
      refs.video.current.load();
      refs.video.current.currentTime = currentTime;
      refs.video.current.playbackRate = playbackRate;
      // play
      if (playing) refs.onPlay.current();
    }
  }, [quality]);
  const onMouseEnter = React.useCallback(() => {
    setVolumeVisible(true);
  }, []);
  const onMouseLeave = React.useCallback(() => {
    setVolumeVisible(false);
  }, []);
  const onUpdating = React.useCallback(() => {
    setUpdating(refs.play.current ? 'play' : true);
    if (refs.play.current) onPause();
  }, [onPause]);
  const onUpdatingDone = React.useCallback(() => {
    const updatingPrevious = refs.updating.current;
    setUpdating(false);
    if (updatingPrevious === 'play') onPlay();
  }, [onPlay]);
  const onFullScreen = React.useCallback(async () => {
    const root = refs.root.current;
    try {
      if (root.requestFullscreen) await root.requestFullscreen();else if (root.webkitRequestFullscreen) await root.webkitRequestFullscreen();else if (root.msRequestFullscreen) await root.msRequestFullscreen();
    } catch (error) {}
  }, []);
  const onFullScreenExit = React.useCallback(async () => {
    const rootDocument = isEnvironment('browser') ? refs.root.current?.ownerDocument || window.document : undefined;
    try {
      if (rootDocument.exitFullscreen) await rootDocument.exitFullscreen();else if (rootDocument.webkitExitFullscreen) await rootDocument.webkitExitFullscreen();else if (rootDocument.msExitFullscreen) await rootDocument.msExitFullscreen();
    } catch (error) {}
  }, []);
  const onPictureInPicture = React.useCallback(async () => {
    const video = refs.video.current;
    try {
      if (video.requestPictureInPicture) await video.requestPictureInPicture();else if (video.webkitRequestPictureInPicture) await video.webkitRequestPictureInPicture();else if (video.msRequestPictureInPicture) await video.msRequestPictureInPicture();
    } catch (error) {}
  }, []);
  const onPictureInPictureExit = React.useCallback(async () => {
    const rootDocument = isEnvironment('browser') ? refs.root.current?.ownerDocument || window.document : undefined;
    try {
      if (rootDocument.exitPictureInPicture) await rootDocument.exitPictureInPicture();else if (rootDocument.webkitExitPictureInPicture) await rootDocument.webkitExitPictureInPicture();else if (rootDocument.msExitPictureInPicture) await rootDocument.msExitPictureInPicture();
    } catch (error) {}
  }, []);
  const onVideoClick = React.useCallback(event => {
    if (event.detail === 1) {
      !play ? onPlay() : onPause();
    }
    if (event.detail === 2) {
      !fullScreen ? onFullScreen() : onFullScreenExit();
    }
  }, [play, fullScreen, onPlay, onPause, onFullScreen, onFullScreenExit]);
  React.useEffect(() => {
    const rootDocument = isEnvironment('browser') ? refs.root.current?.ownerDocument || window.document : undefined;
    rootDocument.addEventListener('mouseup', onUpdatingDone);
    rootDocument.addEventListener('touchend', onUpdatingDone);
    return () => {
      rootDocument.removeEventListener('mouseup', onUpdatingDone);
      rootDocument.removeEventListener('touchend', onUpdatingDone);
    };
  }, []);
  React.useEffect(() => {
    // init
    init();
  }, [src]);
  const durationToValue = item => {
    let value = '';
    const separator = ':';
    if (item.hour) value += `${getLeadingZerosNumber(item.hour, {
      leadingZeros: 0
    })}`;
    if (item.minute) {
      if (value) value += separator;
      value += `${getLeadingZerosNumber(item.minute, {
        leadingZeros: 0
      })}`;
    } else {
      if (value) value += separator;
      value += '0';
    }
    if (item.second) {
      if (value) value += separator;
      value += `${getLeadingZerosNumber(item.second, {
        leadingZeros: 1
      })}`;
    } else {
      if (value) value += separator;
      value += '00';
    }
    return value;
  };
  const onQuality = React.useCallback(version => {
    setQuality(version);
    setOpenMenu(null);
  }, []);
  const onSettingsMenuClose = React.useCallback(() => {
    setOpenMenu(null);
  }, []);
  const getSettingsMenuItems = () => {
    const itemProps = {
      button: true,
      startAlign: 'center',
      endAlign: 'center',
      size: 'small',
      className: 'onesy-videoPlayer-option'
    };
    const items = [];
    if (openMenu) {
      items.push(/*#__PURE__*/React.createElement(ListItem, _extends({
        key: "back",
        start: /*#__PURE__*/React.createElement(IconBack, {
          size: "very small"
        }),
        primary: /*#__PURE__*/React.createElement(Type, {
          version: "b3"
        }, l('Back')),
        onClick: () => setOpenMenu(null)
      }, itemProps)));
    }
    if (!openMenu) {
      if (playbackSpeed_) items.push(/*#__PURE__*/React.createElement(ListItem, _extends({
        key: "playbackSpeed",
        start: /*#__PURE__*/React.createElement(IconPlaybackSpeed, {
          size: "small"
        }),
        primary: /*#__PURE__*/React.createElement(Type, {
          version: "b3"
        }, l('Playback speed')),
        end: /*#__PURE__*/React.createElement(Type, {
          version: "b3",
          priority: "secondary"
        }, playbackSpeed === 1 ? l('Normal') : playbackSpeed),
        onClick: () => setOpenMenu('playbackSpeed')
      }, itemProps)));
      if (quality_) items.push(/*#__PURE__*/React.createElement(ListItem, _extends({
        key: "quality",
        start: /*#__PURE__*/React.createElement(IconQuality, {
          size: "small"
        }),
        primary: /*#__PURE__*/React.createElement(Type, {
          version: "b3"
        }, l('Quality')),
        end: /*#__PURE__*/React.createElement(Type, {
          version: "b3",
          priority: "secondary"
        }, !quality ? l('Original') : `${quality?.meta?.resolution}p`),
        onClick: () => setOpenMenu('quality')
      }, itemProps)));
    } else if (openMenu === 'quality') {
      items.push(/*#__PURE__*/React.createElement(ListItem, _extends({
        key: "original",
        primary: /*#__PURE__*/React.createElement(Type, {
          version: "b3"
        }, `${meta?.resolution}p (original)`),
        onClick: () => quality ? onQuality(null) : undefined,
        selected: !quality
      }, itemProps)));
      versions?.forEach((version, index) => {
        const isSelected = quality?.id === version?.id;
        items.push(/*#__PURE__*/React.createElement(ListItem, _extends({
          key: index,
          primary: /*#__PURE__*/React.createElement(Type, {
            version: "b3"
          }, version?.meta?.resolution, "p"),
          onClick: () => !isSelected ? onQuality(version) : undefined,
          selected: isSelected
        }, itemProps)));
      });
    } else if (openMenu === 'playbackSpeed') {
      const options = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2];
      options.forEach(option => {
        items.push(/*#__PURE__*/React.createElement(ListItem, _extends({
          key: option,
          primary: /*#__PURE__*/React.createElement(Type, {
            version: "b3"
          }, option === 1 ? l('Normal') : option),
          onClick: () => onPlaybackSpeed(option),
          selected: playbackSpeed === option
        }, itemProps)));
      });
    }
    return items;
  };
  const thumbnailsToUse = thumbnails || quality?.thumbnails;
  const thumbnail = thumbnailsToUse ? 1 : undefined;
  const typeProps = _objectSpread({
    version: size === 'large' ? 'b1' : size === 'regular' ? 'b2' : 'b3'
  }, TypeProps);
  const iconButtonProps = _objectSpread({
    version: 'text',
    size,
    disabled
  }, IconButtonProps);
  const sliderProps = _objectSpread({
    color,
    size,
    disabled
  }, SliderProps);
  let url = src;
  let poster;
  if (quality) {
    if (quality?.meta?.resolution) url += `?version=${quality?.meta?.resolution}`;
  }
  if (is('number', thumbnail)) {
    poster = `${url}${url?.includes('?') ? '&' : '?'}thumbnail=${thumbnail}`;
  }
  return /*#__PURE__*/React.createElement(Line, _extends({
    ref: item => {
      if (ref) {
        if (is('function', ref)) ref(item);else ref.current = item;
      }
      refs.root.current = item;
    },
    gap: 1,
    direction: "column",
    align: "unset",
    justify: "unset",
    fullWidth: true,
    Component: Component,
    className: classNames([staticClassName('VideoPlayer', theme) && [`onesy-VideoPlayer-root`, `onesy-VideoPlayer-size-${size}`, fullScreen && `onesy-VideoPlayer-full-screen`], className, classes.root, classes[`size_${size}`], fullScreen && classes.fullScreen])
  }, other), /*#__PURE__*/React.createElement(Line, {
    gap: 0,
    direction: "column",
    align: "unset",
    justify: "unset",
    fullWidth: true,
    className: classNames([classes.wrapper, fullScreen && classes.wrapperFullScreen])
  }, start, /*#__PURE__*/React.createElement("video", {
    ref: refs.video,
    onClick: onVideoClick,
    poster: posterShow ? poster : undefined,
    controls: false,
    className: classNames([classes.video, fullScreen && classes.videoFullScreen])
  }, /*#__PURE__*/React.createElement("source", {
    src: url,
    type: mime
  })), /*#__PURE__*/React.createElement(Surface, {
    ref: refs.controls,
    gap: 0,
    fullWidth: true,
    tonal: tonal,
    color: color !== undefined ? color : theme.palette.light ? 'inverted' : 'default',
    Component: Line,
    className: classNames([classes.controls, classes[`controls_size_${size}`], fullScreen && classes.controlsFullScreen, !mouseMoved?.moved && play && classes.controlsHiddden])
  }, startControls, /*#__PURE__*/React.createElement(Line, {
    fullWidth: true,
    className: classes.wrapperTimeline
  }, /*#__PURE__*/React.createElement(Slider, _extends({
    value: time,
    onChange: onTimeChange,
    min: 0,
    max: duration,
    onMouseDown: onUpdating,
    onTouchStart: onUpdating,
    onMouseUp: onUpdatingDone,
    onToucheEnd: onUpdatingDone
  }, sliderProps, TimelineProps, {
    className: classNames([sliderProps?.className, TimelineProps?.className, classes.timeline])
  }))), /*#__PURE__*/React.createElement(Line, {
    direction: "row",
    align: "center",
    fullWidth: true,
    onMouseLeave: onMouseLeave,
    className: classes.bottomControls,
    style: {
      color: theme.palette.color[color] ? theme.palette.color[color][90] : theme.palette.color.neutral[90]
    }
  }, startButtons, /*#__PURE__*/React.createElement(Line, {
    gap: 1,
    direction: "row",
    align: "center",
    justify: "space-between",
    flexNo: true,
    fullWidth: true
  }, /*#__PURE__*/React.createElement(Line, {
    gap: 1.5,
    direction: "row",
    align: "center",
    flexNo: true
  }, /*#__PURE__*/React.createElement(Line, {
    gap: 0,
    direction: "row",
    align: "center"
  }, /*#__PURE__*/React.createElement(IconButton, _extends({
    onClick: play ? onPause : onPlay
  }, iconButtonProps, PlayButtonProps), play ? /*#__PURE__*/React.createElement(IconPause, null) : /*#__PURE__*/React.createElement(IconPlay, null)), backward && /*#__PURE__*/React.createElement(IconButton, _extends({
    onClick: onBackward
  }, iconButtonProps, BackwardButtonProps), /*#__PURE__*/React.createElement(IconBackward, {
    style: {
      transform: 'rotateY(180deg)'
    }
  })), forward && /*#__PURE__*/React.createElement(IconButton, _extends({
    onClick: onForward
  }, iconButtonProps, ForwardButtonProps), /*#__PURE__*/React.createElement(IconForward, null)), /*#__PURE__*/React.createElement(IconButton, _extends({
    onClick: muted ? onUnmute : onMute,
    onMouseEnter: onMouseEnter
  }, iconButtonProps, VolumeButtonProps), !muted ? /*#__PURE__*/React.createElement(IconVolume, null) : /*#__PURE__*/React.createElement(IconVolumeMuted, null)), /*#__PURE__*/React.createElement(Expand, {
    in: volumeVisible,
    parent: refs.controls.current,
    orientation: "horizontal",
    className: classes.volumeExpand
  }, /*#__PURE__*/React.createElement(Slider, _extends({
    value: volume,
    onChange: onVolumeChange,
    min: 0,
    max: 1,
    orientation: "horizontal"
  }, sliderProps, {
    size: ['small', 'regular'].includes(size) ? 'small' : 'regular'
  }, VolumeProps, {
    className: classNames([sliderProps?.className, VolumeProps?.className, classes.volume])
  })))), /*#__PURE__*/React.createElement(Line, {
    gap: 0.5,
    direction: "row",
    align: "center",
    flexNo: true,
    className: classNames(['onesy-Audio-time', classes.time])
  }, /*#__PURE__*/React.createElement(Type, typeProps, durationToValue(durationMethod(time * 1000, false, true))), /*#__PURE__*/React.createElement(Type, typeProps, "/"), /*#__PURE__*/React.createElement(Type, typeProps, durationToValue(durationMethod(duration * 1000, false, true))))), /*#__PURE__*/React.createElement(Line, {
    gap: 0.5,
    direction: "row",
    align: "center",
    className: classes.endControls
  }, startButtonsEnd, settings && /*#__PURE__*/React.createElement(Menu, _extends({
    menuItems: getSettingsMenuItems(),
    position: "top",
    switch: false,
    portal: !fullScreen,
    onClose: onSettingsMenuClose,
    includeParentQueries: ['.onesy-videoPlayer']
  }, SettingsMenuProps, {
    ListProps: {
      className: classNames([SettingsMenuProps?.ListProps?.className, classes.menuSettings]),
      size: 'small'
    },
    className: classNames(['onesy-videoPlayer', SettingsMenuProps?.className, fullScreen && classes.menuSettingsFullScreen])
  }), /*#__PURE__*/React.createElement(IconButton, _extends({}, iconButtonProps, SettingsButtonProps), /*#__PURE__*/React.createElement(IconSettings, null))), pictureInPicture_ && allowedPictureInPicture() && /*#__PURE__*/React.createElement(IconButton, _extends({
    onClick: !pictureInPicture ? onPictureInPicture : onPictureInPictureExit
  }, iconButtonProps, PictureInPictureButtonProps), /*#__PURE__*/React.createElement(IconPictureInPicture, null)), fullScreen_ && /*#__PURE__*/React.createElement(IconButton, _extends({
    onClick: !fullScreen ? onFullScreen : onFullScreenExit
  }, iconButtonProps, FullScreenButtonProps), fullScreen ? /*#__PURE__*/React.createElement(IconFullScreenExit, null) : /*#__PURE__*/React.createElement(IconFullScreen, null)), endButtonsEnd)), endButtons), endControls), end));
});
VideoPlayer.displayName = 'onesy-VideoPlayer';
export default VideoPlayer;