mutts 1.0.0 → 1.0.1

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 (53) hide show
  1. package/dist/chunks/{decorator-BXsign4Z.js → decorator-8qjFb7dw.js} +2 -2
  2. package/dist/chunks/decorator-8qjFb7dw.js.map +1 -0
  3. package/dist/chunks/{decorator-CPbZNnsX.esm.js → decorator-AbRkXM5O.esm.js} +2 -2
  4. package/dist/chunks/decorator-AbRkXM5O.esm.js.map +1 -0
  5. package/dist/decorator.d.ts +1 -1
  6. package/dist/decorator.esm.js +1 -1
  7. package/dist/decorator.js +1 -1
  8. package/dist/destroyable.esm.js +1 -1
  9. package/dist/destroyable.js +1 -1
  10. package/dist/index.d.ts +1 -1
  11. package/dist/index.esm.js +2 -2
  12. package/dist/index.js +2 -1
  13. package/dist/index.js.map +1 -1
  14. package/dist/mutts.umd.js +1 -1
  15. package/dist/mutts.umd.js.map +1 -1
  16. package/dist/mutts.umd.min.js +1 -1
  17. package/dist/mutts.umd.min.js.map +1 -1
  18. package/dist/reactive.d.ts +4 -3
  19. package/dist/reactive.esm.js +61 -57
  20. package/dist/reactive.esm.js.map +1 -1
  21. package/dist/reactive.js +61 -56
  22. package/dist/reactive.js.map +1 -1
  23. package/dist/std-decorators.esm.js +1 -1
  24. package/dist/std-decorators.js +1 -1
  25. package/docs/reactive.md +616 -0
  26. package/package.json +1 -2
  27. package/dist/chunks/decorator-BXsign4Z.js.map +0 -1
  28. package/dist/chunks/decorator-CPbZNnsX.esm.js.map +0 -1
  29. package/src/decorator.test.ts +0 -495
  30. package/src/decorator.ts +0 -205
  31. package/src/destroyable.test.ts +0 -155
  32. package/src/destroyable.ts +0 -158
  33. package/src/eventful.test.ts +0 -380
  34. package/src/eventful.ts +0 -69
  35. package/src/index.ts +0 -7
  36. package/src/indexable.test.ts +0 -388
  37. package/src/indexable.ts +0 -124
  38. package/src/promiseChain.test.ts +0 -201
  39. package/src/promiseChain.ts +0 -99
  40. package/src/reactive/array.test.ts +0 -923
  41. package/src/reactive/array.ts +0 -352
  42. package/src/reactive/core.test.ts +0 -1663
  43. package/src/reactive/core.ts +0 -866
  44. package/src/reactive/index.ts +0 -28
  45. package/src/reactive/interface.test.ts +0 -1477
  46. package/src/reactive/interface.ts +0 -231
  47. package/src/reactive/map.test.ts +0 -866
  48. package/src/reactive/map.ts +0 -162
  49. package/src/reactive/set.test.ts +0 -289
  50. package/src/reactive/set.ts +0 -142
  51. package/src/std-decorators.test.ts +0 -679
  52. package/src/std-decorators.ts +0 -182
  53. package/src/utils.ts +0 -52
