mutts 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.
Files changed (85) hide show
  1. package/README.md +24 -2
  2. package/dist/chunks/_tslib-C-cuVLvZ.js +73 -0
  3. package/dist/chunks/_tslib-C-cuVLvZ.js.map +1 -0
  4. package/dist/chunks/_tslib-CMEnd0VE.esm.js +68 -0
  5. package/dist/chunks/_tslib-CMEnd0VE.esm.js.map +1 -0
  6. package/dist/chunks/{decorator-BXsign4Z.js → decorator-D4DU97Zg.js} +70 -4
  7. package/dist/chunks/decorator-D4DU97Zg.js.map +1 -0
  8. package/dist/chunks/{decorator-CPbZNnsX.esm.js → decorator-GnHw1Az7.esm.js} +67 -5
  9. package/dist/chunks/decorator-GnHw1Az7.esm.js.map +1 -0
  10. package/dist/chunks/index-DBScoeCX.esm.js +1960 -0
  11. package/dist/chunks/index-DBScoeCX.esm.js.map +1 -0
  12. package/dist/chunks/index-DOTmXL89.js +1983 -0
  13. package/dist/chunks/index-DOTmXL89.js.map +1 -0
  14. package/dist/decorator.d.ts +58 -1
  15. package/dist/decorator.esm.js +1 -1
  16. package/dist/decorator.js +1 -1
  17. package/dist/destroyable.d.ts +42 -0
  18. package/dist/destroyable.esm.js +19 -1
  19. package/dist/destroyable.esm.js.map +1 -1
  20. package/dist/destroyable.js +19 -1
  21. package/dist/destroyable.js.map +1 -1
  22. package/dist/eventful.d.ts +10 -1
  23. package/dist/eventful.esm.js +5 -27
  24. package/dist/eventful.esm.js.map +1 -1
  25. package/dist/eventful.js +15 -37
  26. package/dist/eventful.js.map +1 -1
  27. package/dist/index.d.ts +52 -3
  28. package/dist/index.esm.js +3 -2
  29. package/dist/index.esm.js.map +1 -1
  30. package/dist/index.js +18 -3
  31. package/dist/index.js.map +1 -1
  32. package/dist/indexable.d.ts +26 -0
  33. package/dist/indexable.esm.js +6 -0
  34. package/dist/indexable.esm.js.map +1 -1
  35. package/dist/indexable.js +6 -0
  36. package/dist/indexable.js.map +1 -1
  37. package/dist/mutts.umd.js +1 -1
  38. package/dist/mutts.umd.js.map +1 -1
  39. package/dist/mutts.umd.min.js +1 -1
  40. package/dist/mutts.umd.min.js.map +1 -1
  41. package/dist/promiseChain.d.ts +10 -0
  42. package/dist/promiseChain.esm.js +6 -0
  43. package/dist/promiseChain.esm.js.map +1 -1
  44. package/dist/promiseChain.js +6 -0
  45. package/dist/promiseChain.js.map +1 -1
  46. package/dist/reactive.d.ts +258 -20
  47. package/dist/reactive.esm.js +4 -1454
  48. package/dist/reactive.esm.js.map +1 -1
  49. package/dist/reactive.js +29 -1466
  50. package/dist/reactive.js.map +1 -1
  51. package/dist/std-decorators.d.ts +35 -0
  52. package/dist/std-decorators.esm.js +36 -1
  53. package/dist/std-decorators.esm.js.map +1 -1
  54. package/dist/std-decorators.js +36 -1
  55. package/dist/std-decorators.js.map +1 -1
  56. package/docs/mixin.md +229 -0
  57. package/docs/reactive.md +7931 -458
  58. package/package.json +1 -2
  59. package/dist/chunks/decorator-BXsign4Z.js.map +0 -1
  60. package/dist/chunks/decorator-CPbZNnsX.esm.js.map +0 -1
  61. package/src/decorator.test.ts +0 -495
  62. package/src/decorator.ts +0 -205
  63. package/src/destroyable.test.ts +0 -155
  64. package/src/destroyable.ts +0 -158
  65. package/src/eventful.test.ts +0 -380
  66. package/src/eventful.ts +0 -69
  67. package/src/index.ts +0 -7
  68. package/src/indexable.test.ts +0 -388
  69. package/src/indexable.ts +0 -124
  70. package/src/promiseChain.test.ts +0 -201
  71. package/src/promiseChain.ts +0 -99
  72. package/src/reactive/array.test.ts +0 -923
  73. package/src/reactive/array.ts +0 -352
  74. package/src/reactive/core.test.ts +0 -1663
  75. package/src/reactive/core.ts +0 -866
  76. package/src/reactive/index.ts +0 -28
  77. package/src/reactive/interface.test.ts +0 -1477
  78. package/src/reactive/interface.ts +0 -231
  79. package/src/reactive/map.test.ts +0 -866
  80. package/src/reactive/map.ts +0 -162
  81. package/src/reactive/set.test.ts +0 -289
  82. package/src/reactive/set.ts +0 -142
  83. package/src/std-decorators.test.ts +0 -679
  84. package/src/std-decorators.ts +0 -182
  85. package/src/utils.ts +0 -52
