@oscarpalmer/mora 0.15.0 → 0.16.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/batch.cjs CHANGED
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const effect = require("./effect.cjs");
4
4
  const helpers_is = require("./helpers/is.cjs");
5
- function flushEffects() {
5
+ function flushHandlers() {
6
6
  while (exports.batchDepth === 0 && batchedHandlers.size > 0) {
7
7
  const handlers = [...batchedHandlers];
8
8
  batchedHandlers.clear();
@@ -22,11 +22,11 @@ function stopBatch() {
22
22
  if (exports.batchDepth > 0) {
23
23
  exports.batchDepth -= 1;
24
24
  }
25
- flushEffects();
25
+ flushHandlers();
26
26
  }
27
27
  const batchedHandlers = /* @__PURE__ */ new Set();
28
28
  exports.batchDepth = 0;
29
29
  exports.batchedHandlers = batchedHandlers;
30
- exports.flushEffects = flushEffects;
30
+ exports.flushHandlers = flushHandlers;
31
31
  exports.startBatch = startBatch;
32
32
  exports.stopBatch = stopBatch;
package/dist/batch.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { runEffect } from "./effect.js";
2
2
  import { isEffect } from "./helpers/is.js";
3
- function flushEffects() {
3
+ function flushHandlers() {
4
4
  while (batchDepth === 0 && batchedHandlers.size > 0) {
5
5
  const handlers = [...batchedHandlers];
6
6
  batchedHandlers.clear();
@@ -20,14 +20,14 @@ function stopBatch() {
20
20
  if (batchDepth > 0) {
21
21
  batchDepth -= 1;
22
22
  }
23
- flushEffects();
23
+ flushHandlers();
24
24
  }
25
25
  const batchedHandlers = /* @__PURE__ */ new Set();
26
26
  let batchDepth = 0;
27
27
  export {
28
28
  batchDepth,
29
29
  batchedHandlers,
30
- flushEffects,
30
+ flushHandlers,
31
31
  startBatch,
32
32
  stopBatch
33
33
  };
@@ -1,8 +1,48 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const batch = require("../batch.cjs");
3
4
  const effect = require("../effect.cjs");
4
5
  const value_computed = require("../value/computed.cjs");
5
- const helpers_emit = require("./emit.cjs");
6
+ function differentArrays(first, second) {
7
+ let { length } = first;
8
+ if (length !== second.length) {
9
+ return true;
10
+ }
11
+ let offset = 0;
12
+ if (length >= 100) {
13
+ offset = Math.round(length / 10);
14
+ offset = offset > 25 ? 25 : offset;
15
+ for (let index = 0; index < offset; index += 1) {
16
+ if (!Object.is(first[index], second[index])) {
17
+ return true;
18
+ }
19
+ }
20
+ }
21
+ length -= offset;
22
+ for (let index = offset; index < length; index += 1) {
23
+ if (!Object.is(first[index], second[index])) {
24
+ return true;
25
+ }
26
+ }
27
+ return false;
28
+ }
29
+ function differentValues(first, second) {
30
+ return Array.isArray(first) && Array.isArray(second) ? differentArrays(first, second) : !Object.is(first, second);
31
+ }
32
+ function emitValue(state) {
33
+ for (const computed of state.computeds) {
34
+ computed.effect.dirty = true;
35
+ }
36
+ for (const effect2 of state.effects) {
37
+ batch.batchedHandlers.add(effect2);
38
+ }
39
+ for (const [, subscription] of state.subscriptions) {
40
+ batch.batchedHandlers.add(subscription);
41
+ }
42
+ if (batch.batchDepth === 0) {
43
+ batch.flushHandlers();
44
+ }
45
+ }
6
46
  function getValue(state) {
7
47
  if (value_computed.activeComputed != null) {
8
48
  state.computeds.add(value_computed.activeComputed);
@@ -12,11 +52,7 @@ function getValue(state) {
12
52
  }
13
53
  return state.value;
14
54
  }
15
- function setValue(state, value) {
16
- if (!Object.is(state.value, value)) {
17
- state.value = value;
18
- helpers_emit.emitValue(state);
19
- }
20
- }
55
+ exports.differentArrays = differentArrays;
56
+ exports.differentValues = differentValues;
57
+ exports.emitValue = emitValue;
21
58
  exports.getValue = getValue;
22
- exports.setValue = setValue;
@@ -1,6 +1,46 @@
1
+ import { batchedHandlers, batchDepth, flushHandlers } from "../batch.js";
1
2
  import { activeEffect } from "../effect.js";
2
3
  import { activeComputed } from "../value/computed.js";
3
- import { emitValue } from "./emit.js";
4
+ function differentArrays(first, second) {
5
+ let { length } = first;
6
+ if (length !== second.length) {
7
+ return true;
8
+ }
9
+ let offset = 0;
10
+ if (length >= 100) {
11
+ offset = Math.round(length / 10);
12
+ offset = offset > 25 ? 25 : offset;
13
+ for (let index = 0; index < offset; index += 1) {
14
+ if (!Object.is(first[index], second[index])) {
15
+ return true;
16
+ }
17
+ }
18
+ }
19
+ length -= offset;
20
+ for (let index = offset; index < length; index += 1) {
21
+ if (!Object.is(first[index], second[index])) {
22
+ return true;
23
+ }
24
+ }
25
+ return false;
26
+ }
27
+ function differentValues(first, second) {
28
+ return Array.isArray(first) && Array.isArray(second) ? differentArrays(first, second) : !Object.is(first, second);
29
+ }
30
+ function emitValue(state) {
31
+ for (const computed of state.computeds) {
32
+ computed.effect.dirty = true;
33
+ }
34
+ for (const effect of state.effects) {
35
+ batchedHandlers.add(effect);
36
+ }
37
+ for (const [, subscription] of state.subscriptions) {
38
+ batchedHandlers.add(subscription);
39
+ }
40
+ if (batchDepth === 0) {
41
+ flushHandlers();
42
+ }
43
+ }
4
44
  function getValue(state) {
5
45
  if (activeComputed != null) {
6
46
  state.computeds.add(activeComputed);
@@ -10,13 +50,9 @@ function getValue(state) {
10
50
  }
11
51
  return state.value;
12
52
  }
13
- function setValue(state, value) {
14
- if (!Object.is(state.value, value)) {
15
- state.value = value;
16
- emitValue(state);
17
- }
18
- }
19
53
  export {
20
- getValue,
21
- setValue
54
+ differentArrays,
55
+ differentValues,
56
+ emitValue,
57
+ getValue
22
58
  };
package/dist/mora.full.js CHANGED
@@ -68,7 +68,7 @@ function effect(callback) {
68
68
  }
69
69
  let activeEffect;
70
70
 
71
- function flushEffects() {
71
+ function flushHandlers() {
72
72
  while (batchDepth === 0 && batchedHandlers.size > 0) {
73
73
  const handlers = [...batchedHandlers];
74
74
  batchedHandlers.clear();
@@ -95,49 +95,11 @@ function stopBatch() {
95
95
  if (batchDepth > 0) {
96
96
  batchDepth -= 1;
97
97
  }
98
- flushEffects();
98
+ flushHandlers();
99
99
  }
100
100
  const batchedHandlers = new Set();
101
101
  let batchDepth = 0;
102
102
 
103
- function emitArrayChanges(first, second) {
104
- let { length } = first;
105
- if (length !== second.length) {
106
- return true;
107
- }
108
- let offset = 0;
109
- if (length >= 100) {
110
- offset = Math.round(length / 10);
111
- offset = offset > 25 ? 25 : offset;
112
- for (let index = 0; index < offset; index += 1) {
113
- if (!Object.is(first[index], second[index])) {
114
- return true;
115
- }
116
- }
117
- }
118
- length -= offset;
119
- for (let index = offset; index < length; index += 1) {
120
- if (!Object.is(first[index], second[index])) {
121
- return true;
122
- }
123
- }
124
- return false;
125
- }
126
- function emitValue(state) {
127
- for (const computed of state.computeds) {
128
- computed.effect.dirty = true;
129
- }
130
- for (const effect of state.effects) {
131
- batchedHandlers.add(effect);
132
- }
133
- for (const [, subscription] of state.subscriptions) {
134
- batchedHandlers.add(subscription);
135
- }
136
- if (batchDepth === 0) {
137
- flushEffects();
138
- }
139
- }
140
-
141
103
  class Subscription {
142
104
  state;
143
105
  callback;
@@ -245,7 +207,7 @@ class Computed extends Reactive {
245
207
  * @inheritdoc
246
208
  */
247
209
  get() {
248
- if (activeComputed != null && activeComputed !== this) {
210
+ if (activeComputed != null && this !== activeComputed) {
249
211
  this.state.computeds.add(activeComputed);
250
212
  }
251
213
  if (activeEffect != null && activeEffect !== this.effect.instance) {
@@ -264,6 +226,48 @@ function computed(callback) {
264
226
  return new Computed(callback);
265
227
  }
266
228
 
229
+ function differentArrays(first, second) {
230
+ let { length } = first;
231
+ if (length !== second.length) {
232
+ return true;
233
+ }
234
+ let offset = 0;
235
+ if (length >= 100) {
236
+ offset = Math.round(length / 10);
237
+ offset = offset > 25 ? 25 : offset;
238
+ for (let index = 0; index < offset; index += 1) {
239
+ if (!Object.is(first[index], second[index])) {
240
+ return true;
241
+ }
242
+ }
243
+ }
244
+ length -= offset;
245
+ for (let index = offset; index < length; index += 1) {
246
+ if (!Object.is(first[index], second[index])) {
247
+ return true;
248
+ }
249
+ }
250
+ return false;
251
+ }
252
+ function differentValues(first, second) {
253
+ return Array.isArray(first) && Array.isArray(second)
254
+ ? differentArrays(first, second)
255
+ : !Object.is(first, second);
256
+ }
257
+ function emitValue(state) {
258
+ for (const computed of state.computeds) {
259
+ computed.effect.dirty = true;
260
+ }
261
+ for (const effect of state.effects) {
262
+ batchedHandlers.add(effect);
263
+ }
264
+ for (const [, subscription] of state.subscriptions) {
265
+ batchedHandlers.add(subscription);
266
+ }
267
+ if (batchDepth === 0) {
268
+ flushHandlers();
269
+ }
270
+ }
267
271
  function getValue(state) {
268
272
  if (activeComputed != null) {
269
273
  state.computeds.add(activeComputed);
@@ -273,12 +277,6 @@ function getValue(state) {
273
277
  }
274
278
  return state.value;
275
279
  }
276
- function setValue$1(state, value) {
277
- if (!Object.is(state.value, value)) {
278
- state.value = value;
279
- emitValue(state);
280
- }
281
- }
282
280
 
283
281
  class Signal extends Reactive {
284
282
  constructor(value) {
@@ -294,7 +292,10 @@ class Signal extends Reactive {
294
292
  * Set the value
295
293
  */
296
294
  set(value) {
297
- setValue$1(this.state, value);
295
+ if (differentValues(this.state.value, value)) {
296
+ this.state.value = value;
297
+ emitValue(this.state);
298
+ }
298
299
  }
299
300
  /**
300
301
  * Update the value
@@ -343,6 +344,12 @@ class ReactiveArray extends Reactive {
343
344
  at(index) {
344
345
  return this.get().at(index);
345
346
  }
347
+ /**
348
+ * Clear the array
349
+ */
350
+ clear() {
351
+ this.length = 0;
352
+ }
346
353
  /**
347
354
  * @inheritdoc
348
355
  */
@@ -434,7 +441,7 @@ function updateArray(type, array, state, length) {
434
441
  const result = array[type](...args);
435
442
  if (affectsLength
436
443
  ? array.length !== previousLength
437
- : emitArrayChanges(previousArray, array)) {
444
+ : differentArrays(previousArray, array)) {
438
445
  emitValue(state);
439
446
  length.set(array.length);
440
447
  }
@@ -7,7 +7,6 @@ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read fr
7
7
  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);
8
8
  var _size;
9
9
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
10
- const helpers_emit = require("../helpers/emit.cjs");
11
10
  const helpers_is = require("../helpers/is.cjs");
12
11
  const helpers_value = require("../helpers/value.cjs");
13
12
  const value_computed = require("./computed.cjs");
@@ -45,6 +44,12 @@ class ReactiveArray extends value_reactive.Reactive {
45
44
  at(index) {
46
45
  return this.get().at(index);
47
46
  }
47
+ /**
48
+ * Clear the array
49
+ */
50
+ clear() {
51
+ this.length = 0;
52
+ }
48
53
  /**
49
54
  * @inheritdoc
50
55
  */
@@ -123,7 +128,7 @@ function setValue(target, property, value, state, length) {
123
128
  const previous = Reflect.get(target, property);
124
129
  if (!Object.is(previous, value)) {
125
130
  Reflect.set(target, property, value);
126
- helpers_emit.emitValue(state);
131
+ helpers_value.emitValue(state);
127
132
  length.set(target.length);
128
133
  }
129
134
  return true;
@@ -136,8 +141,8 @@ function updateArray(type, array2, state, length) {
136
141
  const result = array2[type](
137
142
  ...args
138
143
  );
139
- if (affectsLength ? array2.length !== previousLength : helpers_emit.emitArrayChanges(previousArray, array2)) {
140
- helpers_emit.emitValue(state);
144
+ if (affectsLength ? array2.length !== previousLength : helpers_value.differentArrays(previousArray, array2)) {
145
+ helpers_value.emitValue(state);
141
146
  length.set(array2.length);
142
147
  }
143
148
  return result;
@@ -5,9 +5,8 @@ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot
5
5
  var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
6
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
7
  var _size;
8
- import { emitValue, emitArrayChanges } from "../helpers/emit.js";
9
8
  import { arrayName } from "../helpers/is.js";
10
- import { getValue } from "../helpers/value.js";
9
+ import { getValue, emitValue, differentArrays } from "../helpers/value.js";
11
10
  import { computed } from "./computed.js";
12
11
  import { Reactive } from "./reactive.js";
13
12
  import { signal } from "./signal.js";
@@ -43,6 +42,12 @@ class ReactiveArray extends Reactive {
43
42
  at(index) {
44
43
  return this.get().at(index);
45
44
  }
45
+ /**
46
+ * Clear the array
47
+ */
48
+ clear() {
49
+ this.length = 0;
50
+ }
46
51
  /**
47
52
  * @inheritdoc
48
53
  */
@@ -134,7 +139,7 @@ function updateArray(type, array2, state, length) {
134
139
  const result = array2[type](
135
140
  ...args
136
141
  );
137
- if (affectsLength ? array2.length !== previousLength : emitArrayChanges(previousArray, array2)) {
142
+ if (affectsLength ? array2.length !== previousLength : differentArrays(previousArray, array2)) {
138
143
  emitValue(state);
139
144
  length.set(array2.length);
140
145
  }
@@ -41,7 +41,7 @@ class Computed extends value_reactive.Reactive {
41
41
  * @inheritdoc
42
42
  */
43
43
  get() {
44
- if (exports.activeComputed != null && exports.activeComputed !== this) {
44
+ if (exports.activeComputed != null && this !== exports.activeComputed) {
45
45
  this.state.computeds.add(exports.activeComputed);
46
46
  }
47
47
  if (effect.activeEffect != null && effect.activeEffect !== this.effect.instance) {
@@ -39,7 +39,7 @@ class Computed extends Reactive {
39
39
  * @inheritdoc
40
40
  */
41
41
  get() {
42
- if (activeComputed != null && activeComputed !== this) {
42
+ if (activeComputed != null && this !== activeComputed) {
43
43
  this.state.computeds.add(activeComputed);
44
44
  }
45
45
  if (activeEffect != null && activeEffect !== this.effect.instance) {
@@ -17,7 +17,10 @@ class Signal extends value_reactive.Reactive {
17
17
  * Set the value
18
18
  */
19
19
  set(value) {
20
- helpers_value.setValue(this.state, value);
20
+ if (helpers_value.differentValues(this.state.value, value)) {
21
+ this.state.value = value;
22
+ helpers_value.emitValue(this.state);
23
+ }
21
24
  }
22
25
  /**
23
26
  * Update the value
@@ -1,5 +1,5 @@
1
1
  import { signalName } from "../helpers/is.js";
2
- import { getValue, setValue } from "../helpers/value.js";
2
+ import { getValue, differentValues, emitValue } from "../helpers/value.js";
3
3
  import { Reactive } from "./reactive.js";
4
4
  class Signal extends Reactive {
5
5
  constructor(value) {
@@ -15,7 +15,10 @@ class Signal extends Reactive {
15
15
  * Set the value
16
16
  */
17
17
  set(value) {
18
- setValue(this.state, value);
18
+ if (differentValues(this.state.value, value)) {
19
+ this.state.value = value;
20
+ emitValue(this.state);
21
+ }
19
22
  }
20
23
  /**
21
24
  * Update the value
package/package.json CHANGED
@@ -12,14 +12,14 @@
12
12
  "@rollup/plugin-node-resolve": "^16",
13
13
  "@rollup/plugin-typescript": "^12.1",
14
14
  "@types/node": "^22.15",
15
- "@vitest/coverage-istanbul": "^3.1",
15
+ "@vitest/coverage-istanbul": "^3.2",
16
16
  "dts-bundle-generator": "^9.5",
17
17
  "glob": "^11",
18
18
  "jsdom": "^26.1",
19
19
  "tslib": "^2.8",
20
20
  "typescript": "^5.8",
21
21
  "vite": "^6.3",
22
- "vitest": "^3.1"
22
+ "vitest": "^3.2"
23
23
  },
24
24
  "exports": {
25
25
  ".": {
@@ -54,5 +54,5 @@
54
54
  },
55
55
  "type": "module",
56
56
  "types": "./types/index.d.ts",
57
- "version": "0.15.0"
57
+ "version": "0.16.0"
58
58
  }
package/src/batch.ts CHANGED
@@ -2,7 +2,7 @@ import {type Effect, runEffect} from './effect';
2
2
  import {isEffect} from './helpers/is';
3
3
  import type {Subscription} from './subscription';
4
4
 
5
- export function flushEffects(): void {
5
+ export function flushHandlers(): void {
6
6
  while (batchDepth === 0 && batchedHandlers.size > 0) {
7
7
  const handlers = [...batchedHandlers];
8
8
 
@@ -33,7 +33,7 @@ export function stopBatch(): void {
33
33
  batchDepth -= 1;
34
34
  }
35
35
 
36
- flushEffects();
36
+ flushHandlers();
37
37
  }
38
38
 
39
39
  export const batchedHandlers = new Set<Effect | Subscription<unknown>>();
package/src/helpers/is.ts CHANGED
@@ -3,7 +3,7 @@ import type {Effect} from '../effect';
3
3
  import type {ReactiveArray} from '../value/array';
4
4
  import type {Computed} from '../value/computed';
5
5
  import type {Reactive} from '../value/reactive';
6
- import {signal, type Signal} from '../value/signal';
6
+ import type {Signal} from '../value/signal';
7
7
 
8
8
  /**
9
9
  * Is the value a reactive array?
@@ -1,7 +1,62 @@
1
+ import {batchDepth, batchedHandlers, flushHandlers} from '../batch';
1
2
  import {activeEffect} from '../effect';
2
- import {activeComputed} from '../value/computed';
3
+ import {type InternalComputed, activeComputed} from '../value/computed';
3
4
  import type {ReactiveState} from '../value/reactive';
4
- import {emitValue} from './emit';
5
+
6
+ export function differentArrays(first: unknown[], second: unknown[]): boolean {
7
+ let {length} = first;
8
+
9
+ if (length !== second.length) {
10
+ return true;
11
+ }
12
+
13
+ let offset = 0;
14
+
15
+ if (length >= 100) {
16
+ offset = Math.round(length / 10);
17
+ offset = offset > 25 ? 25 : offset;
18
+
19
+ for (let index = 0; index < offset; index += 1) {
20
+ if (!Object.is(first[index], second[index])) {
21
+ return true;
22
+ }
23
+ }
24
+ }
25
+
26
+ length -= offset;
27
+
28
+ for (let index = offset; index < length; index += 1) {
29
+ if (!Object.is(first[index], second[index])) {
30
+ return true;
31
+ }
32
+ }
33
+
34
+ return false;
35
+ }
36
+
37
+ export function differentValues(first: unknown, second: unknown): boolean {
38
+ return Array.isArray(first) && Array.isArray(second)
39
+ ? differentArrays(first, second)
40
+ : !Object.is(first, second);
41
+ }
42
+
43
+ export function emitValue<Value>(state: ReactiveState<Value>): void {
44
+ for (const computed of state.computeds) {
45
+ (computed as unknown as InternalComputed).effect.dirty = true;
46
+ }
47
+
48
+ for (const effect of state.effects) {
49
+ batchedHandlers.add(effect);
50
+ }
51
+
52
+ for (const [, subscription] of state.subscriptions) {
53
+ batchedHandlers.add(subscription as never);
54
+ }
55
+
56
+ if (batchDepth === 0) {
57
+ flushHandlers();
58
+ }
59
+ }
5
60
 
6
61
  export function getValue<Value>(state: ReactiveState<Value>): Value {
7
62
  if (activeComputed != null) {
@@ -14,14 +69,3 @@ export function getValue<Value>(state: ReactiveState<Value>): Value {
14
69
 
15
70
  return state.value;
16
71
  }
17
-
18
- export function setValue<Value>(
19
- state: ReactiveState<Value>,
20
- value: Value,
21
- ): void {
22
- if (!Object.is(state.value, value)) {
23
- state.value = value;
24
-
25
- emitValue(state);
26
- }
27
- }
@@ -1,6 +1,5 @@
1
- import {emitArrayChanges, emitValue} from '../helpers/emit';
2
1
  import {arrayName} from '../helpers/is';
3
- import {getValue} from '../helpers/value';
2
+ import {differentArrays, emitValue, getValue} from '../helpers/value';
4
3
  import {type Computed, computed} from './computed';
5
4
  import {Reactive, type ReactiveState} from './reactive';
6
5
  import {type Signal, signal} from './signal';
@@ -51,6 +50,13 @@ export class ReactiveArray<Item> extends Reactive<Item[]> {
51
50
  return this.get().at(index);
52
51
  }
53
52
 
53
+ /**
54
+ * Clear the array
55
+ */
56
+ clear(): void {
57
+ this.length = 0;
58
+ }
59
+
54
60
  /**
55
61
  * @inheritdoc
56
62
  */
@@ -207,7 +213,7 @@ function updateArray<Item>(
207
213
  if (
208
214
  affectsLength
209
215
  ? array.length !== previousLength
210
- : emitArrayChanges(previousArray, array)
216
+ : differentArrays(previousArray, array)
211
217
  ) {
212
218
  emitValue(state);
213
219
 
@@ -3,7 +3,7 @@ import {type Effect, activeEffect, effect, runEffect} from '../effect';
3
3
  import {computedName} from '../helpers/is';
4
4
  import {Reactive, type ReactiveState} from './reactive';
5
5
 
6
- type ComputedEffect = {
6
+ export type ComputedEffect = {
7
7
  dirty: boolean;
8
8
  instance: Effect;
9
9
  };
@@ -59,7 +59,7 @@ export class Computed<Value> extends Reactive<Value> {
59
59
  * @inheritdoc
60
60
  */
61
61
  get(): Value {
62
- if (activeComputed != null && activeComputed !== this) {
62
+ if (activeComputed != null && this !== activeComputed) {
63
63
  this.state.computeds.add(activeComputed);
64
64
  }
65
65
 
@@ -1,5 +1,5 @@
1
1
  import {signalName} from '../helpers/is';
2
- import {getValue, setValue} from '../helpers/value';
2
+ import {differentValues, emitValue, getValue} from '../helpers/value';
3
3
  import {Reactive} from './reactive';
4
4
 
5
5
  export class Signal<Value> extends Reactive<Value> {
@@ -18,7 +18,11 @@ export class Signal<Value> extends Reactive<Value> {
18
18
  * Set the value
19
19
  */
20
20
  set(value: Value): void {
21
- setValue(this.state, value);
21
+ if (differentValues(this.state.value, value)) {
22
+ this.state.value = value;
23
+
24
+ emitValue(this.state);
25
+ }
22
26
  }
23
27
 
24
28
  /**
package/types/batch.d.cts CHANGED
@@ -57,7 +57,7 @@ declare class Subscription<Value> {
57
57
  * Unsubscribe from changes
58
58
  */
59
59
  export type Unsubscribe = () => void;
60
- export declare function flushEffects(): void;
60
+ export declare function flushHandlers(): void;
61
61
  /**
62
62
  * Start batching effects _(use `stopBatch` to flush and run batched effects)_
63
63
  */
package/types/batch.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { type Effect } from './effect';
2
2
  import type { Subscription } from './subscription';
3
- export declare function flushEffects(): void;
3
+ export declare function flushHandlers(): void;
4
4
  /**
5
5
  * Start batching effects _(use `stopBatch` to flush and run batched effects)_
6
6
  */
@@ -72,6 +72,10 @@ declare class ReactiveArray<Item> extends Reactive<Item[]> {
72
72
  * Get an indexed item
73
73
  */
74
74
  at(index: number): Item | undefined;
75
+ /**
76
+ * Clear the array
77
+ */
78
+ clear(): void;
75
79
  /**
76
80
  * @inheritdoc
77
81
  */
@@ -2,7 +2,7 @@ import type { Effect } from '../effect';
2
2
  import type { ReactiveArray } from '../value/array';
3
3
  import type { Computed } from '../value/computed';
4
4
  import type { Reactive } from '../value/reactive';
5
- import { type Signal } from '../value/signal';
5
+ import type { Signal } from '../value/signal';
6
6
  /**
7
7
  * Is the value a reactive array?
8
8
  */
@@ -57,7 +57,9 @@ declare class Subscription<Value> {
57
57
  * Unsubscribe from changes
58
58
  */
59
59
  export type Unsubscribe = () => void;
60
+ export declare function differentArrays(first: unknown[], second: unknown[]): boolean;
61
+ export declare function differentValues(first: unknown, second: unknown): boolean;
62
+ export declare function emitValue<Value>(state: ReactiveState<Value>): void;
60
63
  export declare function getValue<Value>(state: ReactiveState<Value>): Value;
61
- export declare function setValue<Value>(state: ReactiveState<Value>, value: Value): void;
62
64
 
63
65
  export {};
@@ -1,3 +1,5 @@
1
1
  import type { ReactiveState } from '../value/reactive';
2
+ export declare function differentArrays(first: unknown[], second: unknown[]): boolean;
3
+ export declare function differentValues(first: unknown, second: unknown): boolean;
4
+ export declare function emitValue<Value>(state: ReactiveState<Value>): void;
2
5
  export declare function getValue<Value>(state: ReactiveState<Value>): Value;
3
- export declare function setValue<Value>(state: ReactiveState<Value>, value: Value): void;
package/types/index.d.cts CHANGED
@@ -88,6 +88,10 @@ export declare class ReactiveArray<Item> extends Reactive<Item[]> {
88
88
  * Get an indexed item
89
89
  */
90
90
  at(index: number): Item | undefined;
91
+ /**
92
+ * Clear the array
93
+ */
94
+ clear(): void;
91
95
  /**
92
96
  * @inheritdoc
93
97
  */
@@ -72,6 +72,10 @@ export declare class ReactiveArray<Item> extends Reactive<Item[]> {
72
72
  * Get an indexed item
73
73
  */
74
74
  at(index: number): Item | undefined;
75
+ /**
76
+ * Clear the array
77
+ */
78
+ clear(): void;
75
79
  /**
76
80
  * @inheritdoc
77
81
  */
@@ -15,6 +15,10 @@ export declare class ReactiveArray<Item> extends Reactive<Item[]> {
15
15
  * Get an indexed item
16
16
  */
17
17
  at(index: number): Item | undefined;
18
+ /**
19
+ * Clear the array
20
+ */
21
+ clear(): void;
18
22
  /**
19
23
  * @inheritdoc
20
24
  */
@@ -1,6 +1,6 @@
1
1
  import { type Effect } from '../effect';
2
2
  import { Reactive, type ReactiveState } from './reactive';
3
- type ComputedEffect = {
3
+ export type ComputedEffect = {
4
4
  dirty: boolean;
5
5
  instance: Effect;
6
6
  };
@@ -21,4 +21,3 @@ export declare class Computed<Value> extends Reactive<Value> {
21
21
  * Create a computed value
22
22
  */
23
23
  export declare function computed<Value>(callback: () => Value): Computed<Value>;
24
- export {};
@@ -1,42 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const batch = require("../batch.cjs");
4
- function emitArrayChanges(first, second) {
5
- let { length } = first;
6
- if (length !== second.length) {
7
- return true;
8
- }
9
- let offset = 0;
10
- if (length >= 100) {
11
- offset = Math.round(length / 10);
12
- offset = offset > 25 ? 25 : offset;
13
- for (let index = 0; index < offset; index += 1) {
14
- if (!Object.is(first[index], second[index])) {
15
- return true;
16
- }
17
- }
18
- }
19
- length -= offset;
20
- for (let index = offset; index < length; index += 1) {
21
- if (!Object.is(first[index], second[index])) {
22
- return true;
23
- }
24
- }
25
- return false;
26
- }
27
- function emitValue(state) {
28
- for (const computed of state.computeds) {
29
- computed.effect.dirty = true;
30
- }
31
- for (const effect of state.effects) {
32
- batch.batchedHandlers.add(effect);
33
- }
34
- for (const [, subscription] of state.subscriptions) {
35
- batch.batchedHandlers.add(subscription);
36
- }
37
- if (batch.batchDepth === 0) {
38
- batch.flushEffects();
39
- }
40
- }
41
- exports.emitArrayChanges = emitArrayChanges;
42
- exports.emitValue = emitValue;
@@ -1,42 +0,0 @@
1
- import { batchedHandlers, batchDepth, flushEffects } from "../batch.js";
2
- function emitArrayChanges(first, second) {
3
- let { length } = first;
4
- if (length !== second.length) {
5
- return true;
6
- }
7
- let offset = 0;
8
- if (length >= 100) {
9
- offset = Math.round(length / 10);
10
- offset = offset > 25 ? 25 : offset;
11
- for (let index = 0; index < offset; index += 1) {
12
- if (!Object.is(first[index], second[index])) {
13
- return true;
14
- }
15
- }
16
- }
17
- length -= offset;
18
- for (let index = offset; index < length; index += 1) {
19
- if (!Object.is(first[index], second[index])) {
20
- return true;
21
- }
22
- }
23
- return false;
24
- }
25
- function emitValue(state) {
26
- for (const computed of state.computeds) {
27
- computed.effect.dirty = true;
28
- }
29
- for (const effect of state.effects) {
30
- batchedHandlers.add(effect);
31
- }
32
- for (const [, subscription] of state.subscriptions) {
33
- batchedHandlers.add(subscription);
34
- }
35
- if (batchDepth === 0) {
36
- flushEffects();
37
- }
38
- }
39
- export {
40
- emitArrayChanges,
41
- emitValue
42
- };
@@ -1,52 +0,0 @@
1
- import {batchDepth, batchedHandlers, flushEffects} from '../batch';
2
- import type {InternalComputed} from '../value/computed';
3
- import type {ReactiveState} from '../value/reactive';
4
-
5
- export function emitArrayChanges(first: unknown[], second: unknown[]): boolean {
6
- let {length} = first;
7
-
8
- if (length !== second.length) {
9
- return true;
10
- }
11
-
12
- let offset = 0;
13
-
14
- if (length >= 100) {
15
- offset = Math.round(length / 10);
16
- offset = offset > 25 ? 25 : offset;
17
-
18
- for (let index = 0; index < offset; index += 1) {
19
- if (!Object.is(first[index], second[index])) {
20
- return true;
21
- }
22
- }
23
- }
24
-
25
- length -= offset;
26
-
27
- for (let index = offset; index < length; index += 1) {
28
- if (!Object.is(first[index], second[index])) {
29
- return true;
30
- }
31
- }
32
-
33
- return false;
34
- }
35
-
36
- export function emitValue<Value>(state: ReactiveState<Value>): void {
37
- for (const computed of state.computeds) {
38
- (computed as unknown as InternalComputed).effect.dirty = true;
39
- }
40
-
41
- for (const effect of state.effects) {
42
- batchedHandlers.add(effect);
43
- }
44
-
45
- for (const [, subscription] of state.subscriptions) {
46
- batchedHandlers.add(subscription as never);
47
- }
48
-
49
- if (batchDepth === 0) {
50
- flushEffects();
51
- }
52
- }
@@ -1,63 +0,0 @@
1
- // Generated by dts-bundle-generator v9.5.1
2
-
3
- export type GenericCallback = (...args: any[]) => any;
4
- declare class Effect {
5
- private readonly $mora;
6
- private readonly state;
7
- constructor(callback: GenericCallback);
8
- }
9
- declare class Computed<Value> extends Reactive<Value> {
10
- private readonly effect;
11
- constructor(callback: () => Value);
12
- /**
13
- * @inheritdoc
14
- */
15
- get(): Value;
16
- }
17
- declare abstract class Reactive<Value> {
18
- protected readonly state: ReactiveState<Value>;
19
- constructor(name: string, value: Value);
20
- /**
21
- * Get the value
22
- */
23
- abstract get(): Value;
24
- /**
25
- * Get the value _(without reactivity)_
26
- */
27
- peek(): Value;
28
- /**
29
- * Subscribe to changes
30
- */
31
- subscribe(callback: (value: Value) => void): Unsubscribe;
32
- /**
33
- * JSON representation of the value
34
- */
35
- toJSON(): Value;
36
- /**
37
- * String representation of the value
38
- */
39
- toString(): string;
40
- /**
41
- * Unsubscribe from changes
42
- */
43
- unsubscribe(callback: (value: Value) => void): void;
44
- }
45
- export type ReactiveState<Value> = {
46
- computeds: Set<Computed<unknown>>;
47
- effects: Set<Effect>;
48
- subscriptions: Map<(value: Value) => void, Subscription<Value>>;
49
- value: Value;
50
- };
51
- declare class Subscription<Value> {
52
- state: ReactiveState<Value>;
53
- callback: GenericCallback;
54
- constructor(state: ReactiveState<Value>, callback: GenericCallback);
55
- }
56
- /**
57
- * Unsubscribe from changes
58
- */
59
- export type Unsubscribe = () => void;
60
- export declare function emitArrayChanges(first: unknown[], second: unknown[]): boolean;
61
- export declare function emitValue<Value>(state: ReactiveState<Value>): void;
62
-
63
- export {};
@@ -1,3 +0,0 @@
1
- import type { ReactiveState } from '../value/reactive';
2
- export declare function emitArrayChanges(first: unknown[], second: unknown[]): boolean;
3
- export declare function emitValue<Value>(state: ReactiveState<Value>): void;