You're Invited:Meet the Socket Team at RSAC and BSidesSF 2026, March 23–26.RSVP
Socket
Book a DemoSign in
Socket

@blac/react

Package Overview
Dependencies
Maintainers
1
Versions
76
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@blac/react - npm Package Compare versions

Comparing version
2.0.0-rc.10
to
2.0.0-rc.11
+1
dist/index.cjs.map
{"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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"}
{"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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"}
+55
-0

@@ -37,2 +37,34 @@ let react = require("react");

}
/**
* React hook that connects a component to a state container with automatic re-render on state changes.
*
* Supports three tracking modes:
* - **Auto-tracking** (default): Automatically detects accessed state properties via Proxy
* - **Manual dependencies**: Explicit dependency array like useEffect
* - **No tracking**: Returns full state without optimization
*
* @template T - The state container constructor type
* @param BlocClass - The state container class to connect to
* @param options - Configuration options for tracking mode and instance management
* @returns Tuple with [state, bloc instance, ref]
*
* @example Basic usage
* ```ts
* const [state, myBloc, ref] = useBloc(MyBloc);
* ```
*
* @example With manual dependencies
* ```ts
* const [state, myBloc] = useBloc(MyBloc, {
* dependencies: (state) => [state.count]
* });
* ```
*
* @example With isolated instance
* ```ts
* const [state, myBloc] = useBloc(MyBloc, {
* instanceId: 'unique-id'
* });
* ```
*/
function useBloc(BlocClass, options) {

@@ -101,2 +133,25 @@ const componentRef = (0, react.useRef)({});

//#region src/useBlocActions.ts
/**
* React hook that connects to a state container instance without triggering re-renders.
* Use this when you only need to call actions on the bloc without subscribing to state changes.
*
* @template T - The state container constructor type
* @param BlocClass - The state container class to connect to
* @param options - Configuration options for instance management and lifecycle
* @returns The state container instance for calling actions
*
* @example Basic usage
* ```ts
* const myBloc = useBlocActions(MyBloc);
* // Call methods on the bloc without re-rendering
* myBloc.someMethod();
* ```
*
* @example With isolated instance
* ```ts
* const myBloc = useBlocActions(MyBloc, {
* instanceId: 'unique-id'
* });
* ```
*/
function useBlocActions(BlocClass, options) {

@@ -103,0 +158,0 @@ const componentRef = (0, react.useRef)({});

+114
-9

@@ -0,12 +1,117 @@

import { BlocConstructor } from '@blac/core';
import type { ExtractState } from '@blac/core';
import type { RefObject } from 'react';
import { StateContainer } from '@blac/core';
/* Excluded from this release type: ComponentRef */
/**
* React Integration
* React hook that connects a component to a state container with automatic re-render on state changes.
*
* Clean integration between React and StateContainer architecture.
* Constructor-based API with automatic type inference.
* Supports concurrent (useSyncExternalStore) mode for optimal performance.
* Supports three tracking modes:
* - **Auto-tracking** (default): Automatically detects accessed state properties via Proxy
* - **Manual dependencies**: Explicit dependency array like useEffect
* - **No tracking**: Returns full state without optimization
*
* @template T - The state container constructor type
* @param BlocClass - The state container class to connect to
* @param options - Configuration options for tracking mode and instance management
* @returns Tuple with [state, bloc instance, ref]
*
* @example Basic usage
* ```ts
* const [state, myBloc, ref] = useBloc(MyBloc);
* ```
*
* @example With manual dependencies
* ```ts
* const [state, myBloc] = useBloc(MyBloc, {
* dependencies: (state) => [state.count]
* });
* ```
*
* @example With isolated instance
* ```ts
* const [state, myBloc] = useBloc(MyBloc, {
* instanceId: 'unique-id'
* });
* ```
*/
export { useBloc } from './useBloc';
export { useBlocActions } from './useBlocActions';
export type { UseBlocOptions, UseBlocReturn } from './types';
export type { UseBlocActionsOptions } from './useBlocActions';
//# sourceMappingURL=index.d.ts.map
export declare function useBloc<T extends new (...args: any[]) => StateContainer<any, any>>(BlocClass: T & BlocConstructor<InstanceType<T>>, options?: UseBlocOptions<InstanceType<T>>): UseBlocReturn<InstanceType<T>>;
/**
* React hook that connects to a state container instance without triggering re-renders.
* Use this when you only need to call actions on the bloc without subscribing to state changes.
*
* @template T - The state container constructor type
* @param BlocClass - The state container class to connect to
* @param options - Configuration options for instance management and lifecycle
* @returns The state container instance for calling actions
*
* @example Basic usage
* ```ts
* const myBloc = useBlocActions(MyBloc);
* // Call methods on the bloc without re-rendering
* myBloc.someMethod();
* ```
*
* @example With isolated instance
* ```ts
* const myBloc = useBlocActions(MyBloc, {
* instanceId: 'unique-id'
* });
* ```
*/
export declare function useBlocActions<T extends new (...args: any[]) => StateContainer<any, any>>(BlocClass: T & BlocConstructor<InstanceType<T>>, options?: UseBlocActionsOptions<InstanceType<T>>): InstanceType<T>;
/**
* Configuration options for useBlocActions hook
* @template TBloc - The state container type
* @template TProps - Props type passed to the container
*/
export declare interface UseBlocActionsOptions<TBloc, TProps = any> {
/** Props passed to bloc constructor or updateProps */
props?: TProps;
/** Custom instance identifier for shared or isolated instances */
instanceId?: string | number;
/** Callback invoked when bloc instance mounts */
onMount?: (bloc: TBloc) => void;
/** Callback invoked when bloc instance unmounts */
onUnmount?: (bloc: TBloc) => void;
}
/**
* Configuration options for useBloc hook
* @template TBloc - The state container type
* @template TProps - Props type passed to the container
*/
export declare interface UseBlocOptions<TBloc, TProps = any> {
/** Props passed to bloc constructor or updateProps */
props?: TProps;
/** Custom instance identifier for shared or isolated instances */
instanceId?: string | number;
/** Manual dependency array like useEffect (disables autoTrack) */
dependencies?: (state: ExtractState<TBloc>, bloc: TBloc) => unknown[];
/** Enable automatic property tracking via Proxy (default: true) */
autoTrack?: boolean;
/** Disable caching for getter tracking */
disableGetterCache?: boolean;
/** Callback invoked when bloc instance mounts */
onMount?: (bloc: TBloc) => void;
/** Callback invoked when bloc instance unmounts */
onUnmount?: (bloc: TBloc) => void;
}
/**
* Tuple return type from useBloc hook containing state, bloc instance, and ref
* - [0] Current state value
* - [1] State container instance (bloc) for calling actions
* - [2] Ref object for accessing component ref (advanced use cases)
*/
export declare type UseBlocReturn<TBloc> = [
ExtractState<TBloc>,
TBloc,
RefObject<ComponentRef>
];
export { }

@@ -0,12 +1,117 @@

import { BlocConstructor } from '@blac/core';
import type { ExtractState } from '@blac/core';
import type { RefObject } from 'react';
import { StateContainer } from '@blac/core';
/* Excluded from this release type: ComponentRef */
/**
* React Integration
* React hook that connects a component to a state container with automatic re-render on state changes.
*
* Clean integration between React and StateContainer architecture.
* Constructor-based API with automatic type inference.
* Supports concurrent (useSyncExternalStore) mode for optimal performance.
* Supports three tracking modes:
* - **Auto-tracking** (default): Automatically detects accessed state properties via Proxy
* - **Manual dependencies**: Explicit dependency array like useEffect
* - **No tracking**: Returns full state without optimization
*
* @template T - The state container constructor type
* @param BlocClass - The state container class to connect to
* @param options - Configuration options for tracking mode and instance management
* @returns Tuple with [state, bloc instance, ref]
*
* @example Basic usage
* ```ts
* const [state, myBloc, ref] = useBloc(MyBloc);
* ```
*
* @example With manual dependencies
* ```ts
* const [state, myBloc] = useBloc(MyBloc, {
* dependencies: (state) => [state.count]
* });
* ```
*
* @example With isolated instance
* ```ts
* const [state, myBloc] = useBloc(MyBloc, {
* instanceId: 'unique-id'
* });
* ```
*/
export { useBloc } from './useBloc';
export { useBlocActions } from './useBlocActions';
export type { UseBlocOptions, UseBlocReturn } from './types';
export type { UseBlocActionsOptions } from './useBlocActions';
//# sourceMappingURL=index.d.ts.map
export declare function useBloc<T extends new (...args: any[]) => StateContainer<any, any>>(BlocClass: T & BlocConstructor<InstanceType<T>>, options?: UseBlocOptions<InstanceType<T>>): UseBlocReturn<InstanceType<T>>;
/**
* React hook that connects to a state container instance without triggering re-renders.
* Use this when you only need to call actions on the bloc without subscribing to state changes.
*
* @template T - The state container constructor type
* @param BlocClass - The state container class to connect to
* @param options - Configuration options for instance management and lifecycle
* @returns The state container instance for calling actions
*
* @example Basic usage
* ```ts
* const myBloc = useBlocActions(MyBloc);
* // Call methods on the bloc without re-rendering
* myBloc.someMethod();
* ```
*
* @example With isolated instance
* ```ts
* const myBloc = useBlocActions(MyBloc, {
* instanceId: 'unique-id'
* });
* ```
*/
export declare function useBlocActions<T extends new (...args: any[]) => StateContainer<any, any>>(BlocClass: T & BlocConstructor<InstanceType<T>>, options?: UseBlocActionsOptions<InstanceType<T>>): InstanceType<T>;
/**
* Configuration options for useBlocActions hook
* @template TBloc - The state container type
* @template TProps - Props type passed to the container
*/
export declare interface UseBlocActionsOptions<TBloc, TProps = any> {
/** Props passed to bloc constructor or updateProps */
props?: TProps;
/** Custom instance identifier for shared or isolated instances */
instanceId?: string | number;
/** Callback invoked when bloc instance mounts */
onMount?: (bloc: TBloc) => void;
/** Callback invoked when bloc instance unmounts */
onUnmount?: (bloc: TBloc) => void;
}
/**
* Configuration options for useBloc hook
* @template TBloc - The state container type
* @template TProps - Props type passed to the container
*/
export declare interface UseBlocOptions<TBloc, TProps = any> {
/** Props passed to bloc constructor or updateProps */
props?: TProps;
/** Custom instance identifier for shared or isolated instances */
instanceId?: string | number;
/** Manual dependency array like useEffect (disables autoTrack) */
dependencies?: (state: ExtractState<TBloc>, bloc: TBloc) => unknown[];
/** Enable automatic property tracking via Proxy (default: true) */
autoTrack?: boolean;
/** Disable caching for getter tracking */
disableGetterCache?: boolean;
/** Callback invoked when bloc instance mounts */
onMount?: (bloc: TBloc) => void;
/** Callback invoked when bloc instance unmounts */
onUnmount?: (bloc: TBloc) => void;
}
/**
* Tuple return type from useBloc hook containing state, bloc instance, and ref
* - [0] Current state value
* - [1] State container instance (bloc) for calling actions
* - [2] Ref object for accessing component ref (advanced use cases)
*/
export declare type UseBlocReturn<TBloc> = [
ExtractState<TBloc>,
TBloc,
RefObject<ComponentRef>
];
export { }

@@ -37,2 +37,34 @@ import { useEffect, useMemo, useReducer, useRef, useSyncExternalStore } from "react";

}
/**
* React hook that connects a component to a state container with automatic re-render on state changes.
*
* Supports three tracking modes:
* - **Auto-tracking** (default): Automatically detects accessed state properties via Proxy
* - **Manual dependencies**: Explicit dependency array like useEffect
* - **No tracking**: Returns full state without optimization
*
* @template T - The state container constructor type
* @param BlocClass - The state container class to connect to
* @param options - Configuration options for tracking mode and instance management
* @returns Tuple with [state, bloc instance, ref]
*
* @example Basic usage
* ```ts
* const [state, myBloc, ref] = useBloc(MyBloc);
* ```
*
* @example With manual dependencies
* ```ts
* const [state, myBloc] = useBloc(MyBloc, {
* dependencies: (state) => [state.count]
* });
* ```
*
* @example With isolated instance
* ```ts
* const [state, myBloc] = useBloc(MyBloc, {
* instanceId: 'unique-id'
* });
* ```
*/
function useBloc(BlocClass, options) {

@@ -101,2 +133,25 @@ const componentRef = useRef({});

//#region src/useBlocActions.ts
/**
* React hook that connects to a state container instance without triggering re-renders.
* Use this when you only need to call actions on the bloc without subscribing to state changes.
*
* @template T - The state container constructor type
* @param BlocClass - The state container class to connect to
* @param options - Configuration options for instance management and lifecycle
* @returns The state container instance for calling actions
*
* @example Basic usage
* ```ts
* const myBloc = useBlocActions(MyBloc);
* // Call methods on the bloc without re-rendering
* myBloc.someMethod();
* ```
*
* @example With isolated instance
* ```ts
* const myBloc = useBlocActions(MyBloc, {
* instanceId: 'unique-id'
* });
* ```
*/
function useBlocActions(BlocClass, options) {

@@ -103,0 +158,0 @@ const componentRef = useRef({});

+12
-8
{
"name": "@blac/react",
"version": "2.0.0-rc.10",
"version": "2.0.0-rc.11",
"license": "MIT",

@@ -31,6 +31,7 @@ "author": "Brendan Mullins <jsnanigans@gmail.com>",

"files": [
"dist/**/*.js",
"dist/**/*.cjs",
"dist/**/*.d.ts",
"dist/**/*.d.cts",
"dist/index.js",
"dist/index.cjs",
"dist/index.d.ts",
"dist/index.d.cts",
"dist/*.map",
"README.md",

@@ -52,3 +53,3 @@ "LICENSE"

"react": "^18.0.0 || ^19.0.0",
"@blac/core": "2.0.0-rc.10"
"@blac/core": "2.0.0-rc.11"
},

@@ -82,7 +83,10 @@ "peerDependenciesMeta": {

"vitest": "3.2.4",
"@blac/core": "2.0.0-rc.10"
"@blac/core": "2.0.0-rc.11"
},
"scripts": {
"dev": "tsdown --watch",
"build": "tsdown && tsc -p tsconfig.build.json && cp dist/index.d.ts dist/index.d.cts",
"build": "pnpm build:js && pnpm build:types && pnpm build:dts",
"build:js": "tsdown",
"build:types": "tsc -p tsconfig.build.json",
"build:dts": "api-extractor run --local && cp dist/index.d.ts dist/index.d.cts && rm -rf dist/.types",
"clean": "rm -rf dist",

@@ -89,0 +93,0 @@ "format": "prettier --write \".\"",

import type { ExtractState } from '@blac/core';
import type { RefObject } from 'react';
export interface UseBlocOptions<TBloc, TProps = any> {
props?: TProps;
instanceId?: string | number;
dependencies?: (state: ExtractState<TBloc>, bloc: TBloc) => unknown[];
autoTrack?: boolean;
disableGetterCache?: boolean;
onMount?: (bloc: TBloc) => void;
onUnmount?: (bloc: TBloc) => void;
}
export interface UseBlocOptionsWithDependencies<TBloc, TProps = any> extends UseBlocOptions<TBloc, TProps> {
dependencies: (state: ExtractState<TBloc>, bloc: TBloc) => unknown[];
autoTrack?: never;
}
export type UseBlocReturn<TBloc> = [
ExtractState<TBloc>,
TBloc,
RefObject<ComponentRef>
];
export type ComponentRef = {
__blocInstanceId?: string;
__bridge?: any;
};
//# sourceMappingURL=types.d.ts.map
import { type BlocConstructor, StateContainer } from '@blac/core';
import type { UseBlocOptions, UseBlocReturn } from './types';
export declare function useBloc<T extends new (...args: any[]) => StateContainer<any, any>>(BlocClass: T & BlocConstructor<InstanceType<T>>, options?: UseBlocOptions<InstanceType<T>>): UseBlocReturn<InstanceType<T>>;
//# sourceMappingURL=useBloc.d.ts.map
import { type BlocConstructor, StateContainer } from '@blac/core';
export interface UseBlocActionsOptions<TBloc, TProps = any> {
props?: TProps;
instanceId?: string | number;
onMount?: (bloc: TBloc) => void;
onUnmount?: (bloc: TBloc) => void;
}
export declare function useBlocActions<T extends new (...args: any[]) => StateContainer<any, any>>(BlocClass: T & BlocConstructor<InstanceType<T>>, options?: UseBlocActionsOptions<InstanceType<T>>): InstanceType<T>;
//# sourceMappingURL=useBlocActions.d.ts.map
/**
* Instance key generation utilities for React integration
*/
import type { ComponentRef } from '../types';
/**
* Generate an instance key for a bloc
*
* Logic:
* - If user provides instanceId, use it (convert number to string)
* - If isolated, generate or reuse a unique key for this component
* - Otherwise, return undefined (use default key)
*
* @param componentRef - React component reference (persists across remounts)
* @param isIsolated - Whether the bloc is isolated
* @param providedId - User-provided instance ID (from options)
* @returns Instance key string or undefined for default
*/
export declare function generateInstanceKey(componentRef: ComponentRef, isIsolated: boolean, providedId?: string | number): string | undefined;
//# sourceMappingURL=instance-keys.d.ts.map