@lytjs/reactivity 5.0.1 → 6.0.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/README.md +327 -202
- package/dist/async.cjs +276 -0
- package/dist/async.cjs.map +1 -0
- package/dist/async.d.cts +32 -0
- package/dist/async.d.ts +32 -0
- package/dist/async.mjs +273 -0
- package/dist/async.mjs.map +1 -0
- package/dist/index.cjs +1607 -1
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +226 -0
- package/dist/index.d.ts +226 -0
- package/dist/index.mjs +1543 -1
- package/dist/index.mjs.map +1 -0
- package/dist/ref-CwOCKoy2.d.cts +42 -0
- package/dist/ref-CwOCKoy2.d.ts +42 -0
- package/dist/scope.cjs +74 -0
- package/dist/scope.cjs.map +1 -0
- package/dist/scope.d.cts +71 -0
- package/dist/scope.d.ts +71 -0
- package/dist/scope.mjs +70 -0
- package/dist/scope.mjs.map +1 -0
- package/dist/signal-BOAyevht.d.cts +109 -0
- package/dist/signal-BOAyevht.d.ts +109 -0
- package/dist/signal-component.cjs +39 -0
- package/dist/signal-component.cjs.map +1 -0
- package/dist/signal-component.d.cts +31 -0
- package/dist/signal-component.d.ts +31 -0
- package/dist/signal-component.mjs +35 -0
- package/dist/signal-component.mjs.map +1 -0
- package/dist/signal.cjs +350 -1
- package/dist/signal.cjs.map +1 -0
- package/dist/signal.d.cts +1 -0
- package/dist/signal.d.ts +1 -0
- package/dist/signal.mjs +334 -1
- package/dist/signal.mjs.map +1 -0
- package/dist/types-CMYee6LB.d.cts +270 -0
- package/dist/types-CXeWWYm6.d.ts +270 -0
- package/package.json +54 -31
- package/dist/types/computed.d.ts +0 -70
- package/dist/types/computed.d.ts.map +0 -1
- package/dist/types/effect.d.ts +0 -157
- package/dist/types/effect.d.ts.map +0 -1
- package/dist/types/index.d.ts +0 -21
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/reactive.d.ts +0 -98
- package/dist/types/reactive.d.ts.map +0 -1
- package/dist/types/ref.d.ts +0 -128
- package/dist/types/ref.d.ts.map +0 -1
- package/dist/types/scheduler.d.ts +0 -44
- package/dist/types/scheduler.d.ts.map +0 -1
- package/dist/types/signal-component.d.ts +0 -45
- package/dist/types/signal-component.d.ts.map +0 -1
- package/dist/types/signal.d.ts +0 -87
- package/dist/types/signal.d.ts.map +0 -1
- package/dist/types/watch.d.ts +0 -125
- package/dist/types/watch.d.ts.map +0 -1
package/dist/scope.d.cts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { z as ReactiveEffect } from './types-CMYee6LB.cjs';
|
|
2
|
+
import './ref-CwOCKoy2.cjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* effectScope 收集的条目类型
|
|
6
|
+
* - ReactiveEffect: 响应式副作用
|
|
7
|
+
* - EffectScope: 嵌套的子 scope
|
|
8
|
+
*/
|
|
9
|
+
type EffectScopeEntry = ReactiveEffect | EffectScope;
|
|
10
|
+
|
|
11
|
+
interface EffectScope {
|
|
12
|
+
/** 当前 scope 是否活跃 */
|
|
13
|
+
active: boolean;
|
|
14
|
+
/** scope 收集的 effects */
|
|
15
|
+
effects: EffectScopeEntry[];
|
|
16
|
+
/** scope 注册的清理回调 */
|
|
17
|
+
cleanups: (() => void)[];
|
|
18
|
+
/** 父 scope(嵌套时自动关联) */
|
|
19
|
+
parent: EffectScope | undefined;
|
|
20
|
+
/** 是否脱离父 scope(detached scope 不会被父 scope stop) */
|
|
21
|
+
detached: boolean;
|
|
22
|
+
/** 在 scope 上下文中执行 fn,期间创建的 effect 会被自动收集 */
|
|
23
|
+
run<T>(fn: () => T): T | undefined;
|
|
24
|
+
/** 停止 scope,清理所有收集的 effects 和 cleanups */
|
|
25
|
+
stop(): void;
|
|
26
|
+
}
|
|
27
|
+
interface EffectScopeOptions {
|
|
28
|
+
detached?: boolean;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* 创建一个 effect scope,用于批量管理响应式副作用。
|
|
32
|
+
*
|
|
33
|
+
* @param options - 配置选项。支持传入 boolean(兼容旧 API)或 EffectScopeOptions 对象。
|
|
34
|
+
* @returns EffectScope 实例
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* const scope = effectScope()
|
|
39
|
+
* scope.run(() => {
|
|
40
|
+
* const count = ref(0)
|
|
41
|
+
* watch(count, () => console.log(count.value))
|
|
42
|
+
* })
|
|
43
|
+
* // 不再需要时一次性停止所有副作用
|
|
44
|
+
* scope.stop()
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
declare function effectScope(options?: boolean | EffectScopeOptions): EffectScope;
|
|
48
|
+
/**
|
|
49
|
+
* 获取当前活跃的 effectScope。
|
|
50
|
+
*/
|
|
51
|
+
declare function getCurrentScope(): EffectScope | undefined;
|
|
52
|
+
/**
|
|
53
|
+
* 在当前活跃的 effectScope 中注册一个清理回调。
|
|
54
|
+
* 当 scope 被 stop 时,所有注册的回调会被执行。
|
|
55
|
+
*
|
|
56
|
+
* @param fn - 清理回调函数
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```ts
|
|
60
|
+
* const scope = effectScope()
|
|
61
|
+
* scope.run(() => {
|
|
62
|
+
* onScopeDispose(() => {
|
|
63
|
+
* console.log('scope disposed')
|
|
64
|
+
* })
|
|
65
|
+
* })
|
|
66
|
+
* scope.stop() // 输出: scope disposed
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
declare function onScopeDispose(fn: () => void): void;
|
|
70
|
+
|
|
71
|
+
export { type EffectScope, type EffectScopeOptions, effectScope, getCurrentScope, onScopeDispose };
|
package/dist/scope.d.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { z as ReactiveEffect } from './types-CXeWWYm6.js';
|
|
2
|
+
import './ref-CwOCKoy2.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* effectScope 收集的条目类型
|
|
6
|
+
* - ReactiveEffect: 响应式副作用
|
|
7
|
+
* - EffectScope: 嵌套的子 scope
|
|
8
|
+
*/
|
|
9
|
+
type EffectScopeEntry = ReactiveEffect | EffectScope;
|
|
10
|
+
|
|
11
|
+
interface EffectScope {
|
|
12
|
+
/** 当前 scope 是否活跃 */
|
|
13
|
+
active: boolean;
|
|
14
|
+
/** scope 收集的 effects */
|
|
15
|
+
effects: EffectScopeEntry[];
|
|
16
|
+
/** scope 注册的清理回调 */
|
|
17
|
+
cleanups: (() => void)[];
|
|
18
|
+
/** 父 scope(嵌套时自动关联) */
|
|
19
|
+
parent: EffectScope | undefined;
|
|
20
|
+
/** 是否脱离父 scope(detached scope 不会被父 scope stop) */
|
|
21
|
+
detached: boolean;
|
|
22
|
+
/** 在 scope 上下文中执行 fn,期间创建的 effect 会被自动收集 */
|
|
23
|
+
run<T>(fn: () => T): T | undefined;
|
|
24
|
+
/** 停止 scope,清理所有收集的 effects 和 cleanups */
|
|
25
|
+
stop(): void;
|
|
26
|
+
}
|
|
27
|
+
interface EffectScopeOptions {
|
|
28
|
+
detached?: boolean;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* 创建一个 effect scope,用于批量管理响应式副作用。
|
|
32
|
+
*
|
|
33
|
+
* @param options - 配置选项。支持传入 boolean(兼容旧 API)或 EffectScopeOptions 对象。
|
|
34
|
+
* @returns EffectScope 实例
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* const scope = effectScope()
|
|
39
|
+
* scope.run(() => {
|
|
40
|
+
* const count = ref(0)
|
|
41
|
+
* watch(count, () => console.log(count.value))
|
|
42
|
+
* })
|
|
43
|
+
* // 不再需要时一次性停止所有副作用
|
|
44
|
+
* scope.stop()
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
declare function effectScope(options?: boolean | EffectScopeOptions): EffectScope;
|
|
48
|
+
/**
|
|
49
|
+
* 获取当前活跃的 effectScope。
|
|
50
|
+
*/
|
|
51
|
+
declare function getCurrentScope(): EffectScope | undefined;
|
|
52
|
+
/**
|
|
53
|
+
* 在当前活跃的 effectScope 中注册一个清理回调。
|
|
54
|
+
* 当 scope 被 stop 时,所有注册的回调会被执行。
|
|
55
|
+
*
|
|
56
|
+
* @param fn - 清理回调函数
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```ts
|
|
60
|
+
* const scope = effectScope()
|
|
61
|
+
* scope.run(() => {
|
|
62
|
+
* onScopeDispose(() => {
|
|
63
|
+
* console.log('scope disposed')
|
|
64
|
+
* })
|
|
65
|
+
* })
|
|
66
|
+
* scope.stop() // 输出: scope disposed
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
declare function onScopeDispose(fn: () => void): void;
|
|
70
|
+
|
|
71
|
+
export { type EffectScope, type EffectScopeOptions, effectScope, getCurrentScope, onScopeDispose };
|
package/dist/scope.mjs
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { error } from '@lytjs/common-error';
|
|
2
|
+
import { unsafeCast } from '@lytjs/common-assertions';
|
|
3
|
+
|
|
4
|
+
// src/effect-scope.ts
|
|
5
|
+
var activeEffectScope;
|
|
6
|
+
function effectScope(options) {
|
|
7
|
+
const detached = typeof options === "boolean" ? options : options?.detached;
|
|
8
|
+
const scope = {
|
|
9
|
+
active: true,
|
|
10
|
+
effects: [],
|
|
11
|
+
cleanups: [],
|
|
12
|
+
parent: activeEffectScope,
|
|
13
|
+
detached: !!detached,
|
|
14
|
+
run(fn) {
|
|
15
|
+
if (!this.active) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const prevScope = activeEffectScope;
|
|
19
|
+
activeEffectScope = this;
|
|
20
|
+
try {
|
|
21
|
+
return fn();
|
|
22
|
+
} finally {
|
|
23
|
+
activeEffectScope = prevScope;
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
stop() {
|
|
27
|
+
if (!this.active) return;
|
|
28
|
+
this.active = false;
|
|
29
|
+
for (const effect of this.effects) {
|
|
30
|
+
try {
|
|
31
|
+
effect.stop();
|
|
32
|
+
} catch (e) {
|
|
33
|
+
error(`Error stopping effect in scope: ${String(e)}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
for (const cleanup of this.cleanups) {
|
|
37
|
+
try {
|
|
38
|
+
cleanup();
|
|
39
|
+
} catch (e) {
|
|
40
|
+
error(`Error running cleanup in scope: ${String(e)}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (this.parent) {
|
|
44
|
+
const idx = this.parent.effects.indexOf(unsafeCast(this));
|
|
45
|
+
if (idx !== -1) {
|
|
46
|
+
this.parent.effects.splice(idx, 1);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
this.effects.length = 0;
|
|
50
|
+
this.cleanups.length = 0;
|
|
51
|
+
this.parent = void 0;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
if (!scope.detached && activeEffectScope) {
|
|
55
|
+
activeEffectScope.effects.push(unsafeCast(scope));
|
|
56
|
+
}
|
|
57
|
+
return scope;
|
|
58
|
+
}
|
|
59
|
+
function getCurrentScope() {
|
|
60
|
+
return activeEffectScope;
|
|
61
|
+
}
|
|
62
|
+
function onScopeDispose(fn) {
|
|
63
|
+
if (activeEffectScope) {
|
|
64
|
+
activeEffectScope.cleanups.push(fn);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export { effectScope, getCurrentScope, onScopeDispose };
|
|
69
|
+
//# sourceMappingURL=scope.mjs.map
|
|
70
|
+
//# sourceMappingURL=scope.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/effect-scope.ts"],"names":[],"mappings":";;;;AA8BA,IAAI,iBAAA;AA6BG,SAAS,YAAY,OAAA,EAAqD;AAC/E,EAAA,MAAM,QAAA,GAAW,OAAO,OAAA,KAAY,SAAA,GAAY,UAAU,OAAA,EAAS,QAAA;AACnE,EAAA,MAAM,KAAA,GAAqB;AAAA,IACzB,MAAA,EAAQ,IAAA;AAAA,IACR,SAAS,EAAC;AAAA,IACV,UAAU,EAAC;AAAA,IACX,MAAA,EAAQ,iBAAA;AAAA,IACR,QAAA,EAAU,CAAC,CAAC,QAAA;AAAA,IAEZ,IAAI,EAAA,EAAI;AACN,MAAA,IAAI,CAAC,KAAK,MAAA,EAAQ;AAIhB,QAAA;AAAA,MACF;AACA,MAAA,MAAM,SAAA,GAAY,iBAAA;AAElB,MAAA,iBAAA,GAAoB,IAAA;AACpB,MAAA,IAAI;AACF,QAAA,OAAO,EAAA,EAAG;AAAA,MACZ,CAAA,SAAE;AACA,QAAA,iBAAA,GAAoB,SAAA;AAAA,MACtB;AAAA,IACF,CAAA;AAAA,IAEA,IAAA,GAAO;AACL,MAAA,IAAI,CAAC,KAAK,MAAA,EAAQ;AAClB,MAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AACd,MAAA,KAAA,MAAW,MAAA,IAAU,KAAK,OAAA,EAAS;AACjC,QAAA,IAAI;AACF,UAAA,MAAA,CAAO,IAAA,EAAK;AAAA,QACd,SAAS,CAAA,EAAG;AACV,UAAA,KAAA,CAAM,CAAA,gCAAA,EAAmC,MAAA,CAAO,CAAC,CAAC,CAAA,CAAE,CAAA;AAAA,QACtD;AAAA,MACF;AACA,MAAA,KAAA,MAAW,OAAA,IAAW,KAAK,QAAA,EAAU;AACnC,QAAA,IAAI;AACF,UAAA,OAAA,EAAQ;AAAA,QACV,SAAS,CAAA,EAAG;AACV,UAAA,KAAA,CAAM,CAAA,gCAAA,EAAmC,MAAA,CAAO,CAAC,CAAC,CAAA,CAAE,CAAA;AAAA,QACtD;AAAA,MACF;AACA,MAAA,IAAI,KAAK,MAAA,EAAQ;AACf,QAAA,MAAM,MAAM,IAAA,CAAK,MAAA,CAAO,QAAQ,OAAA,CAAQ,UAAA,CAA6B,IAAI,CAAC,CAAA;AAC1E,QAAA,IAAI,QAAQ,EAAA,EAAI;AACd,UAAA,IAAA,CAAK,MAAA,CAAO,OAAA,CAAQ,MAAA,CAAO,GAAA,EAAK,CAAC,CAAA;AAAA,QACnC;AAAA,MACF;AACA,MAAA,IAAA,CAAK,QAAQ,MAAA,GAAS,CAAA;AACtB,MAAA,IAAA,CAAK,SAAS,MAAA,GAAS,CAAA;AACvB,MAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAAA,IAChB;AAAA,GACF;AAEA,EAAA,IAAI,CAAC,KAAA,CAAM,QAAA,IAAY,iBAAA,EAAmB;AAIxC,IAAA,iBAAA,CAAkB,OAAA,CAAQ,IAAA,CAAK,UAAA,CAA6B,KAAK,CAAC,CAAA;AAAA,EACpE;AAEA,EAAA,OAAO,KAAA;AACT;AAKO,SAAS,eAAA,GAA2C;AACzD,EAAA,OAAO,iBAAA;AACT;AAmBO,SAAS,eAAe,EAAA,EAAsB;AACnD,EAAA,IAAI,iBAAA,EAAmB;AACrB,IAAA,iBAAA,CAAkB,QAAA,CAAS,KAAK,EAAE,CAAA;AAAA,EACpC;AAKF","file":"scope.mjs","sourcesContent":["// src/effect-scope.ts\r\n// Vue 3 风格的 effectScope API\r\n// 用于批量管理响应式副作用的创建和销毁\r\n\r\nimport type { EffectScopeEntry } from './effect-scope-registrar';\r\nimport { warn, error } from '@lytjs/common-error';\r\nimport { unsafeCast } from '@lytjs/common-assertions';\r\n\r\nexport interface EffectScope {\r\n /** 当前 scope 是否活跃 */\r\n active: boolean;\r\n /** scope 收集的 effects */\r\n effects: EffectScopeEntry[];\r\n /** scope 注册的清理回调 */\r\n cleanups: (() => void)[];\r\n /** 父 scope(嵌套时自动关联) */\r\n parent: EffectScope | undefined;\r\n /** 是否脱离父 scope(detached scope 不会被父 scope stop) */\r\n detached: boolean;\r\n /** 在 scope 上下文中执行 fn,期间创建的 effect 会被自动收集 */\r\n run<T>(fn: () => T): T | undefined;\r\n /** 停止 scope,清理所有收集的 effects 和 cleanups */\r\n stop(): void;\r\n}\r\n\r\nexport interface EffectScopeOptions {\r\n detached?: boolean;\r\n}\r\n\r\n/** 当前活跃的 effectScope(唯一来源) */\r\nlet activeEffectScope: EffectScope | undefined;\r\n\r\n/** 获取当前活跃的 effectScope */\r\nexport function getActiveEffectScope(): EffectScope | undefined {\r\n return activeEffectScope;\r\n}\r\n\r\n/** 设置当前活跃的 effectScope */\r\nexport function setActiveEffectScope(scope: EffectScope | undefined): void {\r\n activeEffectScope = scope;\r\n}\r\n\r\n/**\r\n * 创建一个 effect scope,用于批量管理响应式副作用。\r\n *\r\n * @param options - 配置选项。支持传入 boolean(兼容旧 API)或 EffectScopeOptions 对象。\r\n * @returns EffectScope 实例\r\n *\r\n * @example\r\n * ```ts\r\n * const scope = effectScope()\r\n * scope.run(() => {\r\n * const count = ref(0)\r\n * watch(count, () => console.log(count.value))\r\n * })\r\n * // 不再需要时一次性停止所有副作用\r\n * scope.stop()\r\n * ```\r\n */\r\nexport function effectScope(options?: boolean | EffectScopeOptions): EffectScope {\r\n const detached = typeof options === 'boolean' ? options : options?.detached;\r\n const scope: EffectScope = {\r\n active: true,\r\n effects: [],\r\n cleanups: [],\r\n parent: activeEffectScope,\r\n detached: !!detached,\r\n\r\n run(fn) {\r\n if (!this.active) {\r\n if (__DEV__) {\r\n warn(`EffectScope is not active. Cannot run fn.`);\r\n }\r\n return;\r\n }\r\n const prevScope = activeEffectScope;\r\n // eslint-disable-next-line @typescript-eslint/no-this-alias\r\n activeEffectScope = this;\r\n try {\r\n return fn();\r\n } finally {\r\n activeEffectScope = prevScope;\r\n }\r\n },\r\n\r\n stop() {\r\n if (!this.active) return;\r\n this.active = false;\r\n for (const effect of this.effects) {\r\n try {\r\n effect.stop();\r\n } catch (e) {\r\n error(`Error stopping effect in scope: ${String(e)}`);\r\n }\r\n }\r\n for (const cleanup of this.cleanups) {\r\n try {\r\n cleanup();\r\n } catch (e) {\r\n error(`Error running cleanup in scope: ${String(e)}`);\r\n }\r\n }\r\n if (this.parent) {\r\n const idx = this.parent.effects.indexOf(unsafeCast<EffectScopeEntry>(this));\r\n if (idx !== -1) {\r\n this.parent.effects.splice(idx, 1);\r\n }\r\n }\r\n this.effects.length = 0;\r\n this.cleanups.length = 0;\r\n this.parent = undefined;\r\n },\r\n } as EffectScope;\r\n\r\n if (!scope.detached && activeEffectScope) {\r\n // 双重断言是必要的:EffectScope 对象字面量实现了 EffectScopeEntry 所需的\r\n // stop() 方法,但 TypeScript 无法自动推断对象字面量满足联合类型。\r\n // EffectScopeEntry = ReactiveEffect | EffectScope,此处 scope 是 EffectScope 实例。\r\n activeEffectScope.effects.push(unsafeCast<EffectScopeEntry>(scope));\r\n }\r\n\r\n return scope;\r\n}\r\n\r\n/**\r\n * 获取当前活跃的 effectScope。\r\n */\r\nexport function getCurrentScope(): EffectScope | undefined {\r\n return activeEffectScope;\r\n}\r\n\r\n/**\r\n * 在当前活跃的 effectScope 中注册一个清理回调。\r\n * 当 scope 被 stop 时,所有注册的回调会被执行。\r\n *\r\n * @param fn - 清理回调函数\r\n *\r\n * @example\r\n * ```ts\r\n * const scope = effectScope()\r\n * scope.run(() => {\r\n * onScopeDispose(() => {\r\n * console.log('scope disposed')\r\n * })\r\n * })\r\n * scope.stop() // 输出: scope disposed\r\n * ```\r\n */\r\nexport function onScopeDispose(fn: () => void): void {\r\n if (activeEffectScope) {\r\n activeEffectScope.cleanups.push(fn);\r\n } else if (__DEV__) {\r\n warn(\r\n 'onScopeDispose() was called when there was no active effect scope to be associated with.',\r\n );\r\n }\r\n}\r\n"]}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
declare const RefSymbol: unique symbol;
|
|
2
|
+
declare const ShallowRefSymbol: unique symbol;
|
|
3
|
+
declare const ComputedRefSymbol: unique symbol;
|
|
4
|
+
declare const ReactiveSymbol: unique symbol;
|
|
5
|
+
declare const ReadonlySymbol: unique symbol;
|
|
6
|
+
declare const SignalSymbol: unique symbol;
|
|
7
|
+
declare const ComputedSignalSymbol: unique symbol;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @lytjs/reactivity - Shared Types
|
|
11
|
+
* 响应式系统公共类型定义。
|
|
12
|
+
*/
|
|
13
|
+
/** 订阅者回调函数 */
|
|
14
|
+
type Subscriber = () => void;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @lytjs/reactivity - Signal
|
|
18
|
+
* 独立自包含的 Signal 响应式原语。
|
|
19
|
+
* 拥有独立的订阅/通知机制,同时桥接 effect 系统保持互操作性。
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/** Signal 只读接口 */
|
|
23
|
+
interface Signal<T = unknown> {
|
|
24
|
+
/** 读取当前值 */
|
|
25
|
+
(): T;
|
|
26
|
+
readonly [SignalSymbol]: true;
|
|
27
|
+
}
|
|
28
|
+
/** WritableSignal 可写接口 */
|
|
29
|
+
interface WritableSignal<T = unknown> extends Signal<T> {
|
|
30
|
+
/** 设置新值 */
|
|
31
|
+
set(newValue: T): void;
|
|
32
|
+
/** 通过 updater 函数更新值 */
|
|
33
|
+
update(updater: (prev: T) => T): void;
|
|
34
|
+
/** 停止所有订阅通知,释放资源 */
|
|
35
|
+
dispose(): void;
|
|
36
|
+
/** @internal 订阅变更通知 */
|
|
37
|
+
_subscribe(subscriber: Subscriber): () => void;
|
|
38
|
+
/** FIX: P1-5 REACTIVITY-NEW-03 - 手动清理依赖,防止内存泄漏 */
|
|
39
|
+
cleanup(): void;
|
|
40
|
+
}
|
|
41
|
+
/** ComputedSignal 计算信号接口 */
|
|
42
|
+
interface ComputedSignal<T = unknown> extends Signal<T> {
|
|
43
|
+
/** 停止计算信号的依赖追踪和更新 */
|
|
44
|
+
dispose(): void;
|
|
45
|
+
/** @deprecated 使用 dispose() */
|
|
46
|
+
stop?: () => void;
|
|
47
|
+
readonly [ComputedSignalSymbol]: true;
|
|
48
|
+
}
|
|
49
|
+
/** WritableComputedSignal 可写计算信号接口 */
|
|
50
|
+
interface WritableComputedSignal<T = unknown> extends ComputedSignal<T> {
|
|
51
|
+
/** 设置新值(通过 setter 函数) */
|
|
52
|
+
set(newValue: T): void;
|
|
53
|
+
}
|
|
54
|
+
/** ReadonlySignal 只读信号接口 */
|
|
55
|
+
interface ReadonlySignal<T = unknown> {
|
|
56
|
+
/** 读取当前值 */
|
|
57
|
+
(): T;
|
|
58
|
+
readonly [SignalSymbol]: true;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* 创建一个可写 Signal。
|
|
62
|
+
* 使用闭包变量存储值,Set 管理订阅者。
|
|
63
|
+
*/
|
|
64
|
+
declare function signal<T>(initialValue: T): WritableSignal<T>;
|
|
65
|
+
/**
|
|
66
|
+
* 创建一个计算信号。
|
|
67
|
+
* 惰性求值、自动依赖追踪与清理、循环依赖检测。
|
|
68
|
+
*/
|
|
69
|
+
declare function computed<T>(fn: () => T): ComputedSignal<T>;
|
|
70
|
+
/**
|
|
71
|
+
* 创建一个可写计算信号。
|
|
72
|
+
* 通过 getter 读取计算值,通过 setter 写入值。
|
|
73
|
+
* setter 通常会间接更新 getter 依赖的底层 signal。
|
|
74
|
+
*/
|
|
75
|
+
declare function writableComputedSignal<T>(getter: () => T, setter: (value: T) => void): WritableComputedSignal<T>;
|
|
76
|
+
/**
|
|
77
|
+
* 在批处理中执行函数。
|
|
78
|
+
* batch 内多次 signal.set 只在函数结束后统一触发一次通知。
|
|
79
|
+
*/
|
|
80
|
+
declare function signalBatch(fn: () => void): void;
|
|
81
|
+
/**
|
|
82
|
+
* 在取消追踪模式中执行函数。
|
|
83
|
+
* 函数内读取 signal 不会建立依赖关系。
|
|
84
|
+
*/
|
|
85
|
+
declare function signalUntrack<T>(fn: () => T): T;
|
|
86
|
+
/** @internal 检查当前是否处于 untrack 模式(供 effect 系统桥接使用) */
|
|
87
|
+
declare function _isSignalUntracked(): boolean;
|
|
88
|
+
/**
|
|
89
|
+
* @deprecated 使用 computed() 代替
|
|
90
|
+
*/
|
|
91
|
+
declare function computedSignal<T>(fn: () => T): ComputedSignal<T>;
|
|
92
|
+
/** 读取 signal 值 */
|
|
93
|
+
declare function valueOf<T>(sig: Signal<T>): T;
|
|
94
|
+
/** 设置 signal 值(适配器) */
|
|
95
|
+
declare function set<T>(sig: WritableSignal<T> | ReadonlySignal<T>, newValue: T): void;
|
|
96
|
+
/** 通过 updater 更新 signal 值(适配器) */
|
|
97
|
+
declare function update<T>(sig: WritableSignal<T>, updater: (prev: T) => T): void;
|
|
98
|
+
/** 创建只读 signal(适配器) */
|
|
99
|
+
declare function readonlySignal<T>(sig: Signal<T>): ReadonlySignal<T>;
|
|
100
|
+
/** @internal 获取当前活跃订阅者(仅用于测试) */
|
|
101
|
+
declare function _getActiveSubscriber(): Subscriber | null;
|
|
102
|
+
/** @internal 获取 batch 深度(仅用于测试) */
|
|
103
|
+
declare function _getBatchDepth(): number;
|
|
104
|
+
/** @internal 获取待通知订阅者数量(仅用于测试) */
|
|
105
|
+
declare function _getPendingNotificationsCount(): number;
|
|
106
|
+
/** @internal 重置全局状态(仅用于测试) */
|
|
107
|
+
declare function _resetSignalGlobalState(): void;
|
|
108
|
+
|
|
109
|
+
export { ComputedRefSymbol as C, ReactiveSymbol as R, ShallowRefSymbol as S, type WritableComputedSignal as W, _getActiveSubscriber as _, type ComputedSignal as a, type ReadonlySignal as b, ReadonlySymbol as c, RefSymbol as d, type Signal as e, type Subscriber as f, type WritableSignal as g, computedSignal as h, signal as i, signalBatch as j, computed as k, signalUntrack as l, _getBatchDepth as m, _getPendingNotificationsCount as n, _isSignalUntracked as o, _resetSignalGlobalState as p, readonlySignal as r, set as s, update as u, valueOf as v, writableComputedSignal as w };
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
declare const RefSymbol: unique symbol;
|
|
2
|
+
declare const ShallowRefSymbol: unique symbol;
|
|
3
|
+
declare const ComputedRefSymbol: unique symbol;
|
|
4
|
+
declare const ReactiveSymbol: unique symbol;
|
|
5
|
+
declare const ReadonlySymbol: unique symbol;
|
|
6
|
+
declare const SignalSymbol: unique symbol;
|
|
7
|
+
declare const ComputedSignalSymbol: unique symbol;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @lytjs/reactivity - Shared Types
|
|
11
|
+
* 响应式系统公共类型定义。
|
|
12
|
+
*/
|
|
13
|
+
/** 订阅者回调函数 */
|
|
14
|
+
type Subscriber = () => void;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @lytjs/reactivity - Signal
|
|
18
|
+
* 独立自包含的 Signal 响应式原语。
|
|
19
|
+
* 拥有独立的订阅/通知机制,同时桥接 effect 系统保持互操作性。
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/** Signal 只读接口 */
|
|
23
|
+
interface Signal<T = unknown> {
|
|
24
|
+
/** 读取当前值 */
|
|
25
|
+
(): T;
|
|
26
|
+
readonly [SignalSymbol]: true;
|
|
27
|
+
}
|
|
28
|
+
/** WritableSignal 可写接口 */
|
|
29
|
+
interface WritableSignal<T = unknown> extends Signal<T> {
|
|
30
|
+
/** 设置新值 */
|
|
31
|
+
set(newValue: T): void;
|
|
32
|
+
/** 通过 updater 函数更新值 */
|
|
33
|
+
update(updater: (prev: T) => T): void;
|
|
34
|
+
/** 停止所有订阅通知,释放资源 */
|
|
35
|
+
dispose(): void;
|
|
36
|
+
/** @internal 订阅变更通知 */
|
|
37
|
+
_subscribe(subscriber: Subscriber): () => void;
|
|
38
|
+
/** FIX: P1-5 REACTIVITY-NEW-03 - 手动清理依赖,防止内存泄漏 */
|
|
39
|
+
cleanup(): void;
|
|
40
|
+
}
|
|
41
|
+
/** ComputedSignal 计算信号接口 */
|
|
42
|
+
interface ComputedSignal<T = unknown> extends Signal<T> {
|
|
43
|
+
/** 停止计算信号的依赖追踪和更新 */
|
|
44
|
+
dispose(): void;
|
|
45
|
+
/** @deprecated 使用 dispose() */
|
|
46
|
+
stop?: () => void;
|
|
47
|
+
readonly [ComputedSignalSymbol]: true;
|
|
48
|
+
}
|
|
49
|
+
/** WritableComputedSignal 可写计算信号接口 */
|
|
50
|
+
interface WritableComputedSignal<T = unknown> extends ComputedSignal<T> {
|
|
51
|
+
/** 设置新值(通过 setter 函数) */
|
|
52
|
+
set(newValue: T): void;
|
|
53
|
+
}
|
|
54
|
+
/** ReadonlySignal 只读信号接口 */
|
|
55
|
+
interface ReadonlySignal<T = unknown> {
|
|
56
|
+
/** 读取当前值 */
|
|
57
|
+
(): T;
|
|
58
|
+
readonly [SignalSymbol]: true;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* 创建一个可写 Signal。
|
|
62
|
+
* 使用闭包变量存储值,Set 管理订阅者。
|
|
63
|
+
*/
|
|
64
|
+
declare function signal<T>(initialValue: T): WritableSignal<T>;
|
|
65
|
+
/**
|
|
66
|
+
* 创建一个计算信号。
|
|
67
|
+
* 惰性求值、自动依赖追踪与清理、循环依赖检测。
|
|
68
|
+
*/
|
|
69
|
+
declare function computed<T>(fn: () => T): ComputedSignal<T>;
|
|
70
|
+
/**
|
|
71
|
+
* 创建一个可写计算信号。
|
|
72
|
+
* 通过 getter 读取计算值,通过 setter 写入值。
|
|
73
|
+
* setter 通常会间接更新 getter 依赖的底层 signal。
|
|
74
|
+
*/
|
|
75
|
+
declare function writableComputedSignal<T>(getter: () => T, setter: (value: T) => void): WritableComputedSignal<T>;
|
|
76
|
+
/**
|
|
77
|
+
* 在批处理中执行函数。
|
|
78
|
+
* batch 内多次 signal.set 只在函数结束后统一触发一次通知。
|
|
79
|
+
*/
|
|
80
|
+
declare function signalBatch(fn: () => void): void;
|
|
81
|
+
/**
|
|
82
|
+
* 在取消追踪模式中执行函数。
|
|
83
|
+
* 函数内读取 signal 不会建立依赖关系。
|
|
84
|
+
*/
|
|
85
|
+
declare function signalUntrack<T>(fn: () => T): T;
|
|
86
|
+
/** @internal 检查当前是否处于 untrack 模式(供 effect 系统桥接使用) */
|
|
87
|
+
declare function _isSignalUntracked(): boolean;
|
|
88
|
+
/**
|
|
89
|
+
* @deprecated 使用 computed() 代替
|
|
90
|
+
*/
|
|
91
|
+
declare function computedSignal<T>(fn: () => T): ComputedSignal<T>;
|
|
92
|
+
/** 读取 signal 值 */
|
|
93
|
+
declare function valueOf<T>(sig: Signal<T>): T;
|
|
94
|
+
/** 设置 signal 值(适配器) */
|
|
95
|
+
declare function set<T>(sig: WritableSignal<T> | ReadonlySignal<T>, newValue: T): void;
|
|
96
|
+
/** 通过 updater 更新 signal 值(适配器) */
|
|
97
|
+
declare function update<T>(sig: WritableSignal<T>, updater: (prev: T) => T): void;
|
|
98
|
+
/** 创建只读 signal(适配器) */
|
|
99
|
+
declare function readonlySignal<T>(sig: Signal<T>): ReadonlySignal<T>;
|
|
100
|
+
/** @internal 获取当前活跃订阅者(仅用于测试) */
|
|
101
|
+
declare function _getActiveSubscriber(): Subscriber | null;
|
|
102
|
+
/** @internal 获取 batch 深度(仅用于测试) */
|
|
103
|
+
declare function _getBatchDepth(): number;
|
|
104
|
+
/** @internal 获取待通知订阅者数量(仅用于测试) */
|
|
105
|
+
declare function _getPendingNotificationsCount(): number;
|
|
106
|
+
/** @internal 重置全局状态(仅用于测试) */
|
|
107
|
+
declare function _resetSignalGlobalState(): void;
|
|
108
|
+
|
|
109
|
+
export { ComputedRefSymbol as C, ReactiveSymbol as R, ShallowRefSymbol as S, type WritableComputedSignal as W, _getActiveSubscriber as _, type ComputedSignal as a, type ReadonlySignal as b, ReadonlySymbol as c, RefSymbol as d, type Signal as e, type Subscriber as f, type WritableSignal as g, computedSignal as h, signal as i, signalBatch as j, computed as k, signalUntrack as l, _getBatchDepth as m, _getPendingNotificationsCount as n, _isSignalUntracked as o, _resetSignalGlobalState as p, readonlySignal as r, set as s, update as u, valueOf as v, writableComputedSignal as w };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/signal-component.ts
|
|
4
|
+
function extractSignals(options) {
|
|
5
|
+
const signals = [];
|
|
6
|
+
if (options.signals) {
|
|
7
|
+
signals.push(...Object.values(options.signals));
|
|
8
|
+
}
|
|
9
|
+
if (options.computed) {
|
|
10
|
+
signals.push(...Object.values(options.computed));
|
|
11
|
+
}
|
|
12
|
+
return signals;
|
|
13
|
+
}
|
|
14
|
+
function createSignalBinding(sig, onChange) {
|
|
15
|
+
return {
|
|
16
|
+
get: () => sig(),
|
|
17
|
+
set: (value) => {
|
|
18
|
+
sig.set(value);
|
|
19
|
+
onChange?.(value);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function signalToProps(signals) {
|
|
24
|
+
const props = {};
|
|
25
|
+
for (const [key, sig] of Object.entries(signals)) {
|
|
26
|
+
Object.defineProperty(props, key, {
|
|
27
|
+
get: () => sig(),
|
|
28
|
+
enumerable: true,
|
|
29
|
+
configurable: true
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
return props;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
exports.createSignalBinding = createSignalBinding;
|
|
36
|
+
exports.extractSignals = extractSignals;
|
|
37
|
+
exports.signalToProps = signalToProps;
|
|
38
|
+
//# sourceMappingURL=signal-component.cjs.map
|
|
39
|
+
//# sourceMappingURL=signal-component.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/signal-component.ts"],"names":[],"mappings":";;;AAaO,SAAS,eACd,OAAA,EAC+C;AAC/C,EAAA,MAAM,UAAyD,EAAC;AAChE,EAAA,IAAI,QAAQ,OAAA,EAAS;AACnB,IAAA,OAAA,CAAQ,KAAK,GAAI,MAAA,CAAO,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAuB,CAAA;AAAA,EACvE;AACA,EAAA,IAAI,QAAQ,QAAA,EAAU;AACpB,IAAA,OAAA,CAAQ,KAAK,GAAI,MAAA,CAAO,MAAA,CAAO,OAAA,CAAQ,QAAQ,CAA+B,CAAA;AAAA,EAChF;AACA,EAAA,OAAO,OAAA;AACT;AAKO,SAAS,mBAAA,CACd,KACA,QAAA,EAC2C;AAC3C,EAAA,OAAO;AAAA,IACL,GAAA,EAAK,MAAM,GAAA,EAAI;AAAA,IACf,GAAA,EAAK,CAAC,KAAA,KAAa;AACjB,MAAA,GAAA,CAAI,IAAI,KAAK,CAAA;AACb,MAAA,QAAA,GAAW,KAAK,CAAA;AAAA,IAClB;AAAA,GACF;AACF;AASO,SAAS,cAAc,OAAA,EAAmE;AAC/F,EAAA,MAAM,QAAiC,EAAC;AACxC,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,GAAG,KAAK,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAA,EAAG;AAChD,IAAA,MAAA,CAAO,cAAA,CAAe,OAAO,GAAA,EAAK;AAAA,MAChC,GAAA,EAAK,MAAM,GAAA,EAAI;AAAA,MACf,UAAA,EAAY,IAAA;AAAA,MACZ,YAAA,EAAc;AAAA,KACf,CAAA;AAAA,EACH;AACA,EAAA,OAAO,KAAA;AACT","file":"signal-component.cjs","sourcesContent":["// src/signal-component.ts\r\n// Signal 组件集成工具\r\n\r\nimport type { Signal, WritableSignal, ComputedSignal } from './signal';\r\n\r\nexport interface SignalComponentOptions<T = Record<string, unknown>> {\r\n signals?: { [K in keyof T]?: Signal<T[K]> };\r\n computed?: { [K in keyof T]?: ComputedSignal<T[K]> };\r\n}\r\n\r\n/**\r\n * 从组件选项中提取所有 signal 依赖\r\n */\r\nexport function extractSignals(\r\n options: SignalComponentOptions,\r\n): (Signal<unknown> | ComputedSignal<unknown>)[] {\r\n const signals: (Signal<unknown> | ComputedSignal<unknown>)[] = [];\r\n if (options.signals) {\r\n signals.push(...(Object.values(options.signals) as Signal<unknown>[]));\r\n }\r\n if (options.computed) {\r\n signals.push(...(Object.values(options.computed) as ComputedSignal<unknown>[]));\r\n }\r\n return signals;\r\n}\r\n\r\n/**\r\n * 创建 signal 绑定辅助\r\n */\r\nexport function createSignalBinding<T>(\r\n sig: WritableSignal<T>,\r\n onChange?: (value: T) => void,\r\n): { get: () => T; set: (value: T) => void } {\r\n return {\r\n get: () => sig(),\r\n set: (value: T) => {\r\n sig.set(value);\r\n onChange?.(value);\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * 将 signal 值转换为响应式 props\r\n *\r\n * 注意:通过 Object.defineProperty 定义的 getter 会在每次属性访问时调用 signal(),\r\n * 这会触发 signal 的依赖追踪机制。如果此 props 对象在响应式上下文(如 effect 或\r\n * computed)中被读取,访问的 signal 会自动注册为该上下文的依赖。\r\n */\r\nexport function signalToProps(signals: Record<string, Signal<unknown>>): Record<string, unknown> {\r\n const props: Record<string, unknown> = {};\r\n for (const [key, sig] of Object.entries(signals)) {\r\n Object.defineProperty(props, key, {\r\n get: () => sig(),\r\n enumerable: true,\r\n configurable: true,\r\n });\r\n }\r\n return props;\r\n}\r\n"]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { e as Signal, a as ComputedSignal, g as WritableSignal } from './signal-BOAyevht.cjs';
|
|
2
|
+
|
|
3
|
+
interface SignalComponentOptions<T = Record<string, unknown>> {
|
|
4
|
+
signals?: {
|
|
5
|
+
[K in keyof T]?: Signal<T[K]>;
|
|
6
|
+
};
|
|
7
|
+
computed?: {
|
|
8
|
+
[K in keyof T]?: ComputedSignal<T[K]>;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* 从组件选项中提取所有 signal 依赖
|
|
13
|
+
*/
|
|
14
|
+
declare function extractSignals(options: SignalComponentOptions): (Signal<unknown> | ComputedSignal<unknown>)[];
|
|
15
|
+
/**
|
|
16
|
+
* 创建 signal 绑定辅助
|
|
17
|
+
*/
|
|
18
|
+
declare function createSignalBinding<T>(sig: WritableSignal<T>, onChange?: (value: T) => void): {
|
|
19
|
+
get: () => T;
|
|
20
|
+
set: (value: T) => void;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* 将 signal 值转换为响应式 props
|
|
24
|
+
*
|
|
25
|
+
* 注意:通过 Object.defineProperty 定义的 getter 会在每次属性访问时调用 signal(),
|
|
26
|
+
* 这会触发 signal 的依赖追踪机制。如果此 props 对象在响应式上下文(如 effect 或
|
|
27
|
+
* computed)中被读取,访问的 signal 会自动注册为该上下文的依赖。
|
|
28
|
+
*/
|
|
29
|
+
declare function signalToProps(signals: Record<string, Signal<unknown>>): Record<string, unknown>;
|
|
30
|
+
|
|
31
|
+
export { type SignalComponentOptions, createSignalBinding, extractSignals, signalToProps };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { e as Signal, a as ComputedSignal, g as WritableSignal } from './signal-BOAyevht.js';
|
|
2
|
+
|
|
3
|
+
interface SignalComponentOptions<T = Record<string, unknown>> {
|
|
4
|
+
signals?: {
|
|
5
|
+
[K in keyof T]?: Signal<T[K]>;
|
|
6
|
+
};
|
|
7
|
+
computed?: {
|
|
8
|
+
[K in keyof T]?: ComputedSignal<T[K]>;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* 从组件选项中提取所有 signal 依赖
|
|
13
|
+
*/
|
|
14
|
+
declare function extractSignals(options: SignalComponentOptions): (Signal<unknown> | ComputedSignal<unknown>)[];
|
|
15
|
+
/**
|
|
16
|
+
* 创建 signal 绑定辅助
|
|
17
|
+
*/
|
|
18
|
+
declare function createSignalBinding<T>(sig: WritableSignal<T>, onChange?: (value: T) => void): {
|
|
19
|
+
get: () => T;
|
|
20
|
+
set: (value: T) => void;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* 将 signal 值转换为响应式 props
|
|
24
|
+
*
|
|
25
|
+
* 注意:通过 Object.defineProperty 定义的 getter 会在每次属性访问时调用 signal(),
|
|
26
|
+
* 这会触发 signal 的依赖追踪机制。如果此 props 对象在响应式上下文(如 effect 或
|
|
27
|
+
* computed)中被读取,访问的 signal 会自动注册为该上下文的依赖。
|
|
28
|
+
*/
|
|
29
|
+
declare function signalToProps(signals: Record<string, Signal<unknown>>): Record<string, unknown>;
|
|
30
|
+
|
|
31
|
+
export { type SignalComponentOptions, createSignalBinding, extractSignals, signalToProps };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// src/signal-component.ts
|
|
2
|
+
function extractSignals(options) {
|
|
3
|
+
const signals = [];
|
|
4
|
+
if (options.signals) {
|
|
5
|
+
signals.push(...Object.values(options.signals));
|
|
6
|
+
}
|
|
7
|
+
if (options.computed) {
|
|
8
|
+
signals.push(...Object.values(options.computed));
|
|
9
|
+
}
|
|
10
|
+
return signals;
|
|
11
|
+
}
|
|
12
|
+
function createSignalBinding(sig, onChange) {
|
|
13
|
+
return {
|
|
14
|
+
get: () => sig(),
|
|
15
|
+
set: (value) => {
|
|
16
|
+
sig.set(value);
|
|
17
|
+
onChange?.(value);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function signalToProps(signals) {
|
|
22
|
+
const props = {};
|
|
23
|
+
for (const [key, sig] of Object.entries(signals)) {
|
|
24
|
+
Object.defineProperty(props, key, {
|
|
25
|
+
get: () => sig(),
|
|
26
|
+
enumerable: true,
|
|
27
|
+
configurable: true
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
return props;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export { createSignalBinding, extractSignals, signalToProps };
|
|
34
|
+
//# sourceMappingURL=signal-component.mjs.map
|
|
35
|
+
//# sourceMappingURL=signal-component.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/signal-component.ts"],"names":[],"mappings":";AAaO,SAAS,eACd,OAAA,EAC+C;AAC/C,EAAA,MAAM,UAAyD,EAAC;AAChE,EAAA,IAAI,QAAQ,OAAA,EAAS;AACnB,IAAA,OAAA,CAAQ,KAAK,GAAI,MAAA,CAAO,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAuB,CAAA;AAAA,EACvE;AACA,EAAA,IAAI,QAAQ,QAAA,EAAU;AACpB,IAAA,OAAA,CAAQ,KAAK,GAAI,MAAA,CAAO,MAAA,CAAO,OAAA,CAAQ,QAAQ,CAA+B,CAAA;AAAA,EAChF;AACA,EAAA,OAAO,OAAA;AACT;AAKO,SAAS,mBAAA,CACd,KACA,QAAA,EAC2C;AAC3C,EAAA,OAAO;AAAA,IACL,GAAA,EAAK,MAAM,GAAA,EAAI;AAAA,IACf,GAAA,EAAK,CAAC,KAAA,KAAa;AACjB,MAAA,GAAA,CAAI,IAAI,KAAK,CAAA;AACb,MAAA,QAAA,GAAW,KAAK,CAAA;AAAA,IAClB;AAAA,GACF;AACF;AASO,SAAS,cAAc,OAAA,EAAmE;AAC/F,EAAA,MAAM,QAAiC,EAAC;AACxC,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,GAAG,KAAK,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAA,EAAG;AAChD,IAAA,MAAA,CAAO,cAAA,CAAe,OAAO,GAAA,EAAK;AAAA,MAChC,GAAA,EAAK,MAAM,GAAA,EAAI;AAAA,MACf,UAAA,EAAY,IAAA;AAAA,MACZ,YAAA,EAAc;AAAA,KACf,CAAA;AAAA,EACH;AACA,EAAA,OAAO,KAAA;AACT","file":"signal-component.mjs","sourcesContent":["// src/signal-component.ts\r\n// Signal 组件集成工具\r\n\r\nimport type { Signal, WritableSignal, ComputedSignal } from './signal';\r\n\r\nexport interface SignalComponentOptions<T = Record<string, unknown>> {\r\n signals?: { [K in keyof T]?: Signal<T[K]> };\r\n computed?: { [K in keyof T]?: ComputedSignal<T[K]> };\r\n}\r\n\r\n/**\r\n * 从组件选项中提取所有 signal 依赖\r\n */\r\nexport function extractSignals(\r\n options: SignalComponentOptions,\r\n): (Signal<unknown> | ComputedSignal<unknown>)[] {\r\n const signals: (Signal<unknown> | ComputedSignal<unknown>)[] = [];\r\n if (options.signals) {\r\n signals.push(...(Object.values(options.signals) as Signal<unknown>[]));\r\n }\r\n if (options.computed) {\r\n signals.push(...(Object.values(options.computed) as ComputedSignal<unknown>[]));\r\n }\r\n return signals;\r\n}\r\n\r\n/**\r\n * 创建 signal 绑定辅助\r\n */\r\nexport function createSignalBinding<T>(\r\n sig: WritableSignal<T>,\r\n onChange?: (value: T) => void,\r\n): { get: () => T; set: (value: T) => void } {\r\n return {\r\n get: () => sig(),\r\n set: (value: T) => {\r\n sig.set(value);\r\n onChange?.(value);\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * 将 signal 值转换为响应式 props\r\n *\r\n * 注意:通过 Object.defineProperty 定义的 getter 会在每次属性访问时调用 signal(),\r\n * 这会触发 signal 的依赖追踪机制。如果此 props 对象在响应式上下文(如 effect 或\r\n * computed)中被读取,访问的 signal 会自动注册为该上下文的依赖。\r\n */\r\nexport function signalToProps(signals: Record<string, Signal<unknown>>): Record<string, unknown> {\r\n const props: Record<string, unknown> = {};\r\n for (const [key, sig] of Object.entries(signals)) {\r\n Object.defineProperty(props, key, {\r\n get: () => sig(),\r\n enumerable: true,\r\n configurable: true,\r\n });\r\n }\r\n return props;\r\n}\r\n"]}
|