ripple 0.3.7 → 0.3.8
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 +7 -0
- package/package.json +2 -2
- package/src/compiler/phases/1-parse/index.js +37 -194
- package/src/compiler/phases/2-analyze/index.js +63 -18
- package/src/compiler/phases/3-transform/client/index.js +19 -3
- package/src/compiler/phases/3-transform/server/index.js +16 -24
- package/src/compiler/types/parse.d.ts +0 -8
- package/src/runtime/internal/client/composite.js +2 -2
- package/tests/client/array/array.copy-within.test.ripple +12 -12
- package/tests/client/array/array.derived.test.ripple +46 -46
- package/tests/client/array/array.iteration.test.ripple +10 -10
- package/tests/client/array/array.mutations.test.ripple +20 -20
- package/tests/client/array/array.to-methods.test.ripple +6 -6
- package/tests/client/async-suspend.test.ripple +5 -5
- package/tests/client/basic/basic.attributes.test.ripple +81 -81
- package/tests/client/basic/basic.collections.test.ripple +9 -9
- package/tests/client/basic/basic.components.test.ripple +28 -28
- package/tests/client/basic/basic.errors.test.ripple +18 -18
- package/tests/client/basic/basic.events.test.ripple +37 -37
- package/tests/client/basic/basic.get-set.test.ripple +6 -6
- package/tests/client/basic/basic.reactivity.test.ripple +68 -68
- package/tests/client/basic/basic.rendering.test.ripple +19 -19
- package/tests/client/basic/basic.utilities.test.ripple +3 -3
- package/tests/client/boundaries.test.ripple +12 -12
- package/tests/client/compiler/__snapshots__/compiler.assignments.test.ripple.snap +5 -5
- package/tests/client/compiler/compiler.assignments.test.ripple +19 -19
- package/tests/client/compiler/compiler.basic.test.ripple +16 -16
- package/tests/client/compiler/compiler.tracked-access.test.ripple +2 -2
- package/tests/client/composite/composite.dynamic-components.test.ripple +9 -9
- package/tests/client/composite/composite.props.test.ripple +11 -11
- package/tests/client/composite/composite.reactivity.test.ripple +43 -43
- package/tests/client/composite/composite.render.test.ripple +3 -3
- package/tests/client/computed-properties.test.ripple +4 -4
- package/tests/client/date.test.ripple +42 -42
- package/tests/client/dynamic-elements.test.ripple +42 -42
- package/tests/client/events.test.ripple +70 -70
- package/tests/client/for.test.ripple +25 -25
- package/tests/client/head.test.ripple +19 -19
- package/tests/client/html.test.ripple +3 -3
- package/tests/client/input-value.test.ripple +84 -84
- package/tests/client/lazy-destructuring.test.ripple +71 -16
- package/tests/client/map.test.ripple +16 -16
- package/tests/client/media-query.test.ripple +7 -7
- package/tests/client/portal.test.ripple +11 -11
- package/tests/client/ref.test.ripple +4 -4
- package/tests/client/return.test.ripple +52 -52
- package/tests/client/set.test.ripple +6 -6
- package/tests/client/svg.test.ripple +5 -5
- package/tests/client/switch.test.ripple +44 -44
- package/tests/client/try.test.ripple +5 -5
- package/tests/client/url/url.derived.test.ripple +6 -6
- package/tests/client/url-search-params/url-search-params.derived.test.ripple +8 -8
- package/tests/client/url-search-params/url-search-params.iteration.test.ripple +10 -10
- package/tests/client/url-search-params/url-search-params.mutation.test.ripple +10 -10
- package/tests/client/url-search-params/url-search-params.retrieval.test.ripple +18 -18
- package/tests/client/url-search-params/url-search-params.serialization.test.ripple +2 -2
- package/tests/hydration/compiled/client/events.js +25 -25
- package/tests/hydration/compiled/client/for.js +70 -66
- package/tests/hydration/compiled/client/head.js +25 -25
- package/tests/hydration/compiled/client/hmr.js +2 -2
- package/tests/hydration/compiled/client/html.js +3 -3
- package/tests/hydration/compiled/client/if-children.js +24 -24
- package/tests/hydration/compiled/client/if.js +18 -18
- package/tests/hydration/compiled/client/mixed-control-flow.js +9 -9
- package/tests/hydration/compiled/client/portal.js +3 -3
- package/tests/hydration/compiled/client/reactivity.js +16 -16
- package/tests/hydration/compiled/client/return.js +40 -40
- package/tests/hydration/compiled/client/switch.js +12 -12
- package/tests/hydration/compiled/server/events.js +19 -19
- package/tests/hydration/compiled/server/for.js +41 -41
- package/tests/hydration/compiled/server/head.js +26 -26
- package/tests/hydration/compiled/server/hmr.js +2 -2
- package/tests/hydration/compiled/server/html.js +2 -2
- package/tests/hydration/compiled/server/if-children.js +16 -16
- package/tests/hydration/compiled/server/if.js +11 -11
- package/tests/hydration/compiled/server/mixed-control-flow.js +6 -6
- package/tests/hydration/compiled/server/portal.js +2 -2
- package/tests/hydration/compiled/server/reactivity.js +16 -16
- package/tests/hydration/compiled/server/return.js +25 -25
- package/tests/hydration/compiled/server/switch.js +8 -8
- package/tests/hydration/components/events.ripple +25 -25
- package/tests/hydration/components/for.ripple +66 -66
- package/tests/hydration/components/head.ripple +16 -16
- package/tests/hydration/components/hmr.ripple +2 -2
- package/tests/hydration/components/html.ripple +3 -3
- package/tests/hydration/components/if-children.ripple +24 -24
- package/tests/hydration/components/if.ripple +18 -18
- package/tests/hydration/components/mixed-control-flow.ripple +9 -9
- package/tests/hydration/components/portal.ripple +3 -3
- package/tests/hydration/components/reactivity.ripple +16 -16
- package/tests/hydration/components/return.ripple +40 -40
- package/tests/hydration/components/switch.ripple +20 -20
- package/tests/server/await.test.ripple +3 -3
- package/tests/server/basic.attributes.test.ripple +34 -34
- package/tests/server/basic.components.test.ripple +10 -10
- package/tests/server/basic.test.ripple +38 -40
- package/tests/server/composite.props.test.ripple +9 -9
- package/tests/server/dynamic-elements.test.ripple +13 -12
- package/tests/server/head.test.ripple +11 -11
- package/tests/server/lazy-destructuring.test.ripple +27 -4
|
@@ -3,36 +3,36 @@ import { track } from 'ripple';
|
|
|
3
3
|
// Event handling components for hydration testing
|
|
4
4
|
|
|
5
5
|
export component ClickCounter() {
|
|
6
|
-
let count = track(0);
|
|
6
|
+
let &[count] = track(0);
|
|
7
7
|
<div>
|
|
8
8
|
<button
|
|
9
9
|
class="increment"
|
|
10
10
|
onClick={() => {
|
|
11
|
-
|
|
11
|
+
count++;
|
|
12
12
|
}}
|
|
13
13
|
>
|
|
14
14
|
{'Increment'}
|
|
15
15
|
</button>
|
|
16
|
-
<span class="count">{
|
|
16
|
+
<span class="count">{count}</span>
|
|
17
17
|
</div>
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
export component IncrementDecrement() {
|
|
21
|
-
let count = track(0);
|
|
21
|
+
let &[count] = track(0);
|
|
22
22
|
<div>
|
|
23
23
|
<button
|
|
24
24
|
class="decrement"
|
|
25
25
|
onClick={() => {
|
|
26
|
-
|
|
26
|
+
count--;
|
|
27
27
|
}}
|
|
28
28
|
>
|
|
29
29
|
{'-'}
|
|
30
30
|
</button>
|
|
31
|
-
<span class="count">{
|
|
31
|
+
<span class="count">{count}</span>
|
|
32
32
|
<button
|
|
33
33
|
class="increment"
|
|
34
34
|
onClick={() => {
|
|
35
|
-
|
|
35
|
+
count++;
|
|
36
36
|
}}
|
|
37
37
|
>
|
|
38
38
|
{'+'}
|
|
@@ -41,51 +41,51 @@ export component IncrementDecrement() {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
export component MultipleEvents() {
|
|
44
|
-
let clicks = track(0);
|
|
45
|
-
let hovers = track(0);
|
|
44
|
+
let &[clicks] = track(0);
|
|
45
|
+
let &[hovers] = track(0);
|
|
46
46
|
<div>
|
|
47
47
|
<button
|
|
48
48
|
class="target"
|
|
49
49
|
onClick={() => {
|
|
50
|
-
|
|
50
|
+
clicks++;
|
|
51
51
|
}}
|
|
52
52
|
onMouseEnter={() => {
|
|
53
|
-
|
|
53
|
+
hovers++;
|
|
54
54
|
}}
|
|
55
55
|
>
|
|
56
56
|
{'Target'}
|
|
57
57
|
</button>
|
|
58
|
-
<span class="clicks">{
|
|
59
|
-
<span class="hovers">{
|
|
58
|
+
<span class="clicks">{clicks}</span>
|
|
59
|
+
<span class="hovers">{hovers}</span>
|
|
60
60
|
</div>
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
export component MultiStateUpdate() {
|
|
64
|
-
let count = track(0);
|
|
65
|
-
let lastAction = track('none');
|
|
64
|
+
let &[count] = track(0);
|
|
65
|
+
let &[lastAction] = track('none');
|
|
66
66
|
|
|
67
67
|
const handleClick = () => {
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
count++;
|
|
69
|
+
lastAction = 'increment';
|
|
70
70
|
};
|
|
71
71
|
|
|
72
72
|
<div>
|
|
73
73
|
<button class="btn" onClick={handleClick}>{'Click'}</button>
|
|
74
|
-
<span class="count">{
|
|
75
|
-
<span class="action">{
|
|
74
|
+
<span class="count">{count}</span>
|
|
75
|
+
<span class="action">{lastAction}</span>
|
|
76
76
|
</div>
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
export component ToggleButton() {
|
|
80
|
-
let isOn = track(false);
|
|
80
|
+
let &[isOn] = track(false);
|
|
81
81
|
<div>
|
|
82
82
|
<button
|
|
83
83
|
class="toggle"
|
|
84
84
|
onClick={() => {
|
|
85
|
-
|
|
85
|
+
isOn = !isOn;
|
|
86
86
|
}}
|
|
87
87
|
>
|
|
88
|
-
{
|
|
88
|
+
{isOn ? 'ON' : 'OFF'}
|
|
89
89
|
</button>
|
|
90
90
|
</div>
|
|
91
91
|
}
|
|
@@ -95,14 +95,14 @@ export component ChildButton(props: { onClick: () => void; label: string }) {
|
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
export component ParentWithChildButton() {
|
|
98
|
-
let count = track(0);
|
|
98
|
+
let &[count] = track(0);
|
|
99
99
|
<div>
|
|
100
100
|
<ChildButton
|
|
101
101
|
onClick={() => {
|
|
102
|
-
|
|
102
|
+
count++;
|
|
103
103
|
}}
|
|
104
104
|
label="Click me"
|
|
105
105
|
/>
|
|
106
|
-
<span class="count">{
|
|
106
|
+
<span class="count">{count}</span>
|
|
107
107
|
</div>
|
|
108
108
|
}
|
|
@@ -34,51 +34,51 @@ export component KeyedForLoop() {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
export component ReactiveForLoopAdd() {
|
|
37
|
-
let items = track(['A', 'B']);
|
|
37
|
+
let &[items] = track(['A', 'B']);
|
|
38
38
|
<button
|
|
39
39
|
class="add"
|
|
40
40
|
onClick={() => {
|
|
41
|
-
|
|
41
|
+
items = [...items, 'C'];
|
|
42
42
|
}}
|
|
43
43
|
>
|
|
44
44
|
{'Add'}
|
|
45
45
|
</button>
|
|
46
46
|
<ul>
|
|
47
|
-
for (const item of
|
|
47
|
+
for (const item of items) {
|
|
48
48
|
<li>{item}</li>
|
|
49
49
|
}
|
|
50
50
|
</ul>
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
export component ReactiveForLoopRemove() {
|
|
54
|
-
let items = track(['A', 'B', 'C']);
|
|
54
|
+
let &[items] = track(['A', 'B', 'C']);
|
|
55
55
|
<button
|
|
56
56
|
class="remove"
|
|
57
57
|
onClick={() => {
|
|
58
|
-
|
|
58
|
+
items = items.slice(0, -1);
|
|
59
59
|
}}
|
|
60
60
|
>
|
|
61
61
|
{'Remove'}
|
|
62
62
|
</button>
|
|
63
63
|
<ul>
|
|
64
|
-
for (const item of
|
|
64
|
+
for (const item of items) {
|
|
65
65
|
<li>{item}</li>
|
|
66
66
|
}
|
|
67
67
|
</ul>
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
export component ForLoopInteractive() {
|
|
71
|
-
let counts = track([0, 0, 0]);
|
|
71
|
+
let &[counts] = track([0, 0, 0]);
|
|
72
72
|
<div>
|
|
73
|
-
for (const count of
|
|
73
|
+
for (const count of counts; index i) {
|
|
74
74
|
<div class={`item-${i}`}>
|
|
75
75
|
<span class="value">{count}</span>
|
|
76
76
|
<button
|
|
77
77
|
class="increment"
|
|
78
78
|
onClick={() => {
|
|
79
|
-
const newCounts = [
|
|
79
|
+
const newCounts = [...counts];
|
|
80
80
|
newCounts[i]++;
|
|
81
|
-
|
|
81
|
+
counts = newCounts;
|
|
82
82
|
}}
|
|
83
83
|
>
|
|
84
84
|
{'+'}
|
|
@@ -130,7 +130,7 @@ export component ForLoopComplexObjects() {
|
|
|
130
130
|
|
|
131
131
|
// Test reordering items in a keyed for loop
|
|
132
132
|
export component KeyedForLoopReorder() {
|
|
133
|
-
let items = track([
|
|
133
|
+
let &[items] = track([
|
|
134
134
|
{ id: 1, name: 'First' },
|
|
135
135
|
{ id: 2, name: 'Second' },
|
|
136
136
|
{ id: 3, name: 'Third' },
|
|
@@ -138,13 +138,13 @@ export component KeyedForLoopReorder() {
|
|
|
138
138
|
<button
|
|
139
139
|
class="reorder"
|
|
140
140
|
onClick={() => {
|
|
141
|
-
|
|
141
|
+
items = [items[2], items[0], items[1]];
|
|
142
142
|
}}
|
|
143
143
|
>
|
|
144
144
|
{'Reorder'}
|
|
145
145
|
</button>
|
|
146
146
|
<ul>
|
|
147
|
-
for (const item of
|
|
147
|
+
for (const item of items; key item.id) {
|
|
148
148
|
<li class={`item-${item.id}`}>{item.name}</li>
|
|
149
149
|
}
|
|
150
150
|
</ul>
|
|
@@ -152,20 +152,20 @@ export component KeyedForLoopReorder() {
|
|
|
152
152
|
|
|
153
153
|
// Test for loop with item property updates (keyed)
|
|
154
154
|
export component KeyedForLoopUpdate() {
|
|
155
|
-
let items = track([
|
|
155
|
+
let &[items] = track([
|
|
156
156
|
{ id: 1, name: 'Item 1' },
|
|
157
157
|
{ id: 2, name: 'Item 2' },
|
|
158
158
|
]);
|
|
159
159
|
<button
|
|
160
160
|
class="update"
|
|
161
161
|
onClick={() => {
|
|
162
|
-
|
|
162
|
+
items = items.map((item) => (item.id === 1 ? { ...item, name: 'Updated' } : item));
|
|
163
163
|
}}
|
|
164
164
|
>
|
|
165
165
|
{'Update'}
|
|
166
166
|
</button>
|
|
167
167
|
<ul>
|
|
168
|
-
for (const item of
|
|
168
|
+
for (const item of items; key item.id) {
|
|
169
169
|
<li class={`item-${item.id}`}>{item.name}</li>
|
|
170
170
|
}
|
|
171
171
|
</ul>
|
|
@@ -173,18 +173,18 @@ export component KeyedForLoopUpdate() {
|
|
|
173
173
|
|
|
174
174
|
// Test for loop with combined add/remove/reorder
|
|
175
175
|
export component ForLoopMixedOperations() {
|
|
176
|
-
let items = track(['A', 'B', 'C', 'D']);
|
|
176
|
+
let &[items] = track(['A', 'B', 'C', 'D']);
|
|
177
177
|
<button
|
|
178
178
|
class="shuffle"
|
|
179
179
|
onClick={() => {
|
|
180
180
|
// Remove B, add E, reorder to D, C, A, E
|
|
181
|
-
|
|
181
|
+
items = ['D', 'C', 'A', 'E'];
|
|
182
182
|
}}
|
|
183
183
|
>
|
|
184
184
|
{'Shuffle'}
|
|
185
185
|
</button>
|
|
186
186
|
<ul>
|
|
187
|
-
for (const item of
|
|
187
|
+
for (const item of items) {
|
|
188
188
|
<li class={`item-${item}`}>{item}</li>
|
|
189
189
|
}
|
|
190
190
|
</ul>
|
|
@@ -192,12 +192,12 @@ export component ForLoopMixedOperations() {
|
|
|
192
192
|
|
|
193
193
|
// Test for loop inside if block (combined control flow)
|
|
194
194
|
export component ForLoopInsideIf() {
|
|
195
|
-
let showList = track(true);
|
|
196
|
-
let items = track(['X', 'Y', 'Z']);
|
|
195
|
+
let &[showList] = track(true);
|
|
196
|
+
let &[items] = track(['X', 'Y', 'Z']);
|
|
197
197
|
<button
|
|
198
198
|
class="toggle"
|
|
199
199
|
onClick={() => {
|
|
200
|
-
|
|
200
|
+
showList = !showList;
|
|
201
201
|
}}
|
|
202
202
|
>
|
|
203
203
|
{'Toggle List'}
|
|
@@ -205,14 +205,14 @@ export component ForLoopInsideIf() {
|
|
|
205
205
|
<button
|
|
206
206
|
class="add"
|
|
207
207
|
onClick={() => {
|
|
208
|
-
|
|
208
|
+
items = [...items, 'W'];
|
|
209
209
|
}}
|
|
210
210
|
>
|
|
211
211
|
{'Add Item'}
|
|
212
212
|
</button>
|
|
213
|
-
if (
|
|
213
|
+
if (showList) {
|
|
214
214
|
<ul class="list">
|
|
215
|
-
for (const item of
|
|
215
|
+
for (const item of items) {
|
|
216
216
|
<li>{item}</li>
|
|
217
217
|
}
|
|
218
218
|
</ul>
|
|
@@ -221,17 +221,17 @@ export component ForLoopInsideIf() {
|
|
|
221
221
|
|
|
222
222
|
// Test for loop that transitions from empty to populated
|
|
223
223
|
export component ForLoopEmptyToPopulated() {
|
|
224
|
-
let items = track<string[]>([]);
|
|
224
|
+
let &[items] = track<string[]>([]);
|
|
225
225
|
<button
|
|
226
226
|
class="populate"
|
|
227
227
|
onClick={() => {
|
|
228
|
-
|
|
228
|
+
items = ['One', 'Two', 'Three'];
|
|
229
229
|
}}
|
|
230
230
|
>
|
|
231
231
|
{'Populate'}
|
|
232
232
|
</button>
|
|
233
233
|
<ul class="list">
|
|
234
|
-
for (const item of
|
|
234
|
+
for (const item of items) {
|
|
235
235
|
<li>{item}</li>
|
|
236
236
|
}
|
|
237
237
|
</ul>
|
|
@@ -239,17 +239,17 @@ export component ForLoopEmptyToPopulated() {
|
|
|
239
239
|
|
|
240
240
|
// Test for loop that transitions from populated to empty
|
|
241
241
|
export component ForLoopPopulatedToEmpty() {
|
|
242
|
-
let items = track(['One', 'Two', 'Three']);
|
|
242
|
+
let &[items] = track(['One', 'Two', 'Three']);
|
|
243
243
|
<button
|
|
244
244
|
class="clear"
|
|
245
245
|
onClick={() => {
|
|
246
|
-
|
|
246
|
+
items = [];
|
|
247
247
|
}}
|
|
248
248
|
>
|
|
249
249
|
{'Clear'}
|
|
250
250
|
</button>
|
|
251
251
|
<ul class="list">
|
|
252
|
-
for (const item of
|
|
252
|
+
for (const item of items) {
|
|
253
253
|
<li>{item}</li>
|
|
254
254
|
}
|
|
255
255
|
</ul>
|
|
@@ -257,14 +257,14 @@ export component ForLoopPopulatedToEmpty() {
|
|
|
257
257
|
|
|
258
258
|
// Test nested for loops with reactivity
|
|
259
259
|
export component NestedForLoopReactive() {
|
|
260
|
-
let grid = track([
|
|
260
|
+
let &[grid] = track([
|
|
261
261
|
[1, 2],
|
|
262
262
|
[3, 4],
|
|
263
263
|
]);
|
|
264
264
|
<button
|
|
265
265
|
class="add-row"
|
|
266
266
|
onClick={() => {
|
|
267
|
-
|
|
267
|
+
grid = [...grid, [5, 6]];
|
|
268
268
|
}}
|
|
269
269
|
>
|
|
270
270
|
{'Add Row'}
|
|
@@ -272,15 +272,15 @@ export component NestedForLoopReactive() {
|
|
|
272
272
|
<button
|
|
273
273
|
class="update-cell"
|
|
274
274
|
onClick={() => {
|
|
275
|
-
const newGrid =
|
|
275
|
+
const newGrid = grid.map((row) => [...row]);
|
|
276
276
|
newGrid[0][0] = 99;
|
|
277
|
-
|
|
277
|
+
grid = newGrid;
|
|
278
278
|
}}
|
|
279
279
|
>
|
|
280
280
|
{'Update Cell'}
|
|
281
281
|
</button>
|
|
282
282
|
<div class="grid">
|
|
283
|
-
for (const row of
|
|
283
|
+
for (const row of grid; index rowIndex) {
|
|
284
284
|
<div class={`row-${rowIndex}`}>
|
|
285
285
|
for (const cell of row; index colIndex) {
|
|
286
286
|
<span class={`cell-${rowIndex}-${colIndex}`}>{cell}</span>
|
|
@@ -330,17 +330,17 @@ export component ForLoopDeeplyNested() {
|
|
|
330
330
|
|
|
331
331
|
// Test for loop with index that gets updated
|
|
332
332
|
export component ForLoopIndexUpdate() {
|
|
333
|
-
let items = track(['First', 'Second', 'Third']);
|
|
333
|
+
let &[items] = track(['First', 'Second', 'Third']);
|
|
334
334
|
<button
|
|
335
335
|
class="prepend"
|
|
336
336
|
onClick={() => {
|
|
337
|
-
|
|
337
|
+
items = ['Zeroth', ...items];
|
|
338
338
|
}}
|
|
339
339
|
>
|
|
340
340
|
{'Prepend'}
|
|
341
341
|
</button>
|
|
342
342
|
<ul>
|
|
343
|
-
for (const item of
|
|
343
|
+
for (const item of items; index i) {
|
|
344
344
|
<li class={`item-${i}`}>{`[${i}] ${item}`}</li>
|
|
345
345
|
}
|
|
346
346
|
</ul>
|
|
@@ -348,7 +348,7 @@ export component ForLoopIndexUpdate() {
|
|
|
348
348
|
|
|
349
349
|
// Test keyed for loop with index
|
|
350
350
|
export component KeyedForLoopWithIndex() {
|
|
351
|
-
let items = track([
|
|
351
|
+
let &[items] = track([
|
|
352
352
|
{ id: 'a', value: 'Alpha' },
|
|
353
353
|
{ id: 'b', value: 'Beta' },
|
|
354
354
|
{ id: 'c', value: 'Gamma' },
|
|
@@ -356,13 +356,13 @@ export component KeyedForLoopWithIndex() {
|
|
|
356
356
|
<button
|
|
357
357
|
class="reorder"
|
|
358
358
|
onClick={() => {
|
|
359
|
-
|
|
359
|
+
items = [items[1], items[2], items[0]];
|
|
360
360
|
}}
|
|
361
361
|
>
|
|
362
362
|
{'Rotate'}
|
|
363
363
|
</button>
|
|
364
364
|
<ul>
|
|
365
|
-
for (const item of
|
|
365
|
+
for (const item of items; index i; key item.id) {
|
|
366
366
|
<li class={`item-${item.id}`} data-index={i}>{`[${i}] ${item.id}: ${item.value}`}</li>
|
|
367
367
|
}
|
|
368
368
|
</ul>
|
|
@@ -370,10 +370,10 @@ export component KeyedForLoopWithIndex() {
|
|
|
370
370
|
|
|
371
371
|
// Test for loop with sibling elements
|
|
372
372
|
export component ForLoopWithSiblings() {
|
|
373
|
-
let items = track(['A', 'B']);
|
|
373
|
+
let &[items] = track(['A', 'B']);
|
|
374
374
|
<div class="wrapper">
|
|
375
375
|
<header class="before">{'Before'}</header>
|
|
376
|
-
for (const item of
|
|
376
|
+
for (const item of items) {
|
|
377
377
|
<div class={`item-${item}`}>{item}</div>
|
|
378
378
|
}
|
|
379
379
|
<footer class="after">{'After'}</footer>
|
|
@@ -381,7 +381,7 @@ export component ForLoopWithSiblings() {
|
|
|
381
381
|
<button
|
|
382
382
|
class="add"
|
|
383
383
|
onClick={() => {
|
|
384
|
-
|
|
384
|
+
items = [...items, 'C'];
|
|
385
385
|
}}
|
|
386
386
|
>
|
|
387
387
|
{'Add'}
|
|
@@ -403,17 +403,17 @@ export component ForLoopItemState() {
|
|
|
403
403
|
}
|
|
404
404
|
|
|
405
405
|
component TodoItem(props: { id: number; text: string }) {
|
|
406
|
-
let done = track(false);
|
|
406
|
+
let &[done] = track(false);
|
|
407
407
|
<div class={`todo-${props.id}`}>
|
|
408
408
|
<input
|
|
409
409
|
type="checkbox"
|
|
410
410
|
class="checkbox"
|
|
411
|
-
checked={
|
|
411
|
+
checked={done}
|
|
412
412
|
onChange={(e) => {
|
|
413
|
-
|
|
413
|
+
done = (e.target as HTMLInputElement).checked;
|
|
414
414
|
}}
|
|
415
415
|
/>
|
|
416
|
-
<span class={
|
|
416
|
+
<span class={done ? 'completed' : 'pending'}>{props.text}</span>
|
|
417
417
|
</div>
|
|
418
418
|
}
|
|
419
419
|
|
|
@@ -429,17 +429,17 @@ export component ForLoopSingleItem() {
|
|
|
429
429
|
|
|
430
430
|
// Test for loop adding at beginning
|
|
431
431
|
export component ForLoopAddAtBeginning() {
|
|
432
|
-
let items = track(['B', 'C']);
|
|
432
|
+
let &[items] = track(['B', 'C']);
|
|
433
433
|
<button
|
|
434
434
|
class="prepend"
|
|
435
435
|
onClick={() => {
|
|
436
|
-
|
|
436
|
+
items = ['A', ...items];
|
|
437
437
|
}}
|
|
438
438
|
>
|
|
439
439
|
{'Prepend A'}
|
|
440
440
|
</button>
|
|
441
441
|
<ul>
|
|
442
|
-
for (const item of
|
|
442
|
+
for (const item of items) {
|
|
443
443
|
<li class={`item-${item}`}>{item}</li>
|
|
444
444
|
}
|
|
445
445
|
</ul>
|
|
@@ -447,19 +447,19 @@ export component ForLoopAddAtBeginning() {
|
|
|
447
447
|
|
|
448
448
|
// Test for loop adding in the middle
|
|
449
449
|
export component ForLoopAddInMiddle() {
|
|
450
|
-
let items = track(['A', 'C']);
|
|
450
|
+
let &[items] = track(['A', 'C']);
|
|
451
451
|
<button
|
|
452
452
|
class="insert"
|
|
453
453
|
onClick={() => {
|
|
454
|
-
const copy = [
|
|
454
|
+
const copy = [...items];
|
|
455
455
|
copy.splice(1, 0, 'B');
|
|
456
|
-
|
|
456
|
+
items = copy;
|
|
457
457
|
}}
|
|
458
458
|
>
|
|
459
459
|
{'Insert B'}
|
|
460
460
|
</button>
|
|
461
461
|
<ul>
|
|
462
|
-
for (const item of
|
|
462
|
+
for (const item of items) {
|
|
463
463
|
<li class={`item-${item}`}>{item}</li>
|
|
464
464
|
}
|
|
465
465
|
</ul>
|
|
@@ -467,17 +467,17 @@ export component ForLoopAddInMiddle() {
|
|
|
467
467
|
|
|
468
468
|
// Test for loop removing from the middle
|
|
469
469
|
export component ForLoopRemoveFromMiddle() {
|
|
470
|
-
let items = track(['A', 'B', 'C']);
|
|
470
|
+
let &[items] = track(['A', 'B', 'C']);
|
|
471
471
|
<button
|
|
472
472
|
class="remove-middle"
|
|
473
473
|
onClick={() => {
|
|
474
|
-
|
|
474
|
+
items = items.filter((item) => item !== 'B');
|
|
475
475
|
}}
|
|
476
476
|
>
|
|
477
477
|
{'Remove B'}
|
|
478
478
|
</button>
|
|
479
479
|
<ul>
|
|
480
|
-
for (const item of
|
|
480
|
+
for (const item of items) {
|
|
481
481
|
<li class={`item-${item}`}>{item}</li>
|
|
482
482
|
}
|
|
483
483
|
</ul>
|
|
@@ -495,19 +495,19 @@ export component ForLoopLargeList() {
|
|
|
495
495
|
|
|
496
496
|
// Test for loop with swap operation
|
|
497
497
|
export component ForLoopSwap() {
|
|
498
|
-
let items = track(['A', 'B', 'C', 'D']);
|
|
498
|
+
let &[items] = track(['A', 'B', 'C', 'D']);
|
|
499
499
|
<button
|
|
500
500
|
class="swap"
|
|
501
501
|
onClick={() => {
|
|
502
|
-
const copy = [
|
|
502
|
+
const copy = [...items];
|
|
503
503
|
[copy[0], copy[3]] = [copy[3], copy[0]];
|
|
504
|
-
|
|
504
|
+
items = copy;
|
|
505
505
|
}}
|
|
506
506
|
>
|
|
507
507
|
{'Swap First and Last'}
|
|
508
508
|
</button>
|
|
509
509
|
<ul>
|
|
510
|
-
for (const item of
|
|
510
|
+
for (const item of items) {
|
|
511
511
|
<li class={`item-${item}`}>{item}</li>
|
|
512
512
|
}
|
|
513
513
|
</ul>
|
|
@@ -515,17 +515,17 @@ export component ForLoopSwap() {
|
|
|
515
515
|
|
|
516
516
|
// Test for loop with reverse operation
|
|
517
517
|
export component ForLoopReverse() {
|
|
518
|
-
let items = track(['A', 'B', 'C', 'D']);
|
|
518
|
+
let &[items] = track(['A', 'B', 'C', 'D']);
|
|
519
519
|
<button
|
|
520
520
|
class="reverse"
|
|
521
521
|
onClick={() => {
|
|
522
|
-
|
|
522
|
+
items = [...items].reverse();
|
|
523
523
|
}}
|
|
524
524
|
>
|
|
525
525
|
{'Reverse'}
|
|
526
526
|
</button>
|
|
527
527
|
<ul>
|
|
528
|
-
for (const item of
|
|
528
|
+
for (const item of items) {
|
|
529
529
|
<li class={`item-${item}`}>{item}</li>
|
|
530
530
|
}
|
|
531
531
|
</ul>
|
|
@@ -11,13 +11,13 @@ export component StaticTitle() {
|
|
|
11
11
|
|
|
12
12
|
// Reactive title
|
|
13
13
|
export component ReactiveTitle() {
|
|
14
|
-
let title = track('Initial Title');
|
|
14
|
+
let &[title] = track('Initial Title');
|
|
15
15
|
|
|
16
16
|
<head>
|
|
17
|
-
<title>{
|
|
17
|
+
<title>{title}</title>
|
|
18
18
|
</head>
|
|
19
19
|
<div>
|
|
20
|
-
<span>{
|
|
20
|
+
<span>{title}</span>
|
|
21
21
|
</div>
|
|
22
22
|
}
|
|
23
23
|
|
|
@@ -34,25 +34,25 @@ export component MultipleHeadElements() {
|
|
|
34
34
|
|
|
35
35
|
// Head with reactive meta tags
|
|
36
36
|
export component ReactiveMetaTags() {
|
|
37
|
-
let description = track('Initial description');
|
|
37
|
+
let &[description] = track('Initial description');
|
|
38
38
|
|
|
39
39
|
<head>
|
|
40
40
|
<title>{'My Page'}</title>
|
|
41
|
-
<meta name="description" content={
|
|
41
|
+
<meta name="description" content={description} />
|
|
42
42
|
</head>
|
|
43
43
|
|
|
44
|
-
<div>{
|
|
44
|
+
<div>{description}</div>
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
// Title with template literal
|
|
48
48
|
export component TitleWithTemplate() {
|
|
49
|
-
let name = track('World');
|
|
49
|
+
let &[name] = track('World');
|
|
50
50
|
|
|
51
51
|
<head>
|
|
52
|
-
<title>{`Hello ${
|
|
52
|
+
<title>{`Hello ${name}!`}</title>
|
|
53
53
|
</head>
|
|
54
54
|
|
|
55
|
-
<div>{
|
|
55
|
+
<div>{name}</div>
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
// Empty title
|
|
@@ -65,26 +65,26 @@ export component EmptyTitle() {
|
|
|
65
65
|
|
|
66
66
|
// Title with conditional content
|
|
67
67
|
export component ConditionalTitle() {
|
|
68
|
-
let showPrefix = track(true);
|
|
69
|
-
let title = track('Main Page');
|
|
68
|
+
let &[showPrefix] = track(true);
|
|
69
|
+
let &[title] = track('Main Page');
|
|
70
70
|
|
|
71
71
|
<head>
|
|
72
|
-
<title>{
|
|
72
|
+
<title>{showPrefix ? 'App - ' + title : title}</title>
|
|
73
73
|
</head>
|
|
74
74
|
|
|
75
|
-
<div>{
|
|
75
|
+
<div>{title}</div>
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
// Title with computed value
|
|
79
79
|
export component ComputedTitle() {
|
|
80
|
-
let count = track(0);
|
|
80
|
+
let &[count] = track(0);
|
|
81
81
|
let prefix = 'Count: ';
|
|
82
82
|
|
|
83
83
|
<head>
|
|
84
|
-
<title>{prefix +
|
|
84
|
+
<title>{prefix + count}</title>
|
|
85
85
|
</head>
|
|
86
86
|
<div>
|
|
87
|
-
<span>{
|
|
87
|
+
<span>{count}</span>
|
|
88
88
|
</div>
|
|
89
89
|
}
|
|
90
90
|
|
|
@@ -19,10 +19,10 @@ export component Layout({ children }: { children: any }) {
|
|
|
19
19
|
|
|
20
20
|
// A child component with an if block (the key source of deep hydrate_node)
|
|
21
21
|
export component Content() {
|
|
22
|
-
let visible = track(true);
|
|
22
|
+
let &[visible] = track(true);
|
|
23
23
|
|
|
24
24
|
<div class="content">
|
|
25
|
-
if (
|
|
25
|
+
if (visible) {
|
|
26
26
|
<p class="text">{'Hello world'}</p>
|
|
27
27
|
}
|
|
28
28
|
</div>
|
|
@@ -229,13 +229,13 @@ component NavItem({
|
|
|
229
229
|
}
|
|
230
230
|
|
|
231
231
|
component SidebarSection({ title, children }: { title: string; children: any }) {
|
|
232
|
-
let expanded = track(true);
|
|
232
|
+
let &[expanded] = track(true);
|
|
233
233
|
<section class="sidebar-section">
|
|
234
234
|
<div class="section-header">
|
|
235
235
|
<h2>{title}</h2>
|
|
236
|
-
<button onClick={() => (
|
|
236
|
+
<button onClick={() => (expanded = !expanded)}>{'Toggle'}</button>
|
|
237
237
|
</div>
|
|
238
|
-
if (
|
|
238
|
+
if (expanded) {
|
|
239
239
|
<div class="section-items">
|
|
240
240
|
<children />
|
|
241
241
|
</div>
|