@blac/react 0.0.1 → 0.0.2

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.
@@ -1,7 +1,7 @@
1
- import { Blac, BlocBase, BlocClass } from 'blac';
1
+ import { Blac, BlocBase, ValueType, BlocClass } from 'blac';
2
2
  import React from 'react';
3
3
 
4
- declare const BlacContext: React.Context<Blac | null>;
4
+ declare const BlacContext: React.Context<Blac<any, any> | null>;
5
5
 
6
6
  /**
7
7
  * Keep track of the hierarchy of Blac BlocProvider components, so that
@@ -14,16 +14,23 @@ interface ProviderItem {
14
14
  bloc: BlocBase<any>;
15
15
  }
16
16
 
17
- interface ExternalStore<S> {
17
+ interface ExternalStore<B extends BlocBase<any>> {
18
18
  subscribe: (onStoreChange: () => void) => () => void;
19
- getSnapshot: () => S;
20
- getServerSnapshot?: () => S;
19
+ getSnapshot: () => ValueType<B>;
20
+ getServerSnapshot?: () => ValueType<B>;
21
21
  }
22
22
 
23
- type BlocHookData<T extends BlocBase<S>, S> = [value: S, instance: T];
24
- type BlocHookOptions<T extends BlocBase<S>, S> = {
23
+ type BlocHookData<B extends BlocBase<S>, S> = [
24
+ value: ValueType<B>,
25
+ instance: B
26
+ ];
27
+ interface BlocHookOptions {
28
+ /**
29
+ * Set to true if you want blac to automatically create a new instance of the bloc,
30
+ * for this to work, pass the unconstructed class to the hook. The constructor should not expect any arguments.
31
+ */
25
32
  create?: boolean;
26
- };
27
- declare const useBloc: <B extends BlocBase<S>, S>(bloc: BlocClass<B> | (() => B), options?: BlocHookOptions<B, S>) => BlocHookData<B, S>;
33
+ }
34
+ declare const useBloc: <B extends BlocBase<S>, S>(bloc: BlocClass<B> | (() => B), options?: BlocHookOptions) => BlocHookData<B, S>;
28
35
 
29
36
  export { BlacContext, BlocHookData, BlocHookOptions, ExternalStore, ProviderItem, useBloc };
@@ -1,4 +1,4 @@
1
- import React, { useContext, createContext, useMemo, useSyncExternalStore } from 'react';
1
+ import React, { useContext, useMemo, useEffect, createContext, useSyncExternalStore } from 'react';
2
2
 
3
3
  /**
4
4
  * Keep track of the hierarchy of Blac BlocProvider components, so that
@@ -37,6 +37,9 @@ class BlacReact {
37
37
  // add the BlacReact instance to blac
38
38
  this.blac.addPluginKey(BlacReact.pluginKey, this);
39
39
  }
40
+ /**
41
+ * React hook to get the bloc instance from the nearest BlocProvider
42
+ */
40
43
  useLocalBlocContext() {
41
44
  return useContext(this.localContextProvider);
42
45
  }
@@ -44,6 +47,9 @@ class BlacReact {
44
47
  get LocalProvider() {
45
48
  return this._contextLocalProviderKey.Provider;
46
49
  }
50
+ /**
51
+ * React hook to get the id from the nearest BlocProvider
52
+ */
47
53
  useLocalProviderKey() {
48
54
  return useContext(this._contextLocalProviderKey);
49
55
  }
@@ -82,29 +88,67 @@ class BlacReact {
82
88
  }
83
89
  return undefined;
84
90
  }
91
+ providerMounted(options) {
92
+ const { bloc, providerId, localProviderKey } = options;
93
+ let instance = undefined;
94
+ let destroyOnUnmount = true;
95
+ const isFunction = bloc instanceof Function;
96
+ const isLiveBloc = !isFunction &&
97
+ typeof bloc === 'object' &&
98
+ bloc?.isBlacLive;
99
+ if (isFunction) {
100
+ instance = bloc();
101
+ }
102
+ if (isLiveBloc) {
103
+ instance = bloc;
104
+ }
105
+ if (instance) {
106
+ this.addLocalBloc({
107
+ bloc: instance,
108
+ id: providerId,
109
+ parent: localProviderKey,
110
+ });
111
+ }
112
+ return { instance, destroyOnUnmount };
113
+ }
114
+ providerUnmounted(providerId) {
115
+ this.removeLocalBloc;
116
+ }
117
+ useLocalProvider = (options) => {
118
+ const [blocInstance, setBlocInstance] = React.useState(undefined);
119
+ const localProviderKey = this.useLocalProviderKey();
120
+ const providerId = useMemo(() => this.createProviderId(), []);
121
+ useEffect(() => {
122
+ const { instance, destroyOnUnmount } = this.providerMounted({
123
+ ...options,
124
+ localProviderKey,
125
+ providerId,
126
+ });
127
+ setBlocInstance(instance);
128
+ if (destroyOnUnmount)
129
+ return this.providerUnmounted(providerId);
130
+ }, []);
131
+ if (blocInstance)
132
+ return providerId;
133
+ };
85
134
  }
86
135
 
87
136
  const BlacContext = createContext(null);
88
137
 
89
- createContext(null);
90
-
91
138
  const externalBlocStore = (bloc) => {
92
139
  return {
93
140
  subscribe: (listener) => {
94
141
  const unSub = bloc.onStateChange(listener);
95
142
  return () => {
96
143
  unSub();
97
- bloc.dispose();
98
144
  };
99
145
  },
100
146
  getSnapshot: () => bloc.state,
101
147
  };
102
148
  };