@@ -1,162 +0,0 @@
1
- import {
2
- dependant,
3
- makeReactiveEntriesIterator,
4
- makeReactiveIterator,
5
- prototypeForwarding,
6
- reactive,
7
- touched,
8
- touched1,
9
- } from './core'
10
-
11
- const native = Symbol('native')
12
-
13
- // TODO: [prototypeForwarding]
14
-
15
- export class ReactiveWeakMap<K extends object, V> {
16
- declare readonly [native]: WeakMap<K, V>
17
- declare readonly content: symbol
18
- constructor(original: WeakMap<K, V>) {
19
- Object.defineProperties(this, {
20
- [native]: { value: original },
21
- [prototypeForwarding]: { value: original },
22
- content: { value: Symbol('content') },
23
- [Symbol.toStringTag]: { value: 'ReactiveWeakMap' },
24
- })
25
- }
26
-
27
- // Implement WeakMap interface methods with reactivity
28
- delete(key: K): boolean {
29
- const hadKey = this[native].has(key)
30
- const result = this[native].delete(key)
31
-
32
- if (hadKey) touched1(this.content, { type: 'del', prop: key }, key)
33
-
34
- return result
35
- }
36
-
37
- get(key: K): V | undefined {
38
- dependant(this.content, key)
39
- return reactive(this[native].get(key))
40
- }
41
-
42
- has(key: K): boolean {
43
- dependant(this.content, key)
44
- return this[native].has(key)
45
- }
46
-
47
- set(key: K, value: V): this {
48
- // Trigger effects for the specific key
49
- touched1(this.content, { type: this[native].has(key) ? 'set' : 'add', prop: key }, key)
50
- this[native].set(key, value)
51
-
52
- return this
53
- }
54
- }
55
-
56
- export class ReactiveMap<K, V> {
57
- declare readonly [native]: Map<K, V>
58
- declare readonly content: symbol
59
-
60
- constructor(original: Map<K, V>) {
61
- Object.defineProperties(this, {
62
- [native]: { value: original },
63
- [prototypeForwarding]: { value: original },
64
- content: { value: Symbol('content') },
65
- [Symbol.toStringTag]: { value: 'ReactiveMap' },
66
- })
67
- }
68
-
69
- // Implement Map interface methods with reactivity
70
- get size(): number {
71
- dependant(this, 'size') // The ReactiveMap instance still goes through proxy
72
- return this[native].size
73
- }
74
-
75
- clear(): void {
76
- const hadEntries = this[native].size > 0
77
- this[native].clear()
78
-
79
- if (hadEntries) {
80
- const evolution = { type: 'bunch', method: 'clear' } as const
81
- // Clear triggers all effects since all keys are affected
82
- touched1(this, evolution, 'size')
83
- touched(this.content, evolution)
84
- }
85
- }
86
-
87
- entries(): Generator<[K, V]> {
88
- dependant(this.content)
89
- return makeReactiveEntriesIterator(this[native].entries())
90
- }
91
-
92
- forEach(callbackfn: (value: V, key: K, map: Map<K, V>) => void, thisArg?: any): void {
93
- dependant(this.content)
94
- this[native].forEach(callbackfn, thisArg)
95
- }
96
-
97
- keys(): MapIterator<K> {
98
- dependant(this.content)
99
- return this[native].keys()
100
- }
101
-
102
- values(): Generator<V> {
103
- dependant(this.content)
104
- return makeReactiveIterator(this[native].values())
105
- }
106
-
107
- [Symbol.iterator](): Iterator<[K, V]> {
108
- dependant(this.content)
109
- const nativeIterator = this[native][Symbol.iterator]()
110
- return {
111
- next() {
112
- const result = nativeIterator.next()
113
- if (result.done) {
114
- return result
115
- }
116
- return {
117
- value: [result.value[0], reactive(result.value[1])],
118
- done: false,
119
- }
120
- },
121
- }
122
- }
123
-
124
- // Implement Map methods with reactivity
125
- delete(key: K): boolean {
126
- const hadKey = this[native].has(key)
127
- const result = this[native].delete(key)
128
-
129
- if (hadKey) {
130
- const evolution = { type: 'del', prop: key } as const
131
- touched1(this.content, evolution, key)
132
- touched1(this, evolution, 'size')
133
- }
134
-
135
- return result
136
- }
137
-
138
- get(key: K): V | undefined {
139
- dependant(this.content, key)
140
- return reactive(this[native].get(key))
141
- }
142
-
143
- has(key: K): boolean {
144
- dependant(this.content, key)
145
- return this[native].has(key)
146
- }
147
-
148
- set(key: K, value: V): this {
149
- const hadKey = this[native].has(key)
150
- const oldValue = this[native].get(key)
151
- const reactiveValue = reactive(value)
152
- this[native].set(key, reactiveValue)
153
-
154
- if (!hadKey || oldValue !== reactiveValue) {
155
- const evolution = { type: hadKey ? 'set' : 'add', prop: key } as const
156
- touched1(this.content, evolution, key)
157
- touched1(this, evolution, 'size')
158
- }
159
-
160
- return this
161
- }
162
- }
@@ -1,289 +0,0 @@
1
- import { effect, reactive } from './index'
2
-
3
- describe('ReactiveWeakSet', () => {
4
- describe('reactive operations', () => {
5
- it('should track dependencies when checking existence', () => {
6
- const ws = new WeakSet<object>()
7
- const rws = reactive(ws)
8
- const key = { id: 1 }
9
-
10
- let count = 0
11
- effect(() => {
12
- count++
13
- rws.has(key)
14
- })
15
-
16
- expect(count).toBe(1)
17
- rws.add(key)
18
- expect(count).toBe(2)
19
- rws.delete(key)
20
- expect(count).toBe(3)
21
- })
22
-
23
- it('should not trigger when deleting non-existent keys', () => {
24
- const ws = new WeakSet<object>()
25
- const rws = reactive(ws)
26
- const key = { id: 1 }
27
-
28
- let count = 0
29
- effect(() => {
30
- count++
31
- rws.has(key)
32
- })
33
-
34
- expect(count).toBe(1)
35
- rws.delete(key)
36
- expect(count).toBe(1)
37
- })
38
- })
39
-
40
- describe('toStringTag', () => {
41
- it('should have correct toStringTag', () => {
42
- const ws = new WeakSet<object>()
43
- const rws = reactive(ws)
44
- expect(rws[Symbol.toStringTag]).toBe('ReactiveWeakSet')
45
- })
46
- })
47
- })
48
-
49
- describe('ReactiveSet', () => {
50
- describe('reactive operations', () => {
51
- it('should track size dependencies', () => {
52
- const s = new Set<number>()
53
- const rs = reactive(s)
54
-
55
- let count = 0
56
- effect(() => {
57
- count++
58
- rs.size
59
- })
60
-
61
- expect(count).toBe(1)
62
- rs.add(1)
63
- expect(count).toBe(2)
64
- })
65
-
66
- it('should track dependencies when checking existence', () => {
67
- const s = new Set<number>()
68
- const rs = reactive(s)
69
- rs.add(1)
70
-
71
- let count = 0
72
- effect(() => {
73
- count++
74
- rs.has(1)
75
- })
76
-
77
- expect(count).toBe(1)
78
- rs.add(2)
79
- expect(count).toBe(1)
80
- rs.delete(1)
81
- expect(count).toBe(2)
82
- })
83
-
84
- it('should trigger effects when adding new values', () => {
85
- const s = new Set<number>()
86
- const rs = reactive(s)
87
-
88
- let count = 0
89
- effect(() => {
90
- count++
91
- rs.has(1)
92
- })
93
-
94
- expect(count).toBe(1)
95
- rs.add(1)
96
- expect(count).toBe(2)
97
- })
98
-
99
- it('should trigger effects when deleting values', () => {
100
- const s = new Set<number>()
101
- const rs = reactive(s)
102
- rs.add(1)
103
-
104
- let count = 0
105
- effect(() => {
106
- count++
107
- rs.has(1)
108
- })
109
-
110
- expect(count).toBe(1)
111
- rs.delete(1)
112
- expect(count).toBe(2)
113
- })
114
-
115
- it('should not trigger effects when deleting non-existent values', () => {
116
- const s = new Set<number>()
117
- const rs = reactive(s)
118
-
119
- let count = 0
120
- effect(() => {
121
- count++
122
- rs.has(1)
123
- })
124
-
125
- expect(count).toBe(1)
126
- rs.delete(1)
127
- expect(count).toBe(1)
128
- })
129
- })
130
-
131
- describe('allProps reactivity', () => {
132
- it('should trigger allProps effects when adding values', () => {
133
- const s = new Set<number>()
134
- const rs = reactive(s)
135
-
136
- let allPropsCount = 0
137
- effect(() => {
138
- allPropsCount++
139
- // Use iteration to depend on all entries
140
- for (const _v of rs.entries()) {
141
- }
142
- })
143
-
144
- expect(allPropsCount).toBe(1)
145
- rs.add(1)
146
- expect(allPropsCount).toBe(2)
147
- rs.add(2)
148
- expect(allPropsCount).toBe(3)
149
- })
150
-
151
- it('should trigger allProps effects when deleting values', () => {
152
- const s = new Set<number>()
153
- const rs = reactive(s)
154
- rs.add(1)
155
- rs.add(2)
156
-
157
- let allPropsCount = 0
158
- effect(() => {
159
- allPropsCount++
160
- rs.keys()
161
- })
162
-
163
- expect(allPropsCount).toBe(1)
164
- rs.delete(1)
165
- expect(allPropsCount).toBe(2)
166
- rs.delete(2)
167
- expect(allPropsCount).toBe(3)
168
- })
169
-
170
- it('should trigger allProps effects when clearing', () => {
171
- const s = new Set<number>()
172
- const rs = reactive(s)
173
- rs.add(1)
174
- rs.add(2)
175
-
176
- let sizeCount = 0
177
- let allPropsCount = 0
178
- effect(() => {
179
- sizeCount++
180
- rs.size
181
- })
182
- effect(() => {
183
- allPropsCount++
184
- rs.values()
185
- })
186
-
187
- expect(sizeCount).toBe(1)
188
- expect(allPropsCount).toBe(1)
189
- rs.clear()
190
- expect(sizeCount).toBe(2)
191
- expect(allPropsCount).toBe(2)
192
- })
193
- })
194
-
195
- describe('iteration methods', () => {
196
- it('should track allProps for entries()', () => {
197
- const rs = reactive(new Set<number>())
198
-
199
- let count = 0
200
- effect(() => {
201
- count++
202
- rs.entries()
203
- })
204
-
205
- expect(count).toBe(1)
206
- rs.add(1)
207
- expect(count).toBe(2)
208
- })
209
-
210
- it('should track allProps for forEach()', () => {
211
- const rs = reactive(new Set<number>())
212
-
213
- let count = 0
214
- effect(() => {
215
- count++
216
- rs.forEach(() => {})
217
- })
218
-
219
- expect(count).toBe(1)
220
- rs.add(1)
221
- expect(count).toBe(2)
222
- })
223
-
224
- it('should track allProps for keys() and values() and iterator', () => {
225
- const rs = reactive(new Set<number>())
226
-
227
- let countKeys = 0
228
- let countValues = 0
229
- let countIter = 0
230
-
231
- effect(() => {
232
- countKeys++
233
- rs.keys()
234
- })
235
-
236
- effect(() => {
237
- countValues++
238
- rs.values()
239
- })
240
-
241
- effect(() => {
242
- countIter++
243
- for (const _v of rs) {
244
- }
245
- })
246
-
247
- expect(countKeys).toBe(1)
248
- expect(countValues).toBe(1)
249
- expect(countIter).toBe(1)
250
-
251
- rs.add(1)
252
- expect(countKeys).toBe(2)
253
- expect(countValues).toBe(2)
254
- expect(countIter).toBe(2)
255
- })
256
- })
257
-
258
- describe('seamless reactive integration', () => {
259
- it('should automatically create ReactiveSet when using reactive() on native Set', () => {
260
- const nativeSet = new Set([1, 2])
261
- const rs = reactive(nativeSet)
262
- expect(rs.size).toBe(2)
263
- // dependency tracking
264
- let count = 0
265
- effect(() => {
266
- count++
267
- rs.has(1)
268
- })
269
- expect(count).toBe(1)
270
- rs.delete(1)
271
- expect(count).toBe(2)
272
- })
273
-
274
- it('should automatically create ReactiveWeakSet when using reactive() on native WeakSet', () => {
275
- const k = { id: 1 }
276
- const native = new WeakSet([k])
277
- const rws = reactive(native)
278
-
279
- let count = 0
280
- effect(() => {
281
- count++
282
- rws.has(k)
283
- })
284
- expect(count).toBe(1)
285
- rws.delete(k)
286
- expect(count).toBe(2)
287
- })
288
- })
289
- })
@@ -1,142 +0,0 @@
1
- import {
2
- dependant,
3
- makeReactiveEntriesIterator,
4
- makeReactiveIterator,
5
- prototypeForwarding,
6
- reactive,
7
- touched,
8
- touched1,
9
- } from './core'
10
-
11
- const native = Symbol('native')
12
-
13
- // TODO: [prototypeForwarding]
14
-
15
- export class ReactiveWeakSet<T extends object> {
16
- declare readonly [native]: WeakSet<T>
17
- declare readonly content: symbol
18
-
19
- constructor(original: WeakSet<T>) {
20
- Object.defineProperties(this, {
21
- [native]: { value: original },
22
- [prototypeForwarding]: { value: original },
23
- content: { value: Symbol('content') },
24
- [Symbol.toStringTag]: { value: 'ReactiveWeakSet' },
25
- })
26
- }
27
-
28
- add(value: T): this {
29
- const had = this[native].has(value)
30
- this[native].add(value)
31
- if (!had) {
32
- // touch the specific value and the collection view
33
- touched1(this.content, { type: 'add', prop: value }, value)
34
- // no size/allProps for WeakSet
35
- }
36
- return this
37
- }
38
-
39
- delete(value: T): boolean {
40
- const had = this[native].has(value)
41
- const res = this[native].delete(value)
42
- if (had) touched1(this.content, { type: 'del', prop: value }, value)
43
- return res
44
- }
45
-
46
- has(value: T): boolean {
47
- dependant(this.content, value)
48
- return this[native].has(value)
49
- }
50
- }
51
-
52
- export class ReactiveSet<T> {
53
- declare readonly [native]: Set<T>
54
- declare readonly content: symbol
55
- constructor(original: Set<T>) {
56
- Object.defineProperties(this, {
57
- [native]: { value: original },
58
- [prototypeForwarding]: { value: original },
59
- content: { value: Symbol('content') },
60
- [Symbol.toStringTag]: { value: 'ReactiveSet' },
61
- })
62
- }
63
-
64
- get size(): number {
65
- // size depends on the wrapper instance, like Map counterpart
66
- dependant(this, 'size')
67
- return this[native].size
68
- }
69
-
70
- add(value: T): this {
71
- const had = this[native].has(value)
72
- const reactiveValue = reactive(value)
73
- this[native].add(reactiveValue)
74
- if (!had) {
75
- const evolution = { type: 'add', prop: reactiveValue } as const
76
- // touch for value-specific and aggregate dependencies
77
- touched1(this.content, evolution, reactiveValue)
78
- touched1(this, evolution, 'size')
79
- }
80
- return this
81
- }
82
-
83
- clear(): void {
84
- const hadEntries = this[native].size > 0
85
- this[native].clear()
86
- if (hadEntries) {
87
- const evolution = { type: 'bunch', method: 'clear' } as const
88
- touched1(this, evolution, 'size')
89
- touched(this.content, evolution)
90
- }
91
- }
92
-
93
- delete(value: T): boolean {
94
- const had = this[native].has(value)
95
- const res = this[native].delete(value)
96
- if (had) {
97
- const evolution = { type: 'del', prop: value } as const
98
- touched1(this.content, evolution, value)
99
- touched1(this, evolution, 'size')
100
- }
101
- return res
102
- }
103
-
104
- has(value: T): boolean {
105
- dependant(this.content, value)
106
- return this[native].has(value)
107
- }
108
-
109
- entries(): Generator<[T, T]> {
110
- dependant(this.content)
111
- return makeReactiveEntriesIterator(this[native].entries())
112
- }
113
-
114
- forEach(callbackfn: (value: T, value2: T, set: Set<T>) => void, thisArg?: any): void {
115
- dependant(this.content)
116
- this[native].forEach(callbackfn, thisArg)
117
- }
118
-
119
- keys(): Generator<T> {
120
- dependant(this.content)
121
- return makeReactiveIterator(this[native].keys())
122
- }
123
-
124
- values(): Generator<T> {
125
- dependant(this.content)
126
- return makeReactiveIterator(this[native].values())
127
- }
128
-
129
- [Symbol.iterator](): Iterator<T> {
130
- dependant(this.content)
131
- const nativeIterator = this[native][Symbol.iterator]()
132
- return {
133
- next() {
134
- const result = nativeIterator.next()
135
- if (result.done) {
136
- return result
137
- }
138
- return { value: reactive(result.value), done: false }
139
- },
140
- }
141
- }
142
- }