import React , { Component , useContext } from 'react' ; import { StyleSheet , Animated , Easing } from 'react-native' ; import { lightTheme } from '../../constants/themes' ; import type { CustomStyles , ToggleData , ToolbarCustom , ToolbarTheme , } from '../../types' ; export interface ContextProps { apply : ( name : string , value : any ) => void ; selectedFormats : object ; isSelected : ( name : string , value : any ) => boolean ; theme : ToolbarTheme ; show : ( name : string , options : Array < ToggleData > ) => void ; hide : Function ; open : boolean ; options : Array < ToggleData > ; selectionName : string ; getSelected : ( name : string ) => any ; styles ? : CustomStyles ; } const ToolbarContext = React . createContext < ContextProps > ( { apply : ( ) => { } , show : ( ) => { } , hide : ( ) => { } , selectedFormats : { } , open : false , isSelected : ( ) => false , theme : lightTheme , options : [ ] , selectionName : '' , getSelected : ( ) => false , } ) ; export const ToolbarConsumer = ToolbarContext . Consumer ; interface ProviderProps { format : Function ; selectedFormats : Record < string , any > ; theme : ToolbarTheme ; custom ? : ToolbarCustom ; styles ? : CustomStyles ; } interface ProviderState { open : boolean ; isAnimating : boolean ; options : Array < ToggleData > ; name : string ; } export class ToolbarProvider extends Component < ProviderProps , ProviderState > { animatedValue : Animated . Value ; constructor ( props ) { super ( props ) ; this . state = { open : false , isAnimating : false , options : [ ] , name : '' , } ; this . animatedValue = new Animated . Value ( 0 ) ; } show = ( name , options ) => { if ( this . state . isAnimating ) return ; const { theme } = this . props ; if ( theme ) { this . setState ( { options , name , isAnimating : true } , ( ) => { Animated . timing ( this . animatedValue , { toValue : 2 * theme . size + 14 , duration : 200 , easing : Easing . sin , useNativeDriver : false , } ) . start ( ( ) => this . setState ( { open : true , isAnimating : false } ) ) ; } ) ; } } ; hide = ( ) => { if ( this . state . isAnimating ) return ; const { theme } = this . props ; if ( theme ) { this . setState ( { isAnimating : true } , ( ) => { Animated . timing ( this . animatedValue , { toValue : theme . size + 10 , duration : 200 , easing : Easing . linear , useNativeDriver : false , } ) . start ( ( ) => { this . setState ( { name : '' , open : false , options : [ ] , isAnimating : false , } ) ; } ) ; } ) ; } } ; componentDidMount ( ) { const { theme } = this . props ; this . animatedValue = new Animated . Value ( theme . size + 10 ) ; } isSelected = ( name , value = true ) : boolean => { const { selectedFormats } = this . props ; const selected = selectedFormats [ name ] ; return selected ? selected === value : value === false ; } ; getSelected = ( name ) : any => { const { selectedFormats } = this . props ; const selected = selectedFormats [ name ] ; return selected ? selected : false ; } ; apply = ( name , value ) => { const { format , custom } = this . props ; if ( custom ?. actions ) custom . actions . find ( ( x ) => x === name ) ; if ( custom ?. actions && custom ?. actions ?. indexOf ( name ) > - 1 ) { if ( custom ?. handler ) custom . handler ( name , value ) ; } else { format ( name , value ) ; } } ; render ( ) { const { selectedFormats , children , theme , styles } = this . props ; const { open , options , name } = this . state ; const defaultStyles = makeStyles ( theme ) ; const rootStyle = styles ?. toolbar ?. provider ? styles ?. toolbar ?. provider ( defaultStyles . root ) : defaultStyles . root ; return ( < ToolbarContext . Provider value = { { selectedFormats , apply : this . apply , isSelected : this . isSelected , theme , open , show : this . show , hide : this . hide , getSelected : this . getSelected , selectionName : name , options , styles , } } > < Animated . View style = { [ rootStyle , { height : this . animatedValue , } , ] } > { children } < /Animated.View> < /ToolbarContext.Provider>); } } const makeStyles = ( theme ) => StyleSheet . create ( { root : { borderTopWidth : 1 , borderLeftWidth : 1 , borderRightWidth : 1 , borderColor : theme . color , position : 'relative' , backgroundColor : theme . background , width : '100%' , } , } ) ; export const withToolbar = ( MyComponent ) => { const WrappedComponent = React . forwardRef ( ( props , ref ) => ( < ToolbarContext . Consumer > { ( context ) => ( < MyComponent { ... props } ref = { ref } apply = { context . apply } selectedFormats = { context . selectedFormats } / > ) } < /ToolbarContext.Consumer>)); return WrappedComponent ; } ; export const useToolbar = ( ) : ContextProps => useContext ( ToolbarContext ) ;