mutts 1.0.9 → 1.0.11

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 (206) hide show
  1. package/README.md +60 -35
  2. package/dist/browser.cjs +1333 -1760
  3. package/dist/browser.cjs.map +1 -1
  4. package/dist/browser.d.ts +2 -1392
  5. package/dist/browser.dev.cjs +114 -0
  6. package/dist/browser.dev.cjs.map +1 -0
  7. package/dist/browser.dev.d.ts +2 -0
  8. package/dist/browser.dev.esm.js +5 -0
  9. package/dist/browser.dev.esm.js.map +1 -0
  10. package/dist/browser.esm.js +18 -97
  11. package/dist/browser.esm.js.map +1 -1
  12. package/dist/chunks/{async-browser-lvzLOCgk.cjs → async-browser-Dgr5CreQ.cjs} +16 -95
  13. package/dist/chunks/async-browser-Dgr5CreQ.cjs.map +1 -0
  14. package/dist/chunks/{async-node-C3DeIb0y.cjs → async-node-3PrbVAbB.cjs} +3 -1
  15. package/dist/chunks/async-node-3PrbVAbB.cjs.map +1 -0
  16. package/dist/chunks/index-Sf74wXTV.esm.js +2577 -0
  17. package/dist/chunks/index-Sf74wXTV.esm.js.map +1 -0
  18. package/dist/chunks/node-Bo7WU5S2.esm.js +96 -0
  19. package/dist/chunks/node-Bo7WU5S2.esm.js.map +1 -0
  20. package/dist/chunks/{index-VTO-b2vR.cjs → proxy-Cc79Lrzj.cjs} +2593 -3216
  21. package/dist/chunks/proxy-Cc79Lrzj.cjs.map +1 -0
  22. package/dist/chunks/{index-CtA2AWl3.esm.js → proxy-D2C49sXH.esm.js} +2570 -3174
  23. package/dist/chunks/proxy-D2C49sXH.esm.js.map +1 -0
  24. package/dist/debug.cjs +987 -28
  25. package/dist/debug.cjs.map +1 -1
  26. package/dist/debug.d.ts +37 -38
  27. package/dist/debug.esm.js +963 -1
  28. package/dist/debug.esm.js.map +1 -1
  29. package/dist/devtools/manifest.json +1 -1
  30. package/dist/devtools/panel.html +1 -1
  31. package/dist/devtools/panel.js +107 -94
  32. package/dist/devtools/panel.js.map +1 -1
  33. package/dist/index.d.ts +1322 -1
  34. package/dist/mutts.umd.js +6647 -1
  35. package/dist/mutts.umd.js.map +1 -1
  36. package/dist/mutts.umd.min.js +1 -1
  37. package/dist/mutts.umd.min.js.map +1 -1
  38. package/dist/node.cjs +69 -63
  39. package/dist/node.cjs.map +1 -1
  40. package/dist/node.d.ts +2 -2
  41. package/dist/node.dev.cjs +114 -0
  42. package/dist/node.dev.cjs.map +1 -0
  43. package/dist/node.dev.d.ts +2 -0
  44. package/dist/node.dev.esm.js +6 -0
  45. package/dist/node.dev.esm.js.map +1 -0
  46. package/dist/node.esm.js +4 -97
  47. package/dist/node.esm.js.map +1 -1
  48. package/dist/{types-DaHFfhlN.d.ts → types-Bx2PhORg.d.ts} +134 -88
  49. package/docs/ai/api-reference.md +11 -32
  50. package/docs/ai/manual.md +297 -239
  51. package/docs/reactive/advanced.md +318 -9
  52. package/docs/reactive/attend.md +2 -4
  53. package/docs/reactive/collections.md +22 -187
  54. package/docs/reactive/core.md +223 -131
  55. package/docs/reactive/debugging.md +119 -12
  56. package/docs/reactive/error-handling.md +10 -10
  57. package/docs/reactive/resource.md +125 -0
  58. package/docs/reactive.md +3 -4
  59. package/docs/utils.md +70 -0
  60. package/docs/zone.md +1 -1
  61. package/package.json +76 -38
  62. package/dist/chunks/async-browser-lvzLOCgk.cjs.map +0 -1
  63. package/dist/chunks/async-node-C3DeIb0y.cjs.map +0 -1
  64. package/dist/chunks/index-2vea86wD.esm.js +0 -3011
  65. package/dist/chunks/index-2vea86wD.esm.js.map +0 -1
  66. package/dist/chunks/index-CtA2AWl3.esm.js.map +0 -1
  67. package/dist/chunks/index-VTO-b2vR.cjs.map +0 -1
  68. package/dist/debug/debug.d.ts +0 -122
  69. package/dist/debug/debug.d.ts.map +0 -1
  70. package/dist/debug/index.d.ts +0 -4
  71. package/dist/debug/index.d.ts.map +0 -1
  72. package/dist/debug/lineage-panel.d.ts +0 -5
  73. package/dist/debug/lineage-panel.d.ts.map +0 -1
  74. package/dist/debug/lineage.d.ts +0 -79
  75. package/dist/debug/lineage.d.ts.map +0 -1
  76. package/dist/src/async/browser.d.ts +0 -2
  77. package/dist/src/async/browser.d.ts.map +0 -1
  78. package/dist/src/async/index.d.ts +0 -19
  79. package/dist/src/async/index.d.ts.map +0 -1
  80. package/dist/src/async/node.d.ts +0 -2
  81. package/dist/src/async/node.d.ts.map +0 -1
  82. package/dist/src/decorator.d.ts +0 -106
  83. package/dist/src/decorator.d.ts.map +0 -1
  84. package/dist/src/destroyable.d.ts +0 -87
  85. package/dist/src/destroyable.d.ts.map +0 -1
  86. package/dist/src/entry-browser.d.ts +0 -3
  87. package/dist/src/entry-browser.d.ts.map +0 -1
  88. package/dist/src/entry-node.d.ts +0 -3
  89. package/dist/src/entry-node.d.ts.map +0 -1
  90. package/dist/src/eventful.d.ts +0 -20
  91. package/dist/src/eventful.d.ts.map +0 -1
  92. package/dist/src/flavored.d.ts +0 -33
  93. package/dist/src/flavored.d.ts.map +0 -1
  94. package/dist/src/index.d.ts +0 -14
  95. package/dist/src/index.d.ts.map +0 -1
  96. package/dist/src/indexable.d.ts +0 -243
  97. package/dist/src/indexable.d.ts.map +0 -1
  98. package/dist/src/introspection.d.ts +0 -27
  99. package/dist/src/introspection.d.ts.map +0 -1
  100. package/dist/src/iterableWeak.d.ts +0 -53
  101. package/dist/src/iterableWeak.d.ts.map +0 -1
  102. package/dist/src/mixins.d.ts +0 -25
  103. package/dist/src/mixins.d.ts.map +0 -1
  104. package/dist/src/promiseChain.d.ts +0 -20
  105. package/dist/src/promiseChain.d.ts.map +0 -1
  106. package/dist/src/reactive/array.d.ts +0 -48
  107. package/dist/src/reactive/array.d.ts.map +0 -1
  108. package/dist/src/reactive/buffer.d.ts +0 -120
  109. package/dist/src/reactive/buffer.d.ts.map +0 -1
  110. package/dist/src/reactive/change.d.ts +0 -29
  111. package/dist/src/reactive/change.d.ts.map +0 -1
  112. package/dist/src/reactive/deep-touch.d.ts +0 -28
  113. package/dist/src/reactive/deep-touch.d.ts.map +0 -1
  114. package/dist/src/reactive/deep-watch-state.d.ts +0 -25
  115. package/dist/src/reactive/deep-watch-state.d.ts.map +0 -1
  116. package/dist/src/reactive/deep-watch.d.ts +0 -20
  117. package/dist/src/reactive/deep-watch.d.ts.map +0 -1
  118. package/dist/src/reactive/describe.d.ts +0 -12
  119. package/dist/src/reactive/describe.d.ts.map +0 -1
  120. package/dist/src/reactive/effect-context.d.ts +0 -34
  121. package/dist/src/reactive/effect-context.d.ts.map +0 -1
  122. package/dist/src/reactive/effects.d.ts +0 -164
  123. package/dist/src/reactive/effects.d.ts.map +0 -1
  124. package/dist/src/reactive/index.d.ts +0 -19
  125. package/dist/src/reactive/index.d.ts.map +0 -1
  126. package/dist/src/reactive/map.d.ts +0 -28
  127. package/dist/src/reactive/map.d.ts.map +0 -1
  128. package/dist/src/reactive/memoize.d.ts +0 -28
  129. package/dist/src/reactive/memoize.d.ts.map +0 -1
  130. package/dist/src/reactive/non-reactive-state.d.ts +0 -9
  131. package/dist/src/reactive/non-reactive-state.d.ts.map +0 -1
  132. package/dist/src/reactive/non-reactive.d.ts +0 -11
  133. package/dist/src/reactive/non-reactive.d.ts.map +0 -1
  134. package/dist/src/reactive/project.d.ts +0 -40
  135. package/dist/src/reactive/project.d.ts.map +0 -1
  136. package/dist/src/reactive/proxy-state.d.ts +0 -8
  137. package/dist/src/reactive/proxy-state.d.ts.map +0 -1
  138. package/dist/src/reactive/proxy.d.ts +0 -23
  139. package/dist/src/reactive/proxy.d.ts.map +0 -1
  140. package/dist/src/reactive/record.d.ts +0 -115
  141. package/dist/src/reactive/record.d.ts.map +0 -1
  142. package/dist/src/reactive/register.d.ts +0 -125
  143. package/dist/src/reactive/register.d.ts.map +0 -1
  144. package/dist/src/reactive/registry.d.ts +0 -21
  145. package/dist/src/reactive/registry.d.ts.map +0 -1
  146. package/dist/src/reactive/set.d.ts +0 -26
  147. package/dist/src/reactive/set.d.ts.map +0 -1
  148. package/dist/src/reactive/tracking.d.ts +0 -7
  149. package/dist/src/reactive/tracking.d.ts.map +0 -1
  150. package/dist/src/reactive/types.d.ts +0 -424
  151. package/dist/src/reactive/types.d.ts.map +0 -1
  152. package/dist/src/reactive/watch.d.ts +0 -48
  153. package/dist/src/reactive/watch.d.ts.map +0 -1
  154. package/dist/src/std-decorators.d.ts +0 -45
  155. package/dist/src/std-decorators.d.ts.map +0 -1
  156. package/dist/src/utils.d.ts +0 -49
  157. package/dist/src/utils.d.ts.map +0 -1
  158. package/dist/src/zone.d.ts +0 -40
  159. package/dist/src/zone.d.ts.map +0 -1
  160. package/docs/reactive/describe.md +0 -85
  161. package/docs/reactive/project.md +0 -93
  162. package/docs/reactive/scan.md +0 -293
  163. package/src/async/browser.ts +0 -323
  164. package/src/async/index.ts +0 -27
  165. package/src/async/node.ts +0 -92
  166. package/src/decorator.ts +0 -272
  167. package/src/destroyable.ts +0 -199
  168. package/src/entry-browser.ts +0 -5
  169. package/src/entry-node.ts +0 -5
  170. package/src/eventful.ts +0 -110
  171. package/src/flavored.ts +0 -106
  172. package/src/index.d.ts +0 -12
  173. package/src/index.ts +0 -64
  174. package/src/indexable.ts +0 -526
  175. package/src/introspection.ts +0 -59
  176. package/src/iterableWeak.ts +0 -233
  177. package/src/mixins.ts +0 -123
  178. package/src/promiseChain.ts +0 -110
  179. package/src/reactive/array.ts +0 -500
  180. package/src/reactive/buffer.ts +0 -328
  181. package/src/reactive/change.ts +0 -131
  182. package/src/reactive/deep-touch.ts +0 -273
  183. package/src/reactive/deep-watch-state.ts +0 -82
  184. package/src/reactive/deep-watch.ts +0 -171
  185. package/src/reactive/describe.ts +0 -39
  186. package/src/reactive/effect-context.ts +0 -83
  187. package/src/reactive/effects.ts +0 -1434
  188. package/src/reactive/index.ts +0 -72
  189. package/src/reactive/map.ts +0 -142
  190. package/src/reactive/memoize.ts +0 -186
  191. package/src/reactive/non-reactive-state.ts +0 -49
  192. package/src/reactive/non-reactive.ts +0 -43
  193. package/src/reactive/project.md +0 -107
  194. package/src/reactive/project.ts +0 -430
  195. package/src/reactive/proxy-state.ts +0 -27
  196. package/src/reactive/proxy.ts +0 -282
  197. package/src/reactive/record.ts +0 -181
  198. package/src/reactive/register.ts +0 -538
  199. package/src/reactive/registry.ts +0 -72
  200. package/src/reactive/set.ts +0 -117
  201. package/src/reactive/tracking.ts +0 -41
  202. package/src/reactive/types.ts +0 -520
  203. package/src/reactive/watch.ts +0 -180
  204. package/src/std-decorators.ts +0 -256
  205. package/src/utils.ts +0 -300
  206. package/src/zone.ts +0 -142
