{"version":3,"file":"index.cjs","names":[],"sources":["../src/DependencyContainer.tsx","../src/DependencyModule.tsx","../src/hooks.ts"],"sourcesContent":["import type { Container } from 'ditox';\nimport { createContainer } from 'ditox';\nimport React, {\n  createContext,\n  ReactElement,\n  ReactNode,\n  useContext,\n  useEffect,\n  useMemo,\n} from 'react';\n\nexport const DependencyContainerContext = createContext<Container | undefined>(\n  undefined,\n);\n\n/**\n * A callback for binding dependencies to a container\n */\nexport type DependencyContainerBinder = (container: Container) => unknown;\n\n/**\n * Specifies options for a new container:\n * @property binder - A callback which sets up bindings for the container.\n * @property root - If `true` then a new container does not depend on any parent containers\n */\nexport type DependencyContainerParams = {\n  children: ReactNode;\n  root?: boolean;\n  binder?: DependencyContainerBinder;\n};\n\n/**\n * Provides a new dependency container to React app\n *\n * This component creates a new container and provides it to React children.\n *\n * If a `binder` callback is specified, it will be called for the new container\n * to bind it with dependencies.\n *\n * If a parent container exists, it is connected to the current one by default.\n * To create a root container specify `root` parameter as `true`,\n * and the container will not depend on any parent container.\n *\n * @param params.binder - A callback which sets up bindings for the container.\n * @param params.root - If `true` then a new container does not depend on any parent containers\n *\n * @example\n *\n * ```tsx\n * const TOKEN = token();\n *\n * function appDependencyBinder(container: Container) {\n *   container.bindValue(TOKEN, 'value');\n * }\n *\n * function App() {\n *   return (\n *     <DependencyContainer root binder={appDependencyBinder}>\n *       <NestedComponent />\n *     </DependencyContainer>\n *   );\n * }\n * ```\n *\n */\nexport function DependencyContainer(\n  params: DependencyContainerParams,\n): ReactElement {\n  const { children, root, binder } = params;\n  const parentContainer = useContext(DependencyContainerContext);\n\n  const container = useMemo(() => {\n    const container = createContainer(root ? undefined : parentContainer);\n    binder?.(container);\n\n    return container;\n  }, [binder, parentContainer, root]);\n\n  useEffect(() => {\n    return () => container.removeAll();\n  }, [container]);\n\n  return (\n    <DependencyContainerContext.Provider value={container}>\n      {children}\n    </DependencyContainerContext.Provider>\n  );\n}\n\n/**\n * Provides a custom dependency container to React app\n *\n * @param params.container - a custom container\n *\n * @example\n * ```tsx\n * const container = useMemo(() => {\n *   return createContainer();\n * });\n *\n * return (\n *   <CustomDependencyContainer container={container}>\n *     {children}\n *   </CustomDependencyContainer>\n * );\n * ```\n */\nexport function CustomDependencyContainer(params: {\n  children: ReactNode;\n  container: Container;\n}): ReactElement {\n  const { children, container } = params;\n\n  return (\n    <DependencyContainerContext.Provider value={container}>\n      {children}\n    </DependencyContainerContext.Provider>\n  );\n}\n","import type { Module, ModuleDeclaration } from 'ditox';\nimport { bindModule } from 'ditox';\nimport React, { ReactElement, ReactNode, useCallback } from 'react';\nimport {\n  DependencyContainer,\n  DependencyContainerBinder,\n} from './DependencyContainer';\n\n/**\n * Binds the module to a new dependency container.\n *\n * If a parent container exists, it is connected to the current one by default.\n *\n * @param params.module - Module declaration for binding\n * @param params.scope - Optional scope for binding: `singleton` (default) or `scoped`.\n *\n * @example\n *\n * ```tsx\n * const LOGGER_MODULE: ModuleDeclaration<LoggerModule> = {};\n *\n * function App() {\n *   return (\n *     <DependencyModule module={LOGGER_MODULE}>\n *       <NestedComponent />\n *     </DependencyModule>\n *   );\n * }\n * ```\n */\nexport function DependencyModule(params: {\n  children: ReactNode;\n  module: ModuleDeclaration<Module<Record<string, unknown>>>;\n  scope?: 'scoped' | 'singleton';\n}): ReactElement {\n  const { children, module, scope } = params;\n\n  const binder: DependencyContainerBinder = useCallback(\n    (container) => bindModule(container, module, { scope }),\n    [module, scope],\n  );\n\n  return <DependencyContainer binder={binder}>{children}</DependencyContainer>;\n}\n","import { Container, Token } from 'ditox';\nimport { useContext, useMemo } from 'react';\nimport { DependencyContainerContext } from './DependencyContainer';\n\n/**\n * @category Hook\n *\n * Returns a dependency container. Throws an error in case the container is not provided.\n */\nexport function useDependencyContainer(mode: 'strict'): Container;\n/**\n * @category Hook\n *\n * Returns a dependency container, or `undefined` in case the container is not provided.\n */\nexport function useDependencyContainer(\n  mode?: 'optional',\n): Container | undefined;\n/**\n * @internal\n */\nexport function useDependencyContainer(\n  mode?: 'strict' | 'optional',\n): Container | undefined {\n  const container = useContext(DependencyContainerContext);\n\n  if (!container && mode === 'strict') {\n    throw new Error(\n      'Container is not provided by DependencyContainer component',\n    );\n  }\n\n  return container;\n}\n\n/**\n * @category Hook\n *\n * Returns a dependency by token, or fails with an error.\n */\nexport function useDependency<T>(token: Token<T>): T {\n  const container = useDependencyContainer('strict');\n  const value = useMemo(() => container.resolve(token), [container, token]);\n  return value;\n}\n\n/**\n * @category Hook\n *\n * Returns a dependency by token, or `undefined` in case the dependency is not provided.\n */\nexport function useOptionalDependency<T>(token: Token<T>): T | undefined {\n  const container = useDependencyContainer();\n  const value = useMemo(() => container?.get(token), [container, token]);\n  return value;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWA,MAAa,sDACX,OACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDD,SAAgB,oBACd,QACc;CACd,MAAM,EAAE,UAAU,MAAM,WAAW;CACnC,MAAM,wCAA6B,2BAA2B;CAE9D,MAAM,qCAA0B;EAC9B,MAAM,uCAA4B,OAAO,SAAY,gBAAgB;AACrE,iDAAS,UAAU;AAEnB,SAAO;IACN;EAAC;EAAQ;EAAiB;EAAK,CAAC;AAEnC,4BAAgB;AACd,eAAa,UAAU,WAAW;IACjC,CAAC,UAAU,CAAC;AAEf,QACE,4CAAC,2BAA2B,YAAS,OAAO,aACzC,SACmC;;;;;;;;;;;;;;;;;;;;AAsB1C,SAAgB,0BAA0B,QAGzB;CACf,MAAM,EAAE,UAAU,cAAc;AAEhC,QACE,4CAAC,2BAA2B,YAAS,OAAO,aACzC,SACmC;;;;;;;;;;;;;;;;;;;;;;;;;;;ACtF1C,SAAgB,iBAAiB,QAIhB;CACf,MAAM,EAAE,UAAU,QAAQ,UAAU;CAEpC,MAAM,iCACH,oCAAyB,WAAW,QAAQ,EAAE,OAAO,CAAC,EACvD,CAAC,QAAQ,MAAM,CAChB;AAED,QAAO,4CAAC,uBAA4B,UAAS,SAA+B;;;;;;;;ACrB9E,SAAgB,uBACd,MACuB;CACvB,MAAM,kCAAuB,2BAA2B;AAExD,KAAI,CAAC,aAAa,SAAS,SACzB,OAAM,IAAI,MACR,6DACD;AAGH,QAAO;;;;;;;AAQT,SAAgB,cAAiB,OAAoB;CACnD,MAAM,YAAY,uBAAuB,SAAS;AAElD,iCAD4B,UAAU,QAAQ,MAAM,EAAE,CAAC,WAAW,MAAM,CAAC;;;;;;;AAS3E,SAAgB,sBAAyB,OAAgC;CACvE,MAAM,YAAY,wBAAwB;AAE1C,uFAD4B,UAAW,IAAI,MAAM,EAAE,CAAC,WAAW,MAAM,CAAC"}