aberdeen 1.18.2 → 1.19.0

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 (152) hide show
  1. package/README.md +9 -0
  2. package/dist/src/aberdeen.d.ts +27 -0
  3. package/{dist-docs/assets/aberdeen/aberdeen.js → dist/src/aberdeen.dev.js} +776 -15
  4. package/dist/src/aberdeen.dev.js.map +12 -0
  5. package/dist/src/aberdeen.js +59 -13
  6. package/dist/src/aberdeen.js.map +3 -3
  7. package/dist/src/devtools.d.ts +26 -0
  8. package/html-to-aberdeen +9 -5
  9. package/package.json +17 -10
  10. package/skill/A.md +127 -0
  11. package/skill/Dispatcher.md +51 -0
  12. package/skill/OPAQUE.md +15 -0
  13. package/skill/PromiseProxy.md +25 -0
  14. package/skill/Route.md +50 -0
  15. package/skill/SKILL.md +272 -156
  16. package/skill/applyCanon.md +20 -0
  17. package/skill/applyPrediction.md +15 -0
  18. package/skill/back.md +11 -0
  19. package/skill/clean.md +43 -0
  20. package/skill/clone.md +15 -0
  21. package/skill/copy.md +40 -0
  22. package/skill/count.md +32 -0
  23. package/skill/cssVars.md +15 -0
  24. package/skill/darkMode.md +26 -0
  25. package/skill/derive.md +56 -0
  26. package/skill/developer-tools.md +23 -0
  27. package/skill/disableCreateDestroy.md +11 -0
  28. package/skill/dump.md +37 -0
  29. package/skill/freeze.md +20 -0
  30. package/skill/full-example-multi-page-app.md +146 -0
  31. package/skill/go.md +25 -0
  32. package/skill/grow.md +13 -0
  33. package/skill/html-to-aberdeen.md +9 -0
  34. package/skill/insertCss.md +79 -0
  35. package/skill/insertGlobalCss.md +68 -0
  36. package/skill/interceptLinks.md +19 -0
  37. package/skill/invertString.md +32 -0
  38. package/skill/isEmpty.md +38 -0
  39. package/skill/map.md +16 -0
  40. package/skill/matchCurrent.md +27 -0
  41. package/skill/merge.md +27 -0
  42. package/skill/mount.md +48 -0
  43. package/skill/multiMap.md +15 -0
  44. package/skill/onEach.md +14 -0
  45. package/skill/partition.md +15 -0
  46. package/skill/peek.md +36 -0
  47. package/skill/persistScroll.md +13 -0
  48. package/skill/proxy.md +11 -0
  49. package/skill/push.md +13 -0
  50. package/skill/ref.md +39 -0
  51. package/skill/runQueue.md +34 -0
  52. package/skill/setErrorHandler.md +48 -0
  53. package/skill/setLog.md +9 -0
  54. package/skill/setSpacingCssVars.md +31 -0
  55. package/skill/shrink.md +13 -0
  56. package/skill/unmountAll.md +9 -0
  57. package/skill/unproxy.md +43 -0
  58. package/skill/up.md +13 -0
  59. package/src/aberdeen.ts +194 -73
  60. package/src/devtools.ts +685 -0
  61. package/dist-docs/.nojekyll +0 -1
  62. package/dist-docs/Tutorial/index.html +0 -305
  63. package/dist-docs/aberdeen/A/index.html +0 -116
  64. package/dist-docs/aberdeen/CUSTOM_DUMP/index.html +0 -7
  65. package/dist-docs/aberdeen/NO_COPY/index.html +0 -2
  66. package/dist-docs/aberdeen/OPAQUE/index.html +0 -12
  67. package/dist-docs/aberdeen/PromiseProxy/index.html +0 -8
  68. package/dist-docs/aberdeen/clean/index.html +0 -11
  69. package/dist-docs/aberdeen/clone/index.html +0 -5
  70. package/dist-docs/aberdeen/copy/index.html +0 -22
  71. package/dist-docs/aberdeen/count/index.html +0 -7
  72. package/dist-docs/aberdeen/cssVars/index.html +0 -11
  73. package/dist-docs/aberdeen/darkMode/index.html +0 -9
  74. package/dist-docs/aberdeen/default/index.html +0 -342
  75. package/dist-docs/aberdeen/derive/index.html +0 -18
  76. package/dist-docs/aberdeen/disableCreateDestroy/index.html +0 -6
  77. package/dist-docs/aberdeen/dump/index.html +0 -11
  78. package/dist-docs/aberdeen/index.html +0 -54
  79. package/dist-docs/aberdeen/insertCss/index.html +0 -30
  80. package/dist-docs/aberdeen/insertGlobalCss/index.html +0 -19
  81. package/dist-docs/aberdeen/invertString/index.html +0 -13
  82. package/dist-docs/aberdeen/isEmpty/index.html +0 -12
  83. package/dist-docs/aberdeen/map/index.html +0 -26
  84. package/dist-docs/aberdeen/merge/index.html +0 -11
  85. package/dist-docs/aberdeen/mount/index.html +0 -17
  86. package/dist-docs/aberdeen/multiMap/index.html +0 -28
  87. package/dist-docs/aberdeen/onEach/index.html +0 -19
  88. package/dist-docs/aberdeen/partition/index.html +0 -36
  89. package/dist-docs/aberdeen/peek/index.html +0 -40
  90. package/dist-docs/aberdeen/proxy/index.html +0 -35
  91. package/dist-docs/aberdeen/ref/index.html +0 -13
  92. package/dist-docs/aberdeen/runQueue/index.html +0 -13
  93. package/dist-docs/aberdeen/setErrorHandler/index.html +0 -16
  94. package/dist-docs/aberdeen/setSpacingCssVars/index.html +0 -8
  95. package/dist-docs/aberdeen/unmountAll/index.html +0 -5
  96. package/dist-docs/aberdeen/unproxy/index.html +0 -11
  97. package/dist-docs/assets/aberdeen/aberdeen.d.ts +0 -963
  98. package/dist-docs/assets/aberdeen/aberdeen.js.map +0 -11
  99. package/dist-docs/assets/aberdeen/dispatcher.d.ts +0 -57
  100. package/dist-docs/assets/aberdeen/dispatcher.js +0 -66
  101. package/dist-docs/assets/aberdeen/dispatcher.js.map +0 -10
  102. package/dist-docs/assets/aberdeen/helpers/reverseSortedSet.d.ts +0 -96
  103. package/dist-docs/assets/aberdeen/prediction.d.ts +0 -33
  104. package/dist-docs/assets/aberdeen/prediction.js +0 -112
  105. package/dist-docs/assets/aberdeen/prediction.js.map +0 -10
  106. package/dist-docs/assets/aberdeen/route.d.ts +0 -137
  107. package/dist-docs/assets/aberdeen/route.js +0 -287
  108. package/dist-docs/assets/aberdeen/route.js.map +0 -10
  109. package/dist-docs/assets/aberdeen/transitions.d.ts +0 -18
  110. package/dist-docs/assets/aberdeen/transitions.js +0 -47
  111. package/dist-docs/assets/aberdeen/transitions.js.map +0 -10
  112. package/dist-docs/assets/custom.js +0 -573
  113. package/dist-docs/assets/favicon.png +0 -0
  114. package/dist-docs/assets/hierarchy.js +0 -1
  115. package/dist-docs/assets/highlight.css +0 -134
  116. package/dist-docs/assets/icons.js +0 -18
  117. package/dist-docs/assets/icons.svg +0 -1
  118. package/dist-docs/assets/main.js +0 -60
  119. package/dist-docs/assets/navigation.js +0 -1
  120. package/dist-docs/assets/search.js +0 -1
  121. package/dist-docs/assets/style.css +0 -1640
  122. package/dist-docs/dispatcher/Dispatcher/index.html +0 -21
  123. package/dist-docs/dispatcher/MATCH_FAILED/index.html +0 -2
  124. package/dist-docs/dispatcher/MATCH_REST/index.html +0 -2
  125. package/dist-docs/dispatcher/index.html +0 -4
  126. package/dist-docs/hierarchy.html +0 -1
  127. package/dist-docs/index.html +0 -61
  128. package/dist-docs/media/CHANGELOG.md +0 -266
  129. package/dist-docs/modules.html +0 -1
  130. package/dist-docs/prediction/applyCanon/index.html +0 -13
  131. package/dist-docs/prediction/applyPrediction/index.html +0 -8
  132. package/dist-docs/prediction/index.html +0 -9
  133. package/dist-docs/route/Route/index.html +0 -23
  134. package/dist-docs/route/back/index.html +0 -4
  135. package/dist-docs/route/current/index.html +0 -2
  136. package/dist-docs/route/go/index.html +0 -14
  137. package/dist-docs/route/index.html +0 -15
  138. package/dist-docs/route/interceptLinks/index.html +0 -8
  139. package/dist-docs/route/matchCurrent/index.html +0 -10
  140. package/dist-docs/route/persistScroll/index.html +0 -6
  141. package/dist-docs/route/push/index.html +0 -6
  142. package/dist-docs/route/setLog/index.html +0 -3
  143. package/dist-docs/route/up/index.html +0 -5
  144. package/dist-docs/sitemap.xml +0 -239
  145. package/dist-docs/transitions/grow/index.html +0 -6
  146. package/dist-docs/transitions/index.html +0 -5
  147. package/dist-docs/transitions/shrink/index.html +0 -6
  148. package/skill/aberdeen.md +0 -4586
  149. package/skill/dispatcher.md +0 -129
  150. package/skill/prediction.md +0 -73
  151. package/skill/route.md +0 -322
  152. package/skill/transitions.md +0 -59