@@ -259,169 +259,22 @@ effect(() => {
259
259
  })
260
260
  ```
261
261
 
262
- ### `Register`
263
-
264
- `Register` is an ordered, array-like collection that keeps a stable mapping between keys and values. It is useful when you need array semantics (indexable access, ordering, iteration) but also require identity preservation by key—ideal for UI lists keyed by IDs or when you want to memoise entries across reorders.
265
-
266
- ```typescript
267
- import { Register } from 'mutts/reactive'
268
-
269
- // Create a register where the key comes from the `id` field
270
- const list = new Register(({id}: { id: number }) => id, [
271
- { id: 1, label: 'Alpha' },
272
- { id: 2, label: 'Bravo' },
273
- ])
274
-
275
- effect(() => {
276
- console.log('Length:', list.length)
277
- console.log('First label:', list[0]?.label)
278
- })
279
-
280
- // Push uses the key function to keep identities stable
281
- list.push({ id: 3, label: 'Charlie' })
282
-
283
- // Replacing with the same key updates watchers without creating a new identity
284
- list[0] = { id: 1, label: 'Alpha (updated)' }
285
-
286
- // Access by key
287
- const second = list.get(2) // { id: 2, label: 'Bravo' }
288
-
289
- // Duplicate keys share value identity
290
- list.push({ id: 2, label: 'Bravo (new data)' })
291
- console.log(list[1] === list[2]) // true
292
- ```
293
-
294
- **Highlights:**
295
-
296
- - Fully indexable (`list[0]`, `list.at(-1)`, `list.length`, iteration, etc.) thanks to the shared `Indexable` infrastructure.
297
- - Complete array surface forwarding (`map`, `filter`, `reduce`, `concat`, `reverse`, `sort`, `fill`, `copyWithin`, and more) with reactivity preserved.
298
- - Stable key/value map under the hood allows quick lookups via `get()`, `hasKey()`, and `indexOfKey()`.
299
- - When the same key appears multiple times, all slots reference the same underlying value instance, making deduplication and memoisation straightforward.
300
- - Reordering operations emit index-level touches so list reactivity remains predictable in rendered UIs.
301
-
302
- ### Register-specific API (beyond Array)
303
-
304
- The `Register` exposes additional methods and behaviors that standard arrays do not have:
305
-
306
- - `get(key)` / `set(key, value)`
307
- - `get(key: K): T | undefined` returns the latest value for a key.
308
- - `set(key: K, value: T): void` updates the value for an existing key (no-op if key absent).
309
- - Example:
310
- ```typescript
311
- list.set(2, { id: 2, label: 'Bravo (updated)' })
312
- const v = list.get(2)
313
- ```
314
-
315
- - `hasKey(key)` / `indexOfKey(key)`
316
- - `hasKey(key: K): boolean` whether the key is present in any slot.
317
- - `indexOfKey(key: K): number` first index at which the key appears, or `-1`.
318
-
319
- - `remove(key)` / `removeAt(index)`
320
- - `remove(key: K): void` removes all occurrences of `key` from the register.
321
- - `removeAt(index: number): T | undefined` removes a single slot by index and returns its value.
322
-
323
- - `keep(predicate)`
324
- - `keep(predicate: (value: T) => boolean): void` keeps only items for which the predicate returns `true`; items for which it returns `false` are removed. The predicate is evaluated once per distinct key; duplicate keys follow the same decision.
325
-
326
- - `update(...values)`
327
- - `update(...values: T[]): void` updates existing entries by their key; ignores values whose key is not yet present.
328
-
329
- - `upsert(insert, ...values)`
330
- - `upsert(insert: (value: T) => void, ...values: T[]): void` updates by key when present, otherwise calls `insert(value)` so you can decide how to insert (e.g. `push`, `unshift`, or `splice`).
331
- - Example:
332
- ```typescript
333
- list.upsert(v => list.push(v), { id: 4, label: 'Delta' }, { id: 2, label: 'Bravo (again)' })
334
- ```
335
-
336
- - `entries()`
337
- - Iterates `[number, value]` pairs in index order: `IterableIterator<[number, T | undefined]>`.
338
-
339
- - `keys` / `values`
340
- - `keys: ArrayIterator<number>` provides the index iterator (mirrors `Array#keys()`).
341
- - `values: IterableIterator<T>` provides an iterator of values (same as default iteration).
342
-
343
- - `clear()`
344
- - Removes all entries and disposes internal key-tracking effects.
345
-
346
- - `toArray()` / `toString()`
347
- - `toArray(): T[]` materializes the current values into a plain array.
348
- - `toString(): string` returns a concise description like `[Register length=3]`.
349
-
350
- ### Register CRUD Events
351
-
352
- `Register` emits lifecycle events for add, delete, update, and rekey operations. This enables side effects like logging, syncing with external systems, or triggering derived updates.
353
-
354
- ```typescript
355
- const list = register(({id}: { id: number }) => id)
356
-
357
- // Listen to individual events
358
- list.on('add', (item, key, index) => {
359
- console.log(`Added ${key} at index ${index}:`, item)
360
- })
361
-
362
- list.on('delete', (item, key, index) => {
363
- console.log(`Removed ${key} from index ${index}:`, item)
364
- })
365
-
366
- list.on('update', (oldItem, newItem, key, index) => {
367
- console.log(`Updated ${key} at index ${index}`)
368
- })
369
-
370
- list.on('rekey', (item, oldKey, newKey, index) => {
371
- console.log(`Key changed from ${oldKey} to ${newKey}`)
372
- })
373
-
374
- // Bulk event registration
375
- list.on({
376
- add: (item) => console.log('Added:', item),
377
- delete: (item) => console.log('Deleted:', item),
378
- })
379
-
380
- // Global hook - receive all events
381
- const unhook = list.hook((event, ...args) => {
382
- console.log(`Event: ${String(event)}`, args)
383
- })
384
-
385
- // Unsubscribe
386
- const unsubscribe = list.on('add', handler)
387
- unsubscribe()
388
- ```
389
-
390
- **Event Types:**
391
-
392
- | Event | Arguments | Description |
393
- |-------|-----------|-------------|
394
- | `add` | `(item, key, index)` | New item added to register |
395
- | `delete` | `(item, key, index)` | Item removed from register |
396
- | `update` | `(oldItem, newItem, key, index)` | Item value updated (same key) |
397
- | `rekey` | `(item, oldKey, newKey, index)` | Item's key changed |
398
-
399
- **Use Cases:**
400
- - Audit logging
401
- - Syncing with databases
402
- - Triggering notifications
403
- - Cascading updates to dependent systems
404
-
405
- Notes:
406
- - Direct length modification via `list.length = n` is not supported; use `splice` instead.
407
- - Assigning to an index (`list[i] = value`) uses the key function to bind that slot to `value`’s key.
408
-
409
262
  ## Class Reactivity
