ditox-react 3.2.0 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/index.cjs +175 -0
  2. package/dist/index.cjs.map +1 -0
  3. package/dist/{browser/index.d.ts → index.d.cts} +43 -39
  4. package/dist/{umd/index.d.ts → index.d.ts} +43 -39
  5. package/dist/index.js +141 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/index.umd.js +179 -0
  8. package/dist/index.umd.js.map +1 -0
  9. package/package.json +23 -22
  10. package/src/DependencyContainer.test.tsx +32 -35
  11. package/src/DependencyContainer.tsx +5 -5
  12. package/src/DependencyModule.test.tsx +10 -9
  13. package/src/DependencyModule.tsx +6 -6
  14. package/src/hooks.test.tsx +18 -17
  15. package/src/hooks.ts +3 -3
  16. package/src/index.ts +2 -4
  17. package/dist/browser/index.js +0 -2
  18. package/dist/browser/index.js.map +0 -1
  19. package/dist/cjs/DependencyContainer.d.ts +0 -74
  20. package/dist/cjs/DependencyContainer.js +0 -101
  21. package/dist/cjs/DependencyContainer.js.map +0 -1
  22. package/dist/cjs/DependencyModule.d.ts +0 -29
  23. package/dist/cjs/DependencyModule.js +0 -58
  24. package/dist/cjs/DependencyModule.js.map +0 -1
  25. package/dist/cjs/hooks.d.ts +0 -25
  26. package/dist/cjs/hooks.js +0 -39
  27. package/dist/cjs/hooks.js.map +0 -1
  28. package/dist/cjs/index.d.ts +0 -4
  29. package/dist/cjs/index.js +0 -13
  30. package/dist/cjs/index.js.map +0 -1
  31. package/dist/esm/DependencyContainer.d.ts +0 -74
  32. package/dist/esm/DependencyContainer.js +0 -73
  33. package/dist/esm/DependencyContainer.js.map +0 -1
  34. package/dist/esm/DependencyModule.d.ts +0 -29
  35. package/dist/esm/DependencyModule.js +0 -31
  36. package/dist/esm/DependencyModule.js.map +0 -1
  37. package/dist/esm/hooks.d.ts +0 -25
  38. package/dist/esm/hooks.js +0 -33
  39. package/dist/esm/hooks.js.map +0 -1
  40. package/dist/esm/index.d.ts +0 -4
  41. package/dist/esm/index.js +0 -4
  42. package/dist/esm/index.js.map +0 -1
  43. package/dist/umd/index.js +0 -2
  44. package/dist/umd/index.js.map +0 -1
