import React, { createContext, useCallback, useContext, useMemo, useState, } from "react"; type ProviderProps = { children: React.ReactChild; initialContextValue?: S; }; type ContextType = { context: T; setContext: (T) => void; }; type ContextOptions = { selector: (context: S, ...hookArgs: any[]) => T | null; prepareContext: (newContext: T, currentContext?: S, ...hookArgs: any[]) => S; }; export function createZappPipesContext( initialContext: ContextType, options?: ContextOptions ) { const Context = createContext>(initialContext); const defaultSelector = (c: any) => c; const defaultPrepareContext = (n: any) => n; const joinArgs = (args: any[]) => args.join("-"); const { selector = defaultSelector, prepareContext = defaultPrepareContext } = options || {}; function useZappPipesContext(...hookArgs: any[]): [T, (T) => void] { const { context, setContext } = useContext(Context); const joinedArgs = joinArgs(hookArgs); const contextValue = useMemo( () => selector(context, ...hookArgs), // eslint-disable-next-line @wogns3623/better-exhaustive-deps/exhaustive-deps [context, joinedArgs] ); const contextSetter = useCallback( (newContext: T) => { setContext(prepareContext(newContext, context, ...hookArgs)); }, // eslint-disable-next-line @wogns3623/better-exhaustive-deps/exhaustive-deps [context, joinedArgs] ); return useMemo( () => [contextValue, contextSetter], [contextValue, contextSetter] ); } /** Provider accepts `initialContextValue` prop to set the initial context value */ function Provider({ children, initialContextValue }: ProviderProps) { const [context, setContext] = useState( initialContextValue ?? initialContext.context ); return ( {children} ); } function withProvider(Component: React.ComponentType) { return function WithProvider(props: any) { return ( ); }; } return { Context, useZappPipesContext, Provider, withProvider, }; }