reactish-state 1.0.0 → 1.1.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.
@@ -16,10 +16,10 @@ const useSelector = (selectorParamFactory, deps) => {
16
16
  const {
17
17
  cache
18
18
  } = context;
19
- const reactishValues = utils.getReactishValues(items);
20
- const args = reactishValues.concat(deps || selectorFunc);
19
+ const selectorValues = utils.getSelectorValues(items);
20
+ const args = selectorValues.concat(deps || selectorFunc);
21
21
  if (cache && utils.isEqual(args, cache.args)) return cache.val;
22
- const val = selectorFunc(...reactishValues);
22
+ const val = selectorFunc(...selectorValues);
23
23
  context.cache = {
24
24
  args,
25
25
  val
@@ -10,8 +10,8 @@ const createSubscriber = items => listener => {
10
10
  const unsubscribers = items.map(item => item.subscribe(listener));
11
11
  return () => unsubscribers.forEach(unsubscribe => unsubscribe());
12
12
  };
13
- const getReactishValues = items => items.map(item => item.get());
13
+ const getSelectorValues = items => items.map(item => item.get());
14
14
 
15
15
  exports.createSubscriber = createSubscriber;
16
- exports.getReactishValues = getReactishValues;
16
+ exports.getSelectorValues = getSelectorValues;
17
17
  exports.isEqual = isEqual;
@@ -15,7 +15,7 @@ const createSelector = ({
15
15
  let cache;
16
16
  const selector = {
17
17
  get: () => {
18
- const args = utils.getReactishValues(items);
18
+ const args = utils.getSelectorValues(items);
19
19
  if (cache && utils.isEqual(args, cache.args)) return cache.val;
20
20
  const val = selectorFunc(...args);
21
21
  cache = {
@@ -2,15 +2,16 @@
2
2
 
3
3
  const createState = ({
4
4
  middleware
5
- } = {}) => (initialValue, actionCreator, config) => {
5
+ } = {}) => (initialValue, actionBuilder, config) => {
6
6
  let value = initialValue;
7
7
  const listeners = new Set();
8
8
  const get = () => value;
9
9
  let set = newValue => {
10
10
  const nextValue = typeof newValue === 'function' ? newValue(value) : newValue;
11
11
  if (!Object.is(value, nextValue)) {
12
+ const prevValue = value;
12
13
  value = nextValue;
13
- listeners.forEach(listener => listener());
14
+ listeners.forEach(listener => listener(nextValue, prevValue));
14
15
  }
15
16
  };
16
17
  const subscribe = listener => {
@@ -23,7 +24,7 @@ const createState = ({
23
24
  subscribe
24
25
  }, config);
25
26
  return {
26
- ...actionCreator?.(set, get),
27
+ ...actionBuilder?.(set, get),
27
28
  get,
28
29
  set,
29
30
  subscribe
@@ -1,5 +1,5 @@
1
1
  import { useState } from 'react';
2
- import { createSubscriber, getReactishValues, isEqual } from '../utils.mjs';
2
+ import { createSubscriber, getSelectorValues, isEqual } from '../utils.mjs';
3
3
  import { useSnapshot } from './useSnapshot.mjs';
4
4
 
5
5
  const useSelector = (selectorParamFactory, deps) => {
@@ -14,10 +14,10 @@ const useSelector = (selectorParamFactory, deps) => {
14
14
  const {
15
15
  cache
16
16
  } = context;
17
- const reactishValues = getReactishValues(items);
18
- const args = reactishValues.concat(deps || selectorFunc);
17
+ const selectorValues = getSelectorValues(items);
18
+ const args = selectorValues.concat(deps || selectorFunc);
19
19
  if (cache && isEqual(args, cache.args)) return cache.val;
20
- const val = selectorFunc(...reactishValues);
20
+ const val = selectorFunc(...selectorValues);
21
21
  context.cache = {
22
22
  args,
23
23
  val
@@ -8,6 +8,6 @@ const createSubscriber = items => listener => {
8
8
  const unsubscribers = items.map(item => item.subscribe(listener));
9
9
  return () => unsubscribers.forEach(unsubscribe => unsubscribe());
10
10
  };
11
- const getReactishValues = items => items.map(item => item.get());
11
+ const getSelectorValues = items => items.map(item => item.get());
12
12
 
13
- export { createSubscriber, getReactishValues, isEqual };
13
+ export { createSubscriber, getSelectorValues, isEqual };
@@ -1,4 +1,4 @@
1
- import { createSubscriber, getReactishValues, isEqual } from '../utils.mjs';
1
+ import { createSubscriber, getSelectorValues, isEqual } from '../utils.mjs';
2
2
 
3
3
  const createSelector = ({
4
4
  plugin
@@ -13,7 +13,7 @@ const createSelector = ({
13
13
  let cache;
14
14
  const selector = {
15
15
  get: () => {
16
- const args = getReactishValues(items);
16
+ const args = getSelectorValues(items);
17
17
  if (cache && isEqual(args, cache.args)) return cache.val;
18
18
  const val = selectorFunc(...args);
19
19
  cache = {
@@ -1,14 +1,15 @@
1
1
  const createState = ({
2
2
  middleware
3
- } = {}) => (initialValue, actionCreator, config) => {
3
+ } = {}) => (initialValue, actionBuilder, config) => {
4
4
  let value = initialValue;
5
5
  const listeners = new Set();
6
6
  const get = () => value;
7
7
  let set = newValue => {
8
8
  const nextValue = typeof newValue === 'function' ? newValue(value) : newValue;
9
9
  if (!Object.is(value, nextValue)) {
10
+ const prevValue = value;
10
11
  value = nextValue;
11
- listeners.forEach(listener => listener());
12
+ listeners.forEach(listener => listener(nextValue, prevValue));
12
13
  }
13
14
  };
14
15
  const subscribe = listener => {
@@ -21,7 +22,7 @@ const createState = ({
21
22
  subscribe
22
23
  }, config);
23
24
  return {
24
- ...actionCreator?.(set, get),
25
+ ...actionBuilder?.(set, get),
25
26
  get,
26
27
  set,
27
28
  subscribe
@@ -1,5 +1,5 @@
1
1
  'use strict';
2
2
 
3
- const applyPlugin = plugins => (reactish, config) => plugins.forEach(plugin => plugin?.(reactish, config));
3
+ const applyPlugin = plugins => (selector, config) => plugins.forEach(plugin => plugin?.(selector, config));
4
4
 
5
5
  exports.applyPlugin = applyPlugin;
@@ -1,3 +1,3 @@
1
- const applyPlugin = plugins => (reactish, config) => plugins.forEach(plugin => plugin?.(reactish, config));
1
+ const applyPlugin = plugins => (selector, config) => plugins.forEach(plugin => plugin?.(selector, config));
2
2
 
3
3
  export { applyPlugin };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "reactish-state",
3
- "version": "1.0.0",
3
+ "version": "1.1.1",
4
4
  "description": "Simple, decentralized (atomic) state management for React.",
5
5
  "author": "Zheng Song",
6
6
  "license": "MIT",
@@ -80,44 +80,40 @@
80
80
  }
81
81
  },
82
82
  "dependencies": {
83
- "use-sync-external-store": "^1.4.0"
83
+ "use-sync-external-store": "^1.5.0"
84
84
  },
85
85
  "devDependencies": {
86
- "@babel/core": "^7.26.9",
87
- "@babel/preset-env": "^7.26.9",
88
- "@babel/preset-react": "^7.26.3",
89
- "@babel/preset-typescript": "^7.26.0",
86
+ "@babel/core": "^7.28.0",
87
+ "@babel/preset-env": "^7.28.0",
88
+ "@babel/preset-react": "^7.27.1",
89
+ "@babel/preset-typescript": "^7.27.1",
90
90
  "@redux-devtools/extension": "^3.3.0",
91
91
  "@rollup/plugin-babel": "^6.0.4",
92
- "@rollup/plugin-node-resolve": "^16.0.0",
92
+ "@rollup/plugin-node-resolve": "^16.0.1",
93
93
  "@rollup/plugin-replace": "^6.0.2",
94
- "@testing-library/jest-dom": "^6.6.3",
95
- "@testing-library/react": "^16.2.0",
96
- "@types/jest": "^29.5.14",
97
- "@types/react": "^19.0.8",
98
- "@types/use-sync-external-store": "^0.0.6",
94
+ "@testing-library/jest-dom": "^6.6.4",
95
+ "@testing-library/react": "^16.3.0",
96
+ "@types/jest": "^30.0.0",
97
+ "@types/react": "^19.1.9",
98
+ "@types/use-sync-external-store": "^1.5.0",
99
99
  "babel-plugin-pure-annotations": "^0.1.2",
100
- "eslint": "^9.20.1",
101
- "eslint-config-prettier": "^10.0.1",
102
- "eslint-plugin-jest": "^28.11.0",
103
- "eslint-plugin-react": "^7.37.4",
104
- "eslint-plugin-react-hooks": "^5.1.0",
105
- "eslint-plugin-react-hooks-addons": "^0.4.1",
106
- "globals": "^15.15.0",
100
+ "deplift": "^1.0.1",
101
+ "eslint": "^9.32.0",
102
+ "eslint-config-prettier": "^10.1.8",
103
+ "eslint-plugin-jest": "^29.0.1",
104
+ "eslint-plugin-react": "^7.37.5",
105
+ "eslint-plugin-react-hooks": "^5.2.0",
106
+ "eslint-plugin-react-hooks-addons": "^0.5.0",
107
+ "globals": "^16.3.0",
107
108
  "immer": "^10.1.1",
108
- "jest": "^29.7.0",
109
- "jest-environment-jsdom": "^29.7.0",
109
+ "jest": "^30.0.5",
110
+ "jest-environment-jsdom": "^30.0.5",
110
111
  "npm-run-all": "^4.1.5",
111
- "prettier": "^3.4.2",
112
- "react": "^19.0.0",
113
- "react-dom": "^19.0.0",
114
- "rollup": "^4.34.2",
115
- "typescript": "^5.7.3",
116
- "typescript-eslint": "^8.24.0"
117
- },
118
- "overrides": {
119
- "whatwg-url@11.0.0": {
120
- "tr46": "^4"
121
- }
112
+ "prettier": "^3.6.2",
113
+ "react": "^19.1.1",
114
+ "react-dom": "^19.1.1",
115
+ "rollup": "^4.46.2",
116
+ "typescript": "^5.8.3",
117
+ "typescript-eslint": "^8.38.0"
122
118
  }
123
119
  }
package/types/common.d.ts CHANGED
@@ -1,32 +1,37 @@
1
1
  export type Getter<T> = () => T;
2
- export type Setter<T> = (newValue: T | ((value: T) => T), action?: string | {
3
- type: string;
4
- [key: string]: unknown;
5
- }) => void;
6
- export type Listener = () => void;
7
- export type Subscriber = (listener: Listener) => () => void;
8
- export interface Reactish<T> {
2
+ export type Setter<T> = (newValue: T | ((value: T) => T), context?: unknown) => void;
3
+ export type Unsubscriber = () => void;
4
+ export type StateListener<T> = (nextValue: T, prevValue: T) => void;
5
+ export type StateSubscriber<T> = (listener: StateListener<T>) => Unsubscriber;
6
+ export interface State<T> {
9
7
  get: Getter<T>;
10
- subscribe: Subscriber;
8
+ set: Setter<T>;
9
+ subscribe: StateSubscriber<T>;
10
+ }
11
+ export type ActionBuilder<T, A> = ((set: Setter<T>, get: () => T) => A) | null | undefined;
12
+ export type StateWithAction<T, A> = Omit<A, keyof State<T>> & State<T>;
13
+ export type SelectorListener = () => void;
14
+ export type SelectorSubscriber = (listener: SelectorListener) => Unsubscriber;
15
+ export interface Selector<T> {
16
+ get: Getter<T>;
17
+ subscribe: SelectorSubscriber;
11
18
  }
12
19
  export interface Config {
13
20
  key?: string;
14
21
  }
15
22
  export interface Middleware {
16
- <T>(api: Reactish<T> & {
17
- set: Setter<T>;
18
- }, config?: Config): Setter<T>;
23
+ <T>(state: State<T>, config?: Config): Setter<T>;
19
24
  }
20
25
  export interface Plugin {
21
- <T>(reactish: Reactish<T>, config?: Config): void;
26
+ <T>(selector: Selector<T>, config?: Config): void;
22
27
  }
23
- export type ReactishArray = Reactish<unknown>[];
24
- export type ReactishValueArray<RA extends ReactishArray> = {
25
- [index in keyof RA]: ReturnType<RA[index]['get']>;
28
+ export type SelectorArray = Selector<unknown>[];
29
+ export type SelectorValueArray<TArray extends SelectorArray> = {
30
+ [index in keyof TArray]: ReturnType<TArray[index]['get']>;
26
31
  };
27
- export type SelectorFunc<RA extends ReactishArray, T> = (...args: ReactishValueArray<RA>) => T;
28
- export type SelectorParams<RA extends ReactishArray, T> = [...RA, SelectorFunc<RA, T>];
29
- export interface Selector {
30
- <RA extends ReactishArray, T>(...items: SelectorParams<RA, T>): Reactish<T>;
31
- <RA extends ReactishArray, T>(...items: [...SelectorParams<RA, T>, Config]): Reactish<T>;
32
+ export type SelectorFunc<TArray extends SelectorArray, T> = (...args: SelectorValueArray<TArray>) => T;
33
+ export type SelectorParams<TArray extends SelectorArray, T> = [...TArray, SelectorFunc<TArray, T>];
34
+ export interface SelectorBuilder {
35
+ <RA extends SelectorArray, T>(...items: SelectorParams<RA, T>): Selector<T>;
36
+ <RA extends SelectorArray, T>(...items: [...SelectorParams<RA, T>, Config]): Selector<T>;
32
37
  }
@@ -1,3 +1,3 @@
1
- import type { ReactishArray, SelectorParams } from '../common';
2
- declare const useSelector: <RA extends ReactishArray, T>(selectorParamFactory: () => SelectorParams<RA, T>, deps?: unknown[]) => T;
1
+ import type { SelectorArray, SelectorParams } from '../common';
2
+ declare const useSelector: <TArray extends SelectorArray, T>(selectorParamFactory: () => SelectorParams<TArray, T>, deps?: unknown[]) => T;
3
3
  export { useSelector };
@@ -1,3 +1,3 @@
1
- import type { Reactish } from '../common';
2
- declare const useSnapshot: <T>({ subscribe, get }: Reactish<T>) => T;
1
+ import type { Selector } from '../common';
2
+ declare const useSnapshot: <T>({ subscribe, get }: Selector<T>) => T;
3
3
  export { useSnapshot };
package/types/utils.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Subscriber, ReactishArray, ReactishValueArray } from './common';
1
+ import type { SelectorSubscriber, SelectorArray, SelectorValueArray } from './common';
2
2
  export declare const isEqual: (args1: unknown[], args2: unknown[]) => boolean;
3
- export declare const createSubscriber: (items: ReactishArray) => Subscriber;
4
- export declare const getReactishValues: <RA extends ReactishArray>(items: ReactishArray) => ReactishValueArray<RA>;
3
+ export declare const createSubscriber: (items: SelectorArray) => SelectorSubscriber;
4
+ export declare const getSelectorValues: <RA extends SelectorArray>(items: SelectorArray) => SelectorValueArray<RA>;
@@ -1,7 +1,6 @@
1
- import type { Plugin, Selector } from '../common';
1
+ import type { Plugin, SelectorBuilder } from '../common';
2
2
  declare const createSelector: ({ plugin }?: {
3
3
  plugin?: Plugin;
4
- }) => Selector;
5
- declare const selector: Selector;
6
- export type { Selector };
4
+ }) => SelectorBuilder;
5
+ declare const selector: SelectorBuilder;
7
6
  export { selector, createSelector };
@@ -1,12 +1,7 @@
1
- import type { Reactish, Setter, Config, Middleware } from '../common';
2
- type ActionCreator<T, A> = ((set: Setter<T>, get: () => T) => A) | null | undefined;
3
- type VanillaState<T> = Reactish<T> & {
4
- set: Setter<T>;
5
- };
6
- type State<T, A> = Omit<A, keyof VanillaState<T>> & VanillaState<T>;
1
+ import type { ActionBuilder, StateWithAction, Config, Middleware } from '../common';
7
2
  declare const createState: ({ middleware }?: {
8
3
  middleware?: Middleware;
9
- }) => <T, A>(initialValue: T, actionCreator?: ActionCreator<T, A>, config?: Config) => State<T, A>;
10
- declare const state: <T, A>(initialValue: T, actionCreator?: ActionCreator<T, A>, config?: Config) => State<T, A>;
11
- export type { State, ActionCreator };
12
- export { state, createState };
4
+ }) => <T, A>(initialValue: T, actionBuilder?: ActionBuilder<T, A>, config?: Config) => StateWithAction<T, A>;
5
+ declare const state: <T, A>(initialValue: T, actionBuilder?: ActionBuilder<T, A>, config?: Config) => StateWithAction<T, A>;
6
+ type StateBuilder = typeof state;
7
+ export { state, createState, type StateBuilder };