muya 1.1.0 → 2.0.0-beta.1

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.
Files changed (85) hide show
  1. package/README.md +201 -138
  2. package/cjs/index.js +1 -1
  3. package/esm/__tests__/create-async.test.js +1 -0
  4. package/esm/__tests__/test-utils.js +1 -0
  5. package/esm/create.js +1 -1
  6. package/esm/index.js +1 -1
  7. package/esm/subscriber.js +1 -0
  8. package/esm/types.js +1 -1
  9. package/esm/use.js +1 -0
  10. package/esm/utils/__tests__/context.test.js +1 -0
  11. package/esm/utils/__tests__/is.test.js +1 -0
  12. package/esm/utils/__tests__/shallow.test.js +1 -0
  13. package/esm/utils/__tests__/sub-memo.test.js +1 -0
  14. package/esm/utils/common.js +1 -0
  15. package/esm/utils/create-context.js +1 -0
  16. package/esm/utils/create-emitter.js +1 -0
  17. package/esm/utils/is.js +1 -0
  18. package/esm/utils/scheduler.js +1 -0
  19. package/esm/utils/shallow.js +1 -0
  20. package/esm/utils/sub-memo.js +1 -0
  21. package/package.json +1 -1
  22. package/packages/core/__tests__/bench.test.tsx +261 -0
  23. package/packages/core/__tests__/create-async.test.ts +88 -0
  24. package/packages/core/__tests__/create.test.tsx +107 -0
  25. package/packages/core/__tests__/test-utils.ts +40 -0
  26. package/packages/core/__tests__/use-async.test.tsx +44 -0
  27. package/packages/core/__tests__/use.test.tsx +76 -0
  28. package/packages/core/create.ts +67 -0
  29. package/packages/core/index.ts +4 -0
  30. package/packages/core/subscriber.ts +121 -0
  31. package/packages/core/types.ts +15 -0
  32. package/packages/core/use.ts +59 -0
  33. package/packages/core/utils/__tests__/context.test.ts +198 -0
  34. package/packages/core/utils/__tests__/is.test.ts +74 -0
  35. package/packages/core/utils/__tests__/shallow.test.ts +418 -0
  36. package/packages/core/utils/__tests__/sub-memo.test.ts +13 -0
  37. package/packages/core/utils/common.ts +48 -0
  38. package/packages/core/utils/create-context.ts +60 -0
  39. package/packages/core/utils/create-emitter.ts +53 -0
  40. package/packages/core/utils/is.ts +43 -0
  41. package/packages/core/utils/scheduler.ts +59 -0
  42. package/{src → packages/core/utils}/shallow.ts +3 -6
  43. package/packages/core/utils/sub-memo.ts +37 -0
  44. package/types/__tests__/test-utils.d.ts +20 -0
  45. package/types/create.d.ts +14 -21
  46. package/types/index.d.ts +2 -4
  47. package/types/subscriber.d.ts +25 -0
  48. package/types/types.d.ts +9 -65
  49. package/types/use.d.ts +2 -0
  50. package/types/utils/common.d.ts +15 -0
  51. package/types/utils/create-context.d.ts +5 -0
  52. package/types/utils/create-emitter.d.ts +20 -0
  53. package/types/utils/is.d.ts +11 -0
  54. package/types/utils/scheduler.d.ts +6 -0
  55. package/types/utils/sub-memo.d.ts +6 -0
  56. package/esm/common.js +0 -1
  57. package/esm/create-base-state.js +0 -1
  58. package/esm/create-emitter.js +0 -1
  59. package/esm/create-getter-state.js +0 -1
  60. package/esm/is.js +0 -1
  61. package/esm/merge.js +0 -1
  62. package/esm/select.js +0 -1
  63. package/esm/shallow.js +0 -1
  64. package/esm/use-state-value.js +0 -1
  65. package/src/common.ts +0 -28
  66. package/src/create-base-state.ts +0 -35
  67. package/src/create-emitter.ts +0 -24
  68. package/src/create-getter-state.ts +0 -19
  69. package/src/create.ts +0 -102
  70. package/src/index.ts +0 -6
  71. package/src/is.ts +0 -36
  72. package/src/merge.ts +0 -41
  73. package/src/select.ts +0 -33
  74. package/src/state.test.tsx +0 -647
  75. package/src/types.ts +0 -94
  76. package/src/use-state-value.ts +0 -29
  77. package/types/common.d.ts +0 -7
  78. package/types/create-base-state.d.ts +0 -10
  79. package/types/create-emitter.d.ts +0 -7
  80. package/types/create-getter-state.d.ts +0 -6
  81. package/types/is.d.ts +0 -10
  82. package/types/merge.d.ts +0 -2
  83. package/types/select.d.ts +0 -2
  84. package/types/use-state-value.d.ts +0 -10
  85. /package/types/{shallow.d.ts → utils/shallow.d.ts} +0 -0
package/README.md CHANGED
@@ -1,236 +1,299 @@
1
1
 
2
2
  # Muya 🌀
3
- Welcome to Muya – your new best friend for managing state in React applications! Making state management a breeze, focused on simplicity and scalability for real-world scenarios.
4
3
 
