import { useMemo , useRef } from 'react' ; import useUpdate from './useUpdate' ; import { IHookStateInitAction , IHookStateSetAction , resolveHookState } from './misc/hookState' ; export interface ListActions < T > { description set : ( newList : IHookStateSetAction < T [ ] > ) => void ; description push : ( ... items : T [ ] ) => void ; description updateAt : ( index : number , item : T ) => void ; description insertAt : ( index : number , item : T ) => void ; description update : ( predicate : ( a : T , b : T ) => boolean , newItem : T ) => void ; description updateFirst : ( predicate : ( a : T , b : T ) => boolean , newItem : T ) => void ; description upsert : ( predicate : ( a : T , b : T ) => boolean , newItem : T ) => void ; description sort : ( compareFn ? : ( a : T , b : T ) => number ) => void ; description filter : ( callbackFn : ( value : T , index ? : number , array ? : T [ ] ) => boolean , thisArg ? : any ) => void ; description removeAt : ( index : number ) => void ; deprecated remove : ( index : number ) => void ; description clear : ( ) => void ; description reset : ( ) => void ; } function useList < T > ( initialList = [ ] ) { const list = useRef ( resolveHookState ( initialList ) ) ; const update = useUpdate ( ) ; const actions = useMemo < ListActions < T > > ( ( ) => { const a = { set : ( newList ) => { list . current = resolveHookState ( newList , list . current ) ; update ( ) ; } , push : ( ... items ) => { items . length && actions . set ( ( curr ) => curr . concat ( items ) ) ; } , updateAt : ( index , item ) => { actions . set ( ( curr ) => { const arr = curr . slice ( ) ; arr [ index ] = item ; return arr ; } ) ; } , insertAt : ( index , item ) => { actions . set ( ( curr ) => { const arr = curr . slice ( ) ; index > arr . length ? ( arr [ index ] = item ) : arr . splice ( index , 0 , item ) ; return arr ; } ) ; } , update : ( predicate , newItem ) => { actions . set ( ( curr ) => curr . map ( ( item ) => ( predicate ( item , newItem ) ? newItem : item ) ) ) ; } , updateFirst : ( predicate , newItem ) => { const index = list . current . findIndex ( ( item ) => predicate ( item , newItem ) ) ; index >= 0 && actions . updateAt ( index , newItem ) ; } , upsert : ( predicate , newItem ) => { const index = list . current . findIndex ( ( item ) => predicate ( item , newItem ) ) ; index >= 0 ? actions . updateAt ( index , newItem ) : actions . push ( newItem ) ; } , sort : ( compareFn ? ) => { actions . set ( ( curr ) => curr . slice ( ) . sort ( compareFn ) ) ; } , filter : < S extends T > ( callbackFn , thisArg ? ) => { actions . set ( ( curr ) => curr . slice ( ) . filter ( callbackFn , thisArg ) ) ; } , removeAt : ( index ) => { actions . set ( ( curr ) => { const arr = curr . slice ( ) ; arr . splice ( index , 1 ) ; return arr ; } ) ; } , clear : ( ) => { actions . set ( [ ] ) ; } , reset : ( ) => { actions . set ( resolveHookState ( initialList ) . slice ( ) ) ; } , } ; deprecated ( a as ListActions < T > ) . remove = a . removeAt ; return a as ListActions < T > ; } , [ ] ) ; return [ list . current , actions ] ; } export default useList ;