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.
Files changed (182) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/package.json +3 -3
  3. package/src/jsx-runtime.d.ts +2 -2
  4. package/src/runtime/element.js +1 -1
  5. package/src/runtime/index-client.js +11 -11
  6. package/src/runtime/index-server.js +7 -4
  7. package/src/runtime/internal/client/bindings.js +1 -1
  8. package/src/runtime/internal/client/blocks.js +13 -4
  9. package/src/runtime/internal/client/component.js +55 -0
  10. package/src/runtime/internal/client/composite.js +4 -2
  11. package/src/runtime/internal/client/expression.js +65 -7
  12. package/src/runtime/internal/client/hmr.js +54 -43
  13. package/src/runtime/internal/client/index.js +5 -1
  14. package/src/runtime/internal/client/portal.js +70 -69
  15. package/src/runtime/internal/client/render.js +3 -0
  16. package/src/runtime/internal/server/index.js +92 -8
  17. package/tests/client/__snapshots__/html.test.tsrx.snap +3 -3
  18. package/tests/client/array/array.copy-within.test.tsrx +33 -31
  19. package/tests/client/array/array.derived.test.tsrx +186 -169
  20. package/tests/client/array/array.iteration.test.tsrx +40 -37
  21. package/tests/client/array/array.mutations.test.tsrx +113 -101
  22. package/tests/client/array/array.static.test.tsrx +119 -101
  23. package/tests/client/array/array.to-methods.test.tsrx +24 -21
  24. package/tests/client/async-suspend.test.tsrx +247 -246
  25. package/tests/client/basic/__snapshots__/basic.rendering.test.tsrx.snap +0 -1
  26. package/tests/client/basic/basic.attributes.test.tsrx +428 -423
  27. package/tests/client/basic/basic.collections.test.tsrx +109 -102
  28. package/tests/client/basic/basic.components.test.tsrx +323 -205
  29. package/tests/client/basic/basic.errors.test.tsrx +91 -91
  30. package/tests/client/basic/basic.events.test.tsrx +114 -115
  31. package/tests/client/basic/basic.get-set.test.tsrx +97 -87
  32. package/tests/client/basic/basic.hmr.test.tsrx +19 -16
  33. package/tests/client/basic/basic.reactivity.test.tsrx +199 -191
  34. package/tests/client/basic/basic.rendering.test.tsrx +272 -182
  35. package/tests/client/basic/basic.styling.test.tsrx +23 -22
  36. package/tests/client/basic/basic.utilities.test.tsrx +10 -8
  37. package/tests/client/boundaries.test.tsrx +26 -26
  38. package/tests/client/compiler/__snapshots__/compiler.assignments.test.rsrx.snap +5 -5
  39. package/tests/client/compiler/__snapshots__/compiler.assignments.test.tsrx.snap +5 -5
  40. package/tests/client/compiler/compiler.assignments.test.tsrx +77 -81
  41. package/tests/client/compiler/compiler.attributes.test.tsrx +15 -15
  42. package/tests/client/compiler/compiler.basic.test.tsrx +322 -314
  43. package/tests/client/compiler/compiler.regex.test.tsrx +44 -47
  44. package/tests/client/compiler/compiler.tracked-access.test.tsrx +38 -38
  45. package/tests/client/compiler/compiler.try-in-function.test.tsrx +16 -16
  46. package/tests/client/compiler/compiler.typescript.test.tsrx +2 -2
  47. package/tests/client/composite/composite.dynamic-components.test.tsrx +47 -48
  48. package/tests/client/composite/composite.generics.test.tsrx +168 -192
  49. package/tests/client/composite/composite.props.test.tsrx +97 -81
  50. package/tests/client/composite/composite.reactivity.test.tsrx +177 -147
  51. package/tests/client/composite/composite.render.test.tsrx +122 -105
  52. package/tests/client/computed-properties.test.tsrx +28 -28
  53. package/tests/client/context.test.tsrx +21 -21
  54. package/tests/client/css/global-additional-cases.test.tsrx +58 -58
  55. package/tests/client/css/global-advanced-selectors.test.tsrx +16 -16
  56. package/tests/client/css/global-at-rules.test.tsrx +10 -10
  57. package/tests/client/css/global-basic.test.tsrx +14 -14
  58. package/tests/client/css/global-classes-ids.test.tsrx +14 -14
  59. package/tests/client/css/global-combinators.test.tsrx +10 -10
  60. package/tests/client/css/global-complex-nesting.test.tsrx +14 -14
  61. package/tests/client/css/global-edge-cases.test.tsrx +18 -18
  62. package/tests/client/css/global-keyframes.test.tsrx +12 -12
  63. package/tests/client/css/global-nested.test.tsrx +10 -10
  64. package/tests/client/css/global-pseudo.test.tsrx +12 -12
  65. package/tests/client/css/global-scoping.test.tsrx +20 -20
  66. package/tests/client/css/style-identifier.test.tsrx +143 -291
  67. package/tests/client/date.test.tsrx +146 -133
  68. package/tests/client/dynamic-elements.test.tsrx +398 -365
  69. package/tests/client/events.test.tsrx +292 -290
  70. package/tests/client/for.test.tsrx +156 -153
  71. package/tests/client/head.test.tsrx +105 -96
  72. package/tests/client/html.test.tsrx +122 -26
  73. package/tests/client/input-value.test.tsrx +1361 -1314
  74. package/tests/client/lazy-array.test.tsrx +16 -13
  75. package/tests/client/lazy-destructuring.test.tsrx +257 -213
  76. package/tests/client/map.test.tsrx +65 -60
  77. package/tests/client/media-query.test.tsrx +22 -20
  78. package/tests/client/object.test.tsrx +87 -81
  79. package/tests/client/portal.test.tsrx +57 -51
  80. package/tests/client/ref.test.tsrx +233 -202
  81. package/tests/client/return.test.tsrx +71 -2560
  82. package/tests/client/set.test.tsrx +54 -45
  83. package/tests/client/svg.test.tsrx +216 -186
  84. package/tests/client/switch.test.tsrx +194 -193
  85. package/tests/client/track-async-hydration.test.tsrx +18 -14
  86. package/tests/client/tracked-index-access.test.tsrx +28 -18
  87. package/tests/client/try.test.tsrx +675 -548
  88. package/tests/client/tsx.test.tsrx +373 -311
  89. package/tests/client/typescript-generics.test.tsrx +145 -145
  90. package/tests/client/url/url.derived.test.tsrx +33 -28
  91. package/tests/client/url/url.parsing.test.tsrx +61 -51
  92. package/tests/client/url/url.partial-removal.test.tsrx +56 -48
  93. package/tests/client/url/url.reactivity.test.tsrx +142 -125
  94. package/tests/client/url/url.serialization.test.tsrx +13 -11
  95. package/tests/client/url-search-params/url-search-params.derived.test.tsrx +34 -29
  96. package/tests/client/url-search-params/url-search-params.initialization.test.tsrx +25 -21
  97. package/tests/client/url-search-params/url-search-params.iteration.test.tsrx +50 -45
  98. package/tests/client/url-search-params/url-search-params.mutation.test.tsrx +111 -99
  99. package/tests/client/url-search-params/url-search-params.retrieval.test.tsrx +49 -43
  100. package/tests/client/url-search-params/url-search-params.serialization.test.tsrx +14 -12
  101. package/tests/client/url-search-params/url-search-params.tracked-url.test.tsrx +16 -14
  102. package/tests/hydration/basic.test.js +3 -3
  103. package/tests/hydration/compiled/client/basic.js +586 -651
  104. package/tests/hydration/compiled/client/composite.js +79 -104
  105. package/tests/hydration/compiled/client/events.js +140 -148
  106. package/tests/hydration/compiled/client/for.js +1005 -1018
  107. package/tests/hydration/compiled/client/head.js +124 -134
  108. package/tests/hydration/compiled/client/hmr.js +41 -48
  109. package/tests/hydration/compiled/client/html-in-template.js +38 -41
  110. package/tests/hydration/compiled/client/html.js +970 -1314
  111. package/tests/hydration/compiled/client/if-children.js +234 -249
  112. package/tests/hydration/compiled/client/if.js +182 -189
  113. package/tests/hydration/compiled/client/mixed-control-flow.js +347 -303
  114. package/tests/hydration/compiled/client/nested-control-flow.js +1084 -832
  115. package/tests/hydration/compiled/client/portal.js +65 -85
  116. package/tests/hydration/compiled/client/reactivity.js +84 -90
  117. package/tests/hydration/compiled/client/return.js +38 -1939
  118. package/tests/hydration/compiled/client/switch.js +218 -224
  119. package/tests/hydration/compiled/client/track-async-serialization.js +250 -259
  120. package/tests/hydration/compiled/client/try.js +123 -132
  121. package/tests/hydration/compiled/server/basic.js +773 -831
  122. package/tests/hydration/compiled/server/composite.js +166 -191
  123. package/tests/hydration/compiled/server/events.js +170 -184
  124. package/tests/hydration/compiled/server/for.js +851 -909
  125. package/tests/hydration/compiled/server/head.js +206 -216
  126. package/tests/hydration/compiled/server/hmr.js +64 -72
  127. package/tests/hydration/compiled/server/html-in-template.js +42 -76
  128. package/tests/hydration/compiled/server/html.js +1362 -1667
  129. package/tests/hydration/compiled/server/if-children.js +419 -445
  130. package/tests/hydration/compiled/server/if.js +194 -208
  131. package/tests/hydration/compiled/server/mixed-control-flow.js +249 -257
  132. package/tests/hydration/compiled/server/nested-control-flow.js +491 -515
  133. package/tests/hydration/compiled/server/portal.js +152 -160
  134. package/tests/hydration/compiled/server/reactivity.js +94 -106
  135. package/tests/hydration/compiled/server/return.js +28 -2172
  136. package/tests/hydration/compiled/server/switch.js +274 -286
  137. package/tests/hydration/compiled/server/track-async-serialization.js +340 -358
  138. package/tests/hydration/compiled/server/try.js +167 -185
  139. package/tests/hydration/components/basic.tsrx +320 -272
  140. package/tests/hydration/components/composite.tsrx +44 -32
  141. package/tests/hydration/components/events.tsrx +101 -91
  142. package/tests/hydration/components/for.tsrx +510 -452
  143. package/tests/hydration/components/head.tsrx +87 -80
  144. package/tests/hydration/components/hmr.tsrx +22 -17
  145. package/tests/hydration/components/html-in-template.tsrx +22 -17
  146. package/tests/hydration/components/html.tsrx +525 -443
  147. package/tests/hydration/components/if-children.tsrx +158 -148
  148. package/tests/hydration/components/if.tsrx +109 -95
  149. package/tests/hydration/components/mixed-control-flow.tsrx +100 -96
  150. package/tests/hydration/components/nested-control-flow.tsrx +215 -203
  151. package/tests/hydration/components/portal.tsrx +41 -34
  152. package/tests/hydration/components/reactivity.tsrx +37 -27
  153. package/tests/hydration/components/return.tsrx +12 -556
  154. package/tests/hydration/components/switch.tsrx +120 -114
  155. package/tests/hydration/components/track-async-serialization.tsrx +107 -91
  156. package/tests/hydration/components/try.tsrx +55 -40
  157. package/tests/hydration/html.test.js +4 -4
  158. package/tests/hydration/return.test.js +13 -532
  159. package/tests/server/await.test.tsrx +3 -3
  160. package/tests/server/basic.attributes.test.tsrx +264 -195
  161. package/tests/server/basic.components.test.tsrx +296 -169
  162. package/tests/server/basic.test.tsrx +300 -198
  163. package/tests/server/compiler.test.tsrx +62 -60
  164. package/tests/server/composite.props.test.tsrx +77 -63
  165. package/tests/server/composite.test.tsrx +168 -192
  166. package/tests/server/context.test.tsrx +18 -12
  167. package/tests/server/dynamic-elements.test.tsrx +197 -180
  168. package/tests/server/for.test.tsrx +85 -78
  169. package/tests/server/head.test.tsrx +50 -43
  170. package/tests/server/html-nesting-validation.test.tsrx +8 -8
  171. package/tests/server/if.test.tsrx +57 -51
  172. package/tests/server/lazy-destructuring.test.tsrx +366 -294
  173. package/tests/server/return.test.tsrx +76 -1355
  174. package/tests/server/streaming-ssr.test.tsrx +4 -75
  175. package/tests/server/style-identifier.test.tsrx +169 -148
  176. package/tests/server/switch.test.tsrx +91 -85
  177. package/tests/server/track-async-serialization.test.tsrx +105 -85
  178. package/tests/server/try.test.tsrx +374 -280
  179. package/tests/utils/compiler-compat-config.test.js +2 -2
  180. package/tests/utils/runtime-imports.test.js +10 -0
  181. package/types/index.d.ts +8 -0
  182. 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
