@blac/react 2.0.0-rc-13 → 2.0.0-rc-16

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/README.md DELETED
@@ -1,265 +0,0 @@
1
- # @blac/react
2
-
3
- A powerful React integration for the Blac state management library, providing seamless integration between React components and Blac's reactive state management system.
4
-
5
- ## Features
6
-
7
- - 🔄 Automatic re-rendering when relevant state changes
8
- - 🎯 Fine-grained dependency tracking
9
- - 🔍 Property access tracking for optimized updates
10
- - 🎨 TypeScript support with full type inference
11
- - ⚡️ Efficient state management with minimal boilerplate
12
- - 🔄 Support for isolated and shared bloc instances
13
- - 🎯 Custom dependency selectors with access to state, previous state, and instance
14
- - 🚀 Optimized re-rendering with intelligent snapshot comparison
15
-
16
- ## Important: Arrow Functions Required
17
-
18
- All methods in Bloc or Cubit classes must use arrow function syntax (`method = () => {}`) instead of the traditional method syntax (`method() {}`). This is because arrow functions automatically bind `this` to the class instance. Without this binding, methods called from React components would lose their context and could not access instance properties like `this.state` or `this.emit()`.
19
-
20
- ```tsx
21
- // Correct way to define methods in your Bloc/Cubit classes
22
- class CounterBloc extends Cubit<CounterState> {
23
- increment = () => {
24
- this.emit({ ...this.state, count: this.state.count + 1 });
25
- }
26
-
27
- decrement = () => {
28
- this.emit({ ...this.state, count: this.state.count - 1 });
29
- }
30
- }
31
-
32
- // Incorrect way (will cause issues when called from React):
33
- class CounterBloc extends Cubit<CounterState> {
34
- increment() { // ❌ Will lose 'this' context when called from components
35
- this.emit({ ...this.state, count: this.state.count + 1 });
36
- }
37
- }
38
- ```
39
-
40
- ## Installation
41
-
42
- ```bash
43
- npm install @blac/react
44
- # or
45
- yarn add @blac/react
46
- # or
47
- pnpm add @blac/react
48
- ```
49
-
50
- ## Quick Start
51
-
52
- ```tsx
53
- import { useBloc } from '@blac/react';
54
- import { CounterBloc } from './CounterBloc';
55
-
56
- function Counter() {
57
- const [state, counterBloc] = useBloc(CounterBloc);
58
-
59
- return (
60
- <div>
61
- <p>Count: {state.count}</p>
62
- <button onClick={() => counterBloc.increment()}>Increment</button>
63
- </div>
64
- );
65
- }
66
- ```
67
-
68
- ## Usage
69
-
70
- ### Basic Usage
71
-
72
- The `useBloc` hook provides a simple way to connect your React components to Blac's state management system:
73
-
74
- ```tsx
75
- const [state, bloc] = useBloc(YourBloc);
76
- ```
77
-
78
- ### Advanced Configuration
79
-
80
- The hook accepts configuration options for more control:
81
-
82
- ```tsx
83
- const [state, bloc] = useBloc(YourBloc, {
84
- id: 'custom-id', // Optional: Custom identifier for the bloc
85
- props: { /* ... */ }, // Optional: Props to pass to the bloc
86
- onMount: (bloc) => { /* ... */ }, // Optional: Callback when bloc is mounted (similar to useEffect(<>, []))
87
- selector: (currentState, previousState, instance) => [/* ... */], // Optional: Custom dependency tracking
88
- });
89
- ```
90
-
91
- ### Automatic Dependency Tracking
92
-
93
- The hook automatically tracks which state properties and bloc instance properties are accessed in your component and only triggers re-renders when those specific values change:
94
-
95
- ```tsx
96
- function UserProfile() {
97
- const [state, userBloc] = useBloc(UserBloc);
98
-
99
- // Only re-renders when state.name changes
100
- return <h1>{state.name}</h1>;
101
- }
102
- ```
103
-
104
- This also works for getters and computed properties on the Bloc or Cubit class:
105
-
106
- ```tsx
107
- function UserProfile() {
108
- const [state, userBloc] = useBloc(UserBloc);
109
-
110
- // Only re-renders when:
111
- // - state.firstName changes, OR
112
- // - state.lastName changes (because the getter accesses these properties)
113
- return <h1>{userBloc.fullName}</h1>; // Assuming fullName is a getter
114
- }
115
- ```
116
-
117
- #### How It Works
118
-
119
- The dependency tracking system uses JavaScript Proxies to monitor property access during component renders:
120
-
121
- 1. **State Properties**: When you access `state.propertyName`, it's automatically tracked
122
- 2. **Instance Properties**: When you access `bloc.computedValue`, it's automatically tracked
123
- 3. **Intelligent Comparison**: The system separately tracks state dependencies and instance dependencies to handle edge cases where properties are dynamically added/removed
124
- 4. **Optimized Updates**: Components only re-render when tracked dependencies actually change their values
125
-
126
- #### Configuring Proxy Tracking
127
-
128
- By default, BlaC uses proxy-based dependency tracking for optimal performance. You can disable this globally if needed:
129
-
130
- ```tsx
131
- import { Blac } from '@blac/core';
132
-
133
- // Disable automatic dependency tracking globally
134
- Blac.setConfig({ proxyDependencyTracking: false });
135
-
136
- // Now components will re-render on ANY state change
137
- // unless you provide manual dependencies
138
- ```
139
-
140
- When proxy tracking is disabled:
141
- - Components re-render on any state change (similar to traditional state management)
142
- - Manual dependencies via the `selector` option still work as expected
143
- - Useful for debugging or when proxy behavior causes issues
144
-
145
- For more configuration options, see the [@blac/core documentation](https://www.npmjs.com/package/@blac/core).
146
-
147
- ### Custom Dependency Selector
148
-
149
- For more control over when your component re-renders, you can provide a custom dependency selector. The selector function receives the current state, previous state, and bloc instance, and should return an array of values to track:
150
-
151
- ```tsx
152
- const [state, bloc] = useBloc(YourBloc, {
153
- selector: (currentState, previousState, instance) => [
154
- currentState.specificField,
155
- currentState.anotherField,
156
- instance.computedValue // You can also track computed properties from the bloc instance
157
- ]
158
- });
159
- ```
160
-
161
- The component will only re-render when any of the values in the returned array change (using `Object.is` comparison, similar to React's `useEffect` dependency array).
162
-
163
- #### Examples of Custom Selectors
164
-
165
- **Track only specific state properties:**
166
- ```tsx
167
- const [state, userBloc] = useBloc(UserBloc, {
168
- selector: (currentState) => [
169
- currentState.name,
170
- currentState.email
171
- ] // Only re-render when name or email changes, ignore other properties
172
- });
173
- ```
174
-
175
- **Track computed values:**
176
- ```tsx
177
- const [state, shoppingCartBloc] = useBloc(ShoppingCartBloc, {
178
- selector: (currentState, previousState, instance) => [
179
- instance.totalPrice, // Computed getter
180
- currentState.items.length // Number of items
181
- ] // Only re-render when total price or item count changes
182
- });
183
- ```
184
-
185
- **Compare with previous state:**
186
- ```tsx
187
- const [state, chatBloc] = useBloc(ChatBloc, {
188
- selector: (currentState, previousState) => [
189
- currentState.messages.length > (previousState?.messages.length || 0) ? 'new-message' : 'no-change'
190
- ] // Only re-render when new messages are added, not when existing messages change
191
- });
192
- ```
193
-
194
- ## API Reference
195
-
196
- ### useBloc Hook
197
-
198
- ```typescript
199
- function useBloc<B extends BlocConstructor<BlocGeneric>>(
200
- bloc: B,
201
- options?: BlocHookOptions<InstanceType<B>>
202
- ): [BlocState<InstanceType<B>>, InstanceType<B>]
203
- ```
204
-
205
- #### Options
206
-
207
- - `id?: string` - Custom identifier for the bloc instance
208
- - `props?: InferPropsFromGeneric<B>` - Props to pass to the bloc
209
- - `onMount?: (bloc: B) => void` - Callback function invoked when the react component (the consumer) is connected to the bloc instance
210
- - `selector?: (currentState: BlocState<InstanceType<B>>, previousState: BlocState<InstanceType<B>> | undefined, instance: InstanceType<B>) => unknown[]` - Function to select dependencies for re-renders
211
-
212
- ## Best Practices
213
-
214
- 1. **Use Isolated Blocs**: When you need component-specific state, use isolated blocs:
215
- ```tsx
216
- class MyIsolatedBloc extends BlocBase {
217
- static isolated = true;
218
- // ... rest of your bloc implementation
219
- }
220
- ```
221
-
222
- 2. **Use Custom Identifiers**: When you need multiple independent instances of the same Bloc type, use custom identifiers to manage different state contexts:
223
- ```tsx
224
- // In a chat application with multiple chat rooms
225
- function ChatRoom({ roomId }: { roomId: string }) {
226
- const [state, chatBloc] = useBloc(ChatBloc, {
227
- id: `chat-${roomId}`, // Each room gets its own instance
228
- props: { roomId }
229
- });
230
-
231
- return (
232
- <div>
233
- <h2>Room: {roomId}</h2>
234
- {state.messages.map(msg => (
235
- <Message key={msg.id} message={msg} />
236
- ))}
237
- </div>
238
- );
239
- }
240
-
241
- // Usage:
242
- function ChatApp() {
243
- return (
244
- <div>
245
- <ChatRoom roomId="general" />
246
- <ChatRoom roomId="support" />
247
- </div>
248
- );
249
- }
250
- ```
251
-
252
- 3. **Choose the Right Dependency Strategy**:
253
- - **Use automatic tracking** (default) for most cases - it's efficient and requires no setup
254
- - **Use custom selectors** when you need complex logic, computed comparisons, or want to ignore certain property changes
255
- - **Avoid custom selectors** for simple property access - automatic tracking is more efficient
256
-
257
- 4. **Type Safety**: Take advantage of TypeScript's type inference for better development experience and catch errors early.
258
-
259
- ## Contributing
260
-
261
- Contributions are welcome! Please feel free to submit a Pull Request.
262
-
263
- ## License
264
-
265
- MIT
package/dist/index.cjs.js DELETED
@@ -1,2 +0,0 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const S=require("@blac/core"),r=require("react");function I(n,e){const b=r.useRef(0);b.current++;const l=r.useRef({}),c=r.useMemo(()=>new S.BlacAdapter({componentRef:l,blocConstructor:n},{id:e==null?void 0:e.id,dependencies:e==null?void 0:e.dependencies,props:e==null?void 0:e.props,onMount:e==null?void 0:e.onMount,onUnmount:e==null?void 0:e.onUnmount}),[]);c.resetConsumerTracking();const t=r.useRef(0);r.useEffect(()=>{t.current++,c.options={id:e==null?void 0:e.id,dependencies:e==null?void 0:e.dependencies,props:e==null?void 0:e.props,onMount:e==null?void 0:e.onMount,onUnmount:e==null?void 0:e.onUnmount},(e==null?void 0:e.props)!==void 0&&c.updateProps(e.props)},[e==null?void 0:e.props,e==null?void 0:e.id,e==null?void 0:e.dependencies,e==null?void 0:e.onMount,e==null?void 0:e.onUnmount]);const R=r.useRef(0);r.useEffect(()=>(R.current++,c.mount(),()=>{c.unmount()}),[c.blocInstance]);const B=r.useRef(0),u=r.useMemo(()=>(B.current++,d=>{const y=c.createSubscription({onChange:()=>{d()}});return()=>{y()}}),[c.blocInstance]),a=r.useRef(0),s=r.useRef(0),f=r.useSyncExternalStore(u,()=>(a.current++,c.blocInstance.state),()=>{const d=c.blocInstance;return s.current++,d.state}),m=r.useRef(0),M=r.useMemo(()=>(m.current++,c.getProxyState(f)),[f]),g=r.useRef(0),x=r.useMemo(()=>(g.current++,c.getProxyBlocInstance()),[c.blocInstance]);return r.useEffect(()=>{c.updateLastNotified(l.current)}),[M,x]}function U(n,e={}){const b=r.useRef(`external-${S.generateUUID()}`),l=r.useRef(new Set),c=r.useRef(new Set),t=r.useRef(null),R=r.useMemo(()=>{const u=S.Blac.getInstance();if(n.constructor.isolated||n.isolated){const s=new n(e==null?void 0:e.props),f=(e==null?void 0:e.id)||`${n.name}_${S.generateUUID()}`;return s._updateId(f),u.activateBloc(s),s}return u.getBloc(n,{id:e==null?void 0:e.id,props:e==null?void 0:e.props})},[n,e==null?void 0:e.id]),B=r.useMemo(()=>({getSnapshot:()=>{const u=t.current;return u?u.state:void 0},subscribe:u=>{const a=t.current;if(!a)return()=>{};const s=(m,M)=>{try{l.current.clear(),c.current.clear(),e.selector&&a&&e.selector(m,M,a),u.length>0?u(m):u()}catch(g){console.error("Listener error in useExternalBlocStore:",g)}};return a._observer.subscribe({id:b.current,fn:s})},getServerSnapshot:()=>{const u=t.current;return u?u.state:void 0}}),[]);return t.current=R,{externalStore:B,instance:t,usedKeys:l,usedClassPropKeys:c,rid:b.current}}exports.useBloc=I;exports.useBlocNext=I;exports.useExternalBlocStore=U;
2
- //# sourceMappingURL=index.cjs.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.cjs.js","sources":["../src/useBloc.ts","../src/useExternalBlocStore.ts"],"sourcesContent":["import {\n AdapterOptions,\n BlacAdapter,\n BlocBase,\n BlocConstructor,\n BlocState,\n} from '@blac/core';\nimport { useEffect, useMemo, useRef, useSyncExternalStore } from 'react';\n\n/**\n * Type definition for the return type of the useBloc hook\n */\ntype HookTypes<B extends BlocConstructor<BlocBase<any>>> = [\n BlocState<InstanceType<B>>,\n InstanceType<B>,\n];\n\n/**\n * React hook for integrating with Blac state management\n */\nfunction useBloc<B extends BlocConstructor<BlocBase<any>>>(\n blocConstructor: B,\n options?: {\n props?: ConstructorParameters<B>[0];\n id?: string;\n dependencies?: (bloc: InstanceType<B>) => unknown[];\n onMount?: (bloc: InstanceType<B>) => void;\n onUnmount?: (bloc: InstanceType<B>) => void;\n },\n): HookTypes<B> {\n // Create a unique identifier for this hook instance\n const renderCount = useRef(0);\n renderCount.current++;\n\n const componentRef = useRef<object>({});\n\n // Track adapter creation\n const adapter = useMemo(() => {\n const newAdapter = new BlacAdapter<B>(\n {\n componentRef: componentRef,\n blocConstructor,\n },\n {\n id: options?.id,\n dependencies: options?.dependencies,\n props: options?.props,\n onMount: options?.onMount,\n onUnmount: options?.onUnmount,\n },\n );\n return newAdapter;\n }, []);\n\n // Reset tracking at the start of each render to ensure we only track\n // properties accessed during the current render\n adapter.resetConsumerTracking();\n\n // Track options changes and update props\n const optionsChangeCount = useRef(0);\n useEffect(() => {\n optionsChangeCount.current++;\n adapter.options = {\n id: options?.id,\n dependencies: options?.dependencies,\n props: options?.props,\n onMount: options?.onMount,\n onUnmount: options?.onUnmount,\n };\n\n if (options?.props !== undefined) {\n adapter.updateProps(options.props);\n }\n }, [options?.props, options?.id, options?.dependencies, options?.onMount, options?.onUnmount]);\n\n // Register as consumer and handle lifecycle\n const mountEffectCount = useRef(0);\n useEffect(() => {\n mountEffectCount.current++;\n adapter.mount();\n\n return () => {\n adapter.unmount();\n };\n }, [adapter.blocInstance]);\n\n // Subscribe to state changes using useSyncExternalStore\n const subscribeMemoCount = useRef(0);\n const subscribe = useMemo(() => {\n subscribeMemoCount.current++;\n let subscriptionCount = 0;\n\n return (onStoreChange: () => void) => {\n subscriptionCount++;\n const unsubscribe = adapter.createSubscription({\n onChange: () => {\n onStoreChange();\n },\n });\n\n return () => {\n unsubscribe();\n };\n };\n }, [adapter.blocInstance]);\n\n const snapshotCount = useRef(0);\n const serverSnapshotCount = useRef(0);\n\n const rawState: BlocState<InstanceType<B>> = useSyncExternalStore(\n subscribe,\n // Get snapshot\n () => {\n snapshotCount.current++;\n const bloc = adapter.blocInstance;\n const state = bloc.state;\n return state;\n },\n // Get server snapshot (same as client for now)\n () => {\n const bloc = adapter.blocInstance;\n serverSnapshotCount.current++;\n const state = bloc.state;\n return state;\n },\n );\n\n // Create proxies for fine-grained tracking (if enabled)\n const stateMemoCount = useRef(0);\n const finalState = useMemo(() => {\n stateMemoCount.current++;\n const proxyState = adapter.getProxyState(rawState);\n return proxyState;\n }, [rawState]);\n\n const blocMemoCount = useRef(0);\n const finalBloc = useMemo(() => {\n blocMemoCount.current++;\n const proxyBloc = adapter.getProxyBlocInstance();\n return proxyBloc;\n }, [adapter.blocInstance]);\n\n // Mark consumer as rendered after each render\n useEffect(() => {\n adapter.updateLastNotified(componentRef.current);\n });\n\n // Log final hook return\n return [finalState, finalBloc];\n}\n\nexport default useBloc;\n","import {\n Blac,\n BlocBase,\n BlocConstructor,\n BlocState,\n InferPropsFromGeneric,\n generateUUID,\n} from '@blac/core';\nimport { useCallback, useMemo, useRef } from 'react';\n\ninterface ExternalStoreOptions<B extends BlocBase<any>> {\n id?: string;\n props?: InferPropsFromGeneric<B>;\n selector?: (\n currentState: BlocState<B>,\n previousState: BlocState<B>,\n instance: B,\n ) => any[];\n}\n\ninterface ExternalStore<T> {\n getSnapshot: () => T | undefined;\n subscribe: (listener: () => void) => () => void;\n getServerSnapshot?: () => T | undefined;\n}\n\ninterface ExternalBlocStoreResult<B extends BlocBase<any>> {\n externalStore: ExternalStore<BlocState<B>>;\n instance: { current: B | null };\n usedKeys: { current: Set<string> };\n usedClassPropKeys: { current: Set<string> };\n rid: string;\n}\n\n/**\n * Hook for using an external bloc store\n * Provides low-level access to bloc instances for use with React's useSyncExternalStore\n */\nexport default function useExternalBlocStore<\n B extends BlocConstructor<BlocBase<any>>,\n>(\n blocConstructor: B,\n options: ExternalStoreOptions<InstanceType<B>> = {},\n): ExternalBlocStoreResult<InstanceType<B>> {\n const ridRef = useRef<string>(`external-${generateUUID()}`);\n const usedKeysRef = useRef<Set<string>>(new Set());\n const usedClassPropKeysRef = useRef<Set<string>>(new Set());\n const instanceRef = useRef<InstanceType<B> | null>(null);\n\n // Get or create bloc instance\n const bloc = useMemo(() => {\n const blac = Blac.getInstance();\n const base = blocConstructor as unknown as BlocBase<any>;\n\n // For isolated blocs, always create a new instance\n if (\n (base.constructor as any).isolated ||\n (blocConstructor as any).isolated\n ) {\n const newBloc = new blocConstructor(options?.props) as InstanceType<B>;\n const uniqueId =\n options?.id || `${blocConstructor.name}_${generateUUID()}`;\n newBloc._updateId(uniqueId);\n blac.activateBloc(newBloc);\n return newBloc;\n }\n\n // For shared blocs, use the existing getBloc logic\n return blac.getBloc(blocConstructor, {\n id: options?.id,\n props: options?.props,\n });\n }, [blocConstructor, options?.id]);\n\n // Create external store interface\n const externalStore = useMemo<ExternalStore<BlocState<InstanceType<B>>>>(\n () => ({\n getSnapshot: () => {\n const currentInstance = instanceRef.current;\n return currentInstance ? currentInstance.state : undefined;\n },\n subscribe: (listener: () => void) => {\n const currentInstance = instanceRef.current;\n if (!currentInstance) {\n // Return no-op unsubscribe if no instance\n return () => {};\n }\n\n // Wrap listener to handle errors gracefully\n const safeListener = (\n newState: BlocState<InstanceType<B>>,\n oldState: BlocState<InstanceType<B>>,\n ) => {\n try {\n // Reset tracking keys on each listener call\n usedKeysRef.current.clear();\n usedClassPropKeysRef.current.clear();\n\n // Call selector if provided\n if (options.selector && currentInstance) {\n options.selector(newState, oldState, currentInstance);\n }\n\n // Call listener with state if it expects it\n if (listener.length > 0) {\n (listener as any)(newState);\n } else {\n listener();\n }\n } catch (error) {\n console.error('Listener error in useExternalBlocStore:', error);\n // Don't rethrow to prevent breaking other listeners\n }\n };\n\n const unsubscribe = currentInstance._observer.subscribe({\n id: ridRef.current,\n fn: safeListener,\n });\n return unsubscribe;\n },\n getServerSnapshot: () => {\n const currentInstance = instanceRef.current;\n return currentInstance ? currentInstance.state : undefined;\n },\n }),\n [],\n );\n\n // Update instance ref\n instanceRef.current = bloc;\n\n return {\n externalStore,\n instance: instanceRef,\n usedKeys: usedKeysRef,\n usedClassPropKeys: usedClassPropKeysRef,\n rid: ridRef.current,\n };\n}\n"],"names":["useBloc","blocConstructor","options","renderCount","useRef","componentRef","adapter","useMemo","BlacAdapter","optionsChangeCount","useEffect","mountEffectCount","subscribeMemoCount","subscribe","onStoreChange","unsubscribe","snapshotCount","serverSnapshotCount","rawState","useSyncExternalStore","bloc","stateMemoCount","finalState","blocMemoCount","finalBloc","useExternalBlocStore","ridRef","generateUUID","usedKeysRef","usedClassPropKeysRef","instanceRef","blac","Blac","newBloc","uniqueId","externalStore","currentInstance","listener","safeListener","newState","oldState","error"],"mappings":"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"}
package/dist/index.d.ts DELETED
@@ -1,59 +0,0 @@
1
- import { BlocBase } from '@blac/core';
2
- import { BlocConstructor } from '@blac/core';
3
- import { BlocState } from '@blac/core';
4
- import { InferPropsFromGeneric } from '@blac/core';
5
-
6
- declare interface ExternalBlocStoreResult<B extends BlocBase<any>> {
7
- externalStore: ExternalStore<BlocState<B>>;
8
- instance: {
9
- current: B | null;
10
- };
11
- usedKeys: {
12
- current: Set<string>;
13
- };
14
- usedClassPropKeys: {
15
- current: Set<string>;
16
- };
17
- rid: string;
18
- }
19
-
20
- declare interface ExternalStore<T> {
21
- getSnapshot: () => T | undefined;
22
- subscribe: (listener: () => void) => () => void;
23
- getServerSnapshot?: () => T | undefined;
24
- }
25
-
26
- declare interface ExternalStoreOptions<B extends BlocBase<any>> {
27
- id?: string;
28
- props?: InferPropsFromGeneric<B>;
29
- selector?: (currentState: BlocState<B>, previousState: BlocState<B>, instance: B) => any[];
30
- }
31
-
32
- /**
33
- * Type definition for the return type of the useBloc hook
34
- */
35
- declare type HookTypes<B extends BlocConstructor<BlocBase<any>>> = [
36
- BlocState<InstanceType<B>>,
37
- InstanceType<B>
38
- ];
39
-
40
- /**
41
- * React hook for integrating with Blac state management
42
- */
43
- declare function useBloc<B extends BlocConstructor<BlocBase<any>>>(blocConstructor: B, options?: {
44
- props?: ConstructorParameters<B>[0];
45
- id?: string;
46
- dependencies?: (bloc: InstanceType<B>) => unknown[];
47
- onMount?: (bloc: InstanceType<B>) => void;
48
- onUnmount?: (bloc: InstanceType<B>) => void;
49
- }): HookTypes<B>;
50
- export { useBloc }
51
- export { useBloc as useBlocNext }
52
-
53
- /**
54
- * Hook for using an external bloc store
55
- * Provides low-level access to bloc instances for use with React's useSyncExternalStore
56
- */
57
- export declare function useExternalBlocStore<B extends BlocConstructor<BlocBase<any>>>(blocConstructor: B, options?: ExternalStoreOptions<InstanceType<B>>): ExternalBlocStoreResult<InstanceType<B>>;
58
-
59
- export { }
package/dist/index.es.js DELETED
@@ -1,111 +0,0 @@
1
- import { BlacAdapter as v, generateUUID as h, Blac as w } from "@blac/core";
2
- import { useRef as u, useMemo as b, useEffect as M, useSyncExternalStore as U } from "react";
3
- function P(n, e) {
4
- const m = u(0);
5
- m.current++;
6
- const f = u({}), r = b(() => new v(
7
- {
8
- componentRef: f,
9
- blocConstructor: n
10
- },
11
- {
12
- id: e == null ? void 0 : e.id,
13
- dependencies: e == null ? void 0 : e.dependencies,
14
- props: e == null ? void 0 : e.props,
15
- onMount: e == null ? void 0 : e.onMount,
16
- onUnmount: e == null ? void 0 : e.onUnmount
17
- }
18
- ), []);
19
- r.resetConsumerTracking();
20
- const t = u(0);
21
- M(() => {
22
- t.current++, r.options = {
23
- id: e == null ? void 0 : e.id,
24
- dependencies: e == null ? void 0 : e.dependencies,
25
- props: e == null ? void 0 : e.props,
26
- onMount: e == null ? void 0 : e.onMount,
27
- onUnmount: e == null ? void 0 : e.onUnmount
28
- }, (e == null ? void 0 : e.props) !== void 0 && r.updateProps(e.props);
29
- }, [e == null ? void 0 : e.props, e == null ? void 0 : e.id, e == null ? void 0 : e.dependencies, e == null ? void 0 : e.onMount, e == null ? void 0 : e.onUnmount]);
30
- const x = u(0);
31
- M(() => (x.current++, r.mount(), () => {
32
- r.unmount();
33
- }), [r.blocInstance]);
34
- const B = u(0), c = b(() => (B.current++, (l) => {
35
- const g = r.createSubscription({
36
- onChange: () => {
37
- l();
38
- }
39
- });
40
- return () => {
41
- g();
42
- };
43
- }), [r.blocInstance]), a = u(0), d = u(0), s = U(
44
- c,
45
- // Get snapshot
46
- () => (a.current++, r.blocInstance.state),
47
- // Get server snapshot (same as client for now)
48
- () => {
49
- const l = r.blocInstance;
50
- return d.current++, l.state;
51
- }
52
- ), S = u(0), I = b(() => (S.current++, r.getProxyState(s)), [s]), y = u(0), C = b(() => (y.current++, r.getProxyBlocInstance()), [r.blocInstance]);
53
- return M(() => {
54
- r.updateLastNotified(f.current);
55
- }), [I, C];
56
- }
57
- function K(n, e = {}) {
58
- const m = u(`external-${h()}`), f = u(/* @__PURE__ */ new Set()), r = u(/* @__PURE__ */ new Set()), t = u(null), x = b(() => {
59
- const c = w.getInstance();
60
- if (n.constructor.isolated || n.isolated) {
61
- const d = new n(e == null ? void 0 : e.props), s = (e == null ? void 0 : e.id) || `${n.name}_${h()}`;
62
- return d._updateId(s), c.activateBloc(d), d;
63
- }
64
- return c.getBloc(n, {
65
- id: e == null ? void 0 : e.id,
66
- props: e == null ? void 0 : e.props
67
- });
68
- }, [n, e == null ? void 0 : e.id]), B = b(
69
- () => ({
70
- getSnapshot: () => {
71
- const c = t.current;
72
- return c ? c.state : void 0;
73
- },
74
- subscribe: (c) => {
75
- const a = t.current;
76
- if (!a)
77
- return () => {
78
- };
79
- const d = (S, I) => {
80
- try {
81
- f.current.clear(), r.current.clear(), e.selector && a && e.selector(S, I, a), c.length > 0 ? c(S) : c();
82
- } catch (y) {
83
- console.error("Listener error in useExternalBlocStore:", y);
84
- }
85
- };
86
- return a._observer.subscribe({
87
- id: m.current,
88
- fn: d
89
- });
90
- },
91
- getServerSnapshot: () => {
92
- const c = t.current;
93
- return c ? c.state : void 0;
94
- }
95
- }),
96
- []
97
- );
98
- return t.current = x, {
99
- externalStore: B,
100
- instance: t,
101
- usedKeys: f,
102
- usedClassPropKeys: r,
103
- rid: m.current
104
- };
105
- }
106
- export {
107
- P as useBloc,
108
- P as useBlocNext,
109
- K as useExternalBlocStore
110
- };
111
- //# sourceMappingURL=index.es.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.es.js","sources":["../src/useBloc.ts","../src/useExternalBlocStore.ts"],"sourcesContent":["import {\n AdapterOptions,\n BlacAdapter,\n BlocBase,\n BlocConstructor,\n BlocState,\n} from '@blac/core';\nimport { useEffect, useMemo, useRef, useSyncExternalStore } from 'react';\n\n/**\n * Type definition for the return type of the useBloc hook\n */\ntype HookTypes<B extends BlocConstructor<BlocBase<any>>> = [\n BlocState<InstanceType<B>>,\n InstanceType<B>,\n];\n\n/**\n * React hook for integrating with Blac state management\n */\nfunction useBloc<B extends BlocConstructor<BlocBase<any>>>(\n blocConstructor: B,\n options?: {\n props?: ConstructorParameters<B>[0];\n id?: string;\n dependencies?: (bloc: InstanceType<B>) => unknown[];\n onMount?: (bloc: InstanceType<B>) => void;\n onUnmount?: (bloc: InstanceType<B>) => void;\n },\n): HookTypes<B> {\n // Create a unique identifier for this hook instance\n const renderCount = useRef(0);\n renderCount.current++;\n\n const componentRef = useRef<object>({});\n\n // Track adapter creation\n const adapter = useMemo(() => {\n const newAdapter = new BlacAdapter<B>(\n {\n componentRef: componentRef,\n blocConstructor,\n },\n {\n id: options?.id,\n dependencies: options?.dependencies,\n props: options?.props,\n onMount: options?.onMount,\n onUnmount: options?.onUnmount,\n },\n );\n return newAdapter;\n }, []);\n\n // Reset tracking at the start of each render to ensure we only track\n // properties accessed during the current render\n adapter.resetConsumerTracking();\n\n // Track options changes and update props\n const optionsChangeCount = useRef(0);\n useEffect(() => {\n optionsChangeCount.current++;\n adapter.options = {\n id: options?.id,\n dependencies: options?.dependencies,\n props: options?.props,\n onMount: options?.onMount,\n onUnmount: options?.onUnmount,\n };\n\n if (options?.props !== undefined) {\n adapter.updateProps(options.props);\n }\n }, [options?.props, options?.id, options?.dependencies, options?.onMount, options?.onUnmount]);\n\n // Register as consumer and handle lifecycle\n const mountEffectCount = useRef(0);\n useEffect(() => {\n mountEffectCount.current++;\n adapter.mount();\n\n return () => {\n adapter.unmount();\n };\n }, [adapter.blocInstance]);\n\n // Subscribe to state changes using useSyncExternalStore\n const subscribeMemoCount = useRef(0);\n const subscribe = useMemo(() => {\n subscribeMemoCount.current++;\n let subscriptionCount = 0;\n\n return (onStoreChange: () => void) => {\n subscriptionCount++;\n const unsubscribe = adapter.createSubscription({\n onChange: () => {\n onStoreChange();\n },\n });\n\n return () => {\n unsubscribe();\n };\n };\n }, [adapter.blocInstance]);\n\n const snapshotCount = useRef(0);\n const serverSnapshotCount = useRef(0);\n\n const rawState: BlocState<InstanceType<B>> = useSyncExternalStore(\n subscribe,\n // Get snapshot\n () => {\n snapshotCount.current++;\n const bloc = adapter.blocInstance;\n const state = bloc.state;\n return state;\n },\n // Get server snapshot (same as client for now)\n () => {\n const bloc = adapter.blocInstance;\n serverSnapshotCount.current++;\n const state = bloc.state;\n return state;\n },\n );\n\n // Create proxies for fine-grained tracking (if enabled)\n const stateMemoCount = useRef(0);\n const finalState = useMemo(() => {\n stateMemoCount.current++;\n const proxyState = adapter.getProxyState(rawState);\n return proxyState;\n }, [rawState]);\n\n const blocMemoCount = useRef(0);\n const finalBloc = useMemo(() => {\n blocMemoCount.current++;\n const proxyBloc = adapter.getProxyBlocInstance();\n return proxyBloc;\n }, [adapter.blocInstance]);\n\n // Mark consumer as rendered after each render\n useEffect(() => {\n adapter.updateLastNotified(componentRef.current);\n });\n\n // Log final hook return\n return [finalState, finalBloc];\n}\n\nexport default useBloc;\n","import {\n Blac,\n BlocBase,\n BlocConstructor,\n BlocState,\n InferPropsFromGeneric,\n generateUUID,\n} from '@blac/core';\nimport { useCallback, useMemo, useRef } from 'react';\n\ninterface ExternalStoreOptions<B extends BlocBase<any>> {\n id?: string;\n props?: InferPropsFromGeneric<B>;\n selector?: (\n currentState: BlocState<B>,\n previousState: BlocState<B>,\n instance: B,\n ) => any[];\n}\n\ninterface ExternalStore<T> {\n getSnapshot: () => T | undefined;\n subscribe: (listener: () => void) => () => void;\n getServerSnapshot?: () => T | undefined;\n}\n\ninterface ExternalBlocStoreResult<B extends BlocBase<any>> {\n externalStore: ExternalStore<BlocState<B>>;\n instance: { current: B | null };\n usedKeys: { current: Set<string> };\n usedClassPropKeys: { current: Set<string> };\n rid: string;\n}\n\n/**\n * Hook for using an external bloc store\n * Provides low-level access to bloc instances for use with React's useSyncExternalStore\n */\nexport default function useExternalBlocStore<\n B extends BlocConstructor<BlocBase<any>>,\n>(\n blocConstructor: B,\n options: ExternalStoreOptions<InstanceType<B>> = {},\n): ExternalBlocStoreResult<InstanceType<B>> {\n const ridRef = useRef<string>(`external-${generateUUID()}`);\n const usedKeysRef = useRef<Set<string>>(new Set());\n const usedClassPropKeysRef = useRef<Set<string>>(new Set());\n const instanceRef = useRef<InstanceType<B> | null>(null);\n\n // Get or create bloc instance\n const bloc = useMemo(() => {\n const blac = Blac.getInstance();\n const base = blocConstructor as unknown as BlocBase<any>;\n\n // For isolated blocs, always create a new instance\n if (\n (base.constructor as any).isolated ||\n (blocConstructor as any).isolated\n ) {\n const newBloc = new blocConstructor(options?.props) as InstanceType<B>;\n const uniqueId =\n options?.id || `${blocConstructor.name}_${generateUUID()}`;\n newBloc._updateId(uniqueId);\n blac.activateBloc(newBloc);\n return newBloc;\n }\n\n // For shared blocs, use the existing getBloc logic\n return blac.getBloc(blocConstructor, {\n id: options?.id,\n props: options?.props,\n });\n }, [blocConstructor, options?.id]);\n\n // Create external store interface\n const externalStore = useMemo<ExternalStore<BlocState<InstanceType<B>>>>(\n () => ({\n getSnapshot: () => {\n const currentInstance = instanceRef.current;\n return currentInstance ? currentInstance.state : undefined;\n },\n subscribe: (listener: () => void) => {\n const currentInstance = instanceRef.current;\n if (!currentInstance) {\n // Return no-op unsubscribe if no instance\n return () => {};\n }\n\n // Wrap listener to handle errors gracefully\n const safeListener = (\n newState: BlocState<InstanceType<B>>,\n oldState: BlocState<InstanceType<B>>,\n ) => {\n try {\n // Reset tracking keys on each listener call\n usedKeysRef.current.clear();\n usedClassPropKeysRef.current.clear();\n\n // Call selector if provided\n if (options.selector && currentInstance) {\n options.selector(newState, oldState, currentInstance);\n }\n\n // Call listener with state if it expects it\n if (listener.length > 0) {\n (listener as any)(newState);\n } else {\n listener();\n }\n } catch (error) {\n console.error('Listener error in useExternalBlocStore:', error);\n // Don't rethrow to prevent breaking other listeners\n }\n };\n\n const unsubscribe = currentInstance._observer.subscribe({\n id: ridRef.current,\n fn: safeListener,\n });\n return unsubscribe;\n },\n getServerSnapshot: () => {\n const currentInstance = instanceRef.current;\n return currentInstance ? currentInstance.state : undefined;\n },\n }),\n [],\n );\n\n // Update instance ref\n instanceRef.current = bloc;\n\n return {\n externalStore,\n instance: instanceRef,\n usedKeys: usedKeysRef,\n usedClassPropKeys: usedClassPropKeysRef,\n rid: ridRef.current,\n };\n}\n"],"names":["useBloc","blocConstructor","options","renderCount","useRef","componentRef","adapter","useMemo","BlacAdapter","optionsChangeCount","useEffect","mountEffectCount","subscribeMemoCount","subscribe","onStoreChange","unsubscribe","snapshotCount","serverSnapshotCount","rawState","useSyncExternalStore","bloc","stateMemoCount","finalState","blocMemoCount","finalBloc","useExternalBlocStore","ridRef","generateUUID","usedKeysRef","usedClassPropKeysRef","instanceRef","blac","Blac","newBloc","uniqueId","externalStore","currentInstance","listener","safeListener","newState","oldState","error"],"mappings":"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"}