package/dist/index.cjs ADDED
@@ -0,0 +1,175 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ //#region \0rolldown/runtime.js
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
12
+ key = keys[i];
13
+ if (!__hasOwnProp.call(to, key) && key !== except) {
14
+ __defProp(to, key, {
15
+ get: ((k) => from[k]).bind(null, key),
16
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
17
+ });
18
+ }
19
+ }
20
+ }
21
+ return to;
22
+ };
23
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
24
+ value: mod,
25
+ enumerable: true
26
+ }) : target, mod));
27
+
28
+ //#endregion
29
+ let ditox = require("ditox");
30
+ let react = require("react");
31
+ react = __toESM(react);
32
+
33
+ //#region src/DependencyContainer.tsx
34
+ const DependencyContainerContext = (0, react.createContext)(void 0);
35
+ /**
36
+ * Provides a new dependency container to React app
37
+ *
38
+ * This component creates a new container and provides it to React children.
39
+ *
40
+ * If a `binder` callback is specified, it will be called for the new container
41
+ * to bind it with dependencies.
42
+ *
43
+ * If a parent container exists, it is connected to the current one by default.
44
+ * To create a root container specify `root` parameter as `true`,
45
+ * and the container will not depend on any parent container.
46
+ *
47
+ * @param params.binder - A callback which sets up bindings for the container.
48
+ * @param params.root - If `true` then a new container does not depend on any parent containers
49
+ *
50
+ * @example
51
+ *
52
+ * ```tsx
53
+ * const TOKEN = token();
54
+ *
55
+ * function appDependencyBinder(container: Container) {
56
+ * container.bindValue(TOKEN, 'value');
57
+ * }
58
+ *
59
+ * function App() {
60
+ * return (
61
+ * <DependencyContainer root binder={appDependencyBinder}>
62
+ * <NestedComponent />
63
+ * </DependencyContainer>
64
+ * );
65
+ * }
66
+ * ```
67
+ *
68
+ */
69
+ function DependencyContainer(params) {
70
+ const { children, root, binder } = params;
71
+ const parentContainer = (0, react.useContext)(DependencyContainerContext);
72
+ const container = (0, react.useMemo)(() => {
73
+ const container = (0, ditox.createContainer)(root ? void 0 : parentContainer);
74
+ binder === null || binder === void 0 || binder(container);
75
+ return container;
76
+ }, [
77
+ binder,
78
+ parentContainer,
79
+ root
80
+ ]);
81
+ (0, react.useEffect)(() => {
82
+ return () => container.removeAll();
83
+ }, [container]);
84
+ return /* @__PURE__ */ react.default.createElement(DependencyContainerContext.Provider, { value: container }, children);
85
+ }
86
+ /**
87
+ * Provides a custom dependency container to React app
88
+ *
89
+ * @param params.container - a custom container
90
+ *
91
+ * @example
92
+ * ```tsx
93
+ * const container = useMemo(() => {
94
+ * return createContainer();
95
+ * });
96
+ *
97
+ * return (
98
+ * <CustomDependencyContainer container={container}>
99
+ * {children}
100
+ * </CustomDependencyContainer>
101
+ * );
102
+ * ```
103
+ */
104
+ function CustomDependencyContainer(params) {
105
+ const { children, container } = params;
106
+ return /* @__PURE__ */ react.default.createElement(DependencyContainerContext.Provider, { value: container }, children);
107
+ }
108
+
109
+ //#endregion
110
+ //#region src/DependencyModule.tsx
111
+ /**
112
+ * Binds the module to a new dependency container.
113
+ *
114
+ * If a parent container exists, it is connected to the current one by default.
115
+ *
116
+ * @param params.module - Module declaration for binding
117
+ * @param params.scope - Optional scope for binding: `singleton` (default) or `scoped`.
118
+ *
119
+ * @example
120
+ *
121
+ * ```tsx
122
+ * const LOGGER_MODULE: ModuleDeclaration<LoggerModule> = {};
123
+ *
124
+ * function App() {
125
+ * return (
126
+ * <DependencyModule module={LOGGER_MODULE}>
127
+ * <NestedComponent />
128
+ * </DependencyModule>
129
+ * );
130
+ * }
131
+ * ```
132
+ */
133
+ function DependencyModule(params) {
134
+ const { children, module, scope } = params;
135
+ const binder = (0, react.useCallback)((container) => (0, ditox.bindModule)(container, module, { scope }), [module, scope]);
136
+ return /* @__PURE__ */ react.default.createElement(DependencyContainer, { binder }, children);
137
+ }
138
+
139
+ //#endregion
140
+ //#region src/hooks.ts
141
+ /**
142
+ * @internal
143
+ */
144
+ function useDependencyContainer(mode) {
145
+ const container = (0, react.useContext)(DependencyContainerContext);
146
+ if (!container && mode === "strict") throw new Error("Container is not provided by DependencyContainer component");
147
+ return container;
148
+ }
149
+ /**
150
+ * @category Hook
151
+ *
152
+ * Returns a dependency by token, or fails with an error.
153
+ */
154
+ function useDependency(token) {
155
+ const container = useDependencyContainer("strict");
156
+ return (0, react.useMemo)(() => container.resolve(token), [container, token]);
157
+ }
158
+ /**
159
+ * @category Hook
160
+ *
161
+ * Returns a dependency by token, or `undefined` in case the dependency is not provided.
162
+ */
163
+ function useOptionalDependency(token) {
164
+ const container = useDependencyContainer();
165
+ return (0, react.useMemo)(() => container === null || container === void 0 ? void 0 : container.get(token), [container, token]);
166
+ }
167
+
168
+ //#endregion
169
+ exports.CustomDependencyContainer = CustomDependencyContainer;
170
+ exports.DependencyContainer = DependencyContainer;
171
+ exports.DependencyModule = DependencyModule;
172
+ exports.useDependency = useDependency;
173
+ exports.useDependencyContainer = useDependencyContainer;
174
+ exports.useOptionalDependency = useOptionalDependency;
175
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"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"}
@@ -1,6 +1,7 @@
1
- import { Container, Token, ModuleDeclaration, Module } from 'ditox';
2
- import { ReactNode, ReactElement } from 'react';
1
+ import { Container, Module, ModuleDeclaration, Token } from "ditox";
2
+ import { ReactElement, ReactNode } from "react";
3
3
 
