@blac/react 0.0.14 → 0.0.15
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/blac-react.d.ts +8 -66
- package/dist/blac-react.esm.js +108 -242
- package/dist/blac-react.esm.js.map +1 -1
- package/dist/blac-react.js +106 -241
- package/dist/blac-react.js.map +1 -1
- package/package.json +8 -6
- package/readme.md +1 -1
package/dist/blac-react.d.ts
CHANGED
|
@@ -1,67 +1,20 @@
|
|
|
1
|
-
import { Blac, BlocBase,
|
|
1
|
+
import { Blac, BlocBase, ValueType, BlocConstructor } from 'blac';
|
|
2
2
|
import React, { FC, ReactNode } from 'react';
|
|
3
3
|
|
|
4
4
|
declare const BlacApp: FC<{
|
|
5
5
|
children: ReactNode;
|
|
6
|
-
blac
|
|
6
|
+
blac?: Blac<any>;
|
|
7
7
|
}>;
|
|
8
8
|
|
|
9
|
-
/**
|
|
10
|
-
* Keep track of the hierarchy of Blac BlocProvider components, so that
|
|
11
|
-
* useBloc can find the correct bloc instance.
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
interface ProviderItem {
|
|
15
|
-
id: string;
|
|
16
|
-
parent?: string;
|
|
17
|
-
bloc: BlocBase<any>;
|
|
18
|
-
}
|
|
19
|
-
interface ProviderOptions<B> {
|
|
20
|
-
bloc: BlocClass<B> | (() => B);
|
|
21
|
-
debug?: boolean;
|
|
22
|
-
}
|
|
23
9
|
declare class BlacReact {
|
|
24
|
-
blac: Blac<any, any>;
|
|
25
|
-
blacContext: React.Context<Blac<any, any>>;
|
|
26
|
-
localContextProvider: React.Context<BlocBase<any> | null>;
|
|
27
10
|
static pluginKey: string;
|
|
28
|
-
|
|
29
|
-
|
|
11
|
+
blac: Blac<any>;
|
|
12
|
+
blacContext: React.Context<Blac<any>>;
|
|
13
|
+
constructor(blac: Blac<any>, blacContext: React.Context<Blac<any>>);
|
|
30
14
|
static getInstance(throwError?: boolean): BlacReact;
|
|
31
15
|
setup(): void;
|
|
32
|
-
/**
|
|
33
|
-
* React hook to get the bloc instance from the nearest BlocProvider
|
|
34
|
-
*/
|
|
35
|
-
useLocalBlocContext(): BlocBase<any> | null;
|
|
36
|
-
private _contextLocalProviderKey;
|
|
37
|
-
get LocalProvider(): React.Provider<string>;
|
|
38
|
-
/**
|
|
39
|
-
* React hook to get the id from the nearest BlocProvider
|
|
40
|
-
*/
|
|
41
|
-
useLocalProviderKey(): string;
|
|
42
|
-
addLocalBloc: (item: ProviderItem) => void;
|
|
43
|
-
removeLocalBloc: (id: string) => void;
|
|
44
|
-
createProviderId: () => string;
|
|
45
|
-
providerList: ProviderItem[];
|
|
46
|
-
getLocalBlocForProvider<B>(id: string, blocClass: BlocClass<B>): BlocBase<B> | undefined;
|
|
47
|
-
providerMounted(options: {
|
|
48
|
-
providerId: string;
|
|
49
|
-
localProviderKey?: string;
|
|
50
|
-
} & Parameters<BlacReact['useLocalProvider']>[0]): {
|
|
51
|
-
instance: BlocBase<any> | undefined;
|
|
52
|
-
destroyOnUnmount: boolean;
|
|
53
|
-
};
|
|
54
|
-
providerUnmounted(providerId: string | undefined): void;
|
|
55
|
-
readonly useLocalProvider: (options: ProviderOptions<any>) => string | undefined;
|
|
56
16
|
}
|
|
57
17
|
|
|
58
|
-
interface BlocProviderProps<B> {
|
|
59
|
-
children?: ReactNode;
|
|
60
|
-
bloc: BlocClass<B> | (() => B) | B;
|
|
61
|
-
debug?: boolean;
|
|
62
|
-
}
|
|
63
|
-
declare const BlocProvider: FC<BlocProviderProps<any>>;
|
|
64
|
-
|
|
65
18
|
interface ExternalStore<B extends BlocBase<any>> {
|
|
66
19
|
subscribe: (onStoreChange: () => void) => () => void;
|
|
67
20
|
getSnapshot: () => ValueType<B>;
|
|
@@ -69,21 +22,10 @@ interface ExternalStore<B extends BlocBase<any>> {
|
|
|
69
22
|
}
|
|
70
23
|
declare const externalBlocStore: <B extends BlocBase<any>>(bloc: B) => ExternalStore<B>;
|
|
71
24
|
|
|
72
|
-
interface BlocResolveOptions {
|
|
73
|
-
/**
|
|
74
|
-
* Set to true if you want blac to automatically create a new instance of the bloc,
|
|
75
|
-
* for this to work, pass the unconstructed class to the hook. The constructor should not expect any arguments.
|
|
76
|
-
*/
|
|
77
|
-
create?: boolean;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
25
|
type BlocHookData<B extends BlocBase<S>, S> = [
|
|
81
26
|
value: ValueType<B>,
|
|
82
|
-
instance: B
|
|
83
|
-
Provider: FC<{
|
|
84
|
-
children: ReactNode;
|
|
85
|
-
}>
|
|
27
|
+
instance: B
|
|
86
28
|
];
|
|
87
|
-
declare const useBloc: <B extends BlocBase<S>, S>(bloc:
|
|
29
|
+
declare const useBloc: <B extends BlocBase<S>, S>(bloc: BlocConstructor<B>) => BlocHookData<B, S>;
|
|
88
30
|
|
|
89
|
-
export { BlacApp, BlacReact,
|
|
31
|
+
export { BlacApp, BlacReact, ExternalStore, externalBlocStore, useBloc };
|
package/dist/blac-react.esm.js
CHANGED
|
@@ -1,255 +1,121 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Blac } from 'blac';
|
|
2
|
+
import React, { createContext, useMemo, useContext, useSyncExternalStore } from 'react';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
globalThis.blac = this.blac;
|
|
43
|
-
// add the BlacReact instance to blac
|
|
44
|
-
this.blac.addPluginKey(BlacReact.pluginKey, this);
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* React hook to get the bloc instance from the nearest BlocProvider
|
|
48
|
-
*/
|
|
49
|
-
useLocalBlocContext() {
|
|
50
|
-
return useContext(this.localContextProvider);
|
|
51
|
-
}
|
|
52
|
-
_contextLocalProviderKey = React.createContext('none');
|
|
53
|
-
get LocalProvider() {
|
|
54
|
-
return this._contextLocalProviderKey.Provider;
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* React hook to get the id from the nearest BlocProvider
|
|
58
|
-
*/
|
|
59
|
-
useLocalProviderKey() {
|
|
60
|
-
return useContext(this._contextLocalProviderKey);
|
|
61
|
-
}
|
|
62
|
-
addLocalBloc = (item) => {
|
|
63
|
-
this.providerList.push(item);
|
|
64
|
-
};
|
|
65
|
-
removeLocalBloc = (id) => {
|
|
66
|
-
const index = this.providerList.findIndex((i) => i.id === id);
|
|
67
|
-
if (!index)
|
|
68
|
-
return;
|
|
69
|
-
const item = this.providerList[index];
|
|
70
|
-
item.bloc.dispose();
|
|
71
|
-
if (index !== -1) {
|
|
72
|
-
this.providerList.splice(index, 1);
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
|
-
createProviderId = () => {
|
|
76
|
-
return Math.random().toString(36).split('.')[1];
|
|
77
|
-
};
|
|
78
|
-
providerList = new Array();
|
|
79
|
-
getLocalBlocForProvider(id, blocClass) {
|
|
80
|
-
for (const providerItem of this.providerList) {
|
|
81
|
-
if (providerItem.id === id) {
|
|
82
|
-
if (providerItem.bloc instanceof blocClass) {
|
|
83
|
-
return providerItem.bloc;
|
|
84
|
-
}
|
|
85
|
-
let parent = providerItem.parent;
|
|
86
|
-
while (parent) {
|
|
87
|
-
const parentItem = this.providerList.find((i) => i.id === parent);
|
|
88
|
-
if (parentItem?.bloc instanceof blocClass) {
|
|
89
|
-
return parentItem.bloc;
|
|
90
|
-
}
|
|
91
|
-
parent = parentItem?.parent;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
return undefined;
|
|
96
|
-
}
|
|
97
|
-
providerMounted(options) {
|
|
98
|
-
const { bloc, providerId, localProviderKey } = options;
|
|
99
|
-
let instance = undefined;
|
|
100
|
-
let destroyOnUnmount = true;
|
|
101
|
-
const isFunction = bloc instanceof Function;
|
|
102
|
-
const isLiveBloc = !isFunction &&
|
|
103
|
-
typeof bloc === 'object' &&
|
|
104
|
-
bloc?.isBlacLive;
|
|
105
|
-
if (isFunction) {
|
|
106
|
-
instance = bloc();
|
|
107
|
-
}
|
|
108
|
-
if (isLiveBloc) {
|
|
109
|
-
instance = bloc;
|
|
110
|
-
}
|
|
111
|
-
if (instance) {
|
|
112
|
-
this.addLocalBloc({
|
|
113
|
-
bloc: instance,
|
|
114
|
-
id: providerId,
|
|
115
|
-
parent: localProviderKey,
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
return { instance, destroyOnUnmount };
|
|
119
|
-
}
|
|
120
|
-
providerUnmounted(providerId) {
|
|
121
|
-
this.removeLocalBloc(providerId);
|
|
122
|
-
}
|
|
123
|
-
useLocalProvider = (options) => {
|
|
124
|
-
const [blocInstance, setBlocInstance] = React.useState(undefined);
|
|
125
|
-
const localProviderKey = this.useLocalProviderKey();
|
|
126
|
-
const providerId = useMemo(() => this.createProviderId(), []);
|
|
127
|
-
useEffect(() => {
|
|
128
|
-
const { instance, destroyOnUnmount } = this.providerMounted({
|
|
129
|
-
...options,
|
|
130
|
-
localProviderKey,
|
|
131
|
-
providerId,
|
|
132
|
-
});
|
|
133
|
-
setBlocInstance(instance);
|
|
134
|
-
if (destroyOnUnmount)
|
|
135
|
-
return this.providerUnmounted(providerId);
|
|
136
|
-
}, []);
|
|
137
|
-
if (blocInstance)
|
|
138
|
-
return providerId;
|
|
139
|
-
};
|
|
4
|
+
// import { BlocConstructor } from "blac";
|
|
5
|
+
// export interface ProviderItem {
|
|
6
|
+
// id: string;
|
|
7
|
+
// parent?: string;
|
|
8
|
+
// bloc: BlocBase<any>;
|
|
9
|
+
// }
|
|
10
|
+
// interface ProviderOptions<B> {
|
|
11
|
+
// bloc: BlocConstructor<B>;
|
|
12
|
+
// debug?: boolean;
|
|
13
|
+
// }
|
|
14
|
+
class BlacReact {
|
|
15
|
+
static pluginKey = "blacReact";
|
|
16
|
+
blac;
|
|
17
|
+
blacContext;
|
|
18
|
+
constructor(blac, blacContext) {
|
|
19
|
+
const blacReact = blac.getPluginKey(BlacReact.pluginKey);
|
|
20
|
+
// new setup
|
|
21
|
+
this.blac = blac;
|
|
22
|
+
this.blacContext = blacContext;
|
|
23
|
+
this.setup();
|
|
24
|
+
if (blacReact) {
|
|
25
|
+
return blacReact;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
static getInstance(throwError = true) {
|
|
29
|
+
const blac = globalThis.blac;
|
|
30
|
+
if (!blac) {
|
|
31
|
+
throw new Error("BlacReact: blac instance not found");
|
|
32
|
+
}
|
|
33
|
+
const blacReact = blac.getPluginKey(BlacReact.pluginKey);
|
|
34
|
+
if (!blacReact) {
|
|
35
|
+
throw new Error("BlacReact: blacReact instance not found");
|
|
36
|
+
}
|
|
37
|
+
return blacReact;
|
|
38
|
+
}
|
|
39
|
+
setup() {
|
|
40
|
+
globalThis.blac = this.blac;
|
|
41
|
+
this.blac.addPluginKey(BlacReact.pluginKey, this);
|
|
42
|
+
}
|
|
140
43
|
}
|
|
141
44
|
|
|
142
|
-
const BlacContext = createContext(null);
|
|
143
|
-
const BlacApp = (props) => {
|
|
144
|
-
const { children, blac } = props;
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
45
|
+
const BlacContext = createContext(null);
|
|
46
|
+
const BlacApp = (props) => {
|
|
47
|
+
const { children, blac } = props;
|
|
48
|
+
const blacInstance = useMemo(() => blac ?? new Blac(), [blac]);
|
|
49
|
+
const blacApp = useMemo(() => new BlacReact(blacInstance, BlacContext), [blacInstance]);
|
|
50
|
+
if (!blacApp) {
|
|
51
|
+
throw new Error("BlacReact failed to initialize");
|
|
52
|
+
}
|
|
53
|
+
return React.createElement(BlacContext.Provider, { value: blacInstance }, children);
|
|
150
54
|
};
|
|
151
55
|
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
56
|
+
const externalBlocStore = (bloc) => {
|
|
57
|
+
return {
|
|
58
|
+
subscribe: (listener) => {
|
|
59
|
+
const unSub = bloc.onStateChange(listener);
|
|
60
|
+
return () => {
|
|
61
|
+
unSub();
|
|
62
|
+
};
|
|
63
|
+
},
|
|
64
|
+
getSnapshot: () => bloc.state
|
|
65
|
+
};
|
|
159
66
|
};
|
|
160
67
|
|
|
161
|
-
const
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
68
|
+
const resolveBloc = ({ bloc, blacInstance, blacReact
|
|
69
|
+
// create
|
|
70
|
+
}) => {
|
|
71
|
+
// check if its a create function or a class
|
|
72
|
+
const isFunction = bloc instanceof Function;
|
|
73
|
+
const isBloc = isFunction && bloc?.isBlacClass;
|
|
74
|
+
const isLiveBloc = !isFunction &&
|
|
75
|
+
typeof bloc === "object" &&
|
|
76
|
+
bloc?.isBlacLive;
|
|
77
|
+
// if it is a create function, call it
|
|
78
|
+
if (!isBloc && isFunction) {
|
|
79
|
+
return bloc();
|
|
80
|
+
}
|
|
81
|
+
if (bloc?.isBlacLive) {
|
|
82
|
+
return bloc;
|
|
83
|
+
}
|
|
84
|
+
// if it is a class
|
|
85
|
+
const blocClass = bloc;
|
|
86
|
+
if (isLiveBloc) {
|
|
87
|
+
return bloc;
|
|
88
|
+
}
|
|
89
|
+
const registered = blacReact.blac.getBloc(blocClass);
|
|
90
|
+
if (registered) {
|
|
91
|
+
return registered;
|
|
92
|
+
}
|
|
171
93
|
};
|
|
172
|
-
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
const blocClass = bloc;
|
|
187
|
-
// check if the bloc is registered in the blac instance
|
|
188
|
-
if (blacInstance) {
|
|
189
|
-
const e = blacReact.getLocalBlocForProvider(localProviderKey, blocClass);
|
|
190
|
-
if (e) {
|
|
191
|
-
return e;
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
// search in global blocs
|
|
195
|
-
const globalBloc = blacReact.blac.getBloc(blocClass);
|
|
196
|
-
if (globalBloc) {
|
|
197
|
-
return globalBloc;
|
|
198
|
-
}
|
|
199
|
-
if (isLiveBloc) {
|
|
200
|
-
return bloc;
|
|
201
|
-
}
|
|
202
|
-
console.log(typeof bloc, {
|
|
203
|
-
isFunction,
|
|
204
|
-
isBloc,
|
|
205
|
-
isLiveBloc,
|
|
206
|
-
bloc,
|
|
207
|
-
create,
|
|
208
|
-
});
|
|
209
|
-
// if it is not, check if we can create a new instance
|
|
210
|
-
if (!create) {
|
|
211
|
-
// creating it automatically should be opt-in
|
|
212
|
-
throw new Error('useBloc: set create to true to create a new bloc when a class constructor is passed');
|
|
213
|
-
}
|
|
214
|
-
// create a new instance -- this can cause issues if the constructor expects arguments
|
|
215
|
-
const constructed = new blocClass();
|
|
216
|
-
return constructed;
|
|
217
|
-
}
|
|
218
|
-
};
|
|
219
|
-
const useResolvedBloc = (bloc, options = {}) => {
|
|
220
|
-
const blacReact = BlacReact.getInstance();
|
|
221
|
-
const localProviderKey = blacReact.useLocalProviderKey();
|
|
222
|
-
const blacInstance = useContext(BlacContext);
|
|
223
|
-
const resolvedBloc = useMemo(() => {
|
|
224
|
-
if (!blacReact || !localProviderKey) {
|
|
225
|
-
return undefined;
|
|
226
|
-
}
|
|
227
|
-
return resolveBloc({
|
|
228
|
-
bloc,
|
|
229
|
-
blacInstance,
|
|
230
|
-
blacReact,
|
|
231
|
-
localProviderKey,
|
|
232
|
-
create: options.create ?? false
|
|
233
|
-
});
|
|
234
|
-
}, [localProviderKey]);
|
|
235
|
-
console.trace(resolvedBloc, options);
|
|
236
|
-
return resolvedBloc;
|
|
94
|
+
const useResolvedBloc = (bloc) => {
|
|
95
|
+
const blacReact = BlacReact.getInstance();
|
|
96
|
+
const blacInstance = useContext(BlacContext);
|
|
97
|
+
const resolvedBloc = useMemo(() => {
|
|
98
|
+
if (!blacReact) {
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
return resolveBloc({
|
|
102
|
+
bloc,
|
|
103
|
+
blacInstance,
|
|
104
|
+
blacReact
|
|
105
|
+
});
|
|
106
|
+
}, []);
|
|
107
|
+
return resolvedBloc;
|
|
237
108
|
};
|
|
238
109
|
|
|
239
|
-
const useBloc = (bloc
|
|
240
|
-
const resolvedBloc = useResolvedBloc(bloc
|
|
241
|
-
if (!resolvedBloc) {
|
|
242
|
-
throw new Error(
|
|
243
|
-
}
|
|
244
|
-
const { subscribe, getSnapshot } = useMemo(() => externalBlocStore(resolvedBloc), [resolvedBloc]);
|
|
245
|
-
const state = useSyncExternalStore(subscribe, getSnapshot);
|
|
246
|
-
|
|
247
|
-
return ({ children }) => {
|
|
248
|
-
return React.createElement(BlocProvider, { bloc: resolvedBloc }, children);
|
|
249
|
-
};
|
|
250
|
-
}, [resolvedBloc,]);
|
|
251
|
-
return [state, resolvedBloc, Provider];
|
|
110
|
+
const useBloc = (bloc) => {
|
|
111
|
+
const resolvedBloc = useResolvedBloc(bloc);
|
|
112
|
+
if (!resolvedBloc) {
|
|
113
|
+
throw new Error(`useBloc: could not resolve: ${bloc.name || bloc}`);
|
|
114
|
+
}
|
|
115
|
+
const { subscribe, getSnapshot } = useMemo(() => externalBlocStore(resolvedBloc), [resolvedBloc]);
|
|
116
|
+
const state = useSyncExternalStore(subscribe, getSnapshot);
|
|
117
|
+
return [state, resolvedBloc];
|
|
252
118
|
};
|
|
253
119
|
|
|
254
|
-
export { BlacApp, BlacReact,
|
|
120
|
+
export { BlacApp, BlacReact, externalBlocStore, useBloc };
|
|
255
121
|
//# sourceMappingURL=blac-react.esm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blac-react.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"blac-react.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/blac-react.js
CHANGED
|
@@ -1,261 +1,126 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var blac = require('blac');
|
|
3
4
|
var React = require('react');
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
globalThis.blac = this.blac;
|
|
45
|
-
// add the BlacReact instance to blac
|
|
46
|
-
this.blac.addPluginKey(BlacReact.pluginKey, this);
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* React hook to get the bloc instance from the nearest BlocProvider
|
|
50
|
-
*/
|
|
51
|
-
useLocalBlocContext() {
|
|
52
|
-
return React.useContext(this.localContextProvider);
|
|
53
|
-
}
|
|
54
|
-
_contextLocalProviderKey = React.createContext('none');
|
|
55
|
-
get LocalProvider() {
|
|
56
|
-
return this._contextLocalProviderKey.Provider;
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* React hook to get the id from the nearest BlocProvider
|
|
60
|
-
*/
|
|
61
|
-
useLocalProviderKey() {
|
|
62
|
-
return React.useContext(this._contextLocalProviderKey);
|
|
63
|
-
}
|
|
64
|
-
addLocalBloc = (item) => {
|
|
65
|
-
this.providerList.push(item);
|
|
66
|
-
};
|
|
67
|
-
removeLocalBloc = (id) => {
|
|
68
|
-
const index = this.providerList.findIndex((i) => i.id === id);
|
|
69
|
-
if (!index)
|
|
70
|
-
return;
|
|
71
|
-
const item = this.providerList[index];
|
|
72
|
-
item.bloc.dispose();
|
|
73
|
-
if (index !== -1) {
|
|
74
|
-
this.providerList.splice(index, 1);
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
createProviderId = () => {
|
|
78
|
-
return Math.random().toString(36).split('.')[1];
|
|
79
|
-
};
|
|
80
|
-
providerList = new Array();
|
|
81
|
-
getLocalBlocForProvider(id, blocClass) {
|
|
82
|
-
for (const providerItem of this.providerList) {
|
|
83
|
-
if (providerItem.id === id) {
|
|
84
|
-
if (providerItem.bloc instanceof blocClass) {
|
|
85
|
-
return providerItem.bloc;
|
|
86
|
-
}
|
|
87
|
-
let parent = providerItem.parent;
|
|
88
|
-
while (parent) {
|
|
89
|
-
const parentItem = this.providerList.find((i) => i.id === parent);
|
|
90
|
-
if (parentItem?.bloc instanceof blocClass) {
|
|
91
|
-
return parentItem.bloc;
|
|
92
|
-
}
|
|
93
|
-
parent = parentItem?.parent;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
return undefined;
|
|
98
|
-
}
|
|
99
|
-
providerMounted(options) {
|
|
100
|
-
const { bloc, providerId, localProviderKey } = options;
|
|
101
|
-
let instance = undefined;
|
|
102
|
-
let destroyOnUnmount = true;
|
|
103
|
-
const isFunction = bloc instanceof Function;
|
|
104
|
-
const isLiveBloc = !isFunction &&
|
|
105
|
-
typeof bloc === 'object' &&
|
|
106
|
-
bloc?.isBlacLive;
|
|
107
|
-
if (isFunction) {
|
|
108
|
-
instance = bloc();
|
|
109
|
-
}
|
|
110
|
-
if (isLiveBloc) {
|
|
111
|
-
instance = bloc;
|
|
112
|
-
}
|
|
113
|
-
if (instance) {
|
|
114
|
-
this.addLocalBloc({
|
|
115
|
-
bloc: instance,
|
|
116
|
-
id: providerId,
|
|
117
|
-
parent: localProviderKey,
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
return { instance, destroyOnUnmount };
|
|
121
|
-
}
|
|
122
|
-
providerUnmounted(providerId) {
|
|
123
|
-
this.removeLocalBloc(providerId);
|
|
124
|
-
}
|
|
125
|
-
useLocalProvider = (options) => {
|
|
126
|
-
const [blocInstance, setBlocInstance] = React.useState(undefined);
|
|
127
|
-
const localProviderKey = this.useLocalProviderKey();
|
|
128
|
-
const providerId = React.useMemo(() => this.createProviderId(), []);
|
|
129
|
-
React.useEffect(() => {
|
|
130
|
-
const { instance, destroyOnUnmount } = this.providerMounted({
|
|
131
|
-
...options,
|
|
132
|
-
localProviderKey,
|
|
133
|
-
providerId,
|
|
134
|
-
});
|
|
135
|
-
setBlocInstance(instance);
|
|
136
|
-
if (destroyOnUnmount)
|
|
137
|
-
return this.providerUnmounted(providerId);
|
|
138
|
-
}, []);
|
|
139
|
-
if (blocInstance)
|
|
140
|
-
return providerId;
|
|
141
|
-
};
|
|
6
|
+
// import { BlocConstructor } from "blac";
|
|
7
|
+
// export interface ProviderItem {
|
|
8
|
+
// id: string;
|
|
9
|
+
// parent?: string;
|
|
10
|
+
// bloc: BlocBase<any>;
|
|
11
|
+
// }
|
|
12
|
+
// interface ProviderOptions<B> {
|
|
13
|
+
// bloc: BlocConstructor<B>;
|
|
14
|
+
// debug?: boolean;
|
|
15
|
+
// }
|
|
16
|
+
class BlacReact {
|
|
17
|
+
static pluginKey = "blacReact";
|
|
18
|
+
blac;
|
|
19
|
+
blacContext;
|
|
20
|
+
constructor(blac, blacContext) {
|
|
21
|
+
const blacReact = blac.getPluginKey(BlacReact.pluginKey);
|
|
22
|
+
// new setup
|
|
23
|
+
this.blac = blac;
|
|
24
|
+
this.blacContext = blacContext;
|
|
25
|
+
this.setup();
|
|
26
|
+
if (blacReact) {
|
|
27
|
+
return blacReact;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
static getInstance(throwError = true) {
|
|
31
|
+
const blac = globalThis.blac;
|
|
32
|
+
if (!blac) {
|
|
33
|
+
throw new Error("BlacReact: blac instance not found");
|
|
34
|
+
}
|
|
35
|
+
const blacReact = blac.getPluginKey(BlacReact.pluginKey);
|
|
36
|
+
if (!blacReact) {
|
|
37
|
+
throw new Error("BlacReact: blacReact instance not found");
|
|
38
|
+
}
|
|
39
|
+
return blacReact;
|
|
40
|
+
}
|
|
41
|
+
setup() {
|
|
42
|
+
globalThis.blac = this.blac;
|
|
43
|
+
this.blac.addPluginKey(BlacReact.pluginKey, this);
|
|
44
|
+
}
|
|
142
45
|
}
|
|
143
46
|
|
|
144
|
-
const BlacContext = React.createContext(null);
|
|
145
|
-
const BlacApp = (props) => {
|
|
146
|
-
const { children, blac } = props;
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
47
|
+
const BlacContext = React.createContext(null);
|
|
48
|
+
const BlacApp = (props) => {
|
|
49
|
+
const { children, blac: blac$1 } = props;
|
|
50
|
+
const blacInstance = React.useMemo(() => blac$1 ?? new blac.Blac(), [blac$1]);
|
|
51
|
+
const blacApp = React.useMemo(() => new BlacReact(blacInstance, BlacContext), [blacInstance]);
|
|
52
|
+
if (!blacApp) {
|
|
53
|
+
throw new Error("BlacReact failed to initialize");
|
|
54
|
+
}
|
|
55
|
+
return React.createElement(BlacContext.Provider, { value: blacInstance }, children);
|
|
152
56
|
};
|
|
153
57
|
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
58
|
+
const externalBlocStore = (bloc) => {
|
|
59
|
+
return {
|
|
60
|
+
subscribe: (listener) => {
|
|
61
|
+
const unSub = bloc.onStateChange(listener);
|
|
62
|
+
return () => {
|
|
63
|
+
unSub();
|
|
64
|
+
};
|
|
65
|
+
},
|
|
66
|
+
getSnapshot: () => bloc.state
|
|
67
|
+
};
|
|
161
68
|
};
|
|
162
69
|
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
70
|
+
const resolveBloc = ({ bloc, blacInstance, blacReact
|
|
71
|
+
// create
|
|
72
|
+
}) => {
|
|
73
|
+
// check if its a create function or a class
|
|
74
|
+
const isFunction = bloc instanceof Function;
|
|
75
|
+
const isBloc = isFunction && bloc?.isBlacClass;
|
|
76
|
+
const isLiveBloc = !isFunction &&
|
|
77
|
+
typeof bloc === "object" &&
|
|
78
|
+
bloc?.isBlacLive;
|
|
79
|
+
// if it is a create function, call it
|
|
80
|
+
if (!isBloc && isFunction) {
|
|
81
|
+
return bloc();
|
|
82
|
+
}
|
|
83
|
+
if (bloc?.isBlacLive) {
|
|
84
|
+
return bloc;
|
|
85
|
+
}
|
|
86
|
+
// if it is a class
|
|
87
|
+
const blocClass = bloc;
|
|
88
|
+
if (isLiveBloc) {
|
|
89
|
+
return bloc;
|
|
90
|
+
}
|
|
91
|
+
const registered = blacReact.blac.getBloc(blocClass);
|
|
92
|
+
if (registered) {
|
|
93
|
+
return registered;
|
|
94
|
+
}
|
|
173
95
|
};
|
|
174
|
-
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
const
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
const blocClass = bloc;
|
|
189
|
-
// check if the bloc is registered in the blac instance
|
|
190
|
-
if (blacInstance) {
|
|
191
|
-
const e = blacReact.getLocalBlocForProvider(localProviderKey, blocClass);
|
|
192
|
-
if (e) {
|
|
193
|
-
return e;
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
// search in global blocs
|
|
197
|
-
const globalBloc = blacReact.blac.getBloc(blocClass);
|
|
198
|
-
if (globalBloc) {
|
|
199
|
-
return globalBloc;
|
|
200
|
-
}
|
|
201
|
-
if (isLiveBloc) {
|
|
202
|
-
return bloc;
|
|
203
|
-
}
|
|
204
|
-
console.log(typeof bloc, {
|
|
205
|
-
isFunction,
|
|
206
|
-
isBloc,
|
|
207
|
-
isLiveBloc,
|
|
208
|
-
bloc,
|
|
209
|
-
create,
|
|
210
|
-
});
|
|
211
|
-
// if it is not, check if we can create a new instance
|
|
212
|
-
if (!create) {
|
|
213
|
-
// creating it automatically should be opt-in
|
|
214
|
-
throw new Error('useBloc: set create to true to create a new bloc when a class constructor is passed');
|
|
215
|
-
}
|
|
216
|
-
// create a new instance -- this can cause issues if the constructor expects arguments
|
|
217
|
-
const constructed = new blocClass();
|
|
218
|
-
return constructed;
|
|
219
|
-
}
|
|
220
|
-
};
|
|
221
|
-
const useResolvedBloc = (bloc, options = {}) => {
|
|
222
|
-
const blacReact = BlacReact.getInstance();
|
|
223
|
-
const localProviderKey = blacReact.useLocalProviderKey();
|
|
224
|
-
const blacInstance = React.useContext(BlacContext);
|
|
225
|
-
const resolvedBloc = React.useMemo(() => {
|
|
226
|
-
if (!blacReact || !localProviderKey) {
|
|
227
|
-
return undefined;
|
|
228
|
-
}
|
|
229
|
-
return resolveBloc({
|
|
230
|
-
bloc,
|
|
231
|
-
blacInstance,
|
|
232
|
-
blacReact,
|
|
233
|
-
localProviderKey,
|
|
234
|
-
create: options.create ?? false
|
|
235
|
-
});
|
|
236
|
-
}, [localProviderKey]);
|
|
237
|
-
console.trace(resolvedBloc, options);
|
|
238
|
-
return resolvedBloc;
|
|
96
|
+
const useResolvedBloc = (bloc) => {
|
|
97
|
+
const blacReact = BlacReact.getInstance();
|
|
98
|
+
const blacInstance = React.useContext(BlacContext);
|
|
99
|
+
const resolvedBloc = React.useMemo(() => {
|
|
100
|
+
if (!blacReact) {
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
103
|
+
return resolveBloc({
|
|
104
|
+
bloc,
|
|
105
|
+
blacInstance,
|
|
106
|
+
blacReact
|
|
107
|
+
});
|
|
108
|
+
}, []);
|
|
109
|
+
return resolvedBloc;
|
|
239
110
|
};
|
|
240
111
|
|
|
241
|
-
const useBloc = (bloc
|
|
242
|
-
const resolvedBloc = useResolvedBloc(bloc
|
|
243
|
-
if (!resolvedBloc) {
|
|
244
|
-
throw new Error(
|
|
245
|
-
}
|
|
246
|
-
const { subscribe, getSnapshot } = React.useMemo(() => externalBlocStore(resolvedBloc), [resolvedBloc]);
|
|
247
|
-
const state = React.useSyncExternalStore(subscribe, getSnapshot);
|
|
248
|
-
|
|
249
|
-
return ({ children }) => {
|
|
250
|
-
return React.createElement(BlocProvider, { bloc: resolvedBloc }, children);
|
|
251
|
-
};
|
|
252
|
-
}, [resolvedBloc,]);
|
|
253
|
-
return [state, resolvedBloc, Provider];
|
|
112
|
+
const useBloc = (bloc) => {
|
|
113
|
+
const resolvedBloc = useResolvedBloc(bloc);
|
|
114
|
+
if (!resolvedBloc) {
|
|
115
|
+
throw new Error(`useBloc: could not resolve: ${bloc.name || bloc}`);
|
|
116
|
+
}
|
|
117
|
+
const { subscribe, getSnapshot } = React.useMemo(() => externalBlocStore(resolvedBloc), [resolvedBloc]);
|
|
118
|
+
const state = React.useSyncExternalStore(subscribe, getSnapshot);
|
|
119
|
+
return [state, resolvedBloc];
|
|
254
120
|
};
|
|
255
121
|
|
|
256
122
|
exports.BlacApp = BlacApp;
|
|
257
123
|
exports.BlacReact = BlacReact;
|
|
258
|
-
exports.BlocProvider = BlocProvider;
|
|
259
124
|
exports.externalBlocStore = externalBlocStore;
|
|
260
125
|
exports.useBloc = useBloc;
|
|
261
126
|
//# sourceMappingURL=blac-react.js.map
|
package/dist/blac-react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blac-react.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"blac-react.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blac/react",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.15",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "dist/blac-react.js",
|
|
6
6
|
"module": "dist/blac-react.esm.js",
|
|
@@ -29,12 +29,14 @@
|
|
|
29
29
|
"blac": "*"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"@types/react": "^18.
|
|
33
|
-
"@types/react-dom": "^18.
|
|
34
|
-
"@
|
|
32
|
+
"@types/react": "^18.2.17",
|
|
33
|
+
"@types/react-dom": "^18.2.7",
|
|
34
|
+
"@types/react-highlight": "^0.12.5",
|
|
35
|
+
"@vitejs/plugin-react": "^4.0.3",
|
|
35
36
|
"react": "^18.2.0",
|
|
36
37
|
"react-dom": "^18.2.0",
|
|
37
|
-
"
|
|
38
|
-
"
|
|
38
|
+
"react-highlight": "^0.15.0",
|
|
39
|
+
"vite": "^4.4.7",
|
|
40
|
+
"vitest": "^0.33.0"
|
|
39
41
|
}
|
|
40
42
|
}
|
package/readme.md
CHANGED
|
@@ -13,4 +13,4 @@ npm install blac-react
|
|
|
13
13
|
- [Counter with Bloc](ui/examples/CounterWithBloc.tsx)
|
|
14
14
|
- [Counter with Cubit](ui/examples/CounterWithCubit.tsx)
|
|
15
15
|
- [Counter with Global State](ui/examples/CounterWithCubitGlobal.tsx)
|
|
16
|
-
- [Counters with Local State](ui/examples/
|
|
16
|
+
- [Counters with Local State](ui/examples/CounterLocalDemo.tsx)
|