import { cloneDeep } from 'lodash'; import React, { useCallback, useEffect } from 'react'; import useSelectState, { SelectState } from 'Helpers/Hooks/useSelectState'; import ModelBase from './ModelBase'; export type SelectContextAction = | { type: 'reset' } | { type: 'selectAll' } | { type: 'unselectAll' } | { type: 'toggleSelected'; id: number; isSelected: boolean; shiftKey: boolean; } | { type: 'removeItem'; id: number; } | { type: 'updateItems'; items: ModelBase[]; }; export type SelectDispatch = (action: SelectContextAction) => void; interface SelectProviderOptions { // eslint-disable-next-line @typescript-eslint/no-explicit-any children: any; items: Array; } const SelectContext = React.createContext< [SelectState, SelectDispatch] | undefined >(cloneDeep(undefined)); export function SelectProvider( props: SelectProviderOptions ) { const { items } = props; const [state, dispatch] = useSelectState(); const dispatchWrapper = useCallback( (action: SelectContextAction) => { switch (action.type) { case 'reset': case 'removeItem': dispatch(action); break; default: dispatch({ ...action, items, }); break; } }, [items, dispatch] ); const value: [SelectState, SelectDispatch] = [state, dispatchWrapper]; useEffect(() => { dispatch({ type: 'updateItems', items }); }, [items, dispatch]); return ( {props.children} ); } export function useSelect() { const context = React.useContext(SelectContext); if (context === undefined) { throw new Error('useSelect must be used within a SelectProvider'); } return context; }