import React , { useRef , useEffect } from 'react' ; import { SliderProps } from '.' ; import { useFoundation , emptyClientRect } from '@rmwc/base' ; import { EventType , SpecificEventListener } from '@material/base/types' ; import { debounce } from '@rmwc/base' ; import { MDCSliderFoundation } from '@material/slider' ; export const useSliderFoundation = ( props ) => { const trackRef = useRef < HTMLElement > ( ) ; const setTrackRef = ( element ) => ( trackRef . current = element ) ; const trackmarkerContainerRef = useRef < HTMLElement > ( ) ; const setTrackMarkerContainerRef = ( element ) => ( trackmarkerContainerRef . current = element ) ; const { foundation , ... elements } = useFoundation ( { props , elements : { rootEl : true , thumbContainerEl : true , sliderPinEl : true } , foundation : ( { rootEl , thumbContainerEl , sliderPinEl , emit } ) => { return new MDCSliderFoundation ( { hasClass : ( className ) => rootEl . hasClass ( className ) , addClass : ( className ) => rootEl . addClass ( className ) , removeClass : ( className ) => rootEl . removeClass ( className ) , getAttribute : ( name ) => rootEl . getProp ( name as any ) as string | null , setAttribute : debounce ( ( name , value ) => rootEl . setProp ( name as any , value ) , 300 ) , removeAttribute : ( name ) => rootEl . removeProp ( name as any ) , computeBoundingRect : ( ) => rootEl . ref ? rootEl . ref . getBoundingClientRect ( ) : emptyClientRect , getTabIndex : ( ) => ( rootEl . ref ? rootEl . ref . tabIndex : 0 ) , registerInteractionHandler : < K extends EventType > ( evtType , handler ) : void => { rootEl . addEventListener ( evtType , handler ) ; } , deregisterInteractionHandler : < K extends EventType > ( evtType , handler ) : void => { rootEl . removeEventListener ( evtType , handler ) ; } , registerThumbContainerInteractionHandler : < K extends EventType > ( evtType , handler ) : void => { thumbContainerEl . addEventListener ( evtType , handler ) ; } , deregisterThumbContainerInteractionHandler : < K extends EventType > ( evtType , handler ) : void => { thumbContainerEl . removeEventListener ( evtType , handler ) ; } , registerBodyInteractionHandler : < K extends EventType > ( evtType , handler ) : void => { document . body && document . body . addEventListener ( evtType , handler ) ; } , deregisterBodyInteractionHandler : < K extends EventType > ( evtType , handler ) : void => { document . body && document . body . removeEventListener ( evtType , handler ) ; } , registerResizeHandler : ( handler ) : void => { window . addEventListener ( 'resize' , handler ) ; } , deregisterResizeHandler : ( handler ) : void => { window . removeEventListener ( 'resize' , handler ) ; } , notifyInput : ( ) => { emit ( 'onInput' , { value : foundation . getValue ( ) } ) ; } , notifyChange : ( ) => { emit ( 'onChange' , { value : foundation . getValue ( ) } ) ; } , setThumbContainerStyleProperty : ( propertyName , value ) => { thumbContainerEl . setStyle ( propertyName , value ) ; } , setTrackStyleProperty : ( propertyName , value ) => { trackRef . current ?. style . setProperty ( propertyName , value ) ; } , setMarkerValue : ( value ) => { sliderPinEl . setProp ( 'value' , value ) ; } , setTrackMarkers : ( step , max , min ) => { const stepStr = step . toLocaleString ( ) ; const maxStr = max . toLocaleString ( ) ; const minStr = min . toLocaleString ( ) ; const markerAmount = `((${ maxStr } - ${ minStr }) / ${ stepStr })` ; const markerWidth = `2px` ; const markerBkgdImage = `linear-gradient(to right, currentColor ${ markerWidth }, transparent 0)` ; const markerBkgdLayout = `0 center / calc((100% - ${ markerWidth }) / ${ markerAmount }) 100% repeat-x` ; const markerBkgdShorthand = `${ markerBkgdImage } ${ markerBkgdLayout }` ; trackmarkerContainerRef . current ?. style . setProperty ( 'background' , markerBkgdShorthand ) ; } , isRTL : ( ) => ! ! rootEl . ref && getComputedStyle ( rootEl . ref ) . direction === 'rtl' } ) ; } } ) ; useEffect ( ( ) => { props . max !== undefined && foundation . setMax ( + props . max ) ; } , [ props . max , foundation ] ) ; useEffect ( ( ) => { props . min !== undefined && foundation . setMin ( + props . min ) ; } , [ props . min , foundation ] ) ; useEffect ( ( ) => { let value = props . value !== undefined ? Number ( props . value ) : foundation . getValue ( ) ; const min = foundation . getMin ( ) ; const max = foundation . getMax ( ) ; if ( value < min ) { console . warn ( `Attempted to set slider to ${ value } which is less than min: ${ min }` ) ; value = min ; } if ( value > max ) { console . warn ( `Attempted to set slider to ${ value } which is greater than max: ${ max }` ) ; value = max ; } foundation . setValue ( value ) ; } , [ props . value , foundation ] ) ; useEffect ( ( ) => { props . step !== undefined && foundation . setStep ( + props . step ) ; } , [ props . step , foundation ] ) ; useEffect ( ( ) => { props . disabled !== undefined && foundation . setDisabled ( props . disabled ) ; } , [ props . disabled , foundation ] ) ; useEffect ( ( ) => { if ( props . discrete !== undefined ) { foundation . isDiscrete_ = props . discrete ; } if ( props . discrete && foundation . getStep ( ) === 0 ) { foundation . setStep ( 1 ) ; } } , [ props . discrete , foundation ] ) ; useEffect ( ( ) => { const hasTrackMarker = foundation . hasTrackMarker_ ; if ( props . displayMarkers !== undefined && props . displayMarkers !== hasTrackMarker ) { foundation . hasTrackMarker_ = props . displayMarkers ; window . requestAnimationFrame ( ( ) => foundation . setupTrackMarker ( ) ) ; } } , [ props . displayMarkers , foundation ] ) ; useEffect ( ( ) => { const existinghandleDown_ = foundation . handleDown_ . bind ( foundation ) ; foundation . handleDown_ = ( evt ) => { evt . persist ( ) ; existinghandleDown_ ( evt ) ; } ; } , [ foundation ] ) ; return { setTrackRef , setTrackMarkerContainerRef , ... elements } ; } ;