410
263
 
411
- ## Projection
264
+ ## Morphing
412
265
 
413
- ### `project()`
266
+ ### `morph()`
414
267
 
415
- `project()` provides a unified API for transforming reactive collections (arrays, records, and maps) into new reactive collections. Each source entry gets its own reactive effect that recomputes only when that specific entry changes, enabling granular updates perfect for rendering pipelines.
268
+ `morph()` provides a unified API for transforming reactive collections (arrays, records, and maps) into new reactive collections. Each source entry gets its own reactive effect that recomputes only when that specific entry changes, enabling granular updates perfect for rendering pipelines.
416
269
 
417
270
  #### Basic Usage
418
271
 
419
272
  ```typescript
420
- import { cleanup, project, reactive } from 'mutts/reactive'
273
+ import { cleanup, morph, reactive } from 'mutts'
421
274
 
422
275
  // Arrays
423
276
  const users = reactive([{ name: 'John', age: 30 }, { name: 'Jane', age: 25 }])
424
- const names = project.array(users, ({ get }) => get()?.name.toUpperCase() ?? '')
277
+ const names = morph(users, (user) => user.name.toUpperCase())
425
278
 
426
279
  console.log(names) // ['JOHN', 'JANE']
427
280
 
@@ -430,8 +283,7 @@ console.log(names[0]) // 'JOHNNY' - only index 0 recomputed
430
283
 
431
284
  // Records
432
285
  const scores = reactive({ math: 90, science: 85 })
433
- const grades = project.record(scores, ({ get }) => {
434
- const score = get()
286
+ const grades = morph(scores, (score) => {
435
287
  return score >= 90 ? 'A' : score >= 80 ? 'B' : 'C'
436
288
  })
437
289
 
@@ -444,7 +296,7 @@ const inventory = reactive(new Map([
444
296
  ['apples', { count: 10 }],
445
297
  ['oranges', { count: 5 }]
446
298
  ]))
447
- const totals = project.map(inventory, ({ get }) => get()?.count ?? 0)
299
+ const totals = morph(inventory, (item) => item.count)
448
300
 
449
301
  console.log(totals.get('apples')) // 10
450
302
  inventory.get('apples')!.count = 15
@@ -453,41 +305,25 @@ console.log(totals.get('apples')) // 15 - only 'apples' key recomputed
453
305
 
454
306
  #### Automatic Type Selection
455
307
 
456
- You can use `project()` directly and it will automatically select the appropriate helper based on the source type:
308
+ The `morph()` function automatically selects the appropriate helper based on the source type:
457
309
 
458
310
  ```typescript
