floppy-disk 2.16.0 → 3.0.0-experimental.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 CHANGED
@@ -30,7 +30,7 @@ import { createQuery, createMutation } from 'floppy-disk'; // 9.7 kB (gzipped: 3
30
30
 
31
31
  - **Create Store**
32
32
  - Get/set store inside/outside component
33
- - Very simple way to customize the reactivity (state update subscription)
33
+ - Very simple way to customize the reactivity (a.k.a. state update subscription)
34
34
  - Support middleware
35
35
  - Set state interception
36
36
  - Store event (`onSubscribe`, `onUnsubscribe`, etc.)
@@ -112,12 +112,12 @@ Use the hook anywhere, no providers are needed.
112
112
 
113
113
  ```jsx
114
114
  function Cat() {
115
- const age = useCatStore('age');
115
+ const { age } = useCatStore((state) => [state.age]);
116
116
  return <div>Cat's age: {age}</div>;
117
117
  }
118
118
 
119
119
  function Control() {
120
- const increaseAge = useCatStore('increaseAge');
120
+ const { increaseAge } = useCatStore((state) => [state.increaseAge]);
121
121
  return <button onClick={increaseAge}>Increase cat's age</button>;
122
122
  }
123
123
  ```
@@ -130,36 +130,26 @@ Control the reactivity. The concept is same as useEffect dependency array.
130
130
  function YourComponent() {
131
131
  const { age, isSleeping } = useCatStore();
132
132
  // Will re-render every state change ^
133
+ ...
133
134
  }
134
135
 
135
136
  function YourComponent() {
136
137
  const { age, isSleeping } = useCatStore((state) => [state.isSleeping]);
137
138
  // Will only re-render when isSleeping is updated ^
138
139
  // Update on age won't cause re-render this component
140
+ ...
139
141
  }
140
142
 
141
143
  function YourComponent() {
142
144
  const { age, isSleeping } = useCatStore((state) => [state.age, state.isSleeping]);
143
145
  // Will re-render when age or isSleeping is updated ^
146
+ ...
144
147
  }
145
148
 
146
149
  function YourComponent() {
147
150
  const { age, isSleeping } = useCatStore((state) => [state.age > 3]);
148
151
  // Will only re-render when (age>3) is updated
149
- }
150
- ```
151
-
152
- Even simpler way, after version `2.13.0`, we can use store's object key:
153
-
154
- ```jsx
155
- function YourComponent() {
156
- const age = useCatStore('age');
157
- // Will only re-render when age is updated
158
- }
159
-
160
- function YourComponent() {
161
- const age = useCatStore('isSleeping');
162
- // Will only re-render when isSleeping is updated
152
+ ...
163
153
  }
164
154
  ```
165
155
 
@@ -198,7 +188,7 @@ const decreaseAgeSilently = () => {
198
188
  };
199
189
  // 👇 Will not re-render
200
190
  function Cat() {
201
- const age = useCatStore('age');
191
+ const { age } = useCatStore((state) => [state.age]);
202
192
  return <div>Cat's age: {age}</div>;
203
193
  }
204
194
  ```
@@ -268,7 +258,7 @@ Prevent re-render using `Watch`.
268
258
 
269
259
  ```jsx
270
260
  function CatPage() {
271
- const age = useCatStore('age');
261
+ const { age } = useCatStore((state) => [state.age]);
272
262
  // If age changed, this component will re-render which will cause
273
263
  // HeavyComponent1 & HeavyComponent2 to be re-rendered as well.
274
264
  return (
@@ -286,8 +276,8 @@ function CatPageOptimized() {
286
276
  <main>
287
277
  <HeavyComponent1 />
288
278
  <useCatStore.Watch
289
- selectDeps="age"
290
- render={(age) => {
279
+ selectDeps={(state) => [state.age]}
280
+ render={({ age }) => {
291
281
  return <div>Cat's age: {age}</div>;
292
282
  }}
293
283
  />
@@ -338,20 +328,11 @@ function Parent() {
338
328
 
339
329
  function CatAge() {
340
330
  const { age } = useCatStoreContext()((state) => [state.age]);
341
-
342
- // Shorthand after v1.13.0:
343
- // const age = useCatStoreContext()('age');
344
-
345
331
  return <div>Age: {age}</div>;
346
332
  }
347
-
348
333
  function CatIsSleeping() {
349
334
  const useCatStore = useCatStoreContext();
350
335
  const { isSleeping } = useCatStore((state) => [state.isSleeping]);
351
-
352
- // Shorthand after v1.13.0:
353
- // const isSleeping = useCatStore('isSleeping');
354
-
355
336
  return (
356
337
  <>
357
338
  <div>Is Sleeping: {String(isSleeping)}</div>
@@ -802,7 +783,6 @@ Don't use conditional reactivity selector.
802
783
 
803
784
  ```jsx
