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.
- package/README.md +201 -138
- package/cjs/index.js +1 -1
- package/esm/__tests__/create-async.test.js +1 -0
- package/esm/__tests__/test-utils.js +1 -0
- package/esm/create.js +1 -1
- package/esm/index.js +1 -1
- package/esm/subscriber.js +1 -0
- package/esm/types.js +1 -1
- package/esm/use.js +1 -0
- package/esm/utils/__tests__/context.test.js +1 -0
- package/esm/utils/__tests__/is.test.js +1 -0
- package/esm/utils/__tests__/shallow.test.js +1 -0
- package/esm/utils/__tests__/sub-memo.test.js +1 -0
- package/esm/utils/common.js +1 -0
- package/esm/utils/create-context.js +1 -0
- package/esm/utils/create-emitter.js +1 -0
- package/esm/utils/is.js +1 -0
- package/esm/utils/scheduler.js +1 -0
- package/esm/utils/shallow.js +1 -0
- package/esm/utils/sub-memo.js +1 -0
- package/package.json +1 -1
- package/packages/core/__tests__/bench.test.tsx +261 -0
- package/packages/core/__tests__/create-async.test.ts +88 -0
- package/packages/core/__tests__/create.test.tsx +107 -0
- package/packages/core/__tests__/test-utils.ts +40 -0
- package/packages/core/__tests__/use-async.test.tsx +44 -0
- package/packages/core/__tests__/use.test.tsx +76 -0
- package/packages/core/create.ts +67 -0
- package/packages/core/index.ts +4 -0
- package/packages/core/subscriber.ts +121 -0
- package/packages/core/types.ts +15 -0
- package/packages/core/use.ts +59 -0
- package/packages/core/utils/__tests__/context.test.ts +198 -0
- package/packages/core/utils/__tests__/is.test.ts +74 -0
- package/packages/core/utils/__tests__/shallow.test.ts +418 -0
- package/packages/core/utils/__tests__/sub-memo.test.ts +13 -0
- package/packages/core/utils/common.ts +48 -0
- package/packages/core/utils/create-context.ts +60 -0
- package/packages/core/utils/create-emitter.ts +53 -0
- package/packages/core/utils/is.ts +43 -0
- package/packages/core/utils/scheduler.ts +59 -0
- package/{src → packages/core/utils}/shallow.ts +3 -6
- package/packages/core/utils/sub-memo.ts +37 -0
- package/types/__tests__/test-utils.d.ts +20 -0
- package/types/create.d.ts +14 -21
- package/types/index.d.ts +2 -4
- package/types/subscriber.d.ts +25 -0
- package/types/types.d.ts +9 -65
- package/types/use.d.ts +2 -0
- package/types/utils/common.d.ts +15 -0
- package/types/utils/create-context.d.ts +5 -0
- package/types/utils/create-emitter.d.ts +20 -0
- package/types/utils/is.d.ts +11 -0
- package/types/utils/scheduler.d.ts +6 -0
- package/types/utils/sub-memo.d.ts +6 -0
- package/esm/common.js +0 -1
- package/esm/create-base-state.js +0 -1
- package/esm/create-emitter.js +0 -1
- package/esm/create-getter-state.js +0 -1
- package/esm/is.js +0 -1
- package/esm/merge.js +0 -1
- package/esm/select.js +0 -1
- package/esm/shallow.js +0 -1
- package/esm/use-state-value.js +0 -1
- package/src/common.ts +0 -28
- package/src/create-base-state.ts +0 -35
- package/src/create-emitter.ts +0 -24
- package/src/create-getter-state.ts +0 -19
- package/src/create.ts +0 -102
- package/src/index.ts +0 -6
- package/src/is.ts +0 -36
- package/src/merge.ts +0 -41
- package/src/select.ts +0 -33
- package/src/state.test.tsx +0 -647
- package/src/types.ts +0 -94
- package/src/use-state-value.ts +0 -29
- package/types/common.d.ts +0 -7
- package/types/create-base-state.d.ts +0 -10
- package/types/create-emitter.d.ts +0 -7
- package/types/create-getter-state.d.ts +0 -6
- package/types/is.d.ts +0 -10
- package/types/merge.d.ts +0 -2
- package/types/select.d.ts +0 -2
- package/types/use-state-value.d.ts +0 -10
- /package/types/{shallow.d.ts → utils/shallow.d.ts} +0 -0
|
@@ -1,13 +1,10 @@
|
|
|
1
|
+
/* eslint-disable sonarjs/cognitive-complexity */
|
|
1
2
|
import { isArray, isMap, isSet } from './is'
|
|
2
3
|
|
|
3
|
-
// eslint-disable-next-line sonarjs/cognitive-complexity
|
|
4
4
|
export function shallow<T>(valueA: T, valueB: T): boolean {
|
|
5
5
|
if (valueA == valueB) {
|
|
6
6
|
return true
|
|
7
7
|
}
|
|
8
|
-
if (Object.is(valueA, valueB)) {
|
|
9
|
-
return true
|
|
10
|
-
}
|
|
11
8
|
|
|
12
9
|
if (typeof valueA !== 'object' || valueA == null || typeof valueB !== 'object' || valueB == null) {
|
|
13
10
|
return false
|
|
@@ -43,8 +40,8 @@ export function shallow<T>(valueA: T, valueB: T): boolean {
|
|
|
43
40
|
return true
|
|
44
41
|
}
|
|
45
42
|
|
|
46
|
-
const keysA = Object.keys(valueA
|
|
47
|
-
const keysB = Object.keys(valueB
|
|
43
|
+
const keysA = Object.keys(valueA)
|
|
44
|
+
const keysB = Object.keys(valueB)
|
|
48
45
|
if (keysA.length !== keysB.length) return false
|
|
49
46
|
for (const key of keysA) {
|
|
50
47
|
if (
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Subscribe } from '../subscriber'
|
|
2
|
+
import { subscriber } from '../subscriber'
|
|
3
|
+
import type { AnyFunction } from '../types'
|
|
4
|
+
|
|
5
|
+
interface CacheItem<T extends AnyFunction> {
|
|
6
|
+
count: number
|
|
7
|
+
returnType: Subscribe<T>
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const cache = new WeakMap<AnyFunction, CacheItem<AnyFunction>>()
|
|
11
|
+
|
|
12
|
+
export function subMemo<F extends AnyFunction>(anyFunction: F) {
|
|
13
|
+
return {
|
|
14
|
+
call(): Subscribe<F> {
|
|
15
|
+
const item = cache.get(anyFunction)
|
|
16
|
+
if (item) {
|
|
17
|
+
item.count++
|
|
18
|
+
return item.returnType
|
|
19
|
+
}
|
|
20
|
+
const returnType = subscriber(anyFunction)
|
|
21
|
+
const newItem = { count: 1, returnType }
|
|
22
|
+
cache.set(anyFunction, newItem)
|
|
23
|
+
return newItem.returnType
|
|
24
|
+
},
|
|
25
|
+
destroy() {
|
|
26
|
+
const item = cache.get(anyFunction)
|
|
27
|
+
|
|
28
|
+
if (item) {
|
|
29
|
+
item.count--
|
|
30
|
+
if (item.count === 0) {
|
|
31
|
+
item.returnType.destroy()
|
|
32
|
+
cache.delete(anyFunction)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Component } from 'react';
|
|
2
|
+
export declare function longPromise(time?: number): Promise<number>;
|
|
3
|
+
export declare class ErrorBoundary extends Component<{
|
|
4
|
+
fallback: React.ReactNode;
|
|
5
|
+
children: React.ReactNode;
|
|
6
|
+
}, {
|
|
7
|
+
hasError: boolean;
|
|
8
|
+
error: Error | null;
|
|
9
|
+
}> {
|
|
10
|
+
constructor(props: {
|
|
11
|
+
fallback: React.ReactNode;
|
|
12
|
+
children: React.ReactNode;
|
|
13
|
+
});
|
|
14
|
+
static getDerivedStateFromError(error: Error): {
|
|
15
|
+
hasError: boolean;
|
|
16
|
+
error: Error;
|
|
17
|
+
};
|
|
18
|
+
componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void;
|
|
19
|
+
render(): import("react").ReactNode;
|
|
20
|
+
}
|
package/types/create.d.ts
CHANGED
|
@@ -1,21 +1,14 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
* const user = userState();
|
|
16
|
-
*
|
|
17
|
-
* // Access partial data from the state using slice
|
|
18
|
-
* const userAge = userState.slice((state) => state.age)();
|
|
19
|
-
* ```
|
|
20
|
-
*/
|
|
21
|
-
export declare function create<T>(defaultValue: DefaultValue<T>, isEqual?: IsEqual<T>): SetterState<Awaited<T>>;
|
|
1
|
+
import type { Emitter } from './utils/create-emitter';
|
|
2
|
+
import type { Callable, DefaultValue, IsEqual, Listener, SetValue } from './types';
|
|
3
|
+
interface RawState<T> {
|
|
4
|
+
(): T;
|
|
5
|
+
id: number;
|
|
6
|
+
set: (value: SetValue<T>) => void;
|
|
7
|
+
emitter: Emitter<T>;
|
|
8
|
+
listen: Listener<T>;
|
|
9
|
+
}
|
|
10
|
+
export type State<T> = {
|
|
11
|
+
readonly [K in keyof RawState<T>]: RawState<T>[K];
|
|
12
|
+
} & Callable<T>;
|
|
13
|
+
export declare function create<T>(initialValue: DefaultValue<T>, isEqual?: IsEqual<T>): State<T>;
|
|
14
|
+
export {};
|
package/types/index.d.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
export * from './types';
|
|
2
2
|
export { create } from './create';
|
|
3
|
-
export {
|
|
4
|
-
export {
|
|
5
|
-
export { useStateValue } from './use-state-value';
|
|
6
|
-
export { shallow } from './shallow';
|
|
3
|
+
export { use } from './use';
|
|
4
|
+
export { shallow } from './utils/shallow';
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { AnyFunction, Callable, Listener } from './types';
|
|
2
|
+
import type { Emitter } from './utils/create-emitter';
|
|
3
|
+
interface SubscribeContext<T = unknown> {
|
|
4
|
+
addEmitter: (emitter: Emitter<T>) => void;
|
|
5
|
+
id: number;
|
|
6
|
+
sub: () => void;
|
|
7
|
+
}
|
|
8
|
+
interface SubscribeRaw<F extends AnyFunction, T extends ReturnType<F> = ReturnType<F>> {
|
|
9
|
+
(): T;
|
|
10
|
+
emitter: Emitter<T | undefined>;
|
|
11
|
+
destroy: () => void;
|
|
12
|
+
id: number;
|
|
13
|
+
listen: Listener<T>;
|
|
14
|
+
abort: () => void;
|
|
15
|
+
}
|
|
16
|
+
export type Subscribe<F extends AnyFunction, T extends ReturnType<F> = ReturnType<F>> = {
|
|
17
|
+
readonly [K in keyof SubscribeRaw<F, T>]: SubscribeRaw<F, T>[K];
|
|
18
|
+
} & Callable<T>;
|
|
19
|
+
export declare const context: {
|
|
20
|
+
run: <R>(ctxValue: SubscribeContext<unknown> | undefined, cb: () => R | Promise<R>) => R;
|
|
21
|
+
use: () => SubscribeContext<unknown> | undefined;
|
|
22
|
+
wrap: <X>(cb: () => X | Promise<X>) => () => X | Promise<X>;
|
|
23
|
+
};
|
|
24
|
+
export declare function subscriber<F extends AnyFunction, T extends ReturnType<F> = ReturnType<F>>(anyFunction: () => T): Subscribe<F, T>;
|
|
25
|
+
export {};
|
package/types/types.d.ts
CHANGED
|
@@ -1,68 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* Equality check function.
|
|
4
|
-
*/
|
|
1
|
+
export type AnyFunction = (...args: any[]) => any;
|
|
5
2
|
export type IsEqual<T = unknown> = (a: T, b: T) => boolean;
|
|
6
|
-
export type
|
|
7
|
-
|
|
8
|
-
* Set new state value function.
|
|
9
|
-
*/
|
|
10
|
-
export type SetValue<T> = T | Setter<T>;
|
|
11
|
-
export type UpdateValue<T> = T extends object ? Partial<T> : T;
|
|
12
|
-
/**
|
|
13
|
-
* Set new state function
|
|
14
|
-
*/
|
|
15
|
-
export type StateValue<T, S> = undefined extends S ? T : S;
|
|
16
|
-
export type Set<T> = (value: SetValue<T>) => void;
|
|
17
|
-
export type Update<T> = (value: UpdateValue<T>) => void;
|
|
18
|
-
/**
|
|
19
|
-
* Getting state value function.
|
|
20
|
-
*/
|
|
21
|
-
export type GetState<T> = () => T;
|
|
22
|
-
export interface StateDataInternal<T = unknown> {
|
|
23
|
-
value?: T;
|
|
24
|
-
updateVersion: number;
|
|
25
|
-
}
|
|
26
|
-
export declare enum StateKeys {
|
|
27
|
-
IS_STATE = "isState",
|
|
28
|
-
IS_SLICE = "isSlice"
|
|
29
|
-
}
|
|
30
|
-
export interface BaseState<T> {
|
|
31
|
-
/**
|
|
32
|
-
* Reset state to default value if it's basic atom - if it's family - it will clear all family members
|
|
33
|
-
*/
|
|
34
|
-
reset: () => void;
|
|
35
|
-
/**
|
|
36
|
-
* Get current state value
|
|
37
|
-
*/
|
|
38
|
-
getState: GetState<T>;
|
|
39
|
-
select: <S>(selector: (value: T) => S, isEqual?: IsEqual<S>) => GetterState<S>;
|
|
40
|
-
merge: <T2, S>(state2: GetterState<T2>, selector: (value1: T, value2: T2) => S, isEqual?: IsEqual<S>) => GetterState<S>;
|
|
41
|
-
/**
|
|
42
|
-
* Internal state data
|
|
43
|
-
*/
|
|
44
|
-
__internal: {
|
|
45
|
-
emitter: Emitter<T>;
|
|
46
|
-
};
|
|
47
|
-
subscribe: (listener: (value: T) => void) => () => void;
|
|
48
|
-
}
|
|
49
|
-
export interface GetterState<T> extends BaseState<T> {
|
|
50
|
-
<S>(selector?: (state: T) => S, isEqual?: IsEqual<S>): StateValue<T, S>;
|
|
51
|
-
}
|
|
52
|
-
export interface SetterState<T> extends GetterState<T> {
|
|
53
|
-
/**
|
|
54
|
-
* Set new state value
|
|
55
|
-
*/
|
|
56
|
-
setState: Set<T>;
|
|
57
|
-
/**
|
|
58
|
-
* Set new state value
|
|
59
|
-
*/
|
|
60
|
-
updateState: Update<T>;
|
|
61
|
-
}
|
|
62
|
-
export type State<T> = SetterState<T> | GetterState<T>;
|
|
3
|
+
export type SetStateCb<T> = (value: T) => Awaited<T>;
|
|
4
|
+
export type SetValue<T> = SetStateCb<T> | Awaited<T>;
|
|
63
5
|
export type DefaultValue<T> = T | (() => T);
|
|
64
|
-
export
|
|
65
|
-
export interface
|
|
66
|
-
current
|
|
67
|
-
|
|
6
|
+
export type Listener<T> = (listener: (value: T) => void) => () => void;
|
|
7
|
+
export interface Cache<T> {
|
|
8
|
+
current?: T;
|
|
9
|
+
previous?: T;
|
|
68
10
|
}
|
|
11
|
+
export type Callable<T> = () => T;
|
|
12
|
+
export declare const EMPTY_SELECTOR: <T>(stateValue: T) => T;
|
package/types/use.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Cache, IsEqual } from '../types';
|
|
2
|
+
export declare enum Abort {
|
|
3
|
+
Error = "StateAbortError"
|
|
4
|
+
}
|
|
5
|
+
export interface CancelablePromise<T> {
|
|
6
|
+
promise?: Promise<T>;
|
|
7
|
+
controller?: AbortController;
|
|
8
|
+
resolveInitialPromise?: (value: T) => void;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Cancelable promise function, return promise and controller
|
|
12
|
+
*/
|
|
13
|
+
export declare function cancelablePromise<T>(promise: Promise<T>, previousController?: AbortController): CancelablePromise<T>;
|
|
14
|
+
export declare function generateId(): number;
|
|
15
|
+
export declare function canUpdate<T>(cache: Cache<T>, isEqual?: IsEqual<T>): boolean;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type EmitterSubscribe<P = undefined> = (listener: (...params: P[]) => void) => () => void;
|
|
2
|
+
export interface Emitter<T, P = undefined> {
|
|
3
|
+
subscribe: EmitterSubscribe<P>;
|
|
4
|
+
subscribeToOtherEmitter: (emitter: Emitter<unknown>) => void;
|
|
5
|
+
getSnapshot: () => T;
|
|
6
|
+
getInitialSnapshot?: () => T;
|
|
7
|
+
emit: (...params: P[]) => void;
|
|
8
|
+
getSize: () => number;
|
|
9
|
+
clear: () => void;
|
|
10
|
+
contains: (listener: (...params: P[]) => void) => boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Generics parameters are:
|
|
14
|
+
* T: Type of the state
|
|
15
|
+
* R: Type of the snapshot
|
|
16
|
+
* P: Type of the parameters
|
|
17
|
+
* @param getSnapshot
|
|
18
|
+
* @returns
|
|
19
|
+
*/
|
|
20
|
+
export declare function createEmitter<T, P = undefined>(getSnapshot: () => T, getInitialSnapshot?: () => T): Emitter<T, P>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SetStateCb, SetValue } from '../types';
|
|
2
|
+
export declare function isPromise<T>(value: unknown): value is Promise<T>;
|
|
3
|
+
export declare function isFunction<T extends (...args: unknown[]) => unknown>(value: unknown): value is T;
|
|
4
|
+
export declare function isMap(value: unknown): value is Map<unknown, unknown>;
|
|
5
|
+
export declare function isSet(value: unknown): value is Set<unknown>;
|
|
6
|
+
export declare function isArray(value: unknown): value is Array<unknown>;
|
|
7
|
+
export declare function isEqualBase<T>(valueA: T, valueB: T): boolean;
|
|
8
|
+
export declare function isSetValueFunction<T>(value: SetValue<T>): value is SetStateCb<T>;
|
|
9
|
+
export declare function isAbortError(value: unknown): value is DOMException;
|
|
10
|
+
export declare function isAnyOtherError(value: unknown): value is Error;
|
|
11
|
+
export declare function isUndefined(value: unknown): value is undefined;
|
package/esm/common.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{useSyncExternalStoreWithSelector as u}from"use-sync-external-store/shim/with-selector";import{useDebugValue as s}from"react";function S(e){return e}function i(e,t,r){const n=u(e.subscribe,e.getSnapshot,e.getSnapshot,t?o=>t(o):S,r);return s(n),n}export{S as toType,i as useSyncExternalStore};
|
package/esm/create-base-state.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{merge as c}from"./merge";import{select as p}from"./select";function y(n){const{emitter:o,getGetterState:s,reset:i,getState:e}=n;return{getState:e,reset:i,select(t,r){const a=s();return p(a,t,r)},merge(t,r,a){const m=s();return c(m,t,r,a)},__internal:{emitter:o},subscribe(t){return t(e()),o.subscribe(()=>{t(e())})}}}export{y as createBaseState};
|
package/esm/create-emitter.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
function n(r){const t=new Set;return{subscribe:e=>(t.add(e),()=>{t.delete(e)}),emit:(...e)=>{for(const i of t)i(...e)},getSnapshot:r}}export{n as createEmitter};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{useStateValue as n}from"./use-state-value";function i(r){const{baseState:t}=r,e=(a,s)=>n(e,a,s);return e.__internal=t.__internal,e.getState=t.getState,e.reset=t.reset,e.select=t.select,e.merge=t.merge,e.subscribe=t.subscribe,e}export{i as createGetterState};
|
package/esm/is.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
function o(n){return n instanceof Promise}function r(n){return typeof n=="function"}function u(n){return typeof n=="function"}function t(n){return typeof n=="object"&&n!==null}function i(n){return t(n)&&n.isRef===!0}function s(n){return n instanceof Map}function f(n){return n instanceof Set}function a(n){return Array.isArray(n)}function c(n,e){return n===e?!0:!!Object.is(n,e)}export{a as isArray,c as isEqualBase,r as isFunction,s as isMap,t as isObject,o as isPromise,i as isRef,f as isSet,u as isSetValueFunction};
|
package/esm/merge.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{createBaseState as u}from"./create-base-state";import{createEmitter as s}from"./create-emitter";import{createGetterState as c}from"./create-getter-state";import{isEqualBase as f}from"./is";function T(t,e,i,n=f){let r;const a=s(()=>{const S=i(t.getState(),e.getState());return r!==void 0&&n(r,S)?r:(r=S,S)});t.__internal.emitter.subscribe(()=>{a.emit()}),e.__internal.emitter.subscribe(()=>{a.emit()});const o=u({emitter:a,getGetterState:()=>m,getState:()=>i(t.getState(),e.getState()),reset(){t.reset(),e.reset()}}),m=c({baseState:o});return m}export{T as merge};
|
package/esm/select.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{createBaseState as m}from"./create-base-state";import{createEmitter as s}from"./create-emitter";import{createGetterState as u}from"./create-getter-state";import{isEqualBase as c}from"./is";function d(t,a,o=c){let e;const S=s(()=>{const r=a(t.getState());return e!==void 0&&o(e,r)?e:(e=r,r)});t.__internal.emitter.subscribe(()=>{S.emit()});const n=m({emitter:S,getGetterState:()=>i,getState:()=>a(t.getState()),reset:t.reset}),i=u({baseState:n});return i}export{d as select};
|
package/esm/shallow.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{isArray as o,isMap as f,isSet as i}from"./is";function b(t,r){if(t==r||Object.is(t,r))return!0;if(typeof t!="object"||t==null||typeof r!="object"||r==null)return!1;if(f(t)&&f(r)){if(t.size!==r.size)return!1;for(const[n,e]of t)if(!Object.is(e,r.get(n)))return!1;return!0}if(i(t)&&i(r)){if(t.size!==r.size)return!1;for(const n of t)if(!r.has(n))return!1;return!0}if(o(t)&&o(r)){if(t.length!==r.length)return!1;for(const[n,e]of t.entries())if(!Object.is(e,r[n]))return!1;return!0}const s=Object.keys(t),c=Object.keys(r);if(s.length!==c.length)return!1;for(const n of s)if(!Object.prototype.hasOwnProperty.call(r,n)||!Object.is(t[n],r[n]))return!1;return!0}export{b as shallow};
|
package/esm/use-state-value.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{useSyncExternalStore as n,toType as S}from"./common";import{isPromise as i}from"./is";function m(e,r=t=>S(t),o){const t=n(e.__internal.emitter,a=>r(a),o);if(i(t))throw t;return t}export{m as useStateValue};
|
package/src/common.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { useSyncExternalStoreWithSelector as useSync } from 'use-sync-external-store/shim/with-selector'
|
|
2
|
-
import type { Emitter } from './create-emitter'
|
|
3
|
-
import type { IsEqual } from './types'
|
|
4
|
-
import { useDebugValue } from 'react'
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Todo need to remove this
|
|
8
|
-
*/
|
|
9
|
-
export function toType<T>(object?: unknown): T {
|
|
10
|
-
return object as T
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function useSyncExternalStore<T, S>(
|
|
14
|
-
emitter: Emitter<T>,
|
|
15
|
-
selector: (stateValue: T) => S,
|
|
16
|
-
isEqual?: IsEqual<S>,
|
|
17
|
-
): undefined extends S ? T : S {
|
|
18
|
-
const value = useSync<T, S>(
|
|
19
|
-
emitter.subscribe,
|
|
20
|
-
emitter.getSnapshot,
|
|
21
|
-
emitter.getSnapshot,
|
|
22
|
-
selector ? (stateValue) => selector(stateValue) : toType,
|
|
23
|
-
isEqual,
|
|
24
|
-
) as undefined extends S ? T : S
|
|
25
|
-
|
|
26
|
-
useDebugValue(value)
|
|
27
|
-
return value
|
|
28
|
-
}
|
package/src/create-base-state.ts
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import type { Emitter } from './create-emitter'
|
|
2
|
-
import { merge } from './merge'
|
|
3
|
-
import { select } from './select'
|
|
4
|
-
import type { BaseState, GetterState } from './types'
|
|
5
|
-
|
|
6
|
-
interface Options<T> {
|
|
7
|
-
readonly emitter: Emitter<T>
|
|
8
|
-
readonly reset: () => void
|
|
9
|
-
readonly getState: () => T
|
|
10
|
-
readonly getGetterState: () => GetterState<T>
|
|
11
|
-
}
|
|
12
|
-
export function createBaseState<T>(options: Options<T>): BaseState<T> {
|
|
13
|
-
const { emitter, getGetterState, reset, getState } = options
|
|
14
|
-
return {
|
|
15
|
-
getState,
|
|
16
|
-
reset,
|
|
17
|
-
select(selector, isSame) {
|
|
18
|
-
const state = getGetterState()
|
|
19
|
-
return select(state, selector, isSame)
|
|
20
|
-
},
|
|
21
|
-
merge(state2, selector, isEqualHook) {
|
|
22
|
-
const state = getGetterState()
|
|
23
|
-
return merge(state, state2, selector, isEqualHook)
|
|
24
|
-
},
|
|
25
|
-
__internal: {
|
|
26
|
-
emitter,
|
|
27
|
-
},
|
|
28
|
-
subscribe(listener) {
|
|
29
|
-
listener(getState())
|
|
30
|
-
return emitter.subscribe(() => {
|
|
31
|
-
listener(getState())
|
|
32
|
-
})
|
|
33
|
-
},
|
|
34
|
-
}
|
|
35
|
-
}
|
package/src/create-emitter.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
export type EmitterSubscribe<P = undefined> = (listener: (...params: P[]) => void) => () => void
|
|
2
|
-
export interface Emitter<T, R = T, P = undefined> {
|
|
3
|
-
subscribe: EmitterSubscribe<P>
|
|
4
|
-
getSnapshot: () => R
|
|
5
|
-
emit: (...params: P[]) => void
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export function createEmitter<T, R = T, P = undefined>(getSnapshot: () => R): Emitter<T, R, P> {
|
|
9
|
-
const listeners = new Set<(...params: P[]) => void>()
|
|
10
|
-
return {
|
|
11
|
-
subscribe: (listener) => {
|
|
12
|
-
listeners.add(listener)
|
|
13
|
-
return () => {
|
|
14
|
-
listeners.delete(listener)
|
|
15
|
-
}
|
|
16
|
-
},
|
|
17
|
-
emit: (...params) => {
|
|
18
|
-
for (const listener of listeners) {
|
|
19
|
-
listener(...params)
|
|
20
|
-
}
|
|
21
|
-
},
|
|
22
|
-
getSnapshot,
|
|
23
|
-
}
|
|
24
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type { BaseState, GetterState } from './types'
|
|
2
|
-
import { useStateValue } from './use-state-value'
|
|
3
|
-
|
|
4
|
-
interface Options<T> {
|
|
5
|
-
readonly baseState: BaseState<T>
|
|
6
|
-
}
|
|
7
|
-
export function createGetterState<T>(options: Options<T>): GetterState<T> {
|
|
8
|
-
const { baseState } = options
|
|
9
|
-
const useSliceState: GetterState<T> = (useSelector, isEqualHook) => {
|
|
10
|
-
return useStateValue(useSliceState, useSelector, isEqualHook)
|
|
11
|
-
}
|
|
12
|
-
useSliceState.__internal = baseState.__internal
|
|
13
|
-
useSliceState.getState = baseState.getState
|
|
14
|
-
useSliceState.reset = baseState.reset
|
|
15
|
-
useSliceState.select = baseState.select
|
|
16
|
-
useSliceState.merge = baseState.merge
|
|
17
|
-
useSliceState.subscribe = baseState.subscribe
|
|
18
|
-
return useSliceState
|
|
19
|
-
}
|
package/src/create.ts
DELETED
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import { createEmitter } from './create-emitter'
|
|
2
|
-
import type { SetValue, SetterState, StateDataInternal, DefaultValue, GetterState, IsEqual, UpdateValue } from './types'
|
|
3
|
-
import { getDefaultValue } from './types'
|
|
4
|
-
import { isEqualBase, isObject, isPromise, isSetValueFunction } from './is'
|
|
5
|
-
import { createBaseState } from './create-base-state'
|
|
6
|
-
import { createGetterState } from './create-getter-state'
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Creates a basic atom state.
|
|
10
|
-
* @param defaultValue - The initial state value.
|
|
11
|
-
* @param options - Optional settings for the state (e.g., isEqual, onSet).
|
|
12
|
-
* @returns A state object that can be used as a hook and provides state management methods.
|
|
13
|
-
* @example
|
|
14
|
-
* ```typescript
|
|
15
|
-
* // Global scope
|
|
16
|
-
* const counterState = state(0);
|
|
17
|
-
* const userState = state({ name: 'John', age: 20 });
|
|
18
|
-
*
|
|
19
|
-
* // React component
|
|
20
|
-
* const counter = counterState(); // Use as a hook
|
|
21
|
-
* const user = userState();
|
|
22
|
-
*
|
|
23
|
-
* // Access partial data from the state using slice
|
|
24
|
-
* const userAge = userState.slice((state) => state.age)();
|
|
25
|
-
* ```
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
export function create<T>(defaultValue: DefaultValue<T>, isEqual: IsEqual<T> = isEqualBase): SetterState<Awaited<T>> {
|
|
29
|
-
function resolveSetter(value: T, stateSetter: SetValue<T>): T {
|
|
30
|
-
if (isSetValueFunction(stateSetter)) {
|
|
31
|
-
return stateSetter(value)
|
|
32
|
-
}
|
|
33
|
-
return stateSetter
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const stateData: StateDataInternal<T> = {
|
|
37
|
-
updateVersion: 0,
|
|
38
|
-
value: undefined,
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function getValue(): T {
|
|
42
|
-
if (stateData.value === undefined) {
|
|
43
|
-
stateData.value = getDefaultValue(defaultValue)
|
|
44
|
-
}
|
|
45
|
-
return stateData.value
|
|
46
|
-
}
|
|
47
|
-
function get(): T {
|
|
48
|
-
const stateValue = getValue()
|
|
49
|
-
if (isPromise(stateValue)) {
|
|
50
|
-
stateValue.then((data) => {
|
|
51
|
-
stateData.value = data as Awaited<T>
|
|
52
|
-
emitter.emit()
|
|
53
|
-
})
|
|
54
|
-
}
|
|
55
|
-
return stateValue
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function set(stateValue: SetValue<T>) {
|
|
59
|
-
const stateValueData = getValue()
|
|
60
|
-
const newState = resolveSetter(stateValueData, stateValue)
|
|
61
|
-
const isEqualResult = isEqual?.(stateValueData, newState)
|
|
62
|
-
if (isEqualResult || newState === stateValueData) {
|
|
63
|
-
return
|
|
64
|
-
}
|
|
65
|
-
stateData.updateVersion++
|
|
66
|
-
stateData.value = newState
|
|
67
|
-
emitter.emit()
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function update(stateValue: UpdateValue<T>) {
|
|
71
|
-
if (isObject(stateValue)) {
|
|
72
|
-
return set((previousState) => {
|
|
73
|
-
return { ...previousState, ...stateValue }
|
|
74
|
-
})
|
|
75
|
-
}
|
|
76
|
-
set(stateValue as T)
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const emitter = createEmitter<T>(get)
|
|
80
|
-
|
|
81
|
-
const baseState = createBaseState({
|
|
82
|
-
emitter,
|
|
83
|
-
getGetterState: () => setterState,
|
|
84
|
-
getState: get,
|
|
85
|
-
reset() {
|
|
86
|
-
const value = getDefaultValue(defaultValue)
|
|
87
|
-
if (isPromise(value)) {
|
|
88
|
-
value.then((data) => {
|
|
89
|
-
set(data as T)
|
|
90
|
-
})
|
|
91
|
-
return
|
|
92
|
-
}
|
|
93
|
-
set(value)
|
|
94
|
-
},
|
|
95
|
-
})
|
|
96
|
-
|
|
97
|
-
const getterState: GetterState<T> = createGetterState<T>({ baseState })
|
|
98
|
-
const setterState: SetterState<T> = getterState as SetterState<T>
|
|
99
|
-
setterState.setState = set
|
|
100
|
-
setterState.updateState = update
|
|
101
|
-
return setterState as SetterState<Awaited<T>>
|
|
102
|
-
}
|
package/src/index.ts
DELETED
package/src/is.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import type { Ref, Setter, SetValue } from './types'
|
|
2
|
-
|
|
3
|
-
export function isPromise(value: unknown): value is Promise<unknown> {
|
|
4
|
-
return value instanceof Promise
|
|
5
|
-
}
|
|
6
|
-
export function isFunction(value: unknown): value is (...args: unknown[]) => unknown {
|
|
7
|
-
return typeof value === 'function'
|
|
8
|
-
}
|
|
9
|
-
export function isSetValueFunction<T>(value: SetValue<T>): value is Setter<T> {
|
|
10
|
-
return typeof value === 'function'
|
|
11
|
-
}
|
|
12
|
-
export function isObject(value: unknown): value is Record<string, unknown> {
|
|
13
|
-
return typeof value === 'object' && value !== null
|
|
14
|
-
}
|
|
15
|
-
export function isRef<T>(value: unknown): value is Ref<T> {
|
|
16
|
-
return isObject(value) && value.isRef === true
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function isMap(value: unknown): value is Map<unknown, unknown> {
|
|
20
|
-
return value instanceof Map
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function isSet(value: unknown): value is Set<unknown> {
|
|
24
|
-
return value instanceof Set
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function isArray(value: unknown): value is Array<unknown> {
|
|
28
|
-
return Array.isArray(value)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export function isEqualBase<T>(valueA: T, valueB: T): boolean {
|
|
32
|
-
if (valueA === valueB) {
|
|
33
|
-
return true
|
|
34
|
-
}
|
|
35
|
-
return !!Object.is(valueA, valueB)
|
|
36
|
-
}
|
package/src/merge.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { createBaseState } from './create-base-state'
|
|
2
|
-
import { createEmitter } from './create-emitter'
|
|
3
|
-
import { createGetterState } from './create-getter-state'
|
|
4
|
-
import { isEqualBase } from './is'
|
|
5
|
-
import type { IsEqual, GetterState } from './types'
|
|
6
|
-
|
|
7
|
-
export function merge<T1, T2, S>(
|
|
8
|
-
state1: GetterState<T1>,
|
|
9
|
-
state2: GetterState<T2>,
|
|
10
|
-
selector: (value1: T1, value2: T2) => S,
|
|
11
|
-
isEqual: IsEqual<S> = isEqualBase,
|
|
12
|
-
): GetterState<S> {
|
|
13
|
-
let previousData: S | undefined
|
|
14
|
-
const emitter = createEmitter(() => {
|
|
15
|
-
const data = selector(state1.getState(), state2.getState())
|
|
16
|
-
if (previousData !== undefined && isEqual(previousData, data)) {
|
|
17
|
-
return previousData
|
|
18
|
-
}
|
|
19
|
-
previousData = data
|
|
20
|
-
return data
|
|
21
|
-
})
|
|
22
|
-
state1.__internal.emitter.subscribe(() => {
|
|
23
|
-
emitter.emit()
|
|
24
|
-
})
|
|
25
|
-
state2.__internal.emitter.subscribe(() => {
|
|
26
|
-
emitter.emit()
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
const baseState = createBaseState<S>({
|
|
30
|
-
emitter,
|
|
31
|
-
getGetterState: () => getterState,
|
|
32
|
-
getState: () => selector(state1.getState(), state2.getState()),
|
|
33
|
-
reset() {
|
|
34
|
-
state1.reset()
|
|
35
|
-
state2.reset()
|
|
36
|
-
},
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
const getterState: GetterState<S> = createGetterState<S>({ baseState })
|
|
40
|
-
return getterState
|
|
41
|
-
}
|