muya 1.0.3 → 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 (89) hide show
  1. package/README.md +194 -216
  2. package/cjs/index.js +1 -1
  3. package/esm/__tests__/create-async.test.js +1 -0
  4. package/esm/create.js +1 -1
  5. package/esm/index.js +1 -1
  6. package/esm/subscriber.js +1 -0
  7. package/esm/types.js +1 -1
  8. package/esm/use.js +1 -0
  9. package/esm/utils/__tests__/context.test.js +1 -0
  10. package/esm/utils/__tests__/is.test.js +1 -0
  11. package/esm/utils/__tests__/sub-memo.test.js +1 -0
  12. package/esm/utils/common.js +1 -0
  13. package/esm/utils/create-context.js +1 -0
  14. package/esm/utils/create-emitter.js +1 -0
  15. package/esm/utils/is.js +1 -0
  16. package/esm/utils/scheduler.js +1 -0
  17. package/esm/utils/shallow.js +1 -0
  18. package/esm/utils/sub-memo.js +1 -0
  19. package/package.json +1 -4
  20. package/packages/core/__tests__/bench.test.tsx +261 -0
  21. package/packages/core/__tests__/create-async.test.ts +88 -0
  22. package/packages/core/__tests__/create.test.tsx +107 -0
  23. package/packages/core/__tests__/use-async.test.tsx +44 -0
  24. package/packages/core/__tests__/use.test.tsx +76 -0
  25. package/packages/core/create.ts +67 -0
  26. package/packages/core/index.ts +4 -0
  27. package/packages/core/subscriber.ts +121 -0
  28. package/packages/core/types.ts +15 -0
  29. package/packages/core/use.ts +59 -0
  30. package/packages/core/utils/__tests__/context.test.ts +198 -0
  31. package/{src → packages/core/utils}/__tests__/is.test.ts +1 -30
  32. package/packages/core/utils/__tests__/sub-memo.test.ts +13 -0
  33. package/packages/core/utils/common.ts +48 -0
  34. package/packages/core/utils/create-context.ts +60 -0
  35. package/packages/core/utils/create-emitter.ts +53 -0
  36. package/{src → packages/core/utils}/is.ts +11 -13
  37. package/packages/core/utils/scheduler.ts +59 -0
  38. package/{src → packages/core/utils}/shallow.ts +3 -3
  39. package/packages/core/utils/sub-memo.ts +37 -0
  40. package/types/create.d.ts +14 -21
  41. package/types/index.d.ts +2 -4
  42. package/types/subscriber.d.ts +25 -0
  43. package/types/types.d.ts +9 -65
  44. package/types/use.d.ts +2 -0
  45. package/types/utils/common.d.ts +15 -0
  46. package/types/utils/create-context.d.ts +5 -0
  47. package/types/utils/create-emitter.d.ts +20 -0
  48. package/types/{is.d.ts → utils/is.d.ts} +5 -6
  49. package/types/utils/scheduler.d.ts +6 -0
  50. package/types/utils/sub-memo.d.ts +6 -0
  51. package/esm/__tests__/common.test.js +0 -1
  52. package/esm/__tests__/is.test.js +0 -1
  53. package/esm/__tests__/merge.test.js +0 -1
  54. package/esm/__tests__/types.test.js +0 -1
  55. package/esm/common.js +0 -1
  56. package/esm/create-base-state.js +0 -1
  57. package/esm/create-emitter.js +0 -1
  58. package/esm/create-getter-state.js +0 -1
  59. package/esm/is.js +0 -1
  60. package/esm/merge.js +0 -1
  61. package/esm/select.js +0 -1
  62. package/esm/shallow.js +0 -1
  63. package/esm/use-state-value.js +0 -1
  64. package/src/__tests__/common.test.ts +0 -63
  65. package/src/__tests__/create.test.tsx +0 -84
  66. package/src/__tests__/merge.test.ts +0 -78
  67. package/src/__tests__/state.test.tsx +0 -619
  68. package/src/__tests__/types.test.ts +0 -17
  69. package/src/common.ts +0 -60
  70. package/src/create-base-state.ts +0 -31
  71. package/src/create-emitter.ts +0 -24
  72. package/src/create-getter-state.ts +0 -18
  73. package/src/create.ts +0 -127
  74. package/src/index.ts +0 -6
  75. package/src/merge.ts +0 -38
  76. package/src/select.ts +0 -33
  77. package/src/types.ts +0 -94
  78. package/src/use-state-value.ts +0 -32
  79. package/types/common.d.ts +0 -17
  80. package/types/create-base-state.d.ts +0 -10
  81. package/types/create-emitter.d.ts +0 -7
  82. package/types/create-getter-state.d.ts +0 -6
  83. package/types/merge.d.ts +0 -4
  84. package/types/select.d.ts +0 -2
  85. package/types/use-state-value.d.ts +0 -10
  86. /package/esm/{__tests__ → utils/__tests__}/shallow.test.js +0 -0
  87. /package/{src → packages/core}/__tests__/test-utils.ts +0 -0
  88. /package/{src → packages/core/utils}/__tests__/shallow.test.ts +0 -0
  89. /package/types/{shallow.d.ts → utils/shallow.d.ts} +0 -0