103
149
 
104
- // B extends BlocBase<S>,
105
150
  const useBloc = (bloc, options = {}) => {
106
151
  const blacReact = BlacReact.getInstance();
107
- // const localCtxP = blacReact.useLocalBlocContext();
108
152
  const localProviderKey = blacReact.useLocalProviderKey();
109
153
  const blacInstance = useContext(BlacContext);
110
154
  const resolvedBloc = useMemo(() => {
@@ -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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -39,6 +39,9 @@ class BlacReact {
39
39
  // add the BlacReact instance to blac
40
40
  this.blac.addPluginKey(BlacReact.pluginKey, this);
41
41
  }
42
+ /**
43
+ * React hook to get the bloc instance from the nearest BlocProvider
44
+ */
42
45
  useLocalBlocContext() {
43
46
  return React.useContext(this.localContextProvider);
44
47
  }
@@ -46,6 +49,9 @@ class BlacReact {
46
49
  get LocalProvider() {
47
50
  return this._contextLocalProviderKey.Provider;
48
51
  }
52
+ /**
53
+ * React hook to get the id from the nearest BlocProvider
54
+ */
49
55
  useLocalProviderKey() {
50
56
  return React.useContext(this._contextLocalProviderKey);
51
57
  }
@@ -84,29 +90,67 @@ class BlacReact {
84
90
  }
85
91
  return undefined;
86
92
  }
93
+ providerMounted(options) {
94
+ const { bloc, providerId, localProviderKey } = options;
95
+ let instance = undefined;
96
+ let destroyOnUnmount = true;
97
+ const isFunction = bloc instanceof Function;
98
+ const isLiveBloc = !isFunction &&
99
+ typeof bloc === 'object' &&
100
+ bloc?.isBlacLive;
101
+ if (isFunction) {
102
+ instance = bloc();
103
+ }
104
+ if (isLiveBloc) {
105
+ instance = bloc;
106
+ }
107
+ if (instance) {
108
+ this.addLocalBloc({
109
+ bloc: instance,
110
+ id: providerId,
111
+ parent: localProviderKey,
112
+ });
113
+ }
114
+ return { instance, destroyOnUnmount };
115
+ }
116
+ providerUnmounted(providerId) {
117
+ this.removeLocalBloc;
118
+ }
119
+ useLocalProvider = (options) => {
120
+ const [blocInstance, setBlocInstance] = React.useState(undefined);
121
+ const localProviderKey = this.useLocalProviderKey();
122
+ const providerId = React.useMemo(() => this.createProviderId(), []);
123
+ React.useEffect(() => {
124
+ const { instance, destroyOnUnmount } = this.providerMounted({
125
+ ...options,
126
+ localProviderKey,
127
+ providerId,
128
+ });
129
+ setBlocInstance(instance);
130
+ if (destroyOnUnmount)
131
+ return this.providerUnmounted(providerId);
132
+ }, []);
133
+ if (blocInstance)
134
+ return providerId;
135
+ };
87
136
  }
88
137
 
89
138
  const BlacContext = React.createContext(null);
90
139
 
91
- React.createContext(null);
92
-
93
140
  const externalBlocStore = (bloc) => {
94
141
  return {
95
142
  subscribe: (listener) => {
96
143
  const unSub = bloc.onStateChange(listener);
97
144
  return () => {
98
145
  unSub();
99
- bloc.dispose();
100
146
  };
101
147
  },
102
148
  getSnapshot: () => bloc.state,
103
149
  };
104
150
  };
105
151
 
106
- // B extends BlocBase<S>,
107
152
  const useBloc = (bloc, options = {}) => {
108
153
  const blacReact = BlacReact.getInstance();
109
- // const localCtxP = blacReact.useLocalBlocContext();
110
154
  const localProviderKey = blacReact.useLocalProviderKey();
111
155
  const blacInstance = React.useContext(BlacContext);
112
156
  const resolvedBloc = React.useMemo(() => {
@@ -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.1",
3
+ "version": "0.0.2",
4
4
  "license": "MIT",
5
5
  "main": "dist/blac-react.js",
6
6
  "module": "dist/blac-react.esm.js",
@@ -18,6 +18,7 @@
18
18
  ],
19
19
  "scripts": {
20
20
  "dev": "vite",
21
+ "build:demo": "vite build",
21
22
  "build": "rollup -c rollup.config.lib.js",
22
23
  "prettier": "prettier --write ./src",
23
24
  "test": "vitest run",
@@ -28,9 +29,9 @@
28
29
  "blac": "*"
29
30
  },
30
31
  "devDependencies": {
31
- "@vitejs/plugin-react": "^3.1.0",
32
32
  "@types/react": "^18.0.28",
33
33
  "@types/react-dom": "^18.0.11",
34
+ "@vitejs/plugin-react": "^3.1.0",
34
35
  "react": "^18.2.0",
35
36
  "react-dom": "^18.2.0",
36
37
  "vite": "^4.1.4",
package/readme.md ADDED
@@ -0,0 +1,16 @@
1
+ # Blac for React
2
+
3
+ Demo [https://blac-react-demo.vercel.app/](https://blac-react-demo.vercel.app/)
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install blac-react
9
+ ```
10
+
11
+ ## Examples
12
+
13
+ - [Counter with Bloc](ui/examples/CounterWithBloc.tsx)
14
+ - [Counter with Cubit](ui/examples/CounterWithCubit.tsx)
15
+ - [Counter with Global State](ui/examples/CounterWithCubitGlobal.tsx)
16
+ - [Counters with Local State](ui/examples/CounterScoped.tsx)