459
- // Automatically uses project.array
460
- const doubled = project([1, 2, 3], ({ get }) => get() * 2)
311
+ // Arrays
312
+ const doubled = morph([1, 2, 3], (x) => x * 2)
461
313
 
462
- // Automatically uses project.record
463
- const upper = project({ a: 'hello', b: 'world' }, ({ get }) => get()?.toUpperCase() ?? '')
314
+ // Records
315
+ const upper = morph({ a: 'hello', b: 'world' }, (s) => s.toUpperCase())
464
316
 
465
- // Automatically uses project.map
466
- const counts = project(new Map([['x', 1], ['y', 2]]), ({ get }) => get() * 2)
317
+ // Maps
318
+ const counts = morph(new Map([['x', 1], ['y', 2]]), (v) => v * 2)
467
319
  ```
468
320
 
469
- #### Access Object
470
-
471
- The callback receives a `ProjectAccess` object with:
321
+ #### Callback Signature
472
322
 
473
- - **`get()`**: Function that returns the current source value for this key/index
474
- - **`set(value)`**: Function to update the source value (if the source is mutable)
475
- - **`key`**: The current key or index
476
- - **`source`**: Reference to the original source collection
477
- - **`old`**: Previously computed result for this entry (undefined on first run)
478
- - **`value`**: Computed property that mirrors `get()` (for convenience)
323
+ The callback function receives the current value of the entry being processed:
479
324
 
480
325
  ```typescript