package/README.md CHANGED
@@ -1,321 +1,299 @@
1
+
1
2
  # Muya 🌀
2
- Welcome to Muya - Making state management a breeze, focused on simplicity and scalability for real-world scenarios.
3
+
4
+ Welcome to **Muya v2**—a state management library that makes managing state a breeze, focusing on simplicity and scalability for real-world applications.
3
5
 
4
6
  [![Build](https://github.com/samuelgja/muya/actions/workflows/build.yml/badge.svg)](https://github.com/samuelgja/muya/actions/workflows/build.yml)
5
- [![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)
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)
6
8
  [![Build Size](https://img.shields.io/bundlephobia/minzip/muya?label=Bundle%20size)](https://bundlephobia.com/result?p=muya)
7
9
 
10
+ ---
11
+
8
12
  ## 🚀 Features
9
- - Easy State Creation: Kickstart your state management with simple and intuitive APIs.
10
- - Selectors & Merges: Grab exactly what you need from your state and combine multiple states seamlessly.
11
- - Deep Nesting Support: Handle complex state structures without breaking a sweat.
12
- - Optimized Rendering: Prevent unnecessary re-renders
13
- - TypeScript Ready: Fully typed for maximum developer sanity.
14
- - Small Bundle Size: Lightweight and fast, no bloatware here.
15
13
 
16
- ## 📦 Installation
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.
17
20
 
18
- ```bash
19
- bun add muya
20
- ```
21
- or
22
- ```bash
23
- yarn add muya
24
- ```
25
- or
26
- ```bash
27
- npm install muya
28
- ```
29
-
30
- ## 📝 Quick Start
21
+ ---
31
22
 
32
- ```typescript
33
- import { create } from 'muya'
23
+ Info: [Muya v2](https://medium.com/p/106de3d04c43)
34
24
 
35
- const useCounter = create(0)
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.
36
27
 
37
- function App() {
38
- const counter = useCounter()
39
- return <div onClick={() => useCounter.setState((prev) => prev + 1)}>{counter}</div>
40
- }
41
- ```
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!
42
29
 
43
- ### Update
44
- Sugar syntax above the `setState` method for partially updating the state.
45
- ```typescript
46
- import { create } from 'muya'
30
+ ---
47
31
 
48
- const useUser = create({ name: 'John', lastName: 'Doe' })
32
+ ## 📦 Installation
49
33
 
50
- function App() {
51
- const user = useUser()
52
- // this will just partially update only the name field, it's sugar syntax for setState.
53
- return <div onClick={() => useUser.updateState({ name: 'Nope' })}>{user.name}</div>
54
- }
34
+ ```bash
35
+ npm install muya
55
36
  ```
56
37
 
57
- ### Selecting parts of the state globally
58
- ```tsx
59
- import { create } from 'muya'
60
-
61
- const useUser = create({ name: 'John', age: 30 })
38
+ Or using Yarn:
62
39
 
63
- // Selecting only the name part of the state
64
- const useName = useUser.select((user) => user.name)
40
+ ```bash
41
+ yarn add muya
42
+ ```
65
43
 
66
- function App() {
67
- const name = useName()
68
- return <div onClick={() => useUser.setState((prev) => ({ ...prev, name: 'Jane' }))}>{name}</div>
69
- }
44
+ Or using Bun:
70
45
 
46
+ ```bash
47
+ bun add muya
71
48
  ```
72
49
 
73
- ### Merge any states
74
- ```typescript
75
- import { create, shallow, merge } from 'muya'
76
-
77
- const useName = create(() => 'John')
78
- const useAge = create(() => 30)
50
+ ---
79
51
 
80
- const useFullName = merge([useName, useAge], (name, age) => `${name} and ${age}`)
52
+ ## 📝 Quick Start
81
53
 
82
- function App() {
83
- const fullName = useFullName()
84
- return <div onClick={() => useName.setState((prev) => 'Jane')}>{fullName}</div>
85
- }
86
- ```
54
+ Here's how to get started with **Muya v2**:
87
55
 
88
- ### Promise based state and lifecycle management working with React Suspense
89
- This methods are useful for handling async data fetching and lazy loading via React Suspense.
56
+ ### Creating State
90
57
 
91
- #### Immediate Promise resolution
92
58
  ```typescript
93
59
  import { create } from 'muya';
94
- // state will try to resolve the promise immediately, can hit the suspense boundary
95
- const counterState = create(Promise.resolve(0));
96
60
 
97
- function Counter() {
98
- const counter = counterState();
99
- return (
100
- <div onClick={() => counterState.setState((prev) => prev + 1)}>
101
- {counter}
102
- </div>
103
- );
104
- }
61
+ const counter = create(0);
105
62
  ```
106
63
 
107
- #### Lazy Promise resolution
108
- ```typescript
109
- import { create } from 'muya';
110
- // 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
111
- const counterState = create(() => Promise.resolve(0));
64
+ ### Using State in Components
65
+
66
+ ```tsx
67
+ import React from 'react';
68
+ import { use } from 'muya';
112
69
 
113
70
  function Counter() {
114
- const counter = counterState();
71
+ const count = use(counter);
72
+
115
73
  return (
116
- <div onClick={() => counterState.setState((prev) => prev + 1)}>
117
- {counter}
74
+ <div>
75
+ <button onClick={() => counter.set((prev) => prev + 1)}>
76
+ Increment
77
+ </button>
78
+ <p>Count: {count}</p>
118
79
  </div>
119
80
  );
120
81
  }
121
82
  ```
122
83
 
123
- ## 🔍 API Reference
124
-
125
- ### `create`
84
+ ---
126
85
 
127
- Creates a basic atom state.
86
+ ## 📚 Examples
128
87
 
129
- ```typescript
130
- function create<T>(defaultState: T, options?: StateOptions<T>): StateSetter<T>;
131
- ```
88
+ ### Deriving / Selecting State with Functions
132
89
 
133
- **Example:**
90
+ You can derive new state using plain functions:
134
91
 
135
92
  ```typescript
136
- const userState = create({ name: 'John', age: 30 });
93
+ const counter = create(0);
94
+
95
+ function doubled() {
96
+ return counter() * 2;
97
+ }
137
98
  ```
138
99
 
139
- ### `select`
100
+ Use it in a component:
140
101
 
141
- Selects a slice of an existing state directly or via a selector function.
102
+ ```tsx
103
+ function DoubledCounter() {
104
+ const value = use(doubled);
142
105
 
143
- ```typescript
144
- // userState is ready to use as hook, so you can name it with `use` prefix
145
- const userState = create({ name: 'John', age: 30 });
146
- // Direct selection outside the component, is useful for accessing the slices of the state in multiple components
147
- const userAgeState = userState.select((user) => user.age);
106
+ return <p>Doubled Count: {value}</p>;
107
+ }
148
108
  ```
149
109
 
150
- ### `merge`
151
- Merges any number states into a single state.
152
- ```typescript
153
- const useName = create(() => 'John');
154
- const useAge = create(() => 30);
155
- const useFullName = merge([useName, useAge], (name, age) => `${name} and ${age}`);
156
- ```
110
+ ### Complex Derivations
157
111
 
158
- ### `setState`
159
- Sets the state to a new value or a function that returns a new value.
112
+ Create more complex derived states by composing functions:
160
113
 
161
- ```typescript
162
- const userState = create({ name: 'John', age: 30 });
163
- userState.setState({ name: 'Jane' });
164
- ```
114
+ ```tsx
115
+ import { create, use } from 'muya';
165
116
 
166
- ### `updateState`
167
- Partially updates the state with a new value.
117
+ const state1 = create(0);
118
+ const state2 = create(0);
119
+ const state3 = create(0);
168
120
 
169
- ```typescript
170
- const userState = create({ name: 'John', age: 30 });
171
- userState.updateState({ name: 'Jane' });
172
- ```
121
+ function sum() {
122
+ return state1() + state2() + state3();
123
+ }
173
124
 
174
- ### `getState`
175
- Returns the current state value outside the component.
125
+ function multiply() {
126
+ return sum() * 2; // Example multiplier
127
+ }
176
128
 
177
- ```typescript
178
- const userState = create({ name: 'John', age: 30 });
179
- const user = userState.getState();
180
- ```
129
+ function isOdd() {
130
+ return multiply() % 2 === 1;
131
+ }
181
132
 
182
- ### `use`
183
- Creates a hook for the state.
133
+ function App() {
134
+ const isOddValue = use(isOdd);
184
135
 
185
- ```typescript
186
- const useCounter = create(0);
187
- // use inside the component
188
- const counter = useCounter();
136
+ return (
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>
142
+ </div>
143
+ );
144
+ }
189
145
  ```
190
146
 
191
- ### `subscribe`
192
- Subscribes to the state changes.
193
147
 
194
- ```typescript
195
- const userState = create({ name: 'John', age: 30 });
196
- const unsubscribe = userState.subscribe((state) => console.log(state));
197
- ```
148
+ ### Derive state with parameters
149
+ ```tsx
198
150
 
199
- ### Promise Handling
151
+ import React, { useCallback, useState } from 'react';
152
+ import { create, use } from 'muya';
200
153
 
201
- #### Immediate Promise Resolution
154
+ const counter1 = create(0);
155
+ const counter2 = create(0);
202
156
 
203
- ```typescript
204
- import { create } from 'muya';
157
+ function multipliedSum(multiplier: number) {
158
+ return (counter1() + counter2()) * multiplier;
159
+ }
205
160
 
206
- // State will try to resolve the promise immediately, can hit the suspense boundary
207
- const counterState = create(Promise.resolve(0));
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);
208
166
 
209
- function Counter() {
210
- const counter = counterState();
211
167
  return (
212
- <div onClick={() => counterState.setState((prev) => prev + 1)}>
213
- {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>
214
179
  </div>
215
180
  );
216
181
  }
217
182
  ```
218
183
 
219
- #### Lazy Promise Resolution
184
+ ### Async derives State
220
185
 
221
- ```typescript
186
+ ```tsx
222
187
  import { create } from 'muya';
223
188
 
224
- // 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
225
- const counterState = create(() => Promise.resolve(0));
189
+ const counter = create(1);
190
+
191
+ async function fetchData() {
192
+ const response = await fetch(`https://jsonplaceholder.typicode.com/todos/${counter()}`);
193
+ return response.json();
194
+ }
195
+
196
+ // make sure this component is wrapped in a <Suspense> component
197
+ function Component() {
198
+ const data = use(fetchData);
226
199
 
227
- function Counter() {
228
- const counter = counterState();
229
200
  return (
230
- <div onClick={() => counterState.setState((prev) => prev + 1)}>
231
- {counter}
201
+ <div>
202
+ <button onClick={() => counter.set((prev) => prev + 1)}>Increment</button>
203
+ <p>{JSON.stringify(data)}</p>
232
204
  </div>
233
205
  );
234
206
  }
207
+
208
+
235
209
  ```
210
+ ---
236
211
 
237
- #### Promise Rejection Handling
238
212
 
239
- ```typescript
240
- import { create } from 'muya';
241
213
 
242
- // State will reject the promise
243
- const counterState = create(Promise.reject('Error occurred'));
244
214
 
245
- function Counter() {
246
- try {
247
- const counter = counterState();
248
- return <div>{counter}</div>;
249
- } catch (error) {
250
- return <div>Error: {error}</div>;
251
- }
252
- }
253
- ```
215
+ ## 📖 Documentation
254
216
 
255
- #### Error Throwing
217
+ #### `create`
256
218
 
257
219
  ```typescript
258
- import { create } from 'muya';
220
+ function create<T>(initialState: T): State<T>;
221
+ ```
259
222
 
260
- // State will throw an error
261
- const counterState = create(() => {
262
- throw new Error('Error occurred');
263
- });
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.
224
+ ```typescript
225
+ const counter = create(0);
226
+ // set new value
227
+ counter.set(1);
228
+ ```
264
229
 
265
- function Counter() {
266
- try {
267
- const counter = counterState();
268
- return <div>{counter}</div>;
269
- } catch (error) {
270
- return <div>Error: {error.message}</div>;
271
- }
272
- }
230
+ Get the state value outside of react
231
+ ```typescript
232
+ const value = counter();
233
+ // call it like a function
234
+ console.log(value()); // 1
273
235
  ```
274
236
 
275
- #### Setting a state during promise resolution
237
+ Each state created by create has the following properties and methods:
276
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.
243
+
244
+ #### `use` hook
245
+ Use hook to get state value in react component
277
246
  ```typescript
278
- import { create } from 'muya';
247
+ function use<T>(state: State<T> | (() => T)): T;
248
+ ```
249
+ example
250
+ ```tsx
251
+ const counter = create(0);
279
252
 
280
- // State will resolve the promise and set the state
281
- const counterState = create(Promise.resolve(0));
282
- // this will abort current promise and set the state to 10
283
- counterState.setState(10);
284
- function Counter() {
285
- const counter = counterState();
286
- return (
287
- <div onClick={() => counterState.setState((prev) => prev + 1)}>
288
- {counter}
289
- </div>
290
- );
291
- }
253
+ // in react component
254
+ const count = use(counter);
292
255
  ```
293
256
 
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);
262
+ ```
294
263
 
295
- ### Access from outside the component
296
- :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.
297
- ```typescript
298
- const userState = create({ name: 'John', age: 30 });
299
- const user = userState.getState();
264
+
265
+
266
+
267
+
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]);
300
273
  ```
301
- ---
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.
302
276
 
303
- ### Slicing new references
304
- :warning: Slicing data with new references can lead to maximum call stack exceeded error.
305
- It's recommended to not use new references for the state slices, if you need so, use `shallow` or other custom equality checks.
306
- ```typescript
307
- import { state, shallow } from 'muya';
308
- const userState = create({ name: 'John', age: 30 });
309
- // this slice will create new reference object on each call
310
- const useName = userState.select((user) => ({newUser: user.name }), shallow);
277
+ ```tsx
278
+ Copy code
279
+ function App() {
280
+ return (
281
+ <Suspense fallback={<div>Loading...</div>}>
282
+ <DataComponent />
283
+ </Suspense>
284
+ );
285
+ }
311
286
  ```
312
287
 
313
- ## 🤖 Contributing
314
- 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.
315
289
 
316
- ## 🧪 Testing
290
+ ### 🤖 Contributing
291
+ Contributions are welcome! Please read the contributing guidelines before submitting a pull request.
292
+
293
+ ### 🧪 Testing
317
294
  Muya comes with a robust testing suite. Check out the state.test.tsx for examples on how to write your own tests.
318
295
 
319
- ## 📜 License
320
296
 
321
- 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 w=Object.defineProperty;var F=Object.getOwnPropertyDescriptor;var L=Object.getOwnPropertyNames;var W=Object.prototype.hasOwnProperty;var B=(t,e)=>{for(var n in e)w(t,n,{get:e[n],enumerable:!0})},H=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of L(e))!W.call(t,o)&&o!==n&&w(t,o,{get:()=>e[o],enumerable:!(r=F(e,o))||r.enumerable});return t};var J=t=>H(w({},"__esModule",{value:!0}),t);var K={};B(K,{StateKeys:()=>v,create:()=>M,getDefaultValue:()=>y,merge:()=>A,select:()=>g,shallow:()=>U,useStateValue:()=>E});module.exports=J(K);var q=require("use-sync-external-store/shim/with-selector"),I=require("react");function O(t){return t}function R(t,e,n){let r=(0,q.useSyncExternalStoreWithSelector)(t.subscribe,t.getSnapshot,t.getSnapshot,e?o=>e(o):O,n);return(0,I.useDebugValue)(r),r}function k(t,e){e&&e.abort();let n=new AbortController,{signal:r}=n;return{promise:new Promise((a,s)=>{r.addEventListener("abort",()=>{s(new DOMException("Promise was aborted","StateAbortError"))}),t.then(a).catch(s)}),controller:n}}function p(t){return t instanceof Promise}function D(t){return typeof t=="function"}function _(t){return typeof t=="function"}function j(t){return typeof t=="object"&&t!==null}function G(t){return t instanceof Map}function V(t){return t instanceof Set}function h(t){return Array.isArray(t)}function l(t,e){return t===e?!0:!!Object.is(t,e)}function P(t){return t instanceof DOMException&&t.name==="StateAbortError"}function C(t){return t instanceof Error&&t.name!=="StateAbortError"}var v=(n=>(n.IS_STATE="isState",n.IS_SLICE="isSlice",n))(v||{});function y(t){return p(t)?t:D(t)?t():t}function m(t){let e=new Set;return{subscribe:n=>(e.add(n),()=>{e.delete(n)}),emit:(...n)=>{for(let r of e)r(...n)},getSnapshot:t}}function E(t,e=r=>r,n){let r=R(t.__internal.emitter,o=>e(o),n);if(p(r)||C(r))throw r;return r}function T(t){let{baseState:e}=t,n=(r,o)=>E(n,r,o);return n.__internal=e.__internal,n.getState=e.getState,n.reset=e.reset,n.select=e.select,n.subscribe=e.subscribe,n}function g(t,e,n=l){let r,o=m(()=>{let i=e(t.getState());return r!==void 0&&n(r,i)?r:(r=i,i)});t.__internal.emitter.subscribe(()=>{o.emit()});let a=d({emitter:o,getGetterState:()=>s,getState:()=>e(t.getState()),reset:t.reset}),s=T({baseState:a});return s}function d(t){let{emitter:e,getGetterState:n,reset:r,getState:o}=t;return{getState:o,reset:r,select(a,s){let i=n();return g(i,a,s)},__internal:{emitter:e},subscribe(a){return a(o()),e.subscribe(()=>{a(o())})}}}function M(t,e=l){function n(u,S){return _(S)?S(u):S}let r={updateVersion:0,value:void 0};function o(){return r.value===void 0&&(r.value=y(t)),r.value}function a(){let u=o();if(p(u)){let{controller:S,promise:f}=k(u,r.abortController);r.abortController=S,f.then(c=>{r.value=c,b.emit()}).catch(c=>{P(c)||(r.value=new Error(c))})}return u}function s(u){let S=o();r.abortController&&(r.abortController.abort(),r.abortController=void 0);let f=n(S,u);e?.(S,f)||f===S||(r.updateVersion++,r.value=f,b.emit())}function i(u){if(j(u))return s(S=>({...S,...u}));s(u)}let b=m(a),z=d({emitter:b,getGetterState:()=>x,getState:a,reset(){let u=y(t);if(p(u)){let{controller:S,promise:f}=k(u,r.abortController);r.abortController=S,f.then(c=>{s(c)}).catch(c=>{P(c)||(r.value=new Error(c))});return}s(u)}}),x=T({baseState:z});return x.setState=s,x.updateState=i,x}function A(t,e,n=l){let r,o=m(()=>{let i=e(...t.map(b=>b.getState()));return r!==void 0&&n(r,i)?r:(r=i,i)});for(let i of t)i.__internal.emitter.subscribe(()=>{o.emit()});let a=d({emitter:o,getGetterState:()=>s,getState:()=>e(...t.map(i=>i.getState())),reset(){for(let i of t)i.reset()}}),s=T({baseState:a});return s}function U(t,e){if(t==e)return!0;if(typeof t!="object"||t==null||typeof e!="object"||e==null)return!1;if(G(t)&&G(e)){if(t.size!==e.size)return!1;for(let[o,a]of t)if(!Object.is(a,e.get(o)))return!1;return!0}if(V(t)&&V(e)){if(t.size!==e.size)return!1;for(let o of t)if(!e.has(o))return!1;return!0}if(h(t)&&h(e)){if(t.length!==e.length)return!1;for(let[o,a]of t.entries())if(!Object.is(a,e[o]))return!1;return!0}let n=Object.keys(t),r=Object.keys(e);if(n.length!==r.length)return!1;for(let o of n)if(!Object.prototype.hasOwnProperty.call(e,o)||!Object.is(t[o],e[o]))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)})});
package/esm/create.js CHANGED
@@ -1 +1 @@
1
- import{createEmitter as v}from"./create-emitter";import{getDefaultValue as S}from"./types";import{isAbortError as f,isEqualBase as E,isObject as g,isPromise as T,isSetValueFunction as C}from"./is";import{createBaseState as D}from"./create-base-state";import{createGetterState as w}from"./create-getter-state";import{cancelablePromise as m}from"./common";function P(i,p=E){function d(e,r){return C(r)?r(e):r}const t={updateVersion:0,value:void 0};function s(){return t.value===void 0&&(t.value=S(i)),t.value}function c(){const e=s();if(T(e)){const{controller:r,promise:o}=m(e,t.abortController);t.abortController=r,o.then(a=>{t.value=a,l.emit()}).catch(a=>{f(a)||(t.value=new Error(a))})}return e}function n(e){const r=s();t.abortController&&(t.abortController.abort(),t.abortController=void 0);const o=d(r,e);p?.(r,o)||o===r||(t.updateVersion++,t.value=o,l.emit())}function b(e){if(g(e))return n(r=>({...r,...e}));n(e)}const l=v(c),V=D({emitter:l,getGetterState:()=>u,getState:c,reset(){const e=S(i);if(T(e)){const{controller:r,promise:o}=m(e,t.abortController);t.abortController=r,o.then(a=>{n(a)}).catch(a=>{f(a)||(t.value=new Error(a))});return}n(e)}}),u=w({baseState:V});return u.setState=n,u.updateState=b,u}export{P 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 r,isPromise as a}from"./is";var T=(t=>(t.IS_STATE="isState",t.IS_SLICE="isSlice",t))(T||{});function S(e){return a(e)?e:r(e)?e():e}export{T as StateKeys,S 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{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};