@blac/react 2.0.0-rc.11 → 2.0.0-rc.13

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.
package/dist/index.cjs CHANGED
@@ -42,7 +42,8 @@ function determineTrackingMode(options) {
42
42
  * - **Manual dependencies**: Explicit dependency array like useEffect
43
43
  * - **No tracking**: Returns full state without optimization
44
44
  *
45
- * @template T - The state container constructor type
45
+ * @template S - Optional state type override for generic StateContainers (defaults to never)
46
+ * @template T - The state container constructor type (inferred from BlocClass)
46
47
  * @param BlocClass - The state container class to connect to
47
48
  * @param options - Configuration options for tracking mode and instance management
48
49
  * @returns Tuple with [state, bloc instance, ref]
@@ -65,10 +66,15 @@ function determineTrackingMode(options) {
65
66
  * instanceId: 'unique-id'
66
67
  * });
67
68
  * ```
69
+ *
70
+ * @example With generic bloc and explicit state type
71
+ * ```ts
72
+ * const [state, myBloc] = useBloc<MyStateType>(GenericBloc);
73
+ * // state is typed as MyStateType
74
+ * ```
68
75
  */
69
76
  function useBloc(BlocClass, options) {
70
77
  const componentRef = (0, react.useRef)({});
71
- const Constructor = BlocClass;
72
78
  const isIsolated = (0, __blac_core.isIsolatedClass)(BlocClass);
73
79
  const initialPropsRef = (0, react.useRef)(options?.props);
74
80
  const [bloc, subscribe, getSnapshot, instanceKey, adapterState, rawInstance] = (0, react.useMemo)(() => {
@@ -116,7 +122,7 @@ function useBloc(BlocClass, options) {
116
122
  return () => {
117
123
  externalDepsManager.current.cleanup();
118
124
  if (options?.onUnmount) options.onUnmount(bloc);
119
- Constructor.release(instanceKey);
125
+ BlocClass.release(instanceKey);
120
126
  if (isIsolated && !rawInstance.isDisposed) rawInstance.dispose();
121
127
  };
122
128
  }, []);
@@ -133,7 +139,8 @@ function useBloc(BlocClass, options) {
133
139
  * React hook that connects to a state container instance without triggering re-renders.
134
140
  * Use this when you only need to call actions on the bloc without subscribing to state changes.
135
141
  *
136
- * @template T - The state container constructor type
142
+ * @template S - Optional state type override for generic StateContainers (defaults to never)
143
+ * @template T - The state container constructor type (inferred from BlocClass)
137
144
  * @param BlocClass - The state container class to connect to
138
145
  * @param options - Configuration options for instance management and lifecycle
139
146
  * @returns The state container instance for calling actions
@@ -151,15 +158,20 @@ function useBloc(BlocClass, options) {
151
158
  * instanceId: 'unique-id'
152
159
  * });
153
160
  * ```
161
+ *
162
+ * @example With generic bloc and explicit state type
163
+ * ```ts
164
+ * const myBloc = useBlocActions<MyStateType>(GenericBloc);
165
+ * // myBloc.state is typed as MyStateType
166
+ * ```
154
167
  */