804
785
  function Cat({ isSomething }) {
805
- const value = useCatStore(isSomething ? 'age' : 'isSleeping'); // ❌
806
786
  const { age } = useCatStore(isSomething ? (state) => [state.age] : null); // ❌
807
787
  const { age } = useCatStore((state) => (isSomething ? [state.age] : [state.isSleeping])); // ❌
808
788
  return <div>Cat's age: {age}</div>;
package/esm/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export * from './store';
2
- export * from './fetcher';
1
+ export * from './vanilla/init-store';
2
+ export * from './vanilla/fetcher';
3
3
  export * from './react/create-store';
4
4
  export * from './react/create-stores';
5
5
  export * from './react/create-query';
package/esm/index.js CHANGED
@@ -1,5 +1,5 @@
1
- export * from './store';
2
- export * from './fetcher';
1
+ export * from './vanilla/init-store';
2
+ export * from './vanilla/fetcher';
3
3
  export * from './react/create-store';
4
4
  export * from './react/create-stores';
5
5
  export * from './react/create-query';
@@ -6,7 +6,7 @@ export declare const createBiDirectionQuery: <TKey extends StoreKey = StoreKey,
6
6
  getNextPageParam: (lastPage: TResponse, index: number, stateBeforeCallQuery: QueryState<TKey, TResponse, TData, TError, TPageParam>) => Maybe<TPageParam>;
7
7
  select: (response: TResponse, state: Pick<QueryState<TKey, TResponse, TData, TError, TPageParam>, "data" | "key">, direction: 'prev' | 'next') => TData;
8
8
  }) => {
9
- (key: Maybe<TKey>, selectDeps?: "data" | "key" | "error" | "reset" | "status" | "fetch" | "response" | "keyHash" | "forceFetch" | "fetchNextPage" | "optimisticUpdate" | "isWaiting" | "isWaitingNextPage" | "isRefetching" | "isRefetchError" | "isPreviousData" | "isOptimisticData" | "errorUpdatedAt" | "retryCount" | "isGoingToRetry" | "pageParam" | "pageParams" | "hasNextPage" | "retryNextPageCount" | "isGoingToRetryNextPage" | "isLoading" | "isSuccess" | "isError" | "responseUpdatedAt" | import("..").SelectDeps<QueryState<TKey, TResponse, TData, TError, TPageParam>>): {
9
+ (...args: [Maybe<TKey>, import("..").SelectDeps<QueryState<TKey, TResponse, TData, TError, TPageParam>>?] | [import("..").SelectDeps<QueryState<TKey, TResponse, TData, TError, TPageParam>>?]): {
10
10
  data: (never[] | TData)[number][];
11
11
  fetchPrevPage: () => Promise<QueryState<TKey, TResponse, TData, TError, TPageParam>>;
12
12
  hasPrevPage: boolean;
@@ -1,4 +1,4 @@
1
- import { InitStoreOptions } from '../store';
1
+ import { InitStoreOptions } from '../vanilla/init-store';
2
2
  import { UseStore } from './create-store';
3
3
  export type MutationState<TVar, TResponse = any, TError = unknown> = {
4
4
  /**
@@ -1,35 +1,22 @@
1
- import { InitStoreOptions, SelectDeps, SetStoreData, StoreData, StoreInitializer, Subscribers } from '../store';
2
- export type WatchProps<T, K extends SelectDeps<T> | keyof T = SelectDeps<T>> = {
3
- selectDeps?: K;
4
- render: (state: K extends keyof T ? T[K] : T) => any;
1
+ import { InitStoreOptions, SelectDeps, SetStoreState, StoreInitializer, StoreState, Subscribers } from '../vanilla/init-store';
2
+ export type WatchProps<T> = {
3
+ selectDeps?: SelectDeps<T>;
4
+ render: (state: T) => any;
5
5
  };
6
- export type UseStore<T extends StoreData> = {
6
+ export type UseStore<T extends StoreState> = {
7
7
  /**
8
- * @param selectDeps (Optional) A function that return the dependency array (just like in `useEffect`), to trigger reactivity.
8
+ * @param selectDeps A function that return the dependency array (just like in `useEffect`), to trigger reactivity.
9
+ *
9
10
  * Defaults to `undefined` (reactive to all state change) if you didn't set `defaultDeps` on `createStore`.
10
11
  *
11
- * Since version `2.13.0`, we can use a store's object key to control reactivity.
12
+ * Value of `null` will also make it reactive to all state change.
12
13
  *
13
14
  * **IMPORTANT NOTE:** `selectDeps` must not be changed after initialization.
14
- *
15
- * @example
16
- * ```tsx
17
- * const useMyStore = createStore({
18
- * foo: 12,
19
- * bar: true,
20
- * baz: "z",
21
- * });
22
- *
23
- * const MyComponent = () => {
24
- * const foo = useMyStore("foo");
25
- * // Will only re-render if "foo" updated
26
- * };
27
- * ```
28
15
  */
29
- <K extends SelectDeps<T> | keyof T = SelectDeps<T>>(selectDeps?: K): K extends keyof T ? T[K] : T;
16
+ (selectDeps?: SelectDeps<T>): T;
30
17
  get: () => T;
31
- set: (value: SetStoreData<T>, silent?: boolean) => void;
32
- subscribe: (fn: (state: T) => void, selectDeps?: SelectDeps<T> | keyof T) => () => void;
18
+ set: (value: SetStoreState<T>, silent?: boolean) => void;
19
+ subscribe: (fn: (state: T) => void, selectDeps?: SelectDeps<T>) => () => void;
33
20
  getSubscribers: () => Subscribers<T>;
34
21
  /**
35
22
  * ⚛️ (**_Hook_**)
@@ -40,12 +27,12 @@ export type UseStore<T extends StoreData> = {
40
27
  * - This is a hook, put it inside of a React component
41
28
  * - Put this on the root component or parent component, before any component subscribed!
42
29
  */
43
- setDefaultValues: (values: SetStoreData<T>) => void;
44
- Watch: <K extends SelectDeps<T> | keyof T = SelectDeps<T>>(props: WatchProps<T, K>) => any;
30
+ setDefaultValues: (values: SetStoreState<T>) => void;
31
+ Watch: (props: WatchProps<T>) => any;
45
32
  };
46
33
  /**
47
34
  * @see https://floppy-disk.vercel.app/docs/api#createstore
48
35
  */
49
- export declare const createStore: <T extends StoreData>(initializer: StoreInitializer<T>, options?: InitStoreOptions<T> & {
36
+ export declare const createStore: <T extends StoreState>(initializer: StoreInitializer<T>, options?: InitStoreOptions<T> & {
50
37
  defaultDeps?: SelectDeps<T>;
51
38
  }) => UseStore<T>;
@@ -1,5 +1,5 @@
1
1
  import { useEffect, useState } from 'react';
2
- import { initStore, } from '../store';
2
+ import { initStore, } from '../vanilla/init-store';
3
3
  /**
4
4
  * @see https://floppy-disk.vercel.app/docs/api#createstore
5
5
  */
@@ -13,7 +13,7 @@ export const createStore = (initializer, options = {}) => {
13
13
  const [state, setState] = useState(get);
14
14
  // eslint-disable-next-line react-hooks/exhaustive-deps
15
15
  useEffect(() => subscribe(setState, selectDeps), []);
16
- return (typeof selectDeps === 'string' ? state[selectDeps] : state);
16
+ return state;
17
17
  };
18
18
  useStore.get = get;
19
19
  useStore.set = set;
@@ -29,7 +29,7 @@ export const createStore = (initializer, options = {}) => {
29
29
  set(value);
30
30
  });
31
31
  };
32
- const Watch = ({ selectDeps = defaultDeps, render, }) => {
32
+ const Watch = ({ selectDeps = defaultDeps, render }) => {
33
33
  const store = useStore(selectDeps);
34
34
  return render(store);
35
35
  };
@@ -1,49 +1,33 @@
1
- import { InitStoreOptions, InitStoreReturn, SelectDeps, SetStoreData, StoreData, Subscribers } from '../store';
2
1
  import { Maybe } from '../utils';
2
+ import { InitStoreOptions, InitStoreReturn, SelectDeps, SetStoreState, StoreState, Subscribers } from '../vanilla/init-store';
3
3
  import { WatchProps } from './create-store';
4
4
  export type StoreKey = Record<string, any> | undefined;
5
- export type StoresInitializer<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = T | ((api: {
5
+ export type StoresInitializer<TKey extends StoreKey = StoreKey, T extends StoreState = StoreState> = T | ((api: {
6
6
  get: () => T;
7
- set: (value: SetStoreData<T>, silent?: boolean) => void;
7
+ set: (value: SetStoreState<T>, silent?: boolean) => void;
8
8
  key: TKey;
9
9
  keyHash: string;
10
10
  }) => T);
11
- export type UseStores<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = {
11
+ export type UseStores<TKey extends StoreKey = StoreKey, T extends StoreState = StoreState> = {
12
12
  /**
13
13
  * @param key (Optional) Store key, an object that will be hashed into a string as a store identifier.
14
14
  * No need to memoize the store key.
15
15
  *
16
16
  * @param selectDeps (Optional) A function that return the dependency array (just like in `useEffect`), to trigger reactivity.
17
+ *
17
18
  * Defaults to `undefined` (reactive to all state change) if you didn't set `defaultDeps` on `createStores`.
18
19
  *
19
- * Since version `2.13.0`, we can use a store's object key to control reactivity.
20
+ * Value of `null` will also make it reactive to all state change.
20
21
  *
21
22
  * **IMPORTANT NOTE:** `selectDeps` must not be changed after initialization.
22
- *
23
- * @example
24
- * ```tsx
25
- * type StoreKey = { id: string };
26
- * type StoreData = { foo: number; bar: boolean; baz: string };
27
- * const useMyStores = createStores<StoreKey, StoreData>({
28
- * foo: 12,
29
- * bar: true,
30
- * baz: "z",
31
- * });
32
- *
33
- * export const MyComponent = () => {
34
- * const foo = useMyStores({ id: "p1" }, "foo");
35
- * // Will only re-render if "foo" & store key ("id") updated
36
- * };
37
- * ```
38
23
  */
39
- <K extends SelectDeps<T> | keyof T = SelectDeps<T>>(selectDeps?: K): K extends keyof T ? T[K] : T;
40
- <K extends SelectDeps<T> | keyof T = SelectDeps<T>>(key: Maybe<TKey>, selectDeps?: K): K extends keyof T ? T[K] : T;
24
+ (...args: [Maybe<TKey>, SelectDeps<T>?] | [SelectDeps<T>?]): T;
41
25
  get: (key?: Maybe<TKey>) => T;
42
26
  getAll: () => T[];
43
27
  getAllWithSubscriber: () => T[];
44
- set: (key: Maybe<TKey>, value: SetStoreData<T>, silent?: boolean) => void;
45
- setAll: (value: SetStoreData<T>, silent?: boolean) => void;
46
- subscribe: (key: Maybe<TKey>, fn: (state: T) => void, selectDeps?: SelectDeps<T> | keyof T) => () => void;
28
+ set: (key: Maybe<TKey>, value: SetStoreState<T>, silent?: boolean) => void;
29
+ setAll: (value: SetStoreState<T>, silent?: boolean) => void;
30
+ subscribe: (key: Maybe<TKey>, fn: (state: T) => void, selectDeps?: SelectDeps<T>) => () => void;
47
31
  getSubscribers: (key: Maybe<TKey>) => Subscribers<T>;
48
32
  getStore: (key?: Maybe<TKey>) => InitStoreReturn<T>;
49
33
  getStores: () => Map<string, InitStoreReturn<T>>;
@@ -56,12 +40,12 @@ export type UseStores<TKey extends StoreKey = StoreKey, T extends StoreData = St
56
40
  * - This is a hook, put it inside of a React component
57
41
  * - Put this on the root component or parent component, before any component subscribed!
58
42
  */
59
- setDefaultValues: (key: Maybe<TKey>, values: SetStoreData<T>) => void;
60
- Watch: <K extends SelectDeps<T> | keyof T = SelectDeps<T>>(props: WatchProps<T, K> & {
43
+ setDefaultValues: (key: Maybe<TKey>, values: SetStoreState<T>) => void;
44
+ Watch: (props: WatchProps<T> & {
61
45
  storeKey?: Maybe<TKey>;
62
46
  }) => any;
63
47
  };
64
- export type CreateStoresOptions<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = InitStoreOptions<T> & {
48
+ export type CreateStoresOptions<TKey extends StoreKey = StoreKey, T extends StoreState = StoreState> = InitStoreOptions<T> & {
65
49
  onBeforeChangeKey?: (nextKey: TKey, prevKey: TKey) => void;
66
50
  /**
67
51
  * Will be triggered when a single store with a specific key was initialized.
@@ -70,8 +54,8 @@ export type CreateStoresOptions<TKey extends StoreKey = StoreKey, T extends Stor
70
54
  defaultDeps?: SelectDeps<T>;
71
55
  hashKeyFn?: (obj: TKey) => string;
72
56
  };
73
- export declare const hashStoreKey: (value?: any) => string;
57
+ export declare const hashStoreKey: (obj?: any) => string;
74
58
  /**
75
59
  * @see https://floppy-disk.vercel.app/docs/api#createstores
76
60
  */
77
- export declare const createStores: <TKey extends StoreKey = StoreKey, T extends StoreData = StoreData>(initializer: StoresInitializer<TKey, T>, options?: CreateStoresOptions<TKey, T>) => UseStores<TKey, T>;
61
+ export declare const createStores: <TKey extends StoreKey = StoreKey, T extends StoreState = StoreState>(initializer: StoresInitializer<TKey, T>, options?: CreateStoresOptions<TKey, T>) => UseStores<TKey, T>;
@@ -1,32 +1,7 @@
1
1
  import { useEffect, useMemo, useRef, useState } from 'react';
2
- import { initStore, } from '../store';
3
2
  import { getValue, noop } from '../utils';
4
- const hasObjectPrototype = (value) => {
5
- return Object.prototype.toString.call(value) === '[object Object]';
6
- };
7
- const isPlainObject = (value) => {
8
- if (!hasObjectPrototype(value))
9
- return false;
10
- const ctor = value.constructor;
11
- if (typeof ctor === 'undefined')
12
- return true;
13
- const prot = ctor.prototype;
14
- if (!hasObjectPrototype(prot))
15
- return false;
16
- if (!prot.hasOwnProperty('isPrototypeOf'))
17
- return false;
18
- return true;
19
- };
20
- export const hashStoreKey = (value) =>
21
- // Copied from: https://github.com/TanStack/query/blob/main/packages/query-core/src/utils.ts
22
- JSON.stringify(value, (_, val) => isPlainObject(val)
23
- ? Object.keys(val)
24
- .sort()
25
- .reduce((result, key) => {
26
- result[key] = val[key];
27
- return result;
28
- }, {})
29
- : val);
3
+ import { initStore, } from '../vanilla/init-store';
4
+ export const hashStoreKey = (obj) => JSON.stringify(obj, Object.keys(obj).sort());
30
5
  /**
31
6
  * @see https://floppy-disk.vercel.app/docs/api#createstores
32
7
  */
@@ -46,7 +21,7 @@ export const createStores = (initializer, options = {}) => {
46
21
  * **IMPORTANT NOTE:** `selectDeps` function must not be changed after initialization.
47
22
  */
48
23
  const useStores = (...args) => {
49
- const [_key, selectDeps = defaultDeps] = (typeof args[0] === 'function' || typeof args[0] === 'string' ? [{}, args[0]] : args);
24
+ const [_key, selectDeps = defaultDeps] = (typeof args[0] === 'function' ? [{}, args[0]] : args);
50
25
  const key = _key || {};
51
26
  const keyHash = hashKeyFn(key);
52
27
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -63,8 +38,7 @@ export const createStores = (initializer, options = {}) => {
63
38
  }, [keyHash]);
64
39
  if (keyHash !== prevKeyHash.current)
65
40
  onBeforeChangeKey(key, prevKey.current);
66
- const state = get();
67
- return (typeof selectDeps === 'string' ? state[selectDeps] : state);
41
+ return get();
68
42
  };
69
43
  useStores.get = (key) => {
70
44
  const store = getStore(key);
@@ -1,4 +1,4 @@
1
- import { createError, getValue, identityFn } from './utils';
1
+ import { createError, getValue, identityFn } from '../utils';
2
2
  const encodeParams = (params) => Object.entries(params)
3
3
  .filter(([, value]) => value !== undefined && value !== null)
4
4
  .map((kv) => kv.map(encodeURIComponent).join('='))
@@ -1,11 +1,11 @@
1
- import { Maybe } from './utils';
2
- export type StoreData = Record<string, any>;
3
- export type SetStoreData<T> = Partial<T> | ((prevState: T) => Partial<T>);
1
+ import { Maybe } from '../utils';
2
+ export type StoreState = Record<string, any>;
3
+ export type SetStoreState<T> = Partial<T> | ((state: T) => Partial<T>);
4
4
  export type SelectDeps<T> = ((state: T) => any[]) | undefined | null;
5
5
  export type Subscribers<T> = Map<(state: T) => void, SelectDeps<T>>;
6
6
  export type StoreInitializer<T> = T | ((api: {
7
7
  get: () => T;
8
- set: (value: SetStoreData<T>, silent?: boolean) => void;
8
+ set: (value: SetStoreState<T>, silent?: boolean) => void;
9
9
  }) => T);
10
10
  export type StoreEvent<T> = (state: T) => void;
11
11
  export type InitStoreOptions<T> = {
@@ -17,8 +17,8 @@ export type InitStoreOptions<T> = {
17
17
  };
18
18
  export type InitStoreReturn<T> = {
19
19
  get: () => T;
20
- set: (value: SetStoreData<T>, silent?: boolean) => void;
21
- subscribe: (fn: (state: T) => void, selectDeps?: SelectDeps<T> | keyof T) => () => void;
20
+ set: (value: SetStoreState<T>, silent?: boolean) => void;
21
+ subscribe: (fn: (state: T) => void, selectDeps?: SelectDeps<T>) => () => void;
22
22
  getSubscribers: () => Subscribers<T>;
23
23
  };
24
- export declare const initStore: <T extends StoreData>(initializer: StoreInitializer<T>, options?: InitStoreOptions<T>) => InitStoreReturn<T>;
24
+ export declare const initStore: <T extends StoreState>(initializer: StoreInitializer<T>, options?: InitStoreOptions<T>) => InitStoreReturn<T>;
@@ -1,51 +1,51 @@
1
- import { getValue, noop } from './utils';
1
+ import { getValue, noop } from '../utils';
2
2
  export const initStore = (initializer, options = {}) => {
3
3
  const { intercept, onFirstSubscribe = noop, onSubscribe = noop, onUnsubscribe = noop, onLastUnsubscribe = noop, } = options;
4
4
  const subscribers = new Map();
5
5
  const getSubscribers = () => subscribers;
6
- let data;
7
- const get = () => data;
6
+ let state;
7
+ const get = () => state;
8
8
  const set = (value, silent = false) => {
9
- const prevData = data;
10
- data = { ...data, ...getValue(value, data) };
9
+ const prevState = state;
10
+ state = { ...state, ...getValue(value, state) };
11
11
  if (intercept) {
12
- data = { ...data, ...intercept(data, prevData) };
12
+ state = { ...state, ...intercept(state, prevState) };
13
13
  }
14
14
  if (silent)
15
15
  return;
16
- const keys = Object.keys(data);
16
+ const keys = Object.keys(state);
17
17
  subscribers.forEach((selectDeps, fn) => {
18
18
  if (!selectDeps) {
19
19
  for (let i = 0, n = keys.length; i < n; i++) {
20
- if (prevData[keys[i]] !== data[keys[i]]) {
21
- fn(data);
20
+ if (prevState[keys[i]] !== state[keys[i]]) {
21
+ fn(state);
22
22
  break;
23
23
  }
24
24
  }
25
25
  return;
26
26
  }
27
- const prevs = selectDeps(prevData);
28
- const nexts = selectDeps(data);
27
+ const prevs = selectDeps(prevState);
28
+ const nexts = selectDeps(state);
29
29
  for (let i = 0, n = prevs.length; i < n; i++) {
30
30
  if (prevs[i] !== nexts[i]) {
31
- fn(data);
31
+ fn(state);
32
32
  break;
33
33
  }
34
34
  }
35
35
  });
36
36
  };
37
37
  const subscribe = (fn, selectDeps) => {
38
- subscribers.set(fn, (typeof selectDeps === 'string' ? (s) => [s[selectDeps]] : selectDeps));
38
+ subscribers.set(fn, selectDeps);
39
39
  if (subscribers.size === 1)
40
- onFirstSubscribe(data);
41
- onSubscribe(data);
40
+ onFirstSubscribe(state);
41
+ onSubscribe(state);
42
42
  return () => {
43
43
  subscribers.delete(fn);
44
- onUnsubscribe(data);
44
+ onUnsubscribe(state);
45
45
  if (subscribers.size === 0)
46
- onLastUnsubscribe(data);
46
+ onLastUnsubscribe(state);
47
47
  };
48
48
  };
49
- data = getValue(initializer, { get, set });
49
+ state = getValue(initializer, { get, set });
50
50
  return { get, set, subscribe, getSubscribers };
51
51
  };
package/lib/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export * from './store';
2
- export * from './fetcher';
1
+ export * from './vanilla/init-store';
2
+ export * from './vanilla/fetcher';
3
3
  export * from './react/create-store';
4
4
  export * from './react/create-stores';
5
5
  export * from './react/create-query';
package/lib/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
- tslib_1.__exportStar(require("./store"), exports);
5
- tslib_1.__exportStar(require("./fetcher"), exports);
4
+ tslib_1.__exportStar(require("./vanilla/init-store"), exports);
5
+ tslib_1.__exportStar(require("./vanilla/fetcher"), exports);
6
6
  tslib_1.__exportStar(require("./react/create-store"), exports);
7
7
  tslib_1.__exportStar(require("./react/create-stores"), exports);
8
8
  tslib_1.__exportStar(require("./react/create-query"), exports);
@@ -6,7 +6,7 @@ export declare const createBiDirectionQuery: <TKey extends StoreKey = StoreKey,
6
6
  getNextPageParam: (lastPage: TResponse, index: number, stateBeforeCallQuery: QueryState<TKey, TResponse, TData, TError, TPageParam>) => Maybe<TPageParam>;
7
7
  select: (response: TResponse, state: Pick<QueryState<TKey, TResponse, TData, TError, TPageParam>, "data" | "key">, direction: 'prev' | 'next') => TData;
8
8
  }) => {
9
- (key: Maybe<TKey>, selectDeps?: "data" | "key" | "error" | "reset" | "status" | "fetch" | "response" | "keyHash" | "forceFetch" | "fetchNextPage" | "optimisticUpdate" | "isWaiting" | "isWaitingNextPage" | "isRefetching" | "isRefetchError" | "isPreviousData" | "isOptimisticData" | "errorUpdatedAt" | "retryCount" | "isGoingToRetry" | "pageParam" | "pageParams" | "hasNextPage" | "retryNextPageCount" | "isGoingToRetryNextPage" | "isLoading" | "isSuccess" | "isError" | "responseUpdatedAt" | import("..").SelectDeps<QueryState<TKey, TResponse, TData, TError, TPageParam>>): {
9
+ (...args: [Maybe<TKey>, import("..").SelectDeps<QueryState<TKey, TResponse, TData, TError, TPageParam>>?] | [import("..").SelectDeps<QueryState<TKey, TResponse, TData, TError, TPageParam>>?]): {
10
10
  data: (never[] | TData)[number][];
11
11
  fetchPrevPage: () => Promise<QueryState<TKey, TResponse, TData, TError, TPageParam>>;
12
12
  hasPrevPage: boolean;
@@ -1,4 +1,4 @@
1
- import { InitStoreOptions } from '../store';
1
+ import { InitStoreOptions } from '../vanilla/init-store';
2
2
  import { UseStore } from './create-store';
3
3
  export type MutationState<TVar, TResponse = any, TError = unknown> = {
4
4
  /**
@@ -1,35 +1,22 @@
1
- import { InitStoreOptions, SelectDeps, SetStoreData, StoreData, StoreInitializer, Subscribers } from '../store';
2
- export type WatchProps<T, K extends SelectDeps<T> | keyof T = SelectDeps<T>> = {
3
- selectDeps?: K;
4
- render: (state: K extends keyof T ? T[K] : T) => any;
1
+ import { InitStoreOptions, SelectDeps, SetStoreState, StoreInitializer, StoreState, Subscribers } from '../vanilla/init-store';
2
+ export type WatchProps<T> = {
3
+ selectDeps?: SelectDeps<T>;
4
+ render: (state: T) => any;
5
5
  };
6
- export type UseStore<T extends StoreData> = {
6
+ export type UseStore<T extends StoreState> = {
7
7
  /**
8
- * @param selectDeps (Optional) A function that return the dependency array (just like in `useEffect`), to trigger reactivity.
8
+ * @param selectDeps A function that return the dependency array (just like in `useEffect`), to trigger reactivity.
9
+ *
9
10
  * Defaults to `undefined` (reactive to all state change) if you didn't set `defaultDeps` on `createStore`.
10
11
  *
11
- * Since version `2.13.0`, we can use a store's object key to control reactivity.
12
+ * Value of `null` will also make it reactive to all state change.
12
13
  *
13
14
  * **IMPORTANT NOTE:** `selectDeps` must not be changed after initialization.
14
- *
15
- * @example
16
- * ```tsx
17
- * const useMyStore = createStore({
18
- * foo: 12,
19
- * bar: true,
20
- * baz: "z",
21
- * });
22
- *
23
- * const MyComponent = () => {
24
- * const foo = useMyStore("foo");
25
- * // Will only re-render if "foo" updated
26
- * };
27
- * ```
28
15
  */
29
- <K extends SelectDeps<T> | keyof T = SelectDeps<T>>(selectDeps?: K): K extends keyof T ? T[K] : T;
16
+ (selectDeps?: SelectDeps<T>): T;
30
17
  get: () => T;
31
- set: (value: SetStoreData<T>, silent?: boolean) => void;
32
- subscribe: (fn: (state: T) => void, selectDeps?: SelectDeps<T> | keyof T) => () => void;
18
+ set: (value: SetStoreState<T>, silent?: boolean) => void;
19
+ subscribe: (fn: (state: T) => void, selectDeps?: SelectDeps<T>) => () => void;
33
20
  getSubscribers: () => Subscribers<T>;
34
21
  /**
35
22
  * ⚛️ (**_Hook_**)
@@ -40,12 +27,12 @@ export type UseStore<T extends StoreData> = {
40
27
  * - This is a hook, put it inside of a React component
41
28
  * - Put this on the root component or parent component, before any component subscribed!
42
29
  */
43
- setDefaultValues: (values: SetStoreData<T>) => void;
44
- Watch: <K extends SelectDeps<T> | keyof T = SelectDeps<T>>(props: WatchProps<T, K>) => any;
30
+ setDefaultValues: (values: SetStoreState<T>) => void;
31
+ Watch: (props: WatchProps<T>) => any;
45
32
  };
46
33
  /**
47
34
  * @see https://floppy-disk.vercel.app/docs/api#createstore
48
35
  */
49
- export declare const createStore: <T extends StoreData>(initializer: StoreInitializer<T>, options?: InitStoreOptions<T> & {
36
+ export declare const createStore: <T extends StoreState>(initializer: StoreInitializer<T>, options?: InitStoreOptions<T> & {
50
37
  defaultDeps?: SelectDeps<T>;
51
38
  }) => UseStore<T>;
@@ -2,12 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createStore = void 0;
4
4
  const react_1 = require("react");
5
- const store_1 = require("../store");
5
+ const init_store_1 = require("../vanilla/init-store");
6
6
  /**
7
7
  * @see https://floppy-disk.vercel.app/docs/api#createstore
8
8
  */
9
9
  const createStore = (initializer, options = {}) => {
10
- const { get, set, subscribe, getSubscribers } = (0, store_1.initStore)(initializer, options);
10
+ const { get, set, subscribe, getSubscribers } = (0, init_store_1.initStore)(initializer, options);
11
11
  const { defaultDeps } = options;
12
12
  /**
13
13
  * **IMPORTANT NOTE:** `selectDeps` function must not be changed after initialization.
@@ -16,7 +16,7 @@ const createStore = (initializer, options = {}) => {
16
16
  const [state, setState] = (0, react_1.useState)(get);
17
17
  // eslint-disable-next-line react-hooks/exhaustive-deps
18
18
  (0, react_1.useEffect)(() => subscribe(setState, selectDeps), []);
19
- return (typeof selectDeps === 'string' ? state[selectDeps] : state);
19
+ return state;
20
20
  };
21
21
  useStore.get = get;
22
22
  useStore.set = set;
@@ -32,7 +32,7 @@ const createStore = (initializer, options = {}) => {
32
32
  set(value);
33
33
  });
34
34
  };
35
- const Watch = ({ selectDeps = defaultDeps, render, }) => {
35
+ const Watch = ({ selectDeps = defaultDeps, render }) => {
36
36
  const store = useStore(selectDeps);
37
37
  return render(store);
38
38
  };
@@ -1,49 +1,33 @@
1
- import { InitStoreOptions, InitStoreReturn, SelectDeps, SetStoreData, StoreData, Subscribers } from '../store';
2
1
  import { Maybe } from '../utils';
2
+ import { InitStoreOptions, InitStoreReturn, SelectDeps, SetStoreState, StoreState, Subscribers } from '../vanilla/init-store';
3
3
  import { WatchProps } from './create-store';
4
4
  export type StoreKey = Record<string, any> | undefined;
5
- export type StoresInitializer<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = T | ((api: {
5
+ export type StoresInitializer<TKey extends StoreKey = StoreKey, T extends StoreState = StoreState> = T | ((api: {
6
6
  get: () => T;
7
- set: (value: SetStoreData<T>, silent?: boolean) => void;
7
+ set: (value: SetStoreState<T>, silent?: boolean) => void;
8
8
  key: TKey;
9
9
  keyHash: string;
10
10
  }) => T);
11
- export type UseStores<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = {
11
+ export type UseStores<TKey extends StoreKey = StoreKey, T extends StoreState = StoreState> = {
12
12
  /**
13
13
  * @param key (Optional) Store key, an object that will be hashed into a string as a store identifier.
14
14
  * No need to memoize the store key.
15
15
  *
16
16
  * @param selectDeps (Optional) A function that return the dependency array (just like in `useEffect`), to trigger reactivity.
17
+ *
17
18
  * Defaults to `undefined` (reactive to all state change) if you didn't set `defaultDeps` on `createStores`.
18
19
  *
19
- * Since version `2.13.0`, we can use a store's object key to control reactivity.
20
+ * Value of `null` will also make it reactive to all state change.
20
21
  *
21
22
  * **IMPORTANT NOTE:** `selectDeps` must not be changed after initialization.
22
- *
23
- * @example
24
- * ```tsx
25
- * type StoreKey = { id: string };
26
- * type StoreData = { foo: number; bar: boolean; baz: string };
27
- * const useMyStores = createStores<StoreKey, StoreData>({
28
- * foo: 12,
29
- * bar: true,
30
- * baz: "z",
31
- * });
32
- *
33
- * export const MyComponent = () => {
34
- * const foo = useMyStores({ id: "p1" }, "foo");
35
- * // Will only re-render if "foo" & store key ("id") updated
36
- * };
37
- * ```
38
23
  */
39
- <K extends SelectDeps<T> | keyof T = SelectDeps<T>>(selectDeps?: K): K extends keyof T ? T[K] : T;
40
- <K extends SelectDeps<T> | keyof T = SelectDeps<T>>(key: Maybe<TKey>, selectDeps?: K): K extends keyof T ? T[K] : T;
24
+ (...args: [Maybe<TKey>, SelectDeps<T>?] | [SelectDeps<T>?]): T;
41
25
  get: (key?: Maybe<TKey>) => T;
42
26
  getAll: () => T[];
43
27
  getAllWithSubscriber: () => T[];
44
- set: (key: Maybe<TKey>, value: SetStoreData<T>, silent?: boolean) => void;
45
- setAll: (value: SetStoreData<T>, silent?: boolean) => void;
46
- subscribe: (key: Maybe<TKey>, fn: (state: T) => void, selectDeps?: SelectDeps<T> | keyof T) => () => void;
28
+ set: (key: Maybe<TKey>, value: SetStoreState<T>, silent?: boolean) => void;
29
+ setAll: (value: SetStoreState<T>, silent?: boolean) => void;
30
+ subscribe: (key: Maybe<TKey>, fn: (state: T) => void, selectDeps?: SelectDeps<T>) => () => void;
47
31
  getSubscribers: (key: Maybe<TKey>) => Subscribers<T>;
48
32
  getStore: (key?: Maybe<TKey>) => InitStoreReturn<T>;
49
33
  getStores: () => Map<string, InitStoreReturn<T>>;
@@ -56,12 +40,12 @@ export type UseStores<TKey extends StoreKey = StoreKey, T extends StoreData = St
56
40
  * - This is a hook, put it inside of a React component
57
41
  * - Put this on the root component or parent component, before any component subscribed!
58
42
  */
59
- setDefaultValues: (key: Maybe<TKey>, values: SetStoreData<T>) => void;
60
- Watch: <K extends SelectDeps<T> | keyof T = SelectDeps<T>>(props: WatchProps<T, K> & {
43
+ setDefaultValues: (key: Maybe<TKey>, values: SetStoreState<T>) => void;
44
+ Watch: (props: WatchProps<T> & {
61
45
  storeKey?: Maybe<TKey>;
62
46
  }) => any;
63
47
  };
64
- export type CreateStoresOptions<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = InitStoreOptions<T> & {
48
+ export type CreateStoresOptions<TKey extends StoreKey = StoreKey, T extends StoreState = StoreState> = InitStoreOptions<T> & {
65
49
  onBeforeChangeKey?: (nextKey: TKey, prevKey: TKey) => void;
66
50
  /**
67
51
  * Will be triggered when a single store with a specific key was initialized.
@@ -70,8 +54,8 @@ export type CreateStoresOptions<TKey extends StoreKey = StoreKey, T extends Stor
70
54
  defaultDeps?: SelectDeps<T>;
71
55
  hashKeyFn?: (obj: TKey) => string;
72
56
  };
73
- export declare const hashStoreKey: (value?: any) => string;
57
+ export declare const hashStoreKey: (obj?: any) => string;
74
58
  /**
75
59
  * @see https://floppy-disk.vercel.app/docs/api#createstores
76
60
  */
77
- export declare const createStores: <TKey extends StoreKey = StoreKey, T extends StoreData = StoreData>(initializer: StoresInitializer<TKey, T>, options?: CreateStoresOptions<TKey, T>) => UseStores<TKey, T>;
61
+ export declare const createStores: <TKey extends StoreKey = StoreKey, T extends StoreState = StoreState>(initializer: StoresInitializer<TKey, T>, options?: CreateStoresOptions<TKey, T>) => UseStores<TKey, T>;
@@ -2,34 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createStores = exports.hashStoreKey = void 0;
4
4
  const react_1 = require("react");
5
- const store_1 = require("../store");
6
5
  const utils_1 = require("../utils");
7
- const hasObjectPrototype = (value) => {
8
- return Object.prototype.toString.call(value) === '[object Object]';
9
- };
10
- const isPlainObject = (value) => {
11
- if (!hasObjectPrototype(value))
12
- return false;
13
- const ctor = value.constructor;
14
- if (typeof ctor === 'undefined')
15
- return true;
16
- const prot = ctor.prototype;
17
- if (!hasObjectPrototype(prot))
18
- return false;
19
- if (!prot.hasOwnProperty('isPrototypeOf'))
20
- return false;
21
- return true;
22
- };
23
- const hashStoreKey = (value) =>
24
- // Copied from: https://github.com/TanStack/query/blob/main/packages/query-core/src/utils.ts
25
- JSON.stringify(value, (_, val) => isPlainObject(val)
26
- ? Object.keys(val)
27
- .sort()
28
- .reduce((result, key) => {
29
- result[key] = val[key];
30
- return result;
31
- }, {})
32
- : val);
6
+ const init_store_1 = require("../vanilla/init-store");
7
+ const hashStoreKey = (obj) => JSON.stringify(obj, Object.keys(obj).sort());
33
8
  exports.hashStoreKey = hashStoreKey;
34
9
  /**
35
10
  * @see https://floppy-disk.vercel.app/docs/api#createstores
@@ -41,7 +16,7 @@ const createStores = (initializer, options = {}) => {
41
16
  const key = _key || {};
42
17
  const keyHash = hashKeyFn(key);
43
18
  if (!stores.has(keyHash)) {
44
- stores.set(keyHash, (0, store_1.initStore)((api) => (0, utils_1.getValue)(initializer, { key, keyHash, ...api }), options));
19
+ stores.set(keyHash, (0, init_store_1.initStore)((api) => (0, utils_1.getValue)(initializer, { key, keyHash, ...api }), options));
45
20
  onStoreInitialized(key, keyHash);
46
21
  }
47
22
  return stores.get(keyHash);
@@ -50,7 +25,7 @@ const createStores = (initializer, options = {}) => {
50
25
  * **IMPORTANT NOTE:** `selectDeps` function must not be changed after initialization.
51
26
  */
52
27
  const useStores = (...args) => {
53
- const [_key, selectDeps = defaultDeps] = (typeof args[0] === 'function' || typeof args[0] === 'string' ? [{}, args[0]] : args);
28
+ const [_key, selectDeps = defaultDeps] = (typeof args[0] === 'function' ? [{}, args[0]] : args);
54
29
  const key = _key || {};
55
30
  const keyHash = hashKeyFn(key);
56
31
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -67,8 +42,7 @@ const createStores = (initializer, options = {}) => {
67
42
  }, [keyHash]);
68
43
  if (keyHash !== prevKeyHash.current)
69
44
  onBeforeChangeKey(key, prevKey.current);
70
- const state = get();
71
- return (typeof selectDeps === 'string' ? state[selectDeps] : state);
45
+ return get();
72
46
  };
73
47
  useStores.get = (key) => {
74
48
  const store = getStore(key);
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.fetcher = void 0;
4
- const utils_1 = require("./utils");
4
+ const utils_1 = require("../utils");
5
5
  const encodeParams = (params) => Object.entries(params)
6
6
  .filter(([, value]) => value !== undefined && value !== null)
7
7
  .map((kv) => kv.map(encodeURIComponent).join('='))
@@ -1,11 +1,11 @@
1
- import { Maybe } from './utils';
2
- export type StoreData = Record<string, any>;
3
- export type SetStoreData<T> = Partial<T> | ((prevState: T) => Partial<T>);
1
+ import { Maybe } from '../utils';
2
+ export type StoreState = Record<string, any>;
3
+ export type SetStoreState<T> = Partial<T> | ((state: T) => Partial<T>);
4
4
  export type SelectDeps<T> = ((state: T) => any[]) | undefined | null;
5
5
  export type Subscribers<T> = Map<(state: T) => void, SelectDeps<T>>;
6
6
  export type StoreInitializer<T> = T | ((api: {
7
7
  get: () => T;
8
- set: (value: SetStoreData<T>, silent?: boolean) => void;
8
+ set: (value: SetStoreState<T>, silent?: boolean) => void;
9
9
  }) => T);
10
10
  export type StoreEvent<T> = (state: T) => void;
11
11
  export type InitStoreOptions<T> = {
@@ -17,8 +17,8 @@ export type InitStoreOptions<T> = {
17
17
  };
18
18
  export type InitStoreReturn<T> = {
19
19
  get: () => T;
20
- set: (value: SetStoreData<T>, silent?: boolean) => void;
21
- subscribe: (fn: (state: T) => void, selectDeps?: SelectDeps<T> | keyof T) => () => void;
20
+ set: (value: SetStoreState<T>, silent?: boolean) => void;
21
+ subscribe: (fn: (state: T) => void, selectDeps?: SelectDeps<T>) => () => void;
22
22
  getSubscribers: () => Subscribers<T>;
23
23
  };
24
- export declare const initStore: <T extends StoreData>(initializer: StoreInitializer<T>, options?: InitStoreOptions<T>) => InitStoreReturn<T>;
24
+ export declare const initStore: <T extends StoreState>(initializer: StoreInitializer<T>, options?: InitStoreOptions<T>) => InitStoreReturn<T>;
@@ -1,55 +1,55 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.initStore = void 0;
4
- const utils_1 = require("./utils");
4
+ const utils_1 = require("../utils");
5
5
  const initStore = (initializer, options = {}) => {
6
6
  const { intercept, onFirstSubscribe = utils_1.noop, onSubscribe = utils_1.noop, onUnsubscribe = utils_1.noop, onLastUnsubscribe = utils_1.noop, } = options;
7
7
  const subscribers = new Map();
8
8
  const getSubscribers = () => subscribers;
9
- let data;
10
- const get = () => data;
9
+ let state;
10
+ const get = () => state;
11
11
  const set = (value, silent = false) => {
12
- const prevData = data;
13
- data = { ...data, ...(0, utils_1.getValue)(value, data) };
12
+ const prevState = state;
13
+ state = { ...state, ...(0, utils_1.getValue)(value, state) };
14
14
  if (intercept) {
15
- data = { ...data, ...intercept(data, prevData) };
15
+ state = { ...state, ...intercept(state, prevState) };
16
16
  }
17
17
  if (silent)
18
18
  return;
19
- const keys = Object.keys(data);
19
+ const keys = Object.keys(state);
20
20
  subscribers.forEach((selectDeps, fn) => {
21
21
  if (!selectDeps) {
22
22
  for (let i = 0, n = keys.length; i < n; i++) {
23
- if (prevData[keys[i]] !== data[keys[i]]) {
24
- fn(data);
23
+ if (prevState[keys[i]] !== state[keys[i]]) {
24
+ fn(state);
25
25
  break;
26
26
  }
27
27
  }
28
28
  return;
29
29
  }
30
- const prevs = selectDeps(prevData);
31
- const nexts = selectDeps(data);
30
+ const prevs = selectDeps(prevState);
31
+ const nexts = selectDeps(state);
32
32
  for (let i = 0, n = prevs.length; i < n; i++) {
33
33
  if (prevs[i] !== nexts[i]) {
34
- fn(data);
34
+ fn(state);
35
35
  break;
36
36
  }
37
37
  }
38
38
  });
39
39
  };
40
40
  const subscribe = (fn, selectDeps) => {
41
- subscribers.set(fn, (typeof selectDeps === 'string' ? (s) => [s[selectDeps]] : selectDeps));
41
+ subscribers.set(fn, selectDeps);
42
42
  if (subscribers.size === 1)
43
- onFirstSubscribe(data);
44
- onSubscribe(data);
43
+ onFirstSubscribe(state);
44
+ onSubscribe(state);
45
45
  return () => {
46
46
  subscribers.delete(fn);
47
- onUnsubscribe(data);
47
+ onUnsubscribe(state);
48
48
  if (subscribers.size === 0)
49
- onLastUnsubscribe(data);
49
+ onLastUnsubscribe(state);
50
50
  };
51
51
  };
52
- data = (0, utils_1.getValue)(initializer, { get, set });
52
+ state = (0, utils_1.getValue)(initializer, { get, set });
53
53
  return { get, set, subscribe, getSubscribers };
54
54
  };
55
55
  exports.initStore = initStore;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "floppy-disk",
3
- "version": "2.16.0",
3
+ "version": "3.0.0-experimental.1",
4
4
  "description": "FloppyDisk - lightweight, simple, and powerful state management library",
5
5
  "keywords": [
6
6
  "state",
File without changes
File without changes