import * as React from 'react' ; function createContext < ContextValueType extends object | null > ( rootComponentName , defaultContext ? ) { const Context = React . createContext < ContextValueType | undefined > ( defaultContext ) ; function Provider ( props ) { const { children , ... context } = props ; const value = React . useMemo ( ( ) => context , Object . values ( context ) ) as ContextValueType ; return < Context . Provider value = { value } > { children } < /Context.Provider>; } function useContext ( consumerName ) { const context = React . useContext ( Context ) ; if ( context ) return context ; if ( defaultContext !== undefined ) return defaultContext ; throw new Error ( `\`${ consumerName }\` must be used within \`${ rootComponentName }\`` ) ; } Provider . displayName = rootComponentName + 'Provider' ; return [ Provider , useContext ] as const ; } type Scope < C = any > = { [ scopeName ] : React . Context < C > [ ] ; } | undefined ; type ScopeHook = ( scope : Scope ) => { [ __scopeProp ] : Scope ; } ; interface CreateScope { scopeName : string ; ( ) : ScopeHook ; } function createContextScope ( scopeName , createContextScopeDeps = [ ] ) { let defaultContexts = [ ] ; function createContext < ContextValueType extends object | null > ( rootComponentName , defaultContext ? ) { const BaseContext = React . createContext < ContextValueType | undefined > ( defaultContext ) ; const index = defaultContexts . length ; defaultContexts = [ ... defaultContexts , defaultContext ] ; function Provider ( props ) { const { scope , children , ... context } = props ; const Context = scope ?. [ scopeName ] [ index ] || BaseContext ; const value = React . useMemo ( ( ) => context , Object . values ( context ) ) as ContextValueType ; return < Context . Provider value = { value } > { children } < /Context.Provider>; } function useContext ( consumerName , scope ) { const Context = scope ?. [ scopeName ] [ index ] || BaseContext ; const context = React . useContext ( Context ) ; if ( context ) return context ; if ( defaultContext !== undefined ) return defaultContext ; throw new Error ( `\`${ consumerName }\` must be used within \`${ rootComponentName }\`` ) ; } Provider . displayName = rootComponentName + 'Provider' ; return [ Provider , useContext ] as const ; } const createScope = ( ) => { const scopeContexts = defaultContexts . map ( ( defaultContext ) => { return React . createContext ( defaultContext ) ; } ) ; return function useScope ( scope ) { const contexts = scope ?. [ scopeName ] || scopeContexts ; return React . useMemo ( ( ) => ( { [ `__scope${ scopeName }` ] : { ... scope , [ scopeName ] : contexts } } ) , [ scope , contexts ] ) ; } ; } ; createScope . scopeName = scopeName ; return [ createContext , composeContextScopes ( createScope , ... createContextScopeDeps ) ] as const ; } function composeContextScopes ( ... scopes ) { const baseScope = scopes [ 0 ] ; if ( scopes . length === 1 ) return baseScope ; const createScope = ( ) => { const scopeHooks = scopes . map ( ( createScope ) => ( { useScope : createScope ( ) , scopeName : createScope . scopeName , } ) ) ; return function useComposedScopes ( overrideScopes ) { const nextScopes = scopeHooks . reduce ( ( nextScopes , { useScope , scopeName } ) => { const scopeProps = useScope ( overrideScopes ) ; const currentScope = scopeProps [ `__scope${ scopeName }` ] ; return { ... nextScopes , ... currentScope } ; } , { } ) ; return React . useMemo ( ( ) => ( { [ `__scope${ baseScope . scopeName }` ] : nextScopes } ) , [ nextScopes ] ) ; } ; } ; createScope . scopeName = baseScope . scopeName ; return createScope ; } export { createContext , createContextScope } ; export type { CreateScope , Scope } ;