155
168
  function useBlocActions(BlocClass, options) {
156
169
  const componentRef = (0, react.useRef)({});
157
170
  const initialPropsRef = (0, react.useRef)(options?.props);
158
171
  const [bloc, instanceKey] = (0, react.useMemo)(() => {
159
172
  const isIsolated = (0, __blac_core.isIsolatedClass)(BlocClass);
160
- const Constructor = BlocClass;
161
173
  const instanceKey$1 = generateInstanceKey(componentRef.current, isIsolated, options?.instanceId);
162
- return [Constructor.resolve(instanceKey$1, initialPropsRef.current), instanceKey$1];
174
+ return [BlocClass.resolve(instanceKey$1, initialPropsRef.current), instanceKey$1];
163
175
  }, [BlocClass]);
164
176
  (0, react.useEffect)(() => {
165
177
  if (options?.onMount) options.onMount(bloc);
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["instanceKey","subscribeFn: (callback: () => void) => () => void","getSnapshotFn: () => ExtractState<TBloc>","adapterState: AdapterState<TBloc>","adapterState","ExternalDependencyManager","instanceKey"],"sources":["../src/utils/instance-keys.ts","../src/useBloc.ts","../src/useBlocActions.ts"],"sourcesContent":["/**\n * Instance key generation utilities for React integration\n */\n\nimport { generateIsolatedKey } from '@blac/core';\nimport type { ComponentRef } from '../types';\n\n/**\n * Generate an instance key for a bloc\n *\n * Logic:\n * - If user provides instanceId, use it (convert number to string)\n * - If isolated, generate or reuse a unique key for this component\n * - Otherwise, return undefined (use default key)\n *\n * @param componentRef - React component reference (persists across remounts)\n * @param isIsolated - Whether the bloc is isolated\n * @param providedId - User-provided instance ID (from options)\n * @returns Instance key string or undefined for default\n */\nexport function generateInstanceKey(\n componentRef: ComponentRef,\n isIsolated: boolean,\n providedId?: string | number,\n): string | undefined {\n // User explicitly provided an ID - use it\n if (providedId !== undefined) {\n return typeof providedId === 'number' ? String(providedId) : providedId;\n }\n\n // Isolated bloc - generate unique key per component\n if (isIsolated) {\n if (!componentRef.__blocInstanceId) {\n componentRef.__blocInstanceId = generateIsolatedKey();\n }\n return componentRef.__blocInstanceId;\n }\n\n // Shared bloc - use default key (undefined)\n return undefined;\n}\n","import {\n useMemo,\n useSyncExternalStore,\n useEffect,\n useRef,\n useReducer,\n} from 'react';\nimport {\n type BlocConstructor,\n StateContainer,\n type ExtractState,\n type AdapterState,\n ExternalDependencyManager,\n createAutoTrackSubscribe,\n createManualDepsSubscribe,\n createNoTrackSubscribe,\n createAutoTrackSnapshot,\n createManualDepsSnapshot,\n createNoTrackSnapshot,\n initAutoTrackState,\n initManualDepsState,\n initNoTrackState,\n disableGetterTracking,\n isIsolatedClass,\n} from '@blac/core';\nimport type { UseBlocOptions, UseBlocReturn, ComponentRef } from './types';\nimport { generateInstanceKey } from './utils/instance-keys';\n\ntype StateContainerConstructor<TBloc extends StateContainer<any, any>> =\n BlocConstructor<TBloc> & {\n resolve(instanceKey?: string, ...args: any[]): TBloc;\n release(instanceKey?: string): void;\n };\n\ninterface TrackingMode {\n useManualDeps: boolean;\n autoTrackEnabled: boolean;\n}\n\nfunction determineTrackingMode<TBloc extends StateContainer<any, any>>(\n options?: UseBlocOptions<TBloc>,\n): TrackingMode {\n return {\n useManualDeps: options?.dependencies !== undefined,\n autoTrackEnabled: options?.autoTrack !== false,\n };\n}\n\n/**\n * React hook that connects a component to a state container with automatic re-render on state changes.\n *\n * Supports three tracking modes:\n * - **Auto-tracking** (default): Automatically detects accessed state properties via Proxy\n * - **Manual dependencies**: Explicit dependency array like useEffect\n * - **No tracking**: Returns full state without optimization\n *\n * @template T - The state container constructor type\n * @param BlocClass - The state container class to connect to\n * @param options - Configuration options for tracking mode and instance management\n * @returns Tuple with [state, bloc instance, ref]\n *\n * @example Basic usage\n * ```ts\n * const [state, myBloc, ref] = useBloc(MyBloc);\n * ```\n *\n * @example With manual dependencies\n * ```ts\n * const [state, myBloc] = useBloc(MyBloc, {\n * dependencies: (state) => [state.count]\n * });\n * ```\n *\n * @example With isolated instance\n * ```ts\n * const [state, myBloc] = useBloc(MyBloc, {\n * instanceId: 'unique-id'\n * });\n * ```\n */\nexport function useBloc<\n T extends new (...args: any[]) => StateContainer<any, any>,\n>(\n BlocClass: T & BlocConstructor<InstanceType<T>>,\n options?: UseBlocOptions<InstanceType<T>>,\n): UseBlocReturn<InstanceType<T>> {\n type TBloc = InstanceType<T>;\n const componentRef = useRef<ComponentRef>({});\n const Constructor = BlocClass as StateContainerConstructor<TBloc>;\n const isIsolated = isIsolatedClass(BlocClass);\n\n const initialPropsRef = useRef(options?.props);\n\n const [bloc, subscribe, getSnapshot, instanceKey, adapterState, rawInstance] =\n useMemo<\n readonly [\n TBloc,\n (callback: () => void) => () => void,\n () => ExtractState<TBloc>,\n string | undefined,\n AdapterState<TBloc>,\n TBloc,\n ]\n >(() => {\n const instanceKey = generateInstanceKey(\n componentRef.current,\n isIsolated,\n options?.instanceId,\n );\n\n const instance = BlocClass.resolve(instanceKey, initialPropsRef.current);\n\n if (initialPropsRef.current !== undefined) {\n instance.updateProps(initialPropsRef.current);\n }\n\n const { useManualDeps, autoTrackEnabled } =\n determineTrackingMode(options);\n\n let subscribeFn: (callback: () => void) => () => void;\n let getSnapshotFn: () => ExtractState<TBloc>;\n let adapterState: AdapterState<TBloc>;\n\n if (useManualDeps && options?.dependencies) {\n adapterState = initManualDepsState(instance);\n subscribeFn = createManualDepsSubscribe(instance, adapterState, {\n dependencies: options.dependencies,\n });\n getSnapshotFn = createManualDepsSnapshot(instance, adapterState, {\n dependencies: options.dependencies,\n });\n } else if (!autoTrackEnabled) {\n adapterState = initNoTrackState(instance);\n subscribeFn = createNoTrackSubscribe(instance);\n getSnapshotFn = createNoTrackSnapshot(instance);\n } else {\n adapterState = initAutoTrackState(instance);\n subscribeFn = createAutoTrackSubscribe(instance, adapterState);\n getSnapshotFn = createAutoTrackSnapshot(instance, adapterState);\n }\n\n return [\n adapterState.proxiedBloc!,\n subscribeFn,\n getSnapshotFn,\n instanceKey,\n adapterState,\n instance,\n ];\n }, [BlocClass, options?.instanceId]);\n\n const state = useSyncExternalStore(subscribe, getSnapshot);\n\n const [, forceUpdate] = useReducer((x: number) => x + 1, 0);\n\n const externalDepsManager = useRef(new ExternalDependencyManager());\n\n useEffect(() => {\n if (options?.props !== initialPropsRef.current) {\n rawInstance.updateProps(options?.props);\n }\n }, [options?.props, rawInstance]);\n\n useEffect(() => {\n disableGetterTracking(adapterState, rawInstance);\n externalDepsManager.current.updateSubscriptions(\n adapterState.getterTracker,\n rawInstance,\n forceUpdate,\n );\n });\n\n useEffect(() => {\n if (options?.onMount) {\n options.onMount(bloc);\n }\n\n return () => {\n externalDepsManager.current.cleanup();\n\n if (options?.onUnmount) {\n options.onUnmount(bloc);\n }\n\n Constructor.release(instanceKey);\n\n if (isIsolated && !rawInstance.isDisposed) {\n rawInstance.dispose();\n }\n };\n }, []);\n\n return [state, bloc, componentRef] as UseBlocReturn<TBloc>;\n}\n","import { useMemo, useEffect, useRef } from 'react';\nimport {\n type BlocConstructor,\n StateContainer,\n isIsolatedClass,\n} from '@blac/core';\nimport type { ComponentRef } from './types';\nimport { generateInstanceKey } from './utils/instance-keys';\n\ntype StateContainerConstructor<TBloc extends StateContainer<any, any>> =\n BlocConstructor<TBloc> & {\n resolve(instanceKey?: string, ...args: any[]): TBloc;\n release(instanceKey?: string): void;\n };\n\n/**\n * Configuration options for useBlocActions hook\n * @template TBloc - The state container type\n * @template TProps - Props type passed to the container\n */\nexport interface UseBlocActionsOptions<TBloc, TProps = any> {\n /** Props passed to bloc constructor or updateProps */\n props?: TProps;\n /** Custom instance identifier for shared or isolated instances */\n instanceId?: string | number;\n /** Callback invoked when bloc instance mounts */\n onMount?: (bloc: TBloc) => void;\n /** Callback invoked when bloc instance unmounts */\n onUnmount?: (bloc: TBloc) => void;\n}\n\n/**\n * React hook that connects to a state container instance without triggering re-renders.\n * Use this when you only need to call actions on the bloc without subscribing to state changes.\n *\n * @template T - The state container constructor type\n * @param BlocClass - The state container class to connect to\n * @param options - Configuration options for instance management and lifecycle\n * @returns The state container instance for calling actions\n *\n * @example Basic usage\n * ```ts\n * const myBloc = useBlocActions(MyBloc);\n * // Call methods on the bloc without re-rendering\n * myBloc.someMethod();\n * ```\n *\n * @example With isolated instance\n * ```ts\n * const myBloc = useBlocActions(MyBloc, {\n * instanceId: 'unique-id'\n * });\n * ```\n */\nexport function useBlocActions<\n T extends new (...args: any[]) => StateContainer<any, any>,\n>(\n BlocClass: T & BlocConstructor<InstanceType<T>>,\n options?: UseBlocActionsOptions<InstanceType<T>>,\n): InstanceType<T> {\n type TBloc = InstanceType<T>;\n const componentRef = useRef<ComponentRef>({});\n const initialPropsRef = useRef(options?.props);\n\n const [bloc, instanceKey] = useMemo(() => {\n const isIsolated = isIsolatedClass(BlocClass);\n const Constructor = BlocClass as StateContainerConstructor<TBloc>;\n\n const instanceKey = generateInstanceKey(\n componentRef.current,\n isIsolated,\n options?.instanceId,\n );\n\n const instance = Constructor.resolve(instanceKey, initialPropsRef.current);\n\n return [instance, instanceKey] as const;\n }, [BlocClass]);\n\n useEffect(() => {\n if (options?.onMount) {\n options.onMount(bloc);\n }\n\n return () => {\n if (options?.onUnmount) {\n options.onUnmount(bloc);\n }\n\n const Constructor = BlocClass as StateContainerConstructor<TBloc>;\n Constructor.release(instanceKey);\n\n if (isIsolatedClass(BlocClass) && !bloc.isDisposed) {\n bloc.dispose();\n }\n };\n }, []);\n\n return bloc;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["instanceKey","subscribeFn: (callback: () => void) => () => void","getSnapshotFn: () => ExtractState<TBloc>","adapterState: AdapterState<TBloc>","adapterState","ExternalDependencyManager","instanceKey"],"sources":["../src/utils/instance-keys.ts","../src/useBloc.ts","../src/useBlocActions.ts"],"sourcesContent":["/**\n * Instance key generation utilities for React integration\n */\n\nimport { generateIsolatedKey } from '@blac/core';\nimport type { ComponentRef } from '../types';\n\n/**\n * Generate an instance key for a bloc\n *\n * Logic:\n * - If user provides instanceId, use it (convert number to string)\n * - If isolated, generate or reuse a unique key for this component\n * - Otherwise, return undefined (use default key)\n *\n * @param componentRef - React component reference (persists across remounts)\n * @param isIsolated - Whether the bloc is isolated\n * @param providedId - User-provided instance ID (from options)\n * @returns Instance key string or undefined for default\n */\nexport function generateInstanceKey(\n componentRef: ComponentRef,\n isIsolated: boolean,\n providedId?: string | number,\n): string | undefined {\n // User explicitly provided an ID - use it\n if (providedId !== undefined) {\n return typeof providedId === 'number' ? String(providedId) : providedId;\n }\n\n // Isolated bloc - generate unique key per component\n if (isIsolated) {\n if (!componentRef.__blocInstanceId) {\n componentRef.__blocInstanceId = generateIsolatedKey();\n }\n return componentRef.__blocInstanceId;\n }\n\n // Shared bloc - use default key (undefined)\n return undefined;\n}\n","import {\n useMemo,\n useSyncExternalStore,\n useEffect,\n useRef,\n useReducer,\n} from 'react';\nimport {\n type BlocConstructor,\n StateContainer,\n type ExtractState,\n type AdapterState,\n ExternalDependencyManager,\n createAutoTrackSubscribe,\n createManualDepsSubscribe,\n createNoTrackSubscribe,\n createAutoTrackSnapshot,\n createManualDepsSnapshot,\n createNoTrackSnapshot,\n initAutoTrackState,\n initManualDepsState,\n initNoTrackState,\n disableGetterTracking,\n isIsolatedClass,\n} from '@blac/core';\nimport type { UseBlocOptions, UseBlocReturn, ComponentRef } from './types';\nimport { generateInstanceKey } from './utils/instance-keys';\n\ninterface TrackingMode {\n useManualDeps: boolean;\n autoTrackEnabled: boolean;\n}\n\nfunction determineTrackingMode<TBloc extends StateContainer<any, any>>(\n options?: UseBlocOptions<TBloc>,\n): TrackingMode {\n return {\n useManualDeps: options?.dependencies !== undefined,\n autoTrackEnabled: options?.autoTrack !== false,\n };\n}\n\n/**\n * React hook that connects a component to a state container with automatic re-render on state changes.\n *\n * Supports three tracking modes:\n * - **Auto-tracking** (default): Automatically detects accessed state properties via Proxy\n * - **Manual dependencies**: Explicit dependency array like useEffect\n * - **No tracking**: Returns full state without optimization\n *\n * @template S - Optional state type override for generic StateContainers (defaults to never)\n * @template T - The state container constructor type (inferred from BlocClass)\n * @param BlocClass - The state container class to connect to\n * @param options - Configuration options for tracking mode and instance management\n * @returns Tuple with [state, bloc instance, ref]\n *\n * @example Basic usage\n * ```ts\n * const [state, myBloc, ref] = useBloc(MyBloc);\n * ```\n *\n * @example With manual dependencies\n * ```ts\n * const [state, myBloc] = useBloc(MyBloc, {\n * dependencies: (state) => [state.count]\n * });\n * ```\n *\n * @example With isolated instance\n * ```ts\n * const [state, myBloc] = useBloc(MyBloc, {\n * instanceId: 'unique-id'\n * });\n * ```\n *\n * @example With generic bloc and explicit state type\n * ```ts\n * const [state, myBloc] = useBloc<MyStateType>(GenericBloc);\n * // state is typed as MyStateType\n * ```\n */\nexport function useBloc<\n S = never,\n T extends new (...args: any[]) => StateContainer<any, any> = new (\n ...args: any[]\n ) => StateContainer<any, any>,\n>(\n BlocClass: T & BlocConstructor<InstanceType<T>>,\n options?: UseBlocOptions<InstanceType<T>>,\n): UseBlocReturn<InstanceType<T>, S> {\n type TBloc = InstanceType<T>;\n const componentRef = useRef<ComponentRef>({});\n const isIsolated = isIsolatedClass(BlocClass);\n\n const initialPropsRef = useRef(options?.props);\n\n const [bloc, subscribe, getSnapshot, instanceKey, adapterState, rawInstance] =\n useMemo<\n readonly [\n TBloc,\n (callback: () => void) => () => void,\n () => ExtractState<TBloc>,\n string | undefined,\n AdapterState<TBloc>,\n TBloc,\n ]\n >(() => {\n const instanceKey = generateInstanceKey(\n componentRef.current,\n isIsolated,\n options?.instanceId,\n );\n\n const instance = BlocClass.resolve(instanceKey, initialPropsRef.current);\n\n if (initialPropsRef.current !== undefined) {\n instance.updateProps(initialPropsRef.current);\n }\n\n const { useManualDeps, autoTrackEnabled } =\n determineTrackingMode(options);\n\n let subscribeFn: (callback: () => void) => () => void;\n let getSnapshotFn: () => ExtractState<TBloc>;\n let adapterState: AdapterState<TBloc>;\n\n if (useManualDeps && options?.dependencies) {\n adapterState = initManualDepsState(instance);\n subscribeFn = createManualDepsSubscribe(instance, adapterState, {\n dependencies: options.dependencies,\n });\n getSnapshotFn = createManualDepsSnapshot(instance, adapterState, {\n dependencies: options.dependencies,\n });\n } else if (!autoTrackEnabled) {\n adapterState = initNoTrackState(instance);\n subscribeFn = createNoTrackSubscribe(instance);\n getSnapshotFn = createNoTrackSnapshot(instance);\n } else {\n adapterState = initAutoTrackState(instance);\n subscribeFn = createAutoTrackSubscribe(instance, adapterState);\n getSnapshotFn = createAutoTrackSnapshot(instance, adapterState);\n }\n\n return [\n adapterState.proxiedBloc!,\n subscribeFn,\n getSnapshotFn,\n instanceKey,\n adapterState,\n instance,\n ];\n }, [BlocClass, options?.instanceId]);\n\n const state = useSyncExternalStore(subscribe, getSnapshot);\n\n const [, forceUpdate] = useReducer((x: number) => x + 1, 0);\n\n const externalDepsManager = useRef(new ExternalDependencyManager());\n\n useEffect(() => {\n if (options?.props !== initialPropsRef.current) {\n rawInstance.updateProps(options?.props);\n }\n }, [options?.props, rawInstance]);\n\n useEffect(() => {\n disableGetterTracking(adapterState, rawInstance);\n externalDepsManager.current.updateSubscriptions(\n adapterState.getterTracker,\n rawInstance,\n forceUpdate,\n );\n });\n\n useEffect(() => {\n if (options?.onMount) {\n options.onMount(bloc);\n }\n\n return () => {\n externalDepsManager.current.cleanup();\n\n if (options?.onUnmount) {\n options.onUnmount(bloc);\n }\n\n BlocClass.release(instanceKey);\n\n if (isIsolated && !rawInstance.isDisposed) {\n rawInstance.dispose();\n }\n };\n }, []);\n\n return [state, bloc, componentRef] as UseBlocReturn<TBloc, S>;\n}\n","import { useMemo, useEffect, useRef } from 'react';\nimport {\n type BlocConstructor,\n type StateOverride,\n StateContainer,\n isIsolatedClass,\n} from '@blac/core';\nimport type { ComponentRef } from './types';\nimport { generateInstanceKey } from './utils/instance-keys';\n\n/**\n * Configuration options for useBlocActions hook\n * @template TBloc - The state container type\n * @template TProps - Props type passed to the container\n */\nexport interface UseBlocActionsOptions<TBloc, TProps = any> {\n /** Props passed to bloc constructor or updateProps */\n props?: TProps;\n /** Custom instance identifier for shared or isolated instances */\n instanceId?: string | number;\n /** Callback invoked when bloc instance mounts */\n onMount?: (bloc: TBloc) => void;\n /** Callback invoked when bloc instance unmounts */\n onUnmount?: (bloc: TBloc) => void;\n}\n\n/**\n * React hook that connects to a state container instance without triggering re-renders.\n * Use this when you only need to call actions on the bloc without subscribing to state changes.\n *\n * @template S - Optional state type override for generic StateContainers (defaults to never)\n * @template T - The state container constructor type (inferred from BlocClass)\n * @param BlocClass - The state container class to connect to\n * @param options - Configuration options for instance management and lifecycle\n * @returns The state container instance for calling actions\n *\n * @example Basic usage\n * ```ts\n * const myBloc = useBlocActions(MyBloc);\n * // Call methods on the bloc without re-rendering\n * myBloc.someMethod();\n * ```\n *\n * @example With isolated instance\n * ```ts\n * const myBloc = useBlocActions(MyBloc, {\n * instanceId: 'unique-id'\n * });\n * ```\n *\n * @example With generic bloc and explicit state type\n * ```ts\n * const myBloc = useBlocActions<MyStateType>(GenericBloc);\n * // myBloc.state is typed as MyStateType\n * ```\n */\nexport function useBlocActions<\n S = never,\n T extends new (...args: any[]) => StateContainer<any, any> = new (\n ...args: any[]\n ) => StateContainer<any, any>,\n>(\n BlocClass: T & BlocConstructor<InstanceType<T>>,\n options?: UseBlocActionsOptions<InstanceType<T>>,\n): StateOverride<InstanceType<T>, S> {\n const componentRef = useRef<ComponentRef>({});\n const initialPropsRef = useRef(options?.props);\n\n const [bloc, instanceKey] = useMemo(() => {\n const isIsolated = isIsolatedClass(BlocClass);\n\n const instanceKey = generateInstanceKey(\n componentRef.current,\n isIsolated,\n options?.instanceId,\n );\n\n const instance = BlocClass.resolve(instanceKey, initialPropsRef.current);\n\n return [instance, instanceKey] as const;\n }, [BlocClass]);\n\n useEffect(() => {\n if (options?.onMount) {\n options.onMount(bloc);\n }\n\n return () => {\n if (options?.onUnmount) {\n options.onUnmount(bloc);\n }\n\n BlocClass.release(instanceKey);\n\n if (isIsolatedClass(BlocClass) && !bloc.isDisposed) {\n bloc.dispose();\n }\n };\n }, []);\n\n return bloc as StateOverride<InstanceType<T>, S>;\n}\n"],"mappings":"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"}
package/dist/index.d.cts CHANGED
@@ -2,6 +2,7 @@ import { BlocConstructor } from '@blac/core';
2
2
  import type { ExtractState } from '@blac/core';
3
3
  import type { RefObject } from 'react';
4
4
  import { StateContainer } from '@blac/core';
5
+ import { StateOverride } from '@blac/core';
5
6
 
6
7
  /* Excluded from this release type: ComponentRef */
7
8
 
@@ -13,7 +14,8 @@ import { StateContainer } from '@blac/core';
13
14
  * - **Manual dependencies**: Explicit dependency array like useEffect
14
15
  * - **No tracking**: Returns full state without optimization
15
16
  *
16
- * @template T - The state container constructor type
17
+ * @template S - Optional state type override for generic StateContainers (defaults to never)
18
+ * @template T - The state container constructor type (inferred from BlocClass)
17
19
  * @param BlocClass - The state container class to connect to
18
20
  * @param options - Configuration options for tracking mode and instance management
19
21
  * @returns Tuple with [state, bloc instance, ref]
@@ -36,14 +38,21 @@ import { StateContainer } from '@blac/core';
36
38
  * instanceId: 'unique-id'
37
39
  * });
38
40
  * ```
41
+ *
42
+ * @example With generic bloc and explicit state type
43
+ * ```ts
44
+ * const [state, myBloc] = useBloc<MyStateType>(GenericBloc);
45
+ * // state is typed as MyStateType
46
+ * ```
39
47
  */
40
- export declare function useBloc<T extends new (...args: any[]) => StateContainer<any, any>>(BlocClass: T & BlocConstructor<InstanceType<T>>, options?: UseBlocOptions<InstanceType<T>>): UseBlocReturn<InstanceType<T>>;
48
+ export declare function useBloc<S = never, T extends new (...args: any[]) => StateContainer<any, any> = new (...args: any[]) => StateContainer<any, any>>(BlocClass: T & BlocConstructor<InstanceType<T>>, options?: UseBlocOptions<InstanceType<T>>): UseBlocReturn<InstanceType<T>, S>;
41
49
 
42
50
  /**
43
51
  * React hook that connects to a state container instance without triggering re-renders.
44
52
  * Use this when you only need to call actions on the bloc without subscribing to state changes.
45
53
  *
46
- * @template T - The state container constructor type
54
+ * @template S - Optional state type override for generic StateContainers (defaults to never)
55
+ * @template T - The state container constructor type (inferred from BlocClass)
47
56
  * @param BlocClass - The state container class to connect to
48
57
  * @param options - Configuration options for instance management and lifecycle
49
58
  * @returns The state container instance for calling actions
@@ -61,8 +70,14 @@ export declare function useBloc<T extends new (...args: any[]) => StateContainer
61
70
  * instanceId: 'unique-id'
62
71
  * });
63
72
  * ```
73
+ *
74
+ * @example With generic bloc and explicit state type
75
+ * ```ts
76
+ * const myBloc = useBlocActions<MyStateType>(GenericBloc);
77
+ * // myBloc.state is typed as MyStateType
78
+ * ```
64
79
  */
65
- export declare function useBlocActions<T extends new (...args: any[]) => StateContainer<any, any>>(BlocClass: T & BlocConstructor<InstanceType<T>>, options?: UseBlocActionsOptions<InstanceType<T>>): InstanceType<T>;
80
+ export declare function useBlocActions<S = never, T extends new (...args: any[]) => StateContainer<any, any> = new (...args: any[]) => StateContainer<any, any>>(BlocClass: T & BlocConstructor<InstanceType<T>>, options?: UseBlocActionsOptions<InstanceType<T>>): StateOverride<InstanceType<T>, S>;
66
81
 
67
82
  /**
68
83
  * Configuration options for useBlocActions hook
@@ -104,13 +119,18 @@ export declare interface UseBlocOptions<TBloc, TProps = any> {
104
119
 
105
120
  /**
106
121
  * Tuple return type from useBloc hook containing state, bloc instance, and ref
107
- * - [0] Current state value
122
+ * - [0] Current state value (with optional state type override)
108
123
  * - [1] State container instance (bloc) for calling actions
109
124
  * - [2] Ref object for accessing component ref (advanced use cases)
125
+ *
126
+ * @template TBloc - The state container type
127
+ * @template S - Optional state type override for generic StateContainers (defaults to never)
110
128
  */
111
- export declare type UseBlocReturn<TBloc> = [
112
- ExtractState<TBloc>,
113
- TBloc,
129
+ export declare type UseBlocReturn<TBloc extends StateContainer<any, any>, S = never> = [
130
+ [
131
+ S
132
+ ] extends [never] ? ExtractState<TBloc> : S,
133
+ StateOverride<TBloc, S>,
114
134
  RefObject<ComponentRef>
115
135
  ];
116
136
 
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ import { BlocConstructor } from '@blac/core';
2
2
  import type { ExtractState } from '@blac/core';
3
3
  import type { RefObject } from 'react';
4
4
  import { StateContainer } from '@blac/core';
5
+ import { StateOverride } from '@blac/core';
5
6
 
6
7
  /* Excluded from this release type: ComponentRef */
7
8
 
@@ -13,7 +14,8 @@ import { StateContainer } from '@blac/core';
13
14
  * - **Manual dependencies**: Explicit dependency array like useEffect
14
15
  * - **No tracking**: Returns full state without optimization
15
16
  *
16
- * @template T - The state container constructor type
17
+ * @template S - Optional state type override for generic StateContainers (defaults to never)
18
+ * @template T - The state container constructor type (inferred from BlocClass)
17
19
  * @param BlocClass - The state container class to connect to
18
20
  * @param options - Configuration options for tracking mode and instance management
19
21
  * @returns Tuple with [state, bloc instance, ref]
@@ -36,14 +38,21 @@ import { StateContainer } from '@blac/core';
36
38
  * instanceId: 'unique-id'
37
39
  * });
38
40
  * ```
41
+ *
42
+ * @example With generic bloc and explicit state type
43
+ * ```ts
44
+ * const [state, myBloc] = useBloc<MyStateType>(GenericBloc);
45
+ * // state is typed as MyStateType
46
+ * ```
39
47
  */
40
- export declare function useBloc<T extends new (...args: any[]) => StateContainer<any, any>>(BlocClass: T & BlocConstructor<InstanceType<T>>, options?: UseBlocOptions<InstanceType<T>>): UseBlocReturn<InstanceType<T>>;
48
+ export declare function useBloc<S = never, T extends new (...args: any[]) => StateContainer<any, any> = new (...args: any[]) => StateContainer<any, any>>(BlocClass: T & BlocConstructor<InstanceType<T>>, options?: UseBlocOptions<InstanceType<T>>): UseBlocReturn<InstanceType<T>, S>;
41
49
 
42
50
  /**
43
51
  * React hook that connects to a state container instance without triggering re-renders.
44
52
  * Use this when you only need to call actions on the bloc without subscribing to state changes.
45
53
  *
46
- * @template T - The state container constructor type
54
+ * @template S - Optional state type override for generic StateContainers (defaults to never)
55
+ * @template T - The state container constructor type (inferred from BlocClass)
47
56
  * @param BlocClass - The state container class to connect to
48
57
  * @param options - Configuration options for instance management and lifecycle
49
58
  * @returns The state container instance for calling actions
@@ -61,8 +70,14 @@ export declare function useBloc<T extends new (...args: any[]) => StateContainer
61
70
  * instanceId: 'unique-id'
62
71
  * });
63
72
  * ```
73
+ *
74
+ * @example With generic bloc and explicit state type
75
+ * ```ts
76
+ * const myBloc = useBlocActions<MyStateType>(GenericBloc);
77
+ * // myBloc.state is typed as MyStateType
78
+ * ```
64
79
  */
65
- export declare function useBlocActions<T extends new (...args: any[]) => StateContainer<any, any>>(BlocClass: T & BlocConstructor<InstanceType<T>>, options?: UseBlocActionsOptions<InstanceType<T>>): InstanceType<T>;
80
+ export declare function useBlocActions<S = never, T extends new (...args: any[]) => StateContainer<any, any> = new (...args: any[]) => StateContainer<any, any>>(BlocClass: T & BlocConstructor<InstanceType<T>>, options?: UseBlocActionsOptions<InstanceType<T>>): StateOverride<InstanceType<T>, S>;
66
81
 
67
82
  /**
68
83
  * Configuration options for useBlocActions hook
@@ -104,13 +119,18 @@ export declare interface UseBlocOptions<TBloc, TProps = any> {
104
119
 
105
120
  /**
106
121
  * Tuple return type from useBloc hook containing state, bloc instance, and ref
107
- * - [0] Current state value
122
+ * - [0] Current state value (with optional state type override)
108
123
  * - [1] State container instance (bloc) for calling actions
109
124
  * - [2] Ref object for accessing component ref (advanced use cases)
125
+ *
126
+ * @template TBloc - The state container type
127
+ * @template S - Optional state type override for generic StateContainers (defaults to never)
110
128
  */
111
- export declare type UseBlocReturn<TBloc> = [
112
- ExtractState<TBloc>,
113
- TBloc,
129
+ export declare type UseBlocReturn<TBloc extends StateContainer<any, any>, S = never> = [
130
+ [
131
+ S
132
+ ] extends [never] ? ExtractState<TBloc> : S,
133
+ StateOverride<TBloc, S>,
114
134
  RefObject<ComponentRef>
115
135
  ];
116
136
 
package/dist/index.js CHANGED
@@ -42,7 +42,8 @@ function determineTrackingMode(options) {
42
42
  * - **Manual dependencies**: Explicit dependency array like useEffect
43
43
  * - **No tracking**: Returns full state without optimization
44
44
  *
45
- * @template T - The state container constructor type
45
+ * @template S - Optional state type override for generic StateContainers (defaults to never)
46
+ * @template T - The state container constructor type (inferred from BlocClass)
46
47
  * @param BlocClass - The state container class to connect to
47
48
  * @param options - Configuration options for tracking mode and instance management
48
49
  * @returns Tuple with [state, bloc instance, ref]
@@ -65,10 +66,15 @@ function determineTrackingMode(options) {
65
66
  * instanceId: 'unique-id'
66
67
  * });
67
68
  * ```
69
+ *
70
+ * @example With generic bloc and explicit state type
71
+ * ```ts
72
+ * const [state, myBloc] = useBloc<MyStateType>(GenericBloc);
73
+ * // state is typed as MyStateType
74
+ * ```
68
75
  */
69
76
  function useBloc(BlocClass, options) {
70
77
  const componentRef = useRef({});
71
- const Constructor = BlocClass;
72
78
  const isIsolated = isIsolatedClass(BlocClass);
73
79
  const initialPropsRef = useRef(options?.props);
74
80
  const [bloc, subscribe, getSnapshot, instanceKey, adapterState, rawInstance] = useMemo(() => {
@@ -116,7 +122,7 @@ function useBloc(BlocClass, options) {
116
122
  return () => {
117
123
  externalDepsManager.current.cleanup();
118
124
  if (options?.onUnmount) options.onUnmount(bloc);
119
- Constructor.release(instanceKey);
125
+ BlocClass.release(instanceKey);
120
126
  if (isIsolated && !rawInstance.isDisposed) rawInstance.dispose();
121
127
  };
122
128
  }, []);
@@ -133,7 +139,8 @@ function useBloc(BlocClass, options) {
133
139
  * React hook that connects to a state container instance without triggering re-renders.
134
140
  * Use this when you only need to call actions on the bloc without subscribing to state changes.
135
141
  *
136
- * @template T - The state container constructor type
142
+ * @template S - Optional state type override for generic StateContainers (defaults to never)
143
+ * @template T - The state container constructor type (inferred from BlocClass)
137
144
  * @param BlocClass - The state container class to connect to
138
145
  * @param options - Configuration options for instance management and lifecycle
139
146
  * @returns The state container instance for calling actions
@@ -151,15 +158,20 @@ function useBloc(BlocClass, options) {
151
158
  * instanceId: 'unique-id'
152
159
  * });
153
160
  * ```
161
+ *
162
+ * @example With generic bloc and explicit state type
163
+ * ```ts
164
+ * const myBloc = useBlocActions<MyStateType>(GenericBloc);
165
+ * // myBloc.state is typed as MyStateType
166
+ * ```
154
167
  */
155
168
  function useBlocActions(BlocClass, options) {
156
169
  const componentRef = useRef({});
157
170
  const initialPropsRef = useRef(options?.props);
158
171
  const [bloc, instanceKey] = useMemo(() => {
159
172
  const isIsolated = isIsolatedClass(BlocClass);
160
- const Constructor = BlocClass;
161
173
  const instanceKey$1 = generateInstanceKey(componentRef.current, isIsolated, options?.instanceId);
162
- return [Constructor.resolve(instanceKey$1, initialPropsRef.current), instanceKey$1];
174
+ return [BlocClass.resolve(instanceKey$1, initialPropsRef.current), instanceKey$1];
163
175
  }, [BlocClass]);
164
176
  useEffect(() => {
165
177
  if (options?.onMount) options.onMount(bloc);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["instanceKey","subscribeFn: (callback: () => void) => () => void","getSnapshotFn: () => ExtractState<TBloc>","adapterState: AdapterState<TBloc>","adapterState","instanceKey"],"sources":["../src/utils/instance-keys.ts","../src/useBloc.ts","../src/useBlocActions.ts"],"sourcesContent":["/**\n * Instance key generation utilities for React integration\n */\n\nimport { generateIsolatedKey } from '@blac/core';\nimport type { ComponentRef } from '../types';\n\n/**\n * Generate an instance key for a bloc\n *\n * Logic:\n * - If user provides instanceId, use it (convert number to string)\n * - If isolated, generate or reuse a unique key for this component\n * - Otherwise, return undefined (use default key)\n *\n * @param componentRef - React component reference (persists across remounts)\n * @param isIsolated - Whether the bloc is isolated\n * @param providedId - User-provided instance ID (from options)\n * @returns Instance key string or undefined for default\n */\nexport function generateInstanceKey(\n componentRef: ComponentRef,\n isIsolated: boolean,\n providedId?: string | number,\n): string | undefined {\n // User explicitly provided an ID - use it\n if (providedId !== undefined) {\n return typeof providedId === 'number' ? String(providedId) : providedId;\n }\n\n // Isolated bloc - generate unique key per component\n if (isIsolated) {\n if (!componentRef.__blocInstanceId) {\n componentRef.__blocInstanceId = generateIsolatedKey();\n }\n return componentRef.__blocInstanceId;\n }\n\n // Shared bloc - use default key (undefined)\n return undefined;\n}\n","import {\n useMemo,\n useSyncExternalStore,\n useEffect,\n useRef,\n useReducer,\n} from 'react';\nimport {\n type BlocConstructor,\n StateContainer,\n type ExtractState,\n type AdapterState,\n ExternalDependencyManager,\n createAutoTrackSubscribe,\n createManualDepsSubscribe,\n createNoTrackSubscribe,\n createAutoTrackSnapshot,\n createManualDepsSnapshot,\n createNoTrackSnapshot,\n initAutoTrackState,\n initManualDepsState,\n initNoTrackState,\n disableGetterTracking,\n isIsolatedClass,\n} from '@blac/core';\nimport type { UseBlocOptions, UseBlocReturn, ComponentRef } from './types';\nimport { generateInstanceKey } from './utils/instance-keys';\n\ntype StateContainerConstructor<TBloc extends StateContainer<any, any>> =\n BlocConstructor<TBloc> & {\n resolve(instanceKey?: string, ...args: any[]): TBloc;\n release(instanceKey?: string): void;\n };\n\ninterface TrackingMode {\n useManualDeps: boolean;\n autoTrackEnabled: boolean;\n}\n\nfunction determineTrackingMode<TBloc extends StateContainer<any, any>>(\n options?: UseBlocOptions<TBloc>,\n): TrackingMode {\n return {\n useManualDeps: options?.dependencies !== undefined,\n autoTrackEnabled: options?.autoTrack !== false,\n };\n}\n\n/**\n * React hook that connects a component to a state container with automatic re-render on state changes.\n *\n * Supports three tracking modes:\n * - **Auto-tracking** (default): Automatically detects accessed state properties via Proxy\n * - **Manual dependencies**: Explicit dependency array like useEffect\n * - **No tracking**: Returns full state without optimization\n *\n * @template T - The state container constructor type\n * @param BlocClass - The state container class to connect to\n * @param options - Configuration options for tracking mode and instance management\n * @returns Tuple with [state, bloc instance, ref]\n *\n * @example Basic usage\n * ```ts\n * const [state, myBloc, ref] = useBloc(MyBloc);\n * ```\n *\n * @example With manual dependencies\n * ```ts\n * const [state, myBloc] = useBloc(MyBloc, {\n * dependencies: (state) => [state.count]\n * });\n * ```\n *\n * @example With isolated instance\n * ```ts\n * const [state, myBloc] = useBloc(MyBloc, {\n * instanceId: 'unique-id'\n * });\n * ```\n */\nexport function useBloc<\n T extends new (...args: any[]) => StateContainer<any, any>,\n>(\n BlocClass: T & BlocConstructor<InstanceType<T>>,\n options?: UseBlocOptions<InstanceType<T>>,\n): UseBlocReturn<InstanceType<T>> {\n type TBloc = InstanceType<T>;\n const componentRef = useRef<ComponentRef>({});\n const Constructor = BlocClass as StateContainerConstructor<TBloc>;\n const isIsolated = isIsolatedClass(BlocClass);\n\n const initialPropsRef = useRef(options?.props);\n\n const [bloc, subscribe, getSnapshot, instanceKey, adapterState, rawInstance] =\n useMemo<\n readonly [\n TBloc,\n (callback: () => void) => () => void,\n () => ExtractState<TBloc>,\n string | undefined,\n AdapterState<TBloc>,\n TBloc,\n ]\n >(() => {\n const instanceKey = generateInstanceKey(\n componentRef.current,\n isIsolated,\n options?.instanceId,\n );\n\n const instance = BlocClass.resolve(instanceKey, initialPropsRef.current);\n\n if (initialPropsRef.current !== undefined) {\n instance.updateProps(initialPropsRef.current);\n }\n\n const { useManualDeps, autoTrackEnabled } =\n determineTrackingMode(options);\n\n let subscribeFn: (callback: () => void) => () => void;\n let getSnapshotFn: () => ExtractState<TBloc>;\n let adapterState: AdapterState<TBloc>;\n\n if (useManualDeps && options?.dependencies) {\n adapterState = initManualDepsState(instance);\n subscribeFn = createManualDepsSubscribe(instance, adapterState, {\n dependencies: options.dependencies,\n });\n getSnapshotFn = createManualDepsSnapshot(instance, adapterState, {\n dependencies: options.dependencies,\n });\n } else if (!autoTrackEnabled) {\n adapterState = initNoTrackState(instance);\n subscribeFn = createNoTrackSubscribe(instance);\n getSnapshotFn = createNoTrackSnapshot(instance);\n } else {\n adapterState = initAutoTrackState(instance);\n subscribeFn = createAutoTrackSubscribe(instance, adapterState);\n getSnapshotFn = createAutoTrackSnapshot(instance, adapterState);\n }\n\n return [\n adapterState.proxiedBloc!,\n subscribeFn,\n getSnapshotFn,\n instanceKey,\n adapterState,\n instance,\n ];\n }, [BlocClass, options?.instanceId]);\n\n const state = useSyncExternalStore(subscribe, getSnapshot);\n\n const [, forceUpdate] = useReducer((x: number) => x + 1, 0);\n\n const externalDepsManager = useRef(new ExternalDependencyManager());\n\n useEffect(() => {\n if (options?.props !== initialPropsRef.current) {\n rawInstance.updateProps(options?.props);\n }\n }, [options?.props, rawInstance]);\n\n useEffect(() => {\n disableGetterTracking(adapterState, rawInstance);\n externalDepsManager.current.updateSubscriptions(\n adapterState.getterTracker,\n rawInstance,\n forceUpdate,\n );\n });\n\n useEffect(() => {\n if (options?.onMount) {\n options.onMount(bloc);\n }\n\n return () => {\n externalDepsManager.current.cleanup();\n\n if (options?.onUnmount) {\n options.onUnmount(bloc);\n }\n\n Constructor.release(instanceKey);\n\n if (isIsolated && !rawInstance.isDisposed) {\n rawInstance.dispose();\n }\n };\n }, []);\n\n return [state, bloc, componentRef] as UseBlocReturn<TBloc>;\n}\n","import { useMemo, useEffect, useRef } from 'react';\nimport {\n type BlocConstructor,\n StateContainer,\n isIsolatedClass,\n} from '@blac/core';\nimport type { ComponentRef } from './types';\nimport { generateInstanceKey } from './utils/instance-keys';\n\ntype StateContainerConstructor<TBloc extends StateContainer<any, any>> =\n BlocConstructor<TBloc> & {\n resolve(instanceKey?: string, ...args: any[]): TBloc;\n release(instanceKey?: string): void;\n };\n\n/**\n * Configuration options for useBlocActions hook\n * @template TBloc - The state container type\n * @template TProps - Props type passed to the container\n */\nexport interface UseBlocActionsOptions<TBloc, TProps = any> {\n /** Props passed to bloc constructor or updateProps */\n props?: TProps;\n /** Custom instance identifier for shared or isolated instances */\n instanceId?: string | number;\n /** Callback invoked when bloc instance mounts */\n onMount?: (bloc: TBloc) => void;\n /** Callback invoked when bloc instance unmounts */\n onUnmount?: (bloc: TBloc) => void;\n}\n\n/**\n * React hook that connects to a state container instance without triggering re-renders.\n * Use this when you only need to call actions on the bloc without subscribing to state changes.\n *\n * @template T - The state container constructor type\n * @param BlocClass - The state container class to connect to\n * @param options - Configuration options for instance management and lifecycle\n * @returns The state container instance for calling actions\n *\n * @example Basic usage\n * ```ts\n * const myBloc = useBlocActions(MyBloc);\n * // Call methods on the bloc without re-rendering\n * myBloc.someMethod();\n * ```\n *\n * @example With isolated instance\n * ```ts\n * const myBloc = useBlocActions(MyBloc, {\n * instanceId: 'unique-id'\n * });\n * ```\n */\nexport function useBlocActions<\n T extends new (...args: any[]) => StateContainer<any, any>,\n>(\n BlocClass: T & BlocConstructor<InstanceType<T>>,\n options?: UseBlocActionsOptions<InstanceType<T>>,\n): InstanceType<T> {\n type TBloc = InstanceType<T>;\n const componentRef = useRef<ComponentRef>({});\n const initialPropsRef = useRef(options?.props);\n\n const [bloc, instanceKey] = useMemo(() => {\n const isIsolated = isIsolatedClass(BlocClass);\n const Constructor = BlocClass as StateContainerConstructor<TBloc>;\n\n const instanceKey = generateInstanceKey(\n componentRef.current,\n isIsolated,\n options?.instanceId,\n );\n\n const instance = Constructor.resolve(instanceKey, initialPropsRef.current);\n\n return [instance, instanceKey] as const;\n }, [BlocClass]);\n\n useEffect(() => {\n if (options?.onMount) {\n options.onMount(bloc);\n }\n\n return () => {\n if (options?.onUnmount) {\n options.onUnmount(bloc);\n }\n\n const Constructor = BlocClass as StateContainerConstructor<TBloc>;\n Constructor.release(instanceKey);\n\n if (isIsolatedClass(BlocClass) && !bloc.isDisposed) {\n bloc.dispose();\n }\n };\n }, []);\n\n return bloc;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["instanceKey","subscribeFn: (callback: () => void) => () => void","getSnapshotFn: () => ExtractState<TBloc>","adapterState: AdapterState<TBloc>","adapterState","instanceKey"],"sources":["../src/utils/instance-keys.ts","../src/useBloc.ts","../src/useBlocActions.ts"],"sourcesContent":["/**\n * Instance key generation utilities for React integration\n */\n\nimport { generateIsolatedKey } from '@blac/core';\nimport type { ComponentRef } from '../types';\n\n/**\n * Generate an instance key for a bloc\n *\n * Logic:\n * - If user provides instanceId, use it (convert number to string)\n * - If isolated, generate or reuse a unique key for this component\n * - Otherwise, return undefined (use default key)\n *\n * @param componentRef - React component reference (persists across remounts)\n * @param isIsolated - Whether the bloc is isolated\n * @param providedId - User-provided instance ID (from options)\n * @returns Instance key string or undefined for default\n */\nexport function generateInstanceKey(\n componentRef: ComponentRef,\n isIsolated: boolean,\n providedId?: string | number,\n): string | undefined {\n // User explicitly provided an ID - use it\n if (providedId !== undefined) {\n return typeof providedId === 'number' ? String(providedId) : providedId;\n }\n\n // Isolated bloc - generate unique key per component\n if (isIsolated) {\n if (!componentRef.__blocInstanceId) {\n componentRef.__blocInstanceId = generateIsolatedKey();\n }\n return componentRef.__blocInstanceId;\n }\n\n // Shared bloc - use default key (undefined)\n return undefined;\n}\n","import {\n useMemo,\n useSyncExternalStore,\n useEffect,\n useRef,\n useReducer,\n} from 'react';\nimport {\n type BlocConstructor,\n StateContainer,\n type ExtractState,\n type AdapterState,\n ExternalDependencyManager,\n createAutoTrackSubscribe,\n createManualDepsSubscribe,\n createNoTrackSubscribe,\n createAutoTrackSnapshot,\n createManualDepsSnapshot,\n createNoTrackSnapshot,\n initAutoTrackState,\n initManualDepsState,\n initNoTrackState,\n disableGetterTracking,\n isIsolatedClass,\n} from '@blac/core';\nimport type { UseBlocOptions, UseBlocReturn, ComponentRef } from './types';\nimport { generateInstanceKey } from './utils/instance-keys';\n\ninterface TrackingMode {\n useManualDeps: boolean;\n autoTrackEnabled: boolean;\n}\n\nfunction determineTrackingMode<TBloc extends StateContainer<any, any>>(\n options?: UseBlocOptions<TBloc>,\n): TrackingMode {\n return {\n useManualDeps: options?.dependencies !== undefined,\n autoTrackEnabled: options?.autoTrack !== false,\n };\n}\n\n/**\n * React hook that connects a component to a state container with automatic re-render on state changes.\n *\n * Supports three tracking modes:\n * - **Auto-tracking** (default): Automatically detects accessed state properties via Proxy\n * - **Manual dependencies**: Explicit dependency array like useEffect\n * - **No tracking**: Returns full state without optimization\n *\n * @template S - Optional state type override for generic StateContainers (defaults to never)\n * @template T - The state container constructor type (inferred from BlocClass)\n * @param BlocClass - The state container class to connect to\n * @param options - Configuration options for tracking mode and instance management\n * @returns Tuple with [state, bloc instance, ref]\n *\n * @example Basic usage\n * ```ts\n * const [state, myBloc, ref] = useBloc(MyBloc);\n * ```\n *\n * @example With manual dependencies\n * ```ts\n * const [state, myBloc] = useBloc(MyBloc, {\n * dependencies: (state) => [state.count]\n * });\n * ```\n *\n * @example With isolated instance\n * ```ts\n * const [state, myBloc] = useBloc(MyBloc, {\n * instanceId: 'unique-id'\n * });\n * ```\n *\n * @example With generic bloc and explicit state type\n * ```ts\n * const [state, myBloc] = useBloc<MyStateType>(GenericBloc);\n * // state is typed as MyStateType\n * ```\n */\nexport function useBloc<\n S = never,\n T extends new (...args: any[]) => StateContainer<any, any> = new (\n ...args: any[]\n ) => StateContainer<any, any>,\n>(\n BlocClass: T & BlocConstructor<InstanceType<T>>,\n options?: UseBlocOptions<InstanceType<T>>,\n): UseBlocReturn<InstanceType<T>, S> {\n type TBloc = InstanceType<T>;\n const componentRef = useRef<ComponentRef>({});\n const isIsolated = isIsolatedClass(BlocClass);\n\n const initialPropsRef = useRef(options?.props);\n\n const [bloc, subscribe, getSnapshot, instanceKey, adapterState, rawInstance] =\n useMemo<\n readonly [\n TBloc,\n (callback: () => void) => () => void,\n () => ExtractState<TBloc>,\n string | undefined,\n AdapterState<TBloc>,\n TBloc,\n ]\n >(() => {\n const instanceKey = generateInstanceKey(\n componentRef.current,\n isIsolated,\n options?.instanceId,\n );\n\n const instance = BlocClass.resolve(instanceKey, initialPropsRef.current);\n\n if (initialPropsRef.current !== undefined) {\n instance.updateProps(initialPropsRef.current);\n }\n\n const { useManualDeps, autoTrackEnabled } =\n determineTrackingMode(options);\n\n let subscribeFn: (callback: () => void) => () => void;\n let getSnapshotFn: () => ExtractState<TBloc>;\n let adapterState: AdapterState<TBloc>;\n\n if (useManualDeps && options?.dependencies) {\n adapterState = initManualDepsState(instance);\n subscribeFn = createManualDepsSubscribe(instance, adapterState, {\n dependencies: options.dependencies,\n });\n getSnapshotFn = createManualDepsSnapshot(instance, adapterState, {\n dependencies: options.dependencies,\n });\n } else if (!autoTrackEnabled) {\n adapterState = initNoTrackState(instance);\n subscribeFn = createNoTrackSubscribe(instance);\n getSnapshotFn = createNoTrackSnapshot(instance);\n } else {\n adapterState = initAutoTrackState(instance);\n subscribeFn = createAutoTrackSubscribe(instance, adapterState);\n getSnapshotFn = createAutoTrackSnapshot(instance, adapterState);\n }\n\n return [\n adapterState.proxiedBloc!,\n subscribeFn,\n getSnapshotFn,\n instanceKey,\n adapterState,\n instance,\n ];\n }, [BlocClass, options?.instanceId]);\n\n const state = useSyncExternalStore(subscribe, getSnapshot);\n\n const [, forceUpdate] = useReducer((x: number) => x + 1, 0);\n\n const externalDepsManager = useRef(new ExternalDependencyManager());\n\n useEffect(() => {\n if (options?.props !== initialPropsRef.current) {\n rawInstance.updateProps(options?.props);\n }\n }, [options?.props, rawInstance]);\n\n useEffect(() => {\n disableGetterTracking(adapterState, rawInstance);\n externalDepsManager.current.updateSubscriptions(\n adapterState.getterTracker,\n rawInstance,\n forceUpdate,\n );\n });\n\n useEffect(() => {\n if (options?.onMount) {\n options.onMount(bloc);\n }\n\n return () => {\n externalDepsManager.current.cleanup();\n\n if (options?.onUnmount) {\n options.onUnmount(bloc);\n }\n\n BlocClass.release(instanceKey);\n\n if (isIsolated && !rawInstance.isDisposed) {\n rawInstance.dispose();\n }\n };\n }, []);\n\n return [state, bloc, componentRef] as UseBlocReturn<TBloc, S>;\n}\n","import { useMemo, useEffect, useRef } from 'react';\nimport {\n type BlocConstructor,\n type StateOverride,\n StateContainer,\n isIsolatedClass,\n} from '@blac/core';\nimport type { ComponentRef } from './types';\nimport { generateInstanceKey } from './utils/instance-keys';\n\n/**\n * Configuration options for useBlocActions hook\n * @template TBloc - The state container type\n * @template TProps - Props type passed to the container\n */\nexport interface UseBlocActionsOptions<TBloc, TProps = any> {\n /** Props passed to bloc constructor or updateProps */\n props?: TProps;\n /** Custom instance identifier for shared or isolated instances */\n instanceId?: string | number;\n /** Callback invoked when bloc instance mounts */\n onMount?: (bloc: TBloc) => void;\n /** Callback invoked when bloc instance unmounts */\n onUnmount?: (bloc: TBloc) => void;\n}\n\n/**\n * React hook that connects to a state container instance without triggering re-renders.\n * Use this when you only need to call actions on the bloc without subscribing to state changes.\n *\n * @template S - Optional state type override for generic StateContainers (defaults to never)\n * @template T - The state container constructor type (inferred from BlocClass)\n * @param BlocClass - The state container class to connect to\n * @param options - Configuration options for instance management and lifecycle\n * @returns The state container instance for calling actions\n *\n * @example Basic usage\n * ```ts\n * const myBloc = useBlocActions(MyBloc);\n * // Call methods on the bloc without re-rendering\n * myBloc.someMethod();\n * ```\n *\n * @example With isolated instance\n * ```ts\n * const myBloc = useBlocActions(MyBloc, {\n * instanceId: 'unique-id'\n * });\n * ```\n *\n * @example With generic bloc and explicit state type\n * ```ts\n * const myBloc = useBlocActions<MyStateType>(GenericBloc);\n * // myBloc.state is typed as MyStateType\n * ```\n */\nexport function useBlocActions<\n S = never,\n T extends new (...args: any[]) => StateContainer<any, any> = new (\n ...args: any[]\n ) => StateContainer<any, any>,\n>(\n BlocClass: T & BlocConstructor<InstanceType<T>>,\n options?: UseBlocActionsOptions<InstanceType<T>>,\n): StateOverride<InstanceType<T>, S> {\n const componentRef = useRef<ComponentRef>({});\n const initialPropsRef = useRef(options?.props);\n\n const [bloc, instanceKey] = useMemo(() => {\n const isIsolated = isIsolatedClass(BlocClass);\n\n const instanceKey = generateInstanceKey(\n componentRef.current,\n isIsolated,\n options?.instanceId,\n );\n\n const instance = BlocClass.resolve(instanceKey, initialPropsRef.current);\n\n return [instance, instanceKey] as const;\n }, [BlocClass]);\n\n useEffect(() => {\n if (options?.onMount) {\n options.onMount(bloc);\n }\n\n return () => {\n if (options?.onUnmount) {\n options.onUnmount(bloc);\n }\n\n BlocClass.release(instanceKey);\n\n if (isIsolatedClass(BlocClass) && !bloc.isDisposed) {\n bloc.dispose();\n }\n };\n }, []);\n\n return bloc as StateOverride<InstanceType<T>, S>;\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blac/react",
3
- "version": "2.0.0-rc.11",
3
+ "version": "2.0.0-rc.13",
4
4
  "license": "MIT",
5
5
  "author": "Brendan Mullins <jsnanigans@gmail.com>",
6
6
  "repository": {
@@ -49,7 +49,7 @@
49
49
  "peerDependencies": {
50
50
  "@types/react": "^18.0.0 || ^19.0.0",
51
51
  "react": "^18.0.0 || ^19.0.0",
52
- "@blac/core": "2.0.0-rc.11"
52
+ "@blac/core": "2.0.0-rc.13"
53
53
  },
54
54
  "peerDependenciesMeta": {
55
55
  "@types/react": {
@@ -78,7 +78,7 @@
78
78
  "tsdown": "^0.15.7",
79
79
  "typescript": "^5.9.2",
80
80
  "vitest": "3.2.4",
81
- "@blac/core": "2.0.0-rc.11"
81
+ "@blac/core": "2.0.0-rc.13"
82
82
  },
83
83
  "scripts": {
84
84
  "dev": "tsdown --watch",