5
- [![Build](https://github.com/samuelgjabel/muya/actions/workflows/build.yml/badge.svg)](https://github.com/samuelgjabel/muya/actions/workflows/build.yml)
6
- [![Code quality check](https://github.com/samuelgjabel/muya/actions/workflows/code-check.yml/badge.svg)](https://github.com/samuelgjabel/muya/actions/workflows/code-check.yml)
7
- [![Build Size](https://img.shields.io/bundlephobia/minzip/muya?label=Bundle%20size)](https://bundlephobia.com/result?p=muya)
4
+ Welcome to **Muya v2**—a state management library that makes managing state a breeze, focusing on simplicity and scalability for real-world applications.
8
5
 
6
+ [![Build](https://github.com/samuelgja/muya/actions/workflows/build.yml/badge.svg)](https://github.com/samuelgja/muya/actions/workflows/build.yml)
7
+ [![Code Quality Check](https://github.com/samuelgja/muya/actions/workflows/code-check.yml/badge.svg)](https://github.com/samuelgja/muya/actions/workflows/code-check.yml)
8
+ [![Build Size](https://img.shields.io/bundlephobia/minzip/muya?label=Bundle%20size)](https://bundlephobia.com/result?p=muya)
9
9
 
10
+ ---
10
11
 
11
12
  ## 🚀 Features
12
- - Easy State Creation: Kickstart your state management with simple and intuitive APIs.
13
- - Selectors & Merges: Grab exactly what you need from your state and combine multiple states seamlessly.
14
- - Deep Nesting Support: Handle complex state structures without breaking a sweat.
15
- - Optimized Rendering: Prevent unnecessary re-renders with smart equality checks.
16
- - Concurrency Handling: Stay cool under pressure with robust concurrency support.
17
- - TypeScript Ready: Fully typed for maximum developer sanity.
18
13
 
14
+ - **Simple State Creation**: Easily create global state with an intuitive API.
15
+ - **Functional Derivations**: Derive / Compute new state using plain functions, embracing functional programming.
16
+ - **Async Support**: Async derived states work out of the box, with support for React Suspense.
17
+ - **Performance Optimizations**: WIP Batch state updates for optimized rendering.
18
+ - **TypeScript Support**: Fully typed for a better developer experience.
19
+ - **Small Bundle Size**: Lightweight and efficient—no unnecessary bloat.
20
+
21
+ ---
22
+
23
+ Info: [Muya v2](https://medium.com/p/106de3d04c43)
24
+
25
+ ### 💡 How It Works
26
+ Muya v2 uses its own custom context system to track dependencies and notify components when state changes. When you use a function that accesses state in your component, Muya tracks which states are used and re-renders the component when any of them change.
27
+
28
+ This allows you to write derived state as plain functions, making your code more intuitive and closer to standard JavaScript. No need to define selectors or use special APIs—just use functions!
29
+
30
+ ---
19
31
 
20
32
  ## 📦 Installation
21
33
 
22
34
  ```bash
23
- bun add muya
35
+ npm install muya
24
36
  ```
25
- or
37
+
38
+ Or using Yarn:
39
+
26
40
  ```bash
27
41
  yarn add muya
28
42
  ```
29
- or
43
+
44
+ Or using Bun:
45
+
30
46
  ```bash
31
- npm install muya
47
+ bun add muya
32
48
  ```
33
49
 
50
+ ---
51
+
34
52
  ## 📝 Quick Start
35
53
 
36
- ```typescript
37
- import { create } from 'muya'
54
+ Here's how to get started with **Muya v2**:
38
55
 
39
- const useCounter = create(0)
56
+ ### Creating State
40
57
 
41
- function App() {
42
- const counter = useCounter()
43
- return <div onClick={() => useCounter.setState((prev) => prev + 1)}>{counter}</div>
44
- }
58
+ ```typescript
59
+ import { create } from 'muya';
60
+
61
+ const counter = create(0);
45
62
  ```
46
63
 
47
- ### Update
48
- Sugar syntax above the `setState` method for partially updating the state.
49
- ```typescript
50
- import { create } from 'muya'
64
+ ### Using State in Components
51
65
 
52
- const useUser = create({ name: 'John', lastName: 'Doe' })
66
+ ```tsx
67
+ import React from 'react';
68
+ import { use } from 'muya';
53
69
 
54
- function App() {
55
- const user = useUser()
56
- // this will just partially update only the name field, it's sugar syntax for setState.
57
- return <div onClick={() => useUser.updateState({ name: 'Nope' })}>{user.name}</div>
70
+ function Counter() {
71
+ const count = use(counter);
72
+
73
+ return (
74
+ <div>
75
+ <button onClick={() => counter.set((prev) => prev + 1)}>
76
+ Increment
77
+ </button>
78
+ <p>Count: {count}</p>
79
+ </div>
80
+ );
58
81
  }
59
82
  ```
60
83
 
84
+ ---
61
85
 
62
- ### Selecting parts of the state globally
63
- ```tsx
64
- import { create } from 'muya'
86
+ ## 📚 Examples
65
87
 
66
- const useUser = create({ name: 'John', age: 30 })
88
+ ### Deriving / Selecting State with Functions
67
89
 
68
- // Selecting only the name part of the state
69
- const useName = useUser.select((user) => user.name)
90
+ You can derive new state using plain functions:
70
91
 
71
- function App() {
72
- const name = useName()
73
- return <div onClick={() => useUser.setState((prev) => ({ ...prev, name: 'Jane' }))}>{name}</div>
92
+ ```typescript
93
+ const counter = create(0);
94
+
95
+ function doubled() {
96
+ return counter() * 2;
74
97
  }
98
+ ```
75
99
 
100
+ Use it in a component:
101
+
102
+ ```tsx
103
+ function DoubledCounter() {
104
+ const value = use(doubled);
105
+
106
+ return <p>Doubled Count: {value}</p>;
107
+ }
76
108
  ```
77
109
 
78
- ### Merge two states
79
- ```typescript
80
- import { create, shallow } from 'muya'
110
+ ### Complex Derivations
111
+
112
+ Create more complex derived states by composing functions:
81
113
 
82
- const useName = create(() => 'John')
83
- const useAge = create(() => 30)
114
+ ```tsx
115
+ import { create, use } from 'muya';
84
116
 
85
- const useFullName = useName.merge(useAge, (name, age) => ` ${name} and ${age}`, shallow)
117
+ const state1 = create(0);
118
+ const state2 = create(0);
119
+ const state3 = create(0);
86
120
 
87
- function App() {
88
- const fullName = useFullName()
89
- return <div onClick={() => useName.setState((prev) => 'Jane')}>{fullName}</div>
121
+ function sum() {
122
+ return state1() + state2() + state3();
90
123
  }
91
- ```
92
124
 
125
+ function multiply() {
126
+ return sum() * 2; // Example multiplier
127
+ }
93
128
 
94
- ### Promise based state and lifecycle management working with React Suspense
95
- This methods are useful for handling async data fetching and lazy loading via React Suspense.
129
+ function isOdd() {
130
+ return multiply() % 2 === 1;
131
+ }
96
132
 
97
- #### Immediate Promise resolution
98
- ```typescript
99
- import { create } from 'muya';
100
- // state will try to resolve the promise immediately, can hit the suspense boundary
101
- const counterState = create(Promise.resolve(0));
133
+ function App() {
134
+ const isOddValue = use(isOdd);
102
135
 
103
- function Counter() {
104
- const counter = counterState();
105
136
  return (
106
- <div onClick={() => counterState.setState((prev) => prev + 1)}>
107
- {counter}
137
+ <div>
138
+ <button onClick={() => state1.set((c) => c + 1)}>Increment Counter 1</button>
139
+ <button onClick={() => state2.set((c) => c + 1)}>Increment Counter 2</button>
140
+ <button onClick={() => state3.set((c) => c + 1)}>Increment Counter 3</button>
141
+ <p>Is ODD: {isOddValue ? 'Yes' : 'No'}</p>
108
142
  </div>
109
143
  );
110
144
  }
111
145
  ```
112
146
 
113
- #### Lazy Promise resolution
114
- ```typescript
115
- import { create } from 'muya';
116
- // state will lazy resolve the promise on first access, this will hit the suspense boundary if the first access is from component and via `counterState.getState()` method
117
- const counterState = create(() => Promise.resolve(0));
118
147
 
119
- function Counter() {
120
- const counter = counterState();
148
+ ### Derive state with parameters
149
+ ```tsx
150
+
151
+ import React, { useCallback, useState } from 'react';
152
+ import { create, use } from 'muya';
153
+
154
+ const counter1 = create(0);
155
+ const counter2 = create(0);
156
+
157
+ function multipliedSum(multiplier: number) {
158
+ return (counter1() + counter2()) * multiplier;
159
+ }
160
+
161
+ function MultipliedCounter() {
162
+ const [multiplier, setMultiplier] = useState(1);
163
+ // make sure to use useCallback to memoize the function
164
+ const multiply = useCallback(() => multipliedSum(multiplier), [multiplier]);
165
+ const result = use(multiply);
166
+
121
167
  return (
122
- <div onClick={() => counterState.setState((prev) => prev + 1)}>
123
- {counter}
168
+ <div>
169
+ <button onClick={() => counter1.set((c) => c + 1)}>
170
+ Increment Counter 1
171
+ </button>
172
+ <button onClick={() => counter2.set((c) => c + 1)}>
173
+ Increment Counter 2
174
+ </button>
175
+ <button onClick={() => setMultiplier((m) => m + 1)}>
176
+ Increment Multiplier
177
+ </button>
178
+ <p>Result: {result}</p>
124
179
  </div>
125
180
  );
126
181
  }
127
182
  ```
128
183
 
184
+ ### Async derives State
129
185
 
130
- ## 🔍 API Reference
186
+ ```tsx
187
+ import { create } from 'muya';
131
188
 
132
- ### `create`
189
+ const counter = create(1);
133
190
 
134
- Creates a basic atom state.
191
+ async function fetchData() {
192
+ const response = await fetch(`https://jsonplaceholder.typicode.com/todos/${counter()}`);
193
+ return response.json();
194
+ }
135
195
 
136
- ```typescript
137
- function create<T>(defaultState: T, options?: StateOptions<T>): StateSetter<T>;
138
- ```
196
+ // make sure this component is wrapped in a <Suspense> component
197
+ function Component() {
198
+ const data = use(fetchData);
199
+
200
+ return (
201
+ <div>
202
+ <button onClick={() => counter.set((prev) => prev + 1)}>Increment</button>
203
+ <p>{JSON.stringify(data)}</p>
204
+ </div>
205
+ );
206
+ }
139
207
 
140
- **Example:**
141
208
 
142
- ```typescript
143
- const userState = create({ name: 'John', age: 30 });
144
209
  ```
210
+ ---
145
211
 
146
- ### `select`
147
212
 
148
- Selects a slice of an existing state directly or via a selector function.
149
213
 
150
- ```typescript
151
- // userState is ready to use as hook, so you can name it with `use` prefix
152
- const userState = create({ name: 'John', age: 30 });
153
- // Direct selection outside the component, is useful for accessing the slices of the state in multiple components
154
- const userAgeState = userState.select((user) => user.age);
155
- ```
156
-
157
- ### `merge`
158
- Merges two states into a single state.
159
- ```typescript
160
- const useName = create(() => 'John');
161
- const useAge = create(() => 30);
162
- const useFullName = useName.merge(useAge, (name, age) => ` ${name} and ${age}`);
163
- ```
164
214
 
215
+ ## 📖 Documentation
165
216
 
166
- ### `setState`
167
- Sets the state to a new value or a function that returns a new value.
217
+ #### `create`
168
218
 
169
219
  ```typescript
170
- const userState = create({ name: 'John', age: 30 });
171
- userState.setState({ name: 'Jane' });
220
+ function create<T>(initialState: T): State<T>;
172
221
  ```
173
222
 
174
- ### `updateState`
175
- Partially updates the state with a new value.
176
-
223
+ Create return state block or atom, setting a new value to the state will trigger a re-render of all components using the state.
177
224
  ```typescript
178
- const userState = create({ name: 'John', age: 30 });
179
- userState.updateState({ name: 'Jane' });
225
+ const counter = create(0);
226
+ // set new value
227
+ counter.set(1);
180
228
  ```
181
229
 
182
- ### `getState`
183
- Returns the current state value outside the component.
184
-
230
+ Get the state value outside of react
185
231
  ```typescript
186
- const userState = create({ name: 'John', age: 30 });
187
- const user = userState.getState();
232
+ const value = counter();
233
+ // call it like a function
234
+ console.log(value()); // 1
188
235
  ```
189
236
 
190
- ### `use`
191
- Creates a hook for the state.
237
+ Each state created by create has the following properties and methods:
238
+
239
+ - id: number: Unique identifier for the state.
240
+ - (): T: The state is callable to get the current value.
241
+ - set(value: T | ((prev: T) => T)): Update the state value.
242
+ - listen(listener: (value: T) => void): () => void: Subscribe to state changes.
192
243
 
244
+ #### `use` hook
245
+ Use hook to get state value in react component
193
246
  ```typescript
194
- const useCounter = create(0);
195
- // use inside the component
196
- const counter = useCounter();
247
+ function use<T>(state: State<T> | (() => T)): T;
197
248
  ```
249
+ example
250
+ ```tsx
251
+ const counter = create(0);
198
252
 
199
- ### `subscribe`
200
- Subscribes to the state changes.
253
+ // in react component
254
+ const count = use(counter);
255
+ ```
201
256
 
202
- ```typescript
203
- const userState = create({ name: 'John', age: 30 });
204
- const unsubscribe = userState.subscribe((state) => console.log(state));
257
+ Also custom selector to avoid re-rendering the app
258
+ ```tsx
259
+ const doubled = create({doubled:true});
260
+ // in react component
261
+ const value = use(doubled, (state) => state.doubled);
205
262
  ```
206
263
 
207
264
 
208
265
 
209
- ### Access from outside the component
210
- :warning: Avoid using this method for state management in [React Server Components](https://github.com/reactjs/rfcs/blob/main/text/0188-server-components.md), especially in Next.js 13+. It may cause unexpected behavior or privacy concerns.
211
- ```typescript
212
- const userState = create({ name: 'John', age: 30 });
213
- const user = userState.getState();
214
- ```
215
- ---
216
266
 
217
267
 
218
- ### Slicing new references
219
- :warning: Slicing data with new references can lead to maximum call stack exceeded error.
220
- It's recommended to not use new references for the state slices, if you need so, use `shallow` or other custom equality checks.
221
- ```typescript
222
- import { state, shallow } from 'muya';
223
- const userState = create({ name: 'John', age: 30 });
224
- // this slice will create new reference object on each call
225
- const useName = userState.select((user) => ({newUser: user.name }), shallow);
268
+ ### ⚠️ Notes
269
+ Memoization: When using derived functions with parameters, you should memoize them using useCallback to prevent unnecessary re-renders and prevent function calls.
270
+ ```tsx
271
+ Copy code
272
+ const multiply = useCallback(() => multipliedSum(multiplier), [multiplier]);
273
+ ```
274
+ Async Functions: Async functions used in use should handle errors appropriately and may need to use React's Suspense for loading states.
275
+ Also keep in note, setting new state in async derives, will cancel the pending previous one in the queue.
276
+
277
+ ```tsx
278
+ Copy code
279
+ function App() {
280
+ return (
281
+ <Suspense fallback={<div>Loading...</div>}>
282
+ <DataComponent />
283
+ </Suspense>
284
+ );
285
+ }
226
286
  ```
227
287
 
228
- ## 🤖 Contributing
229
- Contributions are welcome! Please read the [contributing guidelines](CONTRIBUTING.md) before submitting a pull request.
288
+ Error Handling: If an async function throws an error, you can catch it using React's error boundaries.
289
+
290
+ ### 🤖 Contributing
291
+ Contributions are welcome! Please read the contributing guidelines before submitting a pull request.
230
292
 
231
- ## 🧪 Testing
293
+ ### 🧪 Testing
232
294
  Muya comes with a robust testing suite. Check out the state.test.tsx for examples on how to write your own tests.
233
295
 
234
- ## 📜 License
235
296
 
236
- Muya is [MIT licensed](LICENSE).
297
+ ### 🙏 Acknowledgments
298
+ Special thanks to reddit to motivate me for v2 :D
299
+
package/cjs/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";var G=Object.defineProperty;var z=Object.getOwnPropertyDescriptor;var F=Object.getOwnPropertyNames;var M=Object.prototype.hasOwnProperty;var C=(t,e)=>{for(var r in e)G(t,r,{get:e[r],enumerable:!0})},L=(t,e,r,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of F(e))!M.call(t,n)&&n!==r&&G(t,n,{get:()=>e[n],enumerable:!(a=z(e,n))||a.enumerable});return t};var W=t=>L(G({},"__esModule",{value:!0}),t);var H={};C(H,{StateKeys:()=>_,create:()=>D,getDefaultValue:()=>y,merge:()=>b,select:()=>g,shallow:()=>v,useStateValue:()=>x});module.exports=W(H);function p(t){return t instanceof Promise}function q(t){return typeof t=="function"}function I(t){return typeof t=="function"}function R(t){return typeof t=="object"&&t!==null}function w(t){return t instanceof Map}function k(t){return t instanceof Set}function V(t){return Array.isArray(t)}function c(t,e){return t===e?!0:!!Object.is(t,e)}var _=(r=>(r.IS_STATE="isState",r.IS_SLICE="isSlice",r))(_||{});function y(t){return p(t)?t:q(t)?t():t}function T(t){let e=new Set;return{subscribe:r=>(e.add(r),()=>{e.delete(r)}),emit:(...r)=>{for(let a of e)a(...r)},getSnapshot:t}}var P=require("use-sync-external-store/shim/with-selector"),h=require("react");function O(t){return t}function j(t,e,r){let a=(0,P.useSyncExternalStoreWithSelector)(t.subscribe,t.getSnapshot,t.getSnapshot,e?n=>e(n):O,r);return(0,h.useDebugValue)(a),a}function x(t,e=a=>a,r){let a=j(t.__internal.emitter,n=>e(n),r);if(p(a))throw a;return a}function m(t){let{baseState:e}=t,r=(a,n)=>x(r,a,n);return r.__internal=e.__internal,r.getState=e.getState,r.reset=e.reset,r.select=e.select,r.merge=e.merge,r.subscribe=e.subscribe,r}function b(t,e,r,a=c){let n,o=T(()=>{let f=r(t.getState(),e.getState());return n!==void 0&&a(n,f)?n:(n=f,f)});t.__internal.emitter.subscribe(()=>{o.emit()}),e.__internal.emitter.subscribe(()=>{o.emit()});let s=l({emitter:o,getGetterState:()=>S,getState:()=>r(t.getState(),e.getState()),reset(){t.reset(),e.reset()}}),S=m({baseState:s});return S}function g(t,e,r=c){let a,n=T(()=>{let S=e(t.getState());return a!==void 0&&r(a,S)?a:(a=S,S)});t.__internal.emitter.subscribe(()=>{n.emit()});let o=l({emitter:n,getGetterState:()=>s,getState:()=>e(t.getState()),reset:t.reset}),s=m({baseState:o});return s}function l(t){let{emitter:e,getGetterState:r,reset:a,getState:n}=t;return{getState:n,reset:a,select(o,s){let S=r();return g(S,o,s)},merge(o,s,S){let f=r();return b(f,o,s,S)},__internal:{emitter:e},subscribe(o){return o(n()),e.subscribe(()=>{o(n())})}}}function D(t,e=c){function r(i,u){return I(u)?u(i):u}let a={updateVersion:0,value:void 0};function n(){return a.value===void 0&&(a.value=y(t)),a.value}function o(){let i=n();return p(i)&&i.then(u=>{a.value=u,f.emit()}),i}function s(i){let u=n(),E=r(u,i);e?.(u,E)||E===u||(a.updateVersion++,a.value=E,f.emit())}function S(i){if(R(i))return s(u=>({...u,...i}));s(i)}let f=T(o),U=l({emitter:f,getGetterState:()=>d,getState:o,reset(){let i=y(t);if(p(i)){i.then(u=>{s(u)});return}s(i)}}),d=m({baseState:U});return d.setState=s,d.updateState=S,d}function v(t,e){if(t==e||Object.is(t,e))return!0;if(typeof t!="object"||t==null||typeof e!="object"||e==null)return!1;if(w(t)&&w(e)){if(t.size!==e.size)return!1;for(let[n,o]of t)if(!Object.is(o,e.get(n)))return!1;return!0}if(k(t)&&k(e)){if(t.size!==e.size)return!1;for(let n of t)if(!e.has(n))return!1;return!0}if(V(t)&&V(e)){if(t.length!==e.length)return!1;for(let[n,o]of t.entries())if(!Object.is(o,e[n]))return!1;return!0}let r=Object.keys(t),a=Object.keys(e);if(r.length!==a.length)return!1;for(let n of r)if(!Object.prototype.hasOwnProperty.call(e,n)||!Object.is(t[n],e[n]))return!1;return!0}
1
+ "use strict";var h=Object.defineProperty;var q=Object.getOwnPropertyDescriptor;var X=Object.getOwnPropertyNames;var N=Object.prototype.hasOwnProperty;var K=(e,t)=>{for(var r in t)h(e,r,{get:t[r],enumerable:!0})},Y=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of X(t))!N.call(e,n)&&n!==r&&h(e,n,{get:()=>t[n],enumerable:!(o=q(t,n))||o.enumerable});return e};var G=e=>Y(h({},"__esModule",{value:!0}),e);var J={};K(J,{EMPTY_SELECTOR:()=>w,create:()=>U,shallow:()=>j,use:()=>H});module.exports=G(J);var w=e=>e;function p(e){return e instanceof Promise}function g(e){return typeof e=="function"}function R(e){return e instanceof Map}function C(e){return e instanceof Set}function P(e){return Array.isArray(e)}function b(e,t){return e===t?!0:!!Object.is(e,t)}function A(e){return typeof e=="function"}function I(e){return e instanceof DOMException&&e.name==="StateAbortError"}function v(e){return e instanceof Error&&e.name!=="StateAbortError"}function l(e){return e===void 0}function M(e,t){t&&t.abort();let r=new AbortController,{signal:o}=r;return{promise:new Promise((i,s)=>{o.addEventListener("abort",()=>{s(new DOMException("Promise was aborted","StateAbortError"))}),e.then(i).catch(s)}),controller:r}}var W=0;function y(){return W++}function E(e,t=(r,o)=>r===o){if(!l(e.current)){if(!l(e.previous)&&t(e.current,e.previous))return!1;e.previous=e.current}return!0}function S(e,t){let r=new Set,o=[];return{clear:()=>{for(let n of o)n();r.clear()},subscribe:n=>(r.add(n),()=>{r.delete(n)}),emit:(...n)=>{for(let i of r)i(...n)},contains:n=>r.has(n),getSnapshot:e,getInitialSnapshot:t,getSize:()=>r.size,subscribeToOtherEmitter(n){let i=n.subscribe(()=>{this.emit()});o.push(i)}}}function D(e){let t=new Set,{onResolveItem:r,onFinish:o}=e,n=performance.now(),i=!1;function s(){let c=performance.now(),f=c-n,{size:m}=t;if(f<.2&&m>0&&m<10){n=c,u();return}i||(i=!0,Promise.resolve().then(()=>{i=!1,n=performance.now(),u()}))}function u(){if(t.size!==0){for(let c of t)r&&r(c),t.delete(c);if(t.size>0){s();return}o()}}function a(c){t.add(c),s()}return a}var $=Symbol("_");function V(e){let t=[];function r(){if(t.length===0)return e;let i=t.at(-1);return i===$?e:i}function o(i,s){t.push(i);let u=s();return p(u)?(async()=>{try{return await u}finally{t.pop()}})():(t.pop(),u)}function n(i){let s=r();return()=>{t.push(s);let u=i();return p(u)?(async()=>{try{return await u}finally{t.pop()}})():(t.pop(),u)}}return{run:o,use:r,wrap:n}}var F=V(void 0);function L(e){let t=[],r={},o={},n=!1,i=S(()=>n?o.current:(n=!0,c()),()=>(n=!0,c()));async function s(){E(o,b)&&(r.controller&&r.controller.abort(),o.current=c(),i.emit())}let u=y(),a={addEmitter(f){let m=f.subscribe(s);t.push(m)},id:u,sub:s},c=function(){let f=F.run(a,e);if(p(f)){let{controller:m,promise:O}=M(f,r.controller);r.controller=m,O?.then(d=>{o.current=d,i.emit()}).catch(d=>{if(!I(d))throw d});let k=O;return o.current=k,k}return o.current=f,f};return c.emitter=i,c.destroy=function(){for(let f of t)f();i.clear()},c.id=u,c.listen=function(f){return i.subscribe(()=>{let m=o.current;if(l(m))throw new Error("The value is undefined");f(m)})},c.abort=function(){r.controller&&r.controller.abort()},c}function U(e,t=b){let r={};function o(){return l(r.current)&&(r.current=g(e)?e():e),r.current}function n(u){let a=o();r.current=A(u)?u(a):u}let i=D({onFinish(){r.current=o(),E(r,t)&&s.emitter.emit()},onResolveItem:n}),s=function(){let u=o(),a=F.use();return a&&!s.emitter.contains(a.sub)&&a.addEmitter(s.emitter),u};return s.listen=function(u){return s.emitter.subscribe(()=>{let a=r.current;if(l(a))throw new Error("The value is undefined");u(a)})},s.emitter=S(()=>s()),s.id=y(),s.set=i,s}var T=require("react");var z=require("react");var x=new WeakMap;function _(e){return{call(){let t=x.get(e);if(t)return t.count++,t.returnType;let o={count:1,returnType:L(e)};return x.set(e,o),o.returnType},destroy(){let t=x.get(e);t&&(t.count--,t.count===0&&(t.returnType.destroy(),x.delete(e)))}}}function H(e,t=w){let r=_(e),o=r.call(),n=o.emitter.getInitialSnapshot??o.emitter.getSnapshot;(0,T.useEffect)(()=>r.destroy,[e]);let i=(0,z.useSyncExternalStore)(o.emitter.subscribe,()=>t(o.emitter.getSnapshot()),()=>t(n()));if((0,T.useDebugValue)(i),p(i))throw i;if(v(i))throw r.destroy(),i;return i}function j(e,t){if(e==t)return!0;if(typeof e!="object"||e==null||typeof t!="object"||t==null)return!1;if(R(e)&&R(t)){if(e.size!==t.size)return!1;for(let[n,i]of e)if(!Object.is(i,t.get(n)))return!1;return!0}if(C(e)&&C(t)){if(e.size!==t.size)return!1;for(let n of e)if(!t.has(n))return!1;return!0}if(P(e)&&P(t)){if(e.length!==t.length)return!1;for(let[n,i]of e.entries())if(!Object.is(i,t[n]))return!1;return!0}let r=Object.keys(e),o=Object.keys(t);if(r.length!==o.length)return!1;for(let n of r)if(!Object.prototype.hasOwnProperty.call(t,n)||!Object.is(e[n],t[n]))return!1;return!0}
@@ -0,0 +1 @@
1
+ import{create as r}from"../create";import{waitFor as c}from"@testing-library/react";import{longPromise as m}from"./test-utils";import{isPromise as u}from"../utils/is";import{subscriber as n}from"../subscriber";describe("create",()=>{it("should subscribe to context and notified it with parameters",async()=>{const t=r(1),i=r(2);function s(){return t()+i()}async function a(p){return t()+i()+s()+p}let o=0;const e=n(()=>a(10));expect(u(e.emitter.getSnapshot())).toBe(!0),e.listen(async()=>{o++}),expect(o).toBe(0),expect(await e()).toBe(16),t.set(2),await c(async()=>{}),expect(await e()).toBe(18),expect(o).toBe(4)}),it("should async subscribe to context and notified it",async()=>{const t=r(1),i=r(Promise.resolve(2));async function s(){return await m(),t()+await i()}async function a(){return t()+await i()+await s()}let o=0;const e=n(a);e.listen(()=>{o++}),e(),expect(t.emitter.getSize()).toBe(1),expect(i.emitter.getSize()).toBe(1),expect(e.emitter.getSize()).toBe(1),t.set(2),await c(async()=>{expect(await e()).toBe(8),expect(o).toBe(5)}),i.set(3),await c(async()=>{expect(await e()).toBe(10),expect(o).toBe(10)}),expect(t.emitter.getSize()).toBe(1),expect(i.emitter.getSize()).toBe(1),expect(e.emitter.getSize()).toBe(1),e.destroy(),expect(t.emitter.getSize()).toBe(0),expect(i.emitter.getSize()).toBe(0),expect(e.emitter.getSize()).toBe(0)})});
@@ -0,0 +1 @@
1
+ import{Component as t}from"react";function n(e=200){return new Promise(r=>{setTimeout(()=>{r(0)},e)})}class c extends t{constructor(r){super(r),this.state={hasError:!1,error:null}}static getDerivedStateFromError(r){return{hasError:!0,error:r}}componentDidCatch(r,o){console.error("ErrorBoundary caught an error:",r,o)}render(){return this.state.hasError?this.props.fallback:this.props.children}}export{c as ErrorBoundary,n as longPromise};
package/esm/create.js CHANGED
@@ -1 +1 @@
1
- import{createEmitter as d}from"./create-emitter";import{getDefaultValue as S}from"./types";import{isEqualBase as V,isObject as v,isPromise as c,isSetValueFunction as g}from"./is";import{createBaseState as D}from"./create-base-state";import{createGetterState as E}from"./create-getter-state";function y(s,f=V){function T(t,e){return g(e)?e(t):e}const a={updateVersion:0,value:void 0};function o(){return a.value===void 0&&(a.value=S(s)),a.value}function l(){const t=o();return c(t)&&t.then(e=>{a.value=e,n.emit()}),t}function r(t){const e=o(),i=T(e,t);f?.(e,i)||i===e||(a.updateVersion++,a.value=i,n.emit())}function m(t){if(v(t))return r(e=>({...e,...t}));r(t)}const n=d(l),p=D({emitter:n,getGetterState:()=>u,getState:l,reset(){const t=S(s);if(c(t)){t.then(e=>{r(e)});return}r(t)}}),u=E({baseState:p});return u.setState=r,u.updateState=m,u}export{y as create};
1
+ import{canUpdate as m,generateId as l}from"./utils/common";import{createEmitter as f}from"./utils/create-emitter";import{isEqualBase as T,isFunction as d,isSetValueFunction as p,isUndefined as o}from"./utils/is";import{createScheduler as S}from"./utils/scheduler";import{context as h}from"./subscriber";function y(i,u=T){const r={};function a(){return o(r.current)&&(r.current=d(i)?i():i),r.current}function c(n){const t=a();r.current=p(n)?n(t):n}const s=S({onFinish(){r.current=a(),m(r,u)&&e.emitter.emit()},onResolveItem:c}),e=function(){const n=a(),t=h.use();return t&&!e.emitter.contains(t.sub)&&t.addEmitter(e.emitter),n};return e.listen=function(n){return e.emitter.subscribe(()=>{const t=r.current;if(o(t))throw new Error("The value is undefined");n(t)})},e.emitter=f(()=>e()),e.id=l(),e.set=s,e}export{y as create};
package/esm/index.js CHANGED
@@ -1 +1 @@
1
- export*from"./types";import{create as t}from"./create";import{select as f}from"./select";import{merge as x}from"./merge";import{useStateValue as l}from"./use-state-value";import{shallow as c}from"./shallow";export{t as create,x as merge,f as select,c as shallow,l as useStateValue};
1
+ export*from"./types";import{create as t}from"./create";import{use as m}from"./use";import{shallow as x}from"./utils/shallow";export{t as create,x as shallow,m as use};
@@ -0,0 +1 @@
1
+ import{cancelablePromise as p,canUpdate as T,generateId as y}from"./utils/common";import{createContext as F}from"./utils/create-context";import{createEmitter as x}from"./utils/create-emitter";import{isAbortError as h,isEqualBase as C,isPromise as R,isUndefined as E}from"./utils/is";const S=F(void 0);function k(d){const u=[],n={},r={};let s=!1;const o=x(()=>s?r.current:(s=!0,t()),()=>(s=!0,t()));async function a(){T(r,C)&&(n.controller&&n.controller.abort(),r.current=t(),o.emit())}const l=y(),f={addEmitter(e){const i=e.subscribe(a);u.push(i)},id:l,sub:a},t=function(){const e=S.run(f,d);if(R(e)){const{controller:i,promise:m}=p(e,n.controller);n.controller=i,m?.then(c=>{r.current=c,o.emit()}).catch(c=>{if(!h(c))throw c});const b=m;return r.current=b,b}return r.current=e,e};return t.emitter=o,t.destroy=function(){for(const e of u)e();o.clear()},t.id=l,t.listen=function(e){return o.subscribe(()=>{const i=r.current;if(E(i))throw new Error("The value is undefined");e(i)})},t.abort=function(){n.controller&&n.controller.abort()},t}export{S as context,k as subscriber};
package/esm/types.js CHANGED
@@ -1 +1 @@
1
- import{isFunction as a,isPromise as r}from"./is";var T=(t=>(t.IS_STATE="isState",t.IS_SLICE="isSlice",t))(T||{});function o(e){return r(e)?e:a(e)?e():e}export{T as StateKeys,o as getDefaultValue};
1
+ const t=e=>e;export{t as EMPTY_SELECTOR};
package/esm/use.js ADDED
@@ -0,0 +1 @@
1
+ import{useDebugValue as u,useEffect as s,useRef as m}from"react";import{EMPTY_SELECTOR as a}from"./types";import{isAnyOtherError as c,isPromise as T}from"./utils/is";import{useSyncExternalStore as d}from"react";import{subMemo as p}from"./utils/sub-memo";const f=10,E=3;function b(t){const e=m({renders:0,startTime:performance.now()});s(()=>{e.current.renders++,!(performance.now()-e.current.startTime<f)&&(e.current.renders<E||(e.current.startTime=performance.now(),e.current.renders=0,console.warn(`Function ${t.name.length>0?t.name:t} seems to be not memoized, wrap the function to the useCallback or use global defined functions.`)))},[t])}function y(t,e=a){const n=p(t),o=n.call(),i=o.emitter.getInitialSnapshot??o.emitter.getSnapshot;s(()=>n.destroy,[t]);const r=d(o.emitter.subscribe,()=>e(o.emitter.getSnapshot()),()=>e(i()));if(u(r),T(r))throw r;if(c(r))throw n.destroy(),r;return r}export{y as use};
@@ -0,0 +1 @@
1
+ import{createContext as c}from"../create-context";import{longPromise as r}from"../../__tests__/test-utils";describe("context",()=>{it("should check context",()=>{const e=c({name:"John Doe"}),t=()=>{e.run({name:"Jane Doe"},()=>{expect(e.use()).toEqual({name:"Jane Doe"})})};expect(e.use()).toEqual({name:"John Doe"}),t(),expect(e.use()).toEqual({name:"John Doe"})}),it("should test async context",e=>{const t=c("empty"),o=async()=>new Promise(u=>setTimeout(u,10));t.run("outer",()=>{expect(t.use()).toEqual("outer"),setTimeout(t.wrap(async()=>{try{await o(),expect(t.use()).toEqual("outer"),s()}catch(u){e(u)}}),10),t.run("inner",()=>{expect(t.use()).toEqual("inner"),setTimeout(t.wrap(()=>{try{expect(t.use()).toEqual("inner"),s()}catch(u){e(u)}}),10)}),expect(t.use()).toEqual("outer")});let n=0;function s(){n+=1,n===2&&e()}}),it("should test async nested context",e=>{const t=c(0);t.run(1,()=>{expect(t.use()).toEqual(1),t.run(2,()=>{t.run(3,()=>{expect(t.use()).toEqual(3),setTimeout(t.wrap(()=>{expect(t.use()).toEqual(3)}),10),expect(t.use()).toEqual(3)}),setTimeout(t.wrap(()=>{expect(t.use()).toEqual(2)}),10),expect(t.use()).toEqual(2),t.run(3,()=>{expect(t.use()).toEqual(3),setTimeout(t.wrap(()=>{expect(t.use()).toEqual(3),t.run(4,()=>{expect(t.use()).toEqual(4),setTimeout(t.wrap(()=>{expect(t.use()).toEqual(4),e()}),10),expect(t.use()).toEqual(4)})}),10),expect(t.use()).toEqual(3)}),expect(t.use()).toEqual(2)}),expect(t.use()).toEqual(1)}),expect(t.use()).toEqual(0)}),it("should stress test context with async random code",async()=>{const t=c(0);for(let n=0;n<1e4;n++)t.run(n,()=>{expect(t.use()).toEqual(n)});const o=[];for(let n=0;n<1e4;n++)t.run(n,()=>{expect(t.use()).toEqual(n);const s=new Promise(u=>{setTimeout(t.wrap(()=>{expect(t.use()).toEqual(n),u(n)}),Math.random()*100)});o.push(s)});await Promise.all(o)}),it("should-test-default-value-with-ctx",async()=>{const e=c({counter:1});e.run({counter:10},async()=>{await r(10),expect(e.use()?.counter).toBe(10)}),e.run({counter:12},()=>{expect(e.use()?.counter).toBe(12)})}),it("should test nested context",()=>{const t=c({count:0});function o(){const n=t.use();expect(n?.count).toBe(0),t.run({count:1},()=>{const s=t.use();expect(s?.count).toBe(1),t.run({count:2},()=>{const u=t.use();expect(u?.count).toBe(2)})})}o(),o()}),it("should test nested context with async when promise is returned, but not waited",async()=>{const e=c({count:0});async function t(){await r(10);const n=e.use();expect(n?.count).toBe(1)}async function o(){await t(),e.wrap(t);const n=e.use();expect(n?.count).toBe(1)}e.run({count:1},o)})});
@@ -0,0 +1 @@
1
+ import{Abort as a}from"../common";import{isPromise as e,isFunction as r,isSetValueFunction as t,isMap as o,isSet as s,isArray as u,isEqualBase as i,isAbortError as n}from"../is";describe("isPromise",()=>{it("should return true for a Promise",()=>{expect(e(Promise.resolve())).toBe(!0)}),it("should return false for a non-Promise",()=>{expect(e(123)).toBe(!1)})}),describe("isFunction",()=>{it("should return true for a function",()=>{expect(r(()=>{})).toBe(!0)}),it("should return false for a non-function",()=>{expect(r(123)).toBe(!1)})}),describe("isSetValueFunction",()=>{it("should return true for a function",()=>{expect(t(()=>{})).toBe(!0)}),it("should return false for a non-function",()=>{expect(t(123)).toBe(!1)})}),describe("isMap",()=>{it("should return true for a Map",()=>{expect(o(new Map)).toBe(!0)}),it("should return false for a non-Map",()=>{expect(o(123)).toBe(!1)})}),describe("isSet",()=>{it("should return true for a Set",()=>{expect(s(new Set)).toBe(!0)}),it("should return false for a non-Set",()=>{expect(s(123)).toBe(!1)})}),describe("isArray",()=>{it("should return true for an array",()=>{expect(u([])).toBe(!0)}),it("should return false for a non-array",()=>{expect(u(123)).toBe(!1)})}),describe("isEqualBase",()=>{it("should return true for equal values",()=>{expect(i(1,1)).toBe(!0)}),it("should return false for non-equal values",()=>{expect(i(1,2)).toBe(!1)})}),describe("isAbortError",()=>{it("should return true for an AbortError",()=>{expect(n(new DOMException("",a.Error))).toBe(!0)}),it("should return false for a non-AbortError",()=>{expect(n(new DOMException("","Error"))).toBe(!1)})});
@@ -0,0 +1 @@
1
+ import{shallow as t}from"../shallow";describe("shallow",()=>{it("should return true for identical primitive values",()=>{expect(t(1,1)).toBe(!0),expect(t("a","a")).toBe(!0),expect(t(!0,!0)).toBe(!0)}),it("should return false for different primitive values",()=>{expect(t(1,2)).toBe(!1),expect(t("a","b")).toBe(!1),expect(t(!0,!1)).toBe(!1)}),it("should return true for identical objects",()=>{const e={a:1};expect(t(e,e)).toBe(!0)}),it("should return false for different objects with diff properties",()=>{expect(t({a:1},{a:2})).toBe(!1)}),it("should return true for identical arrays",()=>{const e=[1,2,3];expect(t(e,e)).toBe(!0)}),it("should return true for different arrays with same elements",()=>{expect(t([1,2,3],[1,2,3])).toBe(!0)}),it("should return true for identical Maps",()=>{const e=new Map([["a",1]]);expect(t(e,e)).toBe(!0)}),it("should return true for different Maps with same entries",()=>{expect(t(new Map([["a",1]]),new Map([["a",1]]))).toBe(!0)}),it("should return true for identical Sets",()=>{const e=new Set([1,2,3]);expect(t(e,e)).toBe(!0)}),it("should return true for different Sets with same elements",()=>{expect(t(new Set([1,2,3]),new Set([1,2,3]))).toBe(!0)}),it("should return true for objects with same reference",()=>{const e={a:1};expect(t(e,e)).toBe(!0)}),it("should return true for objects with different references",()=>{expect(t({a:1},{a:1})).toBe(!0)}),it("should return true for arrays with same reference",()=>{const e=[1,2,3];expect(t(e,e)).toBe(!0)}),it("should return true for arrays with different references",()=>{expect(t([1,2,3],[1,2,3])).toBe(!0)}),it("should return true for Maps with same reference",()=>{const e=new Map([["a",1]]);expect(t(e,e)).toBe(!0)}),it("should return true for Maps with different references",()=>{expect(t(new Map([["a",1]]),new Map([["a",1]]))).toBe(!0)}),it("should return true for Sets with same reference",()=>{const e=new Set([1,2,3]);expect(t(e,e)).toBe(!0)}),it("should return true for Sets with different references",()=>{expect(t(new Set([1,2,3]),new Set([1,2,3]))).toBe(!0)}),it("should return true for objects with same keys and values",()=>{const e={a:1,b:2},r={a:1,b:2};expect(t(e,r)).toBe(!0)}),it("should return false for objects with different keys or values",()=>{const e={a:1,b:2},r={a:1,b:3};expect(t(e,r)).toBe(!1)}),it("should return true for arrays with same elements",()=>{const e=[1,2,3],r=[1,2,3];expect(t(e,r)).toBe(!0)}),it("should return false for arrays with different elements",()=>{const e=[1,2,3],r=[1,2,4];expect(t(e,r)).toBe(!1)}),it("should return true for Maps with same entries",()=>{const e=new Map([["a",1],["b",2]]),r=new Map([["a",1],["b",2]]);expect(t(e,r)).toBe(!0)}),it("should return false for Maps with different entries",()=>{const e=new Map([["a",1],["b",2]]),r=new Map([["a",1],["b",3]]);expect(t(e,r)).toBe(!1)}),it("should return true for Sets with same elements",()=>{const e=new Set([1,2,3]),r=new Set([1,2,3]);expect(t(e,r)).toBe(!0)}),it("should return false for Sets with different elements",()=>{const e=new Set([1,2,3]),r=new Set([1,2,4]);expect(t(e,r)).toBe(!1)}),it("should return false for different objects with same properties",()=>{expect(t({a:1},{a:2})).toBe(!1)}),it("should return false for different arrays with same elements",()=>{expect(t([1,2,3],[1,2,4])).toBe(!1)}),it("should return false for different Maps with same entries",()=>{expect(t(new Map([["a",1]]),new Map([["a",2]]))).toBe(!1)}),it("should return false for different Sets with same elements",()=>{expect(t(new Set([1,2,3]),new Set([1,2,4]))).toBe(!1)}),it("should return false for objects with different reference",()=>{expect(t({a:1},{a:2})).toBe(!1)}),it("should return false for arrays with different reference",()=>{expect(t([1,2,3],[1,2,4])).toBe(!1)}),it("should return false for Maps with different reference",()=>{expect(t(new Map([["a",1]]),new Map([["a",2]]))).toBe(!1)}),it("should return false for Sets with different reference",()=>{expect(t(new Set([1,2,3]),new Set([1,2,4]))).toBe(!1)}),it("should return false for objects with different keys or values in",()=>{const e={a:1,b:2},r={a:1,b:3};expect(t(e,r)).toBe(!1)}),it("should return false for arrays with different elements",()=>{const e=[1,2,3],r=[1,2,4];expect(t(e,r)).toBe(!1)}),it("should return false for Maps with different entries",()=>{const e=new Map([["a",1],["b",2]]),r=new Map([["a",1],["b",3]]);expect(t(e,r)).toBe(!1)}),it("should return false for Sets with different elements",()=>{const e=new Set([1,2,3]),r=new Set([1,2,4]);expect(t(e,r)).toBe(!1)}),it("should return false for objects with different keys or values",()=>{const e={a:1,b:2},r={a:1,b:3};expect(t(e,r)).toBe(!1)}),it("should return false for arrays with different elements",()=>{const e=[1,2,3],r=[1,2,4];expect(t(e,r)).toBe(!1)}),it("should return false for Maps with different entries",()=>{const e=new Map([["a",1],["b",2]]),r=new Map([["a",1],["b",3]]);expect(t(e,r)).toBe(!1)}),it("should return false for Sets with different elements",()=>{const e=new Set([1,2,3]),r=new Set([1,2,4]);expect(t(e,r)).toBe(!1)}),it("should return false for objects with different keys or values",()=>{const e={a:1,b:2},r={a:1,b:3};expect(t(e,r)).toBe(!1)}),it("should return false for arrays with different elements",()=>{const e=[1,2,3],r=[1,2,4];expect(t(e,r)).toBe(!1)}),it("should return false for Maps with different entries",()=>{const e=new Map([["a",1],["b",2]]),r=new Map([["a",1],["b",3]]);expect(t(e,r)).toBe(!1)}),it("should return false for Sets with different elements",()=>{const e=new Set([1,2,3]),r=new Set([1,2,4]);expect(t(e,r)).toBe(!1)}),it("should return false for objects with different keys or values",()=>{const e={a:1,b:2},r={a:1,b:3};expect(t(e,r)).toBe(!1)}),it("should return false for arrays with different elements",()=>{const e=[1,2,3],r=[1,2,4];expect(t(e,r)).toBe(!1)}),it("should return false for Maps with different entries",()=>{const e=new Map([["a",1],["b",2]]),r=new Map([["a",1],["b",3]]);expect(t(e,r)).toBe(!1)}),it("should return false for Sets with different elements",()=>{const e=new Set([1,2,3]),r=new Set([1,2,4]);expect(t(e,r)).toBe(!1)}),it("should return false for objects with different keys or values",()=>{const e={a:1,b:2},r={a:1,b:3};expect(t(e,r)).toBe(!1)}),it("should return false for arrays with different elements",()=>{const e=[1,2,3],r=[1,2,4];expect(t(e,r)).toBe(!1)}),it("should return false for Maps with different entries",()=>{const e=new Map([["a",1],["b",2]]),r=new Map([["a",1],["b",3]]);expect(t(e,r)).toBe(!1)}),it("should return false for Sets with different elements",()=>{const e=new Set([1,2,3]),r=new Set([1,2,4]);expect(t(e,r)).toBe(!1)}),it("should return false for objects with different keys or values",()=>{const e={a:1,b:2},r={a:1,b:3};expect(t(e,r)).toBe(!1)}),it("should return false for arrays with different elements",()=>{const e=[1,2,3],r=[1,2,4];expect(t(e,r)).toBe(!1)}),it("should return false for Maps with different entries",()=>{const e=new Map([["a",1],["b",2]]),r=new Map([["a",1],["b",3]]);expect(t(e,r)).toBe(!1)}),it("should return false for Sets with different elements",()=>{const e=new Set([1,2,3]),r=new Set([1,2,4]);expect(t(e,r)).toBe(!1)}),it("should return false for null and non-null values",()=>{expect(t(null,{})).toBe(!1),expect(t({},null)).toBe(!1)}),it("should return false for objects with different number of keys",()=>{expect(t({a:1},{a:1,b:2})).toBe(!1)}),it("should return false for objects with different keys",()=>{expect(t({a:1},{b:1})).toBe(!1)}),it("should return false for objects with different values",()=>{expect(t({a:1},{a:2})).toBe(!1)}),it("should return false for arrays with different lengths",()=>{expect(t([1,2],[1,2,3])).toBe(!1)}),it("should return false for arrays with different elements",()=>{expect(t([1,2,3],[1,2,4])).toBe(!1)}),it("should return false for Maps with different sizes",()=>{expect(t(new Map([["a",1]]),new Map([["a",1],["b",2]]))).toBe(!1)}),it("should return false for Maps with different keys",()=>{expect(t(new Map([["a",1]]),new Map([["b",1]]))).toBe(!1)}),it("should return false for Maps with different values",()=>{expect(t(new Map([["a",1]]),new Map([["a",2]]))).toBe(!1)}),it("should return false for Sets with different sizes",()=>{expect(t(new Set([1,2]),new Set([1,2,3]))).toBe(!1)}),it("should return false for Sets with different elements",()=>{expect(t(new Set([1,2,3]),new Set([1,2,4]))).toBe(!1)}),it("should return true compare simple values",()=>{expect(t(1,1)).toBe(!0),expect(t("a","a")).toBe(!0),expect(t(!0,!0)).toBe(!0)})});
@@ -0,0 +1 @@
1
+ import{subMemo as t}from"../sub-memo";describe("memo-fn",()=>{it("should create memo fn",()=>{function e(){return!0}const o=t(e);expect(o.call().emitter).toBeDefined()})});
@@ -0,0 +1 @@
1
+ import{isUndefined as i}from"./is";var a=(e=>(e.Error="StateAbortError",e))(a||{});function m(r,e){e&&e.abort();const o=new AbortController,{signal:t}=o;return{promise:new Promise((l,n)=>{t.addEventListener("abort",()=>{n(new DOMException("Promise was aborted","StateAbortError"))}),r.then(l).catch(n)}),controller:o}}let s=0;function p(){return s++}function b(r,e=(o,t)=>o===t){if(!i(r.current)){if(!i(r.previous)&&e(r.current,r.previous))return!1;r.previous=r.current}return!0}export{a as Abort,b as canUpdate,m as cancelablePromise,p as generateId};
@@ -0,0 +1 @@
1
+ import{isPromise as i}from"./is";const a=Symbol("_");function f(s){const t=[];function o(){if(t.length===0)return s;const e=t.at(-1);return e===a?s:e}function u(e,n){t.push(e);const r=n();return i(r)?(async()=>{try{return await r}finally{t.pop()}})():(t.pop(),r)}function c(e){const n=o();return()=>{t.push(n);const r=e();return i(r)?(async()=>{try{return await r}finally{t.pop()}})():(t.pop(),r)}}return{run:u,use:o,wrap:c}}export{f as createContext};
@@ -0,0 +1 @@
1
+ function o(n,s){const t=new Set,i=[];return{clear:()=>{for(const e of i)e();t.clear()},subscribe:e=>(t.add(e),()=>{t.delete(e)}),emit:(...e)=>{for(const r of t)r(...e)},contains:e=>t.has(e),getSnapshot:n,getInitialSnapshot:s,getSize:()=>t.size,subscribeToOtherEmitter(e){const r=e.subscribe(()=>{this.emit()});i.push(r)}}}export{o as createEmitter};
@@ -0,0 +1 @@
1
+ import{Abort as e}from"./common";function o(n){return n instanceof Promise}function i(n){return typeof n=="function"}function u(n){return n instanceof Map}function s(n){return n instanceof Set}function a(n){return Array.isArray(n)}function f(n,r){return n===r?!0:!!Object.is(n,r)}function c(n){return typeof n=="function"}function p(n){return n instanceof DOMException&&n.name===e.Error}function k(n){return n instanceof Error&&n.name!==e.Error}function w(n){return n===void 0}export{p as isAbortError,k as isAnyOtherError,a as isArray,f as isEqualBase,i as isFunction,u as isMap,o as isPromise,s as isSet,c as isSetValueFunction,w as isUndefined};
@@ -0,0 +1 @@
1
+ const T=.2,d=10,E=0;function S(f){const n=new Set,{onResolveItem:r,onFinish:a}=f;let o=performance.now(),t=!1;function s(){const e=performance.now(),u=e-o,{size:c}=n;if(u<.2&&c>0&&c<10){o=e,i();return}t||(t=!0,Promise.resolve().then(()=>{t=!1,o=performance.now(),i()}))}function i(){if(n.size!==0){for(const e of n)r&&r(e),n.delete(e);if(n.size>0){s();return}a()}}function l(e){n.add(e),s()}return l}export{S as createScheduler};
@@ -0,0 +1 @@
1
+ import{isArray as f,isMap as o,isSet as i}from"./is";function b(r,t){if(r==t)return!0;if(typeof r!="object"||r==null||typeof t!="object"||t==null)return!1;if(o(r)&&o(t)){if(r.size!==t.size)return!1;for(const[e,n]of r)if(!Object.is(n,t.get(e)))return!1;return!0}if(i(r)&&i(t)){if(r.size!==t.size)return!1;for(const e of r)if(!t.has(e))return!1;return!0}if(f(r)&&f(t)){if(r.length!==t.length)return!1;for(const[e,n]of r.entries())if(!Object.is(n,t[e]))return!1;return!0}const s=Object.keys(r),c=Object.keys(t);if(s.length!==c.length)return!1;for(const e of s)if(!Object.prototype.hasOwnProperty.call(t,e)||!Object.is(r[e],t[e]))return!1;return!0}export{b as shallow};
@@ -0,0 +1 @@
1
+ import{subscriber as c}from"../subscriber";const r=new WeakMap;function s(t){return{call(){const e=r.get(t);if(e)return e.count++,e.returnType;const n={count:1,returnType:c(t)};return r.set(t,n),n.returnType},destroy(){const e=r.get(t);e&&(e.count--,e.count===0&&(e.returnType.destroy(),r.delete(t)))}}}export{s as subMemo};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "muya",
3
- "version": "1.1.0",
3
+ "version": "2.0.0-beta.1",
4
4
  "author": "samuel.gjabel@gmail.com",
5
5
  "description": "👀 Another React state management library",
6
6
  "license": "MIT",