aberdeen 1.4.3 → 1.6.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.
- package/dist/aberdeen.d.ts +72 -7
- package/dist/aberdeen.js +52 -7
- package/dist/aberdeen.js.map +3 -3
- package/dist/route.js +4 -4
- package/dist/route.js.map +3 -3
- package/dist-min/aberdeen.js +7 -5
- package/dist-min/aberdeen.js.map +3 -3
- package/dist-min/route.js.map +2 -2
- package/package.json +5 -2
- package/skill/SKILL.md +579 -199
- package/skill/aberdeen.md +2322 -0
- package/skill/dispatcher.md +126 -0
- package/skill/prediction.md +73 -0
- package/skill/route.md +249 -0
- package/skill/transitions.md +59 -0
- package/src/aberdeen.ts +129 -15
- package/src/route.ts +3 -3
- package/skill/references/prediction.md +0 -45
- package/skill/references/routing.md +0 -81
- package/skill/references/transitions.md +0 -52
|
@@ -0,0 +1,2322 @@
|
|
|
1
|
+
[**Aberdeen v1.6.0**](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:1315](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L1315)
|
|
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:1319](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L1319)
|
|
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:1327](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L1327)
|
|
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:1323](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L1323)
|
|
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:1737](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L1737)
|
|
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 { cssVars, setSpacingCssVars, $ } from 'aberdeen';
|
|
73
|
+
|
|
74
|
+
// Optionally initialize spacing scale
|
|
75
|
+
setSpacingCssVars(); // Uses defaults: base=1, unit='rem'
|
|
76
|
+
|
|
77
|
+
// Define custom colors - style tag is automatically created
|
|
78
|
+
cssVars.primary = '#3b82f6';
|
|
79
|
+
cssVars.danger = '#ef4444';
|
|
80
|
+
|
|
81
|
+
// Use in elements with the $ prefix
|
|
82
|
+
$('button bg:$primary fg:white');
|
|
83
|
+
|
|
84
|
+
// Use spacing (if setSpacingCssVars() was called)
|
|
85
|
+
$('div mt:$3'); // Sets margin-top to var(--m3)
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
***
|
|
89
|
+
|
|
90
|
+
### NO\_COPY
|
|
91
|
+
|
|
92
|
+
> `const` **NO\_COPY**: *typeof* [`NO_COPY`](#no_copy)
|
|
93
|
+
|
|
94
|
+
Defined in: [aberdeen.ts:1701](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L1701)
|
|
95
|
+
|
|
96
|
+
A symbol that can be added to an object to prevent it from being cloned by [clone](#clone) or [copy](#copy).
|
|
97
|
+
This is useful for objects that should be shared by reference. That also mean that their contents won't
|
|
98
|
+
be observed for changes.
|
|
99
|
+
|
|
100
|
+
## Functions
|
|
101
|
+
|
|
102
|
+
### $()
|
|
103
|
+
|
|
104
|
+
> **$**(...`args`): `undefined` \| `Element`
|
|
105
|
+
|
|
106
|
+
Defined in: [aberdeen.ts:2079](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L2079)
|
|
107
|
+
|
|
108
|
+
The core function for building reactive user interfaces in Aberdeen. It creates and inserts new DOM elements
|
|
109
|
+
and sets attributes/properties/event listeners on DOM elements. It does so in a reactive way, meaning that
|
|
110
|
+
changes will be (mostly) undone when the current *scope* is destroyed or will be re-execute.
|
|
111
|
+
|
|
112
|
+
#### Parameters
|
|
113
|
+
|
|
114
|
+
##### args
|
|
115
|
+
|
|
116
|
+
...`any`[]
|
|
117
|
+
|
|
118
|
+
Any number of arguments can be given. How they're interpreted depends on their types:
|
|
119
|
+
|
|
120
|
+
- `string`: Strings can be used to create and insert new elements, set classnames for the *current* element, and add text to the current element.
|
|
121
|
+
The format of a string is: (**tag** | `.` **class** | **key**=**val** | **key**="**long val**")* ('#' **text** | **key**=)?
|
|
122
|
+
So there can be:
|
|
123
|
+
- Any number of **tag** element, like `h1` or `div`. These elements are created, added to the *current* element, and become the new *current* element for the rest of this `$` function execution.
|
|
124
|
+
- Any number of 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.
|
|
125
|
+
- Any number of key/value pairs with string values, like `placeholder="Your name"` or `data-id=123`. These will be handled according to the rules specified for `object`, below, but with the caveat that values can only be strings. The quotes around string values are optional, unless the value contains spaces. It's not possible to escape quotes within the value. If you want to do that, or if you have user-provided values, use the `object` syntax (see below) or end your string with `key=` followed by the data as a separate argument (see below).
|
|
126
|
+
- The string may end in 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.
|
|
127
|
+
- Alternatively, the string may end in 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 rules specified for `object` below. This is useful when the value is not a string or contains spaces or user data. Example: `$('button text="Click me" click=', () => alert('Clicked!'))` or `$('input.value=', someUserData, "placeholder=", "Type your stuff")`.
|
|
128
|
+
- `function`: When a function (without argument nor a return value) is passed in, it will be reactively executed in its own observer scope, preserving the *current element*. So any `$()` invocations within this function will create DOM elements with our *current* element as parent. 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 `$`, have been cleaned - see also [clean](#clean)).
|
|
129
|
+
- `object`: When an object is passed in, its key-value pairs are used to modify the *current* element in the following ways...
|
|
130
|
+
- `{<attrName>: any}`: The common case is setting the value as an HTML attribute named key. So `{placeholder: "Your name"}` would add `placeholder="Your name"` to the current HTML element.
|
|
131
|
+
- `{<propName>: boolean}` or `{value: any}` or `{selectedIndex: number}`: If the value is a boolean, or if the key is `value` or `selectedIndex`, it is set on the `current` element as a DOM property instead of an HTML attribute. For example `{checked: true}` would do `el.checked = true` for the *current* element.
|
|
132
|
+
- `{".class": boolean}`: 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 `{".hidden": hide}` would toggle the `hidden` CSS class.
|
|
133
|
+
- `{<eventName>: function}`: 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: `{click: myClickHandler}`.
|
|
134
|
+
- `{$<styleProp>: value}`: If the key starts with a `$` character, set a CSS style property with the name of the rest of the key to the given value. Example: `{$backgroundColor: 'red'}`.
|
|
135
|
+
- `{create: string}`: Add the value string as a CSS class to the *current* element, *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`.
|
|
136
|
+
- `{destroy: string}`: When the *current* element is a top-level element to be removed (due to reactivity cleanup), 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`.
|
|
137
|
+
- `{create: function}` and `{destroy: function}`: The function is invoked when the *current* element is the top-level element being created/destroyed. It can be used for more involved creation/deletion animations. In case of `destroy`, the function is responsible for actually removing the element from the DOM (eventually). See `transitions.ts` in the Aberdeen source code for some examples.
|
|
138
|
+
- `{bind: <obsValue>}`: Create a two-way binding element between the `value` property of the given observable (proxy) variable, and the *current* input element (`<input>`, `<select>` or `<textarea>`). This is often used together with [ref](#ref), in order to use properties other than `.value`.
|
|
139
|
+
- `{<any>: <obsvalue>}`: Create a new observer scope and read the `value` property of the given observable (proxy) variable from within it, and apply the contained value using any of the other rules in this list. Example:
|
|
140
|
+
```typescript
|
|
141
|
+
const myColor = proxy('red');
|
|
142
|
+
$('p#Test', {$color: myColor, click: () => myColor.value = 'yellow'})
|
|
143
|
+
// Clicking the text will cause it to change color without recreating the <p> itself
|
|
144
|
+
```
|
|
145
|
+
This is often used together with [ref](#ref), in order to use properties other than `.value`.
|
|
146
|
+
- `{text: string|number}`: Add the value as a `TextNode` to the *current* element.
|
|
147
|
+
- `{html: string}`: Add the value as HTML to the *current* element. This should only be used in exceptional situations. And of course, beware of XSS.
|
|
148
|
+
- `Node`: If 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 `$` function execution.
|
|
149
|
+
|
|
150
|
+
#### Returns
|
|
151
|
+
|
|
152
|
+
`undefined` \| `Element`
|
|
153
|
+
|
|
154
|
+
The most inner DOM element that was created (not counting text nodes nor elements created by content functions),
|
|
155
|
+
or undefined if no elements were created.
|
|
156
|
+
|
|
157
|
+
#### Examples
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
$('button.secondary.outline text=Submit color:red disabled=', false, 'click=', () => console.log('Clicked!'));
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
We want to set `disabled` as a property instead of an attribute, so we must use the `key=` syntax in order to provide
|
|
164
|
+
`false` as a boolean instead of a string.
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
let inputElement: Element = $('label text="Click me" input type=checkbox');
|
|
168
|
+
// You should usually not touch raw DOM elements, unless when integrating
|
|
169
|
+
// with non-Aberdeen code.
|
|
170
|
+
console.log('DOM element:', inputElement);
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
const state = proxy({ count: 0 });
|
|
175
|
+
$('div', () => { // Outer element
|
|
176
|
+
// This scope re-renders when state.count changes
|
|
177
|
+
$(`p#Count is ${state.count}`);
|
|
178
|
+
$('button text=Increment click=', () => state.count++);
|
|
179
|
+
});
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
const user = proxy({ name: '' });
|
|
184
|
+
$('input placeholder=Name bind=', ref(user, 'name'));
|
|
185
|
+
$('h3', () => { // Reactive scope
|
|
186
|
+
$(`#Hello ${user.name || 'stranger'}`);
|
|
187
|
+
});
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
const show = proxy(false);
|
|
192
|
+
$('button click=', () => show.value = !show.value, () => $(show.value ? '#Hide' : '#Show'));
|
|
193
|
+
$(() => { // Reactive scope
|
|
194
|
+
if (show.value) {
|
|
195
|
+
$('p#Details are visible!');
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
***
|
|
201
|
+
|
|
202
|
+
### clean()
|
|
203
|
+
|
|
204
|
+
> **clean**(`cleaner`): `void`
|
|
205
|
+
|
|
206
|
+
Defined in: [aberdeen.ts:2481](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L2481)
|
|
207
|
+
|
|
208
|
+
Registers a cleanup function to be executed just before the current reactive scope
|
|
209
|
+
is destroyed or redraws.
|
|
210
|
+
|
|
211
|
+
This is useful for releasing resources, removing manual event listeners, or cleaning up
|
|
212
|
+
side effects associated with the scope. Cleaners are run in reverse order of registration.
|
|
213
|
+
|
|
214
|
+
Scopes are created by functions like [derive](#derive), [mount](#mount), [$](#) (when given a render function),
|
|
215
|
+
and internally by constructs like [onEach](#oneach).
|
|
216
|
+
|
|
217
|
+
#### Parameters
|
|
218
|
+
|
|
219
|
+
##### cleaner
|
|
220
|
+
|
|
221
|
+
() => `void`
|
|
222
|
+
|
|
223
|
+
The function to execute during cleanup.
|
|
224
|
+
|
|
225
|
+
#### Returns
|
|
226
|
+
|
|
227
|
+
`void`
|
|
228
|
+
|
|
229
|
+
#### Example
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
const myArray = proxy([3, 5, 10]);
|
|
233
|
+
let sum = proxy(0);
|
|
234
|
+
|
|
235
|
+
// Show the array items and maintain the sum
|
|
236
|
+
onEach(myArray, (item, index) => {
|
|
237
|
+
$(`code#${index}→${item}`);
|
|
238
|
+
// We'll update sum.value using peek, as += first does a read, but
|
|
239
|
+
// we don't want to subscribe.
|
|
240
|
+
peek(() => sum.value += item);
|
|
241
|
+
// Clean gets called before each rerun for a certain item index
|
|
242
|
+
// No need for peek here, as the clean code doesn't run in an
|
|
243
|
+
// observer scope.
|
|
244
|
+
clean(() => sum.value -= item);
|
|
245
|
+
})
|
|
246
|
+
|
|
247
|
+
// Show the sum
|
|
248
|
+
$('h1 text=', sum);
|
|
249
|
+
|
|
250
|
+
// Make random changes to the array
|
|
251
|
+
const rnd = () => 0|(Math.random()*20);
|
|
252
|
+
setInterval(() => myArray[rnd()] = rnd(), 1000);
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
***
|
|
256
|
+
|
|
257
|
+
### clone()
|
|
258
|
+
|
|
259
|
+
> **clone**\<`T`\>(`src`): `T`
|
|
260
|
+
|
|
261
|
+
Defined in: [aberdeen.ts:1845](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L1845)
|
|
262
|
+
|
|
263
|
+
Clone an (optionally proxied) object or array.
|
|
264
|
+
|
|
265
|
+
#### Type Parameters
|
|
266
|
+
|
|
267
|
+
##### T
|
|
268
|
+
|
|
269
|
+
`T` *extends* `object`
|
|
270
|
+
|
|
271
|
+
The type of the objects being copied.
|
|
272
|
+
|
|
273
|
+
#### Parameters
|
|
274
|
+
|
|
275
|
+
##### src
|
|
276
|
+
|
|
277
|
+
`T`
|
|
278
|
+
|
|
279
|
+
The object or array to clone. If it is proxied, `clone` will subscribe to any changes to the (nested) data structure.
|
|
280
|
+
|
|
281
|
+
#### Returns
|
|
282
|
+
|
|
283
|
+
`T`
|
|
284
|
+
|
|
285
|
+
A new unproxied array or object (of the same type as `src`), containing a deep copy of `src`.
|
|
286
|
+
|
|
287
|
+
***
|
|
288
|
+
|
|
289
|
+
### copy()
|
|
290
|
+
|
|
291
|
+
#### Call Signature
|
|
292
|
+
|
|
293
|
+
> **copy**\<`T`\>(`dst`, `src`): `boolean`
|
|
294
|
+
|
|
295
|
+
Defined in: [aberdeen.ts:1490](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L1490)
|
|
296
|
+
|
|
297
|
+
Recursively copies properties or array items from `src` to `dst`.
|
|
298
|
+
It's designed to work efficiently with reactive proxies created by [proxy](#proxy).
|
|
299
|
+
|
|
300
|
+
- **Minimizes Updates:** When copying between objects/arrays (proxied or not), if a nested object
|
|
301
|
+
exists in `dst` with the same constructor as the corresponding object in `src`, `copy`
|
|
302
|
+
will recursively copy properties into the existing `dst` object instead of replacing it.
|
|
303
|
+
This minimizes change notifications for reactive updates.
|
|
304
|
+
- **Handles Proxies:** Can accept proxied or unproxied objects/arrays for both `dst` and `src`.
|
|
305
|
+
- **Cross-Type Copying:** Supports copying between Maps and objects. When copying from an object
|
|
306
|
+
to a Map, object properties become Map entries. When copying from a Map to an object, Map entries
|
|
307
|
+
become object properties (only for Maps with string/number/symbol keys).
|
|
308
|
+
|
|
309
|
+
##### Type Parameters
|
|
310
|
+
|
|
311
|
+
###### T
|
|
312
|
+
|
|
313
|
+
`T` *extends* `object`
|
|
314
|
+
|
|
315
|
+
The type of the objects being copied.
|
|
316
|
+
|
|
317
|
+
##### Parameters
|
|
318
|
+
|
|
319
|
+
###### dst
|
|
320
|
+
|
|
321
|
+
`T`
|
|
322
|
+
|
|
323
|
+
The destination object/array/Map (proxied or unproxied).
|
|
324
|
+
|
|
325
|
+
###### src
|
|
326
|
+
|
|
327
|
+
`T`
|
|
328
|
+
|
|
329
|
+
The source object/array/Map (proxied or unproxied). It won't be modified.
|
|
330
|
+
|
|
331
|
+
##### Returns
|
|
332
|
+
|
|
333
|
+
`boolean`
|
|
334
|
+
|
|
335
|
+
`true` if any changes were made to `dst`, or `false` if not.
|
|
336
|
+
|
|
337
|
+
##### Throws
|
|
338
|
+
|
|
339
|
+
Error if attempting to copy an array into a non-array or vice versa.
|
|
340
|
+
|
|
341
|
+
##### Example
|
|
342
|
+
|
|
343
|
+
```typescript
|
|
344
|
+
const source = proxy({ a: 1, b: { c: 2 } });
|
|
345
|
+
const dest = proxy({ b: { d: 3 } });
|
|
346
|
+
copy(dest, source);
|
|
347
|
+
console.log(dest); // proxy({ a: 1, b: { c: 2 } })
|
|
348
|
+
copy(dest, 'b', { e: 4 });
|
|
349
|
+
console.log(dest); // proxy({ a: 1, b: { e: 4 } })
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
#### Call Signature
|
|
353
|
+
|
|
354
|
+
> **copy**\<`T`\>(`dst`, `dstKey`, `src`): `boolean`
|
|
355
|
+
|
|
356
|
+
Defined in: [aberdeen.ts:1497](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L1497)
|
|
357
|
+
|
|
358
|
+
Like above, but copies `src` into `dst[dstKey]`. This is useful if you're unsure if dst[dstKey]
|
|
359
|
+
already exists (as the right type of object) or if you don't want to subscribe to dst[dstKey].
|
|
360
|
+
|
|
361
|
+
##### Type Parameters
|
|
362
|
+
|
|
363
|
+
###### T
|
|
364
|
+
|
|
365
|
+
`T` *extends* `object`
|
|
366
|
+
|
|
367
|
+
##### Parameters
|
|
368
|
+
|
|
369
|
+
###### dst
|
|
370
|
+
|
|
371
|
+
`T`
|
|
372
|
+
|
|
373
|
+
###### dstKey
|
|
374
|
+
|
|
375
|
+
keyof `T`
|
|
376
|
+
|
|
377
|
+
Optional key in `dst` to copy into.
|
|
378
|
+
|
|
379
|
+
###### src
|
|
380
|
+
|
|
381
|
+
`T`\[keyof `T`\]
|
|
382
|
+
|
|
383
|
+
##### Returns
|
|
384
|
+
|
|
385
|
+
`boolean`
|
|
386
|
+
|
|
387
|
+
***
|
|
388
|
+
|
|
389
|
+
### count()
|
|
390
|
+
|
|
391
|
+
> **count**(`proxied`): `ValueRef`\<`number`\>
|
|
392
|
+
|
|
393
|
+
Defined in: [aberdeen.ts:1012](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L1012)
|
|
394
|
+
|
|
395
|
+
Reactively counts the number of properties in an objects.
|
|
396
|
+
|
|
397
|
+
#### Parameters
|
|
398
|
+
|
|
399
|
+
##### proxied
|
|
400
|
+
|
|
401
|
+
`TargetType`
|
|
402
|
+
|
|
403
|
+
The observable object to count. In case an `array` is passed in, a [ref](#ref) to its `.length` will be returned.
|
|
404
|
+
|
|
405
|
+
#### Returns
|
|
406
|
+
|
|
407
|
+
`ValueRef`\<`number`\>
|
|
408
|
+
|
|
409
|
+
an observable object for which the `value` property reflects the number of properties in `proxied` with a value other than `undefined`.
|
|
410
|
+
|
|
411
|
+
#### Example
|
|
412
|
+
|
|
413
|
+
```typescript
|
|
414
|
+
const items = proxy({x: 3, y: 7} as any);
|
|
415
|
+
const cnt = count(items);
|
|
416
|
+
|
|
417
|
+
// Create a DOM text node for the count:
|
|
418
|
+
$('div text=', cnt);
|
|
419
|
+
// <div>2</div>
|
|
420
|
+
|
|
421
|
+
// Or we can use it in an {@link derive} function:
|
|
422
|
+
$(() => console.log("The count is now", cnt.value));
|
|
423
|
+
// The count is now 2
|
|
424
|
+
|
|
425
|
+
// Adding/removing items will update the count
|
|
426
|
+
items.z = 12;
|
|
427
|
+
// Asynchronously, after 0ms:
|
|
428
|
+
// <div>3</div>
|
|
429
|
+
// The count is now 3
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
***
|
|
433
|
+
|
|
434
|
+
### darkMode()
|
|
435
|
+
|
|
436
|
+
> **darkMode**(): `boolean`
|
|
437
|
+
|
|
438
|
+
Defined in: [aberdeen.ts:1819](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L1819)
|
|
439
|
+
|
|
440
|
+
Returns whether the user's browser prefers a dark color scheme.
|
|
441
|
+
|
|
442
|
+
This function is reactive - scopes that call it will re-execute when the
|
|
443
|
+
browser's color scheme preference changes (via the `prefers-color-scheme` media query).
|
|
444
|
+
|
|
445
|
+
Use this in combination with [$](#) and [cssVars](#cssvars) to implement theme switching:
|
|
446
|
+
|
|
447
|
+
#### Returns
|
|
448
|
+
|
|
449
|
+
`boolean`
|
|
450
|
+
|
|
451
|
+
`true` if the browser prefers dark mode, `false` if it prefers light mode.
|
|
452
|
+
|
|
453
|
+
#### Example
|
|
454
|
+
|
|
455
|
+
```javascript
|
|
456
|
+
import { darkMode, cssVars, $, mount } from 'aberdeen';
|
|
457
|
+
|
|
458
|
+
// Reactively set colors based on browser preference
|
|
459
|
+
$(() => {
|
|
460
|
+
if (darkMode()) { // Optionally override this with user settings
|
|
461
|
+
cssVars.bg = '#1a1a1a';
|
|
462
|
+
cssVars.fg = '#e5e5e5';
|
|
463
|
+
} else {
|
|
464
|
+
cssVars.bg = '#ffffff';
|
|
465
|
+
cssVars.fg = '#000000';
|
|
466
|
+
}
|
|
467
|
+
});
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
***
|
|
471
|
+
|
|
472
|
+
### derive()
|
|
473
|
+
|
|
474
|
+
> **derive**\<`T`\>(`func`): `ValueRef`\<`T`\>
|
|
475
|
+
|
|
476
|
+
Defined in: [aberdeen.ts:2533](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L2533)
|
|
477
|
+
|
|
478
|
+
Creates a reactive scope that automatically re-executes the provided function
|
|
479
|
+
whenever any proxied data (created by [proxy](#proxy)) read during its last execution changes, storing
|
|
480
|
+
its return value in an observable.
|
|
481
|
+
|
|
482
|
+
Updates are batched and run asynchronously shortly after the changes occur.
|
|
483
|
+
Use [clean](#clean) to register cleanup logic for the scope.
|
|
484
|
+
Use [peek](#peek) or [unproxy](#unproxy) within the function to read proxied data without subscribing to it.
|
|
485
|
+
|
|
486
|
+
#### Type Parameters
|
|
487
|
+
|
|
488
|
+
##### T
|
|
489
|
+
|
|
490
|
+
`T`
|
|
491
|
+
|
|
492
|
+
#### Parameters
|
|
493
|
+
|
|
494
|
+
##### func
|
|
495
|
+
|
|
496
|
+
() => `T`
|
|
497
|
+
|
|
498
|
+
The function to execute reactively. Any DOM manipulations should typically
|
|
499
|
+
be done using [$](#) within this function. Its return value will be made available as an
|
|
500
|
+
observable returned by the `derive()` function.
|
|
501
|
+
|
|
502
|
+
#### Returns
|
|
503
|
+
|
|
504
|
+
`ValueRef`\<`T`\>
|
|
505
|
+
|
|
506
|
+
An observable object, with its `value` property containing whatever the last run of `func` returned.
|
|
507
|
+
|
|
508
|
+
#### Examples
|
|
509
|
+
|
|
510
|
+
```typescript
|
|
511
|
+
const data = proxy({ user: 'Frank', notifications: 42 });
|
|
512
|
+
|
|
513
|
+
$('main', () => {
|
|
514
|
+
console.log('Welcome');
|
|
515
|
+
$('h3#Welcome, ' + data.user); // Reactive text
|
|
516
|
+
|
|
517
|
+
derive(() => {
|
|
518
|
+
// When data.notifications changes, only this inner scope reruns,
|
|
519
|
+
// leaving the `<p>Welcome, ..</p>` untouched.
|
|
520
|
+
console.log('Notifications');
|
|
521
|
+
$('code.notification-badge text=', data.notifications);
|
|
522
|
+
$('a text=Notify! click=', () => data.notifications++);
|
|
523
|
+
});
|
|
524
|
+
});
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
***Note*** that the above could just as easily be done using `$(func)` instead of `derive(func)`.
|
|
528
|
+
|
|
529
|
+
```typescript
|
|
530
|
+
const counter = proxy(0);
|
|
531
|
+
setInterval(() => counter.value++, 1000);
|
|
532
|
+
const double = derive(() => counter.value * 2);
|
|
533
|
+
|
|
534
|
+
$('h3', () => {
|
|
535
|
+
$(`#counter=${counter.value} double=${double.value}`);
|
|
536
|
+
})
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
***
|
|
540
|
+
|
|
541
|
+
### dump()
|
|
542
|
+
|
|
543
|
+
> **dump**\<`T`\>(`data`): `T`
|
|
544
|
+
|
|
545
|
+
Defined in: [aberdeen.ts:2953](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L2953)
|
|
546
|
+
|
|
547
|
+
Renders a live, recursive dump of a proxied data structure (or any value)
|
|
548
|
+
into the DOM at the current [$](#) insertion point.
|
|
549
|
+
|
|
550
|
+
Uses `<ul>` and `<li>` elements to display object properties and array items.
|
|
551
|
+
Updates reactively if the dumped data changes. Primarily intended for debugging purposes.
|
|
552
|
+
|
|
553
|
+
#### Type Parameters
|
|
554
|
+
|
|
555
|
+
##### T
|
|
556
|
+
|
|
557
|
+
`T`
|
|
558
|
+
|
|
559
|
+
The type of the data being dumped.
|
|
560
|
+
|
|
561
|
+
#### Parameters
|
|
562
|
+
|
|
563
|
+
##### data
|
|
564
|
+
|
|
565
|
+
`T`
|
|
566
|
+
|
|
567
|
+
The proxied data structure (or any value) to display.
|
|
568
|
+
|
|
569
|
+
#### Returns
|
|
570
|
+
|
|
571
|
+
`T`
|
|
572
|
+
|
|
573
|
+
The original `data` argument, allowing for chaining.
|
|
574
|
+
|
|
575
|
+
#### Example
|
|
576
|
+
|
|
577
|
+
```typescript
|
|
578
|
+
import { $, proxy, dump } from 'aberdeen';
|
|
579
|
+
|
|
580
|
+
const state = proxy({
|
|
581
|
+
user: { name: 'Frank', kids: 1 },
|
|
582
|
+
items: ['a', 'b']
|
|
583
|
+
});
|
|
584
|
+
|
|
585
|
+
$('h2#Live State Dump');
|
|
586
|
+
dump(state);
|
|
587
|
+
|
|
588
|
+
// Change state later, the dump in the DOM will update
|
|
589
|
+
setTimeout(() => { state.user.kids++; state.items.push('c'); }, 2000);
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
***
|
|
593
|
+
|
|
594
|
+
### getParentElement()
|
|
595
|
+
|
|
596
|
+
> **getParentElement**(): `Element`
|
|
597
|
+
|
|
598
|
+
Defined in: [aberdeen.ts:2439](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L2439)
|
|
599
|
+
|
|
600
|
+
Gets the parent DOM `Element` where nodes created by [$](#) would currently be inserted.
|
|
601
|
+
|
|
602
|
+
This is context-dependent based on the current reactive scope (e.g., inside a [mount](#mount)
|
|
603
|
+
call or a [$](#) element's render function).
|
|
604
|
+
|
|
605
|
+
**Note:** While this provides access to the DOM element, directly manipulating it outside
|
|
606
|
+
of Aberdeen's control is generally discouraged. Prefer reactive updates using [$](#).
|
|
607
|
+
|
|
608
|
+
#### Returns
|
|
609
|
+
|
|
610
|
+
`Element`
|
|
611
|
+
|
|
612
|
+
The current parent `Element` for DOM insertion.
|
|
613
|
+
|
|
614
|
+
#### Example
|
|
615
|
+
|
|
616
|
+
```typescript
|
|
617
|
+
function thirdPartyLibInit(parentElement) {
|
|
618
|
+
parentElement.innerHTML = "This element is managed by a <em>third party</em> lib."
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
$('div.box', () => {
|
|
622
|
+
// Get the div.box element just created
|
|
623
|
+
const containerElement = getParentElement();
|
|
624
|
+
thirdPartyLibInit(containerElement);
|
|
625
|
+
});
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
***
|
|
629
|
+
|
|
630
|
+
### insertCss()
|
|
631
|
+
|
|
632
|
+
> **insertCss**(`style`, `global`): `string`
|
|
633
|
+
|
|
634
|
+
Defined in: [aberdeen.ts:2222](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L2222)
|
|
635
|
+
|
|
636
|
+
Inserts CSS rules into the document, scoping them with a unique class name.
|
|
637
|
+
|
|
638
|
+
Takes a JavaScript object representation of CSS rules. camelCased property keys are
|
|
639
|
+
converted to kebab-case (e.g., `fontSize` becomes `font-size`).
|
|
640
|
+
|
|
641
|
+
#### Parameters
|
|
642
|
+
|
|
643
|
+
##### style
|
|
644
|
+
|
|
645
|
+
`object`
|
|
646
|
+
|
|
647
|
+
An object where keys are CSS selectors (or camelCased properties) and values are
|
|
648
|
+
CSS properties or nested rule objects.
|
|
649
|
+
- Selectors are usually combined as a descendant-relationship (meaning just a space character) with their parent selector.
|
|
650
|
+
- In case a selector contains a `&`, that character will be replaced by the parent selector.
|
|
651
|
+
- Selectors will be split on `,` characters, each combining with the parent selector with *or* semantics.
|
|
652
|
+
- Selector starting with `'@'` define at-rules like media queries. They may be nested within regular selectors.
|
|
653
|
+
|
|
654
|
+
##### global
|
|
655
|
+
|
|
656
|
+
`boolean` = `false`
|
|
657
|
+
|
|
658
|
+
Deprecated! Use [insertGlobalCss](#insertglobalcss) instead.
|
|
659
|
+
|
|
660
|
+
#### Returns
|
|
661
|
+
|
|
662
|
+
`string`
|
|
663
|
+
|
|
664
|
+
The unique class name prefix used for scoping (e.g., `.AbdStl1`). Use this
|
|
665
|
+
prefix with [$](#) to apply the styles.
|
|
666
|
+
|
|
667
|
+
#### Example
|
|
668
|
+
|
|
669
|
+
```typescript
|
|
670
|
+
const scopeClass = insertCss({
|
|
671
|
+
color: 'red',
|
|
672
|
+
padding: '10px',
|
|
673
|
+
'&:hover': { // Use '&' for the root scoped selector
|
|
674
|
+
backgroundColor: '#535'
|
|
675
|
+
},
|
|
676
|
+
'.child-element': { // Nested selector
|
|
677
|
+
fontWeight: 'bold'
|
|
678
|
+
},
|
|
679
|
+
'@media (max-width: 600px)': {
|
|
680
|
+
padding: '5px'
|
|
681
|
+
}
|
|
682
|
+
});
|
|
683
|
+
// scopeClass might be ".AbdStl1"
|
|
684
|
+
|
|
685
|
+
// Apply the styles
|
|
686
|
+
$(scopeClass, () => { // Add class to the div
|
|
687
|
+
$(`#Scoped content`);
|
|
688
|
+
$('div.child-element#Child'); // .AbdStl1 .child-element rule applies
|
|
689
|
+
});
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
***
|
|
693
|
+
|
|
694
|
+
### insertGlobalCss()
|
|
695
|
+
|
|
696
|
+
> **insertGlobalCss**(`style`): `string`
|
|
697
|
+
|
|
698
|
+
Defined in: [aberdeen.ts:2250](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L2250)
|
|
699
|
+
|
|
700
|
+
Inserts CSS rules globally.
|
|
701
|
+
|
|
702
|
+
Works exactly like [insertCss](#insertcss), but without prefixing selectors with a unique class name.
|
|
703
|
+
|
|
704
|
+
#### Parameters
|
|
705
|
+
|
|
706
|
+
##### style
|
|
707
|
+
|
|
708
|
+
`object`
|
|
709
|
+
|
|
710
|
+
#### Returns
|
|
711
|
+
|
|
712
|
+
`string`
|
|
713
|
+
|
|
714
|
+
#### Example
|
|
715
|
+
|
|
716
|
+
```typescript
|
|
717
|
+
insertGlobalCss({
|
|
718
|
+
'*': {
|
|
719
|
+
fontFamily: 'monospace',
|
|
720
|
+
m: 0, // Using shortcut for margin
|
|
721
|
+
},
|
|
722
|
+
'a': {
|
|
723
|
+
textDecoration: 'none',
|
|
724
|
+
fg: "@primary", // Using foreground shortcut and CSS variable
|
|
725
|
+
}
|
|
726
|
+
});
|
|
727
|
+
|
|
728
|
+
$('a#Styled link');
|
|
729
|
+
```
|
|
730
|
+
|
|
731
|
+
***
|
|
732
|
+
|
|
733
|
+
### invertString()
|
|
734
|
+
|
|
735
|
+
> **invertString**(`input`): `string`
|
|
736
|
+
|
|
737
|
+
Defined in: [aberdeen.ts:149](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L149)
|
|
738
|
+
|
|
739
|
+
Creates a new string that has the opposite sort order compared to the input string.
|
|
740
|
+
|
|
741
|
+
This is achieved by flipping the bits of each character code in the input string.
|
|
742
|
+
The resulting string is intended for use as a sort key, particularly with the
|
|
743
|
+
`makeKey` function in [onEach](#oneach), to achieve a descending sort order.
|
|
744
|
+
|
|
745
|
+
**Warning:** The output string will likely contain non-printable characters or
|
|
746
|
+
appear as gibberish and should not be displayed to the user.
|
|
747
|
+
|
|
748
|
+
#### Parameters
|
|
749
|
+
|
|
750
|
+
##### input
|
|
751
|
+
|
|
752
|
+
`string`
|
|
753
|
+
|
|
754
|
+
The string whose sort order needs to be inverted.
|
|
755
|
+
|
|
756
|
+
#### Returns
|
|
757
|
+
|
|
758
|
+
`string`
|
|
759
|
+
|
|
760
|
+
A new string that will sort in the reverse order of the input string.
|
|
761
|
+
|
|
762
|
+
#### Example
|
|
763
|
+
|
|
764
|
+
```typescript
|
|
765
|
+
const users = proxy([
|
|
766
|
+
{ id: 1, name: 'Charlie', score: 95 },
|
|
767
|
+
{ id: 2, name: 'Alice', score: 100 },
|
|
768
|
+
{ id: 3, name: 'Bob', score: 90 },
|
|
769
|
+
]);
|
|
770
|
+
|
|
771
|
+
onEach(users, (user) => {
|
|
772
|
+
$(`p#${user.name}: ${user.score}`);
|
|
773
|
+
}, (user) => invertString(user.name)); // Reverse alphabetic order
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
#### See
|
|
777
|
+
|
|
778
|
+
[onEach](#oneach) for usage with sorting.
|
|
779
|
+
|
|
780
|
+
***
|
|
781
|
+
|
|
782
|
+
### isEmpty()
|
|
783
|
+
|
|
784
|
+
> **isEmpty**(`proxied`): `boolean`
|
|
785
|
+
|
|
786
|
+
Defined in: [aberdeen.ts:956](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L956)
|
|
787
|
+
|
|
788
|
+
Reactively checks if an observable array or object is empty.
|
|
789
|
+
|
|
790
|
+
This function not only returns the current emptiness state but also establishes
|
|
791
|
+
a reactive dependency. If the emptiness state of the `proxied` object or array
|
|
792
|
+
changes later (e.g., an item is added to an empty array, or the last property
|
|
793
|
+
is deleted from an object), the scope that called `isEmpty` will be automatically
|
|
794
|
+
scheduled for re-evaluation.
|
|
795
|
+
|
|
796
|
+
#### Parameters
|
|
797
|
+
|
|
798
|
+
##### proxied
|
|
799
|
+
|
|
800
|
+
`TargetType`
|
|
801
|
+
|
|
802
|
+
The observable array or object to check.
|
|
803
|
+
|
|
804
|
+
#### Returns
|
|
805
|
+
|
|
806
|
+
`boolean`
|
|
807
|
+
|
|
808
|
+
`true` if the array has length 0 or the object has no own enumerable properties, `false` otherwise.
|
|
809
|
+
|
|
810
|
+
#### Example
|
|
811
|
+
|
|
812
|
+
```typescript
|
|
813
|
+
const items = proxy([]);
|
|
814
|
+
|
|
815
|
+
// Reactively display a message if the items array is empty
|
|
816
|
+
$('div', () => {
|
|
817
|
+
if (isEmpty(items)) {
|
|
818
|
+
$('p i#No items yet!');
|
|
819
|
+
} else {
|
|
820
|
+
onEach(items, item => $('p#'+item));
|
|
821
|
+
}
|
|
822
|
+
});
|
|
823
|
+
|
|
824
|
+
// Adding an item will automatically remove the "No items yet!" message
|
|
825
|
+
setInterval(() => {
|
|
826
|
+
if (!items.length || Math.random()>0.5) items.push('Item');
|
|
827
|
+
else items.length = 0;
|
|
828
|
+
}, 1000)
|
|
829
|
+
```
|
|
830
|
+
|
|
831
|
+
***
|
|
832
|
+
|
|
833
|
+
### map()
|
|
834
|
+
|
|
835
|
+
Reactively maps/filters items from a proxied source array or object to a new proxied array or object.
|
|
836
|
+
|
|
837
|
+
It iterates over the `target` proxy. For each item, it calls `func`.
|
|
838
|
+
- If `func` returns a value, it's added to the result proxy under the same key/index.
|
|
839
|
+
- If `func` returns `undefined`, the item is skipped (filtered out).
|
|
840
|
+
|
|
841
|
+
The returned proxy automatically updates when:
|
|
842
|
+
- Items are added/removed/updated in the `target` proxy.
|
|
843
|
+
- Any proxied data read *within* the `func` call changes (for a specific item).
|
|
844
|
+
|
|
845
|
+
#### Param
|
|
846
|
+
|
|
847
|
+
A function `(value, key) => mappedValue | undefined` that transforms each item.
|
|
848
|
+
It receives the item's value and its key/index. Return `undefined` to filter the item out.
|
|
849
|
+
|
|
850
|
+
#### Template
|
|
851
|
+
|
|
852
|
+
The type of items in the source proxy.
|
|
853
|
+
|
|
854
|
+
#### Template
|
|
855
|
+
|
|
856
|
+
The type of items in the resulting proxy.
|
|
857
|
+
|
|
858
|
+
#### Examples
|
|
859
|
+
|
|
860
|
+
```typescript
|
|
861
|
+
const numbers = proxy([1, 2, 3]);
|
|
862
|
+
const doubled = map(numbers, (n) => n * 2);
|
|
863
|
+
// doubled is proxy([2, 4, 6])
|
|
864
|
+
|
|
865
|
+
$(() => console.log(doubled)); // Logs updates
|
|
866
|
+
numbers.push(4); // doubled becomes proxy([2, 4, 6, 8])
|
|
867
|
+
```
|
|
868
|
+
|
|
869
|
+
```typescript
|
|
870
|
+
const users = proxy({
|
|
871
|
+
'u1': { name: 'Alice', active: true },
|
|
872
|
+
'u2': { name: 'Bob', active: false },
|
|
873
|
+
'u3': { name: 'Charlie', active: true }
|
|
874
|
+
});
|
|
875
|
+
|
|
876
|
+
const activeUserNames = map(users, (user) => user.active ? user.name : undefined);
|
|
877
|
+
// activeUserNames is proxy({ u1: 'Alice', u3: 'Charlie' })
|
|
878
|
+
$(() => console.log(Object.values(activeUserNames)));
|
|
879
|
+
|
|
880
|
+
users.u2.active = true;
|
|
881
|
+
// activeUserNames becomes proxy({ u1: 'Alice', u2: 'Bob', u3: 'Charlie' })
|
|
882
|
+
```
|
|
883
|
+
|
|
884
|
+
#### Call Signature
|
|
885
|
+
|
|
886
|
+
> **map**\<`K`, `IN`, `OUT`\>(`source`, `func`): `Map`\<`K`, `OUT`\>
|
|
887
|
+
|
|
888
|
+
Defined in: [aberdeen.ts:2640](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L2640)
|
|
889
|
+
|
|
890
|
+
When using a Map as `source`.
|
|
891
|
+
|
|
892
|
+
##### Type Parameters
|
|
893
|
+
|
|
894
|
+
###### K
|
|
895
|
+
|
|
896
|
+
`K`
|
|
897
|
+
|
|
898
|
+
###### IN
|
|
899
|
+
|
|
900
|
+
`IN`
|
|
901
|
+
|
|
902
|
+
###### OUT
|
|
903
|
+
|
|
904
|
+
`OUT`
|
|
905
|
+
|
|
906
|
+
##### Parameters
|
|
907
|
+
|
|
908
|
+
###### source
|
|
909
|
+
|
|
910
|
+
`Map`\<`K`, `IN`\>
|
|
911
|
+
|
|
912
|
+
###### func
|
|
913
|
+
|
|
914
|
+
(`value`, `key`) => `undefined` \| `OUT`
|
|
915
|
+
|
|
916
|
+
##### Returns
|
|
917
|
+
|
|
918
|
+
`Map`\<`K`, `OUT`\>
|
|
919
|
+
|
|
920
|
+
#### Call Signature
|
|
921
|
+
|
|
922
|
+
> **map**\<`IN`, `OUT`\>(`source`, `func`): `OUT`[]
|
|
923
|
+
|
|
924
|
+
Defined in: [aberdeen.ts:2645](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L2645)
|
|
925
|
+
|
|
926
|
+
When using an array as `source`.
|
|
927
|
+
|
|
928
|
+
##### Type Parameters
|
|
929
|
+
|
|
930
|
+
###### IN
|
|
931
|
+
|
|
932
|
+
`IN`
|
|
933
|
+
|
|
934
|
+
###### OUT
|
|
935
|
+
|
|
936
|
+
`OUT`
|
|
937
|
+
|
|
938
|
+
##### Parameters
|
|
939
|
+
|
|
940
|
+
###### source
|
|
941
|
+
|
|
942
|
+
`IN`[]
|
|
943
|
+
|
|
944
|
+
###### func
|
|
945
|
+
|
|
946
|
+
(`value`, `index`) => `undefined` \| `OUT`
|
|
947
|
+
|
|
948
|
+
##### Returns
|
|
949
|
+
|
|
950
|
+
`OUT`[]
|
|
951
|
+
|
|
952
|
+
#### Call Signature
|
|
953
|
+
|
|
954
|
+
> **map**\<`IN`, `IN_KEY`, `OUT`\>(`source`, `func`): `Record`\<`string` \| `symbol`, `OUT`\>
|
|
955
|
+
|
|
956
|
+
Defined in: [aberdeen.ts:2650](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L2650)
|
|
957
|
+
|
|
958
|
+
When using an object as `source`.
|
|
959
|
+
|
|
960
|
+
##### Type Parameters
|
|
961
|
+
|
|
962
|
+
###### IN
|
|
963
|
+
|
|
964
|
+
`IN`
|
|
965
|
+
|
|
966
|
+
###### IN_KEY
|
|
967
|
+
|
|
968
|
+
`IN_KEY` *extends* `string` \| `number` \| `symbol`
|
|
969
|
+
|
|
970
|
+
###### OUT
|
|
971
|
+
|
|
972
|
+
`OUT`
|
|
973
|
+
|
|
974
|
+
##### Parameters
|
|
975
|
+
|
|
976
|
+
###### source
|
|
977
|
+
|
|
978
|
+
`Record`\<`IN_KEY`, `IN`\>
|
|
979
|
+
|
|
980
|
+
###### func
|
|
981
|
+
|
|
982
|
+
(`value`, `index`) => `undefined` \| `OUT`
|
|
983
|
+
|
|
984
|
+
##### Returns
|
|
985
|
+
|
|
986
|
+
`Record`\<`string` \| `symbol`, `OUT`\>
|
|
987
|
+
|
|
988
|
+
***
|
|
989
|
+
|
|
990
|
+
### merge()
|
|
991
|
+
|
|
992
|
+
#### Call Signature
|
|
993
|
+
|
|
994
|
+
> **merge**\<`T`\>(`dst`, `value`): `boolean`
|
|
995
|
+
|
|
996
|
+
Defined in: [aberdeen.ts:1540](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L1540)
|
|
997
|
+
|
|
998
|
+
Like [copy](#copy), but uses merge semantics. Properties in `dst` not present in `src` are kept.
|
|
999
|
+
`null`/`undefined` in `src` delete properties in `dst`.
|
|
1000
|
+
|
|
1001
|
+
When the destination is an object and the source is an array, its keys are used as (sparse) array indices.
|
|
1002
|
+
|
|
1003
|
+
##### Type Parameters
|
|
1004
|
+
|
|
1005
|
+
###### T
|
|
1006
|
+
|
|
1007
|
+
`T` *extends* `object`
|
|
1008
|
+
|
|
1009
|
+
##### Parameters
|
|
1010
|
+
|
|
1011
|
+
###### dst
|
|
1012
|
+
|
|
1013
|
+
`T`
|
|
1014
|
+
|
|
1015
|
+
###### value
|
|
1016
|
+
|
|
1017
|
+
`Partial`\<`T`\>
|
|
1018
|
+
|
|
1019
|
+
##### Returns
|
|
1020
|
+
|
|
1021
|
+
`boolean`
|
|
1022
|
+
|
|
1023
|
+
##### Examples
|
|
1024
|
+
|
|
1025
|
+
```typescript
|
|
1026
|
+
const source = { b: { c: 99 }, d: undefined }; // d: undefined will delete
|
|
1027
|
+
const dest = proxy({ a: 1, b: { x: 5 }, d: 4 });
|
|
1028
|
+
merge(dest, source);
|
|
1029
|
+
merge(dest, 'b', { y: 6 }); // merge into dest.b
|
|
1030
|
+
merge(dest, 'c', { z: 7 }); // merge.c doesn't exist yet, so it will just be assigned
|
|
1031
|
+
console.log(dest); // proxy({ a: 1, b: { c: 99, x: 5, y: 6 }, c: { z: 7 } })
|
|
1032
|
+
```
|
|
1033
|
+
|
|
1034
|
+
```typescript
|
|
1035
|
+
const messages = proxy(['msg1', 'msg2', 'msg3']);
|
|
1036
|
+
const update = { 1: 'updated msg2' }; // Update using object key as index
|
|
1037
|
+
merge(messages, update);
|
|
1038
|
+
console.log(messages); // proxy(['msg1', 'updated msg2', 'msg3'])
|
|
1039
|
+
```
|
|
1040
|
+
|
|
1041
|
+
#### Call Signature
|
|
1042
|
+
|
|
1043
|
+
> **merge**\<`T`\>(`dst`, `dstKey`, `value`): `boolean`
|
|
1044
|
+
|
|
1045
|
+
Defined in: [aberdeen.ts:1541](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L1541)
|
|
1046
|
+
|
|
1047
|
+
Like [copy](#copy), but uses merge semantics. Properties in `dst` not present in `src` are kept.
|
|
1048
|
+
`null`/`undefined` in `src` delete properties in `dst`.
|
|
1049
|
+
|
|
1050
|
+
When the destination is an object and the source is an array, its keys are used as (sparse) array indices.
|
|
1051
|
+
|
|
1052
|
+
##### Type Parameters
|
|
1053
|
+
|
|
1054
|
+
###### T
|
|
1055
|
+
|
|
1056
|
+
`T` *extends* `object`
|
|
1057
|
+
|
|
1058
|
+
##### Parameters
|
|
1059
|
+
|
|
1060
|
+
###### dst
|
|
1061
|
+
|
|
1062
|
+
`T`
|
|
1063
|
+
|
|
1064
|
+
###### dstKey
|
|
1065
|
+
|
|
1066
|
+
keyof `T`
|
|
1067
|
+
|
|
1068
|
+
###### value
|
|
1069
|
+
|
|
1070
|
+
`Partial`\<`T`\[keyof `T`\]\>
|
|
1071
|
+
|
|
1072
|
+
##### Returns
|
|
1073
|
+
|
|
1074
|
+
`boolean`
|
|
1075
|
+
|
|
1076
|
+
##### Examples
|
|
1077
|
+
|
|
1078
|
+
```typescript
|
|
1079
|
+
const source = { b: { c: 99 }, d: undefined }; // d: undefined will delete
|
|
1080
|
+
const dest = proxy({ a: 1, b: { x: 5 }, d: 4 });
|
|
1081
|
+
merge(dest, source);
|
|
1082
|
+
merge(dest, 'b', { y: 6 }); // merge into dest.b
|
|
1083
|
+
merge(dest, 'c', { z: 7 }); // merge.c doesn't exist yet, so it will just be assigned
|
|
1084
|
+
console.log(dest); // proxy({ a: 1, b: { c: 99, x: 5, y: 6 }, c: { z: 7 } })
|
|
1085
|
+
```
|
|
1086
|
+
|
|
1087
|
+
```typescript
|
|
1088
|
+
const messages = proxy(['msg1', 'msg2', 'msg3']);
|
|
1089
|
+
const update = { 1: 'updated msg2' }; // Update using object key as index
|
|
1090
|
+
merge(messages, update);
|
|
1091
|
+
console.log(messages); // proxy(['msg1', 'updated msg2', 'msg3'])
|
|
1092
|
+
```
|
|
1093
|
+
|
|
1094
|
+
***
|
|
1095
|
+
|
|
1096
|
+
### mount()
|
|
1097
|
+
|
|
1098
|
+
> **mount**(`parentElement`, `func`): `void`
|
|
1099
|
+
|
|
1100
|
+
Defined in: [aberdeen.ts:2580](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L2580)
|
|
1101
|
+
|
|
1102
|
+
Attaches a reactive Aberdeen UI fragment to an existing DOM element. Without the use of
|
|
1103
|
+
this function, [$](#) will assume `document.body` as its root.
|
|
1104
|
+
|
|
1105
|
+
It creates a top-level reactive scope associated with the `parentElement`. The provided
|
|
1106
|
+
function `func` is executed immediately within this scope. Any proxied data read by `func`
|
|
1107
|
+
will cause it to re-execute when the data changes, updating the DOM elements created within it.
|
|
1108
|
+
|
|
1109
|
+
Calls to [$](#) inside `func` will append nodes to `parentElement`.
|
|
1110
|
+
You can nest [derive](#derive) or other [$](#) scopes within `func`.
|
|
1111
|
+
Use [unmountAll](#unmountall) to clean up all mounted scopes and their DOM nodes.
|
|
1112
|
+
|
|
1113
|
+
Mounting scopes happens reactively, meaning that if this function is called from within another
|
|
1114
|
+
([derive](#derive) or [$](#) or [mount](#mount)) scope that gets cleaned up, so will the mount.
|
|
1115
|
+
|
|
1116
|
+
#### Parameters
|
|
1117
|
+
|
|
1118
|
+
##### parentElement
|
|
1119
|
+
|
|
1120
|
+
`Element`
|
|
1121
|
+
|
|
1122
|
+
The native DOM `Element` to which the UI fragment will be appended.
|
|
1123
|
+
|
|
1124
|
+
##### func
|
|
1125
|
+
|
|
1126
|
+
() => `void`
|
|
1127
|
+
|
|
1128
|
+
The function that defines the UI fragment, typically containing calls to [$](#).
|
|
1129
|
+
|
|
1130
|
+
#### Returns
|
|
1131
|
+
|
|
1132
|
+
`void`
|
|
1133
|
+
|
|
1134
|
+
#### Example
|
|
1135
|
+
|
|
1136
|
+
```javascript
|
|
1137
|
+
// Create a pre-existing DOM structure (without Aberdeen)
|
|
1138
|
+
document.body.innerHTML = `<h3>Static content <span id="title-extra"></span></h3><div class="box" id="app-root"></div>`;
|
|
1139
|
+
|
|
1140
|
+
import { mount, $, proxy } from 'aberdeen';
|
|
1141
|
+
|
|
1142
|
+
const runTime = proxy(0);
|
|
1143
|
+
setInterval(() => runTime.value++, 1000);
|
|
1144
|
+
|
|
1145
|
+
mount(document.getElementById('app-root'), () => {
|
|
1146
|
+
$('h4#Aberdeen App');
|
|
1147
|
+
$(`p#Run time: ${runTime.value}s`);
|
|
1148
|
+
// Conditionally render some content somewhere else in the static page
|
|
1149
|
+
if (runTime.value&1) {
|
|
1150
|
+
mount(document.getElementById('title-extra'), () =>
|
|
1151
|
+
$(`i#(${runTime.value}s)`)
|
|
1152
|
+
);
|
|
1153
|
+
}
|
|
1154
|
+
});
|
|
1155
|
+
```
|
|
1156
|
+
|
|
1157
|
+
Note how the inner mount behaves reactively as well, automatically unmounting when it's parent observer scope re-runs.
|
|
1158
|
+
|
|
1159
|
+
***
|
|
1160
|
+
|
|
1161
|
+
### multiMap()
|
|
1162
|
+
|
|
1163
|
+
Reactively maps items from a source proxy (array or object) to a target proxied object,
|
|
1164
|
+
where each source item can contribute multiple key-value pairs to the target.
|
|
1165
|
+
|
|
1166
|
+
It iterates over the `target` proxy. For each item, it calls `func`.
|
|
1167
|
+
- If `func` returns an object, all key-value pairs from that object are added to the result proxy.
|
|
1168
|
+
- If `func` returns `undefined`, the item contributes nothing.
|
|
1169
|
+
|
|
1170
|
+
The returned proxy automatically updates when:
|
|
1171
|
+
- Items are added/removed/updated in the `target` proxy.
|
|
1172
|
+
- Any proxied data read *within* the `func` call changes (for a specific item).
|
|
1173
|
+
- If multiple input items produce the same output key, the last one processed usually "wins",
|
|
1174
|
+
but the exact behavior on collision depends on update timing.
|
|
1175
|
+
|
|
1176
|
+
This is useful for "flattening" or "indexing" data, or converting an observable array to an observable object.
|
|
1177
|
+
|
|
1178
|
+
#### Param
|
|
1179
|
+
|
|
1180
|
+
The source proxied array or object.
|
|
1181
|
+
|
|
1182
|
+
#### Param
|
|
1183
|
+
|
|
1184
|
+
A function `(value, key) => ({...pairs} | undefined)` that transforms an item
|
|
1185
|
+
into an object of key-value pairs to add, or `undefined` to add nothing.
|
|
1186
|
+
|
|
1187
|
+
#### Template
|
|
1188
|
+
|
|
1189
|
+
The type of items in the source proxy.
|
|
1190
|
+
|
|
1191
|
+
#### Template
|
|
1192
|
+
|
|
1193
|
+
The type of the aggregated output object (should encompass all possible key-value pairs).
|
|
1194
|
+
|
|
1195
|
+
#### Example
|
|
1196
|
+
|
|
1197
|
+
```typescript
|
|
1198
|
+
const items = proxy([
|
|
1199
|
+
{ id: 'a', value: 10 },
|
|
1200
|
+
{ id: 'b', value: 20 },
|
|
1201
|
+
]);
|
|
1202
|
+
const itemsById = multiMap(items, (item) => ({
|
|
1203
|
+
[item.id]: item.value,
|
|
1204
|
+
[item.id+item.id]: item.value*10,
|
|
1205
|
+
}));
|
|
1206
|
+
// itemsById is proxy({ a: 10, aa: 100, b: 20, bb: 200 })
|
|
1207
|
+
|
|
1208
|
+
$(() => console.log(itemsById));
|
|
1209
|
+
|
|
1210
|
+
items.push({ id: 'c', value: 30 });
|
|
1211
|
+
// itemsById becomes proxy({ a: 10, aa: 100, b: 20, bb: 200, c: 30, cc: 300 })
|
|
1212
|
+
```
|
|
1213
|
+
|
|
1214
|
+
#### Call Signature
|
|
1215
|
+
|
|
1216
|
+
> **multiMap**\<`IN`, `OUT`\>(`source`, `func`): `OUT`
|
|
1217
|
+
|
|
1218
|
+
Defined in: [aberdeen.ts:2730](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L2730)
|
|
1219
|
+
|
|
1220
|
+
When using an array as `source`.
|
|
1221
|
+
|
|
1222
|
+
##### Type Parameters
|
|
1223
|
+
|
|
1224
|
+
###### IN
|
|
1225
|
+
|
|
1226
|
+
`IN`
|
|
1227
|
+
|
|
1228
|
+
###### OUT
|
|
1229
|
+
|
|
1230
|
+
`OUT` *extends* `object`
|
|
1231
|
+
|
|
1232
|
+
##### Parameters
|
|
1233
|
+
|
|
1234
|
+
###### source
|
|
1235
|
+
|
|
1236
|
+
`IN`[]
|
|
1237
|
+
|
|
1238
|
+
###### func
|
|
1239
|
+
|
|
1240
|
+
(`value`, `index`) => `undefined` \| `OUT`
|
|
1241
|
+
|
|
1242
|
+
##### Returns
|
|
1243
|
+
|
|
1244
|
+
`OUT`
|
|
1245
|
+
|
|
1246
|
+
#### Call Signature
|
|
1247
|
+
|
|
1248
|
+
> **multiMap**\<`K`, `IN`, `OUT`\>(`source`, `func`): `OUT`
|
|
1249
|
+
|
|
1250
|
+
Defined in: [aberdeen.ts:2735](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L2735)
|
|
1251
|
+
|
|
1252
|
+
When using an object as `source`.
|
|
1253
|
+
|
|
1254
|
+
##### Type Parameters
|
|
1255
|
+
|
|
1256
|
+
###### K
|
|
1257
|
+
|
|
1258
|
+
`K` *extends* `string` \| `number` \| `symbol`
|
|
1259
|
+
|
|
1260
|
+
###### IN
|
|
1261
|
+
|
|
1262
|
+
`IN`
|
|
1263
|
+
|
|
1264
|
+
###### OUT
|
|
1265
|
+
|
|
1266
|
+
`OUT` *extends* `object`
|
|
1267
|
+
|
|
1268
|
+
##### Parameters
|
|
1269
|
+
|
|
1270
|
+
###### source
|
|
1271
|
+
|
|
1272
|
+
`Record`\<`K`, `IN`\>
|
|
1273
|
+
|
|
1274
|
+
###### func
|
|
1275
|
+
|
|
1276
|
+
(`value`, `index`) => `undefined` \| `OUT`
|
|
1277
|
+
|
|
1278
|
+
##### Returns
|
|
1279
|
+
|
|
1280
|
+
`OUT`
|
|
1281
|
+
|
|
1282
|
+
#### Call Signature
|
|
1283
|
+
|
|
1284
|
+
> **multiMap**\<`K`, `IN`, `OUT`\>(`source`, `func`): `OUT`
|
|
1285
|
+
|
|
1286
|
+
Defined in: [aberdeen.ts:2741](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L2741)
|
|
1287
|
+
|
|
1288
|
+
When using a Map as `source`.
|
|
1289
|
+
|
|
1290
|
+
##### Type Parameters
|
|
1291
|
+
|
|
1292
|
+
###### K
|
|
1293
|
+
|
|
1294
|
+
`K`
|
|
1295
|
+
|
|
1296
|
+
###### IN
|
|
1297
|
+
|
|
1298
|
+
`IN`
|
|
1299
|
+
|
|
1300
|
+
###### OUT
|
|
1301
|
+
|
|
1302
|
+
`OUT` *extends* `object`
|
|
1303
|
+
|
|
1304
|
+
##### Parameters
|
|
1305
|
+
|
|
1306
|
+
###### source
|
|
1307
|
+
|
|
1308
|
+
`Map`\<`K`, `IN`\>
|
|
1309
|
+
|
|
1310
|
+
###### func
|
|
1311
|
+
|
|
1312
|
+
(`value`, `key`) => `undefined` \| `OUT`
|
|
1313
|
+
|
|
1314
|
+
##### Returns
|
|
1315
|
+
|
|
1316
|
+
`OUT`
|
|
1317
|
+
|
|
1318
|
+
***
|
|
1319
|
+
|
|
1320
|
+
### onEach()
|
|
1321
|
+
|
|
1322
|
+
Reactively iterates over the items of an observable array or object, optionally rendering content for each item.
|
|
1323
|
+
|
|
1324
|
+
Automatically updates when items are added, removed, or modified.
|
|
1325
|
+
|
|
1326
|
+
#### Param
|
|
1327
|
+
|
|
1328
|
+
The observable array or object to iterate over. Values that are `undefined` are skipped.
|
|
1329
|
+
|
|
1330
|
+
#### Param
|
|
1331
|
+
|
|
1332
|
+
A function called for each item in the array. It receives the item's (observable) value and its index/key. 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.
|
|
1333
|
+
|
|
1334
|
+
#### Param
|
|
1335
|
+
|
|
1336
|
+
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, items are rendered in array index 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.
|
|
1337
|
+
|
|
1338
|
+
#### Examples
|
|
1339
|
+
|
|
1340
|
+
```typescript
|
|
1341
|
+
const items = proxy(['apple', 'banana', 'cherry']);
|
|
1342
|
+
|
|
1343
|
+
// Basic iteration
|
|
1344
|
+
onEach(items, (item, index) => $(`li#${item} (#${index})`));
|
|
1345
|
+
|
|
1346
|
+
// Add a new item - the list updates automatically
|
|
1347
|
+
setTimeout(() => items.push('durian'), 2000);
|
|
1348
|
+
// Same for updates and deletes
|
|
1349
|
+
setTimeout(() => items[1] = 'berry', 4000);
|
|
1350
|
+
setTimeout(() => delete items[2], 6000);
|
|
1351
|
+
```
|
|
1352
|
+
|
|
1353
|
+
```typescript
|
|
1354
|
+
const users = proxy([
|
|
1355
|
+
{ id: 3, group: 1, name: 'Charlie' },
|
|
1356
|
+
{ id: 1, group: 1, name: 'Alice' },
|
|
1357
|
+
{ id: 2, group: 2, name: 'Bob' },
|
|
1358
|
+
]);
|
|
1359
|
+
|
|
1360
|
+
// Sort by name alphabetically
|
|
1361
|
+
onEach(users, (user) => {
|
|
1362
|
+
$(`p#${user.name} (id=${user.id})`);
|
|
1363
|
+
}, (user) => [user.group, user.name]); // Sort by group, and within each group sort by name
|
|
1364
|
+
```
|
|
1365
|
+
|
|
1366
|
+
```javascript
|
|
1367
|
+
const config = proxy({ theme: 'dark', fontSize: 14, showTips: true });
|
|
1368
|
+
|
|
1369
|
+
// Display configuration options
|
|
1370
|
+
$('dl', () => {
|
|
1371
|
+
onEach(config, (value, key) => {
|
|
1372
|
+
if (key === 'showTips') return; // Don't render this one
|
|
1373
|
+
$('dt#'+key);
|
|
1374
|
+
$('dd#'+value);
|
|
1375
|
+
});
|
|
1376
|
+
});
|
|
1377
|
+
|
|
1378
|
+
// Change a value - the display updates automatically
|
|
1379
|
+
setTimeout(() => config.fontSize = 16, 2000);
|
|
1380
|
+
```
|
|
1381
|
+
|
|
1382
|
+
#### See
|
|
1383
|
+
|
|
1384
|
+
[invertString](#invertstring) To easily create keys for reverse sorting.
|
|
1385
|
+
|
|
1386
|
+
#### Call Signature
|
|
1387
|
+
|
|
1388
|
+
> **onEach**\<`K`, `T`\>(`target`, `render`, `makeKey?`): `void`
|
|
1389
|
+
|
|
1390
|
+
Defined in: [aberdeen.ts:834](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L834)
|
|
1391
|
+
|
|
1392
|
+
##### Type Parameters
|
|
1393
|
+
|
|
1394
|
+
###### K
|
|
1395
|
+
|
|
1396
|
+
`K`
|
|
1397
|
+
|
|
1398
|
+
###### T
|
|
1399
|
+
|
|
1400
|
+
`T`
|
|
1401
|
+
|
|
1402
|
+
##### Parameters
|
|
1403
|
+
|
|
1404
|
+
###### target
|
|
1405
|
+
|
|
1406
|
+
`Map`\<`K`, `undefined` \| `T`\>
|
|
1407
|
+
|
|
1408
|
+
###### render
|
|
1409
|
+
|
|
1410
|
+
(`value`, `key`) => `void`
|
|
1411
|
+
|
|
1412
|
+
###### makeKey?
|
|
1413
|
+
|
|
1414
|
+
(`value`, `key`) => `SortKeyType`
|
|
1415
|
+
|
|
1416
|
+
##### Returns
|
|
1417
|
+
|
|
1418
|
+
`void`
|
|
1419
|
+
|
|
1420
|
+
#### Call Signature
|
|
1421
|
+
|
|
1422
|
+
> **onEach**\<`T`\>(`target`, `render`, `makeKey?`): `void`
|
|
1423
|
+
|
|
1424
|
+
Defined in: [aberdeen.ts:839](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L839)
|
|
1425
|
+
|
|
1426
|
+
##### Type Parameters
|
|
1427
|
+
|
|
1428
|
+
###### T
|
|
1429
|
+
|
|
1430
|
+
`T`
|
|
1431
|
+
|
|
1432
|
+
##### Parameters
|
|
1433
|
+
|
|
1434
|
+
###### target
|
|
1435
|
+
|
|
1436
|
+
readonly (`undefined` \| `T`)[]
|
|
1437
|
+
|
|
1438
|
+
###### render
|
|
1439
|
+
|
|
1440
|
+
(`value`, `index`) => `void`
|
|
1441
|
+
|
|
1442
|
+
###### makeKey?
|
|
1443
|
+
|
|
1444
|
+
(`value`, `index`) => `SortKeyType`
|
|
1445
|
+
|
|
1446
|
+
##### Returns
|
|
1447
|
+
|
|
1448
|
+
`void`
|
|
1449
|
+
|
|
1450
|
+
#### Call Signature
|
|
1451
|
+
|
|
1452
|
+
> **onEach**\<`K`, `T`\>(`target`, `render`, `makeKey?`): `void`
|
|
1453
|
+
|
|
1454
|
+
Defined in: [aberdeen.ts:844](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L844)
|
|
1455
|
+
|
|
1456
|
+
##### Type Parameters
|
|
1457
|
+
|
|
1458
|
+
###### K
|
|
1459
|
+
|
|
1460
|
+
`K` *extends* `string` \| `number` \| `symbol`
|
|
1461
|
+
|
|
1462
|
+
###### T
|
|
1463
|
+
|
|
1464
|
+
`T`
|
|
1465
|
+
|
|
1466
|
+
##### Parameters
|
|
1467
|
+
|
|
1468
|
+
###### target
|
|
1469
|
+
|
|
1470
|
+
`Record`\<`K`, `undefined` \| `T`\>
|
|
1471
|
+
|
|
1472
|
+
###### render
|
|
1473
|
+
|
|
1474
|
+
(`value`, `index`) => `void`
|
|
1475
|
+
|
|
1476
|
+
###### makeKey?
|
|
1477
|
+
|
|
1478
|
+
(`value`, `index`) => `SortKeyType`
|
|
1479
|
+
|
|
1480
|
+
##### Returns
|
|
1481
|
+
|
|
1482
|
+
`void`
|
|
1483
|
+
|
|
1484
|
+
***
|
|
1485
|
+
|
|
1486
|
+
### partition()
|
|
1487
|
+
|
|
1488
|
+
Reactively partitions items from a source proxy (array or object) into multiple "bucket" proxies
|
|
1489
|
+
based on keys determined by a classifier function.
|
|
1490
|
+
|
|
1491
|
+
This function iterates through the `source` proxy using [onEach](#oneach). For each item,
|
|
1492
|
+
it calls the classifier `func`, which should return:
|
|
1493
|
+
- A single key (`OUT_K`): The item belongs to the bucket with this key.
|
|
1494
|
+
- An array of keys (`OUT_K[]`): The item belongs to all buckets specified in the array.
|
|
1495
|
+
- `undefined`: The item is not placed in any bucket.
|
|
1496
|
+
|
|
1497
|
+
The function returns a main proxied object. The keys of this object are the bucket keys (`OUT_K`)
|
|
1498
|
+
returned by `func`. Each value associated with a bucket key is another proxied object (the "bucket").
|
|
1499
|
+
This inner bucket object maps the *original* keys/indices from the `source` to the items
|
|
1500
|
+
themselves that were classified into that bucket.
|
|
1501
|
+
|
|
1502
|
+
The entire structure is reactive. Changes in the `source` proxy (adding/removing/updating items)
|
|
1503
|
+
or changes in dependencies read by the `func` will cause the output partitioning to update automatically.
|
|
1504
|
+
Buckets are created dynamically as needed and removed when they become empty.
|
|
1505
|
+
|
|
1506
|
+
#### Param
|
|
1507
|
+
|
|
1508
|
+
The input proxied Array or Record (e.g., created by [proxy](#proxy)) containing the items to partition.
|
|
1509
|
+
|
|
1510
|
+
#### Param
|
|
1511
|
+
|
|
1512
|
+
A classifier function `(value: IN_V, key: IN_K | number) => undefined | OUT_K | OUT_K[]`.
|
|
1513
|
+
It receives the item's value and its original key/index from the `source`. It returns the bucket key(s)
|
|
1514
|
+
the item belongs to, or `undefined` to ignore the item.
|
|
1515
|
+
|
|
1516
|
+
#### Template
|
|
1517
|
+
|
|
1518
|
+
The type of the keys used for the output buckets (string, number, or symbol).
|
|
1519
|
+
|
|
1520
|
+
#### Template
|
|
1521
|
+
|
|
1522
|
+
The type of the values in the source proxy.
|
|
1523
|
+
|
|
1524
|
+
#### Template
|
|
1525
|
+
|
|
1526
|
+
The type of the keys in the source proxy (if it's a Record).
|
|
1527
|
+
|
|
1528
|
+
#### Examples
|
|
1529
|
+
|
|
1530
|
+
```typescript
|
|
1531
|
+
interface Product { id: string; category: string; name: string; }
|
|
1532
|
+
const products = proxy<Product[]>([
|
|
1533
|
+
{ id: 'p1', category: 'Fruit', name: 'Apple' },
|
|
1534
|
+
{ id: 'p2', category: 'Veg', name: 'Carrot' },
|
|
1535
|
+
{ id: 'p3', category: 'Fruit', name: 'Banana' },
|
|
1536
|
+
]);
|
|
1537
|
+
|
|
1538
|
+
// Partition products by category. Output keys are categories (string).
|
|
1539
|
+
// Inner keys are original array indices (number).
|
|
1540
|
+
const productsByCategory = partition(products, (product) => product.category);
|
|
1541
|
+
|
|
1542
|
+
// Reactively show the data structure
|
|
1543
|
+
dump(productsByCategory);
|
|
1544
|
+
|
|
1545
|
+
// Make random changes to the categories, to show reactiveness
|
|
1546
|
+
setInterval(() => products[0|(Math.random()*3)].category = ['Snack','Fruit','Veg'][0|(Math.random()*3)], 2000);
|
|
1547
|
+
```
|
|
1548
|
+
|
|
1549
|
+
```typescript
|
|
1550
|
+
interface User { id: number; tags: string[]; name: string; }
|
|
1551
|
+
const users = proxy({
|
|
1552
|
+
'u1': { name: 'Alice', tags: ['active', 'new'] },
|
|
1553
|
+
'u2': { name: 'Bob', tags: ['active'] }
|
|
1554
|
+
});
|
|
1555
|
+
|
|
1556
|
+
// Partition users by tag. Output keys are tags (string).
|
|
1557
|
+
// Inner keys are original object keys (string: 'u1', 'u2').
|
|
1558
|
+
const usersByTag = partition(users, (user) => user.tags);
|
|
1559
|
+
|
|
1560
|
+
console.log(usersByTag);
|
|
1561
|
+
```
|
|
1562
|
+
|
|
1563
|
+
#### Call Signature
|
|
1564
|
+
|
|
1565
|
+
> **partition**\<`OUT_K`, `IN_V`\>(`source`, `func`): `Record`\<`OUT_K`, `Record`\<`number`, `IN_V`\>\>
|
|
1566
|
+
|
|
1567
|
+
Defined in: [aberdeen.ts:2805](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L2805)
|
|
1568
|
+
|
|
1569
|
+
When using an object as `array`.
|
|
1570
|
+
|
|
1571
|
+
##### Type Parameters
|
|
1572
|
+
|
|
1573
|
+
###### OUT_K
|
|
1574
|
+
|
|
1575
|
+
`OUT_K` *extends* `string` \| `number` \| `symbol`
|
|
1576
|
+
|
|
1577
|
+
###### IN_V
|
|
1578
|
+
|
|
1579
|
+
`IN_V`
|
|
1580
|
+
|
|
1581
|
+
##### Parameters
|
|
1582
|
+
|
|
1583
|
+
###### source
|
|
1584
|
+
|
|
1585
|
+
`IN_V`[]
|
|
1586
|
+
|
|
1587
|
+
###### func
|
|
1588
|
+
|
|
1589
|
+
(`value`, `key`) => `undefined` \| `OUT_K` \| `OUT_K`[]
|
|
1590
|
+
|
|
1591
|
+
##### Returns
|
|
1592
|
+
|
|
1593
|
+
`Record`\<`OUT_K`, `Record`\<`number`, `IN_V`\>\>
|
|
1594
|
+
|
|
1595
|
+
#### Call Signature
|
|
1596
|
+
|
|
1597
|
+
> **partition**\<`IN_K`, `OUT_K`, `IN_V`\>(`source`, `func`): `Record`\<`OUT_K`, `Record`\<`IN_K`, `IN_V`\>\>
|
|
1598
|
+
|
|
1599
|
+
Defined in: [aberdeen.ts:2810](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L2810)
|
|
1600
|
+
|
|
1601
|
+
When using an object as `source`.
|
|
1602
|
+
|
|
1603
|
+
##### Type Parameters
|
|
1604
|
+
|
|
1605
|
+
###### IN_K
|
|
1606
|
+
|
|
1607
|
+
`IN_K` *extends* `string` \| `number` \| `symbol`
|
|
1608
|
+
|
|
1609
|
+
###### OUT_K
|
|
1610
|
+
|
|
1611
|
+
`OUT_K` *extends* `string` \| `number` \| `symbol`
|
|
1612
|
+
|
|
1613
|
+
###### IN_V
|
|
1614
|
+
|
|
1615
|
+
`IN_V`
|
|
1616
|
+
|
|
1617
|
+
##### Parameters
|
|
1618
|
+
|
|
1619
|
+
###### source
|
|
1620
|
+
|
|
1621
|
+
`Record`\<`IN_K`, `IN_V`\>
|
|
1622
|
+
|
|
1623
|
+
###### func
|
|
1624
|
+
|
|
1625
|
+
(`value`, `key`) => `undefined` \| `OUT_K` \| `OUT_K`[]
|
|
1626
|
+
|
|
1627
|
+
##### Returns
|
|
1628
|
+
|
|
1629
|
+
`Record`\<`OUT_K`, `Record`\<`IN_K`, `IN_V`\>\>
|
|
1630
|
+
|
|
1631
|
+
#### Call Signature
|
|
1632
|
+
|
|
1633
|
+
> **partition**\<`IN_K`, `OUT_K`, `IN_V`\>(`source`, `func`): `Record`\<`OUT_K`, `Record`\<`IN_K`, `IN_V`\>\>
|
|
1634
|
+
|
|
1635
|
+
Defined in: [aberdeen.ts:2819](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L2819)
|
|
1636
|
+
|
|
1637
|
+
When using a Map as `source`.
|
|
1638
|
+
|
|
1639
|
+
##### Type Parameters
|
|
1640
|
+
|
|
1641
|
+
###### IN_K
|
|
1642
|
+
|
|
1643
|
+
`IN_K` *extends* `string` \| `number` \| `symbol`
|
|
1644
|
+
|
|
1645
|
+
###### OUT_K
|
|
1646
|
+
|
|
1647
|
+
`OUT_K` *extends* `string` \| `number` \| `symbol`
|
|
1648
|
+
|
|
1649
|
+
###### IN_V
|
|
1650
|
+
|
|
1651
|
+
`IN_V`
|
|
1652
|
+
|
|
1653
|
+
##### Parameters
|
|
1654
|
+
|
|
1655
|
+
###### source
|
|
1656
|
+
|
|
1657
|
+
`Map`\<`IN_K`, `IN_V`\>
|
|
1658
|
+
|
|
1659
|
+
###### func
|
|
1660
|
+
|
|
1661
|
+
(`value`, `key`) => `undefined` \| `OUT_K` \| `OUT_K`[]
|
|
1662
|
+
|
|
1663
|
+
##### Returns
|
|
1664
|
+
|
|
1665
|
+
`Record`\<`OUT_K`, `Record`\<`IN_K`, `IN_V`\>\>
|
|
1666
|
+
|
|
1667
|
+
***
|
|
1668
|
+
|
|
1669
|
+
### peek()
|
|
1670
|
+
|
|
1671
|
+
#### Call Signature
|
|
1672
|
+
|
|
1673
|
+
> **peek**\<`T`, `K`\>(`target`, `key`): `T`\[`K`\]
|
|
1674
|
+
|
|
1675
|
+
Defined in: [aberdeen.ts:2621](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L2621)
|
|
1676
|
+
|
|
1677
|
+
Executes a function or retrieves a value *without* creating subscriptions in the current reactive scope, and returns its result.
|
|
1678
|
+
|
|
1679
|
+
This is useful when you need to access reactive data inside a reactive scope (like [$](#))
|
|
1680
|
+
but do not want changes to that specific data to trigger a re-execute of the scope.
|
|
1681
|
+
|
|
1682
|
+
Note: You may also use [unproxy](#unproxy) to get to the raw underlying data structure, which can be used to similar effect.
|
|
1683
|
+
|
|
1684
|
+
##### Type Parameters
|
|
1685
|
+
|
|
1686
|
+
###### T
|
|
1687
|
+
|
|
1688
|
+
`T` *extends* `object`
|
|
1689
|
+
|
|
1690
|
+
###### K
|
|
1691
|
+
|
|
1692
|
+
`K` *extends* `string` \| `number` \| `symbol`
|
|
1693
|
+
|
|
1694
|
+
##### Parameters
|
|
1695
|
+
|
|
1696
|
+
###### target
|
|
1697
|
+
|
|
1698
|
+
`T`
|
|
1699
|
+
|
|
1700
|
+
Either a function to execute, or an object (which may also be an Array or a Map) to index.
|
|
1701
|
+
|
|
1702
|
+
###### key
|
|
1703
|
+
|
|
1704
|
+
`K`
|
|
1705
|
+
|
|
1706
|
+
Optional key/index to use when `target` is an object.
|
|
1707
|
+
|
|
1708
|
+
##### Returns
|
|
1709
|
+
|
|
1710
|
+
`T`\[`K`\]
|
|
1711
|
+
|
|
1712
|
+
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.
|
|
1713
|
+
|
|
1714
|
+
##### Example
|
|
1715
|
+
|
|
1716
|
+
```typescript
|
|
1717
|
+
const data = proxy({ a: 1, b: 2 });
|
|
1718
|
+
$(() => {
|
|
1719
|
+
// re-executes only when data.a changes, because data.b is peeked.
|
|
1720
|
+
const b = peek(() => data.b);
|
|
1721
|
+
console.log(`A is ${data.a}, B was ${b} when A changed.`);
|
|
1722
|
+
});
|
|
1723
|
+
data.b = 3; // Does not trigger console.log
|
|
1724
|
+
data.a = 2; // Triggers console.log (logs "A is 2, B was 3 when A changed.")
|
|
1725
|
+
```
|
|
1726
|
+
|
|
1727
|
+
#### Call Signature
|
|
1728
|
+
|
|
1729
|
+
> **peek**\<`K`, `V`\>(`target`, `key`): `undefined` \| `V`
|
|
1730
|
+
|
|
1731
|
+
Defined in: [aberdeen.ts:2622](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L2622)
|
|
1732
|
+
|
|
1733
|
+
Executes a function or retrieves a value *without* creating subscriptions in the current reactive scope, and returns its result.
|
|
1734
|
+
|
|
1735
|
+
This is useful when you need to access reactive data inside a reactive scope (like [$](#))
|
|
1736
|
+
but do not want changes to that specific data to trigger a re-execute of the scope.
|
|
1737
|
+
|
|
1738
|
+
Note: You may also use [unproxy](#unproxy) to get to the raw underlying data structure, which can be used to similar effect.
|
|
1739
|
+
|
|
1740
|
+
##### Type Parameters
|
|
1741
|
+
|
|
1742
|
+
###### K
|
|
1743
|
+
|
|
1744
|
+
`K`
|
|
1745
|
+
|
|
1746
|
+
###### V
|
|
1747
|
+
|
|
1748
|
+
`V`
|
|
1749
|
+
|
|
1750
|
+
##### Parameters
|
|
1751
|
+
|
|
1752
|
+
###### target
|
|
1753
|
+
|
|
1754
|
+
`Map`\<`K`, `V`\>
|
|
1755
|
+
|
|
1756
|
+
Either a function to execute, or an object (which may also be an Array or a Map) to index.
|
|
1757
|
+
|
|
1758
|
+
###### key
|
|
1759
|
+
|
|
1760
|
+
`K`
|
|
1761
|
+
|
|
1762
|
+
Optional key/index to use when `target` is an object.
|
|
1763
|
+
|
|
1764
|
+
##### Returns
|
|
1765
|
+
|
|
1766
|
+
`undefined` \| `V`
|
|
1767
|
+
|
|
1768
|
+
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.
|
|
1769
|
+
|
|
1770
|
+
##### Example
|
|
1771
|
+
|
|
1772
|
+
```typescript
|
|
1773
|
+
const data = proxy({ a: 1, b: 2 });
|
|
1774
|
+
$(() => {
|
|
1775
|
+
// re-executes only when data.a changes, because data.b is peeked.
|
|
1776
|
+
const b = peek(() => data.b);
|
|
1777
|
+
console.log(`A is ${data.a}, B was ${b} when A changed.`);
|
|
1778
|
+
});
|
|
1779
|
+
data.b = 3; // Does not trigger console.log
|
|
1780
|
+
data.a = 2; // Triggers console.log (logs "A is 2, B was 3 when A changed.")
|
|
1781
|
+
```
|
|
1782
|
+
|
|
1783
|
+
#### Call Signature
|
|
1784
|
+
|
|
1785
|
+
> **peek**\<`T`\>(`target`, `key`): `undefined` \| `T`
|
|
1786
|
+
|
|
1787
|
+
Defined in: [aberdeen.ts:2623](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L2623)
|
|
1788
|
+
|
|
1789
|
+
Executes a function or retrieves a value *without* creating subscriptions in the current reactive scope, and returns its result.
|
|
1790
|
+
|
|
1791
|
+
This is useful when you need to access reactive data inside a reactive scope (like [$](#))
|
|
1792
|
+
but do not want changes to that specific data to trigger a re-execute of the scope.
|
|
1793
|
+
|
|
1794
|
+
Note: You may also use [unproxy](#unproxy) to get to the raw underlying data structure, which can be used to similar effect.
|
|
1795
|
+
|
|
1796
|
+
##### Type Parameters
|
|
1797
|
+
|
|
1798
|
+
###### T
|
|
1799
|
+
|
|
1800
|
+
`T`
|
|
1801
|
+
|
|
1802
|
+
##### Parameters
|
|
1803
|
+
|
|
1804
|
+
###### target
|
|
1805
|
+
|
|
1806
|
+
`T`[]
|
|
1807
|
+
|
|
1808
|
+
Either a function to execute, or an object (which may also be an Array or a Map) to index.
|
|
1809
|
+
|
|
1810
|
+
###### key
|
|
1811
|
+
|
|
1812
|
+
`number`
|
|
1813
|
+
|
|
1814
|
+
Optional key/index to use when `target` is an object.
|
|
1815
|
+
|
|
1816
|
+
##### Returns
|
|
1817
|
+
|
|
1818
|
+
`undefined` \| `T`
|
|
1819
|
+
|
|
1820
|
+
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.
|
|
1821
|
+
|
|
1822
|
+
##### Example
|
|
1823
|
+
|
|
1824
|
+
```typescript
|
|
1825
|
+
const data = proxy({ a: 1, b: 2 });
|
|
1826
|
+
$(() => {
|
|
1827
|
+
// re-executes only when data.a changes, because data.b is peeked.
|
|
1828
|
+
const b = peek(() => data.b);
|
|
1829
|
+
console.log(`A is ${data.a}, B was ${b} when A changed.`);
|
|
1830
|
+
});
|
|
1831
|
+
data.b = 3; // Does not trigger console.log
|
|
1832
|
+
data.a = 2; // Triggers console.log (logs "A is 2, B was 3 when A changed.")
|
|
1833
|
+
```
|
|
1834
|
+
|
|
1835
|
+
#### Call Signature
|
|
1836
|
+
|
|
1837
|
+
> **peek**\<`T`\>(`target`): `T`
|
|
1838
|
+
|
|
1839
|
+
Defined in: [aberdeen.ts:2624](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L2624)
|
|
1840
|
+
|
|
1841
|
+
Executes a function or retrieves a value *without* creating subscriptions in the current reactive scope, and returns its result.
|
|
1842
|
+
|
|
1843
|
+
This is useful when you need to access reactive data inside a reactive scope (like [$](#))
|
|
1844
|
+
but do not want changes to that specific data to trigger a re-execute of the scope.
|
|
1845
|
+
|
|
1846
|
+
Note: You may also use [unproxy](#unproxy) to get to the raw underlying data structure, which can be used to similar effect.
|
|
1847
|
+
|
|
1848
|
+
##### Type Parameters
|
|
1849
|
+
|
|
1850
|
+
###### T
|
|
1851
|
+
|
|
1852
|
+
`T`
|
|
1853
|
+
|
|
1854
|
+
##### Parameters
|
|
1855
|
+
|
|
1856
|
+
###### target
|
|
1857
|
+
|
|
1858
|
+
() => `T`
|
|
1859
|
+
|
|
1860
|
+
Either a function to execute, or an object (which may also be an Array or a Map) to index.
|
|
1861
|
+
|
|
1862
|
+
##### Returns
|
|
1863
|
+
|
|
1864
|
+
`T`
|
|
1865
|
+
|
|
1866
|
+
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.
|
|
1867
|
+
|
|
1868
|
+
##### Example
|
|
1869
|
+
|
|
1870
|
+
```typescript
|
|
1871
|
+
const data = proxy({ a: 1, b: 2 });
|
|
1872
|
+
$(() => {
|
|
1873
|
+
// re-executes only when data.a changes, because data.b is peeked.
|
|
1874
|
+
const b = peek(() => data.b);
|
|
1875
|
+
console.log(`A is ${data.a}, B was ${b} when A changed.`);
|
|
1876
|
+
});
|
|
1877
|
+
data.b = 3; // Does not trigger console.log
|
|
1878
|
+
data.a = 2; // Triggers console.log (logs "A is 2, B was 3 when A changed.")
|
|
1879
|
+
```
|
|
1880
|
+
|
|
1881
|
+
***
|
|
1882
|
+
|
|
1883
|
+
### proxy()
|
|
1884
|
+
|
|
1885
|
+
Creates a reactive proxy around the given data.
|
|
1886
|
+
|
|
1887
|
+
Reading properties from the returned proxy within a reactive scope (like one created by
|
|
1888
|
+
[$](#) or [derive](#derive)) establishes a subscription. Modifying properties *through*
|
|
1889
|
+
the proxy will notify subscribed scopes, causing them to re-execute.
|
|
1890
|
+
|
|
1891
|
+
- Plain objects and arrays are wrapped in a standard JavaScript `Proxy` that intercepts
|
|
1892
|
+
property access and mutations, but otherwise works like the underlying data.
|
|
1893
|
+
- Primitives (string, number, boolean, null, undefined) are wrapped in an object
|
|
1894
|
+
`{ value: T }` which is then proxied. Access the primitive via the `.value` property.
|
|
1895
|
+
- Promises are represented by proxied objects `{ busy: boolean, value?: T, error?: any }`.
|
|
1896
|
+
Initially, `busy` is `true`. When the promise resolves, `value` is set and `busy`
|
|
1897
|
+
is set to `false`. If the promise is rejected, `error` is set and `busy` is also
|
|
1898
|
+
set to `false`.
|
|
1899
|
+
|
|
1900
|
+
Use [unproxy](#unproxy) to get the original underlying data back.
|
|
1901
|
+
|
|
1902
|
+
#### Param
|
|
1903
|
+
|
|
1904
|
+
The object, array, or primitive value to make reactive.
|
|
1905
|
+
|
|
1906
|
+
#### Template
|
|
1907
|
+
|
|
1908
|
+
The type of the data being proxied.
|
|
1909
|
+
|
|
1910
|
+
#### Examples
|
|
1911
|
+
|
|
1912
|
+
```javascript
|
|
1913
|
+
const state = proxy({ count: 0, message: 'Hello' });
|
|
1914
|
+
$(() => console.log(state.message)); // Subscribes to message
|
|
1915
|
+
setTimeout(() => state.message = 'World', 1000); // Triggers the observing function
|
|
1916
|
+
setTimeout(() => state.count++, 2000); // Triggers nothing
|
|
1917
|
+
```
|
|
1918
|
+
|
|
1919
|
+
```javascript
|
|
1920
|
+
const items = proxy(['a', 'b']);
|
|
1921
|
+
$(() => console.log(items.length)); // Subscribes to length
|
|
1922
|
+
setTimeout(() => items.push('c'), 2000); // Triggers the observing function
|
|
1923
|
+
```
|
|
1924
|
+
|
|
1925
|
+
```javascript
|
|
1926
|
+
const name = proxy('Aberdeen');
|
|
1927
|
+
$(() => console.log(name.value)); // Subscribes to value
|
|
1928
|
+
setTimeout(() => name.value = 'UI', 2000); // Triggers the observing function
|
|
1929
|
+
```
|
|
1930
|
+
|
|
1931
|
+
```typescript
|
|
1932
|
+
class Widget {
|
|
1933
|
+
constructor(public name: string, public width: number, public height: number) {}
|
|
1934
|
+
grow() { this.width *= 2; }
|
|
1935
|
+
toString() { return `${this.name}Widget (${this.width}x${this.height})`; }
|
|
1936
|
+
}
|
|
1937
|
+
let graph: Widget = proxy(new Widget('Graph', 200, 100));
|
|
1938
|
+
$(() => console.log(''+graph));
|
|
1939
|
+
setTimeout(() => graph.grow(), 2000);
|
|
1940
|
+
setTimeout(() => graph.grow(), 4000);
|
|
1941
|
+
```
|
|
1942
|
+
|
|
1943
|
+
#### Call Signature
|
|
1944
|
+
|
|
1945
|
+
> **proxy**\<`T`\>(`target`): [`PromiseProxy`](#promiseproxy)\<`T`\>
|
|
1946
|
+
|
|
1947
|
+
Defined in: [aberdeen.ts:1330](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L1330)
|
|
1948
|
+
|
|
1949
|
+
##### Type Parameters
|
|
1950
|
+
|
|
1951
|
+
###### T
|
|
1952
|
+
|
|
1953
|
+
`T` *extends* `unknown`
|
|
1954
|
+
|
|
1955
|
+
##### Parameters
|
|
1956
|
+
|
|
1957
|
+
###### target
|
|
1958
|
+
|
|
1959
|
+
`Promise`\<`T`\>
|
|
1960
|
+
|
|
1961
|
+
##### Returns
|
|
1962
|
+
|
|
1963
|
+
[`PromiseProxy`](#promiseproxy)\<`T`\>
|
|
1964
|
+
|
|
1965
|
+
#### Call Signature
|
|
1966
|
+
|
|
1967
|
+
> **proxy**\<`T`\>(`target`): `T` *extends* `number` ? `number` : `T` *extends* `string` ? `string` : `T` *extends* `boolean` ? `boolean` : `T`[]
|
|
1968
|
+
|
|
1969
|
+
Defined in: [aberdeen.ts:1331](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L1331)
|
|
1970
|
+
|
|
1971
|
+
##### Type Parameters
|
|
1972
|
+
|
|
1973
|
+
###### T
|
|
1974
|
+
|
|
1975
|
+
`T` *extends* `unknown`
|
|
1976
|
+
|
|
1977
|
+
##### Parameters
|
|
1978
|
+
|
|
1979
|
+
###### target
|
|
1980
|
+
|
|
1981
|
+
`T`[]
|
|
1982
|
+
|
|
1983
|
+
##### Returns
|
|
1984
|
+
|
|
1985
|
+
`T` *extends* `number` ? `number` : `T` *extends* `string` ? `string` : `T` *extends* `boolean` ? `boolean` : `T`[]
|
|
1986
|
+
|
|
1987
|
+
#### Call Signature
|
|
1988
|
+
|
|
1989
|
+
> **proxy**\<`T`\>(`target`): `T`
|
|
1990
|
+
|
|
1991
|
+
Defined in: [aberdeen.ts:1332](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L1332)
|
|
1992
|
+
|
|
1993
|
+
##### Type Parameters
|
|
1994
|
+
|
|
1995
|
+
###### T
|
|
1996
|
+
|
|
1997
|
+
`T` *extends* `object`
|
|
1998
|
+
|
|
1999
|
+
##### Parameters
|
|
2000
|
+
|
|
2001
|
+
###### target
|
|
2002
|
+
|
|
2003
|
+
`T`
|
|
2004
|
+
|
|
2005
|
+
##### Returns
|
|
2006
|
+
|
|
2007
|
+
`T`
|
|
2008
|
+
|
|
2009
|
+
#### Call Signature
|
|
2010
|
+
|
|
2011
|
+
> **proxy**\<`T`\>(`target`): `ValueRef`\<`T` *extends* `number` ? `number` : `T` *extends* `string` ? `string` : `T` *extends* `boolean` ? `boolean` : `T`\>
|
|
2012
|
+
|
|
2013
|
+
Defined in: [aberdeen.ts:1333](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L1333)
|
|
2014
|
+
|
|
2015
|
+
##### Type Parameters
|
|
2016
|
+
|
|
2017
|
+
###### T
|
|
2018
|
+
|
|
2019
|
+
`T` *extends* `unknown`
|
|
2020
|
+
|
|
2021
|
+
##### Parameters
|
|
2022
|
+
|
|
2023
|
+
###### target
|
|
2024
|
+
|
|
2025
|
+
`T`
|
|
2026
|
+
|
|
2027
|
+
##### Returns
|
|
2028
|
+
|
|
2029
|
+
`ValueRef`\<`T` *extends* `number` ? `number` : `T` *extends* `string` ? `string` : `T` *extends* `boolean` ? `boolean` : `T`\>
|
|
2030
|
+
|
|
2031
|
+
***
|
|
2032
|
+
|
|
2033
|
+
### ref()
|
|
2034
|
+
|
|
2035
|
+
> **ref**\<`T`, `K`\>(`target`, `index`): `ValueRef`\<`T`\[`K`\]\>
|
|
2036
|
+
|
|
2037
|
+
Defined in: [aberdeen.ts:1906](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L1906)
|
|
2038
|
+
|
|
2039
|
+
Creates a reactive reference (`{ value: T }`-like object) to a specific value
|
|
2040
|
+
within a proxied object or array.
|
|
2041
|
+
|
|
2042
|
+
This is primarily used for the `bind` property in [$](#) to create two-way data bindings
|
|
2043
|
+
with form elements, and for passing a reactive property to any of the [$](#) key-value pairs.
|
|
2044
|
+
|
|
2045
|
+
Reading `ref.value` accesses the property from the underlying proxy (and subscribes the current scope).
|
|
2046
|
+
Assigning to `ref.value` updates the property in the underlying proxy (triggering reactive updates).
|
|
2047
|
+
|
|
2048
|
+
#### Type Parameters
|
|
2049
|
+
|
|
2050
|
+
##### T
|
|
2051
|
+
|
|
2052
|
+
`T` *extends* `TargetType`
|
|
2053
|
+
|
|
2054
|
+
##### K
|
|
2055
|
+
|
|
2056
|
+
`K` *extends* `string` \| `number` \| `symbol`
|
|
2057
|
+
|
|
2058
|
+
#### Parameters
|
|
2059
|
+
|
|
2060
|
+
##### target
|
|
2061
|
+
|
|
2062
|
+
`T`
|
|
2063
|
+
|
|
2064
|
+
The reactive proxy (created by [proxy](#proxy)) containing the target property.
|
|
2065
|
+
|
|
2066
|
+
##### index
|
|
2067
|
+
|
|
2068
|
+
`K`
|
|
2069
|
+
|
|
2070
|
+
The key (for objects) or index (for arrays) of the property to reference.
|
|
2071
|
+
|
|
2072
|
+
#### Returns
|
|
2073
|
+
|
|
2074
|
+
`ValueRef`\<`T`\[`K`\]\>
|
|
2075
|
+
|
|
2076
|
+
A reference object with a `value` property linked to the specified proxy property.
|
|
2077
|
+
|
|
2078
|
+
#### Example
|
|
2079
|
+
|
|
2080
|
+
```javascript
|
|
2081
|
+
const formData = proxy({ color: 'orange', velocity: 42 });
|
|
2082
|
+
|
|
2083
|
+
// Usage with `bind`
|
|
2084
|
+
$('input type=text bind=', ref(formData, 'color'));
|
|
2085
|
+
|
|
2086
|
+
// Usage as a dynamic property, causes a TextNode with just the name to be created and live-updated
|
|
2087
|
+
$('p text="Selected color: " text=', ref(formData, 'color'), 'color:', ref(formData, 'color'));
|
|
2088
|
+
|
|
2089
|
+
// Changes are actually stored in formData - this causes logs like `{color: "Blue", velocity 42}`
|
|
2090
|
+
$(() => console.log(formData))
|
|
2091
|
+
```
|
|
2092
|
+
|
|
2093
|
+
***
|
|
2094
|
+
|
|
2095
|
+
### runQueue()
|
|
2096
|
+
|
|
2097
|
+
> **runQueue**(): `void`
|
|
2098
|
+
|
|
2099
|
+
Defined in: [aberdeen.ts:69](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L69)
|
|
2100
|
+
|
|
2101
|
+
Forces the immediate and synchronous execution of all pending reactive updates.
|
|
2102
|
+
|
|
2103
|
+
Normally, changes to observed data sources (like proxied objects or arrays)
|
|
2104
|
+
are processed asynchronously in a batch after a brief timeout (0ms). This function
|
|
2105
|
+
allows you to bypass the timeout and process the update queue immediately.
|
|
2106
|
+
|
|
2107
|
+
This can be useful in specific scenarios where you need the DOM to be updated
|
|
2108
|
+
synchronously.
|
|
2109
|
+
|
|
2110
|
+
This function is re-entrant, meaning it is safe to call `runQueue` from within
|
|
2111
|
+
a function that is itself being executed as part of an update cycle triggered
|
|
2112
|
+
by a previous (or the same) `runQueue` call.
|
|
2113
|
+
|
|
2114
|
+
#### Returns
|
|
2115
|
+
|
|
2116
|
+
`void`
|
|
2117
|
+
|
|
2118
|
+
#### Example
|
|
2119
|
+
|
|
2120
|
+
```typescript
|
|
2121
|
+
const data = proxy("before");
|
|
2122
|
+
|
|
2123
|
+
$('#'+data);
|
|
2124
|
+
console.log(1, document.body.innerHTML); // before
|
|
2125
|
+
|
|
2126
|
+
// Make an update that should cause the DOM to change.
|
|
2127
|
+
data.value = "after";
|
|
2128
|
+
|
|
2129
|
+
// Normally, the DOM update would happen after a timeout.
|
|
2130
|
+
// But this causes an immediate update:
|
|
2131
|
+
runQueue();
|
|
2132
|
+
|
|
2133
|
+
console.log(2, document.body.innerHTML); // after
|
|
2134
|
+
```
|
|
2135
|
+
|
|
2136
|
+
***
|
|
2137
|
+
|
|
2138
|
+
### setErrorHandler()
|
|
2139
|
+
|
|
2140
|
+
> **setErrorHandler**(`handler?`): `void`
|
|
2141
|
+
|
|
2142
|
+
Defined in: [aberdeen.ts:2409](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L2409)
|
|
2143
|
+
|
|
2144
|
+
Sets a custom error handler function for errors that occur asynchronously
|
|
2145
|
+
within reactive scopes (e.g., during updates triggered by proxy changes in
|
|
2146
|
+
[derive](#derive) or [$](#) render functions).
|
|
2147
|
+
|
|
2148
|
+
The default handler logs the error to `console.error` and adds a simple
|
|
2149
|
+
'Error' message div to the DOM at the location where the error occurred (if possible).
|
|
2150
|
+
|
|
2151
|
+
Your handler can provide custom logging, UI feedback, or suppress the default
|
|
2152
|
+
error message.
|
|
2153
|
+
|
|
2154
|
+
#### Parameters
|
|
2155
|
+
|
|
2156
|
+
##### handler?
|
|
2157
|
+
|
|
2158
|
+
(`error`) => `undefined` \| `boolean`
|
|
2159
|
+
|
|
2160
|
+
A function that accepts the `Error` object.
|
|
2161
|
+
- Return `false` to prevent adding an error message to the DOM.
|
|
2162
|
+
- Return `true` or `undefined` (or throw) to allow the error messages to be added to the DOM.
|
|
2163
|
+
|
|
2164
|
+
#### Returns
|
|
2165
|
+
|
|
2166
|
+
`void`
|
|
2167
|
+
|
|
2168
|
+
#### Example
|
|
2169
|
+
|
|
2170
|
+
```typescript
|
|
2171
|
+
setErrorHandler(error => {
|
|
2172
|
+
console.warn('Aberdeen render error:', error.message);
|
|
2173
|
+
// Log to error reporting service
|
|
2174
|
+
// myErrorReporter.log(error);
|
|
2175
|
+
|
|
2176
|
+
try {
|
|
2177
|
+
// Attempt to show a custom message in the UI
|
|
2178
|
+
$('div.error-message#Oops, something went wrong!');
|
|
2179
|
+
} catch (e) {
|
|
2180
|
+
// Ignore errors during error handling itself
|
|
2181
|
+
}
|
|
2182
|
+
|
|
2183
|
+
return false; // Suppress default console log and DOM error message
|
|
2184
|
+
});
|
|
2185
|
+
|
|
2186
|
+
// Styling for our custom error message
|
|
2187
|
+
insertCss({
|
|
2188
|
+
'.error-message': {
|
|
2189
|
+
backgroundColor: '#e31f00',
|
|
2190
|
+
display: 'inline-block',
|
|
2191
|
+
color: 'white',
|
|
2192
|
+
borderRadius: '3px',
|
|
2193
|
+
padding: '2px 4px',
|
|
2194
|
+
}
|
|
2195
|
+
}, true); // global style
|
|
2196
|
+
|
|
2197
|
+
// Cause an error within a render scope.
|
|
2198
|
+
$('div.box', () => {
|
|
2199
|
+
// Will cause our error handler to insert an error message within the box
|
|
2200
|
+
noSuchFunction();
|
|
2201
|
+
})
|
|
2202
|
+
```
|
|
2203
|
+
|
|
2204
|
+
***
|
|
2205
|
+
|
|
2206
|
+
### setSpacingCssVars()
|
|
2207
|
+
|
|
2208
|
+
> **setSpacingCssVars**(`base`, `unit`): `void`
|
|
2209
|
+
|
|
2210
|
+
Defined in: [aberdeen.ts:1759](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L1759)
|
|
2211
|
+
|
|
2212
|
+
Initializes `cssVars[1]` through `cssVars[12]` with an exponential spacing scale.
|
|
2213
|
+
|
|
2214
|
+
The scale is calculated as `2^(n-3) * base`, providing values from `0.25 * base` to `512 * base`.
|
|
2215
|
+
|
|
2216
|
+
#### Parameters
|
|
2217
|
+
|
|
2218
|
+
##### base
|
|
2219
|
+
|
|
2220
|
+
`number` = `1`
|
|
2221
|
+
|
|
2222
|
+
The base size for the spacing scale (default: 1). If unit is 'rem' or 'em', this is in that unit. If unit is 'px', this is the pixel value.
|
|
2223
|
+
|
|
2224
|
+
##### unit
|
|
2225
|
+
|
|
2226
|
+
`string` = `'rem'`
|
|
2227
|
+
|
|
2228
|
+
The CSS unit to use (default: 'rem'). Can be 'rem', 'em', 'px', or any other valid CSS unit.
|
|
2229
|
+
|
|
2230
|
+
#### Returns
|
|
2231
|
+
|
|
2232
|
+
`void`
|
|
2233
|
+
|
|
2234
|
+
#### Example
|
|
2235
|
+
|
|
2236
|
+
```javascript
|
|
2237
|
+
// Use default scale (0.25rem to 512rem)
|
|
2238
|
+
setSpacingCssVars();
|
|
2239
|
+
|
|
2240
|
+
// Use custom base size
|
|
2241
|
+
setSpacingCssVars(16, 'px'); // 4px to 8192px
|
|
2242
|
+
|
|
2243
|
+
// Use em units
|
|
2244
|
+
setSpacingCssVars(1, 'em'); // 0.25em to 512em
|
|
2245
|
+
```
|
|
2246
|
+
|
|
2247
|
+
***
|
|
2248
|
+
|
|
2249
|
+
### unmountAll()
|
|
2250
|
+
|
|
2251
|
+
> **unmountAll**(): `void`
|
|
2252
|
+
|
|
2253
|
+
Defined in: [aberdeen.ts:2590](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L2590)
|
|
2254
|
+
|
|
2255
|
+
Removes all Aberdeen-managed DOM nodes and stops all active reactive scopes
|
|
2256
|
+
(created by [mount](#mount), [derive](#derive), [$](#) with functions, etc.).
|
|
2257
|
+
|
|
2258
|
+
This effectively cleans up the entire Aberdeen application state.
|
|
2259
|
+
|
|
2260
|
+
#### Returns
|
|
2261
|
+
|
|
2262
|
+
`void`
|
|
2263
|
+
|
|
2264
|
+
***
|
|
2265
|
+
|
|
2266
|
+
### unproxy()
|
|
2267
|
+
|
|
2268
|
+
> **unproxy**\<`T`\>(`target`): `T`
|
|
2269
|
+
|
|
2270
|
+
Defined in: [aberdeen.ts:1447](https://github.com/vanviegen/aberdeen/blob/6b79c7fce769810bdcbd326b8ee6ef1c8e1fc011/src/aberdeen.ts#L1447)
|
|
2271
|
+
|
|
2272
|
+
Returns the original, underlying data target from a reactive proxy created by [proxy](#proxy).
|
|
2273
|
+
If the input `target` is not a proxy, it is returned directly.
|
|
2274
|
+
|
|
2275
|
+
This is useful when you want to avoid triggering subscriptions during read operations or
|
|
2276
|
+
re-executes during write operations. Using [peek](#peek) is an alternative way to achieve this.
|
|
2277
|
+
|
|
2278
|
+
#### Type Parameters
|
|
2279
|
+
|
|
2280
|
+
##### T
|
|
2281
|
+
|
|
2282
|
+
`T`
|
|
2283
|
+
|
|
2284
|
+
The type of the target.
|
|
2285
|
+
|
|
2286
|
+
#### Parameters
|
|
2287
|
+
|
|
2288
|
+
##### target
|
|
2289
|
+
|
|
2290
|
+
`T`
|
|
2291
|
+
|
|
2292
|
+
A proxied object, array, or any other value.
|
|
2293
|
+
|
|
2294
|
+
#### Returns
|
|
2295
|
+
|
|
2296
|
+
`T`
|
|
2297
|
+
|
|
2298
|
+
The underlying (unproxied) data, or the input value if it wasn't a proxy.
|
|
2299
|
+
|
|
2300
|
+
#### Example
|
|
2301
|
+
|
|
2302
|
+
```typescript
|
|
2303
|
+
const userProxy = proxy({ name: 'Frank' });
|
|
2304
|
+
const rawUser = unproxy(userProxy);
|
|
2305
|
+
|
|
2306
|
+
// Log reactively
|
|
2307
|
+
$(() => console.log('proxied', userProxy.name));
|
|
2308
|
+
// The following will only ever log once, as we're not subscribing to any observable
|
|
2309
|
+
$(() => console.log('unproxied', rawUser.name));
|
|
2310
|
+
|
|
2311
|
+
// This cause the first log to run again:
|
|
2312
|
+
setTimeout(() => userProxy.name += '!', 1000);
|
|
2313
|
+
|
|
2314
|
+
// This doesn't cause any new logs:
|
|
2315
|
+
setTimeout(() => rawUser.name += '?', 2000);
|
|
2316
|
+
|
|
2317
|
+
// Both userProxy and rawUser end up as `{name: 'Frank!?'}`
|
|
2318
|
+
setTimeout(() => {
|
|
2319
|
+
console.log('final proxied', userProxy)
|
|
2320
|
+
console.log('final unproxied', rawUser)
|
|
2321
|
+
}, 3000);
|
|
2322
|
+
```
|