import * as React from 'react' ; import curry from 'lodash/curry' ; export type StateProp = { stateName ? : string ; } ; type Store = Map < string , any > ; const unwrapValue = ( value ) => { let actualValue = value ; if ( typeof value === 'object' && value !== null && 'currentTarget' in value ) { const { currentTarget } = value ; actualValue = currentTarget . type === 'checkbox' ? currentTarget . checked : currentTarget . value ; } return actualValue ; } ; const makeStoreConsumer = ( defaultState , store , setStore ) => { const setDefaultState = ( key , value ) => defaultState . set ( key , value ) ; const getState = ( key ) => store . get ( key ) ?? defaultState . get ( key ) ; const setState = curry ( ( key , value ) => setStore ( new Map ( store . set ( key , unwrapValue ( value ) ) ) ) ) ; const toggleState = ( key ) => setState ( key , ! getState ( key ) ) ; const resetState = ( ... keys ) => { if ( keys . length ) { keys . forEach ( ( key ) => { store . delete ( key ) ; } ) ; setStore ( new Map ( store ) ) ; } else { setStore ( new Map ( ) ) ; } } ; return { setDefaultState , getState , setState , toggleState , resetState , } ; } ; const PlayroomStateContext = React . createContext < ReturnType < typeof makeStoreConsumer > | null > ( null ) ; type Props = { defaultState ? : Map < string , any > ; } ; export const PlayroomStateProvider = ( { defaultState : defaultStateProp , children , } ) => { const [ fallbackDefaultState ] = React . useState ( ( ) => new Map ( ) ) ; const defaultState = defaultStateProp ?? fallbackDefaultState ; const state = React . useState ( new Map < string , any > ( ) ) ; const storeConsumer = React . useMemo ( ( ) => makeStoreConsumer ( defaultState , ... state ) , [ state , defaultState ] ) ; return ( < PlayroomStateContext . Provider value = { storeConsumer } > { children } < /PlayroomStateContext.Provider>); } ; export const usePlayroomStore = ( ) => { const storeConsumer = React . useContext ( PlayroomStateContext ) ; if ( ! storeConsumer ) throw new Error ( 'Must be within PlayroomStateProvider' ) ; return storeConsumer ; } ; type Callback = ( ... args : any [ ] ) => void ; const noop = ( ) => { } ; export const useFallbackState = < Value , Handler extends Callback > ( stateKey , value , onChange , defaultValue ? ) : [ NonNullable < Value > , ( ... args : Parameters < Handler > ) => void ] => { const playroomState = usePlayroomStore ( ) ; const [ internalStateValue , setInternalStateValue ] = React . useState ( defaultValue ) ; const wrapChangeHandler = ( handler ) : ( ( ... args : Parameters < Handler > ) => void ) => ( ... args ) => { if ( value === undefined ) { ; ( stateKey ? playroomState . setState ( stateKey ) : setInternalStateValue ) ( unwrapValue ( args [ 0 ] ) ) ; } ; ( handler || noop ) ( ... args ) ; } ; const handleChange = wrapChangeHandler ( onChange || noop ) ; const resolvedValue = value ?? ( stateKey ? playroomState . getState ( stateKey ) ?? defaultValue : internalStateValue ) ; return [ resolvedValue , handleChange ] ; } ;