4
+ //#region src/DependencyContainer.d.ts
4
5
  /**
5
6
  * A callback for binding dependencies to a container
6
7
  */
@@ -11,9 +12,9 @@ type DependencyContainerBinder = (container: Container) => unknown;
11
12
  * @property root - If `true` then a new container does not depend on any parent containers
12
13
  */
13
14
  type DependencyContainerParams = {
14
- children: ReactNode;
15
- root?: boolean;
16
- binder?: DependencyContainerBinder;
15
+ children: ReactNode;
16
+ root?: boolean;
17
+ binder?: DependencyContainerBinder;
17
18
  };
18
19
  /**
19
20
  * Provides a new dependency container to React app
@@ -59,7 +60,7 @@ declare function DependencyContainer(params: DependencyContainerParams): ReactEl
59
60
  * ```tsx
60
61
  * const container = useMemo(() => {
61
62
  * return createContainer();
62
- * }
63
+ * });
63
64
  *
64
65
  * return (
65
66
  * <CustomDependencyContainer container={container}>
@@ -69,10 +70,40 @@ declare function DependencyContainer(params: DependencyContainerParams): ReactEl
69
70
  * ```
70
71
  */
71
72
  declare function CustomDependencyContainer(params: {
72
- children: ReactNode;
73
- container: Container;
73
+ children: ReactNode;
74
+ container: Container;
74
75
  }): ReactElement;
75
-
76
+ //#endregion
77
+ //#region src/DependencyModule.d.ts
78
+ /**
79
+ * Binds the module to a new dependency container.
80
+ *
81
+ * If a parent container exists, it is connected to the current one by default.
82
+ *
83
+ * @param params.module - Module declaration for binding
84
+ * @param params.scope - Optional scope for binding: `singleton` (default) or `scoped`.
85
+ *
86
+ * @example
87
+ *
88
+ * ```tsx
89
+ * const LOGGER_MODULE: ModuleDeclaration<LoggerModule> = {};
90
+ *
91
+ * function App() {
92
+ * return (
93
+ * <DependencyModule module={LOGGER_MODULE}>
94
+ * <NestedComponent />
95
+ * </DependencyModule>
96
+ * );
97
+ * }
98
+ * ```
99
+ */
100
+ declare function DependencyModule(params: {
101
+ children: ReactNode;
102
+ module: ModuleDeclaration<Module<Record<string, unknown>>>;
103
+ scope?: 'scoped' | 'singleton';
104
+ }): ReactElement;
105
+ //#endregion
106
+ //#region src/hooks.d.ts
76
107
  /**
77
108
  * @category Hook
78
109
  *
@@ -97,33 +128,6 @@ declare function useDependency<T>(token: Token<T>): T;
97
128
  * Returns a dependency by token, or `undefined` in case the dependency is not provided.
98
129
  */
99
130
  declare function useOptionalDependency<T>(token: Token<T>): T | undefined;
100
-
101
- /**
102
- * Binds the module to a new dependency container.
103
- *
104
- * If a parent container exists, it is connected to the current one by default.
105
- *
106
- * @param params.module - Module declaration for binding
107
- * @param params.scope - Optional scope for binding: `singleton` (default) or `scoped`.
108
- *
109
- * @example
110
- *
111
- * ```tsx
112
- * const LOGGER_MODULE: ModuleDeclaration<LoggerModule> = {
113
- *
114
- * function App() {
115
- * return (
116
- * <DependencyModule module={LOGGER_MODULE}>
117
- * <NestedComponent />
118
- * </DependencyModule>
119
- * );
120
- * }
121
- * ```
122
- */
123
- declare function DependencyModule(params: {
124
- children: ReactNode;
125
- module: ModuleDeclaration<Module<Record<string, unknown>>>;
126
- scope?: 'scoped' | 'singleton';
127
- }): ReactElement;
128
-
129
- export { CustomDependencyContainer, DependencyContainer, DependencyContainerBinder, DependencyContainerParams, DependencyModule, useDependency, useDependencyContainer, useOptionalDependency };
131
+ //#endregion
132
+ export { CustomDependencyContainer, DependencyContainer, type DependencyContainerBinder, type DependencyContainerParams, DependencyModule, useDependency, useDependencyContainer, useOptionalDependency };
133
+ //# sourceMappingURL=index.d.cts.map
@@ -1,6 +1,7 @@
1
- import { Container, Token, ModuleDeclaration, Module } from 'ditox';
2
- import { ReactNode, ReactElement } from 'react';
1
+ import { Container, Module, ModuleDeclaration, Token } from "ditox";
2
+ import React, { ReactElement, ReactNode } from "react";
3
3
 
