ripple 0.3.2 → 0.3.4
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/CHANGELOG.md +85 -0
- package/package.json +2 -2
- package/src/compiler/identifier-utils.js +0 -2
- package/src/compiler/phases/1-parse/index.js +101 -195
- package/src/compiler/phases/2-analyze/index.js +82 -174
- package/src/compiler/phases/2-analyze/prune.js +2 -2
- package/src/compiler/phases/3-transform/client/index.js +174 -264
- package/src/compiler/phases/3-transform/segments.js +0 -22
- package/src/compiler/phases/3-transform/server/index.js +185 -42
- package/src/compiler/types/index.d.ts +14 -33
- package/src/compiler/utils.js +32 -20
- package/src/runtime/index-client.js +0 -17
- package/src/runtime/internal/client/bindings.js +118 -7
- package/src/runtime/internal/client/render.js +5 -1
- package/src/runtime/internal/client/runtime.js +1 -1
- package/src/runtime/internal/client/types.d.ts +4 -0
- package/tests/client/array/array.copy-within.test.ripple +7 -7
- package/tests/client/array/array.derived.test.ripple +24 -24
- package/tests/client/array/array.iteration.test.ripple +7 -7
- package/tests/client/array/array.mutations.test.ripple +17 -17
- package/tests/client/array/array.to-methods.test.ripple +4 -4
- package/tests/client/async-suspend.test.ripple +3 -3
- package/tests/client/basic/basic.attributes.test.ripple +31 -31
- package/tests/client/basic/basic.collections.test.ripple +6 -6
- package/tests/client/basic/basic.components.test.ripple +8 -8
- package/tests/client/basic/basic.errors.test.ripple +31 -34
- package/tests/client/basic/basic.events.test.ripple +11 -11
- package/tests/client/basic/basic.get-set.test.ripple +18 -18
- package/tests/client/basic/basic.reactivity.test.ripple +36 -36
- package/tests/client/basic/basic.rendering.test.ripple +7 -7
- package/tests/client/basic/basic.utilities.test.ripple +4 -4
- package/tests/client/boundaries.test.ripple +7 -7
- package/tests/client/compiler/__snapshots__/compiler.typescript.test.ripple.snap +24 -0
- package/tests/client/compiler/compiler.assignments.test.ripple +12 -10
- package/tests/client/compiler/compiler.basic.test.ripple +58 -60
- package/tests/client/compiler/compiler.tracked-access.test.ripple +14 -8
- package/tests/client/compiler/compiler.typescript.test.ripple +31 -0
- package/tests/client/composite/composite.dynamic-components.test.ripple +6 -6
- package/tests/client/composite/composite.props.test.ripple +9 -9
- package/tests/client/composite/composite.reactivity.test.ripple +23 -23
- package/tests/client/composite/composite.render.test.ripple +52 -4
- package/tests/client/computed-properties.test.ripple +3 -3
- package/tests/client/context.test.ripple +3 -3
- package/tests/client/css/global-additional-cases.test.ripple +5 -2
- package/tests/client/css/style-identifier.test.ripple +40 -49
- package/tests/client/date.test.ripple +39 -39
- package/tests/client/dynamic-elements.test.ripple +37 -37
- package/tests/client/events.test.ripple +25 -25
- package/tests/client/for.test.ripple +8 -8
- package/tests/client/head.test.ripple +7 -7
- package/tests/client/html.test.ripple +2 -2
- package/tests/client/input-value.test.ripple +376 -177
- package/tests/client/lazy-destructuring.test.ripple +185 -0
- package/tests/client/map.test.ripple +20 -20
- package/tests/client/media-query.test.ripple +4 -4
- package/tests/client/object.test.ripple +5 -5
- package/tests/client/portal.test.ripple +4 -4
- package/tests/client/ref.test.ripple +3 -3
- package/tests/client/return.test.ripple +17 -17
- package/tests/client/set.test.ripple +10 -10
- package/tests/client/svg.test.ripple +6 -5
- package/tests/client/switch.test.ripple +10 -10
- package/tests/client/tracked-expression.test.ripple +3 -1
- package/tests/client/try.test.ripple +4 -4
- package/tests/client/url/url.derived.test.ripple +6 -7
- package/tests/client/url/url.parsing.test.ripple +9 -9
- package/tests/client/url/url.partial-removal.test.ripple +9 -9
- package/tests/client/url/url.reactivity.test.ripple +16 -16
- package/tests/client/url/url.serialization.test.ripple +3 -3
- package/tests/client/url-search-params/url-search-params.derived.test.ripple +7 -8
- package/tests/client/url-search-params/url-search-params.initialization.test.ripple +6 -4
- package/tests/client/url-search-params/url-search-params.iteration.test.ripple +12 -12
- package/tests/client/url-search-params/url-search-params.mutation.test.ripple +18 -18
- package/tests/client/url-search-params/url-search-params.retrieval.test.ripple +16 -16
- package/tests/client/url-search-params/url-search-params.serialization.test.ripple +4 -4
- package/tests/client/url-search-params/url-search-params.tracked-url.test.ripple +3 -3
- package/tests/hydration/build-components.js +4 -10
- package/tests/hydration/compiled/client/basic.js +4 -4
- package/tests/hydration/compiled/client/events.js +2 -0
- package/tests/hydration/compiled/client/for.js +2 -0
- package/tests/hydration/compiled/client/head.js +13 -11
- package/tests/hydration/compiled/client/hmr.js +4 -2
- package/tests/hydration/compiled/client/html.js +82 -95
- package/tests/hydration/compiled/client/if-children.js +8 -9
- package/tests/hydration/compiled/client/if.js +2 -0
- package/tests/hydration/compiled/client/mixed-control-flow.js +4 -2
- package/tests/hydration/compiled/client/portal.js +1 -1
- package/tests/hydration/compiled/client/reactivity.js +2 -0
- package/tests/hydration/compiled/client/return.js +2 -0
- package/tests/hydration/compiled/client/switch.js +2 -0
- package/tests/hydration/compiled/server/composite.js +2 -2
- package/tests/hydration/compiled/server/events.js +2 -0
- package/tests/hydration/compiled/server/for.js +2 -0
- package/tests/hydration/compiled/server/head.js +13 -11
- package/tests/hydration/compiled/server/hmr.js +2 -0
- package/tests/hydration/compiled/server/html.js +2 -0
- package/tests/hydration/compiled/server/if-children.js +2 -0
- package/tests/hydration/compiled/server/if.js +2 -0
- package/tests/hydration/compiled/server/mixed-control-flow.js +2 -0
- package/tests/hydration/compiled/server/portal.js +1 -1
- package/tests/hydration/compiled/server/reactivity.js +2 -0
- package/tests/hydration/compiled/server/return.js +2 -0
- package/tests/hydration/compiled/server/switch.js +2 -0
- package/tests/hydration/components/composite.ripple +1 -1
- package/tests/hydration/components/events.ripple +10 -8
- package/tests/hydration/components/for.ripple +22 -20
- package/tests/hydration/components/head.ripple +8 -6
- package/tests/hydration/components/hmr.ripple +3 -1
- package/tests/hydration/components/html.ripple +3 -1
- package/tests/hydration/components/if-children.ripple +9 -7
- package/tests/hydration/components/if.ripple +7 -5
- package/tests/hydration/components/mixed-control-flow.ripple +5 -3
- package/tests/hydration/components/portal.ripple +2 -2
- package/tests/hydration/components/reactivity.ripple +11 -9
- package/tests/hydration/components/return.ripple +13 -11
- package/tests/hydration/components/switch.ripple +6 -4
- package/tests/server/__snapshots__/compiler.test.ripple.snap +22 -0
- package/tests/server/await.test.ripple +2 -2
- package/tests/server/basic.attributes.test.ripple +21 -19
- package/tests/server/basic.components.test.ripple +5 -4
- package/tests/server/basic.test.ripple +21 -20
- package/tests/server/compiler.test.ripple +36 -5
- package/tests/server/composite.props.test.ripple +7 -6
- package/tests/server/context.test.ripple +3 -1
- package/tests/server/dynamic-elements.test.ripple +24 -24
- package/tests/server/head.test.ripple +7 -5
- package/tests/server/style-identifier.test.ripple +95 -16
- package/types/index.d.ts +4 -1
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { flushSync, track } from 'ripple';
|
|
2
|
+
|
|
3
|
+
describe('lazy destructuring', () => {
|
|
4
|
+
it('lazily accesses object properties with const', () => {
|
|
5
|
+
component Inner(&{ a, b }: { a: number; b: string }) {
|
|
6
|
+
<pre>{`${a}-${b}`}</pre>
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
component Test() {
|
|
10
|
+
let a = track(1);
|
|
11
|
+
let b = track('hello');
|
|
12
|
+
|
|
13
|
+
<Inner {@a} {@b} />
|
|
14
|
+
<button
|
|
15
|
+
onClick={() => {
|
|
16
|
+
@a = 2;
|
|
17
|
+
@b = 'world';
|
|
18
|
+
}}
|
|
19
|
+
>
|
|
20
|
+
{'update'}
|
|
21
|
+
</button>
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
render(Test);
|
|
25
|
+
expect(container.querySelector('pre')!.textContent).toBe('1-hello');
|
|
26
|
+
container.querySelector('button')!.click();
|
|
27
|
+
flushSync();
|
|
28
|
+
expect(container.querySelector('pre')!.textContent).toBe('2-world');
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('lazily accesses array elements with const', () => {
|
|
32
|
+
component Inner(&{ first, second }: { first: number; second: number }) {
|
|
33
|
+
<pre>{`${first}-${second}`}</pre>
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
component Test() {
|
|
37
|
+
let first = track(10);
|
|
38
|
+
let second = track(20);
|
|
39
|
+
|
|
40
|
+
<Inner {@first} {@second} />
|
|
41
|
+
<button
|
|
42
|
+
onClick={() => {
|
|
43
|
+
@first = 30;
|
|
44
|
+
@second = 40;
|
|
45
|
+
}}
|
|
46
|
+
>
|
|
47
|
+
{'update'}
|
|
48
|
+
</button>
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
render(Test);
|
|
52
|
+
expect(container.querySelector('pre')!.textContent).toBe('10-20');
|
|
53
|
+
container.querySelector('button')!.click();
|
|
54
|
+
flushSync();
|
|
55
|
+
expect(container.querySelector('pre')!.textContent).toBe('30-40');
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('supports default values in lazy object destructuring', () => {
|
|
59
|
+
component Test() {
|
|
60
|
+
const obj = { a: 5 };
|
|
61
|
+
const &{ a, b = 99 } = obj;
|
|
62
|
+
<pre>{`${a}-${b}`}</pre>
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
render(Test);
|
|
66
|
+
expect(container.querySelector('pre')!.textContent).toBe('5-99');
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('supports lazy destructuring in component params', () => {
|
|
70
|
+
component Inner(&{ name, age }: { name: string; age: number }) {
|
|
71
|
+
<pre>{`${name}-${age}`}</pre>
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
component Test() {
|
|
75
|
+
<Inner name="Alice" age={30} />
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
render(Test);
|
|
79
|
+
expect(container.querySelector('pre')!.textContent).toBe('Alice-30');
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('supports lazy destructuring in component params with reactivity', () => {
|
|
83
|
+
component Inner(&{ count }: { count: number }) {
|
|
84
|
+
<pre>{count}</pre>
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
component Test() {
|
|
88
|
+
let count = track(0);
|
|
89
|
+
|
|
90
|
+
<Inner {@count} />
|
|
91
|
+
<button
|
|
92
|
+
onClick={() => {
|
|
93
|
+
@count++;
|
|
94
|
+
}}
|
|
95
|
+
>
|
|
96
|
+
{'increment'}
|
|
97
|
+
</button>
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
render(Test);
|
|
101
|
+
expect(container.querySelector('pre')!.textContent).toBe('0');
|
|
102
|
+
container.querySelector('button')!.click();
|
|
103
|
+
flushSync();
|
|
104
|
+
expect(container.querySelector('pre')!.textContent).toBe('1');
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('supports lazy destructuring in function params', () => {
|
|
108
|
+
component Test() {
|
|
109
|
+
function getInfo(&{ x, y }: { x: number; y: number }) {
|
|
110
|
+
return x + y;
|
|
111
|
+
}
|
|
112
|
+
const result = getInfo({ x: 3, y: 7 });
|
|
113
|
+
<pre>{result}</pre>
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
render(Test);
|
|
117
|
+
expect(container.querySelector('pre')!.textContent).toBe('10');
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it('supports let lazy destructuring with assignment writeback', () => {
|
|
121
|
+
component Test() {
|
|
122
|
+
const obj = { a: 1, b: 2 };
|
|
123
|
+
let &{ a, b } = obj;
|
|
124
|
+
a = 10;
|
|
125
|
+
b = 20;
|
|
126
|
+
<pre>{`${obj.a}-${obj.b}`}</pre>
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
render(Test);
|
|
130
|
+
expect(container.querySelector('pre')!.textContent).toBe('10-20');
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('supports compound assignment operators on lazy bindings', () => {
|
|
134
|
+
component Test() {
|
|
135
|
+
const obj = { a: 5, b: 10 };
|
|
136
|
+
let &{ a, b } = obj;
|
|
137
|
+
a += 3;
|
|
138
|
+
b *= 2;
|
|
139
|
+
<pre>{`${obj.a}-${obj.b}`}</pre>
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
render(Test);
|
|
143
|
+
expect(container.querySelector('pre')!.textContent).toBe('8-20');
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it('supports update expressions on lazy bindings', () => {
|
|
147
|
+
component Test() {
|
|
148
|
+
const obj = { count: 0 };
|
|
149
|
+
let &{ count } = obj;
|
|
150
|
+
count++;
|
|
151
|
+
count++;
|
|
152
|
+
count--;
|
|
153
|
+
<pre>{obj.count}</pre>
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
render(Test);
|
|
157
|
+
expect(container.querySelector('pre')!.textContent).toBe('1');
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it('supports function params with lazy destructuring and default values', () => {
|
|
161
|
+
component Test() {
|
|
162
|
+
function calc(&{ x, y = 100 }: { x: number; y?: number }) {
|
|
163
|
+
return x + y;
|
|
164
|
+
}
|
|
165
|
+
const a = calc({ x: 5, y: 10 });
|
|
166
|
+
const b = calc({ x: 5 });
|
|
167
|
+
<pre>{`${a}-${b}`}</pre>
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
render(Test);
|
|
171
|
+
expect(container.querySelector('pre')!.textContent).toBe('15-105');
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('supports lazy destructuring with default value writeback', () => {
|
|
175
|
+
component Test() {
|
|
176
|
+
const obj: { a: number; b?: number } = { a: 1 };
|
|
177
|
+
let &{ a, b = 50 } = obj;
|
|
178
|
+
b = 99;
|
|
179
|
+
<pre>{`${a}-${obj.b}`}</pre>
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
render(Test);
|
|
183
|
+
expect(container.querySelector('pre')!.textContent).toBe('1-99');
|
|
184
|
+
});
|
|
185
|
+
});
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { flushSync,
|
|
1
|
+
import { RippleMap, flushSync, track } from 'ripple';
|
|
2
2
|
|
|
3
3
|
describe('RippleMap', () => {
|
|
4
4
|
it('handles set with update and delete operations with a reactive size var', () => {
|
|
5
5
|
component MapTest() {
|
|
6
|
-
let map =
|
|
7
|
-
let value =
|
|
8
|
-
let size =
|
|
6
|
+
let map = RippleMap([['a', 1], ['b', 2], ['c', 3]]);
|
|
7
|
+
let value = track(() => map.get('a'));
|
|
8
|
+
let size = track(() => map.size);
|
|
9
9
|
|
|
10
10
|
<button onClick={() => map.set('d', 4)}>{'set'}</button>
|
|
11
11
|
<button onClick={() => map.delete('b')}>{'delete'}</button>
|
|
@@ -42,7 +42,7 @@ describe('RippleMap', () => {
|
|
|
42
42
|
|
|
43
43
|
it('handles clear operation', () => {
|
|
44
44
|
component MapTest() {
|
|
45
|
-
let map =
|
|
45
|
+
let map = RippleMap([['a', 1], ['b', 2], ['c', 3]]);
|
|
46
46
|
|
|
47
47
|
<button onClick={() => map.clear()}>{'clear'}</button>
|
|
48
48
|
<pre>{map.size}</pre>
|
|
@@ -60,8 +60,8 @@ describe('RippleMap', () => {
|
|
|
60
60
|
|
|
61
61
|
it('handles has operation and tracks reactive $has', () => {
|
|
62
62
|
component MapTest() {
|
|
63
|
-
let map =
|
|
64
|
-
let has =
|
|
63
|
+
let map = RippleMap([['a', 1], ['b', 2], ['c', 3]]);
|
|
64
|
+
let has = track(() => map.has('b'));
|
|
65
65
|
|
|
66
66
|
<button onClick={() => map.delete('b')}>{'delete'}</button>
|
|
67
67
|
<pre>{@has}</pre>
|
|
@@ -80,10 +80,10 @@ describe('RippleMap', () => {
|
|
|
80
80
|
|
|
81
81
|
it('handles reactivity of keys, values, and entries', () => {
|
|
82
82
|
component MapTest() {
|
|
83
|
-
let map =
|
|
84
|
-
let keys =
|
|
85
|
-
let values =
|
|
86
|
-
let entries =
|
|
83
|
+
let map = RippleMap([['x', 10], ['y', 20]]);
|
|
84
|
+
let keys = track(() => Array.from(map.keys()));
|
|
85
|
+
let values = track(() => Array.from(map.values()));
|
|
86
|
+
let entries = track(() => Array.from(map.entries()));
|
|
87
87
|
|
|
88
88
|
<button onClick={() => map.delete('x')}>{'delete'}</button>
|
|
89
89
|
|
|
@@ -110,7 +110,7 @@ describe('RippleMap', () => {
|
|
|
110
110
|
|
|
111
111
|
it('toJSON returns correct object', () => {
|
|
112
112
|
component MapTest() {
|
|
113
|
-
let map =
|
|
113
|
+
let map = RippleMap([['foo', 1], ['bar', 2]]);
|
|
114
114
|
|
|
115
115
|
<pre>{JSON.stringify(map)}</pre>
|
|
116
116
|
}
|
|
@@ -120,9 +120,9 @@ describe('RippleMap', () => {
|
|
|
120
120
|
expect(container.querySelectorAll('pre')[0].textContent).toBe('[["foo",1],["bar",2]]');
|
|
121
121
|
});
|
|
122
122
|
|
|
123
|
-
it('creates empty RippleMap using
|
|
123
|
+
it('creates empty RippleMap using RippleMap() shorthand syntax', () => {
|
|
124
124
|
component MapTest() {
|
|
125
|
-
let map =
|
|
125
|
+
let map = RippleMap();
|
|
126
126
|
|
|
127
127
|
<button onClick={() => map.set('a', 1)}>{'add'}</button>
|
|
128
128
|
<pre>{map.size}</pre>
|
|
@@ -139,10 +139,10 @@ describe('RippleMap', () => {
|
|
|
139
139
|
expect(container.querySelector('pre').textContent).toBe('1');
|
|
140
140
|
});
|
|
141
141
|
|
|
142
|
-
it('creates RippleMap with initial entries using
|
|
142
|
+
it('creates RippleMap with initial entries using RippleMap() shorthand syntax', () => {
|
|
143
143
|
component MapTest() {
|
|
144
|
-
let map =
|
|
145
|
-
let value =
|
|
144
|
+
let map = RippleMap([['a', 1], ['b', 2], ['c', 3]]);
|
|
145
|
+
let value = track(() => map.get('b'));
|
|
146
146
|
|
|
147
147
|
<button onClick={() => map.set('b', 10)}>{'update'}</button>
|
|
148
148
|
<pre>{map.size}</pre>
|
|
@@ -161,10 +161,10 @@ describe('RippleMap', () => {
|
|
|
161
161
|
expect(container.querySelectorAll('pre')[1].textContent).toBe('10');
|
|
162
162
|
});
|
|
163
163
|
|
|
164
|
-
it('handles all operations with
|
|
164
|
+
it('handles all operations with RippleMap() shorthand syntax', () => {
|
|
165
165
|
component MapTest() {
|
|
166
|
-
let map =
|
|
167
|
-
let keys =
|
|
166
|
+
let map = RippleMap([['x', 100], ['y', 200]]);
|
|
167
|
+
let keys = track(() => Array.from(map.keys()));
|
|
168
168
|
|
|
169
169
|
<button onClick={() => map.set('z', 300)}>{'add'}</button>
|
|
170
170
|
<button onClick={() => map.delete('x')}>{'delete'}</button>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { flushSync } from 'ripple';
|
|
1
|
+
import { MediaQuery, flushSync, track } from 'ripple';
|
|
2
2
|
|
|
3
3
|
type Callback = (event: MediaQueryListEvent) => void;
|
|
4
4
|
|
|
@@ -51,7 +51,7 @@ describe('MediaQuery', () => {
|
|
|
51
51
|
const media = '(min-width: 600px)';
|
|
52
52
|
|
|
53
53
|
component App() {
|
|
54
|
-
const medium =
|
|
54
|
+
const medium = MediaQuery(media);
|
|
55
55
|
|
|
56
56
|
<div>
|
|
57
57
|
<p>{@medium}</p>
|
|
@@ -86,7 +86,7 @@ describe('MediaQuery', () => {
|
|
|
86
86
|
const media = '(min-width: 600px)';
|
|
87
87
|
|
|
88
88
|
component App() {
|
|
89
|
-
let show =
|
|
89
|
+
let show = track(true);
|
|
90
90
|
|
|
91
91
|
if (@show) {
|
|
92
92
|
<Child />
|
|
@@ -96,7 +96,7 @@ describe('MediaQuery', () => {
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
component Child() {
|
|
99
|
-
const medium =
|
|
99
|
+
const medium = MediaQuery(media);
|
|
100
100
|
|
|
101
101
|
<div>
|
|
102
102
|
<p>{@medium}</p>
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RippleObject, flushSync } from 'ripple';
|
|
2
2
|
import { TRACKED_OBJECT } from '../../src/runtime/internal/client/constants.js';
|
|
3
3
|
|
|
4
4
|
describe('RippleObject', () => {
|
|
5
5
|
it('makes new properties reactive', () => {
|
|
6
6
|
component ObjectTest() {
|
|
7
|
-
const obj =
|
|
7
|
+
const obj = new RippleObject({ a: -1 });
|
|
8
8
|
|
|
9
9
|
obj.a = 0;
|
|
10
10
|
|
|
@@ -33,7 +33,7 @@ describe('RippleObject', () => {
|
|
|
33
33
|
|
|
34
34
|
it('makes existing object properties reactive', () => {
|
|
35
35
|
component ObjectTest() {
|
|
36
|
-
const obj =
|
|
36
|
+
const obj = new RippleObject({ a: 0 });
|
|
37
37
|
|
|
38
38
|
<pre>{obj.a}</pre>
|
|
39
39
|
<button
|
|
@@ -60,7 +60,7 @@ describe('RippleObject', () => {
|
|
|
60
60
|
|
|
61
61
|
it('checks if property exists via the has trap', () => {
|
|
62
62
|
component ObjectTest() {
|
|
63
|
-
const obj =
|
|
63
|
+
const obj = new RippleObject({ a: -1, b: 1 });
|
|
64
64
|
|
|
65
65
|
obj.a = 0;
|
|
66
66
|
|
|
@@ -167,7 +167,7 @@ describe('RippleObject', () => {
|
|
|
167
167
|
|
|
168
168
|
it('uses the hash syntax for creating RippleObject', () => {
|
|
169
169
|
component ObjectTest() {
|
|
170
|
-
const obj =
|
|
170
|
+
const obj = new RippleObject({ a: 0, b: 1, c: { d: { e: 8 } } });
|
|
171
171
|
|
|
172
172
|
<pre>{obj.a}</pre>
|
|
173
173
|
<pre>{TRACKED_OBJECT in obj}</pre>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Portal, flushSync } from 'ripple';
|
|
1
|
+
import { Portal, flushSync, track } from 'ripple';
|
|
2
2
|
|
|
3
3
|
describe('Portal', () => {
|
|
4
4
|
afterEach(() => {
|
|
@@ -46,7 +46,7 @@ describe('Portal', () => {
|
|
|
46
46
|
|
|
47
47
|
it('cleans up portal content when destroyed via conditional rendering', () => {
|
|
48
48
|
component TestPortal() {
|
|
49
|
-
let open =
|
|
49
|
+
let open = track(true);
|
|
50
50
|
|
|
51
51
|
if (@open) {
|
|
52
52
|
<Portal target={document.body}>
|
|
@@ -72,7 +72,7 @@ describe('Portal', () => {
|
|
|
72
72
|
|
|
73
73
|
it('opens and closes portal via conditional rendering', () => {
|
|
74
74
|
component TestPortal() {
|
|
75
|
-
let open =
|
|
75
|
+
let open = track(false);
|
|
76
76
|
|
|
77
77
|
if (@open) {
|
|
78
78
|
<Portal target={document.body}>
|
|
@@ -138,7 +138,7 @@ describe('Portal', () => {
|
|
|
138
138
|
|
|
139
139
|
it('handles portal with reactive content', () => {
|
|
140
140
|
component TestReactivePortal() {
|
|
141
|
-
let count =
|
|
141
|
+
let count = track(0);
|
|
142
142
|
|
|
143
143
|
<Portal target={document.body}>
|
|
144
144
|
<div class="test-portal">
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { PropsWithExtras } from 'ripple';
|
|
2
2
|
import { describe, it, expect } from 'vitest';
|
|
3
|
-
import {
|
|
3
|
+
import { RippleArray, createRefKey, flushSync, track } from 'ripple';
|
|
4
4
|
|
|
5
5
|
describe('refs', () => {
|
|
6
6
|
it('capture a <div>', () => {
|
|
@@ -50,7 +50,7 @@ describe('refs', () => {
|
|
|
50
50
|
let logs: string[] = [];
|
|
51
51
|
|
|
52
52
|
component App() {
|
|
53
|
-
let value =
|
|
53
|
+
let value = track('test');
|
|
54
54
|
|
|
55
55
|
function inputRef(node: HTMLInputElement) {
|
|
56
56
|
logs.push('ref called');
|
|
@@ -81,7 +81,7 @@ describe('refs', () => {
|
|
|
81
81
|
let logs: string[] = [];
|
|
82
82
|
|
|
83
83
|
component App() {
|
|
84
|
-
let value =
|
|
84
|
+
let value = track('test');
|
|
85
85
|
|
|
86
86
|
function inputRef(node: HTMLInputElement) {
|
|
87
87
|
logs.push('ref called');
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { flushSync } from 'ripple';
|
|
2
|
+
import { flushSync, track } from 'ripple';
|
|
3
3
|
import { compile } from 'ripple/compiler';
|
|
4
4
|
|
|
5
5
|
describe('returns in prohibited scopes', () => {
|
|
@@ -64,7 +64,7 @@ describe('early return in client components', () => {
|
|
|
64
64
|
|
|
65
65
|
it('reactive: condition changes from false to true hides rest', () => {
|
|
66
66
|
component App() {
|
|
67
|
-
let condition =
|
|
67
|
+
let condition = track(false);
|
|
68
68
|
|
|
69
69
|
<button
|
|
70
70
|
onClick={() => {
|
|
@@ -93,7 +93,7 @@ describe('early return in client components', () => {
|
|
|
93
93
|
|
|
94
94
|
it('reactive: condition changes from true to false shows rest', () => {
|
|
95
95
|
component App() {
|
|
96
|
-
let condition =
|
|
96
|
+
let condition = track(true);
|
|
97
97
|
|
|
98
98
|
<button
|
|
99
99
|
onClick={() => {
|
|
@@ -905,8 +905,8 @@ describe('early return in client components', () => {
|
|
|
905
905
|
|
|
906
906
|
it('reactive: nested return condition changes', () => {
|
|
907
907
|
component App() {
|
|
908
|
-
let a =
|
|
909
|
-
let b =
|
|
908
|
+
let a = track(true);
|
|
909
|
+
let b = track(true);
|
|
910
910
|
|
|
911
911
|
<button
|
|
912
912
|
onClick={() => {
|
|
@@ -940,7 +940,7 @@ describe('early return in client components', () => {
|
|
|
940
940
|
|
|
941
941
|
it('reactive: return in nested element scope', () => {
|
|
942
942
|
component App() {
|
|
943
|
-
let show =
|
|
943
|
+
let show = track(true);
|
|
944
944
|
|
|
945
945
|
<button
|
|
946
946
|
onClick={() => {
|
|
@@ -1214,7 +1214,7 @@ describe('early return in client components', () => {
|
|
|
1214
1214
|
|
|
1215
1215
|
it('reactive: nested return - outer condition changes to false shows rest', () => {
|
|
1216
1216
|
component App() {
|
|
1217
|
-
let a =
|
|
1217
|
+
let a = track(true);
|
|
1218
1218
|
let b = true;
|
|
1219
1219
|
|
|
1220
1220
|
<button
|
|
@@ -1251,7 +1251,7 @@ describe('early return in client components', () => {
|
|
|
1251
1251
|
component App() {
|
|
1252
1252
|
let a = true;
|
|
1253
1253
|
let b = true;
|
|
1254
|
-
let c =
|
|
1254
|
+
let c = track(true);
|
|
1255
1255
|
|
|
1256
1256
|
<button
|
|
1257
1257
|
onClick={() => {
|
|
@@ -2208,10 +2208,10 @@ describe('early return in client components', () => {
|
|
|
2208
2208
|
|
|
2209
2209
|
it('nested reactive: toggling conditions updates DOM', () => {
|
|
2210
2210
|
component App() {
|
|
2211
|
-
let a =
|
|
2212
|
-
let b =
|
|
2213
|
-
let c =
|
|
2214
|
-
let d =
|
|
2211
|
+
let a = track(false);
|
|
2212
|
+
let b = track(false);
|
|
2213
|
+
let c = track(false);
|
|
2214
|
+
let d = track(false);
|
|
2215
2215
|
|
|
2216
2216
|
<button
|
|
2217
2217
|
class="toggle-c"
|
|
@@ -2279,7 +2279,7 @@ describe('early return in client components', () => {
|
|
|
2279
2279
|
() => {
|
|
2280
2280
|
component App() {
|
|
2281
2281
|
let a = true;
|
|
2282
|
-
let b =
|
|
2282
|
+
let b = track(true);
|
|
2283
2283
|
|
|
2284
2284
|
<button
|
|
2285
2285
|
class="toggle"
|
|
@@ -2326,7 +2326,7 @@ describe('early return in client components', () => {
|
|
|
2326
2326
|
|
|
2327
2327
|
it('reactive sibling returns cycle through first, second, and fallback branches', () => {
|
|
2328
2328
|
component App() {
|
|
2329
|
-
let mode =
|
|
2329
|
+
let mode = track('first');
|
|
2330
2330
|
|
|
2331
2331
|
<button
|
|
2332
2332
|
class="toggle"
|
|
@@ -2382,8 +2382,8 @@ describe('early return in client components', () => {
|
|
|
2382
2382
|
|
|
2383
2383
|
it('reactive nested returns with tracked outer and inner flags transition correctly', () => {
|
|
2384
2384
|
component App() {
|
|
2385
|
-
let a =
|
|
2386
|
-
let b =
|
|
2385
|
+
let a = track(true);
|
|
2386
|
+
let b = track(true);
|
|
2387
2387
|
|
|
2388
2388
|
<button
|
|
2389
2389
|
class="toggle-a"
|
|
@@ -2446,7 +2446,7 @@ describe('early return in client components', () => {
|
|
|
2446
2446
|
|
|
2447
2447
|
it('reactive else-if return chain transitions between return and non-return states', () => {
|
|
2448
2448
|
component App() {
|
|
2449
|
-
let status =
|
|
2449
|
+
let status = track(0);
|
|
2450
2450
|
|
|
2451
2451
|
<button
|
|
2452
2452
|
class="toggle"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { flushSync,
|
|
1
|
+
import { RippleSet, flushSync, track } from 'ripple';
|
|
2
2
|
|
|
3
3
|
describe('RippleSet', () => {
|
|
4
4
|
it('handles add and delete operations', () => {
|
|
@@ -60,7 +60,7 @@ describe('RippleSet', () => {
|
|
|
60
60
|
it('handles has operation', () => {
|
|
61
61
|
component SetTest() {
|
|
62
62
|
let items = new RippleSet([1, 2, 3]);
|
|
63
|
-
let hasValue =
|
|
63
|
+
let hasValue = track(() => items.has(2));
|
|
64
64
|
|
|
65
65
|
<button onClick={() => items.delete(2)}>{'delete'}</button>
|
|
66
66
|
<pre>{@hasValue}</pre>
|
|
@@ -78,9 +78,9 @@ describe('RippleSet', () => {
|
|
|
78
78
|
expect(container.querySelectorAll('pre')[0].textContent).toBe('false');
|
|
79
79
|
});
|
|
80
80
|
|
|
81
|
-
it('creates empty RippleSet using
|
|
81
|
+
it('creates empty RippleSet using RippleSet() shorthand syntax', () => {
|
|
82
82
|
component SetTest() {
|
|
83
|
-
let items =
|
|
83
|
+
let items = RippleSet();
|
|
84
84
|
|
|
85
85
|
<button onClick={() => items.add(1)}>{'add'}</button>
|
|
86
86
|
<pre>{items.size}</pre>
|
|
@@ -97,10 +97,10 @@ describe('RippleSet', () => {
|
|
|
97
97
|
expect(container.querySelector('pre').textContent).toBe('1');
|
|
98
98
|
});
|
|
99
99
|
|
|
100
|
-
it('creates RippleSet with initial values using
|
|
100
|
+
it('creates RippleSet with initial values using RippleSet() shorthand syntax', () => {
|
|
101
101
|
component SetTest() {
|
|
102
|
-
let items =
|
|
103
|
-
let hasValue =
|
|
102
|
+
let items = RippleSet([1, 2, 3, 4]);
|
|
103
|
+
let hasValue = track(() => items.has(3));
|
|
104
104
|
|
|
105
105
|
<button onClick={() => items.delete(3)}>{'delete'}</button>
|
|
106
106
|
<pre>{items.size}</pre>
|
|
@@ -120,10 +120,10 @@ describe('RippleSet', () => {
|
|
|
120
120
|
expect(container.querySelectorAll('pre')[1].textContent).toBe('false');
|
|
121
121
|
});
|
|
122
122
|
|
|
123
|
-
it('handles all operations with
|
|
123
|
+
it('handles all operations with RippleSet() shorthand syntax', () => {
|
|
124
124
|
component SetTest() {
|
|
125
|
-
let items =
|
|
126
|
-
let values =
|
|
125
|
+
let items = RippleSet([10, 20, 30]);
|
|
126
|
+
let values = track(() => Array.from(items.values()));
|
|
127
127
|
|
|
128
128
|
<button onClick={() => items.add(40)}>{'add'}</button>
|
|
129
129
|
<button onClick={() => items.delete(20)}>{'delete'}</button>
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { track } from 'ripple';
|
|
1
2
|
import type { Component, PropsWithChildren, PropsWithExtras } from 'ripple';
|
|
2
3
|
|
|
3
4
|
describe('SVG namespace handling', () => {
|
|
@@ -289,7 +290,7 @@ describe('SVG namespace handling', () => {
|
|
|
289
290
|
}
|
|
290
291
|
|
|
291
292
|
component App() {
|
|
292
|
-
let dynTag =
|
|
293
|
+
let dynTag = track('polygon');
|
|
293
294
|
<SVG>
|
|
294
295
|
<@dynTag points="0,0 30,0 15,10" />
|
|
295
296
|
</SVG>
|
|
@@ -316,7 +317,7 @@ describe('SVG namespace handling', () => {
|
|
|
316
317
|
}
|
|
317
318
|
|
|
318
319
|
component App() {
|
|
319
|
-
let Component =
|
|
320
|
+
let Component = track(() => Polygon);
|
|
320
321
|
<SVG>
|
|
321
322
|
<@Component points="0,0 30,0 15,10" />
|
|
322
323
|
</SVG>
|
|
@@ -333,19 +334,19 @@ describe('SVG namespace handling', () => {
|
|
|
333
334
|
|
|
334
335
|
it('should render SVG as a dynamic top element with any dynamic children elements', () => {
|
|
335
336
|
component SVG({ children }: PropsWithChildren<{}>) {
|
|
336
|
-
const tag =
|
|
337
|
+
const tag = track('svg');
|
|
337
338
|
<@tag width={100} height={50} fill="red" viewBox="0 0 30 10" preserveAspectRatio="none">
|
|
338
339
|
<children />
|
|
339
340
|
</@tag>
|
|
340
341
|
}
|
|
341
342
|
|
|
342
343
|
component Polygon({ points }: PropsWithExtras<{ points: string }>) {
|
|
343
|
-
let dynTag =
|
|
344
|
+
let dynTag = track('polygon');
|
|
344
345
|
<@dynTag {points} />
|
|
345
346
|
}
|
|
346
347
|
|
|
347
348
|
component App() {
|
|
348
|
-
let Component =
|
|
349
|
+
let Component = track(() => Polygon);
|
|
349
350
|
<SVG>
|
|
350
351
|
<@Component points="0,0 30,0 15,10" />
|
|
351
352
|
</SVG>
|