{
  "name": "create-context",
  "author": "Brendan Dash (https://shadcn-hooks.com)",
  "description": "Create a context object.",
  "files": [
    {
      "path": "registry/lib/create-context.tsx",
      "content": "import * as React from 'react'\n\nfunction createContext<ContextValueType extends object | null>(\n  rootComponentName: string,\n  defaultContext?: ContextValueType,\n) {\n  'use no memo'\n  const Context = React.createContext<ContextValueType | undefined>(\n    defaultContext,\n  )\n\n  const Provider: React.FC<ContextValueType & { children: React.ReactNode }> = (\n    props,\n  ) => {\n    const { children, ...context } = props\n    // Only re-memoize when prop values change\n\n    const value = React.useMemo(\n      () => context,\n      // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps, react-hooks/use-memo\n      Object.values(context),\n    ) as ContextValueType\n    return <Context value={value}>{children}</Context>\n  }\n\n  Provider.displayName = `${rootComponentName}Provider`\n\n  function useContext(consumerName: string) {\n    const context = React.use(Context)\n    if (context) return context\n    if (defaultContext !== undefined) return defaultContext\n    // if a defaultContext wasn't specified, it's a required context.\n    throw new Error(\n      `\\`${consumerName}\\` must be used within \\`${rootComponentName}\\``,\n    )\n  }\n\n  return [Provider, useContext] as const\n}\n\n/* -------------------------------------------------------------------------------------------------\n * createContextScope\n * -----------------------------------------------------------------------------------------------*/\n\ntype Scope<C = any> = { [scopeName: string]: React.Context<C>[] } | undefined\ntype ScopeHook = (scope: Scope) => { [__scopeProp: string]: Scope }\ninterface CreateScope {\n  scopeName: string;\n  (): ScopeHook\n}\n\nfunction createContextScope(\n  scopeName: string,\n  createContextScopeDeps: CreateScope[] = [],\n) {\n  let defaultContexts: any[] = []\n\n  /* -----------------------------------------------------------------------------------------------\n   * createContext\n   * ---------------------------------------------------------------------------------------------*/\n\n  function createContext<ContextValueType extends object | null>(\n    rootComponentName: string,\n    defaultContext?: ContextValueType,\n  ) {\n    'use no memo'\n    const BaseContext = React.createContext<ContextValueType | undefined>(\n      defaultContext,\n    )\n    const index = defaultContexts.length\n    defaultContexts = [...defaultContexts, defaultContext]\n\n    const Provider: React.FC<\n      ContextValueType & {\n        scope: Scope<ContextValueType>\n        children: React.ReactNode\n      }\n    > = (props) => {\n      const { scope, children, ...context } = props\n      const Context = scope?.[scopeName]?.[index] || BaseContext\n      // Only re-memoize when prop values change\n\n      const value = React.useMemo(\n        () => context,\n        // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps, react-hooks/use-memo\n        Object.values(context),\n      ) as ContextValueType\n      return <Context value={value}>{children}</Context>\n    }\n\n    Provider.displayName = `${rootComponentName}Provider`\n\n    function useContext(\n      consumerName: string,\n      scope: Scope<ContextValueType | undefined>,\n    ) {\n      const Context = scope?.[scopeName]?.[index] || BaseContext\n      const context = React.use(Context)\n      if (context) return context\n      if (defaultContext !== undefined) return defaultContext\n      // if a defaultContext wasn't specified, it's a required context.\n      throw new Error(\n        `\\`${consumerName}\\` must be used within \\`${rootComponentName}\\``,\n      )\n    }\n\n    return [Provider, useContext] as const\n  }\n\n  /* -----------------------------------------------------------------------------------------------\n   * createScope\n   * ---------------------------------------------------------------------------------------------*/\n\n  const createScope: CreateScope = () => {\n    const scopeContexts = defaultContexts.map((defaultContext) => {\n      return React.createContext(defaultContext)\n    })\n    return function useScope(scope: Scope) {\n      const contexts = scope?.[scopeName] || scopeContexts\n      return React.useMemo(\n        () => ({\n          [`__scope${scopeName}`]: { ...scope, [scopeName]: contexts },\n        }),\n        [scope, contexts],\n      )\n    }\n  }\n\n  createScope.scopeName = scopeName\n  return [\n    createContext,\n    composeContextScopes(createScope, ...createContextScopeDeps),\n  ] as const\n}\n\n/* -------------------------------------------------------------------------------------------------\n * composeContextScopes\n * -----------------------------------------------------------------------------------------------*/\n\nfunction composeContextScopes(\n  ...scopes: [CreateScope, ...CreateScope[]]\n): CreateScope {\n  const baseScope = scopes[0]\n  if (scopes.length === 1) return baseScope\n\n  const createScope: CreateScope = () => {\n    const scopeHooks = scopes.map((createScope) => ({\n      useScope: createScope(),\n      scopeName: createScope.scopeName,\n    }))\n\n    return function useComposedScopes(overrideScopes) {\n      const nextScopes = scopeHooks.reduce(\n        (nextScopes, { useScope, scopeName }) => {\n          // We are calling a hook inside a callback which React warns against to avoid inconsistent\n          // renders, however, scoping doesn't have render side effects so we ignore the rule.\n          // eslint-disable-next-line react-hooks/rules-of-hooks\n          const scopeProps = useScope(overrideScopes)\n          const currentScope = scopeProps[`__scope${scopeName}`]\n          return { ...nextScopes, ...currentScope }\n        },\n        {},\n      )\n\n      return React.useMemo(\n        () => ({ [`__scope${baseScope.scopeName}`]: nextScopes }),\n        [nextScopes],\n      )\n    }\n  }\n\n  createScope.scopeName = baseScope.scopeName\n  return createScope\n}\n\n/* -----------------------------------------------------------------------------------------------*/\n\nexport { createContext, createContextScope }\nexport type { CreateScope, Scope }\n",
      "type": "registry:lib"
    }
  ],
  "type": "registry:lib"
}