4
+ //#region src/DependencyContainer.d.ts
4
5
  /**
5
6
  * A callback for binding dependencies to a container
6
7
  */
@@ -11,9 +12,9 @@ type DependencyContainerBinder = (container: Container) => unknown;
11
12
  * @property root - If `true` then a new container does not depend on any parent containers
12
13
  */
13
14
  type DependencyContainerParams = {
14
- children: ReactNode;
15
- root?: boolean;
16
- binder?: DependencyContainerBinder;
15
+ children: ReactNode;
16
+ root?: boolean;
17
+ binder?: DependencyContainerBinder;
17
18
  };
18
19
  /**
19
20
  * Provides a new dependency container to React app
@@ -59,7 +60,7 @@ declare function DependencyContainer(params: DependencyContainerParams): ReactEl
59
60
  * ```tsx
60
61
  * const container = useMemo(() => {
61
62
  * return createContainer();
62
- * }
63
+ * });
63
64
  *
64
65
  * return (
65
66
  * <CustomDependencyContainer container={container}>
@@ -69,10 +70,40 @@ declare function DependencyContainer(params: DependencyContainerParams): ReactEl
69
70
  * ```
70
71
  */
71
72
  declare function CustomDependencyContainer(params: {
72
- children: ReactNode;
73
- container: Container;
73
+ children: ReactNode;
74
+ container: Container;
74
75
  }): ReactElement;
75
-
76
+ //#endregion
77
+ //#region src/DependencyModule.d.ts
78
+ /**
79
+ * Binds the module to a new dependency container.
80
+ *
81
+ * If a parent container exists, it is connected to the current one by default.
82
+ *
83
+ * @param params.module - Module declaration for binding
84
+ * @param params.scope - Optional scope for binding: `singleton` (default) or `scoped`.
85
+ *
86
+ * @example
87
+ *
88
+ * ```tsx
89
+ * const LOGGER_MODULE: ModuleDeclaration<LoggerModule> = {};
90
+ *
91
+ * function App() {
92
+ * return (
93
+ * <DependencyModule module={LOGGER_MODULE}>
94
+ * <NestedComponent />
95
+ * </DependencyModule>
96
+ * );
97
+ * }
98
+ * ```
99
+ */
100
+ declare function DependencyModule(params: {
101
+ children: ReactNode;
102
+ module: ModuleDeclaration<Module<Record<string, unknown>>>;
103
+ scope?: 'scoped' | 'singleton';
104
+ }): ReactElement;
105
+ //#endregion
106
+ //#region src/hooks.d.ts
76
107
  /**
77
108
  * @category Hook
78
109
  *
@@ -97,33 +128,6 @@ declare function useDependency<T>(token: Token<T>): T;
97
128
  * Returns a dependency by token, or `undefined` in case the dependency is not provided.
98
129
  */
99
130
  declare function useOptionalDependency<T>(token: Token<T>): T | undefined;
