ripple 0.3.68 → 0.3.69
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 +48 -0
- package/package.json +3 -3
- package/src/jsx-runtime.d.ts +2 -2
- package/src/runtime/element.js +1 -1
- package/src/runtime/index-client.js +11 -11
- package/src/runtime/index-server.js +7 -4
- package/src/runtime/internal/client/bindings.js +1 -1
- package/src/runtime/internal/client/blocks.js +13 -4
- package/src/runtime/internal/client/component.js +55 -0
- package/src/runtime/internal/client/composite.js +4 -2
- package/src/runtime/internal/client/expression.js +65 -7
- package/src/runtime/internal/client/hmr.js +54 -43
- package/src/runtime/internal/client/index.js +5 -1
- package/src/runtime/internal/client/portal.js +70 -69
- package/src/runtime/internal/client/render.js +3 -0
- package/src/runtime/internal/server/index.js +92 -8
- package/tests/client/__snapshots__/html.test.tsrx.snap +3 -3
- package/tests/client/array/array.copy-within.test.tsrx +33 -31
- package/tests/client/array/array.derived.test.tsrx +186 -169
- package/tests/client/array/array.iteration.test.tsrx +40 -37
- package/tests/client/array/array.mutations.test.tsrx +113 -101
- package/tests/client/array/array.static.test.tsrx +119 -101
- package/tests/client/array/array.to-methods.test.tsrx +24 -21
- package/tests/client/async-suspend.test.tsrx +247 -246
- package/tests/client/basic/__snapshots__/basic.rendering.test.tsrx.snap +0 -1
- package/tests/client/basic/basic.attributes.test.tsrx +428 -423
- package/tests/client/basic/basic.collections.test.tsrx +109 -102
- package/tests/client/basic/basic.components.test.tsrx +323 -205
- package/tests/client/basic/basic.errors.test.tsrx +91 -91
- package/tests/client/basic/basic.events.test.tsrx +114 -115
- package/tests/client/basic/basic.get-set.test.tsrx +97 -87
- package/tests/client/basic/basic.hmr.test.tsrx +19 -16
- package/tests/client/basic/basic.reactivity.test.tsrx +199 -191
- package/tests/client/basic/basic.rendering.test.tsrx +272 -182
- package/tests/client/basic/basic.styling.test.tsrx +23 -22
- package/tests/client/basic/basic.utilities.test.tsrx +10 -8
- package/tests/client/boundaries.test.tsrx +26 -26
- package/tests/client/compiler/__snapshots__/compiler.assignments.test.rsrx.snap +5 -5
- package/tests/client/compiler/__snapshots__/compiler.assignments.test.tsrx.snap +5 -5
- package/tests/client/compiler/compiler.assignments.test.tsrx +77 -81
- package/tests/client/compiler/compiler.attributes.test.tsrx +15 -15
- package/tests/client/compiler/compiler.basic.test.tsrx +322 -314
- package/tests/client/compiler/compiler.regex.test.tsrx +44 -47
- package/tests/client/compiler/compiler.tracked-access.test.tsrx +38 -38
- package/tests/client/compiler/compiler.try-in-function.test.tsrx +16 -16
- package/tests/client/compiler/compiler.typescript.test.tsrx +2 -2
- package/tests/client/composite/composite.dynamic-components.test.tsrx +47 -48
- package/tests/client/composite/composite.generics.test.tsrx +168 -192
- package/tests/client/composite/composite.props.test.tsrx +97 -81
- package/tests/client/composite/composite.reactivity.test.tsrx +177 -147
- package/tests/client/composite/composite.render.test.tsrx +122 -105
- package/tests/client/computed-properties.test.tsrx +28 -28
- package/tests/client/context.test.tsrx +21 -21
- package/tests/client/css/global-additional-cases.test.tsrx +58 -58
- package/tests/client/css/global-advanced-selectors.test.tsrx +16 -16
- package/tests/client/css/global-at-rules.test.tsrx +10 -10
- package/tests/client/css/global-basic.test.tsrx +14 -14
- package/tests/client/css/global-classes-ids.test.tsrx +14 -14
- package/tests/client/css/global-combinators.test.tsrx +10 -10
- package/tests/client/css/global-complex-nesting.test.tsrx +14 -14
- package/tests/client/css/global-edge-cases.test.tsrx +18 -18
- package/tests/client/css/global-keyframes.test.tsrx +12 -12
- package/tests/client/css/global-nested.test.tsrx +10 -10
- package/tests/client/css/global-pseudo.test.tsrx +12 -12
- package/tests/client/css/global-scoping.test.tsrx +20 -20
- package/tests/client/css/style-identifier.test.tsrx +143 -291
- package/tests/client/date.test.tsrx +146 -133
- package/tests/client/dynamic-elements.test.tsrx +398 -365
- package/tests/client/events.test.tsrx +292 -290
- package/tests/client/for.test.tsrx +156 -153
- package/tests/client/head.test.tsrx +105 -96
- package/tests/client/html.test.tsrx +122 -26
- package/tests/client/input-value.test.tsrx +1361 -1314
- package/tests/client/lazy-array.test.tsrx +16 -13
- package/tests/client/lazy-destructuring.test.tsrx +257 -213
- package/tests/client/map.test.tsrx +65 -60
- package/tests/client/media-query.test.tsrx +22 -20
- package/tests/client/object.test.tsrx +87 -81
- package/tests/client/portal.test.tsrx +57 -51
- package/tests/client/ref.test.tsrx +233 -202
- package/tests/client/return.test.tsrx +71 -2560
- package/tests/client/set.test.tsrx +54 -45
- package/tests/client/svg.test.tsrx +216 -186
- package/tests/client/switch.test.tsrx +194 -193
- package/tests/client/track-async-hydration.test.tsrx +18 -14
- package/tests/client/tracked-index-access.test.tsrx +28 -18
- package/tests/client/try.test.tsrx +675 -548
- package/tests/client/tsx.test.tsrx +373 -311
- package/tests/client/typescript-generics.test.tsrx +145 -145
- package/tests/client/url/url.derived.test.tsrx +33 -28
- package/tests/client/url/url.parsing.test.tsrx +61 -51
- package/tests/client/url/url.partial-removal.test.tsrx +56 -48
- package/tests/client/url/url.reactivity.test.tsrx +142 -125
- package/tests/client/url/url.serialization.test.tsrx +13 -11
- package/tests/client/url-search-params/url-search-params.derived.test.tsrx +34 -29
- package/tests/client/url-search-params/url-search-params.initialization.test.tsrx +25 -21
- package/tests/client/url-search-params/url-search-params.iteration.test.tsrx +50 -45
- package/tests/client/url-search-params/url-search-params.mutation.test.tsrx +111 -99
- package/tests/client/url-search-params/url-search-params.retrieval.test.tsrx +49 -43
- package/tests/client/url-search-params/url-search-params.serialization.test.tsrx +14 -12
- package/tests/client/url-search-params/url-search-params.tracked-url.test.tsrx +16 -14
- package/tests/hydration/basic.test.js +3 -3
- package/tests/hydration/compiled/client/basic.js +586 -651
- package/tests/hydration/compiled/client/composite.js +79 -104
- package/tests/hydration/compiled/client/events.js +140 -148
- package/tests/hydration/compiled/client/for.js +1005 -1018
- package/tests/hydration/compiled/client/head.js +124 -134
- package/tests/hydration/compiled/client/hmr.js +41 -48
- package/tests/hydration/compiled/client/html-in-template.js +38 -41
- package/tests/hydration/compiled/client/html.js +970 -1314
- package/tests/hydration/compiled/client/if-children.js +234 -249
- package/tests/hydration/compiled/client/if.js +182 -189
- package/tests/hydration/compiled/client/mixed-control-flow.js +347 -303
- package/tests/hydration/compiled/client/nested-control-flow.js +1084 -832
- package/tests/hydration/compiled/client/portal.js +65 -85
- package/tests/hydration/compiled/client/reactivity.js +84 -90
- package/tests/hydration/compiled/client/return.js +38 -1939
- package/tests/hydration/compiled/client/switch.js +218 -224
- package/tests/hydration/compiled/client/track-async-serialization.js +250 -259
- package/tests/hydration/compiled/client/try.js +123 -132
- package/tests/hydration/compiled/server/basic.js +773 -831
- package/tests/hydration/compiled/server/composite.js +166 -191
- package/tests/hydration/compiled/server/events.js +170 -184
- package/tests/hydration/compiled/server/for.js +851 -909
- package/tests/hydration/compiled/server/head.js +206 -216
- package/tests/hydration/compiled/server/hmr.js +64 -72
- package/tests/hydration/compiled/server/html-in-template.js +42 -76
- package/tests/hydration/compiled/server/html.js +1362 -1667
- package/tests/hydration/compiled/server/if-children.js +419 -445
- package/tests/hydration/compiled/server/if.js +194 -208
- package/tests/hydration/compiled/server/mixed-control-flow.js +249 -257
- package/tests/hydration/compiled/server/nested-control-flow.js +491 -515
- package/tests/hydration/compiled/server/portal.js +152 -160
- package/tests/hydration/compiled/server/reactivity.js +94 -106
- package/tests/hydration/compiled/server/return.js +28 -2172
- package/tests/hydration/compiled/server/switch.js +274 -286
- package/tests/hydration/compiled/server/track-async-serialization.js +340 -358
- package/tests/hydration/compiled/server/try.js +167 -185
- package/tests/hydration/components/basic.tsrx +320 -272
- package/tests/hydration/components/composite.tsrx +44 -32
- package/tests/hydration/components/events.tsrx +101 -91
- package/tests/hydration/components/for.tsrx +510 -452
- package/tests/hydration/components/head.tsrx +87 -80
- package/tests/hydration/components/hmr.tsrx +22 -17
- package/tests/hydration/components/html-in-template.tsrx +22 -17
- package/tests/hydration/components/html.tsrx +525 -443
- package/tests/hydration/components/if-children.tsrx +158 -148
- package/tests/hydration/components/if.tsrx +109 -95
- package/tests/hydration/components/mixed-control-flow.tsrx +100 -96
- package/tests/hydration/components/nested-control-flow.tsrx +215 -203
- package/tests/hydration/components/portal.tsrx +41 -34
- package/tests/hydration/components/reactivity.tsrx +37 -27
- package/tests/hydration/components/return.tsrx +12 -556
- package/tests/hydration/components/switch.tsrx +120 -114
- package/tests/hydration/components/track-async-serialization.tsrx +107 -91
- package/tests/hydration/components/try.tsrx +55 -40
- package/tests/hydration/html.test.js +4 -4
- package/tests/hydration/return.test.js +13 -532
- package/tests/server/await.test.tsrx +3 -3
- package/tests/server/basic.attributes.test.tsrx +264 -195
- package/tests/server/basic.components.test.tsrx +296 -169
- package/tests/server/basic.test.tsrx +300 -198
- package/tests/server/compiler.test.tsrx +62 -60
- package/tests/server/composite.props.test.tsrx +77 -63
- package/tests/server/composite.test.tsrx +168 -192
- package/tests/server/context.test.tsrx +18 -12
- package/tests/server/dynamic-elements.test.tsrx +197 -180
- package/tests/server/for.test.tsrx +85 -78
- package/tests/server/head.test.tsrx +50 -43
- package/tests/server/html-nesting-validation.test.tsrx +8 -8
- package/tests/server/if.test.tsrx +57 -51
- package/tests/server/lazy-destructuring.test.tsrx +366 -294
- package/tests/server/return.test.tsrx +76 -1355
- package/tests/server/streaming-ssr.test.tsrx +4 -75
- package/tests/server/style-identifier.test.tsrx +169 -148
- package/tests/server/switch.test.tsrx +91 -85
- package/tests/server/track-async-serialization.test.tsrx +105 -85
- package/tests/server/try.test.tsrx +374 -280
- package/tests/utils/compiler-compat-config.test.js +2 -2
- package/tests/utils/runtime-imports.test.js +10 -0
- package/types/index.d.ts +8 -0
- package/tests/client/__snapshots__/html.test.rsrx.snap +0 -40
|
@@ -2,45 +2,55 @@ import { flushSync, track } from 'ripple';
|
|
|
2
2
|
|
|
3
3
|
describe('tsx expression', () => {
|
|
4
4
|
it('renders an empty <tsx></tsx> element', () => {
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
function App() {
|
|
6
|
+
return <>
|
|
7
|
+
<tsx></tsx>
|
|
8
|
+
</>;
|
|
7
9
|
}
|
|
8
10
|
render(App);
|
|
9
11
|
expect(container.textContent).toBe('');
|
|
10
12
|
});
|
|
11
13
|
|
|
12
14
|
it('renders an empty <></> fragment shorthand', () => {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
function App() {
|
|
16
|
+
return <>
|
|
17
|
+
<></>
|
|
18
|
+
</>;
|
|
15
19
|
}
|
|
16
20
|
render(App);
|
|
17
21
|
expect(container.textContent).toBe('');
|
|
18
22
|
});
|
|
19
23
|
|
|
20
24
|
it('renders an empty <tsx></tsx> assigned to a variable', () => {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
25
|
+
function App() {
|
|
26
|
+
return <>
|
|
27
|
+
const el = <tsx></tsx>;
|
|
28
|
+
{el}
|
|
29
|
+
</>;
|
|
24
30
|
}
|
|
25
31
|
render(App);
|
|
26
32
|
expect(container.textContent).toBe('');
|
|
27
33
|
});
|
|
28
34
|
|
|
29
35
|
it('renders an empty <></> fragment assigned to a variable', () => {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
36
|
+
function App() {
|
|
37
|
+
return <>
|
|
38
|
+
const el = <></>;
|
|
39
|
+
{el}
|
|
40
|
+
</>;
|
|
33
41
|
}
|
|
34
42
|
render(App);
|
|
35
43
|
expect(container.textContent).toBe('');
|
|
36
44
|
});
|
|
37
45
|
|
|
38
46
|
it('renders a basic fragment shorthand element', () => {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
<
|
|
42
|
-
|
|
43
|
-
|
|
47
|
+
function App() {
|
|
48
|
+
return <>
|
|
49
|
+
const el = <tsx>
|
|
50
|
+
<div>hello world</div>
|
|
51
|
+
</tsx>;
|
|
52
|
+
{el}
|
|
53
|
+
</>;
|
|
44
54
|
}
|
|
45
55
|
render(App);
|
|
46
56
|
expect(container.textContent).toBe('hello world');
|
|
@@ -48,32 +58,30 @@ describe('tsx expression', () => {
|
|
|
48
58
|
});
|
|
49
59
|
|
|
50
60
|
it('applies scoped classes inside tsx blocks and fragment shorthand', () => {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
<
|
|
54
|
-
<
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
</style>
|
|
61
|
+
function App() {
|
|
62
|
+
return <>
|
|
63
|
+
<tsx>
|
|
64
|
+
<div class="card">
|
|
65
|
+
<h2>
|
|
66
|
+
{'tsx block'}
|
|
67
|
+
</h2>
|
|
68
|
+
</div>
|
|
69
|
+
</tsx>
|
|
70
|
+
<>
|
|
71
|
+
<div class="card">
|
|
72
|
+
<h2>{'fragment shorthand'}</h2>
|
|
73
|
+
</div>
|
|
74
|
+
</>
|
|
75
|
+
<style>
|
|
76
|
+
.card {
|
|
77
|
+
padding: 1rem;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
h2 {
|
|
81
|
+
color: red;
|
|
82
|
+
}
|
|
83
|
+
</style>
|
|
84
|
+
</>;
|
|
77
85
|
}
|
|
78
86
|
|
|
79
87
|
render(App);
|
|
@@ -98,11 +106,13 @@ describe('tsx expression', () => {
|
|
|
98
106
|
});
|
|
99
107
|
|
|
100
108
|
it('renders a tsx element assigned to a variable', () => {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
109
|
+
function App() {
|
|
110
|
+
return <>
|
|
111
|
+
const el = <tsx>
|
|
112
|
+
<span class="test">content</span>
|
|
113
|
+
</tsx>;
|
|
114
|
+
{el}
|
|
115
|
+
</>;
|
|
106
116
|
}
|
|
107
117
|
render(App);
|
|
108
118
|
const span = container.querySelector('span.test');
|
|
@@ -111,12 +121,14 @@ describe('tsx expression', () => {
|
|
|
111
121
|
});
|
|
112
122
|
|
|
113
123
|
it('renders a tsx element with multiple children', () => {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
<
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
124
|
+
function App() {
|
|
125
|
+
return <>
|
|
126
|
+
const el = <tsx>
|
|
127
|
+
<div>first</div>
|
|
128
|
+
<div>second</div>
|
|
129
|
+
</tsx>;
|
|
130
|
+
{el}
|
|
131
|
+
</>;
|
|
120
132
|
}
|
|
121
133
|
render(App);
|
|
122
134
|
const divs = container.querySelectorAll('div');
|
|
@@ -126,13 +138,15 @@ describe('tsx expression', () => {
|
|
|
126
138
|
});
|
|
127
139
|
|
|
128
140
|
it('renders a tsx element with nested elements', () => {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
<
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
141
|
+
function App() {
|
|
142
|
+
return <>
|
|
143
|
+
const el = <tsx>
|
|
144
|
+
<div class="outer">
|
|
145
|
+
<span class="inner">nested</span>
|
|
146
|
+
</div>
|
|
147
|
+
</tsx>;
|
|
148
|
+
{el}
|
|
149
|
+
</>;
|
|
136
150
|
}
|
|
137
151
|
render(App);
|
|
138
152
|
const outer = container.querySelector('div.outer');
|
|
@@ -143,11 +157,13 @@ describe('tsx expression', () => {
|
|
|
143
157
|
});
|
|
144
158
|
|
|
145
159
|
it('renders a tsx element inline in a parent element', () => {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
<
|
|
149
|
-
|
|
150
|
-
|
|
160
|
+
function App() {
|
|
161
|
+
return <>
|
|
162
|
+
const el = <tsx>
|
|
163
|
+
<span>inline</span>
|
|
164
|
+
</tsx>;
|
|
165
|
+
<div class="parent">{el}</div>
|
|
166
|
+
</>;
|
|
151
167
|
}
|
|
152
168
|
render(App);
|
|
153
169
|
const parent = container.querySelector('div.parent');
|
|
@@ -157,15 +173,17 @@ describe('tsx expression', () => {
|
|
|
157
173
|
});
|
|
158
174
|
|
|
159
175
|
it('renders a tsx element with reactive expressions', () => {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
<
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
176
|
+
function App() {
|
|
177
|
+
return <>
|
|
178
|
+
let &[count] = track(0);
|
|
179
|
+
const el = <tsx>
|
|
180
|
+
<div>
|
|
181
|
+
{'count: ' + count}
|
|
182
|
+
</div>
|
|
183
|
+
</tsx>;
|
|
184
|
+
{el}
|
|
185
|
+
<button onClick={() => count++}>{'increment'}</button>
|
|
186
|
+
</>;
|
|
169
187
|
}
|
|
170
188
|
render(App);
|
|
171
189
|
expect(container.querySelector('div').textContent).toBe('count: 0');
|
|
@@ -176,16 +194,17 @@ describe('tsx expression', () => {
|
|
|
176
194
|
});
|
|
177
195
|
|
|
178
196
|
it('conditionally renders tsx elements', () => {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
197
|
+
function App() {
|
|
198
|
+
return <>
|
|
199
|
+
let &[show] = track(true);
|
|
200
|
+
const el = <tsx>
|
|
201
|
+
<div class="tsx-content">visible</div>
|
|
202
|
+
</tsx>;
|
|
203
|
+
if (show) {
|
|
204
|
+
{el}
|
|
205
|
+
}
|
|
206
|
+
<button onClick={() => (show = !show)}>{'toggle'}</button>
|
|
207
|
+
</>;
|
|
189
208
|
}
|
|
190
209
|
render(App);
|
|
191
210
|
expect(container.querySelector('.tsx-content')).toBeTruthy();
|
|
@@ -200,15 +219,17 @@ describe('tsx expression', () => {
|
|
|
200
219
|
});
|
|
201
220
|
|
|
202
221
|
it('renders tsx element passed as children prop', () => {
|
|
203
|
-
|
|
204
|
-
|
|
222
|
+
function Child(&{ children }: { children: any }) {
|
|
223
|
+
return <><div class="wrapper">{children}</div></>;
|
|
205
224
|
}
|
|
206
225
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
<
|
|
210
|
-
|
|
211
|
-
|
|
226
|
+
function App() {
|
|
227
|
+
return <>
|
|
228
|
+
const el = <tsx>
|
|
229
|
+
<span>from tsx</span>
|
|
230
|
+
</tsx>;
|
|
231
|
+
<Child children={el} />
|
|
232
|
+
</>;
|
|
212
233
|
}
|
|
213
234
|
render(App);
|
|
214
235
|
const wrapper = container.querySelector('.wrapper');
|
|
@@ -218,11 +239,13 @@ describe('tsx expression', () => {
|
|
|
218
239
|
});
|
|
219
240
|
|
|
220
241
|
it('renders tsx element with text content only', () => {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
242
|
+
function App() {
|
|
243
|
+
return <>
|
|
244
|
+
const el = <tsx>
|
|
245
|
+
just text
|
|
246
|
+
</tsx>;
|
|
247
|
+
{el}
|
|
248
|
+
</>;
|
|
226
249
|
}
|
|
227
250
|
|
|
228
251
|
render(App);
|
|
@@ -230,11 +253,13 @@ describe('tsx expression', () => {
|
|
|
230
253
|
});
|
|
231
254
|
|
|
232
255
|
it('renders tsx element with static attributes', () => {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
256
|
+
function App() {
|
|
257
|
+
return <>
|
|
258
|
+
const el = <tsx>
|
|
259
|
+
<div id="my-id" class="my-class" data-testid="test" aria-label="label">content</div>
|
|
260
|
+
</tsx>;
|
|
261
|
+
{el}
|
|
262
|
+
</>;
|
|
238
263
|
}
|
|
239
264
|
|
|
240
265
|
render(App);
|
|
@@ -246,14 +271,15 @@ describe('tsx expression', () => {
|
|
|
246
271
|
});
|
|
247
272
|
|
|
248
273
|
it('renders tsx element with dynamic attribute values', () => {
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
274
|
+
function App() {
|
|
275
|
+
return <>
|
|
276
|
+
let &[name] = track('initial');
|
|
277
|
+
const el = <tsx>
|
|
278
|
+
<div id={name} class={'cls-' + name}>content</div>
|
|
279
|
+
</tsx>;
|
|
280
|
+
{el}
|
|
281
|
+
<button onClick={() => (name = 'updated')}>{'update'}</button>
|
|
282
|
+
</>;
|
|
257
283
|
}
|
|
258
284
|
|
|
259
285
|
render(App);
|
|
@@ -268,16 +294,17 @@ describe('tsx expression', () => {
|
|
|
268
294
|
});
|
|
269
295
|
|
|
270
296
|
it('renders tsx element with event handlers', () => {
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
297
|
+
function App() {
|
|
298
|
+
return <>
|
|
299
|
+
let &[clicked] = track(false);
|
|
300
|
+
const el = <tsx>
|
|
301
|
+
<button onClick={() => (clicked = true)}>
|
|
302
|
+
{'click me'}
|
|
303
|
+
</button>
|
|
304
|
+
</tsx>;
|
|
305
|
+
{el}
|
|
306
|
+
<div class="status">{clicked ? 'clicked' : 'not clicked'}</div>
|
|
307
|
+
</>;
|
|
281
308
|
}
|
|
282
309
|
|
|
283
310
|
render(App);
|
|
@@ -289,16 +316,17 @@ describe('tsx expression', () => {
|
|
|
289
316
|
});
|
|
290
317
|
|
|
291
318
|
it('renders tsx element with boolean attributes', () => {
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
319
|
+
function App() {
|
|
320
|
+
return <>
|
|
321
|
+
let &[isDisabled] = track(true);
|
|
322
|
+
const el = <tsx>
|
|
323
|
+
<button disabled={isDisabled}>
|
|
324
|
+
{'btn'}
|
|
325
|
+
</button>
|
|
326
|
+
</tsx>;
|
|
327
|
+
{el}
|
|
328
|
+
<button class="toggle" onClick={() => (isDisabled = !isDisabled)}>{'toggle'}</button>
|
|
329
|
+
</>;
|
|
302
330
|
}
|
|
303
331
|
|
|
304
332
|
render(App);
|
|
@@ -310,14 +338,15 @@ describe('tsx expression', () => {
|
|
|
310
338
|
});
|
|
311
339
|
|
|
312
340
|
it('renders tsx element with style attribute', () => {
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
341
|
+
function App() {
|
|
342
|
+
return <>
|
|
343
|
+
let &[color] = track('red');
|
|
344
|
+
const el = <tsx>
|
|
345
|
+
<div style={'color: ' + color}>styled</div>
|
|
346
|
+
</tsx>;
|
|
347
|
+
{el}
|
|
348
|
+
<button onClick={() => (color = 'blue')}>{'change color'}</button>
|
|
349
|
+
</>;
|
|
321
350
|
}
|
|
322
351
|
|
|
323
352
|
render(App);
|
|
@@ -329,21 +358,22 @@ describe('tsx expression', () => {
|
|
|
329
358
|
});
|
|
330
359
|
|
|
331
360
|
it('renders tsx element with multiple dynamic attributes', () => {
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
361
|
+
function App() {
|
|
362
|
+
return <>
|
|
363
|
+
let &[index] = track(0);
|
|
364
|
+
const el = <tsx>
|
|
365
|
+
<div
|
|
366
|
+
id={'item-' + index}
|
|
367
|
+
class={'item pos-' + index}
|
|
368
|
+
data-index={index}
|
|
369
|
+
title={'Item ' + index}
|
|
370
|
+
>
|
|
371
|
+
{'Item ' + index}
|
|
372
|
+
</div>
|
|
373
|
+
</tsx>;
|
|
374
|
+
{el}
|
|
375
|
+
<button onClick={() => index++}>{'next'}</button>
|
|
376
|
+
</>;
|
|
347
377
|
}
|
|
348
378
|
|
|
349
379
|
render(App);
|
|
@@ -362,16 +392,18 @@ describe('tsx expression', () => {
|
|
|
362
392
|
});
|
|
363
393
|
|
|
364
394
|
it('renders fragment shorthand passed directly as component prop', () => {
|
|
365
|
-
|
|
366
|
-
|
|
395
|
+
function Wrapper(&{ content }: { content: any }) {
|
|
396
|
+
return <><div class="wrapper">{content}</div></>;
|
|
367
397
|
}
|
|
368
398
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
<
|
|
373
|
-
|
|
374
|
-
|
|
399
|
+
function App() {
|
|
400
|
+
return <>
|
|
401
|
+
<Wrapper
|
|
402
|
+
content={<tsx>
|
|
403
|
+
<span class="inner">direct prop</span>
|
|
404
|
+
</tsx>}
|
|
405
|
+
/>
|
|
406
|
+
</>;
|
|
375
407
|
}
|
|
376
408
|
|
|
377
409
|
render(App);
|
|
@@ -382,22 +414,26 @@ describe('tsx expression', () => {
|
|
|
382
414
|
});
|
|
383
415
|
|
|
384
416
|
it('renders fragment shorthand passed directly as children prop', () => {
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
<
|
|
388
|
-
|
|
389
|
-
|
|
417
|
+
function Card(&{ title, children }: { title: any; children: any }) {
|
|
418
|
+
return <>
|
|
419
|
+
<div class="card">
|
|
420
|
+
<h2 class="card-title">{title}</h2>
|
|
421
|
+
<div class="card-body">{children}</div>
|
|
422
|
+
</div>
|
|
423
|
+
</>;
|
|
390
424
|
}
|
|
391
425
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
<
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
<
|
|
399
|
-
|
|
400
|
-
|
|
426
|
+
function App() {
|
|
427
|
+
return <>
|
|
428
|
+
<Card
|
|
429
|
+
title={<tsx>
|
|
430
|
+
<span class="bold">Title</span>
|
|
431
|
+
</tsx>}
|
|
432
|
+
children={<tsx>
|
|
433
|
+
<p>Card content here</p>
|
|
434
|
+
</tsx>}
|
|
435
|
+
/>
|
|
436
|
+
</>;
|
|
401
437
|
}
|
|
402
438
|
|
|
403
439
|
render(App);
|
|
@@ -413,9 +449,11 @@ describe('tsx expression', () => {
|
|
|
413
449
|
</tsx>;
|
|
414
450
|
}
|
|
415
451
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
452
|
+
function App() {
|
|
453
|
+
return <>
|
|
454
|
+
const badge = createBadge('New');
|
|
455
|
+
{badge}
|
|
456
|
+
</>;
|
|
419
457
|
}
|
|
420
458
|
|
|
421
459
|
render(App);
|
|
@@ -430,13 +468,15 @@ describe('tsx expression', () => {
|
|
|
430
468
|
</tsx>;
|
|
431
469
|
}
|
|
432
470
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
471
|
+
function App() {
|
|
472
|
+
return <>
|
|
473
|
+
const items = ['Apple', 'Banana', 'Cherry'];
|
|
474
|
+
<ul>
|
|
475
|
+
for (const item of items) {
|
|
476
|
+
{createListItem(item)}
|
|
477
|
+
}
|
|
478
|
+
</ul>
|
|
479
|
+
</>;
|
|
440
480
|
}
|
|
441
481
|
|
|
442
482
|
render(App);
|
|
@@ -448,12 +488,14 @@ describe('tsx expression', () => {
|
|
|
448
488
|
});
|
|
449
489
|
|
|
450
490
|
it('renders tsx from factory function passed to component', () => {
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
491
|
+
function List(&{ renderItem, items }: { renderItem: (item: string) => any; items: string[] }) {
|
|
492
|
+
return <>
|
|
493
|
+
<ul class="list">
|
|
494
|
+
for (const item of items) {
|
|
495
|
+
{renderItem(item)}
|
|
496
|
+
}
|
|
497
|
+
</ul>
|
|
498
|
+
</>;
|
|
457
499
|
}
|
|
458
500
|
|
|
459
501
|
function itemRenderer(item: string) {
|
|
@@ -464,8 +506,8 @@ describe('tsx expression', () => {
|
|
|
464
506
|
</tsx>;
|
|
465
507
|
}
|
|
466
508
|
|
|
467
|
-
|
|
468
|
-
|
|
509
|
+
function App() {
|
|
510
|
+
return <><List items={['One', 'Two', 'Three']} renderItem={itemRenderer} /></>;
|
|
469
511
|
}
|
|
470
512
|
|
|
471
513
|
render(App);
|
|
@@ -488,12 +530,13 @@ describe('tsx expression', () => {
|
|
|
488
530
|
</tsx>;
|
|
489
531
|
}
|
|
490
532
|
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
533
|
+
function App() {
|
|
534
|
+
return <>
|
|
535
|
+
let &[count] = track(0);
|
|
536
|
+
const counterElement = createCounter('Count:', () => count);
|
|
537
|
+
{counterElement}
|
|
538
|
+
<button onClick={() => count++}>{'increment'}</button>
|
|
539
|
+
</>;
|
|
497
540
|
}
|
|
498
541
|
|
|
499
542
|
render(App);
|
|
@@ -521,9 +564,11 @@ describe('tsx expression', () => {
|
|
|
521
564
|
</tsx>;
|
|
522
565
|
}
|
|
523
566
|
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
567
|
+
function App() {
|
|
568
|
+
return <>
|
|
569
|
+
const btn = createButton('save', 'Save');
|
|
570
|
+
{btn}
|
|
571
|
+
</>;
|
|
527
572
|
}
|
|
528
573
|
|
|
529
574
|
render(App);
|
|
@@ -534,27 +579,31 @@ describe('tsx expression', () => {
|
|
|
534
579
|
});
|
|
535
580
|
|
|
536
581
|
it('renders deeply nested tsx and tsrx expression values', () => {
|
|
537
|
-
function
|
|
538
|
-
return
|
|
582
|
+
function HelperItem({ item }: { item: number }) {
|
|
583
|
+
return <><div class="helper-item">{item}</div></>;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
function MakeFragment({ label }: { label: string }) {
|
|
587
|
+
return <>
|
|
539
588
|
<span class="label">{label}</span>
|
|
540
589
|
const test = <tsx>
|
|
541
590
|
{[1, 2, 3, 4].map(
|
|
542
591
|
(item) => <tsx>
|
|
543
|
-
{
|
|
544
|
-
<div class="helper-item">{item}</div>
|
|
545
|
-
</tsrx>}
|
|
592
|
+
<HelperItem item={item} />
|
|
546
593
|
</tsx>,
|
|
547
594
|
)}
|
|
548
595
|
</tsx>;
|
|
549
596
|
{test}
|
|
550
|
-
|
|
597
|
+
</>;
|
|
551
598
|
}
|
|
552
599
|
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
{
|
|
556
|
-
|
|
557
|
-
|
|
600
|
+
function App() {
|
|
601
|
+
return <>
|
|
602
|
+
{<tsx>
|
|
603
|
+
{[1, 2, 3].map((item) => <div class="app-item">{item}</div>)}
|
|
604
|
+
</tsx>}
|
|
605
|
+
<MakeFragment label="from helper" />
|
|
606
|
+
</>;
|
|
558
607
|
}
|
|
559
608
|
|
|
560
609
|
render(App);
|
|
@@ -573,16 +622,19 @@ describe('tsx expression', () => {
|
|
|
573
622
|
});
|
|
574
623
|
|
|
575
624
|
it('renders tsrx nested directly inside a top-level tsx expression value', () => {
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
625
|
+
function App() {
|
|
626
|
+
return <>
|
|
627
|
+
const content = <tsx>
|
|
628
|
+
<section class="outer">
|
|
629
|
+
{<>
|
|
630
|
+
<div class="inner">
|
|
631
|
+
{'from tsrx'}
|
|
632
|
+
</div>
|
|
633
|
+
</>}
|
|
634
|
+
</section>
|
|
635
|
+
</tsx>;
|
|
636
|
+
{content}
|
|
637
|
+
</>;
|
|
586
638
|
}
|
|
587
639
|
|
|
588
640
|
render(App);
|
|
@@ -593,18 +645,21 @@ describe('tsx expression', () => {
|
|
|
593
645
|
});
|
|
594
646
|
|
|
595
647
|
it('renders nested elements from tsrx inside a top-level tsx value', () => {
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
<
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
648
|
+
function App() {
|
|
649
|
+
return <>
|
|
650
|
+
const content = <tsx>
|
|
651
|
+
<div class="wrapper">
|
|
652
|
+
{<>
|
|
653
|
+
<section class="native">
|
|
654
|
+
<span class="nested-tsrx">
|
|
655
|
+
{'inside nested tsrx'}
|
|
656
|
+
</span>
|
|
657
|
+
</section>
|
|
658
|
+
</>}
|
|
659
|
+
</div>
|
|
660
|
+
</tsx>;
|
|
661
|
+
{content}
|
|
662
|
+
</>;
|
|
608
663
|
}
|
|
609
664
|
|
|
610
665
|
render(App);
|
|
@@ -614,20 +669,19 @@ describe('tsx expression', () => {
|
|
|
614
669
|
expect(native.querySelector('.nested-tsrx').textContent).toBe('inside nested tsrx');
|
|
615
670
|
});
|
|
616
671
|
|
|
617
|
-
it('renders tsx declared
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
672
|
+
it('renders tsx declared before a top-level tsx value', () => {
|
|
673
|
+
function App() {
|
|
674
|
+
return <>
|
|
675
|
+
const nested = <tsx>
|
|
676
|
+
<span class="nested-tsx">
|
|
677
|
+
{'inside nested tsx'}
|
|
678
|
+
</span>
|
|
679
|
+
</tsx>;
|
|
680
|
+
const content = <tsx>
|
|
626
681
|
<div class="native">{nested}</div>
|
|
627
|
-
</
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
{content}
|
|
682
|
+
</tsx>;
|
|
683
|
+
{content}
|
|
684
|
+
</>;
|
|
631
685
|
}
|
|
632
686
|
|
|
633
687
|
render(App);
|
|
@@ -638,21 +692,25 @@ describe('tsx expression', () => {
|
|
|
638
692
|
});
|
|
639
693
|
|
|
640
694
|
it('renders tsx as prop with fallback in component', () => {
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
695
|
+
function Alert(&{ icon, message }: { icon?: any; message: string }) {
|
|
696
|
+
return <>
|
|
697
|
+
<div class="alert">
|
|
698
|
+
{icon}
|
|
699
|
+
<span class="message">{message}</span>
|
|
700
|
+
</div>
|
|
701
|
+
</>;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
function App() {
|
|
705
|
+
return <>
|
|
706
|
+
<Alert message="No icon" />
|
|
707
|
+
<Alert
|
|
708
|
+
icon={<tsx>
|
|
709
|
+
<span class="custom-icon">✓</span>
|
|
710
|
+
</tsx>}
|
|
711
|
+
message="Custom icon"
|
|
712
|
+
/>
|
|
713
|
+
</>;
|
|
656
714
|
}
|
|
657
715
|
|
|
658
716
|
render(App);
|
|
@@ -669,18 +727,19 @@ describe('tsx expression', () => {
|
|
|
669
727
|
</tsx>;
|
|
670
728
|
}
|
|
671
729
|
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
730
|
+
function App() {
|
|
731
|
+
return <>
|
|
732
|
+
const items = [
|
|
733
|
+
{ className: 'item-a', content: 'A' },
|
|
734
|
+
{ className: 'item-b', content: 'B' },
|
|
735
|
+
{ className: 'item-c', content: 'C' },
|
|
736
|
+
];
|
|
737
|
+
<div class="container">
|
|
738
|
+
for (const item of items) {
|
|
739
|
+
{createItem(item.className, item.content)}
|
|
740
|
+
}
|
|
741
|
+
</div>
|
|
742
|
+
</>;
|
|
684
743
|
}
|
|
685
744
|
|
|
686
745
|
render(App);
|
|
@@ -706,11 +765,13 @@ describe('tsx expression', () => {
|
|
|
706
765
|
</tsx>;
|
|
707
766
|
}
|
|
708
767
|
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
768
|
+
function App() {
|
|
769
|
+
return <>
|
|
770
|
+
let &[status] = track('default');
|
|
771
|
+
{createContent(status)}
|
|
772
|
+
<button class="set-success" onClick={() => (status = 'success')}>{'Success'}</button>
|
|
773
|
+
<button class="set-error" onClick={() => (status = 'error')}>{'Error'}</button>
|
|
774
|
+
</>;
|
|
714
775
|
}
|
|
715
776
|
|
|
716
777
|
render(App);
|
|
@@ -730,11 +791,11 @@ describe('tsx expression', () => {
|
|
|
730
791
|
|
|
731
792
|
describe('tsrx expression', () => {
|
|
732
793
|
it('renders native double-quoted text in an assigned fragment', () => {
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
794
|
+
function App() {
|
|
795
|
+
return <>
|
|
796
|
+
const el = <><div>"Hello world"</div></>;
|
|
797
|
+
{el}
|
|
798
|
+
</>;
|
|
738
799
|
}
|
|
739
800
|
|
|
740
801
|
render(App);
|
|
@@ -745,12 +806,14 @@ describe('tsrx expression', () => {
|
|
|
745
806
|
});
|
|
746
807
|
|
|
747
808
|
it('runs setup statements before native template output', () => {
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
const
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
809
|
+
function App() {
|
|
810
|
+
return <>
|
|
811
|
+
const el = <>
|
|
812
|
+
const label = 'from setup';
|
|
813
|
+
<div>{label}</div>
|
|
814
|
+
</>;
|
|
815
|
+
{el}
|
|
816
|
+
</>;
|
|
754
817
|
}
|
|
755
818
|
|
|
756
819
|
render(App);
|
|
@@ -759,14 +822,13 @@ describe('tsrx expression', () => {
|
|
|
759
822
|
});
|
|
760
823
|
|
|
761
824
|
it('updates reactive expressions inside native fragments', () => {
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
<button onClick={() => count++}>{'increment'}</button>
|
|
825
|
+
function App() {
|
|
826
|
+
return <>
|
|
827
|
+
let &[count] = track(0);
|
|
828
|
+
const el = <><div>{'count: ' + count}</div></>;
|
|
829
|
+
{el}
|
|
830
|
+
<button onClick={() => count++}>{'increment'}</button>
|
|
831
|
+
</>;
|
|
770
832
|
}
|
|
771
833
|
|
|
772
834
|
render(App);
|
|
@@ -778,13 +840,15 @@ describe('tsrx expression', () => {
|
|
|
778
840
|
});
|
|
779
841
|
|
|
780
842
|
it('renders native control flow inside an assigned fragment', () => {
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
843
|
+
function App() {
|
|
844
|
+
return <>
|
|
845
|
+
const el = <>
|
|
846
|
+
if (true) {
|
|
847
|
+
<span>"visible"</span>
|
|
848
|
+
}
|
|
849
|
+
</>;
|
|
850
|
+
{el}
|
|
851
|
+
</>;
|
|
788
852
|
}
|
|
789
853
|
|
|
790
854
|
render(App);
|
|
@@ -792,15 +856,13 @@ describe('tsrx expression', () => {
|
|
|
792
856
|
expect(container.querySelector('span').textContent).toBe('visible');
|
|
793
857
|
});
|
|
794
858
|
|
|
795
|
-
it('renders fragments returned from
|
|
796
|
-
function
|
|
797
|
-
return
|
|
798
|
-
<span>{label}</span>
|
|
799
|
-
</tsrx>;
|
|
859
|
+
it('renders fragments returned from component functions outside components', () => {
|
|
860
|
+
function MakeFragment({ label }: { label: string }) {
|
|
861
|
+
return <><span>{label}</span></>;
|
|
800
862
|
}
|
|
801
863
|
|
|
802
|
-
|
|
803
|
-
|
|
864
|
+
function App() {
|
|
865
|
+
return <><MakeFragment label="from helper" /></>;
|
|
804
866
|
}
|
|
805
867
|
|
|
806
868
|
render(App);
|