ripple 0.2.83 → 0.2.84
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/package.json +1 -1
- package/src/compiler/phases/1-parse/index.js +1151 -1121
- package/src/compiler/phases/2-analyze/index.js +561 -523
- package/src/compiler/phases/3-transform/client/index.js +84 -28
- package/src/compiler/phases/3-transform/server/index.js +1 -1
- package/src/compiler/utils.js +613 -595
- package/src/runtime/index-client.js +8 -2
- package/src/runtime/internal/client/constants.js +9 -8
- package/src/runtime/internal/client/head.js +14 -0
- package/src/runtime/internal/client/index.js +42 -35
- package/src/runtime/internal/client/operations.js +34 -30
- package/src/runtime/internal/client/runtime.js +22 -27
- package/tests/client/basic.test.ripple +105 -11
- package/types/index.d.ts +6 -11
|
@@ -25,7 +25,7 @@ export function mount(component, options) {
|
|
|
25
25
|
if (target.firstChild) {
|
|
26
26
|
target.textContent = '';
|
|
27
27
|
}
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
target.append(anchor);
|
|
30
30
|
|
|
31
31
|
const cleanup_events = handle_root_events(target);
|
|
@@ -42,7 +42,13 @@ export function mount(component, options) {
|
|
|
42
42
|
|
|
43
43
|
export { create_context as createContext } from './internal/client/context.js';
|
|
44
44
|
|
|
45
|
-
export {
|
|
45
|
+
export {
|
|
46
|
+
flush_sync as flushSync,
|
|
47
|
+
track,
|
|
48
|
+
trackSplit,
|
|
49
|
+
untrack,
|
|
50
|
+
deferred,
|
|
51
|
+
} from './internal/client/runtime.js';
|
|
46
52
|
|
|
47
53
|
export { TrackedArray } from './array.js';
|
|
48
54
|
|
|
@@ -7,14 +7,15 @@ export var TRY_BLOCK = 1 << 6;
|
|
|
7
7
|
export var IF_BLOCK = 1 << 7;
|
|
8
8
|
export var COMPOSITE_BLOCK = 1 << 8;
|
|
9
9
|
export var ASYNC_BLOCK = 1 << 9;
|
|
10
|
-
export var
|
|
11
|
-
export var
|
|
12
|
-
export var
|
|
13
|
-
export var
|
|
14
|
-
export var
|
|
15
|
-
export var
|
|
16
|
-
export var
|
|
17
|
-
export var
|
|
10
|
+
export var HEAD_BLOCK = 1 << 10;
|
|
11
|
+
export var CONTAINS_UPDATE = 1 << 11;
|
|
12
|
+
export var CONTAINS_TEARDOWN = 1 << 12;
|
|
13
|
+
export var BLOCK_HAS_RUN = 1 << 13;
|
|
14
|
+
export var TRACKED = 1 << 14;
|
|
15
|
+
export var DERIVED = 1 << 15;
|
|
16
|
+
export var DEFERRED = 1 << 16;
|
|
17
|
+
export var PAUSED = 1 << 17;
|
|
18
|
+
export var DESTROYED = 1 << 18;
|
|
18
19
|
|
|
19
20
|
export var CONTROL_FLOW_BLOCK = FOR_BLOCK | IF_BLOCK | TRY_BLOCK | COMPOSITE_BLOCK;
|
|
20
21
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { render } from './blocks.js';
|
|
2
|
+
import { HEAD_BLOCK } from './constants.js';
|
|
3
|
+
import { create_text } from './operations.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @param {(anchor: Node) => void} render_fn
|
|
7
|
+
* @returns {void}
|
|
8
|
+
*/
|
|
9
|
+
export function head(render_fn) {
|
|
10
|
+
/** @type {Comment | Text} */
|
|
11
|
+
var anchor = document.head.appendChild(create_text());
|
|
12
|
+
|
|
13
|
+
render(() => render_fn(anchor), HEAD_BLOCK);
|
|
14
|
+
}
|
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export {
|
|
2
|
+
first_child as child,
|
|
3
|
+
child_frag,
|
|
4
|
+
next_sibling as sibling,
|
|
5
|
+
document,
|
|
6
|
+
} from './operations.js';
|
|
2
7
|
|
|
3
8
|
export {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
set_text,
|
|
10
|
+
set_class,
|
|
11
|
+
set_attribute,
|
|
12
|
+
set_value,
|
|
13
|
+
set_checked,
|
|
14
|
+
set_selected,
|
|
10
15
|
} from './render.js';
|
|
11
16
|
|
|
12
17
|
export { render, render_spread, async, ref } from './blocks.js';
|
|
@@ -14,33 +19,33 @@ export { render, render_spread, async, ref } from './blocks.js';
|
|
|
14
19
|
export { event, delegate } from './events.js';
|
|
15
20
|
|
|
16
21
|
export {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
22
|
+
active_block,
|
|
23
|
+
scope,
|
|
24
|
+
safe_scope,
|
|
25
|
+
with_scope,
|
|
26
|
+
get,
|
|
27
|
+
get_tracked,
|
|
28
|
+
get_derived,
|
|
29
|
+
set,
|
|
30
|
+
async_computed,
|
|
31
|
+
tracked,
|
|
32
|
+
spread_props,
|
|
33
|
+
computed_property,
|
|
34
|
+
call_property,
|
|
35
|
+
get_property,
|
|
36
|
+
set_property,
|
|
37
|
+
update,
|
|
38
|
+
update_pre,
|
|
39
|
+
update_property,
|
|
40
|
+
update_pre_property,
|
|
41
|
+
push_component,
|
|
42
|
+
pop_component,
|
|
43
|
+
untrack,
|
|
44
|
+
ref_prop,
|
|
45
|
+
fallback,
|
|
46
|
+
exclude_from_object,
|
|
47
|
+
derived,
|
|
48
|
+
maybe_tracked,
|
|
44
49
|
} from './runtime.js';
|
|
45
50
|
|
|
46
51
|
export { composite } from './composite.js';
|
|
@@ -53,4 +58,6 @@ export { try_block as try, aborted } from './try.js';
|
|
|
53
58
|
|
|
54
59
|
export { template, append } from './template.js';
|
|
55
60
|
|
|
56
|
-
export { tracked_array } from '../../array.js';
|
|
61
|
+
export { tracked_array } from '../../array.js';
|
|
62
|
+
|
|
63
|
+
export { head } from './head.js';
|
|
@@ -5,34 +5,38 @@ var first_child_getter;
|
|
|
5
5
|
/** @type {() => Node | null} */
|
|
6
6
|
var next_sibling_getter;
|
|
7
7
|
|
|
8
|
+
/** @type {Document} */
|
|
9
|
+
export var document;
|
|
10
|
+
|
|
8
11
|
export var is_firefox;
|
|
9
12
|
|
|
10
13
|
export function init_operations() {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
var node_prototype = Node.prototype;
|
|
15
|
+
var element_prototype = Element.prototype;
|
|
16
|
+
var object_prototype = Object.prototype;
|
|
17
|
+
var event_target_prototype = EventTarget.prototype;
|
|
15
18
|
|
|
16
|
-
|
|
19
|
+
is_firefox = /Firefox/.test(navigator.userAgent);
|
|
20
|
+
document = window.document;
|
|
17
21
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
// @ts-ignore
|
|
23
|
+
first_child_getter = get_descriptor(node_prototype, 'firstChild').get;
|
|
24
|
+
// @ts-ignore
|
|
25
|
+
next_sibling_getter = get_descriptor(node_prototype, 'nextSibling').get;
|
|
22
26
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
27
|
+
// the following assignments improve perf of lookups on DOM nodes
|
|
28
|
+
// @ts-expect-error
|
|
29
|
+
element_prototype.__click = undefined;
|
|
30
|
+
// @ts-expect-error
|
|
31
|
+
element_prototype.__className = '';
|
|
32
|
+
// @ts-expect-error
|
|
33
|
+
element_prototype.__attributes = null;
|
|
34
|
+
// @ts-expect-error
|
|
35
|
+
element_prototype.__styles = null;
|
|
36
|
+
// @ts-expect-error
|
|
37
|
+
element_prototype.__e = undefined;
|
|
38
|
+
// @ts-expect-error
|
|
39
|
+
event_target_prototype.__root = undefined;
|
|
36
40
|
}
|
|
37
41
|
|
|
38
42
|
/**
|
|
@@ -42,16 +46,16 @@ export function init_operations() {
|
|
|
42
46
|
*/
|
|
43
47
|
/*@__NO_SIDE_EFFECTS__*/
|
|
44
48
|
export function first_child(node) {
|
|
45
|
-
|
|
49
|
+
return first_child_getter.call(node);
|
|
46
50
|
}
|
|
47
51
|
|
|
48
52
|
export function child_frag(node) {
|
|
49
|
-
|
|
53
|
+
var child = first_child(node);
|
|
50
54
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
+
if (child.nodeType === 8 && child.data === '') {
|
|
56
|
+
return next_sibling(child);
|
|
57
|
+
}
|
|
58
|
+
return child;
|
|
55
59
|
}
|
|
56
60
|
|
|
57
61
|
/**
|
|
@@ -61,9 +65,9 @@ export function child_frag(node) {
|
|
|
61
65
|
*/
|
|
62
66
|
/*@__NO_SIDE_EFFECTS__*/
|
|
63
67
|
export function next_sibling(node) {
|
|
64
|
-
|
|
68
|
+
return next_sibling_getter.call(node);
|
|
65
69
|
}
|
|
66
70
|
|
|
67
71
|
export function create_text(value = '') {
|
|
68
|
-
|
|
72
|
+
return document.createTextNode(value);
|
|
69
73
|
}
|
|
@@ -289,36 +289,35 @@ export function derived(fn, block, get, set) {
|
|
|
289
289
|
|
|
290
290
|
/**
|
|
291
291
|
* @param {any} v
|
|
292
|
-
* @param {
|
|
292
|
+
* @param {Function | undefined} get
|
|
293
|
+
* @param {Function | undefined} set
|
|
293
294
|
* @param {Block} b
|
|
294
|
-
* @returns {Tracked | Derived
|
|
295
|
+
* @returns {Tracked | Derived}
|
|
295
296
|
*/
|
|
296
|
-
export function track(v,
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
var set;
|
|
300
|
-
|
|
301
|
-
if (o !== undefined) {
|
|
302
|
-
get = o.get;
|
|
303
|
-
set = o.set;
|
|
297
|
+
export function track(v, get, set, b) {
|
|
298
|
+
if (is_tracked_object(v)) {
|
|
299
|
+
return v;
|
|
304
300
|
}
|
|
305
301
|
|
|
306
|
-
if (
|
|
307
|
-
|
|
308
|
-
return v;
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
if (typeof v === 'function') {
|
|
312
|
-
return derived(v, b, get, set);
|
|
313
|
-
}
|
|
314
|
-
return tracked(v, b, get, set);
|
|
302
|
+
if (typeof v === 'function') {
|
|
303
|
+
return derived(v, b, get, set);
|
|
315
304
|
}
|
|
305
|
+
return tracked(v, b, get, set);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* @param {Record<string|symbol, any>} v
|
|
310
|
+
* @param {(symbol | string)[]} l
|
|
311
|
+
* @param {Block} b
|
|
312
|
+
* @returns {Tracked[]}
|
|
313
|
+
*/
|
|
314
|
+
export function trackSplit(v, l, b) {
|
|
315
|
+
var is_tracked = is_tracked_object(v);
|
|
316
316
|
|
|
317
317
|
if (is_tracked || typeof v !== 'object' || v === null || is_array(v)) {
|
|
318
318
|
throw new TypeError('Invalid value: expected a non-tracked object');
|
|
319
319
|
}
|
|
320
320
|
|
|
321
|
-
var list = o.split ?? [];
|
|
322
321
|
/** @type {Tracked[]} */
|
|
323
322
|
var out = [];
|
|
324
323
|
/** @type {Record<string|symbol, any>} */
|
|
@@ -326,8 +325,8 @@ export function track(v, o, b) {
|
|
|
326
325
|
/** @type {Record<PropertyKey, any | null>} */
|
|
327
326
|
var descriptors = get_descriptors(v);
|
|
328
327
|
|
|
329
|
-
for (let i = 0, key, t, exists = true; i <
|
|
330
|
-
key =
|
|
328
|
+
for (let i = 0, key, t, exists = true; i < l.length; i++) {
|
|
329
|
+
key = l[i];
|
|
331
330
|
|
|
332
331
|
if (is_tracked_object(v[key])) {
|
|
333
332
|
t = v[key];
|
|
@@ -775,7 +774,7 @@ export function get_tracked(tracked) {
|
|
|
775
774
|
}
|
|
776
775
|
var get = tracked.a.get;
|
|
777
776
|
if (get) {
|
|
778
|
-
|
|
777
|
+
value = get(value);
|
|
779
778
|
}
|
|
780
779
|
return value;
|
|
781
780
|
}
|
|
@@ -791,10 +790,6 @@ export function set(tracked, value, block) {
|
|
|
791
790
|
if (value !== old_value) {
|
|
792
791
|
var tracked_block = tracked.b;
|
|
793
792
|
|
|
794
|
-
if (!tracked_block) {
|
|
795
|
-
debugger;
|
|
796
|
-
}
|
|
797
|
-
|
|
798
793
|
if ((block.f & CONTAINS_TEARDOWN) !== 0) {
|
|
799
794
|
if (teardown) {
|
|
800
795
|
old_values.set(tracked, value);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
-
import { mount, flushSync, effect, track } from 'ripple';
|
|
2
|
+
import { mount, flushSync, effect, track, trackSplit } from 'ripple';
|
|
3
3
|
import { compile } from 'ripple/compiler';
|
|
4
|
+
import { TRACKED_ARRAY } from '../../src/runtime/internal/client/constants.js';
|
|
4
5
|
|
|
5
6
|
describe('basic client', () => {
|
|
6
7
|
let container;
|
|
@@ -1271,7 +1272,7 @@ describe('basic client', () => {
|
|
|
1271
1272
|
expect(container).toMatchSnapshot();
|
|
1272
1273
|
});
|
|
1273
1274
|
|
|
1274
|
-
it('can retain reactivity for destructure rest via track
|
|
1275
|
+
it('can retain reactivity for destructure rest via track trackSplit', () => {
|
|
1275
1276
|
let logs = [];
|
|
1276
1277
|
|
|
1277
1278
|
component App() {
|
|
@@ -1296,7 +1297,7 @@ describe('basic client', () => {
|
|
|
1296
1297
|
}
|
|
1297
1298
|
|
|
1298
1299
|
component Child(props: PropsWithChildren<{ count: Tracked<number> }>) {
|
|
1299
|
-
const [children, count, rest] =
|
|
1300
|
+
const [children, count, rest] = trackSplit(props, ['children', 'count']);
|
|
1300
1301
|
|
|
1301
1302
|
if (@count < 2) {
|
|
1302
1303
|
<button {...@rest}><@children /></button>
|
|
@@ -1329,12 +1330,12 @@ describe('basic client', () => {
|
|
|
1329
1330
|
expect(logs).toEqual(['ref called','cleanup ref']);
|
|
1330
1331
|
});
|
|
1331
1332
|
|
|
1332
|
-
it('errors on invalid value as null for track with
|
|
1333
|
+
it('errors on invalid value as null for track with trackSplit', () => {
|
|
1333
1334
|
component App() {
|
|
1334
1335
|
let message = track('');
|
|
1335
1336
|
|
|
1336
1337
|
try{
|
|
1337
|
-
const [a, b, rest] =
|
|
1338
|
+
const [a, b, rest] = trackSplit(null, ['a', 'b']);
|
|
1338
1339
|
} catch(e) {
|
|
1339
1340
|
@message = e.message;
|
|
1340
1341
|
}
|
|
@@ -1348,12 +1349,12 @@ describe('basic client', () => {
|
|
|
1348
1349
|
expect(pre.textContent).toBe('Invalid value: expected a non-tracked object');
|
|
1349
1350
|
});
|
|
1350
1351
|
|
|
1351
|
-
it('errors on invalid value as array for track with
|
|
1352
|
+
it('errors on invalid value as array for track with trackSplit', () => {
|
|
1352
1353
|
component App() {
|
|
1353
1354
|
let message = track('');
|
|
1354
1355
|
|
|
1355
1356
|
try{
|
|
1356
|
-
const [a, b, rest] =
|
|
1357
|
+
const [a, b, rest] = trackSplit([1, 2, 3], ['a', 'b']);
|
|
1357
1358
|
} catch(e) {
|
|
1358
1359
|
@message = e.message;
|
|
1359
1360
|
}
|
|
@@ -1367,13 +1368,13 @@ describe('basic client', () => {
|
|
|
1367
1368
|
expect(pre.textContent).toBe('Invalid value: expected a non-tracked object');
|
|
1368
1369
|
});
|
|
1369
1370
|
|
|
1370
|
-
it('errors on invalid value as tracked for track with
|
|
1371
|
+
it('errors on invalid value as tracked for track with trackSplit', () => {
|
|
1371
1372
|
component App() {
|
|
1372
1373
|
const t = track({a: 1, b: 2, c: 3});
|
|
1373
1374
|
let message = track('');
|
|
1374
1375
|
|
|
1375
1376
|
try{
|
|
1376
|
-
const [a, b, rest] =
|
|
1377
|
+
const [a, b, rest] = trackSplit(t, ['a', 'b']);
|
|
1377
1378
|
} catch(e) {
|
|
1378
1379
|
@message = e.message;
|
|
1379
1380
|
}
|
|
@@ -1387,9 +1388,9 @@ describe('basic client', () => {
|
|
|
1387
1388
|
expect(pre.textContent).toBe('Invalid value: expected a non-tracked object');
|
|
1388
1389
|
});
|
|
1389
1390
|
|
|
1390
|
-
it('returns undefined for non-existent props in track with
|
|
1391
|
+
it('returns undefined for non-existent props in track with trackSplit', () => {
|
|
1391
1392
|
component App() {
|
|
1392
|
-
const [a, b, rest] =
|
|
1393
|
+
const [a, b, rest] = trackSplit({a: 1, c: 1}, ['a', 'b']);
|
|
1393
1394
|
|
|
1394
1395
|
<pre>{@a}</pre>
|
|
1395
1396
|
<pre>{String(@b)}</pre>
|
|
@@ -1433,4 +1434,97 @@ describe('basic client', () => {
|
|
|
1433
1434
|
render(App);
|
|
1434
1435
|
expect(container).toMatchSnapshot();
|
|
1435
1436
|
});
|
|
1437
|
+
|
|
1438
|
+
it('uses track get and set where both mutate value', () => {
|
|
1439
|
+
component App() {
|
|
1440
|
+
let count = track(0, v => v + 1, v => v * 2);
|
|
1441
|
+
|
|
1442
|
+
|
|
1443
|
+
<div class='count'>{@count}</div>
|
|
1444
|
+
<button onClick={() => { @count++ }}>{'Increment'}</button>
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1447
|
+
render(App);
|
|
1448
|
+
|
|
1449
|
+
const countDiv = container.querySelector('.count');
|
|
1450
|
+
const button = container.querySelector('button');
|
|
1451
|
+
|
|
1452
|
+
expect(countDiv.textContent).toBe('1');
|
|
1453
|
+
|
|
1454
|
+
button.click();
|
|
1455
|
+
flushSync();
|
|
1456
|
+
expect(countDiv.textContent).toBe('5');
|
|
1457
|
+
});
|
|
1458
|
+
|
|
1459
|
+
it('uses track get and set where set only mutates value', () => {
|
|
1460
|
+
component App() {
|
|
1461
|
+
let count = track(1, v => v, v => v * 2);
|
|
1462
|
+
|
|
1463
|
+
|
|
1464
|
+
<div class='count'>{@count}</div>
|
|
1465
|
+
<button onClick={() => { @count++ }}>{'Increment'}</button>
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1468
|
+
render(App);
|
|
1469
|
+
|
|
1470
|
+
const countDiv = container.querySelector('.count');
|
|
1471
|
+
const button = container.querySelector('button');
|
|
1472
|
+
|
|
1473
|
+
expect(countDiv.textContent).toBe('1');
|
|
1474
|
+
|
|
1475
|
+
button.click();
|
|
1476
|
+
flushSync();
|
|
1477
|
+
expect(countDiv.textContent).toBe('4');
|
|
1478
|
+
});
|
|
1479
|
+
|
|
1480
|
+
it('uses track get and set where get only mutates value', () => {
|
|
1481
|
+
component App() {
|
|
1482
|
+
let count = track(0, v => v + 1, v => v);
|
|
1483
|
+
|
|
1484
|
+
|
|
1485
|
+
<div class='count'>{@count}</div>
|
|
1486
|
+
<button onClick={() => { @count++ }}>{'Increment'}</button>
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
render(App);
|
|
1490
|
+
|
|
1491
|
+
const countDiv = container.querySelector('.count');
|
|
1492
|
+
const button = container.querySelector('button');
|
|
1493
|
+
|
|
1494
|
+
expect(countDiv.textContent).toBe('1');
|
|
1495
|
+
|
|
1496
|
+
button.click();
|
|
1497
|
+
flushSync();
|
|
1498
|
+
expect(countDiv.textContent).toBe('3');
|
|
1499
|
+
});
|
|
1500
|
+
|
|
1501
|
+
it('works as a reactive TrackedArray when constructed using # syntactic sugar', () => {
|
|
1502
|
+
component App() {
|
|
1503
|
+
const array = #[1, 2, 3];
|
|
1504
|
+
|
|
1505
|
+
<pre>{String(array[3])}</pre>
|
|
1506
|
+
<pre>{array[0]}</pre>
|
|
1507
|
+
<pre>{TRACKED_ARRAY in array}</pre>
|
|
1508
|
+
|
|
1509
|
+
<button onClick={() => { array.push(array.length + 1); array[0] = array[0] + 1 }}>{'Add'}</button>
|
|
1510
|
+
}
|
|
1511
|
+
|
|
1512
|
+
render(App);
|
|
1513
|
+
|
|
1514
|
+
const pre1 = container.querySelectorAll('pre')[0];
|
|
1515
|
+
const pre2 = container.querySelectorAll('pre')[1];
|
|
1516
|
+
const pre3 = container.querySelectorAll('pre')[2];
|
|
1517
|
+
const button = container.querySelector('button');
|
|
1518
|
+
|
|
1519
|
+
expect(pre1.textContent).toBe('undefined');
|
|
1520
|
+
expect(pre2.textContent).toBe('1');
|
|
1521
|
+
expect(pre3.textContent).toBe('true');
|
|
1522
|
+
|
|
1523
|
+
button.click();
|
|
1524
|
+
flushSync();
|
|
1525
|
+
|
|
1526
|
+
expect(pre1.textContent).toBe('4');
|
|
1527
|
+
expect(pre2.textContent).toBe('2');
|
|
1528
|
+
});
|
|
1436
1529
|
});
|
|
1530
|
+
|
package/types/index.d.ts
CHANGED
|
@@ -76,26 +76,21 @@ export type PropsWithExtras<T extends object> = Props & T & Record<string, unkno
|
|
|
76
76
|
export type PropsWithChildren<T extends object = {}> =
|
|
77
77
|
Expand<Omit<Props, 'children'> & { children: Component } & T>;
|
|
78
78
|
|
|
79
|
-
type UnwrapTracked<T> = [T] extends [Tracked<infer V>] ? T : Tracked<T>;
|
|
80
|
-
|
|
81
|
-
// force ts to evaluate and expand a type fully
|
|
82
79
|
type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;
|
|
83
80
|
|
|
84
81
|
type PickKeys<T, K extends readonly (keyof T)[]> =
|
|
85
|
-
{ [I in keyof K]:
|
|
82
|
+
{ [I in keyof K]: Tracked<T[K[I] & keyof T]> };
|
|
86
83
|
|
|
87
84
|
type RestKeys<T, K extends readonly (keyof T)[]> = Expand<Omit<T, K[number]>>;
|
|
88
85
|
|
|
89
86
|
type SplitResult<T extends Props, K extends readonly (keyof T)[]> =
|
|
90
|
-
[...PickKeys<T, K>,
|
|
91
|
-
|
|
92
|
-
type TrackOptions<T> = { split?: readonly (string | number | symbol)[], get?: (v: T) => T, set?: (v: T) => T };
|
|
87
|
+
[...PickKeys<T, K>, Tracked<RestKeys<T, K>>];
|
|
93
88
|
|
|
94
|
-
export declare function track<V>(value?: V | (() => V)): Tracked<V>;
|
|
89
|
+
export declare function track<V>(value?: V | (() => V), get?: (v: V) => V, set?: (v: V) => V): Tracked<V>;
|
|
95
90
|
|
|
96
|
-
export declare function
|
|
97
|
-
|
|
98
|
-
|
|
91
|
+
export declare function trackSplit<V extends Props, const K extends readonly (keyof V)[]>(
|
|
92
|
+
value: V,
|
|
93
|
+
splitKeys: K,
|
|
99
94
|
): SplitResult<V, K>;
|
|
100
95
|
|
|
101
96
|
export function on<Type extends keyof WindowEventMap>(
|