481
- const transformed = project.array(items, (access) => {
482
- // Access the source value
483
- const item = access.get()
484
-
485
- // Access the key/index
486
- console.log(`Processing index ${access.key}`)
487
-
488
- // Leverage previous result
489
- console.log(`Previous result: ${access.old}`)
490
-
326
+ const transformed = morph(items, (item) => {
491
327
  // Transform and return
492
328
  return item.value * 2
493
329
  })
@@ -505,9 +341,8 @@ const users = reactive([
505
341
  ])
506
342
 
507
343
  let computeCount = 0
508
- const summaries = project.array(users, ({ get }) => {
344
+ const summaries = morph(users, (user) => {
509
345
  computeCount++
510
- const user = get()
511
346
  return `${user.name}: ${user.score}`
512
347
  })
513
348
 
@@ -525,11 +360,11 @@ console.log(computeCount) // 5 (only new index 3 computed)
525
360
 
526
361
  #### Key Addition and Removal
527
362
 
528
- `project()` automatically handles keys being added or removed from the source:
363
+ `morph()` automatically handles keys being added or removed from the source:
529
364
 
530
365
  ```typescript
531
366
  const source = reactive({ a: 1, b: 2 })
532
- const doubled = project.record(source, ({ get }) => get() * 2)
367
+ const doubled = morph(source, (val) => val * 2)
533
368
 
534
369
  console.log(doubled.a) // 2
535
370
  console.log(doubled.b) // 4
@@ -548,7 +383,7 @@ console.log('a' in doubled) // false (automatically removed)
548
383
  The returned object includes a `cleanup` symbol that stops all reactive effects:
549
384
 
550
385
  ```typescript
551
- const result = project.array(items, ({ get }) => get() * 2)
386
+ const result = morph(items, (item) => item * 2)
552
387
 
553
388
  // Later, when done
554
389
  result[cleanup]() // Stops all effects and cleans up
@@ -566,7 +401,7 @@ result[cleanup]() // Stops all effects and cleans up
566
401
  ### `organized()`
567
402
 
568
403
  ```typescript
569
- import { cleanup, organized, reactive } from 'mutts/reactive'
404
+ import { cleanup, organized, reactive } from 'mutts'
570
405
 
571
406
  const source = reactive<Record<string, number>>({ apples: 1, oranges: 2 })
572
407