@blac/react 2.0.7 → 2.0.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/dist/index.cjs +5 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/testing.cjs +40 -0
- package/dist/testing.cjs.map +1 -0
- package/dist/testing.d.cts +14 -0
- package/dist/testing.d.ts +14 -0
- package/dist/testing.js +38 -0
- package/dist/testing.js.map +1 -0
- package/package.json +33 -22
package/dist/index.cjs
CHANGED
|
@@ -126,7 +126,11 @@ function useBloc(BlocClass, options) {
|
|
|
126
126
|
const manager = externalDepsManager.current;
|
|
127
127
|
(0, _blac_adapter.disableGetterTracking)(adapterState, rawInstance);
|
|
128
128
|
manager.updateSubscriptions(adapterState.getterState, rawInstance, forceUpdate);
|
|
129
|
-
}
|
|
129
|
+
}, [
|
|
130
|
+
adapterState,
|
|
131
|
+
rawInstance,
|
|
132
|
+
forceUpdate
|
|
133
|
+
]);
|
|
130
134
|
(0, react.useEffect)(() => {
|
|
131
135
|
const manager = externalDepsManager.current;
|
|
132
136
|
if (options?.onMount) options.onMount(bloc);
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["ExternalDepsManager"],"sources":["../src/config.ts","../src/useBloc.ts"],"sourcesContent":["/**\n * Global configuration for @blac/react\n */\n\nexport interface BlacReactConfig {\n /** Enable automatic property tracking via Proxy (default: true) */\n autoTrack: boolean;\n}\n\nconst defaultConfig: BlacReactConfig = {\n autoTrack: true,\n};\n\nlet globalConfig: BlacReactConfig = { ...defaultConfig };\n\n/**\n * Configure global defaults for @blac/react hooks.\n *\n * @example\n * ```ts\n * import { configureBlacReact } from '@blac/react';\n *\n * // Disable auto-tracking globally\n * configureBlacReact({\n * autoTrack: false\n * });\n * ```\n *\n * @param config - Partial configuration to merge with defaults\n */\nexport function configureBlacReact(config: Partial<BlacReactConfig>): void {\n globalConfig = { ...globalConfig, ...config };\n}\n\n/**\n * Get the current global configuration.\n * @internal\n */\nexport function getBlacReactConfig(): BlacReactConfig {\n return globalConfig;\n}\n\n/**\n * Reset configuration to defaults (useful for testing).\n * @internal\n */\nexport function resetBlacReactConfig(): void {\n globalConfig = { ...defaultConfig };\n}\n","import {\n useMemo,\n useSyncExternalStore,\n useEffect,\n useRef,\n useReducer,\n} from 'react';\nimport {\n type ExtractState,\n type AdapterState,\n ExternalDepsManager,\n autoTrackSubscribe,\n manualDepsSubscribe,\n noTrackSubscribe,\n autoTrackSnapshot,\n manualDepsSnapshot,\n noTrackSnapshot,\n autoTrackInit,\n manualDepsInit,\n noTrackInit,\n disableGetterTracking,\n type StateContainerConstructor,\n type InstanceState,\n acquire,\n release,\n} from '@blac/adapter';\nimport type { UseBlocOptions, UseBlocReturn, ComponentRef } from './types';\nimport { getBlacReactConfig } from './config';\n\ninterface TrackingMode {\n useManualDeps: boolean;\n autoTrackEnabled: boolean;\n}\n\nfunction determineTrackingMode<TBloc extends StateContainerConstructor>(\n options?: Pick<UseBlocOptions<TBloc>, 'autoTrack' | 'dependencies'>,\n): TrackingMode {\n const globalConfig = getBlacReactConfig();\n const autoTrackEnabled =\n options?.autoTrack !== undefined\n ? options.autoTrack\n : globalConfig.autoTrack;\n\n return {\n useManualDeps: options?.dependencies !== undefined,\n autoTrackEnabled,\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 (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 named instance\n * ```ts\n * const [state, myBloc] = useBloc(MyBloc, {\n * instanceId: 'unique-id'\n * });\n * ```\n */\nexport function useBloc<\n T extends StateContainerConstructor = StateContainerConstructor,\n>(\n BlocClass: T,\n options?: UseBlocOptions<T>,\n): UseBlocReturn<T, ExtractState<T>> {\n type TBloc = InstanceState<T>;\n\n const componentRef = useRef<ComponentRef>({});\n const depsRef = useRef(options?.dependencies);\n depsRef.current = options?.dependencies;\n const instanceId = options?.instanceId;\n const autoTrack = options?.autoTrack;\n const dependencies = options?.dependencies;\n\n const [bloc, subscribe, getSnapshot, instanceKey, adapterState, rawInstance] =\n useMemo<\n readonly [\n TBloc,\n (callback: () => void) => () => void,\n () => ExtractState<T>,\n string | undefined,\n AdapterState<T>,\n TBloc,\n ]\n >(() => {\n const instanceKey =\n instanceId !== undefined ? String(instanceId) : undefined;\n\n const instance = acquire(BlocClass, instanceKey) as TBloc;\n\n const { useManualDeps, autoTrackEnabled } = determineTrackingMode({\n autoTrack,\n dependencies,\n });\n\n let subscribeFn: (callback: () => void) => () => void;\n let getSnapshotFn: () => ExtractState<T>;\n let adapterState: AdapterState<T>;\n\n if (useManualDeps && dependencies) {\n adapterState = manualDepsInit(instance);\n const stableConfig = {\n dependencies: (state: ExtractState<T>, bloc: InstanceState<T>) => {\n const deps = depsRef.current;\n return deps ? deps(state, bloc) : [];\n },\n };\n subscribeFn = manualDepsSubscribe(instance, adapterState, stableConfig);\n getSnapshotFn = manualDepsSnapshot(\n instance,\n adapterState,\n stableConfig,\n );\n } else if (!autoTrackEnabled) {\n adapterState = noTrackInit(instance);\n subscribeFn = noTrackSubscribe(instance);\n getSnapshotFn = noTrackSnapshot(instance);\n } else {\n adapterState = autoTrackInit(instance);\n subscribeFn = autoTrackSubscribe(instance, adapterState);\n getSnapshotFn = autoTrackSnapshot(instance, adapterState);\n }\n\n const safeSubscribeFn = (callback: () => void) => {\n if (instance.isDisposed) return () => {};\n return subscribeFn(callback);\n };\n\n return [\n adapterState.proxiedBloc as TBloc,\n safeSubscribeFn,\n getSnapshotFn,\n instanceKey,\n adapterState,\n instance,\n ];\n //
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["ExternalDepsManager"],"sources":["../src/config.ts","../src/useBloc.ts"],"sourcesContent":["/**\n * Global configuration for @blac/react\n */\n\nexport interface BlacReactConfig {\n /** Enable automatic property tracking via Proxy (default: true) */\n autoTrack: boolean;\n}\n\nconst defaultConfig: BlacReactConfig = {\n autoTrack: true,\n};\n\nlet globalConfig: BlacReactConfig = { ...defaultConfig };\n\n/**\n * Configure global defaults for @blac/react hooks.\n *\n * @example\n * ```ts\n * import { configureBlacReact } from '@blac/react';\n *\n * // Disable auto-tracking globally\n * configureBlacReact({\n * autoTrack: false\n * });\n * ```\n *\n * @param config - Partial configuration to merge with defaults\n */\nexport function configureBlacReact(config: Partial<BlacReactConfig>): void {\n globalConfig = { ...globalConfig, ...config };\n}\n\n/**\n * Get the current global configuration.\n * @internal\n */\nexport function getBlacReactConfig(): BlacReactConfig {\n return globalConfig;\n}\n\n/**\n * Reset configuration to defaults (useful for testing).\n * @internal\n */\nexport function resetBlacReactConfig(): void {\n globalConfig = { ...defaultConfig };\n}\n","import {\n useMemo,\n useSyncExternalStore,\n useEffect,\n useRef,\n useReducer,\n} from 'react';\nimport {\n type ExtractState,\n type AdapterState,\n ExternalDepsManager,\n autoTrackSubscribe,\n manualDepsSubscribe,\n noTrackSubscribe,\n autoTrackSnapshot,\n manualDepsSnapshot,\n noTrackSnapshot,\n autoTrackInit,\n manualDepsInit,\n noTrackInit,\n disableGetterTracking,\n type StateContainerConstructor,\n type InstanceState,\n acquire,\n release,\n} from '@blac/adapter';\nimport type { UseBlocOptions, UseBlocReturn, ComponentRef } from './types';\nimport { getBlacReactConfig } from './config';\n\ninterface TrackingMode {\n useManualDeps: boolean;\n autoTrackEnabled: boolean;\n}\n\nfunction determineTrackingMode<TBloc extends StateContainerConstructor>(\n options?: Pick<UseBlocOptions<TBloc>, 'autoTrack' | 'dependencies'>,\n): TrackingMode {\n const globalConfig = getBlacReactConfig();\n const autoTrackEnabled =\n options?.autoTrack !== undefined\n ? options.autoTrack\n : globalConfig.autoTrack;\n\n return {\n useManualDeps: options?.dependencies !== undefined,\n autoTrackEnabled,\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 (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 named instance\n * ```ts\n * const [state, myBloc] = useBloc(MyBloc, {\n * instanceId: 'unique-id'\n * });\n * ```\n */\nexport function useBloc<\n T extends StateContainerConstructor = StateContainerConstructor,\n>(\n BlocClass: T,\n options?: UseBlocOptions<T>,\n): UseBlocReturn<T, ExtractState<T>> {\n type TBloc = InstanceState<T>;\n\n const componentRef = useRef<ComponentRef>({});\n const depsRef = useRef(options?.dependencies);\n depsRef.current = options?.dependencies;\n const instanceId = options?.instanceId;\n const autoTrack = options?.autoTrack;\n const dependencies = options?.dependencies;\n\n const [bloc, subscribe, getSnapshot, instanceKey, adapterState, rawInstance] =\n useMemo<\n readonly [\n TBloc,\n (callback: () => void) => () => void,\n () => ExtractState<T>,\n string | undefined,\n AdapterState<T>,\n TBloc,\n ]\n >(() => {\n const instanceKey =\n instanceId !== undefined ? String(instanceId) : undefined;\n\n const instance = acquire(BlocClass, instanceKey) as TBloc;\n\n const { useManualDeps, autoTrackEnabled } = determineTrackingMode({\n autoTrack,\n dependencies,\n });\n\n let subscribeFn: (callback: () => void) => () => void;\n let getSnapshotFn: () => ExtractState<T>;\n let adapterState: AdapterState<T>;\n\n if (useManualDeps && dependencies) {\n adapterState = manualDepsInit(instance);\n const stableConfig = {\n dependencies: (state: ExtractState<T>, bloc: InstanceState<T>) => {\n const deps = depsRef.current;\n return deps ? deps(state, bloc) : [];\n },\n };\n subscribeFn = manualDepsSubscribe(instance, adapterState, stableConfig);\n getSnapshotFn = manualDepsSnapshot(\n instance,\n adapterState,\n stableConfig,\n );\n } else if (!autoTrackEnabled) {\n adapterState = noTrackInit(instance);\n subscribeFn = noTrackSubscribe(instance);\n getSnapshotFn = noTrackSnapshot(instance);\n } else {\n adapterState = autoTrackInit(instance);\n subscribeFn = autoTrackSubscribe(instance, adapterState);\n getSnapshotFn = autoTrackSnapshot(instance, adapterState);\n }\n\n const safeSubscribeFn = (callback: () => void) => {\n if (instance.isDisposed) return () => {};\n return subscribeFn(callback);\n };\n\n return [\n adapterState.proxiedBloc as TBloc,\n safeSubscribeFn,\n getSnapshotFn,\n instanceKey,\n adapterState,\n instance,\n ];\n // oxlint-disable-next-line react-hooks/exhaustive-deps\n }, [BlocClass, instanceId]);\n\n const state = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n const [, forceUpdate] = useReducer((x: number) => x + 1, 0);\n\n const externalDepsManager = useRef(new ExternalDepsManager());\n\n useEffect(() => {\n const manager = externalDepsManager.current;\n disableGetterTracking(adapterState, rawInstance);\n manager.updateSubscriptions(\n adapterState.getterState,\n rawInstance,\n forceUpdate,\n );\n }, [adapterState, rawInstance, forceUpdate]);\n\n useEffect(() => {\n const manager = externalDepsManager.current;\n if (options?.onMount) {\n options.onMount(bloc as InstanceType<T>);\n }\n\n return () => {\n manager.cleanup();\n\n if (options?.onUnmount) {\n options.onUnmount(bloc as InstanceType<T>);\n }\n\n release(BlocClass, instanceKey);\n };\n // oxlint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return [state, bloc, componentRef] as UseBlocReturn<T, ExtractState<T>>;\n}\n"],"mappings":";;;AAaA,IAAI,eAAgC,EAHlC,WAAW,MAG2C;;;;;;;;;;;;;;;;AAiBxD,SAAgB,mBAAmB,QAAwC;AACzE,gBAAe;EAAE,GAAG;EAAc,GAAG;EAAQ;;;;;;AAO/C,SAAgB,qBAAsC;AACpD,QAAO;;;;ACLT,SAAS,sBACP,SACc;CACd,MAAM,eAAe,oBAAoB;CACzC,MAAM,mBACJ,SAAS,cAAc,KAAA,IACnB,QAAQ,YACR,aAAa;AAEnB,QAAO;EACL,eAAe,SAAS,iBAAiB,KAAA;EACzC;EACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCH,SAAgB,QAGd,WACA,SACmC;CAGnC,MAAM,gBAAA,GAAA,MAAA,QAAoC,EAAE,CAAC;CAC7C,MAAM,WAAA,GAAA,MAAA,QAAiB,SAAS,aAAa;AAC7C,SAAQ,UAAU,SAAS;CAC3B,MAAM,aAAa,SAAS;CAC5B,MAAM,YAAY,SAAS;CAC3B,MAAM,eAAe,SAAS;CAE9B,MAAM,CAAC,MAAM,WAAW,aAAa,aAAa,cAAc,gBAAA,GAAA,MAAA,eAUtD;EACN,MAAM,cACJ,eAAe,KAAA,IAAY,OAAO,WAAW,GAAG,KAAA;EAElD,MAAM,YAAA,GAAA,cAAA,SAAmB,WAAW,YAAY;EAEhD,MAAM,EAAE,eAAe,qBAAqB,sBAAsB;GAChE;GACA;GACD,CAAC;EAEF,IAAI;EACJ,IAAI;EACJ,IAAI;AAEJ,MAAI,iBAAiB,cAAc;AACjC,mBAAA,GAAA,cAAA,gBAA8B,SAAS;GACvC,MAAM,eAAe,EACnB,eAAe,OAAwB,SAA2B;IAChE,MAAM,OAAO,QAAQ;AACrB,WAAO,OAAO,KAAK,OAAO,KAAK,GAAG,EAAE;MAEvC;AACD,kBAAA,GAAA,cAAA,qBAAkC,UAAU,cAAc,aAAa;AACvE,oBAAA,GAAA,cAAA,oBACE,UACA,cACA,aACD;aACQ,CAAC,kBAAkB;AAC5B,mBAAA,GAAA,cAAA,aAA2B,SAAS;AACpC,kBAAA,GAAA,cAAA,kBAA+B,SAAS;AACxC,oBAAA,GAAA,cAAA,iBAAgC,SAAS;SACpC;AACL,mBAAA,GAAA,cAAA,eAA6B,SAAS;AACtC,kBAAA,GAAA,cAAA,oBAAiC,UAAU,aAAa;AACxD,oBAAA,GAAA,cAAA,mBAAkC,UAAU,aAAa;;EAG3D,MAAM,mBAAmB,aAAyB;AAChD,OAAI,SAAS,WAAY,cAAa;AACtC,UAAO,YAAY,SAAS;;AAG9B,SAAO;GACL,aAAa;GACb;GACA;GACA;GACA;GACA;GACD;IAEA,CAAC,WAAW,WAAW,CAAC;CAE7B,MAAM,SAAA,GAAA,MAAA,sBAA6B,WAAW,aAAa,YAAY;CAEvE,MAAM,GAAG,gBAAA,GAAA,MAAA,aAA2B,MAAc,IAAI,GAAG,EAAE;CAE3D,MAAM,uBAAA,GAAA,MAAA,QAA6B,IAAIA,cAAAA,qBAAqB,CAAC;AAE7D,EAAA,GAAA,MAAA,iBAAgB;EACd,MAAM,UAAU,oBAAoB;AACpC,GAAA,GAAA,cAAA,uBAAsB,cAAc,YAAY;AAChD,UAAQ,oBACN,aAAa,aACb,aACA,YACD;IACA;EAAC;EAAc;EAAa;EAAY,CAAC;AAE5C,EAAA,GAAA,MAAA,iBAAgB;EACd,MAAM,UAAU,oBAAoB;AACpC,MAAI,SAAS,QACX,SAAQ,QAAQ,KAAwB;AAG1C,eAAa;AACX,WAAQ,SAAS;AAEjB,OAAI,SAAS,UACX,SAAQ,UAAU,KAAwB;AAG5C,IAAA,GAAA,cAAA,SAAQ,WAAW,YAAY;;IAGhC,EAAE,CAAC;AAEN,QAAO;EAAC;EAAO;EAAM;EAAa"}
|
package/dist/index.js
CHANGED
|
@@ -125,7 +125,11 @@ function useBloc(BlocClass, options) {
|
|
|
125
125
|
const manager = externalDepsManager.current;
|
|
126
126
|
disableGetterTracking(adapterState, rawInstance);
|
|
127
127
|
manager.updateSubscriptions(adapterState.getterState, rawInstance, forceUpdate);
|
|
128
|
-
}
|
|
128
|
+
}, [
|
|
129
|
+
adapterState,
|
|
130
|
+
rawInstance,
|
|
131
|
+
forceUpdate
|
|
132
|
+
]);
|
|
129
133
|
useEffect(() => {
|
|
130
134
|
const manager = externalDepsManager.current;
|
|
131
135
|
if (options?.onMount) options.onMount(bloc);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/config.ts","../src/useBloc.ts"],"sourcesContent":["/**\n * Global configuration for @blac/react\n */\n\nexport interface BlacReactConfig {\n /** Enable automatic property tracking via Proxy (default: true) */\n autoTrack: boolean;\n}\n\nconst defaultConfig: BlacReactConfig = {\n autoTrack: true,\n};\n\nlet globalConfig: BlacReactConfig = { ...defaultConfig };\n\n/**\n * Configure global defaults for @blac/react hooks.\n *\n * @example\n * ```ts\n * import { configureBlacReact } from '@blac/react';\n *\n * // Disable auto-tracking globally\n * configureBlacReact({\n * autoTrack: false\n * });\n * ```\n *\n * @param config - Partial configuration to merge with defaults\n */\nexport function configureBlacReact(config: Partial<BlacReactConfig>): void {\n globalConfig = { ...globalConfig, ...config };\n}\n\n/**\n * Get the current global configuration.\n * @internal\n */\nexport function getBlacReactConfig(): BlacReactConfig {\n return globalConfig;\n}\n\n/**\n * Reset configuration to defaults (useful for testing).\n * @internal\n */\nexport function resetBlacReactConfig(): void {\n globalConfig = { ...defaultConfig };\n}\n","import {\n useMemo,\n useSyncExternalStore,\n useEffect,\n useRef,\n useReducer,\n} from 'react';\nimport {\n type ExtractState,\n type AdapterState,\n ExternalDepsManager,\n autoTrackSubscribe,\n manualDepsSubscribe,\n noTrackSubscribe,\n autoTrackSnapshot,\n manualDepsSnapshot,\n noTrackSnapshot,\n autoTrackInit,\n manualDepsInit,\n noTrackInit,\n disableGetterTracking,\n type StateContainerConstructor,\n type InstanceState,\n acquire,\n release,\n} from '@blac/adapter';\nimport type { UseBlocOptions, UseBlocReturn, ComponentRef } from './types';\nimport { getBlacReactConfig } from './config';\n\ninterface TrackingMode {\n useManualDeps: boolean;\n autoTrackEnabled: boolean;\n}\n\nfunction determineTrackingMode<TBloc extends StateContainerConstructor>(\n options?: Pick<UseBlocOptions<TBloc>, 'autoTrack' | 'dependencies'>,\n): TrackingMode {\n const globalConfig = getBlacReactConfig();\n const autoTrackEnabled =\n options?.autoTrack !== undefined\n ? options.autoTrack\n : globalConfig.autoTrack;\n\n return {\n useManualDeps: options?.dependencies !== undefined,\n autoTrackEnabled,\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 (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 named instance\n * ```ts\n * const [state, myBloc] = useBloc(MyBloc, {\n * instanceId: 'unique-id'\n * });\n * ```\n */\nexport function useBloc<\n T extends StateContainerConstructor = StateContainerConstructor,\n>(\n BlocClass: T,\n options?: UseBlocOptions<T>,\n): UseBlocReturn<T, ExtractState<T>> {\n type TBloc = InstanceState<T>;\n\n const componentRef = useRef<ComponentRef>({});\n const depsRef = useRef(options?.dependencies);\n depsRef.current = options?.dependencies;\n const instanceId = options?.instanceId;\n const autoTrack = options?.autoTrack;\n const dependencies = options?.dependencies;\n\n const [bloc, subscribe, getSnapshot, instanceKey, adapterState, rawInstance] =\n useMemo<\n readonly [\n TBloc,\n (callback: () => void) => () => void,\n () => ExtractState<T>,\n string | undefined,\n AdapterState<T>,\n TBloc,\n ]\n >(() => {\n const instanceKey =\n instanceId !== undefined ? String(instanceId) : undefined;\n\n const instance = acquire(BlocClass, instanceKey) as TBloc;\n\n const { useManualDeps, autoTrackEnabled } = determineTrackingMode({\n autoTrack,\n dependencies,\n });\n\n let subscribeFn: (callback: () => void) => () => void;\n let getSnapshotFn: () => ExtractState<T>;\n let adapterState: AdapterState<T>;\n\n if (useManualDeps && dependencies) {\n adapterState = manualDepsInit(instance);\n const stableConfig = {\n dependencies: (state: ExtractState<T>, bloc: InstanceState<T>) => {\n const deps = depsRef.current;\n return deps ? deps(state, bloc) : [];\n },\n };\n subscribeFn = manualDepsSubscribe(instance, adapterState, stableConfig);\n getSnapshotFn = manualDepsSnapshot(\n instance,\n adapterState,\n stableConfig,\n );\n } else if (!autoTrackEnabled) {\n adapterState = noTrackInit(instance);\n subscribeFn = noTrackSubscribe(instance);\n getSnapshotFn = noTrackSnapshot(instance);\n } else {\n adapterState = autoTrackInit(instance);\n subscribeFn = autoTrackSubscribe(instance, adapterState);\n getSnapshotFn = autoTrackSnapshot(instance, adapterState);\n }\n\n const safeSubscribeFn = (callback: () => void) => {\n if (instance.isDisposed) return () => {};\n return subscribeFn(callback);\n };\n\n return [\n adapterState.proxiedBloc as TBloc,\n safeSubscribeFn,\n getSnapshotFn,\n instanceKey,\n adapterState,\n instance,\n ];\n //
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/config.ts","../src/useBloc.ts"],"sourcesContent":["/**\n * Global configuration for @blac/react\n */\n\nexport interface BlacReactConfig {\n /** Enable automatic property tracking via Proxy (default: true) */\n autoTrack: boolean;\n}\n\nconst defaultConfig: BlacReactConfig = {\n autoTrack: true,\n};\n\nlet globalConfig: BlacReactConfig = { ...defaultConfig };\n\n/**\n * Configure global defaults for @blac/react hooks.\n *\n * @example\n * ```ts\n * import { configureBlacReact } from '@blac/react';\n *\n * // Disable auto-tracking globally\n * configureBlacReact({\n * autoTrack: false\n * });\n * ```\n *\n * @param config - Partial configuration to merge with defaults\n */\nexport function configureBlacReact(config: Partial<BlacReactConfig>): void {\n globalConfig = { ...globalConfig, ...config };\n}\n\n/**\n * Get the current global configuration.\n * @internal\n */\nexport function getBlacReactConfig(): BlacReactConfig {\n return globalConfig;\n}\n\n/**\n * Reset configuration to defaults (useful for testing).\n * @internal\n */\nexport function resetBlacReactConfig(): void {\n globalConfig = { ...defaultConfig };\n}\n","import {\n useMemo,\n useSyncExternalStore,\n useEffect,\n useRef,\n useReducer,\n} from 'react';\nimport {\n type ExtractState,\n type AdapterState,\n ExternalDepsManager,\n autoTrackSubscribe,\n manualDepsSubscribe,\n noTrackSubscribe,\n autoTrackSnapshot,\n manualDepsSnapshot,\n noTrackSnapshot,\n autoTrackInit,\n manualDepsInit,\n noTrackInit,\n disableGetterTracking,\n type StateContainerConstructor,\n type InstanceState,\n acquire,\n release,\n} from '@blac/adapter';\nimport type { UseBlocOptions, UseBlocReturn, ComponentRef } from './types';\nimport { getBlacReactConfig } from './config';\n\ninterface TrackingMode {\n useManualDeps: boolean;\n autoTrackEnabled: boolean;\n}\n\nfunction determineTrackingMode<TBloc extends StateContainerConstructor>(\n options?: Pick<UseBlocOptions<TBloc>, 'autoTrack' | 'dependencies'>,\n): TrackingMode {\n const globalConfig = getBlacReactConfig();\n const autoTrackEnabled =\n options?.autoTrack !== undefined\n ? options.autoTrack\n : globalConfig.autoTrack;\n\n return {\n useManualDeps: options?.dependencies !== undefined,\n autoTrackEnabled,\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 (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 named instance\n * ```ts\n * const [state, myBloc] = useBloc(MyBloc, {\n * instanceId: 'unique-id'\n * });\n * ```\n */\nexport function useBloc<\n T extends StateContainerConstructor = StateContainerConstructor,\n>(\n BlocClass: T,\n options?: UseBlocOptions<T>,\n): UseBlocReturn<T, ExtractState<T>> {\n type TBloc = InstanceState<T>;\n\n const componentRef = useRef<ComponentRef>({});\n const depsRef = useRef(options?.dependencies);\n depsRef.current = options?.dependencies;\n const instanceId = options?.instanceId;\n const autoTrack = options?.autoTrack;\n const dependencies = options?.dependencies;\n\n const [bloc, subscribe, getSnapshot, instanceKey, adapterState, rawInstance] =\n useMemo<\n readonly [\n TBloc,\n (callback: () => void) => () => void,\n () => ExtractState<T>,\n string | undefined,\n AdapterState<T>,\n TBloc,\n ]\n >(() => {\n const instanceKey =\n instanceId !== undefined ? String(instanceId) : undefined;\n\n const instance = acquire(BlocClass, instanceKey) as TBloc;\n\n const { useManualDeps, autoTrackEnabled } = determineTrackingMode({\n autoTrack,\n dependencies,\n });\n\n let subscribeFn: (callback: () => void) => () => void;\n let getSnapshotFn: () => ExtractState<T>;\n let adapterState: AdapterState<T>;\n\n if (useManualDeps && dependencies) {\n adapterState = manualDepsInit(instance);\n const stableConfig = {\n dependencies: (state: ExtractState<T>, bloc: InstanceState<T>) => {\n const deps = depsRef.current;\n return deps ? deps(state, bloc) : [];\n },\n };\n subscribeFn = manualDepsSubscribe(instance, adapterState, stableConfig);\n getSnapshotFn = manualDepsSnapshot(\n instance,\n adapterState,\n stableConfig,\n );\n } else if (!autoTrackEnabled) {\n adapterState = noTrackInit(instance);\n subscribeFn = noTrackSubscribe(instance);\n getSnapshotFn = noTrackSnapshot(instance);\n } else {\n adapterState = autoTrackInit(instance);\n subscribeFn = autoTrackSubscribe(instance, adapterState);\n getSnapshotFn = autoTrackSnapshot(instance, adapterState);\n }\n\n const safeSubscribeFn = (callback: () => void) => {\n if (instance.isDisposed) return () => {};\n return subscribeFn(callback);\n };\n\n return [\n adapterState.proxiedBloc as TBloc,\n safeSubscribeFn,\n getSnapshotFn,\n instanceKey,\n adapterState,\n instance,\n ];\n // oxlint-disable-next-line react-hooks/exhaustive-deps\n }, [BlocClass, instanceId]);\n\n const state = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n const [, forceUpdate] = useReducer((x: number) => x + 1, 0);\n\n const externalDepsManager = useRef(new ExternalDepsManager());\n\n useEffect(() => {\n const manager = externalDepsManager.current;\n disableGetterTracking(adapterState, rawInstance);\n manager.updateSubscriptions(\n adapterState.getterState,\n rawInstance,\n forceUpdate,\n );\n }, [adapterState, rawInstance, forceUpdate]);\n\n useEffect(() => {\n const manager = externalDepsManager.current;\n if (options?.onMount) {\n options.onMount(bloc as InstanceType<T>);\n }\n\n return () => {\n manager.cleanup();\n\n if (options?.onUnmount) {\n options.onUnmount(bloc as InstanceType<T>);\n }\n\n release(BlocClass, instanceKey);\n };\n // oxlint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return [state, bloc, componentRef] as UseBlocReturn<T, ExtractState<T>>;\n}\n"],"mappings":";;AAaA,IAAI,eAAgC,EAHlC,WAAW,MAG2C;;;;;;;;;;;;;;;;AAiBxD,SAAgB,mBAAmB,QAAwC;AACzE,gBAAe;EAAE,GAAG;EAAc,GAAG;EAAQ;;;;;;AAO/C,SAAgB,qBAAsC;AACpD,QAAO;;;;ACLT,SAAS,sBACP,SACc;CACd,MAAM,eAAe,oBAAoB;CACzC,MAAM,mBACJ,SAAS,cAAc,KAAA,IACnB,QAAQ,YACR,aAAa;AAEnB,QAAO;EACL,eAAe,SAAS,iBAAiB,KAAA;EACzC;EACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCH,SAAgB,QAGd,WACA,SACmC;CAGnC,MAAM,eAAe,OAAqB,EAAE,CAAC;CAC7C,MAAM,UAAU,OAAO,SAAS,aAAa;AAC7C,SAAQ,UAAU,SAAS;CAC3B,MAAM,aAAa,SAAS;CAC5B,MAAM,YAAY,SAAS;CAC3B,MAAM,eAAe,SAAS;CAE9B,MAAM,CAAC,MAAM,WAAW,aAAa,aAAa,cAAc,eAC9D,cASQ;EACN,MAAM,cACJ,eAAe,KAAA,IAAY,OAAO,WAAW,GAAG,KAAA;EAElD,MAAM,WAAW,QAAQ,WAAW,YAAY;EAEhD,MAAM,EAAE,eAAe,qBAAqB,sBAAsB;GAChE;GACA;GACD,CAAC;EAEF,IAAI;EACJ,IAAI;EACJ,IAAI;AAEJ,MAAI,iBAAiB,cAAc;AACjC,kBAAe,eAAe,SAAS;GACvC,MAAM,eAAe,EACnB,eAAe,OAAwB,SAA2B;IAChE,MAAM,OAAO,QAAQ;AACrB,WAAO,OAAO,KAAK,OAAO,KAAK,GAAG,EAAE;MAEvC;AACD,iBAAc,oBAAoB,UAAU,cAAc,aAAa;AACvE,mBAAgB,mBACd,UACA,cACA,aACD;aACQ,CAAC,kBAAkB;AAC5B,kBAAe,YAAY,SAAS;AACpC,iBAAc,iBAAiB,SAAS;AACxC,mBAAgB,gBAAgB,SAAS;SACpC;AACL,kBAAe,cAAc,SAAS;AACtC,iBAAc,mBAAmB,UAAU,aAAa;AACxD,mBAAgB,kBAAkB,UAAU,aAAa;;EAG3D,MAAM,mBAAmB,aAAyB;AAChD,OAAI,SAAS,WAAY,cAAa;AACtC,UAAO,YAAY,SAAS;;AAG9B,SAAO;GACL,aAAa;GACb;GACA;GACA;GACA;GACA;GACD;IAEA,CAAC,WAAW,WAAW,CAAC;CAE7B,MAAM,QAAQ,qBAAqB,WAAW,aAAa,YAAY;CAEvE,MAAM,GAAG,eAAe,YAAY,MAAc,IAAI,GAAG,EAAE;CAE3D,MAAM,sBAAsB,OAAO,IAAI,qBAAqB,CAAC;AAE7D,iBAAgB;EACd,MAAM,UAAU,oBAAoB;AACpC,wBAAsB,cAAc,YAAY;AAChD,UAAQ,oBACN,aAAa,aACb,aACA,YACD;IACA;EAAC;EAAc;EAAa;EAAY,CAAC;AAE5C,iBAAgB;EACd,MAAM,UAAU,oBAAoB;AACpC,MAAI,SAAS,QACX,SAAQ,QAAQ,KAAwB;AAG1C,eAAa;AACX,WAAQ,SAAS;AAEjB,OAAI,SAAS,UACX,SAAQ,UAAU,KAAwB;AAG5C,WAAQ,WAAW,YAAY;;IAGhC,EAAE,CAAC;AAEN,QAAO;EAAC;EAAO;EAAM;EAAa"}
|
package/dist/testing.cjs
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
let _blac_core = require("@blac/core");
|
|
3
|
+
let _blac_core_testing = require("@blac/core/testing");
|
|
4
|
+
let _testing_library_react = require("@testing-library/react");
|
|
5
|
+
//#region src/testing.ts
|
|
6
|
+
function renderWithBloc(ui, options) {
|
|
7
|
+
const { bloc: BlocClass, instanceKey, ...stubOptions } = options;
|
|
8
|
+
const previous = (0, _blac_core.getRegistry)();
|
|
9
|
+
(0, _blac_core.setRegistry)(new _blac_core.StateContainerRegistry());
|
|
10
|
+
const instance = (0, _blac_core_testing.createCubitStub)(BlocClass, stubOptions);
|
|
11
|
+
(0, _blac_core_testing.registerOverride)(BlocClass, instance, instanceKey);
|
|
12
|
+
const renderResult = (0, _testing_library_react.render)(ui);
|
|
13
|
+
const originalUnmount = renderResult.unmount;
|
|
14
|
+
renderResult.unmount = () => {
|
|
15
|
+
originalUnmount();
|
|
16
|
+
(0, _blac_core.setRegistry)(previous);
|
|
17
|
+
};
|
|
18
|
+
return {
|
|
19
|
+
...renderResult,
|
|
20
|
+
bloc: instance
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function renderWithRegistry(ui, setup) {
|
|
24
|
+
const previous = (0, _blac_core.getRegistry)();
|
|
25
|
+
const testRegistry = new _blac_core.StateContainerRegistry();
|
|
26
|
+
(0, _blac_core.setRegistry)(testRegistry);
|
|
27
|
+
setup(testRegistry);
|
|
28
|
+
const renderResult = (0, _testing_library_react.render)(ui);
|
|
29
|
+
const originalUnmount = renderResult.unmount;
|
|
30
|
+
renderResult.unmount = () => {
|
|
31
|
+
originalUnmount();
|
|
32
|
+
(0, _blac_core.setRegistry)(previous);
|
|
33
|
+
};
|
|
34
|
+
return renderResult;
|
|
35
|
+
}
|
|
36
|
+
//#endregion
|
|
37
|
+
exports.renderWithBloc = renderWithBloc;
|
|
38
|
+
exports.renderWithRegistry = renderWithRegistry;
|
|
39
|
+
|
|
40
|
+
//# sourceMappingURL=testing.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.cjs","names":["StateContainerRegistry"],"sources":["../src/testing.ts"],"sourcesContent":["import type { ReactElement } from 'react';\nimport type { RenderResult } from '@testing-library/react';\nimport type { StateContainerConstructor } from '@blac/core';\nimport { StateContainerRegistry, getRegistry, setRegistry } from '@blac/core';\nimport {\n registerOverride,\n createCubitStub,\n type CubitStubOptions,\n} from '@blac/core/testing';\nimport { render } from '@testing-library/react';\n\ninterface RenderWithBlocOptions<\n T extends StateContainerConstructor,\n> extends CubitStubOptions<T> {\n bloc: T;\n instanceKey?: string;\n}\n\nexport function renderWithBloc<T extends StateContainerConstructor>(\n ui: ReactElement,\n options: RenderWithBlocOptions<T>,\n): RenderResult & { bloc: InstanceType<T> } {\n const { bloc: BlocClass, instanceKey, ...stubOptions } = options;\n\n const previous = getRegistry();\n const testRegistry = new StateContainerRegistry();\n setRegistry(testRegistry);\n\n const instance = createCubitStub(BlocClass, stubOptions);\n registerOverride(BlocClass, instance, instanceKey);\n\n const renderResult = render(ui);\n\n const originalUnmount = renderResult.unmount;\n renderResult.unmount = () => {\n originalUnmount();\n setRegistry(previous);\n };\n\n return {\n ...renderResult,\n bloc: instance,\n };\n}\n\nexport function renderWithRegistry(\n ui: ReactElement,\n setup: (registry: StateContainerRegistry) => void,\n): RenderResult {\n const previous = getRegistry();\n const testRegistry = new StateContainerRegistry();\n setRegistry(testRegistry);\n\n setup(testRegistry);\n\n const renderResult = render(ui);\n\n const originalUnmount = renderResult.unmount;\n renderResult.unmount = () => {\n originalUnmount();\n setRegistry(previous);\n };\n\n return renderResult;\n}\n"],"mappings":";;;;;AAkBA,SAAgB,eACd,IACA,SAC0C;CAC1C,MAAM,EAAE,MAAM,WAAW,aAAa,GAAG,gBAAgB;CAEzD,MAAM,YAAA,GAAA,WAAA,cAAwB;AAE9B,EAAA,GAAA,WAAA,aADqB,IAAIA,WAAAA,wBAAwB,CACxB;CAEzB,MAAM,YAAA,GAAA,mBAAA,iBAA2B,WAAW,YAAY;AACxD,EAAA,GAAA,mBAAA,kBAAiB,WAAW,UAAU,YAAY;CAElD,MAAM,gBAAA,GAAA,uBAAA,QAAsB,GAAG;CAE/B,MAAM,kBAAkB,aAAa;AACrC,cAAa,gBAAgB;AAC3B,mBAAiB;AACjB,GAAA,GAAA,WAAA,aAAY,SAAS;;AAGvB,QAAO;EACL,GAAG;EACH,MAAM;EACP;;AAGH,SAAgB,mBACd,IACA,OACc;CACd,MAAM,YAAA,GAAA,WAAA,cAAwB;CAC9B,MAAM,eAAe,IAAIA,WAAAA,wBAAwB;AACjD,EAAA,GAAA,WAAA,aAAY,aAAa;AAEzB,OAAM,aAAa;CAEnB,MAAM,gBAAA,GAAA,uBAAA,QAAsB,GAAG;CAE/B,MAAM,kBAAkB,aAAa;AACrC,cAAa,gBAAgB;AAC3B,mBAAiB;AACjB,GAAA,GAAA,WAAA,aAAY,SAAS;;AAGvB,QAAO"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ReactElement } from 'react';
|
|
2
|
+
import type { RenderResult } from '@testing-library/react';
|
|
3
|
+
import type { StateContainerConstructor } from '@blac/core';
|
|
4
|
+
import { StateContainerRegistry } from '@blac/core';
|
|
5
|
+
import { type CubitStubOptions } from '@blac/core/testing';
|
|
6
|
+
interface RenderWithBlocOptions<T extends StateContainerConstructor> extends CubitStubOptions<T> {
|
|
7
|
+
bloc: T;
|
|
8
|
+
instanceKey?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function renderWithBloc<T extends StateContainerConstructor>(ui: ReactElement, options: RenderWithBlocOptions<T>): RenderResult & {
|
|
11
|
+
bloc: InstanceType<T>;
|
|
12
|
+
};
|
|
13
|
+
export declare function renderWithRegistry(ui: ReactElement, setup: (registry: StateContainerRegistry) => void): RenderResult;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ReactElement } from 'react';
|
|
2
|
+
import type { RenderResult } from '@testing-library/react';
|
|
3
|
+
import type { StateContainerConstructor } from '@blac/core';
|
|
4
|
+
import { StateContainerRegistry } from '@blac/core';
|
|
5
|
+
import { type CubitStubOptions } from '@blac/core/testing';
|
|
6
|
+
interface RenderWithBlocOptions<T extends StateContainerConstructor> extends CubitStubOptions<T> {
|
|
7
|
+
bloc: T;
|
|
8
|
+
instanceKey?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function renderWithBloc<T extends StateContainerConstructor>(ui: ReactElement, options: RenderWithBlocOptions<T>): RenderResult & {
|
|
11
|
+
bloc: InstanceType<T>;
|
|
12
|
+
};
|
|
13
|
+
export declare function renderWithRegistry(ui: ReactElement, setup: (registry: StateContainerRegistry) => void): RenderResult;
|
|
14
|
+
export {};
|
package/dist/testing.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { StateContainerRegistry, getRegistry, setRegistry } from "@blac/core";
|
|
2
|
+
import { createCubitStub, registerOverride } from "@blac/core/testing";
|
|
3
|
+
import { render } from "@testing-library/react";
|
|
4
|
+
//#region src/testing.ts
|
|
5
|
+
function renderWithBloc(ui, options) {
|
|
6
|
+
const { bloc: BlocClass, instanceKey, ...stubOptions } = options;
|
|
7
|
+
const previous = getRegistry();
|
|
8
|
+
setRegistry(new StateContainerRegistry());
|
|
9
|
+
const instance = createCubitStub(BlocClass, stubOptions);
|
|
10
|
+
registerOverride(BlocClass, instance, instanceKey);
|
|
11
|
+
const renderResult = render(ui);
|
|
12
|
+
const originalUnmount = renderResult.unmount;
|
|
13
|
+
renderResult.unmount = () => {
|
|
14
|
+
originalUnmount();
|
|
15
|
+
setRegistry(previous);
|
|
16
|
+
};
|
|
17
|
+
return {
|
|
18
|
+
...renderResult,
|
|
19
|
+
bloc: instance
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function renderWithRegistry(ui, setup) {
|
|
23
|
+
const previous = getRegistry();
|
|
24
|
+
const testRegistry = new StateContainerRegistry();
|
|
25
|
+
setRegistry(testRegistry);
|
|
26
|
+
setup(testRegistry);
|
|
27
|
+
const renderResult = render(ui);
|
|
28
|
+
const originalUnmount = renderResult.unmount;
|
|
29
|
+
renderResult.unmount = () => {
|
|
30
|
+
originalUnmount();
|
|
31
|
+
setRegistry(previous);
|
|
32
|
+
};
|
|
33
|
+
return renderResult;
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
export { renderWithBloc, renderWithRegistry };
|
|
37
|
+
|
|
38
|
+
//# sourceMappingURL=testing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.js","names":[],"sources":["../src/testing.ts"],"sourcesContent":["import type { ReactElement } from 'react';\nimport type { RenderResult } from '@testing-library/react';\nimport type { StateContainerConstructor } from '@blac/core';\nimport { StateContainerRegistry, getRegistry, setRegistry } from '@blac/core';\nimport {\n registerOverride,\n createCubitStub,\n type CubitStubOptions,\n} from '@blac/core/testing';\nimport { render } from '@testing-library/react';\n\ninterface RenderWithBlocOptions<\n T extends StateContainerConstructor,\n> extends CubitStubOptions<T> {\n bloc: T;\n instanceKey?: string;\n}\n\nexport function renderWithBloc<T extends StateContainerConstructor>(\n ui: ReactElement,\n options: RenderWithBlocOptions<T>,\n): RenderResult & { bloc: InstanceType<T> } {\n const { bloc: BlocClass, instanceKey, ...stubOptions } = options;\n\n const previous = getRegistry();\n const testRegistry = new StateContainerRegistry();\n setRegistry(testRegistry);\n\n const instance = createCubitStub(BlocClass, stubOptions);\n registerOverride(BlocClass, instance, instanceKey);\n\n const renderResult = render(ui);\n\n const originalUnmount = renderResult.unmount;\n renderResult.unmount = () => {\n originalUnmount();\n setRegistry(previous);\n };\n\n return {\n ...renderResult,\n bloc: instance,\n };\n}\n\nexport function renderWithRegistry(\n ui: ReactElement,\n setup: (registry: StateContainerRegistry) => void,\n): RenderResult {\n const previous = getRegistry();\n const testRegistry = new StateContainerRegistry();\n setRegistry(testRegistry);\n\n setup(testRegistry);\n\n const renderResult = render(ui);\n\n const originalUnmount = renderResult.unmount;\n renderResult.unmount = () => {\n originalUnmount();\n setRegistry(previous);\n };\n\n return renderResult;\n}\n"],"mappings":";;;;AAkBA,SAAgB,eACd,IACA,SAC0C;CAC1C,MAAM,EAAE,MAAM,WAAW,aAAa,GAAG,gBAAgB;CAEzD,MAAM,WAAW,aAAa;AAE9B,aADqB,IAAI,wBAAwB,CACxB;CAEzB,MAAM,WAAW,gBAAgB,WAAW,YAAY;AACxD,kBAAiB,WAAW,UAAU,YAAY;CAElD,MAAM,eAAe,OAAO,GAAG;CAE/B,MAAM,kBAAkB,aAAa;AACrC,cAAa,gBAAgB;AAC3B,mBAAiB;AACjB,cAAY,SAAS;;AAGvB,QAAO;EACL,GAAG;EACH,MAAM;EACP;;AAGH,SAAgB,mBACd,IACA,OACc;CACd,MAAM,WAAW,aAAa;CAC9B,MAAM,eAAe,IAAI,wBAAwB;AACjD,aAAY,aAAa;AAEzB,OAAM,aAAa;CAEnB,MAAM,eAAe,OAAO,GAAG;CAE/B,MAAM,kBAAkB,aAAa;AACrC,cAAa,gBAAgB;AAC3B,mBAAiB;AACjB,cAAY,SAAS;;AAGvB,QAAO"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blac/react",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.9",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Brendan Mullins <jsnanigans@gmail.com>",
|
|
6
6
|
"description": "React bindings for BlaC — useBloc hook with automatic re-render optimization",
|
|
@@ -27,6 +27,16 @@
|
|
|
27
27
|
"types": "./dist/index.d.cts",
|
|
28
28
|
"default": "./dist/index.cjs"
|
|
29
29
|
}
|
|
30
|
+
},
|
|
31
|
+
"./testing": {
|
|
32
|
+
"import": {
|
|
33
|
+
"types": "./dist/testing.d.ts",
|
|
34
|
+
"default": "./dist/testing.js"
|
|
35
|
+
},
|
|
36
|
+
"require": {
|
|
37
|
+
"types": "./dist/testing.d.cts",
|
|
38
|
+
"default": "./dist/testing.cjs"
|
|
39
|
+
}
|
|
30
40
|
}
|
|
31
41
|
},
|
|
32
42
|
"files": [
|
|
@@ -48,12 +58,13 @@
|
|
|
48
58
|
"bloc-pattern"
|
|
49
59
|
],
|
|
50
60
|
"dependencies": {
|
|
51
|
-
"@blac/adapter": "^2.0.
|
|
61
|
+
"@blac/adapter": "^2.0.9"
|
|
52
62
|
},
|
|
53
63
|
"peerDependencies": {
|
|
64
|
+
"@testing-library/react": "^14.0.0 || ^15.0.0 || ^16.0.0",
|
|
54
65
|
"@types/react": "^18.0.0 || ^19.0.0",
|
|
55
66
|
"react": "^18.0.0 || ^19.0.0",
|
|
56
|
-
"@blac/core": "^2.0.
|
|
67
|
+
"@blac/core": "^2.0.9"
|
|
57
68
|
},
|
|
58
69
|
"peerDependenciesMeta": {
|
|
59
70
|
"@types/react": {
|
|
@@ -61,6 +72,9 @@
|
|
|
61
72
|
},
|
|
62
73
|
"@types/react-dom": {
|
|
63
74
|
"optional": true
|
|
75
|
+
},
|
|
76
|
+
"@testing-library/react": {
|
|
77
|
+
"optional": true
|
|
64
78
|
}
|
|
65
79
|
},
|
|
66
80
|
"devDependencies": {
|
|
@@ -71,35 +85,32 @@
|
|
|
71
85
|
"@types/react": "^19.1.9",
|
|
72
86
|
"@types/react-dom": "^19.1.7",
|
|
73
87
|
"@vitejs/plugin-react": "^4.7.0",
|
|
74
|
-
"@vitest/browser": "^3.2.4",
|
|
75
|
-
"@vitest/coverage-v8": "^3.2.4",
|
|
76
88
|
"babel-plugin-react-compiler": "^1.0.0",
|
|
77
|
-
"eslint-plugin-react-compiler": "19.1.0-rc.2",
|
|
78
89
|
"happy-dom": "^18.0.1",
|
|
79
90
|
"jsdom": "^26.1.0",
|
|
80
|
-
"prettier": "^3.6.2",
|
|
81
91
|
"publint": "^0.3.12",
|
|
82
92
|
"react": "^19.1.1",
|
|
83
93
|
"react-dom": "^19.1.1",
|
|
84
|
-
"tsdown": "^0.15.7",
|
|
85
94
|
"typescript": "^5.9.2",
|
|
86
|
-
"vite": "
|
|
87
|
-
"vitest": "
|
|
88
|
-
"
|
|
95
|
+
"vite": "npm:@voidzero-dev/vite-plus-core@latest",
|
|
96
|
+
"vitest": "npm:@voidzero-dev/vite-plus-test@latest",
|
|
97
|
+
"vite-plus": "latest",
|
|
98
|
+
"@blac/core": "2.0.9"
|
|
89
99
|
},
|
|
90
100
|
"scripts": {
|
|
91
|
-
"dev": "
|
|
92
|
-
"build": "
|
|
101
|
+
"dev": "vp pack --watch",
|
|
102
|
+
"build": "vp pack && tsc -p tsconfig.build.json && cp dist/index.d.ts dist/index.d.cts && cp dist/testing.d.ts dist/testing.d.cts",
|
|
93
103
|
"clean": "rm -rf dist",
|
|
94
|
-
"format": "
|
|
95
|
-
"
|
|
96
|
-
"lint
|
|
97
|
-
"
|
|
98
|
-
"test
|
|
99
|
-
"test:
|
|
100
|
-
"test:
|
|
101
|
-
"test:
|
|
102
|
-
"test:
|
|
104
|
+
"format": "vp fmt \".\"",
|
|
105
|
+
"format:check": "vp fmt \".\" --check",
|
|
106
|
+
"lint": "vp lint src",
|
|
107
|
+
"lint:fix": "vp lint src --fix",
|
|
108
|
+
"test": "vp test run",
|
|
109
|
+
"test:watch": "vp test --watch",
|
|
110
|
+
"test:memory": "NODE_OPTIONS='--expose-gc' vp test run --config vitest.config.performance.ts",
|
|
111
|
+
"test:performance": "vp test run --config vitest.config.performance.ts",
|
|
112
|
+
"test:compiler": "vp test run --config vitest.config.compiler.ts",
|
|
113
|
+
"test:watch:compiler": "vp test --watch --config vitest.config.compiler.ts",
|
|
103
114
|
"test:both": "pnpm test && echo '\n\n=== Running tests WITH React Compiler ===\n' && pnpm test:compiler",
|
|
104
115
|
"verify": "node ../../scripts/run-workspace-bin.mjs publint",
|
|
105
116
|
"typecheck": "tsc --noEmit",
|