@oscarpalmer/mora 0.11.1 → 0.13.0
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/dist/array.cjs +130 -0
- package/dist/array.js +130 -0
- package/dist/computed.cjs +1 -1
- package/dist/computed.js +1 -1
- package/dist/index.cjs +2 -0
- package/dist/index.js +2 -0
- package/dist/mora.full.js +234 -87
- package/dist/reactive.cjs +12 -0
- package/dist/reactive.js +12 -0
- package/dist/signal.cjs +9 -32
- package/dist/signal.js +4 -27
- package/dist/value.cjs +38 -0
- package/dist/value.js +38 -0
- package/package.json +1 -1
- package/src/array.ts +201 -0
- package/src/computed.ts +1 -1
- package/src/index.ts +2 -0
- package/src/reactive.ts +19 -0
- package/src/signal.ts +7 -34
- package/src/value.ts +47 -0
- package/types/array.d.cts +101 -0
- package/types/array.d.ts +41 -0
- package/types/batch.d.cts +22 -10
- package/types/computed.d.cts +22 -10
- package/types/computed.d.ts +1 -1
- package/types/index.d.cts +67 -12
- package/types/index.d.ts +2 -0
- package/types/is.d.cts +23 -11
- package/types/reactive.d.cts +22 -10
- package/types/reactive.d.ts +12 -0
- package/types/signal.d.cts +26 -11
- package/types/signal.d.ts +4 -1
- package/types/subscription.d.cts +25 -13
- package/types/value.d.cts +64 -0
- package/types/value.d.ts +4 -0
package/dist/array.cjs
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __typeError = (msg) => {
|
|
3
|
+
throw TypeError(msg);
|
|
4
|
+
};
|
|
5
|
+
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
6
|
+
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
7
|
+
var __privateAdd = (obj, member, value2) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value2);
|
|
8
|
+
var _size;
|
|
9
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
10
|
+
const reactive = require("./reactive.cjs");
|
|
11
|
+
const signal = require("./signal.cjs");
|
|
12
|
+
const value = require("./value.cjs");
|
|
13
|
+
class ReactiveArray extends reactive.Reactive {
|
|
14
|
+
constructor(value2) {
|
|
15
|
+
super(
|
|
16
|
+
"array",
|
|
17
|
+
new Proxy(value2, {
|
|
18
|
+
get: (target, property) => updateMethods.has(property) ? updateArray(property, target, this.state, __privateGet(this, _size)) : Reflect.get(target, property),
|
|
19
|
+
set: (target, property, value22) => setValue(target, property, value22, this.state, __privateGet(this, _size))
|
|
20
|
+
})
|
|
21
|
+
);
|
|
22
|
+
__privateAdd(this, _size, signal.signal(0));
|
|
23
|
+
__privateGet(this, _size).set(value2.length);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The length of the array
|
|
27
|
+
*/
|
|
28
|
+
get length() {
|
|
29
|
+
return __privateGet(this, _size).get();
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Set the length of the array
|
|
33
|
+
*/
|
|
34
|
+
set length(value2) {
|
|
35
|
+
if (typeof value2 === "number" && value2 >= 0 && value2 !== this.state.value.length) {
|
|
36
|
+
this.get().length = value2;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* @inheritdoc
|
|
41
|
+
*/
|
|
42
|
+
get() {
|
|
43
|
+
return value.getValue(this.state);
|
|
44
|
+
}
|
|
45
|
+
peek(length) {
|
|
46
|
+
return length === true ? __privateGet(this, _size).peek() : [...this.state.value];
|
|
47
|
+
}
|
|
48
|
+
set(first, second) {
|
|
49
|
+
if (Array.isArray(first)) {
|
|
50
|
+
this.state.value.splice(0, this.state.value.length, ...first);
|
|
51
|
+
} else if (first === "length") {
|
|
52
|
+
this.length = second;
|
|
53
|
+
} else if (typeof first === "number") {
|
|
54
|
+
this.state.value[first] = second;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
_size = new WeakMap();
|
|
59
|
+
function array(value2) {
|
|
60
|
+
return new ReactiveArray(Array.isArray(value2) ? value2 : []);
|
|
61
|
+
}
|
|
62
|
+
function emit(first, second) {
|
|
63
|
+
let { length } = first;
|
|
64
|
+
if (length !== second.length) {
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
let offset = 0;
|
|
68
|
+
if (length >= 100) {
|
|
69
|
+
offset = Math.round(length / 10);
|
|
70
|
+
offset = offset > 25 ? 25 : offset;
|
|
71
|
+
for (let index = 0; index < offset; index += 1) {
|
|
72
|
+
if (!Object.is(first[index], second[index])) {
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
length -= offset;
|
|
78
|
+
for (let index = offset; index < length; index += 1) {
|
|
79
|
+
if (!Object.is(first[index], second[index])) {
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
function setValue(target, property, value$1, state, length) {
|
|
86
|
+
const isIndex = !Number.isNaN(Number(property));
|
|
87
|
+
const isLength = property === "length";
|
|
88
|
+
if (!isIndex && !isLength) {
|
|
89
|
+
return Reflect.set(target, property, value$1);
|
|
90
|
+
}
|
|
91
|
+
const previous = Reflect.get(target, property);
|
|
92
|
+
if (Object.is(previous, value$1)) {
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
Reflect.set(target, property, value$1);
|
|
96
|
+
value.emitValue(state);
|
|
97
|
+
length.set(target.length);
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
function updateArray(type, array2, state, length) {
|
|
101
|
+
const affectsLength = lengthAffectingMethods.has(type);
|
|
102
|
+
const previousArray = affectsLength ? [] : [...array2];
|
|
103
|
+
const previousLength = array2.length;
|
|
104
|
+
return (...args) => {
|
|
105
|
+
const result = array2[type](
|
|
106
|
+
...args
|
|
107
|
+
);
|
|
108
|
+
if (affectsLength ? array2.length !== previousLength : emit(previousArray, array2)) {
|
|
109
|
+
value.emitValue(state);
|
|
110
|
+
length.set(array2.length);
|
|
111
|
+
}
|
|
112
|
+
return result;
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
const lengthAffectingMethods = /* @__PURE__ */ new Set([
|
|
116
|
+
"pop",
|
|
117
|
+
"push",
|
|
118
|
+
"shift",
|
|
119
|
+
"unshift"
|
|
120
|
+
]);
|
|
121
|
+
const updateMethods = /* @__PURE__ */ new Set([
|
|
122
|
+
...lengthAffectingMethods,
|
|
123
|
+
"copyWithin",
|
|
124
|
+
"fill",
|
|
125
|
+
"reverse",
|
|
126
|
+
"sort",
|
|
127
|
+
"splice"
|
|
128
|
+
]);
|
|
129
|
+
exports.ReactiveArray = ReactiveArray;
|
|
130
|
+
exports.array = array;
|
package/dist/array.js
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
var __typeError = (msg) => {
|
|
2
|
+
throw TypeError(msg);
|
|
3
|
+
};
|
|
4
|
+
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
5
|
+
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
6
|
+
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
7
|
+
var _size;
|
|
8
|
+
import { Reactive } from "./reactive.js";
|
|
9
|
+
import { signal } from "./signal.js";
|
|
10
|
+
import { getValue, emitValue } from "./value.js";
|
|
11
|
+
class ReactiveArray extends Reactive {
|
|
12
|
+
constructor(value) {
|
|
13
|
+
super(
|
|
14
|
+
"array",
|
|
15
|
+
new Proxy(value, {
|
|
16
|
+
get: (target, property) => updateMethods.has(property) ? updateArray(property, target, this.state, __privateGet(this, _size)) : Reflect.get(target, property),
|
|
17
|
+
set: (target, property, value2) => setValue(target, property, value2, this.state, __privateGet(this, _size))
|
|
18
|
+
})
|
|
19
|
+
);
|
|
20
|
+
__privateAdd(this, _size, signal(0));
|
|
21
|
+
__privateGet(this, _size).set(value.length);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* The length of the array
|
|
25
|
+
*/
|
|
26
|
+
get length() {
|
|
27
|
+
return __privateGet(this, _size).get();
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Set the length of the array
|
|
31
|
+
*/
|
|
32
|
+
set length(value) {
|
|
33
|
+
if (typeof value === "number" && value >= 0 && value !== this.state.value.length) {
|
|
34
|
+
this.get().length = value;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* @inheritdoc
|
|
39
|
+
*/
|
|
40
|
+
get() {
|
|
41
|
+
return getValue(this.state);
|
|
42
|
+
}
|
|
43
|
+
peek(length) {
|
|
44
|
+
return length === true ? __privateGet(this, _size).peek() : [...this.state.value];
|
|
45
|
+
}
|
|
46
|
+
set(first, second) {
|
|
47
|
+
if (Array.isArray(first)) {
|
|
48
|
+
this.state.value.splice(0, this.state.value.length, ...first);
|
|
49
|
+
} else if (first === "length") {
|
|
50
|
+
this.length = second;
|
|
51
|
+
} else if (typeof first === "number") {
|
|
52
|
+
this.state.value[first] = second;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
_size = new WeakMap();
|
|
57
|
+
function array(value) {
|
|
58
|
+
return new ReactiveArray(Array.isArray(value) ? value : []);
|
|
59
|
+
}
|
|
60
|
+
function emit(first, second) {
|
|
61
|
+
let { length } = first;
|
|
62
|
+
if (length !== second.length) {
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
let offset = 0;
|
|
66
|
+
if (length >= 100) {
|
|
67
|
+
offset = Math.round(length / 10);
|
|
68
|
+
offset = offset > 25 ? 25 : offset;
|
|
69
|
+
for (let index = 0; index < offset; index += 1) {
|
|
70
|
+
if (!Object.is(first[index], second[index])) {
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
length -= offset;
|
|
76
|
+
for (let index = offset; index < length; index += 1) {
|
|
77
|
+
if (!Object.is(first[index], second[index])) {
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
function setValue(target, property, value, state, length) {
|
|
84
|
+
const isIndex = !Number.isNaN(Number(property));
|
|
85
|
+
const isLength = property === "length";
|
|
86
|
+
if (!isIndex && !isLength) {
|
|
87
|
+
return Reflect.set(target, property, value);
|
|
88
|
+
}
|
|
89
|
+
const previous = Reflect.get(target, property);
|
|
90
|
+
if (Object.is(previous, value)) {
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
Reflect.set(target, property, value);
|
|
94
|
+
emitValue(state);
|
|
95
|
+
length.set(target.length);
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
function updateArray(type, array2, state, length) {
|
|
99
|
+
const affectsLength = lengthAffectingMethods.has(type);
|
|
100
|
+
const previousArray = affectsLength ? [] : [...array2];
|
|
101
|
+
const previousLength = array2.length;
|
|
102
|
+
return (...args) => {
|
|
103
|
+
const result = array2[type](
|
|
104
|
+
...args
|
|
105
|
+
);
|
|
106
|
+
if (affectsLength ? array2.length !== previousLength : emit(previousArray, array2)) {
|
|
107
|
+
emitValue(state);
|
|
108
|
+
length.set(array2.length);
|
|
109
|
+
}
|
|
110
|
+
return result;
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
const lengthAffectingMethods = /* @__PURE__ */ new Set([
|
|
114
|
+
"pop",
|
|
115
|
+
"push",
|
|
116
|
+
"shift",
|
|
117
|
+
"unshift"
|
|
118
|
+
]);
|
|
119
|
+
const updateMethods = /* @__PURE__ */ new Set([
|
|
120
|
+
...lengthAffectingMethods,
|
|
121
|
+
"copyWithin",
|
|
122
|
+
"fill",
|
|
123
|
+
"reverse",
|
|
124
|
+
"sort",
|
|
125
|
+
"splice"
|
|
126
|
+
]);
|
|
127
|
+
export {
|
|
128
|
+
ReactiveArray,
|
|
129
|
+
array
|
|
130
|
+
};
|
package/dist/computed.cjs
CHANGED
package/dist/computed.js
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const array = require("./array.cjs");
|
|
3
4
|
const batch = require("./batch.cjs");
|
|
4
5
|
const computed = require("./computed.cjs");
|
|
5
6
|
const effect = require("./effect.cjs");
|
|
6
7
|
const is = require("./is.cjs");
|
|
7
8
|
const signal = require("./signal.cjs");
|
|
9
|
+
exports.array = array.array;
|
|
8
10
|
exports.startBatch = batch.startBatch;
|
|
9
11
|
exports.stopBatch = batch.stopBatch;
|
|
10
12
|
exports.computed = computed.computed;
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { array } from "./array.js";
|
|
1
2
|
import { startBatch, stopBatch } from "./batch.js";
|
|
2
3
|
import { computed } from "./computed.js";
|
|
3
4
|
import { effect } from "./effect.js";
|
|
4
5
|
import { isComputed, isEffect, isReactive, isSignal } from "./is.js";
|
|
5
6
|
import { signal } from "./signal.js";
|
|
6
7
|
export {
|
|
8
|
+
array,
|
|
7
9
|
computed,
|
|
8
10
|
effect,
|
|
9
11
|
isComputed,
|
package/dist/mora.full.js
CHANGED
|
@@ -1,3 +1,76 @@
|
|
|
1
|
+
class Subscription {
|
|
2
|
+
state;
|
|
3
|
+
callback;
|
|
4
|
+
constructor(state, callback) {
|
|
5
|
+
this.state = state;
|
|
6
|
+
this.callback = callback;
|
|
7
|
+
callback(state.value);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
function noop() { }
|
|
11
|
+
function subscribe(state, callback) {
|
|
12
|
+
if (typeof callback !== 'function' || state.subscriptions.has(callback)) {
|
|
13
|
+
return noop;
|
|
14
|
+
}
|
|
15
|
+
state.subscriptions.set(callback, new Subscription(state, callback));
|
|
16
|
+
return () => {
|
|
17
|
+
unsubscribe(state, callback);
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function unsubscribe(state, callback) {
|
|
21
|
+
const subscription = state.subscriptions.get(callback);
|
|
22
|
+
state.subscriptions.delete(callback);
|
|
23
|
+
if (subscription != null) {
|
|
24
|
+
subscription.callback = noop;
|
|
25
|
+
subscription.state = undefined;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
class Reactive {
|
|
30
|
+
state = {
|
|
31
|
+
computeds: new Set(),
|
|
32
|
+
effects: new Set(),
|
|
33
|
+
subscriptions: new Map(),
|
|
34
|
+
value: undefined,
|
|
35
|
+
};
|
|
36
|
+
constructor(name, value) {
|
|
37
|
+
this.state.value = value;
|
|
38
|
+
Object.defineProperty(this, '$mora', {
|
|
39
|
+
value: name,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Get the value _(without reactivity)_
|
|
44
|
+
*/
|
|
45
|
+
peek() {
|
|
46
|
+
return this.state.value;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Subscribe to changes
|
|
50
|
+
*/
|
|
51
|
+
subscribe(callback) {
|
|
52
|
+
return subscribe(this.state, callback);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* JSON representation of the value
|
|
56
|
+
*/
|
|
57
|
+
toJSON() {
|
|
58
|
+
return this.get();
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* String representation of the value
|
|
62
|
+
*/
|
|
63
|
+
toString() {
|
|
64
|
+
return String(this.get());
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Unsubscribe from changes
|
|
68
|
+
*/
|
|
69
|
+
unsubscribe(callback) {
|
|
70
|
+
unsubscribe(this.state, callback);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
1
74
|
class Effect {
|
|
2
75
|
constructor(callback) {
|
|
3
76
|
Object.defineProperty(this, '$mora', {
|
|
@@ -87,67 +160,6 @@ function stopBatch() {
|
|
|
87
160
|
const batchedHandlers = new Set();
|
|
88
161
|
let batchDepth = 0;
|
|
89
162
|
|
|
90
|
-
class Subscription {
|
|
91
|
-
state;
|
|
92
|
-
callback;
|
|
93
|
-
constructor(state, callback) {
|
|
94
|
-
this.state = state;
|
|
95
|
-
this.callback = callback;
|
|
96
|
-
callback(state.value);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
function noop() { }
|
|
100
|
-
function subscribe(state, callback) {
|
|
101
|
-
if (typeof callback !== 'function' || state.subscriptions.has(callback)) {
|
|
102
|
-
return noop;
|
|
103
|
-
}
|
|
104
|
-
state.subscriptions.set(callback, new Subscription(state, callback));
|
|
105
|
-
return () => {
|
|
106
|
-
unsubscribe(state, callback);
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
function unsubscribe(state, callback) {
|
|
110
|
-
const subscription = state.subscriptions.get(callback);
|
|
111
|
-
state.subscriptions.delete(callback);
|
|
112
|
-
if (subscription != null) {
|
|
113
|
-
subscription.callback = noop;
|
|
114
|
-
subscription.state = undefined;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
class Reactive {
|
|
119
|
-
state = {
|
|
120
|
-
computeds: new Set(),
|
|
121
|
-
effects: new Set(),
|
|
122
|
-
subscriptions: new Map(),
|
|
123
|
-
value: undefined,
|
|
124
|
-
};
|
|
125
|
-
constructor(name, value) {
|
|
126
|
-
this.state.value = value;
|
|
127
|
-
Object.defineProperty(this, '$mora', {
|
|
128
|
-
value: name,
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* Get the value _(without reactivity)_
|
|
133
|
-
*/
|
|
134
|
-
peek() {
|
|
135
|
-
return this.state.value;
|
|
136
|
-
}
|
|
137
|
-
/**
|
|
138
|
-
* Subscribe to changes
|
|
139
|
-
*/
|
|
140
|
-
subscribe(callback) {
|
|
141
|
-
return subscribe(this.state, callback);
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* Unsubscribe from changes
|
|
145
|
-
*/
|
|
146
|
-
unsubscribe(callback) {
|
|
147
|
-
unsubscribe(this.state, callback);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
163
|
let activeComputed;
|
|
152
164
|
class Computed extends Reactive {
|
|
153
165
|
effect = {
|
|
@@ -179,7 +191,7 @@ class Computed extends Reactive {
|
|
|
179
191
|
});
|
|
180
192
|
}
|
|
181
193
|
/**
|
|
182
|
-
*
|
|
194
|
+
* @inheritdoc
|
|
183
195
|
*/
|
|
184
196
|
get() {
|
|
185
197
|
if (activeComputed != null && activeComputed !== this) {
|
|
@@ -201,42 +213,52 @@ function computed(callback) {
|
|
|
201
213
|
return new Computed(callback);
|
|
202
214
|
}
|
|
203
215
|
|
|
216
|
+
function emitValue(state) {
|
|
217
|
+
for (const computed of state.computeds) {
|
|
218
|
+
computed.effect.dirty = true;
|
|
219
|
+
}
|
|
220
|
+
for (const effect of state.effects) {
|
|
221
|
+
batchedHandlers.add(effect);
|
|
222
|
+
}
|
|
223
|
+
for (const [, subscription] of state.subscriptions) {
|
|
224
|
+
batchedHandlers.add(subscription);
|
|
225
|
+
}
|
|
226
|
+
if (batchDepth === 0) {
|
|
227
|
+
flushEffects();
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
function getValue(state) {
|
|
231
|
+
if (activeComputed != null) {
|
|
232
|
+
state.computeds.add(activeComputed);
|
|
233
|
+
}
|
|
234
|
+
if (activeEffect != null) {
|
|
235
|
+
state.effects.add(activeEffect);
|
|
236
|
+
}
|
|
237
|
+
return state.value;
|
|
238
|
+
}
|
|
239
|
+
function setValue$1(state, value) {
|
|
240
|
+
if (Object.is(state.value, value)) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
state.value = value;
|
|
244
|
+
emitValue(state);
|
|
245
|
+
}
|
|
246
|
+
|
|
204
247
|
class Signal extends Reactive {
|
|
205
248
|
constructor(value) {
|
|
206
249
|
super('signal', value);
|
|
207
250
|
}
|
|
208
251
|
/**
|
|
209
|
-
*
|
|
252
|
+
* @inheritdoc
|
|
210
253
|
*/
|
|
211
254
|
get() {
|
|
212
|
-
|
|
213
|
-
this.state.computeds.add(activeComputed);
|
|
214
|
-
}
|
|
215
|
-
if (activeEffect != null) {
|
|
216
|
-
this.state.effects.add(activeEffect);
|
|
217
|
-
}
|
|
218
|
-
return this.state.value;
|
|
255
|
+
return getValue(this.state);
|
|
219
256
|
}
|
|
220
257
|
/**
|
|
221
258
|
* Set the value
|
|
222
259
|
*/
|
|
223
260
|
set(value) {
|
|
224
|
-
|
|
225
|
-
return;
|
|
226
|
-
}
|
|
227
|
-
this.state.value = value;
|
|
228
|
-
for (const computed of this.state.computeds) {
|
|
229
|
-
computed.effect.dirty = true;
|
|
230
|
-
}
|
|
231
|
-
for (const effect of this.state.effects) {
|
|
232
|
-
batchedHandlers.add(effect);
|
|
233
|
-
}
|
|
234
|
-
for (const [, subscription] of this.state.subscriptions) {
|
|
235
|
-
batchedHandlers.add(subscription);
|
|
236
|
-
}
|
|
237
|
-
if (batchDepth === 0) {
|
|
238
|
-
flushEffects();
|
|
239
|
-
}
|
|
261
|
+
setValue$1(this.state, value);
|
|
240
262
|
}
|
|
241
263
|
/**
|
|
242
264
|
* Update the value
|
|
@@ -245,8 +267,133 @@ class Signal extends Reactive {
|
|
|
245
267
|
this.set(callback(this.state.value));
|
|
246
268
|
}
|
|
247
269
|
}
|
|
270
|
+
/**
|
|
271
|
+
* Create a reactive value
|
|
272
|
+
*/
|
|
248
273
|
function signal(value) {
|
|
249
274
|
return new Signal(value);
|
|
250
275
|
}
|
|
251
276
|
|
|
252
|
-
|
|
277
|
+
class ReactiveArray extends Reactive {
|
|
278
|
+
#size = signal(0);
|
|
279
|
+
/**
|
|
280
|
+
* The length of the array
|
|
281
|
+
*/
|
|
282
|
+
get length() {
|
|
283
|
+
return this.#size.get();
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Set the length of the array
|
|
287
|
+
*/
|
|
288
|
+
set length(value) {
|
|
289
|
+
if (typeof value === 'number' &&
|
|
290
|
+
value >= 0 &&
|
|
291
|
+
value !== this.state.value.length) {
|
|
292
|
+
this.get().length = value;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
constructor(value) {
|
|
296
|
+
super('array', new Proxy(value, {
|
|
297
|
+
get: (target, property) => updateMethods.has(property)
|
|
298
|
+
? updateArray(property, target, this.state, this.#size)
|
|
299
|
+
: Reflect.get(target, property),
|
|
300
|
+
set: (target, property, value) => setValue(target, property, value, this.state, this.#size),
|
|
301
|
+
}));
|
|
302
|
+
this.#size.set(value.length);
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* @inheritdoc
|
|
306
|
+
*/
|
|
307
|
+
get() {
|
|
308
|
+
return getValue(this.state);
|
|
309
|
+
}
|
|
310
|
+
peek(length) {
|
|
311
|
+
return length === true ? this.#size.peek() : [...this.state.value];
|
|
312
|
+
}
|
|
313
|
+
set(first, second) {
|
|
314
|
+
if (Array.isArray(first)) {
|
|
315
|
+
this.state.value.splice(0, this.state.value.length, ...first);
|
|
316
|
+
}
|
|
317
|
+
else if (first === 'length') {
|
|
318
|
+
this.length = second;
|
|
319
|
+
}
|
|
320
|
+
else if (typeof first === 'number') {
|
|
321
|
+
this.state.value[first] = second;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Create a reactive array
|
|
327
|
+
*/
|
|
328
|
+
function array(value) {
|
|
329
|
+
return new ReactiveArray(Array.isArray(value) ? value : []);
|
|
330
|
+
}
|
|
331
|
+
function emit(first, second) {
|
|
332
|
+
let { length } = first;
|
|
333
|
+
if (length !== second.length) {
|
|
334
|
+
return true;
|
|
335
|
+
}
|
|
336
|
+
let offset = 0;
|
|
337
|
+
if (length >= 100) {
|
|
338
|
+
offset = Math.round(length / 10);
|
|
339
|
+
offset = offset > 25 ? 25 : offset;
|
|
340
|
+
for (let index = 0; index < offset; index += 1) {
|
|
341
|
+
if (!Object.is(first[index], second[index])) {
|
|
342
|
+
return true;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
length -= offset;
|
|
347
|
+
for (let index = offset; index < length; index += 1) {
|
|
348
|
+
if (!Object.is(first[index], second[index])) {
|
|
349
|
+
return true;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
return false;
|
|
353
|
+
}
|
|
354
|
+
function setValue(target, property, value, state, length) {
|
|
355
|
+
const isIndex = !Number.isNaN(Number(property));
|
|
356
|
+
const isLength = property === 'length';
|
|
357
|
+
if (!isIndex && !isLength) {
|
|
358
|
+
return Reflect.set(target, property, value);
|
|
359
|
+
}
|
|
360
|
+
const previous = Reflect.get(target, property);
|
|
361
|
+
if (Object.is(previous, value)) {
|
|
362
|
+
return true;
|
|
363
|
+
}
|
|
364
|
+
Reflect.set(target, property, value);
|
|
365
|
+
emitValue(state);
|
|
366
|
+
length.set(target.length);
|
|
367
|
+
return true;
|
|
368
|
+
}
|
|
369
|
+
function updateArray(type, array, state, length) {
|
|
370
|
+
const affectsLength = lengthAffectingMethods.has(type);
|
|
371
|
+
const previousArray = affectsLength ? [] : [...array];
|
|
372
|
+
const previousLength = array.length;
|
|
373
|
+
return (...args) => {
|
|
374
|
+
const result = array[type](...args);
|
|
375
|
+
if (affectsLength
|
|
376
|
+
? array.length !== previousLength
|
|
377
|
+
: emit(previousArray, array)) {
|
|
378
|
+
emitValue(state);
|
|
379
|
+
length.set(array.length);
|
|
380
|
+
}
|
|
381
|
+
return result;
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
const lengthAffectingMethods = new Set([
|
|
385
|
+
'pop',
|
|
386
|
+
'push',
|
|
387
|
+
'shift',
|
|
388
|
+
'unshift',
|
|
389
|
+
]);
|
|
390
|
+
const updateMethods = new Set([
|
|
391
|
+
...lengthAffectingMethods,
|
|
392
|
+
'copyWithin',
|
|
393
|
+
'fill',
|
|
394
|
+
'reverse',
|
|
395
|
+
'sort',
|
|
396
|
+
'splice',
|
|
397
|
+
]);
|
|
398
|
+
|
|
399
|
+
export { array, computed, effect, isComputed, isEffect, isReactive, isSignal, signal, startBatch, stopBatch };
|
package/dist/reactive.cjs
CHANGED
|
@@ -29,6 +29,18 @@ class Reactive {
|
|
|
29
29
|
subscribe(callback) {
|
|
30
30
|
return subscription.subscribe(this.state, callback);
|
|
31
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* JSON representation of the value
|
|
34
|
+
*/
|
|
35
|
+
toJSON() {
|
|
36
|
+
return this.get();
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* String representation of the value
|
|
40
|
+
*/
|
|
41
|
+
toString() {
|
|
42
|
+
return String(this.get());
|
|
43
|
+
}
|
|
32
44
|
/**
|
|
33
45
|
* Unsubscribe from changes
|
|
34
46
|
*/
|
package/dist/reactive.js
CHANGED
|
@@ -27,6 +27,18 @@ class Reactive {
|
|
|
27
27
|
subscribe(callback) {
|
|
28
28
|
return subscribe(this.state, callback);
|
|
29
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* JSON representation of the value
|
|
32
|
+
*/
|
|
33
|
+
toJSON() {
|
|
34
|
+
return this.get();
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* String representation of the value
|
|
38
|
+
*/
|
|
39
|
+
toString() {
|
|
40
|
+
return String(this.get());
|
|
41
|
+
}
|
|
30
42
|
/**
|
|
31
43
|
* Unsubscribe from changes
|
|
32
44
|
*/
|