@retreon/cells 0.1.1 → 0.2.0-2025-06-23.7d6d015
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +83 -95
- package/dist/cells.cjs +1 -1
- package/dist/cells.d.ts +8 -7
- package/dist/cells.js +69 -71
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -5,162 +5,150 @@
|
|
|
5
5
|
|
|
6
6
|
## Purpose
|
|
7
7
|
|
|
8
|
-
Retreon Cells is an implementation of Signals.
|
|
8
|
+
Retreon Cells is an implementation of [Signals](https://dev.to/this-is-learning/the-evolution-of-signals-in-javascript-8ob) with first-class support for **[Volatile Functions](https://learn.microsoft.com/en-us/office/dev/add-ins/excel/custom-functions-volatile)**, a primitive for binding external data sources.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
This is a low-level library. It biases towards power and expressiveness over safety and convenience. As such, several components are out of scope:
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
- Error caching
|
|
13
|
+
- Cycle detection
|
|
14
|
+
- Effect management
|
|
13
15
|
|
|
14
|
-
|
|
16
|
+
## Other Projects
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
There are many high-quality libraries implementing signal-based reactivity:
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
- [SolidJS Signals](https://github.com/solidjs/signals)
|
|
21
|
+
- [Preact Signals](https://github.com/preactjs/signals)
|
|
22
|
+
- [Alien Signals](https://github.com/stackblitz/alien-signals) (used by Vue, XState, many others)
|
|
23
|
+
- [TC39 Proposal Reference Implementation](https://github.com/proposal-signals/signal-polyfill)
|
|
19
24
|
|
|
20
|
-
|
|
25
|
+
`@retreon/cells` exists to explore the space of Volatile Functions and serve as a concrete example of how it might work in practice. It spawned out of a discussion thread [here](https://github.com/tc39/proposal-signals/issues/237).
|
|
26
|
+
|
|
27
|
+
## Overview
|
|
28
|
+
|
|
29
|
+
- **Cell:** Holds a value. Can only be read or replaced.
|
|
30
|
+
- **Source:** Similar to a cell, but binds to externally owned data.
|
|
31
|
+
- **Formula:** Computes a cached value using cells, sources, or other formulas.
|
|
32
|
+
- **Watcher:** Listens for changes on a cell, source, or formula.
|
|
21
33
|
|
|
22
34
|
## Installation
|
|
23
35
|
|
|
24
36
|
```bash
|
|
25
|
-
npm install @retreon/cells
|
|
37
|
+
npm install --save @retreon/cells
|
|
26
38
|
```
|
|
27
39
|
|
|
28
|
-
##
|
|
40
|
+
## API
|
|
41
|
+
|
|
42
|
+
### `cell`
|
|
43
|
+
|
|
44
|
+
Creates a mutable value container. Like a spreadsheet cell, it holds a value that can be updated.
|
|
29
45
|
|
|
30
46
|
```ts
|
|
31
|
-
|
|
47
|
+
const count = cell(0);
|
|
48
|
+
```
|
|
32
49
|
|
|
33
|
-
|
|
34
|
-
const quantity = cell(2);
|
|
35
|
-
const price = cell(19.99);
|
|
50
|
+
### `source`
|
|
36
51
|
|
|
37
|
-
|
|
38
|
-
const total = formula(() => get(quantity) * get(price));
|
|
52
|
+
Binds to an untracked data source. Examples are `window.innerHeight`, `document.visibilityState`, `localStorage.getItem()`, or any value that changes over time.
|
|
39
53
|
|
|
40
|
-
|
|
41
|
-
const
|
|
42
|
-
() =>
|
|
54
|
+
```ts
|
|
55
|
+
const viewport = source(
|
|
56
|
+
() => ({
|
|
57
|
+
width: window.innerWidth,
|
|
58
|
+
height: window.innerHeight,
|
|
59
|
+
}),
|
|
43
60
|
(onChange) => {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return () => clearInterval(interval);
|
|
61
|
+
window.addEventListener('resize', onChange);
|
|
62
|
+
return () => window.removeEventListener('resize', onChange);
|
|
47
63
|
},
|
|
48
64
|
);
|
|
49
|
-
|
|
50
|
-
// Composed formula using both stable and volatile data
|
|
51
|
-
const receipt = formula(() => ({
|
|
52
|
-
total: get(total),
|
|
53
|
-
time: get(timestamp),
|
|
54
|
-
}));
|
|
55
|
-
|
|
56
|
-
// Read values
|
|
57
|
-
console.log(get(receipt));
|
|
58
|
-
// { total: 39.98, time: 1577836800000 }
|
|
59
|
-
|
|
60
|
-
// Update state atomically
|
|
61
|
-
batch((swap) => {
|
|
62
|
-
swap(quantity, 3);
|
|
63
|
-
swap(price, 24.99);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
// Watch for changes
|
|
67
|
-
const dispose = watch(total, () => {
|
|
68
|
-
console.log(`Total changed to: ${get(total)}`);
|
|
69
|
-
});
|
|
70
65
|
```
|
|
71
66
|
|
|
72
|
-
|
|
67
|
+
Sources run in two modes:
|
|
73
68
|
|
|
74
|
-
|
|
69
|
+
- **Volatile (unwatched):** Every read is fresh, not cached.
|
|
70
|
+
- **Non-Volatile (watched):** Reads are cached and only recomputed when necessary.
|
|
75
71
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
```ts
|
|
79
|
-
const count = cell(0);
|
|
80
|
-
```
|
|
72
|
+
Sources start volatile until they become watched. If a `subscribe()` handler is provided, the source upgrades to non-volatile and only triggers changes when it calls `onChange`.
|
|
81
73
|
|
|
82
|
-
### `formula
|
|
74
|
+
### `formula`
|
|
83
75
|
|
|
84
|
-
|
|
76
|
+
Formulas compute a value using cells and sources. The result is cached until a dependency changes.
|
|
85
77
|
|
|
86
78
|
```ts
|
|
87
79
|
const doubled = formula(() => get(count) * 2);
|
|
88
80
|
```
|
|
89
81
|
|
|
90
|
-
|
|
82
|
+
Formulas that depend on volatile sources are never cached and will always re-evaluate.
|
|
91
83
|
|
|
92
|
-
|
|
84
|
+
### `get`
|
|
93
85
|
|
|
94
|
-
|
|
95
|
-
// Volatile: always fresh
|
|
96
|
-
const random = source(() => Math.random());
|
|
86
|
+
Reads the current value of a source, cell, or formula.
|
|
97
87
|
|
|
98
|
-
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
(onChange) => {
|
|
102
|
-
window.addEventListener('resize', onChange);
|
|
103
|
-
return () => window.removeEventListener('resize', onChange);
|
|
104
|
-
},
|
|
105
|
-
);
|
|
88
|
+
```ts
|
|
89
|
+
const value = cell(10);
|
|
90
|
+
get(value); // => 10
|
|
106
91
|
```
|
|
107
92
|
|
|
108
|
-
|
|
93
|
+
When used inside a formula, the value is automatically tracked as a dependency.
|
|
109
94
|
|
|
110
|
-
|
|
95
|
+
### `untracked`
|
|
96
|
+
|
|
97
|
+
Allows reading cells, sources, and formulas without adding them as dependencies.
|
|
111
98
|
|
|
112
99
|
```ts
|
|
113
|
-
const
|
|
100
|
+
const a = cell('a');
|
|
101
|
+
const b = cell('b');
|
|
102
|
+
|
|
103
|
+
// Only `a` is added to the set of dependencies. `b` is ignored.
|
|
104
|
+
const result = formula(() => {
|
|
105
|
+
const trackedValue = get(a);
|
|
106
|
+
const untrackedValue = untracked(() => get(b));
|
|
107
|
+
});
|
|
114
108
|
```
|
|
115
109
|
|
|
116
|
-
### `batch
|
|
110
|
+
### `batch`
|
|
117
111
|
|
|
118
|
-
|
|
112
|
+
Updates the value of one or more cells atomically.
|
|
119
113
|
|
|
120
114
|
```ts
|
|
121
115
|
batch((swap) => {
|
|
122
116
|
swap(cellA, 1);
|
|
123
117
|
swap(cellB, 2);
|
|
124
|
-
// Watchers fire after both updates complete
|
|
125
118
|
});
|
|
126
119
|
```
|
|
127
120
|
|
|
128
|
-
|
|
121
|
+
Watchers are only notified after all changes are applied (glitch-free evaluation).
|
|
122
|
+
|
|
123
|
+
### `watch`
|
|
129
124
|
|
|
130
|
-
Subscribes to
|
|
125
|
+
Subscribes to a cell, source, or formula.
|
|
131
126
|
|
|
132
127
|
```ts
|
|
133
|
-
const dispose = watch(total, () => {
|
|
134
|
-
console.log('Total updated:',
|
|
128
|
+
const [dispose, renew] = watch(total, () => {
|
|
129
|
+
console.log('Total updated:', renew());
|
|
135
130
|
});
|
|
136
|
-
|
|
137
|
-
// Later: stop watching
|
|
138
|
-
dispose();
|
|
139
131
|
```
|
|
140
132
|
|
|
141
|
-
|
|
133
|
+
If the target is a formula, all its recursive dependencies are observed. Any `source()` values used are immediately promoted to non-volatile.
|
|
142
134
|
|
|
143
|
-
|
|
135
|
+
Calling `renew()` re-evaluates the value and updates the set of observed dependencies. Calling `dispose()` clears the watcher and releases all values. If this was the only watcher observing a `source()`, it will downgrade to volatile mode.
|
|
144
136
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
137
|
+
> [!WARNING]
|
|
138
|
+
> Calling `watch()` does **not** evaluate formulas. If the formula hasn't been evaluated yet, or hasn't been evaluated since dependencies changed, `watch()` will subscribe to stale dependencies.
|
|
139
|
+
>
|
|
140
|
+
> While it provides control over how and when formulas execute, the API is easy to misuse. It's recommended to abstract it with higher-level utilities.
|
|
148
141
|
|
|
149
|
-
|
|
150
|
-
const result = formula(() => {
|
|
151
|
-
const trackedValue = get(a); // This creates a dependency
|
|
152
|
-
const untrackedValue = untracked(() => get(b)); // This does not
|
|
153
|
-
return trackedValue + untrackedValue;
|
|
154
|
-
});
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
### `visitDependencies(signal, visitor)`
|
|
142
|
+
### `visitDependencies`
|
|
158
143
|
|
|
159
|
-
Visits all
|
|
144
|
+
Visits all cells, sources, and formulas in a dependency graph.
|
|
160
145
|
|
|
161
146
|
```ts
|
|
162
|
-
const visited = visitDependencies(
|
|
163
|
-
console.log(
|
|
147
|
+
const visited = visitDependencies(expression, (dep) => {
|
|
148
|
+
console.log('Found:', dep.type);
|
|
164
149
|
});
|
|
165
|
-
// Logs: "Found formula", "Found cell", "Found cell", "Found source"
|
|
166
150
|
```
|
|
151
|
+
|
|
152
|
+
It returns the set of all dependencies including the value provided.
|
|
153
|
+
|
|
154
|
+
**Note:** like `watch()`, `visitDependencies()` does not evaluate formulas and may return a stale (cached) set of dependencies. You may want to force evaluation before calling this API.
|
package/dist/cells.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});let
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});let o=0;function h(){return++o}const b=(t,e)=>{t.w.add(e)},w=(t,e)=>{t.w.delete(e)},C=t=>({t:"c",c:t,v:o,w:new Set});let c=null,i=!1;const k=(t,e)=>{const n=c;c=t;try{return e()}finally{c=n}},x=t=>{const e=i;i=!0;try{return t()}finally{i=e}},D=t=>{const e=c;c=null;try{return t()}finally{c=e}},E=t=>({t:"f",f:t,c:void 0,v:-1,d:new Map,x:!1}),F=(t,e)=>{t.d.set(e,e.v)},V=t=>{if(t.x)return!0;if(t.v===o)return!1;for(const[e,n]of t.d)if(e.t==="s"&&e.x||e.v!==n)return!0;return t.v===-1},T=t=>{if(!V(t))return t.c;t.d.clear(),t.x=!1;const e=k(t,t.f);for(const n of t.d.keys())if(n.t==="s"&&n.x||n.t==="f"&&n.x){t.x=!0;break}return t.c=e,t.v=o,e},d={};function S(t,e){const n=new Set;function r(s){if(!n.has(s)&&(n.add(s),e==null||e(s),s.t==="f"))for(const[u]of s.d)r(u)}return r(t),n}const y=t=>(c&&F(c,t),t.t==="c"?t.c:t.t==="f"?T(t):j(t)),z=(t,e)=>({s:t,c:e,d:new Set}),l=(t,e=!0)=>{const n=x(()=>S(t.s));n.forEach(r=>{t.d.has(r)||(r.t==="c"?b(r,t):r.t==="s"&&A(r,t))}),t.d.forEach(r=>{n.has(r)||(r.t==="c"?w(r,t):r.t==="s"&&p(r,t))}),t.d=n,e&&(0,t.c)()},M=t=>{t.d.forEach(e=>{e.t==="c"?w(e,t):e.t==="s"&&p(e,t)}),t.d.clear()},N=(t,e)=>{const n=z(t,e);return l(n,!1),[()=>M(n),()=>{const u=x(()=>y(t));return l(n,!1),u}]},j=t=>(t.x&&i&&W(t),t.x?(0,t.r)():(t.c===d&&(t.c=t.r()),t.c)),W=t=>{t.x&&t.s&&(t.x=!1,t.d=t.s(()=>{t.c=d,t.v=h();for(const e of t.w)l(e)}))},A=(t,e)=>{t.w.add(e),t.w.size===1&&W(t)},p=(t,e)=>{t.w.delete(e),t.w.size===0&&(t.x=!0,t.d&&(t.d(),t.d=void 0),t.c=d)},B=(t,e)=>({t:"s",r:t,s:e,c:d,v:o,w:new Set,x:!0,d:void 0});let f=!1;const a=new Set;function I(t){if(f)return t(v);f=!0,a.clear();try{const e=t(v);for(const n of a)l(n);return e}finally{f=!1,a.clear()}}function v(t,e){if(!f)throw new Error("Cell mutations must occur within a batch()");if(t.c!==e){t.c=e,t.v=h();for(const n of t.w)a.add(n)}}exports.batch=I;exports.cell=C;exports.formula=E;exports.get=y;exports.source=B;exports.untracked=D;exports.visitDependencies=S;exports.watch=N;
|
package/dist/cells.d.ts
CHANGED
|
@@ -133,9 +133,7 @@ export declare interface Source<T> {
|
|
|
133
133
|
/** Disposer for the subscription */
|
|
134
134
|
d?: Disposer;
|
|
135
135
|
/** Cached value */
|
|
136
|
-
c: T |
|
|
137
|
-
/** Whether the cache is primed */
|
|
138
|
-
p: boolean;
|
|
136
|
+
c: T | typeof STALE;
|
|
139
137
|
/** Volatile flag */
|
|
140
138
|
x: boolean;
|
|
141
139
|
/** Version */
|
|
@@ -174,6 +172,9 @@ export declare interface Source<T> {
|
|
|
174
172
|
*/
|
|
175
173
|
export declare const source: <T>(read: () => T, subscribe?: (onChange: () => void) => () => void) => Source<T>;
|
|
176
174
|
|
|
175
|
+
/** Sentinel value indicating cache is empty. */
|
|
176
|
+
declare const STALE: {};
|
|
177
|
+
|
|
177
178
|
export declare type SwapFunction = <T>(cell: Cell<T>, newValue: T) => void;
|
|
178
179
|
|
|
179
180
|
/**
|
|
@@ -230,14 +231,14 @@ export declare function visitDependencies<T>(signal: Signal<T>, visitor?: (signa
|
|
|
230
231
|
*
|
|
231
232
|
* @param signal - The signal to watch
|
|
232
233
|
* @param onChange - Function to call when the signal changes
|
|
233
|
-
* @returns A
|
|
234
|
+
* @returns A tuple of [dispose, renew] functions
|
|
234
235
|
*
|
|
235
236
|
* @example
|
|
236
237
|
* ```typescript
|
|
237
238
|
* const count = cell(0);
|
|
238
239
|
*
|
|
239
|
-
* const dispose = watch(count, () => {
|
|
240
|
-
* console.log('Count changed to:',
|
|
240
|
+
* const [dispose, renew] = watch(count, () => {
|
|
241
|
+
* console.log('Count changed to:', renew());
|
|
241
242
|
* });
|
|
242
243
|
*
|
|
243
244
|
* batch((swap) => {
|
|
@@ -247,7 +248,7 @@ export declare function visitDependencies<T>(signal: Signal<T>, visitor?: (signa
|
|
|
247
248
|
* dispose(); // Stop watching
|
|
248
249
|
* ```
|
|
249
250
|
*/
|
|
250
|
-
export declare const watch: <T>(signal: Signal<T>, onChange: ChangeHandler) => Disposer;
|
|
251
|
+
export declare const watch: <T>(signal: Signal<T>, onChange: ChangeHandler) => [dispose: Disposer, renew: () => T];
|
|
251
252
|
|
|
252
253
|
declare interface Watcher<T> {
|
|
253
254
|
/** Signal */
|
package/dist/cells.js
CHANGED
|
@@ -1,21 +1,19 @@
|
|
|
1
|
-
let
|
|
2
|
-
function
|
|
3
|
-
return ++
|
|
1
|
+
let o = 0;
|
|
2
|
+
function x() {
|
|
3
|
+
return ++o;
|
|
4
4
|
}
|
|
5
|
-
const
|
|
5
|
+
const y = (t, e) => {
|
|
6
6
|
t.w.add(e);
|
|
7
|
-
},
|
|
7
|
+
}, h = (t, e) => {
|
|
8
8
|
t.w.delete(e);
|
|
9
|
-
},
|
|
9
|
+
}, T = (t) => ({
|
|
10
10
|
t: "c",
|
|
11
11
|
c: t,
|
|
12
|
-
v:
|
|
12
|
+
v: o,
|
|
13
13
|
w: /* @__PURE__ */ new Set()
|
|
14
14
|
});
|
|
15
|
-
let c = null,
|
|
16
|
-
const
|
|
17
|
-
c && k(c, t);
|
|
18
|
-
}, W = (t, e) => {
|
|
15
|
+
let c = null, i = !1;
|
|
16
|
+
const p = (t, e) => {
|
|
19
17
|
const n = c;
|
|
20
18
|
c = t;
|
|
21
19
|
try {
|
|
@@ -23,15 +21,15 @@ const y = (t) => {
|
|
|
23
21
|
} finally {
|
|
24
22
|
c = n;
|
|
25
23
|
}
|
|
26
|
-
},
|
|
27
|
-
const e =
|
|
28
|
-
|
|
24
|
+
}, w = (t) => {
|
|
25
|
+
const e = i;
|
|
26
|
+
i = !0;
|
|
29
27
|
try {
|
|
30
28
|
return t();
|
|
31
29
|
} finally {
|
|
32
|
-
|
|
30
|
+
i = e;
|
|
33
31
|
}
|
|
34
|
-
},
|
|
32
|
+
}, A = (t) => {
|
|
35
33
|
const e = c;
|
|
36
34
|
c = null;
|
|
37
35
|
try {
|
|
@@ -39,119 +37,119 @@ const y = (t) => {
|
|
|
39
37
|
} finally {
|
|
40
38
|
c = e;
|
|
41
39
|
}
|
|
42
|
-
},
|
|
40
|
+
}, B = (t) => ({
|
|
43
41
|
t: "f",
|
|
44
42
|
f: t,
|
|
45
43
|
c: void 0,
|
|
46
44
|
v: -1,
|
|
47
45
|
d: /* @__PURE__ */ new Map(),
|
|
48
46
|
x: !1
|
|
49
|
-
}),
|
|
47
|
+
}), C = (t, e) => {
|
|
50
48
|
t.d.set(e, e.v);
|
|
51
|
-
},
|
|
49
|
+
}, E = (t) => {
|
|
52
50
|
if (t.x)
|
|
53
51
|
return !0;
|
|
54
|
-
if (t.v ===
|
|
52
|
+
if (t.v === o)
|
|
55
53
|
return !1;
|
|
56
54
|
for (const [e, n] of t.d)
|
|
57
55
|
if (e.t === "s" && e.x || e.v !== n)
|
|
58
56
|
return !0;
|
|
59
57
|
return t.v === -1;
|
|
60
|
-
},
|
|
61
|
-
if (!
|
|
58
|
+
}, b = (t) => {
|
|
59
|
+
if (!E(t))
|
|
62
60
|
return t.c;
|
|
63
61
|
t.d.clear(), t.x = !1;
|
|
64
|
-
const e =
|
|
62
|
+
const e = p(t, t.f);
|
|
65
63
|
for (const n of t.d.keys())
|
|
66
64
|
if (n.t === "s" && n.x || n.t === "f" && n.x) {
|
|
67
65
|
t.x = !0;
|
|
68
66
|
break;
|
|
69
67
|
}
|
|
70
|
-
return t.c = e, t.v =
|
|
71
|
-
};
|
|
72
|
-
function
|
|
68
|
+
return t.c = e, t.v = o, e;
|
|
69
|
+
}, l = {};
|
|
70
|
+
function k(t, e) {
|
|
73
71
|
const n = /* @__PURE__ */ new Set();
|
|
74
|
-
function r(
|
|
75
|
-
if (!n.has(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
r(p);
|
|
79
|
-
}
|
|
72
|
+
function r(s) {
|
|
73
|
+
if (!n.has(s) && (n.add(s), e == null || e(s), s.t === "f"))
|
|
74
|
+
for (const [u] of s.d)
|
|
75
|
+
r(u);
|
|
80
76
|
}
|
|
81
77
|
return r(t), n;
|
|
82
78
|
}
|
|
83
|
-
const
|
|
79
|
+
const D = (t) => (c && C(c, t), t.t === "c" ? t.c : t.t === "f" ? b(t) : z(t)), F = (t, e) => ({
|
|
84
80
|
s: t,
|
|
85
81
|
c: e,
|
|
86
82
|
d: /* @__PURE__ */ new Set()
|
|
87
83
|
}), d = (t, e = !0) => {
|
|
88
|
-
const n =
|
|
89
|
-
() =>
|
|
84
|
+
const n = w(
|
|
85
|
+
() => k(t.s)
|
|
90
86
|
);
|
|
91
87
|
n.forEach((r) => {
|
|
92
|
-
t.d.has(r) || (r.t === "c" ?
|
|
88
|
+
t.d.has(r) || (r.t === "c" ? y(r, t) : r.t === "s" && N(r, t));
|
|
93
89
|
}), t.d.forEach((r) => {
|
|
94
|
-
n.has(r) || (r.t === "c" ?
|
|
90
|
+
n.has(r) || (r.t === "c" ? h(r, t) : r.t === "s" && W(r, t));
|
|
95
91
|
}), t.d = n, e && (0, t.c)();
|
|
96
|
-
},
|
|
92
|
+
}, V = (t) => {
|
|
97
93
|
t.d.forEach((e) => {
|
|
98
|
-
e.t === "c" ?
|
|
94
|
+
e.t === "c" ? h(e, t) : e.t === "s" && W(e, t);
|
|
99
95
|
}), t.d.clear();
|
|
100
|
-
},
|
|
101
|
-
const n =
|
|
102
|
-
return d(n, !1), () =>
|
|
103
|
-
|
|
96
|
+
}, I = (t, e) => {
|
|
97
|
+
const n = F(t, e);
|
|
98
|
+
return d(n, !1), [() => V(n), () => {
|
|
99
|
+
const u = w(() => D(t));
|
|
100
|
+
return d(n, !1), u;
|
|
101
|
+
}];
|
|
102
|
+
}, z = (t) => (t.x && i && S(t), t.x ? (0, t.r)() : (t.c === l && (t.c = t.r()), t.c)), S = (t) => {
|
|
104
103
|
t.x && t.s && (t.x = !1, t.d = t.s(() => {
|
|
105
|
-
t.c =
|
|
104
|
+
t.c = l, t.v = x();
|
|
106
105
|
for (const e of t.w)
|
|
107
106
|
d(e);
|
|
108
107
|
}));
|
|
109
|
-
},
|
|
110
|
-
t.w.add(e), t.w.size === 1 &&
|
|
111
|
-
},
|
|
112
|
-
t.w.delete(e), t.w.size === 0 && (t.x = !0, t.d && (t.d(), t.d = void 0), t.c =
|
|
113
|
-
},
|
|
108
|
+
}, N = (t, e) => {
|
|
109
|
+
t.w.add(e), t.w.size === 1 && S(t);
|
|
110
|
+
}, W = (t, e) => {
|
|
111
|
+
t.w.delete(e), t.w.size === 0 && (t.x = !0, t.d && (t.d(), t.d = void 0), t.c = l);
|
|
112
|
+
}, L = (t, e) => ({
|
|
114
113
|
t: "s",
|
|
115
114
|
r: t,
|
|
116
115
|
s: e,
|
|
117
|
-
c:
|
|
118
|
-
v:
|
|
116
|
+
c: l,
|
|
117
|
+
v: o,
|
|
119
118
|
w: /* @__PURE__ */ new Set(),
|
|
120
119
|
x: !0,
|
|
121
|
-
p: !1,
|
|
122
120
|
d: void 0
|
|
123
|
-
})
|
|
124
|
-
let
|
|
121
|
+
});
|
|
122
|
+
let f = !1;
|
|
125
123
|
const a = /* @__PURE__ */ new Set();
|
|
126
|
-
function
|
|
127
|
-
if (
|
|
128
|
-
return t(
|
|
129
|
-
|
|
124
|
+
function M(t) {
|
|
125
|
+
if (f)
|
|
126
|
+
return t(v);
|
|
127
|
+
f = !0, a.clear();
|
|
130
128
|
try {
|
|
131
|
-
const e = t(
|
|
129
|
+
const e = t(v);
|
|
132
130
|
for (const n of a)
|
|
133
131
|
d(n);
|
|
134
132
|
return e;
|
|
135
133
|
} finally {
|
|
136
|
-
|
|
134
|
+
f = !1, a.clear();
|
|
137
135
|
}
|
|
138
136
|
}
|
|
139
|
-
function
|
|
140
|
-
if (!
|
|
137
|
+
function v(t, e) {
|
|
138
|
+
if (!f)
|
|
141
139
|
throw new Error("Cell mutations must occur within a batch()");
|
|
142
140
|
if (t.c !== e) {
|
|
143
|
-
t.c = e, t.v =
|
|
141
|
+
t.c = e, t.v = x();
|
|
144
142
|
for (const n of t.w)
|
|
145
143
|
a.add(n);
|
|
146
144
|
}
|
|
147
145
|
}
|
|
148
146
|
export {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
147
|
+
M as batch,
|
|
148
|
+
T as cell,
|
|
149
|
+
B as formula,
|
|
150
|
+
D as get,
|
|
151
|
+
L as source,
|
|
152
|
+
A as untracked,
|
|
153
|
+
k as visitDependencies,
|
|
154
|
+
I as watch
|
|
157
155
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package",
|
|
3
3
|
"name": "@retreon/cells",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.2.0-2025-06-23.7d6d015",
|
|
5
5
|
"description": "A minimal spreadsheet engine",
|
|
6
6
|
"author": "Jesse Gibson <JesseTheGibson@gmail.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@eslint/js": "^9.17.0",
|
|
55
|
-
"@types/eslint__js": "^
|
|
55
|
+
"@types/eslint__js": "^9.0.0",
|
|
56
56
|
"@types/node": "^24.0.1",
|
|
57
57
|
"@typescript-eslint/eslint-plugin": "^8.18.2",
|
|
58
58
|
"keep-a-changelog": "^2.6.2",
|