package/skill/aberdeen.md DELETED
@@ -1,4586 +0,0 @@
1
- [**Aberdeen v1.18.2**](README.md)
2
-
3
- ***
4
-
5
- [Aberdeen](README.md) / aberdeen
6
-
7
- # aberdeen
8
-
9
- ## Interfaces
10
-
11
- ### PromiseProxy
12
-
13
- Defined in: [aberdeen.ts:1531](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L1531)
14
-
15
- When `proxy` is called with a Promise, the returned object has this shape.
16
-
17
- #### Type Parameters
18
-
19
- ##### T
20
-
21
- `T`
22
-
23
- #### Properties
24
-
25
- ##### busy
26
-
27
- > **busy**: `boolean`
28
-
29
- Defined in: [aberdeen.ts:1535](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L1535)
30
-
31
- True if the promise is still pending, false if it has resolved or rejected.
32
-
33
- ##### error?
34
-
35
- > `optional` **error**: `any`
36
-
37
- Defined in: [aberdeen.ts:1543](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L1543)
38
-
39
- If the promise has rejected, this contains the rejection error.
40
-
41
- ##### value?
42
-
43
- > `optional` **value**: `T`
44
-
45
- Defined in: [aberdeen.ts:1539](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L1539)
46
-
47
- If the promise has resolved, this contains the resolved value.
48
-
49
- ## Variables
50
-
51
- ### cssVars
52
-
53
- > `const` **cssVars**: `Record`\<`string`, `string`\>
54
-
55
- Defined in: [aberdeen.ts:1975](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L1975)
56
-
57
- A reactive object containing CSS variable definitions.
58
-
59
- Any property you assign to `cssVars` becomes available as a CSS custom property throughout your application.
60
-
61
- Use [setSpacingCssVars](#setspacingcssvars) to optionally initialize `cssVars[1]` through `cssVars[12]` with an exponential spacing scale.
62
-
63
- When you reference a CSS variable in Aberdeen using the `$` prefix (e.g., `$primary`), it automatically resolves to `var(--primary)`.
64
- For numeric keys (which can't be used directly as CSS custom property names), Aberdeen prefixes them with `m` (e.g., `$3` becomes `var(--m3)`).
65
-
66
- When you add the first property to cssVars, Aberdeen automatically creates a reactive `<style>` tag in `<head>`
67
- containing the `:root` CSS custom property declarations. The style tag is automatically removed if cssVars becomes empty.
68
-
69
- #### Example
70
-
71
- ```javascript
72
- import A from 'aberdeen';
73
-
74
- // Optionally initialize spacing scale
75
- A.setSpacingCssVars(); // Uses defaults: base=1, unit='rem'
76
-
77
- // Define custom colors - style tag is automatically created
78
- A.cssVars.primary = '#3b82f6';
79
- A.cssVars.danger = '#ef4444';
80
-
81
- // Use in elements with the $ prefix
82
- A('button bg:$primary fg:white #I'm a primary button');
83
-
84
- // Use spacing (if setSpacingCssVars() was called)
85
- A('hr mt:$3'); // Sets margin-top to var(--m3)
86
- ```
87
-
88
- ***
89
-
90
- ### CUSTOM\_DUMP
91
-
92
- > `const` **CUSTOM\_DUMP**: *typeof* [`CUSTOM_DUMP`](#custom_dump)
93
-
94
- Defined in: [aberdeen.ts:3495](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L3495)
95
-
96
- When set on an object or its prototype chain, [dump](#dump) calls this as a render function
97
- (with the object as `this`) instead of its default recursive rendering. If the value is not
98
- a function, it's treated as a string to display.
99
-
100
- #### Example
101
-
102
- ```typescript
103
- class Color {
104
- constructor(public r: number, public g: number, public b: number) {}
105
- [CUSTOM_DUMP]() { A(`#rgb(${this.r}, ${this.g}, ${this.b})`); }
106
- }
107
- ```
108
-
109
- ***
110
-
111
- ### default
112
-
113
- > **default**: (...`args`) => `undefined` \| `Element` & `object`
114
-
115
- Defined in: [aberdeen.ts:3589](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L3589)
116
-
117
- The main Aberdeen API. `A` is itself a callable function for building reactive DOM trees
118
- (creating elements, setting attributes, adding content). All other Aberdeen functions and
119
- values are available as properties on `A`.
120
-
121
- #### Type declaration
122
-
123
- ##### clean()
124
-
125
- > **clean**: (`cleaner`) => `void`
126
-
127
- Registers a cleanup function to be executed just before the current reactive scope
128
- is destroyed or redraws.
129
-
130
- This is useful for releasing resources, removing manual event listeners, or cleaning up
131
- side effects associated with the scope. Cleaners are run in reverse order of registration.
132
-
133
- Scopes are created by functions like [derive](#derive), [mount](#mount), [A](#a) (when given a render function),
134
- and internally by constructs like [onEach](#oneach).
135
-
136
- Registers a cleanup function to be executed just before the current reactive scope
137
- is destroyed or redraws.
138
-
139
- This is useful for releasing resources, removing manual event listeners, or cleaning up
140
- side effects associated with the scope. Cleaners are run in reverse order of registration.
141
-
142
- Scopes are created by functions like [derive](#derive), [mount](#mount), [A](#a) (when given a render function),
143
- and internally by constructs like [onEach](#oneach).
144
-
145
- ###### Parameters
146
-
147
- ###### cleaner
148
-
149
- () => `void`
150
-
151
- The function to execute during cleanup.
152
-
153
- ###### Returns
154
-
155
- `void`
156
-
157
- ###### Example
158
-
159
- ```typescript
160
- const $numbers = A.proxy([3, 5, 10]);
161
- let $sum = A.proxy(0);
162
-
163
- // Show the array items and maintain the sum
164
- A.onEach($numbers, (item, index) => {
165
- A(`code#${index}→${item}`);
166
- // We'll update $sum.value using peek, as += first does a read, but
167
- // we don't want to subscribe.
168
- A.peek(() => $sum.value += item);
169
- // Clean gets called before each rerun for a certain item index
170
- // No need for peek here, as the clean code doesn't run in an
171
- // observer scope.
172
- A.clean(() => $sum.value -= item);
173
- })
174
-
175
- // Show the sum
176
- A('h1 text=', $sum);
177
-
178
- // Make random changes to the array
179
- const rnd = () => 0|(Math.random()*20);
180
- setInterval(() => $numbers[rnd()] = rnd(), 1000);
181
- ```
182
-
183
- ##### clone()
184
-
185
- > **clone**: \<`T`\>(`src`) => `T`
186
-
187
- Clone an (optionally proxied) object or array.
188
-
189
- Clone an (optionally proxied) object or array.
190
-
191
- ###### Type Parameters
192
-
193
- ###### T
194
-
195
- `T` *extends* `object`
196
-
197
- The type of the objects being copied.
198
-
199
- ###### Parameters
200
-
201
- ###### src
202
-
203
- `T`
204
-
205
- The object or array to clone. If it is proxied, `clone` will subscribe to any changes to the (nested) data structure.
206
-
207
- ###### Returns
208
-
209
- `T`
210
-
211
- A new unproxied array or object (of the same type as `src`), containing a deep copy of `src`.
212
-
213
- ###### Returns
214
-
215
- A new unproxied array or object (of the same type as `src`), containing a deep copy of `src`.
216
-
217
- ##### copy()
218
-
219
- > **copy**: \{\<`T`\>(`dst`, `src`): `boolean`; \<`T`\>(`dst`, `dstKey`, `src`): `boolean`; \}
220
-
221
- Recursively copies properties or array items from `src` to `dst`.
222
- It's designed to work efficiently with reactive proxies created by [proxy](#proxy).
223
-
224
- - **Minimizes Updates:** When copying between objects/arrays (proxied or not), if a nested object
225
- exists in `dst` with the same constructor as the corresponding object in `src`, `copy`
226
- will recursively copy properties into the existing `dst` object instead of replacing it.
227
- This minimizes change notifications for reactive (proxied) destinations.
228
- - **Fast with Proxies:** When copying to/from proxied objects, `copy` uses Aberdeen internals
229
- to speed things up (compared to a non-Aberdeen-aware deep copy).
230
-
231
- ###### Call Signature
232
-
233
- > \<`T`\>(`dst`, `src`): `boolean`
234
-
235
- Recursively copies properties or array items from `src` to `dst`.
236
- It's designed to work efficiently with reactive proxies created by [proxy](#proxy).
237
-
238
- - **Minimizes Updates:** When copying between objects/arrays (proxied or not), if a nested object
239
- exists in `dst` with the same constructor as the corresponding object in `src`, `copy`
240
- will recursively copy properties into the existing `dst` object instead of replacing it.
241
- This minimizes change notifications for reactive (proxied) destinations.
242
- - **Fast with Proxies:** When copying to/from proxied objects, `copy` uses Aberdeen internals
243
- to speed things up (compared to a non-Aberdeen-aware deep copy).
244
-
245
- ###### Type Parameters
246
-
247
- ###### T
248
-
249
- `T` *extends* `object`
250
-
251
- The type of the objects being copied.
252
-
253
- ###### Parameters
254
-
255
- ###### dst
256
-
257
- `T`
258
-
259
- The destination object/array/Map (proxied or unproxied).
260
-
261
- ###### src
262
-
263
- `T`
264
-
265
- The source object/array/Map (proxied or unproxied). It won't be modified.
266
-
267
- ###### Returns
268
-
269
- `boolean`
270
-
271
- `true` if any changes were made to `dst`, or `false` if not.
272
-
273
- ###### Throws
274
-
275
- Error if attempting to copy an array into a non-array or vice versa.
276
-
277
- ###### Example
278
-
279
- ```typescript
280
- const $source = A.proxy({ a: 1, b: { c: 2 } });
281
- const $dest = A.proxy({ b: { d: 3 } });
282
- A.copy($dest, $source);
283
- console.log($dest); // proxy({ a: 1, b: { c: 2 } })
284
- A.copy($dest, 'b', { e: 4 });
285
- console.log($dest); // proxy({ a: 1, b: { e: 4 } })
286
- ```
287
-
288
- ###### Call Signature
289
-
290
- > \<`T`\>(`dst`, `dstKey`, `src`): `boolean`
291
-
292
- Like above, but copies `src` into `dst[dstKey]`. This is useful if you're unsure if dst[dstKey]
293
- already exists (as the right type of object) or if you don't want to subscribe to dst[dstKey].
294
-
295
- ###### Type Parameters
296
-
297
- ###### T
298
-
299
- `T` *extends* `object`
300
-
301
- ###### Parameters
302
-
303
- ###### dst
304
-
305
- `T`
306
-
307
- ###### dstKey
308
-
309
- keyof `T`
310
-
311
- Optional key in `dst` to copy into.
312
-
313
- ###### src
314
-
315
- `T`\[keyof `T`\]
316
-
317
- ###### Returns
318
-
319
- `boolean`
320
-
321
- ###### Returns
322
-
323
- `true` if any changes were made to `dst`, or `false` if not.
324
-
325
- ##### count()
326
-
327
- > **count**: (`proxied`) => `ValueRef`\<`number`\>
328
-
329
- Reactively counts the number of properties in an object.
330
-
331
- Reactively counts the number of properties in an object.
332
-
333
- ###### Parameters
334
-
335
- ###### proxied
336
-
337
- `TargetType`
338
-
339
- The observable object to count. In case an `array`, `Map`, or `Set` is passed in, a [ref](#ref) to its `.length` or `.size` will be returned.
340
-
341
- ###### Returns
342
-
343
- `ValueRef`\<`number`\>
344
-
345
- an observable object for which the `value` property reflects the number of properties in `proxied` with a value other than `undefined`, or the collection size for arrays, Maps, and Sets.
346
-
347
- ###### Example
348
-
349
- ```typescript
350
- const $items = A.proxy({x: 3, y: 7} as any);
351
- const $count = A.count($items);
352
-
353
- // Create a DOM text node for the count:
354
- A('div text=', $count);
355
- // <div>2</div>
356
-
357
- // Or we can use it in an {@link derive} function:
358
- A(() => console.log("The count is now", $count.value));
359
- // The count is now 2
360
-
361
- // Adding/removing items will update the count
362
- $items.z = 12;
363
- // Asynchronously, after 0ms:
364
- // <div>3</div>
365
- // The count is now 3
366
- ```
367
-
368
- ###### Returns
369
-
370
- an observable object for which the `value` property reflects the number of properties in `proxied` with a value other than `undefined`, or the collection size for arrays, Maps, and Sets.
371
-
372
- ##### cssVars
373
-
374
- > **cssVars**: `Record`\<`string`, `string`\>
375
-
376
- A reactive object containing CSS variable definitions.
377
-
378
- Any property you assign to `cssVars` becomes available as a CSS custom property throughout your application.
379
-
380
- Use [setSpacingCssVars](#setspacingcssvars) to optionally initialize `cssVars[1]` through `cssVars[12]` with an exponential spacing scale.
381
-
382
- When you reference a CSS variable in Aberdeen using the `$` prefix (e.g., `$primary`), it automatically resolves to `var(--primary)`.
383
- For numeric keys (which can't be used directly as CSS custom property names), Aberdeen prefixes them with `m` (e.g., `$3` becomes `var(--m3)`).
384
-
385
- When you add the first property to cssVars, Aberdeen automatically creates a reactive `<style>` tag in `<head>`
386
- containing the `:root` CSS custom property declarations. The style tag is automatically removed if cssVars becomes empty.
387
-
388
- ##### CUSTOM\_DUMP
389
-
390
- > **CUSTOM\_DUMP**: `symbol`
391
-
392
- When set on an object or its prototype chain, [dump](#dump) calls this as a render function
393
- (with the object as `this`) instead of its default recursive rendering. If the value is not
394
- a function, it's treated as a string to display.
395
-
396
- ##### darkMode()
397
-
398
- > **darkMode**: () => `boolean`
399
-
400
- Returns whether the user's browser prefers a dark color scheme.
401
-
402
- This function is reactive - scopes that call it will re-execute when the
403
- browser's color scheme preference changes (via the `prefers-color-scheme` media query).
404
-
405
- Use this in combination with [A](#a) and [cssVars](#cssvars) to implement theme switching:
406
-
407
- Returns whether the user's browser prefers a dark color scheme.
408
-
409
- This function is reactive - scopes that call it will re-execute when the
410
- browser's color scheme preference changes (via the `prefers-color-scheme` media query).
411
-
412
- Use this in combination with [A](#a) and [cssVars](#cssvars) to implement theme switching:
413
-
414
- ###### Returns
415
-
416
- `boolean`
417
-
418
- `true` if the browser prefers dark mode, `false` if it prefers light mode.
419
-
420
- ###### Example
421
-
422
- ```javascript
423
- import A from 'aberdeen';
424
-
425
- // Reactively set colors based on browser preference
426
- A(() => {
427
- A.cssVars.bg = A.darkMode() ? '#1a1a1a' : '#ffffff';
428
- A.cssVars.fg = A.darkMode() ? '#e5e5e5' : '#000000';
429
- });
430
-
431
- A('div bg:$bg fg:$fg p:1rem #Colors change based on system dark mode preference');
432
- ```
433
-
434
- ###### Returns
435
-
436
- `true` if the browser prefers dark mode, `false` if it prefers light mode.
437
-
438
- ##### derive()
439
-
440
- > **derive**: \<`T`\>(`func`) => `ValueRef`\<`T`\>
441
-
442
- Creates a reactive scope that automatically re-executes the provided function
443
- whenever any proxied data (created by [proxy](#proxy)) read during its last execution changes, storing
444
- its return value in an observable.
445
-
446
- Updates are batched and run asynchronously shortly after the changes occur.
447
- Use [clean](#clean) to register cleanup logic for the scope.
448
- Use [peek](#peek) or [unproxy](#unproxy) within the function to read proxied data without subscribing to it.
449
-
450
- Creates a reactive scope that automatically re-executes the provided function
451
- whenever any proxied data (created by [proxy](#proxy)) read during its last execution changes, storing
452
- its return value in an observable.
453
-
454
- Updates are batched and run asynchronously shortly after the changes occur.
455
- Use [clean](#clean) to register cleanup logic for the scope.
456
- Use [peek](#peek) or [unproxy](#unproxy) within the function to read proxied data without subscribing to it.
457
-
458
- ###### Type Parameters
459
-
460
- ###### T
461
-
462
- `T`
463
-
464
- ###### Parameters
465
-
466
- ###### func
467
-
468
- () => `T`
469
-
470
- The function to execute reactively. Any DOM manipulations should typically
471
- be done using [A](#a) within this function. Its return value will be made available as an
472
- observable returned by the `derive()` function.
473
-
474
- ###### Returns
475
-
476
- `ValueRef`\<`T`\>
477
-
478
- An observable object, with its `value` property containing whatever the last run of `func` returned.
479
-
480
- ###### Examples
481
-
482
- ```typescript
483
- const $data = A.proxy({ user: 'Frank', notifications: 42 });
484
-
485
- A('main', () => {
486
- console.log('Welcome');
487
- A('h3#Welcome, ' + $data.user); // Reactive text
488
-
489
- A.derive(() => {
490
- // When $data.notifications changes, only this inner scope reruns,
491
- // leaving the `<p>Welcome, ..</p>` untouched.
492
- console.log('Notifications');
493
- A('code.notification-badge text=', $data.notifications);
494
- A('a text=Notify! click=', () => $data.notifications++);
495
- });
496
- });
497
- ```
498
-
499
- ***Note*** that the above could just as easily be done using `A(func)` instead of `derive(func)`.
500
-
501
- ```typescript
502
- const $counter = A.proxy(0);
503
- setInterval(() => $counter.value++, 1000);
504
- const $double = A.derive(() => $counter.value * 2);
505
-
506
- A('h3', () => {
507
- A(`#counter=${$counter.value} double=${$double.value}`);
508
- })
509
- ```
510
-
511
- ###### Returns
512
-
513
- An observable object, with its `value` property containing whatever the last run of `func` returned.
514
-
515
- ##### disableCreateDestroy()
516
-
517
- > **disableCreateDestroy**: () => `void`
518
-
519
- Make the `create` and `destroy` special properties no-ops.
520
-
521
- This is useful from within automated testing environments, where the transitioning
522
- new and lingering old elements may make writing reliable selectors difficult.
523
-
524
- As this is only intended for testing, there's no way to re-enable the special properties
525
- once disabled.
526
-
527
- Make the `create` and `destroy` special properties no-ops.
528
-
529
- This is useful from within automated testing environments, where the transitioning
530
- new and lingering old elements may make writing reliable selectors difficult.
531
-
532
- As this is only intended for testing, there's no way to re-enable the special properties
533
- once disabled.
534
-
535
- ###### Returns
536
-
537
- `void`
538
-
539
- ##### dump()
540
-
541
- > **dump**: \<`T`\>(`data`) => `T`
542
-
543
- Renders a live, recursive dump of a proxied data structure (or any value)
544
- into the DOM at the current [A](#a) insertion point.
545
-
546
- Uses `<ul>` and `<li>` elements to display object properties and array items.
547
- Updates reactively if the dumped data changes. Primarily intended for debugging purposes.
548
-
549
- Renders a live, recursive dump of a proxied data structure (or any value)
550
- into the DOM at the current [A](#a) insertion point.
551
-
552
- Uses `<ul>` and `<li>` elements to display object properties and array items.
553
- Updates reactively if the dumped data changes. Primarily intended for debugging purposes.
554
-
555
- ###### Type Parameters
556
-
557
- ###### T
558
-
559
- `T`
560
-
561
- The type of the data being dumped.
562
-
563
- ###### Parameters
564
-
565
- ###### data
566
-
567
- `T`
568
-
569
- The proxied data structure (or any value) to display.
570
-
571
- ###### Returns
572
-
573
- `T`
574
-
575
- The original `data` argument, allowing for chaining.
576
-
577
- ###### Example
578
-
579
- ```typescript
580
- import A from 'aberdeen';
581
-
582
- const $state = A.proxy({
583
- user: { name: 'Frank', kids: 1 },
584
- items: ['a', 'b']
585
- });
586
-
587
- A('h2#Live State Dump');
588
- A.dump($state);
589
-
590
- // Change state later, the dump in the DOM will update
591
- setTimeout(() => { $state.user.kids++; $state.items.push('c'); }, 2000);
592
- ```
593
-
594
- ###### Returns
595
-
596
- The original `data` argument, allowing for chaining.
597
-
598
- ##### insertCss()
599
-
600
- > **insertCss**: (`style`) => `string`
601
-
602
- Inserts CSS rules into the document, scoping them with a unique class name.
603
-
604
- The `style` parameter can be either:
605
- - A **concise style string** (for rules applying to the root class).
606
- - An **object** where keys are selectors (with `&` representing the root class)
607
- and values are concise style strings or nested objects. When the key does not contain `&`,
608
- it is treated as a descendant selector. So `{p: "color:red"}` becomes `".AbdStlX p { color: red; }"` with `AbdStlX` being the generated class name.
609
-
610
- ### Concise Style Strings
611
-
612
- Concise style strings use two syntaxes (same as inline CSS in [A](#a)):
613
- - **Short form** `key:value` (no space after colon): The value ends at the next whitespace.
614
- Example: `'m:$3 bg:red r:8px'`
615
- - **Long form** `key: value;` (space after colon): The value continues until a semicolon.
616
- Example: `'box-shadow: 2px 0 6px black; transition: all 0.3s ease;'`
617
-
618
- Both forms can be mixed: `'m:$3 box-shadow: 0 2px 4px rgba(0,0,0,0.2); bg:$cardBg'`
619
-
620
- Supports the same CSS shortcuts as [A](#a) and CSS variable references with `$` (e.g., `$primary`, `$3`).
621
-
622
- Inserts CSS rules into the document, scoping them with a unique class name.
623
-
624
- The `style` parameter can be either:
625
- - A **concise style string** (for rules applying to the root class).
626
- - An **object** where keys are selectors (with `&` representing the root class)
627
- and values are concise style strings or nested objects. When the key does not contain `&`,
628
- it is treated as a descendant selector. So `{p: "color:red"}` becomes `".AbdStlX p { color: red; }"` with `AbdStlX` being the generated class name.
629
-
630
- ### Concise Style Strings
631
-
632
- Concise style strings use two syntaxes (same as inline CSS in [A](#a)):
633
- - **Short form** `key:value` (no space after colon): The value ends at the next whitespace.
634
- Example: `'m:$3 bg:red r:8px'`
635
- - **Long form** `key: value;` (space after colon): The value continues until a semicolon.
636
- Example: `'box-shadow: 2px 0 6px black; transition: all 0.3s ease;'`
637
-
638
- Both forms can be mixed: `'m:$3 box-shadow: 0 2px 4px rgba(0,0,0,0.2); bg:$cardBg'`
639
-
640
- Supports the same CSS shortcuts as [A](#a) and CSS variable references with `$` (e.g., `$primary`, `$3`).
641
-
642
- ###### Parameters
643
-
644
- ###### style
645
-
646
- A concise style string or a style object.
647
-
648
- `string` | `object`
649
-
650
- ###### Returns
651
-
652
- `string`
653
-
654
- The unique class name prefix used for scoping (e.g., `.AbdStl1`).
655
- Use this prefix with [A](#a) to apply the styles.
656
-
657
- ###### Examples
658
-
659
- ```typescript
660
- const cardClass = A.insertCss({
661
- '&': 'bg:white p:$4 r:8px transition: background-color 0.3s;',
662
- '&:hover': 'bg:#f5f5f5',
663
- });
664
-
665
- A('section', cardClass, () => {
666
- A('p#Card content');
667
- });
668
- ```
669
-
670
- ```typescript
671
- const formClass = A.insertCss({
672
- '&': 'bg:#0004 p:$3 r:$2',
673
- button: {
674
- '&': 'bg:$primary fg:white p:$2 r:4px cursor:pointer',
675
- '&:hover': 'bg:$primaryHover',
676
- '&:disabled': 'bg:#ccc cursor:not-allowed',
677
- '.icon': 'display:inline-block mr:$1',
678
- '@media (max-width: 600px)': 'p:$1 font-size:14px'
679
- }
680
- });
681
-
682
- A('form', formClass, () => {
683
- A('button', () => {
684
- A('span.icon text=🔥');
685
- A('#Click Me');
686
- });
687
- });
688
- ```
689
-
690
- ```typescript
691
- const badge = A.insertCss({
692
- '&::before': 'content: "★"; color:gold mr:$1',
693
- '&': 'position:relative box-shadow: 0 2px 8px rgba(0,0,0,0.15);'
694
- });
695
-
696
- A(badge + ' span#Product Name');
697
- ```
698
-
699
- ###### Returns
700
-
701
- The unique class name prefix used for scoping (e.g., `.AbdStl1`).
702
- Use this prefix with [A](#a) to apply the styles.
703
-
704
- ##### insertGlobalCss()
705
-
706
- > **insertGlobalCss**: (`style`) => `void`
707
-
708
- Inserts CSS rules globally (unscoped).
709
-
710
- Works exactly like [insertCss](#insertcss), but without prefixing selectors with a unique class name.
711
- This is useful for global resets, base styles, or styles that need to apply to the entire document.
712
-
713
- Accepts the same concise style string syntax and CSS shortcuts as [insertCss](#insertcss).
714
- See [insertCss](#insertcss) for detailed documentation on syntax and shortcuts.
715
-
716
- Inserts CSS rules globally (unscoped).
717
-
718
- Works exactly like [insertCss](#insertcss), but without prefixing selectors with a unique class name.
719
- This is useful for global resets, base styles, or styles that need to apply to the entire document.
720
-
721
- Accepts the same concise style string syntax and CSS shortcuts as [insertCss](#insertcss).
722
- See [insertCss](#insertcss) for detailed documentation on syntax and shortcuts.
723
-
724
- ###### Parameters
725
-
726
- ###### style
727
-
728
- `object`
729
-
730
- Object with selectors as keys and concise CSS strings as values.
731
-
732
- ###### Returns
733
-
734
- `void`
735
-
736
- ###### Examples
737
-
738
- ```typescript
739
- // Set up global styles using CSS shortcuts
740
- A.insertGlobalCss({
741
- "*": "m:0 p:0 box-sizing:border-box",
742
- "body": "font-family: system-ui, sans-serif; m:0 p:$3 bg:#434 fg:#d0dafa",
743
- "a": "text-decoration:none fg:#57f",
744
- "a:hover": "text-decoration:underline",
745
- "code": "font-family:monospace bg:#222 fg:#afc p:4px r:3px"
746
- });
747
-
748
- A('h2#Title without margins');
749
- A('a#This is a link');
750
- A('code#const x = 42;');
751
- ```
752
-
753
- ```typescript
754
- A.insertGlobalCss({
755
- "html": "font-size:16px",
756
- "body": "line-height:1.6",
757
- "h1, h2, h3": "font-weight:600 mt:$4 mb:$2",
758
- "@media (max-width: 768px)": {
759
- "html": "font-size:14px",
760
- "body": "p:$2"
761
- },
762
- "@media (prefers-color-scheme: dark)": {
763
- "body": "bg:#1a1a1a fg:#e5e5e5",
764
- "code": "bg:#2a2a2a"
765
- }
766
- });
767
- ```
768
- At-rules such as `@media` and `@keyframes` should use nested objects. For keyframes,
769
- the step selectors (`0%`, `50%`, `100%`, etc.) become the nested keys and each value
770
- should be a concise CSS declaration string.
771
-
772
- ```typescript
773
- A.insertGlobalCss({
774
- "@keyframes connection-pulse": {
775
- "0%": "box-shadow: inset 0 0 0 0 rgba(255, 70, 70, 0.4);",
776
- "50%": "box-shadow: inset 0 0 0 6px rgba(255, 70, 70, 0.08);",
777
- "100%": "box-shadow: inset 0 0 0 0 rgba(255, 70, 70, 0.4);"
778
- }
779
- });
780
- ```
781
-
782
- ##### invertString()
783
-
784
- > **invertString**: (`input`) => `string`
785
-
786
- Creates a new string that has the opposite sort order compared to the input string.
787
-
788
- This is achieved by flipping the bits of each character code in the input string.
789
- The resulting string is intended for use as a sort key, particularly with the
790
- `makeKey` function in [onEach](#oneach), to achieve a descending sort order.
791
-
792
- **Warning:** The output string will likely contain non-printable characters or
793
- appear as gibberish and should not be displayed to the user.
794
-
795
- Creates a new string that has the opposite sort order compared to the input string.
796
-
797
- This is achieved by flipping the bits of each character code in the input string.
798
- The resulting string is intended for use as a sort key, particularly with the
799
- `makeKey` function in [onEach](#oneach), to achieve a descending sort order.
800
-
801
- **Warning:** The output string will likely contain non-printable characters or
802
- appear as gibberish and should not be displayed to the user.
803
-
804
- ###### Parameters
805
-
806
- ###### input
807
-
808
- `string`
809
-
810
- The string whose sort order needs to be inverted.
811
-
812
- ###### Returns
813
-
814
- `string`
815
-
816
- A new string that will sort in the reverse order of the input string.
817
-
818
- ###### Example
819
-
820
- ```typescript
821
- const $users = A.proxy([
822
- { id: 1, name: 'Charlie', score: 95 },
823
- { id: 2, name: 'Alice', score: 100 },
824
- { id: 3, name: 'Bob', score: 90 },
825
- ]);
826
-
827
- A.onEach($users, ($user) => {
828
- A(`p#${$user.name}: ${$user.score}`);
829
- }, ($user) => A.invertString($user.name)); // Reverse alphabetic order
830
- ```
831
-
832
- ###### See
833
-
834
- [onEach](#oneach) for usage with sorting.
835
-
836
- ###### Returns
837
-
838
- A new string that will sort in the reverse order of the input string.
839
-
840
- ##### isEmpty()
841
-
842
- > **isEmpty**: (`proxied`) => `boolean`
843
-
844
- Reactively checks if an observable array, object, Map, or Set is empty.
845
-
846
- This function not only returns the current emptiness state but also establishes
847
- a reactive dependency. If the emptiness state of the `proxied` object or array
848
- changes later (e.g., an item is added to an empty array, or the last property
849
- is deleted from an object), the scope that called `isEmpty` will be automatically
850
- scheduled for re-evaluation.
851
-
852
- Reactively checks if an observable array, object, Map, or Set is empty.
853
-
854
- This function not only returns the current emptiness state but also establishes
855
- a reactive dependency. If the emptiness state of the `proxied` object or array
856
- changes later (e.g., an item is added to an empty array, or the last property
857
- is deleted from an object), the scope that called `isEmpty` will be automatically
858
- scheduled for re-evaluation.
859
-
860
- ###### Parameters
861
-
862
- ###### proxied
863
-
864
- `TargetType`
865
-
866
- The observable array, object, Map, or Set to check.
867
-
868
- ###### Returns
869
-
870
- `boolean`
871
-
872
- `true` if the array has length 0, the Map/Set has size 0, or the object has no own enumerable properties, `false` otherwise.
873
-
874
- ###### Example
875
-
876
- ```typescript
877
- const $items = A.proxy([]);
878
-
879
- // Reactively display a message if the items array is empty
880
- A('div', () => {
881
- if (A.isEmpty($items)) {
882
- A('p i#No items yet!');
883
- } else {
884
- A.onEach($items, item => A('p#'+item));
885
- }
886
- });
887
-
888
- // Adding an item will automatically remove the "No items yet!" message
889
- setInterval(() => {
890
- if (!$items.length || Math.random()>0.5) $items.push('Item');
891
- else $items.length = 0;
892
- }, 1000)
893
- ```
894
-
895
- ###### Returns
896
-
897
- `true` if the array has length 0, the Map/Set has size 0, or the object has no own enumerable properties, `false` otherwise.
898
-
899
- ##### map()
900
-
901
- > **map**: \{\<`K`, `IN`, `OUT`\>(`source`, `func`): `Map`\<`K`, `OUT`\>; \<`IN`, `OUT`\>(`source`, `func`): `OUT`[]; \<`IN`, `IN_KEY`, `OUT`\>(`source`, `func`): `Record`\<`string` \| `symbol`, `OUT`\>; \}
902
-
903
- Reactively maps/filters items from a proxied source array or object to a new proxied array or object.
904
-
905
- It iterates over the `target` proxy. For each item, it calls `func`.
906
- - If `func` returns a value, it's added to the result proxy under the same key/index.
907
- - If `func` returns `undefined`, the item is skipped (filtered out).
908
-
909
- The returned proxy automatically updates when:
910
- - Items are added/removed/updated in the `target` proxy.
911
- - Any proxied data read *within* the `func` call changes (for a specific item).
912
-
913
- ###### Call Signature
914
-
915
- > \<`K`, `IN`, `OUT`\>(`source`, `func`): `Map`\<`K`, `OUT`\>
916
-
917
- When using a Map as `source`.
918
-
919
- ###### Type Parameters
920
-
921
- ###### K
922
-
923
- `K`
924
-
925
- ###### IN
926
-
927
- `IN`
928
-
929
- ###### OUT
930
-
931
- `OUT`
932
-
933
- ###### Parameters
934
-
935
- ###### source
936
-
937
- `Map`\<`K`, `IN`\>
938
-
939
- ###### func
940
-
941
- (`value`, `key`) => `undefined` \| `OUT`
942
-
943
- ###### Returns
944
-
945
- `Map`\<`K`, `OUT`\>
946
-
947
- ###### Call Signature
948
-
949
- > \<`IN`, `OUT`\>(`source`, `func`): `OUT`[]
950
-
951
- When using an array as `source`.
952
-
953
- ###### Type Parameters
954
-
955
- ###### IN
956
-
957
- `IN`
958
-
959
- ###### OUT
960
-
961
- `OUT`
962
-
963
- ###### Parameters
964
-
965
- ###### source
966
-
967
- `IN`[]
968
-
969
- ###### func
970
-
971
- (`value`, `index`) => `undefined` \| `OUT`
972
-
973
- ###### Returns
974
-
975
- `OUT`[]
976
-
977
- ###### Call Signature
978
-
979
- > \<`IN`, `IN_KEY`, `OUT`\>(`source`, `func`): `Record`\<`string` \| `symbol`, `OUT`\>
980
-
981
- When using an object as `source`.
982
-
983
- ###### Type Parameters
984
-
985
- ###### IN
986
-
987
- `IN`
988
-
989
- ###### IN_KEY
990
-
991
- `IN_KEY` *extends* `string` \| `number` \| `symbol`
992
-
993
- ###### OUT
994
-
995
- `OUT`
996
-
997
- ###### Parameters
998
-
999
- ###### source
1000
-
1001
- `Record`\<`IN_KEY`, `IN`\>
1002
-
1003
- ###### func
1004
-
1005
- (`value`, `index`) => `undefined` \| `OUT`
1006
-
1007
- ###### Returns
1008
-
1009
- `Record`\<`string` \| `symbol`, `OUT`\>
1010
-
1011
- ###### Returns
1012
-
1013
- A new proxied array or object containing the mapped values.
1014
-
1015
- ##### merge()
1016
-
1017
- > **merge**: \{\<`T`\>(`dst`, `value`): `boolean`; \<`T`\>(`dst`, `dstKey`, `value`): `boolean`; \}
1018
-
1019
- Like [copy](#copy), but uses merge semantics. Properties in `dst` not present in `src` are kept.
1020
- `null`/`undefined` in `src` delete properties in `dst`.
1021
-
1022
- ###### Call Signature
1023
-
1024
- > \<`T`\>(`dst`, `value`): `boolean`
1025
-
1026
- Like [copy](#copy), but uses merge semantics. Properties in `dst` not present in `src` are kept.
1027
- `null`/`undefined` in `src` delete properties in `dst`.
1028
-
1029
- ###### Type Parameters
1030
-
1031
- ###### T
1032
-
1033
- `T` *extends* `object`
1034
-
1035
- ###### Parameters
1036
-
1037
- ###### dst
1038
-
1039
- `T`
1040
-
1041
- ###### value
1042
-
1043
- `Partial`\<`T`\>
1044
-
1045
- ###### Returns
1046
-
1047
- `boolean`
1048
-
1049
- ###### Example
1050
-
1051
- ```typescript
1052
- const source = { b: { c: 99 }, d: undefined }; // d: undefined will delete
1053
- const $dest = A.proxy({ a: 1, b: { x: 5 }, d: 4 });
1054
- A.merge($dest, source);
1055
- A.merge($dest, 'b', { y: 6 }); // merge into $dest.b
1056
- A.merge($dest, 'c', { z: 7 }); // $dest.c doesn't exist yet, so it will just be assigned
1057
- console.log($dest); // proxy({ a: 1, b: { c: 99, x: 5, y: 6 }, c: { z: 7 } })
1058
- ```
1059
-
1060
- ###### Call Signature
1061
-
1062
- > \<`T`\>(`dst`, `dstKey`, `value`): `boolean`
1063
-
1064
- Like [copy](#copy), but uses merge semantics. Properties in `dst` not present in `src` are kept.
1065
- `null`/`undefined` in `src` delete properties in `dst`.
1066
-
1067
- ###### Type Parameters
1068
-
1069
- ###### T
1070
-
1071
- `T` *extends* `object`
1072
-
1073
- ###### Parameters
1074
-
1075
- ###### dst
1076
-
1077
- `T`
1078
-
1079
- ###### dstKey
1080
-
1081
- keyof `T`
1082
-
1083
- ###### value
1084
-
1085
- `Partial`\<`T`\[keyof `T`\]\>
1086
-
1087
- ###### Returns
1088
-
1089
- `boolean`
1090
-
1091
- ###### Example
1092
-
1093
- ```typescript
1094
- const source = { b: { c: 99 }, d: undefined }; // d: undefined will delete
1095
- const $dest = A.proxy({ a: 1, b: { x: 5 }, d: 4 });
1096
- A.merge($dest, source);
1097
- A.merge($dest, 'b', { y: 6 }); // merge into $dest.b
1098
- A.merge($dest, 'c', { z: 7 }); // $dest.c doesn't exist yet, so it will just be assigned
1099
- console.log($dest); // proxy({ a: 1, b: { c: 99, x: 5, y: 6 }, c: { z: 7 } })
1100
- ```
1101
-
1102
- ##### mount()
1103
-
1104
- > **mount**: (`parentElement`, `func`) => `void`
1105
-
1106
- Attaches a reactive Aberdeen UI fragment to an existing DOM element. Without the use of
1107
- this function, [A](#a) will assume `document.body` as its root.
1108
-
1109
- It creates a top-level reactive scope associated with the `parentElement`. The provided
1110
- function `func` is executed immediately within this scope. Any proxied data read by `func`
1111
- will cause it to re-execute when the data changes, updating the DOM elements created within it.
1112
-
1113
- Calls to [A](#a) inside `func` will append nodes to `parentElement`.
1114
- You can nest [derive](#derive) or other [A](#a) scopes within `func`.
1115
- Use [unmountAll](#unmountall) to clean up all mounted scopes and their DOM nodes.
1116
-
1117
- Mounting scopes happens reactively, meaning that if this function is called from within another
1118
- ([derive](#derive) or [A](#a) or [mount](#mount)) scope that gets cleaned up, so will the mount.
1119
-
1120
- Attaches a reactive Aberdeen UI fragment to an existing DOM element. Without the use of
1121
- this function, [A](#a) will assume `document.body` as its root.
1122
-
1123
- It creates a top-level reactive scope associated with the `parentElement`. The provided
1124
- function `func` is executed immediately within this scope. Any proxied data read by `func`
1125
- will cause it to re-execute when the data changes, updating the DOM elements created within it.
1126
-
1127
- Calls to [A](#a) inside `func` will append nodes to `parentElement`.
1128
- You can nest [derive](#derive) or other [A](#a) scopes within `func`.
1129
- Use [unmountAll](#unmountall) to clean up all mounted scopes and their DOM nodes.
1130
-
1131
- Mounting scopes happens reactively, meaning that if this function is called from within another
1132
- ([derive](#derive) or [A](#a) or [mount](#mount)) scope that gets cleaned up, so will the mount.
1133
-
1134
- ###### Parameters
1135
-
1136
- ###### parentElement
1137
-
1138
- `Element`
1139
-
1140
- The native DOM `Element` to which the UI fragment will be appended.
1141
-
1142
- ###### func
1143
-
1144
- () => `void`
1145
-
1146
- The function that defines the UI fragment, typically containing calls to [A](#a).
1147
-
1148
- ###### Returns
1149
-
1150
- `void`
1151
-
1152
- ###### Example
1153
-
1154
- ```javascript
1155
- // Create a pre-existing DOM structure (without Aberdeen)
1156
- document.body.innerHTML = `<h3>Static content <span id="title-extra"></span></h3><div class="box" id="app-root"></div>`;
1157
-
1158
- import A from 'aberdeen';
1159
-
1160
- const $runTime = A.proxy(0);
1161
- setInterval(() => $runTime.value++, 1000);
1162
-
1163
- A.mount(document.getElementById('app-root'), () => {
1164
- A('h4#Aberdeen App');
1165
- A(`p#Run time: ${$runTime.value}s`);
1166
- // Conditionally render some content somewhere else in the static page
1167
- if ($runTime.value&1) {
1168
- A.mount(document.getElementById('title-extra'), () =>
1169
- A(`i#(${$runTime.value}s)`)
1170
- );
1171
- }
1172
- });
1173
- ```
1174
-
1175
- Note how the inner mount behaves reactively as well, automatically unmounting when it's parent observer scope re-runs.
1176
-
1177
- ##### multiMap()
1178
-
1179
- > **multiMap**: \{\<`IN`, `OUT`\>(`source`, `func`): `OUT`; \<`K`, `IN`, `OUT`\>(`source`, `func`): `OUT`; \<`K`, `IN`, `OUT`\>(`source`, `func`): `OUT`; \}
1180
-
1181
- Reactively maps items from a source proxy (array or object) to a target proxied object,
1182
- where each source item can contribute multiple key-value pairs to the target.
1183
-
1184
- It iterates over the `target` proxy. For each item, it calls `func`.
1185
- - If `func` returns an object, all key-value pairs from that object are added to the result proxy.
1186
- - If `func` returns `undefined`, the item contributes nothing.
1187
-
1188
- The returned proxy automatically updates when:
1189
- - Items are added/removed/updated in the `target` proxy.
1190
- - Any proxied data read *within* the `func` call changes (for a specific item).
1191
- - If multiple input items produce the same output key, the last one processed usually "wins",
1192
- but the exact behavior on collision depends on update timing.
1193
-
1194
- This is useful for "flattening" or "indexing" data, or converting an observable array to an observable object.
1195
-
1196
- ###### Call Signature
1197
-
1198
- > \<`IN`, `OUT`\>(`source`, `func`): `OUT`
1199
-
1200
- When using an array as `source`.
1201
-
1202
- ###### Type Parameters
1203
-
1204
- ###### IN
1205
-
1206
- `IN`
1207
-
1208
- ###### OUT
1209
-
1210
- `OUT` *extends* `object`
1211
-
1212
- ###### Parameters
1213
-
1214
- ###### source
1215
-
1216
- `IN`[]
1217
-
1218
- ###### func
1219
-
1220
- (`value`, `index`) => `undefined` \| `OUT`
1221
-
1222
- ###### Returns
1223
-
1224
- `OUT`
1225
-
1226
- ###### Call Signature
1227
-
1228
- > \<`K`, `IN`, `OUT`\>(`source`, `func`): `OUT`
1229
-
1230
- When using an object as `source`.
1231
-
1232
- ###### Type Parameters
1233
-
1234
- ###### K
1235
-
1236
- `K` *extends* `string` \| `number` \| `symbol`
1237
-
1238
- ###### IN
1239
-
1240
- `IN`
1241
-
1242
- ###### OUT
1243
-
1244
- `OUT` *extends* `object`
1245
-
1246
- ###### Parameters
1247
-
1248
- ###### source
1249
-
1250
- `Record`\<`K`, `IN`\>
1251
-
1252
- ###### func
1253
-
1254
- (`value`, `index`) => `undefined` \| `OUT`
1255
-
1256
- ###### Returns
1257
-
1258
- `OUT`
1259
-
1260
- ###### Call Signature
1261
-
1262
- > \<`K`, `IN`, `OUT`\>(`source`, `func`): `OUT`
1263
-
1264
- When using a Map as `source`.
1265
-
1266
- ###### Type Parameters
1267
-
1268
- ###### K
1269
-
1270
- `K`
1271
-
1272
- ###### IN
1273
-
1274
- `IN`
1275
-
1276
- ###### OUT
1277
-
1278
- `OUT` *extends* `object`
1279
-
1280
- ###### Parameters
1281
-
1282
- ###### source
1283
-
1284
- `Map`\<`K`, `IN`\>
1285
-
1286
- ###### func
1287
-
1288
- (`value`, `key`) => `undefined` \| `OUT`
1289
-
1290
- ###### Returns
1291
-
1292
- `OUT`
1293
-
1294
- ###### Returns
1295
-
1296
- A new proxied object containing the aggregated key-value pairs.
1297
-
1298
- ##### NO\_COPY
1299
-
1300
- > **NO\_COPY**: `symbol`
1301
-
1302
- Use [OPAQUE](#opaque) instead. This is an alias kept for backward compatibility.
1303
-
1304
- ##### onEach()
1305
-
1306
- > **onEach**: \{\<`K`, `T`\>(`target`, `render`, `makeKey?`): `void`; \<`T`\>(`target`, `render`, `makeKey?`): `void`; \<`T`\>(`target`, `render`, `makeKey?`): `void`; \<`K`, `T`\>(`target`, `render`, `makeKey?`): `void`; \}
1307
-
1308
- Reactively iterates over the items of an observable array, object, Map, or Set, optionally rendering content for each item.
1309
-
1310
- Automatically updates when items are added, removed, or modified.
1311
-
1312
- ###### Call Signature
1313
-
1314
- > \<`K`, `T`\>(`target`, `render`, `makeKey?`): `void`
1315
-
1316
- ###### Type Parameters
1317
-
1318
- ###### K
1319
-
1320
- `K`
1321
-
1322
- ###### T
1323
-
1324
- `T`
1325
-
1326
- ###### Parameters
1327
-
1328
- ###### target
1329
-
1330
- `Map`\<`K`, `undefined` \| `T`\>
1331
-
1332
- ###### render
1333
-
1334
- (`value`, `key`) => `void`
1335
-
1336
- ###### makeKey?
1337
-
1338
- (`value`, `key`) => `SortKeyType`
1339
-
1340
- ###### Returns
1341
-
1342
- `void`
1343
-
1344
- ###### Call Signature
1345
-
1346
- > \<`T`\>(`target`, `render`, `makeKey?`): `void`
1347
-
1348
- ###### Type Parameters
1349
-
1350
- ###### T
1351
-
1352
- `T`
1353
-
1354
- ###### Parameters
1355
-
1356
- ###### target
1357
-
1358
- `Set`\<`T`\>
1359
-
1360
- ###### render
1361
-
1362
- (`value`) => `void`
1363
-
1364
- ###### makeKey?
1365
-
1366
- (`value`) => `SortKeyType`
1367
-
1368
- ###### Returns
1369
-
1370
- `void`
1371
-
1372
- ###### Call Signature
1373
-
1374
- > \<`T`\>(`target`, `render`, `makeKey?`): `void`
1375
-
1376
- ###### Type Parameters
1377
-
1378
- ###### T
1379
-
1380
- `T`
1381
-
1382
- ###### Parameters
1383
-
1384
- ###### target
1385
-
1386
- readonly (`undefined` \| `T`)[]
1387
-
1388
- ###### render
1389
-
1390
- (`value`, `index`) => `void`
1391
-
1392
- ###### makeKey?
1393
-
1394
- (`value`, `index`) => `SortKeyType`
1395
-
1396
- ###### Returns
1397
-
1398
- `void`
1399
-
1400
- ###### Call Signature
1401
-
1402
- > \<`K`, `T`\>(`target`, `render`, `makeKey?`): `void`
1403
-
1404
- ###### Type Parameters
1405
-
1406
- ###### K
1407
-
1408
- `K` *extends* `string` \| `number` \| `symbol`
1409
-
1410
- ###### T
1411
-
1412
- `T`
1413
-
1414
- ###### Parameters
1415
-
1416
- ###### target
1417
-
1418
- `Record`\<`K`, `undefined` \| `T`\>
1419
-
1420
- ###### render
1421
-
1422
- (`value`, `index`) => `void`
1423
-
1424
- ###### makeKey?
1425
-
1426
- (`value`, `index`) => `SortKeyType`
1427
-
1428
- ###### Returns
1429
-
1430
- `void`
1431
-
1432
- ##### OPAQUE
1433
-
1434
- > **OPAQUE**: `symbol`
1435
-
1436
- A symbol that controls how Aberdeen handles an object in copy operations and proxy wrapping.
1437
-
1438
- The **presence** of this symbol (regardless of its value) prevents deep-copying: the object is
1439
- stored and passed by reference in [clone](#clone) and [copy](#copy).
1440
-
1441
- The **value** of the symbol controls proxy wrapping when the object is read from reactive state:
1442
- - **Truthy** (e.g. `true`): the object is fully opaque — it is not wrapped in a proxy, so its
1443
- properties are not observable. Use this for objects that break when proxied (e.g. class instances
1444
- with internal slots, Promises) or that must be invisible to Aberdeen's reactive system.
1445
- - **Falsy** (e.g. `false`): the object is still wrapped in a proxy, so reads on its properties
1446
- create reactive dependencies as normal — only deep-copying is suppressed.
1447
-
1448
- ##### partition()
1449
-
1450
- > **partition**: \{\<`OUT_K`, `IN_V`\>(`source`, `func`): `Record`\<`OUT_K`, `Record`\<`number`, `IN_V`\>\>; \<`IN_K`, `OUT_K`, `IN_V`\>(`source`, `func`): `Record`\<`OUT_K`, `Record`\<`IN_K`, `IN_V`\>\>; \<`IN_K`, `OUT_K`, `IN_V`\>(`source`, `func`): `Record`\<`OUT_K`, `Record`\<`IN_K`, `IN_V`\>\>; \}
1451
-
1452
- Reactively partitions items from a source proxy (array or object) into multiple "bucket" proxies
1453
- based on keys determined by a classifier function.
1454
-
1455
- This function iterates through the `source` proxy using [onEach](#oneach). For each item,
1456
- it calls the classifier `func`, which should return:
1457
- - A single key (`OUT_K`): The item belongs to the bucket with this key.
1458
- - An array of keys (`OUT_K[]`): The item belongs to all buckets specified in the array.
1459
- - `undefined`: The item is not placed in any bucket.
1460
-
1461
- The function returns a main proxied object. The keys of this object are the bucket keys (`OUT_K`)
1462
- returned by `func`. Each value associated with a bucket key is another proxied object (the "bucket").
1463
- This inner bucket object maps the *original* keys/indices from the `source` to the items
1464
- themselves that were classified into that bucket.
1465
-
1466
- The entire structure is reactive. Changes in the `source` proxy (adding/removing/updating items)
1467
- or changes in dependencies read by the `func` will cause the output partitioning to update automatically.
1468
- Buckets are created dynamically as needed and removed when they become empty.
1469
-
1470
- ###### Call Signature
1471
-
1472
- > \<`OUT_K`, `IN_V`\>(`source`, `func`): `Record`\<`OUT_K`, `Record`\<`number`, `IN_V`\>\>
1473
-
1474
- When using an object as `array`.
1475
-
1476
- ###### Type Parameters
1477
-
1478
- ###### OUT_K
1479
-
1480
- `OUT_K` *extends* `string` \| `number` \| `symbol`
1481
-
1482
- ###### IN_V
1483
-
1484
- `IN_V`
1485
-
1486
- ###### Parameters
1487
-
1488
- ###### source
1489
-
1490
- `IN_V`[]
1491
-
1492
- ###### func
1493
-
1494
- (`value`, `key`) => `undefined` \| `OUT_K` \| `OUT_K`[]
1495
-
1496
- ###### Returns
1497
-
1498
- `Record`\<`OUT_K`, `Record`\<`number`, `IN_V`\>\>
1499
-
1500
- ###### Call Signature
1501
-
1502
- > \<`IN_K`, `OUT_K`, `IN_V`\>(`source`, `func`): `Record`\<`OUT_K`, `Record`\<`IN_K`, `IN_V`\>\>
1503
-
1504
- When using an object as `source`.
1505
-
1506
- ###### Type Parameters
1507
-
1508
- ###### IN_K
1509
-
1510
- `IN_K` *extends* `string` \| `number` \| `symbol`
1511
-
1512
- ###### OUT_K
1513
-
1514
- `OUT_K` *extends* `string` \| `number` \| `symbol`
1515
-
1516
- ###### IN_V
1517
-
1518
- `IN_V`
1519
-
1520
- ###### Parameters
1521
-
1522
- ###### source
1523
-
1524
- `Record`\<`IN_K`, `IN_V`\>
1525
-
1526
- ###### func
1527
-
1528
- (`value`, `key`) => `undefined` \| `OUT_K` \| `OUT_K`[]
1529
-
1530
- ###### Returns
1531
-
1532
- `Record`\<`OUT_K`, `Record`\<`IN_K`, `IN_V`\>\>
1533
-
1534
- ###### Call Signature
1535
-
1536
- > \<`IN_K`, `OUT_K`, `IN_V`\>(`source`, `func`): `Record`\<`OUT_K`, `Record`\<`IN_K`, `IN_V`\>\>
1537
-
1538
- When using a Map as `source`.
1539
-
1540
- ###### Type Parameters
1541
-
1542
- ###### IN_K
1543
-
1544
- `IN_K` *extends* `string` \| `number` \| `symbol`
1545
-
1546
- ###### OUT_K
1547
-
1548
- `OUT_K` *extends* `string` \| `number` \| `symbol`
1549
-
1550
- ###### IN_V
1551
-
1552
- `IN_V`
1553
-
1554
- ###### Parameters
1555
-
1556
- ###### source
1557
-
1558
- `Map`\<`IN_K`, `IN_V`\>
1559
-
1560
- ###### func
1561
-
1562
- (`value`, `key`) => `undefined` \| `OUT_K` \| `OUT_K`[]
1563
-
1564
- ###### Returns
1565
-
1566
- `Record`\<`OUT_K`, `Record`\<`IN_K`, `IN_V`\>\>
1567
-
1568
- ###### Returns
1569
-
1570
- A proxied object where keys are the bucket identifiers (`OUT_K`) and values are proxied Records
1571
- (`Record<IN_K | number, IN_V>`) representing the buckets. Each bucket maps original source keys/indices
1572
- to the items belonging to that bucket.
1573
-
1574
- ##### peek()
1575
-
1576
- > **peek**: \{\<`T`, `K`\>(`target`, `key`): `T`\[`K`\]; \<`K`, `V`\>(`target`, `key`): `undefined` \| `V`; \<`T`\>(`target`, `key`): `undefined` \| `T`; \<`T`\>(`target`): `T`; \}
1577
-
1578
- Executes a function or retrieves a value *without* creating subscriptions in the current reactive scope, and returns its result.
1579
-
1580
- This is useful when you need to access reactive data inside a reactive scope (like [A](#a))
1581
- but do not want changes to that specific data to trigger a re-execute of the scope.
1582
-
1583
- Note: You may also use [unproxy](#unproxy) to get to the raw underlying data structure, which can be used to similar effect.
1584
-
1585
- ###### Call Signature
1586
-
1587
- > \<`T`, `K`\>(`target`, `key`): `T`\[`K`\]
1588
-
1589
- Executes a function or retrieves a value *without* creating subscriptions in the current reactive scope, and returns its result.
1590
-
1591
- This is useful when you need to access reactive data inside a reactive scope (like [A](#a))
1592
- but do not want changes to that specific data to trigger a re-execute of the scope.
1593
-
1594
- Note: You may also use [unproxy](#unproxy) to get to the raw underlying data structure, which can be used to similar effect.
1595
-
1596
- ###### Type Parameters
1597
-
1598
- ###### T
1599
-
1600
- `T` *extends* `object`
1601
-
1602
- ###### K
1603
-
1604
- `K` *extends* `string` \| `number` \| `symbol`
1605
-
1606
- ###### Parameters
1607
-
1608
- ###### target
1609
-
1610
- `T`
1611
-
1612
- Either a function to execute, or an object (which may also be an Array or a Map) to index.
1613
-
1614
- ###### key
1615
-
1616
- `K`
1617
-
1618
- Optional key/index to use when `target` is an object.
1619
-
1620
- ###### Returns
1621
-
1622
- `T`\[`K`\]
1623
-
1624
- The result of the function call, or the value at `target[key]` when `target` is an object or `target.get(key)` when it's a Map.
1625
-
1626
- ###### Example
1627
-
1628
- ```typescript
1629
- const $data = A.proxy({ a: 1, b: 2 });
1630
- A(() => {
1631
- // re-executes only when $data.a changes, because $data.b is peeked.
1632
- const b = A.peek(() => $data.b);
1633
- console.log(`A is ${$data.a}, B was ${b} when A changed.`);
1634
- });
1635
- $data.b = 3; // Does not trigger console.log
1636
- $data.a = 2; // Triggers console.log (logs "A is 2, B was 3 when A changed.")
1637
- ```
1638
-
1639
- ###### Call Signature
1640
-
1641
- > \<`K`, `V`\>(`target`, `key`): `undefined` \| `V`
1642
-
1643
- Executes a function or retrieves a value *without* creating subscriptions in the current reactive scope, and returns its result.
1644
-
1645
- This is useful when you need to access reactive data inside a reactive scope (like [A](#a))
1646
- but do not want changes to that specific data to trigger a re-execute of the scope.
1647
-
1648
- Note: You may also use [unproxy](#unproxy) to get to the raw underlying data structure, which can be used to similar effect.
1649
-
1650
- ###### Type Parameters
1651
-
1652
- ###### K
1653
-
1654
- `K`
1655
-
1656
- ###### V
1657
-
1658
- `V`
1659
-
1660
- ###### Parameters
1661
-
1662
- ###### target
1663
-
1664
- `Map`\<`K`, `V`\>
1665
-
1666
- Either a function to execute, or an object (which may also be an Array or a Map) to index.
1667
-
1668
- ###### key
1669
-
1670
- `K`
1671
-
1672
- Optional key/index to use when `target` is an object.
1673
-
1674
- ###### Returns
1675
-
1676
- `undefined` \| `V`
1677
-
1678
- The result of the function call, or the value at `target[key]` when `target` is an object or `target.get(key)` when it's a Map.
1679
-
1680
- ###### Example
1681
-
1682
- ```typescript
1683
- const $data = A.proxy({ a: 1, b: 2 });
1684
- A(() => {
1685
- // re-executes only when $data.a changes, because $data.b is peeked.
1686
- const b = A.peek(() => $data.b);
1687
- console.log(`A is ${$data.a}, B was ${b} when A changed.`);
1688
- });
1689
- $data.b = 3; // Does not trigger console.log
1690
- $data.a = 2; // Triggers console.log (logs "A is 2, B was 3 when A changed.")
1691
- ```
1692
-
1693
- ###### Call Signature
1694
-
1695
- > \<`T`\>(`target`, `key`): `undefined` \| `T`
1696
-
1697
- Executes a function or retrieves a value *without* creating subscriptions in the current reactive scope, and returns its result.
1698
-
1699
- This is useful when you need to access reactive data inside a reactive scope (like [A](#a))
1700
- but do not want changes to that specific data to trigger a re-execute of the scope.
1701
-
1702
- Note: You may also use [unproxy](#unproxy) to get to the raw underlying data structure, which can be used to similar effect.
1703
-
1704
- ###### Type Parameters
1705
-
1706
- ###### T
1707
-
1708
- `T`
1709
-
1710
- ###### Parameters
1711
-
1712
- ###### target
1713
-
1714
- `T`[]
1715
-
1716
- Either a function to execute, or an object (which may also be an Array or a Map) to index.
1717
-
1718
- ###### key
1719
-
1720
- `number`
1721
-
1722
- Optional key/index to use when `target` is an object.
1723
-
1724
- ###### Returns
1725
-
1726
- `undefined` \| `T`
1727
-
1728
- The result of the function call, or the value at `target[key]` when `target` is an object or `target.get(key)` when it's a Map.
1729
-
1730
- ###### Example
1731
-
1732
- ```typescript
1733
- const $data = A.proxy({ a: 1, b: 2 });
1734
- A(() => {
1735
- // re-executes only when $data.a changes, because $data.b is peeked.
1736
- const b = A.peek(() => $data.b);
1737
- console.log(`A is ${$data.a}, B was ${b} when A changed.`);
1738
- });
1739
- $data.b = 3; // Does not trigger console.log
1740
- $data.a = 2; // Triggers console.log (logs "A is 2, B was 3 when A changed.")
1741
- ```
1742
-
1743
- ###### Call Signature
1744
-
1745
- > \<`T`\>(`target`): `T`
1746
-
1747
- Executes a function or retrieves a value *without* creating subscriptions in the current reactive scope, and returns its result.
1748
-
1749
- This is useful when you need to access reactive data inside a reactive scope (like [A](#a))
1750
- but do not want changes to that specific data to trigger a re-execute of the scope.
1751
-
1752
- Note: You may also use [unproxy](#unproxy) to get to the raw underlying data structure, which can be used to similar effect.
1753
-
1754
- ###### Type Parameters
1755
-
1756
- ###### T
1757
-
1758
- `T`
1759
-
1760
- ###### Parameters
1761
-
1762
- ###### target
1763
-
1764
- () => `T`
1765
-
1766
- Either a function to execute, or an object (which may also be an Array or a Map) to index.
1767
-
1768
- ###### Returns
1769
-
1770
- `T`
1771
-
1772
- The result of the function call, or the value at `target[key]` when `target` is an object or `target.get(key)` when it's a Map.
1773
-
1774
- ###### Example
1775
-
1776
- ```typescript
1777
- const $data = A.proxy({ a: 1, b: 2 });
1778
- A(() => {
1779
- // re-executes only when $data.a changes, because $data.b is peeked.
1780
- const b = A.peek(() => $data.b);
1781
- console.log(`A is ${$data.a}, B was ${b} when A changed.`);
1782
- });
1783
- $data.b = 3; // Does not trigger console.log
1784
- $data.a = 2; // Triggers console.log (logs "A is 2, B was 3 when A changed.")
1785
- ```
1786
-
1787
- ###### Returns
1788
-
1789
- The result of the function call, or the value at `target[key]` when `target` is an object or `target.get(key)` when it's a Map.
1790
-
1791
- ##### proxy()
1792
-
1793
- > **proxy**: \{\<`T`\>(`target`): [`PromiseProxy`](#promiseproxy)\<`T`\>; \<`T`\>(`target`): `T` *extends* `number` ? `number` : `T` *extends* `string` ? `string` : `T` *extends* `boolean` ? `boolean` : `T`[]; \<`T`\>(`target`): `T`; \<`T`\>(`target`): `ValueRef`\<`T` *extends* `number` ? `number` : `T` *extends* `string` ? `string` : `T` *extends* `boolean` ? `boolean` : `T`\>; \}
1794
-
1795
- Creates a reactive proxy around the given data.
1796
-
1797
- Reading properties from the returned proxy within a reactive scope (like one created by
1798
- [A](#a) or [derive](#derive)) establishes a subscription. Modifying properties *through*
1799
- the proxy will notify subscribed scopes, causing them to re-execute.
1800
-
1801
- - Plain objects, arrays, Maps, and Sets are wrapped in a standard JavaScript `Proxy` that intercepts
1802
- property access and mutations, but otherwise works like the underlying data.
1803
- - Primitives (string, number, boolean, null, undefined) are wrapped in an object
1804
- `{ value: T }` which is then proxied. Access the primitive via the `.value` property.
1805
- - Promises are represented by proxied objects `{ busy: boolean, value?: T, error?: any }`.
1806
- Initially, `busy` is `true`. When the promise resolves, `value` is set and `busy`
1807
- is set to `false`. If the promise is rejected, `error` is set and `busy` is also
1808
- set to `false`.
1809
-
1810
- Use [unproxy](#unproxy) to get the original underlying data back.
1811
- By convention in the examples below, local variables that hold proxied values are prefixed with `$`.
1812
-
1813
- ###### Call Signature
1814
-
1815
- > \<`T`\>(`target`): [`PromiseProxy`](#promiseproxy)\<`T`\>
1816
-
1817
- ###### Type Parameters
1818
-
1819
- ###### T
1820
-
1821
- `T` *extends* `unknown`
1822
-
1823
- ###### Parameters
1824
-
1825
- ###### target
1826
-
1827
- `Promise`\<`T`\>
1828
-
1829
- ###### Returns
1830
-
1831
- [`PromiseProxy`](#promiseproxy)\<`T`\>
1832
-
1833
- ###### Call Signature
1834
-
1835
- > \<`T`\>(`target`): `T` *extends* `number` ? `number` : `T` *extends* `string` ? `string` : `T` *extends* `boolean` ? `boolean` : `T`[]
1836
-
1837
- ###### Type Parameters
1838
-
1839
- ###### T
1840
-
1841
- `T` *extends* `unknown`
1842
-
1843
- ###### Parameters
1844
-
1845
- ###### target
1846
-
1847
- `T`[]
1848
-
1849
- ###### Returns
1850
-
1851
- `T` *extends* `number` ? `number` : `T` *extends* `string` ? `string` : `T` *extends* `boolean` ? `boolean` : `T`[]
1852
-
1853
- ###### Call Signature
1854
-
1855
- > \<`T`\>(`target`): `T`
1856
-
1857
- ###### Type Parameters
1858
-
1859
- ###### T
1860
-
1861
- `T` *extends* `object`
1862
-
1863
- ###### Parameters
1864
-
1865
- ###### target
1866
-
1867
- `T`
1868
-
1869
- ###### Returns
1870
-
1871
- `T`
1872
-
1873
- ###### Call Signature
1874
-
1875
- > \<`T`\>(`target`): `ValueRef`\<`T` *extends* `number` ? `number` : `T` *extends* `string` ? `string` : `T` *extends* `boolean` ? `boolean` : `T`\>
1876
-
1877
- ###### Type Parameters
1878
-
1879
- ###### T
1880
-
1881
- `T` *extends* `unknown`
1882
-
1883
- ###### Parameters
1884
-
1885
- ###### target
1886
-
1887
- `T`
1888
-
1889
- ###### Returns
1890
-
1891
- `ValueRef`\<`T` *extends* `number` ? `number` : `T` *extends* `string` ? `string` : `T` *extends* `boolean` ? `boolean` : `T`\>
1892
-
1893
- ###### Returns
1894
-
1895
- A reactive proxy wrapping the target data.
1896
-
1897
- ##### ref()
1898
-
1899
- > **ref**: \<`T`, `K`\>(`target`, `index`) => `ValueRef`\<`T`\[`K`\]\>
1900
-
1901
- Creates a reactive reference (`{ value: T }`-like object) to a specific value
1902
- within a proxied object or array.
1903
-
1904
- This is primarily used for the `bind` property in [A](#a) to create two-way data bindings
1905
- with form elements, and for passing a reactive property to any of the [A](#a) key-value pairs.
1906
-
1907
- Reading `ref.value` accesses the property from the underlying proxy (and subscribes the current scope).
1908
- Assigning to `ref.value` updates the property in the underlying proxy (triggering reactive updates).
1909
-
1910
- Creates a reactive reference (`{ value: T }`-like object) to a specific value
1911
- within a proxied object or array.
1912
-
1913
- This is primarily used for the `bind` property in [A](#a) to create two-way data bindings
1914
- with form elements, and for passing a reactive property to any of the [A](#a) key-value pairs.
1915
-
1916
- Reading `ref.value` accesses the property from the underlying proxy (and subscribes the current scope).
1917
- Assigning to `ref.value` updates the property in the underlying proxy (triggering reactive updates).
1918
-
1919
- ###### Type Parameters
1920
-
1921
- ###### T
1922
-
1923
- `T` *extends* `TargetType`
1924
-
1925
- ###### K
1926
-
1927
- `K` *extends* `string` \| `number` \| `symbol`
1928
-
1929
- ###### Parameters
1930
-
1931
- ###### target
1932
-
1933
- `T`
1934
-
1935
- The reactive proxy (created by [proxy](#proxy)) containing the target property.
1936
-
1937
- ###### index
1938
-
1939
- `K`
1940
-
1941
- The key (for objects) or index (for arrays) of the property to reference.
1942
-
1943
- ###### Returns
1944
-
1945
- `ValueRef`\<`T`\[`K`\]\>
1946
-
1947
- A reference object with a `value` property linked to the specified proxy property.
1948
-
1949
- ###### Example
1950
-
1951
- ```javascript
1952
- const $formData = A.proxy({ color: 'orange', velocity: 42 });
1953
-
1954
- // Usage with `bind`
1955
- A('input type=text bind=', A.ref($formData, 'color'));
1956
-
1957
- // Usage as a dynamic property, causes a TextNode with just the name to be created and live-updated
1958
- A('p text="Selected color: " text=', A.ref($formData, 'color'), 'color:', A.ref($formData, 'color'));
1959
-
1960
- // Changes are actually stored in $formData - this causes logs like `{color: "Blue", velocity 42}`
1961
- A(() => console.log($formData))
1962
- ```
1963
-
1964
- ###### Returns
1965
-
1966
- A reference object with a `value` property linked to the specified proxy property.
1967
-
1968
- ##### runQueue()
1969
-
1970
- > **runQueue**: () => `void`
1971
-
1972
- Forces the immediate and synchronous execution of all pending reactive updates.
1973
-
1974
- Normally, changes to observed data sources (like proxied objects or arrays)
1975
- are processed asynchronously in a batch after a brief timeout (0ms). This function
1976
- allows you to bypass the timeout and process the update queue immediately.
1977
-
1978
- This can be useful in specific scenarios where you need the DOM to be updated
1979
- synchronously.
1980
-
1981
- This function is re-entrant, meaning it is safe to call `runQueue` from within
1982
- a function that is itself being executed as part of an update cycle triggered
1983
- by a previous (or the same) `runQueue` call.
1984
-
1985
- Forces the immediate and synchronous execution of all pending reactive updates.
1986
-
1987
- Normally, changes to observed data sources (like proxied objects or arrays)
1988
- are processed asynchronously in a batch after a brief timeout (0ms). This function
1989
- allows you to bypass the timeout and process the update queue immediately.
1990
-
1991
- This can be useful in specific scenarios where you need the DOM to be updated
1992
- synchronously.
1993
-
1994
- This function is re-entrant, meaning it is safe to call `runQueue` from within
1995
- a function that is itself being executed as part of an update cycle triggered
1996
- by a previous (or the same) `runQueue` call.
1997
-
1998
- ###### Returns
1999
-
2000
- `void`
2001
-
2002
- ###### Example
2003
-
2004
- ```typescript
2005
- const $data = A.proxy("before");
2006
-
2007
- A('#', $data);
2008
- console.log(1, document.body.innerHTML); // before
2009
-
2010
- // Make an update that should cause the DOM to change.
2011
- $data.value = "after";
2012
-
2013
- // Normally, the DOM update would happen after a timeout.
2014
- // But this causes an immediate update:
2015
- A.runQueue();
2016
-
2017
- console.log(2, document.body.innerHTML); // after
2018
- ```
2019
-
2020
- ##### setErrorHandler()
2021
-
2022
- > **setErrorHandler**: (`handler?`) => `void`
2023
-
2024
- Sets a custom error handler function for errors that occur asynchronously
2025
- within reactive scopes (e.g., during updates triggered by proxy changes in
2026
- [derive](#derive) or [A](#a) render functions).
2027
-
2028
- The default handler logs the error to `console.error` and adds a simple
2029
- 'Error' message div to the DOM at the location where the error occurred (if possible).
2030
-
2031
- Your handler can provide custom logging, UI feedback, or suppress the default
2032
- error message.
2033
-
2034
- Sets a custom error handler function for errors that occur asynchronously
2035
- within reactive scopes (e.g., during updates triggered by proxy changes in
2036
- [derive](#derive) or [A](#a) render functions).
2037
-
2038
- The default handler logs the error to `console.error` and adds a simple
2039
- 'Error' message div to the DOM at the location where the error occurred (if possible).
2040
-
2041
- Your handler can provide custom logging, UI feedback, or suppress the default
2042
- error message.
2043
-
2044
- ###### Parameters
2045
-
2046
- ###### handler?
2047
-
2048
- (`error`) => `undefined` \| `boolean`
2049
-
2050
- A function that accepts the `Error` object.
2051
- - Return `false` to prevent adding an error message to the DOM.
2052
- - Return `true` or `undefined` (or throw) to allow the error messages to be added to the DOM.
2053
-
2054
- ###### Returns
2055
-
2056
- `void`
2057
-
2058
- ###### Example
2059
-
2060
- ```typescript
2061
- A.setErrorHandler(error => {
2062
- console.warn('Aberdeen render error:', error.message);
2063
- // Log to error reporting service
2064
- // myErrorReporter.log(error);
2065
-
2066
- try {
2067
- // Attempt to show a custom message in the UI
2068
- A('div#Oops, something went wrong!', errorClass);
2069
- } catch (e) {
2070
- // Ignore errors during error handling itself
2071
- }
2072
-
2073
- return false; // Suppress default console log and DOM error message
2074
- });
2075
-
2076
- // Styling for our custom error message
2077
- const errorClass = A.insertCss('background-color:#e31f00 display:inline-block color:white r:3px padding: 2px 4px;');
2078
-
2079
- // Cause an error within a render scope.
2080
- A('div.box', () => {
2081
- // Will cause our error handler to insert an error message within the box
2082
- noSuchFunction();
2083
- })
2084
- ```
2085
-
2086
- ##### setSpacingCssVars()
2087
-
2088
- > **setSpacingCssVars**: (`base`, `unit`) => `void`
2089
-
2090
- Initializes `cssVars[0]` through `cssVars[12]` with an exponential spacing scale.
2091
-
2092
- The scale is calculated as `2^(n-3) * base`, providing values from `0.25 * base` to `512 * base`.
2093
-
2094
- Initializes `cssVars[0]` through `cssVars[12]` with an exponential spacing scale.
2095
-
2096
- The scale is calculated as `2^(n-3) * base`, providing values from `0.25 * base` to `512 * base`.
2097
-
2098
- ###### Parameters
2099
-
2100
- ###### base
2101
-
2102
- `number` = `1`
2103
-
2104
- The base size for the spacing scale that will apply to `cssVars[3]`. Every step up the scale will double this, while every step down will halve it. Defaults to 1.
2105
-
2106
- ###### unit
2107
-
2108
- `string` = `'rem'`
2109
-
2110
- The CSS unit to use, like 'rem', 'em', or 'px'. Defaults to 'rem'.
2111
-
2112
- ###### Returns
2113
-
2114
- `void`
2115
-
2116
- ###### Example
2117
-
2118
- ```javascript
2119
- import A from 'aberdeen';
2120
- // Use default scale (0.25rem to 512rem)
2121
- A.setSpacingCssVars();
2122
-
2123
- // Use custom base size
2124
- A.setSpacingCssVars(16, 'px'); // 4px to 8192px
2125
-
2126
- // Use em units
2127
- A.setSpacingCssVars(1, 'em'); // 0.25em to 512em
2128
-
2129
- // Show the last generated spacing values
2130
- A.onEach(A.cssVars, (value, key) => {
2131
- A(`div #${key} → ${value}`)
2132
- }, (value, key) => parseInt(key)); // Numeric sort
2133
- ```
2134
-
2135
- ##### unmountAll()
2136
-
2137
- > **unmountAll**: () => `void`
2138
-
2139
- Removes all Aberdeen-managed DOM nodes and stops all active reactive scopes
2140
- (created by [mount](#mount), [derive](#derive), [A](#a) with functions, etc.).
2141
-
2142
- This effectively cleans up the entire Aberdeen application state. Aside from in
2143
- automated tests, there should probably be little reason to call this function.
2144
-
2145
- Removes all Aberdeen-managed DOM nodes and stops all active reactive scopes
2146
- (created by [mount](#mount), [derive](#derive), [A](#a) with functions, etc.).
2147
-
2148
- This effectively cleans up the entire Aberdeen application state. Aside from in
2149
- automated tests, there should probably be little reason to call this function.
2150
-
2151
- ###### Returns
2152
-
2153
- `void`
2154
-
2155
- ##### unproxy()
2156
-
2157
- > **unproxy**: \<`T`\>(`target`) => `T`
2158
-
2159
- Returns the original, underlying data target from a reactive proxy created by [proxy](#proxy).
2160
- If the input `target` is not a proxy, it is returned directly.
2161
-
2162
- This is useful when you want to avoid triggering subscriptions during read operations or
2163
- re-executes during write operations. Using [peek](#peek) is an alternative way to achieve this.
2164
-
2165
- Returns the original, underlying data target from a reactive proxy created by [proxy](#proxy).
2166
- If the input `target` is not a proxy, it is returned directly.
2167
-
2168
- This is useful when you want to avoid triggering subscriptions during read operations or
2169
- re-executes during write operations. Using [peek](#peek) is an alternative way to achieve this.
2170
-
2171
- ###### Type Parameters
2172
-
2173
- ###### T
2174
-
2175
- `T`
2176
-
2177
- The type of the target.
2178
-
2179
- ###### Parameters
2180
-
2181
- ###### target
2182
-
2183
- `T`
2184
-
2185
- A proxied object, array, or any other value.
2186
-
2187
- ###### Returns
2188
-
2189
- `T`
2190
-
2191
- The underlying (unproxied) data, or the input value if it wasn't a proxy.
2192
-
2193
- ###### Example
2194
-
2195
- ```typescript
2196
- const $user = A.proxy({ name: 'Frank' });
2197
- const rawUser = A.unproxy($user);
2198
-
2199
- // Log reactively
2200
- A(() => console.log('proxied', $user.name));
2201
- // The following will only ever log once, as we're not subscribing to any observable
2202
- A(() => console.log('unproxied', rawUser.name));
2203
-
2204
- // This cause the first log to run again:
2205
- setTimeout(() => $user.name += '!', 1000);
2206
-
2207
- // This doesn't cause any new logs:
2208
- setTimeout(() => rawUser.name += '?', 2000);
2209
-
2210
- // Both $user and rawUser end up as `{name: 'Frank!?'}`
2211
- setTimeout(() => {
2212
- console.log('final proxied', $user)
2213
- console.log('final unproxied', rawUser)
2214
- }, 3000);
2215
- ```
2216
-
2217
- ###### Returns
2218
-
2219
- The underlying (unproxied) data, or the input value if it wasn't a proxy.
2220
-
2221
- #### Example
2222
-
2223
- ```typescript
2224
- import A from 'aberdeen';
2225
-
2226
- const $state = A.proxy({ count: 0 });
2227
- A('div', () => {
2228
- A(`p#Count: ${$state.count}`);
2229
- A('button text=+ click=', () => $state.count++);
2230
- });
2231
- ```
2232
-
2233
- ***
2234
-
2235
- ### ~~NO\_COPY~~
2236
-
2237
- > `const` **NO\_COPY**: `symbol` = `OPAQUE`
2238
-
2239
- Defined in: [aberdeen.ts:1927](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L1927)
2240
-
2241
- Use [OPAQUE](#opaque) instead. This is an alias kept for backward compatibility.
2242
-
2243
- #### Deprecated
2244
-
2245
- ***
2246
-
2247
- ### OPAQUE
2248
-
2249
- > `const` **OPAQUE**: *typeof* [`OPAQUE`](#opaque)
2250
-
2251
- Defined in: [aberdeen.ts:1920](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L1920)
2252
-
2253
- A symbol that controls how Aberdeen handles an object in copy operations and proxy wrapping.
2254
-
2255
- The **presence** of this symbol (regardless of its value) prevents deep-copying: the object is
2256
- stored and passed by reference in [clone](#clone) and [copy](#copy).
2257
-
2258
- The **value** of the symbol controls proxy wrapping when the object is read from reactive state:
2259
- - **Truthy** (e.g. `true`): the object is fully opaque — it is not wrapped in a proxy, so its
2260
- properties are not observable. Use this for objects that break when proxied (e.g. class instances
2261
- with internal slots, Promises) or that must be invisible to Aberdeen's reactive system.
2262
- - **Falsy** (e.g. `false`): the object is still wrapped in a proxy, so reads on its properties
2263
- create reactive dependencies as normal — only deep-copying is suppressed.
2264
-
2265
- ## Functions
2266
-
2267
- ### A()
2268
-
2269
- > **A**(...`args`): `undefined` \| `Element`
2270
-
2271
- Defined in: [aberdeen.ts:2418](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L2418)
2272
-
2273
- The core function for building reactive user interfaces in Aberdeen. It creates and inserts new DOM elements
2274
- and sets attributes/properties/event listeners on DOM elements. It does so in a reactive way, meaning that
2275
- changes will be (mostly) undone when the current *scope* is destroyed or will be re-execute.
2276
-
2277
- #### Parameters
2278
-
2279
- ##### args
2280
-
2281
- ...`any`[]
2282
-
2283
- Any number of arguments can be given. How they're interpreted depends on their types:
2284
-
2285
- ### String arguments
2286
- Strings can be used to create and insert new elements, set classnames for the *current* element, and add text to the current element.
2287
- The format of a string is: (**tag** | `.` **class** | **key**[=:]**val** | **key**[=:]"**val containing spaces**")* ('#' **text** | **key**[=:])?
2288
-
2289
- So a string may consist of any number of...
2290
- - **tag** elements, like `h1` or `div`. These elements are created, added to the *current* element, and become the new *current* element for the rest of this `A` function execution.
2291
- - CSS classes prefixed by `.` characters. These classes will be added to the *current* element. Optionally, CSS classes can be appended to a **tag** without a space. So both `div.myclass` and `div .myclass` are valid and do the same thing.
2292
- - Property key/value pairs, like `type=password`, `placeholder="Your name"` or `data-id=123`. When the value contains spaces, it needs to be quoted with either "double quotes", 'single quotes' or `backticks`. Quotes within quoted values cannot be escaped (see the next rule for a solution). Key/value pairs will be handled according to *Property rules* below, but with the caveat that values can only be strings.
2293
- - CSS key/value pairs using two syntaxes:
2294
- - **Short form** `key:value` (no space after colon): The value ends at the next whitespace. Example: `m:$3 bg:red r:8px`
2295
- - **Long form** `key: value;` (space after colon): The value continues until a semicolon. Example: `box-shadow: 2px 0 6px black; transition: all 0.3s ease;`
2296
-
2297
- Both forms support CSS shortcuts (see below). You can mix them: `m:$3 box-shadow: 0 2px 4px rgba(0,0,0,0.2); bg:$cardBg`
2298
- The elements must be separated by spaces, except before a `.cssClass` if it is preceded by either **tag** or another CSS class.
2299
-
2300
- And a string may end in...
2301
- - A '#' followed by text, which will be added as a `TextNode` to the *current* element. The text ranges til the end of the string, and may contain any characters, including spaces and quotes.
2302
- - A key followed by an '=' character, in which case the value is expected as a separate argument. The key/value pair is set according to the *Property rules* below. This is useful when the value is not a string or contains spaces or user data. Example: `A('button text="Click me" click=', () => alert('Clicked!'))` or `A('input.value=', someUserData, "placeholder=", "Type your stuff")`. In case the value is a proxied object, its `.value` property will be applied reactively without needing to rerender the parent scope.
2303
- - A key followed by a ':' character (with no value), in which case the value is expected as a separate argument. The value is treated as a CSS value to be set inline on the *current* element. Example: `A('div margin-top:', someValueInPx)`. In case the value is a proxied object, its `.value` property will be applied reactively without needing to rerender the parent scope.
2304
-
2305
- ### Function arguments
2306
- When a function (without arguments nor a return value) is passed in, it will be reactively executed in its own observer scope, preserving the *current* element. So any `A()` invocations within this function will add child elements to or set properties on that element. If the function reads observable data, and that data is changed later on, the function we re-execute (after side effects, such as DOM modifications through `A`, have been cleaned - see also [clean](#clean)).
2307
-
2308
- ### Object arguments
2309
- When an object is passed in, its key-value pairs are used to modify the *current* element according to the *Property rules* below, *unless* the key starts with a `$` character, in which case that character is stripped of and the key/value pair is treated as a CSS property, subject to the *CSS shortcuts* below. In case a value is a proxied object, its `.value` property will be applied reactively without needing to rerender the parent scope. In most cases, the string notation (`key=` and `key:`) is preferred over this object notation, for readability.
2310
-
2311
- ### DOM node arguments
2312
- When a DOM Node (Element or TextNode) is passed in, it is added as a child to the *current* element. If the Node is an Element, it becomes the new *current* element for the rest of this `A` function execution.
2313
-
2314
- ### Property rules
2315
- - **Attribute:** The common case is setting the value as an HTML attribute named key. For example `A('input placeholder=Name')` results in `<input placeholder="Name">`.
2316
- - **Event listener:** If the value is a `function` it is set as an event listener for the event with the name given by the key. For example: A('button text=Press! click=', () => alert('Clicked!'))`. The event listener will be removed when the current scope is destroyed.
2317
- - **DOM property:** When the value is a boolean, or the key is `"value"` or `"selectedIndex"`, it is set on the `current` element as a DOM property instead of an HTML attribute. For example `A('checked=', true)` would do `el.checked = true` for the *current* element.
2318
- - **Conditional CSS class:** If the key starts with a `.` character, its either added to or removed from the *current* element as a CSS class, based on the truthiness of the value. So `A('.hidden=', isHidden)` would toggle the `hidden` CSS class. This only works if the `=` is the last character of the string, and the next argument is the value. Its common for the value to be a proxied object, in which case its `.value` is reactively applied without needing to rerender the parent scope.
2319
- - **Create transition:** When the key is `"create"`, the value will be added as a CSS class to the *current* element immediately, and then removed right after the browser has finished doing a layout pass. This behavior only triggers when the scope setting the `create` is the top-level scope being (re-)run. This allows for creation transitions, without triggering the transitions for deeply nested elements being drawn as part of a larger component. The string may also contain multiple dot-separated CSS classes, such as `.fade.grow`. The initial dot is optional. Alternatively, to allow for more complex transitions, the value may be a function that receives the `HTMLElement` being created as its only argument. It is *only* called if this is the top-level element being created in this scope run. See `transitions.ts` in the Aberdeen source code for some examples.
2320
- - **Destroy transition:** When the key is `"destroy"` the value will be used to apply a CSS transition if the *current* element is later on removed from the DOM and is the top-level element to be removed. This happens as follows: actual removal from the DOM is delayed by 2 seconds, and in the mean-time the value string is added as a CSS class to the element, allowing for a deletion transition. The string may also contain multiple dot-separated CSS classes, such as `.fade.shrink`. The initial dot is optional. Alternatively, to allow for more complex transitions, the value may be a function that receives the `HTMLElement` to be removed from the DOM as its only argument. This function may perform any transitions and is then itself responsible for eventually removing the element from the DOM. See `transitions.ts` in the Aberdeen source code for some examples.
2321
- - **Two-way data binding:** When the key is `"bind"` a two-way binding between the `.value` property of the given proxied object, and the *current* input element (`<input>`, `<select>` or `<textarea>`) is created. This is often used together with {@link ref}, in order to use properties other than `.value`.
2322
- - **Text:**: If the key is `"text"`, the value will be appended as a `TextNode` to the *current* element. The same can also be done with the `#` syntax in string arguments, though `text=` allows additional properties to come after in the same string: `A('button text=Hello click=', alert)`.
2323
- - **Unsafe HTML:** When the key is `"html"`, the value will be added as HTML to the *current* element. This should only be used in exceptional situations. Beware of XSS! Never use this with untrusted user data.
2324
- - **Rich text:** When the key is `"rich"`, the value is parsed as simple markdown-like syntax and rendered as inline elements. Supports `*italic*`, `**bold**`, `` `code` ``, and `[link text](/path)`. All text content is safely escaped, making it suitable for user data (though links should be validated if untrusted). Example: `A('p rich="Click *here* for **more** info")`.
2325
-
2326
- ### CSS shortcuts
2327
- For conciseness, Aberdeen supports some CSS shortcuts when setting CSS properties.
2328
- | Shortcut | Expands to |
2329
- |----------|------------|
2330
- | `m`, `mt`, `mb`, `ml`, `mr` | `margin`, `margin-top`, `margin-bottom`, `margin-left`, `margin-right` |
2331
- | `mv`, `mh` | Vertical (top+bottom) or horizontal (left+right) margins |
2332
- | `p`, `pt`, `pb`, `pl`, `pr` | `padding`, `padding-top`, `padding-bottom`, `padding-left`, `padding-right` |
2333
- | `pv`, `ph` | Vertical or horizontal padding |
2334
- | `w`, `h` | `width`, `height` |
2335
- | `bg` | `background` |
2336
- | `fg` | `color` |
2337
- | `r` | `border-radius` |
2338
-
2339
- Also, when the value is a string starting with `$`, it is treated as a reference to a CSS variable, expanding to `var(--variableName)`. For numeric variable names (which can't be used directly as CSS custom property names), Aberdeen prefixes them with `m`, so `$3` expands to `var(--m3)`. This is primarily intended for use with [setSpacingCssVars](#setspacingcssvars), which initializes spacing variables named `0` through `12` with an exponential spacing scale.
2340
-
2341
- To *set* a CSS custom property inline on an element, use a `--name` or (symmetrically with the `$`-reference syntax above) a `$name` key. For example `A('div --primary:red')` and `A('div $primary:red')` both set `--primary` to `red`.
2342
-
2343
- #### Returns
2344
-
2345
- `undefined` \| `Element`
2346
-
2347
- The most inner DOM element that was created (not counting text nodes nor elements created by content functions), or the current element if no new element was created. You should normally not need to use the return value - use this function's DOM manipulation abilities instead. One valid use case is when integrating with non-Aberdeen code that requires a reference to a DOM element.
2348
-
2349
- #### Examples
2350
-
2351
- ```typescript
2352
- A('button.secondary.outline text=Submit color:red disabled=', false, 'click=', () => console.log('Clicked!'));
2353
- ```
2354
-
2355
- We want to set `disabled` as a property instead of an attribute, so we must use the `key=` syntax in order to provide
2356
- `false` as a boolean instead of a string.
2357
-
2358
- ```typescript
2359
- let inputElement: Element = A('label text="Click me" input type=checkbox');
2360
- // You should usually not touch raw DOM elements, unless when integrating
2361
- // with non-Aberdeen code.
2362
- console.log('DOM element:', inputElement);
2363
- ```
2364
-
2365
- ```typescript
2366
- const $state = A.proxy({ count: 0 });
2367
- A('div', () => { // Outer element
2368
- // This scope re-renders when $state.count changes
2369
- A(`p#Count is ${$state.count}`);
2370
- A('button text=Increment click=', () => $state.count++);
2371
- });
2372
- ```
2373
-
2374
- ```typescript
2375
- const $user = A.proxy({ name: '' });
2376
- A('input placeholder=Name bind=', A.ref($user, 'name'));
2377
- A('h3', () => { // Reactive scope
2378
- A(`#Hello ${$user.name || 'stranger'}`);
2379
- });
2380
- ```
2381
-
2382
- ```typescript
2383
- const $show = A.proxy(false);
2384
- A('button click=', () => $show.value = !$show.value, () => A($show.value ? '#Hide' : '#Show'));
2385
- A(() => { // Reactive scope
2386
- if ($show.value) {
2387
- A('p#Details are visible!');
2388
- }
2389
- });
2390
- ```
2391
-
2392
- ```typescript
2393
- const $myColor = A.proxy('red');
2394
- A('p text="The color is " text=', $myColor, 'click=', () => $myColor.value = 'yellow')
2395
- // Clicking the text will cause it to change color without recreating the <p> itself
2396
- ```
2397
- This is often used together with [ref](#ref), in order to use properties other than `.value`.
2398
-
2399
- ***
2400
-
2401
- ### clean()
2402
-
2403
- > **clean**(`cleaner`): `void`
2404
-
2405
- Defined in: [aberdeen.ts:2965](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L2965)
2406
-
2407
- Registers a cleanup function to be executed just before the current reactive scope
2408
- is destroyed or redraws.
2409
-
2410
- This is useful for releasing resources, removing manual event listeners, or cleaning up
2411
- side effects associated with the scope. Cleaners are run in reverse order of registration.
2412
-
2413
- Scopes are created by functions like [derive](#derive), [mount](#mount), [A](#a) (when given a render function),
2414
- and internally by constructs like [onEach](#oneach).
2415
-
2416
- #### Parameters
2417
-
2418
- ##### cleaner
2419
-
2420
- () => `void`
2421
-
2422
- The function to execute during cleanup.
2423
-
2424
- #### Returns
2425
-
2426
- `void`
2427
-
2428
- #### Example
2429
-
2430
- ```typescript
2431
- const $numbers = A.proxy([3, 5, 10]);
2432
- let $sum = A.proxy(0);
2433
-
2434
- // Show the array items and maintain the sum
2435
- A.onEach($numbers, (item, index) => {
2436
- A(`code#${index}→${item}`);
2437
- // We'll update $sum.value using peek, as += first does a read, but
2438
- // we don't want to subscribe.
2439
- A.peek(() => $sum.value += item);
2440
- // Clean gets called before each rerun for a certain item index
2441
- // No need for peek here, as the clean code doesn't run in an
2442
- // observer scope.
2443
- A.clean(() => $sum.value -= item);
2444
- })
2445
-
2446
- // Show the sum
2447
- A('h1 text=', $sum);
2448
-
2449
- // Make random changes to the array
2450
- const rnd = () => 0|(Math.random()*20);
2451
- setInterval(() => $numbers[rnd()] = rnd(), 1000);
2452
- ```
2453
-
2454
- ***
2455
-
2456
- ### clone()
2457
-
2458
- > **clone**\<`T`\>(`src`): `T`
2459
-
2460
- Defined in: [aberdeen.ts:2098](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L2098)
2461
-
2462
- Clone an (optionally proxied) object or array.
2463
-
2464
- #### Type Parameters
2465
-
2466
- ##### T
2467
-
2468
- `T` *extends* `object`
2469
-
2470
- The type of the objects being copied.
2471
-
2472
- #### Parameters
2473
-
2474
- ##### src
2475
-
2476
- `T`
2477
-
2478
- The object or array to clone. If it is proxied, `clone` will subscribe to any changes to the (nested) data structure.
2479
-
2480
- #### Returns
2481
-
2482
- `T`
2483
-
2484
- A new unproxied array or object (of the same type as `src`), containing a deep copy of `src`.
2485
-
2486
- ***
2487
-
2488
- ### copy()
2489
-
2490
- #### Call Signature
2491
-
2492
- > **copy**\<`T`\>(`dst`, `src`): `boolean`
2493
-
2494
- Defined in: [aberdeen.ts:1712](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L1712)
2495
-
2496
- Recursively copies properties or array items from `src` to `dst`.
2497
- It's designed to work efficiently with reactive proxies created by [proxy](#proxy).
2498
-
2499
- - **Minimizes Updates:** When copying between objects/arrays (proxied or not), if a nested object
2500
- exists in `dst` with the same constructor as the corresponding object in `src`, `copy`
2501
- will recursively copy properties into the existing `dst` object instead of replacing it.
2502
- This minimizes change notifications for reactive (proxied) destinations.
2503
- - **Fast with Proxies:** When copying to/from proxied objects, `copy` uses Aberdeen internals
2504
- to speed things up (compared to a non-Aberdeen-aware deep copy).
2505
-
2506
- ##### Type Parameters
2507
-
2508
- ###### T
2509
-
2510
- `T` *extends* `object`
2511
-
2512
- The type of the objects being copied.
2513
-
2514
- ##### Parameters
2515
-
2516
- ###### dst
2517
-
2518
- `T`
2519
-
2520
- The destination object/array/Map (proxied or unproxied).
2521
-
2522
- ###### src
2523
-
2524
- `T`
2525
-
2526
- The source object/array/Map (proxied or unproxied). It won't be modified.
2527
-
2528
- ##### Returns
2529
-
2530
- `boolean`
2531
-
2532
- `true` if any changes were made to `dst`, or `false` if not.
2533
-
2534
- ##### Throws
2535
-
2536
- Error if attempting to copy an array into a non-array or vice versa.
2537
-
2538
- ##### Example
2539
-
2540
- ```typescript
2541
- const $source = A.proxy({ a: 1, b: { c: 2 } });
2542
- const $dest = A.proxy({ b: { d: 3 } });
2543
- A.copy($dest, $source);
2544
- console.log($dest); // proxy({ a: 1, b: { c: 2 } })
2545
- A.copy($dest, 'b', { e: 4 });
2546
- console.log($dest); // proxy({ a: 1, b: { e: 4 } })
2547
- ```
2548
-
2549
- #### Call Signature
2550
-
2551
- > **copy**\<`T`\>(`dst`, `dstKey`, `src`): `boolean`
2552
-
2553
- Defined in: [aberdeen.ts:1719](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L1719)
2554
-
2555
- Like above, but copies `src` into `dst[dstKey]`. This is useful if you're unsure if dst[dstKey]
2556
- already exists (as the right type of object) or if you don't want to subscribe to dst[dstKey].
2557
-
2558
- ##### Type Parameters
2559
-
2560
- ###### T
2561
-
2562
- `T` *extends* `object`
2563
-
2564
- ##### Parameters
2565
-
2566
- ###### dst
2567
-
2568
- `T`
2569
-
2570
- ###### dstKey
2571
-
2572
- keyof `T`
2573
-
2574
- Optional key in `dst` to copy into.
2575
-
2576
- ###### src
2577
-
2578
- `T`\[keyof `T`\]
2579
-
2580
- ##### Returns
2581
-
2582
- `boolean`
2583
-
2584
- ***
2585
-
2586
- ### count()
2587
-
2588
- > **count**(`proxied`): `ValueRef`\<`number`\>
2589
-
2590
- Defined in: [aberdeen.ts:1160](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L1160)
2591
-
2592
- Reactively counts the number of properties in an object.
2593
-
2594
- #### Parameters
2595
-
2596
- ##### proxied
2597
-
2598
- `TargetType`
2599
-
2600
- The observable object to count. In case an `array`, `Map`, or `Set` is passed in, a [ref](#ref) to its `.length` or `.size` will be returned.
2601
-
2602
- #### Returns
2603
-
2604
- `ValueRef`\<`number`\>
2605
-
2606
- an observable object for which the `value` property reflects the number of properties in `proxied` with a value other than `undefined`, or the collection size for arrays, Maps, and Sets.
2607
-
2608
- #### Example
2609
-
2610
- ```typescript
2611
- const $items = A.proxy({x: 3, y: 7} as any);
2612
- const $count = A.count($items);
2613
-
2614
- // Create a DOM text node for the count:
2615
- A('div text=', $count);
2616
- // <div>2</div>
2617
-
2618
- // Or we can use it in an {@link derive} function:
2619
- A(() => console.log("The count is now", $count.value));
2620
- // The count is now 2
2621
-
2622
- // Adding/removing items will update the count
2623
- $items.z = 12;
2624
- // Asynchronously, after 0ms:
2625
- // <div>3</div>
2626
- // The count is now 3
2627
- ```
2628
-
2629
- ***
2630
-
2631
- ### darkMode()
2632
-
2633
- > **darkMode**(): `boolean`
2634
-
2635
- Defined in: [aberdeen.ts:2055](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L2055)
2636
-
2637
- Returns whether the user's browser prefers a dark color scheme.
2638
-
2639
- This function is reactive - scopes that call it will re-execute when the
2640
- browser's color scheme preference changes (via the `prefers-color-scheme` media query).
2641
-
2642
- Use this in combination with [A](#a) and [cssVars](#cssvars) to implement theme switching:
2643
-
2644
- #### Returns
2645
-
2646
- `boolean`
2647
-
2648
- `true` if the browser prefers dark mode, `false` if it prefers light mode.
2649
-
2650
- #### Example
2651
-
2652
- ```javascript
2653
- import A from 'aberdeen';
2654
-
2655
- // Reactively set colors based on browser preference
2656
- A(() => {
2657
- A.cssVars.bg = A.darkMode() ? '#1a1a1a' : '#ffffff';
2658
- A.cssVars.fg = A.darkMode() ? '#e5e5e5' : '#000000';
2659
- });
2660
-
2661
- A('div bg:$bg fg:$fg p:1rem #Colors change based on system dark mode preference');
2662
- ```
2663
-
2664
- ***
2665
-
2666
- ### derive()
2667
-
2668
- > **derive**\<`T`\>(`func`): `ValueRef`\<`T`\>
2669
-
2670
- Defined in: [aberdeen.ts:3017](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L3017)
2671
-
2672
- Creates a reactive scope that automatically re-executes the provided function
2673
- whenever any proxied data (created by [proxy](#proxy)) read during its last execution changes, storing
2674
- its return value in an observable.
2675
-
2676
- Updates are batched and run asynchronously shortly after the changes occur.
2677
- Use [clean](#clean) to register cleanup logic for the scope.
2678
- Use [peek](#peek) or [unproxy](#unproxy) within the function to read proxied data without subscribing to it.
2679
-
2680
- #### Type Parameters
2681
-
2682
- ##### T
2683
-
2684
- `T`
2685
-
2686
- #### Parameters
2687
-
2688
- ##### func
2689
-
2690
- () => `T`
2691
-
2692
- The function to execute reactively. Any DOM manipulations should typically
2693
- be done using [A](#a) within this function. Its return value will be made available as an
2694
- observable returned by the `derive()` function.
2695
-
2696
- #### Returns
2697
-
2698
- `ValueRef`\<`T`\>
2699
-
2700
- An observable object, with its `value` property containing whatever the last run of `func` returned.
2701
-
2702
- #### Examples
2703
-
2704
- ```typescript
2705
- const $data = A.proxy({ user: 'Frank', notifications: 42 });
2706
-
2707
- A('main', () => {
2708
- console.log('Welcome');
2709
- A('h3#Welcome, ' + $data.user); // Reactive text
2710
-
2711
- A.derive(() => {
2712
- // When $data.notifications changes, only this inner scope reruns,
2713
- // leaving the `<p>Welcome, ..</p>` untouched.
2714
- console.log('Notifications');
2715
- A('code.notification-badge text=', $data.notifications);
2716
- A('a text=Notify! click=', () => $data.notifications++);
2717
- });
2718
- });
2719
- ```
2720
-
2721
- ***Note*** that the above could just as easily be done using `A(func)` instead of `derive(func)`.
2722
-
2723
- ```typescript
2724
- const $counter = A.proxy(0);
2725
- setInterval(() => $counter.value++, 1000);
2726
- const $double = A.derive(() => $counter.value * 2);
2727
-
2728
- A('h3', () => {
2729
- A(`#counter=${$counter.value} double=${$double.value}`);
2730
- })
2731
- ```
2732
-
2733
- ***
2734
-
2735
- ### disableCreateDestroy()
2736
-
2737
- > **disableCreateDestroy**(): `void`
2738
-
2739
- Defined in: [aberdeen.ts:2292](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L2292)
2740
-
2741
- Make the `create` and `destroy` special properties no-ops.
2742
-
2743
- This is useful from within automated testing environments, where the transitioning
2744
- new and lingering old elements may make writing reliable selectors difficult.
2745
-
2746
- As this is only intended for testing, there's no way to re-enable the special properties
2747
- once disabled.
2748
-
2749
- #### Returns
2750
-
2751
- `void`
2752
-
2753
- ***
2754
-
2755
- ### dump()
2756
-
2757
- > **dump**\<`T`\>(`data`): `T`
2758
-
2759
- Defined in: [aberdeen.ts:3438](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L3438)
2760
-
2761
- Renders a live, recursive dump of a proxied data structure (or any value)
2762
- into the DOM at the current [A](#a) insertion point.
2763
-
2764
- Uses `<ul>` and `<li>` elements to display object properties and array items.
2765
- Updates reactively if the dumped data changes. Primarily intended for debugging purposes.
2766
-
2767
- #### Type Parameters
2768
-
2769
- ##### T
2770
-
2771
- `T`
2772
-
2773
- The type of the data being dumped.
2774
-
2775
- #### Parameters
2776
-
2777
- ##### data
2778
-
2779
- `T`
2780
-
2781
- The proxied data structure (or any value) to display.
2782
-
2783
- #### Returns
2784
-
2785
- `T`
2786
-
2787
- The original `data` argument, allowing for chaining.
2788
-
2789
- #### Example
2790
-
2791
- ```typescript
2792
- import A from 'aberdeen';
2793
-
2794
- const $state = A.proxy({
2795
- user: { name: 'Frank', kids: 1 },
2796
- items: ['a', 'b']
2797
- });
2798
-
2799
- A('h2#Live State Dump');
2800
- A.dump($state);
2801
-
2802
- // Change state later, the dump in the DOM will update
2803
- setTimeout(() => { $state.user.kids++; $state.items.push('c'); }, 2000);
2804
- ```
2805
-
2806
- ***
2807
-
2808
- ### insertCss()
2809
-
2810
- > **insertCss**(`style`): `string`
2811
-
2812
- Defined in: [aberdeen.ts:2616](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L2616)
2813
-
2814
- Inserts CSS rules into the document, scoping them with a unique class name.
2815
-
2816
- The `style` parameter can be either:
2817
- - A **concise style string** (for rules applying to the root class).
2818
- - An **object** where keys are selectors (with `&` representing the root class)
2819
- and values are concise style strings or nested objects. When the key does not contain `&`,
2820
- it is treated as a descendant selector. So `{p: "color:red"}` becomes `".AbdStlX p { color: red; }"` with `AbdStlX` being the generated class name.
2821
-
2822
- ### Concise Style Strings
2823
-
2824
- Concise style strings use two syntaxes (same as inline CSS in [A](#a)):
2825
- - **Short form** `key:value` (no space after colon): The value ends at the next whitespace.
2826
- Example: `'m:$3 bg:red r:8px'`
2827
- - **Long form** `key: value;` (space after colon): The value continues until a semicolon.
2828
- Example: `'box-shadow: 2px 0 6px black; transition: all 0.3s ease;'`
2829
-
2830
- Both forms can be mixed: `'m:$3 box-shadow: 0 2px 4px rgba(0,0,0,0.2); bg:$cardBg'`
2831
-
2832
- Supports the same CSS shortcuts as [A](#a) and CSS variable references with `$` (e.g., `$primary`, `$3`).
2833
-
2834
- #### Parameters
2835
-
2836
- ##### style
2837
-
2838
- A concise style string or a style object.
2839
-
2840
- `string` | `object`
2841
-
2842
- #### Returns
2843
-
2844
- `string`
2845
-
2846
- The unique class name prefix used for scoping (e.g., `.AbdStl1`).
2847
- Use this prefix with [A](#a) to apply the styles.
2848
-
2849
- #### Examples
2850
-
2851
- ```typescript
2852
- const cardClass = A.insertCss({
2853
- '&': 'bg:white p:$4 r:8px transition: background-color 0.3s;',
2854
- '&:hover': 'bg:#f5f5f5',
2855
- });
2856
-
2857
- A('section', cardClass, () => {
2858
- A('p#Card content');
2859
- });
2860
- ```
2861
-
2862
- ```typescript
2863
- const formClass = A.insertCss({
2864
- '&': 'bg:#0004 p:$3 r:$2',
2865
- button: {
2866
- '&': 'bg:$primary fg:white p:$2 r:4px cursor:pointer',
2867
- '&:hover': 'bg:$primaryHover',
2868
- '&:disabled': 'bg:#ccc cursor:not-allowed',
2869
- '.icon': 'display:inline-block mr:$1',
2870
- '@media (max-width: 600px)': 'p:$1 font-size:14px'
2871
- }
2872
- });
2873
-
2874
- A('form', formClass, () => {
2875
- A('button', () => {
2876
- A('span.icon text=🔥');
2877
- A('#Click Me');
2878
- });
2879
- });
2880
- ```
2881
-
2882
- ```typescript
2883
- const badge = A.insertCss({
2884
- '&::before': 'content: "★"; color:gold mr:$1',
2885
- '&': 'position:relative box-shadow: 0 2px 8px rgba(0,0,0,0.15);'
2886
- });
2887
-
2888
- A(badge + ' span#Product Name');
2889
- ```
2890
-
2891
- ***
2892
-
2893
- ### insertGlobalCss()
2894
-
2895
- > **insertGlobalCss**(`style`): `void`
2896
-
2897
- Defined in: [aberdeen.ts:2768](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L2768)
2898
-
2899
- Inserts CSS rules globally (unscoped).
2900
-
2901
- Works exactly like [insertCss](#insertcss), but without prefixing selectors with a unique class name.
2902
- This is useful for global resets, base styles, or styles that need to apply to the entire document.
2903
-
2904
- Accepts the same concise style string syntax and CSS shortcuts as [insertCss](#insertcss).
2905
- See [insertCss](#insertcss) for detailed documentation on syntax and shortcuts.
2906
-
2907
- #### Parameters
2908
-
2909
- ##### style
2910
-
2911
- `object`
2912
-
2913
- Object with selectors as keys and concise CSS strings as values.
2914
-
2915
- #### Returns
2916
-
2917
- `void`
2918
-
2919
- #### Examples
2920
-
2921
- ```typescript
2922
- // Set up global styles using CSS shortcuts
2923
- A.insertGlobalCss({
2924
- "*": "m:0 p:0 box-sizing:border-box",
2925
- "body": "font-family: system-ui, sans-serif; m:0 p:$3 bg:#434 fg:#d0dafa",
2926
- "a": "text-decoration:none fg:#57f",
2927
- "a:hover": "text-decoration:underline",
2928
- "code": "font-family:monospace bg:#222 fg:#afc p:4px r:3px"
2929
- });
2930
-
2931
- A('h2#Title without margins');
2932
- A('a#This is a link');
2933
- A('code#const x = 42;');
2934
- ```
2935
-
2936
- ```typescript
2937
- A.insertGlobalCss({
2938
- "html": "font-size:16px",
2939
- "body": "line-height:1.6",
2940
- "h1, h2, h3": "font-weight:600 mt:$4 mb:$2",
2941
- "@media (max-width: 768px)": {
2942
- "html": "font-size:14px",
2943
- "body": "p:$2"
2944
- },
2945
- "@media (prefers-color-scheme: dark)": {
2946
- "body": "bg:#1a1a1a fg:#e5e5e5",
2947
- "code": "bg:#2a2a2a"
2948
- }
2949
- });
2950
- ```
2951
- At-rules such as `@media` and `@keyframes` should use nested objects. For keyframes,
2952
- the step selectors (`0%`, `50%`, `100%`, etc.) become the nested keys and each value
2953
- should be a concise CSS declaration string.
2954
-
2955
- ```typescript
2956
- A.insertGlobalCss({
2957
- "@keyframes connection-pulse": {
2958
- "0%": "box-shadow: inset 0 0 0 0 rgba(255, 70, 70, 0.4);",
2959
- "50%": "box-shadow: inset 0 0 0 6px rgba(255, 70, 70, 0.08);",
2960
- "100%": "box-shadow: inset 0 0 0 0 rgba(255, 70, 70, 0.4);"
2961
- }
2962
- });
2963
- ```
2964
-
2965
- ***
2966
-
2967
- ### invertString()
2968
-
2969
- > **invertString**(`input`): `string`
2970
-
2971
- Defined in: [aberdeen.ts:195](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L195)
2972
-
2973
- Creates a new string that has the opposite sort order compared to the input string.
2974
-
2975
- This is achieved by flipping the bits of each character code in the input string.
2976
- The resulting string is intended for use as a sort key, particularly with the
2977
- `makeKey` function in [onEach](#oneach), to achieve a descending sort order.
2978
-
2979
- **Warning:** The output string will likely contain non-printable characters or
2980
- appear as gibberish and should not be displayed to the user.
2981
-
2982
- #### Parameters
2983
-
2984
- ##### input
2985
-
2986
- `string`
2987
-
2988
- The string whose sort order needs to be inverted.
2989
-
2990
- #### Returns
2991
-
2992
- `string`
2993
-
2994
- A new string that will sort in the reverse order of the input string.
2995
-
2996
- #### Example
2997
-
2998
- ```typescript
2999
- const $users = A.proxy([
3000
- { id: 1, name: 'Charlie', score: 95 },
3001
- { id: 2, name: 'Alice', score: 100 },
3002
- { id: 3, name: 'Bob', score: 90 },
3003
- ]);
3004
-
3005
- A.onEach($users, ($user) => {
3006
- A(`p#${$user.name}: ${$user.score}`);
3007
- }, ($user) => A.invertString($user.name)); // Reverse alphabetic order
3008
- ```
3009
-
3010
- #### See
3011
-
3012
- [onEach](#oneach) for usage with sorting.
3013
-
3014
- ***
3015
-
3016
- ### isEmpty()
3017
-
3018
- > **isEmpty**(`proxied`): `boolean`
3019
-
3020
- Defined in: [aberdeen.ts:1098](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L1098)
3021
-
3022
- Reactively checks if an observable array, object, Map, or Set is empty.
3023
-
3024
- This function not only returns the current emptiness state but also establishes
3025
- a reactive dependency. If the emptiness state of the `proxied` object or array
3026
- changes later (e.g., an item is added to an empty array, or the last property
3027
- is deleted from an object), the scope that called `isEmpty` will be automatically
3028
- scheduled for re-evaluation.
3029
-
3030
- #### Parameters
3031
-
3032
- ##### proxied
3033
-
3034
- `TargetType`
3035
-
3036
- The observable array, object, Map, or Set to check.
3037
-
3038
- #### Returns
3039
-
3040
- `boolean`
3041
-
3042
- `true` if the array has length 0, the Map/Set has size 0, or the object has no own enumerable properties, `false` otherwise.
3043
-
3044
- #### Example
3045
-
3046
- ```typescript
3047
- const $items = A.proxy([]);
3048
-
3049
- // Reactively display a message if the items array is empty
3050
- A('div', () => {
3051
- if (A.isEmpty($items)) {
3052
- A('p i#No items yet!');
3053
- } else {
3054
- A.onEach($items, item => A('p#'+item));
3055
- }
3056
- });
3057
-
3058
- // Adding an item will automatically remove the "No items yet!" message
3059
- setInterval(() => {
3060
- if (!$items.length || Math.random()>0.5) $items.push('Item');
3061
- else $items.length = 0;
3062
- }, 1000)
3063
- ```
3064
-
3065
- ***
3066
-
3067
- ### map()
3068
-
3069
- Reactively maps/filters items from a proxied source array or object to a new proxied array or object.
3070
-
3071
- It iterates over the `target` proxy. For each item, it calls `func`.
3072
- - If `func` returns a value, it's added to the result proxy under the same key/index.
3073
- - If `func` returns `undefined`, the item is skipped (filtered out).
3074
-
3075
- The returned proxy automatically updates when:
3076
- - Items are added/removed/updated in the `target` proxy.
3077
- - Any proxied data read *within* the `func` call changes (for a specific item).
3078
-
3079
- #### Param
3080
-
3081
- A function `(value, key) => mappedValue | undefined` that transforms each item.
3082
- It receives the item's value and its key/index. Return `undefined` to filter the item out.
3083
-
3084
- #### Template
3085
-
3086
- The type of items in the source proxy.
3087
-
3088
- #### Template
3089
-
3090
- The type of items in the resulting proxy.
3091
-
3092
- #### Examples
3093
-
3094
- ```typescript
3095
- const $numbers = A.proxy([1, 2, 3]);
3096
- const $doubled = A.map($numbers, (n) => n * 2);
3097
- // $doubled is proxy([2, 4, 6])
3098
-
3099
- A(() => console.log($doubled)); // Logs updates
3100
- $numbers.push(4); // $doubled becomes proxy([2, 4, 6, 8])
3101
- ```
3102
-
3103
- ```typescript
3104
- const $users = A.proxy({
3105
- 'u1': { name: 'Alice', active: true },
3106
- 'u2': { name: 'Bob', active: false },
3107
- 'u3': { name: 'Charlie', active: true }
3108
- });
3109
-
3110
- const $activeUserNames = A.map($users, ($user) => $user.active ? $user.name : undefined);
3111
- // $activeUserNames is proxy({ u1: 'Alice', u3: 'Charlie' })
3112
- A(() => console.log(Object.values($activeUserNames)));
3113
-
3114
- $users.u2.active = true;
3115
- // $activeUserNames becomes proxy({ u1: 'Alice', u2: 'Bob', u3: 'Charlie' })
3116
- ```
3117
-
3118
- #### Call Signature
3119
-
3120
- > **map**\<`K`, `IN`, `OUT`\>(`source`, `func`): `Map`\<`K`, `OUT`\>
3121
-
3122
- Defined in: [aberdeen.ts:3125](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L3125)
3123
-
3124
- When using a Map as `source`.
3125
-
3126
- ##### Type Parameters
3127
-
3128
- ###### K
3129
-
3130
- `K`
3131
-
3132
- ###### IN
3133
-
3134
- `IN`
3135
-
3136
- ###### OUT
3137
-
3138
- `OUT`
3139
-
3140
- ##### Parameters
3141
-
3142
- ###### source
3143
-
3144
- `Map`\<`K`, `IN`\>
3145
-
3146
- ###### func
3147
-
3148
- (`value`, `key`) => `undefined` \| `OUT`
3149
-
3150
- ##### Returns
3151
-
3152
- `Map`\<`K`, `OUT`\>
3153
-
3154
- #### Call Signature
3155
-
3156
- > **map**\<`IN`, `OUT`\>(`source`, `func`): `OUT`[]
3157
-
3158
- Defined in: [aberdeen.ts:3130](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L3130)
3159
-
3160
- When using an array as `source`.
3161
-
3162
- ##### Type Parameters
3163
-
3164
- ###### IN
3165
-
3166
- `IN`
3167
-
3168
- ###### OUT
3169
-
3170
- `OUT`
3171
-
3172
- ##### Parameters
3173
-
3174
- ###### source
3175
-
3176
- `IN`[]
3177
-
3178
- ###### func
3179
-
3180
- (`value`, `index`) => `undefined` \| `OUT`
3181
-
3182
- ##### Returns
3183
-
3184
- `OUT`[]
3185
-
3186
- #### Call Signature
3187
-
3188
- > **map**\<`IN`, `IN_KEY`, `OUT`\>(`source`, `func`): `Record`\<`string` \| `symbol`, `OUT`\>
3189
-
3190
- Defined in: [aberdeen.ts:3135](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L3135)
3191
-
3192
- When using an object as `source`.
3193
-
3194
- ##### Type Parameters
3195
-
3196
- ###### IN
3197
-
3198
- `IN`
3199
-
3200
- ###### IN_KEY
3201
-
3202
- `IN_KEY` *extends* `string` \| `number` \| `symbol`
3203
-
3204
- ###### OUT
3205
-
3206
- `OUT`
3207
-
3208
- ##### Parameters
3209
-
3210
- ###### source
3211
-
3212
- `Record`\<`IN_KEY`, `IN`\>
3213
-
3214
- ###### func
3215
-
3216
- (`value`, `index`) => `undefined` \| `OUT`
3217
-
3218
- ##### Returns
3219
-
3220
- `Record`\<`string` \| `symbol`, `OUT`\>
3221
-
3222
- ***
3223
-
3224
- ### merge()
3225
-
3226
- #### Call Signature
3227
-
3228
- > **merge**\<`T`\>(`dst`, `value`): `boolean`
3229
-
3230
- Defined in: [aberdeen.ts:1752](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L1752)
3231
-
3232
- Like [copy](#copy), but uses merge semantics. Properties in `dst` not present in `src` are kept.
3233
- `null`/`undefined` in `src` delete properties in `dst`.
3234
-
3235
- ##### Type Parameters
3236
-
3237
- ###### T
3238
-
3239
- `T` *extends* `object`
3240
-
3241
- ##### Parameters
3242
-
3243
- ###### dst
3244
-
3245
- `T`
3246
-
3247
- ###### value
3248
-
3249
- `Partial`\<`T`\>
3250
-
3251
- ##### Returns
3252
-
3253
- `boolean`
3254
-
3255
- ##### Example
3256
-
3257
- ```typescript
3258
- const source = { b: { c: 99 }, d: undefined }; // d: undefined will delete
3259
- const $dest = A.proxy({ a: 1, b: { x: 5 }, d: 4 });
3260
- A.merge($dest, source);
3261
- A.merge($dest, 'b', { y: 6 }); // merge into $dest.b
3262
- A.merge($dest, 'c', { z: 7 }); // $dest.c doesn't exist yet, so it will just be assigned
3263
- console.log($dest); // proxy({ a: 1, b: { c: 99, x: 5, y: 6 }, c: { z: 7 } })
3264
- ```
3265
-
3266
- #### Call Signature
3267
-
3268
- > **merge**\<`T`\>(`dst`, `dstKey`, `value`): `boolean`
3269
-
3270
- Defined in: [aberdeen.ts:1753](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L1753)
3271
-
3272
- Like [copy](#copy), but uses merge semantics. Properties in `dst` not present in `src` are kept.
3273
- `null`/`undefined` in `src` delete properties in `dst`.
3274
-
3275
- ##### Type Parameters
3276
-
3277
- ###### T
3278
-
3279
- `T` *extends* `object`
3280
-
3281
- ##### Parameters
3282
-
3283
- ###### dst
3284
-
3285
- `T`
3286
-
3287
- ###### dstKey
3288
-
3289
- keyof `T`
3290
-
3291
- ###### value
3292
-
3293
- `Partial`\<`T`\[keyof `T`\]\>
3294
-
3295
- ##### Returns
3296
-
3297
- `boolean`
3298
-
3299
- ##### Example
3300
-
3301
- ```typescript
3302
- const source = { b: { c: 99 }, d: undefined }; // d: undefined will delete
3303
- const $dest = A.proxy({ a: 1, b: { x: 5 }, d: 4 });
3304
- A.merge($dest, source);
3305
- A.merge($dest, 'b', { y: 6 }); // merge into $dest.b
3306
- A.merge($dest, 'c', { z: 7 }); // $dest.c doesn't exist yet, so it will just be assigned
3307
- console.log($dest); // proxy({ a: 1, b: { c: 99, x: 5, y: 6 }, c: { z: 7 } })
3308
- ```
3309
-
3310
- ***
3311
-
3312
- ### mount()
3313
-
3314
- > **mount**(`parentElement`, `func`): `void`
3315
-
3316
- Defined in: [aberdeen.ts:3064](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L3064)
3317
-
3318
- Attaches a reactive Aberdeen UI fragment to an existing DOM element. Without the use of
3319
- this function, [A](#a) will assume `document.body` as its root.
3320
-
3321
- It creates a top-level reactive scope associated with the `parentElement`. The provided
3322
- function `func` is executed immediately within this scope. Any proxied data read by `func`
3323
- will cause it to re-execute when the data changes, updating the DOM elements created within it.
3324
-
3325
- Calls to [A](#a) inside `func` will append nodes to `parentElement`.
3326
- You can nest [derive](#derive) or other [A](#a) scopes within `func`.
3327
- Use [unmountAll](#unmountall) to clean up all mounted scopes and their DOM nodes.
3328
-
3329
- Mounting scopes happens reactively, meaning that if this function is called from within another
3330
- ([derive](#derive) or [A](#a) or [mount](#mount)) scope that gets cleaned up, so will the mount.
3331
-
3332
- #### Parameters
3333
-
3334
- ##### parentElement
3335
-
3336
- `Element`
3337
-
3338
- The native DOM `Element` to which the UI fragment will be appended.
3339
-
3340
- ##### func
3341
-
3342
- () => `void`
3343
-
3344
- The function that defines the UI fragment, typically containing calls to [A](#a).
3345
-
3346
- #### Returns
3347
-
3348
- `void`
3349
-
3350
- #### Example
3351
-
3352
- ```javascript
3353
- // Create a pre-existing DOM structure (without Aberdeen)
3354
- document.body.innerHTML = `<h3>Static content <span id="title-extra"></span></h3><div class="box" id="app-root"></div>`;
3355
-
3356
- import A from 'aberdeen';
3357
-
3358
- const $runTime = A.proxy(0);
3359
- setInterval(() => $runTime.value++, 1000);
3360
-
3361
- A.mount(document.getElementById('app-root'), () => {
3362
- A('h4#Aberdeen App');
3363
- A(`p#Run time: ${$runTime.value}s`);
3364
- // Conditionally render some content somewhere else in the static page
3365
- if ($runTime.value&1) {
3366
- A.mount(document.getElementById('title-extra'), () =>
3367
- A(`i#(${$runTime.value}s)`)
3368
- );
3369
- }
3370
- });
3371
- ```
3372
-
3373
- Note how the inner mount behaves reactively as well, automatically unmounting when it's parent observer scope re-runs.
3374
-
3375
- ***
3376
-
3377
- ### multiMap()
3378
-
3379
- Reactively maps items from a source proxy (array or object) to a target proxied object,
3380
- where each source item can contribute multiple key-value pairs to the target.
3381
-
3382
- It iterates over the `target` proxy. For each item, it calls `func`.
3383
- - If `func` returns an object, all key-value pairs from that object are added to the result proxy.
3384
- - If `func` returns `undefined`, the item contributes nothing.
3385
-
3386
- The returned proxy automatically updates when:
3387
- - Items are added/removed/updated in the `target` proxy.
3388
- - Any proxied data read *within* the `func` call changes (for a specific item).
3389
- - If multiple input items produce the same output key, the last one processed usually "wins",
3390
- but the exact behavior on collision depends on update timing.
3391
-
3392
- This is useful for "flattening" or "indexing" data, or converting an observable array to an observable object.
3393
-
3394
- #### Param
3395
-
3396
- The source proxied array or object.
3397
-
3398
- #### Param
3399
-
3400
- A function `(value, key) => ({...pairs} | undefined)` that transforms an item
3401
- into an object of key-value pairs to add, or `undefined` to add nothing.
3402
-
3403
- #### Template
3404
-
3405
- The type of items in the source proxy.
3406
-
3407
- #### Template
3408
-
3409
- The type of the aggregated output object (should encompass all possible key-value pairs).
3410
-
3411
- #### Example
3412
-
3413
- ```typescript
3414
- const $items = A.proxy([
3415
- { id: 'a', value: 10 },
3416
- { id: 'b', value: 20 },
3417
- ]);
3418
- const $itemsById = A.multiMap($items, ($item) => ({
3419
- [$item.id]: $item.value,
3420
- [$item.id+$item.id]: $item.value*10,
3421
- }));
3422
- // $itemsById is proxy({ a: 10, aa: 100, b: 20, bb: 200 })
3423
-
3424
- A(() => console.log($itemsById));
3425
-
3426
- $items.push({ id: 'c', value: 30 });
3427
- // $itemsById becomes proxy({ a: 10, aa: 100, b: 20, bb: 200, c: 30, cc: 300 })
3428
- ```
3429
-
3430
- #### Call Signature
3431
-
3432
- > **multiMap**\<`IN`, `OUT`\>(`source`, `func`): `OUT`
3433
-
3434
- Defined in: [aberdeen.ts:3215](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L3215)
3435
-
3436
- When using an array as `source`.
3437
-
3438
- ##### Type Parameters
3439
-
3440
- ###### IN
3441
-
3442
- `IN`
3443
-
3444
- ###### OUT
3445
-
3446
- `OUT` *extends* `object`
3447
-
3448
- ##### Parameters
3449
-
3450
- ###### source
3451
-
3452
- `IN`[]
3453
-
3454
- ###### func
3455
-
3456
- (`value`, `index`) => `undefined` \| `OUT`
3457
-
3458
- ##### Returns
3459
-
3460
- `OUT`
3461
-
3462
- #### Call Signature
3463
-
3464
- > **multiMap**\<`K`, `IN`, `OUT`\>(`source`, `func`): `OUT`
3465
-
3466
- Defined in: [aberdeen.ts:3220](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L3220)
3467
-
3468
- When using an object as `source`.
3469
-
3470
- ##### Type Parameters
3471
-
3472
- ###### K
3473
-
3474
- `K` *extends* `string` \| `number` \| `symbol`
3475
-
3476
- ###### IN
3477
-
3478
- `IN`
3479
-
3480
- ###### OUT
3481
-
3482
- `OUT` *extends* `object`
3483
-
3484
- ##### Parameters
3485
-
3486
- ###### source
3487
-
3488
- `Record`\<`K`, `IN`\>
3489
-
3490
- ###### func
3491
-
3492
- (`value`, `index`) => `undefined` \| `OUT`
3493
-
3494
- ##### Returns
3495
-
3496
- `OUT`
3497
-
3498
- #### Call Signature
3499
-
3500
- > **multiMap**\<`K`, `IN`, `OUT`\>(`source`, `func`): `OUT`
3501
-
3502
- Defined in: [aberdeen.ts:3226](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L3226)
3503
-
3504
- When using a Map as `source`.
3505
-
3506
- ##### Type Parameters
3507
-
3508
- ###### K
3509
-
3510
- `K`
3511
-
3512
- ###### IN
3513
-
3514
- `IN`
3515
-
3516
- ###### OUT
3517
-
3518
- `OUT` *extends* `object`
3519
-
3520
- ##### Parameters
3521
-
3522
- ###### source
3523
-
3524
- `Map`\<`K`, `IN`\>
3525
-
3526
- ###### func
3527
-
3528
- (`value`, `key`) => `undefined` \| `OUT`
3529
-
3530
- ##### Returns
3531
-
3532
- `OUT`
3533
-
3534
- ***
3535
-
3536
- ### onEach()
3537
-
3538
- Reactively iterates over the items of an observable array, object, Map, or Set, optionally rendering content for each item.
3539
-
3540
- Automatically updates when items are added, removed, or modified.
3541
-
3542
- #### Param
3543
-
3544
- The observable array, object, Map, or Set to iterate over. Values that are `undefined` are skipped.
3545
-
3546
- #### Param
3547
-
3548
- A function called for each item. It receives the item's (observable) value and its index/key. For Sets, only the value is provided. Any DOM elements created within this function will be associated with the item, placed at the right spot in the DOM, and cleaned up when redrawing/removing the item.
3549
-
3550
- #### Param
3551
-
3552
- An optional function to generate a sort key for each item. This controls the order in which items are rendered in the DOM. If omitted, arrays use index order, Sets use the item value itself, and objects/Maps use their natural key order. The returned key can be a number, string, or an array of numbers/strings for composite sorting. Use [invertString](#invertstring) on string keys for descending order. Returning `null` or `undefined` from `makeKey` will prevent the item from being rendered.
3553
-
3554
- #### Examples
3555
-
3556
- ```typescript
3557
- const $items = A.proxy(['apple', 'banana', 'cherry']);
3558
-
3559
- // Basic iteration
3560
- A.onEach($items, (item, index) => A(`li#${item} (#${index})`));
3561
-
3562
- // Add a new item - the list updates automatically
3563
- setTimeout(() => $items.push('durian'), 2000);
3564
- // Same for updates and deletes
3565
- setTimeout(() => $items[1] = 'berry', 4000);
3566
- setTimeout(() => delete $items[2], 6000);
3567
- ```
3568
-
3569
- ```typescript
3570
- const $users = A.proxy([
3571
- { id: 3, group: 1, name: 'Charlie' },
3572
- { id: 1, group: 1, name: 'Alice' },
3573
- { id: 2, group: 2, name: 'Bob' },
3574
- ]);
3575
-
3576
- // Sort by name alphabetically
3577
- A.onEach($users, ($user) => {
3578
- A(`p#${$user.name} (id=${$user.id})`);
3579
- }, ($user) => [$user.group, $user.name]); // Sort by group, and within each group sort by name
3580
- ```
3581
-
3582
- ```javascript
3583
- const $config = A.proxy({ theme: 'dark', fontSize: 14, showTips: true });
3584
-
3585
- // Display configuration options
3586
- A('dl', () => {
3587
- A.onEach($config, (value, key) => {
3588
- if (key === 'showTips') return; // Don't render this one
3589
- A('dt#'+key);
3590
- A('dd#'+value);
3591
- });
3592
- });
3593
-
3594
- // Change a value - the display updates automatically
3595
- setTimeout(() => $config.fontSize = 16, 2000);
3596
- ```
3597
-
3598
- ```javascript
3599
- const $tags = A.proxy(new Set(['ui', 'fast', 'tiny']));
3600
-
3601
- A('ul', () => {
3602
- A.onEach($tags, (tag) => { // Defaults to alphabetically ordering by tag
3603
- A(`li#${tag}`);
3604
- });
3605
- });
3606
-
3607
- setTimeout(() => $tags.add('reactive'), 2000);
3608
- ```
3609
-
3610
- #### See
3611
-
3612
- [invertString](#invertstring) To easily create keys for reverse sorting.
3613
-
3614
- #### Call Signature
3615
-
3616
- > **onEach**\<`K`, `T`\>(`target`, `render`, `makeKey?`): `void`
3617
-
3618
- Defined in: [aberdeen.ts:957](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L957)
3619
-
3620
- ##### Type Parameters
3621
-
3622
- ###### K
3623
-
3624
- `K`
3625
-
3626
- ###### T
3627
-
3628
- `T`
3629
-
3630
- ##### Parameters
3631
-
3632
- ###### target
3633
-
3634
- `Map`\<`K`, `undefined` \| `T`\>
3635
-
3636
- ###### render
3637
-
3638
- (`value`, `key`) => `void`
3639
-
3640
- ###### makeKey?
3641
-
3642
- (`value`, `key`) => `SortKeyType`
3643
-
3644
- ##### Returns
3645
-
3646
- `void`
3647
-
3648
- #### Call Signature
3649
-
3650
- > **onEach**\<`T`\>(`target`, `render`, `makeKey?`): `void`
3651
-
3652
- Defined in: [aberdeen.ts:962](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L962)
3653
-
3654
- ##### Type Parameters
3655
-
3656
- ###### T
3657
-
3658
- `T`
3659
-
3660
- ##### Parameters
3661
-
3662
- ###### target
3663
-
3664
- `Set`\<`T`\>
3665
-
3666
- ###### render
3667
-
3668
- (`value`) => `void`
3669
-
3670
- ###### makeKey?
3671
-
3672
- (`value`) => `SortKeyType`
3673
-
3674
- ##### Returns
3675
-
3676
- `void`
3677
-
3678
- #### Call Signature
3679
-
3680
- > **onEach**\<`T`\>(`target`, `render`, `makeKey?`): `void`
3681
-
3682
- Defined in: [aberdeen.ts:967](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L967)
3683
-
3684
- ##### Type Parameters
3685
-
3686
- ###### T
3687
-
3688
- `T`
3689
-
3690
- ##### Parameters
3691
-
3692
- ###### target
3693
-
3694
- readonly (`undefined` \| `T`)[]
3695
-
3696
- ###### render
3697
-
3698
- (`value`, `index`) => `void`
3699
-
3700
- ###### makeKey?
3701
-
3702
- (`value`, `index`) => `SortKeyType`
3703
-
3704
- ##### Returns
3705
-
3706
- `void`
3707
-
3708
- #### Call Signature
3709
-
3710
- > **onEach**\<`K`, `T`\>(`target`, `render`, `makeKey?`): `void`
3711
-
3712
- Defined in: [aberdeen.ts:972](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L972)
3713
-
3714
- ##### Type Parameters
3715
-
3716
- ###### K
3717
-
3718
- `K` *extends* `string` \| `number` \| `symbol`
3719
-
3720
- ###### T
3721
-
3722
- `T`
3723
-
3724
- ##### Parameters
3725
-
3726
- ###### target
3727
-
3728
- `Record`\<`K`, `undefined` \| `T`\>
3729
-
3730
- ###### render
3731
-
3732
- (`value`, `index`) => `void`
3733
-
3734
- ###### makeKey?
3735
-
3736
- (`value`, `index`) => `SortKeyType`
3737
-
3738
- ##### Returns
3739
-
3740
- `void`
3741
-
3742
- ***
3743
-
3744
- ### partition()
3745
-
3746
- Reactively partitions items from a source proxy (array or object) into multiple "bucket" proxies
3747
- based on keys determined by a classifier function.
3748
-
3749
- This function iterates through the `source` proxy using [onEach](#oneach). For each item,
3750
- it calls the classifier `func`, which should return:
3751
- - A single key (`OUT_K`): The item belongs to the bucket with this key.
3752
- - An array of keys (`OUT_K[]`): The item belongs to all buckets specified in the array.
3753
- - `undefined`: The item is not placed in any bucket.
3754
-
3755
- The function returns a main proxied object. The keys of this object are the bucket keys (`OUT_K`)
3756
- returned by `func`. Each value associated with a bucket key is another proxied object (the "bucket").
3757
- This inner bucket object maps the *original* keys/indices from the `source` to the items
3758
- themselves that were classified into that bucket.
3759
-
3760
- The entire structure is reactive. Changes in the `source` proxy (adding/removing/updating items)
3761
- or changes in dependencies read by the `func` will cause the output partitioning to update automatically.
3762
- Buckets are created dynamically as needed and removed when they become empty.
3763
-
3764
- #### Param
3765
-
3766
- The input proxied Array or Record (e.g., created by [proxy](#proxy)) containing the items to partition.
3767
-
3768
- #### Param
3769
-
3770
- A classifier function `(value: IN_V, key: IN_K | number) => undefined | OUT_K | OUT_K[]`.
3771
- It receives the item's value and its original key/index from the `source`. It returns the bucket key(s)
3772
- the item belongs to, or `undefined` to ignore the item.
3773
-
3774
- #### Template
3775
-
3776
- The type of the keys used for the output buckets (string, number, or symbol).
3777
-
3778
- #### Template
3779
-
3780
- The type of the values in the source proxy.
3781
-
3782
- #### Template
3783
-
3784
- The type of the keys in the source proxy (if it's a Record).
3785
-
3786
- #### Examples
3787
-
3788
- ```typescript
3789
- interface Product { id: string; category: string; name: string; }
3790
- const $products = A.proxy<Product[]>([
3791
- { id: 'p1', category: 'Fruit', name: 'Apple' },
3792
- { id: 'p2', category: 'Veg', name: 'Carrot' },
3793
- { id: 'p3', category: 'Fruit', name: 'Banana' },
3794
- ]);
3795
-
3796
- // Partition products by category. Output keys are categories (string).
3797
- // Inner keys are original array indices (number).
3798
- const $productsByCategory = A.partition($products, ($product) => $product.category);
3799
-
3800
- // Reactively show the data structure
3801
- A.dump($productsByCategory);
3802
-
3803
- // Make random changes to the categories, to show reactiveness
3804
- setInterval(() => $products[0|(Math.random()*3)].category = ['Snack','Fruit','Veg'][0|(Math.random()*3)], 2000);
3805
- ```
3806
-
3807
- ```typescript
3808
- interface User { id: number; tags: string[]; name: string; }
3809
- const $users = A.proxy({
3810
- 'u1': { name: 'Alice', tags: ['active', 'new'] },
3811
- 'u2': { name: 'Bob', tags: ['active'] }
3812
- });
3813
-
3814
- // Partition users by tag. Output keys are tags (string).
3815
- // Inner keys are original object keys (string: 'u1', 'u2').
3816
- const $usersByTag = A.partition($users, ($user) => $user.tags);
3817
-
3818
- console.log($usersByTag);
3819
- ```
3820
-
3821
- #### Call Signature
3822
-
3823
- > **partition**\<`OUT_K`, `IN_V`\>(`source`, `func`): `Record`\<`OUT_K`, `Record`\<`number`, `IN_V`\>\>
3824
-
3825
- Defined in: [aberdeen.ts:3290](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L3290)
3826
-
3827
- When using an object as `array`.
3828
-
3829
- ##### Type Parameters
3830
-
3831
- ###### OUT_K
3832
-
3833
- `OUT_K` *extends* `string` \| `number` \| `symbol`
3834
-
3835
- ###### IN_V
3836
-
3837
- `IN_V`
3838
-
3839
- ##### Parameters
3840
-
3841
- ###### source
3842
-
3843
- `IN_V`[]
3844
-
3845
- ###### func
3846
-
3847
- (`value`, `key`) => `undefined` \| `OUT_K` \| `OUT_K`[]
3848
-
3849
- ##### Returns
3850
-
3851
- `Record`\<`OUT_K`, `Record`\<`number`, `IN_V`\>\>
3852
-
3853
- #### Call Signature
3854
-
3855
- > **partition**\<`IN_K`, `OUT_K`, `IN_V`\>(`source`, `func`): `Record`\<`OUT_K`, `Record`\<`IN_K`, `IN_V`\>\>
3856
-
3857
- Defined in: [aberdeen.ts:3295](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L3295)
3858
-
3859
- When using an object as `source`.
3860
-
3861
- ##### Type Parameters
3862
-
3863
- ###### IN_K
3864
-
3865
- `IN_K` *extends* `string` \| `number` \| `symbol`
3866
-
3867
- ###### OUT_K
3868
-
3869
- `OUT_K` *extends* `string` \| `number` \| `symbol`
3870
-
3871
- ###### IN_V
3872
-
3873
- `IN_V`
3874
-
3875
- ##### Parameters
3876
-
3877
- ###### source
3878
-
3879
- `Record`\<`IN_K`, `IN_V`\>
3880
-
3881
- ###### func
3882
-
3883
- (`value`, `key`) => `undefined` \| `OUT_K` \| `OUT_K`[]
3884
-
3885
- ##### Returns
3886
-
3887
- `Record`\<`OUT_K`, `Record`\<`IN_K`, `IN_V`\>\>
3888
-
3889
- #### Call Signature
3890
-
3891
- > **partition**\<`IN_K`, `OUT_K`, `IN_V`\>(`source`, `func`): `Record`\<`OUT_K`, `Record`\<`IN_K`, `IN_V`\>\>
3892
-
3893
- Defined in: [aberdeen.ts:3304](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L3304)
3894
-
3895
- When using a Map as `source`.
3896
-
3897
- ##### Type Parameters
3898
-
3899
- ###### IN_K
3900
-
3901
- `IN_K` *extends* `string` \| `number` \| `symbol`
3902
-
3903
- ###### OUT_K
3904
-
3905
- `OUT_K` *extends* `string` \| `number` \| `symbol`
3906
-
3907
- ###### IN_V
3908
-
3909
- `IN_V`
3910
-
3911
- ##### Parameters
3912
-
3913
- ###### source
3914
-
3915
- `Map`\<`IN_K`, `IN_V`\>
3916
-
3917
- ###### func
3918
-
3919
- (`value`, `key`) => `undefined` \| `OUT_K` \| `OUT_K`[]
3920
-
3921
- ##### Returns
3922
-
3923
- `Record`\<`OUT_K`, `Record`\<`IN_K`, `IN_V`\>\>
3924
-
3925
- ***
3926
-
3927
- ### peek()
3928
-
3929
- #### Call Signature
3930
-
3931
- > **peek**\<`T`, `K`\>(`target`, `key`): `T`\[`K`\]
3932
-
3933
- Defined in: [aberdeen.ts:3106](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L3106)
3934
-
3935
- Executes a function or retrieves a value *without* creating subscriptions in the current reactive scope, and returns its result.
3936
-
3937
- This is useful when you need to access reactive data inside a reactive scope (like [A](#a))
3938
- but do not want changes to that specific data to trigger a re-execute of the scope.
3939
-
3940
- Note: You may also use [unproxy](#unproxy) to get to the raw underlying data structure, which can be used to similar effect.
3941
-
3942
- ##### Type Parameters
3943
-
3944
- ###### T
3945
-
3946
- `T` *extends* `object`
3947
-
3948
- ###### K
3949
-
3950
- `K` *extends* `string` \| `number` \| `symbol`
3951
-
3952
- ##### Parameters
3953
-
3954
- ###### target
3955
-
3956
- `T`
3957
-
3958
- Either a function to execute, or an object (which may also be an Array or a Map) to index.
3959
-
3960
- ###### key
3961
-
3962
- `K`
3963
-
3964
- Optional key/index to use when `target` is an object.
3965
-
3966
- ##### Returns
3967
-
3968
- `T`\[`K`\]
3969
-
3970
- The result of the function call, or the value at `target[key]` when `target` is an object or `target.get(key)` when it's a Map.
3971
-
3972
- ##### Example
3973
-
3974
- ```typescript
3975
- const $data = A.proxy({ a: 1, b: 2 });
3976
- A(() => {
3977
- // re-executes only when $data.a changes, because $data.b is peeked.
3978
- const b = A.peek(() => $data.b);
3979
- console.log(`A is ${$data.a}, B was ${b} when A changed.`);
3980
- });
3981
- $data.b = 3; // Does not trigger console.log
3982
- $data.a = 2; // Triggers console.log (logs "A is 2, B was 3 when A changed.")
3983
- ```
3984
-
3985
- #### Call Signature
3986
-
3987
- > **peek**\<`K`, `V`\>(`target`, `key`): `undefined` \| `V`
3988
-
3989
- Defined in: [aberdeen.ts:3107](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L3107)
3990
-
3991
- Executes a function or retrieves a value *without* creating subscriptions in the current reactive scope, and returns its result.
3992
-
3993
- This is useful when you need to access reactive data inside a reactive scope (like [A](#a))
3994
- but do not want changes to that specific data to trigger a re-execute of the scope.
3995
-
3996
- Note: You may also use [unproxy](#unproxy) to get to the raw underlying data structure, which can be used to similar effect.
3997
-
3998
- ##### Type Parameters
3999
-
4000
- ###### K
4001
-
4002
- `K`
4003
-
4004
- ###### V
4005
-
4006
- `V`
4007
-
4008
- ##### Parameters
4009
-
4010
- ###### target
4011
-
4012
- `Map`\<`K`, `V`\>
4013
-
4014
- Either a function to execute, or an object (which may also be an Array or a Map) to index.
4015
-
4016
- ###### key
4017
-
4018
- `K`
4019
-
4020
- Optional key/index to use when `target` is an object.
4021
-
4022
- ##### Returns
4023
-
4024
- `undefined` \| `V`
4025
-
4026
- The result of the function call, or the value at `target[key]` when `target` is an object or `target.get(key)` when it's a Map.
4027
-
4028
- ##### Example
4029
-
4030
- ```typescript
4031
- const $data = A.proxy({ a: 1, b: 2 });
4032
- A(() => {
4033
- // re-executes only when $data.a changes, because $data.b is peeked.
4034
- const b = A.peek(() => $data.b);
4035
- console.log(`A is ${$data.a}, B was ${b} when A changed.`);
4036
- });
4037
- $data.b = 3; // Does not trigger console.log
4038
- $data.a = 2; // Triggers console.log (logs "A is 2, B was 3 when A changed.")
4039
- ```
4040
-
4041
- #### Call Signature
4042
-
4043
- > **peek**\<`T`\>(`target`, `key`): `undefined` \| `T`
4044
-
4045
- Defined in: [aberdeen.ts:3108](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L3108)
4046
-
4047
- Executes a function or retrieves a value *without* creating subscriptions in the current reactive scope, and returns its result.
4048
-
4049
- This is useful when you need to access reactive data inside a reactive scope (like [A](#a))
4050
- but do not want changes to that specific data to trigger a re-execute of the scope.
4051
-
4052
- Note: You may also use [unproxy](#unproxy) to get to the raw underlying data structure, which can be used to similar effect.
4053
-
4054
- ##### Type Parameters
4055
-
4056
- ###### T
4057
-
4058
- `T`
4059
-
4060
- ##### Parameters
4061
-
4062
- ###### target
4063
-
4064
- `T`[]
4065
-
4066
- Either a function to execute, or an object (which may also be an Array or a Map) to index.
4067
-
4068
- ###### key
4069
-
4070
- `number`
4071
-
4072
- Optional key/index to use when `target` is an object.
4073
-
4074
- ##### Returns
4075
-
4076
- `undefined` \| `T`
4077
-
4078
- The result of the function call, or the value at `target[key]` when `target` is an object or `target.get(key)` when it's a Map.
4079
-
4080
- ##### Example
4081
-
4082
- ```typescript
4083
- const $data = A.proxy({ a: 1, b: 2 });
4084
- A(() => {
4085
- // re-executes only when $data.a changes, because $data.b is peeked.
4086
- const b = A.peek(() => $data.b);
4087
- console.log(`A is ${$data.a}, B was ${b} when A changed.`);
4088
- });
4089
- $data.b = 3; // Does not trigger console.log
4090
- $data.a = 2; // Triggers console.log (logs "A is 2, B was 3 when A changed.")
4091
- ```
4092
-
4093
- #### Call Signature
4094
-
4095
- > **peek**\<`T`\>(`target`): `T`
4096
-
4097
- Defined in: [aberdeen.ts:3109](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L3109)
4098
-
4099
- Executes a function or retrieves a value *without* creating subscriptions in the current reactive scope, and returns its result.
4100
-
4101
- This is useful when you need to access reactive data inside a reactive scope (like [A](#a))
4102
- but do not want changes to that specific data to trigger a re-execute of the scope.
4103
-
4104
- Note: You may also use [unproxy](#unproxy) to get to the raw underlying data structure, which can be used to similar effect.
4105
-
4106
- ##### Type Parameters
4107
-
4108
- ###### T
4109
-
4110
- `T`
4111
-
4112
- ##### Parameters
4113
-
4114
- ###### target
4115
-
4116
- () => `T`
4117
-
4118
- Either a function to execute, or an object (which may also be an Array or a Map) to index.
4119
-
4120
- ##### Returns
4121
-
4122
- `T`
4123
-
4124
- The result of the function call, or the value at `target[key]` when `target` is an object or `target.get(key)` when it's a Map.
4125
-
4126
- ##### Example
4127
-
4128
- ```typescript
4129
- const $data = A.proxy({ a: 1, b: 2 });
4130
- A(() => {
4131
- // re-executes only when $data.a changes, because $data.b is peeked.
4132
- const b = A.peek(() => $data.b);
4133
- console.log(`A is ${$data.a}, B was ${b} when A changed.`);
4134
- });
4135
- $data.b = 3; // Does not trigger console.log
4136
- $data.a = 2; // Triggers console.log (logs "A is 2, B was 3 when A changed.")
4137
- ```
4138
-
4139
- ***
4140
-
4141
- ### proxy()
4142
-
4143
- Creates a reactive proxy around the given data.
4144
-
4145
- Reading properties from the returned proxy within a reactive scope (like one created by
4146
- [A](#a) or [derive](#derive)) establishes a subscription. Modifying properties *through*
4147
- the proxy will notify subscribed scopes, causing them to re-execute.
4148
-
4149
- - Plain objects, arrays, Maps, and Sets are wrapped in a standard JavaScript `Proxy` that intercepts
4150
- property access and mutations, but otherwise works like the underlying data.
4151
- - Primitives (string, number, boolean, null, undefined) are wrapped in an object
4152
- `{ value: T }` which is then proxied. Access the primitive via the `.value` property.
4153
- - Promises are represented by proxied objects `{ busy: boolean, value?: T, error?: any }`.
4154
- Initially, `busy` is `true`. When the promise resolves, `value` is set and `busy`
4155
- is set to `false`. If the promise is rejected, `error` is set and `busy` is also
4156
- set to `false`.
4157
-
4158
- Use [unproxy](#unproxy) to get the original underlying data back.
4159
- By convention in the examples below, local variables that hold proxied values are prefixed with `$`.
4160
-
4161
- #### Param
4162
-
4163
- The object, array, Map, Set, or primitive value to make reactive.
4164
-
4165
- #### Template
4166
-
4167
- The type of the data being proxied.
4168
-
4169
- #### Examples
4170
-
4171
- ```javascript
4172
- const $state = A.proxy({ count: 0, message: 'Hello' });
4173
- A(() => console.log($state.message)); // Subscribes to message
4174
- setTimeout(() => $state.message = 'World', 1000); // Triggers the observing function
4175
- setTimeout(() => $state.count++, 2000); // Triggers nothing
4176
- ```
4177
-
4178
- ```javascript
4179
- const $items = A.proxy(['a', 'b']);
4180
- A(() => console.log($items.length)); // Subscribes to length
4181
- setTimeout(() => $items.push('c'), 2000); // Triggers the observing function
4182
- ```
4183
-
4184
- ```javascript
4185
- const $name = A.proxy('Aberdeen');
4186
- A(() => console.log($name.value)); // Subscribes to value
4187
- setTimeout(() => $name.value = 'UI', 2000); // Triggers the observing function
4188
- ```
4189
-
4190
- ```javascript
4191
- const $tags = A.proxy(new Set(['ui', 'tiny']));
4192
- A(() => console.log($tags.has('ui'), $tags.size));
4193
- setTimeout(() => $tags.add('fast'), 1000);
4194
- ```
4195
-
4196
- ```typescript
4197
- class Widget {
4198
- constructor(public name: string, public width: number, public height: number) {}
4199
- grow() { this.width *= 2; }
4200
- toString() { return `${this.name}Widget (${this.width}x${this.height})`; }
4201
- }
4202
- let $graph: Widget = A.proxy(new Widget('Graph', 200, 100));
4203
- A(() => console.log(''+$graph));
4204
- setTimeout(() => $graph.grow(), 2000);
4205
- setTimeout(() => $graph.grow(), 4000);
4206
- ```
4207
-
4208
- #### Call Signature
4209
-
4210
- > **proxy**\<`T`\>(`target`): [`PromiseProxy`](#promiseproxy)\<`T`\>
4211
-
4212
- Defined in: [aberdeen.ts:1546](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L1546)
4213
-
4214
- ##### Type Parameters
4215
-
4216
- ###### T
4217
-
4218
- `T` *extends* `unknown`
4219
-
4220
- ##### Parameters
4221
-
4222
- ###### target
4223
-
4224
- `Promise`\<`T`\>
4225
-
4226
- ##### Returns
4227
-
4228
- [`PromiseProxy`](#promiseproxy)\<`T`\>
4229
-
4230
- #### Call Signature
4231
-
4232
- > **proxy**\<`T`\>(`target`): `T` *extends* `number` ? `number` : `T` *extends* `string` ? `string` : `T` *extends* `boolean` ? `boolean` : `T`[]
4233
-
4234
- Defined in: [aberdeen.ts:1547](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L1547)
4235
-
4236
- ##### Type Parameters
4237
-
4238
- ###### T
4239
-
4240
- `T` *extends* `unknown`
4241
-
4242
- ##### Parameters
4243
-
4244
- ###### target
4245
-
4246
- `T`[]
4247
-
4248
- ##### Returns
4249
-
4250
- `T` *extends* `number` ? `number` : `T` *extends* `string` ? `string` : `T` *extends* `boolean` ? `boolean` : `T`[]
4251
-
4252
- #### Call Signature
4253
-
4254
- > **proxy**\<`T`\>(`target`): `T`
4255
-
4256
- Defined in: [aberdeen.ts:1548](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L1548)
4257
-
4258
- ##### Type Parameters
4259
-
4260
- ###### T
4261
-
4262
- `T` *extends* `object`
4263
-
4264
- ##### Parameters
4265
-
4266
- ###### target
4267
-
4268
- `T`
4269
-
4270
- ##### Returns
4271
-
4272
- `T`
4273
-
4274
- #### Call Signature
4275
-
4276
- > **proxy**\<`T`\>(`target`): `ValueRef`\<`T` *extends* `number` ? `number` : `T` *extends* `string` ? `string` : `T` *extends* `boolean` ? `boolean` : `T`\>
4277
-
4278
- Defined in: [aberdeen.ts:1549](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L1549)
4279
-
4280
- ##### Type Parameters
4281
-
4282
- ###### T
4283
-
4284
- `T` *extends* `unknown`
4285
-
4286
- ##### Parameters
4287
-
4288
- ###### target
4289
-
4290
- `T`
4291
-
4292
- ##### Returns
4293
-
4294
- `ValueRef`\<`T` *extends* `number` ? `number` : `T` *extends* `string` ? `string` : `T` *extends* `boolean` ? `boolean` : `T`\>
4295
-
4296
- ***
4297
-
4298
- ### ref()
4299
-
4300
- > **ref**\<`T`, `K`\>(`target`, `index`): `ValueRef`\<`T`\[`K`\]\>
4301
-
4302
- Defined in: [aberdeen.ts:2160](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L2160)
4303
-
4304
- Creates a reactive reference (`{ value: T }`-like object) to a specific value
4305
- within a proxied object or array.
4306
-
4307
- This is primarily used for the `bind` property in [A](#a) to create two-way data bindings
4308
- with form elements, and for passing a reactive property to any of the [A](#a) key-value pairs.
4309
-
4310
- Reading `ref.value` accesses the property from the underlying proxy (and subscribes the current scope).
4311
- Assigning to `ref.value` updates the property in the underlying proxy (triggering reactive updates).
4312
-
4313
- #### Type Parameters
4314
-
4315
- ##### T
4316
-
4317
- `T` *extends* `TargetType`
4318
-
4319
- ##### K
4320
-
4321
- `K` *extends* `string` \| `number` \| `symbol`
4322
-
4323
- #### Parameters
4324
-
4325
- ##### target
4326
-
4327
- `T`
4328
-
4329
- The reactive proxy (created by [proxy](#proxy)) containing the target property.
4330
-
4331
- ##### index
4332
-
4333
- `K`
4334
-
4335
- The key (for objects) or index (for arrays) of the property to reference.
4336
-
4337
- #### Returns
4338
-
4339
- `ValueRef`\<`T`\[`K`\]\>
4340
-
4341
- A reference object with a `value` property linked to the specified proxy property.
4342
-
4343
- #### Example
4344
-
4345
- ```javascript
4346
- const $formData = A.proxy({ color: 'orange', velocity: 42 });
4347
-
4348
- // Usage with `bind`
4349
- A('input type=text bind=', A.ref($formData, 'color'));
4350
-
4351
- // Usage as a dynamic property, causes a TextNode with just the name to be created and live-updated
4352
- A('p text="Selected color: " text=', A.ref($formData, 'color'), 'color:', A.ref($formData, 'color'));
4353
-
4354
- // Changes are actually stored in $formData - this causes logs like `{color: "Blue", velocity 42}`
4355
- A(() => console.log($formData))
4356
- ```
4357
-
4358
- ***
4359
-
4360
- ### runQueue()
4361
-
4362
- > **runQueue**(): `void`
4363
-
4364
- Defined in: [aberdeen.ts:110](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L110)
4365
-
4366
- Forces the immediate and synchronous execution of all pending reactive updates.
4367
-
4368
- Normally, changes to observed data sources (like proxied objects or arrays)
4369
- are processed asynchronously in a batch after a brief timeout (0ms). This function
4370
- allows you to bypass the timeout and process the update queue immediately.
4371
-
4372
- This can be useful in specific scenarios where you need the DOM to be updated
4373
- synchronously.
4374
-
4375
- This function is re-entrant, meaning it is safe to call `runQueue` from within
4376
- a function that is itself being executed as part of an update cycle triggered
4377
- by a previous (or the same) `runQueue` call.
4378
-
4379
- #### Returns
4380
-
4381
- `void`
4382
-
4383
- #### Example
4384
-
4385
- ```typescript
4386
- const $data = A.proxy("before");
4387
-
4388
- A('#', $data);
4389
- console.log(1, document.body.innerHTML); // before
4390
-
4391
- // Make an update that should cause the DOM to change.
4392
- $data.value = "after";
4393
-
4394
- // Normally, the DOM update would happen after a timeout.
4395
- // But this causes an immediate update:
4396
- A.runQueue();
4397
-
4398
- console.log(2, document.body.innerHTML); // after
4399
- ```
4400
-
4401
- ***
4402
-
4403
- ### setErrorHandler()
4404
-
4405
- > **setErrorHandler**(`handler?`): `void`
4406
-
4407
- Defined in: [aberdeen.ts:2921](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L2921)
4408
-
4409
- Sets a custom error handler function for errors that occur asynchronously
4410
- within reactive scopes (e.g., during updates triggered by proxy changes in
4411
- [derive](#derive) or [A](#a) render functions).
4412
-
4413
- The default handler logs the error to `console.error` and adds a simple
4414
- 'Error' message div to the DOM at the location where the error occurred (if possible).
4415
-
4416
- Your handler can provide custom logging, UI feedback, or suppress the default
4417
- error message.
4418
-
4419
- #### Parameters
4420
-
4421
- ##### handler?
4422
-
4423
- (`error`) => `undefined` \| `boolean`
4424
-
4425
- A function that accepts the `Error` object.
4426
- - Return `false` to prevent adding an error message to the DOM.
4427
- - Return `true` or `undefined` (or throw) to allow the error messages to be added to the DOM.
4428
-
4429
- #### Returns
4430
-
4431
- `void`
4432
-
4433
- #### Example
4434
-
4435
- ```typescript
4436
- A.setErrorHandler(error => {
4437
- console.warn('Aberdeen render error:', error.message);
4438
- // Log to error reporting service
4439
- // myErrorReporter.log(error);
4440
-
4441
- try {
4442
- // Attempt to show a custom message in the UI
4443
- A('div#Oops, something went wrong!', errorClass);
4444
- } catch (e) {
4445
- // Ignore errors during error handling itself
4446
- }
4447
-
4448
- return false; // Suppress default console log and DOM error message
4449
- });
4450
-
4451
- // Styling for our custom error message
4452
- const errorClass = A.insertCss('background-color:#e31f00 display:inline-block color:white r:3px padding: 2px 4px;');
4453
-
4454
- // Cause an error within a render scope.
4455
- A('div.box', () => {
4456
- // Will cause our error handler to insert an error message within the box
4457
- noSuchFunction();
4458
- })
4459
- ```
4460
-
4461
- ***
4462
-
4463
- ### setSpacingCssVars()
4464
-
4465
- > **setSpacingCssVars**(`base`, `unit`): `void`
4466
-
4467
- Defined in: [aberdeen.ts:2003](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L2003)
4468
-
4469
- Initializes `cssVars[0]` through `cssVars[12]` with an exponential spacing scale.
4470
-
4471
- The scale is calculated as `2^(n-3) * base`, providing values from `0.25 * base` to `512 * base`.
4472
-
4473
- #### Parameters
4474
-
4475
- ##### base
4476
-
4477
- `number` = `1`
4478
-
4479
- The base size for the spacing scale that will apply to `cssVars[3]`. Every step up the scale will double this, while every step down will halve it. Defaults to 1.
4480
-
4481
- ##### unit
4482
-
4483
- `string` = `'rem'`
4484
-
4485
- The CSS unit to use, like 'rem', 'em', or 'px'. Defaults to 'rem'.
4486
-
4487
- #### Returns
4488
-
4489
- `void`
4490
-
4491
- #### Example
4492
-
4493
- ```javascript
4494
- import A from 'aberdeen';
4495
- // Use default scale (0.25rem to 512rem)
4496
- A.setSpacingCssVars();
4497
-
4498
- // Use custom base size
4499
- A.setSpacingCssVars(16, 'px'); // 4px to 8192px
4500
-
4501
- // Use em units
4502
- A.setSpacingCssVars(1, 'em'); // 0.25em to 512em
4503
-
4504
- // Show the last generated spacing values
4505
- A.onEach(A.cssVars, (value, key) => {
4506
- A(`div #${key} → ${value}`)
4507
- }, (value, key) => parseInt(key)); // Numeric sort
4508
- ```
4509
-
4510
- ***
4511
-
4512
- ### unmountAll()
4513
-
4514
- > **unmountAll**(): `void`
4515
-
4516
- Defined in: [aberdeen.ts:3075](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L3075)
4517
-
4518
- Removes all Aberdeen-managed DOM nodes and stops all active reactive scopes
4519
- (created by [mount](#mount), [derive](#derive), [A](#a) with functions, etc.).
4520
-
4521
- This effectively cleans up the entire Aberdeen application state. Aside from in
4522
- automated tests, there should probably be little reason to call this function.
4523
-
4524
- #### Returns
4525
-
4526
- `void`
4527
-
4528
- ***
4529
-
4530
- ### unproxy()
4531
-
4532
- > **unproxy**\<`T`\>(`target`): `T`
4533
-
4534
- Defined in: [aberdeen.ts:1671](https://github.com/vanviegen/aberdeen/blob/ae96ee5d2bf101de8d04c7efc61a03e8fe8fe6f7/src/aberdeen.ts#L1671)
4535
-
4536
- Returns the original, underlying data target from a reactive proxy created by [proxy](#proxy).
4537
- If the input `target` is not a proxy, it is returned directly.
4538
-
4539
- This is useful when you want to avoid triggering subscriptions during read operations or
4540
- re-executes during write operations. Using [peek](#peek) is an alternative way to achieve this.
4541
-
4542
- #### Type Parameters
4543
-
4544
- ##### T
4545
-
4546
- `T`
4547
-
4548
- The type of the target.
4549
-
4550
- #### Parameters
4551
-
4552
- ##### target
4553
-
4554
- `T`
4555
-
4556
- A proxied object, array, or any other value.
4557
-
4558
- #### Returns
4559
-
4560
- `T`
4561
-
4562
- The underlying (unproxied) data, or the input value if it wasn't a proxy.
4563
-
4564
- #### Example
4565
-
4566
- ```typescript
4567
- const $user = A.proxy({ name: 'Frank' });
4568
- const rawUser = A.unproxy($user);
4569
-
4570
- // Log reactively
4571
- A(() => console.log('proxied', $user.name));
4572
- // The following will only ever log once, as we're not subscribing to any observable
4573
- A(() => console.log('unproxied', rawUser.name));
4574
-
4575
- // This cause the first log to run again:
4576
- setTimeout(() => $user.name += '!', 1000);
4577
-
4578
- // This doesn't cause any new logs:
4579
- setTimeout(() => rawUser.name += '?', 2000);
4580
-
4581
- // Both $user and rawUser end up as `{name: 'Frank!?'}`
4582
- setTimeout(() => {
4583
- console.log('final proxied', $user)
4584
- console.log('final unproxied', rawUser)
4585
- }, 3000);
4586
- ```