- component App() {
6
- <tsx></tsx>
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
- component App() {
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
- component App() {
22
- const el = <tsx></tsx>;
23
- {el}
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
- component App() {
31
- const el = <></>;
32
- {el}
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
- component App() {
40
- const el = <tsx>
41
- <div>hello world</div>
42
- </tsx>;
43
- {el}
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
- component App() {
52
- <tsx>
53
- <div class="card">
54
- <h2>
55
- {'tsx block'}
56
- </h2>
57
- </div>
58
- </tsx>
59
-
60
- <>
61
- <div class="card">
62
- <h2>
63
- {'fragment shorthand'}
64
- </h2>
65
- </div>
66
- </>
67
-
68
- <style>
69
- .card {
70
- padding: 1rem;
71
- }
72
-
73
- h2 {
74
- color: red;
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
- component App() {
102
- const el = <tsx>
103
- <span class="test">content</span>
104
- </tsx>;
105
- {el}
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
- component App() {
115
- const el = <tsx>
116
- <div>first</div>
117
- <div>second</div>
118
- </tsx>;
119
- {el}
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
- component App() {
130
- const el = <tsx>
131
- <div class="outer">
132
- <span class="inner">nested</span>
133
- </div>
134
- </tsx>;
135
- {el}
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
- component App() {
147
- const el = <tsx>
148
- <span>inline</span>
149
- </tsx>;
150
- <div class="parent">{el}</div>
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
- component App() {
161
- let &[count] = track(0);
162
- const el = <tsx>
163
- <div>
164
- {'count: ' + count}
165
- </div>
166
- </tsx>;
167
- {el}
168
- <button onClick={() => count++}>{'increment'}</button>
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
- component App() {
180
- let &[show] = track(true);
181
- const el = <tsx>
182
- <div class="tsx-content">visible</div>
183
- </tsx>;
184
-
185
- if (show) {
186
- {el}
187
- }
188
- <button onClick={() => (show = !show)}>{'toggle'}</button>
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
- component Child(&{ children }: { children: any }) {
204
- <div class="wrapper">{children}</div>
222
+ function Child(&{ children }: { children: any }) {
223
+ return <><div class="wrapper">{children}</div></>;
205
224
  }
206
225
 
207
- component App() {
208
- const el = <tsx>
209
- <span>from tsx</span>
210
- </tsx>;
211
- <Child children={el} />
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
- component App() {
222
- const el = <tsx>
223
- just text
224
- </tsx>;
225
- {el}
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
- component App() {
234
- const el = <tsx>
235
- <div id="my-id" class="my-class" data-testid="test" aria-label="label">content</div>
236
- </tsx>;
237
- {el}
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
- component App() {
250
- let &[name] = track('initial');
251
-
252
- const el = <tsx>
253
- <div id={name} class={'cls-' + name}>content</div>
254
- </tsx>;
255
- {el}
256
- <button onClick={() => (name = 'updated')}>{'update'}</button>
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
- component App() {
272
- let &[clicked] = track(false);
273
-
274
- const el = <tsx>
275
- <button onClick={() => (clicked = true)}>
276
- {'click me'}
277
- </button>
278
- </tsx>;
279
- {el}
280
- <div class="status">{clicked ? 'clicked' : 'not clicked'}</div>
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
- component App() {
293
- let &[isDisabled] = track(true);
294
-
295
- const el = <tsx>
296
- <button disabled={isDisabled}>
297
- {'btn'}
298
- </button>
299
- </tsx>;
300
- {el}
301
- <button class="toggle" onClick={() => (isDisabled = !isDisabled)}>{'toggle'}</button>
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
- component App() {
314
- let &[color] = track('red');
315
-
316
- const el = <tsx>
317
- <div style={'color: ' + color}>styled</div>
318
- </tsx>;
319
- {el}
320
- <button onClick={() => (color = 'blue')}>{'change color'}</button>
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
- component App() {
333
- let &[index] = track(0);
334
-
335
- const el = <tsx>
336
- <div
337
- id={'item-' + index}
338
- class={'item pos-' + index}
339
- data-index={index}
340
- title={'Item ' + index}
341
- >
342
- {'Item ' + index}
343
- </div>
344
- </tsx>;
345
- {el}
346
- <button onClick={() => index++}>{'next'}</button>
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
- component Wrapper(&{ content }: { content: any }) {
366
- <div class="wrapper">{content}</div>
395
+ function Wrapper(&{ content }: { content: any }) {
396
+ return <><div class="wrapper">{content}</div></>;
367
397
  }
368
398
 
369
- component App() {
370
- <Wrapper
371
- content={<tsx>
372
- <span class="inner">direct prop</span>
373
- </tsx>}
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
- component Card(&{ title, children }: { title: any; children: any }) {
386
- <div class="card">
387
- <h2 class="card-title">{title}</h2>
388
- <div class="card-body">{children}</div>
389
- </div>
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
- component App() {
393
- <Card
394
- title={<tsx>
395
- <span class="bold">Title</span>
396
- </tsx>}
397
- children={<tsx>
398
- <p>Card content here</p>
399
- </tsx>}
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
- component App() {
417
- const badge = createBadge('New');
418
- {badge}
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
- component App() {
434
- const items = ['Apple', 'Banana', 'Cherry'];
435
- <ul>
436
- for (const item of items) {
437
- {createListItem(item)}
438
- }
439
- </ul>
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
- component List(&{ renderItem, items }: { renderItem: (item: string) => any; items: string[] }) {
452
- <ul class="list">
453
- for (const item of items) {
454
- {renderItem(item)}
455
- }
456
- </ul>
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
- component App() {
468
- <List items={['One', 'Two', 'Three']} renderItem={itemRenderer} />
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
- component App() {
492
- let &[count] = track(0);
493
-
494
- const counterElement = createCounter('Count:', () => count);
495
- {counterElement}
496
- <button onClick={() => count++}>{'increment'}</button>
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
- component App() {
525
- const btn = createButton('save', 'Save');
526
- {btn}
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 makeFragment(label: string) {
538
- return <tsrx>
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
- {<tsrx>
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
- </tsrx>;
597
+ </>;
551
598
  }
552
599
 
553
- component App() {
554
- {<tsx>
555
- {[1, 2, 3].map((item) => <div class="app-item">{item}</div>)}
556
- </tsx>}
557
- {makeFragment('from helper')}
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
- component App() {
577
- const content = <tsx>
578
- <section class="outer">
579
- {<tsrx>
580
- <div class="inner">{'from tsrx'}</div>
581
- </tsrx>}
582
- </section>
583
- </tsx>;
584
-
585
- {content}
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
- component App() {
597
- const content = <tsx>
598
- <div class="wrapper">
599
- {<tsrx>
600
- <section class="native">
601
- <span class="nested-tsrx">{'inside nested tsrx'}</span>
602
- </section>
603
- </tsrx>}
604
- </div>
605
- </tsx>;
606
-
607
- {content}
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 inside tsrx nested from a top-level tsx value', () => {
618
- component App() {
619
- const content = <tsx>
620
- {<tsrx>
621
- const nested = <tsx>
622
- <span class="nested-tsx">
623
- {'inside nested tsx'}
624
- </span>
625
- </tsx>;
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
- </tsrx>}
628
- </tsx>;
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
- component Alert(&{ icon, message }: { icon?: any; message: string }) {
642
- <div class="alert">
643
- {icon}
644
- <span class="message">{message}</span>
645
- </div>
646
- }
647
-
648
- component App() {
649
- <Alert message="No icon" />
650
- <Alert
651
- icon={<tsx>
652
- <span class="custom-icon">✓</span>
653
- </tsx>}
654
- message="Custom icon"
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
- component App() {
673
- const items = [
674
- { className: 'item-a', content: 'A' },
675
- { className: 'item-b', content: 'B' },
676
- { className: 'item-c', content: 'C' },
677
- ];
678
-
679
- <div class="container">
680
- for (const item of items) {
681
- {createItem(item.className, item.content)}
682
- }
683
- </div>
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
- component App() {
710
- let &[status] = track('default');
711
- {createContent(status)}
712
- <button class="set-success" onClick={() => (status = 'success')}>{'Success'}</button>
713
- <button class="set-error" onClick={() => (status = 'error')}>{'Error'}</button>
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
- component App() {
734
- const el = <tsrx>
735
- <div>"Hello world"</div>
736
- </tsrx>;
737
- {el}
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
- component App() {
749
- const el = <tsrx>
750
- const label = 'from setup';
751
- <div>{label}</div>
752
- </tsrx>;
753
- {el}
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
- component App() {
763
- let &[count] = track(0);
764
-
765
- const el = <tsrx>
766
- <div>{'count: ' + count}</div>
767
- </tsrx>;
768
- {el}
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
- component App() {
782
- const el = <tsrx>
783
- if (true) {
784
- <span>"visible"</span>
785
- }
786
- </tsrx>;
787
- {el}
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 helpers outside components', () => {
796
- function makeFragment(label: string) {
797
- return <tsrx>
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
- component App() {
803
- {makeFragment('from helper')}
864
+ function App() {
865
+ return <><MakeFragment label="from helper" /></>;
804
866
  }
805
867
 
806
868
  render(App);