@blac/react 2.0.0-rc.8 → 2.0.0-rc.9
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blac/react",
|
|
3
|
-
"version": "2.0.0-rc.
|
|
3
|
+
"version": "2.0.0-rc.9",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Brendan Mullins <jsnanigans@gmail.com>",
|
|
6
6
|
"repository": {
|
|
@@ -32,7 +32,6 @@
|
|
|
32
32
|
"dist/**/*.cjs",
|
|
33
33
|
"dist/**/*.d.ts",
|
|
34
34
|
"dist/**/*.d.cts",
|
|
35
|
-
"dist/**/*.map",
|
|
36
35
|
"README.md",
|
|
37
36
|
"LICENSE"
|
|
38
37
|
],
|
|
@@ -49,7 +48,7 @@
|
|
|
49
48
|
"peerDependencies": {
|
|
50
49
|
"@types/react": "^18.0.0 || ^19.0.0",
|
|
51
50
|
"react": "^18.0.0 || ^19.0.0",
|
|
52
|
-
"@blac/core": "2.0.0-rc.
|
|
51
|
+
"@blac/core": "2.0.0-rc.9"
|
|
53
52
|
},
|
|
54
53
|
"peerDependenciesMeta": {
|
|
55
54
|
"@types/react": {
|
|
@@ -77,8 +76,8 @@
|
|
|
77
76
|
"react-dom": "^19.1.1",
|
|
78
77
|
"tsdown": "^0.15.7",
|
|
79
78
|
"typescript": "^5.9.2",
|
|
80
|
-
"vitest": "
|
|
81
|
-
"@blac/core": "2.0.0-rc.
|
|
79
|
+
"vitest": "3.2.4",
|
|
80
|
+
"@blac/core": "2.0.0-rc.9"
|
|
82
81
|
},
|
|
83
82
|
"scripts": {
|
|
84
83
|
"dev": "tsdown --watch",
|
package/dist/index.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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>> =\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>>(\n options?: UseBlocOptions<TBloc>,\n): TrackingMode {\n return {\n useManualDeps: options?.dependencies !== undefined,\n autoTrackEnabled: options?.autoTrack !== false,\n };\n}\n\n/**\n * Lifecycle: INITIAL MOUNT\n * 1. useMemo runs once - creates bloc, subscribeFn, getSnapshotFn\n * 2. useSyncExternalStore calls getSnapshotFn (1st time) - lazy creates tracker, starts tracking, returns proxy\n * 3. Component renders - proxy tracks property accesses\n * 4. useSyncExternalStore calls getSnapshotFn (2nd time) - captures tracked paths, starts new tracking, returns proxy\n * 5. useSyncExternalStore calls subscribeFn - sets up state change listener\n *\n * Lifecycle: STATE CHANGE\n * 1. Bloc state changes\n * 2. subscribeFn callback checks hasChanges() - only re-renders if tracked paths changed\n * 3. If re-render: getSnapshotFn captures previous paths, starts tracking, returns proxy\n *\n * Lifecycle: RE-RENDER (parent re-render)\n * 1. useMemo returns cached values (same bloc, subscribeFn, getSnapshotFn)\n * 2. useSyncExternalStore calls getSnapshotFn - captures paths, starts tracking, returns proxy\n */\nexport function useBloc<T extends new (...args: any[]) => StateContainer<any>>(\n BlocClass: T & BlocConstructor<InstanceType<T>>,\n options?: UseBlocOptions<InstanceType<T>>,\n): UseBlocReturn<InstanceType<T>> {\n // Component reference that persists across React Strict Mode remounts\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 [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 // Generate instance key\n const instanceKey = generateInstanceKey(\n componentRef.current,\n isIsolated,\n options?.instanceId,\n );\n\n // Get or create bloc instance with ownership (increments ref count)\n const instance = BlocClass.resolve(instanceKey, options?.staticProps);\n\n // Determine tracking mode\n const { useManualDeps, autoTrackEnabled } =\n determineTrackingMode(options);\n\n // Create subscribe and getSnapshot functions based on tracking mode\n let subscribeFn: (callback: () => void) => () => void;\n let getSnapshotFn: () => ExtractState<TBloc>;\n let adapterState: AdapterState<TBloc>;\n\n if (useManualDeps && options?.dependencies) {\n // Manual dependencies mode - no automatic tracking\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 // No tracking mode\n adapterState = initNoTrackState(instance);\n subscribeFn = createNoTrackSubscribe(instance);\n getSnapshotFn = createNoTrackSnapshot(instance);\n } else {\n // Auto-tracking mode - enable both state and getter tracking\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 // Force re-render mechanism for external bloc changes\n const [, forceUpdate] = useReducer((x: number) => x + 1, 0);\n\n // External dependency manager (persists across renders)\n const externalDepsManager = useRef(new ExternalDependencyManager());\n\n // Disable getter tracking and manage external bloc subscriptions after each render\n useEffect(() => {\n disableGetterTracking(adapterState, rawInstance);\n externalDepsManager.current.updateSubscriptions(\n adapterState.getterTracker,\n rawInstance,\n forceUpdate,\n );\n }); // Run on every render to pick up new dependencies and disable tracking\n\n // Mount/unmount lifecycle\n useEffect(() => {\n // Call onMount callback if provided\n if (options?.onMount) {\n options.onMount(bloc);\n }\n\n return () => {\n // Cleanup in proper order: subscriptions -> callbacks -> disposal\n\n // 1. Clean up external subscriptions FIRST (before bloc is disposed)\n externalDepsManager.current.cleanup();\n\n // 2. Call onUnmount callback if provided\n if (options?.onUnmount) {\n options.onUnmount(bloc);\n }\n\n // 3. Release bloc reference\n Constructor.release(instanceKey);\n\n // 4. For isolated instances, dispose manually since registry doesn't track them\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>> =\n BlocConstructor<TBloc> & {\n resolve(instanceKey?: string, ...args: any[]): TBloc;\n release(instanceKey?: string): void;\n };\n\nexport interface UseBlocActionsOptions<TBloc> {\n staticProps?: any;\n instanceId?: string | number;\n onMount?: (bloc: TBloc) => void;\n onUnmount?: (bloc: TBloc) => void;\n}\n\nexport function useBlocActions<\n T extends new (...args: any[]) => StateContainer<any>,\n>(\n BlocClass: T & BlocConstructor<InstanceType<T>>,\n options?: UseBlocActionsOptions<InstanceType<T>>,\n): InstanceType<T> {\n // Component reference that persists across React Strict Mode remounts\n type TBloc = InstanceType<T>;\n const componentRef = useRef<ComponentRef>({});\n\n const [bloc, instanceKey] = useMemo(() => {\n const isIsolated = isIsolatedClass(BlocClass);\n const Constructor = BlocClass as StateContainerConstructor<TBloc>;\n\n // Generate instance key\n const instanceKey = generateInstanceKey(\n componentRef.current,\n isIsolated,\n options?.instanceId,\n );\n\n // Get or create bloc instance with ownership (increments ref count)\n const instance = options?.staticProps\n ? Constructor.resolve(instanceKey, options.staticProps)\n : Constructor.resolve(instanceKey);\n\n return [instance, instanceKey] as const;\n }, [BlocClass]);\n\n // Mount/unmount lifecycle\n useEffect(() => {\n // Call onMount callback if provided\n if (options?.onMount) {\n options.onMount(bloc);\n }\n\n return () => {\n // Call onUnmount callback if provided\n if (options?.onUnmount) {\n options.onUnmount(bloc);\n }\n\n // Release bloc reference\n const Constructor = BlocClass as StateContainerConstructor<TBloc>;\n Constructor.release(instanceKey);\n\n // For isolated instances, dispose manually since registry doesn't track them\n if (isIsolatedClass(BlocClass) && !bloc.isDisposed) {\n bloc.dispose();\n }\n };\n }, []);\n\n return bloc;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAoBA,SAAgB,oBACd,cACA,YACA,YACoB;AAEpB,KAAI,eAAe,OACjB,QAAO,OAAO,eAAe,WAAW,OAAO,WAAW,GAAG;AAI/D,KAAI,YAAY;AACd,MAAI,CAAC,aAAa,iBAChB,cAAa,yDAAwC;AAEvD,SAAO,aAAa;;;;;;ACIxB,SAAS,sBACP,SACc;AACd,QAAO;EACL,eAAe,SAAS,iBAAiB;EACzC,kBAAkB,SAAS,cAAc;EAC1C;;;;;;;;;;;;;;;;;;;AAoBH,SAAgB,QACd,WACA,SACgC;CAGhC,MAAM,iCAAoC,EAAE,CAAC;CAC7C,MAAM,cAAc;CACpB,MAAM,8CAA6B,UAAU;CAE7C,MAAM,CAAC,MAAM,WAAW,aAAa,aAAa,cAAc,wCAUtD;EAEN,MAAMA,gBAAc,oBAClB,aAAa,SACb,YACA,SAAS,WACV;EAGD,MAAM,WAAW,UAAU,QAAQA,eAAa,SAAS,YAAY;EAGrE,MAAM,EAAE,eAAe,qBACrB,sBAAsB,QAAQ;EAGhC,IAAIC;EACJ,IAAIC;EACJ,IAAIC;AAEJ,MAAI,iBAAiB,SAAS,cAAc;AAE1C,yDAAmC,SAAS;AAC5C,4DAAwC,UAAUC,gBAAc,EAC9D,cAAc,QAAQ,cACvB,CAAC;AACF,6DAAyC,UAAUA,gBAAc,EAC/D,cAAc,QAAQ,cACvB,CAAC;aACO,CAAC,kBAAkB;AAE5B,sDAAgC,SAAS;AACzC,yDAAqC,SAAS;AAC9C,0DAAsC,SAAS;SAC1C;AAEL,wDAAkC,SAAS;AAC3C,2DAAuC,UAAUA,eAAa;AAC9D,4DAAwC,UAAUA,eAAa;;AAGjE,SAAO;GACLA,eAAa;GACb;GACA;GACAJ;GACAI;GACA;GACD;IACA,CAAC,WAAW,SAAS,WAAW,CAAC;CAEtC,MAAM,wCAA6B,WAAW,YAAY;CAG1D,MAAM,GAAG,sCAA2B,MAAc,IAAI,GAAG,EAAE;CAG3D,MAAM,wCAA6B,IAAIC,uCAA2B,CAAC;AAGnE,4BAAgB;AACd,yCAAsB,cAAc,YAAY;AAChD,sBAAoB,QAAQ,oBAC1B,aAAa,eACb,aACA,YACD;GACD;AAGF,4BAAgB;AAEd,MAAI,SAAS,QACX,SAAQ,QAAQ,KAAK;AAGvB,eAAa;AAIX,uBAAoB,QAAQ,SAAS;AAGrC,OAAI,SAAS,UACX,SAAQ,UAAU,KAAK;AAIzB,eAAY,QAAQ,YAAY;AAGhC,OAAI,cAAc,CAAC,YAAY,WAC7B,aAAY,SAAS;;IAGxB,EAAE,CAAC;AAEN,QAAO;EAAC;EAAO;EAAM;EAAa;;;;;AChKpC,SAAgB,eAGd,WACA,SACiB;CAGjB,MAAM,iCAAoC,EAAE,CAAC;CAE7C,MAAM,CAAC,MAAM,wCAA6B;EACxC,MAAM,8CAA6B,UAAU;EAC7C,MAAM,cAAc;EAGpB,MAAMC,gBAAc,oBAClB,aAAa,SACb,YACA,SAAS,WACV;AAOD,SAAO,CAJU,SAAS,cACtB,YAAY,QAAQA,eAAa,QAAQ,YAAY,GACrD,YAAY,QAAQA,cAAY,EAElBA,cAAY;IAC7B,CAAC,UAAU,CAAC;AAGf,4BAAgB;AAEd,MAAI,SAAS,QACX,SAAQ,QAAQ,KAAK;AAGvB,eAAa;AAEX,OAAI,SAAS,UACX,SAAQ,UAAU,KAAK;AAKzB,GADoB,UACR,QAAQ,YAAY;AAGhC,wCAAoB,UAAU,IAAI,CAAC,KAAK,WACtC,MAAK,SAAS;;IAGjB,EAAE,CAAC;AAEN,QAAO"}
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7D,YAAY,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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>> =\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>>(\n options?: UseBlocOptions<TBloc>,\n): TrackingMode {\n return {\n useManualDeps: options?.dependencies !== undefined,\n autoTrackEnabled: options?.autoTrack !== false,\n };\n}\n\n/**\n * Lifecycle: INITIAL MOUNT\n * 1. useMemo runs once - creates bloc, subscribeFn, getSnapshotFn\n * 2. useSyncExternalStore calls getSnapshotFn (1st time) - lazy creates tracker, starts tracking, returns proxy\n * 3. Component renders - proxy tracks property accesses\n * 4. useSyncExternalStore calls getSnapshotFn (2nd time) - captures tracked paths, starts new tracking, returns proxy\n * 5. useSyncExternalStore calls subscribeFn - sets up state change listener\n *\n * Lifecycle: STATE CHANGE\n * 1. Bloc state changes\n * 2. subscribeFn callback checks hasChanges() - only re-renders if tracked paths changed\n * 3. If re-render: getSnapshotFn captures previous paths, starts tracking, returns proxy\n *\n * Lifecycle: RE-RENDER (parent re-render)\n * 1. useMemo returns cached values (same bloc, subscribeFn, getSnapshotFn)\n * 2. useSyncExternalStore calls getSnapshotFn - captures paths, starts tracking, returns proxy\n */\nexport function useBloc<T extends new (...args: any[]) => StateContainer<any>>(\n BlocClass: T & BlocConstructor<InstanceType<T>>,\n options?: UseBlocOptions<InstanceType<T>>,\n): UseBlocReturn<InstanceType<T>> {\n // Component reference that persists across React Strict Mode remounts\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 [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 // Generate instance key\n const instanceKey = generateInstanceKey(\n componentRef.current,\n isIsolated,\n options?.instanceId,\n );\n\n // Get or create bloc instance with ownership (increments ref count)\n const instance = BlocClass.resolve(instanceKey, options?.staticProps);\n\n // Determine tracking mode\n const { useManualDeps, autoTrackEnabled } =\n determineTrackingMode(options);\n\n // Create subscribe and getSnapshot functions based on tracking mode\n let subscribeFn: (callback: () => void) => () => void;\n let getSnapshotFn: () => ExtractState<TBloc>;\n let adapterState: AdapterState<TBloc>;\n\n if (useManualDeps && options?.dependencies) {\n // Manual dependencies mode - no automatic tracking\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 // No tracking mode\n adapterState = initNoTrackState(instance);\n subscribeFn = createNoTrackSubscribe(instance);\n getSnapshotFn = createNoTrackSnapshot(instance);\n } else {\n // Auto-tracking mode - enable both state and getter tracking\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 // Force re-render mechanism for external bloc changes\n const [, forceUpdate] = useReducer((x: number) => x + 1, 0);\n\n // External dependency manager (persists across renders)\n const externalDepsManager = useRef(new ExternalDependencyManager());\n\n // Disable getter tracking and manage external bloc subscriptions after each render\n useEffect(() => {\n disableGetterTracking(adapterState, rawInstance);\n externalDepsManager.current.updateSubscriptions(\n adapterState.getterTracker,\n rawInstance,\n forceUpdate,\n );\n }); // Run on every render to pick up new dependencies and disable tracking\n\n // Mount/unmount lifecycle\n useEffect(() => {\n // Call onMount callback if provided\n if (options?.onMount) {\n options.onMount(bloc);\n }\n\n return () => {\n // Cleanup in proper order: subscriptions -> callbacks -> disposal\n\n // 1. Clean up external subscriptions FIRST (before bloc is disposed)\n externalDepsManager.current.cleanup();\n\n // 2. Call onUnmount callback if provided\n if (options?.onUnmount) {\n options.onUnmount(bloc);\n }\n\n // 3. Release bloc reference\n Constructor.release(instanceKey);\n\n // 4. For isolated instances, dispose manually since registry doesn't track them\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>> =\n BlocConstructor<TBloc> & {\n resolve(instanceKey?: string, ...args: any[]): TBloc;\n release(instanceKey?: string): void;\n };\n\nexport interface UseBlocActionsOptions<TBloc> {\n staticProps?: any;\n instanceId?: string | number;\n onMount?: (bloc: TBloc) => void;\n onUnmount?: (bloc: TBloc) => void;\n}\n\nexport function useBlocActions<\n T extends new (...args: any[]) => StateContainer<any>,\n>(\n BlocClass: T & BlocConstructor<InstanceType<T>>,\n options?: UseBlocActionsOptions<InstanceType<T>>,\n): InstanceType<T> {\n // Component reference that persists across React Strict Mode remounts\n type TBloc = InstanceType<T>;\n const componentRef = useRef<ComponentRef>({});\n\n const [bloc, instanceKey] = useMemo(() => {\n const isIsolated = isIsolatedClass(BlocClass);\n const Constructor = BlocClass as StateContainerConstructor<TBloc>;\n\n // Generate instance key\n const instanceKey = generateInstanceKey(\n componentRef.current,\n isIsolated,\n options?.instanceId,\n );\n\n // Get or create bloc instance with ownership (increments ref count)\n const instance = options?.staticProps\n ? Constructor.resolve(instanceKey, options.staticProps)\n : Constructor.resolve(instanceKey);\n\n return [instance, instanceKey] as const;\n }, [BlocClass]);\n\n // Mount/unmount lifecycle\n useEffect(() => {\n // Call onMount callback if provided\n if (options?.onMount) {\n options.onMount(bloc);\n }\n\n return () => {\n // Call onUnmount callback if provided\n if (options?.onUnmount) {\n options.onUnmount(bloc);\n }\n\n // Release bloc reference\n const Constructor = BlocClass as StateContainerConstructor<TBloc>;\n Constructor.release(instanceKey);\n\n // For isolated instances, dispose manually since registry doesn't track them\n if (isIsolatedClass(BlocClass) && !bloc.isDisposed) {\n bloc.dispose();\n }\n };\n }, []);\n\n return bloc;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAoBA,SAAgB,oBACd,cACA,YACA,YACoB;AAEpB,KAAI,eAAe,OACjB,QAAO,OAAO,eAAe,WAAW,OAAO,WAAW,GAAG;AAI/D,KAAI,YAAY;AACd,MAAI,CAAC,aAAa,iBAChB,cAAa,mBAAmB,qBAAqB;AAEvD,SAAO,aAAa;;;;;;ACIxB,SAAS,sBACP,SACc;AACd,QAAO;EACL,eAAe,SAAS,iBAAiB;EACzC,kBAAkB,SAAS,cAAc;EAC1C;;;;;;;;;;;;;;;;;;;AAoBH,SAAgB,QACd,WACA,SACgC;CAGhC,MAAM,eAAe,OAAqB,EAAE,CAAC;CAC7C,MAAM,cAAc;CACpB,MAAM,aAAa,gBAAgB,UAAU;CAE7C,MAAM,CAAC,MAAM,WAAW,aAAa,aAAa,cAAc,eAC9D,cASQ;EAEN,MAAMA,gBAAc,oBAClB,aAAa,SACb,YACA,SAAS,WACV;EAGD,MAAM,WAAW,UAAU,QAAQA,eAAa,SAAS,YAAY;EAGrE,MAAM,EAAE,eAAe,qBACrB,sBAAsB,QAAQ;EAGhC,IAAIC;EACJ,IAAIC;EACJ,IAAIC;AAEJ,MAAI,iBAAiB,SAAS,cAAc;AAE1C,oBAAe,oBAAoB,SAAS;AAC5C,iBAAc,0BAA0B,UAAUC,gBAAc,EAC9D,cAAc,QAAQ,cACvB,CAAC;AACF,mBAAgB,yBAAyB,UAAUA,gBAAc,EAC/D,cAAc,QAAQ,cACvB,CAAC;aACO,CAAC,kBAAkB;AAE5B,oBAAe,iBAAiB,SAAS;AACzC,iBAAc,uBAAuB,SAAS;AAC9C,mBAAgB,sBAAsB,SAAS;SAC1C;AAEL,oBAAe,mBAAmB,SAAS;AAC3C,iBAAc,yBAAyB,UAAUA,eAAa;AAC9D,mBAAgB,wBAAwB,UAAUA,eAAa;;AAGjE,SAAO;GACLA,eAAa;GACb;GACA;GACAJ;GACAI;GACA;GACD;IACA,CAAC,WAAW,SAAS,WAAW,CAAC;CAEtC,MAAM,QAAQ,qBAAqB,WAAW,YAAY;CAG1D,MAAM,GAAG,eAAe,YAAY,MAAc,IAAI,GAAG,EAAE;CAG3D,MAAM,sBAAsB,OAAO,IAAI,2BAA2B,CAAC;AAGnE,iBAAgB;AACd,wBAAsB,cAAc,YAAY;AAChD,sBAAoB,QAAQ,oBAC1B,aAAa,eACb,aACA,YACD;GACD;AAGF,iBAAgB;AAEd,MAAI,SAAS,QACX,SAAQ,QAAQ,KAAK;AAGvB,eAAa;AAIX,uBAAoB,QAAQ,SAAS;AAGrC,OAAI,SAAS,UACX,SAAQ,UAAU,KAAK;AAIzB,eAAY,QAAQ,YAAY;AAGhC,OAAI,cAAc,CAAC,YAAY,WAC7B,aAAY,SAAS;;IAGxB,EAAE,CAAC;AAEN,QAAO;EAAC;EAAO;EAAM;EAAa;;;;;AChKpC,SAAgB,eAGd,WACA,SACiB;CAGjB,MAAM,eAAe,OAAqB,EAAE,CAAC;CAE7C,MAAM,CAAC,MAAM,eAAe,cAAc;EACxC,MAAM,aAAa,gBAAgB,UAAU;EAC7C,MAAM,cAAc;EAGpB,MAAMC,gBAAc,oBAClB,aAAa,SACb,YACA,SAAS,WACV;AAOD,SAAO,CAJU,SAAS,cACtB,YAAY,QAAQA,eAAa,QAAQ,YAAY,GACrD,YAAY,QAAQA,cAAY,EAElBA,cAAY;IAC7B,CAAC,UAAU,CAAC;AAGf,iBAAgB;AAEd,MAAI,SAAS,QACX,SAAQ,QAAQ,KAAK;AAGvB,eAAa;AAEX,OAAI,SAAS,UACX,SAAQ,UAAU,KAAK;AAKzB,GADoB,UACR,QAAQ,YAAY;AAGhC,OAAI,gBAAgB,UAAU,IAAI,CAAC,KAAK,WACtC,MAAK,SAAS;;IAGjB,EAAE,CAAC;AAEN,QAAO"}
|
package/dist/types.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,WAAW,cAAc,CAAC,KAAK;IACnC,WAAW,CAAC,EAAE,GAAG,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,KAAK,KAAK,OAAO,EAAE,CAAC;IACtE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,IAAI,CAAC;IAChC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,8BAA8B,CAAC,KAAK,CACnD,SAAQ,cAAc,CAAC,KAAK,CAAC;IAC7B,YAAY,EAAE,CAAC,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,KAAK,KAAK,OAAO,EAAE,CAAC;IACrE,SAAS,CAAC,EAAE,KAAK,CAAC;CACnB;AAED,MAAM,MAAM,aAAa,CAAC,KAAK,IAAI;IACjC,YAAY,CAAC,KAAK,CAAC;IACnB,KAAK;IACL,SAAS,CAAC,YAAY,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,GAAG,CAAC;CAChB,CAAC"}
|
package/dist/useBloc.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useBloc.d.ts","sourceRoot":"","sources":["../src/useBloc.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,KAAK,eAAe,EACpB,cAAc,EAef,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAgB,MAAM,SAAS,CAAC;AAuB3E;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,OAAO,CAAC,CAAC,SAAS,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,cAAc,CAAC,GAAG,CAAC,EAC3E,SAAS,EAAE,CAAC,GAAG,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAC/C,OAAO,CAAC,EAAE,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,GACxC,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAmHhC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useBlocActions.d.ts","sourceRoot":"","sources":["../src/useBlocActions.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,eAAe,EACpB,cAAc,EAEf,MAAM,YAAY,CAAC;AAUpB,MAAM,WAAW,qBAAqB,CAAC,KAAK;IAC1C,WAAW,CAAC,EAAE,GAAG,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,IAAI,CAAC;IAChC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,IAAI,CAAC;CACnC;AAED,wBAAgB,cAAc,CAC5B,CAAC,SAAS,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,cAAc,CAAC,GAAG,CAAC,EAErD,SAAS,EAAE,CAAC,GAAG,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAC/C,OAAO,CAAC,EAAE,qBAAqB,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,GAC/C,YAAY,CAAC,CAAC,CAAC,CAiDjB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"instance-keys.d.ts","sourceRoot":"","sources":["../../src/utils/instance-keys.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7C;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,YAAY,EAC1B,UAAU,EAAE,OAAO,EACnB,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,GAC3B,MAAM,GAAG,SAAS,CAgBpB"}
|