100
-
101
- /**
102
- * Binds the module to a new dependency container.
103
- *
104
- * If a parent container exists, it is connected to the current one by default.
105
- *
106
- * @param params.module - Module declaration for binding
107
- * @param params.scope - Optional scope for binding: `singleton` (default) or `scoped`.
108
- *
109
- * @example
110
- *
111
- * ```tsx
112
- * const LOGGER_MODULE: ModuleDeclaration<LoggerModule> = {
113
- *
114
- * function App() {
115
- * return (
116
- * <DependencyModule module={LOGGER_MODULE}>
117
- * <NestedComponent />
118
- * </DependencyModule>
119
- * );
120
- * }
121
- * ```
122
- */
123
- declare function DependencyModule(params: {
124
- children: ReactNode;
125
- module: ModuleDeclaration<Module<Record<string, unknown>>>;
126
- scope?: 'scoped' | 'singleton';
127
- }): ReactElement;
128
-
129
- export { CustomDependencyContainer, DependencyContainer, DependencyContainerBinder, DependencyContainerParams, DependencyModule, useDependency, useDependencyContainer, useOptionalDependency };
131
+ //#endregion
132
+ export { CustomDependencyContainer, DependencyContainer, type DependencyContainerBinder, type DependencyContainerParams, DependencyModule, useDependency, useDependencyContainer, useOptionalDependency };
133
+ //# sourceMappingURL=index.d.ts.map
package/dist/index.js ADDED
@@ -0,0 +1,141 @@
1
+ import { bindModule, createContainer } from "ditox";
2
+ import React, { createContext, useCallback, useContext, useEffect, useMemo } from "react";
3
+
4
+ //#region src/DependencyContainer.tsx
5
+ const DependencyContainerContext = createContext(void 0);
6
+ /**
7
+ * Provides a new dependency container to React app
8
+ *
9
+ * This component creates a new container and provides it to React children.
10
+ *
11
+ * If a `binder` callback is specified, it will be called for the new container
12
+ * to bind it with dependencies.
13
+ *
14
+ * If a parent container exists, it is connected to the current one by default.
15
+ * To create a root container specify `root` parameter as `true`,
16
+ * and the container will not depend on any parent container.
17
+ *
18
+ * @param params.binder - A callback which sets up bindings for the container.
19
+ * @param params.root - If `true` then a new container does not depend on any parent containers
20
+ *
21
+ * @example
22
+ *
23
+ * ```tsx
24
+ * const TOKEN = token();
25
+ *
26
+ * function appDependencyBinder(container: Container) {
27
+ * container.bindValue(TOKEN, 'value');
28
+ * }
29
+ *
30
+ * function App() {
31
+ * return (
32
+ * <DependencyContainer root binder={appDependencyBinder}>
33
+ * <NestedComponent />
34
+ * </DependencyContainer>
35
+ * );
36
+ * }
37
+ * ```
38
+ *
39
+ */
40
+ function DependencyContainer(params) {
41
+ const { children, root, binder } = params;
42
+ const parentContainer = useContext(DependencyContainerContext);
43
+ const container = useMemo(() => {
44
+ const container = createContainer(root ? void 0 : parentContainer);
45
+ binder === null || binder === void 0 || binder(container);
46
+ return container;
47
+ }, [
48
+ binder,
49
+ parentContainer,
50
+ root
51
+ ]);
52
+ useEffect(() => {
53
+ return () => container.removeAll();
54
+ }, [container]);
55
+ return /* @__PURE__ */ React.createElement(DependencyContainerContext.Provider, { value: container }, children);
56
+ }
57
+ /**
58
+ * Provides a custom dependency container to React app
59
+ *
60
+ * @param params.container - a custom container
61
+ *
62
+ * @example
63
+ * ```tsx
64
+ * const container = useMemo(() => {
65
+ * return createContainer();
66
+ * });
67
+ *
68
+ * return (
69
+ * <CustomDependencyContainer container={container}>
70
+ * {children}
71
+ * </CustomDependencyContainer>
72
+ * );
73
+ * ```
74
+ */
75
+ function CustomDependencyContainer(params) {
76
+ const { children, container } = params;
77
+ return /* @__PURE__ */ React.createElement(DependencyContainerContext.Provider, { value: container }, children);
78
+ }
79
+
80
+ //#endregion
81
+ //#region src/DependencyModule.tsx
82
+ /**
83
+ * Binds the module to a new dependency container.
84
+ *
85
+ * If a parent container exists, it is connected to the current one by default.
86
+ *
87
+ * @param params.module - Module declaration for binding
88
+ * @param params.scope - Optional scope for binding: `singleton` (default) or `scoped`.
89
+ *
90
+ * @example
91
+ *
92
+ * ```tsx
93
+ * const LOGGER_MODULE: ModuleDeclaration<LoggerModule> = {};
94
+ *
95
+ * function App() {
96
+ * return (
97
+ * <DependencyModule module={LOGGER_MODULE}>
98
+ * <NestedComponent />
99
+ * </DependencyModule>
100
+ * );
101
+ * }
102
+ * ```
103
+ */
104
+ function DependencyModule(params) {
105
+ const { children, module, scope } = params;
106
+ const binder = useCallback((container) => bindModule(container, module, { scope }), [module, scope]);
107
+ return /* @__PURE__ */ React.createElement(DependencyContainer, { binder }, children);
108
+ }
109
+
110
+ //#endregion
111
+ //#region src/hooks.ts
112
+ /**
113
+ * @internal
114
+ */
115
+ function useDependencyContainer(mode) {
116
+ const container = useContext(DependencyContainerContext);
117
+ if (!container && mode === "strict") throw new Error("Container is not provided by DependencyContainer component");
118
+ return container;
119
+ }
120
+ /**
121
+ * @category Hook
122
+ *
123
+ * Returns a dependency by token, or fails with an error.
124
+ */
125
+ function useDependency(token) {
126
+ const container = useDependencyContainer("strict");
127
+ return useMemo(() => container.resolve(token), [container, token]);
128
+ }
129
+ /**
130
+ * @category Hook
131
+ *
132
+ * Returns a dependency by token, or `undefined` in case the dependency is not provided.
133
+ */
134
+ function useOptionalDependency(token) {
135
+ const container = useDependencyContainer();
136
+ return useMemo(() => container === null || container === void 0 ? void 0 : container.get(token), [container, token]);
137
+ }
138
+
139
+ //#endregion
140
+ export { CustomDependencyContainer, DependencyContainer, DependencyModule, useDependency, useDependencyContainer, useOptionalDependency };
141
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","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,6BAA6B,cACxC,OACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDD,SAAgB,oBACd,QACc;CACd,MAAM,EAAE,UAAU,MAAM,WAAW;CACnC,MAAM,kBAAkB,WAAW,2BAA2B;CAE9D,MAAM,YAAY,cAAc;EAC9B,MAAM,YAAY,gBAAgB,OAAO,SAAY,gBAAgB;AACrE,iDAAS,UAAU;AAEnB,SAAO;IACN;EAAC;EAAQ;EAAiB;EAAK,CAAC;AAEnC,iBAAgB;AACd,eAAa,UAAU,WAAW;IACjC,CAAC,UAAU,CAAC;AAEf,QACE,oCAAC,2BAA2B,YAAS,OAAO,aACzC,SACmC;;;;;;;;;;;;;;;;;;;;AAsB1C,SAAgB,0BAA0B,QAGzB;CACf,MAAM,EAAE,UAAU,cAAc;AAEhC,QACE,oCAAC,2BAA2B,YAAS,OAAO,aACzC,SACmC;;;;;;;;;;;;;;;;;;;;;;;;;;;ACtF1C,SAAgB,iBAAiB,QAIhB;CACf,MAAM,EAAE,UAAU,QAAQ,UAAU;CAEpC,MAAM,SAAoC,aACvC,cAAc,WAAW,WAAW,QAAQ,EAAE,OAAO,CAAC,EACvD,CAAC,QAAQ,MAAM,CAChB;AAED,QAAO,oCAAC,uBAA4B,UAAS,SAA+B;;;;;;;;ACrB9E,SAAgB,uBACd,MACuB;CACvB,MAAM,YAAY,WAAW,2BAA2B;AAExD,KAAI,CAAC,aAAa,SAAS,SACzB,OAAM,IAAI,MACR,6DACD;AAGH,QAAO;;;;;;;AAQT,SAAgB,cAAiB,OAAoB;CACnD,MAAM,YAAY,uBAAuB,SAAS;AAElD,QADc,cAAc,UAAU,QAAQ,MAAM,EAAE,CAAC,WAAW,MAAM,CAAC;;;;;;;AAS3E,SAAgB,sBAAyB,OAAgC;CACvE,MAAM,YAAY,wBAAwB;AAE1C,QADc,oEAAc,UAAW,IAAI,MAAM,EAAE,CAAC,WAAW,MAAM,CAAC"}