@bromscandium/core 1.0.0 → 1.0.2

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/src/ref.ts CHANGED
@@ -1,243 +1,243 @@
1
- /**
2
- * Ref implementation for wrapping primitive and object values in reactive containers.
3
- * @module
4
- */
5
-
6
- import { track, trigger, getActiveEffect } from './dep.js';
7
- import { reactive, toRaw } from './reactive.js';
8
-
9
- /** Internal flag used to identify ref objects */
10
- export const RefFlag = '__b_isRef';
11
-
12
- /**
13
- * A reactive reference that wraps a value and tracks access to its `.value` property.
14
- */
15
- export interface Ref<T = any> {
16
- value: T;
17
- readonly [RefFlag]: true;
18
- }
19
-
20
- /**
21
- * A computed ref with a read-only value that is derived from other reactive state.
22
- */
23
- export interface ComputedRef<T = any> extends Ref<T> {
24
- readonly value: T;
25
- }
26
-
27
- class RefImpl<T> {
28
- private _value: T;
29
- private _rawValue: T;
30
- public readonly [RefFlag] = true;
31
-
32
- constructor(value: T) {
33
- this._rawValue = toRaw(value) as T;
34
- this._value = toReactive(value);
35
- }
36
-
37
- get value(): T {
38
- trackRefValue(this);
39
- return this._value;
40
- }
41
-
42
- set value(newValue: T) {
43
- const rawNewValue = toRaw(newValue) as T;
44
- if (!Object.is(rawNewValue, this._rawValue)) {
45
- this._rawValue = rawNewValue;
46
- this._value = toReactive(newValue);
47
- triggerRefValue(this);
48
- }
49
- }
50
- }
51
-
52
- function toReactive<T>(value: T): T {
53
- return typeof value === 'object' && value !== null
54
- ? reactive(value as object) as T
55
- : value;
56
- }
57
-
58
- function trackRefValue(ref: any): void {
59
- if (getActiveEffect()) {
60
- track(ref, 'value');
61
- }
62
- }
63
-
64
- function triggerRefValue(ref: any): void {
65
- trigger(ref, 'value');
66
- }
67
-
68
- /**
69
- * Creates a reactive reference for a value.
70
- * Object values are automatically made deeply reactive.
71
- *
72
- * @param value - The initial value for the ref
73
- * @returns A reactive ref containing the value
74
- *
75
- * @example
76
- * ```ts
77
- * const count = ref(0);
78
- * console.log(count.value); // 0
79
- * count.value++; // Triggers effects
80
- *
81
- * const obj = ref({ nested: 1 });
82
- * obj.value.nested++; // Also triggers effects (deep reactivity)
83
- * ```
84
- */
85
- export function ref<T>(value: T): Ref<T>;
86
- export function ref<T = any>(): Ref<T | undefined>;
87
- export function ref<T>(value?: T): Ref<T> {
88
- if (isRef(value)) {
89
- return value as Ref<T>;
90
- }
91
- return new RefImpl(value) as Ref<T>;
92
- }
93
-
94
- /**
95
- * Checks if a value is a ref created by `ref()` or `computed()`.
96
- *
97
- * @param value - The value to check
98
- * @returns True if the value is a ref
99
- *
100
- * @example
101
- * ```ts
102
- * isRef(ref(0)); // true
103
- * isRef(0); // false
104
- * isRef(computed(() => 1)); // true
105
- * ```
106
- */
107
- export function isRef<T>(value: Ref<T> | unknown): value is Ref<T> {
108
- return !!(value && (value as any)[RefFlag] === true);
109
- }
110
-
111
- /**
112
- * Unwraps a ref to get its inner value. Returns the value directly if not a ref.
113
- *
114
- * @param ref - A ref or plain value to unwrap
115
- * @returns The unwrapped value
116
- *
117
- * @example
118
- * ```ts
119
- * unref(ref(1)); // 1
120
- * unref(1); // 1
121
- * ```
122
- */
123
- export function unref<T>(ref: T | Ref<T>): T {
124
- return isRef(ref) ? ref.value : ref;
125
- }
126
-
127
- /**
128
- * Creates a ref that syncs with a property of a reactive object.
129
- * The ref stays connected to the source object.
130
- *
131
- * @param object - The source reactive object
132
- * @param key - The property key to create a ref for
133
- * @returns A ref linked to the specified property
134
- *
135
- * @example
136
- * ```ts
137
- * const state = reactive({ count: 0 });
138
- * const countRef = toRef(state, 'count');
139
- * countRef.value++; // Also updates state.count
140
- * ```
141
- */
142
- export function toRef<T extends object, K extends keyof T>(
143
- object: T,
144
- key: K
145
- ): Ref<T[K]> {
146
- const val = object[key];
147
- if (isRef(val)) {
148
- return val as Ref<T[K]>;
149
- }
150
-
151
- return {
152
- get value() {
153
- return object[key];
154
- },
155
- set value(newValue) {
156
- object[key] = newValue;
157
- },
158
- [RefFlag]: true,
159
- } as Ref<T[K]>;
160
- }
161
-
162
- /**
163
- * Converts all properties of a reactive object into refs.
164
- * Each ref is linked to the corresponding property on the source object.
165
- *
166
- * @param object - The source reactive object
167
- * @returns An object with the same keys, where each value is a ref
168
- *
169
- * @example
170
- * ```ts
171
- * const state = reactive({ count: 0, name: 'test' });
172
- * const { count, name } = toRefs(state);
173
- * count.value++; // Updates state.count
174
- * ```
175
- */
176
- export function toRefs<T extends object>(object: T): { [K in keyof T]: Ref<T[K]> } {
177
- const result: any = {};
178
- for (const key in object) {
179
- result[key] = toRef(object, key);
180
- }
181
- return result;
182
- }
183
-
184
- /**
185
- * A shallow ref type (same interface as Ref but without deep reactivity).
186
- */
187
- export type ShallowRef<T = any> = Ref<T>;
188
-
189
- class ShallowRefImpl<T> {
190
- private _value: T;
191
- public readonly [RefFlag] = true;
192
-
193
- constructor(value: T) {
194
- this._value = value;
195
- }
196
-
197
- get value(): T {
198
- trackRefValue(this);
199
- return this._value;
200
- }
201
-
202
- set value(newValue: T) {
203
- if (!Object.is(newValue, this._value)) {
204
- this._value = newValue;
205
- triggerRefValue(this);
206
- }
207
- }
208
- }
209
-
210
- /**
211
- * Creates a ref that does not make its value deeply reactive.
212
- * Only reassigning `.value` will trigger effects, not mutations to nested properties.
213
- *
214
- * @param value - The initial value for the shallow ref
215
- * @returns A shallow ref containing the value
216
- *
217
- * @example
218
- * ```ts
219
- * const state = shallowRef({ nested: 0 });
220
- * state.value.nested++; // Does NOT trigger effects
221
- * state.value = { nested: 1 }; // Triggers effects
222
- * ```
223
- */
224
- export function shallowRef<T>(value: T): ShallowRef<T> {
225
- return new ShallowRefImpl(value) as ShallowRef<T>;
226
- }
227
-
228
- /**
229
- * Manually triggers effects that depend on a ref.
230
- * Useful after mutating the inner value of a shallow ref.
231
- *
232
- * @param ref - The ref to trigger
233
- *
234
- * @example
235
- * ```ts
236
- * const state = shallowRef({ count: 0 });
237
- * state.value.count++; // No automatic trigger
238
- * triggerRef(state); // Manually trigger effects
239
- * ```
240
- */
241
- export function triggerRef(ref: Ref): void {
242
- triggerRefValue(ref);
243
- }
1
+ /**
2
+ * Ref implementation for wrapping primitive and object values in reactive containers.
3
+ * @module
4
+ */
5
+
6
+ import { track, trigger, getActiveEffect } from './dep.js';
7
+ import { reactive, toRaw } from './reactive.js';
8
+
9
+ /** Internal flag used to identify ref objects */
10
+ export const RefFlag = '__b_isRef';
11
+
12
+ /**
13
+ * A reactive reference that wraps a value and tracks access to its `.value` property.
14
+ */
15
+ export interface Ref<T = any> {
16
+ value: T;
17
+ readonly [RefFlag]: true;
18
+ }
19
+
20
+ /**
21
+ * A computed ref with a read-only value that is derived from other reactive state.
22
+ */
23
+ export interface ComputedRef<T = any> extends Ref<T> {
24
+ readonly value: T;
25
+ }
26
+
27
+ class RefImpl<T> {
28
+ private _value: T;
29
+ private _rawValue: T;
30
+ public readonly [RefFlag] = true;
31
+
32
+ constructor(value: T) {
33
+ this._rawValue = toRaw(value) as T;
34
+ this._value = toReactive(value);
35
+ }
36
+
37
+ get value(): T {
38
+ trackRefValue(this);
39
+ return this._value;
40
+ }
41
+
42
+ set value(newValue: T) {
43
+ const rawNewValue = toRaw(newValue) as T;
44
+ if (!Object.is(rawNewValue, this._rawValue)) {
45
+ this._rawValue = rawNewValue;
46
+ this._value = toReactive(newValue);
47
+ triggerRefValue(this);
48
+ }
49
+ }
50
+ }
51
+
52
+ function toReactive<T>(value: T): T {
53
+ return typeof value === 'object' && value !== null
54
+ ? reactive(value as object) as T
55
+ : value;
56
+ }
57
+
58
+ function trackRefValue(ref: any): void {
59
+ if (getActiveEffect()) {
60
+ track(ref, 'value');
61
+ }
62
+ }
63
+
64
+ function triggerRefValue(ref: any): void {
65
+ trigger(ref, 'value');
66
+ }
67
+
68
+ /**
69
+ * Creates a reactive reference for a value.
70
+ * Object values are automatically made deeply reactive.
71
+ *
72
+ * @param value - The initial value for the ref
73
+ * @returns A reactive ref containing the value
74
+ *
75
+ * @example
76
+ * ```ts
77
+ * const count = ref(0);
78
+ * console.log(count.value); // 0
79
+ * count.value++; // Triggers effects
80
+ *
81
+ * const obj = ref({ nested: 1 });
82
+ * obj.value.nested++; // Also triggers effects (deep reactivity)
83
+ * ```
84
+ */
85
+ export function ref<T>(value: T): Ref<T>;
86
+ export function ref<T = any>(): Ref<T | undefined>;
87
+ export function ref<T>(value?: T): Ref<T> {
88
+ if (isRef(value)) {
89
+ return value as Ref<T>;
90
+ }
91
+ return new RefImpl(value) as Ref<T>;
92
+ }
93
+
94
+ /**
95
+ * Checks if a value is a ref created by `ref()` or `computed()`.
96
+ *
97
+ * @param value - The value to check
98
+ * @returns True if the value is a ref
99
+ *
100
+ * @example
101
+ * ```ts
102
+ * isRef(ref(0)); // true
103
+ * isRef(0); // false
104
+ * isRef(computed(() => 1)); // true
105
+ * ```
106
+ */
107
+ export function isRef<T>(value: Ref<T> | unknown): value is Ref<T> {
108
+ return !!(value && (value as any)[RefFlag] === true);
109
+ }
110
+
111
+ /**
112
+ * Unwraps a ref to get its inner value. Returns the value directly if not a ref.
113
+ *
114
+ * @param ref - A ref or plain value to unwrap
115
+ * @returns The unwrapped value
116
+ *
117
+ * @example
118
+ * ```ts
119
+ * unref(ref(1)); // 1
120
+ * unref(1); // 1
121
+ * ```
122
+ */
123
+ export function unref<T>(ref: T | Ref<T>): T {
124
+ return isRef(ref) ? ref.value : ref;
125
+ }
126
+
127
+ /**
128
+ * Creates a ref that syncs with a property of a reactive object.
129
+ * The ref stays connected to the source object.
130
+ *
131
+ * @param object - The source reactive object
132
+ * @param key - The property key to create a ref for
133
+ * @returns A ref linked to the specified property
134
+ *
135
+ * @example
136
+ * ```ts
137
+ * const state = reactive({ count: 0 });
138
+ * const countRef = toRef(state, 'count');
139
+ * countRef.value++; // Also updates state.count
140
+ * ```
141
+ */
142
+ export function toRef<T extends object, K extends keyof T>(
143
+ object: T,
144
+ key: K
145
+ ): Ref<T[K]> {
146
+ const val = object[key];
147
+ if (isRef(val)) {
148
+ return val as Ref<T[K]>;
149
+ }
150
+
151
+ return {
152
+ get value() {
153
+ return object[key];
154
+ },
155
+ set value(newValue) {
156
+ object[key] = newValue;
157
+ },
158
+ [RefFlag]: true,
159
+ } as Ref<T[K]>;
160
+ }
161
+
162
+ /**
163
+ * Converts all properties of a reactive object into refs.
164
+ * Each ref is linked to the corresponding property on the source object.
165
+ *
166
+ * @param object - The source reactive object
167
+ * @returns An object with the same keys, where each value is a ref
168
+ *
169
+ * @example
170
+ * ```ts
171
+ * const state = reactive({ count: 0, name: 'test' });
172
+ * const { count, name } = toRefs(state);
173
+ * count.value++; // Updates state.count
174
+ * ```
175
+ */
176
+ export function toRefs<T extends object>(object: T): { [K in keyof T]: Ref<T[K]> } {
177
+ const result: any = {};
178
+ for (const key in object) {
179
+ result[key] = toRef(object, key);
180
+ }
181
+ return result;
182
+ }
183
+
184
+ /**
185
+ * A shallow ref type (same interface as Ref but without deep reactivity).
186
+ */
187
+ export type ShallowRef<T = any> = Ref<T>;
188
+
189
+ class ShallowRefImpl<T> {
190
+ private _value: T;
191
+ public readonly [RefFlag] = true;
192
+
193
+ constructor(value: T) {
194
+ this._value = value;
195
+ }
196
+
197
+ get value(): T {
198
+ trackRefValue(this);
199
+ return this._value;
200
+ }
201
+
202
+ set value(newValue: T) {
203
+ if (!Object.is(newValue, this._value)) {
204
+ this._value = newValue;
205
+ triggerRefValue(this);
206
+ }
207
+ }
208
+ }
209
+
210
+ /**
211
+ * Creates a ref that does not make its value deeply reactive.
212
+ * Only reassigning `.value` will trigger effects, not mutations to nested properties.
213
+ *
214
+ * @param value - The initial value for the shallow ref
215
+ * @returns A shallow ref containing the value
216
+ *
217
+ * @example
218
+ * ```ts
219
+ * const state = shallowRef({ nested: 0 });
220
+ * state.value.nested++; // Does NOT trigger effects
221
+ * state.value = { nested: 1 }; // Triggers effects
222
+ * ```
223
+ */
224
+ export function shallowRef<T>(value: T): ShallowRef<T> {
225
+ return new ShallowRefImpl(value) as ShallowRef<T>;
226
+ }
227
+
228
+ /**
229
+ * Manually triggers effects that depend on a ref.
230
+ * Useful after mutating the inner value of a shallow ref.
231
+ *
232
+ * @param ref - The ref to trigger
233
+ *
234
+ * @example
235
+ * ```ts
236
+ * const state = shallowRef({ count: 0 });
237
+ * state.value.count++; // No automatic trigger
238
+ * triggerRef(state); // Manually trigger effects
239
+ * ```
240
+ */
241
+ export function triggerRef(ref: Ref): void {
242
+ triggerRefValue(ref);
243
+ }