@@ -1,352 +0,0 @@
1
- import { Indexable } from '../indexable'
2
- import {
3
- dependant,
4
- makeReactiveEntriesIterator,
5
- makeReactiveIterator,
6
- prototypeForwarding,
7
- reactive,
8
- touched,
9
- } from './core'
10
-
11
- const native = Symbol('native')
12
- const isArray = Array.isArray
13
- Array.isArray = ((value: any) =>
14
- // biome-ignore lint/suspicious/useIsArray: We are defining it
15
- isArray(value) || (value instanceof Array && native in value)) as any
16
- class ReactiveBaseArray {
17
- declare readonly [native]: any[]
18
- }
19
- function* index(i: number, { length = true } = {}): IterableIterator<number | 'length'> {
20
- yield i
21
- if (length) yield 'length'
22
- }
23
-
24
- function* range(
25
- a: number,
26
- b: number,
27
- { length = false } = {}
28
- ): IterableIterator<number | 'length'> {
29
- const start = Math.min(a, b)
30
- const end = Math.max(a, b)
31
- for (let i = start; i <= end; i++) yield i
32
- if (length) yield 'length'
33
- }
34
- export class ReactiveArray extends Indexable(ReactiveBaseArray, {
35
- get(i: number): any {
36
- dependant(this[native], i)
37
- return reactive(this[native][i])
38
- },
39
- set(i: number, value: any) {
40
- const added = i >= this[native].length
41
- this[native][i] = value
42
- touched(this[native], { type: 'bunch', method: 'set' }, index(i, { length: added }))
43
- },
44
- getLength() {
45
- dependant(this[native], 'length')
46
- return this[native].length
47
- },
48
- setLength(value: number) {
49
- const oldLength = this[native].length
50
- try {
51
- this[native].length = value
52
- } finally {
53
- touched(
54
- this[native],
55
- { type: 'set', prop: 'length' },
56
- range(oldLength, value, { length: true })
57
- )
58
- }
59
- },
60
- }) {
61
- declare length: number
62
- constructor(original: any[]) {
63
- super()
64
- Object.defineProperties(this, {
65
- // We have to make it double, as [native] must be `unique symbol` - impossible through import
66
- [native]: { value: original },
67
- [prototypeForwarding]: { value: original },
68
- })
69
- }
70
-
71
- // Safe array access with negative indices
72
- at(index: number): any {
73
- const actualIndex = index < 0 ? this[native].length + index : index
74
- dependant(this, actualIndex)
75
- if (actualIndex < 0 || actualIndex >= this[native].length) return undefined
76
- return reactive(this[native][actualIndex])
77
- }
78
-
79
- push(...items: any[]) {
80
- const oldLength = this[native].length
81
- try {
82
- return this[native].push(...items)
83
- } finally {
84
- touched(
85
- this,
86
- { type: 'bunch', method: 'push' },
87
- range(oldLength, oldLength + items.length - 1, { length: true })
88
- )
89
- }
90
- }
91
-
92
- pop() {
93
- if (this[native].length === 0) return undefined
94
- try {
95
- return reactive(this[native].pop())
96
- } finally {
97
- touched(this, { type: 'bunch', method: 'pop' }, index(this[native].length))
98
- }
99
- }
100
-
101
- shift() {
102
- if (this[native].length === 0) return undefined
103
- try {
104
- return reactive(this[native].shift())
105
- } finally {
106
- touched(
107
- this,
108
- { type: 'bunch', method: 'shift' },
109
- range(0, this[native].length + 1, { length: true })
110
- )
111
- }
112
- }
113
-
114
- unshift(...items: any[]) {
115
- try {
116
- return this[native].unshift(...items)
117
- } finally {
118
- touched(
119
- this,
120
- { type: 'bunch', method: 'unshift' },
121
- range(0, this[native].length - items.length, { length: true })
122
- )
123
- }
124
- }
125
-
126
- splice(start: number, deleteCount?: number, ...items: any[]) {
127
- const oldLength = this[native].length
128
- if (deleteCount === undefined) deleteCount = oldLength - start
129
- try {
130
- if (deleteCount === undefined) return reactive(this[native].splice(start))
131
- return reactive(this[native].splice(start, deleteCount, ...items))
132
- } finally {
133
- touched(
134
- this,
135
- { type: 'bunch', method: 'splice' },
136
- // TODO: edge cases
137
- deleteCount === items.length
138
- ? range(start, start + deleteCount)
139
- : range(start, oldLength + Math.max(items.length - deleteCount, 0), {
140
- length: true,
141
- })
142
- )
143
- }
144
- }
145
-
146
- reverse() {
147
- try {
148
- return this[native].reverse()
149
- } finally {
150
- touched(this, { type: 'bunch', method: 'reverse' }, range(0, this[native].length - 1))
151
- }
152
- }
153
-
154
- sort(compareFn?: (a: any, b: any) => number) {
155
- try {
156
- return this[native].sort(compareFn) as any
157
- } finally {
158
- touched(this, { type: 'bunch', method: 'sort' }, range(0, this[native].length - 1))
159
- }
160
- }
161
-
162
- fill(value: any, start?: number, end?: number) {
163
- try {
164
- if (start === undefined) return this[native].fill(value) as any
165
- if (end === undefined) return this[native].fill(value, start) as any
166
- return this[native].fill(value, start, end) as any
167
- } finally {
168
- touched(this, { type: 'bunch', method: 'fill' }, range(0, this[native].length - 1))
169
- }
170
- }
171
-
172
- copyWithin(target: number, start: number, end?: number) {
173
- try {
174
- if (end === undefined) return this[native].copyWithin(target, start) as any
175
- return this[native].copyWithin(target, start, end) as any
176
- } finally {
177
- touched(
178
- this,
179
- { type: 'bunch', method: 'copyWithin' },
180
- // TODO: calculate the range properly
181
- range(0, this[native].length - 1)
182
- )
183
- }
184
- // Touch all affected indices with a single allProps call
185
- }
186
-
187
- // Immutable versions of mutator methods
188
- toReversed(): any[] {
189
- dependant(this)
190
- return reactive(this[native].toReversed())
191
- }
192
-
193
- toSorted(compareFn?: (a: any, b: any) => number): any[] {
194
- dependant(this)
195
- return reactive(this[native].toSorted(compareFn))
196
- }
197
-
198
- toSpliced(start: number, deleteCount?: number, ...items: any[]): any[] {
199
- dependant(this)
200
- return deleteCount === undefined
201
- ? this[native].toSpliced(start)
202
- : this[native].toSpliced(start, deleteCount, ...items)
203
- }
204
-
205
- with(index: number, value: any): any[] {
206
- dependant(this)
207
- return reactive(this[native].with(index, value))
208
- }
209
-
210
- // Iterator methods with reactivity tracking
211
- entries() {
212
- dependant(this)
213
- return makeReactiveEntriesIterator(this[native].entries())
214
- }
215
-
216
- keys() {
217
- dependant(this)
218
- return this[native].keys()
219
- }
220
-
221
- values() {
222
- dependant(this)
223
- return makeReactiveIterator(this[native].values())
224
- }
225
-
226
- [Symbol.iterator]() {
227
- dependant(this)
228
- const nativeIterator = this[native][Symbol.iterator]()
229
- return {
230
- next() {
231
- const result = nativeIterator.next()
232
- if (result.done) {
233
- return result
234
- }
235
- return { value: reactive(result.value), done: false }
236
- },
237
- }
238
- }
239
-
240
- indexOf(searchElement: any, fromIndex?: number): number {
241
- dependant(this)
242
- return this[native].indexOf(searchElement, fromIndex)
243
- }
244
-
245
- lastIndexOf(searchElement: any, fromIndex?: number): number {
246
- dependant(this)
247
- return this[native].lastIndexOf(searchElement, fromIndex)
248
- }
249
-
250
- includes(searchElement: any, fromIndex?: number): boolean {
251
- dependant(this)
252
- return this[native].includes(searchElement, fromIndex)
253
- }
254
-
255
- find(
256
- predicate: (this: any, value: any, index: number, obj: any[]) => boolean,
257
- thisArg?: any
258
- ): any {
259
- dependant(this)
260
- return reactive(this[native].find(predicate, thisArg))
261
- }
262
-
263
- findIndex(
264
- predicate: (this: any, value: any, index: number, obj: any[]) => boolean,
265
- thisArg?: any
266
- ): number {
267
- dependant(this)
268
- return this[native].findIndex(predicate, thisArg)
269
- }
270
-
271
- flat(): any[] {
272
- dependant(this)
273
- return reactive(this[native].flat())
274
- }
275
-
276
- flatMap(
277
- callbackfn: (this: any, value: any, index: number, array: any[]) => any[],
278
- thisArg?: any
279
- ): any[] {
280
- dependant(this)
281
- return reactive(this[native].flatMap(callbackfn, thisArg))
282
- }
283
-
284
- filter(callbackfn: (value: any, index: number, array: any[]) => boolean, thisArg?: any): any[] {
285
- dependant(this)
286
- return reactive(this[native].filter(callbackfn as any, thisArg))
287
- }
288
-
289
- map(callbackfn: (value: any, index: number, array: any[]) => any, thisArg?: any): any[] {
290
- dependant(this)
291
- return reactive(this[native].map(callbackfn as any, thisArg))
292
- }
293
-
294
- reduce(
295
- callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any,
296
- initialValue?: any
297
- ): any {
298
- dependant(this)
299
- const result =
300
- initialValue === undefined
301
- ? this[native].reduce(callbackfn as any)
302
- : this[native].reduce(callbackfn as any, initialValue)
303
- return reactive(result)
304
- }
305
-
306
- reduceRight(
307
- callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any,
308
- initialValue?: any
309
- ): any {
310
- dependant(this)
311
- const result =
312
- initialValue !== undefined
313
- ? this[native].reduceRight(callbackfn as any, initialValue)
314
- : (this[native] as any).reduceRight(callbackfn as any)
315
- return reactive(result)
316
- }
317
-
318
- slice(start?: number, end?: number): any[] {
319
- for (const i of range(start || 0, end || this[native].length - 1)) dependant(this, i)
320
- return start === undefined
321
- ? this[native].slice()
322
- : end === undefined
323
- ? this[native].slice(start)
324
- : this[native].slice(start, end)
325
- }
326
-
327
- concat(...items: any[]): any[] {
328
- dependant(this)
329
- return reactive(this[native].concat(...items))
330
- }
331
-
332
- join(separator?: string): string {
333
- dependant(this)
334
- return this[native].join(separator as any)
335
- }
336
-
337
- forEach(callbackfn: (value: any, index: number, array: any[]) => void, thisArg?: any): void {
338
- dependant(this)
339
- this[native].forEach(callbackfn as any, thisArg)
340
- }
341
-
342
- // TODO: re-implement for fun dependencies? (eg - every only check the first ones until it find some)
343
- every(callbackfn: (value: any, index: number, array: any[]) => boolean, thisArg?: any): boolean {
344
- dependant(this)
345
- return this[native].every(callbackfn as any, thisArg)
346
- }
347
-
348
- some(callbackfn: (value: any, index: number, array: any[]) => boolean, thisArg?: any): boolean {
349
- dependant(this)
350
- return this[native].some(callbackfn as any, thisArg)
351
- }
352
- }