chem-rx 0.0.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.
@@ -0,0 +1,26 @@
1
+ {
2
+ "index.js": {
3
+ "bundled": 2254,
4
+ "minified": 1146,
5
+ "gzipped": 529,
6
+ "treeshaked": {
7
+ "rollup": {
8
+ "code": 13,
9
+ "import_statements": 13
10
+ },
11
+ "webpack": {
12
+ "code": 997
13
+ }
14
+ }
15
+ },
16
+ "index.cjs.js": {
17
+ "bundled": 2625,
18
+ "minified": 1302,
19
+ "gzipped": 570
20
+ },
21
+ "index.iife.js": {
22
+ "bundled": 2825,
23
+ "minified": 1233,
24
+ "gzipped": 550
25
+ }
26
+ }
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 wetonium
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,80 @@
1
+ # chem-rx
2
+
3
+ `chem-rx` wraps`rx.js` to provide a state management solution focused on
4
+ simplicity. Useable with or without React!
5
+
6
+ ## Atom
7
+
8
+ `chem-rx` is an atomic approach to state management, similar to
9
+ [jotai](https://github.com/pmndrs/jotai) or
10
+ [Recoil](https://github.com/facebookexperimental/Recoil).
11
+
12
+ Atoms are state containers that take any value - object, array, or primitive.
13
+
14
+ ```
15
+ import { Atom } from 'chem-rx'
16
+
17
+ const numberAtom: BaseAtom = Atom(0)
18
+ const stringAtom: BaseAtom = Atom('hello')
19
+ const arrayAtom: ArrayAtom = Atom(['hello', 'world'])
20
+ const objectAtom: ObjectAtom = Atom({ 'hello': 'world', 'world': 'hello' })
21
+ ```
22
+
23
+ ### Getting & setting values
24
+
25
+ `Atom` will automatically return an instance of `BaseAtom`, `ArrayAtom`, or
26
+ `ObjectAtom` depending on the input.
27
+
28
+ ```
29
+ /*
30
+ * BaseAtom
31
+ */
32
+ numberAtom.set(2)
33
+ numberAtom.value()
34
+ // 2
35
+
36
+ /*
37
+ * ArrayAtom
38
+ */
39
+ arrayAtom.push('!')
40
+ arrayAtom.value()
41
+ // ['hello', 'world', '!']
42
+ arrayAtom.get(1)
43
+ // 'world'
44
+
45
+ /*
46
+ * ObjectAtom
47
+ */
48
+ objectAtom.set('world', 'hi')
49
+ objectAtom.value()
50
+ // {'hello': 'world', 'world': 'hi'}
51
+
52
+ objectAtom.set('sup', 'earth')
53
+ // {'hello': 'world', 'world': 'hi', 'sup': 'earth'}
54
+
55
+ objectAtom.get('world')
56
+ // 'hi'
57
+ ```
58
+
59
+ ### Transforming Atoms
60
+
61
+ ### Composing Atoms & ReadOnlyAtoms
62
+
63
+ ### Subscribing to updates
64
+
65
+ ## Use with React
66
+
67
+ ### useAtom
68
+
69
+ ### hydrateAtoms
70
+
71
+ ## Use with rx.js
72
+
73
+ ## Why...?
74
+
75
+ This library spawned out of a love for the flexibility and expressiveness of
76
+ [rx.js](https://github.com/ReactiveX/rxjs) Observables, and the simplicity of
77
+ atomic libraries like [jotai](https://github.com/pmndrs/jotai).
78
+
79
+ Its primary focus is on ease of use and code cleanliness, and is my go-to
80
+ library for all client-side state management
@@ -0,0 +1,24 @@
1
+ module.exports = (api, targets) => {
2
+ // https://babeljs.io/docs/en/config-files#config-function-api
3
+ const isTestEnv = api.env("test");
4
+
5
+ return {
6
+ babelrc: false,
7
+ ignore: ["./node_modules"],
8
+ presets: [
9
+ [
10
+ "@babel/preset-env",
11
+ {
12
+ loose: true,
13
+ modules: isTestEnv ? "commonjs" : false,
14
+ targets: isTestEnv ? { node: "current" } : targets,
15
+ },
16
+ ],
17
+ "@babel/preset-typescript",
18
+ ],
19
+ plugins: [
20
+ "@babel/plugin-transform-react-jsx",
21
+ ["@babel/plugin-transform-typescript", { isTSX: true }],
22
+ ],
23
+ };
24
+ };
package/dist/Atom.d.ts ADDED
@@ -0,0 +1,29 @@
1
+ import { BehaviorSubject, Observable, OperatorFunction, Subscription } from "rxjs";
2
+ export type AtomTuple<T> = {
3
+ [K in keyof T]: Atom<T[K]>;
4
+ };
5
+ export declare class Atom<T> {
6
+ _behavior$: BehaviorSubject<T>;
7
+ _parent?: BehaviorSubject<T>[];
8
+ _bonds: BehaviorSubject<T>[];
9
+ _fromObservable: Observable<T> | null;
10
+ _fromObservableSubscription: Subscription | null;
11
+ static combine<A extends readonly unknown[]>(...atoms: readonly [...AtomTuple<A>]): Atom<A>;
12
+ constructor(_value: T | Observable<T>);
13
+ push(nextVal: T): void;
14
+ transform(): Atom<T>;
15
+ transform<A>(op1: OperatorFunction<T, A>): Atom<A>;
16
+ transform<A, B>(op1: OperatorFunction<T, A>, op2: OperatorFunction<A, B>): Atom<B>;
17
+ transform<A, B, C>(op1: OperatorFunction<T, A>, op2: OperatorFunction<A, B>, op3: OperatorFunction<B, C>): Atom<C>;
18
+ transform<A, B, C, D>(op1: OperatorFunction<T, A>, op2: OperatorFunction<A, B>, op3: OperatorFunction<B, C>, op4: OperatorFunction<C, D>): Atom<D>;
19
+ transform<A, B, C, D, E>(op1: OperatorFunction<T, A>, op2: OperatorFunction<A, B>, op3: OperatorFunction<B, C>, op4: OperatorFunction<C, D>, op5: OperatorFunction<D, E>): Atom<E>;
20
+ transform<A, B, C, D, E, F>(op1: OperatorFunction<T, A>, op2: OperatorFunction<A, B>, op3: OperatorFunction<B, C>, op4: OperatorFunction<C, D>, op5: OperatorFunction<D, E>, op6: OperatorFunction<E, F>): Atom<F>;
21
+ transform<A, B, C, D, E, F, G>(op1: OperatorFunction<T, A>, op2: OperatorFunction<A, B>, op3: OperatorFunction<B, C>, op4: OperatorFunction<C, D>, op5: OperatorFunction<D, E>, op6: OperatorFunction<E, F>, op7: OperatorFunction<F, G>): Atom<G>;
22
+ transform<A, B, C, D, E, F, G, H>(op1: OperatorFunction<T, A>, op2: OperatorFunction<A, B>, op3: OperatorFunction<B, C>, op4: OperatorFunction<C, D>, op5: OperatorFunction<D, E>, op6: OperatorFunction<E, F>, op7: OperatorFunction<F, G>, op8: OperatorFunction<G, H>): Atom<H>;
23
+ transform<A, B, C, D, E, F, G, H, I>(op1: OperatorFunction<T, A>, op2: OperatorFunction<A, B>, op3: OperatorFunction<B, C>, op4: OperatorFunction<C, D>, op5: OperatorFunction<D, E>, op6: OperatorFunction<E, F>, op7: OperatorFunction<F, G>, op8: OperatorFunction<G, H>, op9: OperatorFunction<H, I>): Atom<I>;
24
+ transform<A, B, C, D, E, F, G, H, I>(op1: OperatorFunction<T, A>, op2: OperatorFunction<A, B>, op3: OperatorFunction<B, C>, op4: OperatorFunction<C, D>, op5: OperatorFunction<D, E>, op6: OperatorFunction<E, F>, op7: OperatorFunction<F, G>, op8: OperatorFunction<G, H>, op9: OperatorFunction<H, I>, ...operations: OperatorFunction<any, any>[]): Atom<unknown>;
25
+ subscribe(...params: Parameters<BehaviorSubject<T>["subscribe"]>): Subscription;
26
+ getValue(): T;
27
+ dispose(): void;
28
+ }
29
+ //# sourceMappingURL=Atom.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Atom.d.ts","sourceRoot":"","sources":["../src/Atom.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EAGf,UAAU,EACV,gBAAgB,EAChB,YAAY,EACb,MAAM,MAAM,CAAC;AAGd,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI;KACxB,CAAC,IAAI,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAC3B,CAAC;AAEF,qBAAa,IAAI,CAAC,CAAC;IACjB,UAAU,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC;IAE/B,OAAO,CAAC,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/B,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,CAAM;IAElC,eAAe,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CAAQ;IAC7C,2BAA2B,EAAE,YAAY,GAAG,IAAI,CAAQ;IAExD,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,SAAS,OAAO,EAAE,EACzC,GAAG,KAAK,EAAE,SAAS,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,GACnC,IAAI,CAAC,CAAC,CAAC;gBAKE,MAAM,EAAE,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC;IAarC,IAAI,CAAC,OAAO,EAAE,CAAC;IAKf,SAAS,IAAI,IAAI,CAAC,CAAC,CAAC;IACpB,SAAS,CAAC,CAAC,EAAE,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IAClD,SAAS,CAAC,CAAC,EAAE,CAAC,EACZ,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,GAC1B,IAAI,CAAC,CAAC,CAAC;IACV,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EACf,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,GAC1B,IAAI,CAAC,CAAC,CAAC;IACV,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAClB,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,GAC1B,IAAI,CAAC,CAAC,CAAC;IACV,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EACrB,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,GAC1B,IAAI,CAAC,CAAC,CAAC;IACV,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EACxB,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,GAC1B,IAAI,CAAC,CAAC,CAAC;IACV,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,GAC1B,IAAI,CAAC,CAAC,CAAC;IACV,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAC9B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,GAC1B,IAAI,CAAC,CAAC,CAAC;IACV,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EACjC,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,GAC1B,IAAI,CAAC,CAAC,CAAC;IACV,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EACjC,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3B,GAAG,UAAU,EAAE,gBAAgB,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,GAC1C,IAAI,CAAC,OAAO,CAAC;IAUhB,SAAS,CAAC,GAAG,MAAM,EAAE,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IAIhE,QAAQ;IAKR,OAAO;CAGR"}
@@ -0,0 +1,9 @@
1
+ import { Subject, Subscription } from "rxjs";
2
+ export declare class Signal<T = void> {
3
+ _subject$: Subject<T>;
4
+ constructor();
5
+ ping(value: T): void;
6
+ subscribe(...params: Parameters<Subject<T>["subscribe"]>): Subscription;
7
+ dispose(): void;
8
+ }
9
+ //# sourceMappingURL=Signal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Signal.d.ts","sourceRoot":"","sources":["../src/Signal.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EAIP,YAAY,EACb,MAAM,MAAM,CAAC;AAGd,qBAAa,MAAM,CAAC,CAAC,GAAG,IAAI;IAC1B,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;;IAOtB,IAAI,CAAC,KAAK,EAAE,CAAC;IAIb,SAAS,CAAC,GAAG,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IAKxD,OAAO;CAGR"}
@@ -0,0 +1,3 @@
1
+ import { Atom } from "./Atom";
2
+ export declare function hydrateAtoms(values: readonly [Atom<any>, any][]): void;
3
+ //# sourceMappingURL=hydrateAtoms.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hydrateAtoms.d.ts","sourceRoot":"","sources":["../src/hydrateAtoms.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE9B,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,QAI/D"}
@@ -0,0 +1,143 @@
1
+ 'use strict';
2
+
3
+ var rxjs = require('rxjs');
4
+ var react = require('react');
5
+
6
+ var Atom = /*#__PURE__*/function () {
7
+ Atom.combine = function combine() {
8
+ for (var _len = arguments.length, atoms = new Array(_len), _key = 0; _key < _len; _key++) {
9
+ atoms[_key] = arguments[_key];
10
+ }
11
+ var observable = rxjs.combineLatest.apply(void 0, atoms.map(function (a) {
12
+ return a._behavior$;
13
+ }));
14
+ return new Atom(observable);
15
+ };
16
+ function Atom(_value) {
17
+ var _this = this;
18
+ this._bonds = [];
19
+ this._fromObservable = null;
20
+ this._fromObservableSubscription = null;
21
+ if (rxjs.isObservable(_value)) {
22
+ this._fromObservable = _value;
23
+ this._behavior$ = new rxjs.BehaviorSubject(null);
24
+ this._fromObservableSubscription = _value.subscribe(function (value) {
25
+ _this.push(value);
26
+ });
27
+ } else {
28
+ // if it's just a value just use a regular behavior subject
29
+ this._behavior$ = new rxjs.BehaviorSubject(_value);
30
+ }
31
+ }
32
+ var _proto = Atom.prototype;
33
+ _proto.push = function push(nextVal) {
34
+ this._behavior$.next(nextVal);
35
+ }
36
+
37
+ // taken from Observable
38
+ ;
39
+ _proto.transform = function transform() {
40
+ var _this$_behavior$;
41
+ // @ts-ignore can't match overloaded function
42
+ var observable = (_this$_behavior$ = this._behavior$).pipe.apply(_this$_behavior$, arguments);
43
+ return new Atom(observable);
44
+ };
45
+ _proto.subscribe = function subscribe() {
46
+ var _this$_behavior$2;
47
+ return (_this$_behavior$2 = this._behavior$).subscribe.apply(_this$_behavior$2, arguments);
48
+ };
49
+ _proto.getValue = function getValue() {
50
+ return this._behavior$.getValue();
51
+ }
52
+
53
+ // not needed?
54
+ ;
55
+ _proto.dispose = function dispose() {
56
+ var _this$_fromObservable;
57
+ (_this$_fromObservable = this._fromObservableSubscription) == null ? void 0 : _this$_fromObservable.unsubscribe();
58
+ };
59
+ return Atom;
60
+ }();
61
+
62
+ function useAtom(atom) {
63
+ var _useState = react.useState(atom.getValue()),
64
+ value = _useState[0],
65
+ setValue = _useState[1];
66
+ react.useEffect(function () {
67
+ var subscription = atom.subscribe(function (val) {
68
+ setValue(val);
69
+ });
70
+ return function () {
71
+ subscription.unsubscribe();
72
+ };
73
+ }, [atom]);
74
+ return value;
75
+ }
76
+
77
+ function _unsupportedIterableToArray(o, minLen) {
78
+ if (!o) return;
79
+ if (typeof o === "string") return _arrayLikeToArray(o, minLen);
80
+ var n = Object.prototype.toString.call(o).slice(8, -1);
81
+ if (n === "Object" && o.constructor) n = o.constructor.name;
82
+ if (n === "Map" || n === "Set") return Array.from(o);
83
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
84
+ }
85
+ function _arrayLikeToArray(arr, len) {
86
+ if (len == null || len > arr.length) len = arr.length;
87
+ for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
88
+ return arr2;
89
+ }
90
+ function _createForOfIteratorHelperLoose(o, allowArrayLike) {
91
+ var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
92
+ if (it) return (it = it.call(o)).next.bind(it);
93
+ if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
94
+ if (it) o = it;
95
+ var i = 0;
96
+ return function () {
97
+ if (i >= o.length) return {
98
+ done: true
99
+ };
100
+ return {
101
+ done: false,
102
+ value: o[i++]
103
+ };
104
+ };
105
+ }
106
+ throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
107
+ }
108
+
109
+ function hydrateAtoms(values) {
110
+ for (var _iterator = _createForOfIteratorHelperLoose(values), _step; !(_step = _iterator()).done;) {
111
+ var _step$value = _step.value,
112
+ atom = _step$value[0],
113
+ value = _step$value[1];
114
+ atom.push(value);
115
+ }
116
+ }
117
+
118
+ var Signal = /*#__PURE__*/function () {
119
+ function Signal() {
120
+ // if it's just a value just use a regular behavior subject
121
+ this._subject$ = new rxjs.Subject();
122
+ }
123
+ var _proto = Signal.prototype;
124
+ _proto.ping = function ping(value) {
125
+ this._subject$.next(value);
126
+ };
127
+ _proto.subscribe = function subscribe() {
128
+ var _this$_subject$;
129
+ return (_this$_subject$ = this._subject$).subscribe.apply(_this$_subject$, arguments);
130
+ }
131
+
132
+ // not needed?
133
+ ;
134
+ _proto.dispose = function dispose() {
135
+ this._subject$.unsubscribe();
136
+ };
137
+ return Signal;
138
+ }();
139
+
140
+ exports.Atom = Atom;
141
+ exports.Signal = Signal;
142
+ exports.hydrateAtoms = hydrateAtoms;
143
+ exports.useAtom = useAtom;
@@ -0,0 +1,5 @@
1
+ export { Atom } from "./Atom";
2
+ export { useAtom } from "./useAtom";
3
+ export { hydrateAtoms } from "./hydrateAtoms";
4
+ export { Signal } from "./Signal";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC"}
@@ -0,0 +1,145 @@
1
+ var chemicalRx = (function (exports, rxjs, react) {
2
+ 'use strict';
3
+
4
+ var Atom = /*#__PURE__*/function () {
5
+ Atom.combine = function combine() {
6
+ for (var _len = arguments.length, atoms = new Array(_len), _key = 0; _key < _len; _key++) {
7
+ atoms[_key] = arguments[_key];
8
+ }
9
+ var observable = rxjs.combineLatest.apply(void 0, atoms.map(function (a) {
10
+ return a._behavior$;
11
+ }));
12
+ return new Atom(observable);
13
+ };
14
+ function Atom(_value) {
15
+ var _this = this;
16
+ this._bonds = [];
17
+ this._fromObservable = null;
18
+ this._fromObservableSubscription = null;
19
+ if (rxjs.isObservable(_value)) {
20
+ this._fromObservable = _value;
21
+ this._behavior$ = new rxjs.BehaviorSubject(null);
22
+ this._fromObservableSubscription = _value.subscribe(function (value) {
23
+ _this.push(value);
24
+ });
25
+ } else {
26
+ // if it's just a value just use a regular behavior subject
27
+ this._behavior$ = new rxjs.BehaviorSubject(_value);
28
+ }
29
+ }
30
+ var _proto = Atom.prototype;
31
+ _proto.push = function push(nextVal) {
32
+ this._behavior$.next(nextVal);
33
+ }
34
+
35
+ // taken from Observable
36
+ ;
37
+ _proto.transform = function transform() {
38
+ var _this$_behavior$;
39
+ // @ts-ignore can't match overloaded function
40
+ var observable = (_this$_behavior$ = this._behavior$).pipe.apply(_this$_behavior$, arguments);
41
+ return new Atom(observable);
42
+ };
43
+ _proto.subscribe = function subscribe() {
44
+ var _this$_behavior$2;
45
+ return (_this$_behavior$2 = this._behavior$).subscribe.apply(_this$_behavior$2, arguments);
46
+ };
47
+ _proto.getValue = function getValue() {
48
+ return this._behavior$.getValue();
49
+ }
50
+
51
+ // not needed?
52
+ ;
53
+ _proto.dispose = function dispose() {
54
+ var _this$_fromObservable;
55
+ (_this$_fromObservable = this._fromObservableSubscription) == null ? void 0 : _this$_fromObservable.unsubscribe();
56
+ };
57
+ return Atom;
58
+ }();
59
+
60
+ function useAtom(atom) {
61
+ var _useState = react.useState(atom.getValue()),
62
+ value = _useState[0],
63
+ setValue = _useState[1];
64
+ react.useEffect(function () {
65
+ var subscription = atom.subscribe(function (val) {
66
+ setValue(val);
67
+ });
68
+ return function () {
69
+ subscription.unsubscribe();
70
+ };
71
+ }, [atom]);
72
+ return value;
73
+ }
74
+
75
+ function _unsupportedIterableToArray(o, minLen) {
76
+ if (!o) return;
77
+ if (typeof o === "string") return _arrayLikeToArray(o, minLen);
78
+ var n = Object.prototype.toString.call(o).slice(8, -1);
79
+ if (n === "Object" && o.constructor) n = o.constructor.name;
80
+ if (n === "Map" || n === "Set") return Array.from(o);
81
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
82
+ }
83
+ function _arrayLikeToArray(arr, len) {
84
+ if (len == null || len > arr.length) len = arr.length;
85
+ for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
86
+ return arr2;
87
+ }
88
+ function _createForOfIteratorHelperLoose(o, allowArrayLike) {
89
+ var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
90
+ if (it) return (it = it.call(o)).next.bind(it);
91
+ if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
92
+ if (it) o = it;
93
+ var i = 0;
94
+ return function () {
95
+ if (i >= o.length) return {
96
+ done: true
97
+ };
98
+ return {
99
+ done: false,
100
+ value: o[i++]
101
+ };
102
+ };
103
+ }
104
+ throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
105
+ }
106
+
107
+ function hydrateAtoms(values) {
108
+ for (var _iterator = _createForOfIteratorHelperLoose(values), _step; !(_step = _iterator()).done;) {
109
+ var _step$value = _step.value,
110
+ atom = _step$value[0],
111
+ value = _step$value[1];
112
+ atom.push(value);
113
+ }
114
+ }
115
+
116
+ var Signal = /*#__PURE__*/function () {
117
+ function Signal() {
118
+ // if it's just a value just use a regular behavior subject
119
+ this._subject$ = new rxjs.Subject();
120
+ }
121
+ var _proto = Signal.prototype;
122
+ _proto.ping = function ping(value) {
123
+ this._subject$.next(value);
124
+ };
125
+ _proto.subscribe = function subscribe() {
126
+ var _this$_subject$;
127
+ return (_this$_subject$ = this._subject$).subscribe.apply(_this$_subject$, arguments);
128
+ }
129
+
130
+ // not needed?
131
+ ;
132
+ _proto.dispose = function dispose() {
133
+ this._subject$.unsubscribe();
134
+ };
135
+ return Signal;
136
+ }();
137
+
138
+ exports.Atom = Atom;
139
+ exports.Signal = Signal;
140
+ exports.hydrateAtoms = hydrateAtoms;
141
+ exports.useAtom = useAtom;
142
+
143
+ return exports;
144
+
145
+ })({}, rxjs, React);
package/dist/index.js ADDED
@@ -0,0 +1,86 @@
1
+ import { combineLatest, isObservable, BehaviorSubject, Subject } from 'rxjs';
2
+ import { useState, useEffect } from 'react';
3
+
4
+ class Atom {
5
+ static combine(...atoms) {
6
+ const observable = combineLatest(...atoms.map(a => a._behavior$));
7
+ return new Atom(observable);
8
+ }
9
+ constructor(_value) {
10
+ this._bonds = [];
11
+ this._fromObservable = null;
12
+ this._fromObservableSubscription = null;
13
+ if (isObservable(_value)) {
14
+ this._fromObservable = _value;
15
+ this._behavior$ = new BehaviorSubject(null);
16
+ this._fromObservableSubscription = _value.subscribe(value => {
17
+ this.push(value);
18
+ });
19
+ } else {
20
+ // if it's just a value just use a regular behavior subject
21
+ this._behavior$ = new BehaviorSubject(_value);
22
+ }
23
+ }
24
+ push(nextVal) {
25
+ this._behavior$.next(nextVal);
26
+ }
27
+
28
+ // taken from Observable
29
+
30
+ transform(...operations) {
31
+ // @ts-ignore can't match overloaded function
32
+ const observable = this._behavior$.pipe(...operations);
33
+ return new Atom(observable);
34
+ }
35
+ subscribe(...params) {
36
+ return this._behavior$.subscribe(...params);
37
+ }
38
+ getValue() {
39
+ return this._behavior$.getValue();
40
+ }
41
+
42
+ // not needed?
43
+ dispose() {
44
+ var _this$_fromObservable;
45
+ (_this$_fromObservable = this._fromObservableSubscription) == null ? void 0 : _this$_fromObservable.unsubscribe();
46
+ }
47
+ }
48
+
49
+ function useAtom(atom) {
50
+ const [value, setValue] = useState(atom.getValue());
51
+ useEffect(() => {
52
+ const subscription = atom.subscribe(val => {
53
+ setValue(val);
54
+ });
55
+ return () => {
56
+ subscription.unsubscribe();
57
+ };
58
+ }, [atom]);
59
+ return value;
60
+ }
61
+
62
+ function hydrateAtoms(values) {
63
+ for (const [atom, value] of values) {
64
+ atom.push(value);
65
+ }
66
+ }
67
+
68
+ class Signal {
69
+ constructor() {
70
+ // if it's just a value just use a regular behavior subject
71
+ this._subject$ = new Subject();
72
+ }
73
+ ping(value) {
74
+ this._subject$.next(value);
75
+ }
76
+ subscribe(...params) {
77
+ return this._subject$.subscribe(...params);
78
+ }
79
+
80
+ // not needed?
81
+ dispose() {
82
+ this._subject$.unsubscribe();
83
+ }
84
+ }
85
+
86
+ export { Atom, Signal, hydrateAtoms, useAtom };
@@ -0,0 +1,32 @@
1
+ declare class GenericClass<T> {
2
+ }
3
+ export type GetGenericType<C extends GenericClass<any>> = C extends GenericClass<infer T> ? T : unknown;
4
+ export type KeyOfValueType<T, V> = {
5
+ [K in keyof T]: T[K] extends V ? K : never;
6
+ }[keyof T];
7
+ export type IsObject<T> = T extends object ? T : never;
8
+ export type IsntObject<T> = T extends object ? never : T;
9
+ export type IsntFunction<T> = T extends Function ? never : T;
10
+ export type OmitKeysWithNeverValues<T> = {
11
+ [K in keyof T as T[K] extends never ? never : K]: T[K];
12
+ };
13
+ export declare function assertUnreachable(_value?: never): never;
14
+ type ValidFunction<Arguments extends unknown[], ReturnType> = unknown[] extends Arguments ? unknown extends ReturnType ? never : (...args: Arguments) => ReturnType : (...args: Arguments) => ReturnType;
15
+ export type Overloads<T extends (...args: unknown[]) => unknown> = T extends {
16
+ (...args: infer A1): infer R1;
17
+ (...args: infer A2): infer R2;
18
+ (...args: infer A3): infer R3;
19
+ (...args: infer A4): infer R4;
20
+ (...args: infer A5): infer R5;
21
+ (...args: infer A6): infer R6;
22
+ (...args: infer A7): infer R7;
23
+ (...args: infer A8): infer R8;
24
+ (...args: infer A9): infer R9;
25
+ (...args: infer A10): infer R10;
26
+ (...args: infer A11): infer R11;
27
+ (...args: infer A12): infer R12;
28
+ } ? ValidFunction<A1, R1> | ValidFunction<A2, R2> | ValidFunction<A3, R3> | ValidFunction<A4, R4> | ValidFunction<A5, R5> | ValidFunction<A6, R6> | ValidFunction<A7, R7> | ValidFunction<A8, R8> | ValidFunction<A9, R9> | ValidFunction<A10, R10> | ValidFunction<A11, R11> | ValidFunction<A12, R12> : never;
29
+ export type OverloadedParameters<T extends (...args: any[]) => unknown> = Parameters<Overloads<T>>;
30
+ export type OverloadedReturnType<T extends (...args: any[]) => unknown> = ReturnType<Overloads<T>>;
31
+ export {};
32
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Atom } from "./Atom";
2
+ export declare function useAtom<T>(atom: Atom<T>): T;
3
+ //# sourceMappingURL=useAtom.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAtom.d.ts","sourceRoot":"","sources":["../src/useAtom.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE9B,wBAAgB,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAc3C"}
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "chem-rx",
3
+ "version": "0.0.1",
4
+ "description": "react state primitives powered by rx.js",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/dxu/chem-rx.git"
10
+ },
11
+ "author": "dxu",
12
+ "license": "MIT",
13
+ "bugs": {
14
+ "url": "https://github.com/dxu/chem-rx/issues"
15
+ },
16
+ "homepage": "https://github.com/dxu/chem-rx#readme",
17
+ "devDependencies": {
18
+ "@babel/core": "^7.22.10",
19
+ "@babel/plugin-transform-react-jsx": "^7.22.5",
20
+ "@babel/plugin-transform-typescript": "^7.22.10",
21
+ "@babel/preset-env": "^7.22.10",
22
+ "@babel/preset-typescript": "^7.22.5",
23
+ "@rollup/plugin-babel": "^6.0.3",
24
+ "@rollup/plugin-node-resolve": "^15.1.0",
25
+ "@rollup/plugin-typescript": "^11.1.2",
26
+ "@types/jest": "^29.5.3",
27
+ "@types/react": "^18.2.20",
28
+ "jest": "^29.6.2",
29
+ "rimraf": "^5.0.1",
30
+ "rollup": "^3.28.0",
31
+ "rollup-plugin-size-snapshot": "^0.12.0",
32
+ "rollup-plugin-typescript2": "^0.35.0",
33
+ "rollup-plugin-visualizer": "^5.9.2",
34
+ "rxjs": "^7.8.1",
35
+ "typescript": "^5.1.6"
36
+ },
37
+ "peerDependencies": {
38
+ "react": "^18.2.0",
39
+ "rxjs": "^7.5.7"
40
+ },
41
+ "exports": {
42
+ ".": "./dist/index.js",
43
+ "./index.cjs.js": "./dist/index.cjs.js"
44
+ },
45
+ "scripts": {
46
+ "prebuild": "rimraf dist",
47
+ "test": "jest",
48
+ "clean": "rm -rf ./dist",
49
+ "build": "npm run prebuild && rollup -c"
50
+ }
51
+ }
@@ -0,0 +1,92 @@
1
+ const path = require("path");
2
+
3
+ const { visualizer } = require("rollup-plugin-visualizer");
4
+
5
+ const babel = require("@rollup/plugin-babel");
6
+ const resolve = require("@rollup/plugin-node-resolve");
7
+ const typescript = require("@rollup/plugin-typescript");
8
+ // const { sizeSnapshot } = require("rollup-plugin-size-snapshot");
9
+
10
+ const createBabelConfig = require("./babel.config");
11
+
12
+ const { root } = path.parse(process.cwd());
13
+ const external = (id) => !id.startsWith(".") && !id.startsWith(root);
14
+ const extensions = [".js", ".ts", ".tsx"];
15
+ const getBabelOptions = (targets) => ({
16
+ babelHelpers: "bundled",
17
+ ...createBabelConfig({ env: (env) => env === "build" }, targets),
18
+ extensions,
19
+ });
20
+
21
+ function createDeclarationConfig(input, output) {
22
+ return {
23
+ input,
24
+ output: {
25
+ dir: output,
26
+ },
27
+ external,
28
+ plugins: [
29
+ typescript({
30
+ declaration: true,
31
+ emitDeclarationOnly: true,
32
+ outDir: output,
33
+ }),
34
+ ],
35
+ };
36
+ }
37
+
38
+ function createESMConfig(input, output) {
39
+ return {
40
+ input,
41
+ output: { file: output, format: "esm" },
42
+ external,
43
+ plugins: [
44
+ babel(getBabelOptions({ node: 8 })),
45
+ // sizeSnapshot(),
46
+ resolve({ extensions }),
47
+ visualizer(),
48
+ ],
49
+ };
50
+ }
51
+
52
+ function createCommonJSConfig(input, output) {
53
+ return {
54
+ input,
55
+ output: { file: output, format: "cjs", exports: "named" },
56
+ external,
57
+ plugins: [
58
+ babel(getBabelOptions({ ie: 11 })),
59
+ // sizeSnapshot(),
60
+ resolve({ extensions }),
61
+ ],
62
+ };
63
+ }
64
+
65
+ function createIIFEConfig(input, output, globalName) {
66
+ return {
67
+ input,
68
+ output: {
69
+ file: output,
70
+ format: "iife",
71
+ exports: "named",
72
+ name: globalName,
73
+ globals: {
74
+ react: "React",
75
+ rxjs: "rxjs",
76
+ },
77
+ },
78
+ external,
79
+ plugins: [
80
+ babel(getBabelOptions({ ie: 11 })),
81
+ // sizeSnapshot(),
82
+ resolve({ extensions }),
83
+ ],
84
+ };
85
+ }
86
+
87
+ module.exports = [
88
+ createDeclarationConfig(`src/index.ts`, "dist"),
89
+ createESMConfig("src/index.ts", "dist/index.js"),
90
+ createCommonJSConfig("src/index.ts", "dist/index.cjs.js"),
91
+ createIIFEConfig("src/index.ts", "dist/index.iife.js", "chemicalRx"),
92
+ ];
package/src/Atom.ts ADDED
@@ -0,0 +1,200 @@
1
+ import {
2
+ BehaviorSubject,
3
+ combineLatest,
4
+ isObservable,
5
+ map,
6
+ Observable,
7
+ OperatorFunction,
8
+ Subscription,
9
+ } from "rxjs";
10
+ import { OverloadedParameters, OverloadedReturnType } from "./types";
11
+
12
+ export type AtomTuple<T> = {
13
+ [K in keyof T]: ReadOnlyAtom<T[K]>;
14
+ };
15
+
16
+ // export class ReadOnlyAtom<T> {}
17
+
18
+ export class ReadOnlyAtom<T> {
19
+ _behavior$: BehaviorSubject<T>;
20
+
21
+ _parent?: BehaviorSubject<T>[];
22
+ _bonds: BehaviorSubject<T>[] = [];
23
+
24
+ _fromObservable: Observable<T> | null = null;
25
+ _fromObservableSubscription: Subscription | null = null;
26
+
27
+ constructor(_value: T | Observable<T>) {
28
+ if (isObservable(_value)) {
29
+ this._fromObservable = _value;
30
+ this._behavior$ = new BehaviorSubject<T>(null!);
31
+ this._fromObservableSubscription = _value.subscribe((value) => {
32
+ this._behavior$.next(value);
33
+ });
34
+ } else {
35
+ // if it's just a value just use a regular behavior subject
36
+ this._behavior$ = new BehaviorSubject<T>(_value);
37
+ }
38
+ }
39
+
40
+ // taken from Observable
41
+ pipe(): ReadOnlyAtom<T>;
42
+ pipe<A>(op1: OperatorFunction<T, A>): ReadOnlyAtom<A>;
43
+ pipe<A, B>(
44
+ op1: OperatorFunction<T, A>,
45
+ op2: OperatorFunction<A, B>
46
+ ): ReadOnlyAtom<B>;
47
+ pipe<A, B, C>(
48
+ op1: OperatorFunction<T, A>,
49
+ op2: OperatorFunction<A, B>,
50
+ op3: OperatorFunction<B, C>
51
+ ): ReadOnlyAtom<C>;
52
+ pipe<A, B, C, D>(
53
+ op1: OperatorFunction<T, A>,
54
+ op2: OperatorFunction<A, B>,
55
+ op3: OperatorFunction<B, C>,
56
+ op4: OperatorFunction<C, D>
57
+ ): ReadOnlyAtom<D>;
58
+ pipe<A, B, C, D, E>(
59
+ op1: OperatorFunction<T, A>,
60
+ op2: OperatorFunction<A, B>,
61
+ op3: OperatorFunction<B, C>,
62
+ op4: OperatorFunction<C, D>,
63
+ op5: OperatorFunction<D, E>
64
+ ): ReadOnlyAtom<E>;
65
+ pipe<A, B, C, D, E, F>(
66
+ op1: OperatorFunction<T, A>,
67
+ op2: OperatorFunction<A, B>,
68
+ op3: OperatorFunction<B, C>,
69
+ op4: OperatorFunction<C, D>,
70
+ op5: OperatorFunction<D, E>,
71
+ op6: OperatorFunction<E, F>
72
+ ): ReadOnlyAtom<F>;
73
+ pipe<A, B, C, D, E, F, G>(
74
+ op1: OperatorFunction<T, A>,
75
+ op2: OperatorFunction<A, B>,
76
+ op3: OperatorFunction<B, C>,
77
+ op4: OperatorFunction<C, D>,
78
+ op5: OperatorFunction<D, E>,
79
+ op6: OperatorFunction<E, F>,
80
+ op7: OperatorFunction<F, G>
81
+ ): ReadOnlyAtom<G>;
82
+ pipe<A, B, C, D, E, F, G, H>(
83
+ op1: OperatorFunction<T, A>,
84
+ op2: OperatorFunction<A, B>,
85
+ op3: OperatorFunction<B, C>,
86
+ op4: OperatorFunction<C, D>,
87
+ op5: OperatorFunction<D, E>,
88
+ op6: OperatorFunction<E, F>,
89
+ op7: OperatorFunction<F, G>,
90
+ op8: OperatorFunction<G, H>
91
+ ): ReadOnlyAtom<H>;
92
+ pipe<A, B, C, D, E, F, G, H, I>(
93
+ op1: OperatorFunction<T, A>,
94
+ op2: OperatorFunction<A, B>,
95
+ op3: OperatorFunction<B, C>,
96
+ op4: OperatorFunction<C, D>,
97
+ op5: OperatorFunction<D, E>,
98
+ op6: OperatorFunction<E, F>,
99
+ op7: OperatorFunction<F, G>,
100
+ op8: OperatorFunction<G, H>,
101
+ op9: OperatorFunction<H, I>
102
+ ): ReadOnlyAtom<I>;
103
+ pipe<A, B, C, D, E, F, G, H, I>(
104
+ op1: OperatorFunction<T, A>,
105
+ op2: OperatorFunction<A, B>,
106
+ op3: OperatorFunction<B, C>,
107
+ op4: OperatorFunction<C, D>,
108
+ op5: OperatorFunction<D, E>,
109
+ op6: OperatorFunction<E, F>,
110
+ op7: OperatorFunction<F, G>,
111
+ op8: OperatorFunction<G, H>,
112
+ op9: OperatorFunction<H, I>,
113
+ ...operations: OperatorFunction<any, any>[]
114
+ ): ReadOnlyAtom<unknown>;
115
+
116
+ pipe(
117
+ ...operations: OverloadedParameters<Observable<T>["pipe"]>
118
+ ): ReadOnlyAtom<any> {
119
+ // @ts-ignore can't match overloaded function
120
+ const observable = this._behavior$.pipe(...operations);
121
+ const newAtom = new ReadOnlyAtom(observable);
122
+
123
+ return newAtom;
124
+ }
125
+
126
+ transform(transformFn: (value: T, index: number) => any): ReadOnlyAtom<any> {
127
+ return this.pipe(map(transformFn));
128
+ }
129
+
130
+ subscribe(...params: Parameters<BehaviorSubject<T>["subscribe"]>) {
131
+ return this._behavior$.subscribe(...params);
132
+ }
133
+
134
+ value() {
135
+ return this._behavior$.getValue();
136
+ }
137
+
138
+ // not needed?
139
+ dispose() {
140
+ this._fromObservableSubscription?.unsubscribe();
141
+ }
142
+ }
143
+
144
+ export class BaseAtom<T> extends ReadOnlyAtom<T> {
145
+ set(nextVal: T) {
146
+ this._behavior$.next(nextVal);
147
+ }
148
+ }
149
+
150
+ export class ArrayAtom<T> extends ReadOnlyAtom<T[]> {
151
+ push(nextVal: T) {
152
+ this._behavior$.next([...this._behavior$.getValue(), nextVal]);
153
+ }
154
+ get(idx: number) {
155
+ return this.value()[idx];
156
+ }
157
+ }
158
+
159
+ export class ObjectAtom<
160
+ T extends Record<K, V>,
161
+ K extends keyof T = keyof T,
162
+ V = T[K]
163
+ > extends ReadOnlyAtom<T> {
164
+ set(nextKey: K, nextValue: V) {
165
+ this._behavior$.next({
166
+ ...this._behavior$.getValue(),
167
+ [nextKey]: nextValue,
168
+ });
169
+ }
170
+ get(nextKey: K) {
171
+ return this.value()[nextKey];
172
+ }
173
+ }
174
+
175
+ export function Atom<T>(value: T[]): ArrayAtom<T>;
176
+ export function Atom<T extends object, K extends keyof T = keyof T>(
177
+ _value: T
178
+ ): ObjectAtom<T>;
179
+ export function Atom<T>(_value: Observable<T> | T): BaseAtom<T>;
180
+ export function Atom<T>(
181
+ _value: T | Observable<T>
182
+ ): BaseAtom<T> | ArrayAtom<T> | ObjectAtom<T> {
183
+ let atom;
184
+ if (Array.isArray(_value)) {
185
+ atom = new ArrayAtom<T>(_value); // For arrays
186
+ } else if (typeof _value === "object" && _value !== null) {
187
+ atom = new ObjectAtom<T>(_value); // For objects
188
+ } else {
189
+ atom = new BaseAtom(_value); // For other types
190
+ }
191
+ return atom;
192
+ }
193
+
194
+ Atom.combine = <A extends readonly unknown[]>(
195
+ ...atoms: readonly [...AtomTuple<A>]
196
+ ): ReadOnlyAtom<A> => {
197
+ const observable = combineLatest(...atoms.map((a) => a._behavior$));
198
+ const newAtom = new ReadOnlyAtom(observable) as unknown as ReadOnlyAtom<A>;
199
+ return newAtom;
200
+ };
package/src/Signal.ts ADDED
@@ -0,0 +1,30 @@
1
+ import {
2
+ Subject,
3
+ isObservable,
4
+ Observable,
5
+ OperatorFunction,
6
+ Subscription,
7
+ } from "rxjs";
8
+ import { OverloadedParameters, OverloadedReturnType } from "./types";
9
+
10
+ export class Signal<T = void> {
11
+ _subject$: Subject<T>;
12
+
13
+ constructor() {
14
+ // if it's just a value just use a regular behavior subject
15
+ this._subject$ = new Subject<T>();
16
+ }
17
+
18
+ ping(value: T) {
19
+ this._subject$.next(value);
20
+ }
21
+
22
+ subscribe(...params: Parameters<Subject<T>["subscribe"]>) {
23
+ return this._subject$.subscribe(...params);
24
+ }
25
+
26
+ // not needed?
27
+ dispose() {
28
+ this._subject$.unsubscribe();
29
+ }
30
+ }
@@ -0,0 +1,7 @@
1
+ import { Atom } from "./Atom";
2
+
3
+ export function hydrateAtoms(values: readonly [Atom<any>, any][]) {
4
+ for (const [atom, value] of values) {
5
+ atom.push(value);
6
+ }
7
+ }
package/src/index.ts ADDED
@@ -0,0 +1,4 @@
1
+ export { Atom } from "./Atom";
2
+ export { useAtom } from "./useAtom";
3
+ export { hydrateAtoms } from "./hydrateAtoms";
4
+ export { Signal } from "./Signal";
package/src/types.ts ADDED
@@ -0,0 +1,66 @@
1
+ // Helper types if needed
2
+
3
+ class GenericClass<T> {}
4
+ export type GetGenericType<C extends GenericClass<any>> =
5
+ C extends GenericClass<infer T> ? T : unknown;
6
+
7
+ export type KeyOfValueType<T, V> = {
8
+ [K in keyof T]: T[K] extends V ? K : never;
9
+ }[keyof T];
10
+
11
+ export type IsObject<T> = T extends object ? T : never;
12
+ export type IsntObject<T> = T extends object ? never : T;
13
+ export type IsntFunction<T> = T extends Function ? never : T;
14
+
15
+ export type OmitKeysWithNeverValues<T> = {
16
+ [K in keyof T as T[K] extends never ? never : K]: T[K];
17
+ };
18
+
19
+ export function assertUnreachable(_value?: never): never {
20
+ throw new Error("Statement should be unreachable");
21
+ }
22
+
23
+ // https://github.com/microsoft/TypeScript/issues/32164
24
+
25
+ type ValidFunction<
26
+ Arguments extends unknown[],
27
+ ReturnType
28
+ > = unknown[] extends Arguments
29
+ ? unknown extends ReturnType
30
+ ? never
31
+ : (...args: Arguments) => ReturnType
32
+ : (...args: Arguments) => ReturnType;
33
+
34
+ export type Overloads<T extends (...args: unknown[]) => unknown> = T extends {
35
+ (...args: infer A1): infer R1;
36
+ (...args: infer A2): infer R2;
37
+ (...args: infer A3): infer R3;
38
+ (...args: infer A4): infer R4;
39
+ (...args: infer A5): infer R5;
40
+ (...args: infer A6): infer R6;
41
+ (...args: infer A7): infer R7;
42
+ (...args: infer A8): infer R8;
43
+ (...args: infer A9): infer R9;
44
+ (...args: infer A10): infer R10;
45
+ (...args: infer A11): infer R11;
46
+ (...args: infer A12): infer R12;
47
+ }
48
+ ?
49
+ | ValidFunction<A1, R1>
50
+ | ValidFunction<A2, R2>
51
+ | ValidFunction<A3, R3>
52
+ | ValidFunction<A4, R4>
53
+ | ValidFunction<A5, R5>
54
+ | ValidFunction<A6, R6>
55
+ | ValidFunction<A7, R7>
56
+ | ValidFunction<A8, R8>
57
+ | ValidFunction<A9, R9>
58
+ | ValidFunction<A10, R10>
59
+ | ValidFunction<A11, R11>
60
+ | ValidFunction<A12, R12>
61
+ : never;
62
+
63
+ export type OverloadedParameters<T extends (...args: any[]) => unknown> =
64
+ Parameters<Overloads<T>>;
65
+ export type OverloadedReturnType<T extends (...args: any[]) => unknown> =
66
+ ReturnType<Overloads<T>>;
package/src/useAtom.ts ADDED
@@ -0,0 +1,18 @@
1
+ import { useEffect, useState } from "react";
2
+ import { Atom } from "./Atom";
3
+
4
+ export function useAtom<T>(atom: Atom<T>): T {
5
+ const [value, setValue] = useState<T>(atom.getValue());
6
+
7
+ useEffect(() => {
8
+ const subscription = atom.subscribe((val) => {
9
+ setValue(val);
10
+ });
11
+
12
+ return () => {
13
+ subscription.unsubscribe();
14
+ };
15
+ }, [atom]);
16
+
17
+ return value;
18
+ }
@@ -0,0 +1,125 @@
1
+ import {
2
+ ArrayAtom,
3
+ Atom,
4
+ BaseAtom,
5
+ ObjectAtom,
6
+ ReadOnlyAtom,
7
+ } from "../src/Atom";
8
+ import { map, of } from "rxjs";
9
+
10
+ test("Base Atom values test", () => {
11
+ const atom = Atom("aweofij");
12
+ expect(atom instanceof BaseAtom).toBe(true);
13
+ expect(atom.value()).toBe("aweofij");
14
+
15
+ atom.set("apro");
16
+
17
+ expect(atom.value()).toBe("apro");
18
+ });
19
+
20
+ test("Object Atom values test", () => {
21
+ const atom = Atom<{ [key: string]: string }>({
22
+ firstKey: "firstValue",
23
+ secondKey: "secondValue",
24
+ });
25
+ expect(atom instanceof ObjectAtom).toBe(true);
26
+ expect(atom.value()["firstKey"]).toBe("firstValue");
27
+
28
+ expect(atom.value()["secondKey"]).toBe("secondValue");
29
+ atom.set("secondKey", "newSecondValue");
30
+ expect(atom.value()["secondKey"]).toBe("newSecondValue");
31
+
32
+ expect(atom.value()["thirdKey"]).toBeUndefined();
33
+ expect(atom.value()).not.toHaveProperty("thirdKey");
34
+ atom.set("thirdKey", "thirdValue");
35
+ expect(atom.value()["thirdKey"]).toBe("thirdValue");
36
+ });
37
+
38
+ test("Object Atom get function test", () => {
39
+ const atom = Atom<{ [key: string]: string }>({
40
+ firstKey: "firstValue",
41
+ secondKey: "secondValue",
42
+ });
43
+ expect(atom instanceof ObjectAtom).toBe(true);
44
+ expect(atom.get("firstKey")).toBe("firstValue");
45
+
46
+ expect(atom.get("secondKey")).toBe("secondValue");
47
+ atom.set("secondKey", "newSecondValue");
48
+ expect(atom.get("secondKey")).toBe("newSecondValue");
49
+
50
+ expect(atom.get("thirdKey")).toBeUndefined();
51
+ expect(atom.value()).not.toHaveProperty("thirdKey");
52
+ atom.set("thirdKey", "thirdValue");
53
+ expect(atom.get("thirdKey")).toBe("thirdValue");
54
+ });
55
+
56
+ test("Array Atom values test", () => {
57
+ const atom = Atom(["first"]);
58
+ expect(atom instanceof ArrayAtom).toBe(true);
59
+ expect(atom.value().length).toBe(1);
60
+ expect(atom.value()[0]).toBe("first");
61
+
62
+ atom.push("second");
63
+ expect(atom.value().length).toBe(2);
64
+ expect(atom.value()[1]).toBe("second");
65
+ });
66
+
67
+ test("Array Atom get index test", () => {
68
+ const atom = Atom(["first"]);
69
+ expect(atom instanceof ArrayAtom).toBe(true);
70
+ expect(atom.value().length).toBe(1);
71
+ expect(atom.get(0)).toBe("first");
72
+
73
+ atom.push("second");
74
+ expect(atom.value().length).toBe(2);
75
+ expect(atom.get(1)).toBe("second");
76
+ });
77
+
78
+ test("Test native pipe", () => {
79
+ const atom = Atom(3);
80
+ expect(atom instanceof BaseAtom).toBe(true);
81
+ expect(atom.value()).toBe(3);
82
+
83
+ const transformedAtom = atom.pipe(map((x) => x * x));
84
+ expect(transformedAtom instanceof ReadOnlyAtom).toBe(true);
85
+ expect(transformedAtom).not.toHaveProperty("push");
86
+
87
+ expect(transformedAtom.value()).toBe(9);
88
+ });
89
+
90
+ test("Test transform", () => {
91
+ const atom = Atom(3);
92
+ expect(atom instanceof BaseAtom).toBe(true);
93
+ expect(atom.value()).toBe(3);
94
+
95
+ const transformedAtom = atom.transform((x) => x * x);
96
+ expect(transformedAtom instanceof ReadOnlyAtom).toBe(true);
97
+ expect(transformedAtom).not.toHaveProperty("push");
98
+
99
+ expect(transformedAtom.value()).toBe(9);
100
+ });
101
+
102
+ test("Test combine", () => {
103
+ const normalizedData = Atom<{ [key: string]: { name: string } }>({
104
+ a: { name: "a" },
105
+ b: { name: "b" },
106
+ c: { name: "c" },
107
+ });
108
+ const ids = Atom<string[]>(["a", "b", "c"]);
109
+ const combined = Atom.combine(normalizedData, ids).transform(
110
+ ([normed, ids]) => {
111
+ return ids.map((id) => normed[id]);
112
+ }
113
+ );
114
+ expect(combined).not.toHaveProperty("push");
115
+
116
+ expect(combined instanceof ReadOnlyAtom).toBe(true);
117
+
118
+ expect(combined instanceof ReadOnlyAtom).toBe(true);
119
+ expect(combined).not.toHaveProperty("push");
120
+ const combinedValue = combined.value();
121
+ expect(combinedValue.length).toBe(3);
122
+ expect(combinedValue[0].name).toBe("a");
123
+ expect(combinedValue[1].name).toBe("b");
124
+ expect(combinedValue[2].name).toBe("c");
125
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "compilerOptions": {
3
+ "declaration": true,
4
+ "emitDeclarationOnly": true,
5
+ "declarationMap": true,
6
+ "rootDir": "./src",
7
+ "target": "esnext",
8
+ "strict": true,
9
+ "jsx": "react-jsx",
10
+ "esModuleInterop": true,
11
+ "moduleResolution": "node",
12
+ "noUncheckedIndexedAccess": true,
13
+ "exactOptionalPropertyTypes": true,
14
+ "baseUrl": ".",
15
+ "outDir": "dist",
16
+ "paths": {
17
+ "chemical-rx": ["./src/index.ts"],
18
+ "chemical-rx/*": ["./src/*.ts"]
19
+ }
20
+ },
21
+ "include": ["src/**/*"],
22
+ "exclude": ["node_modules", "dist"]
23
+ }