atomaric 0.0.60 → 0.0.61

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/package.json CHANGED
@@ -1,23 +1,21 @@
1
1
  {
2
2
  "name": "atomaric",
3
3
  "description": "Manage your project state",
4
- "version": "0.0.60",
4
+ "version": "0.0.61",
5
5
  "type": "module",
6
- "source": "./src/index.ts",
7
- "main": "./src/index.ts",
8
- "module": "./src/index.ts",
9
- "types": "./src/index.ts",
6
+ "main": "./build/atomaric.umd.cjs",
7
+ "module": "./build/atomaric.js",
8
+ "types": "./types/index.d.ts",
10
9
  "exports": {
11
10
  ".": {
12
- "types": "./src/index.ts",
13
- "import": "./src/index.ts",
14
- "default": "./src/index.ts"
11
+ "types": "./types/index.d.ts",
12
+ "require": "./build/atomaric.umd.cjs",
13
+ "import": "./build/atomaric.js"
15
14
  }
16
15
  },
17
16
  "files": [
18
17
  "build",
19
- "types",
20
- "src"
18
+ "types"
21
19
  ],
22
20
  "keywords": [
23
21
  "react",
package/src/class.ts DELETED
@@ -1,295 +0,0 @@
1
- import {
2
- AtomOptions,
3
- AtomSetDeferredMethod,
4
- AtomSetMethod,
5
- AtomStoreKey,
6
- AtomSubscribeMethod,
7
- Atom as AtomType,
8
- DefaultActions,
9
- } from '../types';
10
- import { makeDoFillerActions } from './makeDoFillerActions';
11
-
12
- type Subscriber<Value> = (value: Value) => void;
13
-
14
- type Tools = { exp?: number };
15
-
16
- export class Atom<Value, Actions extends Record<string, Function> = {}> implements AtomType<Value, Actions> {
17
- get;
18
- set: AtomSetMethod<Value>;
19
- setDeferred: AtomSetDeferredMethod<Value>;
20
- reset: () => void;
21
- subscribe: AtomSubscribeMethod<Value>;
22
- initialValue;
23
- isInitialValue;
24
- do!: Actions & DefaultActions<Value>;
25
-
26
- constructor(initialValue: Value, storeKeyOrOptions: AtomStoreKey | AtomOptions<Value, Actions> | undefined) {
27
- const updateCurrentValue = (value: Value) => (______current_value_____ = value);
28
- const getCurrentValue = () => ______current_value_____;
29
- const subscribers = new Set<Subscriber<Value>>();
30
- const invokeSubscriber = (sub: Subscriber<Value>) => sub(get());
31
-
32
- let isQueueWait = true;
33
- let lastIsPreventSave = false as boolean | nil;
34
-
35
- let ______current_value_____ = initialValue;
36
- let debounceTimeout: ReturnType<typeof setTimeout> | number | undefined;
37
- let save: (val: Value) => void = () => {};
38
- let get = () => getCurrentValue();
39
- let tools: Tools | null | undefined = null;
40
-
41
- let doFiller = () => {
42
- const doActions = makeDoFillerActions<Value, Actions>(initialValue, proxiedSelf, storeKeyOrOptions);
43
- doFiller = () => doActions;
44
- return doActions;
45
- };
46
-
47
- const proxiedSelf = new Proxy(this, {
48
- get: (self, prop) => (prop === 'do' ? doFiller() : self[prop as 'do']),
49
- set: retFalse,
50
- });
51
-
52
- const promiseResolver = () => {
53
- isQueueWait = true;
54
- if (lastIsPreventSave !== true) save(get());
55
- lastIsPreventSave = false;
56
-
57
- try {
58
- updateHere.postMessage({ key, value: getCurrentValue() });
59
- } catch (e) {}
60
- };
61
-
62
- const set: typeof this.set = (value, isPreventSave) => {
63
- const nextValue = typeof value === 'function' ? (value as (value: Value) => Value)(get()) : value;
64
-
65
- if (nextValue === get()) return;
66
-
67
- updateCurrentValue(nextValue);
68
- lastIsPreventSave = isPreventSave;
69
-
70
- if (isQueueWait) {
71
- isQueueWait = false;
72
- subscribers.forEach(invokeSubscriber);
73
-
74
- queueMicrotask(promiseResolver);
75
- }
76
- };
77
-
78
- this.set = (value, isPreventSave) => set(value, isPreventSave);
79
- this.get = () => get();
80
- this.initialValue = initialValue;
81
- this.isInitialValue = () => initialValue === getCurrentValue();
82
-
83
- this.subscribe = sub => {
84
- subscribers.add(sub);
85
- return () => {
86
- subscribers.delete(sub);
87
- };
88
- };
89
-
90
- this.reset = () => {
91
- set(initialValue, true);
92
- };
93
-
94
- const deferredTimeOut = (value: Value, isPreventSave: boolean) => {
95
- set(value, isPreventSave);
96
- debounceTimeout = undefined;
97
- };
98
-
99
- this.setDeferred = (value, debounceMs = 500, isPreventSave, isInitInvoke = true) => {
100
- if (isInitInvoke && debounceTimeout === undefined) set(value, isPreventSave);
101
- clearTimeout(debounceTimeout);
102
- debounceTimeout = setTimeout(deferredTimeOut, debounceMs, value, isPreventSave);
103
- };
104
-
105
- if (storeKeyOrOptions == null) return proxiedSelf;
106
-
107
- ////////////////////////
108
- //////////////////////// storaged value
109
- ////////////////////////
110
-
111
- let storeKey = null;
112
- let exp = null;
113
- let warnOnDuplicateStoreKey = true;
114
- let listenStorageChanges = true;
115
- let isUnchangable = false;
116
- let expTimeout = -1 as never as ReturnType<typeof setTimeout>;
117
-
118
- let unzipValue: AtomOptions<Value, Actions>['unzipValue'] =
119
- initialValue instanceof Set ? strValue => new Set(strValue) : val => val;
120
-
121
- let zipValue: AtomOptions<Value, Actions>['zipValue'] =
122
- initialValue instanceof Set
123
- ? val => {
124
- if (val instanceof Set) return Array.from(val);
125
-
126
- console.error(val);
127
- throw 'The value is not Set instance';
128
- }
129
- : val => val;
130
-
131
- if (typeof storeKeyOrOptions === 'string') {
132
- storeKey = storeKeyOrOptions;
133
- } else if ('storeKey' in storeKeyOrOptions) {
134
- warnOnDuplicateStoreKey = storeKeyOrOptions.warnOnDuplicateStoreKey ?? warnOnDuplicateStoreKey;
135
- listenStorageChanges = storeKeyOrOptions.listenStorageChanges ?? listenStorageChanges;
136
- storeKey = storeKeyOrOptions.storeKey;
137
-
138
- unzipValue = storeKeyOrOptions.unzipValue ?? unzipValue;
139
- zipValue = storeKeyOrOptions.zipValue ?? zipValue;
140
- isUnchangable = storeKeyOrOptions.unchangable ?? isUnchangable;
141
- exp = storeKeyOrOptions.exp ?? exp;
142
- } else return proxiedSelf;
143
-
144
- const key = `${prefix}${storeKey}`;
145
- const stringifyValue =
146
- exp === null || !(exp(proxiedSelf, key in localStorage) instanceof Date)
147
- ? (value: Value) => JSON.stringify([zipValue(value)])
148
- : (value: Value) => {
149
- tools ??= {};
150
- tools.exp = exp(proxiedSelf, key in localStorage).getTime();
151
-
152
- if (tools.exp - Date.now() < 24 * 60 * 60 * 1000) {
153
- clearTimeout(expTimeout);
154
- clearTimeout(initResetTimeouts[key]);
155
- expTimeout = setTimeout(() => this.reset(), tools.exp - Date.now());
156
- }
157
-
158
- tools.exp = Math.trunc(tools.exp / 1000);
159
-
160
- return JSON.stringify([zipValue(value), tools]);
161
- };
162
-
163
- const parseValue = (value: string): Value => {
164
- const val = JSON.parse(value);
165
- tools = val[1];
166
-
167
- return unzipValue(val[0]);
168
- };
169
-
170
- let isInactualValue = true;
171
- registeredAtoms[key] = proxiedSelf;
172
-
173
- if (localStorage[`atom/${storeKey}`]) {
174
- localStorage[key] ||= `[${localStorage[`atom/${storeKey}`]}]`;
175
- delete localStorage[`atom/${storeKey}`];
176
- }
177
-
178
- get = () => {
179
- get = getCurrentValue;
180
-
181
- if (isInactualValue) {
182
- isInactualValue = false;
183
- try {
184
- updateCurrentValue(key in localStorage ? parseValue(localStorage[key]) : initialValue);
185
- } catch (e) {
186
- console.warn('Invalid json value', localStorage[key]);
187
- }
188
- }
189
-
190
- return getCurrentValue();
191
- };
192
-
193
- save = value => {
194
- if (value === initialValue) {
195
- this.reset();
196
- return;
197
- }
198
- localStorage[key] = stringifyValue(value);
199
- };
200
-
201
- this.reset = () => {
202
- delete localStorage[key];
203
- set(initialValue, true);
204
- };
205
-
206
- if (warnOnDuplicateStoreKey && update[key] !== undefined) console.warn('Duplicate Atom key', storeKey);
207
-
208
- if (listenStorageChanges) {
209
- if (isUnchangable) {
210
- let isCantChange = false;
211
- let timeout: ReturnType<typeof setTimeout>;
212
-
213
- unchangableAtoms[key] = this as never;
214
- update[key] = () => {
215
- clearTimeout(timeout);
216
- timeout = setTimeout(() => (isCantChange = false), 10);
217
-
218
- if (isCantChange) return;
219
- isCantChange = true;
220
-
221
- localStorage[key] = stringifyValue(getCurrentValue());
222
- };
223
- } else
224
- update[key] = event => {
225
- if (event.newValue === null) {
226
- this.reset();
227
- return;
228
- }
229
-
230
- try {
231
- set(parseValue(event.newValue));
232
- } catch (_e) {
233
- console.warn('Invalid json value', event.newValue);
234
- }
235
- };
236
- }
237
-
238
- return proxiedSelf;
239
- }
240
- }
241
-
242
- let updateHere: BroadcastChannel;
243
- try {
244
- updateHere = new BroadcastChannel('updateHere');
245
- updateHere.addEventListener('message', event => {
246
- unchangableAtoms[event.data.key]?.set(event.data.value, true);
247
- });
248
- } catch (e) {}
249
-
250
- const localStorage = window.localStorage;
251
- const update: Partial<Record<string, (event: StorageEvent) => void>> = {};
252
- const unchangableAtoms: Partial<Record<string, Atom<unknown>>> = {};
253
- const retFalse = (_self: any, prop: string) => {
254
- throw `${prop} is readonly property`;
255
- };
256
-
257
- window.addEventListener('storage', event => {
258
- if (event.key === null || event.newValue === event.oldValue) return;
259
- update[event.key]?.(event);
260
- });
261
-
262
- const setItem = localStorage.setItem.bind(localStorage);
263
- const removeItem = localStorage.removeItem.bind(localStorage);
264
-
265
- localStorage.setItem = (key, value) => {
266
- if (unchangableAtoms[key] !== undefined) return;
267
- setItem.call(localStorage, key, value);
268
- };
269
- localStorage.removeItem = key => {
270
- if (unchangableAtoms[key] !== undefined) return;
271
- removeItem.call(localStorage, key);
272
- };
273
- const expMatcherReg = /"exp":\s*(\d+)/;
274
- const prefix = `atom\\`;
275
- const registeredAtoms: Record<string, Atom<any>> = {};
276
- const initResetTimeouts: Record<string, ReturnType<typeof setTimeout>> = {};
277
-
278
- setTimeout(() => {
279
- Object.keys(localStorage).forEach(key => {
280
- if (!key.startsWith(prefix) || typeof localStorage[key] !== 'string') return;
281
- const secTs = +localStorage[key].match(expMatcherReg)?.[1]!;
282
-
283
- if (!secTs || secTs * 1000 - Date.now() > 24 * 60 * 60 * 1000) return;
284
-
285
- const jsonValue = JSON.parse(localStorage[key]);
286
-
287
- if (!Array.isArray(jsonValue) || jsonValue[1] == null || !('exp' in jsonValue[1]) || jsonValue[1].exp !== secTs)
288
- return;
289
-
290
- initResetTimeouts[key] = setTimeout(() => {
291
- if (registeredAtoms[key]) registeredAtoms[key].reset();
292
- else delete localStorage[key];
293
- }, secTs * 1000 - Date.now());
294
- });
295
- }, 1000);
package/src/globals.d.ts DELETED
@@ -1,52 +0,0 @@
1
- import { knownStameskaIconNames } from 'shared/values/index/known-icons';
2
-
3
- enum NotANumber {
4
- nan = 'NaN',
5
- }
6
-
7
- declare global {
8
- type num = 0 | 1;
9
- type str = '' | '1';
10
- type nil = null | undefined;
11
- type und = undefined;
12
- type TimeOut = ReturnType<typeof setTimeout> | und | number;
13
- type intStr = `${'-' | ''}${number}`;
14
- type doubleStr = `${'-' | ''}${intStr}.${number}`;
15
- type numberStr = `${'-' | ''}${intStr}${`.${number}` | ''}`;
16
- type StringBySlash = `${string}/${string}`;
17
- type func = (arg: unknown, ...args: unknown[]) => unknown | void;
18
-
19
- type KRecord<Key extends string | number, Value> = (Record<`${Key}`, Value> | Record<Key, Value>) &
20
- Record<`${Key}` | Key, Value>;
21
- type PRecord<Key extends string | number, Value> = Partial<KRecord<Key, Value>>;
22
-
23
- /** Record with <Required key, Partial key, Value> */
24
- type RPRecord<ReqiredKey extends string | number, Key extends string | number, Value> = KRecord<ReqiredKey, Value> &
25
- Partial<KRecord<Exclude<Key, ReqiredKey>, Value>>;
26
-
27
- type RKey<Key extends number> = Key | `${Key}`;
28
-
29
- type OmitOwn<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
30
- type WithRewrites<T, P> = Pick<T, Exclude<keyof T, keyof P>> & Pick<P, keyof P>;
31
-
32
- type NaN = NotANumber;
33
- type NaNumber = number | NotANumber;
34
- type FalsyValue = false | '' | 0 | nil;
35
-
36
- type PropagationStopperEvent = { stopPropagation(): void };
37
- type PropagationStopper = (event: PropagationStopperEvent) => void;
38
-
39
- type DefaultPreventerEvent = { preventDefault(): void };
40
- type DefaultPreventer = (event: DefaultPreventerEvent) => void;
41
-
42
- type PreventerAndStopperCallback = (event: DefaultPreventerEvent & PropagationStopperEvent) => void;
43
-
44
- type NonUndefined<T> = T extends undefined ? never : T;
45
- type NonNull<T> = T extends null ? never : T;
46
- type NonNil<T> = T extends nil ? never : T;
47
-
48
- type Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never };
49
- type XOR<T, U> = (Without<T, U> & U) | (Without<U, T> & T);
50
-
51
- type KnownStameskaIconName = keyof typeof knownStameskaIconNames;
52
- }
package/src/index.ts DELETED
@@ -1,2 +0,0 @@
1
- export * from './class';
2
- export * from './lib';
package/src/lib.ts DELETED
@@ -1,36 +0,0 @@
1
- import { useSyncExternalStore } from 'react';
2
- import {
3
- atom as atomType,
4
- configureAtomaric as configureAtomaricType,
5
- useAtomDo as useAtomDoType,
6
- useAtomGet as useAtomGetType,
7
- useAtomSetDeferred as useAtomSetDeferredType,
8
- useAtomSet as useAtomSetType,
9
- useAtom as useAtomType,
10
- useAtomValue as useAtomValueType,
11
- } from '../types';
12
- import { Atom } from './class';
13
-
14
- let useSyncExtStore = (() => {
15
- throw 'call configureAtomaric() before all!';
16
- }) as typeof useSyncExternalStore;
17
-
18
- export const configuredOptions: Partial<Parameters<typeof configureAtomaricType>[0]> = {};
19
-
20
- export const configureAtomaric: typeof configureAtomaricType = options => {
21
- configuredOptions.useSyncExternalStore = useSyncExtStore = options.useSyncExternalStore;
22
- configuredOptions.keyPathSeparator = options.keyPathSeparator;
23
- };
24
-
25
- export const useAtomValue: typeof useAtomValueType = atom => {
26
- return useSyncExtStore(atom.subscribe, atom.get);
27
- };
28
-
29
- export const useAtomSet: typeof useAtomSetType = atom => atom.set;
30
- export const useAtomSetDeferred: typeof useAtomSetDeferredType = atom => atom.setDeferred;
31
- export const useAtomGet: typeof useAtomGetType = atom => atom.get;
32
- export const useAtomDo: typeof useAtomDoType = atom => atom.do;
33
-
34
- export const useAtom: typeof useAtomType = atom => [useAtomValue(atom), useAtomSet(atom)];
35
-
36
- export const atom: typeof atomType = (value, storeKeyOrOptions) => new Atom(value, storeKeyOrOptions);
@@ -1,35 +0,0 @@
1
- export const makeDeepProxyObject = <T extends object>(
2
- target: T,
3
- handler: ProxyHandler<T> & {
4
- onSet: <I extends object>(
5
- target: I,
6
- path: (string | number)[],
7
- setKey: number | string,
8
- value: unknown,
9
- prevValue: unknown,
10
- ) => boolean;
11
- },
12
- ) => {
13
- const proxer = <I extends object>(target: I, keys: (number | string)[], level: number) =>
14
- new Proxy(target, {
15
- get: (target, key, reciever) => {
16
- const value =
17
- level === 0 && handler.get != null ? handler.get(target as never, key, reciever) : target[key as never];
18
-
19
- return typeof value === 'object' && value !== null
20
- ? proxer(
21
- Array.isArray(value) ? value.slice(0) : { ...value },
22
- keys.concat(Array.isArray(target) ? +(key as never) : (key as never)),
23
- level + 1,
24
- )
25
- : value;
26
- },
27
- set: (target, key, value) => {
28
- if (!handler.onSet(target, keys, key as never, value, target[key as never])) return true;
29
- target[key as never] = value as never;
30
- return true;
31
- },
32
- });
33
-
34
- return proxer(target, [], 0);
35
- };
@@ -1,225 +0,0 @@
1
- import { AtomOptions, AtomStoreKey, DefaultActions } from '../types';
2
- import { Atom } from './class';
3
- import { configuredOptions } from './lib';
4
- import { makeDeepProxyObject } from './makeDeepProxyObject';
5
-
6
- type nil = null | undefined;
7
-
8
- export const makeDoFillerActions = <Value, Actions extends Record<string, Function>>(
9
- initialValue: Value,
10
- atom: Atom<Value, Actions>,
11
- storeKeyOrOptions: AtomStoreKey | AtomOptions<Value, Actions> | undefined,
12
- ) => {
13
- let defaultActions: DefaultActions<any> | null = null;
14
-
15
- if (typeof initialValue === 'number') {
16
- defaultActions = fillActions<number>(
17
- atom as never,
18
- atom => ({
19
- increment: delta => {
20
- atom.set(+atom.get() + (delta ?? 0));
21
- },
22
- }),
23
- initialValue,
24
- );
25
- } else if (typeof initialValue === 'boolean') {
26
- defaultActions = fillActions<boolean>(
27
- atom as never,
28
- atom => ({
29
- toggle: () => {
30
- atom.set(!atom.get());
31
- },
32
- }),
33
- initialValue,
34
- );
35
- } else if (Array.isArray(initialValue)) {
36
- defaultActions = fillActions<any[]>(
37
- atom as never,
38
- atom => ({
39
- push: (...values) => {
40
- atom.set(atom.get().concat(values));
41
- },
42
- unshift: (...values) => {
43
- atom.set(values.concat(atom.get()));
44
- },
45
- update: updater => {
46
- const prev = atom.get();
47
- const newValue = updateValue(prev, updater);
48
- if (newValue === prev) return;
49
- atom.set(newValue);
50
- },
51
- filter: filter => {
52
- atom.set(atom.get().filter(filter ?? itIt));
53
- },
54
- add: value => {
55
- if (atom.get().includes(value)) return;
56
- atom.set(atom.get().concat([value]));
57
- },
58
- remove: value => {
59
- const index = atom.get().indexOf(value);
60
- if (index < 0) return;
61
- const newArray = atom.get().slice(0);
62
- newArray.splice(index, 1);
63
- atom.set(newArray);
64
- },
65
- toggle: (value, isAddInStart) => {
66
- const newArray = atom.get().slice();
67
- const index = newArray.indexOf(value);
68
- if (index < 0) {
69
- if (isAddInStart) newArray.unshift(value);
70
- else newArray.push(value);
71
- } else newArray.splice(index, 1);
72
- atom.set(newArray);
73
- },
74
- }),
75
- initialValue,
76
- );
77
- } else if (initialValue instanceof Set) {
78
- defaultActions = fillActions<Set<any>>(
79
- atom as never,
80
- atom => ({
81
- add: value => {
82
- atom.set(new Set(atom.get()).add(value));
83
- },
84
- delete: value => {
85
- const newSet = new Set(atom.get());
86
- newSet.delete(value);
87
- atom.set(newSet);
88
- },
89
- toggle: value => {
90
- const newSet = new Set(atom.get());
91
-
92
- if (newSet.has(value)) newSet.delete(value);
93
- else newSet.add(value);
94
-
95
- atom.set(newSet);
96
- },
97
- clear: () => {
98
- atom.set(new Set());
99
- },
100
- }),
101
- initialValue,
102
- );
103
- } else if (initialValue instanceof Object) {
104
- const keyPathSeparator = configuredOptions.keyPathSeparator || '.';
105
-
106
- defaultActions = fillActions<object>(
107
- atom as never,
108
- atom => ({
109
- setPartial: value =>
110
- atom.set(prev => ({
111
- ...prev,
112
- ...(typeof value === 'function' ? value(atom.get()) : value),
113
- })),
114
- update: updater => {
115
- const prev = atom.get();
116
- const newValue = updateValue(prev, updater);
117
- if (newValue === prev) return;
118
- atom.set(newValue);
119
- },
120
- setDeepPartial: (path: string, value: any, donor, separator = keyPathSeparator as never) => {
121
- if (!separator) return;
122
-
123
- if (path.includes(separator)) {
124
- let keys = path.split(separator);
125
- const lastKey = keys[keys.length - 1];
126
- keys = keys.slice(0, -1);
127
- const newObject = { ...atom.get() };
128
- let lastObject: Record<string, unknown> = newObject;
129
- let lastDonorObject = donor as Record<string, unknown> | nil;
130
-
131
- for (const key of keys) {
132
- lastDonorObject = lastDonorObject?.[Array.isArray(lastDonorObject) ? '0' : key] as never;
133
- const currentObject = lastObject[makeKey(lastObject, key)] ?? (Array.isArray(lastDonorObject) ? [] : {});
134
-
135
- if (currentObject == null || typeof currentObject !== 'object') {
136
- if (donor == null) throw 'Incorrect path for setDeepPartial';
137
-
138
- const newValue = typeof value === 'function' ? value(undefined) : value;
139
-
140
- if (atom.get()[path as never] !== newValue) atom.do.setPartial({ [path]: newValue });
141
- return;
142
- }
143
-
144
- lastObject = lastObject[makeKey(lastObject, key)] = (
145
- Array.isArray(currentObject) ? [...currentObject] : { ...currentObject }
146
- ) as never;
147
- }
148
-
149
- const prev = lastObject[lastKey];
150
- lastObject[lastKey] = typeof value === 'function' ? value(lastObject[lastKey]) : value;
151
-
152
- if (prev !== lastObject[lastKey]) atom.set(newObject);
153
-
154
- return;
155
- }
156
-
157
- const prevValue = atom.get()[path as never];
158
- const newValue = typeof value === 'function' ? value(prevValue) : value;
159
- if (newValue !== prevValue) atom.do.setPartial({ [path]: newValue });
160
- },
161
- }),
162
- initialValue,
163
- );
164
- }
165
-
166
- const actions =
167
- typeof storeKeyOrOptions === 'object' && storeKeyOrOptions != null && 'do' in storeKeyOrOptions
168
- ? storeKeyOrOptions.do(
169
- (value, isPreventSave) => atom.set(value, isPreventSave),
170
- () => atom.get(),
171
- atom,
172
- (value, debounceMs, isPreventSave) => atom.setDeferred(value, debounceMs, isPreventSave),
173
- )
174
- : null;
175
-
176
- const doActions = {};
177
-
178
- if (actions) Object.keys(actions).forEach(key => Object.defineProperty(doActions, key, { get: () => actions[key] }));
179
-
180
- if (defaultActions)
181
- Object.keys(defaultActions).forEach(key =>
182
- Object.defineProperty(doActions, key, { get: () => defaultActions[key as never] }),
183
- );
184
-
185
- return doActions;
186
- };
187
-
188
- const itIt = <It>(it: It) => it;
189
- const fillActions = <Value, ValAtom extends Atom<Value> = Atom<Value>>(
190
- atom: ValAtom,
191
- actions: (atom: ValAtom) => DefaultActions<Value>,
192
- _value: Value,
193
- ) => actions(atom);
194
-
195
- const updateValue = <Object extends object | unknown[]>(object: Object, updater: (object: Object) => void): Object => {
196
- const newObject = Array.isArray(object) ? object.slice(0) : { ...object };
197
- let isSomeSetted = false;
198
-
199
- const pro = makeDeepProxyObject(object, {
200
- onSet: (_, keys, setKey, value, prevValue) => {
201
- if (value === prevValue) return true;
202
- let currentObject = newObject as Record<string, unknown> | unknown[];
203
-
204
- isSomeSetted = true;
205
-
206
- for (const key of keys) {
207
- const nextObject = currentObject[key as never] as object;
208
-
209
- currentObject = currentObject[key as never] = (
210
- Array.isArray(nextObject) ? nextObject.slice(0) : { ...nextObject }
211
- ) as never;
212
- }
213
-
214
- currentObject[setKey as never] = value as never;
215
-
216
- return true;
217
- },
218
- });
219
-
220
- updater(pro);
221
-
222
- return isSomeSetted ? (newObject as never) : object;
223
- };
224
-
225
- const makeKey = (obj: object, key: string) => (Array.isArray(obj) ? `${+key}` : key);
package/src/test.tsx DELETED
@@ -1,207 +0,0 @@
1
- import React, { useEffect, useSyncExternalStore } from 'react';
2
- import { createRoot } from 'react-dom/client';
3
- import { atom, configureAtomaric, useAtomDo, useAtomValue } from './lib';
4
-
5
- configureAtomaric({ useSyncExternalStore, keyPathSeparator: '.' });
6
-
7
- createRoot(document.getElementById('root')!).render(
8
- <React.StrictMode>
9
- <App />
10
- </React.StrictMode>,
11
- );
12
-
13
- const testAtom = atom(new Set<number>(), {
14
- storeKey: 'test:set',
15
- do: set => ({
16
- update12: () => set(prev => new Set(prev).add(12)),
17
- }),
18
- });
19
-
20
- const testTextAtom = atom('', {
21
- storeKey: 'test:text',
22
- unchangable: true,
23
- exp: () => new Date(Date.now() + 3 * 1000),
24
-
25
- zipValue: value => ({ value }),
26
- unzipValue: val => val.value,
27
-
28
- do: set => ({
29
- addText: (text: string) => {
30
- set(prev => prev + text);
31
- },
32
- }),
33
- });
34
-
35
- const array: (number | '')[] = [3, 1, 7, 4, 8, 9, 5];
36
- const arrayAtom = atom(array, {
37
- do: () => ({
38
- nothing: () => {},
39
- }),
40
- });
41
-
42
- console.info(Object.keys(arrayAtom));
43
- // arrayAtom.do.filter = {};
44
-
45
- console.info(arrayAtom);
46
- arrayAtom.do.push(0);
47
- arrayAtom.do.nothing();
48
- console.info(arrayAtom.get());
49
- arrayAtom.do.unshift(-1);
50
- console.info(arrayAtom.get());
51
- arrayAtom.do.update(arr => arr.sort());
52
- console.info(arrayAtom.get());
53
- arrayAtom.do.filter();
54
- console.info(arrayAtom.get());
55
-
56
- atom(0, 'a:a');
57
- atom(0, { storeKey: 'a:a' });
58
- atom(0, { storeKey: 'a:a', warnOnDuplicateStoreKey: false });
59
-
60
- (function testDeepPartialChanges() {
61
- const b = { c: [{ d: 8, e: 'e', f: 'F' }] };
62
- const a = { f: { g: '' }, b };
63
- const deepTest = atom({ a, b });
64
-
65
- deepTest.do.setDeepPartial('b.c.0.d', 123, { b: { c: [{}] } });
66
- deepTest.do.setDeepPartial('b+c+8+e', 'EE', null, '+');
67
-
68
- console.info(deepTest.get(), deepTest.get().a.f === a.f, deepTest.get().b.c === b.c);
69
- })();
70
-
71
- (function testDeepPartialChanges() {
72
- const enum Id {
73
- def = 0,
74
- }
75
-
76
- const deepTest = atom(
77
- {} as Record<
78
- Id,
79
- {
80
- in: { inin: [{ ininin: number }] }[];
81
- out: { some: { req: 0 } };
82
- else: { if: {} };
83
- }
84
- >,
85
- );
86
-
87
- deepTest.do.setDeepPartial(`${Id.def}.in.${9}.inin.0`, { ininin: 9 }, { [Id.def]: { in: [{ inin: [] }] } });
88
- console.info('Id.def', deepTest.get());
89
-
90
- deepTest.do.setDeepPartial(`${Id.def}+in+ 4 +inin+0+ininin`, () => 7, { [Id.def]: { in: [{ inin: [{}] }] } }, '+');
91
- console.info('Id.def', deepTest.get());
92
-
93
- // will throw
94
- // console.error(deepTest.get()[Id.def]?.out.some.req);
95
- })();
96
-
97
- (function testDeepPartialSetWithDonor() {
98
- const a: {
99
- val: {
100
- b?: { c?: { f: { g?: { e: string } }[] }[] };
101
- f: { l: number; g?: number };
102
- };
103
- } = { val: { f: { l: 9 } } };
104
-
105
- const deepTest = atom(a);
106
-
107
- deepTest.do.setDeepPartial('val.b.c.4.f', [{ g: { e: '^' } }], { val: { b: { c: [{}] } } });
108
- deepTest.do.setDeepPartial('val.b.c.4.f.5.g', { e: '!!@' }, { val: { b: { c: [{ f: [{}] }] } } });
109
- deepTest.do.setDeepPartial('val.b.c.4.f.2', { g: { e: '2' } }, { val: { b: { c: [{ f: [] }] } } });
110
- deepTest.do.setDeepPartial('val.b.c.4.f.5.g.e', 'FIVE', { val: { b: { c: [{ f: [{ g: {} }] }] } } });
111
- deepTest.do.setDeepPartial('val.f.l', 123, { val: { f: {} } });
112
-
113
- deepTest.do.setDeepPartial('val***f***g', 777, { val: { f: {} } }, '***');
114
-
115
- console.info(deepTest.get());
116
- })();
117
-
118
- (function testUpdate() {
119
- const a: {
120
- val: {
121
- b: { c: { f: { g: { e: string } }[] }[] };
122
- };
123
- f: { l: { v: { r: number } }; g?: number };
124
- num: number;
125
- } = {
126
- val: { b: { c: [{ f: [{ g: { e: '1' } }] }] } },
127
- f: { l: { v: { r: 8 } } },
128
- num: 8,
129
- };
130
-
131
- const updateTest = atom(a);
132
-
133
- const prevF = a.val.b.c[0].f;
134
- const prevV = a.f.l.v;
135
-
136
- console.info(updateTest.get() === a);
137
-
138
- updateTest.do.update(a => {
139
- a.val.b.c[0].f[0].g.e = '2';
140
- // a.num = 0;
141
- });
142
- console.info(
143
- updateTest.get() === a,
144
- prevF === a.val.b.c[0].f,
145
- prevV === updateTest.get().f.l.v,
146
- updateTest.get().val.b.c[0].f === a.val.b.c[0].f,
147
- a.val.b.c[0].f[0].g,
148
- updateTest.get().val.b.c[0].f[0].g,
149
- );
150
- })();
151
-
152
- const numAtom = atom(0);
153
-
154
- const inputValueAtom = atom('');
155
-
156
- function App() {
157
- const test = useAtomValue(testAtom);
158
- const testText = useAtomValue(testTextAtom);
159
- const testDo = useAtomDo(testAtom);
160
- const value = useAtomValue(inputValueAtom);
161
- console.log({ num: useAtomValue(numAtom) });
162
-
163
- console.info(test);
164
-
165
- useEffect(() => {
166
- const onClick = () => {
167
- testDo.add(Date.now());
168
- testDo.update12();
169
- testTextAtom.do.addText('1');
170
-
171
- numAtom.set(num => {
172
- console.log(num);
173
- return 1;
174
- });
175
- numAtom.set(3);
176
- numAtom.set(num => {
177
- console.log(num);
178
- return 4;
179
- });
180
- numAtom.set(num => {
181
- console.log(num);
182
- return 5;
183
- });
184
- numAtom.set(6);
185
- numAtom.set(num => {
186
- console.log(num);
187
- return 7;
188
- });
189
- };
190
-
191
- window.addEventListener('click', onClick);
192
- return () => window.removeEventListener('click', onClick);
193
- }, []);
194
-
195
- return (
196
- <>
197
- {testText}
198
- <input
199
- value={value}
200
- onChange={event => {
201
- inputValueAtom.set(event.currentTarget.value + '*');
202
- inputValueAtom.set(event.currentTarget.value);
203
- }}
204
- />
205
- </>
206
- );
207
- }