UNPKG

reka-ui

Version:

Vue port for Radix UI Primitives.

58 lines (50 loc) 1.91 kB
import type { InjectionKey } from 'vue' import { inject, provide } from 'vue' /** * @param providerComponentName - The name(s) of the component(s) providing the context. * * There are situations where context can come from multiple components. In such cases, you might need to give an array of component names to provide your context, instead of just a single string. * * @param contextName The description for injection key symbol. */ export function createContext<ContextValue>( providerComponentName: string | string[], contextName?: string, ) { const symbolDescription = typeof providerComponentName === 'string' && !contextName ? `${providerComponentName}Context` : contextName const injectionKey: InjectionKey<ContextValue | null> = Symbol(symbolDescription) /** * @param fallback The context value to return if the injection fails. * * @throws When context injection failed and no fallback is specified. * This happens when the component injecting the context is not a child of the root component providing the context. */ const injectContext = < T extends ContextValue | null | undefined = ContextValue, >( fallback?: T, ): T extends null ? ContextValue | null : ContextValue => { const context = inject(injectionKey, fallback) if (context) return context if (context === null) return context as any throw new Error( `Injection \`${injectionKey.toString()}\` not found. Component must be used within ${ Array.isArray(providerComponentName) ? `one of the following components: ${providerComponentName.join( ', ', )}` : `\`${providerComponentName}\`` }`, ) } const provideContext = (contextValue: ContextValue) => { provide(injectionKey, contextValue) return contextValue } return [injectContext, provideContext] as const }