@flowgram-vue/reactive 0.2.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/LICENSE +22 -0
- package/README.md +38 -0
- package/dist/index.cjs +526 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +215 -0
- package/dist/index.js +517 -0
- package/dist/index.js.map +1 -0
- package/package.json +54 -0
- package/src/core/reactive-base-state.ts +45 -0
- package/src/core/reactive-state.ts +89 -0
- package/src/core/tracker.ts +440 -0
- package/src/hooks/use-observe.ts +45 -0
- package/src/hooks/use-reactive-state.ts +12 -0
- package/src/hooks/use-readonly-reactive-state.ts +13 -0
- package/src/index.ts +15 -0
- package/src/utils/create-proxy.ts +30 -0
- package/src/vue/observe.ts +58 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
4
|
+
Copyright (c) 2026 Crayon
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Reactive
|
|
2
|
+
|
|
3
|
+
## Usage
|
|
4
|
+
|
|
5
|
+
### 创建响应式数据并做依赖追踪
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
|
|
9
|
+
import { ReactiveState, Tracker } from '@flowgram-vue/reactive'
|
|
10
|
+
|
|
11
|
+
// 创建 数据
|
|
12
|
+
const reactiveState = new ReactiveState<{ a: number, b: number }>({ a: 0, b: 0 })
|
|
13
|
+
|
|
14
|
+
// 监听函数
|
|
15
|
+
const result = Tracker.autorun(() => {
|
|
16
|
+
console.log('run: ', reactiveState.value, reactiveState.value.a)
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
// 更新字典数据 a 会自动执行上边的 autorun
|
|
20
|
+
reactiveState.value.a = 1
|
|
21
|
+
|
|
22
|
+
// 更新数据 b 则不会执行,因为 autorun 函数里没有依赖
|
|
23
|
+
reactiveState.value.b = 1
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
### Vue 中使用
|
|
28
|
+
|
|
29
|
+
```vue
|
|
30
|
+
<script setup lang="ts">
|
|
31
|
+
import { h } from 'vue'
|
|
32
|
+
import { useReactiveState, observe } from '@flowgram-vue/reactive'
|
|
33
|
+
|
|
34
|
+
const SomeComp = observe((props: { state: { a: number } }) => h('div', props.state.a))
|
|
35
|
+
|
|
36
|
+
const state = useReactiveState<{ a: number, b: number }>({ a: 0, b: 0 })
|
|
37
|
+
</script>
|
|
38
|
+
```
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,526 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var vue = require('vue');
|
|
4
|
+
|
|
5
|
+
// src/core/tracker.ts
|
|
6
|
+
exports.Tracker = void 0;
|
|
7
|
+
((Tracker2) => {
|
|
8
|
+
const _pendingComputations = [];
|
|
9
|
+
const _afterFlushCallbacks = [];
|
|
10
|
+
let _willFlush = false;
|
|
11
|
+
let _inFlush = false;
|
|
12
|
+
let _inCompute = false;
|
|
13
|
+
let _currentComputation = void 0;
|
|
14
|
+
let _throwFirstError = false;
|
|
15
|
+
function _throwOrLog(msg, e) {
|
|
16
|
+
if (_throwFirstError) {
|
|
17
|
+
throw e;
|
|
18
|
+
} else {
|
|
19
|
+
console.error(`[Tracker error] ${msg}`, e);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function _runFlush(options) {
|
|
23
|
+
if (inFlush()) throw new Error("Can't call Tracker.flush while flushing");
|
|
24
|
+
if (_inCompute) throw new Error("Can't flush inside Tracker.autorun");
|
|
25
|
+
options = options || {};
|
|
26
|
+
_inFlush = true;
|
|
27
|
+
_willFlush = true;
|
|
28
|
+
_throwFirstError = !!options.throwFirstError;
|
|
29
|
+
var recomputedCount = 0;
|
|
30
|
+
var finishedTry = false;
|
|
31
|
+
try {
|
|
32
|
+
while (_pendingComputations.length || _afterFlushCallbacks.length) {
|
|
33
|
+
while (_pendingComputations.length) {
|
|
34
|
+
var comp = _pendingComputations.shift();
|
|
35
|
+
comp._recompute();
|
|
36
|
+
if (comp._needsRecompute()) {
|
|
37
|
+
_pendingComputations.unshift(comp);
|
|
38
|
+
}
|
|
39
|
+
if (!options.finishSynchronously && ++recomputedCount > 100) {
|
|
40
|
+
finishedTry = true;
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (_afterFlushCallbacks.length) {
|
|
45
|
+
var func = _afterFlushCallbacks.shift();
|
|
46
|
+
try {
|
|
47
|
+
func();
|
|
48
|
+
} catch (e) {
|
|
49
|
+
_throwOrLog("afterFlush", e);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
finishedTry = true;
|
|
54
|
+
} finally {
|
|
55
|
+
if (!finishedTry) {
|
|
56
|
+
_inFlush = false;
|
|
57
|
+
_runFlush({
|
|
58
|
+
finishSynchronously: options.finishSynchronously,
|
|
59
|
+
throwFirstError: false
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
_willFlush = false;
|
|
63
|
+
_inFlush = false;
|
|
64
|
+
if (_pendingComputations.length || _afterFlushCallbacks.length) {
|
|
65
|
+
if (options.finishSynchronously) {
|
|
66
|
+
throw new Error("still have more to do?");
|
|
67
|
+
}
|
|
68
|
+
setTimeout(_requireFlush, 10);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function _requireFlush() {
|
|
73
|
+
if (!_willFlush) {
|
|
74
|
+
setTimeout(_runFlush, 0);
|
|
75
|
+
_willFlush = true;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function withComputation(computation, f) {
|
|
79
|
+
let previousComputation = _currentComputation;
|
|
80
|
+
_currentComputation = computation;
|
|
81
|
+
try {
|
|
82
|
+
return f.call(null, computation);
|
|
83
|
+
} finally {
|
|
84
|
+
_currentComputation = previousComputation;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
Tracker2.withComputation = withComputation;
|
|
88
|
+
function withoutComputation(f) {
|
|
89
|
+
let previousComputation = _currentComputation;
|
|
90
|
+
_currentComputation = void 0;
|
|
91
|
+
try {
|
|
92
|
+
return f(void 0);
|
|
93
|
+
} finally {
|
|
94
|
+
_currentComputation = previousComputation;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
Tracker2.withoutComputation = withoutComputation;
|
|
98
|
+
function isActive() {
|
|
99
|
+
return !!_currentComputation;
|
|
100
|
+
}
|
|
101
|
+
Tracker2.isActive = isActive;
|
|
102
|
+
function getCurrentComputation() {
|
|
103
|
+
return _currentComputation;
|
|
104
|
+
}
|
|
105
|
+
Tracker2.getCurrentComputation = getCurrentComputation;
|
|
106
|
+
function autorun(f, options) {
|
|
107
|
+
var c = new Computation2(f, _currentComputation, options?.onError);
|
|
108
|
+
if (isActive())
|
|
109
|
+
Tracker2.onInvalidate(function() {
|
|
110
|
+
c.stop();
|
|
111
|
+
});
|
|
112
|
+
return c;
|
|
113
|
+
}
|
|
114
|
+
Tracker2.autorun = autorun;
|
|
115
|
+
function onInvalidate(f) {
|
|
116
|
+
if (!_currentComputation) {
|
|
117
|
+
throw new Error("Tracker.onInvalidate requires a currentComputation");
|
|
118
|
+
}
|
|
119
|
+
_currentComputation.onInvalidate(f);
|
|
120
|
+
}
|
|
121
|
+
Tracker2.onInvalidate = onInvalidate;
|
|
122
|
+
function inFlush() {
|
|
123
|
+
return _inFlush;
|
|
124
|
+
}
|
|
125
|
+
Tracker2.inFlush = inFlush;
|
|
126
|
+
function flush(options) {
|
|
127
|
+
_runFlush({
|
|
128
|
+
finishSynchronously: true,
|
|
129
|
+
throwFirstError: options && options.throwFirstError
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
Tracker2.flush = flush;
|
|
133
|
+
function afterFlush(f) {
|
|
134
|
+
_afterFlushCallbacks.push(f);
|
|
135
|
+
_requireFlush();
|
|
136
|
+
}
|
|
137
|
+
Tracker2.afterFlush = afterFlush;
|
|
138
|
+
class Computation2 {
|
|
139
|
+
constructor(_fn, parent, _onError) {
|
|
140
|
+
this._fn = _fn;
|
|
141
|
+
this.parent = parent;
|
|
142
|
+
this._onError = _onError;
|
|
143
|
+
this._onInvalidateCallbacks = [];
|
|
144
|
+
this._onStopCallbacks = [];
|
|
145
|
+
this._recomputing = false;
|
|
146
|
+
/**
|
|
147
|
+
* 是否停止
|
|
148
|
+
*/
|
|
149
|
+
this.stopped = false;
|
|
150
|
+
/**
|
|
151
|
+
* 未开始执行则返回 false
|
|
152
|
+
*/
|
|
153
|
+
this.invalidated = false;
|
|
154
|
+
/**
|
|
155
|
+
* 是否第一次执行
|
|
156
|
+
*/
|
|
157
|
+
this.firstRun = true;
|
|
158
|
+
let hasError = true;
|
|
159
|
+
try {
|
|
160
|
+
this._compute();
|
|
161
|
+
hasError = false;
|
|
162
|
+
} finally {
|
|
163
|
+
this.firstRun = false;
|
|
164
|
+
if (hasError) {
|
|
165
|
+
this.stop();
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
onInvalidate(f) {
|
|
170
|
+
if (this.invalidated) {
|
|
171
|
+
withoutComputation(f.bind(null, this));
|
|
172
|
+
} else {
|
|
173
|
+
this._onInvalidateCallbacks.push(f);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* @summary Invalidates this computation so that it will be rerun.
|
|
178
|
+
*/
|
|
179
|
+
invalidate() {
|
|
180
|
+
if (!this.invalidated) {
|
|
181
|
+
if (!this._recomputing && !this.stopped) {
|
|
182
|
+
_requireFlush();
|
|
183
|
+
_pendingComputations.push(this);
|
|
184
|
+
}
|
|
185
|
+
this.invalidated = true;
|
|
186
|
+
for (var i = 0, f; f = this._onInvalidateCallbacks[i]; i++) {
|
|
187
|
+
withoutComputation(f.bind(null, this));
|
|
188
|
+
}
|
|
189
|
+
this._onInvalidateCallbacks = [];
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* @summary Prevents this computation from rerunning.
|
|
194
|
+
* @locus Client
|
|
195
|
+
*/
|
|
196
|
+
stop() {
|
|
197
|
+
if (!this.stopped) {
|
|
198
|
+
this.stopped = true;
|
|
199
|
+
this.invalidate();
|
|
200
|
+
for (let i = 0, f; f = this._onStopCallbacks[i]; i++) {
|
|
201
|
+
withoutComputation(f.bind(null, this));
|
|
202
|
+
}
|
|
203
|
+
this._onStopCallbacks = [];
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
onStop(f) {
|
|
207
|
+
if (this.stopped) {
|
|
208
|
+
withoutComputation(f.bind(null, this));
|
|
209
|
+
} else {
|
|
210
|
+
this._onStopCallbacks.push(f);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
_compute() {
|
|
214
|
+
this.invalidated = false;
|
|
215
|
+
var previousInCompute = _inCompute;
|
|
216
|
+
_inCompute = true;
|
|
217
|
+
try {
|
|
218
|
+
this._result = Tracker2.withComputation(this, this._fn);
|
|
219
|
+
} finally {
|
|
220
|
+
_inCompute = previousInCompute;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
_needsRecompute() {
|
|
224
|
+
return this.invalidated && !this.stopped;
|
|
225
|
+
}
|
|
226
|
+
_recompute() {
|
|
227
|
+
this._recomputing = true;
|
|
228
|
+
try {
|
|
229
|
+
if (this._needsRecompute()) {
|
|
230
|
+
try {
|
|
231
|
+
this._compute();
|
|
232
|
+
} catch (e) {
|
|
233
|
+
if (this._onError) {
|
|
234
|
+
this._onError(e);
|
|
235
|
+
} else {
|
|
236
|
+
_throwOrLog("recompute", e);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
} finally {
|
|
241
|
+
this._recomputing = false;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* @summary Process the reactive updates for this computation immediately
|
|
246
|
+
* and ensure that the computation is rerun. The computation is rerun only
|
|
247
|
+
* if it is invalidated.
|
|
248
|
+
*/
|
|
249
|
+
flush() {
|
|
250
|
+
if (this._recomputing) return;
|
|
251
|
+
this._recompute();
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* @summary Causes the function inside this computation to run and
|
|
255
|
+
* synchronously process all reactive updtes.
|
|
256
|
+
* @locus Client
|
|
257
|
+
*/
|
|
258
|
+
run() {
|
|
259
|
+
this.invalidate();
|
|
260
|
+
this.flush();
|
|
261
|
+
}
|
|
262
|
+
get result() {
|
|
263
|
+
return this._result;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
Tracker2.Computation = Computation2;
|
|
267
|
+
class Dependency3 {
|
|
268
|
+
constructor() {
|
|
269
|
+
this._dependents = /* @__PURE__ */ new Set();
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Declares that the current computation (or `fromComputation` if given) depends on `dependency`. The computation will be invalidated the next time `dependency` changes.
|
|
273
|
+
* If there is no current computation and `depend()` is called with no arguments, it does nothing and returns false.
|
|
274
|
+
* Returns true if the computation is a new dependent of `dependency` rather than an existing one.
|
|
275
|
+
*/
|
|
276
|
+
depend(computation) {
|
|
277
|
+
if (!computation) {
|
|
278
|
+
if (!isActive()) {
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
computation = _currentComputation;
|
|
282
|
+
}
|
|
283
|
+
if (!this._dependents.has(computation)) {
|
|
284
|
+
this._dependents.add(computation);
|
|
285
|
+
computation.onInvalidate(() => {
|
|
286
|
+
this._dependents.delete(computation);
|
|
287
|
+
});
|
|
288
|
+
return true;
|
|
289
|
+
}
|
|
290
|
+
return false;
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Invalidate all dependent computations immediately and remove them as dependents.
|
|
294
|
+
*/
|
|
295
|
+
changed() {
|
|
296
|
+
for (const dep of this._dependents) {
|
|
297
|
+
dep.invalidate();
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* True if this Dependency has one or more dependent Computations, which would be invalidated if this Dependency were to change.
|
|
302
|
+
*/
|
|
303
|
+
hasDependents() {
|
|
304
|
+
return this._dependents.size !== 0;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
Tracker2.Dependency = Dependency3;
|
|
308
|
+
})(exports.Tracker || (exports.Tracker = {}));
|
|
309
|
+
|
|
310
|
+
// src/core/reactive-base-state.ts
|
|
311
|
+
var ReactiveBaseState = class {
|
|
312
|
+
constructor(initialValue, opts) {
|
|
313
|
+
this._dep = new exports.Tracker.Dependency();
|
|
314
|
+
this._isEqual = (a, b) => a == b;
|
|
315
|
+
this._value = initialValue;
|
|
316
|
+
if (opts?.isEqual) {
|
|
317
|
+
this._isEqual = opts.isEqual;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
_addDepend(dep) {
|
|
321
|
+
if (exports.Tracker.isActive()) {
|
|
322
|
+
dep.depend();
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
hasDependents() {
|
|
326
|
+
return this._dep.hasDependents();
|
|
327
|
+
}
|
|
328
|
+
get value() {
|
|
329
|
+
this._addDepend(this._dep);
|
|
330
|
+
return this._value;
|
|
331
|
+
}
|
|
332
|
+
set value(newValue) {
|
|
333
|
+
if (!this._isEqual(this._value, newValue)) {
|
|
334
|
+
this._value = newValue;
|
|
335
|
+
this._dep.changed();
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
// src/utils/create-proxy.ts
|
|
341
|
+
function createProxy(target, opts) {
|
|
342
|
+
let useProxy = "Proxy" in window;
|
|
343
|
+
if (process.env.NODE_ENV === "test") {
|
|
344
|
+
if (global.__ignoreProxy) {
|
|
345
|
+
useProxy = false;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
if (useProxy) {
|
|
349
|
+
return new Proxy(target, opts);
|
|
350
|
+
}
|
|
351
|
+
const result = {};
|
|
352
|
+
for (const key in target) {
|
|
353
|
+
Object.defineProperty(result, key, {
|
|
354
|
+
enumerable: true,
|
|
355
|
+
get: opts.get ? () => opts.get(target, key) : void 0,
|
|
356
|
+
set: opts.set ? (newValue) => opts.set(target, key, newValue) : void 0
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
return result;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// src/core/reactive-state.ts
|
|
363
|
+
var Dependency = exports.Tracker.Dependency;
|
|
364
|
+
var ReactiveState = class extends ReactiveBaseState {
|
|
365
|
+
constructor() {
|
|
366
|
+
super(...arguments);
|
|
367
|
+
this._keyDeps = /* @__PURE__ */ new Map();
|
|
368
|
+
}
|
|
369
|
+
set(key, value) {
|
|
370
|
+
this._ensureKey(key);
|
|
371
|
+
const oldValue = this._value[key];
|
|
372
|
+
if (!this._isEqual(oldValue, value)) {
|
|
373
|
+
this._value[key] = value;
|
|
374
|
+
this._keyDeps.get(key).changed();
|
|
375
|
+
return true;
|
|
376
|
+
}
|
|
377
|
+
return false;
|
|
378
|
+
}
|
|
379
|
+
get(key) {
|
|
380
|
+
this._ensureKey(key);
|
|
381
|
+
this._addDepend(this._keyDeps.get(key));
|
|
382
|
+
return this._value[key];
|
|
383
|
+
}
|
|
384
|
+
_ensureKey(key) {
|
|
385
|
+
if (!this._keyDeps.has(key)) {
|
|
386
|
+
this._keyDeps.set(key, new Dependency());
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
hasDependents() {
|
|
390
|
+
if (this._dep.hasDependents()) return true;
|
|
391
|
+
for (const dep of this._keyDeps.values()) {
|
|
392
|
+
if (dep.hasDependents()) return true;
|
|
393
|
+
}
|
|
394
|
+
return false;
|
|
395
|
+
}
|
|
396
|
+
keys() {
|
|
397
|
+
return Object.keys(this._value);
|
|
398
|
+
}
|
|
399
|
+
set value(newValue) {
|
|
400
|
+
if (!this._isEqual(this._value, newValue)) {
|
|
401
|
+
this._value = newValue;
|
|
402
|
+
this._keyDeps.clear();
|
|
403
|
+
this._dep.changed();
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
get value() {
|
|
407
|
+
this._addDepend(this._dep);
|
|
408
|
+
if (!this._proxyValue) {
|
|
409
|
+
this._proxyValue = createProxy(this._value, {
|
|
410
|
+
get: (target, key) => this.get(key),
|
|
411
|
+
set: (target, key, newValue) => {
|
|
412
|
+
this.set(key, newValue);
|
|
413
|
+
return true;
|
|
414
|
+
}
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
return this._proxyValue;
|
|
418
|
+
}
|
|
419
|
+
get readonlyValue() {
|
|
420
|
+
this._addDepend(this._dep);
|
|
421
|
+
if (!this._proxyReadonlyValue) {
|
|
422
|
+
this._proxyReadonlyValue = createProxy(this._value, {
|
|
423
|
+
get: (target, key) => this.get(key),
|
|
424
|
+
set: (newValue, key) => {
|
|
425
|
+
throw new Error(`[ReactiveState] Cannnot set readonly field "${key}"`);
|
|
426
|
+
}
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
return this._proxyReadonlyValue;
|
|
430
|
+
}
|
|
431
|
+
};
|
|
432
|
+
function useObserve(value) {
|
|
433
|
+
const instance = vue.getCurrentInstance();
|
|
434
|
+
const tick = vue.shallowRef(0);
|
|
435
|
+
const computationMap = /* @__PURE__ */ new Map();
|
|
436
|
+
const refresh = () => {
|
|
437
|
+
tick.value += 1;
|
|
438
|
+
instance?.update();
|
|
439
|
+
};
|
|
440
|
+
const clear = () => {
|
|
441
|
+
computationMap.forEach((comp) => comp.stop());
|
|
442
|
+
computationMap.clear();
|
|
443
|
+
};
|
|
444
|
+
vue.onBeforeUpdate(clear);
|
|
445
|
+
vue.onBeforeUnmount(clear);
|
|
446
|
+
if (value === void 0) return {};
|
|
447
|
+
return createProxy(value, {
|
|
448
|
+
get(_target, key) {
|
|
449
|
+
void tick.value;
|
|
450
|
+
let computation = computationMap.get(key);
|
|
451
|
+
if (!computation) {
|
|
452
|
+
computation = new exports.Tracker.Computation((c) => {
|
|
453
|
+
if (!c.firstRun) {
|
|
454
|
+
refresh();
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
return value[key];
|
|
458
|
+
});
|
|
459
|
+
computationMap.set(key, computation);
|
|
460
|
+
}
|
|
461
|
+
return value[key];
|
|
462
|
+
}
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
// src/hooks/use-reactive-state.ts
|
|
467
|
+
function useReactiveState(v) {
|
|
468
|
+
const state = v instanceof ReactiveState ? v : new ReactiveState(v);
|
|
469
|
+
return useObserve(state.value);
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// src/hooks/use-readonly-reactive-state.ts
|
|
473
|
+
function useReadonlyReactiveState(state) {
|
|
474
|
+
return useObserve(state.readonlyValue);
|
|
475
|
+
}
|
|
476
|
+
function observe(fc) {
|
|
477
|
+
return vue.defineComponent({
|
|
478
|
+
name: "ReactiveObserver",
|
|
479
|
+
inheritAttrs: false,
|
|
480
|
+
setup(_, { attrs, slots }) {
|
|
481
|
+
const instance = vue.getCurrentInstance();
|
|
482
|
+
const tick = vue.shallowRef(0);
|
|
483
|
+
const childrenRef = { current: null };
|
|
484
|
+
const computationRef = { current: void 0 };
|
|
485
|
+
const refresh = () => {
|
|
486
|
+
tick.value += 1;
|
|
487
|
+
instance?.update();
|
|
488
|
+
};
|
|
489
|
+
vue.onBeforeUnmount(() => {
|
|
490
|
+
computationRef.current?.stop();
|
|
491
|
+
});
|
|
492
|
+
return () => {
|
|
493
|
+
void tick.value;
|
|
494
|
+
computationRef.current?.stop();
|
|
495
|
+
const slotChildren = slots.default?.();
|
|
496
|
+
const childrenFromSlot = slotChildren && slotChildren.length === 1 ? slotChildren[0] : slotChildren;
|
|
497
|
+
const props = {
|
|
498
|
+
...attrs,
|
|
499
|
+
children: childrenFromSlot ?? attrs.children
|
|
500
|
+
};
|
|
501
|
+
computationRef.current = new exports.Tracker.Computation((c) => {
|
|
502
|
+
if (c.firstRun) {
|
|
503
|
+
childrenRef.current = fc(props);
|
|
504
|
+
} else {
|
|
505
|
+
refresh();
|
|
506
|
+
}
|
|
507
|
+
});
|
|
508
|
+
return childrenRef.current ?? null;
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// src/index.ts
|
|
515
|
+
var { Dependency: Dependency2, Computation } = exports.Tracker;
|
|
516
|
+
|
|
517
|
+
exports.Computation = Computation;
|
|
518
|
+
exports.Dependency = Dependency2;
|
|
519
|
+
exports.ReactiveBaseState = ReactiveBaseState;
|
|
520
|
+
exports.ReactiveState = ReactiveState;
|
|
521
|
+
exports.observe = observe;
|
|
522
|
+
exports.useObserve = useObserve;
|
|
523
|
+
exports.useReactiveState = useReactiveState;
|
|
524
|
+
exports.useReadonlyReactiveState = useReadonlyReactiveState;
|
|
525
|
+
//# sourceMappingURL=index.cjs.map
|
|
526
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/tracker.ts","../src/core/reactive-base-state.ts","../src/utils/create-proxy.ts","../src/core/reactive-state.ts","../src/hooks/use-observe.ts","../src/hooks/use-reactive-state.ts","../src/hooks/use-readonly-reactive-state.ts","../src/vue/observe.ts","../src/index.ts"],"names":["Tracker","Computation","Dependency","getCurrentInstance","shallowRef","onBeforeUpdate","onBeforeUnmount","defineComponent"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\n/**\n * Fork from: https://github.com/meteor/meteor/blob/devel/packages/tracker/tracker.js\n */\ntype ICallback<ARG = void, RET = void> = (arg: ARG) => RET;\n\n/**\n * Tracker 是一套 响应式依赖追踪 库,来源于 Meteor.Tracker\n * https://docs.meteor.com/api/Tracker.html#tracker-autorun-and-async-callbacks\n * https://github.com/meteor/meteor/blob/devel/packages/tracker/tracker.js\n *\n * 相关论文:https://dl.acm.org/doi/fullHtml/10.1145/3184558.3185978\n */\nexport namespace Tracker {\n const _pendingComputations: Computation[] = [];\n const _afterFlushCallbacks: ICallback[] = [];\n // `true` if a Tracker.flush is scheduled, or if we are in Tracker.flush now\n let _willFlush = false;\n // `true` if we are in Tracker.flush now\n let _inFlush = false;\n // `true` if we are computing a computation now, either first time\n // or recompute. This matches Tracker.active unless we are inside\n // Tracker.nonreactive, which nullfies currentComputation even though\n // an enclosing computation may still be running.\n let _inCompute = false;\n let _currentComputation: Computation | undefined = undefined;\n // `true` if the `_throwFirstError` option was passed in to the call\n // to Tracker.flush that we are in. When set, throw rather than log the\n // first error encountered while flushing. Before throwing the error,\n // finish flushing (from a finally block), logging any subsequent\n // errors.\n let _throwFirstError = false;\n\n export interface FlushOptions {\n finishSynchronously?: boolean;\n throwFirstError?: boolean;\n }\n\n function _throwOrLog(msg: string, e: any) {\n if (_throwFirstError) {\n throw e;\n } else {\n console.error(`[Tracker error] ${msg}`, e);\n }\n }\n\n // Run all pending computations and afterFlush callbacks. If we were not called\n // directly via Tracker.flush, this may return before they're all done to allow\n // the event loop to run a little before continuing.\n function _runFlush(options?: FlushOptions) {\n // Nested flush could plausibly happen if, say, a flush causes\n // DOM mutation, which causes a \"blur\" event, which runs an\n // app event handler that calls Tracker.flush. At the moment\n // Spark blocks event handlers during DOM mutation anyway,\n // because the LiveRange tree isn't valid. And we don't have\n // any useful notion of a nested flush.\n if (inFlush()) throw new Error(\"Can't call Tracker.flush while flushing\");\n\n if (_inCompute) throw new Error(\"Can't flush inside Tracker.autorun\");\n\n options = options || {};\n\n _inFlush = true;\n _willFlush = true;\n _throwFirstError = !!options.throwFirstError;\n\n var recomputedCount = 0;\n var finishedTry = false;\n try {\n while (_pendingComputations.length || _afterFlushCallbacks.length) {\n // recompute all pending computations\n while (_pendingComputations.length) {\n var comp = _pendingComputations.shift()!;\n comp._recompute();\n if (comp._needsRecompute()) {\n _pendingComputations.unshift(comp);\n }\n\n if (!options.finishSynchronously && ++recomputedCount > 100) {\n finishedTry = true;\n return;\n }\n }\n\n if (_afterFlushCallbacks.length) {\n // call one afterFlush callback, which may\n // invalidate more computations\n var func = _afterFlushCallbacks.shift()!;\n try {\n func();\n } catch (e: any) {\n _throwOrLog('afterFlush', e);\n }\n }\n }\n finishedTry = true;\n } finally {\n if (!finishedTry) {\n // we're erroring due to throwFirstError being true.\n _inFlush = false; // needed before calling `Tracker.flush()` again\n // finish flushing\n _runFlush({\n finishSynchronously: options.finishSynchronously,\n throwFirstError: false,\n });\n }\n _willFlush = false;\n _inFlush = false;\n if (_pendingComputations.length || _afterFlushCallbacks.length) {\n // We're yielding because we ran a bunch of computations and we aren't\n // required to finish synchronously, so we'd like to give the event loop a\n // chance. We should flush again soon.\n if (options.finishSynchronously) {\n throw new Error('still have more to do?'); // shouldn't happen\n }\n setTimeout(_requireFlush, 10);\n }\n }\n }\n\n function _requireFlush() {\n if (!_willFlush) {\n setTimeout(_runFlush, 0);\n _willFlush = true;\n }\n }\n\n /******************************** Tracker Base API ******************************************/\n\n /**\n * 函数在响应式模块中执行\n * @param computation\n * @param f\n */\n export function withComputation<T = any>(\n computation: Computation,\n f: ICallback<Computation, T>,\n ): T {\n let previousComputation = _currentComputation;\n _currentComputation = computation;\n try {\n return f.call(null, computation);\n } finally {\n _currentComputation = previousComputation;\n }\n }\n\n /**\n * 函数在非响应式模块中执行\n */\n export function withoutComputation<T = any>(f: ICallback<undefined, T>): T {\n let previousComputation = _currentComputation;\n _currentComputation = undefined;\n try {\n return f(undefined);\n } finally {\n _currentComputation = previousComputation;\n }\n }\n\n export function isActive(): boolean {\n return !!_currentComputation;\n }\n\n export function getCurrentComputation(): Computation | undefined {\n return _currentComputation;\n }\n\n /**\n * Run a function now and rerun it later whenever its dependencies\n * change. Returns a Computation object that can be used to stop or observe the\n * rerunning.\n */\n export function autorun<T = any>(\n f: IComputationCallback<T>,\n options?: { onError: ICallback<Error> },\n ): Computation<T> {\n var c = new Computation<T>(f, _currentComputation, options?.onError);\n\n if (isActive())\n Tracker.onInvalidate(function () {\n c.stop();\n });\n\n return c;\n }\n\n export function onInvalidate(f: ICallback<Computation | undefined>) {\n if (!_currentComputation) {\n throw new Error('Tracker.onInvalidate requires a currentComputation');\n }\n _currentComputation.onInvalidate(f);\n }\n\n /**\n * True if we are computing a computation now, either first time or recompute. This matches Tracker.active unless we are inside Tracker.nonreactive, which nullfies currentComputation even though an enclosing computation may still be running.\n */\n export function inFlush(): boolean {\n return _inFlush;\n }\n\n /**\n * Process all reactive updates immediately and ensure that all invalidated computations are rerun.\n */\n export function flush(options?: Omit<FlushOptions, 'finishSynchronously'>) {\n _runFlush({\n finishSynchronously: true,\n throwFirstError: options && options.throwFirstError,\n });\n }\n\n /**\n * Schedules a function to be called during the next flush, or later in the current flush if one is in progress, after all invalidated computations have been rerun. The function will be run once and not on subsequent flushes unless `afterFlush` is called again.\n */\n export function afterFlush(f: ICallback) {\n _afterFlushCallbacks.push(f);\n _requireFlush();\n }\n\n /********************************************************************************************/\n\n export type IComputationCallback<V = any> = ICallback<Computation, V>;\n\n /**\n * A Computation object represents code that is repeatedly rerun\n * in response to\n * reactive data changes. Computations don't have return values; they just\n * perform actions, such as rerendering a template on the screen. Computations\n * are created using Tracker.autorun. Use stop to prevent further rerunning of a\n * computation.\n */\n export class Computation<V = any> {\n private _onInvalidateCallbacks: IComputationCallback[] = [];\n\n private _onStopCallbacks: IComputationCallback[] = [];\n\n private _recomputing = false;\n\n private _result: V;\n\n /**\n * 是否停止\n */\n public stopped = false;\n\n /**\n * 未开始执行则返回 false\n */\n public invalidated = false;\n\n /**\n * 是否第一次执行\n */\n public firstRun = true;\n\n constructor(\n private _fn: IComputationCallback<V>,\n public readonly parent?: Computation,\n private readonly _onError?: ICallback<Error>,\n ) {\n let hasError = true;\n try {\n this._compute();\n hasError = false;\n } finally {\n this.firstRun = false;\n if (hasError) {\n this.stop();\n }\n }\n }\n\n onInvalidate(f: IComputationCallback): void {\n if (this.invalidated) {\n withoutComputation(f.bind(null, this));\n } else {\n this._onInvalidateCallbacks.push(f);\n }\n }\n\n /**\n * @summary Invalidates this computation so that it will be rerun.\n */\n invalidate() {\n if (!this.invalidated) {\n // if we're currently in _recompute(), don't enqueue\n // ourselves, since we'll rerun immediately anyway.\n if (!this._recomputing && !this.stopped) {\n _requireFlush();\n _pendingComputations.push(this);\n }\n\n this.invalidated = true;\n\n // callbacks can't add callbacks, because\n // this.invalidated === true.\n for (var i = 0, f: IComputationCallback; (f = this._onInvalidateCallbacks[i]); i++) {\n withoutComputation(f.bind(null, this));\n }\n this._onInvalidateCallbacks = [];\n }\n }\n\n /**\n * @summary Prevents this computation from rerunning.\n * @locus Client\n */\n stop() {\n if (!this.stopped) {\n this.stopped = true;\n this.invalidate();\n for (let i = 0, f: IComputationCallback; (f = this._onStopCallbacks[i]); i++) {\n withoutComputation(f.bind(null, this));\n }\n this._onStopCallbacks = [];\n }\n }\n\n onStop(f: IComputationCallback): void {\n if (this.stopped) {\n withoutComputation(f.bind(null, this));\n } else {\n this._onStopCallbacks.push(f);\n }\n }\n\n private _compute(): void {\n this.invalidated = false;\n\n var previousInCompute = _inCompute;\n _inCompute = true;\n try {\n this._result = Tracker.withComputation<V>(this, this._fn);\n } finally {\n _inCompute = previousInCompute;\n }\n }\n\n _needsRecompute() {\n return this.invalidated && !this.stopped;\n }\n\n _recompute() {\n this._recomputing = true;\n try {\n if (this._needsRecompute()) {\n try {\n this._compute();\n } catch (e: any) {\n if (this._onError) {\n this._onError(e);\n } else {\n _throwOrLog('recompute', e);\n }\n }\n }\n } finally {\n this._recomputing = false;\n }\n }\n\n /**\n * @summary Process the reactive updates for this computation immediately\n * and ensure that the computation is rerun. The computation is rerun only\n * if it is invalidated.\n */\n flush() {\n if (this._recomputing) return;\n\n this._recompute();\n }\n\n /**\n * @summary Causes the function inside this computation to run and\n * synchronously process all reactive updtes.\n * @locus Client\n */\n run() {\n this.invalidate();\n this.flush();\n }\n\n get result(): V {\n return this._result;\n }\n }\n\n /**\n * A Dependency represents an atomic unit of reactive data that a\n * computation might depend on. Reactive data sources such as Session or\n * Minimongo internally create different Dependency objects for different\n * pieces of data, each of which may be depended on by multiple computations.\n * When the data changes, the computations are invalidated.\n */\n export class Dependency {\n private _dependents: Set<Computation> = new Set<Computation>();\n\n /**\n * Declares that the current computation (or `fromComputation` if given) depends on `dependency`. The computation will be invalidated the next time `dependency` changes.\n * If there is no current computation and `depend()` is called with no arguments, it does nothing and returns false.\n * Returns true if the computation is a new dependent of `dependency` rather than an existing one.\n */\n depend(computation?: Computation): boolean {\n if (!computation) {\n if (!isActive()) {\n return false;\n }\n computation = _currentComputation;\n }\n if (!this._dependents.has(computation!)) {\n this._dependents.add(computation!);\n computation!.onInvalidate(() => {\n this._dependents.delete(computation!);\n });\n return true;\n }\n return false;\n }\n\n /**\n * Invalidate all dependent computations immediately and remove them as dependents.\n */\n changed() {\n for (const dep of this._dependents) {\n dep.invalidate();\n }\n }\n\n /**\n * True if this Dependency has one or more dependent Computations, which would be invalidated if this Dependency were to change.\n */\n hasDependents() {\n return this._dependents.size !== 0;\n }\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { Tracker } from './tracker';\n\ntype IStateEqual = (a: any, b: any) => boolean;\n\nexport class ReactiveBaseState<V> {\n protected _dep = new Tracker.Dependency();\n\n protected _value: V;\n\n protected _isEqual: IStateEqual = (a: any, b: any) => a == b;\n\n protected _addDepend(dep: Tracker.Dependency): void {\n if (Tracker.isActive()) {\n dep.depend();\n }\n }\n\n constructor(initialValue: V, opts?: { isEqual?: IStateEqual }) {\n this._value = initialValue;\n if (opts?.isEqual) {\n this._isEqual = opts.isEqual;\n }\n }\n\n hasDependents(): boolean {\n return this._dep.hasDependents();\n }\n\n get value(): V {\n this._addDepend(this._dep);\n return this._value;\n }\n\n set value(newValue: V) {\n if (!this._isEqual(this._value, newValue)) {\n this._value = newValue;\n this._dep.changed();\n }\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\ninterface ProxyOptions<V> {\n get?: (target: V, key: string) => any;\n set?: (target: V, key: string, newValue: any) => boolean;\n}\n\nexport function createProxy<V extends Record<string, any>>(target: V, opts: ProxyOptions<V>): V {\n let useProxy = 'Proxy' in window;\n if (process.env.NODE_ENV === 'test') {\n if ((global as any).__ignoreProxy) {\n useProxy = false;\n }\n }\n if (useProxy) {\n return new Proxy<V>(target, opts);\n }\n const result: V = {} as V;\n for (const key in target) {\n Object.defineProperty(result, key, {\n enumerable: true,\n get: opts.get ? () => opts.get!(target, key) : undefined,\n set: opts.set ? (newValue: any) => opts.set!(target, key, newValue) : undefined,\n });\n }\n return result;\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { Tracker } from './tracker';\n\nimport Dependency = Tracker.Dependency;\n\nimport { ReactiveBaseState } from './reactive-base-state';\nimport { createProxy } from '../utils/create-proxy';\n\nexport class ReactiveState<V extends Record<string, any>> extends ReactiveBaseState<V> {\n private _keyDeps: Map<string, Dependency> = new Map();\n\n set<K extends keyof V & string>(key: K, value: V[K]): boolean {\n this._ensureKey(key);\n const oldValue = this._value[key];\n if (!this._isEqual(oldValue, value)) {\n this._value[key] = value;\n this._keyDeps.get(key)!.changed();\n return true;\n }\n return false;\n }\n\n get<K extends keyof V & string>(key: K): V[K] {\n this._ensureKey(key);\n this._addDepend(this._keyDeps.get(key)!);\n return this._value[key];\n }\n\n protected _ensureKey(key: keyof V & string) {\n if (!this._keyDeps.has(key)) {\n this._keyDeps.set(key, new Dependency());\n }\n }\n\n hasDependents(): boolean {\n if (this._dep.hasDependents()) return true;\n for (const dep of this._keyDeps.values()) {\n if (dep.hasDependents()) return true;\n }\n return false;\n }\n\n keys(): string[] {\n return Object.keys(this._value);\n }\n\n set value(newValue: V) {\n if (!this._isEqual(this._value, newValue)) {\n this._value = newValue;\n this._keyDeps.clear();\n this._dep.changed();\n }\n }\n\n private _proxyValue: V;\n\n get value(): V {\n this._addDepend(this._dep);\n if (!this._proxyValue) {\n this._proxyValue = createProxy<V>(this._value, {\n get: (target, key: string) => this.get(key),\n set: (target, key: string, newValue) => {\n this.set(key, newValue);\n return true;\n },\n });\n }\n return this._proxyValue;\n }\n\n private _proxyReadonlyValue: V;\n\n get readonlyValue(): Readonly<V> {\n this._addDepend(this._dep);\n if (!this._proxyReadonlyValue) {\n this._proxyReadonlyValue = createProxy(this._value, {\n get: (target, key: string) => this.get(key),\n set: (newValue, key: string) => {\n throw new Error(`[ReactiveState] Cannnot set readonly field \"${key}\"`);\n },\n });\n }\n return this._proxyReadonlyValue;\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { getCurrentInstance, onBeforeUnmount, onBeforeUpdate, shallowRef } from 'vue';\n\nimport { createProxy } from '../utils/create-proxy';\nimport { Tracker } from '../core/tracker';\n\nimport Computation = Tracker.Computation;\n\nexport function useObserve<T extends Record<string, any>>(value: T | undefined): T {\n const instance = getCurrentInstance();\n const tick = shallowRef(0);\n const computationMap = new Map<string, Computation>();\n const refresh = () => {\n tick.value += 1;\n instance?.update();\n };\n const clear = () => {\n computationMap.forEach((comp) => comp.stop());\n computationMap.clear();\n };\n onBeforeUpdate(clear);\n onBeforeUnmount(clear);\n if (value === undefined) return {} as T;\n return createProxy(value, {\n get(_target, key: string) {\n void tick.value;\n let computation = computationMap.get(key);\n if (!computation) {\n computation = new Tracker.Computation((c) => {\n if (!c.firstRun) {\n refresh();\n return;\n }\n return value[key];\n });\n computationMap.set(key, computation);\n }\n return value[key];\n },\n });\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { ReactiveState } from '../core/reactive-state';\nimport { useObserve } from './use-observe';\n\nexport function useReactiveState<T extends Record<string, any>>(v: ReactiveState<T> | T): T {\n const state = v instanceof ReactiveState ? v : new ReactiveState(v);\n return useObserve<T>(state.value);\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { ReactiveState } from '../core/reactive-state';\nimport { useObserve } from './use-observe';\n\nexport function useReadonlyReactiveState<T extends Record<string, any>>(\n state: ReactiveState<T>,\n): Readonly<T> {\n return useObserve<T>(state.readonlyValue);\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport {\n defineComponent,\n getCurrentInstance,\n onBeforeUnmount,\n shallowRef,\n type Component,\n type VNode,\n} from 'vue';\n\nimport { Tracker } from '../core/tracker';\n\nimport Computation = Tracker.Computation;\n\nexport function observe<T = any>(fc: (props: T) => VNode | null | undefined): Component {\n return defineComponent({\n name: 'ReactiveObserver',\n inheritAttrs: false,\n setup(_, { attrs, slots }) {\n const instance = getCurrentInstance();\n const tick = shallowRef(0);\n const childrenRef: { current: VNode | null | undefined } = { current: null };\n const computationRef: { current: Computation | undefined } = { current: undefined };\n const refresh = () => {\n tick.value += 1;\n instance?.update();\n };\n\n onBeforeUnmount(() => {\n computationRef.current?.stop();\n });\n\n return () => {\n void tick.value;\n computationRef.current?.stop();\n const slotChildren = slots.default?.();\n const childrenFromSlot =\n slotChildren && slotChildren.length === 1 ? slotChildren[0] : slotChildren;\n const props = {\n ...attrs,\n children: childrenFromSlot ?? (attrs as { children?: unknown }).children,\n } as T;\n computationRef.current = new Tracker.Computation((c) => {\n if (c.firstRun) {\n childrenRef.current = fc(props);\n } else {\n refresh();\n }\n });\n return childrenRef.current ?? null;\n };\n },\n });\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { Tracker } from './core/tracker';\n\nexport { Tracker } from './core/tracker';\nexport { ReactiveState } from './core/reactive-state';\nexport { ReactiveBaseState } from './core/reactive-base-state';\nexport { useReactiveState } from './hooks/use-reactive-state';\nexport { useReadonlyReactiveState } from './hooks/use-readonly-reactive-state';\nexport { useObserve } from './hooks/use-observe';\nexport { observe } from './vue/observe';\nexport const { Dependency, Computation } = Tracker;\n"]}
|