import * as React from 'react' ; import RangeSlider , { RangeSliderPosition } from '@gilbarbara/react-range-slider' ; import ClickOutside from './ClickOutside' ; import VolumeHigh from './icons/VolumeHigh' ; import VolumeLow from './icons/VolumeLow' ; import VolumeMute from './icons/VolumeMute' ; import { px , styled } from '../styles' ; import { StyledProps , StylesOptions } from '../types/common' ; interface Props { playerPosition : string ; setVolume : ( volume : number ) => any ; styles : StylesOptions ; title : string ; volume : number ; } interface State { isOpen : boolean ; volume : number ; } const Wrapper = styled ( 'div' ) ( { 'pointer-events' : 'all' , position : 'relative' , zIndex : 20 , '> div' : { display : 'flex' , flexDirection : 'column' , padding : px ( 12 ) , position : 'absolute' , right : `-${ px ( 3 ) }` , } , '> button' : { fontSize : px ( 26 ) , } , '@media (max-width: 1023px)' : { display : 'none' , } , } , ( { style } ) => ( { '> button' : { color : style . c , } , '> div' : { backgroundColor : style . bgColor , boxShadow : style . altColor ? `1px 1px 10px ${ style . altColor }` : 'none' , [ style . p ] : '120%' , } , } ) , 'VolumeRSWP' ) ; export default class Volume extends React . PureComponent < Props , State > { private timeout : number | undefined ; constructor ( props ) { super ( props ) ; this . state = { isOpen : false , volume : props . volume , } ; } public componentDidUpdate ( previousProps ) { const { volume : volumeState } = this . state ; const { volume } = this . props ; if ( previousProps . volume !== volume && volume !== volumeState ) { this . setState ( { volume } ) ; } } private handleClick = ( ) => { this . setState ( state => ( { isOpen : ! state . isOpen } ) ) ; } ; private handleChangeSlider = ( { y } ) => { const { setVolume } = this . props ; const volume = Math . round ( y ) / 100 ; clearTimeout ( this . timeout ) ; this . timeout = window . setTimeout ( ( ) => { setVolume ( volume ) ; } , 250 ) ; this . setState ( { volume } ) ; } ; private handleAfterEnd = ( ) => { setTimeout ( ( ) => { this . setState ( { isOpen : false } ) ; } , 100 ) ; } ; public render ( ) { const { isOpen , volume } = this . state ; const { playerPosition , styles : { altColor , bgColor , color } , title , } = this . props ; let icon = < VolumeHigh />; if ( volume === 0 ) { icon = < VolumeMute />; } else if ( volume <= 0.5 ) { icon = < VolumeLow />; } return ( < Wrapper style = { { altColor , bgColor , c : color , p : playerPosition } } > { isOpen && ( < ClickOutside onClick = { this . handleClick } > < RangeSlider axis = "y" className = "rrs" onAfterEnd = { this . handleAfterEnd } onChange = { this . handleChangeSlider } styles = { { options : { thumbBorder : `2px solid ${ color }` , thumbBorderRadius : 12 , thumbColor : bgColor , thumbSize : 12 , padding : 0 , rangeColor : altColor || '#ccc' , trackColor : color , width : 6 , } , } } y = { volume * 100 } yMax = { 100 } yMin = { 0 } / > < /ClickOutside>)} < button aria - label = { title } onClick = { ! isOpen ? this . handleClick : undefined } title = { title } type = "button" > { icon } < /button> < /Wrapper>); } }