ripple 0.2.152 → 0.2.154
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/README.md +3 -3
- package/package.json +5 -5
- package/src/compiler/phases/1-parse/index.js +1 -1
- package/src/compiler/phases/3-transform/client/index.js +37 -16
- package/src/compiler/phases/3-transform/server/index.js +43 -25
- package/src/runtime/internal/client/events.js +5 -1
- package/src/runtime/internal/client/index.js +2 -1
- package/src/runtime/internal/client/render.js +18 -15
- package/src/runtime/internal/client/runtime.js +75 -10
- package/src/runtime/internal/server/index.js +51 -11
- package/src/server/index.js +1 -1
- package/tests/client/array/array.derived.test.ripple +61 -33
- package/tests/client/array/array.iteration.test.ripple +3 -1
- package/tests/client/array/array.mutations.test.ripple +19 -15
- package/tests/client/array/array.static.test.ripple +115 -104
- package/tests/client/array/array.to-methods.test.ripple +3 -3
- package/tests/client/basic/basic.attributes.test.ripple +110 -57
- package/tests/client/basic/basic.collections.test.ripple +41 -22
- package/tests/client/basic/basic.errors.test.ripple +12 -6
- package/tests/client/basic/basic.events.test.ripple +51 -33
- package/tests/client/basic/basic.reactivity.test.ripple +120 -56
- package/tests/client/basic/basic.rendering.test.ripple +49 -19
- package/tests/client/basic/basic.styling.test.ripple +2 -2
- package/tests/client/basic/basic.utilities.test.ripple +1 -1
- package/tests/client/boundaries.test.ripple +70 -58
- package/tests/client/compiler/compiler.assignments.test.ripple +32 -4
- package/tests/client/compiler/compiler.attributes.test.ripple +46 -46
- package/tests/client/compiler/compiler.basic.test.ripple +18 -15
- package/tests/client/compiler/compiler.tracked-access.test.ripple +53 -42
- package/tests/client/compiler/compiler.typescript.test.ripple +1 -2
- package/tests/client/composite/composite.dynamic-components.test.ripple +6 -6
- package/tests/client/composite/composite.generics.test.ripple +39 -36
- package/tests/client/composite/composite.props.test.ripple +4 -3
- package/tests/client/composite/composite.reactivity.test.ripple +112 -27
- package/tests/client/composite/composite.render.test.ripple +9 -8
- package/tests/client/computed-properties.test.ripple +24 -24
- package/tests/client/context.test.ripple +11 -9
- package/tests/client/date.test.ripple +3 -1
- package/tests/client/dynamic-elements.test.ripple +103 -78
- package/tests/client/for.test.ripple +27 -17
- package/tests/client/head.test.ripple +42 -6
- package/tests/client/html.test.ripple +42 -32
- package/tests/client/input-value.test.ripple +4 -4
- package/tests/client/map.test.ripple +140 -141
- package/tests/client/media-query.test.ripple +31 -31
- package/tests/client/object.test.ripple +148 -112
- package/tests/client/portal.test.ripple +29 -15
- package/tests/client/ref.test.ripple +9 -3
- package/tests/client/set.test.ripple +111 -111
- package/tests/client/tracked-expression.test.ripple +16 -17
- package/tests/client/url/url.derived.test.ripple +19 -9
- package/tests/client/url/url.parsing.test.ripple +24 -8
- package/tests/client/url/url.partial-removal.test.ripple +12 -4
- package/tests/client/url/url.reactivity.test.ripple +63 -25
- package/tests/client/url/url.serialization.test.ripple +18 -6
- package/tests/client/url-search-params/url-search-params.derived.test.ripple +10 -6
- package/tests/client/url-search-params/url-search-params.iteration.test.ripple +3 -1
- package/tests/client/url-search-params/url-search-params.mutation.test.ripple +26 -14
- package/tests/client/url-search-params/url-search-params.tracked-url.test.ripple +3 -1
- package/tests/server/await.test.ripple +23 -22
- package/tests/server/basic.test.ripple +1 -1
- package/tests/server/compiler.test.ripple +3 -7
- package/tests/server/composite.test.ripple +38 -36
- package/tests/server/for.test.ripple +9 -5
- package/tests/server/if.test.ripple +1 -1
- package/tests/server/streaming-ssr.test.ripple +67 -0
- package/types/server.d.ts +5 -4
|
@@ -1,21 +1,26 @@
|
|
|
1
|
-
import { track, flushSync, effect } from 'ripple';
|
|
1
|
+
import { track, trackSplit, flushSync, effect } from 'ripple';
|
|
2
2
|
|
|
3
3
|
describe('composite > reactivity', () => {
|
|
4
4
|
it('renders composite components with object state', () => {
|
|
5
5
|
component Button({ obj }: { obj: { count: Tracked<number> } }) {
|
|
6
|
-
<button
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
<button
|
|
7
|
+
class="count2"
|
|
8
|
+
onClick={() => {
|
|
9
|
+
obj.@count++;
|
|
10
|
+
}}
|
|
11
|
+
>
|
|
12
|
+
{obj.@count}
|
|
13
|
+
</button>
|
|
9
14
|
}
|
|
10
15
|
|
|
11
16
|
component App() {
|
|
12
17
|
<div>
|
|
13
18
|
let obj = {
|
|
14
|
-
count: track(0)
|
|
19
|
+
count: track(0),
|
|
15
20
|
};
|
|
16
21
|
|
|
17
|
-
<span class=
|
|
18
|
-
<Button
|
|
22
|
+
<span class="count">{obj.@count}</span>
|
|
23
|
+
<Button {obj} />
|
|
19
24
|
</div>
|
|
20
25
|
}
|
|
21
26
|
|
|
@@ -32,29 +37,34 @@ describe('composite > reactivity', () => {
|
|
|
32
37
|
|
|
33
38
|
it('renders composite components with object state wrapped in an if statement', () => {
|
|
34
39
|
component Button({ obj }: { obj: { count: Tracked<number> } }) {
|
|
35
|
-
<button
|
|
36
|
-
|
|
37
|
-
|
|
40
|
+
<button
|
|
41
|
+
class="count2"
|
|
42
|
+
onClick={() => {
|
|
43
|
+
obj.@count++;
|
|
44
|
+
}}
|
|
45
|
+
>
|
|
46
|
+
{obj.@count}
|
|
47
|
+
</button>
|
|
38
48
|
}
|
|
39
49
|
|
|
40
50
|
component OtherComponent({ obj }: { obj: { count: Tracked<number> } }) {
|
|
41
|
-
<div class=
|
|
51
|
+
<div class="count3">{obj.@count}</div>
|
|
42
52
|
}
|
|
43
53
|
|
|
44
54
|
component App() {
|
|
45
55
|
<div>
|
|
46
56
|
let obj = {
|
|
47
|
-
count: track(0)
|
|
57
|
+
count: track(0),
|
|
48
58
|
};
|
|
49
59
|
|
|
50
|
-
<span class=
|
|
60
|
+
<span class="count">{obj.@count}</span>
|
|
51
61
|
<span>{' '}</span>
|
|
52
62
|
if (obj) {
|
|
53
|
-
<Button
|
|
63
|
+
<Button {obj} />
|
|
54
64
|
}
|
|
55
65
|
|
|
56
66
|
if (obj) {
|
|
57
|
-
<OtherComponent
|
|
67
|
+
<OtherComponent {obj} />
|
|
58
68
|
}
|
|
59
69
|
</div>
|
|
60
70
|
}
|
|
@@ -74,14 +84,26 @@ describe('composite > reactivity', () => {
|
|
|
74
84
|
it('parents and children have isolated state', () => {
|
|
75
85
|
component Button(props: { count: number }) {
|
|
76
86
|
let count = track(() => props.count);
|
|
77
|
-
<button
|
|
87
|
+
<button
|
|
88
|
+
onClick={() => {
|
|
89
|
+
@count++;
|
|
90
|
+
}}
|
|
91
|
+
>
|
|
92
|
+
{'child: ' + @count}
|
|
93
|
+
</button>
|
|
78
94
|
}
|
|
79
95
|
|
|
80
96
|
component App() {
|
|
81
97
|
<div>
|
|
82
98
|
let count = track(0);
|
|
83
99
|
|
|
84
|
-
<button
|
|
100
|
+
<button
|
|
101
|
+
onClick={() => {
|
|
102
|
+
@count++;
|
|
103
|
+
}}
|
|
104
|
+
>
|
|
105
|
+
{'parent: ' + @count}
|
|
106
|
+
</button>
|
|
85
107
|
<Button {@count} />
|
|
86
108
|
</div>
|
|
87
109
|
}
|
|
@@ -107,16 +129,28 @@ describe('composite > reactivity', () => {
|
|
|
107
129
|
});
|
|
108
130
|
|
|
109
131
|
it('parents and children have isolated connected state (destructured props)', () => {
|
|
110
|
-
component Button({count}: { count: number }) {
|
|
132
|
+
component Button({ count }: { count: number }) {
|
|
111
133
|
let local_count = track(() => count);
|
|
112
|
-
<button
|
|
134
|
+
<button
|
|
135
|
+
onClick={() => {
|
|
136
|
+
@local_count++;
|
|
137
|
+
}}
|
|
138
|
+
>
|
|
139
|
+
{'child: ' + @local_count}
|
|
140
|
+
</button>
|
|
113
141
|
}
|
|
114
142
|
|
|
115
143
|
component App() {
|
|
116
144
|
<div>
|
|
117
145
|
let count = track(0);
|
|
118
146
|
|
|
119
|
-
<button
|
|
147
|
+
<button
|
|
148
|
+
onClick={() => {
|
|
149
|
+
@count++;
|
|
150
|
+
}}
|
|
151
|
+
>
|
|
152
|
+
{'parent: ' + @count}
|
|
153
|
+
</button>
|
|
120
154
|
<Button {@count} />
|
|
121
155
|
</div>
|
|
122
156
|
}
|
|
@@ -149,15 +183,25 @@ describe('composite > reactivity', () => {
|
|
|
149
183
|
const b = track(2);
|
|
150
184
|
const c = track(3);
|
|
151
185
|
|
|
152
|
-
const obj = track(
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
186
|
+
const obj = track(
|
|
187
|
+
() => ({
|
|
188
|
+
@a,
|
|
189
|
+
@b,
|
|
190
|
+
@c,
|
|
191
|
+
}),
|
|
192
|
+
);
|
|
157
193
|
|
|
158
194
|
<Child {...@obj} />
|
|
159
195
|
|
|
160
|
-
<button
|
|
196
|
+
<button
|
|
197
|
+
onClick={() => {
|
|
198
|
+
@a++;
|
|
199
|
+
@b++;
|
|
200
|
+
@c++;
|
|
201
|
+
}}
|
|
202
|
+
>
|
|
203
|
+
{'Increment all'}
|
|
204
|
+
</button>
|
|
161
205
|
}
|
|
162
206
|
|
|
163
207
|
component Child({ a, b, c }: { a: number; b: number; c: number }) {
|
|
@@ -165,7 +209,7 @@ describe('composite > reactivity', () => {
|
|
|
165
209
|
logs.push(`Child effect: ${a}, ${b}, ${c}`);
|
|
166
210
|
});
|
|
167
211
|
|
|
168
|
-
<div>{a + ' ' +
|
|
212
|
+
<div>{a + ' ' + b + ' ' + c}</div>
|
|
169
213
|
}
|
|
170
214
|
|
|
171
215
|
render(App);
|
|
@@ -181,4 +225,45 @@ describe('composite > reactivity', () => {
|
|
|
181
225
|
expect(container.querySelector('div').textContent).toBe('2 3 4');
|
|
182
226
|
expect(logs).toEqual(['Child effect: 1, 2, 3', 'Child effect: 2, 3, 4']);
|
|
183
227
|
});
|
|
228
|
+
|
|
229
|
+
it(
|
|
230
|
+
'keeps reactivity for spread props via intermediate components and usage of trackSplit()',
|
|
231
|
+
() => {
|
|
232
|
+
component App() {
|
|
233
|
+
const count = track(0);
|
|
234
|
+
<CounterWrapper {@count} up={() => @count++} down={() => @count--} />
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
component CounterWrapper(props) {
|
|
238
|
+
<div>
|
|
239
|
+
<Counter {...props} />
|
|
240
|
+
</div>
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
component Counter(props) {
|
|
244
|
+
const [count, up, down, rest] = trackSplit(props, ['count', 'up', 'down']);
|
|
245
|
+
<button onClick={() => @up()}>{'UP'}</button>
|
|
246
|
+
<button onClick={() => @down()}>{'DOWN'}</button>
|
|
247
|
+
<span {...@rest}>{`Counter: ${@count}`}</span>
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
render(App);
|
|
251
|
+
|
|
252
|
+
const buttonIncrement = container.querySelectorAll('button')[0];
|
|
253
|
+
const buttonDecrement = container.querySelectorAll('button')[1];
|
|
254
|
+
const span = container.querySelector('span');
|
|
255
|
+
|
|
256
|
+
expect(span.textContent).toBe('Counter: 0');
|
|
257
|
+
|
|
258
|
+
buttonIncrement.click();
|
|
259
|
+
flushSync();
|
|
260
|
+
|
|
261
|
+
expect(span.textContent).toBe('Counter: 1');
|
|
262
|
+
|
|
263
|
+
buttonDecrement.click();
|
|
264
|
+
flushSync();
|
|
265
|
+
|
|
266
|
+
expect(span.textContent).toBe('Counter: 0');
|
|
267
|
+
},
|
|
268
|
+
);
|
|
184
269
|
});
|
|
@@ -40,11 +40,11 @@ describe('composite > render', () => {
|
|
|
40
40
|
component App() {
|
|
41
41
|
<Button>
|
|
42
42
|
component A() {
|
|
43
|
-
<div>{
|
|
43
|
+
<div>{'I am A'}</div>
|
|
44
44
|
}
|
|
45
|
-
<div>{
|
|
45
|
+
<div>{'other text'}</div>
|
|
46
46
|
component B() {
|
|
47
|
-
<div>{
|
|
47
|
+
<div>{'I am B'}</div>
|
|
48
48
|
}
|
|
49
49
|
</Button>
|
|
50
50
|
}
|
|
@@ -58,13 +58,14 @@ describe('composite > render', () => {
|
|
|
58
58
|
component App() {
|
|
59
59
|
let name = 'Click Me';
|
|
60
60
|
|
|
61
|
-
<Child
|
|
62
|
-
|
|
63
|
-
>{name}</Child>;
|
|
61
|
+
<Child class="my-button">{name}</Child>
|
|
62
|
+
|
|
64
63
|
}
|
|
65
64
|
|
|
66
|
-
component Child({children, ...rest}: {children: string; class: string}) {
|
|
67
|
-
<button {...rest}
|
|
65
|
+
component Child({ children, ...rest }: { children: string; class: string }) {
|
|
66
|
+
<button {...rest}>
|
|
67
|
+
<children />
|
|
68
|
+
</button>
|
|
68
69
|
}
|
|
69
70
|
|
|
70
71
|
render(App);
|
|
@@ -1,45 +1,45 @@
|
|
|
1
1
|
import { flushSync, track } from 'ripple';
|
|
2
2
|
|
|
3
3
|
describe('computed tracked properties', () => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
it('should update a property using assignment', () => {
|
|
5
|
+
component App() {
|
|
6
|
+
let obj = {
|
|
7
|
+
[0]: track(0),
|
|
8
|
+
};
|
|
9
9
|
|
|
10
10
|
<div>{obj.@[0]}</div>
|
|
11
11
|
|
|
12
12
|
<button onClick={() => { obj.@[0] += 1 }}>{"Increment"}</button>
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
render(App);
|
|
16
|
+
expect(container).toMatchSnapshot();
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
const button = container.querySelector('button');
|
|
19
|
+
button.click();
|
|
20
|
+
flushSync();
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
expect(container).toMatchSnapshot();
|
|
23
|
+
});
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
it('should update a property using update expressions', () => {
|
|
26
|
+
component App() {
|
|
27
|
+
let obj = {
|
|
28
|
+
[0]: track(0),
|
|
29
|
+
};
|
|
30
30
|
|
|
31
31
|
<div>{obj.@[0]}</div>
|
|
32
32
|
|
|
33
33
|
<button onClick={() => { obj.@[0]++ }}>{"Increment"}</button>
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
render(App);
|
|
37
|
+
expect(container).toMatchSnapshot();
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
const button = container.querySelector('button');
|
|
40
|
+
button.click();
|
|
41
|
+
flushSync();
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
expect(container).toMatchSnapshot();
|
|
44
|
+
});
|
|
45
45
|
});
|
|
@@ -14,7 +14,7 @@ describe('context', () => {
|
|
|
14
14
|
component TestContext() {
|
|
15
15
|
const value = MyContext.get();
|
|
16
16
|
|
|
17
|
-
MyContext.set(
|
|
17
|
+
MyContext.set('Hello from context!');
|
|
18
18
|
|
|
19
19
|
<Child />
|
|
20
20
|
}
|
|
@@ -25,22 +25,24 @@ describe('context', () => {
|
|
|
25
25
|
});
|
|
26
26
|
|
|
27
27
|
it('handles context captured inside a computed tracked', () => {
|
|
28
|
-
|
|
29
|
-
const MyContext = new Context<number | null>(null)
|
|
28
|
+
const MyContext = new Context<number | null>(null);
|
|
30
29
|
|
|
31
30
|
const doubleContext = () => {
|
|
32
|
-
const value = MyContext.get() as number
|
|
33
|
-
return value * 2
|
|
34
|
-
}
|
|
31
|
+
const value = MyContext.get() as number;
|
|
32
|
+
return value * 2;
|
|
33
|
+
};
|
|
35
34
|
|
|
36
35
|
component App() {
|
|
37
|
-
MyContext.set(4)
|
|
36
|
+
MyContext.set(4);
|
|
38
37
|
|
|
39
38
|
<h3>{MyContext.get()}</h3>
|
|
40
39
|
|
|
41
|
-
<h4>
|
|
40
|
+
<h4>
|
|
41
|
+
{'2x:'}
|
|
42
|
+
{doubleContext()}
|
|
43
|
+
</h4>
|
|
42
44
|
|
|
43
|
-
MyContext.set(8)
|
|
45
|
+
MyContext.set(8);
|
|
44
46
|
}
|
|
45
47
|
|
|
46
48
|
render(App);
|
|
@@ -250,7 +250,9 @@ describe('TrackedDate', () => {
|
|
|
250
250
|
let day = track(() => date.getDate());
|
|
251
251
|
let hours = track(() => date.getHours());
|
|
252
252
|
|
|
253
|
-
<button onClick={() => date.setTime(new Date(2026, 5, 15, 14, 45, 30).getTime())}>
|
|
253
|
+
<button onClick={() => date.setTime(new Date(2026, 5, 15, 14, 45, 30).getTime())}>
|
|
254
|
+
{'Change All'}
|
|
255
|
+
</button>
|
|
254
256
|
<div>
|
|
255
257
|
{'Year: '}
|
|
256
258
|
{@year}
|