@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/reactive.ts CHANGED
@@ -1,162 +1,162 @@
1
- /**
2
- * Proxy-based reactivity system for deep reactive state management.
3
- * @module
4
- */
5
-
6
- import { track, trigger } from './dep.js';
7
-
8
- const reactiveMap = new WeakMap<object, object>();
9
- const rawMap = new WeakMap<object, object>();
10
-
11
- /**
12
- * Internal flags used to identify reactive objects.
13
- */
14
- export const ReactiveFlags = {
15
- IS_REACTIVE: '__b_isReactive',
16
- RAW: '__b_raw',
17
- } as const;
18
-
19
- /**
20
- * Creates a deeply reactive proxy of an object.
21
- * Changes to the object or its nested properties will automatically trigger effects.
22
- *
23
- * @param target - The object to make reactive
24
- * @returns A reactive proxy of the target object
25
- *
26
- * @example
27
- * ```ts
28
- * const state = reactive({ count: 0, nested: { value: 1 } });
29
- * state.count++; // Triggers effects tracking 'count'
30
- * state.nested.value++; // Triggers effects tracking nested 'value'
31
- * ```
32
- */
33
- export function reactive<T extends object>(target: T): T {
34
- if (reactiveMap.has(target)) {
35
- return reactiveMap.get(target) as T;
36
- }
37
-
38
- if ((target as any)[ReactiveFlags.IS_REACTIVE]) {
39
- return target;
40
- }
41
-
42
- const proxy = new Proxy(target, {
43
- get(target, key, receiver) {
44
- if (key === ReactiveFlags.IS_REACTIVE) {
45
- return true;
46
- }
47
- if (key === ReactiveFlags.RAW) {
48
- return target;
49
- }
50
-
51
- const result = Reflect.get(target, key, receiver);
52
-
53
- track(target, key);
54
-
55
- if (typeof result === 'object' && result !== null) {
56
- return reactive(result);
57
- }
58
-
59
- return result;
60
- },
61
-
62
- set(target, key, value, receiver) {
63
- const oldValue = Reflect.get(target, key, receiver);
64
-
65
- const newValue = (value as any)?.[ReactiveFlags.RAW] || value;
66
-
67
- const result = Reflect.set(target, key, newValue, receiver);
68
-
69
- if (!Object.is(oldValue, newValue)) {
70
- trigger(target, key);
71
- }
72
-
73
- return result;
74
- },
75
-
76
- deleteProperty(target, key) {
77
- const hadKey = Reflect.has(target, key);
78
- const result = Reflect.deleteProperty(target, key);
79
-
80
- if (hadKey && result) {
81
- trigger(target, key);
82
- }
83
-
84
- return result;
85
- },
86
-
87
- has(target, key) {
88
- track(target, key);
89
- return Reflect.has(target, key);
90
- },
91
-
92
- ownKeys(target) {
93
- track(target, Symbol('iterate'));
94
- return Reflect.ownKeys(target);
95
- },
96
- });
97
-
98
- reactiveMap.set(target, proxy);
99
- rawMap.set(proxy, target);
100
-
101
- return proxy as T;
102
- }
103
-
104
- /**
105
- * Checks if a value is a reactive proxy created by `reactive()`.
106
- *
107
- * @param value - The value to check
108
- * @returns True if the value is a reactive proxy
109
- *
110
- * @example
111
- * ```ts
112
- * const state = reactive({ count: 0 });
113
- * isReactive(state); // true
114
- * isReactive({ count: 0 }); // false
115
- * ```
116
- */
117
- export function isReactive(value: unknown): boolean {
118
- return !!(value && (value as any)[ReactiveFlags.IS_REACTIVE]);
119
- }
120
-
121
- /**
122
- * Returns the raw, non-reactive version of a reactive object.
123
- * Useful when you need to read values without triggering dependency tracking.
124
- *
125
- * @param observed - The reactive object to unwrap
126
- * @returns The original non-reactive object
127
- *
128
- * @example
129
- * ```ts
130
- * const state = reactive({ count: 0 });
131
- * const raw = toRaw(state);
132
- * raw === state; // false
133
- * isReactive(raw); // false
134
- * ```
135
- */
136
- export function toRaw<T>(observed: T): T {
137
- const raw = (observed as any)?.[ReactiveFlags.RAW];
138
- return raw ? toRaw(raw) : observed;
139
- }
140
-
141
- /**
142
- * Marks an object so it will never be converted to a reactive proxy.
143
- * Useful for values that should not be made reactive, like third-party class instances.
144
- *
145
- * @param value - The object to mark as non-reactive
146
- * @returns The same object, marked as raw
147
- *
148
- * @example
149
- * ```ts
150
- * const obj = markRaw({ count: 0 });
151
- * const state = reactive({ data: obj });
152
- * isReactive(state.data); // false - obj was marked raw
153
- * ```
154
- */
155
- export function markRaw<T extends object>(value: T): T {
156
- Object.defineProperty(value, ReactiveFlags.IS_REACTIVE, {
157
- configurable: true,
158
- enumerable: false,
159
- value: false,
160
- });
161
- return value;
162
- }
1
+ /**
2
+ * Proxy-based reactivity system for deep reactive state management.
3
+ * @module
4
+ */
5
+
6
+ import { track, trigger } from './dep.js';
7
+
8
+ const reactiveMap = new WeakMap<object, object>();
9
+ const rawMap = new WeakMap<object, object>();
10
+
11
+ /**
12
+ * Internal flags used to identify reactive objects.
13
+ */
14
+ export const ReactiveFlags = {
15
+ IS_REACTIVE: '__b_isReactive',
16
+ RAW: '__b_raw',
17
+ } as const;
18
+
19
+ /**
20
+ * Creates a deeply reactive proxy of an object.
21
+ * Changes to the object or its nested properties will automatically trigger effects.
22
+ *
23
+ * @param target - The object to make reactive
24
+ * @returns A reactive proxy of the target object
25
+ *
26
+ * @example
27
+ * ```ts
28
+ * const state = reactive({ count: 0, nested: { value: 1 } });
29
+ * state.count++; // Triggers effects tracking 'count'
30
+ * state.nested.value++; // Triggers effects tracking nested 'value'
31
+ * ```
32
+ */
33
+ export function reactive<T extends object>(target: T): T {
34
+ if (reactiveMap.has(target)) {
35
+ return reactiveMap.get(target) as T;
36
+ }
37
+
38
+ if ((target as any)[ReactiveFlags.IS_REACTIVE]) {
39
+ return target;
40
+ }
41
+
42
+ const proxy = new Proxy(target, {
43
+ get(target, key, receiver) {
44
+ if (key === ReactiveFlags.IS_REACTIVE) {
45
+ return true;
46
+ }
47
+ if (key === ReactiveFlags.RAW) {
48
+ return target;
49
+ }
50
+
51
+ const result = Reflect.get(target, key, receiver);
52
+
53
+ track(target, key);
54
+
55
+ if (typeof result === 'object' && result !== null) {
56
+ return reactive(result);
57
+ }
58
+
59
+ return result;
60
+ },
61
+
62
+ set(target, key, value, receiver) {
63
+ const oldValue = Reflect.get(target, key, receiver);
64
+
65
+ const newValue = (value as any)?.[ReactiveFlags.RAW] || value;
66
+
67
+ const result = Reflect.set(target, key, newValue, receiver);
68
+
69
+ if (!Object.is(oldValue, newValue)) {
70
+ trigger(target, key);
71
+ }
72
+
73
+ return result;
74
+ },
75
+
76
+ deleteProperty(target, key) {
77
+ const hadKey = Reflect.has(target, key);
78
+ const result = Reflect.deleteProperty(target, key);
79
+
80
+ if (hadKey && result) {
81
+ trigger(target, key);
82
+ }
83
+
84
+ return result;
85
+ },
86
+
87
+ has(target, key) {
88
+ track(target, key);
89
+ return Reflect.has(target, key);
90
+ },
91
+
92
+ ownKeys(target) {
93
+ track(target, Symbol('iterate'));
94
+ return Reflect.ownKeys(target);
95
+ },
96
+ });
97
+
98
+ reactiveMap.set(target, proxy);
99
+ rawMap.set(proxy, target);
100
+
101
+ return proxy as T;
102
+ }
103
+
104
+ /**
105
+ * Checks if a value is a reactive proxy created by `reactive()`.
106
+ *
107
+ * @param value - The value to check
108
+ * @returns True if the value is a reactive proxy
109
+ *
110
+ * @example
111
+ * ```ts
112
+ * const state = reactive({ count: 0 });
113
+ * isReactive(state); // true
114
+ * isReactive({ count: 0 }); // false
115
+ * ```
116
+ */
117
+ export function isReactive(value: unknown): boolean {
118
+ return !!(value && (value as any)[ReactiveFlags.IS_REACTIVE]);
119
+ }
120
+
121
+ /**
122
+ * Returns the raw, non-reactive version of a reactive object.
123
+ * Useful when you need to read values without triggering dependency tracking.
124
+ *
125
+ * @param observed - The reactive object to unwrap
126
+ * @returns The original non-reactive object
127
+ *
128
+ * @example
129
+ * ```ts
130
+ * const state = reactive({ count: 0 });
131
+ * const raw = toRaw(state);
132
+ * raw === state; // false
133
+ * isReactive(raw); // false
134
+ * ```
135
+ */
136
+ export function toRaw<T>(observed: T): T {
137
+ const raw = (observed as any)?.[ReactiveFlags.RAW];
138
+ return raw ? toRaw(raw) : observed;
139
+ }
140
+
141
+ /**
142
+ * Marks an object so it will never be converted to a reactive proxy.
143
+ * Useful for values that should not be made reactive, like third-party class instances.
144
+ *
145
+ * @param value - The object to mark as non-reactive
146
+ * @returns The same object, marked as raw
147
+ *
148
+ * @example
149
+ * ```ts
150
+ * const obj = markRaw({ count: 0 });
151
+ * const state = reactive({ data: obj });
152
+ * isReactive(state.data); // false - obj was marked raw
153
+ * ```
154
+ */
155
+ export function markRaw<T extends object>(value: T): T {
156
+ Object.defineProperty(value, ReactiveFlags.IS_REACTIVE, {
157
+ configurable: true,
158
+ enumerable: false,
159
+ value: false,
160
+ });
161
+ return value;
162
+ }